summaryrefslogtreecommitdiff
path: root/drivers/gpu/rogue
diff options
context:
space:
mode:
authorzxl <zhuangxl@rock-chips.com>2015-03-25 11:05:17 +0800
committerzxl <zhuangxl@rock-chips.com>2015-03-25 11:19:31 +0800
commit2a14944523fe53e44f5d49d049d2d57a514501e5 (patch)
treeb9e7858d7fa57e4b2b251494c8221e6a85dba7e3 /drivers/gpu/rogue
parent8d9dca881a087adb0083043185813b7a700d54f0 (diff)
RK3368 GPU version: L0.10
Init Power Rogue DDK code Signed-off-by: zxl <zhuangxl@rock-chips.com>
Diffstat (limited to 'drivers/gpu/rogue')
-rw-r--r--drivers/gpu/rogue/GPL-COPYING344
-rw-r--r--drivers/gpu/rogue/INSTALL58
-rwxr-xr-xdrivers/gpu/rogue/Kconfig8
-rw-r--r--drivers/gpu/rogue/MIT-COPYING41
-rwxr-xr-xdrivers/gpu/rogue/Makefile249
-rw-r--r--drivers/gpu/rogue/README32
-rw-r--r--drivers/gpu/rogue/build/linux/bits.mk125
-rw-r--r--drivers/gpu/rogue/build/linux/buildvars.mk279
-rw-r--r--drivers/gpu/rogue/build/linux/commands.mk357
-rw-r--r--drivers/gpu/rogue/build/linux/common/3rdparty.mk98
-rw-r--r--drivers/gpu/rogue/build/linux/common/android/arch.mk100
-rw-r--r--drivers/gpu/rogue/build/linux/common/android/arch_common.mk77
-rw-r--r--drivers/gpu/rogue/build/linux/common/android/extra_config.mk69
-rw-r--r--drivers/gpu/rogue/build/linux/common/android/features.mk230
-rw-r--r--drivers/gpu/rogue/build/linux/common/android/install.sh.tpl323
-rw-r--r--drivers/gpu/rogue/build/linux/common/android/paths.mk52
-rw-r--r--drivers/gpu/rogue/build/linux/common/android/platform_version.mk178
-rw-r--r--drivers/gpu/rogue/build/linux/common/pvrgdb.mk40
-rw-r--r--drivers/gpu/rogue/build/linux/common/testchip.mk62
-rw-r--r--drivers/gpu/rogue/build/linux/config/compiler.mk194
-rw-r--r--drivers/gpu/rogue/build/linux/config/compilers/aarch64-linux-android.mk12
-rw-r--r--drivers/gpu/rogue/build/linux/config/compilers/arm-eabi.mk2
-rw-r--r--drivers/gpu/rogue/build/linux/config/compilers/arm-linux-androideabi.mk2
-rw-r--r--drivers/gpu/rogue/build/linux/config/compilers/i386-linux-gnu.mk2
-rw-r--r--drivers/gpu/rogue/build/linux/config/compilers/x86_64-linux-gnu.mk29
-rw-r--r--drivers/gpu/rogue/build/linux/config/core.mk755
-rw-r--r--drivers/gpu/rogue/build/linux/config/help.mk74
-rw-r--r--drivers/gpu/rogue/build/linux/config/kernel_version.mk100
-rw-r--r--drivers/gpu/rogue/build/linux/config/preconfig.mk157
-rw-r--r--drivers/gpu/rogue/build/linux/defs.mk264
-rw-r--r--drivers/gpu/rogue/build/linux/generic_arm_android/Makefile122
-rw-r--r--drivers/gpu/rogue/build/linux/kbuild/Makefile.template92
-rw-r--r--drivers/gpu/rogue/build/linux/kbuild/kbuild.mk89
-rw-r--r--drivers/gpu/rogue/build/linux/moduledefs/host_i386.mk57
-rw-r--r--drivers/gpu/rogue/build/linux/moduledefs/host_x86_64.mk57
-rw-r--r--drivers/gpu/rogue/build/linux/moduledefs/target_aarch64.mk98
-rw-r--r--drivers/gpu/rogue/build/linux/moduledefs/target_armv7-a.mk103
-rw-r--r--drivers/gpu/rogue/build/linux/moduledefs/target_i686.mk102
-rw-r--r--drivers/gpu/rogue/build/linux/moduledefs/target_neutral.mk44
-rw-r--r--drivers/gpu/rogue/build/linux/moduledefs/target_x86_64.mk100
-rw-r--r--drivers/gpu/rogue/build/linux/moduledefs_common.mk121
-rw-r--r--drivers/gpu/rogue/build/linux/modules.mk48
-rw-r--r--drivers/gpu/rogue/build/linux/modules/_objects.mk117
-rw-r--r--drivers/gpu/rogue/build/linux/modules/kernel_module.mk92
-rw-r--r--drivers/gpu/rogue/build/linux/pc_android/Makefile139
-rw-r--r--drivers/gpu/rogue/build/linux/prepare_tree.mk56
-rw-r--r--drivers/gpu/rogue/build/linux/pvrversion.mk57
-rw-r--r--drivers/gpu/rogue/build/linux/scripts.mk341
-rw-r--r--drivers/gpu/rogue/build/linux/this_makefile.mk68
-rwxr-xr-xdrivers/gpu/rogue/build/linux/tools/cc-check.sh120
-rw-r--r--drivers/gpu/rogue/build/linux/toplevel.mk291
-rw-r--r--drivers/gpu/rogue/config_kernel.h33
-rw-r--r--drivers/gpu/rogue/config_kernel.mk26
-rw-r--r--drivers/gpu/rogue/dc_fbdev/Kbuild.mk49
-rw-r--r--drivers/gpu/rogue/dc_fbdev/Linux.mk45
-rwxr-xr-xdrivers/gpu/rogue/dc_fbdev/dc_fbdev.c893
-rw-r--r--drivers/gpu/rogue/generated/breakpoint_bridge/common_breakpoint_bridge.h157
-rw-r--r--drivers/gpu/rogue/generated/breakpoint_bridge/server_breakpoint_bridge.c371
-rw-r--r--drivers/gpu/rogue/generated/cachegeneric_bridge/common_cachegeneric_bridge.h75
-rw-r--r--drivers/gpu/rogue/generated/cachegeneric_bridge/server_cachegeneric_bridge.c126
-rw-r--r--drivers/gpu/rogue/generated/cmm_bridge/common_cmm_bridge.h178
-rw-r--r--drivers/gpu/rogue/generated/cmm_bridge/server_cmm_bridge.c611
-rw-r--r--drivers/gpu/rogue/generated/dc_bridge/common_dc_bridge.h578
-rw-r--r--drivers/gpu/rogue/generated/dc_bridge/server_dc_bridge.c2164
-rw-r--r--drivers/gpu/rogue/generated/debugmisc_bridge/common_debugmisc_bridge.h160
-rw-r--r--drivers/gpu/rogue/generated/debugmisc_bridge/server_debugmisc_bridge.c343
-rw-r--r--drivers/gpu/rogue/generated/dmabuf_bridge/common_dmabuf_bridge.h79
-rw-r--r--drivers/gpu/rogue/generated/dmabuf_bridge/server_dmabuf_bridge.c174
-rw-r--r--drivers/gpu/rogue/generated/dmm_bridge/client_mm_bridge.c535
-rw-r--r--drivers/gpu/rogue/generated/dmm_bridge/client_mm_bridge.h165
-rw-r--r--drivers/gpu/rogue/generated/dpdumpmm_bridge/client_pdumpmm_bridge.c256
-rw-r--r--drivers/gpu/rogue/generated/dpvrtl_bridge/client_pvrtl_bridge.c177
-rw-r--r--drivers/gpu/rogue/generated/dri_bridge/client_ri_bridge.c181
-rw-r--r--drivers/gpu/rogue/generated/dsync_bridge/client_sync_bridge.c492
-rw-r--r--drivers/gpu/rogue/generated/dsync_bridge/client_sync_bridge.h161
-rw-r--r--drivers/gpu/rogue/generated/mm_bridge/common_mm_bridge.h527
-rw-r--r--drivers/gpu/rogue/generated/mm_bridge/server_mm_bridge.c1851
-rw-r--r--drivers/gpu/rogue/generated/pdump_bridge/common_pdump_bridge.h208
-rw-r--r--drivers/gpu/rogue/generated/pdump_bridge/server_pdump_bridge.c332
-rw-r--r--drivers/gpu/rogue/generated/pdumpcmm_bridge/common_pdumpcmm_bridge.h87
-rw-r--r--drivers/gpu/rogue/generated/pdumpcmm_bridge/server_pdumpcmm_bridge.c198
-rw-r--r--drivers/gpu/rogue/generated/pdumpmm_bridge/client_pdumpmm_bridge.h113
-rw-r--r--drivers/gpu/rogue/generated/pdumpmm_bridge/common_pdumpmm_bridge.h244
-rw-r--r--drivers/gpu/rogue/generated/pdumpmm_bridge/server_pdumpmm_bridge.c617
-rw-r--r--drivers/gpu/rogue/generated/pvrtl_bridge/client_pvrtl_bridge.h83
-rw-r--r--drivers/gpu/rogue/generated/pvrtl_bridge/common_pvrtl_bridge.h196
-rw-r--r--drivers/gpu/rogue/generated/pvrtl_bridge/server_pvrtl_bridge.c477
-rw-r--r--drivers/gpu/rogue/generated/regconfig_bridge/common_regconfig_bridge.h150
-rw-r--r--drivers/gpu/rogue/generated/regconfig_bridge/server_regconfig_bridge.c304
-rw-r--r--drivers/gpu/rogue/generated/rgxcmp_bridge/common_rgxcmp_bridge.h200
-rw-r--r--drivers/gpu/rogue/generated/rgxcmp_bridge/server_rgxcmp_bridge.c905
-rw-r--r--drivers/gpu/rogue/generated/rgxhwperf_bridge/common_rgxhwperf_bridge.h140
-rw-r--r--drivers/gpu/rogue/generated/rgxhwperf_bridge/server_rgxhwperf_bridge.c340
-rw-r--r--drivers/gpu/rogue/generated/rgxinit_bridge/common_rgxinit_bridge.h174
-rw-r--r--drivers/gpu/rogue/generated/rgxinit_bridge/server_rgxinit_bridge.c575
-rw-r--r--drivers/gpu/rogue/generated/rgxpdump_bridge/common_rgxpdump_bridge.h95
-rw-r--r--drivers/gpu/rogue/generated/rgxpdump_bridge/server_rgxpdump_bridge.c183
-rw-r--r--drivers/gpu/rogue/generated/rgxta3d_bridge/common_rgxta3d_bridge.h519
-rw-r--r--drivers/gpu/rogue/generated/rgxta3d_bridge/server_rgxta3d_bridge.c2502
-rw-r--r--drivers/gpu/rogue/generated/rgxtq_bridge/common_rgxtq_bridge.h185
-rw-r--r--drivers/gpu/rogue/generated/rgxtq_bridge/server_rgxtq_bridge.c1411
-rw-r--r--drivers/gpu/rogue/generated/ri_bridge/client_ri_bridge.h84
-rw-r--r--drivers/gpu/rogue/generated/ri_bridge/common_ri_bridge.h194
-rw-r--r--drivers/gpu/rogue/generated/ri_bridge/server_ri_bridge.c504
-rw-r--r--drivers/gpu/rogue/generated/smm_bridge/common_smm_bridge.h114
-rw-r--r--drivers/gpu/rogue/generated/smm_bridge/server_smm_bridge.c328
-rw-r--r--drivers/gpu/rogue/generated/srvcore_bridge/common_srvcore_bridge.h385
-rw-r--r--drivers/gpu/rogue/generated/srvcore_bridge/server_srvcore_bridge.c909
-rw-r--r--drivers/gpu/rogue/generated/sync_bridge/common_sync_bridge.h480
-rw-r--r--drivers/gpu/rogue/generated/sync_bridge/server_sync_bridge.c1737
-rw-r--r--drivers/gpu/rogue/generated/syncexport_bridge/common_syncexport_bridge.h113
-rw-r--r--drivers/gpu/rogue/generated/syncexport_bridge/server_syncexport_bridge.c366
-rw-r--r--drivers/gpu/rogue/generated/syncsexport_bridge/common_syncsexport_bridge.h113
-rw-r--r--drivers/gpu/rogue/generated/syncsexport_bridge/server_syncsexport_bridge.c315
-rw-r--r--drivers/gpu/rogue/generated/timerquery_bridge/common_timerquery_bridge.h134
-rw-r--r--drivers/gpu/rogue/generated/timerquery_bridge/server_timerquery_bridge.c266
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.0.h67
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.20.h67
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.30.h67
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.5.h67
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.12.h66
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.15.h67
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.19.h67
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.4.h66
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.5.h66
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.6.h66
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.20.h66
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.51.h69
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.4.53.h69
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.6.61.h70
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.16.h68
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.17.h68
-rw-r--r--drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.46.h68
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.14.4.4.h75
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.31.2.0.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.32.4.19.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.33.2.5.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.39.4.19.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.48.2.0.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.49.4.15.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.67.2.5.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.7.4.5.h75
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.72.4.12.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.20.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.30.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.76.4.6.h73
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.81.4.15.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.82.4.5.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.85.2.5.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.86.4.12.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_12.4.1.20.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.20.4.53.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.24.6.61.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.29.2.51.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.33.4.53.h71
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.5.1.17.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.6.1.17.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.8.1.16.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.9.1.46.h72
-rw-r--r--drivers/gpu/rogue/hwdefs/km/rgx_cr_defs_km.h4069
-rw-r--r--drivers/gpu/rogue/hwdefs/km/rgxdefs_km.h140
-rw-r--r--drivers/gpu/rogue/hwdefs/km/rgxmmudefs_km.h395
-rw-r--r--drivers/gpu/rogue/include/adf/adf_ext.h108
-rw-r--r--drivers/gpu/rogue/include/cache_external.h75
-rw-r--r--drivers/gpu/rogue/include/dbgdrvif_srv5.h264
-rw-r--r--drivers/gpu/rogue/include/dc_external.h71
-rw-r--r--drivers/gpu/rogue/include/devicemem_typedefs.h104
-rw-r--r--drivers/gpu/rogue/include/fbc_types.h64
-rw-r--r--drivers/gpu/rogue/include/img_defs.h231
-rw-r--r--drivers/gpu/rogue/include/img_types.h290
-rw-r--r--drivers/gpu/rogue/include/imgpixfmts_km.h78
-rw-r--r--drivers/gpu/rogue/include/imgyuv.h63
-rw-r--r--drivers/gpu/rogue/include/lock_types.h75
-rw-r--r--drivers/gpu/rogue/include/pdumpdefs.h201
-rwxr-xr-xdrivers/gpu/rogue/include/pvr_debug.h475
-rw-r--r--drivers/gpu/rogue/include/pvr_fd_sync_user.h160
-rw-r--r--drivers/gpu/rogue/include/pvrmodule.h48
-rw-r--r--drivers/gpu/rogue/include/pvrsrv_device_types.h112
-rw-r--r--drivers/gpu/rogue/include/pvrsrv_devmem.h550
-rw-r--r--drivers/gpu/rogue/include/pvrsrv_error.h61
-rw-r--r--drivers/gpu/rogue/include/pvrsrv_errors.h327
-rw-r--r--drivers/gpu/rogue/include/pvrsrv_memallocflags.h492
-rw-r--r--drivers/gpu/rogue/include/pvrsrv_surface.h150
-rwxr-xr-xdrivers/gpu/rogue/include/pvrversion.h74
-rw-r--r--drivers/gpu/rogue/include/rgx_common.h129
-rw-r--r--drivers/gpu/rogue/include/rgx_heaps.h85
-rw-r--r--drivers/gpu/rogue/include/rgx_hwperf_km.h358
-rw-r--r--drivers/gpu/rogue/include/rgx_memallocflags.h49
-rw-r--r--drivers/gpu/rogue/include/rgx_meta.h345
-rw-r--r--drivers/gpu/rogue/include/rgx_options_km.h204
-rw-r--r--drivers/gpu/rogue/include/rgxscript.h178
-rw-r--r--drivers/gpu/rogue/include/ri_typedefs.h55
-rw-r--r--drivers/gpu/rogue/include/services.h1258
-rw-r--r--drivers/gpu/rogue/include/servicesext.h180
-rw-r--r--drivers/gpu/rogue/include/sync_external.h78
-rw-r--r--drivers/gpu/rogue/include/system/rgx_tc/apollo_regs.h79
-rw-r--r--drivers/gpu/rogue/include/system/rgx_tc/pdp_regs.h75
-rw-r--r--drivers/gpu/rogue/include/system/rgx_tc/tcf_clk_ctrl.h808
-rw-r--r--drivers/gpu/rogue/include/system/rgx_tc/tcf_pll.h311
-rw-r--r--drivers/gpu/rogue/include/system/rgx_tc/tcf_rgbpdp_regs.h559
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/Kbuild.mk66
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/Linux.mk57
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_common.c480
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_common.h80
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_fbdev.c849
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_pdp.c1179
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/apollo.c1440
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/apollo_drv.h101
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/ion_lma_heap.c257
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/ion_lma_heap.h52
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.c2119
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.h91
-rw-r--r--drivers/gpu/rogue/kernel/drivers/staging/imgtec/services_kernel_client.h152
-rw-r--r--drivers/gpu/rogue/services/include/cache_defines.h52
-rw-r--r--drivers/gpu/rogue/services/include/dc_common.h74
-rw-r--r--drivers/gpu/rogue/services/include/env/linux/ion_sys.h76
-rw-r--r--drivers/gpu/rogue/services/include/env/linux/pvr_bridge_io.h69
-rw-r--r--drivers/gpu/rogue/services/include/kerneldisplay.h598
-rw-r--r--drivers/gpu/rogue/services/include/pdump.h76
-rw-r--r--drivers/gpu/rogue/services/include/physheap.h120
-rw-r--r--drivers/gpu/rogue/services/include/pvr_bridge.h213
-rw-r--r--drivers/gpu/rogue/services/include/pvr_bridge_client.h80
-rw-r--r--drivers/gpu/rogue/services/include/pvr_tl.h198
-rw-r--r--drivers/gpu/rogue/services/include/pvr_tlcommon.h193
-rw-r--r--drivers/gpu/rogue/services/include/rgx_bridge.h99
-rw-r--r--drivers/gpu/rogue/services/include/rgx_fwif.h467
-rw-r--r--drivers/gpu/rogue/services/include/rgx_fwif_alignchecks_km.h86
-rw-r--r--drivers/gpu/rogue/services/include/rgx_fwif_km.h801
-rw-r--r--drivers/gpu/rogue/services/include/rgx_fwif_resetframework.h68
-rw-r--r--drivers/gpu/rogue/services/include/rgx_fwif_shared.h439
-rw-r--r--drivers/gpu/rogue/services/include/rgx_pdump_panics.h67
-rw-r--r--drivers/gpu/rogue/services/include/rgx_tq_shared.h63
-rw-r--r--drivers/gpu/rogue/services/include/rgxapi_km.h186
-rw-r--r--drivers/gpu/rogue/services/include/shared/allocmem.h79
-rw-r--r--drivers/gpu/rogue/services/include/shared/hash.h229
-rw-r--r--drivers/gpu/rogue/services/include/shared/lock.h97
-rw-r--r--drivers/gpu/rogue/services/include/shared/ra.h207
-rw-r--r--drivers/gpu/rogue/services/server/common/cache_generic.c58
-rw-r--r--drivers/gpu/rogue/services/server/common/connection_server.c239
-rw-r--r--drivers/gpu/rogue/services/server/common/dc_server.c2288
-rw-r--r--drivers/gpu/rogue/services/server/common/devicemem_heapcfg.c133
-rw-r--r--drivers/gpu/rogue/services/server/common/devicemem_server.c764
-rw-r--r--drivers/gpu/rogue/services/server/common/handle.c1933
-rw-r--r--drivers/gpu/rogue/services/server/common/handle_generic.c1018
-rw-r--r--drivers/gpu/rogue/services/server/common/lists.c135
-rw-r--r--drivers/gpu/rogue/services/server/common/mmu_common.c2895
-rw-r--r--drivers/gpu/rogue/services/server/common/pdump_common.c2671
-rw-r--r--drivers/gpu/rogue/services/server/common/pdump_mmu.c1008
-rw-r--r--drivers/gpu/rogue/services/server/common/pdump_physmem.c479
-rw-r--r--drivers/gpu/rogue/services/server/common/physheap.c271
-rw-r--r--drivers/gpu/rogue/services/server/common/physmem.c107
-rw-r--r--drivers/gpu/rogue/services/server/common/physmem_lma.c952
-rw-r--r--drivers/gpu/rogue/services/server/common/pmr.c2653
-rwxr-xr-xdrivers/gpu/rogue/services/server/common/power.c942
-rwxr-xr-xdrivers/gpu/rogue/services/server/common/process_stats.c2757
-rw-r--r--drivers/gpu/rogue/services/server/common/pvrsrv.c2468
-rw-r--r--drivers/gpu/rogue/services/server/common/resman.c1043
-rw-r--r--drivers/gpu/rogue/services/server/common/ri_server.c1255
-rw-r--r--drivers/gpu/rogue/services/server/common/scp.c923
-rw-r--r--drivers/gpu/rogue/services/server/common/srvcore.c619
-rw-r--r--drivers/gpu/rogue/services/server/common/sync_server.c1707
-rw-r--r--drivers/gpu/rogue/services/server/common/tlintern.c301
-rw-r--r--drivers/gpu/rogue/services/server/common/tlserver.c349
-rw-r--r--drivers/gpu/rogue/services/server/common/tlstream.c842
-rw-r--r--drivers/gpu/rogue/services/server/common/tutils.c1629
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/debugmisc_server.c141
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/debugmisc_server.h81
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxbreakpoint.c269
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxbreakpoint.h136
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxccb.c1463
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxccb.h164
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxcompute.c531
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxcompute.h177
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.c2141
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.h152
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxdevice.h371
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxfwutils.c3967
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxfwutils.h662
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxheapconfig.h181
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.c1727
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.h114
-rwxr-xr-xdrivers/gpu/rogue/services/server/devices/rgx/rgxinit.c2972
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxinit.h196
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxmem.c508
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxmem.h76
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxmmuinit.c943
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxmmuinit.h60
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxpdump.c133
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxpdump.h112
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxpower.c1268
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxpower.h189
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxregconfig.c227
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxregconfig.h123
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxsync.c197
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxsync.h80
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxta3d.c3423
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxta3d.h467
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxtimerquery.c239
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxtimerquery.h129
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxtransfer.c1084
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxtransfer.h155
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxutils.c288
-rw-r--r--drivers/gpu/rogue/services/server/devices/rgx/rgxutils.h69
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/Kbuild.mk459
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/Linux.mk46
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/allocmem.c184
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/devicemem_mmap_stub.c133
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/driverlock.h57
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/env_connection.h114
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/env_data.h72
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/event.c362
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/event.h48
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/linkage.h64
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/mm.c105
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/mm.h86
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/mmap.c498
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/mmap.h84
-rwxr-xr-xdrivers/gpu/rogue/services/server/env/linux/module.c1234
-rwxr-xr-xdrivers/gpu/rogue/services/server/env/linux/osconnection_server.c132
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/osfunc.c2048
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/osfunc_arm.c171
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/osfunc_arm64.c118
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/osfunc_x86.c143
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/ossecure_export.c192
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pdump.c462
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/physmem_dmabuf.c663
-rwxr-xr-xdrivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.c1640
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/physmem_tdmetacode_linux.c375
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/physmem_tdsecbuf_linux.c375
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/private_data.h96
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_bridge_k.c595
-rwxr-xr-xdrivers/gpu/rogue/services/server/env/linux/pvr_debug.c1479
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.c454
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.h83
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.c408
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.h96
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/pvr_uaccess.h106
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/rogue_trace_events.h152
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/trace_events.c79
-rw-r--r--drivers/gpu/rogue/services/server/env/linux/trace_events.h83
-rw-r--r--drivers/gpu/rogue/services/server/include/cache_generic.h52
-rw-r--r--drivers/gpu/rogue/services/server/include/connection_server.h98
-rw-r--r--drivers/gpu/rogue/services/server/include/dc_server.h156
-rw-r--r--drivers/gpu/rogue/services/server/include/debug_request_ids.h59
-rw-r--r--drivers/gpu/rogue/services/server/include/device.h300
-rw-r--r--drivers/gpu/rogue/services/server/include/devicemem_heapcfg.h145
-rw-r--r--drivers/gpu/rogue/services/server/include/devicemem_server.h357
-rw-r--r--drivers/gpu/rogue/services/server/include/devicemem_server_utils.h191
-rw-r--r--drivers/gpu/rogue/services/server/include/handle.h451
-rw-r--r--drivers/gpu/rogue/services/server/include/handle_impl.h86
-rw-r--r--drivers/gpu/rogue/services/server/include/lists.h336
-rw-r--r--drivers/gpu/rogue/services/server/include/mmu_common.h534
-rw-r--r--drivers/gpu/rogue/services/server/include/osconnection_server.h95
-rw-r--r--drivers/gpu/rogue/services/server/include/osfunc.h433
-rw-r--r--drivers/gpu/rogue/services/server/include/ossecure_export.h52
-rw-r--r--drivers/gpu/rogue/services/server/include/pdump_km.h742
-rw-r--r--drivers/gpu/rogue/services/server/include/pdump_mmu.h175
-rw-r--r--drivers/gpu/rogue/services/server/include/pdump_osfunc.h347
-rw-r--r--drivers/gpu/rogue/services/server/include/pdump_physmem.h212
-rw-r--r--drivers/gpu/rogue/services/server/include/pdump_symbolicaddr.h55
-rw-r--r--drivers/gpu/rogue/services/server/include/physmem.h102
-rw-r--r--drivers/gpu/rogue/services/server/include/physmem_dmabuf.h63
-rw-r--r--drivers/gpu/rogue/services/server/include/physmem_lma.h74
-rw-r--r--drivers/gpu/rogue/services/server/include/physmem_osmem.h114
-rw-r--r--drivers/gpu/rogue/services/server/include/pmr.h813
-rw-r--r--drivers/gpu/rogue/services/server/include/pmr_impl.h178
-rw-r--r--drivers/gpu/rogue/services/server/include/power.h144
-rw-r--r--drivers/gpu/rogue/services/server/include/process_stats.h172
-rw-r--r--drivers/gpu/rogue/services/server/include/pvrsrv.h477
-rw-r--r--drivers/gpu/rogue/services/server/include/pvrsrv_device.h194
-rw-r--r--drivers/gpu/rogue/services/server/include/resman.h199
-rw-r--r--drivers/gpu/rogue/services/server/include/ri_server.h87
-rw-r--r--drivers/gpu/rogue/services/server/include/scp.h224
-rw-r--r--drivers/gpu/rogue/services/server/include/secure_export.h65
-rw-r--r--drivers/gpu/rogue/services/server/include/srvcore.h219
-rw-r--r--drivers/gpu/rogue/services/server/include/srvkm.h197
-rw-r--r--drivers/gpu/rogue/services/server/include/sync_server.h318
-rw-r--r--drivers/gpu/rogue/services/server/include/sync_server_internal.h55
-rw-r--r--drivers/gpu/rogue/services/server/include/tlintern.h210
-rw-r--r--drivers/gpu/rogue/services/server/include/tlserver.h100
-rw-r--r--drivers/gpu/rogue/services/server/include/tlstream.h336
-rwxr-xr-xdrivers/gpu/rogue/services/shared/common/devicemem.c1951
-rw-r--r--drivers/gpu/rogue/services/shared/common/devicemem_pdump.c323
-rw-r--r--drivers/gpu/rogue/services/shared/common/devicemem_utils.c704
-rw-r--r--drivers/gpu/rogue/services/shared/common/dllist.c77
-rw-r--r--drivers/gpu/rogue/services/shared/common/hash.c669
-rw-r--r--drivers/gpu/rogue/services/shared/common/ra.c1339
-rw-r--r--drivers/gpu/rogue/services/shared/common/sync.c1762
-rw-r--r--drivers/gpu/rogue/services/shared/common/tlclient.c365
-rw-r--r--drivers/gpu/rogue/services/shared/common/uniq_key_splay_tree.c244
-rw-r--r--drivers/gpu/rogue/services/shared/common/uniq_key_splay_tree.h95
-rw-r--r--drivers/gpu/rogue/services/shared/devices/rgx/rgx_compat_bvnc.c165
-rw-r--r--drivers/gpu/rogue/services/shared/devices/rgx/rgx_compat_bvnc.h96
-rw-r--r--drivers/gpu/rogue/services/shared/include/cache_internal.h58
-rw-r--r--drivers/gpu/rogue/services/shared/include/devicemem.h543
-rw-r--r--drivers/gpu/rogue/services/shared/include/devicemem_mmap.h102
-rw-r--r--drivers/gpu/rogue/services/shared/include/devicemem_pdump.h343
-rw-r--r--drivers/gpu/rogue/services/shared/include/devicemem_utils.h378
-rw-r--r--drivers/gpu/rogue/services/shared/include/dllist.h292
-rw-r--r--drivers/gpu/rogue/services/shared/include/sync.h373
-rw-r--r--drivers/gpu/rogue/services/shared/include/sync_internal.h120
-rw-r--r--drivers/gpu/rogue/services/shared/include/tlclient.h169
-rw-r--r--drivers/gpu/rogue/services/shared/include/tltestdefs.h164
-rw-r--r--drivers/gpu/rogue/services/system/rgx_linux_apollo/Kbuild.mk50
-rw-r--r--drivers/gpu/rogue/services/system/rgx_linux_apollo/apollo.h56
-rw-r--r--drivers/gpu/rogue/services/system/rgx_linux_apollo/sysconfig.c675
-rw-r--r--drivers/gpu/rogue/services/system/rgx_linux_apollo/sysinfo.h68
-rw-r--r--drivers/gpu/rogue/services/system/rgx_nohw/Kbuild.mk46
-rw-r--r--drivers/gpu/rogue/services/system/rgx_nohw/sysconfig.c236
-rw-r--r--drivers/gpu/rogue/services/system/rgx_nohw/sysconfig.h68
-rw-r--r--drivers/gpu/rogue/services/system/rgx_nohw/sysinfo.h71
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/Kbuild.mk67
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/apollo.h93
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher.h70
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher_linux.c252
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/ion_support_tc.c173
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/ion_sys_private.h51
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/sysconfig.c2106
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/sysconfig.h372
-rw-r--r--drivers/gpu/rogue/services/system/rgx_tc/sysinfo.h71
-rw-r--r--drivers/gpu/rogue/system/common/interrupt_linux.h52
-rw-r--r--drivers/gpu/rogue/system/common/interrupt_support.c159
-rw-r--r--drivers/gpu/rogue/system/common/ion_support_generic.c161
-rw-r--r--drivers/gpu/rogue/system/common/lma_heap_ion.c205
-rw-r--r--drivers/gpu/rogue/system/common/lma_heap_ion.h45
-rw-r--r--drivers/gpu/rogue/system/common/pci_support.c657
-rw-r--r--drivers/gpu/rogue/system/include/interrupt_support.h59
-rw-r--r--drivers/gpu/rogue/system/include/ion_support.h46
-rw-r--r--drivers/gpu/rogue/system/include/pci_support.h74
-rw-r--r--drivers/gpu/rogue/system/include/syscommon.h167
-rw-r--r--drivers/gpu/rogue/system/rk3368/Kbuild.mk49
-rwxr-xr-xdrivers/gpu/rogue/system/rk3368/rk_init.c1897
-rwxr-xr-xdrivers/gpu/rogue/system/rk3368/rk_init.h160
-rwxr-xr-xdrivers/gpu/rogue/system/rk3368/sysconfig.c242
-rwxr-xr-xdrivers/gpu/rogue/system/rk3368/sysconfig.h72
-rw-r--r--drivers/gpu/rogue/system/rk3368/sysinfo.h71
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/Kbuild.mk50
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/Linux.mk45
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv.c1573
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv.h114
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv_ioctl.h58
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/common/handle.c141
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/common/hostfunc.h82
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/common/ioctl.c335
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/linux/hostfunc.c382
-rw-r--r--drivers/gpu/rogue/tools/services/debug/dbgdriv/linux/main.c358
-rw-r--r--drivers/gpu/rogue/tools/services/debug/include/linuxsrv.h69
447 files changed, 163862 insertions, 0 deletions
diff --git a/drivers/gpu/rogue/GPL-COPYING b/drivers/gpu/rogue/GPL-COPYING
new file mode 100644
index 000000000000..83d1261af023
--- /dev/null
+++ b/drivers/gpu/rogue/GPL-COPYING
@@ -0,0 +1,344 @@
+-------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+-------------------------------------------------------------------------
+
diff --git a/drivers/gpu/rogue/INSTALL b/drivers/gpu/rogue/INSTALL
new file mode 100644
index 000000000000..1af75389b211
--- /dev/null
+++ b/drivers/gpu/rogue/INSTALL
@@ -0,0 +1,58 @@
+Rogue Embedded Systems DDK for the Linux kernel.
+Copyright (C) Imagination Technologies Ltd. All rights reserved.
+======================================================================
+
+This file covers how to build and install the Imagination Technologies
+Rogue DDK for the Linux kernel. For full details, see the relevant platform
+guide.
+
+
+Build System Environment Variables
+-------------------------------------------
+
+The Rogue DDK Build scripts depend on a number of environment variables
+being setup before compilation or installation of DDK software can
+commence:
+
+$DISCIMAGE
+The DDK Build scripts install files to the location specified by the
+DISCIMAGE environment variable. To do so, they need to know where the
+target system image resides:
+$ export DISCIMAGE=/path/to/filesystem
+If you are building on the target system, you can set this to '/'.
+
+$KERNELDIR
+When building the Rogue DDK kernel module, the build needs access
+to the headers of the Linux kernel.
+If you are building on the target machine, you can set this as follows:
+$ export KERNELDIR=/usr/src/linux-headers-`uname -r`
+
+$CROSS_COMPILE
+If you intend on targeting a platform that is different from your build
+machine (e.g.,if you are compiling on an x86 but targeting ARM) you need
+to set the CROSS_COMPILE variable so that the build system uses the correct
+compiler. E.g.,
+$ export CROSS_COMPILE=arm-linux-gnueabi-
+
+
+Build and Install Instructions
+-------------------------------------------
+
+The Rogue DDK configures different target builds within directories under
+build/linux/.
+
+The most interesting build targets are:
+
+ build Makes everything
+ clobber Removes all binaries for all builds as well.
+ install Runs the install script generated by the build.
+
+The following variables may be set on the command line to influence a build.
+
+ BUILD The type of build being performed.
+ Alternatives are release, timing or debug.
+
+To build for, change to the appropriate target directory, e.g.:
+$ cd eurasiacon/build/linux/<platform>
+$ make BUILD=debug
+$ sudo make install
diff --git a/drivers/gpu/rogue/Kconfig b/drivers/gpu/rogue/Kconfig
new file mode 100755
index 000000000000..91d129f29c46
--- /dev/null
+++ b/drivers/gpu/rogue/Kconfig
@@ -0,0 +1,8 @@
+config POWERVR_ROGUE
+ tristate "PowerVR Rogue"
+ default n
+ help
+ Driver for PowerVR Rogue hardware.
+
+ Say Y here if your SoC contains a PowerVR Rogue GPU. For more
+ information, see <http://www.imgtec.com/powervr/>.
diff --git a/drivers/gpu/rogue/MIT-COPYING b/drivers/gpu/rogue/MIT-COPYING
new file mode 100644
index 000000000000..0cbd14e06cbc
--- /dev/null
+++ b/drivers/gpu/rogue/MIT-COPYING
@@ -0,0 +1,41 @@
+
+This software is Copyright (C) Imagination Technologies Ltd.
+
+You may use, distribute and copy this software under the terms of the MIT
+license displayed 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, this Software 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 Software 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 from each file
+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.
+
+-----------------------------------------------------------------------------
+
+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.
+
+-----------------------------------------------------------------------------
diff --git a/drivers/gpu/rogue/Makefile b/drivers/gpu/rogue/Makefile
new file mode 100755
index 000000000000..f5478bb32c68
--- /dev/null
+++ b/drivers/gpu/rogue/Makefile
@@ -0,0 +1,249 @@
+include drivers/gpu/rogue/config_kernel.mk
+
+obj-$(CONFIG_POWERVR_ROGUE) += pvrsrvkm.o
+
+ccflags-y += -include drivers/gpu/rogue/config_kernel.h \
+ -Idrivers/gpu/rogue \
+ -Idrivers/gpu/rogue/hwdefs \
+ -Idrivers/gpu/rogue/hwdefs/km \
+ -Idrivers/gpu/rogue/system/include \
+ -Idrivers/gpu/rogue/system/common \
+ -Idrivers/gpu/rogue/system/$(PVR_SYSTEM) \
+ -Idrivers/gpu/rogue/services/server/include \
+ -Idrivers/gpu/rogue/include \
+ -Idrivers/gpu/rogue/services/include \
+ -Idrivers/gpu/rogue/services/include/shared \
+ -Idrivers/gpu/rogue/services/shared/include \
+ -Idrivers/gpu/rogue/services/shared/devices/rgx \
+ -Idrivers/gpu/rogue/services/server/env/linux \
+ -Idrivers/gpu/rogue/kernel/drivers/staging/imgtec \
+ -Idrivers/gpu/rogue/services/include/env/linux \
+ -Idrivers/gpu/rogue/services/server/devices/rgx
+
+tmp := $(addprefix -I,$(wildcard drivers/gpu/rogue/generated/*))
+ccflags-y += $(tmp)
+
+########
+pvrsrvkm-y += \
+ services/server/env/linux/event.o \
+ services/server/env/linux/mm.o \
+ services/server/env/linux/mmap.o \
+ services/server/env/linux/module.o \
+ services/server/env/linux/devicemem_mmap_stub.o \
+ services/server/env/linux/osfunc.o \
+ services/server/env/linux/allocmem.o \
+ services/server/env/linux/osconnection_server.o \
+ services/server/env/linux/pdump.o \
+ services/server/env/linux/physmem_osmem_linux.o \
+ services/server/env/linux/pvr_debugfs.o \
+ services/server/env/linux/pvr_bridge_k.o \
+ services/server/env/linux/pvr_debug.o \
+ services/server/env/linux/physmem_tdmetacode_linux.o \
+ services/server/env/linux/physmem_tdsecbuf_linux.o \
+ services/server/common/devicemem_heapcfg.o \
+ services/shared/common/devicemem.o \
+ services/shared/common/devicemem_utils.o \
+ services/shared/common/hash.o \
+ services/shared/common/ra.o \
+ services/shared/common/sync.o \
+ services/shared/common/dllist.o \
+ services/server/common/devicemem_server.o \
+ services/server/common/handle.o \
+ services/server/common/lists.o \
+ services/server/common/mmu_common.o \
+ services/server/common/connection_server.o \
+ services/server/common/physheap.o \
+ services/server/common/physmem.o \
+ services/server/common/physmem_lma.o \
+ services/server/common/pmr.o \
+ services/server/common/power.o \
+ services/server/common/process_stats.o \
+ services/server/common/pvrsrv.o \
+ services/server/common/resman.o \
+ services/server/common/srvcore.o \
+ services/server/common/sync_server.o \
+ services/server/common/tlintern.o \
+ services/shared/common/tlclient.o \
+ services/server/common/tlserver.o \
+ services/server/common/tlstream.o \
+ services/server/common/tutils.o \
+ services/shared/common/uniq_key_splay_tree.o \
+ services/server/devices/rgx/rgxsync.o
+
+ifeq ($(SUPPORT_DISPLAY_CLASS),1)
+pvrsrvkm-y += \
+ services/server/common/dc_server.o \
+ services/server/common/scp.o
+endif
+
+ifeq ($(PVR_RI_DEBUG),1)
+pvrsrvkm-y += services/server/common/ri_server.o
+endif
+
+ifeq ($(PVR_HANDLE_BACKEND),generic)
+pvrsrvkm-y += services/server/common/handle_generic.o
+else
+ifeq ($(PVR_HANDLE_BACKEND),idr)
+pvrsrvkm-y += handle_idr.o
+endif
+endif
+
+ifeq ($(SUPPORT_GPUTRACE_EVENTS),1)
+pvrsrvkm-y += services/server/env/linux/pvr_gputrace.o
+endif
+
+
+pvrsrvkm-$(CONFIG_X86) += services/server/env/linux/osfunc_x86.o
+pvrsrvkm-$(CONFIG_ARM) += services/server/env/linux/osfunc_arm.o
+pvrsrvkm-$(CONFIG_ARM64) += services/server/env/linux/osfunc_arm64.o
+pvrsrvkm-$(CONFIG_METAG) += osfunc_metag.o
+pvrsrvkm-$(CONFIG_MIPS) += osfunc_mips.o
+pvrsrvkm-$(CONFIG_EVENT_TRACING) += services/server/env/linux/trace_events.o
+
+
+ifeq ($(PDUMP),1)
+pvrsrvkm-y += \
+ services/server/common/pdump_common.o \
+ services/server/common/pdump_mmu.o \
+ services/server/common/pdump_physmem.o \
+ services/shared/common/devicemem_pdump.o
+endif
+
+pvrsrvkm-y += \
+ services/server/devices/rgx/rgxinit.o \
+ services/server/devices/rgx/rgxdebug.o \
+ services/server/devices/rgx/rgxhwperf.o \
+ services/server/devices/rgx/rgxmem.o \
+ services/server/devices/rgx/rgxta3d.o \
+ services/server/devices/rgx/rgxcompute.o \
+ services/server/devices/rgx/rgxccb.o \
+ services/server/devices/rgx/rgxmmuinit.o \
+ services/server/devices/rgx/rgxpower.o \
+ services/server/devices/rgx/rgxtransfer.o \
+ services/server/devices/rgx/rgxutils.o \
+ services/server/devices/rgx/rgxfwutils.o \
+ services/server/devices/rgx/rgxbreakpoint.o \
+ services/server/devices/rgx/debugmisc_server.o \
+ services/shared/devices/rgx/rgx_compat_bvnc.o \
+ services/server/devices/rgx/rgxregconfig.o \
+ services/server/devices/rgx/rgxtimerquery.o
+
+ifeq ($(SUPPORT_RAY_TRACING),1)
+pvrsrvkm-y += rgxray.o
+endif
+
+ifeq ($(PDUMP),1)
+pvrsrvkm-y += services/server/devices/rgx/rgxpdump.o
+endif
+
+ifeq ($(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC),1)
+pvrsrvkm-y += \
+ kernel/drivers/staging/imgtec/pvr_sync.o
+endif
+
+pvrsrvkm-y += \
+ generated/mm_bridge/server_mm_bridge.o \
+ generated/dmm_bridge/client_mm_bridge.o \
+ generated/pdumpmm_bridge/server_pdumpmm_bridge.o \
+ generated/dpdumpmm_bridge/client_pdumpmm_bridge.o \
+ generated/cmm_bridge/server_cmm_bridge.o \
+ generated/pdumpcmm_bridge/server_pdumpcmm_bridge.o \
+ generated/pdump_bridge/server_pdump_bridge.o \
+ generated/rgxtq_bridge/server_rgxtq_bridge.o \
+ generated/rgxinit_bridge/server_rgxinit_bridge.o \
+ generated/rgxta3d_bridge/server_rgxta3d_bridge.o \
+ generated/rgxcmp_bridge/server_rgxcmp_bridge.o \
+ generated/srvcore_bridge/server_srvcore_bridge.o \
+ generated/sync_bridge/server_sync_bridge.o \
+ generated/dsync_bridge/client_sync_bridge.o \
+ generated/breakpoint_bridge/server_breakpoint_bridge.o \
+ generated/debugmisc_bridge/server_debugmisc_bridge.o \
+ generated/rgxpdump_bridge/server_rgxpdump_bridge.o \
+ generated/pvrtl_bridge/server_pvrtl_bridge.o \
+ generated/dpvrtl_bridge/client_pvrtl_bridge.o \
+ generated/rgxhwperf_bridge/server_rgxhwperf_bridge.o \
+ generated/regconfig_bridge/server_regconfig_bridge.o \
+ generated/timerquery_bridge/server_timerquery_bridge.o
+
+ifeq ($(PVR_RI_DEBUG),1)
+pvrsrvkm-y += \
+ generated/ri_bridge/server_ri_bridge.o \
+ generated/dri_bridge/client_ri_bridge.o
+endif
+
+ifeq ($(SUPPORT_DISPLAY_CLASS),1)
+pvrsrvkm-y += \
+ generated/dc_bridge/server_dc_bridge.o
+endif
+
+ifeq ($(SUPPORT_RAY_TRACING),1)
+pvrsrvkm-y += generated/rgxray_bridge/server_rgxray_bridge.o
+endif
+
+ifeq ($(CACHEFLUSH_TYPE),CACHEFLUSH_GENERIC)
+pvrsrvkm-y += \
+ services/server/common/cache_generic.o \
+ generated/cachegeneric_bridge/server_cachegeneric_bridge.o
+endif
+
+ifeq ($(SUPPORT_SECURE_EXPORT),1)
+pvrsrvkm-y += \
+ services/server/env/linux/ossecure_export.o \
+ generated/smm_bridge/server_smm_bridge.o \
+ generated/syncsexport_bridge/server_syncsexport_bridge.o
+endif
+ifeq ($(SUPPORT_INSECURE_EXPORT),1)
+pvrsrvkm-y += \
+ generated/syncexport_bridge/server_syncexport_bridge.o
+endif
+
+ifeq ($(SUPPORT_ION),1)
+pvrsrvkm-y += generated/dmabuf_bridge/server_dmabuf_bridge.o
+pvrsrvkm-y += services/server/env/linux/physmem_dmabuf.o
+endif # SUPPORT_ION
+
+#ccflags-y += \
+# -mno-soft-float
+
+#dc_pdp-y += \
+# dc_pdp/dc_pdp.o \
+# dc_pdp/pdp_osfuncs.o \
+# dc_osfuncs.o
+
+pvrsrvkm-y += \
+ system/$(PVR_SYSTEM)/sysconfig.o
+# system/common/pci_support.o
+
+ifeq ($(PVR_SYSTEM),rgx_tc)
+pvrsrvkm-y += system/$(PVR_SYSTEM)/apollo_flasher_linux.o
+endif
+
+ifeq ($(PVR_SYSTEM),rk3368)
+pvrsrvkm-y += system/$(PVR_SYSTEM)/rk_init.o
+endif
+
+#ifneq ($(SUPPORT_DRM),1)
+#pvrsrvkm-y += system/common/interrupt_support.o
+#endif
+
+ifeq ($(SUPPORT_ION),1)
+ifeq ($(LMA),1)
+# For LMA, use the TC-specific ion heap.
+pvrsrvkm-y += \
+ system/$(PVR_SYSTEM)/ion_support.o \
+ system/common/ion_lma_heap.o
+else
+# For UMA, use the generic ion support code, which creates heaps from system
+# memory.
+#pvrsrvkm-y += \
+# system/common/ion_support_generic.o
+endif # LMA
+endif # SUPPORT_ION
+
+dbgdrv-y += \
+ tools/services/debug/dbgdriv/common/dbgdriv.o \
+ tools/services/debug/dbgdriv/common/ioctl.o \
+ tools/services/debug/dbgdriv/common/handle.o \
+ tools/services/debug/dbgdriv/linux/main.o \
+ tools/services/debug/dbgdriv/linux/hostfunc.o
+
diff --git a/drivers/gpu/rogue/README b/drivers/gpu/rogue/README
new file mode 100644
index 000000000000..8579ae18896c
--- /dev/null
+++ b/drivers/gpu/rogue/README
@@ -0,0 +1,32 @@
+Rogue Embedded Systems DDK for Linux kernel.
+Copyright (C) Imagination Technologies Ltd. All rights reserved.
+======================================================================
+
+
+About
+-------------------------------------------
+
+This is the Imagination Technologies Rogue DDK for the Linux kernel.
+
+
+License
+-------------------------------------------
+
+You may use, distribute and copy this software under the terms of the MIT
+license. Details of this license can be found in the file "MIT-COPYING".
+
+Alternatively, you may use, distribute and copy this software under the terms
+of the GNU General Public License version 2. The full GNU General Public
+License version 2 can be found in the file "GPL-COPYING".
+
+
+Build and Install Instructions
+-------------------------------------------
+
+For details see the "INSTALL" file and the platform guide.
+
+Contact information:
+-------------------------------------------
+
+Imagination Technologies Ltd. <gpl-support@imgtec.com>
+Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
diff --git a/drivers/gpu/rogue/build/linux/bits.mk b/drivers/gpu/rogue/build/linux/bits.mk
new file mode 100644
index 000000000000..e993c636d2d3
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/bits.mk
@@ -0,0 +1,125 @@
+########################################################################### ###
+#@Title Useful special targets which don't build anything
+#@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.
+### ###########################################################################
+
+ifneq ($(filter dumpvar-%,$(MAKECMDGOALS)),)
+dumpvar-%: ;
+$(foreach _var_to_dump,$(patsubst dumpvar-%,%,$(filter dumpvar-%,$(MAKECMDGOALS))),$(info $(if $(filter undefined,$(origin $(_var_to_dump))),# $$($(_var_to_dump)) is not set,$(_var_to_dump) := $($(_var_to_dump)))))
+endif
+
+ifneq ($(filter whereis-%,$(MAKECMDGOALS)),)
+whereis-%: ;
+$(foreach _module_to_find,$(patsubst whereis-%,%,$(filter whereis-%,$(MAKECMDGOALS))),$(info $(if $(INTERNAL_MAKEFILE_FOR_MODULE_$(_module_to_find)),$(INTERNAL_MAKEFILE_FOR_MODULE_$(_module_to_find)),# No module $(_module_to_find))))
+endif
+
+ifneq ($(filter whatis-%,$(MAKECMDGOALS)),)
+whatis-$(HOST_OUT)/%: ;
+whatis-$(TARGET_PRIMARY_OUT)/%: ;
+whatis-$(TARGET_NEUTRAL_OUT)/%: ;
+$(foreach _file_to_find,$(patsubst whatis-%,%,$(filter whatis-%,$(MAKECMDGOALS))),$(info $(strip $(foreach _m,$(ALL_MODULES),$(if $(filter $(_file_to_find),$(INTERNAL_TARGETS_FOR_$(_m))),$(_file_to_find) is in $(_m) which is defined in $(INTERNAL_MAKEFILE_FOR_MODULE_$(_m)),)))))
+endif
+
+.PHONY: ls-modules
+ls-modules:
+ @: $(foreach _m,$(ALL_MODULES),$(info $($(_m)_type) $(_m) $(patsubst $(TOP)/%,%,$(INTERNAL_MAKEFILE_FOR_MODULE_$(_m)))))
+
+.PHONY: ls-types
+ls-types:
+ @: $(info $(sort $(patsubst host_%,%,$(foreach _m,$(ALL_MODULES),$($(_m)_type)))))
+
+ifeq ($(strip $(MAKECMDGOALS)),visualise)
+FORMAT ?= xlib
+GRAPHVIZ ?= neato
+visualise: $(OUT)/MAKE_RULES.dot
+ $(GRAPHVIZ) -T$(FORMAT) -o $(OUT)/MAKE_RULES.$(FORMAT) $<
+$(OUT)/MAKE_RULES.dot: $(OUT)/MAKE_RULES
+ perl $(MAKE_TOP)/tools/depgraph.pl -t $(TOP) -g $(firstword $(GRAPHVIZ)) $(OUT)/MAKE_RULES >$(OUT)/MAKE_RULES.dot
+$(OUT)/MAKE_RULES: $(ALL_MAKEFILES)
+ -$(MAKE) -C $(TOP) -f $(MAKE_TOP)/toplevel.mk TOP=$(TOP) OUT=$(OUT) ls-modules -qp >$(OUT)/MAKE_RULES 2>&1
+else
+visualise:
+ @: $(error visualise specified along with other goals. This is not supported)
+endif
+
+.PHONY: help confighelp
+help:
+ @echo 'Build targets'
+ @echo ' make, make build Build all components of the build'
+ @echo ' make components Build only the user-mode components'
+ @echo ' make kbuild Build only the kernel-mode components'
+ @echo " make docs Build the build's supporting documentation"
+ @echo ' make MODULE Build the module MODULE and all of its dependencies'
+ @echo ' make binary_.../target/libsomething.so'
+ @echo ' Build a particular file (including intermediates)'
+ @echo 'Variables'
+ @echo ' make V=1 ... Print the commands that are executed'
+ @echo ' make W=1 ... Enable extra compiler warnings'
+ @echo ' make D=opt ... Set build system debug option (D=help for a list)'
+ @echo ' make OUT=dir ... Place output+intermediates in specified directory'
+ @echo ' make CHECK=cmd ... Check source with static analyser or other tool'
+ @echo ' EXCLUDED_APIS=... List of APIs to remove from the build'
+ @echo ' make SOMEOPTION=1 ... Set configuration options (see "make confighelp")'
+ @echo ' Defaults are set by $(PVR_BUILD_DIR)/Makefile'
+ @echo 'Clean targets'
+ @echo ' make clean Remove output files for the current build'
+ @echo ' make clobber As "make clean", but remove build config too'
+ @echo ' make clean-MODULE Clean (or clobber) only files for MODULE'
+ @echo ''
+ @echo 'Special targets'
+ @echo ' make whereis-MODULE Show the path to the Linux.mk defining MODULE'
+ @echo ' make whatis-FILE Show which module builds an output FILE'
+ @echo ' make ls-modules List all modules defined by makefiles'
+
+# This rule runs in the configuration stage, in config/help.mk. Make a dummy
+# target here to suppress "no rule to make target 'confighelp' messages.
+confighelp: ;
+
+ifneq ($(filter help,$(D)),)
+empty :=
+space := $(empty) $(empty)
+$(info Debug options)
+$(info $(space)D=modules dump module info)
+$(info $(space)D=config dump all config options + type and origin)
+$(info $(space)D=freeze-config prevent config changes)
+$(info $(space)D=config-changes dump diffs when config changes)
+$(info $(space)D=nobuild stop before running the main build)
+$(info Options can be combined: make D=freeze-config,config-changes)
+$(error D=help given)
+endif
diff --git a/drivers/gpu/rogue/build/linux/buildvars.mk b/drivers/gpu/rogue/build/linux/buildvars.mk
new file mode 100644
index 000000000000..25077d90baf6
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/buildvars.mk
@@ -0,0 +1,279 @@
+########################################################################### ###
+#@Title Define global variables
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@Description This file is read once at the start of the build, after reading
+# in config.mk. It should define the non-MODULE_* variables used
+# in commands, like ALL_CFLAGS
+#@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.
+### ###########################################################################
+
+# NOTE: You must *not* use the cc-option et al macros in COMMON_FLAGS,
+# COMMON_CFLAGS or COMMON_USER_FLAGS. These flags are shared between
+# host and target, which might use compilers with different capabilities.
+
+# ANOTHER NOTE: All flags here must be architecture-independent (i.e. no
+# -march or toolchain include paths)
+
+# These flags are used for kernel, User C and User C++
+#
+COMMON_FLAGS := -W -Wall
+
+# Some GCC warnings are C only, so we must mask them from C++
+#
+COMMON_CFLAGS := $(COMMON_FLAGS) \
+ -Wdeclaration-after-statement -Wno-format-zero-length \
+ -Wmissing-prototypes -Wstrict-prototypes
+
+# User C and User C++ optimization control. Does not affect kernel.
+#
+ifeq ($(BUILD),debug)
+COMMON_USER_FLAGS := -O0
+else
+OPTIM ?= -O2
+ifeq ($(USE_LTO),1)
+COMMON_USER_FLAGS := $(OPTIM) -flto
+else
+COMMON_USER_FLAGS := $(OPTIM)
+endif
+endif
+
+# GCOV support for user-mode coverage statistics
+#
+ifeq ($(GCOV_BUILD),on)
+COMMON_USER_FLAGS += -fprofile-arcs -ftest-coverage
+endif
+
+# Driver has not yet been audited for aliasing issues
+#
+COMMON_USER_FLAGS += -fno-strict-aliasing
+
+# We always enable debugging. Either the release binaries are stripped
+# and the symbols put in the symbolpackage, or we're building debug.
+#
+COMMON_USER_FLAGS += -g
+
+# User C and User C++ warning flags
+#
+COMMON_USER_FLAGS += \
+ -Wpointer-arith -Wunused-parameter \
+ -Wmissing-format-attribute
+
+# Additional warnings, and optional warnings.
+#
+TESTED_TARGET_USER_FLAGS := \
+ $(call cc-option,-Wno-missing-field-initializers) \
+ $(call cc-option,-fdiagnostics-show-option) \
+ $(call cc-option,-Wno-self-assign) \
+ $(call cc-option,-Wno-parentheses-equality)
+TESTED_HOST_USER_FLAGS := \
+ $(call host-cc-option,-Wno-missing-field-initializers) \
+ $(call host-cc-option,-fdiagnostics-show-option) \
+ $(call host-cc-option,-Wno-self-assign) \
+ $(call host-cc-option,-Wno-parentheses-equality)
+
+# These flags are clang-specific.
+# -Wno-unused-command-line-argument works around a buggy interaction
+# with ccache, see https://bugzilla.samba.org/show_bug.cgi?id=8118
+# -fcolor-diagnostics force-enables colored error messages which
+# get disabled when ccache is piped through ccache.
+#
+TESTED_TARGET_USER_FLAGS += \
+ $(call cc-option,-Qunused-arguments) \
+ $(call cc-option,-fcolor-diagnostics)
+TESTED_HOST_USER_FLAGS += \
+ $(call host-cc-option,-Qunused-arguments) \
+ $(call host-cc-option,-fcolor-diagnostics)
+
+ifeq ($(W),1)
+TESTED_TARGET_USER_FLAGS += \
+ $(call cc-option,-Wbad-function-cast) \
+ $(call cc-option,-Wcast-qual) \
+ $(call cc-option,-Wcast-align) \
+ $(call cc-option,-Wconversion) \
+ $(call cc-option,-Wdisabled-optimization) \
+ $(call cc-option,-Wlogical-op) \
+ $(call cc-option,-Wmissing-declarations) \
+ $(call cc-option,-Wmissing-include-dirs) \
+ $(call cc-option,-Wnested-externs) \
+ $(call cc-option,-Wold-style-definition) \
+ $(call cc-option,-Woverlength-strings) \
+ $(call cc-option,-Wpacked) \
+ $(call cc-option,-Wpacked-bitfield-compat) \
+ $(call cc-option,-Wpadded) \
+ $(call cc-option,-Wredundant-decls) \
+ $(call cc-option,-Wshadow) \
+ $(call cc-option,-Wswitch-default) \
+ $(call cc-option,-Wvla) \
+ $(call cc-option,-Wwrite-strings)
+TESTED_HOST_USER_FLAGS += \
+ $(call host-cc-option,-Wbad-function-cast) \
+ $(call host-cc-option,-Wcast-qual) \
+ $(call host-cc-option,-Wcast-align) \
+ $(call host-cc-option,-Wconversion) \
+ $(call host-cc-option,-Wdisabled-optimization) \
+ $(call host-cc-option,-Wlogical-op) \
+ $(call host-cc-option,-Wmissing-declarations) \
+ $(call host-cc-option,-Wmissing-include-dirs) \
+ $(call host-cc-option,-Wnested-externs) \
+ $(call host-cc-option,-Wold-style-definition) \
+ $(call host-cc-option,-Woverlength-strings) \
+ $(call host-cc-option,-Wpacked) \
+ $(call host-cc-option,-Wpacked-bitfield-compat) \
+ $(call host-cc-option,-Wpadded) \
+ $(call host-cc-option,-Wredundant-decls) \
+ $(call host-cc-option,-Wshadow) \
+ $(call host-cc-option,-Wswitch-default) \
+ $(call host-cc-option,-Wvla) \
+ $(call host-cc-option,-Wwrite-strings)
+endif
+
+TESTED_TARGET_USER_FLAGS += \
+ $(call cc-optional-warning,-Wunused-but-set-variable)
+TESTED_HOST_USER_FLAGS += \
+ $(call host-cc-optional-warning,-Wunused-but-set-variable)
+
+KBUILD_FLAGS := \
+ -Wno-unused-parameter -Wno-sign-compare
+
+TESTED_KBUILD_FLAGS := \
+ $(call kernel-cc-option,-Wmissing-include-dirs) \
+ $(call kernel-cc-option,-Wno-type-limits) \
+ $(call kernel-cc-option,-Wno-pointer-arith) \
+ $(call kernel-cc-option,-Wno-aggregate-return) \
+ $(call kernel-cc-option,-Wno-unused-but-set-variable) \
+ $(call kernel-cc-optional-warning,-Wbad-function-cast) \
+ $(call kernel-cc-optional-warning,-Wcast-qual) \
+ $(call kernel-cc-optional-warning,-Wcast-align) \
+ $(call kernel-cc-optional-warning,-Wconversion) \
+ $(call kernel-cc-optional-warning,-Wdisabled-optimization) \
+ $(call kernel-cc-optional-warning,-Wlogical-op) \
+ $(call kernel-cc-optional-warning,-Wmissing-declarations) \
+ $(call kernel-cc-optional-warning,-Wmissing-include-dirs) \
+ $(call kernel-cc-optional-warning,-Wnested-externs) \
+ $(call kernel-cc-optional-warning,-Wno-missing-field-initializers) \
+ $(call kernel-cc-optional-warning,-Wold-style-definition) \
+ $(call kernel-cc-optional-warning,-Woverlength-strings) \
+ $(call kernel-cc-optional-warning,-Wpacked) \
+ $(call kernel-cc-optional-warning,-Wpacked-bitfield-compat) \
+ $(call kernel-cc-optional-warning,-Wpadded) \
+ $(call kernel-cc-optional-warning,-Wredundant-decls) \
+ $(call kernel-cc-optional-warning,-Wshadow) \
+ $(call kernel-cc-optional-warning,-Wswitch-default) \
+ $(call kernel-cc-optional-warning,-Wvla) \
+ $(call kernel-cc-optional-warning,-Wwrite-strings)
+
+# User C only
+#
+ALL_CFLAGS := \
+ $(COMMON_USER_FLAGS) $(COMMON_CFLAGS) $(TESTED_TARGET_USER_FLAGS) \
+ $(SYS_CFLAGS)
+ALL_HOST_CFLAGS := \
+ $(COMMON_USER_FLAGS) $(COMMON_CFLAGS) $(TESTED_HOST_USER_FLAGS)
+
+# User C++ only
+#
+ALL_CXXFLAGS := \
+ -fno-rtti -fno-exceptions \
+ $(COMMON_USER_FLAGS) $(COMMON_FLAGS) $(TESTED_TARGET_USER_FLAGS) \
+ $(SYS_CXXFLAGS)
+ALL_HOST_CXXFLAGS := \
+ -fno-rtti -fno-exceptions \
+ $(COMMON_USER_FLAGS) $(COMMON_FLAGS) $(TESTED_HOST_USER_FLAGS)
+
+# Workaround for some target clangs that don't support -O0 w/ PIC.
+#
+ifeq ($(cc-is-clang),true)
+ALL_CFLAGS := $(patsubst -O0,-O1,$(ALL_CFLAGS))
+ALL_CXXFLAGS := $(patsubst -O0,-O1,$(ALL_CXXFLAGS))
+endif
+
+# Add GCOV_DIR just for target
+#
+ifeq ($(GCOV_BUILD),on)
+ifneq ($(GCOV_DIR),)
+ALL_CFLAGS += -fprofile-dir=$(GCOV_DIR)
+ALL_CXXFLAGS += -fprofile-dir=$(GCOV_DIR)
+endif
+endif
+
+# Kernel C only
+#
+ALL_KBUILD_CFLAGS := $(COMMON_CFLAGS) $(KBUILD_FLAGS) $(TESTED_KBUILD_FLAGS)
+
+# User C and C++
+#
+# NOTE: ALL_HOST_LDFLAGS should probably be using -rpath-link too, and if we
+# ever need to support building host shared libraries, it's required.
+#
+# We can't use it right now because we want to support non-GNU-compatible
+# linkers like the Darwin 'ld' which doesn't support -rpath-link.
+#
+# For the same reason (Darwin 'ld') don't bother checking for text
+# relocations in host binaries.
+#
+ALL_HOST_LDFLAGS :=
+ALL_LDFLAGS := -Wl,--warn-shared-textrel
+
+ifeq ($(GCOV_BUILD),on)
+ALL_LDFLAGS += -fprofile-arcs
+ALL_HOST_LDFLAGS += -fprofile-arcs
+endif
+
+ALL_LDFLAGS += $(SYS_LDFLAGS)
+
+# This variable contains a list of all modules built by kbuild
+ALL_KBUILD_MODULES :=
+
+# This variable contains a list of all modules which contain C++ source files
+ALL_CXX_MODULES :=
+
+# Toolchain triple for cross environment
+CROSS_TRIPLE := $(patsubst %-,%,$(CROSS_COMPILE))
+
+ifneq ($(TOOLCHAIN),)
+$(warning **********************************************)
+$(warning The TOOLCHAIN option has been removed, but)
+$(warning you have it set (via $(origin TOOLCHAIN)))
+$(warning **********************************************)
+endif
+
+# We need the glibc version to generate the cache names for LLVM and XOrg components.
+ifeq ($(CROSS_COMPILE),)
+LIBC_VERSION_PROBE := $(shell ldd $(shell which true) | awk '/libc.so/{print $$3'} )
+LIBC_VERSION := $(shell $(LIBC_VERSION_PROBE)| tr -d '(),' | head -1)
+endif
diff --git a/drivers/gpu/rogue/build/linux/commands.mk b/drivers/gpu/rogue/build/linux/commands.mk
new file mode 100644
index 000000000000..3ab5fcb2fe54
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/commands.mk
@@ -0,0 +1,357 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+# from-one-* recipes make a thing from one source file, so they use $<. Others
+# use $(MODULE_something) instead of $^
+
+# We expect that MODULE_*FLAGS contains all the flags we need, including the
+# flags for all modules (like $(ALL_CFLAGS) and $(ALL_HOST_CFLAGS)), and
+# excluding flags for include search dirs or for linking libraries. The
+# exceptions are ALL_EXE_LDFLAGS and ALL_LIB_LDFLAGS, since they depend on the
+# type of thing being linked, so they appear in the commands below
+
+define host-o-from-one-c
+$(if $(V),,@echo " HOST_CC " $(call relative-to-top,$<))
+$(MODULE_CC) -MD -MF $(patsubst %.o,%.d,$@) -c $(MODULE_CFLAGS) \
+ $(MODULE_INCLUDE_FLAGS) -include $(CONFIG_H) $< -o $@
+endef
+
+define target-o-from-one-c
+$(if $(V),,@echo " CC " $(call relative-to-top,$<))
+$(MODULE_CC) -MD -MF $(patsubst %.o,%.d,$@) -c $(MODULE_CFLAGS) \
+ $(MODULE_INCLUDE_FLAGS) -include $(CONFIG_H) $< -o $@
+endef
+
+define host-o-from-one-cxx
+$(if $(V),,@echo " HOST_CXX" $(call relative-to-top,$<))
+$(MODULE_CXX) -MD -MF $(patsubst %.o,%.d,$@) -c $(MODULE_CXXFLAGS) \
+ $(MODULE_INCLUDE_FLAGS) -include $(CONFIG_H) $< -o $@
+endef
+
+define target-o-from-one-cxx
+$(if $(V),,@echo " CXX " $(call relative-to-top,$<))
+$(MODULE_CXX) -MD -MF $(patsubst %.o,%.d,$@) -c $(MODULE_CXXFLAGS) \
+ $(MODULE_INCLUDE_FLAGS) -include $(CONFIG_H) $< -o $@
+endef
+
+define host-executable-from-o
+$(if $(V),,@echo " HOST_LD " $(call relative-to-top,$@))
+$(MODULE_CC) $(MODULE_LDFLAGS) \
+ -o $@ $(sort $(MODULE_ALL_OBJECTS)) $(MODULE_LIBRARY_DIR_FLAGS) \
+ $(MODULE_LIBRARY_FLAGS)
+endef
+
+define host-executable-cxx-from-o
+$(if $(V),,@echo " HOST_LD " $(call relative-to-top,$@))
+$(MODULE_CXX) $(MODULE_LDFLAGS) \
+ -o $@ $(sort $(MODULE_ALL_OBJECTS)) $(MODULE_LIBRARY_DIR_FLAGS) \
+ $(MODULE_LIBRARY_FLAGS)
+endef
+
+define target-executable-from-o
+$(if $(V),,@echo " LD " $(call relative-to-top,$@))
+$(MODULE_CC) \
+ $(MODULE_EXE_LDFLAGS) $(MODULE_LDFLAGS) -o $@ \
+ $(MODULE_EXE_CRTBEGIN) $(MODULE_ALL_OBJECTS) $(MODULE_EXE_CRTEND) \
+ $(MODULE_LIBRARY_DIR_FLAGS) $(MODULE_LIBRARY_FLAGS) $(MODULE_LIBGCC)
+endef
+
+define target-executable-cxx-from-o
+$(if $(V),,@echo " LD " $(call relative-to-top,$@))
+$(MODULE_CXX) \
+ $(MODULE_EXE_LDFLAGS) $(MODULE_LDFLAGS) -o $@ \
+ $(MODULE_EXE_CRTBEGIN) $(MODULE_ALL_OBJECTS) $(MODULE_EXE_CRTEND) \
+ $(MODULE_LIBRARY_DIR_FLAGS) $(MODULE_LIBRARY_FLAGS) $(MODULE_LIBGCC)
+endef
+
+define target-shared-library-from-o
+$(if $(V),,@echo " LD " $(call relative-to-top,$@))
+$(MODULE_CC) -shared -Wl,-Bsymbolic \
+ $(MODULE_LIB_LDFLAGS) $(MODULE_LDFLAGS) -o $@ \
+ $(MODULE_LIB_CRTBEGIN) $(MODULE_ALL_OBJECTS) $(MODULE_LIB_CRTEND) \
+ $(MODULE_LIBRARY_DIR_FLAGS) $(MODULE_LIBRARY_FLAGS) $(MODULE_LIBGCC)
+endef
+
+define host-shared-library-from-o
+$(if $(V),,@echo " HOST_LD " $(call relative-to-top,$@))
+$(MODULE_CC) -shared -Wl,-Bsymbolic \
+ $(MODULE_LDFLAGS) -o $@ \
+ $(sort $(MODULE_ALL_OBJECTS)) \
+ $(MODULE_LIBRARY_DIR_FLAGS) $(MODULE_LIBRARY_FLAGS)
+endef
+
+# If there were any C++ source files in a shared library, we use one of
+# these recipes, which run the C++ compiler to link the final library
+define target-shared-library-cxx-from-o
+$(if $(V),,@echo " LD " $(call relative-to-top,$@))
+$(MODULE_CXX) -shared -Wl,-Bsymbolic \
+ $(MODULE_LIB_LDFLAGS) $(MODULE_LDFLAGS) -o $@ \
+ $(MODULE_LIB_CRTBEGIN) $(MODULE_ALL_OBJECTS) $(MODULE_LIB_CRTEND) \
+ $(MODULE_LIBRARY_DIR_FLAGS) $(MODULE_LIBRARY_FLAGS) $(MODULE_LIBGCC)
+endef
+
+define host-shared-library-cxx-from-o
+$(if $(V),,@echo " HOST_LD " $(call relative-to-top,$@))
+$(MODULE_CXX) -shared -Wl,-Bsymbolic \
+ $(MODULE_LDFLAGS) -o $@ \
+ $(sort $(MODULE_ALL_OBJECTS)) \
+ $(MODULE_LIBRARY_DIR_FLAGS) $(MODULE_LIBRARY_FLAGS)
+endef
+
+define host-copy-debug-information
+$(HOST_OBJCOPY) --only-keep-debug $@ $(basename $@).dbg
+endef
+
+define host-strip-debug-information
+$(HOST_STRIP) --strip-unneeded $@
+endef
+
+define host-add-debuglink
+$(if $(V),,@echo " DBGLINK " $(call relative-to-top,$(basename $@).dbg))
+$(HOST_OBJCOPY) --add-gnu-debuglink=$(basename $@).dbg $@
+endef
+
+define target-copy-debug-information
+$(OBJCOPY) --only-keep-debug $@ $(basename $@).dbg
+endef
+
+define target-strip-debug-information
+$(STRIP) --strip-unneeded $@
+endef
+
+define target-add-debuglink
+$(if $(V),,@echo " DBGLINK " $(call relative-to-top,$(basename $@).dbg))
+$(OBJCOPY) --add-gnu-debuglink=$(basename $@).dbg $@
+endef
+
+define host-static-library-from-o
+$(if $(V),,@echo " HOST_AR " $(call relative-to-top,$@))
+$(HOST_AR) cru $@ $(sort $(MODULE_ALL_OBJECTS))
+endef
+
+define target-static-library-from-o
+$(if $(V),,@echo " AR " $(call relative-to-top,$@))
+$(AR) cru $@ $(sort $(MODULE_ALL_OBJECTS))
+endef
+
+define tab-c-from-y
+$(if $(V),,@echo " BISON " $(call relative-to-top,$<))
+$(BISON) $(MODULE_BISON_FLAGS) -o $@ -d $<
+endef
+
+define l-c-from-l
+$(if $(V),,@echo " FLEX " $(call relative-to-top,$<))
+$(FLEX) $(MODULE_FLEX_FLAGS) -o$@ $<
+endef
+
+define l-cc-from-l
+$(if $(V),,@echo " FLEXXX " $(call relative-to-top,$<))
+$(FLEXXX) $(MODULE_FLEXXX_FLAGS) -o$@ $<
+endef
+
+define clean-dirs
+$(if $(V),,@echo " RM " $(call relative-to-top,$(MODULE_DIRS_TO_REMOVE)))
+$(RM) -rf $(MODULE_DIRS_TO_REMOVE)
+endef
+
+define make-directory
+$(MKDIR) -p $@
+endef
+
+ifeq ($(DISABLE_CHECK_EXPORTS),)
+define check-exports
+endef
+else
+define check-exports
+endef
+endif
+
+# Check a source file with the program specified in $(CHECK).
+# If $(CHECK) is empty, don't do anything.
+ifeq ($(CHECK),)
+check-src :=
+else
+define check-src-1
+$(if $(V),,@echo " CHECK " $(call relative-to-top,$<))
+$(if $(IGNORE_CHECK_ERRORS),-,)$(CHECK) $(MODULE_INCLUDE_FLAGS) \
+ $(if $(CHECK_NO_CONFIG_H),,-include $(CONFIG_H)) \
+ $(filter -D%,$(MODULE_CFLAGS)) \
+ $(CHECKFLAGS) $<
+endef
+# If CHECK_ONLY is set, only check files matching a Make pattern.
+# e.g. CHECK_ONLY=opengles1/%.c
+define check-src
+$(if $(and $(if $(CHECK_ONLY),$(filter $(CHECK_ONLY),$<),true), \
+ $(if $(CHECK_EXCLUDE),$(filter-out $(CHECK_EXCLUDE),$<),true)),$(check-src-1),@:)
+endef
+endif
+
+# Programs used in recipes
+
+BISON ?= bison
+CC ?= gcc
+CC_SECONDARY ?= $(CC)
+CROSS_COMPILE_SECONDARY ?= $(CROSS_COMPILE)
+CXX ?= g++
+CXX_SECONDARY ?= $(CXX)
+HOST_CC ?= gcc
+HOST_CXX ?= g++
+JAR ?= jar
+JAVA ?= java
+JAVAC ?= javac
+PYTHON ?= python
+ZIP ?= zip
+
+ifeq ($(USE_CCACHE),1)
+CCACHE ?= ccache
+endif
+ifeq ($(USE_DISTCC),1)
+DISTCC ?= distcc
+endif
+
+# Define CHMOD and CC_CHECK first so we can use cc-is-clang
+#
+override CHMOD := $(if $(V),,@)chmod
+override CC_CHECK := $(if $(V),,@)$(MAKE_TOP)/tools/cc-check.sh
+
+# If clang is detected, the compiler name is invariant but CROSS_COMPILE
+# is reflected in the use of -target. For GCC this is always encoded into
+# the binary. If CROSS_COMPILE is not set we can skip this.
+#
+# If we're doing a build with multiple target architectures, we might need
+# two separate compilers to build binaries for each architecture. In this
+# case, CROSS_COMPILE and CROSS_COMPILE_SECONDARY are the cross compiler
+# prefix for the two compilers - $(CC) and $(CC_SECONDARY).
+#
+# Set the secondary compiler first before we overwrite $(CC).
+#
+
+ifneq ($(CROSS_COMPILE_SECONDARY),)
+ ifeq ($(cc-is-clang),true)
+ override CC_SECONDARY := \
+ $(CC_SECONDARY) \
+ -target $(patsubst %-,%,$(CROSS_COMPILE_SECONDARY)) \
+ -B$(dir $(shell which $(CROSS_COMPILE_SECONDARY)gcc))
+ override CXX_SECONDARY := \
+ $(CXX_SECONDARY) \
+ -target $(patsubst %-,%,$(CROSS_COMPILE_SECONDARY)) \
+ -B$(dir $(shell which $(CROSS_COMPILE_SECONDARY)gcc))
+ else
+ ifeq ($(origin CC_SECONDARY),file)
+ override CC_SECONDARY := $(CROSS_COMPILE_SECONDARY)$(CC_SECONDARY)
+ endif
+ ifeq ($(origin CXX_SECONDARY),file)
+ override CXX_SECONDARY := $(CROSS_COMPILE_SECONDARY)$(CXX_SECONDARY)
+ endif
+ endif
+endif
+
+# Apply compiler wrappers and V=1 handling
+override CC_SECONDARY := $(if $(V),,@)$(CCACHE)$(DISTCC) $(CC_SECONDARY)
+override CXX_SECONDARY := $(if $(V),,@)$(CCACHE)$(DISTCC) $(CXX_SECONDARY)
+
+ifneq ($(CROSS_COMPILE),)
+ ifeq ($(cc-is-clang),true)
+ override CC := \
+ $(CC) \
+ -target $(patsubst %-,%,$(CROSS_COMPILE)) \
+ -B$(dir $(shell which $(CROSS_COMPILE)gcc))
+ override CXX := \
+ $(CXX) \
+ -target $(patsubst %-,%,$(CROSS_COMPILE)) \
+ -B$(dir $(shell which $(CROSS_COMPILE)gcc))
+ else
+ ifeq ($(origin CC),file)
+ override CC := $(CROSS_COMPILE)$(CC)
+ endif
+ ifeq ($(origin CXX),file)
+ override CXX := $(CROSS_COMPILE)$(CXX)
+ endif
+ endif
+else
+ $(if $(CROSS_COMPILE_SECONDARY),$(error CROSS_COMPILE_SECONDARY is set but CROSS_COMPILE is empty))
+endif
+
+# Apply compiler wrappers and V=1 handling
+override CC := $(if $(V),,@)$(CCACHE)$(DISTCC) $(CC)
+override CXX := $(if $(V),,@)$(CCACHE)$(DISTCC) $(CXX)
+
+override AR := $(if $(V),,@)$(CROSS_COMPILE)ar
+override BISON := $(if $(V),,@)$(BISON)
+override BZIP2 := $(if $(V),,@)bzip2 -9
+override CAT := $(if $(V),,@)cat
+override CHECK := $(if $(CHECK),$(if $(V),,@)$(CHECK),)
+override CP := $(if $(V),,@)cp
+override ECHO := $(if $(V),,@)echo
+override FLEX := $(if $(V),,@)flex
+override FLEXXX := $(if $(V),,@)flex++
+override GREP := $(if $(V),,@)grep
+override HOST_AR := $(if $(V),,@)ar
+override HOST_CC := $(if $(V),,@)$(CCACHE) $(HOST_CC)
+override HOST_CXX := $(if $(V),,@)$(CCACHE) $(HOST_CXX)
+override HOST_OBJCOPY := $(if $(V),,@)objcopy
+override HOST_STRIP := $(if $(V),,@)strip
+override INSTALL := $(if $(V),,@)install
+override JAR := $(if $(V),,@)$(JAR)
+override JAVA := $(if $(V),,@)$(JAVA)
+override JAVAC := $(if $(V),,@)$(JAVAC)
+override LN := $(if $(V),,@)ln -f -s
+override M4 := $(if $(V),,@)m4
+override MKDIR := $(if $(V),,@)mkdir
+override MV := $(if $(V),,@)mv
+override OBJCOPY := $(if $(V),,@)$(CROSS_COMPILE)objcopy
+override PERL := $(if $(V),,@)perl
+override PSC := $(if $(V),,@)$(HOST_OUT)/psc_standalone
+override PYTHON := $(if $(V),,@)$(PYTHON)
+override RANLIB := $(if $(V),,@)$(CROSS_COMPILE)ranlib
+override RM := $(if $(V),,@)rm -f
+override ROGUEASM := $(if $(V),,@)$(HOST_OUT)/rogueasm
+override SED := $(if $(V),,@)sed
+override STRIP := $(if $(V),,@)$(CROSS_COMPILE)strip
+override TAR := $(if $(V),,@)tar
+override TOUCH := $(if $(V),,@)touch
+override TEST := $(if $(V),,@)test
+override VHD2INC := $(if $(V),,@)$(HOST_OUT)/vhd2inc
+override XXD := $(if $(V),,@)xxd
+override ZIP := $(if $(V),,@)$(ZIP)
+
+ifeq ($(SUPPORT_NEUTRINO_PLATFORM),1)
+include $(MAKE_TOP)/common/neutrino/commands_neutrino.mk
+endif
diff --git a/drivers/gpu/rogue/build/linux/common/3rdparty.mk b/drivers/gpu/rogue/build/linux/common/3rdparty.mk
new file mode 100644
index 000000000000..9fa667d61ef8
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/3rdparty.mk
@@ -0,0 +1,98 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+########################################################################### ###
+# Display class drivers
+########################################################################### ###
+
+ifeq ($(DISPLAY_CONTROLLER),dc_example)
+$(eval $(call TunableKernelConfigC,DC_EXAMPLE_WIDTH,))
+$(eval $(call TunableKernelConfigC,DC_EXAMPLE_HEIGHT,))
+$(eval $(call TunableKernelConfigC,DC_EXAMPLE_DPI,))
+$(eval $(call TunableKernelConfigC,DC_EXAMPLE_BIT_DEPTH,))
+$(eval $(call TunableKernelConfigC,DC_EXAMPLE_FBC_MODE,))
+endif
+
+ifeq ($(DISPLAY_CONTROLLER),dc_fbdev)
+$(eval $(call TunableKernelConfigC,DC_FBDEV_REFRESH,))
+
+$(eval $(call TunableKernelConfigC,DC_FBDEV_FORCE_XRGB8888,,\
+Force the dc_fbdev display driver to use XRGB8888. This is necessary_\
+when the underlying Linux framebuffer driver does not ignore alpha_\
+meaning an alpha value of 0 results in nothing being displayed._\
+))
+
+$(eval $(call TunableKernelConfigC,DC_FBDEV_NUM_PREFERRED_BUFFERS,,\
+The maximum number of display buffers the dc_fbdev display driver_\
+supports. The underlying Linux framebuffer driver must be capable_\
+of allocating sufficient memory for the number of buffers chosen._\
+))
+endif
+
+ifeq ($(DISPLAY_CONTROLLER),dc_pdp)
+$(eval $(call TunableKernelConfigC,DCPDP_WIDTH,))
+$(eval $(call TunableKernelConfigC,DCPDP_HEIGHT,))
+$(eval $(call TunableKernelConfigC,DCPDP_DPI,))
+$(eval $(call TunableKernelConfigC,DCPDP_DYNAMIC_GTF_TIMING,1))
+$(eval $(call TunableKernelConfigC,DCPDP_NO_INTERRUPTS,))
+endif
+
+ifeq ($(DISPLAY_CONTROLLER),adf_pdp)
+$(eval $(call TunableKernelConfigC,ADF_PDP_WIDTH,))
+$(eval $(call TunableKernelConfigC,ADF_PDP_HEIGHT,))
+endif
+
+########################################################################### ###
+# DRM display drivers
+########################################################################### ###
+
+ifeq ($(DISPLAY_CONTROLLER),dc_drmfbdev)
+$(eval $(call TunableKernelConfigC,DC_FBDEV_FORCE_XRGB8888,,\
+Force the dc_fbdev display driver to use XRGB8888. This is necessary_\
+when the underlying Linux framebuffer driver does not ignore alpha_\
+meaning an alpha value of 0 results in nothing being displayed._\
+))
+
+$(eval $(call TunableKernelConfigC,DC_FBDEV_NUM_PREFERRED_BUFFERS,,\
+The maximum number of display buffers the dc_fbdev display driver_\
+supports. The underlying Linux framebuffer driver must be capable_\
+of allocating sufficient memory for the number of buffers chosen._\
+))
+endif
diff --git a/drivers/gpu/rogue/build/linux/common/android/arch.mk b/drivers/gpu/rogue/build/linux/common/android/arch.mk
new file mode 100644
index 000000000000..2df0daa8e655
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/android/arch.mk
@@ -0,0 +1,100 @@
+########################################################################### ###
+#@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 ../common/android/platform_version.mk
+
+# Now we have included the platform_version.mk file, we know we have a
+# correctly configured OUT_DIR and can probe it to figure out our
+# architecture. For backwards compatibility with KitKat, use the deprecated
+# ro.product.cpu.abi (primary architecture) property instead of abilist64.
+
+$(eval $(subst #,$(newline),$(shell cat $(BUILD_PROP) | \
+ grep '^ro.product.cpu.abi=\|^ro.product.cpu.abilist32=' | \
+ sed -e 's,ro.product.cpu.abi=,JNI_CPU_ABI=,' \
+ -e 's,ro.product.cpu.abilist32=,JNI_CPU_ABI_2ND=,' | \
+ tr ',' ' ' | tr '\n' '#')))
+
+# If ARCH is set, use that to remap to an "Android" ARCH..
+ANDROID_ARCH := $(filter arm arm64 mips mips64 x86 x86_64,$(ARCH))
+
+# x86 is special and has another legacy ARCH name which is remapped
+ifeq ($(ARCH),i386)
+ANDROID_ARCH := x86
+endif
+
+ifeq ($(ANDROID_ARCH),)
+# ..otherwise, try to use the ABI list to figure it out.
+ifneq ($(filter armeabi-v7a armeabi,$(JNI_CPU_ABI)),)
+ANDROID_ARCH=arm
+else ifneq ($(filter arm64-v8a,$(JNI_CPU_ABI)),)
+ANDROID_ARCH=arm64
+else ifneq ($(filter mips,$(JNI_CPU_ABI)),)
+ANDROID_ARCH=mips
+else ifneq ($(filter mips64,$(JNI_CPU_ABI)),)
+ANDROID_ARCH=mips64
+else ifneq ($(filter x86,$(JNI_CPU_ABI)),)
+ANDROID_ARCH=x86
+else ifneq ($(filter x86_64,$(JNI_CPU_ABI)),)
+ANDROID_ARCH=x86_64
+else
+$(error ARCH not set and JNI_CPU_ABI=$(JNI_CPU_ABI) was not remappable)
+endif
+endif
+
+JNI_CPU_ABI := $(word 1,$(JNI_CPU_ABI))
+JNI_CPU_ABI_2ND := $(word 1,$(JNI_CPU_ABI_2ND))
+
+include ../common/android/arch_common.mk
+
+ifneq ($(filter arm arm64 mips mips64,$(ANDROID_ARCH)),)
+LDM_PLATFORM ?= 1
+endif
+
+ifneq ($(filter x86 x86_64,$(ANDROID_ARCH)),)
+KERNEL_CROSS_COMPILE ?= undef
+endif
+
+ifneq ($(filter arm64 mips64 x86_64,$(ANDROID_ARCH)),)
+ifeq ($(MULTIARCH),)
+$(warning *** 64-bit architecture detected. Enabling MULTIARCH=1.)
+$(warning *** If you want a 64-bit only build, use MULTIARCH=64only.)
+export MULTIARCH := 1
+endif
+endif
diff --git a/drivers/gpu/rogue/build/linux/common/android/arch_common.mk b/drivers/gpu/rogue/build/linux/common/android/arch_common.mk
new file mode 100644
index 000000000000..9c8286a567ec
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/android/arch_common.mk
@@ -0,0 +1,77 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+SYS_CFLAGS := \
+ -fno-short-enums \
+ -funwind-tables \
+ -D__linux__
+SYS_INCLUDES := \
+ -isystem $(ANDROID_ROOT)/bionic/libc/include \
+ -isystem $(ANDROID_ROOT)/bionic/libc/kernel/uapi \
+ -isystem $(ANDROID_ROOT)/bionic/libm/include \
+ -isystem $(ANDROID_ROOT)/bionic/libthread_db/include \
+ -isystem $(ANDROID_ROOT)/external/libunwind/include \
+ -isystem $(ANDROID_ROOT)/external/openssl/include \
+ -isystem $(ANDROID_ROOT)/frameworks/base/include \
+ -isystem $(ANDROID_ROOT)/hardware/libhardware/include \
+ -isystem $(ANDROID_ROOT)/system/core/include \
+ -isystem $(ANDROID_ROOT)/system/core/adf/libadf/include \
+ -isystem $(ANDROID_ROOT)/system/core/adf/libadfhwc/include \
+ -isystem $(ANDROID_ROOT)/system/core/libsync/include \
+ -isystem $(ANDROID_ROOT)/system/core/libsync \
+ -isystem $(ANDROID_ROOT)/system/media/camera/include
+
+# Obsolete libc includes
+SYS_INCLUDES += \
+ -isystem $(ANDROID_ROOT)/bionic/libc/kernel/common \
+ -isystem $(ANDROID_ROOT)/bionic/libc/kernel/arch-$(ANDROID_ARCH)
+
+# The following include is a workaround for ICS 4.0.4 partial directory change
+SYS_INCLUDES += \
+ -isystem $(ANDROID_ROOT)/frameworks/base/native/include \
+ -isystem $(ANDROID_ROOT)/frameworks/native/include
+
+ifeq ($(_CLANG),true)
+SYS_INCLUDES := \
+ -nostdinc $(SYS_INCLUDES) \
+ -isystem $(ANDROID_ROOT)/external/clang/lib/Headers
+endif
+
+OPTIM := -O2
diff --git a/drivers/gpu/rogue/build/linux/common/android/extra_config.mk b/drivers/gpu/rogue/build/linux/common/android/extra_config.mk
new file mode 100644
index 000000000000..88c5002fadde
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/android/extra_config.mk
@@ -0,0 +1,69 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+$(eval $(call UserConfigMake,libpthread_ldflags,))
+$(eval $(call UserConfigMake,librt_ldflags,))
+$(eval $(call UserConfigMake,TARGET_ROOT,$(TARGET_ROOT)))
+$(eval $(call UserConfigMake,TARGET_DEVICE,$(TARGET_DEVICE)))
+
+$(eval $(call BothConfigMake,SUPPORT_ANDROID_PLATFORM,1))
+
+$(eval $(call BothConfigC,ANDROID,))
+
+$(eval $(call UserConfigC,SUPPORT_ANDROID_PLATFORM,1))
+
+# These are set automatically according to the platform version.
+$(eval $(call TunableBothConfigC,PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC,))
+$(eval $(call TunableBothConfigC,PVR_ANDROID_DISABLE_MULTI_SYNCS,))
+
+# These are user-tunable.
+
+
+$(eval $(call TunableBothConfigC,PVR_ANDROID_HAS_SW_INCOMPATIBLE_FRAMEBUFFER,,\
+Enable this to support running Android$(apos)s software GLES renderer_\
+with gralloc from the DDK._\
+))
+
+
+# These are set automatically according to the platform version.
+$(eval $(call TunableBothConfigMake,PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC,))
+
+# These are user-tunable.
+
diff --git a/drivers/gpu/rogue/build/linux/common/android/features.mk b/drivers/gpu/rogue/build/linux/common/android/features.mk
new file mode 100644
index 000000000000..eaf55294944a
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/android/features.mk
@@ -0,0 +1,230 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+# Basic support option tuning for Android
+#
+SUPPORT_ANDROID_PLATFORM := 1
+SUPPORT_OPENGLES1_V1_ONLY := 1
+DONT_USE_SONAMES := 1
+
+# Always print debugging after 5 seconds of no activity
+#
+CLIENT_DRIVER_DEFAULT_WAIT_RETRIES := 50
+
+# Android WSEGL is always the same
+#
+OPK_DEFAULT := libpvrANDROID_WSEGL.so
+
+# srvkm is always built
+#
+KERNEL_COMPONENTS := srvkm
+
+# Kernel modules are always installed here under Android
+#
+# Time:2014-08-26
+# Note:change module's path from /system/modules/ to /system/lib/modules/
+# Modifier: zxl
+PVRSRV_MODULE_BASEDIR := /system/lib/modules/
+
+# Enable secure FD export in Services
+#
+SUPPORT_SECURE_EXPORT := 1
+
+# It is no longer supported disable this for Android, but we can still
+# do so for the Linux DDK, so don't use NonTunableOption.
+#
+override SUPPORT_ION := 1
+
+# Show GPU activity in systrace
+#
+SUPPORT_GPUTRACE_EVENTS ?= 1
+
+##############################################################################
+# Unless overridden by the user, assume the RenderScript Compute API level
+# matches that of the SDK API_LEVEL.
+#
+RSC_API_LEVEL ?= $(API_LEVEL)
+ifeq ($(RSC_API_LEVEL),21)
+RSC_API_LEVEL := 20
+endif
+
+##############################################################################
+# JB MR1 introduces cross-process syncs associated with a fd.
+# This requires a new enough kernel version to have the base/sync driver.
+#
+#zxl:Temporarily closed for user build mode(Depend on libgui: LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC)
+EGL_EXTENSION_ANDROID_NATIVE_FENCE_SYNC ?= 1
+PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC ?= 1
+
+##############################################################################
+# Handle various platform includes for unittests
+#
+SYS_INCLUDES += \
+ -isystem $(ANDROID_ROOT)/libnativehelper/include/nativehelper
+SYS_KHRONOS_INCLUDES += \
+ -I$(ANDROID_ROOT)/frameworks/native/opengl/include
+
+##############################################################################
+# Android doesn't use these install script variables. They're still in place
+# because the Linux install scripts use them.
+#
+SHLIB_DESTDIR := not-used
+EGL_DESTDIR := not-used
+
+# Must give our EGL/GLES libraries a globally unique name
+#
+EGL_BASENAME_SUFFIX := _POWERVR_ROGUE
+
+# Use stlport instead of libstdc++ for STL compatibility
+#
+SYS_CXXFLAGS := -fuse-cxa-atexit $(SYS_CFLAGS)
+SYS_INCLUDES += \
+ -isystem $(ANDROID_ROOT)/bionic \
+ -isystem $(ANDROID_ROOT)/external/stlport/stlport
+
+##############################################################################
+# ICS requires that at least one driver EGLConfig advertises the
+# EGL_RECORDABLE_ANDROID attribute. The platform requires that surfaces
+# rendered with this config can be consumed by an OMX video encoder.
+#
+EGL_EXTENSION_ANDROID_RECORDABLE := 1
+
+##############################################################################
+# ICS added the EGL_ANDROID_blob_cache extension. Enable support for this
+# extension in EGL/GLESv2.
+#
+EGL_EXTENSION_ANDROID_BLOB_CACHE ?= 1
+
+##############################################################################
+# Framebuffer target extension is used to find configs compatible with
+# the framebuffer
+#
+EGL_EXTENSION_ANDROID_FRAMEBUFFER_TARGET := 1
+
+##############################################################################
+# Disable the MEMINFO wrapper pvCpuVirtAddr feature. All Android DDK
+# components no longer require it. This enables lazy CPU mappings, which
+# improves allocation performance.
+#
+ifneq ($(PDUMP),1)
+PVRSRV_NO_MEMINFO_CPU_VIRT_ADDR ?= 1
+endif
+
+##############################################################################
+# JB added a new corkscrew API for userland backtracing.
+#
+ifeq ($(is_at_least_lollipop),0)
+PVR_ANDROID_HAS_CORKSCREW_API := 1
+endif
+
+##############################################################################
+# This is currently broken on KK. Disable until fixed.
+#
+SUPPORT_ANDROID_APPHINTS := 0
+
+##############################################################################
+# KitKat added very provisional/early support for sRGB render targets
+#
+# (Leaving this optional until the framework makes it mandatory.)
+#
+PVR_ANDROID_HAS_HAL_PIXEL_FORMAT_sRGB ?= 1
+
+##############################################################################
+# Switch on ADF support for KitKat MR1 or newer.
+#
+# Customers using AOSP KitKat MR1 sources need to copy and build the libadf
+# and libadfhwc libraries from AOSP master system/core into their device/
+# directories and build the components as dynamic libraries. Examples of how
+# to do this are shown in the bundled 'pc_android' and 'generic_arm_android'
+# directories in the device package.
+#
+# Customers using AOSP master do not need to make any changes.
+# ADF requires kernel/common derivative kernels >= 3.10.
+#
+ifeq ($(is_at_least_kitkat_mr1),1)
+#SUPPORT_ADF ?= 1
+#SUPPORT_DC ?= 1
+endif
+
+##############################################################################
+# Versions of Android between Cupcake and KitKat MR1 required Java 6.
+#
+ifeq ($(is_at_least_lollipop),0)
+LEGACY_USE_JAVA6 ?= 1
+endif
+
+##############################################################################
+# Versions of Android between ICS and KitKat MR1 used ion .heap_mask instead
+# of .heap_id_mask.
+#
+ifeq ($(is_at_least_lollipop),0)
+PVR_ANDROID_HAS_ION_FIELD_HEAP_MASK := 1
+endif
+
+##############################################################################
+# Lollipop supports 64-bit. Configure BCC to emit both 32-bit and 64-bit LLVM
+# bitcode in the renderscript driver.
+#
+ifeq ($(is_at_least_lollipop),1)
+PVR_ANDROID_BCC_MULTIARCH_SUPPORT := 1
+endif
+
+##############################################################################
+# Lollipop annotates the cursor allocation with USAGE_CURSOR to enable it to
+# be accelerated with special cursor hardware (rather than wasting an
+# overlay). This flag stops the DDK from blocking the allocation.
+#
+ifeq ($(is_at_least_lollipop),1)
+PVR_ANDROID_HAS_GRALLOC_USAGE_CURSOR := 1
+endif
+
+##############################################################################
+# Lollipop changed the camera HAL metadata specification to require that
+# CONTROL_MAX_REGIONS specifies 3 integers (instead of 1).
+#
+ifeq ($(is_at_least_lollipop),1)
+PVR_ANDROID_CAMERA_CONTROL_MAX_REGIONS_HAS_THREE := 1
+endif
+
+# Placeholder for future version handling
+#
+ifeq ($(is_future_version),1)
+-include ../common/android/future_version.mk
+endif
diff --git a/drivers/gpu/rogue/build/linux/common/android/install.sh.tpl b/drivers/gpu/rogue/build/linux/common/android/install.sh.tpl
new file mode 100644
index 000000000000..b949c8c9146a
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/android/install.sh.tpl
@@ -0,0 +1,323 @@
+#!/bin/bash
+############################################################################ ###
+#@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.
+#### ###########################################################################
+# Help on how to invoke
+#
+function usage {
+ echo "usage: $0 [options...]"
+ echo ""
+ echo "Options: -v Verbose mode."
+ echo " -n Dry-run mode."
+ echo " -u Uninstall-only mode."
+ echo " --root <path> Use <path> as the root of the install file system."
+ echo " (Overrides the DISCIMAGE environment variable.)"
+ exit 1
+}
+
+WD=`pwd`
+SCRIPT_ROOT=`dirname $0`
+cd $SCRIPT_ROOT
+
+PVRVERSION=[PVRVERSION]
+PVRBUILD=[PVRBUILD]
+PRIMARY_ARCH="[PRIMARY_ARCH]"
+ARCHITECTURES="[ARCHITECTURES]"
+
+# These destination directories are the same for 32- or 64-bit binaries.
+# zxl: change module's path from /system/modules/ to /system/lib/modules/
+MOD_DESTDIR=/system/lib/modules
+BIN_DESTDIR=/system/vendor/bin
+DATA_DESTDIR=${BIN_DESTDIR}
+
+# Exit with an error messages.
+# $1=blurb
+#
+function bail {
+ if [ ! -z "$1" ]; then
+ echo "$1" >&2
+ fi
+
+ echo "" >&2
+ echo "Installation failed" >&2
+ exit 1
+}
+
+# Copy all the required files into their appropriate places on the local machine.
+function install_locally {
+ # Define functions required for local installs
+
+ # basic installation function
+ # $1=fromfile, $2=destfilename, $3=blurb, $4=chmod-flags, $5=chown-flags
+ #
+ function install_file {
+ if [ -z "$DDK_INSTALL_LOG" ]; then
+ bail "INTERNAL ERROR: Invoking install without setting logfile name"
+ fi
+ DESTFILE=${DISCIMAGE}$2
+ DESTDIR=`dirname $DESTFILE`
+
+ if [ ! -e $1 ]; then
+ [ -n "$VERBOSE" ] && echo "skipping file $1 -> $2"
+ return
+ fi
+
+ # Destination directory - make sure it's there and writable
+ #
+ if [ -d "${DESTDIR}" ]; then
+ if [ ! -w "${DESTDIR}" ]; then
+ bail "${DESTDIR} is not writable."
+ fi
+ else
+ $DOIT mkdir -p ${DESTDIR} || bail "Couldn't mkdir -p ${DESTDIR}"
+ [ -n "$VERBOSE" ] && echo "Created directory `dirname $2`"
+ fi
+
+ # Delete the original so that permissions don't persist.
+ #
+ $DOIT rm -f $DESTFILE
+
+ $DOIT cp -f $1 $DESTFILE || bail "Couldn't copy $1 to $DESTFILE"
+ $DOIT chmod $4 ${DESTFILE}
+
+ echo "$3 `basename $1` -> $2"
+ $DOIT echo "file $2" >> $DDK_INSTALL_LOG
+ }
+
+ # Android-specific targetfs mkdir workarounds
+ if [ ! -d ${DISCIMAGE}/data ]; then
+ mkdir ${DISCIMAGE}/data
+ chown 1000:1000 ${DISCIMAGE}/data
+ chmod 0771 ${DISCIMAGE}/data
+ fi
+ if [ ! -d ${DISCIMAGE}/data/app ]; then
+ mkdir ${DISCIMAGE}/data/app
+ chown 1000:1000 ${DISCIMAGE}/data/app
+ chmod 0771 ${DISCIMAGE}/data/app
+ fi
+
+ for arch in $ARCHITECTURES; do
+ if [ ! -d $arch ]; then
+ echo "Unknown architecture $arch. Aborting"
+ #exit 1
+ fi
+
+ case $arch in
+ target*64)
+ SHLIB_DESTDIR=/system/vendor/lib64
+ ;;
+ *)
+ SHLIB_DESTDIR=/system/vendor/lib
+ esac
+ EGL_DESTDIR=${SHLIB_DESTDIR}/egl
+
+ pushd $arch > /dev/null
+ # Install UM components
+ if [ -f install_um.sh ]; then
+ DDK_INSTALL_LOG=$UMLOG
+ echo "Installing User components for architecture $arch"
+ $DOIT echo "version $PVRVERSION" > $DDK_INSTALL_LOG
+ source install_um.sh
+ echo
+ fi
+ popd > /dev/null
+ done
+
+ pushd $PRIMARY_ARCH > /dev/null
+ # Install KM components
+ if [ -f install_km.sh ]; then
+ DDK_INSTALL_LOG=$KMLOG
+ echo "Installing Kernel components for architecture $PRIMARY_ARCH"
+ $DOIT echo "version $PVRVERSION" > $DDK_INSTALL_LOG
+ source install_km.sh
+ echo
+ fi
+ popd > /dev/null
+
+ $DOIT mkdir -p ${DISCIMAGE}/system/lib/egl
+ $DOIT cat >${DISCIMAGE}/system/lib/egl/egl.cfg <<EOF
+0 0 POWERVR_ROGUE
+EOF
+ $DOIT echo "file /system/lib/egl/egl.cfg" >> $DDK_INSTALL_LOG
+
+ # Create an OLDLOG so old versions of the driver can uninstall.
+ $DOIT echo "version $PVRVERSION" > $OLDLOG
+ if [ -f $KMLOG ]; then
+ tail -n +2 $KMLOG >> $OLDLOG
+ fi
+ if [ -f $UMLOG ]; then
+ tail -n +2 $UMLOG >> $OLDLOG
+ fi
+
+ # Make sure new logs are newer than $OLDLOG
+ touch -m -d "last sunday" $OLDLOG
+}
+
+# Read the appropriate install log and delete anything therein.
+function uninstall_locally {
+ # Function to uninstall something.
+ function do_uninstall {
+ LOG=$1
+
+ if [ ! -f $LOG ]; then
+ echo "Nothing to un-install."
+ return;
+ fi
+
+ BAD=0
+ VERSION=""
+ while read type data; do
+ case $type in
+ version)
+ echo "Uninstalling existing version $data"
+ VERSION="$data"
+ ;;
+ link|file)
+ if [ -z "$VERSION" ]; then
+ BAD=1;
+ echo "No version record at head of $LOG"
+ elif ! $DOIT rm -f ${DISCIMAGE}${data}; then
+ BAD=1;
+ else
+ [ -n "$VERBOSE" ] && echo "Deleted $type $data"
+ fi
+ ;;
+ tree)
+ ;;
+ esac
+ done < $1;
+
+ if [ $BAD = 0 ]; then
+ echo "Uninstallation completed."
+ $DOIT rm -f $LOG
+ else
+ echo "Uninstallation failed!!!"
+ fi
+ }
+
+ if [ -z "$OLDLOG" -o -z "$KMLOG" -o -z "$UMLOG" ]; then
+ bail "INTERNAL ERROR: Invoking uninstall without setting logfile name"
+ fi
+
+ # Uninstall anything installed using the old-style install scripts.
+ LEGACY_LOG=0
+ if [ -f $OLDLOG ]; then
+ if [ -f $KMLOG -a $KMLOG -nt $OLDLOG ]; then
+ # Last install was new scheme.
+ rm $OLDLOG
+ elif [ -f $UMLOG -a $UMLOG -nt $OLDLOG ]; then
+ # Last install was new scheme.
+ rm $OLDLOG
+ else
+ echo "Uninstalling all components from legacy log."
+ do_uninstall $OLDLOG
+ LEGACY_LOG=1
+ echo
+ fi
+ fi
+
+ if [ $LEGACY_LOG = 0 ]; then
+ # Uninstall KM components if we are doing a KM install.
+ if [ -f install_km.sh -a -f $KMLOG ]; then
+ echo "Uninstalling Kernel components"
+ do_uninstall $KMLOG
+ echo
+ fi
+ # Uninstall UM components if we are doing a UM install.
+ if [ -f install_um.sh -a -f $UMLOG ]; then
+ echo "Uninstalling User components"
+ do_uninstall $UMLOG
+ echo
+ fi
+ fi
+}
+
+# Work out if there are any special instructions.
+#
+while [ "$1" ]; do
+ case "$1" in
+ -v|--verbose)
+ VERBOSE=v
+ ;;
+ -r|--root)
+ DISCIMAGE=$2
+ shift;
+ ;;
+ -u|--uninstall)
+ UNINSTALL_ONLY=y
+ ;;
+ -n)
+ DOIT=echo
+ ;;
+ -h | --help | *)
+ usage
+ ;;
+ esac
+ shift
+done
+
+if [ ! -z "$DISCIMAGE" ]; then
+
+ if [ ! -d "$DISCIMAGE" ]; then
+ bail "$0: $DISCIMAGE does not exist."
+ fi
+
+ echo
+ if [ $DISCIMAGE == "/" ]; then
+ echo "Installing PowerVR '$PVRVERSION ($PVRBUILD)' locally"
+ else
+ echo "Installing PowerVR '$PVRVERSION ($PVRBUILD)' on $DISCIMAGE"
+ fi
+ echo
+ echo "File system installation root is $DISCIMAGE"
+ echo
+
+ OLDLOG=$DISCIMAGE/powervr_ddk_install.log
+ KMLOG=$DISCIMAGE/powervr_ddk_install_km.log
+ UMLOG=$DISCIMAGE/powervr_ddk_install_um.log
+
+ uninstall_locally
+
+ if [ "$UNINSTALL_ONLY" != "y" ]; then
+ install_locally
+ fi
+
+else
+ bail "DISCIMAGE must be set for installation to be possible."
+fi
diff --git a/drivers/gpu/rogue/build/linux/common/android/paths.mk b/drivers/gpu/rogue/build/linux/common/android/paths.mk
new file mode 100644
index 000000000000..6cc7cc7efe97
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/android/paths.mk
@@ -0,0 +1,52 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+TARGET_BUILD_TYPE ?= release
+
+HOST_OS ?= linux
+HOST_ARCH ?= x86
+
+OUT_DIR ?= $(ANDROID_ROOT)/out
+
+ifeq ($(TARGET_BUILD_TYPE),debug)
+TARGET_ROOT := $(OUT_DIR)/debug/target
+else
+TARGET_ROOT := $(OUT_DIR)/target
+endif
diff --git a/drivers/gpu/rogue/build/linux/common/android/platform_version.mk b/drivers/gpu/rogue/build/linux/common/android/platform_version.mk
new file mode 100644
index 000000000000..37eec2b8a316
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/android/platform_version.mk
@@ -0,0 +1,178 @@
+########################################################################### ###
+#@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 there's no build.prop file in the expected location, bail out. Tell the
+# user which file we were trying to read in case TARGET_DEVICE was not set.
+#
+BUILD_PROP := $(TARGET_ROOT)/product/$(TARGET_DEVICE)/system/build.prop
+ifeq ($(wildcard $(BUILD_PROP)),)
+$(warning *** Could not determine Android version. Did you set ANDROID_ROOT,\
+OUT_DIR and TARGET_DEVICE in your environment correctly?)
+$(error Error reading $(BUILD_PROP))
+endif
+
+# Extract version.release and version.codename from the build.prop file.
+# If either of the values aren't in the build.prop, the Make variables won't
+# be defined, and fallback handling will take place.
+#
+define newline
+
+
+endef
+$(eval $(subst #,$(newline),$(shell cat $(BUILD_PROP) | \
+ grep '^ro.build.version.release=\|^ro.build.version.codename=' | \
+ sed -e 's,ro.build.version.release=,PLATFORM_RELEASE=,' \
+ -e 's,ro.build.version.codename=,PLATFORM_CODENAME=,' | tr '\n' '#')))
+
+define release-starts-with
+$(shell echo $(PLATFORM_RELEASE) | grep -q ^$(1); \
+ [ "$$?" = "0" ] && echo 1 || echo 0)
+endef
+
+# ro.build.version.release contains the version number for release builds, or
+# the version codename otherwise. In this case we need to assume that the
+# version of Android we're building against has the features that are in the
+# final release of that version, so we set PLATFORM_RELEASE to the
+# corresponding release number.
+#
+# NOTE: It's the _string_ ordering that matters here, not the version number
+# ordering. You need to make sure that strings that are sub-strings of other
+# checked strings appear _later_ in this list.
+#
+# e.g. 'KitKatMR' starts with 'KitKat', but it is not KitKat.
+#
+ifeq ($(call release-starts-with,JellyBeanMR1),1)
+PLATFORM_RELEASE := 4.2
+else ifeq ($(call release-starts-with,JellyBeanMR),1)
+PLATFORM_RELEASE := 4.3
+else ifeq ($(call release-starts-with,JellyBean),1)
+PLATFORM_RELEASE := 4.1
+else ifeq ($(call release-starts-with,KeyLimePie),1)
+PLATFORM_RELEASE := 4.4
+else ifeq ($(call release-starts-with,KitKatMR),1)
+PLATFORM_RELEASE := 4.4.1
+else ifeq ($(call release-starts-with,KitKat),1)
+PLATFORM_RELEASE := 4.4
+else ifeq ($(call release-starts-with,Lollipop),1)
+PLATFORM_RELEASE := 5.0
+else ifeq ($(PLATFORM_CODENAME),AOSP)
+# AOSP (master) will normally have PLATFORM_CODENAME set to AOSP
+PLATFORM_RELEASE := 5.1
+else ifeq ($(shell echo $(PLATFORM_RELEASE) | grep -qE "[A-Za-z]+"; echo $$?),0)
+PLATFORM_RELEASE := 5.1
+endif
+
+PLATFORM_RELEASE_MAJ := $(shell echo $(PLATFORM_RELEASE) | cut -f1 -d'.')
+PLATFORM_RELEASE_MIN := $(shell echo $(PLATFORM_RELEASE) | cut -f2 -d'.')
+PLATFORM_RELEASE_PATCH := $(shell echo $(PLATFORM_RELEASE) | cut -f3 -d'.')
+
+# Not all versions have a patchlevel; fix that up here
+#
+ifeq ($(PLATFORM_RELEASE_PATCH),)
+PLATFORM_RELEASE_PATCH := 0
+endif
+
+# Macros to help categorize support for features and API_LEVEL for tests.
+#
+is_at_least_jellybean_mr1 := \
+ $(shell ( test $(PLATFORM_RELEASE_MAJ) -gt 4 || \
+ ( test $(PLATFORM_RELEASE_MAJ) -eq 4 && \
+ test $(PLATFORM_RELEASE_MIN) -ge 2 ) ) && echo 1 || echo 0)
+is_at_least_jellybean_mr2 := \
+ $(shell ( test $(PLATFORM_RELEASE_MAJ) -gt 4 || \
+ ( test $(PLATFORM_RELEASE_MAJ) -eq 4 && \
+ test $(PLATFORM_RELEASE_MIN) -ge 3 ) ) && echo 1 || echo 0)
+is_at_least_kitkat := \
+ $(shell ( test $(PLATFORM_RELEASE_MAJ) -gt 4 || \
+ ( test $(PLATFORM_RELEASE_MAJ) -eq 4 && \
+ test $(PLATFORM_RELEASE_MIN) -ge 4 ) ) && echo 1 || echo 0)
+is_at_least_kitkat_mr1 := \
+ $(shell ( test $(PLATFORM_RELEASE_MAJ) -gt 4 || \
+ ( test $(PLATFORM_RELEASE_MAJ) -eq 4 && \
+ test $(PLATFORM_RELEASE_MIN) -gt 4 ) || \
+ ( test $(PLATFORM_RELEASE_MAJ) -eq 4 && \
+ test $(PLATFORM_RELEASE_MIN) -eq 4 && \
+ test $(PLATFORM_RELEASE_PATCH) -ge 1 ) ) && echo 1 || echo 0)
+is_at_least_lollipop := \
+ $(shell ( test $(PLATFORM_RELEASE_MAJ) -ge 5 ) && echo 1 || echo 0)
+
+# Assume "future versions" are >=5.1, but we don't really know
+is_future_version := \
+ $(shell ( test $(PLATFORM_RELEASE_MAJ) -gt 5 || \
+ ( test $(PLATFORM_RELEASE_MAJ) -eq 5 && \
+ test $(PLATFORM_RELEASE_MIN) -gt 0 ) ) && echo 1 || echo 0)
+
+# Sometimes a feature is introduced in AOSP master that isn't in the current
+# future version, but both versions are beyond our support level. This variable
+# can be used to differentiate those builds.
+#
+ifeq ($(PLATFORM_CODENAME)$(is_future_version),AOSP1)
+is_aosp_master := 1
+else
+is_aosp_master := 0
+endif
+
+# Picking an exact match of API_LEVEL for the platform we're building
+# against can avoid compatibility theming and affords better integration.
+#
+ifeq ($(is_future_version),1)
+# Temporarily pin to 19 until it is actually bumped to 20
+API_LEVEL := 19
+else ifeq ($(is_at_least_lollipop),1)
+API_LEVEL := 21
+#API_LEVEL := 20 was l-preview
+else ifeq ($(is_at_least_kitkat),1)
+API_LEVEL := 19
+else ifeq ($(is_at_least_jellybean_mr2),1)
+API_LEVEL := 18
+else ifeq ($(is_at_least_jellybean_mr1),1)
+API_LEVEL := 17
+else
+$(error Must build against Android >= 4.2)
+endif
+
+# Each DDK is tested against only a single version of the platform.
+# Warn if a different platform version is used.
+#
+ifeq ($(is_future_version),1)
+$(info WARNING: Android version is newer than this DDK supports)
+else ifneq ($(is_at_least_kitkat),1)
+$(info WARNING: Android version is older than this DDK supports)
+endif
diff --git a/drivers/gpu/rogue/build/linux/common/pvrgdb.mk b/drivers/gpu/rogue/build/linux/common/pvrgdb.mk
new file mode 100644
index 000000000000..b5f84d41d6c7
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/pvrgdb.mk
@@ -0,0 +1,40 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
diff --git a/drivers/gpu/rogue/build/linux/common/testchip.mk b/drivers/gpu/rogue/build/linux/common/testchip.mk
new file mode 100644
index 000000000000..e9bb7eee5a10
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/common/testchip.mk
@@ -0,0 +1,62 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+ifeq ($(RGX_BVNC),1.82.4.5)
+ $(eval $(call TunableKernelConfigC,TC_APOLLO_ES2,1))
+endif
+
+ifeq ($(PVR_SYSTEM),$(filter $(PVR_SYSTEM),rgx_tc rgx_tc_es2))
+$(eval $(call TunableKernelConfigC,TC_MEMORY_CONFIG,$(TC_MEMORY_CONFIG),\
+Selects the memory configuration to be used. The choices are:_\
+* TC_MEMORY_LOCAL (Rogue and the display controller use local card memory)_\
+* TC_MEMORY_HOST (Rogue and the display controller use system memory)_\
+* TC_MEMORY_HYBRID (Rogue uses system memory and the display controller uses local card memory)))
+endif
+ifeq ($(PVR_SYSTEM), rgx_linux_apollo)
+$(eval $(call BothConfigC,TC_MEMORY_CONFIG,TC_MEMORY_LOCAL))
+$(call $(NonTunableOption,TC_MEMORY_CONFIG))
+endif
+
+ifeq ($(TC_MEMORY_CONFIG),TC_MEMORY_LOCAL)
+LMA := 1
+endif
+
+$(eval $(call TunableBothConfigC,LMA,))
+$(eval $(call TunableKernelConfigMake,LMA,))
diff --git a/drivers/gpu/rogue/build/linux/config/compiler.mk b/drivers/gpu/rogue/build/linux/config/compiler.mk
new file mode 100644
index 000000000000..c1384eaae16e
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/compiler.mk
@@ -0,0 +1,194 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+# Check for valid values of $(MULTIARCH).
+ifeq ($(strip $(MULTIARCH)),0)
+$(error MULTIARCH must be empty to disable multiarch)
+endif
+
+define calculate-compiler-preferred-target
+ ifeq ($(2),qcc)
+ $(1)_compiler_preferred_target := qcc
+ else
+ $(1)_compiler_preferred_target := $$(shell $(2) -dumpmachine)
+ ifeq ($$($(1)_compiler_preferred_target),)
+ $$(warning No output from '$(2) -dumpmachine')
+ $$(warning Check that the compiler is in your PATH and CROSS_COMPILE is)
+ $$(warning set correctly.)
+ $$(error Unable to run compiler '$(2)')
+ endif
+ ifneq ($$(filter x86_64-%,$$($(1)_compiler_preferred_target)),)
+ $(1)_compiler_preferred_target := x86_64-linux-gnu
+ endif
+ ifneq ($$(filter i386-% i486-% i686-%,$$($(1)_compiler_preferred_target)),)
+ $(1)_compiler_preferred_target := i386-linux-gnu
+ endif
+ ifneq ($$(filter armv7a-cros-linux-gnueabi,$$($(1)_compiler_preferred_target)),)
+ $(1)_compiler_preferred_target := arm-linux-gnueabi
+ endif
+ endif
+endef
+
+define cross-compiler-name
+ ifeq ($$(origin CC),file)
+ $(1) := $(2)$(3)
+ else
+ ifeq ($$(_CLANG),true)
+ $(1) := $(3) -target $$(patsubst %-,%,$(2))
+ else
+ $(1) := $(3)
+ endif
+ endif
+endef
+
+# Work out the host compiler architecture
+$(eval $(call calculate-compiler-preferred-target,host,$(HOST_CC)))
+
+ifeq ($(host_compiler_preferred_target),x86_64-linux-gnu)
+ HOST_PRIMARY_ARCH := host_x86_64
+ HOST_32BIT_ARCH := host_i386
+ HOST_FORCE_32BIT := -m32
+else
+ifeq ($(host_compiler_preferred_target),i386-linux-gnu)
+ HOST_PRIMARY_ARCH := host_i386
+ HOST_32BIT_ARCH := host_i386
+else
+ $(error Unknown host compiler target architecture $(host_compiler_preferred_target))
+endif
+endif
+
+# Workaround our lack of support for non-Linux HOST_CCs
+ifneq ($(HOST_CC_IS_LINUX),1)
+ $(warning $$(HOST_CC) is non-Linux. Trying to work around.)
+ override HOST_CC := $(HOST_CC) -D__linux__
+ $(eval $(call BothConfigMake,HOST_CC,$(HOST_CC)))
+endif
+
+$(eval $(call BothConfigMake,HOST_PRIMARY_ARCH,$(HOST_PRIMARY_ARCH)))
+$(eval $(call BothConfigMake,HOST_32BIT_ARCH,$(HOST_32BIT_ARCH)))
+$(eval $(call BothConfigMake,HOST_FORCE_32BIT,$(HOST_FORCE_32BIT)))
+
+TARGET_ALL_ARCH :=
+TARGET_PRIMARY_ARCH :=
+TARGET_SECONDARY_ARCH :=
+
+# Work out the target compiler cross triple, and include the corresponding
+# compilers/*.mk file, which sets TARGET_PRIMARY_ARCH and
+# TARGET_SECONDARY_ARCH for that compiler.
+#
+compilers := ../config/compilers
+define include-compiler-file
+ ifeq ($(strip $(1)),)
+ $$(error empty arg passed to include-compiler-file)
+ endif
+ ifeq ($$(wildcard $$(compilers)/$(1).mk),)
+ $$(warning ******************************************************)
+ $$(warning Compiler target '$(1)' not recognised)
+ $$(warning (missing $$(compilers)/$(1).mk file))
+ $$(warning ******************************************************)
+ $$(error Compiler '$(1)' not recognised)
+ endif
+ include $$(compilers)/$(1).mk
+endef
+
+# Check the kernel cross compiler to work out which architecture it targets.
+# We can then tell if CROSS_COMPILE targets a different architecture.
+ifneq ($(origin KERNEL_CROSS_COMPILE),undefined)
+ # First, calculate the value of KERNEL_CROSS_COMPILE as it would be seen by
+ # the main build, so we can check it here in the config stage.
+ $(call one-word-only,KERNEL_CROSS_COMPILE)
+ _kernel_cross_compile := $(if $(filter undef,$(KERNEL_CROSS_COMPILE)),,$(KERNEL_CROSS_COMPILE))
+ # We can take shortcuts with KERNEL_CROSS_COMPILE, as we don't want to
+ # respect CC and we don't support clang in that part currently.
+ _kernel_cross_compile := $(_kernel_cross_compile)gcc
+ # Then check the compiler.
+ $(eval $(call calculate-compiler-preferred-target,target,$(_kernel_cross_compile)))
+ $(eval $(call include-compiler-file,$(target_compiler_preferred_target)))
+ _kernel_primary_arch := $(TARGET_PRIMARY_ARCH)
+else
+ # We can take shortcuts with KERNEL_CROSS_COMPILE, as we don't want to
+ # respect CC and we don't support clang in that part currently.
+ _kernel_cross_compile := $(CROSS_COMPILE)gcc
+ # KERNEL_CROSS_COMPILE will be the same as CROSS_COMPILE, so we don't need
+ # to do the compatibility check.
+ _kernel_primary_arch :=
+endif
+
+$(eval $(call cross-compiler-name,_cc,$(CROSS_COMPILE),$(CC)))
+$(eval $(call cross-compiler-name,_cc_secondary,$(if $(CROSS_COMPILE_SECONDARY),$(CROSS_COMPILE_SECONDARY),$(CROSS_COMPILE)),$(CC_SECONDARY)))
+$(eval $(call calculate-compiler-preferred-target,target,$(_cc)))
+$(eval $(call include-compiler-file,$(target_compiler_preferred_target)))
+
+# Sanity check: if KERNEL_CROSS_COMPILE was set, it has to target the same
+# architecture as CROSS_COMPILE.
+ifneq ($(_kernel_primary_arch),)
+ ifneq ($(TARGET_PRIMARY_ARCH),$(_kernel_primary_arch))
+ $(warning ********************************************************)
+ $(warning Error: Kernel and user-mode cross compilers build for)
+ $(warning different targets)
+ $(warning $(space)$(space)CROSS_COMPILE=$(CROSS_COMPILE))
+ $(warning $(space)$(space)$(space)builds for $(TARGET_PRIMARY_ARCH))
+ $(warning $(space)$(space)KERNEL_CROSS_COMPILE=$(KERNEL_CROSS_COMPILE))
+ $(warning $(space)$(space)$(space)builds for $(_kernel_primary_arch))
+ $(warning ********************************************************)
+ $(error Mismatching kernel and user-mode cross compilers)
+ endif
+endif
+
+ifneq ($(MULTIARCH),32only)
+TARGET_ALL_ARCH += $(TARGET_PRIMARY_ARCH)
+endif
+ifneq ($(MULTIARCH),64only)
+TARGET_ALL_ARCH += $(TARGET_SECONDARY_ARCH)
+endif
+
+$(eval $(call BothConfigMake,TARGET_PRIMARY_ARCH,$(TARGET_PRIMARY_ARCH)))
+$(eval $(call BothConfigMake,TARGET_SECONDARY_ARCH,$(TARGET_SECONDARY_ARCH)))
+$(eval $(call BothConfigMake,TARGET_ALL_ARCH,$(TARGET_ALL_ARCH)))
+$(eval $(call BothConfigMake,TARGET_FORCE_32BIT,$(TARGET_FORCE_32BIT)))
+
+$(info ******* Multiarch build: $(if $(MULTIARCH),yes,no))
+$(info ******* Primary arch: $(if $(TARGET_PRIMARY_ARCH),$(TARGET_PRIMARY_ARCH),none))
+$(info ******* Secondary arch: $(if $(TARGET_SECONDARY_ARCH),$(TARGET_SECONDARY_ARCH),none))
+
+# Find the paths to libgcc for the primary and secondary architectures.
+LIBGCC := $(shell $(_cc) -print-libgcc-file-name)
+LIBGCC_SECONDARY := $(shell $(_cc_secondary) $(TARGET_FORCE_32BIT) -print-libgcc-file-name)
diff --git a/drivers/gpu/rogue/build/linux/config/compilers/aarch64-linux-android.mk b/drivers/gpu/rogue/build/linux/config/compilers/aarch64-linux-android.mk
new file mode 100644
index 000000000000..97136fe6a45d
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/compilers/aarch64-linux-android.mk
@@ -0,0 +1,12 @@
+# 64-bit Android AArch64 compiler
+TARGET_PRIMARY_ARCH := target_aarch64
+ifeq ($(MULTIARCH),1)
+ TARGET_SECONDARY_ARCH := target_armv7-a
+ ifneq ($(MAKECMDGOALS),kbuild)
+ ifneq ($(COMPONENTS),)
+ ifeq ($(CROSS_COMPILE_SECONDARY),)
+ $(error CROSS_COMPILE_SECONDARY must be set for multiarch ARM builds)
+ endif
+ endif
+ endif
+endif
diff --git a/drivers/gpu/rogue/build/linux/config/compilers/arm-eabi.mk b/drivers/gpu/rogue/build/linux/config/compilers/arm-eabi.mk
new file mode 100644
index 000000000000..d671ba9ccc18
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/compilers/arm-eabi.mk
@@ -0,0 +1,2 @@
+# 32-bit ARM EABI compiler
+TARGET_PRIMARY_ARCH := target_armv7-a
diff --git a/drivers/gpu/rogue/build/linux/config/compilers/arm-linux-androideabi.mk b/drivers/gpu/rogue/build/linux/config/compilers/arm-linux-androideabi.mk
new file mode 100644
index 000000000000..8aaeaadf43d9
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/compilers/arm-linux-androideabi.mk
@@ -0,0 +1,2 @@
+# 32-bit Android ARM compiler
+include $(compilers)/arm-eabi.mk
diff --git a/drivers/gpu/rogue/build/linux/config/compilers/i386-linux-gnu.mk b/drivers/gpu/rogue/build/linux/config/compilers/i386-linux-gnu.mk
new file mode 100644
index 000000000000..cd9539c7cf68
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/compilers/i386-linux-gnu.mk
@@ -0,0 +1,2 @@
+# 32-bit x86 compiler
+TARGET_PRIMARY_ARCH := target_i686
diff --git a/drivers/gpu/rogue/build/linux/config/compilers/x86_64-linux-gnu.mk b/drivers/gpu/rogue/build/linux/config/compilers/x86_64-linux-gnu.mk
new file mode 100644
index 000000000000..008e86b35a92
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/compilers/x86_64-linux-gnu.mk
@@ -0,0 +1,29 @@
+# 64-bit x86 compiler
+TARGET_FORCE_32BIT := -m32
+
+ifneq ($(KERNELDIR),)
+ ifneq ($(ARCH),i386)
+ ifeq ($(shell grep -q "CONFIG_X86_32=y" $(KERNELDIR)/.config && echo 1 || echo 0),1)
+ $(warning ******************************************************)
+ $(warning Your kernel appears to be configured for 32-bit x86,)
+ $(warning but CROSS_COMPILE (or KERNEL_CROSS_COMPILE) points)
+ $(warning to a 64-bit compiler.)
+ $(warning If you want a 32-bit build, either set CROSS_COMPILE)
+ $(warning to point to a 32-bit compiler, or build with ARCH=i386)
+ $(warning to force 32-bit mode with your existing compiler.)
+ $(warning ******************************************************)
+ $(error Invalid CROSS_COMPILE / kernel architecture combination)
+ endif # CONFIG_X86_32
+ endif # ARCH=i386
+endif # KERNELDIR
+
+# If ARCH=i386 is set, force a build for 32-bit only, even though we're
+# using a 64-bit compiler.
+ifeq ($(ARCH),i386)
+ include $(compilers)/i386-linux-gnu.mk
+else
+ TARGET_PRIMARY_ARCH := target_x86_64
+ ifeq ($(MULTIARCH),1)
+ TARGET_SECONDARY_ARCH := target_i686
+ endif # MULTIARCH
+endif
diff --git a/drivers/gpu/rogue/build/linux/config/core.mk b/drivers/gpu/rogue/build/linux/config/core.mk
new file mode 100644
index 000000000000..ddfef8546156
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/core.mk
@@ -0,0 +1,755 @@
+########################################################################### ###
+#@File
+#@Title Root build configuration.
+#@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.
+### ###########################################################################
+
+# Configuration wrapper for new build system. This file deals with
+# configuration of the build. Add to this file anything that deals
+# with switching driver options on/off and altering the defines or
+# objects the build uses.
+#
+# At the end of this file is an exhaustive list of all variables
+# that are passed between the platform/config stage and the generic
+# build. PLEASE refrain from adding more variables than necessary
+# to this stage -- almost all options can go through config.h.
+#
+
+# Sanity check: Make sure preconfig has been included
+ifeq ($(TOP),)
+$(error TOP not defined: Was preconfig.mk included in root makefile?)
+endif
+
+################################# MACROS ####################################
+
+ALL_TUNABLE_OPTIONS :=
+
+# This records the config option's help text and default value. Note that
+# the help text can't contain a literal comma. Use $(comma) instead.
+define RegisterOptionHelp
+ALL_TUNABLE_OPTIONS += $(1)
+ifeq ($(INTERNAL_DESCRIPTION_FOR_$(1)),)
+INTERNAL_DESCRIPTION_FOR_$(1) := $(3)
+endif
+INTERNAL_CONFIG_DEFAULT_FOR_$(1) := $(2)
+$(if $(4),\
+ $(error Too many arguments in config option '$(1)' (stray comma in help text?)))
+endef
+
+# Write out a kernel GNU make option.
+#
+define KernelConfigMake
+$$(shell echo "override $(1) := $(2)" >>$(CONFIG_KERNEL_MK).new)
+$(if $(filter config,$(D)),$(info KernelConfigMake $(1) := $(2) # $(if $($(1)),$(origin $(1)),default)))
+endef
+
+# Write out a GNU make option for both user & kernel
+#
+define BothConfigMake
+$$(eval $$(call KernelConfigMake,$(1),$(2)))
+$$(eval $$(call UserConfigMake,$(1),$(2)))
+endef
+
+# Conditionally write out a kernel GNU make option
+#
+define _TunableKernelConfigMake
+ifneq ($$($(1)),)
+ifneq ($$($(1)),0)
+$$(eval $$(call KernelConfigMake,$(1),$$($(1))))
+endif
+else
+ifneq ($(2),)
+$$(eval $$(call KernelConfigMake,$(1),$(2)))
+endif
+endif
+endef
+
+define TunableKernelConfigMake
+$$(eval $$(call _TunableKernelConfigMake,$(1),$(2)))
+$(call RegisterOptionHelp,$(1),$(2),$(3),$(4))
+endef
+
+# Conditionally write out a GNU make option for both user & kernel
+#
+define TunableBothConfigMake
+$$(eval $$(call _TunableKernelConfigMake,$(1),$(2)))
+$$(eval $$(call _TunableUserConfigMake,$(1),$(2)))
+$(call RegisterOptionHelp,$(1),$(2),$(3),$(4))
+endef
+
+# Write out a kernel-only option
+#
+define KernelConfigC
+$$(shell echo "#define $(1) $(2)" >>$(CONFIG_KERNEL_H).new)
+$(if $(filter config,$(D)),$(info KernelConfigC #define $(1) $(2) /* $(if $($(1)),$(origin $(1)),default) */),)
+endef
+
+# Write out an option for both user & kernel
+#
+define BothConfigC
+$$(eval $$(call KernelConfigC,$(1),$(2)))
+$$(eval $$(call UserConfigC,$(1),$(2)))
+endef
+
+# Conditionally write out a kernel-only option
+#
+define _TunableKernelConfigC
+ifneq ($$($(1)),)
+ifneq ($$($(1)),0)
+ifeq ($$($(1)),1)
+$$(eval $$(call KernelConfigC,$(1),))
+else
+$$(eval $$(call KernelConfigC,$(1),$$($(1))))
+endif
+endif
+else
+ifneq ($(2),)
+ifeq ($(2),1)
+$$(eval $$(call KernelConfigC,$(1),))
+else
+$$(eval $$(call KernelConfigC,$(1),$(2)))
+endif
+endif
+endif
+endef
+
+define TunableKernelConfigC
+$$(eval $$(call _TunableKernelConfigC,$(1),$(2)))
+ALL_TUNABLE_OPTIONS += $(1)
+ifeq ($(INTERNAL_DESCRIPTION_FOR_$(1)),)
+INTERNAL_DESCRIPTION_FOR_$(1) := $(3)
+endif
+INTERNAL_CONFIG_DEFAULT_FOR_$(1) := $(2)
+endef
+
+# Conditionally write out an option for both user & kernel
+#
+define TunableBothConfigC
+$$(eval $$(call _TunableKernelConfigC,$(1),$(2)))
+$$(eval $$(call _TunableUserConfigC,$(1),$(2)))
+$(call RegisterOptionHelp,$(1),$(2),$(3),$(4))
+endef
+
+# Use this to mark config options which have to exist, but aren't
+# user-tunable. Warn if an attempt is made to change it.
+#
+define NonTunableOption
+$(if $(filter command line environment,$(origin $(1))),\
+ $(error Changing '$(1)' is not supported))
+endef
+
+############################### END MACROS ##################################
+
+# Check we have a new enough version of GNU make.
+#
+need := 3.81
+ifeq ($(filter $(need),$(firstword $(sort $(MAKE_VERSION) $(need)))),)
+$(error A version of GNU make >= $(need) is required - this is version $(MAKE_VERSION))
+endif
+
+# Decide whether we need a BVNC
+ifneq ($(COMPILER_BVNC_LIST),)
+ DONT_NEED_RGX_BVNC := 1
+endif
+
+include ../defs.mk
+
+# Infer PVR_BUILD_DIR from the directory configuration is launched from.
+# Check anyway that such a directory exists.
+#
+PVR_BUILD_DIR := $(notdir $(abspath .))
+$(call directory-must-exist,$(TOP)/build/linux/$(PVR_BUILD_DIR))
+
+# Output directory for configuration, object code,
+# final programs/libraries, and install/rc scripts.
+#
+BUILD ?= release
+ifneq ($(filter $(WINDOW_SYSTEM),xorg wayland nullws nulldrmws ews_drm nulladfws ews_adf),)
+OUT ?= $(TOP)/binary_$(PVR_BUILD_DIR)_$(WINDOW_SYSTEM)_$(BUILD)
+else
+OUT ?= $(TOP)/binary_$(PVR_BUILD_DIR)_$(BUILD)
+endif
+override OUT := $(if $(filter /%,$(OUT)),$(OUT),$(TOP)/$(OUT))
+
+CONFIG_MK := $(OUT)/config.mk
+CONFIG_H := $(OUT)/config.h
+CONFIG_KERNEL_MK := $(OUT)/config_kernel.mk
+CONFIG_KERNEL_H := $(OUT)/config_kernel.h
+
+# Convert commas to spaces in $(D). This is so you can say "make
+# D=config-changes,freeze-config" and have $(filter config-changes,$(D))
+# still work.
+override D := $(subst $(comma),$(space),$(D))
+
+# Create the OUT directory
+#
+$(shell mkdir -p $(OUT))
+
+# Some targets don't need information about any modules. If we only specify
+# these targets on the make command line, set INTERNAL_CLOBBER_ONLY to
+# indicate that toplevel.mk shouldn't read any makefiles
+CLOBBER_ONLY_TARGETS := clean clobber help install
+INTERNAL_CLOBBER_ONLY :=
+ifneq ($(strip $(MAKECMDGOALS)),)
+INTERNAL_CLOBBER_ONLY := \
+$(if \
+ $(strip $(foreach _cmdgoal,$(MAKECMDGOALS),\
+ $(if $(filter $(_cmdgoal),$(CLOBBER_ONLY_TARGETS)),,x))),,true)
+endif
+
+# For a clobber-only build, we shouldn't regenerate any config files
+ifneq ($(INTERNAL_CLOBBER_ONLY),true)
+
+-include ../config/user-defs.mk
+
+#
+# Core handling
+
+
+# delete any previous intermediary files
+$(shell \
+ for file in $(CONFIG_KERNEL_H).new $(CONFIG_KERNEL_MK).new ; do \
+ rm -f $$file; \
+ done)
+
+ifeq ($(DONT_NEED_RGX_BVNC),)
+ # Extract the BNC config name
+ RGX_BNC_SPLIT := $(subst .,$(space) ,$(RGX_BVNC))
+ RGX_BNC := $(word 1,$(RGX_BNC_SPLIT)).V.$(word 3,$(RGX_BNC_SPLIT)).$(word 4,$(RGX_BNC_SPLIT))
+
+ # Check BVNC core version
+ ALL_KM_BVNCS := \
+ $(patsubst rgxcore_km_%.h,%,\
+ $(notdir $(shell ls $(TOP)/hwdefs/km/cores/rgxcore_km_*.h)))
+ ifeq ($(filter $(RGX_BVNC),$(ALL_KM_BVNCS)),)
+ $(error Error: Invalid Kernel core RGX_BVNC=$(RGX_BVNC). \
+ Valid Kernel core BVNCs: $(subst $(space),$(comma)$(space),$(ALL_KM_BVNCS)))
+ endif
+
+ # Check if BVNC core file exist
+ RGX_BVNC_CORE_KM := $(TOP)/hwdefs/km/cores/rgxcore_km_$(RGX_BVNC).h
+ RGX_BVNC_CORE_KM_HEADER := \"cores/rgxcore_km_$(RGX_BVNC).h\"
+ # "rgxcore_km_$(RGX_BVNC).h"
+ ifeq ($(wildcard $(RGX_BVNC_CORE_KM)),)
+ $(error The file $(RGX_BVNC_CORE_KM) does not exist. \
+ Valid BVNCs: $(ALL_KM_BVNCS))
+ endif
+
+ # Check BNC config version
+ ALL_KM_BNCS := \
+ $(patsubst rgxconfig_km_%.h,%,\
+ $(notdir $(shell ls $(TOP)/hwdefs/km/configs/rgxconfig_km_*.h)))
+ ifeq ($(filter $(RGX_BNC),$(ALL_KM_BNCS)),)
+ $(error Error: Invalid Kernel config RGX_BNC=$(RGX_BNC). \
+ Valid Kernel config BNCs: $(subst $(space),$(comma)$(space),$(ALL_KM_BNCS)))
+ endif
+
+ # Check if BNC config file exist
+ RGX_BNC_CONFIG_KM := $(TOP)/hwdefs/km/configs/rgxconfig_km_$(RGX_BNC).h
+ RGX_BNC_CONFIG_KM_HEADER := \"configs/rgxconfig_km_$(RGX_BNC).h\"
+ #"rgxcore_km_$(RGX_BNC).h"
+ ifeq ($(wildcard $(RGX_BNC_CONFIG_KM)),)
+ $(error The file $(RGX_BNC_CONFIG_KM) does not exist. \
+ Valid BNCs: $(ALL_KM_BNCS))
+ endif
+endif
+
+# Enforced dependencies. Move this to an include.
+#
+SUPPORT_LINUX_USING_WORKQUEUES ?= 1
+ifeq ($(SUPPORT_LINUX_USING_WORKQUEUES),1)
+override PVR_LINUX_USING_WORKQUEUES := 1
+override PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE := 1
+override PVR_LINUX_TIMERS_USING_WORKQUEUES := 1
+else ifeq ($(SUPPORT_LINUX_USING_SHARED_WORKQUEUES),1)
+override PVR_LINUX_USING_WORKQUEUES := 1
+override PVR_LINUX_MISR_USING_WORKQUEUE := 1
+override PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE := 1
+endif
+
+ifeq ($(NO_HARDWARE),1)
+override SYS_USING_INTERRUPTS := 0
+endif
+
+# Rather than requiring the user to have to define two variables (one quoted,
+# one not), make PVRSRV_MODNAME a non-tunable and give it an overridable
+# default here.
+#
+PVRSRV_MODNAME ?= pvrsrvkm
+
+MAX_POOL_PAGES ?= 10240
+
+# Normally builds don't touch these, but we use them to influence the
+# components list. Make sure these are defined early enough to make this
+# possible.
+#
+ifeq ($(SUPPORT_DRM),1)
+SUPPORT_DISPLAY_CLASS := 0
+else
+ifeq ($(SUPPORT_ADF),1)
+SUPPORT_DISPLAY_CLASS := 0
+else
+ifeq ($(SUPPORT_DC),1)
+SUPPORT_DISPLAY_CLASS ?= 1
+else
+endif
+endif
+endif
+
+ifeq ($(DONT_NEED_RGX_BVNC),)
+# we can only do this stuff if we have a BVNC
+
+ SUPPORT_RAY_TRACING := \
+ $(shell grep -qw RGX_FEATURE_RAY_TRACING $(RGX_BNC_CONFIG_KM) && echo 1)
+
+ SUPPORT_DMA :=\
+ $(shell grep -qw RGX_FEATURE_META_DMA_CHANNEL_COUNT $(RGX_BNC_CONFIG_KM) && echo 1)
+endif
+
+# Default place for shared libraries
+SHLIB_DESTDIR ?= /usr/lib
+
+# Build's selected list of components.
+# - components.mk is a per-build file that specifies the components that are
+# to be built
+-include components.mk
+
+# Set up the host and target compiler.
+include ../config/compiler.mk
+
+# PDUMP needs extra components
+#
+ifeq ($(PDUMP),1)
+ifneq ($(COMPONENTS),)
+COMPONENTS += pdump
+endif
+ifeq ($(SUPPORT_DRM),1)
+EXTRA_PVRSRVKM_COMPONENTS += dbgdrv
+else
+KERNEL_COMPONENTS += dbgdrv
+endif
+endif
+
+# HWPerf KM Interface example
+#
+ifeq ($(SUPPORT_KERNEL_HWPERF_TEST),1)
+KERNEL_COMPONENTS += rgxhwpdrv
+endif
+
+# PVRGDB needs extra components
+#
+ifeq ($(PVRGDB),1)
+ifneq ($(COMPONENTS),)
+COMPONENTS += pvrdebugger pvrgdb pvrdebugipc
+endif
+override SUPPORT_EXPORTING_MEMORY_CONTEXT := 1
+endif
+
+$(if $(filter config,$(D)),$(info Build configuration:))
+
+################################# CONFIG ####################################
+
+ifneq ($(SUPPORT_NEUTRINO_PLATFORM), 1)
+
+# If KERNELDIR is set, write it out to the config.mk, with
+# KERNEL_COMPONENTS and KERNEL_ID
+#
+ifneq ($(strip $(KERNELDIR)),)
+PVRSRV_MODULE_BASEDIR ?= /lib/modules/$(KERNEL_ID)/extra/
+$(eval $(call BothConfigMake,KERNELDIR,$(KERNELDIR)))
+$(eval $(call BothConfigMake,KERNEL_ID,$(KERNEL_ID)))
+$(eval $(call KernelConfigMake,KERNEL_COMPONENTS,$(KERNEL_COMPONENTS)))
+$(eval $(call TunableKernelConfigMake,EXTRA_PVRSRVKM_COMPONENTS,,\
+List of components that should be built in to pvrsrvkm.ko$(comma) rather than_\
+forming separate kernel modules._\
+))
+
+# If KERNEL_CROSS_COMPILE is set to "undef", this is magically
+# equivalent to being unset. If it is unset, we use CROSS_COMPILE
+# (which might also be unset). If it is set, use it directly.
+ifneq ($(KERNEL_CROSS_COMPILE),undef)
+KERNEL_CROSS_COMPILE ?= $(CROSS_COMPILE)
+$(eval $(call TunableBothConfigMake,KERNEL_CROSS_COMPILE,))
+endif
+
+# Check the KERNELDIR has a kernel built and also check that it is
+# not 64-bit, which we do not support.
+KERNEL_AUTOCONF := \
+ $(strip $(wildcard $(KERNELDIR)/include/linux/autoconf.h) \
+ $(wildcard $(KERNELDIR)/include/generated/autoconf.h))
+ifeq ($(KERNEL_AUTOCONF),)
+$(warning autoconf.h not found in $$(KERNELDIR)/include/linux \
+or $$(KERNELDIR)/include/generated. Check your $$(KERNELDIR) variable \
+and kernel configuration.)
+endif
+else
+$(if $(KERNEL_COMPONENTS),$(warning KERNELDIR is not set. Kernel components cannot be built))
+endif
+
+endif # !Neutrino
+
+# Normally this is off for Linux, and only used by Android, but if customers
+# are testing their display engines using NULLADFWS, they need to enable it
+# for dmabuf support under Linux. The sync header is needed by adf_pdp.
+#
+SUPPORT_ION ?= 0
+ifneq ($(SUPPORT_ION),0)
+# Support kernels built out-of-tree with O=/other/path
+# In those cases, KERNELDIR will be O, not the source tree.
+ifneq ($(wildcard $(KERNELDIR)/source),)
+KSRCDIR := $(KERNELDIR)/source
+else
+KSRCDIR := $(KERNELDIR)
+endif
+ifneq ($(wildcard $(KSRCDIR)/drivers/staging/android/ion/ion.h),)
+# The kernel has a more recent version of ion, located in drivers/staging.
+# Change the default header paths and the behaviour wrt sg_dma_len.
+PVR_ANDROID_ION_HEADER := \"../drivers/staging/android/ion/ion.h\"
+PVR_ANDROID_ION_PRIV_HEADER := \"../drivers/staging/android/ion/ion_priv.h\"
+PVR_ANDROID_ION_USE_SG_LENGTH := 1
+endif
+ifneq ($(wildcard $(KSRCDIR)/drivers/staging/android/sync.h),)
+# The kernel has a more recent version of the sync driver, located in
+# drivers/staging. Change the default header path.
+PVR_ANDROID_SYNC_HEADER := \"../drivers/staging/android/sync.h\"
+endif
+$(eval $(call BothConfigMake,SUPPORT_ION,1))
+$(eval $(call BothConfigC,SUPPORT_ION,))
+$(eval $(call TunableKernelConfigC,PVR_ANDROID_ION_HEADER,\"linux/ion.h\"))
+$(eval $(call TunableKernelConfigC,PVR_ANDROID_ION_PRIV_HEADER,\"../drivers/gpu/ion/ion_priv.h\"))
+$(eval $(call TunableKernelConfigC,PVR_ANDROID_ION_USE_SG_LENGTH,))
+$(eval $(call TunableKernelConfigC,PVR_ANDROID_SYNC_HEADER,\"linux/sync.h\"))
+endif
+
+$(eval $(call UserConfigC,PVRSRV_MODULE_BASEDIR,\"$(PVRSRV_MODULE_BASEDIR)\"))
+
+# Ideally configured by platform Makefiles, as necessary
+#
+
+$(if $(USE_CCACHE),$(if $(USE_DISTCC),$(error\
+Enabling both USE_CCACHE and USE_DISTCC at the same time is not supported)))
+
+# Invariant options for Linux
+#
+$(eval $(call BothConfigC,LINUX,))
+
+$(eval $(call BothConfigC,PVR_BUILD_DIR,"\"$(PVR_BUILD_DIR)\""))
+$(eval $(call BothConfigC,PVR_BUILD_TYPE,"\"$(BUILD)\""))
+$(eval $(call BothConfigC,PVRSRV_MODNAME,"\"$(PVRSRV_MODNAME)\""))
+$(eval $(call BothConfigMake,PVRSRV_MODNAME,$(PVRSRV_MODNAME)))
+$(eval $(call BothConfigMake,PVR_BUILD_DIR,$(PVR_BUILD_DIR)))
+$(eval $(call BothConfigMake,PVR_BUILD_TYPE,$(BUILD)))
+
+$(eval $(call BothConfigC,SUPPORT_RGX,1))
+$(eval $(call UserConfigMake,SUPPORT_RGX,1))
+
+$(eval $(call BothConfigC,PVR_SECURE_HANDLES,))
+$(eval $(call UserConfigC,PVR_TLS_USE_GCC__thread_KEYWORD,))
+
+ifneq ($(DISPLAY_CONTROLLER),)
+$(eval $(call BothConfigC,DISPLAY_CONTROLLER,$(DISPLAY_CONTROLLER)))
+$(eval $(call BothConfigMake,DISPLAY_CONTROLLER,$(DISPLAY_CONTROLLER)))
+endif
+
+$(eval $(call UserConfigC,OPK_DEFAULT,"\"$(OPK_DEFAULT)\""))
+$(eval $(call UserConfigC,OPK_FALLBACK,"\"$(OPK_FALLBACK)\""))
+
+$(eval $(call BothConfigMake,PVR_SYSTEM,$(PVR_SYSTEM)))
+
+ifeq ($(MESA_EGL),1)
+$(eval $(call UserConfigMake,LIB_IMG_EGL,pvr_dri_if))
+else
+$(eval $(call UserConfigMake,LIB_IMG_EGL,IMGegl))
+endif
+
+# Build-type dependent options
+#
+$(eval $(call BothConfigMake,BUILD,$(BUILD)))
+
+ifeq ($(BUILD),debug)
+PVR_RI_DEBUG ?= 1
+$(eval $(call BothConfigC,DEBUG,))
+$(eval $(call KernelConfigC,DEBUG_LINUX_MEMORY_ALLOCATIONS,))
+$(eval $(call KernelConfigC,DEBUG_LINUX_MEM_AREAS,))
+$(eval $(call KernelConfigC,DEBUG_LINUX_MMAP_AREAS,))
+$(eval $(call KernelConfigC,DEBUG_BRIDGE_KM,))
+$(eval $(call KernelConfigC,DEBUG_HANDLEALLOC_KM,))
+$(eval $(call UserConfigC,DLL_METRIC,1))
+$(eval $(call TunableBothConfigC,RGXFW_ALIGNCHECKS,1))
+$(eval $(call TunableBothConfigC,PVRSRV_DEBUG_CCB_MAX,))
+else ifeq ($(BUILD),release)
+$(eval $(call BothConfigC,RELEASE,))
+$(eval $(call TunableBothConfigMake,DEBUGLINK,1))
+$(eval $(call TunableBothConfigC,RGXFW_ALIGNCHECKS,))
+else ifeq ($(BUILD),timing)
+$(eval $(call BothConfigC,TIMING,))
+$(eval $(call UserConfigC,DLL_METRIC,1))
+$(eval $(call TunableBothConfigMake,DEBUGLINK,1))
+else
+$(error BUILD= must be either debug, release or timing)
+endif
+
+
+
+# User-configurable options
+#
+ifeq ($(DONT_NEED_RGX_BVNC),)
+ $(eval $(call TunableBothConfigC,RGX_BVNC_CORE_KM_HEADER,))
+ $(eval $(call TunableBothConfigC,RGX_BNC_CONFIG_KM_HEADER,))
+ endif
+
+$(eval $(call TunableBothConfigC,SUPPORT_DBGDRV_EVENT_OBJECTS,1))
+$(eval $(call TunableBothConfigC,PVR_DBG_BREAK_ASSERT_FAIL,,\
+Enable this to treat PVR_DBG_BREAK as PVR_ASSERT(0)._\
+Otherwise it is ignored._\
+))
+$(eval $(call TunableBothConfigC,PDUMP,,\
+Enable parameter dumping in the driver._\
+This adds code to record the parameters being sent to the hardware for_\
+later analysis._\
+))
+$(eval $(call TunableBothConfigC,NO_HARDWARE,,\
+Disable hardware interactions (e.g. register writes) that the driver would_\
+normally perform. A driver built with this option can$(apos)t drive hardware$(comma)_\
+but with PDUMP enabled$(comma) it can capture parameters to be played back later._\
+))
+$(eval $(call TunableBothConfigC,PDUMP_DEBUG_OUTFILES,))
+$(eval $(call TunableBothConfigC,SYS_USING_INTERRUPTS,1))
+$(eval $(call TunableBothConfigC,PVRSRV_NEED_PVR_DPF,,\
+Enable this to turn on PVR_DPF in release builds._\
+))
+$(eval $(call TunableBothConfigC,PVRSRV_NEED_PVR_ASSERT,,\
+Enable this to turn on PVR_ASSERT in release builds._\
+))
+$(eval $(call TunableBothConfigC,PVRSRV_NEED_PVR_TRACE,,\
+Enable this to turn on PVR_TRACE in release builds._\
+))
+$(eval $(call TunableBothConfigC,REFCOUNT_DEBUG,))
+$(eval $(call TunableBothConfigC,DC_DEBUG,))
+$(eval $(call TunableBothConfigC,SCP_DEBUG,))
+$(eval $(call TunableBothConfigC,CACHEFLUSH_TYPE,CACHEFLUSH_GENERIC))
+$(eval $(call TunableBothConfigC,SUPPORT_INSECURE_EXPORT,1))
+$(eval $(call TunableBothConfigC,SUPPORT_SECURE_EXPORT,1,\
+Enable support for secure device memory and sync export._\
+This replaces export handles with file descriptors$(comma) which can be passed_\
+between processes to share memory._\
+))
+$(eval $(call TunableBothConfigC,SUPPORT_PMMIF,))
+$(eval $(call TunableBothConfigC,SUPPORT_GPUTRACE_EVENTS,))
+$(eval $(call TunableBothConfigC,SUPPORT_KERNEL_HWPERF,))
+$(eval $(call TunableBothConfigC,SUPPORT_DISPLAY_CLASS,))
+$(eval $(call TunableBothConfigC,PVRSRV_DEBUG_CCB_MAX,))
+$(eval $(call TunableBothConfigC,SUPPORT_TRUSTED_DEVICE,))
+$(eval $(call TunableBothConfigC,TRUSTED_DEVICE_DEFAULT_ENABLED,))
+$(eval $(call TunableBothConfigC,SUPPORT_EXPORTING_MEMORY_CONTEXT,))
+$(eval $(call TunableBothConfigC,SUPPORT_USER_REGISTER_CONFIGURATION,))
+$(eval $(call TunableBothConfigC,FIX_DUSTS_POW_ON_INIT,))
+
+$(eval $(call TunableKernelConfigC,DEBUG_HANDLEALLOC_INFO_KM,))
+$(eval $(call TunableKernelConfigC,SUPPORT_LINUX_X86_WRITECOMBINE,1))
+$(eval $(call TunableKernelConfigC,SUPPORT_LINUX_X86_PAT,1))
+$(eval $(call TunableKernelConfigC,PVRSRV_RESET_ON_HWTIMEOUT,))
+$(eval $(call TunableKernelConfigC,PVR_LINUX_USING_WORKQUEUES,))
+$(eval $(call TunableKernelConfigC,PVR_LINUX_MISR_USING_WORKQUEUE,))
+$(eval $(call TunableKernelConfigC,PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE,))
+$(eval $(call TunableKernelConfigC,PVR_LINUX_TIMERS_USING_WORKQUEUES,))
+$(eval $(call TunableKernelConfigC,PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE,))
+$(eval $(call TunableKernelConfigC,PVR_LDM_PLATFORM_PRE_REGISTERED,))
+$(eval $(call TunableKernelConfigC,PVR_LDM_DRIVER_REGISTRATION_NAME,"\"$(PVRSRV_MODNAME)\""))
+$(eval $(call TunableBothConfigC,LDM_PLATFORM,))
+$(eval $(call TunableBothConfigC,LDM_PCI,))
+$(eval $(call TunableBothConfigC,PVRSRV_ENABLE_FULL_SYNC_TRACKING,))
+$(eval $(call TunableKernelConfigC,SYNC_DEBUG,))
+$(eval $(call TunableKernelConfigC,SUPPORT_DUMP_CLIENT_CCB_COMMANDS,))
+$(eval $(call TunableKernelConfigC,PVR_LINUX_DONT_USE_RANGE_BASED_INVALIDATE,))
+$(eval $(call TunableKernelConfigC,PVR_MMAP_USE_VM_INSERT,))
+$(eval $(call TunableKernelConfigC,SUPPORT_MMU_PxE_MAP_ON_DEMAND,))
+$(eval $(call TunableKernelConfigC,SUPPORT_MMU_MODIFICATION_LOGGING,,\
+Enable support for logging of page table modifications. This is as debug_\
+feature for use when debugging page-faults which are showing what look to_\
+be unexpected values. It keeps a history of the last few modifications types_\
+(map/unmap) and the value written during as a result of that operation._\
+))
+$(eval $(call TunableKernelConfigC,SUPPORT_DC_COMPLETE_TIMEOUT_DEBUG,))
+$(eval $(call TunableKernelConfigC,SUPPORT_SYSTEM_INTERRUPT_HANDLING,,\
+Enable support for system level interrupt handling. This is intended_\
+for use on systems that have two or more levels of interrupt registers_\
+which require the top level register to be cleared by the system layer_\
+because it is not specific to one single device._\
+))
+
+$(eval $(call TunableBothConfigC,SUPPORT_PVR_VALGRIND,))
+
+
+
+
+
+ifneq ($(SUPPORT_ANDROID_PLATFORM),1)
+ endif
+
+
+$(eval $(call TunableBothConfigMake,CACHEFLUSH_TYPE,CACHEFLUSH_GENERIC))
+$(eval $(call TunableBothConfigMake,PDUMP,))
+$(eval $(call TunableBothConfigMake,SUPPORT_INSECURE_EXPORT,1))
+$(eval $(call TunableBothConfigMake,SUPPORT_SECURE_EXPORT,1))
+$(eval $(call TunableBothConfigMake,SUPPORT_PMMIF,))
+$(eval $(call TunableBothConfigMake,SUPPORT_DISPLAY_CLASS,))
+$(eval $(call TunableBothConfigMake,SUPPORT_RAY_TRACING,))
+
+$(eval $(call TunableBothConfigMake,SUPPORT_GPUTRACE_EVENTS,))
+$(eval $(call TunableBothConfigMake,SUPPORT_KERNEL_HWPERF,))
+
+$(eval $(call TunableBothConfigMake,OPTIM,,\
+Specify the optimisation flags passed to the compiler. Normally this_\
+is autoconfigured based on the build type._\
+))
+$(eval $(call TunableBothConfigC,SUPPORT_MMU_FREELIST,))
+$(eval $(call TunableBothConfigC,SUPPORT_VFP,))
+
+$(eval $(call TunableBothConfigC,SUPPORT_META_SLAVE_BOOT,))
+
+$(eval $(call UserConfigC,EGL_BASENAME_SUFFIX,\"$(EGL_BASENAME_SUFFIX)\"))
+
+
+
+
+
+$(eval $(call TunableBothConfigC,PVR_TESTING_UTILS,,\
+Enable this to build in support for testing the PVR Transport Layer API._\
+))
+
+
+TQ_CAPTURE_PARAMS ?= 1
+
+$(eval $(call TunableBothConfigC,TDMETACODE,))
+$(eval $(call TunableBothConfigC,PVR_DPF_ADHOC_DEBUG_ON,))
+$(eval $(call TunableBothConfigC,RGXFW_DEBUG_LOG_GROUP,))
+$(eval $(call TunableBothConfigC,SUPPORT_POWMON_WO_GPIO_PIN,))
+
+
+$(eval $(call TunableKernelConfigMake,PVR_HANDLE_BACKEND,generic,\
+Specifies the back-end that should be used$(comma) by the Services kernel handle_\
+interface$(comma) to allocate handles. The available backends are:_\
+* generic (OS agnostic)_\
+* idr (Uses the Linux IDR interface)_\
+))
+
+
+$(eval $(call TunableBothConfigC,PVRSRV_ENABLE_PROCESS_STATS,1,\
+Enable Process Statistics via DebugFS._\
+))
+
+$(eval $(call TunableKernelConfigC,SUPPORT_SHARED_SLC,,))
+
+# PVR_RI_DEBUG is set to enable RI annotation of devmem allocations
+# This is enabled by default for debug builds.
+#
+$(eval $(call TunableBothConfigMake,PVR_RI_DEBUG,))
+$(eval $(call TunableBothConfigC,PVR_RI_DEBUG,,\
+Enable Resource Information (RI) debug. This logs details of_\
+resource allocations with annotation to help indicate their use._\
+))
+
+$(eval $(call TunableKernelConfigC,PVRSRV_ENABLE_MEMORY_STATS,,\
+Enable Memory allocations to be recorded and published via Process Statistics._\
+))
+
+$(eval $(call TunableKernelConfigC,PVRSRV_ENABLE_FW_TRACE_DEBUGFS,,\
+Enable automatic decoding of Firmware Trace via DebugFS._\
+))
+
+$(eval $(call TunableKernelConfigC,PVR_LINUX_PYSMEM_MAX_POOL_PAGES,"$(MAX_POOL_PAGES)"))
+$(eval $(call TunableKernelConfigC,PVR_LINUX_VMALLOC_ALLOCATION_THRESHOLD, 16384 ))
+
+
+# Tunable RGX_MAX_TA_SYNCS / RGX_MAX_3D_SYNCS to increase the size of sync array in the DDK
+# If defined, these macros take up the values as defined in the environment,
+# Else, the default value is taken up as defined in include/rgxapi.h
+#
+
+endif # INTERNAL_CLOBBER_ONLY
+
+export INTERNAL_CLOBBER_ONLY
+export TOP
+export OUT
+
+MAKE_ETC := -Rr --no-print-directory -C $(TOP) TOP=$(TOP) OUT=$(OUT) \
+ -f build/linux/toplevel.mk
+
+# This must match the default value of MAKECMDGOALS below, and the default
+# goal in toplevel.mk
+.DEFAULT_GOAL := build
+
+ifeq ($(MAKECMDGOALS),)
+MAKECMDGOALS := build
+else
+# We can't pass autogen to toplevel.mk
+MAKECMDGOALS := $(filter-out autogen,$(MAKECMDGOALS))
+endif
+
+.PHONY: autogen
+autogen:
+ifeq ($(INTERNAL_CLOBBER_ONLY),)
+ @$(MAKE) -s --no-print-directory -C $(TOP) \
+ -f build/linux/prepare_tree.mk \
+ LDM_PCI=$(LDM_PCI) \
+ LDM_PLATFORM=$(LDM_PLATFORM)
+else
+ @:
+endif
+
+include ../config/help.mk
+
+# This deletes built-in suffix rules. Otherwise the submake isn't run when
+# saying e.g. "make thingy.a"
+.SUFFIXES:
+
+# Because we have a match-anything rule below, we'll run the main build when
+# we're actually trying to remake various makefiles after they're read in.
+# These rules try to prevent that
+%.mk: ;
+Makefile%: ;
+Makefile: ;
+
+.PHONY: build kbuild install
+build kbuild install: autogen
+ @$(if $(MAKECMDGOALS),$(MAKE) $(MAKE_ETC) $(MAKECMDGOALS) $(eval MAKECMDGOALS :=),:)
+
+%: autogen
+ @$(if $(MAKECMDGOALS),$(MAKE) $(MAKE_ETC) $(MAKECMDGOALS) $(eval MAKECMDGOALS :=),:)
diff --git a/drivers/gpu/rogue/build/linux/config/help.mk b/drivers/gpu/rogue/build/linux/config/help.mk
new file mode 100644
index 000000000000..4d6ef013bca7
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/help.mk
@@ -0,0 +1,74 @@
+########################################################################### ###
+#@File
+#@Title Targets for printing config option help
+#@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.
+### ###########################################################################
+
+define newline
+
+
+endef
+empty :=
+
+define abbrev-option-value
+$(if $(word 6,$(1)),$(wordlist 1,5,$(1))...,$(1))
+endef
+
+define print-option-help
+# Print the option name and value
+$(info $(1) ($(if $($(1)),$(call abbrev-option-value,$($(1))),<unset>), default $(if $(INTERNAL_CONFIG_DEFAULT_FOR_$(1)),$(call abbrev-option-value,$(INTERNAL_CONFIG_DEFAULT_FOR_$(1))),<unset>))$(if $(INTERNAL_DESCRIPTION_FOR_$(1)),:,))
+# Ensure the config help text ends with a newline
+$(and $(INTERNAL_DESCRIPTION_FOR_$(1)),$(if $(filter %_,$(word $(words $(INTERNAL_DESCRIPTION_FOR_$(1))),$(INTERNAL_DESCRIPTION_FOR_$(1)))),,$(eval INTERNAL_DESCRIPTION_FOR_$(1) := $(INTERNAL_DESCRIPTION_FOR_$(1))_ )))
+# Print the config help text
+$(info $(empty) $(subst _ ,$(newline) ,$(INTERNAL_DESCRIPTION_FOR_$(1))))
+endef
+
+.PHONY: confighelp allconfighelp
+# Show only the config options that have help text
+confighelp:
+ @: $(foreach _o,$(sort $(ALL_TUNABLE_OPTIONS)),$(if $(INTERNAL_DESCRIPTION_FOR_$(_o)),$(call print-option-help,$(_o)),))
+# Show all the config options
+allconfighelp:
+ @: $(foreach _o,$(sort $(ALL_TUNABLE_OPTIONS)),$(call print-option-help,$(_o)))
+
+
+ifneq ($(filter confighelp-%,$(MAKECMDGOALS)),)
+confighelp-%:
+ @: $(if $(filter $*,$(ALL_TUNABLE_OPTIONS)),$(call print-option-help,$*),$(info $* is not a tunable config option))
+endif
diff --git a/drivers/gpu/rogue/build/linux/config/kernel_version.mk b/drivers/gpu/rogue/build/linux/config/kernel_version.mk
new file mode 100644
index 000000000000..35ecceb354a3
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/kernel_version.mk
@@ -0,0 +1,100 @@
+########################################################################### ###
+#@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 $(KERNELDIR),,$(error KERNELDIR must be set to obtain a version))
+
+override KERNEL_VERSION := \
+ $(shell grep "^VERSION = " $(KERNELDIR)/Makefile | cut -f3 -d' ')
+override KERNEL_PATCHLEVEL := \
+ $(shell grep "^PATCHLEVEL = " $(KERNELDIR)/Makefile | cut -f3 -d' ')
+override KERNEL_SUBLEVEL := \
+ $(shell grep "^SUBLEVEL = " $(KERNELDIR)/Makefile | cut -f3 -d' ')
+override KERNEL_EXTRAVERSION := \
+ $(shell grep "^EXTRAVERSION = " $(KERNELDIR)/Makefile | cut -f3 -d' ')
+
+# Break the kernel version up into a space separated list
+kernel_version_as_list := $(KERNEL_VERSION) \
+ $(KERNEL_PATCHLEVEL) \
+ $(KERNEL_SUBLEVEL) \
+ $(patsubst .%,%,$(KERNEL_EXTRAVERSION))
+
+# The base ID doesn't have to be accurate; we only use it for
+# feature checks which will not care about extraversion bits
+#
+override KERNEL_BASE_ID := \
+ $(KERNEL_VERSION).$(KERNEL_PATCHLEVEL).$(KERNEL_SUBLEVEL)
+
+# Try to get the kernel ID from the kernel.release file.
+#
+KERNEL_ID ?= \
+ $(shell cat $(KERNELDIR)/include/config/kernel.release 2>/dev/null)
+
+# If the kernel ID isn't set yet, try to set it from the UTS_RELEASE
+# macro.
+#
+ifeq ($(strip $(KERNEL_ID)),)
+KERNEL_ID := \
+ $(shell grep -h '\#define UTS_RELEASE' \
+ $(KERNELDIR)/include/linux/* | cut -f3 -d' ' | sed s/\"//g)
+endif
+
+ifeq ($(strip $(KERNEL_ID)),)
+KERNEL_ID := \
+ $(KERNEL_VERSION).$(KERNEL_PATCHLEVEL).$(KERNEL_SUBLEVEL)$(KERNEL_EXTRAVERSION)
+endif
+
+# Return 1 if the kernel version is at least the value passed to the
+# function, else return nothing.
+# Examples
+# $(call kernel-version-at-least,2,6,35)
+# $(call kernel-version-at-least,2,6,35,7)
+#
+define kernel-version-at-least
+$(shell set -- $(kernel_version_as_list) 0 0 0 0; \
+ Y=true; \
+ for D in $1 $2 $3 $4; \
+ do \
+ [ $$1 ] || break; \
+ [ $$1 -eq $$D ] && { shift; continue; };\
+ [ $$1 -lt $$D ] && Y=; \
+ break; \
+ done; \
+ echo $$Y)
+endef
diff --git a/drivers/gpu/rogue/build/linux/config/preconfig.mk b/drivers/gpu/rogue/build/linux/config/preconfig.mk
new file mode 100644
index 000000000000..681ac375f2dd
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/config/preconfig.mk
@@ -0,0 +1,157 @@
+########################################################################### ###
+#@File
+#@Title Set up configuration required by build-directory Makefiles
+#@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.
+### ###########################################################################
+
+# NOTE: Don't put anything in this file that isn't strictly required
+# by the build-directory Makefiles. It should go in core.mk otherwise.
+
+TOP := $(abspath ../../..)
+
+# Some miscellaneous things to make comma substitutions easier.
+apos := '#'
+comma := ,
+empty :=
+space := $(empty) $(empty)
+
+ifneq ($(words $(TOP)),1)
+$(warning This source tree is located in a path which contains whitespace,)
+$(warning which is not supported.)
+$(warning )
+$(warning $(space)The root is: $(TOP))
+$(warning )
+$(error Whitespace found in $$(TOP))
+endif
+
+$(call directory-must-exist,$(TOP))
+
+ifneq ($(SUPPORT_NEUTRINO_PLATFORM),1)
+
+CC_CHECK := ../tools/cc-check.sh
+CHMOD := chmod
+
+# GNU Make has builtin values for CC/CXX which we don't want to trust. This
+# is because $(CROSS_COMPILE)$(CC) doesn't always expand to a cross compiler
+# toolchain binary name (e.g. most toolchains have 'gcc' but not 'cc').
+
+ifeq ($(origin CC),default)
+ _CC := $(CROSS_COMPILE)gcc
+ CC := gcc
+else
+ _CLANG := $(shell $(CC_CHECK) --clang --cc $(CC))
+ ifeq ($(_CLANG),true)
+ _CC := $(CC) -target $(patsubst %-,%,$(CROSS_COMPILE))
+ else
+ _CC := $(CC)
+ endif
+endif
+
+ifeq ($(origin CXX),default)
+ _CXX := $(CROSS_COMPILE)g++
+ CXX := g++
+else
+ _CLANGXX := $(shell $(CC_CHECK) --clang --cc $(CXX))
+ ifeq ($(_CLANGXX),true)
+ _CXX := $(CXX) -target $(patsubst %-,%,$(CROSS_COMPILE))
+ else
+ _CXX := $(CXX)
+ endif
+endif
+
+CC_SECONDARY ?= $(CC)
+HOST_CC ?= gcc
+
+# Work out if we are targeting ARM before we start tweaking _CC.
+TARGETING_AARCH64 := $(shell \
+ $(_CC) -dM -E - </dev/null | grep -q __aarch64__ && echo 1)
+
+TARGETING_ARM := $(shell \
+ $(_CC) -dM -E - </dev/null | grep __arm__ >/dev/null 2>&1 && echo 1)
+
+TARGETING_MIPS := $(shell \
+ $(_CC) -dM -E - </dev/null | grep __mips__ >/dev/null 2>&1 && echo 1)
+
+HOST_CC_IS_LINUX := $(shell \
+ $(HOST_CC) -dM -E - </dev/null | grep __linux__ >/dev/null 2>&1 && echo 1)
+
+ifneq ($(strip $(KERNELDIR)),)
+include ../config/kernel_version.mk
+endif
+
+# The user didn't set CROSS_COMPILE. There's probably nothing wrong
+# with that, but we'll let them know anyway.
+#
+ifeq ($(origin CROSS_COMPILE), undefined)
+$(warning CROSS_COMPILE is not set. Target components will be built with the host compiler)
+endif
+
+endif # !Neutrino
+
+# The user is trying to set one of the old SUPPORT_ options on the
+# command line or in the environment. This isn't supported any more
+# and will often break the build. The user is generally only trying
+# to remove a component from the list of targets to build, so we'll
+# point them at the new way of doing this.
+define sanity-check-support-option-origin
+ifeq ($$(filter undefined file,$$(origin $(1))),)
+$$(warning *** Setting $(1) via $$(origin $(1)) is deprecated)
+$$(error If you are trying to disable a component, use e.g. EXCLUDED_APIS="opengles1 opengl")
+endif
+endef
+$(foreach _o,SYS_CFLAGS SYS_CXXFLAGS SYS_INCLUDES SYS_EXE_LDFLAGS SYS_LIB_LDFLAGS,$(eval $(call sanity-check-support-option-origin,$(_o))))
+
+# Check for words in EXCLUDED_APIS that aren't understood by the
+# common/apis/*.mk files. This should be kept in sync with all the tests on
+# EXCLUDED_APIS in those files
+_excludable_apis := opencl opengl opengles1 opengles3 openrl unittests rscompute scripts composerhal servicestools hwperftools testchiptools rogue2d memtrackhal camerahal
+_excluded_apis := $(subst $(comma),$(space),$(EXCLUDED_APIS))
+
+_unrecognised := $(strip $(filter-out $(_excludable_apis),$(_excluded_apis)))
+ifneq ($(_unrecognised),)
+$(warning *** Ignoring unrecognised entries in EXCLUDED_APIS: $(_unrecognised))
+$(warning *** EXCLUDED_APIS was set via $(origin EXCLUDED_APIS) to: $(EXCLUDED_APIS))
+$(warning *** Excludable APIs are: $(_excludable_apis))
+endif
+
+override EXCLUDED_APIS := $(filter $(_excludable_apis), $(_excluded_apis))
+
+ifeq ($(SUPPORT_NEUTRINO_PLATFORM),1)
+include ../common/neutrino/preconfig_neutrino.mk
+endif
diff --git a/drivers/gpu/rogue/build/linux/defs.mk b/drivers/gpu/rogue/build/linux/defs.mk
new file mode 100644
index 000000000000..7b2a2c0fee2e
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/defs.mk
@@ -0,0 +1,264 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+define must-be-defined
+$(if $(filter undefined,$(origin $(1))),$(error In makefile $(THIS_MAKEFILE): $$($(1)) must be defined),)
+endef
+
+define must-be-nonempty
+$(if $(strip $($(1))),,$(error In makefile $(THIS_MAKEFILE): $$($(1)) must contain a value))
+endef
+
+define directory-must-exist
+$(if $(wildcard $(abspath $(1)/)),,$(error Directory $(1) must exist))
+endef
+
+define one-word-only
+$(if $(filter-out $(firstword $($(1))),$($(1))),$(error In makefile $(THIS_MAKEFILE): $$($(1)) must contain only one word),)
+endef
+
+define host-intermediates-of
+$(addprefix $(HOST_OUT)/intermediates/$(1)/,$(2))
+endef
+
+define module-library
+$(patsubst lib%.so,%,$(if $($(1)_target),$($(1)_target),$(1).so))
+endef
+
+# This is done to allow module type makefiles to use $(THIS_MAKEFILE)
+define register-module
+INTERNAL_MAKEFILE_FOR_MODULE_$(1) := $(THIS_MAKEFILE)
+endef
+
+define process-module-arch
+MODULE_ARCH := $$(strip $(2))
+include $$(MAKE_TOP)/moduledefs_common.mk
+include $$(MAKE_TOP)/moduledefs/$$(MODULE_ARCH).mk
+include $$(MAKE_TOP)/modules/$$(strip $$($$(THIS_MODULE)_type)).mk
+.SECONDARY: $$(MODULE_INTERMEDIATES_DIR)
+$$(MODULE_INTERMEDIATES_DIR):
+ $$(make-directory)
+MODULE_CLEAN_TARGETS += $$(MODULE_INTERMEDIATES_DIR)
+INTERNAL_TARGETS_FOR_$(1) += $$(MODULE_TARGETS)
+INTERNAL_CLEAN_TARGETS_FOR_$(1) += $$(MODULE_CLEAN_TARGETS)
+INTERNAL_CLOBBER_TARGETS_FOR_$(1) += $$(MODULE_CLEAN_TARGETS) $$(MODULE_CLOBBER_TARGETS) $$(MODULE_TARGETS)
+endef
+
+target_neutral_types := \
+ apk \
+ bison_parser \
+ bridge \
+ copy_files \
+ custom \
+ flex_lexer \
+ flexxx_lexer \
+ gen_dispatch \
+ rsc_scriptc \
+ image_header \
+ inline_shaders \
+ java_archive \
+ module_group \
+ pds_header \
+ rgxfw \
+ usc_header \
+ rscbitcode_header
+
+doc_types := \
+ doc \
+ doxygen
+
+define calculate-arch-list
+# Work out the target platforms for this module
+MODULE_ARCH_LIST := $(2)
+ifeq ($$(MODULE_ARCH_LIST),)
+ifneq ($$(filter $(1),$(doc_types)),)
+MODULE_ARCH_LIST := doc
+else
+ifneq ($$(filter $(1),$(target_neutral_types)),)
+MODULE_ARCH_LIST := target_neutral
+else
+ifneq ($$(filter $(1),kernel_module),)
+MODULE_ARCH_LIST := $(TARGET_PRIMARY_ARCH)
+else
+MODULE_ARCH_LIST := $(TARGET_ALL_ARCH)
+endif
+endif
+endif
+endif
+endef
+
+define process-module
+THIS_MODULE := $(1)
+THIS_MAKEFILE := $(INTERNAL_MAKEFILE_FOR_MODULE_$(1))
+INTERNAL_TARGETS_FOR_$(1) :=
+INTERNAL_CLEAN_TARGETS_FOR_$(1) :=
+INTERNAL_CLOBBER_TARGETS_FOR_$(1) :=
+include $$(MAKE_TOP)/this_makefile.mk
+$$(call must-be-nonempty,THIS_MAKEFILE)
+$$(call must-be-nonempty,$(1)_type)
+$$(eval $$(call calculate-arch-list,$$($(1)_type),$$($(1)_arch)))
+INTERNAL_ARCH_LIST_FOR_$(1) := $$(MODULE_ARCH_LIST)
+$$(foreach _m,$$(MODULE_ARCH_LIST),$$(eval $$(call process-module-arch,$(1),$$(_m))))
+endef
+
+# This can be used by module_type.mk files to indicate that they can't be
+# built as host_module_type
+define target-build-only
+$(if $(filter true,$(MODULE_HOST_BUILD)),$(error In makefile $(THIS_MAKEFILE): Module $(THIS_MODULE) attempted to build a host $(1), which is not supported))
+endef
+
+define relative-to-top
+$(patsubst $(TOP)/%,%,$(1))
+endef
+
+define cc-check
+$(shell \
+ CC_CHECK=$(patsubst @%,%,$(CC_CHECK)) && \
+ $(patsubst @%,%,$(CHMOD)) +x $$CC_CHECK && \
+ $$CC_CHECK --cc "$(1)" --out "$(2)" $(3))
+endef
+
+define cc-is-clang
+$(call cc-check,$(patsubst @%,%,$(CC)),$(OUT),--clang)
+endef
+
+define cc-option
+$(call cc-check,$(patsubst @%,%,$(CC)),$(OUT),$(1))
+endef
+
+define cxx-option
+$(call cc-check,$(patsubst @%,%,$(CXX)),$(OUT),$(1))
+endef
+
+define host-cc-option
+$(call cc-check,$(patsubst @%,%,$(HOST_CC)),$(OUT),$(1))
+endef
+
+define host-cxx-option
+$(call cc-check,$(patsubst @%,%,$(HOST_CXX)),$(OUT),$(1))
+endef
+
+define kernel-cc-option
+$(call cc-check,$(KERNEL_CROSS_COMPILE)gcc,$(OUT),$(1))
+endef
+
+# Turn a particular warning on, or explicitly turn it off, depending on
+# the value of W. The "-W" or "-Wno-" part of the warning need not be
+# specified.
+define cc-optional-warning
+$(call cc-option,-W$(if $(W),,no-)$(patsubst -W%,%,$(patsubst -Wno-%,%,$(1))))
+endef
+
+define host-cc-optional-warning
+$(call host-cc-option,-W$(if $(W),,no-)$(patsubst -W%,%,$(patsubst -Wno-%,%,$(1))))
+endef
+
+define kernel-cc-optional-warning
+$(call kernel-cc-option,-W$(if $(W),,no-)$(patsubst -W%,%,$(patsubst -Wno-%,%,$(1))))
+endef
+
+define module-info-line
+$(if $(filter modules,$(D)),$(info [$(THIS_MODULE)] <$(MODULE_ARCH)> $(1)),)
+endef
+
+# $(call if-exists,A,B) => A if A is a file which exists, otherwise B
+define if-exists
+$(if $(wildcard $(1)),$(1),$(2))
+endef
+
+#
+# Joins a given list of strings together with the given separator.
+#
+# (1): the list of strings to join
+# (2): the separator to use for joining
+#
+NOOP=
+SPACE=$(NOOP) $(NOOP)
+define list-join
+$(subst $(SPACE),$(2),$(strip $(1)))
+endef
+
+#
+# Check if a given path is absolute
+#
+# $(1): path to check
+# $(2): return when true
+# $(3): return when false
+#
+define if-abs-path
+$(if $(filter /%,$(1)),$(2),$(3))
+endef
+
+#
+# Add a prefix to every path in a list, when the path isn't absolute.
+#
+# $(1): prefix to add
+# $(2): list of paths
+#
+define addprefix-ifnot-abs
+$(foreach _path,$(2),$(call if-abs-path,$(_path),$(_path),$(1)$(_path)))
+endef
+
+#
+# Return the directory part of a path normalized (without trailing slashes)
+#
+# $(1): Path to normalize
+#
+define normalized-dir
+$(if $(filter /,$(dir $(1))),$(dir $(1)),$(if $(findstring /,$(dir $(1))),$(patsubst %/,%,$(dir $(1))),$(dir $(1))))
+endef
+
+# Definitions to handle the various suffixes allowed for C++ files.
+INTERNAL_CXX_SUFFIXES := .cc .cxx .cpp .c++
+define filter-cxx-files
+$(filter $(addprefix %,$(INTERNAL_CXX_SUFFIXES)),$(1))
+endef
+
+define filter-out-cxx-files
+$(filter-out $(addprefix %,$(INTERNAL_CXX_SUFFIXES)),$(1))
+endef
+
+define objects-from-cxx-files
+$(foreach _suffix,$(INTERNAL_CXX_SUFFIXES),$(patsubst %$(_suffix),%.o,$(filter %$(_suffix),$(1))))
+endef
+
+define unsupported-module-var
+$(if $(strip $($(THIS_MODULE)_$(1))),$(error In makefile $(THIS_MAKEFILE): Setting '$(THIS_MODULE)_$(1)' has no effect, because $(THIS_MODULE) has type $($(THIS_MODULE)_type)))
+endef
diff --git a/drivers/gpu/rogue/build/linux/generic_arm_android/Makefile b/drivers/gpu/rogue/build/linux/generic_arm_android/Makefile
new file mode 100644
index 000000000000..f292a6e41339
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/generic_arm_android/Makefile
@@ -0,0 +1,122 @@
+########################################################################### ###
+#@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 ../config/preconfig.mk
+
+# If a TARGET_PRODUCT is specified but not a TARGET_DEVICE, try to
+# derive the TARGET_DEVICE from TARGET_PRODUCT.
+#
+ifeq ($(TARGET_DEVICE),)
+override TARGET_DEVICE := \
+ $(patsubst mini_%,%,$(patsubst full_%,%,$(TARGET_PRODUCT)))
+ifeq ($(TARGET_DEVICE),arm64_img)
+override TARGET_DEVICE := arm64
+endif
+ifeq ($(TARGET_DEVICE),armv7a_neon_img)
+override TARGET_DEVICE := armv7-a-neon
+endif
+endif
+
+ifeq ($(TARGET_DEVICE),)
+# Prefer arm64 now for MULTIARCH=1 builds.
+# Use TARGET_DEVICE=armv7-a-neon for 32-bit only builds.
+override TARGET_DEVICE := arm64
+endif
+
+ifeq ($(TARGET_DEVICE),armv7-a-neon)
+# The 32-bit only Android build is still using separate toolchains for
+# kernel and userspace, force this on the DDK side when it's detected.
+KERNEL_CROSS_COMPILE ?= arm-eabi-
+endif
+
+ifeq ($(MULTIARCH),1)
+override TARGET_DEVICE := rk3368
+else
+override TARGET_DEVICE := rk3368_32
+endif
+HAL_VARIANT ?= rk3368
+PVR_SYSTEM := rk3368
+NO_HARDWARE := 0
+LDM_PLATFORM := 1
+#RGX_BVNC ?= 1.75.2.30
+#rockchip G6110
+RGX_BVNC ?= 5.9.1.46
+
+include ../common/android/paths.mk
+include ../common/android/arch.mk
+include ../common/android/features.mk
+
+ifeq ($(SUPPORT_ADF),1)
+ifneq ($(is_future_version),1)
+SYS_INCLUDES += \
+ -isystem $(ANDROID_ROOT)/device/img/generic/adf/libadf/include \
+ -isystem $(ANDROID_ROOT)/device/img/generic/adf/libadfhwc/include
+endif
+endif
+
+PVR_LDM_PLATFORM_PRE_REGISTERED := 1
+
+#zxl: build adf_fbdev.ko
+ifeq ($(SUPPORT_ADF),1)
+ADF_FBDEV ?= adf_fbdev
+KERNEL_COMPONENTS += $(ADF_FBDEV)
+endif
+
+ifneq ($(SUPPORT_ADF),1)
+ifeq ($(SUPPORT_DC),1)
+DISPLAY_CONTROLLER ?= dc_fbdev
+KERNEL_COMPONENTS += $(DISPLAY_CONTROLLER)
+ifeq ($(DISPLAY_CONTROLLER),dc_example)
+DC_EXAMPLE_WIDTH ?= 640
+DC_EXAMPLE_HEIGHT ?= 480
+DC_EXAMPLE_BIT_DEPTH ?= 32
+DC_EXAMPLE_DPI ?= 160
+endif
+endif
+endif
+
+#zxl: 3 fb buffer
+DC_FBDEV_NUM_PREFERRED_BUFFERS := 3
+
+CACHEFLUSH_TYPE ?= CACHEFLUSH_GENERIC
+
+include ../config/core.mk
+include ../common/3rdparty.mk
+include ../common/android/extra_config.mk
diff --git a/drivers/gpu/rogue/build/linux/kbuild/Makefile.template b/drivers/gpu/rogue/build/linux/kbuild/Makefile.template
new file mode 100644
index 000000000000..ee1f56459dd6
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/kbuild/Makefile.template
@@ -0,0 +1,92 @@
+########################################################################### ###
+#@Title Root kernel makefile
+#@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.
+### ###########################################################################
+
+# This top-level kbuild makefile builds all the Linux kernel modules in the
+# DDK. To run kbuild, this makefile is copied to $(TARGET_PRIMARY_OUT)/kbuild/Makefile
+# and make is invoked in $(TARGET_PRIMARY_OUT)/kbuild.
+
+# This makefile doesn't define any kbuild special variables apart from
+# ccflags-y and obj-m. The variables for objects are picked up by including
+# the kbuild makefile fragments named in $(INTERNAL_KBUILD_MAKEFILES). The
+# list of objects that these fragments make is collected in
+# $(INTERNAL_KBUILD_OBJECTS) and $(INTERNAL_EXTRA_KBUILD_OBJECTS). These
+# variables are set according to the build's $(KERNEL_COMPONENTS) and
+# $(EXTRA_PVRSRVKM_COMPONENTS). To add a new kernel module to the build, edit
+# these variables in the per-build Makefile.
+
+include $(OUT)/config_kernel.mk
+
+.SECONDARY:
+
+define symlink-source-file
+@if [ ! -e $(dir $@) ]; then mkdir -p $(dir $@); fi
+@if [ ! -h $@ ]; then ln -sf $< $@; fi
+endef
+
+bridge_base := $(BRIDGE_SOURCE_ROOT)
+
+$(OUT)/$(TARGET_PRIMARY_ARCH)/kbuild/%.c: $(TOP)/%.c
+ $(symlink-source-file)
+
+$(OUT)/$(TARGET_PRIMARY_ARCH)/kbuild/generated/%.c: $(bridge_base)/%.c
+ $(symlink-source-file)
+
+ccflags-y += -D__linux__ -include $(OUT)/config_kernel.h \
+ -I$(OUT)/include \
+ -I$(TOP)/include \
+ -I$(TOP)/hwdefs/km \
+ -I$(TOP)/services/include \
+ -I$(TOP)/services/include/shared \
+ -I$(TOP)/services/shared/include \
+ -I$(TOP)/services/shared/common \
+ -I$(TOP)/services/system/$(PVR_SYSTEM) \
+ -I$(TOP)/services/system/include \
+ -I$(TOP)/services/server/common \
+ -I$(TOP)/services/server/devices/rgx \
+ -I$(TOP)/services/server/env/linux \
+ -I$(TOP)/services/server/include
+
+include $(INTERNAL_KBUILD_MAKEFILES)
+
+$(if $(pvrsrvkm-y),,$(error pvrsrvkm-y was empty, which could mean that srvkm is missing from $$(KERNEL_COMPONENTS)))
+pvrsrvkm-y += $(foreach _m,$(INTERNAL_EXTRA_KBUILD_OBJECTS:.o=),$($(_m)-y))
+
+obj-m += $(INTERNAL_KBUILD_OBJECTS)
diff --git a/drivers/gpu/rogue/build/linux/kbuild/kbuild.mk b/drivers/gpu/rogue/build/linux/kbuild/kbuild.mk
new file mode 100644
index 000000000000..31afa4823557
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/kbuild/kbuild.mk
@@ -0,0 +1,89 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+$(TARGET_PRIMARY_OUT)/kbuild/Makefile: $(MAKE_TOP)/kbuild/Makefile.template
+ @[ ! -e $(dir $@) ] && mkdir -p $(dir $@) || true
+ $(CP) -f $< $@
+
+# We need to make INTERNAL_KBUILD_MAKEFILES absolute because the files will be
+# read while chdir'd into $(KERNELDIR)
+INTERNAL_KBUILD_MAKEFILES := $(abspath $(foreach _m,$(KERNEL_COMPONENTS) $(EXTRA_PVRSRVKM_COMPONENTS),$(if $(INTERNAL_KBUILD_MAKEFILE_FOR_$(_m)),$(INTERNAL_KBUILD_MAKEFILE_FOR_$(_m)),$(error Unknown kbuild module "$(_m)"))))
+INTERNAL_KBUILD_OBJECTS := $(foreach _m,$(KERNEL_COMPONENTS),$(if $(INTERNAL_KBUILD_OBJECTS_FOR_$(_m)),$(INTERNAL_KBUILD_OBJECTS_FOR_$(_m)),$(error BUG: Unknown kbuild module "$(_m)" should have been caught earlier)))
+INTERNAL_EXTRA_KBUILD_OBJECTS := $(foreach _m,$(EXTRA_PVRSRVKM_COMPONENTS),$(if $(INTERNAL_KBUILD_OBJECTS_FOR_$(_m)),$(INTERNAL_KBUILD_OBJECTS_FOR_$(_m)),$(error BUG: Unknown kbuild module "$(_m)" should have been caught earlier)))
+.PHONY: kbuild kbuild_clean kbuild_check
+
+kbuild_check:
+ @: $(if $(strip $(KERNELDIR)),,$(error KERNELDIR must be set))
+ @: $(call directory-must-exist,$(KERNELDIR))
+ @: $(foreach _m,$(ALL_KBUILD_MODULES),$(if $(wildcard $(abspath $(INTERNAL_KBUILD_MAKEFILE_FOR_$(_m)))),,$(error In makefile $(INTERNAL_MAKEFILE_FOR_MODULE_$(_m)): Module $(_m) requires kbuild makefile $(INTERNAL_KBUILD_MAKEFILE_FOR_$(_m)), which is missing)))
+ @: $(if $(filter-out command line override,$(origin build)),,$(error Overriding $$(build) (with "make build=...") will break kbuild))
+
+kbuild: kbuild_check $(TARGET_PRIMARY_OUT)/kbuild/Makefile
+ $(if $(V),,@)$(MAKE) -Rr --no-print-directory -C $(KERNELDIR) \
+ M=$(abspath $(TARGET_PRIMARY_OUT)/kbuild) \
+ INTERNAL_KBUILD_MAKEFILES="$(INTERNAL_KBUILD_MAKEFILES)" \
+ INTERNAL_KBUILD_OBJECTS="$(INTERNAL_KBUILD_OBJECTS)" \
+ INTERNAL_EXTRA_KBUILD_OBJECTS="$(INTERNAL_EXTRA_KBUILD_OBJECTS)" \
+ BRIDGE_SOURCE_ROOT=$(abspath $(BRIDGE_SOURCE_ROOT)) \
+ TARGET_PRIMARY_ARCH=$(TARGET_PRIMARY_ARCH) \
+ CROSS_COMPILE="$(CCACHE) $(KERNEL_CROSS_COMPILE)" \
+ EXTRA_CFLAGS="$(ALL_KBUILD_CFLAGS)" \
+ V=$(V) W=$(W) \
+ CHECK="$(patsubst @%,%,$(CHECK))" $(if $(CHECK),C=1,) \
+ TOP=$(TOP)
+ @for kernel_module in $(addprefix $(TARGET_PRIMARY_OUT)/kbuild/,$(INTERNAL_KBUILD_OBJECTS:.o=.ko)); do \
+ cp $$kernel_module $(TARGET_PRIMARY_OUT); \
+ done
+
+kbuild_clean: kbuild_check $(TARGET_PRIMARY_OUT)/kbuild/Makefile
+ $(if $(V),,@)$(MAKE) -Rr --no-print-directory -C $(KERNELDIR) \
+ M=$(abspath $(TARGET_PRIMARY_OUT)/kbuild) \
+ INTERNAL_KBUILD_MAKEFILES="$(INTERNAL_KBUILD_MAKEFILES)" \
+ INTERNAL_KBUILD_OBJECTS="$(INTERNAL_KBUILD_OBJECTS)" \
+ INTERNAL_EXTRA_KBUILD_OBJECTS="$(INTERNAL_EXTRA_KBUILD_OBJECTS)" \
+ BRIDGE_SOURCE_ROOT=$(abspath $(BRIDGE_SOURCE_ROOT)) \
+ TARGET_PRIMARY_ARCH=$(TARGET_PRIMARY_ARCH) \
+ CROSS_COMPILE="$(CCACHE) $(KERNEL_CROSS_COMPILE)" \
+ EXTRA_CFLAGS="$(ALL_KBUILD_CFLAGS)" \
+ V=$(V) W=$(W) \
+ TOP=$(TOP) clean
+
+kbuild_install: install
+kbuild: install_script_km
diff --git a/drivers/gpu/rogue/build/linux/moduledefs/host_i386.mk b/drivers/gpu/rogue/build/linux/moduledefs/host_i386.mk
new file mode 100644
index 000000000000..c07e86bb443e
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/moduledefs/host_i386.mk
@@ -0,0 +1,57 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+MODULE_HOST_BUILD := true
+
+MODULE_CC := $(HOST_CC) $(HOST_FORCE_32BIT)
+MODULE_CXX := $(HOST_CXX) $(HOST_FORCE_32BIT)
+
+MODULE_CFLAGS := $(ALL_HOST_CFLAGS) $($(THIS_MODULE)_cflags) $(HOST_FORCE_32BIT)
+MODULE_CXXFLAGS := $(ALL_HOST_CXXFLAGS) $($(THIS_MODULE)_cxxflags) $(HOST_FORCE_32BIT)
+MODULE_LDFLAGS := $(ALL_HOST_LDFLAGS) -L$(MODULE_OUT) $($(THIS_MODULE)_ldflags) $(HOST_FORCE_32BIT)
+
+ifneq ($(BUILD),debug)
+ifeq ($(USE_LTO),1)
+MODULE_LDFLAGS := \
+ $(sort $(filter-out -W% -D%,$(ALL_HOST_CFLAGS) $(ALL_HOST_CXXFLAGS))) \
+ $(MODULE_LDFLAGS)
+endif
+endif
diff --git a/drivers/gpu/rogue/build/linux/moduledefs/host_x86_64.mk b/drivers/gpu/rogue/build/linux/moduledefs/host_x86_64.mk
new file mode 100644
index 000000000000..cb1af1d6ce6f
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/moduledefs/host_x86_64.mk
@@ -0,0 +1,57 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+MODULE_HOST_BUILD := true
+
+MODULE_CC := $(HOST_CC)
+MODULE_CXX := $(HOST_CXX)
+
+MODULE_CFLAGS := $(ALL_HOST_CFLAGS) $($(THIS_MODULE)_cflags)
+MODULE_CXXFLAGS := $(ALL_HOST_CXXFLAGS) $($(THIS_MODULE)_cxxflags)
+MODULE_LDFLAGS := $(ALL_HOST_LDFLAGS) -L$(MODULE_OUT) $($(THIS_MODULE)_ldflags)
+
+ifneq ($(BUILD),debug)
+ifeq ($(USE_LTO),1)
+MODULE_LDFLAGS := \
+ $(sort $(filter-out -W% -D%,$(ALL_HOST_CFLAGS) $(ALL_HOST_CXXFLAGS))) \
+ $(MODULE_LDFLAGS)
+endif
+endif
diff --git a/drivers/gpu/rogue/build/linux/moduledefs/target_aarch64.mk b/drivers/gpu/rogue/build/linux/moduledefs/target_aarch64.mk
new file mode 100644
index 000000000000..20326f995995
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/moduledefs/target_aarch64.mk
@@ -0,0 +1,98 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+MODULE_CC := $(CC)
+MODULE_CXX := $(CXX)
+
+MODULE_CFLAGS := $(ALL_CFLAGS) $($(THIS_MODULE)_cflags)
+MODULE_CXXFLAGS := $(ALL_CXXFLAGS) $($(THIS_MODULE)_cxxflags)
+MODULE_LDFLAGS := $(ALL_LDFLAGS) $($(THIS_MODULE)_ldflags) -L$(MODULE_OUT) -Xlinker -rpath-link=$(MODULE_OUT)
+
+# Since this is a target module, add system-specific include flags.
+MODULE_INCLUDE_FLAGS := $(SYS_INCLUDES) $(MODULE_INCLUDE_FLAGS)
+
+ifneq ($(SUPPORT_ANDROID_PLATFORM),)
+_obj := $(TARGET_ROOT)/product/$(TARGET_DEVICE)/obj
+
+# Linker flags used to find system libraries.
+MODULE_SYSTEM_LIBRARY_DIR_FLAGS += \
+ -L$(_obj)/lib \
+ -Xlinker -rpath-link=$(_obj)/lib \
+ -L$(TARGET_ROOT)/product/$(TARGET_DEVICE)/system/lib64 \
+ -Xlinker -rpath-link=$(TARGET_ROOT)/product/$(TARGET_DEVICE)/system/lib64
+
+# Add architecture-specific Android include flags
+MODULE_INCLUDE_FLAGS := \
+ -isystem $(ANDROID_ROOT)/bionic/libc/arch-arm64/include \
+ -isystem $(ANDROID_ROOT)/bionic/libc/kernel/uapi/asm-arm64 \
+ -isystem $(ANDROID_ROOT)/bionic/libm/include/arm64 \
+ $(MODULE_INCLUDE_FLAGS)
+
+MODULE_LDFLAGS += $(MODULE_SYSTEM_LIBRARY_DIR_FLAGS)
+
+MODULE_EXE_LDFLAGS := \
+ -Bdynamic -nostdlib -Wl,-dynamic-linker,/system/bin/linker64 \
+ -lc -ldl -lcutils
+MODULE_LIB_LDFLAGS := $(MODULE_EXE_LDFLAGS)
+
+MODULE_EXE_CRTBEGIN := $(_obj)/lib/crtbegin_dynamic.o
+MODULE_EXE_CRTEND := $(_obj)/lib/crtend_android.o
+
+MODULE_LIB_CRTBEGIN := $(_obj)/lib/crtbegin_so.o
+MODULE_LIB_CRTEND := $(_obj)/lib/crtend_so.o
+
+MODULE_LIBGCC := $(LIBGCC)
+endif
+
+ifneq ($(BUILD),debug)
+ifeq ($(USE_LTO),1)
+MODULE_LDFLAGS := \
+ $(sort $(filter-out -W% -D%,$(ALL_CFLAGS) $(ALL_CXXFLAGS))) \
+ $(MODULE_LDFLAGS)
+endif
+endif
+
+MODULE_SSL_ARCH :=
+
+# Neutrino qcc requires "-Wc," prefix for compiler flags
+ifeq ($(SUPPORT_NEUTRINO_PLATFORM),1)
+include $(MAKE_TOP)/common/neutrino/modify_moduledefs.mk
+endif
diff --git a/drivers/gpu/rogue/build/linux/moduledefs/target_armv7-a.mk b/drivers/gpu/rogue/build/linux/moduledefs/target_armv7-a.mk
new file mode 100644
index 000000000000..abb169e97f22
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/moduledefs/target_armv7-a.mk
@@ -0,0 +1,103 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+MODULE_CC := $(CC_SECONDARY) -march=armv7-a -mfloat-abi=softfp
+MODULE_CXX := $(CXX_SECONDARY) -march=armv7-a -mfloat-abi=softfp
+
+ifneq ($(BUILD),debug)
+MODULE_CC := $(MODULE_CC) -mthumb
+MODULE_CXX := $(MODULE_CXX) -mthumb
+endif
+
+MODULE_CFLAGS := $(ALL_CFLAGS) $($(THIS_MODULE)_cflags)
+MODULE_CXXFLAGS := $(ALL_CXXFLAGS) $($(THIS_MODULE)_cxxflags)
+MODULE_LDFLAGS := $(ALL_LDFLAGS) $($(THIS_MODULE)_ldflags) -L$(MODULE_OUT) -Xlinker -rpath-link=$(MODULE_OUT)
+
+# Since this is a target module, add system-specific include flags.
+MODULE_INCLUDE_FLAGS := $(SYS_INCLUDES) $(MODULE_INCLUDE_FLAGS)
+
+ifneq ($(SUPPORT_ANDROID_PLATFORM),)
+_obj := $(TARGET_ROOT)/product/$(TARGET_DEVICE)/obj$(if $(MULTIARCH),_arm,)
+
+# Linker flags used to find system libraries.
+MODULE_SYSTEM_LIBRARY_DIR_FLAGS += \
+ -L$(_obj)/lib \
+ -Xlinker -rpath-link=$(_obj)/lib \
+ -L$(TARGET_ROOT)/product/$(TARGET_DEVICE)/system/lib \
+ -Xlinker -rpath-link=$(TARGET_ROOT)/product/$(TARGET_DEVICE)/system/lib
+
+# Add architecture-specific Android include flags
+MODULE_INCLUDE_FLAGS := \
+ -isystem $(ANDROID_ROOT)/bionic/libc/arch-arm/include \
+ -isystem $(ANDROID_ROOT)/bionic/libc/kernel/uapi/asm-arm \
+ -isystem $(ANDROID_ROOT)/bionic/libm/include/arm \
+ $(MODULE_INCLUDE_FLAGS)
+
+MODULE_LDFLAGS += $(MODULE_SYSTEM_LIBRARY_DIR_FLAGS)
+
+MODULE_EXE_LDFLAGS := \
+ -Bdynamic -nostdlib -Wl,-dynamic-linker,/system/bin/linker \
+ -lc -ldl -lcutils
+MODULE_LIB_LDFLAGS := $(MODULE_EXE_LDFLAGS)
+
+MODULE_EXE_CRTBEGIN := $(_obj)/lib/crtbegin_dynamic.o
+MODULE_EXE_CRTEND := $(_obj)/lib/crtend_android.o
+
+MODULE_LIB_CRTBEGIN := $(_obj)/lib/crtbegin_so.o
+MODULE_LIB_CRTEND := $(_obj)/lib/crtend_so.o
+
+MODULE_LIBGCC := $(LIBGCC_SECONDARY)
+endif
+
+ifneq ($(BUILD),debug)
+ifeq ($(USE_LTO),1)
+MODULE_LDFLAGS := \
+ $(sort $(filter-out -W% -D%,$(ALL_CFLAGS) $(ALL_CXXFLAGS))) \
+ $(MODULE_LDFLAGS)
+endif
+endif
+
+MODULE_SSL_ARCH :=
+
+# Neutrino qcc requires "-Wc," prefix for compiler flags
+ifeq ($(SUPPORT_NEUTRINO_PLATFORM),1)
+include $(MAKE_TOP)/common/neutrino/modify_moduledefs.mk
+endif
diff --git a/drivers/gpu/rogue/build/linux/moduledefs/target_i686.mk b/drivers/gpu/rogue/build/linux/moduledefs/target_i686.mk
new file mode 100644
index 000000000000..8978f7897fcd
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/moduledefs/target_i686.mk
@@ -0,0 +1,102 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+MODULE_CC := $(CC_SECONDARY) $(TARGET_FORCE_32BIT) -march=i686
+MODULE_CXX := $(CXX_SECONDARY) $(TARGET_FORCE_32BIT) -march=i686
+
+MODULE_CFLAGS := $(ALL_CFLAGS) $($(THIS_MODULE)_cflags) $(TARGET_FORCE_32BIT) -march=i686
+MODULE_CXXFLAGS := $(ALL_CXXFLAGS) $($(THIS_MODULE)_cxxflags) $(TARGET_FORCE_32BIT) -march=i686
+MODULE_LDFLAGS := $(ALL_LDFLAGS) $($(THIS_MODULE)_ldflags) -L$(MODULE_OUT) -Xlinker -rpath-link=$(MODULE_OUT) $(TARGET_FORCE_32BIT)
+
+# Since this is a target module, add system-specific include flags.
+MODULE_INCLUDE_FLAGS := $(SYS_INCLUDES) $(MODULE_INCLUDE_FLAGS)
+
+ifneq ($(SUPPORT_ANDROID_PLATFORM),)
+_obj := $(TARGET_ROOT)/product/$(TARGET_DEVICE)/obj$(if $(MULTIARCH),_x86,)
+
+# Linker flags used to find system libraries.
+MODULE_SYSTEM_LIBRARY_DIR_FLAGS += \
+ -L$(_obj)/lib \
+ -Xlinker -rpath-link=$(_obj)/lib \
+ -L$(TARGET_ROOT)/product/$(TARGET_DEVICE)/system/lib \
+ -Xlinker -rpath-link=$(TARGET_ROOT)/product/$(TARGET_DEVICE)/system/lib
+
+# Add architecture-specific Android include flags
+MODULE_INCLUDE_FLAGS := \
+ -isystem $(ANDROID_ROOT)/bionic/libc/arch-x86/include \
+ -isystem $(ANDROID_ROOT)/bionic/libc/kernel/uapi/asm-x86 \
+ -isystem $(ANDROID_ROOT)/bionic/libm/include/i387 \
+ $(MODULE_INCLUDE_FLAGS)
+
+MODULE_LDFLAGS += $(MODULE_SYSTEM_LIBRARY_DIR_FLAGS)
+
+MODULE_EXE_LDFLAGS := \
+ -Bdynamic -nostdlib -Wl,-dynamic-linker,/system/bin/linker \
+ -lc -ldl -lcutils
+MODULE_LIB_LDFLAGS := $(MODULE_EXE_LDFLAGS)
+
+MODULE_EXE_CRTBEGIN := $(_obj)/lib/crtbegin_dynamic.o
+MODULE_EXE_CRTEND := $(_obj)/lib/crtend_android.o
+
+MODULE_LIB_CRTBEGIN := $(_obj)/lib/crtbegin_so.o
+MODULE_LIB_CRTEND := $(_obj)/lib/crtend_so.o
+
+MODULE_LIBGCC := $(LIBGCC_SECONDARY)
+else
+# On Linux, we currently don't need to specify any flags to find the system
+# libraries.
+MODULE_SYSTEM_LIBRARY_DIR_FLAGS :=
+endif
+
+ifneq ($(BUILD),debug)
+ifeq ($(USE_LTO),1)
+MODULE_LDFLAGS := \
+ $(sort $(filter-out -W% -D%,$(ALL_CFLAGS) $(ALL_CXXFLAGS))) \
+ $(MODULE_LDFLAGS)
+endif
+endif
+
+MODULE_SSL_ARCH := linux-generic32
+
+# Neutrino qcc requires "-Wc," prefix for compiler flags
+ifeq ($(SUPPORT_NEUTRINO_PLATFORM),1)
+include $(MAKE_TOP)/common/neutrino/modify_moduledefs.mk
+endif
diff --git a/drivers/gpu/rogue/build/linux/moduledefs/target_neutral.mk b/drivers/gpu/rogue/build/linux/moduledefs/target_neutral.mk
new file mode 100644
index 000000000000..6b58e5e81387
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/moduledefs/target_neutral.mk
@@ -0,0 +1,44 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+MODULE_BISON_FLAGS := $(ALL_BISON_FLAGS) $($(THIS_MODULE)_bisonflags)
+MODULE_FLEX_FLAGS := $(ALL_FLEX_FLAGS) $($(THIS_MODULE)_flexflags)
+MODULE_FLEXXX_FLAGS := $(ALL_FLEXXX_FLAGS) $($(THIS_MODULE)_flexxxflags)
diff --git a/drivers/gpu/rogue/build/linux/moduledefs/target_x86_64.mk b/drivers/gpu/rogue/build/linux/moduledefs/target_x86_64.mk
new file mode 100644
index 000000000000..9eacfb0d31f4
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/moduledefs/target_x86_64.mk
@@ -0,0 +1,100 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+MODULE_CC := $(CC) -march=x86-64
+MODULE_CXX := $(CXX) -march=x86-64
+
+MODULE_CFLAGS := $(ALL_CFLAGS) $($(THIS_MODULE)_cflags) -march=x86-64
+MODULE_CXXFLAGS := $(ALL_CXXFLAGS) $($(THIS_MODULE)_cxxflags) -march=x86-64
+MODULE_LDFLAGS := $(ALL_LDFLAGS) $($(THIS_MODULE)_ldflags) -L$(MODULE_OUT) -Xlinker -rpath-link=$(MODULE_OUT)
+
+# Since this is a target module, add system-specific include flags.
+MODULE_INCLUDE_FLAGS := $(SYS_INCLUDES) $(MODULE_INCLUDE_FLAGS)
+
+ifneq ($(SUPPORT_ANDROID_PLATFORM),)
+# Linker flags used to find system libraries.
+MODULE_SYSTEM_LIBRARY_DIR_FLAGS += \
+ -L$(TARGET_ROOT)/product/$(TARGET_DEVICE)/obj/lib \
+ -Xlinker -rpath-link=$(TARGET_ROOT)/product/$(TARGET_DEVICE)/obj/lib \
+ -L$(TARGET_ROOT)/product/$(TARGET_DEVICE)/system/lib64 \
+ -Xlinker -rpath-link=$(TARGET_ROOT)/product/$(TARGET_DEVICE)/system/lib64
+
+# Add architecture-specific Android include flags
+MODULE_INCLUDE_FLAGS := \
+ -isystem $(ANDROID_ROOT)/bionic/libc/arch-x86_64/include \
+ -isystem $(ANDROID_ROOT)/bionic/libc/kernel/uapi/asm-x86 \
+ -isystem $(ANDROID_ROOT)/bionic/libm/include/amd64 \
+ $(MODULE_INCLUDE_FLAGS)
+
+MODULE_LDFLAGS += $(MODULE_SYSTEM_LIBRARY_DIR_FLAGS)
+
+MODULE_EXE_LDFLAGS := \
+ -Bdynamic -nostdlib -Wl,-dynamic-linker,/system/bin/linker64 \
+ -lc -ldl -lcutils
+MODULE_LIB_LDFLAGS := $(MODULE_EXE_LDFLAGS)
+
+MODULE_EXE_CRTBEGIN := $(TARGET_ROOT)/product/$(TARGET_DEVICE)/obj/lib/crtbegin_dynamic.o
+MODULE_EXE_CRTEND := $(TARGET_ROOT)/product/$(TARGET_DEVICE)/obj/lib/crtend_android.o
+
+MODULE_LIB_CRTBEGIN := $(TARGET_ROOT)/product/$(TARGET_DEVICE)/obj/lib/crtbegin_so.o
+MODULE_LIB_CRTEND := $(TARGET_ROOT)/product/$(TARGET_DEVICE)/obj/lib/crtend_so.o
+
+MODULE_LIBGCC := $(LIBGCC)
+else
+# On Linux, we currently don't need to specify any flags to find the system
+# libraries.
+MODULE_SYSTEM_LIBRARY_DIR_FLAGS :=
+endif
+
+ifneq ($(BUILD),debug)
+ifeq ($(USE_LTO),1)
+MODULE_LDFLAGS := \
+ $(sort $(filter-out -W% -D%,$(ALL_CFLAGS) $(ALL_CXXFLAGS))) \
+ $(MODULE_LDFLAGS)
+endif
+endif
+
+MODULE_SSL_ARCH := linux-x86_64
+
+# Neutrino qcc requires "-Wc," prefix for compiler flags
+ifeq ($(SUPPORT_NEUTRINO_PLATFORM),1)
+include $(MAKE_TOP)/common/neutrino/modify_moduledefs.mk
+endif
diff --git a/drivers/gpu/rogue/build/linux/moduledefs_common.mk b/drivers/gpu/rogue/build/linux/moduledefs_common.mk
new file mode 100644
index 000000000000..9d0fbbf614d1
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/moduledefs_common.mk
@@ -0,0 +1,121 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+MODULE_OUT := $(RELATIVE_OUT)/$(MODULE_ARCH)
+MODULE_INTERMEDIATES_DIR := $(MODULE_OUT)/intermediates/$(THIS_MODULE)
+
+MODULE_TARGETS :=
+MODULE_HOST_BUILD :=
+MODULE_CLEAN_TARGETS :=
+MODULE_CLOBBER_TARGETS :=
+
+MODULE_CFLAGS :=
+MODULE_CXXFLAGS :=
+MODULE_LDFLAGS :=
+MODULE_BISON_FLAGS :=
+MODULE_FLEX_FLAGS :=
+MODULE_FLEXXX_FLAGS :=
+
+# Only allow cflags that do not affect code generation. This is to ensure
+# proper binary compatibility when LTO (Link-Time Optimization) is enabled.
+# We make exceptions for the below flags which will all fail linkage in
+# non-LTO mode if incorrectly specified.
+#
+# NOTE: Only used by static_library and objects right now. Other module
+# types should not be affected by complex code generation flags w/ LTO.
+# Set MODULE_CHECK_CFLAGS in the module makefile to enable this check.
+MODULE_CHECK_CFLAGS :=
+MODULE_ALLOWED_CFLAGS := -W% -D% -std=% -fPIC -fPIE -pie -m32
+
+# -L flags for library search dirs: these are relative to $(TOP), unless
+# they're absolute paths
+MODULE_LIBRARY_DIR_FLAGS := $(foreach _path,$($(THIS_MODULE)_libpaths),$(if $(filter /%,$(_path)),-L$(call relative-to-top,$(_path)),-L$(_path)))
+# -L options to find system libraries (may be arch-specific)
+MODULE_SYSTEM_LIBRARY_DIR_FLAGS :=
+# -I flags for header search dirs (same rules as for -L)
+MODULE_INCLUDE_FLAGS := $(foreach _path,$($(THIS_MODULE)_includes),$(if $(filter /%,$(_path)),-I$(call relative-to-top,$(_path)),-I$(_path)))
+
+# If the build provides some external khronos include flags, and the module
+# hasn't explicitly opted out of path substitution, prepend the system path
+# to the DDK khronos header include path. This causes the platform headers
+# to override the DDK versions. This is the default behaviour for Android.
+ifneq ($(SYS_KHRONOS_INCLUDES),)
+ifneq ($($(THIS_MODULE)_force_internal_khronos_headers),1)
+MODULE_INCLUDE_FLAGS := $(patsubst -Iinclude/khronos,$(SYS_KHRONOS_INCLUDES) -Iinclude/khronos,$(MODULE_INCLUDE_FLAGS))
+endif
+endif
+
+# These define the rules for finding source files.
+# - If a name begins with a slash, we strip $(TOP) off the front if it begins
+# with $(TOP). This is so that we don't get really long error messages from
+# the compiler if the source tree is in a deeply nested directory, but we
+# still do get absolute paths if you say "make OUT=/tmp/somewhere"
+# - Otherwise, if a name contains a slash and begins with $(OUT), we leave it
+# as it is. This is so you can say "module_src :=
+# $(TARGET_INTERMEDIATES)/something/generated.c"
+# - Otherwise, we assume it's a path referring to somewhere under the
+# directory containing Linux.mk, and add $(THIS_DIR) to it
+_SOURCES_WITHOUT_SLASH := $(strip $(foreach _s,$($(THIS_MODULE)_src),$(if $(findstring /,$(_s)),,$(_s))))
+_SOURCES_WITH_SLASH := $(strip $(foreach _s,$($(THIS_MODULE)_src),$(if $(findstring /,$(_s)),$(_s),)))
+MODULE_SOURCES := $(addprefix $(THIS_DIR)/,$(_SOURCES_WITHOUT_SLASH))
+MODULE_SOURCES += $(call relative-to-top,$(filter /%,$(_SOURCES_WITH_SLASH)))
+
+_RELATIVE_SOURCES_WITH_SLASH := $(filter-out /%,$(_SOURCES_WITH_SLASH))
+_OUTDIR_RELATIVE_SOURCES_WITH_SLASH := $(filter $(RELATIVE_OUT)/%,$(_RELATIVE_SOURCES_WITH_SLASH))
+_THISDIR_RELATIVE_SOURCES_WITH_SLASH := $(filter-out $(RELATIVE_OUT)/%,$(_RELATIVE_SOURCES_WITH_SLASH))
+MODULE_SOURCES += $(_OUTDIR_RELATIVE_SOURCES_WITH_SLASH)
+MODULE_SOURCES += $(addprefix $(THIS_DIR)/,$(_THISDIR_RELATIVE_SOURCES_WITH_SLASH))
+
+# Add generated sources
+MODULE_SOURCES += $(addprefix $(MODULE_OUT)/,$($(THIS_MODULE)_src_relative))
+
+# -l flags for each library. The rules are:
+# - for all static libs, use -lfoo
+# - for all in-tree or external libs, use $(libfoo_ldflags) if that
+# variable is defined (empty counts as defined). Otherwise use
+# -lfoo.
+MODULE_LIBRARY_FLAGS := $(addprefix -l, $($(THIS_MODULE)_staticlibs)) $(addprefix -l,$($(THIS_MODULE)_libs)) $(foreach _lib,$($(THIS_MODULE)_extlibs),$(if $(filter undefined,$(origin lib$(_lib)_ldflags)),-l$(_lib),$(lib$(_lib)_ldflags)))
+
+# pkg-config integration; primarily used by X.Org
+# We don't support arbitrary CFLAGS yet (just includes)
+$(foreach _package,$($(THIS_MODULE)_packages),\
+ $(eval MODULE_INCLUDE_FLAGS += `pkg-config --cflags-only-I $(_package)`)\
+ $(eval MODULE_LIBRARY_FLAGS += `pkg-config --libs-only-l $(_package)`)\
+ $(eval MODULE_LIBRARY_DIR_FLAGS += `pkg-config --libs-only-L $(_package)`))
diff --git a/drivers/gpu/rogue/build/linux/modules.mk b/drivers/gpu/rogue/build/linux/modules.mk
new file mode 100644
index 000000000000..971f21a20a25
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/modules.mk
@@ -0,0 +1,48 @@
+########################################################################### ###
+#@Title Module processing
+#@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.
+### ###########################################################################
+
+# Bits for processing $(modules) after reading in each Linux.mk
+
+#$(info ---- $(modules) ----)
+
+$(foreach _m,$(modules),$(if $(filter $(_m),$(ALL_MODULES)),$(error In makefile $(THIS_MAKEFILE): Duplicate module $(_m) (first seen in $(INTERNAL_MAKEFILE_FOR_MODULE_$(_m))) listed in $$(modules)),$(eval $(call register-module,$(_m)))))
+
+ALL_MODULES += $(modules)
diff --git a/drivers/gpu/rogue/build/linux/modules/_objects.mk b/drivers/gpu/rogue/build/linux/modules/_objects.mk
new file mode 100644
index 000000000000..ecfa56bdb1a7
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/modules/_objects.mk
@@ -0,0 +1,117 @@
+########################################################################### ###
+#@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.
+#@Description Common processing for all modules that compile code.
+### ###########################################################################
+
+# Filter for source types
+MODULE_C_SOURCES := $(filter %.c,$(MODULE_SOURCES))
+MODULE_CXX_SOURCES := $(call filter-cxx-files,$(MODULE_SOURCES))
+
+MODULE_UNRECOGNISED_SOURCES := $(call filter-out-cxx-files,$(filter-out %.c,$(MODULE_SOURCES)))
+
+ifneq ($(strip $(MODULE_UNRECOGNISED_SOURCES)),)
+$(error In makefile $(THIS_MAKEFILE): Module $(THIS_MODULE) specified source files with unrecognised suffixes: $(MODULE_UNRECOGNISED_SOURCES))
+endif
+
+# Objects built from MODULE_SOURCES
+MODULE_C_OBJECTS := $(addprefix $(MODULE_INTERMEDIATES_DIR)/,$(notdir $(MODULE_C_SOURCES:.c=.o)))
+MODULE_CXX_OBJECTS := $(addprefix $(MODULE_INTERMEDIATES_DIR)/,$(notdir $(call objects-from-cxx-files,$(MODULE_CXX_SOURCES))))
+
+# MODULE_GENERATED_DEPENDENCIES are generated as a side effect of running the
+# rules below, but if we wanted to generate .d files for things that GCC
+# couldn't handle, we could add a rule with $(MODULE_GENERATED_DEPENDENCIES)
+# as a target
+MODULE_GENERATED_DEPENDENCIES := $(MODULE_C_OBJECTS:.o=.d) $(MODULE_CXX_OBJECTS:.o=.d)
+-include $(MODULE_GENERATED_DEPENDENCIES)
+
+MODULE_DEPENDS := $(addprefix $(MODULE_OUT)/,$($(THIS_MODULE)_depends))
+MODULE_DEPENDS += $(addprefix $(GENERATED_CODE_OUT)/,$($(THIS_MODULE)_genheaders))
+
+# Add any MODULE_OUT relative include flags here
+MODULE_INCLUDE_FLAGS += $(addprefix -I $(MODULE_OUT)/, $($(THIS_MODULE)_includes_relative))
+
+define rule-for-objects-o-from-one-c
+$(1): MODULE_CC := $$(MODULE_CC)
+$(1): MODULE_CFLAGS := $$(MODULE_CFLAGS)
+$(1): MODULE_INCLUDE_FLAGS := $$(MODULE_INCLUDE_FLAGS)
+$(1): MODULE_ALLOWED_CFLAGS := $$(MODULE_ALLOWED_CFLAGS)
+$(1): THIS_MODULE := $$(THIS_MODULE)
+ifneq ($(PKG_CONFIG_ENV_VAR),)
+$(1): export PKG_CONFIG_TOP_BUILD_DIR := $(abspath $(MODULE_OUT))
+$(1): export $(PKG_CONFIG_ENV_VAR) := $(abspath $(MODULE_OUT)/lws_pkgconfig)
+endif
+$(1): $$(MODULE_DEPENDS) $$(THIS_MAKEFILE)
+$(1): | $$(MODULE_INTERMEDIATES_DIR)
+$(1): $(2)
+ @: $(if $(MODULE_CHECK_CFLAGS),
+ $(if $(filter-out $(MODULE_ALLOWED_CFLAGS),$($(THIS_MODULE)_cflags)),\
+ $(error $(THIS_MODULE): LTO-incompatible cflag(s) used: \
+ $(filter-out $(MODULE_ALLOWED_CFLAGS),$($(THIS_MODULE)_cflags)))))
+ $$(check-src)
+ifeq ($(MODULE_HOST_BUILD),true)
+ $$(host-o-from-one-c)
+else
+ $$(target-o-from-one-c)
+endif
+endef
+
+# This rule is used to compile C++ source files
+define rule-for-objects-o-from-one-cxx
+$(1): MODULE_CXX := $$(MODULE_CXX)
+$(1): MODULE_CXXFLAGS := $$(MODULE_CXXFLAGS)
+$(1): MODULE_INCLUDE_FLAGS := $$(MODULE_INCLUDE_FLAGS)
+$(1): MODULE_ALLOWED_CFLAGS := $$(MODULE_ALLOWED_CFLAGS)
+$(1): THIS_MODULE := $$(THIS_MODULE)
+ifneq ($(PKG_CONFIG_ENV_VAR),)
+$(1): export PKG_CONFIG_TOP_BUILD_DIR := $(abspath $(MODULE_OUT))
+$(1): export $(PKG_CONFIG_ENV_VAR) := $(abspath $(MODULE_OUT)/lws_pkgconfig)
+endif
+$(1): $$(MODULE_DEPENDS) $$(THIS_MAKEFILE)
+$(1): | $$(MODULE_INTERMEDIATES_DIR)
+$(1): $(2)
+ @: $(if $(MODULE_CHECK_CFLAGS),
+ $(if $(filter-out $(MODULE_ALLOWED_CFLAGS),$($(THIS_MODULE)_cxxflags)),\
+ $(error $(THIS_MODULE): LTO-incompatible cxxflag(s) used: \
+ $(filter-out $(MODULE_ALLOWED_CFLAGS),$($(THIS_MODULE)_cxxflags)))))
+ifeq ($(MODULE_HOST_BUILD),true)
+ $$(host-o-from-one-cxx)
+else
+ $$(target-o-from-one-cxx)
+endif
+endef
diff --git a/drivers/gpu/rogue/build/linux/modules/kernel_module.mk b/drivers/gpu/rogue/build/linux/modules/kernel_module.mk
new file mode 100644
index 000000000000..9a2ae69c49fe
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/modules/kernel_module.mk
@@ -0,0 +1,92 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+# Rules for making kernel modules with kbuild. This makefile doesn't define
+# any rules that build the modules, it only copies the kbuild Makefile into
+# the right place and then invokes kbuild to do the actual build
+
+$(call target-build-only,kernel module)
+
+MODULE_KBUILD_DIR := $(MODULE_OUT)/kbuild
+
+# $(THIS_MODULE)_makefile names the kbuild makefile fragment used to build
+# this module's objects
+$(call must-be-nonempty,$(THIS_MODULE)_makefile)
+MODULE_KBUILD_MAKEFILE := $($(THIS_MODULE)_makefile)
+
+# $(THIS_MODULE)_target specifies the name of the kernel module
+$(call must-be-nonempty,$(THIS_MODULE)_target)
+MODULE_TARGETS := $($(THIS_MODULE)_target)
+MODULE_KBUILD_OBJECTS := $($(THIS_MODULE)_target:.ko=.o)
+
+$(call module-info-line,kernel module: $(MODULE_TARGETS))
+
+# Unusually, we define $(THIS_MODULE)_install_path if the user didn't, as we
+# can't use MODULE_INSTALL_PATH in the scripts.mk logic.
+ifeq ($($(THIS_MODULE)_install_path),)
+$(THIS_MODULE)_install_path := \
+ $${MOD_DESTDIR}/$(patsubst $(MODULE_OUT)/%,%,$(MODULE_TARGETS))
+endif
+
+MODULE_INSTALL_PATH := $($(THIS_MODULE)_install_path)
+
+# Here we could maybe include $(MODULE_KBUILD_MAKEFILE) and look at
+# $(MODULE_KBUILD_OBJECTS)-y to see which source files might be built
+
+.PHONY: $(THIS_MODULE)
+$(THIS_MODULE): MODULE_KBUILD_MAKEFILE := $(MODULE_KBUILD_MAKEFILE)
+$(THIS_MODULE): MODULE_KBUILD_OBJECTS := $(MODULE_KBUILD_OBJECTS)
+$(THIS_MODULE):
+ @echo "kbuild module '$@'"
+ @echo " MODULE_KBUILD_MAKEFILE := $(MODULE_KBUILD_MAKEFILE)"
+ @echo " MODULE_KBUILD_OBJECTS := $(MODULE_KBUILD_OBJECTS)"
+ @echo ' Being built:' $(if $(filter $@,$(KERNEL_COMPONENTS)),"yes (separate module)",$(if $(filter $@,$(EXTRA_PVRSRVKM_COMPONENTS)),"yes (into pvrsrvkm)","no"))
+ @echo "Module $@ is a kbuild module. Run 'make kbuild' to make it"
+ @false
+
+$(MODULE_INTERMEDIATES_DIR)/.install: MODULE_TYPE := $($(THIS_MODULE)_type)
+$(MODULE_INTERMEDIATES_DIR)/.install: MODULE_INSTALL_PATH := $(MODULE_INSTALL_PATH)
+$(MODULE_INTERMEDIATES_DIR)/.install: MODULE_TARGETS := $(patsubst $(MODULE_OUT)/%,%,$(MODULE_TARGETS))
+$(MODULE_INTERMEDIATES_DIR)/.install: $(THIS_MAKEFILE) | $(MODULE_INTERMEDIATES_DIR)
+ @echo 'install_file $(MODULE_TARGETS) $(MODULE_INSTALL_PATH) "$(MODULE_TYPE)" 0644 0:0' >$@
+
+ALL_KBUILD_MODULES += $(THIS_MODULE)
+INTERNAL_KBUILD_MAKEFILE_FOR_$(THIS_MODULE) := $(MODULE_KBUILD_MAKEFILE)
+INTERNAL_KBUILD_OBJECTS_FOR_$(THIS_MODULE) := $(MODULE_KBUILD_OBJECTS)
diff --git a/drivers/gpu/rogue/build/linux/pc_android/Makefile b/drivers/gpu/rogue/build/linux/pc_android/Makefile
new file mode 100644
index 000000000000..996d13a8a8bb
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/pc_android/Makefile
@@ -0,0 +1,139 @@
+########################################################################### ###
+#@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 ../config/preconfig.mk
+
+# If a TARGET_PRODUCT is specified but not a TARGET_DEVICE, try to
+# derive the TARGET_DEVICE from TARGET_PRODUCT.
+#
+ifeq ($(TARGET_DEVICE),)
+override TARGET_DEVICE := \
+ $(patsubst mini_%,%,$(patsubst full_%,%,$(TARGET_PRODUCT)))
+endif
+
+ifeq ($(TARGET_DEVICE),)
+override TARGET_DEVICE := pc
+endif
+
+HAL_VARIANT := pc
+
+#RGX_BVNC ?= 1.7.4.5
+RGX_BVNC ?= 1.82.4.5
+
+include ../common/android/paths.mk
+include ../common/android/arch.mk
+include ../common/android/features.mk
+
+ifeq ($(SUPPORT_ADF),1)
+ifneq ($(is_future_version),1)
+SYS_INCLUDES += \
+ -isystem $(ANDROID_ROOT)/device/img/pc/adf/libadf/include \
+ -isystem $(ANDROID_ROOT)/device/img/pc/adf/libadfhwc/include
+endif
+endif
+
+ifeq ($(NO_HARDWARE),1)
+ LDM_PLATFORM := 1
+ PVR_SYSTEM := rgx_nohw
+ # If we end up using dc_fbdev, Android always wants to be
+ # triple buffered in when running in pure-software mode.
+ DC_FBDEV_NUM_PREFERRED_BUFFERS := 3
+else
+ ifeq ($(SUPPORT_ADF),1)
+ PVR_LDM_PLATFORM_PRE_REGISTERED := 1
+ LMA := 1
+ LDM_PLATFORM := 1
+ PVR_SYSTEM := rgx_linux_apollo
+ SUPPORT_SYSTEM_INTERRUPT_HANDLING := 1
+ ION_DEFAULT_HEAP_ID_MASK := (1 << (ION_HEAP_TYPE_CUSTOM + 2))
+ else
+ LDM_PCI := 1
+ PVR_SYSTEM := rgx_tc
+ TC_MEMORY_CONFIG := TC_MEMORY_LOCAL
+ SUPPORT_SYSTEM_INTERRUPT_HANDLING := 1
+ endif
+endif
+
+ifeq ($(SUPPORT_ADF),1)
+ ifneq ($(NO_HARDWARE),1)
+ DISPLAY_CONTROLLER ?= adf_pdp
+ endif
+else
+ ifeq ($(NO_HARDWARE),1)
+ DISPLAY_CONTROLLER ?= dc_example
+ else
+ DISPLAY_CONTROLLER ?= dc_pdp
+ endif
+endif
+
+ifeq ($(DISPLAY_CONTROLLER),adf_pdp)
+ADF_PDP_WIDTH ?= 1280
+ADF_PDP_HEIGHT ?= 720
+KERNEL_COMPONENTS += apollo
+endif
+
+KERNEL_COMPONENTS += $(DISPLAY_CONTROLLER)
+
+CACHEFLUSH_TYPE ?= CACHEFLUSH_X86
+
+PVR_ANDROID_DEFER_CLEAR ?= 1
+
+ifeq ($(PVR_SYSTEM),rgx_tc)
+ifeq ($(TC_MEMORY_CONFIG),TC_MEMORY_LOCAL)
+LMA := 1
+# Tell ion that we want memory from the test chip local memory
+# heap. The choice of ION_HEAP_TYPE_CUSTOM+1 as the ID is
+# arbitrary, but it has to match the one specified in the
+# TC-specific ion support code.
+ION_DEFAULT_HEAP_ID_MASK := 1 << (ION_HEAP_TYPE_CUSTOM + 1)
+endif
+endif
+
+ifeq ($(DISPLAY_CONTROLLER),dc_pdp)
+DCPDP_WIDTH ?= 1280
+DCPDP_HEIGHT ?= 720
+DCPDP_NO_INTERRUPTS ?= 1
+endif
+
+include ../config/core.mk
+include ../common/android/extra_config.mk
+include ../common/pvrgdb.mk
+include ../common/3rdparty.mk
+include ../common/testchip.mk
diff --git a/drivers/gpu/rogue/build/linux/prepare_tree.mk b/drivers/gpu/rogue/build/linux/prepare_tree.mk
new file mode 100644
index 000000000000..d59314368ee3
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/prepare_tree.mk
@@ -0,0 +1,56 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+.PHONY: prepare_tree
+
+prepare_tree:
+
+INTERNAL_INCLUDED_PREPARE_HEADERS :=
+-include build/linux/prepare_headers.mk
+ifneq ($(INTERNAL_INCLUDED_PREPARE_HEADERS),true)
+missing_headers := $(strip $(shell test ! -e include/pvrversion.h && echo true))
+ifdef missing_headers
+$(info )
+$(info ** include/pvrversion.h is missing, and cannot be rebuilt.)
+$(info ** Cannot continue.)
+$(info )
+$(error Missing headers)
+endif
+endif
diff --git a/drivers/gpu/rogue/build/linux/pvrversion.mk b/drivers/gpu/rogue/build/linux/pvrversion.mk
new file mode 100644
index 000000000000..10c25f3ce072
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/pvrversion.mk
@@ -0,0 +1,57 @@
+########################################################################### ###
+#@Title Extract info from pvrversion.h
+#@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.
+### ###########################################################################
+
+# Version information
+PVRVERSION_H := $(call if-exists,include/pvrversion.h,$(OUT)/include/pvrversion.h)
+
+ifneq ($(wildcard $(PVRVERSION_H)),)
+
+# scripts.mk uses these to set the install script's version suffix
+PVRVERSION_MAJ := $(shell perl -ne '/\sPVRVERSION_MAJ\s+(\w+)/ and print $$1' $(PVRVERSION_H))
+PVRVERSION_MIN := $(shell perl -ne '/\sPVRVERSION_MIN\s+(\w+)/ and print $$1' $(PVRVERSION_H))
+PVRVERSION_FAMILY := $(shell perl -ne '/\sPVRVERSION_FAMILY\s+"(\S+)"/ and print $$1' $(PVRVERSION_H))
+PVRVERSION_BRANCHNAME := $(shell perl -ne '/\sPVRVERSION_BRANCHNAME\s+"(\S+)"/ and print $$1' $(PVRVERSION_H))
+PVRVERSION_BUILD := $(shell perl -ne '/\sPVRVERSION_BUILD\s+(\w+)/ and print $$1' $(PVRVERSION_H))
+
+PVRVERSION_NUM := $(PVRVERSION_MAJ).$(PVRVERSION_MIN).$(PVRVERSION_BUILD)
+PVRVERSION := "$(PVRVERSION_FAMILY)_$(PVRVERSION_BRANCHNAME)\@$(PVRVERSION_BUILD)"
+
+endif
diff --git a/drivers/gpu/rogue/build/linux/scripts.mk b/drivers/gpu/rogue/build/linux/scripts.mk
new file mode 100644
index 000000000000..4b388a649be5
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/scripts.mk
@@ -0,0 +1,341 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+ifeq ($(SUPPORT_ANDROID_PLATFORM),)
+
+define if-component
+ ifneq ($$(filter $(1),$$(COMPONENTS)),)
+ M4DEFS += $(2)
+ endif
+endef
+
+define if-kernel-component
+ ifneq ($$(filter $(1),$$(KERNEL_COMPONENTS)),)
+ M4DEFS_K += $(2)
+ endif
+endef
+
+# common.m4 lives here
+#
+M4FLAGS := -I$(MAKE_TOP)/scripts
+
+# These defs are required for both KM and UM install script.
+M4DEFS_K := \
+ -DPVRVERSION="$(PVRVERSION)" \
+ -DPVR_BUILD_DIR=$(PVR_BUILD_DIR) \
+ -DPVRSRV_MODNAME=$(PVRSRV_MODNAME)
+
+ifeq ($(SUPPORT_DRM),1)
+ M4DEFS_K += \
+ -DSUPPORT_DRM=1 \
+ -DSUPPORT_DRM_DC_MODULE=1
+endif
+
+ifeq ($(PDUMP),1)
+ M4DEFS_K += -DPDUMP=1
+endif
+
+ifneq ($(DISPLAY_CONTROLLER),)
+ $(eval $(call if-kernel-component,$(DISPLAY_CONTROLLER),\
+ -DDISPLAY_CONTROLLER=$(DISPLAY_CONTROLLER)))
+endif
+
+# These defs are not derived from user variables
+#
+M4DEFS := \
+ -DSOLIB_VERSION=$(PVRVERSION_MAJ).$(PVRVERSION_MIN).$(PVRVERSION_BUILD)
+
+# XOrg support options are convoluted, so don't bother with if-component.
+ifneq ($(filter pvr_video,$(COMPONENTS)),) # This is an X build
+ M4DEFS += -DSUPPORT_LWS=1
+ M4DEFS += -DSUPPORT_XORG=1
+ M4DEFS += -DXORG_EXPLICIT_PVR_SERVICES_LOAD=$(XORG_EXPLICIT_PVR_SERVICES_LOAD)
+
+ ifneq ($(XORG_WAYLAND),1)
+ M4DEFS += -DXORG_WAYLAND=1
+ endif
+
+ ifeq ($(LWS_NATIVE),1)
+ M4DEFS += -DPVR_XORG_DESTDIR=/usr/bin
+ M4DEFS += -DPVR_CONF_DESTDIR=/etc/X11
+ $(eval $(call if-component,opengl_mesa,-DSUPPORT_MESA=1))
+ else
+ M4DEFS += -DLWS_INSTALL_TREE=1
+ M4DEFS += -DPVR_XORG_DESTDIR=$(LWS_PREFIX)/bin
+ M4DEFS += -DPVR_CONF_DESTDIR=$(LWS_PREFIX)/etc/X11
+ $(eval $(call if-component,pvr_input, -DSUPPORT_DDX_INPUT=1))
+ $(eval $(call if-component,opengl_mesa,-DSUPPORT_LIBGL=1 -DSUPPORT_MESA=1))
+ endif
+else # This is a non-X build
+ ifneq ($(filter pvr_dri,$(COMPONENTS)),) # This is a Wayland build
+ M4DEFS += -DSUPPORT_LWS=1
+ M4DEFS += -DSUPPORT_WAYLAND=1
+
+ ifeq ($(LWS_NATIVE),1)
+ else
+ M4DEFS += -DLWS_INSTALL_TREE=1
+ endif
+ else # This is a non-X and Wayland build
+ $(eval $(call if-component,opengl,-DSUPPORT_LIBGL=1))
+ endif
+endif
+
+# Map other COMPONENTS on to SUPPORT_ defs
+#
+$(eval $(call if-component,opengles1,\
+ -DSUPPORT_OPENGLES1=1 -DOGLES1_MODULE=$(opengles1_target) \
+ -DSUPPORT_OPENGLES1_V1_ONLY=0))
+$(eval $(call if-component,opengles3,\
+ -DSUPPORT_OPENGLES3=1 -DOGLES3_MODULE=$(opengles3_target)))
+$(eval $(call if-component,egl,\
+ -DSUPPORT_LIBEGL=1 -DEGL_MODULE=$(egl_target)))
+$(eval $(call if-component,glslcompiler,\
+ -DSUPPORT_SOURCE_SHADER=1))
+$(eval $(call if-component,opencl,\
+ -DSUPPORT_OPENCL=1))
+$(eval $(call if-component,liboclcompiler,\
+ -DSUPPORT_OCL_COMPILER=1))
+$(eval $(call if-component,openrl,\
+ -DSUPPORT_OPENRL=1))
+$(eval $(call if-component,rscompute,\
+ -DSUPPORT_RSC=1))
+$(eval $(call if-component,librscruntime,\
+ -DSUPPORT_RSC_RUNTIME=1))
+$(eval $(call if-component,librsccompiler,\
+ -DSUPPORT_RSC_COMPILER=1))
+$(eval $(call if-component,opengl opengl_mesa,\
+ -DSUPPORT_OPENGL=1))
+$(eval $(call if-component,null_ws,\
+ -DSUPPORT_NULL_WS=1))
+$(eval $(call if-component,null_drm_ws,\
+ -DSUPPORT_NULL_DRM_WS=1 \
+ -DSUPPORT_LWS=1 \
+ -DLWS_INSTALL_TREE=1))
+$(eval $(call if-component,null_remote,\
+ -DSUPPORT_NULL_REMOTE=1))
+$(eval $(call if-component,null_adf_ws,\
+ -DSUPPORT_NULL_ADF_WS=1))
+$(eval $(call if-component,ews_ws,\
+ -DSUPPORT_EWS=1))
+$(eval $(call if-component,ews_wm,\
+ -DSUPPORT_LUA=1))
+$(eval $(call if-component,graphicshal,\
+ -DSUPPORT_GRAPHICS_HAL=1))
+$(eval $(call if-component,xmultiegltest,\
+ -DSUPPORT_XUNITTESTS=1))
+$(eval $(call if-component,pvrgdb,\
+ -DPVRGDB=1))
+
+ifeq ($(PVR_REMOTE),1)
+ M4DEFS += -DPVR_REMOTE=1
+endif
+
+ifneq ($(filter pvr_dri,$(COMPONENTS)),)
+ M4DEFS += -DPVR_DRI_MODULE=1
+endif
+
+# Build UM script using old scheme using M4
+define create-install-um-script-m4
+$(RELATIVE_OUT)/$(1)/install_um.sh: $(PVRVERSION_H) $(CONFIG_MK) \
+ $(MAKE_TOP)/scripts/common.m4 \
+ $(MAKE_TOP)/$(PVR_BUILD_DIR)/install_um.sh.m4 \
+ | $(RELATIVE_OUT)/$(1)
+ $$(if $(V),,@echo " GEN " $$(call relative-to-top,$$@))
+ $(M4) $(M4FLAGS) $(M4DEFS) $(M4DEFS_K) \
+ $(MAKE_TOP)/scripts/common.m4 \
+ $(MAKE_TOP)/$(PVR_BUILD_DIR)/install_um.sh.m4 > $$@
+install_script: $(RELATIVE_OUT)/$(1)/install_um.sh
+endef
+
+$(foreach _t,$(TARGET_ALL_ARCH),$(eval $(call create-install-um-script-m4,$(_t))))
+
+$(TARGET_PRIMARY_OUT)/rc.pvr: $(PVRVERSION_H) $(CONFIG_MK) $(CONFIG_KERNEL_MK) \
+ $(MAKE_TOP)/scripts/rc.pvr.m4 $(MAKE_TOP)/scripts/common.m4 \
+ $(MAKE_TOP)/$(PVR_BUILD_DIR)/rc.pvr.m4 \
+ | $(TARGET_PRIMARY_OUT)
+ $(if $(V),,@echo " GEN " $(call relative-to-top,$@))
+ $(M4) $(M4FLAGS) $(M4DEFS) $(M4DEFS_K) $(MAKE_TOP)/scripts/rc.pvr.m4 \
+ $(MAKE_TOP)/$(PVR_BUILD_DIR)/rc.pvr.m4 > $@
+ $(CHMOD) +x $@
+init_script: $(TARGET_PRIMARY_OUT)/rc.pvr
+
+$(TARGET_PRIMARY_OUT)/udev.pvr: $(CONFIG_KERNEL_MK) \
+ $(MAKE_TOP)/scripts/udev.pvr.m4 \
+ | $(TARGET_PRIMARY_OUT)
+ $(if $(V),,@echo " GEN " $(call relative-to-top,$@))
+ $(M4) $(M4FLAGS) $(M4DEFS_K) $(MAKE_TOP)/scripts/udev.pvr.m4 > $@
+udev_rules: $(TARGET_PRIMARY_OUT)/udev.pvr
+
+endif # ifeq ($(SUPPORT_ANDROID_PLATFORM),)
+
+# This code mimics the way Make processes our implicit/explicit goal list.
+# It tries to build up a list of components that were actually built, from
+# whence an install script is generated.
+#
+ifneq ($(MAKECMDGOALS),)
+BUILT_UM := $(MAKECMDGOALS)
+ifneq ($(filter build services_all components,$(MAKECMDGOALS)),)
+BUILT_UM += $(COMPONENTS)
+endif
+BUILT_UM := $(sort $(filter $(ALL_MODULES) xorg wl,$(BUILT_UM)))
+else
+BUILT_UM := $(sort $(COMPONENTS))
+endif
+
+ifneq ($(MAKECMDGOALS),)
+BUILT_KM := $(MAKECMDGOALS)
+ifneq ($(filter build services_all kbuild,$(MAKECMDGOALS)),)
+BUILT_KM += $(KERNEL_COMPONENTS)
+endif
+BUILT_KM := $(sort $(filter $(ALL_MODULES),$(BUILT_KM)))
+else
+BUILT_KM := $(sort $(KERNEL_COMPONENTS))
+endif
+
+INSTALL_UM_MODULES := \
+ $(strip $(foreach _m,$(BUILT_UM),\
+ $(if $(filter doc module_group,$($(_m)_type)),,\
+ $(if $(filter host_%,$($(_m)_arch)),,\
+ $(if $($(_m)_install_path),$(_m),\
+ $(warning WARNING: UM $(_m)_install_path not defined))))))
+
+# Build up a list of installable shared libraries. The shared_library module
+# type is specially guaranteed to define $(_m)_target, even if the Linux.mk
+# itself didn't. The list is formatted with <module>:<target> pairs e.g.
+# "moduleA:libmoduleA.so moduleB:libcustom.so" for later processing.
+ALL_SHARED_INSTALLABLE := \
+ $(sort $(foreach _a,$(ALL_MODULES),\
+ $(if $(filter shared_library,$($(_a)_type)),$(_a):$($(_a)_target),)))
+
+# Handle implicit install dependencies. Executables and shared libraries may
+# be linked against other shared libraries. Avoid requiring the user to
+# specify the program's binary dependencies explicitly with $(m)_install_extra
+INSTALL_UM_MODULES := \
+ $(sort $(INSTALL_UM_MODULES) \
+ $(foreach _a,$(ALL_SHARED_INSTALLABLE),\
+ $(foreach _m,$(INSTALL_UM_MODULES),\
+ $(foreach _l,$($(_m)_libs),\
+ $(if $(filter lib$(_l).so,$(word 2,$(subst :, ,$(_a)))),\
+ $(word 1,$(subst :, ,$(_a))))))))
+
+# Add explicit dependencies that must be installed
+INSTALL_UM_MODULES := \
+ $(sort $(INSTALL_UM_MODULES) \
+ $(foreach _m,$(INSTALL_UM_MODULES),\
+ $($(_m)_install_dependencies)))
+
+define calculate-um-fragments
+# Work out which modules are required for this arch.
+INSTALL_UM_MODULES_$(1) := \
+ $$(strip $$(foreach _m,$(INSTALL_UM_MODULES),\
+ $$(if $$(filter $(1),$$(INTERNAL_ARCH_LIST_FOR_$$(_m))),$$(_m))))
+
+INSTALL_UM_FRAGMENTS_$(1) := $$(foreach _m,$$(INSTALL_UM_MODULES_$(1)),$(RELATIVE_OUT)/$(1)/intermediates/$$(_m)/.install)
+
+.PHONY: install_um_$(1)_debug
+install_um_$(1)_debug: $$(INSTALL_UM_FRAGMENTS_$(1))
+ $(CAT) $$^
+endef
+
+$(foreach _t,$(TARGET_ALL_ARCH) target_neutral,$(eval $(call calculate-um-fragments,$(_t))))
+
+INSTALL_KM_FRAGMENTS := \
+ $(strip $(foreach _m,$(BUILT_KM),\
+ $(if $(filter-out kernel_module,$($(_m)_type)),,\
+ $(if $($(_m)_install_path),\
+ $(TARGET_PRIMARY_OUT)/intermediates/$(_m)/.install,\
+ $(warning WARNING: KM $(_m)_install_path not defined)))))
+
+.PHONY: install_km_debug
+install_km_debug: $(INSTALL_KM_FRAGMENTS)
+ $(CAT) $^
+
+ifneq ($(INSTALL_KM_FRAGMENTS),)
+$(TARGET_PRIMARY_OUT)/install_km.sh: $(INSTALL_KM_FRAGMENTS) $(CONFIG_KERNEL_MK) | $(TARGET_PRIMARY_OUT)
+ $(if $(V),,@echo " GEN " $(call relative-to-top,$@))
+ $(ECHO) KERNELVERSION=$(KERNEL_ID) > $@
+ifeq ($(SUPPORT_ANDROID_PLATFORM),)
+ $(ECHO) MOD_DESTDIR=/lib/modules/$(KERNEL_ID)/extra >> $@
+endif
+ $(CAT) $(INSTALL_KM_FRAGMENTS) >> $@
+install_script_km: $(TARGET_PRIMARY_OUT)/install_km.sh
+endif
+
+# Build UM script using new scheme which does not use M4 for anything
+# (Only works for Android and target_neutral right now.)
+define create-install-um-script
+ifneq ($$(INSTALL_UM_FRAGMENTS_$(1)),)
+$(RELATIVE_OUT)/$(1)/install_um.sh: $$(INSTALL_UM_FRAGMENTS_$(1)) | $(RELATIVE_OUT)/$(1)
+ $(if $(V),,@echo " GEN " $$(call relative-to-top,$$@))
+ $(CAT) $$(INSTALL_UM_FRAGMENTS_$(1)) > $$@
+install_script: $(RELATIVE_OUT)/$(1)/install_um.sh
+endif
+endef
+$(eval $(call create-install-um-script,target_neutral))
+
+ifneq ($(SUPPORT_ANDROID_PLATFORM),)
+$(foreach _t,$(TARGET_ALL_ARCH),$(eval $(call create-install-um-script,$(_t))))
+endif
+
+# Build the top-level install script that drives the install.
+ifneq ($(SUPPORT_ANDROID_PLATFORM),)
+install_sh_template := $(MAKE_TOP)/common/android/install.sh.tpl
+else
+install_sh_template := $(MAKE_TOP)/scripts/install.sh.tpl
+endif
+
+$(RELATIVE_OUT)/install.sh: $(PVRVERSION_H) | $(RELATIVE_OUT)
+# In customer packages only one of config.mk or config_kernel.mk will exist.
+# We can depend on either one, as long as we rebuild the install script when
+# the config options it uses change.
+$(RELATIVE_OUT)/install.sh: $(call if-exists,$(CONFIG_MK),$(CONFIG_KERNEL_MK))
+$(RELATIVE_OUT)/install.sh: $(install_sh_template)
+ $(if $(V),,@echo " GEN " $(call relative-to-top,$@))
+ $(ECHO) 's/\[PVRVERSION\]/$(subst /,\/,$(PVRVERSION))/g;' > $(RELATIVE_OUT)/install.sh.sed
+ $(ECHO) 's/\[PVRBUILD\]/$(BUILD)/g;' >> $(RELATIVE_OUT)/install.sh.sed
+ $(ECHO) 's/\[PRIMARY_ARCH\]/$(TARGET_PRIMARY_ARCH)/g;' >> $(RELATIVE_OUT)/install.sh.sed
+ $(ECHO) 's/\[ARCHITECTURES\]/$(TARGET_ALL_ARCH)/g;' >> $(RELATIVE_OUT)/install.sh.sed
+ $(ECHO) 's/\[LWS_PREFIX\]/$(subst /,\/,$(LWS_PREFIX))/g;' >> $(RELATIVE_OUT)/install.sh.sed
+ $(ECHO) 's/\[SHLIB_DESTDIR\]/$(subst /,\/,$(SHLIB_DESTDIR))/g;' >> $(RELATIVE_OUT)/install.sh.sed
+ @sed -f $(RELATIVE_OUT)/install.sh.sed $< > $@
+ $(CHMOD) +x $@
+ $(RM) $(RELATIVE_OUT)/install.sh.sed
+install_script: $(RELATIVE_OUT)/install.sh
+install_script_km: $(RELATIVE_OUT)/install.sh
diff --git a/drivers/gpu/rogue/build/linux/this_makefile.mk b/drivers/gpu/rogue/build/linux/this_makefile.mk
new file mode 100644
index 000000000000..c31200123d0e
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/this_makefile.mk
@@ -0,0 +1,68 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+# Find out the path of the Linux.mk makefile currently being processed, and
+# set paths used by the build rules
+
+# This magic is used so we can use this_makefile.mk twice: first when reading
+# in each Linux.mk, and then again when generating rules. There we set
+# $(THIS_MAKEFILE), and $(REMAINING_MAKEFILES) should be empty
+ifneq ($(strip $(REMAINING_MAKEFILES)),)
+
+# Absolute path to the Linux.mk being processed
+THIS_MAKEFILE := $(firstword $(REMAINING_MAKEFILES))
+
+# The list of makefiles left to process
+REMAINING_MAKEFILES := $(wordlist 2,$(words $(REMAINING_MAKEFILES)),$(REMAINING_MAKEFILES))
+
+else
+
+# When generating rules, we should have read in every Linux.mk
+$(if $(INTERNAL_INCLUDED_ALL_MAKEFILES),,$(error No makefiles left in $$(REMAINING_MAKEFILES), but $$(INTERNAL_INCLUDED_ALL_MAKEFILES) is not set))
+
+endif
+
+# Path to the directory containing Linux.mk
+THIS_DIR := $(patsubst %/,%,$(dir $(THIS_MAKEFILE)))
+ifeq ($(strip $(THIS_DIR)),)
+$(error Empty $$(THIS_DIR) for makefile "$(THIS_MAKEFILE)")
+endif
+
+modules :=
diff --git a/drivers/gpu/rogue/build/linux/tools/cc-check.sh b/drivers/gpu/rogue/build/linux/tools/cc-check.sh
new file mode 100755
index 000000000000..773a88f71118
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/tools/cc-check.sh
@@ -0,0 +1,120 @@
+#!/bin/sh
+########################################################################### ###
+#@File
+#@Title Test the nature of the C compiler.
+#@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.
+### ###########################################################################
+
+LANG=C
+export LANG
+
+usage() {
+ echo "usage: $0 [--64] [--clang] --cc CC [--out OUT] [cflag]"
+ exit 1
+}
+
+check_clang() {
+ $CC -Wp,-dM -E - </dev/null | grep __clang__ >/dev/null 2>&1
+ if [ "$?" = "0" ]; then
+ # Clang must be passed a program with a main() that returns 0.
+ # It will produce an error if main() is improperly specified.
+ IS_CLANG=1
+ TEST_PROGRAM="int main(void){return 0;}"
+ else
+ # If we're not clang, assume we're GCC. GCC needs to be passed
+ # a program with a faulty return in main() so that another
+ # warning (unrelated to the flag being tested) is emitted.
+ # This will cause GCC to warn about the unsupported warning flag.
+ IS_CLANG=0
+ TEST_PROGRAM="int main(void){return;}"
+ fi
+}
+
+do_cc() {
+ echo "$TEST_PROGRAM" 2> /dev/null | $CC -W -Wall $3 -xc -c - -o $1 >$2 2>&1
+}
+
+while [ 1 ]; do
+ if [ "$1" = "--64" ]; then
+ [ -z $CLANG ] && BIT_CHECK=1
+ elif [ "$1" = "--clang" ]; then
+ [ -z $BIT_CHECK ] && CLANG=1
+ elif [ "$1" = "--cc" ]; then
+ [ "x$2" = "x" ] && usage
+ CC="$2" && shift
+ elif [ "$1" = "--out" ]; then
+ [ "x$2" = "x" ] && usage
+ OUT="$2" && shift
+ elif [ "${1#--}" != "$1" ]; then
+ usage
+ else
+ break
+ fi
+ shift
+done
+
+[ "x$CC" = "x" ] && usage
+[ "x$CLANG" = "x" -a "x$OUT" = "x" ] && usage
+ccof=$OUT/cc-sanity-check
+log=${ccof}.log
+
+check_clang
+
+if [ "x$BIT_CHECK" = "x1" ]; then
+ do_cc $ccof $log ""
+ file $ccof | grep 64-bit >/dev/null 2>&1
+ [ "$?" = "0" ] && echo true || echo false
+elif [ "x$CLANG" = "x1" ]; then
+ [ "x$IS_CLANG" = "x1" ] && echo true || echo false
+else
+ [ "x$1" = "x" ] && usage
+ do_cc $ccof $log $1
+ if [ "$?" = "0" ]; then
+ # compile passed, but was the warning unrecognized?
+ if [ "x$IS_CLANG" = "x1" ]; then
+ grep "^warning: unknown warning option '$1'" $log >/dev/null 2>&1
+ else
+ grep -E "(^cc1: warning: unrecognized command line option \"$1\"|^cc1: warning: command line option \"$1\" is valid for C\+\+/ObjC\+\+ but not for C|gcc: unrecognized option '$1')" $log >/dev/null 2>&1
+ fi
+ [ "$?" = "1" ] && echo $1
+ fi
+fi
+
+rm -f $ccof $log
+exit 0
diff --git a/drivers/gpu/rogue/build/linux/toplevel.mk b/drivers/gpu/rogue/build/linux/toplevel.mk
new file mode 100644
index 000000000000..cb5d9d432938
--- /dev/null
+++ b/drivers/gpu/rogue/build/linux/toplevel.mk
@@ -0,0 +1,291 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+# Define the default goal. This masks a previous definition of the default
+# goal in config/core.mk, which must match this one
+.PHONY: build
+build: components
+
+MAKE_TOP := build/linux
+THIS_MAKEFILE := (top-level makefiles)
+
+include $(MAKE_TOP)/defs.mk
+
+ifeq ($(OUT),)
+$(error Must specify output directory with OUT=)
+endif
+
+ifeq ($(TOP),)
+$(error Must specify root of source tree with TOP=)
+endif
+$(call directory-must-exist,$(TOP))
+
+# RELATIVE_OUT is relative only if it's under $(TOP)
+RELATIVE_OUT := $(patsubst $(TOP)/%,%,$(OUT))
+CONFIG_MK := $(RELATIVE_OUT)/config.mk
+CONFIG_H := $(RELATIVE_OUT)/config.h
+CONFIG_KERNEL_MK := $(RELATIVE_OUT)/config_kernel.mk
+CONFIG_KERNEL_H := $(RELATIVE_OUT)/config_kernel.h
+
+# Convert commas to spaces in $(D). This is so you can say "make
+# D=config-changes,freeze-config" and have $(filter config-changes,$(D))
+# still work.
+comma := ,
+empty :=
+space := $(empty) $(empty)
+override D := $(subst $(comma),$(space),$(D))
+
+ifneq ($(INTERNAL_CLOBBER_ONLY),true)
+# Create the out directory
+#
+$(shell mkdir -p $(OUT))
+
+# If these generated files differ from any pre-existing ones,
+# replace them, causing affected parts of the driver to rebuild.
+#
+_want_config_diff := $(filter config-changes,$(D))
+_freeze_config := $(strip $(filter freeze-config,$(D)))
+_updated_config_files := $(shell \
+ $(if $(_want_config_diff),rm -f $(OUT)/config.diff;,) \
+ for file in $(CONFIG_MK) $(CONFIG_H) \
+ $(CONFIG_KERNEL_MK) $(CONFIG_KERNEL_H); do \
+ diff -U 0 $$file $$file.new \
+ >>$(if $(_want_config_diff),$(OUT)/config.diff,/dev/null) 2>/dev/null \
+ && rm -f $$file.new \
+ || echo $$file; \
+ done)
+
+ifneq ($(_want_config_diff),)
+# We send the diff to stderr so it isn't captured by $(shell)
+$(shell [ -s $(OUT)/config.diff ] && echo >&2 "Configuration changed in $(RELATIVE_OUT):" && cat >&2 $(OUT)/config.diff)
+endif
+
+ifneq ($(_freeze_config),)
+$(if $(_updated_config_files),$(error Configuration change in $(RELATIVE_OUT) prevented by D=freeze-config),)
+endif
+
+# Update the config, if changed
+$(foreach _f,$(_updated_config_files), \
+ $(shell mv -f $(_f).new $(_f) >/dev/null 2>/dev/null))
+
+endif # INTERNAL_CLOBBER_ONLY
+
+MAKEFLAGS := -Rr --no-print-directory
+
+ifneq ($(INTERNAL_CLOBBER_ONLY),true)
+
+# This is so you can say "find $(TOP) -name Linux.mk > /tmp/something; export
+# ALL_MAKEFILES=/tmp/something; make" and avoid having to run find. This is
+# handy if your source tree is mounted over NFS or something
+override ALL_MAKEFILES := $(call relative-to-top,$(if $(strip $(ALL_MAKEFILES)),$(shell cat $(ALL_MAKEFILES)),$(shell find $(TOP) -type f -name Linux.mk -print -o -type d -name '.*' -prune)))
+ifeq ($(strip $(ALL_MAKEFILES)),)
+$(info ** Unable to find any Linux.mk files under $$(TOP). This could mean that)
+$(info ** there are no makefiles, or that ALL_MAKEFILES is set in the environment)
+$(info ** and points to a nonexistent or empty file.)
+$(error No makefiles)
+endif
+
+else # clobber-only
+ALL_MAKEFILES :=
+endif
+
+ifeq ($(SUPPORT_NEUTRINO_PLATFORM),1)
+include $(MAKE_TOP)/common/neutrino/subst_makefiles.mk
+endif
+
+unexport ALL_MAKEFILES
+
+REMAINING_MAKEFILES := $(ALL_MAKEFILES)
+ALL_MODULES :=
+INTERNAL_INCLUDED_ALL_MAKEFILES :=
+
+ALL_LDFLAGS :=
+
+# Please do not change the format of the following lines
+-include $(CONFIG_MK)
+-include $(CONFIG_KERNEL_MK)
+# OK to change now
+
+# If we haven't set host/target archs, set some sensible defaults now.
+# This allows things like prune.sh to work
+ifeq ($(HOST_PRIMARY_ARCH),)
+ifneq ($(FORCE_ARCH),)
+HOST_PRIMARY_ARCH := host_i386
+HOST_32BIT_ARCH := host_i386
+TARGET_PRIMARY_ARCH := target_i686
+TARGET_ALL_ARCH := target_i686
+endif
+endif
+
+# Output directory for configuration, object code,
+# final programs/libraries, and install/rc scripts.
+HOST_OUT := $(RELATIVE_OUT)/$(HOST_PRIMARY_ARCH)
+HOST_32BIT_OUT := $(RELATIVE_OUT)/$(HOST_32BIT_ARCH)
+TARGET_OUT := $(RELATIVE_OUT)/$(TARGET_PRIMARY_ARCH)
+TARGET_PRIMARY_OUT := $(RELATIVE_OUT)/$(TARGET_PRIMARY_ARCH)
+TARGET_NEUTRAL_OUT := $(RELATIVE_OUT)/target_neutral
+BRIDGE_SOURCE_ROOT := $(call if-exists,$(TOP)/generated,$(TARGET_NEUTRAL_OUT)/intermediates)
+GENERATED_CODE_OUT := $(TARGET_NEUTRAL_OUT)/intermediates
+DOCS_OUT := $(RELATIVE_OUT)/doc
+
+# Mark subdirectories of $(OUT) as secondary, and provide rules to create
+# them.
+OUT_SUBDIRS := $(addprefix $(RELATIVE_OUT)/,$(TARGET_ALL_ARCH)) \
+ $(TARGET_NEUTRAL_OUT) $(DOCS_OUT) $(if $(HOST_PRIMARY_ARCH),$(sort $(HOST_OUT) $(HOST_32BIT_OUT)))
+.SECONDARY: $(OUT_SUBDIRS)
+$(OUT_SUBDIRS):
+ $(make-directory)
+
+ifneq ($(INTERNAL_CLOBBER_ONLY),true)
+-include $(MAKE_TOP)/pvrversion.mk
+ifeq ($(SUPPORT_BUILD_LWS),1)
+-include $(MAKE_TOP)/lwsconf.mk
+endif
+-include $(MAKE_TOP)/llvm.mk
+-include $(MAKE_TOP)/common/bridges.mk
+endif
+
+include $(MAKE_TOP)/commands.mk
+include $(MAKE_TOP)/buildvars.mk
+
+HOST_INTERMEDIATES := $(HOST_OUT)/intermediates
+TARGET_INTERMEDIATES := $(TARGET_OUT)/intermediates
+
+ifneq ($(KERNEL_COMPONENTS),)
+build: kbuild
+endif
+
+# "make bridges" makes all the modules which are bridges. This is used by
+# builds which ship pregenerated bridge headers.
+.PHONY: bridges
+bridges:
+
+# Include each Linux.mk, then include modules.mk to save some information
+# about each module
+include $(foreach _Linux.mk,$(ALL_MAKEFILES),$(MAKE_TOP)/this_makefile.mk $(_Linux.mk) $(MAKE_TOP)/modules.mk)
+
+ifeq ($(strip $(REMAINING_MAKEFILES)),)
+INTERNAL_INCLUDED_ALL_MAKEFILES := true
+else
+$(error Impossible: $(words $(REMAINING_MAKEFILES)) makefiles were mysteriously ignored when reading $$(ALL_MAKEFILES))
+endif
+
+# At this point, all Linux.mks have been included. Now generate rules to build
+# each module: for each module in $(ALL_MODULES), set per-makefile variables
+$(foreach _m,$(ALL_MODULES),$(eval $(call process-module,$(_m))))
+
+.PHONY: kbuild install
+kbuild install:
+
+ifneq ($(INTERNAL_CLOBBER_ONLY),true)
+-include $(MAKE_TOP)/scripts.mk
+-include $(MAKE_TOP)/kbuild/kbuild.mk
+endif
+# We won't depend on 'build' here so that people can build subsets of
+# components and still have the install script attempt to install the
+# subset.
+install:
+ @if [ ! -d "$(DISCIMAGE)" ]; then \
+ echo; \
+ echo "** DISCIMAGE was not set or does not point to a valid directory."; \
+ echo "** Cannot continue with install."; \
+ echo; \
+ exit 1; \
+ fi
+ @if [ ! -f $(RELATIVE_OUT)/install.sh ]; then \
+ echo; \
+ echo "** install.sh not found in $(RELATIVE_OUT)."; \
+ echo "** Cannot continue with install."; \
+ echo; \
+ exit 1; \
+ fi
+ @cd $(RELATIVE_OUT) && ./install.sh
+
+.PHONY: uninstall
+uninstall: install_script
+uninstall:
+ @if [ ! -d "$(DISCIMAGE)" ]; then \
+ echo; \
+ echo "** DISCIMAGE was not set or does not point to a valid directory."; \
+ echo "** Cannot continue with uninstall."; \
+ echo; \
+ exit 1; \
+ fi
+ @if [ ! -f $(RELATIVE_OUT)/install.sh ]; then \
+ echo; \
+ echo "** install.sh not found in $(RELATIVE_OUT)."; \
+ echo "** Cannot continue with uninstall."; \
+ echo; \
+ exit 1; \
+ fi
+ @cd $(RELATIVE_OUT) && ./install.sh -u
+
+# You can say 'make all_modules' to attempt to make everything, or 'make
+# components' to only make the things which are listed (in the per-build
+# makefiles) as components of the build.
+.PHONY: all_modules all_docs components
+all_modules: $(ALL_MODULES)
+all_docs: ;
+components: $(COMPONENTS)
+
+# Cleaning
+.PHONY: clean clobber
+clean: MODULE_DIRS_TO_REMOVE := $(OUT_SUBDIRS)
+clean:
+ $(clean-dirs)
+clobber: MODULE_DIRS_TO_REMOVE := $(OUT)
+clobber:
+ $(clean-dirs)
+
+# Saying 'make clean-MODULE' removes the intermediates for MODULE.
+# clobber-MODULE deletes the output files as well
+clean-%:
+ $(if $(V),,@echo " RM " $(call relative-to-top,$(INTERNAL_CLEAN_TARGETS_FOR_$*)))
+ $(RM) -rf $(INTERNAL_CLEAN_TARGETS_FOR_$*)
+clobber-%:
+ $(if $(V),,@echo " RM " $(call relative-to-top,$(INTERNAL_CLOBBER_TARGETS_FOR_$*)))
+ $(RM) -rf $(INTERNAL_CLOBBER_TARGETS_FOR_$*)
+
+include $(MAKE_TOP)/bits.mk
+
+# D=nobuild stops the build before any recipes are run. This line should
+# come at the end of this makefile.
+$(if $(filter nobuild,$(D)),$(error D=nobuild given),)
diff --git a/drivers/gpu/rogue/config_kernel.h b/drivers/gpu/rogue/config_kernel.h
new file mode 100644
index 000000000000..18168ff53db6
--- /dev/null
+++ b/drivers/gpu/rogue/config_kernel.h
@@ -0,0 +1,33 @@
+#define SUPPORT_ION
+#define PVR_ANDROID_ION_HEADER "../drivers/staging/android/ion/ion.h"
+#define PVR_ANDROID_ION_PRIV_HEADER "../drivers/staging/android/ion/ion_priv.h"
+#define PVR_ANDROID_ION_USE_SG_LENGTH
+#define PVR_ANDROID_SYNC_HEADER "../drivers/staging/android/sync.h"
+#define LINUX
+#define PVR_BUILD_DIR "generic_arm_android"
+#define PVR_BUILD_TYPE "release"
+#define PVRSRV_MODNAME "pvrsrvkm"
+#define SUPPORT_RGX 1
+#define PVR_SECURE_HANDLES
+#define RELEASE
+#define RGX_BVNC_CORE_KM_HEADER "cores/rgxcore_km_5.9.1.46.h"
+#define RGX_BNC_CONFIG_KM_HEADER "configs/rgxconfig_km_5.V.1.46.h"
+#define SUPPORT_DBGDRV_EVENT_OBJECTS
+#define SYS_USING_INTERRUPTS
+#define CACHEFLUSH_TYPE CACHEFLUSH_GENERIC
+#define SUPPORT_INSECURE_EXPORT
+#define SUPPORT_SECURE_EXPORT
+#define SUPPORT_GPUTRACE_EVENTS
+#define SUPPORT_LINUX_X86_WRITECOMBINE
+#define SUPPORT_LINUX_X86_PAT
+#define PVR_LINUX_USING_WORKQUEUES
+#define PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE
+#define PVR_LINUX_TIMERS_USING_WORKQUEUES
+#define PVR_LDM_PLATFORM_PRE_REGISTERED
+#define PVR_LDM_DRIVER_REGISTRATION_NAME "pvrsrvkm"
+#define LDM_PLATFORM
+#define PVRSRV_ENABLE_PROCESS_STATS
+#define PVR_LINUX_PYSMEM_MAX_POOL_PAGES 10240
+#define PVR_LINUX_VMALLOC_ALLOCATION_THRESHOLD 16384
+#define ANDROID
+#define PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC
diff --git a/drivers/gpu/rogue/config_kernel.mk b/drivers/gpu/rogue/config_kernel.mk
new file mode 100644
index 000000000000..493cf06999d5
--- /dev/null
+++ b/drivers/gpu/rogue/config_kernel.mk
@@ -0,0 +1,26 @@
+override HOST_PRIMARY_ARCH := host_x86_64
+override HOST_32BIT_ARCH := host_i386
+override HOST_FORCE_32BIT := -m32
+override TARGET_PRIMARY_ARCH := target_aarch64
+override TARGET_SECONDARY_ARCH := target_armv7-a
+override TARGET_ALL_ARCH := target_aarch64 target_armv7-a
+override TARGET_FORCE_32BIT :=
+override KERNELDIR := /work/zxl/project/rk3368/kernel
+override KERNEL_ID := 3.10.0
+override KERNEL_COMPONENTS := srvkm
+override KERNEL_CROSS_COMPILE := /work/zxl/project/rk3368/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
+override SUPPORT_ION := 1
+override PVRSRV_MODNAME := pvrsrvkm
+override PVR_BUILD_DIR := generic_arm_android
+override PVR_BUILD_TYPE := release
+override PVR_SYSTEM := rk3368
+override BUILD := release
+override DEBUGLINK := 1
+override CACHEFLUSH_TYPE := CACHEFLUSH_GENERIC
+override SUPPORT_INSECURE_EXPORT := 1
+override SUPPORT_SECURE_EXPORT := 1
+override SUPPORT_GPUTRACE_EVENTS := 1
+override OPTIM := -O2
+override PVR_HANDLE_BACKEND := generic
+override SUPPORT_ANDROID_PLATFORM := 1
+override PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC := 1
diff --git a/drivers/gpu/rogue/dc_fbdev/Kbuild.mk b/drivers/gpu/rogue/dc_fbdev/Kbuild.mk
new file mode 100644
index 000000000000..3c2cb4f865fa
--- /dev/null
+++ b/drivers/gpu/rogue/dc_fbdev/Kbuild.mk
@@ -0,0 +1,49 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+ccflags-y += \
+ -I$(TOP)/services/3rdparty/dc_fbdev
+
+dc_fbdev-y += \
+ services/3rdparty/dc_fbdev/dc_fbdev.o
+
+ifneq ($(W),1)
+#CFLAGS_dc_fbdev.o := -Werror
+endif
diff --git a/drivers/gpu/rogue/dc_fbdev/Linux.mk b/drivers/gpu/rogue/dc_fbdev/Linux.mk
new file mode 100644
index 000000000000..05a7e15c1934
--- /dev/null
+++ b/drivers/gpu/rogue/dc_fbdev/Linux.mk
@@ -0,0 +1,45 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+modules := dc_fbdev
+
+dc_fbdev_type := kernel_module
+dc_fbdev_target := dc_fbdev.ko
+dc_fbdev_makefile := $(THIS_DIR)/Kbuild.mk
diff --git a/drivers/gpu/rogue/dc_fbdev/dc_fbdev.c b/drivers/gpu/rogue/dc_fbdev/dc_fbdev.c
new file mode 100755
index 000000000000..c8f5e3de0a0d
--- /dev/null
+++ b/drivers/gpu/rogue/dc_fbdev/dc_fbdev.c
@@ -0,0 +1,893 @@
+/*************************************************************************/ /*!
+@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/console.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+
+#include "kerneldisplay.h"
+#include "imgpixfmts_km.h"
+#include "pvrmodule.h" /* for MODULE_LICENSE() */
+
+#if !defined(CONFIG_FB)
+#error dc_fbdev needs Linux framebuffer support. Enable it in your kernel.
+#endif
+
+#define DRVNAME "dc_fbdev"
+#define DC_PHYS_HEAP_ID 0
+#define MAX_COMMANDS_IN_FLIGHT 2
+
+#if defined(DC_FBDEV_NUM_PREFERRED_BUFFERS)
+#define NUM_PREFERRED_BUFFERS DC_FBDEV_NUM_PREFERRED_BUFFERS
+#else
+#define NUM_PREFERRED_BUFFERS 2
+#endif
+
+#define FALLBACK_REFRESH_RATE 60
+#define FALLBACK_DPI 160
+
+struct fb_var_screeninfo sDefaultVar; //chenli: store default fb_var_screeninfo
+
+typedef struct
+{
+ IMG_HANDLE hSrvHandle;
+ IMG_UINT32 ePixFormat;
+ struct fb_info *psLINFBInfo;
+ bool bCanFlip;
+}
+DC_FBDEV_DEVICE;
+
+typedef struct
+{
+ DC_FBDEV_DEVICE *psDeviceData;
+ IMG_HANDLE hLastConfigData;
+ IMG_UINT32 ui32AllocUseMask;
+}
+DC_FBDEV_CONTEXT;
+
+typedef struct
+{
+ DC_FBDEV_CONTEXT *psDeviceContext;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32ByteStride;
+ IMG_UINT32 ui32BufferID;
+}
+DC_FBDEV_BUFFER;
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+static DC_FBDEV_DEVICE *gpsDeviceData;
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,29))
+static inline void console_lock(void)
+{
+ acquire_console_sem();
+}
+
+static inline void console_unlock(void)
+{
+ release_console_sem();
+}
+#endif
+
+static
+void DC_FBDEV_GetInfo(IMG_HANDLE hDeviceData,
+ DC_DISPLAY_INFO *psDisplayInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(hDeviceData);
+
+ strncpy(psDisplayInfo->szDisplayName, DRVNAME " 1", DC_NAME_SIZE);
+
+ psDisplayInfo->ui32MinDisplayPeriod = 0;
+ psDisplayInfo->ui32MaxDisplayPeriod = 1;
+ psDisplayInfo->ui32MaxPipes = 1;
+ psDisplayInfo->bUnlatchedSupported = IMG_FALSE;
+}
+
+static
+PVRSRV_ERROR DC_FBDEV_PanelQueryCount(IMG_HANDLE hDeviceData,
+ IMG_UINT32 *pui32NumPanels)
+{
+ PVR_UNREFERENCED_PARAMETER(hDeviceData);
+ *pui32NumPanels = 1;
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR DC_FBDEV_PanelQuery(IMG_HANDLE hDeviceData,
+ IMG_UINT32 ui32PanelsArraySize,
+ IMG_UINT32 *pui32NumPanels,
+ PVRSRV_PANEL_INFO *psPanelInfo)
+{
+ DC_FBDEV_DEVICE *psDeviceData = hDeviceData;
+ struct fb_var_screeninfo *psVar = &psDeviceData->psLINFBInfo->var;
+ struct fb_var_screeninfo sVar = { .pixclock = 0 };
+
+ if(!lock_fb_info(psDeviceData->psLINFBInfo))
+ return PVRSRV_ERROR_RETRY;
+
+ *pui32NumPanels = 1;
+
+ psPanelInfo[0].sSurfaceInfo.sFormat.ePixFormat = psDeviceData->ePixFormat;
+ psPanelInfo[0].sSurfaceInfo.sDims.ui32Width = psVar->xres;
+ psPanelInfo[0].sSurfaceInfo.sDims.ui32Height = psVar->yres;
+ psPanelInfo[0].sSurfaceInfo.sFormat.eMemLayout = PVRSRV_SURFACE_MEMLAYOUT_STRIDED;
+ psPanelInfo[0].sSurfaceInfo.sFormat.u.sFBCLayout.eFBCompressionMode = FB_COMPRESSION_NONE;
+
+ /* Conformant fbdev drivers should have `var' and mode in sync by now,
+ * but some don't (like drmfb), so try a couple of different ways to
+ * get the info before falling back to the default.
+ */
+ if(psVar->xres > 0 && psVar->yres > 0 && psVar->pixclock > 0)
+ sVar = *psVar;
+ else if(psDeviceData->psLINFBInfo->mode)
+ fb_videomode_to_var(&sVar, psDeviceData->psLINFBInfo->mode);
+
+ /* Override the refresh rate when defined. */
+#ifdef DC_FBDEV_REFRESH
+ psPanelInfo[0].ui32RefreshRate = DC_FBDEV_REFRESH;
+#else
+ if(sVar.xres > 0 && sVar.yres > 0 && sVar.pixclock > 0)
+ {
+ psPanelInfo[0].ui32RefreshRate = 1000000000LU /
+ ((sVar.upper_margin + sVar.lower_margin +
+ sVar.yres + sVar.vsync_len) *
+ (sVar.left_margin + sVar.right_margin +
+ sVar.xres + sVar.hsync_len) *
+ (sVar.pixclock / 1000));
+ }
+ else
+ psPanelInfo[0].ui32RefreshRate = FALLBACK_REFRESH_RATE;
+#endif
+
+ psPanelInfo[0].ui32XDpi =
+ ((int)sVar.width > 0) ? (254000 / sVar.width * psVar->xres / 10000) : FALLBACK_DPI;
+
+ psPanelInfo[0].ui32YDpi =
+ ((int)sVar.height > 0) ? 254000 / sVar.height * psVar->yres / 10000 : FALLBACK_DPI;
+
+ unlock_fb_info(psDeviceData->psLINFBInfo);
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR DC_FBDEV_FormatQuery(IMG_HANDLE hDeviceData,
+ IMG_UINT32 ui32NumFormats,
+ PVRSRV_SURFACE_FORMAT *pasFormat,
+ IMG_UINT32 *pui32Supported)
+{
+ DC_FBDEV_DEVICE *psDeviceData = hDeviceData;
+ int i;
+
+ for(i = 0; i < ui32NumFormats; i++)
+ {
+ pui32Supported[i] = 0;
+
+ if(pasFormat[i].ePixFormat == psDeviceData->ePixFormat)
+ pui32Supported[i]++;
+ }
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR DC_FBDEV_DimQuery(IMG_HANDLE hDeviceData,
+ IMG_UINT32 ui32NumDims,
+ PVRSRV_SURFACE_DIMS *psDim,
+ IMG_UINT32 *pui32Supported)
+{
+ DC_FBDEV_DEVICE *psDeviceData = hDeviceData;
+ struct fb_var_screeninfo *psVar = &psDeviceData->psLINFBInfo->var;
+ int i;
+
+ if(!lock_fb_info(psDeviceData->psLINFBInfo))
+ return PVRSRV_ERROR_RETRY;
+
+ for(i = 0; i < ui32NumDims; i++)
+ {
+ pui32Supported[i] = 0;
+
+ if(psDim[i].ui32Width == psVar->xres &&
+ psDim[i].ui32Height == psVar->yres)
+ pui32Supported[i]++;
+ }
+
+ unlock_fb_info(psDeviceData->psLINFBInfo);
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR DC_FBDEV_ContextCreate(IMG_HANDLE hDeviceData,
+ IMG_HANDLE *hDisplayContext)
+{
+ DC_FBDEV_CONTEXT *psDeviceContext;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ psDeviceContext = kzalloc(sizeof(DC_FBDEV_CONTEXT), GFP_KERNEL);
+ if(!psDeviceContext)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_out;
+ }
+
+ psDeviceContext->psDeviceData = hDeviceData;
+ *hDisplayContext = psDeviceContext;
+
+err_out:
+ return eError;
+}
+
+static PVRSRV_ERROR
+DC_FBDEV_ContextConfigureCheck(IMG_HANDLE hDisplayContext,
+ IMG_UINT32 ui32PipeCount,
+ PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+ IMG_HANDLE *ahBuffers)
+{
+ DC_FBDEV_CONTEXT *psDeviceContext = hDisplayContext;
+ DC_FBDEV_DEVICE *psDeviceData = psDeviceContext->psDeviceData;
+ struct fb_var_screeninfo *psVar = &psDeviceData->psLINFBInfo->var;
+ DC_FBDEV_BUFFER *psBuffer;
+ PVRSRV_ERROR eError;
+
+ if(ui32PipeCount != 1)
+ {
+ eError = PVRSRV_ERROR_DC_TOO_MANY_PIPES;
+ goto err_out;
+ }
+
+ if(!ahBuffers)
+ {
+ eError = PVRSRV_ERROR_DC_INVALID_CONFIG;
+ goto err_out;
+ }
+
+ if(!lock_fb_info(psDeviceData->psLINFBInfo))
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ goto err_out;
+ }
+
+ psBuffer = ahBuffers[0];
+
+ if(pasSurfAttrib[0].sCrop.sDims.ui32Width != psVar->xres ||
+ pasSurfAttrib[0].sCrop.sDims.ui32Height != psVar->yres ||
+ pasSurfAttrib[0].sCrop.i32XOffset != 0 ||
+ pasSurfAttrib[0].sCrop.i32YOffset != 0)
+ {
+ eError = PVRSRV_ERROR_DC_INVALID_CROP_RECT;
+ goto err_unlock;
+ }
+
+ if(pasSurfAttrib[0].sDisplay.sDims.ui32Width !=
+ pasSurfAttrib[0].sCrop.sDims.ui32Width ||
+ pasSurfAttrib[0].sDisplay.sDims.ui32Height !=
+ pasSurfAttrib[0].sCrop.sDims.ui32Height ||
+ pasSurfAttrib[0].sDisplay.i32XOffset !=
+ pasSurfAttrib[0].sCrop.i32XOffset ||
+ pasSurfAttrib[0].sDisplay.i32YOffset !=
+ pasSurfAttrib[0].sCrop.i32YOffset)
+ {
+ eError = PVRSRV_ERROR_DC_INVALID_DISPLAY_RECT;
+ goto err_unlock;
+ }
+
+ if(psBuffer->ui32Width != psVar->xres &&
+ psBuffer->ui32Height != psVar->yres)
+ {
+ eError = PVRSRV_ERROR_DC_INVALID_BUFFER_DIMS;
+ goto err_unlock;
+ }
+
+ eError = PVRSRV_OK;
+err_unlock:
+ unlock_fb_info(psDeviceData->psLINFBInfo);
+err_out:
+ return eError;
+}
+
+static int DumpFbInfo( struct fb_var_screeninfo *info)
+{
+#if 0
+ printk("dump: vir[%d,%d] [%d,%d,%d,%d] format=%d \n",
+ info->xres_virtual,info->yres_virtual,
+ info->xoffset,
+ info->yoffset,
+ info->xres,
+ info->yres,
+ (info->nonstd & 0xff));
+#endif
+ return 0;
+}
+
+static
+void DC_FBDEV_ContextConfigure(IMG_HANDLE hDisplayContext,
+ IMG_UINT32 ui32PipeCount,
+ PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+ IMG_HANDLE *ahBuffers,
+ IMG_UINT32 ui32DisplayPeriod,
+ IMG_HANDLE hConfigData)
+{
+ DC_FBDEV_CONTEXT *psDeviceContext = hDisplayContext;
+ DC_FBDEV_DEVICE *psDeviceData = psDeviceContext->psDeviceData;
+ struct fb_var_screeninfo sVar = psDeviceData->psLINFBInfo->var;
+ int err;
+ IMG_BOOL bReset=false;
+
+ PVR_UNREFERENCED_PARAMETER(ui32PipeCount);
+ PVR_UNREFERENCED_PARAMETER(pasSurfAttrib);
+ PVR_UNREFERENCED_PARAMETER(ui32DisplayPeriod);
+
+ if(psDeviceContext->hLastConfigData)
+ DCDisplayConfigurationRetired(psDeviceContext->hLastConfigData);
+
+ sVar.yoffset = 0;
+
+ //chenli: if current FB's format is not RGBX_8888, reset fb_var_screeninfo
+ if((sVar.nonstd & 0xff) != (sDefaultVar.nonstd & 0xff))
+ {
+ DumpFbInfo(&sDefaultVar);
+ sVar = sDefaultVar;
+ bReset = true;
+ }
+
+ if(ui32PipeCount == 0)
+ {
+ /* If the pipe count is zero, we're tearing down. Don't record
+ * any new configurations, but still allow the display to pan
+ * back to buffer 0.
+ */
+ psDeviceContext->hLastConfigData = IMG_NULL;
+
+ /*
+ We still need to "retire" this NULL flip as that signals back to
+ the DC core that we've finished doing what we need to do
+ and it can destroy the display context
+ */
+ DCDisplayConfigurationRetired(hConfigData);
+ }
+ else
+ {
+ BUG_ON(ahBuffers == IMG_NULL);
+
+ if(psDeviceData->bCanFlip)
+ {
+ DC_FBDEV_BUFFER *psBuffer = ahBuffers[0];
+ sVar.yoffset = sVar.yres * psBuffer->ui32BufferID;
+ }
+
+ psDeviceContext->hLastConfigData = hConfigData;
+ }
+
+ if(lock_fb_info(psDeviceData->psLINFBInfo) || bReset)
+ {
+ console_lock();
+
+ /* If we're supposed to be able to flip, but the yres_virtual
+ * has been changed to an unsupported (smaller) value, we need
+ * to change it back (this is a workaround for some Linux fbdev
+ * drivers that seem to lose any modifications to yres_virtual
+ * after a blank.)
+ */
+ if((psDeviceData->bCanFlip &&
+ sVar.yres_virtual < sVar.yres * NUM_PREFERRED_BUFFERS) || bReset)
+ {
+ sVar.activate = FB_ACTIVATE_NOW;
+ sVar.yres_virtual = sVar.yres * NUM_PREFERRED_BUFFERS;
+
+#if 0
+ //chenli: if the virtual screen resolution not changed, res_virtual should not be changed
+ if(bReset == false)
+ {
+ sVar.xres_virtual = sVar.xres;
+ sVar.yres_virtual = sVar.yoffset + sVar.yres;
+ }
+#endif
+
+ err = fb_set_var(psDeviceData->psLINFBInfo, &sVar);
+ if(err)
+ pr_err("fb_set_var failed (err=%d)\n", err);
+ }
+ else
+ {
+ err = fb_pan_display(psDeviceData->psLINFBInfo, &sVar);
+ if(err)
+ pr_err("fb_pan_display failed (err=%d)\n", err);
+ }
+
+ console_unlock();
+ unlock_fb_info(psDeviceData->psLINFBInfo);
+ }
+}
+
+static
+void DC_FBDEV_ContextDestroy(IMG_HANDLE hDisplayContext)
+{
+ DC_FBDEV_CONTEXT *psDeviceContext = hDisplayContext;
+
+ BUG_ON(psDeviceContext->hLastConfigData != IMG_NULL);
+ kfree(psDeviceContext);
+}
+
+static
+IMG_BOOL DC_FBDEV_GetBufferID(DC_FBDEV_CONTEXT *psDeviceContext, IMG_UINT32 *pui32BufferID)
+{
+ IMG_UINT32 ui32BufferID;
+
+ /* If we don't support flipping, allow this code to give every
+ * allocated buffer the same ID. This means that the display
+ * won't be panned, and the same page list will be used for
+ * every allocation.
+ */
+ if (!psDeviceContext->psDeviceData->bCanFlip)
+ {
+ *pui32BufferID = 0;
+ return IMG_TRUE;
+ }
+
+ for (ui32BufferID = 0; ui32BufferID < NUM_PREFERRED_BUFFERS; ++ui32BufferID)
+ {
+ if ((psDeviceContext->ui32AllocUseMask & (1UL << ui32BufferID)) == 0)
+ {
+ psDeviceContext->ui32AllocUseMask |= (1UL << ui32BufferID);
+
+ *pui32BufferID = ui32BufferID;
+
+ return IMG_TRUE;
+ }
+ }
+ return IMG_FALSE;
+}
+
+static
+void DC_FBDEV_PutBufferID(DC_FBDEV_CONTEXT *psDeviceContext, IMG_UINT32 ui32BufferID)
+{
+ psDeviceContext->ui32AllocUseMask &= ~(1UL << ui32BufferID);
+}
+
+#define BYTE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+static
+PVRSRV_ERROR DC_FBDEV_BufferAlloc(IMG_HANDLE hDisplayContext,
+ DC_BUFFER_CREATE_INFO *psCreateInfo,
+ IMG_DEVMEM_LOG2ALIGN_T *puiLog2PageSize,
+ IMG_UINT32 *pui32PageCount,
+ IMG_UINT32 *pui32PhysHeapID,
+ IMG_UINT32 *pui32ByteStride,
+ IMG_HANDLE *phBuffer)
+{
+ DC_FBDEV_CONTEXT *psDeviceContext = hDisplayContext;
+ DC_FBDEV_DEVICE *psDeviceData = psDeviceContext->psDeviceData;
+ PVRSRV_SURFACE_INFO *psSurfInfo = &psCreateInfo->sSurface;
+ PVRSRV_ERROR eError;
+ DC_FBDEV_BUFFER *psBuffer;
+ IMG_UINT32 ui32ByteSize;
+
+ if (psSurfInfo->sFormat.ePixFormat != psDeviceData->ePixFormat)
+ {
+ eError = PVRSRV_ERROR_UNSUPPORTED_PIXEL_FORMAT;
+ goto err_out;
+ }
+
+ psBuffer = kmalloc(sizeof(DC_FBDEV_BUFFER), GFP_KERNEL);
+ if (!psBuffer)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_out;
+ }
+
+ psBuffer->psDeviceContext = psDeviceContext;
+ psBuffer->ui32ByteStride =
+ psSurfInfo->sDims.ui32Width * psCreateInfo->ui32BPP;
+
+ psBuffer->ui32Width = psSurfInfo->sDims.ui32Width;
+ psBuffer->ui32Height = psSurfInfo->sDims.ui32Height;
+
+ if (!DC_FBDEV_GetBufferID(psDeviceContext, &psBuffer->ui32BufferID))
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free;
+ }
+
+ ui32ByteSize = psBuffer->ui32ByteStride * psBuffer->ui32Height;
+
+ *puiLog2PageSize = PAGE_SHIFT;
+ *pui32PageCount = BYTE_TO_PAGES(ui32ByteSize);
+ *pui32PhysHeapID = DC_PHYS_HEAP_ID;
+ *pui32ByteStride = psBuffer->ui32ByteStride;
+ *phBuffer = psBuffer;
+
+ return PVRSRV_OK;
+
+err_free:
+ kfree(psBuffer);
+
+err_out:
+ return eError;
+}
+
+static
+PVRSRV_ERROR DC_FBDEV_BufferAcquire(IMG_HANDLE hBuffer,
+ IMG_DEV_PHYADDR *pasDevPAddr,
+ IMG_PVOID *ppvLinAddr)
+{
+ DC_FBDEV_BUFFER *psBuffer = hBuffer;
+ DC_FBDEV_DEVICE *psDeviceData = psBuffer->psDeviceContext->psDeviceData;
+ IMG_UINT32 ui32ByteSize = psBuffer->ui32ByteStride * psBuffer->ui32Height;
+ IMG_UINTPTR_T uiStartAddr;
+ IMG_UINT32 i, ui32MaxLen;
+
+ uiStartAddr = psDeviceData->psLINFBInfo->fix.smem_start +
+ psBuffer->ui32BufferID * ui32ByteSize;
+
+ ui32MaxLen = psDeviceData->psLINFBInfo->fix.smem_len -
+ psBuffer->ui32BufferID * ui32ByteSize;
+
+ for (i = 0; i < BYTE_TO_PAGES(ui32ByteSize); i++)
+ {
+ BUG_ON(i * PAGE_SIZE >= ui32MaxLen);
+ pasDevPAddr[i].uiAddr = uiStartAddr + (i * PAGE_SIZE);
+ }
+
+ /* We're UMA, so services will do the right thing and make
+ * its own CPU virtual address mapping for the buffer.
+ */
+ *ppvLinAddr = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+static void DC_FBDEV_BufferRelease(IMG_HANDLE hBuffer)
+{
+ PVR_UNREFERENCED_PARAMETER(hBuffer);
+}
+
+static void DC_FBDEV_BufferFree(IMG_HANDLE hBuffer)
+{
+ DC_FBDEV_BUFFER *psBuffer = hBuffer;
+
+ DC_FBDEV_PutBufferID(psBuffer->psDeviceContext, psBuffer->ui32BufferID);
+
+ kfree(psBuffer);
+}
+
+/* If we can flip, we need to make sure we have the memory to do so.
+ *
+ * We'll assume that the fbdev device provides extra space in
+ * yres_virtual for panning; xres_virtual is theoretically supported,
+ * but it involves more work.
+ *
+ * If the fbdev device doesn't have yres_virtual > yres, we'll try
+ * requesting it before bailing. Userspace applications commonly do
+ * this with an FBIOPUT_VSCREENINFO ioctl().
+ *
+ * Another problem is with a limitation in the services DC -- it
+ * needs framebuffers to be page aligned (this is a SW limitation,
+ * the HW can support non-page-aligned buffers). So we have to
+ * check that stride * height for a single buffer is page aligned.
+ */
+
+static bool DC_FBDEV_FlipPossible(struct fb_info *psLINFBInfo)
+{
+ struct fb_var_screeninfo sVar = psLINFBInfo->var;
+ int err;
+
+ if(!psLINFBInfo->fix.xpanstep && !psLINFBInfo->fix.ypanstep &&
+ !psLINFBInfo->fix.ywrapstep)
+ {
+ pr_err("The fbdev device detected does not support ypan/ywrap. "
+ "Flipping disabled.\n");
+ return false;
+ }
+
+ if((psLINFBInfo->fix.line_length * sVar.yres) % PAGE_SIZE != 0)
+ {
+ pr_err("Line length (in bytes) x yres is not a multiple of "
+ "page size. Flipping disabled.\n");
+ return false;
+ }
+
+ /* We might already have enough space */
+ if(sVar.yres * NUM_PREFERRED_BUFFERS <= sVar.yres_virtual)
+ return true;
+
+ pr_err("No buffer space for flipping; asking for more.\n");
+ pr_err("sVar.yres=%d,sVar.yres_virtual=%d",sVar.yres,sVar.yres_virtual);
+
+ //zxl:if open it,will lead to penguin Logo show error
+#if 0
+ if((sVar.nonstd & 0xff) != (sDefaultVar.nonstd & 0xff))
+ {
+ DumpFbInfo(&sDefaultVar);
+ sVar = sDefaultVar;
+ }
+#endif
+
+ sVar.activate = FB_ACTIVATE_NOW;
+ sVar.yres_virtual = sVar.yres * NUM_PREFERRED_BUFFERS;
+ err = fb_set_var(psLINFBInfo, &sVar);
+ if(err)
+ {
+ pr_err("fb_set_var failed (err=%d). Flipping disabled.\n", err);
+ return false;
+ }
+
+ if(sVar.yres * NUM_PREFERRED_BUFFERS > sVar.yres_virtual)
+ {
+ pr_err("Failed to obtain additional buffer space. "
+ "Flipping disabled.\n");
+ return false;
+ }
+
+ /* Some fbdev drivers allow the yres_virtual modification through,
+ * but don't actually update the fix. We need the fix to be updated
+ * and more memory allocated, so we can actually take advantage of
+ * the increased yres_virtual.
+ */
+ if(psLINFBInfo->fix.smem_len < psLINFBInfo->fix.line_length * sVar.yres_virtual)
+ {
+ pr_err("'fix' not re-allocated with sufficient buffer space. "
+ "Flipping disabled.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int __init DC_FBDEV_init(void)
+{
+ static DC_DEVICE_FUNCTIONS sDCFunctions =
+ {
+ .pfnGetInfo = DC_FBDEV_GetInfo,
+ .pfnPanelQueryCount = DC_FBDEV_PanelQueryCount,
+ .pfnPanelQuery = DC_FBDEV_PanelQuery,
+ .pfnFormatQuery = DC_FBDEV_FormatQuery,
+ .pfnDimQuery = DC_FBDEV_DimQuery,
+ .pfnSetBlank = IMG_NULL,
+ .pfnSetVSyncReporting = IMG_NULL,
+ .pfnLastVSyncQuery = IMG_NULL,
+ .pfnContextCreate = DC_FBDEV_ContextCreate,
+ .pfnContextDestroy = DC_FBDEV_ContextDestroy,
+ .pfnContextConfigure = DC_FBDEV_ContextConfigure,
+ .pfnContextConfigureCheck = DC_FBDEV_ContextConfigureCheck,
+ .pfnBufferAlloc = DC_FBDEV_BufferAlloc,
+ .pfnBufferAcquire = DC_FBDEV_BufferAcquire,
+ .pfnBufferRelease = DC_FBDEV_BufferRelease,
+ .pfnBufferFree = DC_FBDEV_BufferFree,
+ };
+
+ struct fb_info *psLINFBInfo;
+ IMG_PIXFMT ePixFormat;
+ int err = -ENODEV;
+
+ psLINFBInfo = registered_fb[0];
+ if(!psLINFBInfo)
+ {
+ pr_err("No Linux framebuffer (fbdev) device is registered!\n"
+ "Check you have a framebuffer driver compiled into your "
+ "kernel\nand that it is enabled on the cmdline.\n");
+ goto err_out;
+ }
+
+ if(!lock_fb_info(psLINFBInfo))
+ goto err_out;
+
+ console_lock();
+
+ /* Filter out broken FB devices */
+ if(!psLINFBInfo->fix.smem_len || !psLINFBInfo->fix.line_length)
+ {
+ pr_err("The fbdev device detected had a zero smem_len or "
+ "line_length,\nwhich suggests it is a broken driver.\n");
+ goto err_unlock;
+ }
+
+ if(psLINFBInfo->fix.type != FB_TYPE_PACKED_PIXELS ||
+ psLINFBInfo->fix.visual != FB_VISUAL_TRUECOLOR)
+ {
+ pr_err("The fbdev device detected is not truecolor with packed "
+ "pixels.\n");
+ goto err_unlock;
+ }
+
+#if 1
+ /*chenli: If FB uses RGB888 format after boot logo,
+ the value we need should be caculated with the RGB888 format
+ */
+ if(psLINFBInfo->var.bits_per_pixel ==16)
+ {
+ psLINFBInfo->var.bits_per_pixel = 32;
+ psLINFBInfo->var.red.length = 8;
+ psLINFBInfo->var.green.length = 8;
+ psLINFBInfo->var.blue.length = 8 ;
+ psLINFBInfo->var.red.offset = 16;
+ psLINFBInfo->var.green.offset = 8;
+ psLINFBInfo->var.blue.offset = 0;
+ psLINFBInfo->var.red.msb_right = 0;
+ psLINFBInfo->fix.line_length *= 2;
+ }
+#endif
+
+ if(psLINFBInfo->var.bits_per_pixel == 32)
+ {
+ if(psLINFBInfo->var.red.length != 8 ||
+ psLINFBInfo->var.green.length != 8 ||
+ psLINFBInfo->var.blue.length != 8 ||
+ psLINFBInfo->var.red.offset != 16 ||
+ psLINFBInfo->var.green.offset != 8 ||
+ psLINFBInfo->var.blue.offset != 0)
+ {
+ pr_err("The fbdev device detected uses an unrecognized "
+ "32bit pixel format (%u/%u/%u, %u/%u/%u)\n",
+ psLINFBInfo->var.red.length,
+ psLINFBInfo->var.green.length,
+ psLINFBInfo->var.blue.length,
+ psLINFBInfo->var.red.offset,
+ psLINFBInfo->var.green.offset,
+ psLINFBInfo->var.blue.offset);
+ goto err_unlock;
+ }
+#if defined(DC_FBDEV_FORCE_XRGB8888)
+ ePixFormat = IMG_PIXFMT_B8G8R8X8_UNORM;
+#else
+ ePixFormat = IMG_PIXFMT_B8G8R8A8_UNORM;
+#endif
+ }
+ else if(psLINFBInfo->var.bits_per_pixel == 16)
+ {
+ if(psLINFBInfo->var.red.length != 5 ||
+ psLINFBInfo->var.green.length != 6 ||
+ psLINFBInfo->var.blue.length != 5 ||
+ psLINFBInfo->var.red.offset != 11 ||
+ psLINFBInfo->var.green.offset != 5 ||
+ psLINFBInfo->var.blue.offset != 0)
+ {
+ pr_err("The fbdev device detected uses an unrecognized "
+ "16bit pixel format (%u/%u/%u, %u/%u/%u)\n",
+ psLINFBInfo->var.red.length,
+ psLINFBInfo->var.green.length,
+ psLINFBInfo->var.blue.length,
+ psLINFBInfo->var.red.offset,
+ psLINFBInfo->var.green.offset,
+ psLINFBInfo->var.blue.offset);
+ goto err_unlock;
+ }
+ ePixFormat = IMG_PIXFMT_B5G6R5_UNORM;
+ }
+ else
+ {
+ pr_err("The fbdev device detected uses an unsupported "
+ "bpp (%u).\n", psLINFBInfo->var.bits_per_pixel);
+ goto err_unlock;
+ }
+#if 1
+ //save defalut fb info
+ sDefaultVar = psLINFBInfo->var;
+ sDefaultVar.reserved[0] = 0;
+ sDefaultVar.reserved[1] = 0;
+ sDefaultVar.reserved[2] = 0;
+ sDefaultVar.yres_virtual = sDefaultVar.yres * 3;
+ sDefaultVar.nonstd &= 0xffffff00;
+ sDefaultVar.nonstd |= 5; //zxl:to match ePixFormat=IMG_PIXFMT_B8G8R8A8_UNORM
+ sDefaultVar.grayscale &= 0xff;
+ sDefaultVar.grayscale |= (sDefaultVar.xres<<8) + (sDefaultVar.yres<<20);
+ sDefaultVar.activate = FB_ACTIVATE_NOW;
+ sDefaultVar.yres_virtual = sDefaultVar.yres * NUM_PREFERRED_BUFFERS;
+#endif
+
+ if(!try_module_get(psLINFBInfo->fbops->owner))
+ {
+ pr_err("try_module_get() failed");
+ goto err_unlock;
+ }
+
+ if(psLINFBInfo->fbops->fb_open &&
+ psLINFBInfo->fbops->fb_open(psLINFBInfo, 0) != 0)
+ {
+ pr_err("fb_open() failed");
+ goto err_module_put;
+ }
+
+ gpsDeviceData = kmalloc(sizeof(DC_FBDEV_DEVICE), GFP_KERNEL);
+ if(!gpsDeviceData)
+ goto err_module_put;
+
+ gpsDeviceData->psLINFBInfo = psLINFBInfo;
+ gpsDeviceData->ePixFormat = ePixFormat;
+
+ if(DCRegisterDevice(&sDCFunctions,
+ MAX_COMMANDS_IN_FLIGHT,
+ gpsDeviceData,
+ &gpsDeviceData->hSrvHandle) != PVRSRV_OK)
+ goto err_kfree;
+
+ gpsDeviceData->bCanFlip = DC_FBDEV_FlipPossible(psLINFBInfo);
+
+ pr_info("Found usable fbdev device (%s):\n"
+ "range (physical) = 0x%lx-0x%lx\n"
+ "size (bytes) = 0x%x\n"
+ "xres x yres = %ux%u\n"
+ "xres x yres (v) = %ux%u\n"
+ "img pix fmt = %u\n"
+ "flipping? = %d\n",
+ psLINFBInfo->fix.id,
+ psLINFBInfo->fix.smem_start,
+ psLINFBInfo->fix.smem_start + psLINFBInfo->fix.smem_len,
+ psLINFBInfo->fix.smem_len,
+ psLINFBInfo->var.xres, psLINFBInfo->var.yres,
+ psLINFBInfo->var.xres_virtual, psLINFBInfo->var.yres_virtual,
+ ePixFormat, gpsDeviceData->bCanFlip);
+ err = 0;
+err_unlock:
+ console_unlock();
+ unlock_fb_info(psLINFBInfo);
+err_out:
+ return err;
+err_kfree:
+ kfree(gpsDeviceData);
+err_module_put:
+ module_put(psLINFBInfo->fbops->owner);
+ goto err_unlock;
+}
+
+static void __exit DC_FBDEV_exit(void)
+{
+ DC_FBDEV_DEVICE *psDeviceData = gpsDeviceData;
+ struct fb_info *psLINFBInfo = psDeviceData->psLINFBInfo;
+
+ lock_fb_info(psLINFBInfo);
+ console_lock();
+
+ if(psLINFBInfo->fbops->fb_release)
+ psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
+
+ module_put(psLINFBInfo->fbops->owner);
+
+ console_unlock();
+ unlock_fb_info(psLINFBInfo);
+
+ DCUnregisterDevice(psDeviceData->hSrvHandle);
+ kfree(psDeviceData);
+}
+
+module_init(DC_FBDEV_init);
+module_exit(DC_FBDEV_exit);
diff --git a/drivers/gpu/rogue/generated/breakpoint_bridge/common_breakpoint_bridge.h b/drivers/gpu/rogue/generated/breakpoint_bridge/common_breakpoint_bridge.h
new file mode 100644
index 000000000000..4a4665255498
--- /dev/null
+++ b/drivers/gpu/rogue/generated/breakpoint_bridge/common_breakpoint_bridge.h
@@ -0,0 +1,157 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for breakpoint
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for breakpoint
+@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_BREAKPOINT_BRIDGE_H
+#define COMMON_BREAKPOINT_BRIDGE_H
+
+#include "rgx_bridge.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_BREAKPOINT_CMD_FIRST (PVRSRV_BRIDGE_BREAKPOINT_START)
+#define PVRSRV_BRIDGE_BREAKPOINT_RGXSETBREAKPOINT PVRSRV_IOWR(PVRSRV_BRIDGE_BREAKPOINT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_BREAKPOINT_RGXCLEARBREAKPOINT PVRSRV_IOWR(PVRSRV_BRIDGE_BREAKPOINT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_BREAKPOINT_RGXENABLEBREAKPOINT PVRSRV_IOWR(PVRSRV_BRIDGE_BREAKPOINT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_BREAKPOINT_RGXDISABLEBREAKPOINT PVRSRV_IOWR(PVRSRV_BRIDGE_BREAKPOINT_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_BREAKPOINT_RGXOVERALLOCATEBPREGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_BREAKPOINT_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_BREAKPOINT_CMD_LAST (PVRSRV_BRIDGE_BREAKPOINT_CMD_FIRST+4)
+
+
+/*******************************************
+ RGXSetBreakpoint
+ *******************************************/
+
+/* Bridge in structure for RGXSetBreakpoint */
+typedef struct PVRSRV_BRIDGE_IN_RGXSETBREAKPOINT_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_HANDLE hPrivData;
+ IMG_UINT32 eFWDataMaster;
+ IMG_UINT32 ui32BreakpointAddr;
+ IMG_UINT32 ui32HandlerAddr;
+ IMG_UINT32 ui32DM;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXSETBREAKPOINT;
+
+
+/* Bridge out structure for RGXSetBreakpoint */
+typedef struct PVRSRV_BRIDGE_OUT_RGXSETBREAKPOINT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXSETBREAKPOINT;
+
+/*******************************************
+ RGXClearBreakpoint
+ *******************************************/
+
+/* Bridge in structure for RGXClearBreakpoint */
+typedef struct PVRSRV_BRIDGE_IN_RGXCLEARBREAKPOINT_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_HANDLE hPrivData;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCLEARBREAKPOINT;
+
+
+/* Bridge out structure for RGXClearBreakpoint */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCLEARBREAKPOINT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCLEARBREAKPOINT;
+
+/*******************************************
+ RGXEnableBreakpoint
+ *******************************************/
+
+/* Bridge in structure for RGXEnableBreakpoint */
+typedef struct PVRSRV_BRIDGE_IN_RGXENABLEBREAKPOINT_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_HANDLE hPrivData;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXENABLEBREAKPOINT;
+
+
+/* Bridge out structure for RGXEnableBreakpoint */
+typedef struct PVRSRV_BRIDGE_OUT_RGXENABLEBREAKPOINT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXENABLEBREAKPOINT;
+
+/*******************************************
+ RGXDisableBreakpoint
+ *******************************************/
+
+/* Bridge in structure for RGXDisableBreakpoint */
+typedef struct PVRSRV_BRIDGE_IN_RGXDISABLEBREAKPOINT_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_HANDLE hPrivData;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDISABLEBREAKPOINT;
+
+
+/* Bridge out structure for RGXDisableBreakpoint */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDISABLEBREAKPOINT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDISABLEBREAKPOINT;
+
+/*******************************************
+ RGXOverallocateBPRegisters
+ *******************************************/
+
+/* Bridge in structure for RGXOverallocateBPRegisters */
+typedef struct PVRSRV_BRIDGE_IN_RGXOVERALLOCATEBPREGISTERS_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32TempRegs;
+ IMG_UINT32 ui32SharedRegs;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXOVERALLOCATEBPREGISTERS;
+
+
+/* Bridge out structure for RGXOverallocateBPRegisters */
+typedef struct PVRSRV_BRIDGE_OUT_RGXOVERALLOCATEBPREGISTERS_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXOVERALLOCATEBPREGISTERS;
+
+#endif /* COMMON_BREAKPOINT_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/breakpoint_bridge/server_breakpoint_bridge.c b/drivers/gpu/rogue/generated/breakpoint_bridge/server_breakpoint_bridge.c
new file mode 100644
index 000000000000..f2cb78e1ba26
--- /dev/null
+++ b/drivers/gpu/rogue/generated/breakpoint_bridge/server_breakpoint_bridge.c
@@ -0,0 +1,371 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for breakpoint
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for breakpoint
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxbreakpoint.h"
+
+
+#include "common_breakpoint_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeRGXSetBreakpoint(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXSETBREAKPOINT *psRGXSetBreakpointIN,
+ PVRSRV_BRIDGE_OUT_RGXSETBREAKPOINT *psRGXSetBreakpointOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_BREAKPOINT_RGXSETBREAKPOINT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXSetBreakpointOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXSetBreakpointIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXSetBreakpointOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSetBreakpoint_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXSetBreakpointOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPrivDataInt,
+ psRGXSetBreakpointIN->hPrivData,
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+ if(psRGXSetBreakpointOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSetBreakpoint_exit;
+ }
+
+ }
+
+ psRGXSetBreakpointOUT->eError =
+ PVRSRVRGXSetBreakpointKM(
+ hDevNodeInt,
+ hPrivDataInt,
+ psRGXSetBreakpointIN->eFWDataMaster,
+ psRGXSetBreakpointIN->ui32BreakpointAddr,
+ psRGXSetBreakpointIN->ui32HandlerAddr,
+ psRGXSetBreakpointIN->ui32DM);
+
+
+
+RGXSetBreakpoint_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXClearBreakpoint(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCLEARBREAKPOINT *psRGXClearBreakpointIN,
+ PVRSRV_BRIDGE_OUT_RGXCLEARBREAKPOINT *psRGXClearBreakpointOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_BREAKPOINT_RGXCLEARBREAKPOINT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXClearBreakpointOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXClearBreakpointIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXClearBreakpointOUT->eError != PVRSRV_OK)
+ {
+ goto RGXClearBreakpoint_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXClearBreakpointOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPrivDataInt,
+ psRGXClearBreakpointIN->hPrivData,
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+ if(psRGXClearBreakpointOUT->eError != PVRSRV_OK)
+ {
+ goto RGXClearBreakpoint_exit;
+ }
+
+ }
+
+ psRGXClearBreakpointOUT->eError =
+ PVRSRVRGXClearBreakpointKM(
+ hDevNodeInt,
+ hPrivDataInt);
+
+
+
+RGXClearBreakpoint_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXEnableBreakpoint(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXENABLEBREAKPOINT *psRGXEnableBreakpointIN,
+ PVRSRV_BRIDGE_OUT_RGXENABLEBREAKPOINT *psRGXEnableBreakpointOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_BREAKPOINT_RGXENABLEBREAKPOINT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXEnableBreakpointOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXEnableBreakpointIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXEnableBreakpointOUT->eError != PVRSRV_OK)
+ {
+ goto RGXEnableBreakpoint_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXEnableBreakpointOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPrivDataInt,
+ psRGXEnableBreakpointIN->hPrivData,
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+ if(psRGXEnableBreakpointOUT->eError != PVRSRV_OK)
+ {
+ goto RGXEnableBreakpoint_exit;
+ }
+
+ }
+
+ psRGXEnableBreakpointOUT->eError =
+ PVRSRVRGXEnableBreakpointKM(
+ hDevNodeInt,
+ hPrivDataInt);
+
+
+
+RGXEnableBreakpoint_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDisableBreakpoint(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDISABLEBREAKPOINT *psRGXDisableBreakpointIN,
+ PVRSRV_BRIDGE_OUT_RGXDISABLEBREAKPOINT *psRGXDisableBreakpointOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_BREAKPOINT_RGXDISABLEBREAKPOINT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDisableBreakpointOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXDisableBreakpointIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXDisableBreakpointOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDisableBreakpoint_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXDisableBreakpointOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPrivDataInt,
+ psRGXDisableBreakpointIN->hPrivData,
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+ if(psRGXDisableBreakpointOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDisableBreakpoint_exit;
+ }
+
+ }
+
+ psRGXDisableBreakpointOUT->eError =
+ PVRSRVRGXDisableBreakpointKM(
+ hDevNodeInt,
+ hPrivDataInt);
+
+
+
+RGXDisableBreakpoint_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXOverallocateBPRegisters(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXOVERALLOCATEBPREGISTERS *psRGXOverallocateBPRegistersIN,
+ PVRSRV_BRIDGE_OUT_RGXOVERALLOCATEBPREGISTERS *psRGXOverallocateBPRegistersOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_BREAKPOINT_RGXOVERALLOCATEBPREGISTERS);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXOverallocateBPRegistersOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXOverallocateBPRegistersIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXOverallocateBPRegistersOUT->eError != PVRSRV_OK)
+ {
+ goto RGXOverallocateBPRegisters_exit;
+ }
+
+ }
+
+ psRGXOverallocateBPRegistersOUT->eError =
+ PVRSRVRGXOverallocateBPRegistersKM(
+ hDevNodeInt,
+ psRGXOverallocateBPRegistersIN->ui32TempRegs,
+ psRGXOverallocateBPRegistersIN->ui32SharedRegs);
+
+
+
+RGXOverallocateBPRegisters_exit:
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterBREAKPOINTFunctions(IMG_VOID);
+IMG_VOID UnregisterBREAKPOINTFunctions(IMG_VOID);
+
+/*
+ * Register all BREAKPOINT functions with services
+ */
+PVRSRV_ERROR RegisterBREAKPOINTFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_BREAKPOINT_RGXSETBREAKPOINT, PVRSRVBridgeRGXSetBreakpoint);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_BREAKPOINT_RGXCLEARBREAKPOINT, PVRSRVBridgeRGXClearBreakpoint);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_BREAKPOINT_RGXENABLEBREAKPOINT, PVRSRVBridgeRGXEnableBreakpoint);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_BREAKPOINT_RGXDISABLEBREAKPOINT, PVRSRVBridgeRGXDisableBreakpoint);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_BREAKPOINT_RGXOVERALLOCATEBPREGISTERS, PVRSRVBridgeRGXOverallocateBPRegisters);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all breakpoint functions with services
+ */
+IMG_VOID UnregisterBREAKPOINTFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/cachegeneric_bridge/common_cachegeneric_bridge.h b/drivers/gpu/rogue/generated/cachegeneric_bridge/common_cachegeneric_bridge.h
new file mode 100644
index 000000000000..92f4cb0a479b
--- /dev/null
+++ b/drivers/gpu/rogue/generated/cachegeneric_bridge/common_cachegeneric_bridge.h
@@ -0,0 +1,75 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for cachegeneric
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for cachegeneric
+@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_CACHEGENERIC_BRIDGE_H
+#define COMMON_CACHEGENERIC_BRIDGE_H
+
+#include "cache_external.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_CACHEGENERIC_CMD_FIRST (PVRSRV_BRIDGE_CACHEGENERIC_START)
+#define PVRSRV_BRIDGE_CACHEGENERIC_CACHEOPQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CACHEGENERIC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CACHEGENERIC_CMD_LAST (PVRSRV_BRIDGE_CACHEGENERIC_CMD_FIRST+0)
+
+
+/*******************************************
+ CacheOpQueue
+ *******************************************/
+
+/* Bridge in structure for CacheOpQueue */
+typedef struct PVRSRV_BRIDGE_IN_CACHEOPQUEUE_TAG
+{
+ PVRSRV_CACHE_OP iuCacheOp;
+} PVRSRV_BRIDGE_IN_CACHEOPQUEUE;
+
+
+/* Bridge out structure for CacheOpQueue */
+typedef struct PVRSRV_BRIDGE_OUT_CACHEOPQUEUE_TAG
+{
+ PVRSRV_ERROR eError;
+} PVRSRV_BRIDGE_OUT_CACHEOPQUEUE;
+
+#endif /* COMMON_CACHEGENERIC_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/cachegeneric_bridge/server_cachegeneric_bridge.c b/drivers/gpu/rogue/generated/cachegeneric_bridge/server_cachegeneric_bridge.c
new file mode 100644
index 000000000000..ed8cf78242b4
--- /dev/null
+++ b/drivers/gpu/rogue/generated/cachegeneric_bridge/server_cachegeneric_bridge.c
@@ -0,0 +1,126 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for cachegeneric
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for cachegeneric
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "cache_generic.h"
+
+
+#include "common_cachegeneric_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeCacheOpQueue(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CACHEOPQUEUE *psCacheOpQueueIN,
+ PVRSRV_BRIDGE_OUT_CACHEOPQUEUE *psCacheOpQueueOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CACHEGENERIC_CACHEOPQUEUE);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ psCacheOpQueueOUT->eError =
+ CacheOpQueue(
+ psCacheOpQueueIN->iuCacheOp);
+
+
+
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterCACHEGENERICFunctions(IMG_VOID);
+IMG_VOID UnregisterCACHEGENERICFunctions(IMG_VOID);
+
+/*
+ * Register all CACHEGENERIC functions with services
+ */
+PVRSRV_ERROR RegisterCACHEGENERICFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CACHEGENERIC_CACHEOPQUEUE, PVRSRVBridgeCacheOpQueue);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all cachegeneric functions with services
+ */
+IMG_VOID UnregisterCACHEGENERICFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/cmm_bridge/common_cmm_bridge.h b/drivers/gpu/rogue/generated/cmm_bridge/common_cmm_bridge.h
new file mode 100644
index 000000000000..c16d71551fbf
--- /dev/null
+++ b/drivers/gpu/rogue/generated/cmm_bridge/common_cmm_bridge.h
@@ -0,0 +1,178 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for cmm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for cmm
+@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_CMM_BRIDGE_H
+#define COMMON_CMM_BRIDGE_H
+
+#include "devicemem_typedefs.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_CMM_CMD_FIRST (PVRSRV_BRIDGE_CMM_START)
+#define PVRSRV_BRIDGE_CMM_PMRWRITEPMPAGELIST PVRSRV_IOWR(PVRSRV_BRIDGE_CMM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CMM_PMRWRITEVFPPAGELIST PVRSRV_IOWR(PVRSRV_BRIDGE_CMM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_CMM_PMRUNWRITEPMPAGELIST PVRSRV_IOWR(PVRSRV_BRIDGE_CMM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_CMM_DEVMEMINTCTXEXPORT PVRSRV_IOWR(PVRSRV_BRIDGE_CMM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_CMM_DEVMEMINTCTXUNEXPORT PVRSRV_IOWR(PVRSRV_BRIDGE_CMM_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_CMM_DEVMEMINTCTXIMPORT PVRSRV_IOWR(PVRSRV_BRIDGE_CMM_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_CMM_CMD_LAST (PVRSRV_BRIDGE_CMM_CMD_FIRST+5)
+
+
+/*******************************************
+ PMRWritePMPageList
+ *******************************************/
+
+/* Bridge in structure for PMRWritePMPageList */
+typedef struct PVRSRV_BRIDGE_IN_PMRWRITEPMPAGELIST_TAG
+{
+ IMG_HANDLE hPageListPMR;
+ IMG_DEVMEM_OFFSET_T uiTableOffset;
+ IMG_DEVMEM_SIZE_T uiTableLength;
+ IMG_HANDLE hReferencePMR;
+ IMG_UINT32 ui32Log2PageSize;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRWRITEPMPAGELIST;
+
+
+/* Bridge out structure for PMRWritePMPageList */
+typedef struct PVRSRV_BRIDGE_OUT_PMRWRITEPMPAGELIST_TAG
+{
+ IMG_HANDLE hPageList;
+ IMG_UINT64 ui64CheckSum;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRWRITEPMPAGELIST;
+
+/*******************************************
+ PMRWriteVFPPageList
+ *******************************************/
+
+/* Bridge in structure for PMRWriteVFPPageList */
+typedef struct PVRSRV_BRIDGE_IN_PMRWRITEVFPPAGELIST_TAG
+{
+ IMG_HANDLE hFreeListPMR;
+ IMG_DEVMEM_OFFSET_T uiTableOffset;
+ IMG_DEVMEM_SIZE_T uiTableLength;
+ IMG_UINT32 ui32TableBase;
+ IMG_UINT32 ui32Log2PageSize;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRWRITEVFPPAGELIST;
+
+
+/* Bridge out structure for PMRWriteVFPPageList */
+typedef struct PVRSRV_BRIDGE_OUT_PMRWRITEVFPPAGELIST_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRWRITEVFPPAGELIST;
+
+/*******************************************
+ PMRUnwritePMPageList
+ *******************************************/
+
+/* Bridge in structure for PMRUnwritePMPageList */
+typedef struct PVRSRV_BRIDGE_IN_PMRUNWRITEPMPAGELIST_TAG
+{
+ IMG_HANDLE hPageList;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRUNWRITEPMPAGELIST;
+
+
+/* Bridge out structure for PMRUnwritePMPageList */
+typedef struct PVRSRV_BRIDGE_OUT_PMRUNWRITEPMPAGELIST_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRUNWRITEPMPAGELIST;
+
+/*******************************************
+ DevmemIntCtxExport
+ *******************************************/
+
+/* Bridge in structure for DevmemIntCtxExport */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTCTXEXPORT_TAG
+{
+ IMG_HANDLE hDevMemServerContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTCTXEXPORT;
+
+
+/* Bridge out structure for DevmemIntCtxExport */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTCTXEXPORT_TAG
+{
+ IMG_HANDLE hDevMemIntCtxExport;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTCTXEXPORT;
+
+/*******************************************
+ DevmemIntCtxUnexport
+ *******************************************/
+
+/* Bridge in structure for DevmemIntCtxUnexport */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTCTXUNEXPORT_TAG
+{
+ IMG_HANDLE hDevMemIntCtxExport;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTCTXUNEXPORT;
+
+
+/* Bridge out structure for DevmemIntCtxUnexport */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTCTXUNEXPORT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTCTXUNEXPORT;
+
+/*******************************************
+ DevmemIntCtxImport
+ *******************************************/
+
+/* Bridge in structure for DevmemIntCtxImport */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTCTXIMPORT_TAG
+{
+ IMG_HANDLE hDevMemIntCtxExport;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTCTXIMPORT;
+
+
+/* Bridge out structure for DevmemIntCtxImport */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTCTXIMPORT_TAG
+{
+ IMG_HANDLE hDevMemServerContext;
+ IMG_HANDLE hPrivData;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTCTXIMPORT;
+
+#endif /* COMMON_CMM_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/cmm_bridge/server_cmm_bridge.c b/drivers/gpu/rogue/generated/cmm_bridge/server_cmm_bridge.c
new file mode 100644
index 000000000000..4c4172bf3dfa
--- /dev/null
+++ b/drivers/gpu/rogue/generated/cmm_bridge/server_cmm_bridge.c
@@ -0,0 +1,611 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for cmm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for cmm
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "pmr.h"
+#include "devicemem_server.h"
+
+
+#include "common_cmm_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+PMRUnwritePMPageListResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DevmemIntCtxUnexportResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgePMRWritePMPageList(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRWRITEPMPAGELIST *psPMRWritePMPageListIN,
+ PVRSRV_BRIDGE_OUT_PMRWRITEPMPAGELIST *psPMRWritePMPageListOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPageListPMRInt = IMG_NULL;
+ IMG_HANDLE hPageListPMRInt2 = IMG_NULL;
+ PMR * psReferencePMRInt = IMG_NULL;
+ IMG_HANDLE hReferencePMRInt2 = IMG_NULL;
+ PMR_PAGELIST * psPageListInt = IMG_NULL;
+ IMG_HANDLE hPageListInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CMM_PMRWRITEPMPAGELIST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRWritePMPageListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPageListPMRInt2,
+ psPMRWritePMPageListIN->hPageListPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRWritePMPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRWritePMPageList_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRWritePMPageListOUT->eError = ResManFindPrivateDataByPtr(hPageListPMRInt2, (IMG_VOID **) &psPageListPMRInt);
+
+ if(psPMRWritePMPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRWritePMPageList_exit;
+ }
+ }
+
+ {
+ /* Look up the address from the handle */
+ psPMRWritePMPageListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hReferencePMRInt2,
+ psPMRWritePMPageListIN->hReferencePMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRWritePMPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRWritePMPageList_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRWritePMPageListOUT->eError = ResManFindPrivateDataByPtr(hReferencePMRInt2, (IMG_VOID **) &psReferencePMRInt);
+
+ if(psPMRWritePMPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRWritePMPageList_exit;
+ }
+ }
+
+ psPMRWritePMPageListOUT->eError =
+ PMRWritePMPageList(
+ psPageListPMRInt,
+ psPMRWritePMPageListIN->uiTableOffset,
+ psPMRWritePMPageListIN->uiTableLength,
+ psReferencePMRInt,
+ psPMRWritePMPageListIN->ui32Log2PageSize,
+ &psPageListInt,
+ &psPMRWritePMPageListOUT->ui64CheckSum);
+ /* Exit early if bridged call fails */
+ if(psPMRWritePMPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRWritePMPageList_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hPageListInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR_PAGELIST,
+ psPageListInt,
+ (RESMAN_FREE_FN)&PMRUnwritePMPageList);
+ if (hPageListInt2 == IMG_NULL)
+ {
+ psPMRWritePMPageListOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PMRWritePMPageList_exit;
+ }
+ psPMRWritePMPageListOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psPMRWritePMPageListOUT->hPageList,
+ (IMG_HANDLE) hPageListInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_PAGELIST,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psPMRWritePMPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRWritePMPageList_exit;
+ }
+
+
+PMRWritePMPageList_exit:
+ if (psPMRWritePMPageListOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPageListInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPageListInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPageListInt)
+ {
+ PMRUnwritePMPageList(psPageListInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRWriteVFPPageList(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRWRITEVFPPAGELIST *psPMRWriteVFPPageListIN,
+ PVRSRV_BRIDGE_OUT_PMRWRITEVFPPAGELIST *psPMRWriteVFPPageListOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psFreeListPMRInt = IMG_NULL;
+ IMG_HANDLE hFreeListPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CMM_PMRWRITEVFPPAGELIST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRWriteVFPPageListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hFreeListPMRInt2,
+ psPMRWriteVFPPageListIN->hFreeListPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRWriteVFPPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRWriteVFPPageList_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRWriteVFPPageListOUT->eError = ResManFindPrivateDataByPtr(hFreeListPMRInt2, (IMG_VOID **) &psFreeListPMRInt);
+
+ if(psPMRWriteVFPPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRWriteVFPPageList_exit;
+ }
+ }
+
+ psPMRWriteVFPPageListOUT->eError =
+ PMRWriteVFPPageList(
+ psFreeListPMRInt,
+ psPMRWriteVFPPageListIN->uiTableOffset,
+ psPMRWriteVFPPageListIN->uiTableLength,
+ psPMRWriteVFPPageListIN->ui32TableBase,
+ psPMRWriteVFPPageListIN->ui32Log2PageSize);
+
+
+
+PMRWriteVFPPageList_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRUnwritePMPageList(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRUNWRITEPMPAGELIST *psPMRUnwritePMPageListIN,
+ PVRSRV_BRIDGE_OUT_PMRUNWRITEPMPAGELIST *psPMRUnwritePMPageListOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hPageListInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CMM_PMRUNWRITEPMPAGELIST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRUnwritePMPageListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPageListInt2,
+ psPMRUnwritePMPageListIN->hPageList,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_PAGELIST);
+ if(psPMRUnwritePMPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRUnwritePMPageList_exit;
+ }
+
+ }
+
+ psPMRUnwritePMPageListOUT->eError = PMRUnwritePMPageListResManProxy(hPageListInt2);
+ /* Exit early if bridged call fails */
+ if(psPMRUnwritePMPageListOUT->eError != PVRSRV_OK)
+ {
+ goto PMRUnwritePMPageList_exit;
+ }
+
+ psPMRUnwritePMPageListOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psPMRUnwritePMPageListIN->hPageList,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_PAGELIST);
+
+
+PMRUnwritePMPageList_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntCtxExport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTCTXEXPORT *psDevmemIntCtxExportIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTCTXEXPORT *psDevmemIntCtxExportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DEVMEMINT_CTX * psDevMemServerContextInt = IMG_NULL;
+ IMG_HANDLE hDevMemServerContextInt2 = IMG_NULL;
+ DEVMEMINT_CTX_EXPORT * psDevMemIntCtxExportInt = IMG_NULL;
+ IMG_HANDLE hDevMemIntCtxExportInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CMM_DEVMEMINTCTXEXPORT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntCtxExportOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevMemServerContextInt2,
+ psDevmemIntCtxExportIN->hDevMemServerContext,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+ if(psDevmemIntCtxExportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxExport_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemIntCtxExportOUT->eError = ResManFindPrivateDataByPtr(hDevMemServerContextInt2, (IMG_VOID **) &psDevMemServerContextInt);
+
+ if(psDevmemIntCtxExportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxExport_exit;
+ }
+ }
+
+ psDevmemIntCtxExportOUT->eError =
+ DevmemIntCtxExport(
+ psDevMemServerContextInt,
+ &psDevMemIntCtxExportInt);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntCtxExportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxExport_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hDevMemIntCtxExportInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DEVICEMEM2_CONTEXT_EXPORT,
+ psDevMemIntCtxExportInt,
+ (RESMAN_FREE_FN)&DevmemIntCtxUnexport);
+ if (hDevMemIntCtxExportInt2 == IMG_NULL)
+ {
+ psDevmemIntCtxExportOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DevmemIntCtxExport_exit;
+ }
+ /* see if it's already exported */
+ psDevmemIntCtxExportOUT->eError =
+ PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &psDevmemIntCtxExportOUT->hDevMemIntCtxExport,
+ (IMG_HANDLE) hDevMemIntCtxExportInt2,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT);
+ if(psDevmemIntCtxExportOUT->eError == PVRSRV_OK)
+ {
+ /* It's already exported */
+ return 0;
+ }
+
+ psDevmemIntCtxExportOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psDevmemIntCtxExportOUT->hDevMemIntCtxExport,
+ (IMG_HANDLE) hDevMemIntCtxExportInt2,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDevmemIntCtxExportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxExport_exit;
+ }
+
+
+DevmemIntCtxExport_exit:
+ if (psDevmemIntCtxExportOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hDevMemIntCtxExportInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hDevMemIntCtxExportInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psDevMemIntCtxExportInt)
+ {
+ DevmemIntCtxUnexport(psDevMemIntCtxExportInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntCtxUnexport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTCTXUNEXPORT *psDevmemIntCtxUnexportIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTCTXUNEXPORT *psDevmemIntCtxUnexportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevMemIntCtxExportInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CMM_DEVMEMINTCTXUNEXPORT);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntCtxUnexportOUT->eError =
+ PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE *) &hDevMemIntCtxExportInt2,
+ psDevmemIntCtxUnexportIN->hDevMemIntCtxExport,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT);
+ if(psDevmemIntCtxUnexportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxUnexport_exit;
+ }
+
+ }
+
+ psDevmemIntCtxUnexportOUT->eError = DevmemIntCtxUnexportResManProxy(hDevMemIntCtxExportInt2);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntCtxUnexportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxUnexport_exit;
+ }
+
+ psDevmemIntCtxUnexportOUT->eError =
+ PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE) psDevmemIntCtxUnexportIN->hDevMemIntCtxExport,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT);
+
+
+DevmemIntCtxUnexport_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntCtxImport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTCTXIMPORT *psDevmemIntCtxImportIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTCTXIMPORT *psDevmemIntCtxImportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DEVMEMINT_CTX_EXPORT * psDevMemIntCtxExportInt = IMG_NULL;
+ IMG_HANDLE hDevMemIntCtxExportInt2 = IMG_NULL;
+ DEVMEMINT_CTX * psDevMemServerContextInt = IMG_NULL;
+ IMG_HANDLE hDevMemServerContextInt2 = IMG_NULL;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CMM_DEVMEMINTCTXIMPORT);
+
+
+
+ psDevmemIntCtxImportOUT->hDevMemServerContext = IMG_NULL;
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntCtxImportOUT->eError =
+ PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE *) &hDevMemIntCtxExportInt2,
+ psDevmemIntCtxImportIN->hDevMemIntCtxExport,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT);
+ if(psDevmemIntCtxImportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxImport_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemIntCtxImportOUT->eError = ResManFindPrivateDataByPtr(hDevMemIntCtxExportInt2, (IMG_VOID **) &psDevMemIntCtxExportInt);
+
+ if(psDevmemIntCtxImportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxImport_exit;
+ }
+ }
+
+ psDevmemIntCtxImportOUT->eError =
+ DevmemIntCtxImport(
+ psDevMemIntCtxExportInt,
+ &psDevMemServerContextInt,
+ &hPrivDataInt);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntCtxImportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxImport_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hDevMemServerContextInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DEVICEMEM2_CONTEXT,
+ psDevMemServerContextInt,
+ (RESMAN_FREE_FN)&DevmemIntCtxDestroy);
+ if (hDevMemServerContextInt2 == IMG_NULL)
+ {
+ psDevmemIntCtxImportOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DevmemIntCtxImport_exit;
+ }
+ psDevmemIntCtxImportOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDevmemIntCtxImportOUT->hDevMemServerContext,
+ (IMG_HANDLE) hDevMemServerContextInt2,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDevmemIntCtxImportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxImport_exit;
+ }
+ psDevmemIntCtxImportOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+ &psDevmemIntCtxImportOUT->hPrivData,
+ (IMG_HANDLE) hPrivDataInt,
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+ ,psDevmemIntCtxImportOUT->hDevMemServerContext);
+ if (psDevmemIntCtxImportOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxImport_exit;
+ }
+
+
+DevmemIntCtxImport_exit:
+ if (psDevmemIntCtxImportOUT->eError != PVRSRV_OK)
+ {
+ if (psDevmemIntCtxImportOUT->hDevMemServerContext)
+ {
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDevmemIntCtxImportOUT->hDevMemServerContext,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+ }
+
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hDevMemServerContextInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hDevMemServerContextInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psDevMemServerContextInt)
+ {
+ DevmemIntCtxDestroy(psDevMemServerContextInt);
+ }
+ }
+
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterCMMFunctions(IMG_VOID);
+IMG_VOID UnregisterCMMFunctions(IMG_VOID);
+
+/*
+ * Register all CMM functions with services
+ */
+PVRSRV_ERROR RegisterCMMFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CMM_PMRWRITEPMPAGELIST, PVRSRVBridgePMRWritePMPageList);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CMM_PMRWRITEVFPPAGELIST, PVRSRVBridgePMRWriteVFPPageList);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CMM_PMRUNWRITEPMPAGELIST, PVRSRVBridgePMRUnwritePMPageList);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CMM_DEVMEMINTCTXEXPORT, PVRSRVBridgeDevmemIntCtxExport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CMM_DEVMEMINTCTXUNEXPORT, PVRSRVBridgeDevmemIntCtxUnexport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CMM_DEVMEMINTCTXIMPORT, PVRSRVBridgeDevmemIntCtxImport);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all cmm functions with services
+ */
+IMG_VOID UnregisterCMMFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/dc_bridge/common_dc_bridge.h b/drivers/gpu/rogue/generated/dc_bridge/common_dc_bridge.h
new file mode 100644
index 000000000000..afa08781d361
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dc_bridge/common_dc_bridge.h
@@ -0,0 +1,578 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for dc
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for dc
+@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_DC_BRIDGE_H
+#define COMMON_DC_BRIDGE_H
+
+#include "pvrsrv_surface.h"
+#include "dc_external.h"
+#include "dc_common.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_DC_CMD_FIRST (PVRSRV_BRIDGE_DC_START)
+#define PVRSRV_BRIDGE_DC_DCDEVICESQUERYCOUNT PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DC_DCDEVICESENUMERATE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_DC_DCDEVICEACQUIRE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_DC_DCDEVICERELEASE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_DC_DCGETINFO PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_DC_DCPANELQUERYCOUNT PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_DC_DCPANELQUERY PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_DC_DCFORMATQUERY PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_DC_DCDIMQUERY PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_DC_DCSETBLANK PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_DC_DCSETVSYNCREPORTING PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_DC_DCLASTVSYNCQUERY PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_DC_DCSYSTEMBUFFERACQUIRE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_DC_DCSYSTEMBUFFERRELEASE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTCREATE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTCONFIGURECHECK PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTCONFIGURE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTDESTROY PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_DC_DCBUFFERALLOC PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_DC_DCBUFFERIMPORT PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_DC_DCBUFFERFREE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_DC_DCBUFFERUNIMPORT PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+21)
+#define PVRSRV_BRIDGE_DC_DCBUFFERPIN PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+22)
+#define PVRSRV_BRIDGE_DC_DCBUFFERUNPIN PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+23)
+#define PVRSRV_BRIDGE_DC_DCBUFFERACQUIRE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+24)
+#define PVRSRV_BRIDGE_DC_DCBUFFERRELEASE PVRSRV_IOWR(PVRSRV_BRIDGE_DC_CMD_FIRST+25)
+#define PVRSRV_BRIDGE_DC_CMD_LAST (PVRSRV_BRIDGE_DC_CMD_FIRST+25)
+
+
+/*******************************************
+ DCDevicesQueryCount
+ *******************************************/
+
+/* Bridge in structure for DCDevicesQueryCount */
+typedef struct PVRSRV_BRIDGE_IN_DCDEVICESQUERYCOUNT_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCDEVICESQUERYCOUNT;
+
+
+/* Bridge out structure for DCDevicesQueryCount */
+typedef struct PVRSRV_BRIDGE_OUT_DCDEVICESQUERYCOUNT_TAG
+{
+ IMG_UINT32 ui32DeviceCount;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCDEVICESQUERYCOUNT;
+
+/*******************************************
+ DCDevicesEnumerate
+ *******************************************/
+
+/* Bridge in structure for DCDevicesEnumerate */
+typedef struct PVRSRV_BRIDGE_IN_DCDEVICESENUMERATE_TAG
+{
+ IMG_UINT32 ui32DeviceArraySize;
+ /* Output pointer pui32DeviceIndex is also an implied input */
+ IMG_UINT32 * pui32DeviceIndex;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCDEVICESENUMERATE;
+
+
+/* Bridge out structure for DCDevicesEnumerate */
+typedef struct PVRSRV_BRIDGE_OUT_DCDEVICESENUMERATE_TAG
+{
+ IMG_UINT32 ui32DeviceCount;
+ IMG_UINT32 * pui32DeviceIndex;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCDEVICESENUMERATE;
+
+/*******************************************
+ DCDeviceAcquire
+ *******************************************/
+
+/* Bridge in structure for DCDeviceAcquire */
+typedef struct PVRSRV_BRIDGE_IN_DCDEVICEACQUIRE_TAG
+{
+ IMG_UINT32 ui32DeviceIndex;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCDEVICEACQUIRE;
+
+
+/* Bridge out structure for DCDeviceAcquire */
+typedef struct PVRSRV_BRIDGE_OUT_DCDEVICEACQUIRE_TAG
+{
+ IMG_HANDLE hDevice;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCDEVICEACQUIRE;
+
+/*******************************************
+ DCDeviceRelease
+ *******************************************/
+
+/* Bridge in structure for DCDeviceRelease */
+typedef struct PVRSRV_BRIDGE_IN_DCDEVICERELEASE_TAG
+{
+ IMG_HANDLE hDevice;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCDEVICERELEASE;
+
+
+/* Bridge out structure for DCDeviceRelease */
+typedef struct PVRSRV_BRIDGE_OUT_DCDEVICERELEASE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCDEVICERELEASE;
+
+/*******************************************
+ DCGetInfo
+ *******************************************/
+
+/* Bridge in structure for DCGetInfo */
+typedef struct PVRSRV_BRIDGE_IN_DCGETINFO_TAG
+{
+ IMG_HANDLE hDevice;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCGETINFO;
+
+
+/* Bridge out structure for DCGetInfo */
+typedef struct PVRSRV_BRIDGE_OUT_DCGETINFO_TAG
+{
+ DC_DISPLAY_INFO sDisplayInfo;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCGETINFO;
+
+/*******************************************
+ DCPanelQueryCount
+ *******************************************/
+
+/* Bridge in structure for DCPanelQueryCount */
+typedef struct PVRSRV_BRIDGE_IN_DCPANELQUERYCOUNT_TAG
+{
+ IMG_HANDLE hDevice;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCPANELQUERYCOUNT;
+
+
+/* Bridge out structure for DCPanelQueryCount */
+typedef struct PVRSRV_BRIDGE_OUT_DCPANELQUERYCOUNT_TAG
+{
+ IMG_UINT32 ui32NumPanels;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCPANELQUERYCOUNT;
+
+/*******************************************
+ DCPanelQuery
+ *******************************************/
+
+/* Bridge in structure for DCPanelQuery */
+typedef struct PVRSRV_BRIDGE_IN_DCPANELQUERY_TAG
+{
+ IMG_HANDLE hDevice;
+ IMG_UINT32 ui32PanelsArraySize;
+ /* Output pointer psPanelInfo is also an implied input */
+ PVRSRV_PANEL_INFO * psPanelInfo;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCPANELQUERY;
+
+
+/* Bridge out structure for DCPanelQuery */
+typedef struct PVRSRV_BRIDGE_OUT_DCPANELQUERY_TAG
+{
+ IMG_UINT32 ui32NumPanels;
+ PVRSRV_PANEL_INFO * psPanelInfo;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCPANELQUERY;
+
+/*******************************************
+ DCFormatQuery
+ *******************************************/
+
+/* Bridge in structure for DCFormatQuery */
+typedef struct PVRSRV_BRIDGE_IN_DCFORMATQUERY_TAG
+{
+ IMG_HANDLE hDevice;
+ IMG_UINT32 ui32NumFormats;
+ PVRSRV_SURFACE_FORMAT * psFormat;
+ /* Output pointer pui32Supported is also an implied input */
+ IMG_UINT32 * pui32Supported;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCFORMATQUERY;
+
+
+/* Bridge out structure for DCFormatQuery */
+typedef struct PVRSRV_BRIDGE_OUT_DCFORMATQUERY_TAG
+{
+ IMG_UINT32 * pui32Supported;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCFORMATQUERY;
+
+/*******************************************
+ DCDimQuery
+ *******************************************/
+
+/* Bridge in structure for DCDimQuery */
+typedef struct PVRSRV_BRIDGE_IN_DCDIMQUERY_TAG
+{
+ IMG_HANDLE hDevice;
+ IMG_UINT32 ui32NumDims;
+ PVRSRV_SURFACE_DIMS * psDim;
+ /* Output pointer pui32Supported is also an implied input */
+ IMG_UINT32 * pui32Supported;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCDIMQUERY;
+
+
+/* Bridge out structure for DCDimQuery */
+typedef struct PVRSRV_BRIDGE_OUT_DCDIMQUERY_TAG
+{
+ IMG_UINT32 * pui32Supported;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCDIMQUERY;
+
+/*******************************************
+ DCSetBlank
+ *******************************************/
+
+/* Bridge in structure for DCSetBlank */
+typedef struct PVRSRV_BRIDGE_IN_DCSETBLANK_TAG
+{
+ IMG_HANDLE hDevice;
+ IMG_BOOL bEnabled;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCSETBLANK;
+
+
+/* Bridge out structure for DCSetBlank */
+typedef struct PVRSRV_BRIDGE_OUT_DCSETBLANK_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCSETBLANK;
+
+/*******************************************
+ DCSetVSyncReporting
+ *******************************************/
+
+/* Bridge in structure for DCSetVSyncReporting */
+typedef struct PVRSRV_BRIDGE_IN_DCSETVSYNCREPORTING_TAG
+{
+ IMG_HANDLE hDevice;
+ IMG_BOOL bEnabled;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCSETVSYNCREPORTING;
+
+
+/* Bridge out structure for DCSetVSyncReporting */
+typedef struct PVRSRV_BRIDGE_OUT_DCSETVSYNCREPORTING_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCSETVSYNCREPORTING;
+
+/*******************************************
+ DCLastVSyncQuery
+ *******************************************/
+
+/* Bridge in structure for DCLastVSyncQuery */
+typedef struct PVRSRV_BRIDGE_IN_DCLASTVSYNCQUERY_TAG
+{
+ IMG_HANDLE hDevice;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCLASTVSYNCQUERY;
+
+
+/* Bridge out structure for DCLastVSyncQuery */
+typedef struct PVRSRV_BRIDGE_OUT_DCLASTVSYNCQUERY_TAG
+{
+ IMG_INT64 i64Timestamp;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCLASTVSYNCQUERY;
+
+/*******************************************
+ DCSystemBufferAcquire
+ *******************************************/
+
+/* Bridge in structure for DCSystemBufferAcquire */
+typedef struct PVRSRV_BRIDGE_IN_DCSYSTEMBUFFERACQUIRE_TAG
+{
+ IMG_HANDLE hDevice;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCSYSTEMBUFFERACQUIRE;
+
+
+/* Bridge out structure for DCSystemBufferAcquire */
+typedef struct PVRSRV_BRIDGE_OUT_DCSYSTEMBUFFERACQUIRE_TAG
+{
+ IMG_UINT32 ui32Stride;
+ IMG_HANDLE hBuffer;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCSYSTEMBUFFERACQUIRE;
+
+/*******************************************
+ DCSystemBufferRelease
+ *******************************************/
+
+/* Bridge in structure for DCSystemBufferRelease */
+typedef struct PVRSRV_BRIDGE_IN_DCSYSTEMBUFFERRELEASE_TAG
+{
+ IMG_HANDLE hBuffer;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCSYSTEMBUFFERRELEASE;
+
+
+/* Bridge out structure for DCSystemBufferRelease */
+typedef struct PVRSRV_BRIDGE_OUT_DCSYSTEMBUFFERRELEASE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCSYSTEMBUFFERRELEASE;
+
+/*******************************************
+ DCDisplayContextCreate
+ *******************************************/
+
+/* Bridge in structure for DCDisplayContextCreate */
+typedef struct PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCREATE_TAG
+{
+ IMG_HANDLE hDevice;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCREATE;
+
+
+/* Bridge out structure for DCDisplayContextCreate */
+typedef struct PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCREATE_TAG
+{
+ IMG_HANDLE hDisplayContext;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCREATE;
+
+/*******************************************
+ DCDisplayContextConfigureCheck
+ *******************************************/
+
+/* Bridge in structure for DCDisplayContextConfigureCheck */
+typedef struct PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCONFIGURECHECK_TAG
+{
+ IMG_HANDLE hDisplayContext;
+ IMG_UINT32 ui32PipeCount;
+ PVRSRV_SURFACE_CONFIG_INFO * psSurfInfo;
+ IMG_HANDLE * phBuffers;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCONFIGURECHECK;
+
+
+/* Bridge out structure for DCDisplayContextConfigureCheck */
+typedef struct PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCONFIGURECHECK_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCONFIGURECHECK;
+
+/*******************************************
+ DCDisplayContextConfigure
+ *******************************************/
+
+/* Bridge in structure for DCDisplayContextConfigure */
+typedef struct PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCONFIGURE_TAG
+{
+ IMG_HANDLE hDisplayContext;
+ IMG_UINT32 ui32PipeCount;
+ PVRSRV_SURFACE_CONFIG_INFO * psSurfInfo;
+ IMG_HANDLE * phBuffers;
+ IMG_UINT32 ui32SyncCount;
+ IMG_HANDLE * phSync;
+ IMG_BOOL * pbUpdate;
+ IMG_UINT32 ui32DisplayPeriod;
+ IMG_UINT32 ui32MaxDepth;
+ IMG_INT32 i32AcquireFd;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCONFIGURE;
+
+
+/* Bridge out structure for DCDisplayContextConfigure */
+typedef struct PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCONFIGURE_TAG
+{
+ IMG_INT32 i32ReleaseFd;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCONFIGURE;
+
+/*******************************************
+ DCDisplayContextDestroy
+ *******************************************/
+
+/* Bridge in structure for DCDisplayContextDestroy */
+typedef struct PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTDESTROY_TAG
+{
+ IMG_HANDLE hDisplayContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTDESTROY;
+
+
+/* Bridge out structure for DCDisplayContextDestroy */
+typedef struct PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTDESTROY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTDESTROY;
+
+/*******************************************
+ DCBufferAlloc
+ *******************************************/
+
+/* Bridge in structure for DCBufferAlloc */
+typedef struct PVRSRV_BRIDGE_IN_DCBUFFERALLOC_TAG
+{
+ IMG_HANDLE hDisplayContext;
+ DC_BUFFER_CREATE_INFO sSurfInfo;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCBUFFERALLOC;
+
+
+/* Bridge out structure for DCBufferAlloc */
+typedef struct PVRSRV_BRIDGE_OUT_DCBUFFERALLOC_TAG
+{
+ IMG_UINT32 ui32Stride;
+ IMG_HANDLE hBuffer;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCBUFFERALLOC;
+
+/*******************************************
+ DCBufferImport
+ *******************************************/
+
+/* Bridge in structure for DCBufferImport */
+typedef struct PVRSRV_BRIDGE_IN_DCBUFFERIMPORT_TAG
+{
+ IMG_HANDLE hDisplayContext;
+ IMG_UINT32 ui32NumPlanes;
+ IMG_HANDLE * phImport;
+ DC_BUFFER_IMPORT_INFO sSurfAttrib;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCBUFFERIMPORT;
+
+
+/* Bridge out structure for DCBufferImport */
+typedef struct PVRSRV_BRIDGE_OUT_DCBUFFERIMPORT_TAG
+{
+ IMG_HANDLE hBuffer;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCBUFFERIMPORT;
+
+/*******************************************
+ DCBufferFree
+ *******************************************/
+
+/* Bridge in structure for DCBufferFree */
+typedef struct PVRSRV_BRIDGE_IN_DCBUFFERFREE_TAG
+{
+ IMG_HANDLE hBuffer;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCBUFFERFREE;
+
+
+/* Bridge out structure for DCBufferFree */
+typedef struct PVRSRV_BRIDGE_OUT_DCBUFFERFREE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCBUFFERFREE;
+
+/*******************************************
+ DCBufferUnimport
+ *******************************************/
+
+/* Bridge in structure for DCBufferUnimport */
+typedef struct PVRSRV_BRIDGE_IN_DCBUFFERUNIMPORT_TAG
+{
+ IMG_HANDLE hBuffer;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCBUFFERUNIMPORT;
+
+
+/* Bridge out structure for DCBufferUnimport */
+typedef struct PVRSRV_BRIDGE_OUT_DCBUFFERUNIMPORT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCBUFFERUNIMPORT;
+
+/*******************************************
+ DCBufferPin
+ *******************************************/
+
+/* Bridge in structure for DCBufferPin */
+typedef struct PVRSRV_BRIDGE_IN_DCBUFFERPIN_TAG
+{
+ IMG_HANDLE hBuffer;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCBUFFERPIN;
+
+
+/* Bridge out structure for DCBufferPin */
+typedef struct PVRSRV_BRIDGE_OUT_DCBUFFERPIN_TAG
+{
+ IMG_HANDLE hPinHandle;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCBUFFERPIN;
+
+/*******************************************
+ DCBufferUnpin
+ *******************************************/
+
+/* Bridge in structure for DCBufferUnpin */
+typedef struct PVRSRV_BRIDGE_IN_DCBUFFERUNPIN_TAG
+{
+ IMG_HANDLE hPinHandle;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCBUFFERUNPIN;
+
+
+/* Bridge out structure for DCBufferUnpin */
+typedef struct PVRSRV_BRIDGE_OUT_DCBUFFERUNPIN_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCBUFFERUNPIN;
+
+/*******************************************
+ DCBufferAcquire
+ *******************************************/
+
+/* Bridge in structure for DCBufferAcquire */
+typedef struct PVRSRV_BRIDGE_IN_DCBUFFERACQUIRE_TAG
+{
+ IMG_HANDLE hBuffer;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCBUFFERACQUIRE;
+
+
+/* Bridge out structure for DCBufferAcquire */
+typedef struct PVRSRV_BRIDGE_OUT_DCBUFFERACQUIRE_TAG
+{
+ IMG_HANDLE hExtMem;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCBUFFERACQUIRE;
+
+/*******************************************
+ DCBufferRelease
+ *******************************************/
+
+/* Bridge in structure for DCBufferRelease */
+typedef struct PVRSRV_BRIDGE_IN_DCBUFFERRELEASE_TAG
+{
+ IMG_HANDLE hExtMem;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DCBUFFERRELEASE;
+
+
+/* Bridge out structure for DCBufferRelease */
+typedef struct PVRSRV_BRIDGE_OUT_DCBUFFERRELEASE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DCBUFFERRELEASE;
+
+#endif /* COMMON_DC_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/dc_bridge/server_dc_bridge.c b/drivers/gpu/rogue/generated/dc_bridge/server_dc_bridge.c
new file mode 100644
index 000000000000..5e3de0a95fa3
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dc_bridge/server_dc_bridge.c
@@ -0,0 +1,2164 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for dc
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for dc
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "dc_server.h"
+
+
+#include "common_dc_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+DCDeviceReleaseResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DCSystemBufferReleaseResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DCDisplayContextDestroyResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DCBufferFreeResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DCBufferUnimportResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DCBufferUnpinResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DCBufferReleaseResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeDCDevicesQueryCount(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCDEVICESQUERYCOUNT *psDCDevicesQueryCountIN,
+ PVRSRV_BRIDGE_OUT_DCDEVICESQUERYCOUNT *psDCDevicesQueryCountOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCDEVICESQUERYCOUNT);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(psDCDevicesQueryCountIN);
+
+
+
+
+ psDCDevicesQueryCountOUT->eError =
+ DCDevicesQueryCount(
+ &psDCDevicesQueryCountOUT->ui32DeviceCount);
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCDevicesEnumerate(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCDEVICESENUMERATE *psDCDevicesEnumerateIN,
+ PVRSRV_BRIDGE_OUT_DCDEVICESENUMERATE *psDCDevicesEnumerateOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_UINT32 *pui32DeviceIndexInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCDEVICESENUMERATE);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+ psDCDevicesEnumerateOUT->pui32DeviceIndex = psDCDevicesEnumerateIN->pui32DeviceIndex;
+
+
+ if (psDCDevicesEnumerateIN->ui32DeviceArraySize != 0)
+ {
+ pui32DeviceIndexInt = OSAllocMem(psDCDevicesEnumerateIN->ui32DeviceArraySize * sizeof(IMG_UINT32));
+ if (!pui32DeviceIndexInt)
+ {
+ psDCDevicesEnumerateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDevicesEnumerate_exit;
+ }
+ }
+
+
+ psDCDevicesEnumerateOUT->eError =
+ DCDevicesEnumerate(
+ psDCDevicesEnumerateIN->ui32DeviceArraySize,
+ &psDCDevicesEnumerateOUT->ui32DeviceCount,
+ pui32DeviceIndexInt);
+
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psDCDevicesEnumerateOUT->pui32DeviceIndex, (psDCDevicesEnumerateOUT->ui32DeviceCount * sizeof(IMG_UINT32)))
+ || (OSCopyToUser(NULL, psDCDevicesEnumerateOUT->pui32DeviceIndex, pui32DeviceIndexInt,
+ (psDCDevicesEnumerateOUT->ui32DeviceCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psDCDevicesEnumerateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCDevicesEnumerate_exit;
+ }
+
+
+DCDevicesEnumerate_exit:
+ if (pui32DeviceIndexInt)
+ OSFreeMem(pui32DeviceIndexInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCDeviceAcquire(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCDEVICEACQUIRE *psDCDeviceAcquireIN,
+ PVRSRV_BRIDGE_OUT_DCDEVICEACQUIRE *psDCDeviceAcquireOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCDEVICEACQUIRE);
+
+
+
+
+
+ psDCDeviceAcquireOUT->eError =
+ DCDeviceAcquire(
+ psDCDeviceAcquireIN->ui32DeviceIndex,
+ &psDeviceInt);
+ /* Exit early if bridged call fails */
+ if(psDCDeviceAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCDeviceAcquire_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hDeviceInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DC_DEVICE,
+ psDeviceInt,
+ (RESMAN_FREE_FN)&DCDeviceRelease);
+ if (hDeviceInt2 == IMG_NULL)
+ {
+ psDCDeviceAcquireOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DCDeviceAcquire_exit;
+ }
+ psDCDeviceAcquireOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDCDeviceAcquireOUT->hDevice,
+ (IMG_HANDLE) hDeviceInt2,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDCDeviceAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCDeviceAcquire_exit;
+ }
+
+
+DCDeviceAcquire_exit:
+ if (psDCDeviceAcquireOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hDeviceInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hDeviceInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psDeviceInt)
+ {
+ DCDeviceRelease(psDeviceInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCDeviceRelease(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCDEVICERELEASE *psDCDeviceReleaseIN,
+ PVRSRV_BRIDGE_OUT_DCDEVICERELEASE *psDCDeviceReleaseOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCDEVICERELEASE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCDeviceReleaseOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCDeviceReleaseIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCDeviceReleaseOUT->eError != PVRSRV_OK)
+ {
+ goto DCDeviceRelease_exit;
+ }
+
+ }
+
+ psDCDeviceReleaseOUT->eError = DCDeviceReleaseResManProxy(hDeviceInt2);
+ /* Exit early if bridged call fails */
+ if(psDCDeviceReleaseOUT->eError != PVRSRV_OK)
+ {
+ goto DCDeviceRelease_exit;
+ }
+
+ psDCDeviceReleaseOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDCDeviceReleaseIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+
+
+DCDeviceRelease_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCGetInfo(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCGETINFO *psDCGetInfoIN,
+ PVRSRV_BRIDGE_OUT_DCGETINFO *psDCGetInfoOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCGETINFO);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCGetInfoOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCGetInfoIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCGetInfoOUT->eError != PVRSRV_OK)
+ {
+ goto DCGetInfo_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCGetInfoOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCGetInfoOUT->eError != PVRSRV_OK)
+ {
+ goto DCGetInfo_exit;
+ }
+ }
+
+ psDCGetInfoOUT->eError =
+ DCGetInfo(
+ psDeviceInt,
+ &psDCGetInfoOUT->sDisplayInfo);
+
+
+
+DCGetInfo_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCPanelQueryCount(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCPANELQUERYCOUNT *psDCPanelQueryCountIN,
+ PVRSRV_BRIDGE_OUT_DCPANELQUERYCOUNT *psDCPanelQueryCountOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCPANELQUERYCOUNT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCPanelQueryCountOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCPanelQueryCountIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCPanelQueryCountOUT->eError != PVRSRV_OK)
+ {
+ goto DCPanelQueryCount_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCPanelQueryCountOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCPanelQueryCountOUT->eError != PVRSRV_OK)
+ {
+ goto DCPanelQueryCount_exit;
+ }
+ }
+
+ psDCPanelQueryCountOUT->eError =
+ DCPanelQueryCount(
+ psDeviceInt,
+ &psDCPanelQueryCountOUT->ui32NumPanels);
+
+
+
+DCPanelQueryCount_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCPanelQuery(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCPANELQUERY *psDCPanelQueryIN,
+ PVRSRV_BRIDGE_OUT_DCPANELQUERY *psDCPanelQueryOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+ PVRSRV_PANEL_INFO *psPanelInfoInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCPANELQUERY);
+
+
+ psDCPanelQueryOUT->psPanelInfo = psDCPanelQueryIN->psPanelInfo;
+
+
+ if (psDCPanelQueryIN->ui32PanelsArraySize != 0)
+ {
+ psPanelInfoInt = OSAllocMem(psDCPanelQueryIN->ui32PanelsArraySize * sizeof(PVRSRV_PANEL_INFO));
+ if (!psPanelInfoInt)
+ {
+ psDCPanelQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCPanelQuery_exit;
+ }
+ }
+
+
+ {
+ /* Look up the address from the handle */
+ psDCPanelQueryOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCPanelQueryIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCPanelQueryOUT->eError != PVRSRV_OK)
+ {
+ goto DCPanelQuery_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCPanelQueryOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCPanelQueryOUT->eError != PVRSRV_OK)
+ {
+ goto DCPanelQuery_exit;
+ }
+ }
+
+ psDCPanelQueryOUT->eError =
+ DCPanelQuery(
+ psDeviceInt,
+ psDCPanelQueryIN->ui32PanelsArraySize,
+ &psDCPanelQueryOUT->ui32NumPanels,
+ psPanelInfoInt);
+
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psDCPanelQueryOUT->psPanelInfo, (psDCPanelQueryOUT->ui32NumPanels * sizeof(PVRSRV_PANEL_INFO)))
+ || (OSCopyToUser(NULL, psDCPanelQueryOUT->psPanelInfo, psPanelInfoInt,
+ (psDCPanelQueryOUT->ui32NumPanels * sizeof(PVRSRV_PANEL_INFO))) != PVRSRV_OK) )
+ {
+ psDCPanelQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCPanelQuery_exit;
+ }
+
+
+DCPanelQuery_exit:
+ if (psPanelInfoInt)
+ OSFreeMem(psPanelInfoInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCFormatQuery(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCFORMATQUERY *psDCFormatQueryIN,
+ PVRSRV_BRIDGE_OUT_DCFORMATQUERY *psDCFormatQueryOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+ PVRSRV_SURFACE_FORMAT *psFormatInt = IMG_NULL;
+ IMG_UINT32 *pui32SupportedInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCFORMATQUERY);
+
+
+ psDCFormatQueryOUT->pui32Supported = psDCFormatQueryIN->pui32Supported;
+
+
+ if (psDCFormatQueryIN->ui32NumFormats != 0)
+ {
+ psFormatInt = OSAllocMem(psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT));
+ if (!psFormatInt)
+ {
+ psDCFormatQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCFormatQuery_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDCFormatQueryIN->psFormat, psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT))
+ || (OSCopyFromUser(NULL, psFormatInt, psDCFormatQueryIN->psFormat,
+ psDCFormatQueryIN->ui32NumFormats * sizeof(PVRSRV_SURFACE_FORMAT)) != PVRSRV_OK) )
+ {
+ psDCFormatQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCFormatQuery_exit;
+ }
+ if (psDCFormatQueryIN->ui32NumFormats != 0)
+ {
+ pui32SupportedInt = OSAllocMem(psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32));
+ if (!pui32SupportedInt)
+ {
+ psDCFormatQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCFormatQuery_exit;
+ }
+ }
+
+
+ {
+ /* Look up the address from the handle */
+ psDCFormatQueryOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCFormatQueryIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCFormatQueryOUT->eError != PVRSRV_OK)
+ {
+ goto DCFormatQuery_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCFormatQueryOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCFormatQueryOUT->eError != PVRSRV_OK)
+ {
+ goto DCFormatQuery_exit;
+ }
+ }
+
+ psDCFormatQueryOUT->eError =
+ DCFormatQuery(
+ psDeviceInt,
+ psDCFormatQueryIN->ui32NumFormats,
+ psFormatInt,
+ pui32SupportedInt);
+
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psDCFormatQueryOUT->pui32Supported, (psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32)))
+ || (OSCopyToUser(NULL, psDCFormatQueryOUT->pui32Supported, pui32SupportedInt,
+ (psDCFormatQueryIN->ui32NumFormats * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psDCFormatQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCFormatQuery_exit;
+ }
+
+
+DCFormatQuery_exit:
+ if (psFormatInt)
+ OSFreeMem(psFormatInt);
+ if (pui32SupportedInt)
+ OSFreeMem(pui32SupportedInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCDimQuery(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCDIMQUERY *psDCDimQueryIN,
+ PVRSRV_BRIDGE_OUT_DCDIMQUERY *psDCDimQueryOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+ PVRSRV_SURFACE_DIMS *psDimInt = IMG_NULL;
+ IMG_UINT32 *pui32SupportedInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCDIMQUERY);
+
+
+ psDCDimQueryOUT->pui32Supported = psDCDimQueryIN->pui32Supported;
+
+
+ if (psDCDimQueryIN->ui32NumDims != 0)
+ {
+ psDimInt = OSAllocMem(psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS));
+ if (!psDimInt)
+ {
+ psDCDimQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDimQuery_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDCDimQueryIN->psDim, psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS))
+ || (OSCopyFromUser(NULL, psDimInt, psDCDimQueryIN->psDim,
+ psDCDimQueryIN->ui32NumDims * sizeof(PVRSRV_SURFACE_DIMS)) != PVRSRV_OK) )
+ {
+ psDCDimQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCDimQuery_exit;
+ }
+ if (psDCDimQueryIN->ui32NumDims != 0)
+ {
+ pui32SupportedInt = OSAllocMem(psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32));
+ if (!pui32SupportedInt)
+ {
+ psDCDimQueryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDimQuery_exit;
+ }
+ }
+
+
+ {
+ /* Look up the address from the handle */
+ psDCDimQueryOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCDimQueryIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCDimQueryOUT->eError != PVRSRV_OK)
+ {
+ goto DCDimQuery_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCDimQueryOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCDimQueryOUT->eError != PVRSRV_OK)
+ {
+ goto DCDimQuery_exit;
+ }
+ }
+
+ psDCDimQueryOUT->eError =
+ DCDimQuery(
+ psDeviceInt,
+ psDCDimQueryIN->ui32NumDims,
+ psDimInt,
+ pui32SupportedInt);
+
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psDCDimQueryOUT->pui32Supported, (psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32)))
+ || (OSCopyToUser(NULL, psDCDimQueryOUT->pui32Supported, pui32SupportedInt,
+ (psDCDimQueryIN->ui32NumDims * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psDCDimQueryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCDimQuery_exit;
+ }
+
+
+DCDimQuery_exit:
+ if (psDimInt)
+ OSFreeMem(psDimInt);
+ if (pui32SupportedInt)
+ OSFreeMem(pui32SupportedInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCSetBlank(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCSETBLANK *psDCSetBlankIN,
+ PVRSRV_BRIDGE_OUT_DCSETBLANK *psDCSetBlankOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCSETBLANK);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCSetBlankOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCSetBlankIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCSetBlankOUT->eError != PVRSRV_OK)
+ {
+ goto DCSetBlank_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCSetBlankOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCSetBlankOUT->eError != PVRSRV_OK)
+ {
+ goto DCSetBlank_exit;
+ }
+ }
+
+ psDCSetBlankOUT->eError =
+ DCSetBlank(
+ psDeviceInt,
+ psDCSetBlankIN->bEnabled);
+
+
+
+DCSetBlank_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCSetVSyncReporting(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCSETVSYNCREPORTING *psDCSetVSyncReportingIN,
+ PVRSRV_BRIDGE_OUT_DCSETVSYNCREPORTING *psDCSetVSyncReportingOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCSETVSYNCREPORTING);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCSetVSyncReportingOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCSetVSyncReportingIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCSetVSyncReportingOUT->eError != PVRSRV_OK)
+ {
+ goto DCSetVSyncReporting_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCSetVSyncReportingOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCSetVSyncReportingOUT->eError != PVRSRV_OK)
+ {
+ goto DCSetVSyncReporting_exit;
+ }
+ }
+
+ psDCSetVSyncReportingOUT->eError =
+ DCSetVSyncReporting(
+ psDeviceInt,
+ psDCSetVSyncReportingIN->bEnabled);
+
+
+
+DCSetVSyncReporting_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCLastVSyncQuery(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCLASTVSYNCQUERY *psDCLastVSyncQueryIN,
+ PVRSRV_BRIDGE_OUT_DCLASTVSYNCQUERY *psDCLastVSyncQueryOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCLASTVSYNCQUERY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCLastVSyncQueryOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCLastVSyncQueryIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCLastVSyncQueryOUT->eError != PVRSRV_OK)
+ {
+ goto DCLastVSyncQuery_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCLastVSyncQueryOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCLastVSyncQueryOUT->eError != PVRSRV_OK)
+ {
+ goto DCLastVSyncQuery_exit;
+ }
+ }
+
+ psDCLastVSyncQueryOUT->eError =
+ DCLastVSyncQuery(
+ psDeviceInt,
+ &psDCLastVSyncQueryOUT->i64Timestamp);
+
+
+
+DCLastVSyncQuery_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCSystemBufferAcquire(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCSYSTEMBUFFERACQUIRE *psDCSystemBufferAcquireIN,
+ PVRSRV_BRIDGE_OUT_DCSYSTEMBUFFERACQUIRE *psDCSystemBufferAcquireOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+ DC_BUFFER * psBufferInt = IMG_NULL;
+ IMG_HANDLE hBufferInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCSYSTEMBUFFERACQUIRE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCSystemBufferAcquireOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCSystemBufferAcquireIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCSystemBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCSystemBufferAcquire_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCSystemBufferAcquireOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCSystemBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCSystemBufferAcquire_exit;
+ }
+ }
+
+ psDCSystemBufferAcquireOUT->eError =
+ DCSystemBufferAcquire(
+ psDeviceInt,
+ &psDCSystemBufferAcquireOUT->ui32Stride,
+ &psBufferInt);
+ /* Exit early if bridged call fails */
+ if(psDCSystemBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCSystemBufferAcquire_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hBufferInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DC_BUFFER,
+ psBufferInt,
+ (RESMAN_FREE_FN)&DCSystemBufferRelease);
+ if (hBufferInt2 == IMG_NULL)
+ {
+ psDCSystemBufferAcquireOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DCSystemBufferAcquire_exit;
+ }
+ psDCSystemBufferAcquireOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDCSystemBufferAcquireOUT->hBuffer,
+ (IMG_HANDLE) hBufferInt2,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED
+ );
+ if (psDCSystemBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCSystemBufferAcquire_exit;
+ }
+
+
+DCSystemBufferAcquire_exit:
+ if (psDCSystemBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hBufferInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hBufferInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psBufferInt)
+ {
+ DCSystemBufferRelease(psBufferInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCSystemBufferRelease(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCSYSTEMBUFFERRELEASE *psDCSystemBufferReleaseIN,
+ PVRSRV_BRIDGE_OUT_DCSYSTEMBUFFERRELEASE *psDCSystemBufferReleaseOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hBufferInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCSYSTEMBUFFERRELEASE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCSystemBufferReleaseOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hBufferInt2,
+ psDCSystemBufferReleaseIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+ if(psDCSystemBufferReleaseOUT->eError != PVRSRV_OK)
+ {
+ goto DCSystemBufferRelease_exit;
+ }
+
+ }
+
+ psDCSystemBufferReleaseOUT->eError = DCSystemBufferReleaseResManProxy(hBufferInt2);
+ /* Exit early if bridged call fails */
+ if(psDCSystemBufferReleaseOUT->eError != PVRSRV_OK)
+ {
+ goto DCSystemBufferRelease_exit;
+ }
+
+ psDCSystemBufferReleaseOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDCSystemBufferReleaseIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+
+
+DCSystemBufferRelease_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCDisplayContextCreate(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCREATE *psDCDisplayContextCreateIN,
+ PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCREATE *psDCDisplayContextCreateOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DEVICE * psDeviceInt = IMG_NULL;
+ IMG_HANDLE hDeviceInt2 = IMG_NULL;
+ DC_DISPLAY_CONTEXT * psDisplayContextInt = IMG_NULL;
+ IMG_HANDLE hDisplayContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTCREATE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCDisplayContextCreateOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceInt2,
+ psDCDisplayContextCreateIN->hDevice,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE);
+ if(psDCDisplayContextCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextCreate_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCDisplayContextCreateOUT->eError = ResManFindPrivateDataByPtr(hDeviceInt2, (IMG_VOID **) &psDeviceInt);
+
+ if(psDCDisplayContextCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextCreate_exit;
+ }
+ }
+
+ psDCDisplayContextCreateOUT->eError =
+ DCDisplayContextCreate(
+ psDeviceInt,
+ &psDisplayContextInt);
+ /* Exit early if bridged call fails */
+ if(psDCDisplayContextCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextCreate_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hDisplayContextInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DC_DISPLAY_CONTEXT,
+ psDisplayContextInt,
+ (RESMAN_FREE_FN)&DCDisplayContextDestroy);
+ if (hDisplayContextInt2 == IMG_NULL)
+ {
+ psDCDisplayContextCreateOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DCDisplayContextCreate_exit;
+ }
+ psDCDisplayContextCreateOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDCDisplayContextCreateOUT->hDisplayContext,
+ (IMG_HANDLE) hDisplayContextInt2,
+ PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDCDisplayContextCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextCreate_exit;
+ }
+
+
+DCDisplayContextCreate_exit:
+ if (psDCDisplayContextCreateOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hDisplayContextInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hDisplayContextInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psDisplayContextInt)
+ {
+ DCDisplayContextDestroy(psDisplayContextInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCDisplayContextConfigureCheck(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCONFIGURECHECK *psDCDisplayContextConfigureCheckIN,
+ PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCONFIGURECHECK *psDCDisplayContextConfigureCheckOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DISPLAY_CONTEXT * psDisplayContextInt = IMG_NULL;
+ IMG_HANDLE hDisplayContextInt2 = IMG_NULL;
+ PVRSRV_SURFACE_CONFIG_INFO *psSurfInfoInt = IMG_NULL;
+ DC_BUFFER * *psBuffersInt = IMG_NULL;
+ IMG_HANDLE *hBuffersInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTCONFIGURECHECK);
+
+
+
+
+ if (psDCDisplayContextConfigureCheckIN->ui32PipeCount != 0)
+ {
+ psSurfInfoInt = OSAllocMem(psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO));
+ if (!psSurfInfoInt)
+ {
+ psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDisplayContextConfigureCheck_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDCDisplayContextConfigureCheckIN->psSurfInfo, psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO))
+ || (OSCopyFromUser(NULL, psSurfInfoInt, psDCDisplayContextConfigureCheckIN->psSurfInfo,
+ psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO)) != PVRSRV_OK) )
+ {
+ psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCDisplayContextConfigureCheck_exit;
+ }
+ if (psDCDisplayContextConfigureCheckIN->ui32PipeCount != 0)
+ {
+ psBuffersInt = OSAllocMem(psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(DC_BUFFER *));
+ if (!psBuffersInt)
+ {
+ psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDisplayContextConfigureCheck_exit;
+ }
+ hBuffersInt2 = OSAllocMem(psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE));
+ if (!hBuffersInt2)
+ {
+ psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDisplayContextConfigureCheck_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDCDisplayContextConfigureCheckIN->phBuffers, psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hBuffersInt2, psDCDisplayContextConfigureCheckIN->phBuffers,
+ psDCDisplayContextConfigureCheckIN->ui32PipeCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psDCDisplayContextConfigureCheckOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCDisplayContextConfigureCheck_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psDCDisplayContextConfigureCheckOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDisplayContextInt2,
+ psDCDisplayContextConfigureCheckIN->hDisplayContext,
+ PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+ if(psDCDisplayContextConfigureCheckOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigureCheck_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCDisplayContextConfigureCheckOUT->eError = ResManFindPrivateDataByPtr(hDisplayContextInt2, (IMG_VOID **) &psDisplayContextInt);
+
+ if(psDCDisplayContextConfigureCheckOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigureCheck_exit;
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psDCDisplayContextConfigureCheckIN->ui32PipeCount;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psDCDisplayContextConfigureCheckOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hBuffersInt2[i],
+ hBuffersInt2[i],
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+ if(psDCDisplayContextConfigureCheckOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigureCheck_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCDisplayContextConfigureCheckOUT->eError = ResManFindPrivateDataByPtr(hBuffersInt2[i], (IMG_VOID **) &psBuffersInt[i]);
+
+ if(psDCDisplayContextConfigureCheckOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigureCheck_exit;
+ }
+ }
+ }
+ }
+
+ psDCDisplayContextConfigureCheckOUT->eError =
+ DCDisplayContextConfigureCheck(
+ psDisplayContextInt,
+ psDCDisplayContextConfigureCheckIN->ui32PipeCount,
+ psSurfInfoInt,
+ psBuffersInt);
+
+
+
+DCDisplayContextConfigureCheck_exit:
+ if (psSurfInfoInt)
+ OSFreeMem(psSurfInfoInt);
+ if (psBuffersInt)
+ OSFreeMem(psBuffersInt);
+ if (hBuffersInt2)
+ OSFreeMem(hBuffersInt2);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCDisplayContextConfigure(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTCONFIGURE *psDCDisplayContextConfigureIN,
+ PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTCONFIGURE *psDCDisplayContextConfigureOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DISPLAY_CONTEXT * psDisplayContextInt = IMG_NULL;
+ IMG_HANDLE hDisplayContextInt2 = IMG_NULL;
+ PVRSRV_SURFACE_CONFIG_INFO *psSurfInfoInt = IMG_NULL;
+ DC_BUFFER * *psBuffersInt = IMG_NULL;
+ IMG_HANDLE *hBuffersInt2 = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * *psSyncInt = IMG_NULL;
+ IMG_HANDLE *hSyncInt2 = IMG_NULL;
+ IMG_BOOL *bUpdateInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTCONFIGURE);
+
+
+
+
+ if (psDCDisplayContextConfigureIN->ui32PipeCount != 0)
+ {
+ psSurfInfoInt = OSAllocMem(psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO));
+ if (!psSurfInfoInt)
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDCDisplayContextConfigureIN->psSurfInfo, psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO))
+ || (OSCopyFromUser(NULL, psSurfInfoInt, psDCDisplayContextConfigureIN->psSurfInfo,
+ psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(PVRSRV_SURFACE_CONFIG_INFO)) != PVRSRV_OK) )
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+ if (psDCDisplayContextConfigureIN->ui32PipeCount != 0)
+ {
+ psBuffersInt = OSAllocMem(psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(DC_BUFFER *));
+ if (!psBuffersInt)
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+ hBuffersInt2 = OSAllocMem(psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE));
+ if (!hBuffersInt2)
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDCDisplayContextConfigureIN->phBuffers, psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hBuffersInt2, psDCDisplayContextConfigureIN->phBuffers,
+ psDCDisplayContextConfigureIN->ui32PipeCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+ if (psDCDisplayContextConfigureIN->ui32SyncCount != 0)
+ {
+ psSyncInt = OSAllocMem(psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psSyncInt)
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+ hSyncInt2 = OSAllocMem(psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE));
+ if (!hSyncInt2)
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDCDisplayContextConfigureIN->phSync, psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hSyncInt2, psDCDisplayContextConfigureIN->phSync,
+ psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+ if (psDCDisplayContextConfigureIN->ui32SyncCount != 0)
+ {
+ bUpdateInt = OSAllocMem(psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL));
+ if (!bUpdateInt)
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDCDisplayContextConfigureIN->pbUpdate, psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL))
+ || (OSCopyFromUser(NULL, bUpdateInt, psDCDisplayContextConfigureIN->pbUpdate,
+ psDCDisplayContextConfigureIN->ui32SyncCount * sizeof(IMG_BOOL)) != PVRSRV_OK) )
+ {
+ psDCDisplayContextConfigureOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCDisplayContextConfigure_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psDCDisplayContextConfigureOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDisplayContextInt2,
+ psDCDisplayContextConfigureIN->hDisplayContext,
+ PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+ if(psDCDisplayContextConfigureOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigure_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCDisplayContextConfigureOUT->eError = ResManFindPrivateDataByPtr(hDisplayContextInt2, (IMG_VOID **) &psDisplayContextInt);
+
+ if(psDCDisplayContextConfigureOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigure_exit;
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psDCDisplayContextConfigureIN->ui32PipeCount;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psDCDisplayContextConfigureOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hBuffersInt2[i],
+ hBuffersInt2[i],
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+ if(psDCDisplayContextConfigureOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigure_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCDisplayContextConfigureOUT->eError = ResManFindPrivateDataByPtr(hBuffersInt2[i], (IMG_VOID **) &psBuffersInt[i]);
+
+ if(psDCDisplayContextConfigureOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigure_exit;
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psDCDisplayContextConfigureIN->ui32SyncCount;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psDCDisplayContextConfigureOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncInt2[i],
+ hSyncInt2[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psDCDisplayContextConfigureOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigure_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCDisplayContextConfigureOUT->eError = ResManFindPrivateDataByPtr(hSyncInt2[i], (IMG_VOID **) &psSyncInt[i]);
+
+ if(psDCDisplayContextConfigureOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextConfigure_exit;
+ }
+ }
+ }
+ }
+
+ psDCDisplayContextConfigureOUT->eError =
+ DCDisplayContextConfigure(
+ psDisplayContextInt,
+ psDCDisplayContextConfigureIN->ui32PipeCount,
+ psSurfInfoInt,
+ psBuffersInt,
+ psDCDisplayContextConfigureIN->ui32SyncCount,
+ psSyncInt,
+ bUpdateInt,
+ psDCDisplayContextConfigureIN->ui32DisplayPeriod,
+ psDCDisplayContextConfigureIN->ui32MaxDepth,
+ psDCDisplayContextConfigureIN->i32AcquireFd,
+ &psDCDisplayContextConfigureOUT->i32ReleaseFd);
+
+
+
+DCDisplayContextConfigure_exit:
+ if (psSurfInfoInt)
+ OSFreeMem(psSurfInfoInt);
+ if (psBuffersInt)
+ OSFreeMem(psBuffersInt);
+ if (hBuffersInt2)
+ OSFreeMem(hBuffersInt2);
+ if (psSyncInt)
+ OSFreeMem(psSyncInt);
+ if (hSyncInt2)
+ OSFreeMem(hSyncInt2);
+ if (bUpdateInt)
+ OSFreeMem(bUpdateInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCDisplayContextDestroy(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCDISPLAYCONTEXTDESTROY *psDCDisplayContextDestroyIN,
+ PVRSRV_BRIDGE_OUT_DCDISPLAYCONTEXTDESTROY *psDCDisplayContextDestroyOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDisplayContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTDESTROY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCDisplayContextDestroyOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDisplayContextInt2,
+ psDCDisplayContextDestroyIN->hDisplayContext,
+ PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+ if(psDCDisplayContextDestroyOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextDestroy_exit;
+ }
+
+ }
+
+ psDCDisplayContextDestroyOUT->eError = DCDisplayContextDestroyResManProxy(hDisplayContextInt2);
+ /* Exit early if bridged call fails */
+ if(psDCDisplayContextDestroyOUT->eError != PVRSRV_OK)
+ {
+ goto DCDisplayContextDestroy_exit;
+ }
+
+ psDCDisplayContextDestroyOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDCDisplayContextDestroyIN->hDisplayContext,
+ PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+
+
+DCDisplayContextDestroy_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCBufferAlloc(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCBUFFERALLOC *psDCBufferAllocIN,
+ PVRSRV_BRIDGE_OUT_DCBUFFERALLOC *psDCBufferAllocOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DISPLAY_CONTEXT * psDisplayContextInt = IMG_NULL;
+ IMG_HANDLE hDisplayContextInt2 = IMG_NULL;
+ DC_BUFFER * psBufferInt = IMG_NULL;
+ IMG_HANDLE hBufferInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCBUFFERALLOC);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCBufferAllocOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDisplayContextInt2,
+ psDCBufferAllocIN->hDisplayContext,
+ PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+ if(psDCBufferAllocOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferAlloc_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCBufferAllocOUT->eError = ResManFindPrivateDataByPtr(hDisplayContextInt2, (IMG_VOID **) &psDisplayContextInt);
+
+ if(psDCBufferAllocOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferAlloc_exit;
+ }
+ }
+
+ psDCBufferAllocOUT->eError =
+ DCBufferAlloc(
+ psDisplayContextInt,
+ &psDCBufferAllocIN->sSurfInfo,
+ &psDCBufferAllocOUT->ui32Stride,
+ &psBufferInt);
+ /* Exit early if bridged call fails */
+ if(psDCBufferAllocOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferAlloc_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hBufferInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DC_BUFFER,
+ psBufferInt,
+ (RESMAN_FREE_FN)&DCBufferFree);
+ if (hBufferInt2 == IMG_NULL)
+ {
+ psDCBufferAllocOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DCBufferAlloc_exit;
+ }
+ psDCBufferAllocOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDCBufferAllocOUT->hBuffer,
+ (IMG_HANDLE) hBufferInt2,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDCBufferAllocOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferAlloc_exit;
+ }
+
+
+DCBufferAlloc_exit:
+ if (psDCBufferAllocOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hBufferInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hBufferInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psBufferInt)
+ {
+ DCBufferFree(psBufferInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCBufferImport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCBUFFERIMPORT *psDCBufferImportIN,
+ PVRSRV_BRIDGE_OUT_DCBUFFERIMPORT *psDCBufferImportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_DISPLAY_CONTEXT * psDisplayContextInt = IMG_NULL;
+ IMG_HANDLE hDisplayContextInt2 = IMG_NULL;
+ PMR * *psImportInt = IMG_NULL;
+ IMG_HANDLE *hImportInt2 = IMG_NULL;
+ DC_BUFFER * psBufferInt = IMG_NULL;
+ IMG_HANDLE hBufferInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCBUFFERIMPORT);
+
+
+
+
+ if (psDCBufferImportIN->ui32NumPlanes != 0)
+ {
+ psImportInt = OSAllocMem(psDCBufferImportIN->ui32NumPlanes * sizeof(PMR *));
+ if (!psImportInt)
+ {
+ psDCBufferImportOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCBufferImport_exit;
+ }
+ hImportInt2 = OSAllocMem(psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE));
+ if (!hImportInt2)
+ {
+ psDCBufferImportOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DCBufferImport_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDCBufferImportIN->phImport, psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hImportInt2, psDCBufferImportIN->phImport,
+ psDCBufferImportIN->ui32NumPlanes * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psDCBufferImportOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DCBufferImport_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psDCBufferImportOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDisplayContextInt2,
+ psDCBufferImportIN->hDisplayContext,
+ PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT);
+ if(psDCBufferImportOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferImport_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCBufferImportOUT->eError = ResManFindPrivateDataByPtr(hDisplayContextInt2, (IMG_VOID **) &psDisplayContextInt);
+
+ if(psDCBufferImportOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferImport_exit;
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psDCBufferImportIN->ui32NumPlanes;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psDCBufferImportOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hImportInt2[i],
+ hImportInt2[i],
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psDCBufferImportOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferImport_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCBufferImportOUT->eError = ResManFindPrivateDataByPtr(hImportInt2[i], (IMG_VOID **) &psImportInt[i]);
+
+ if(psDCBufferImportOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferImport_exit;
+ }
+ }
+ }
+ }
+
+ psDCBufferImportOUT->eError =
+ DCBufferImport(
+ psDisplayContextInt,
+ psDCBufferImportIN->ui32NumPlanes,
+ psImportInt,
+ &psDCBufferImportIN->sSurfAttrib,
+ &psBufferInt);
+ /* Exit early if bridged call fails */
+ if(psDCBufferImportOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferImport_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hBufferInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DC_BUFFER,
+ psBufferInt,
+ (RESMAN_FREE_FN)&DCBufferFree);
+ if (hBufferInt2 == IMG_NULL)
+ {
+ psDCBufferImportOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DCBufferImport_exit;
+ }
+ psDCBufferImportOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDCBufferImportOUT->hBuffer,
+ (IMG_HANDLE) hBufferInt2,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDCBufferImportOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferImport_exit;
+ }
+
+
+DCBufferImport_exit:
+ if (psDCBufferImportOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hBufferInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hBufferInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psBufferInt)
+ {
+ DCBufferFree(psBufferInt);
+ }
+ }
+
+ if (psImportInt)
+ OSFreeMem(psImportInt);
+ if (hImportInt2)
+ OSFreeMem(hImportInt2);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCBufferFree(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCBUFFERFREE *psDCBufferFreeIN,
+ PVRSRV_BRIDGE_OUT_DCBUFFERFREE *psDCBufferFreeOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hBufferInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCBUFFERFREE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCBufferFreeOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hBufferInt2,
+ psDCBufferFreeIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+ if(psDCBufferFreeOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferFree_exit;
+ }
+
+ }
+
+ psDCBufferFreeOUT->eError = DCBufferFreeResManProxy(hBufferInt2);
+ /* Exit early if bridged call fails */
+ if(psDCBufferFreeOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferFree_exit;
+ }
+
+ psDCBufferFreeOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDCBufferFreeIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+
+
+DCBufferFree_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCBufferUnimport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCBUFFERUNIMPORT *psDCBufferUnimportIN,
+ PVRSRV_BRIDGE_OUT_DCBUFFERUNIMPORT *psDCBufferUnimportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hBufferInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCBUFFERUNIMPORT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCBufferUnimportOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hBufferInt2,
+ psDCBufferUnimportIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+ if(psDCBufferUnimportOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferUnimport_exit;
+ }
+
+ }
+
+ psDCBufferUnimportOUT->eError = DCBufferUnimportResManProxy(hBufferInt2);
+ /* Exit early if bridged call fails */
+ if(psDCBufferUnimportOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferUnimport_exit;
+ }
+
+ psDCBufferUnimportOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDCBufferUnimportIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+
+
+DCBufferUnimport_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCBufferPin(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCBUFFERPIN *psDCBufferPinIN,
+ PVRSRV_BRIDGE_OUT_DCBUFFERPIN *psDCBufferPinOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_BUFFER * psBufferInt = IMG_NULL;
+ IMG_HANDLE hBufferInt2 = IMG_NULL;
+ DC_PIN_HANDLE hPinHandleInt = IMG_NULL;
+ IMG_HANDLE hPinHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCBUFFERPIN);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCBufferPinOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hBufferInt2,
+ psDCBufferPinIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+ if(psDCBufferPinOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferPin_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCBufferPinOUT->eError = ResManFindPrivateDataByPtr(hBufferInt2, (IMG_VOID **) &psBufferInt);
+
+ if(psDCBufferPinOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferPin_exit;
+ }
+ }
+
+ psDCBufferPinOUT->eError =
+ DCBufferPin(
+ psBufferInt,
+ &hPinHandleInt);
+ /* Exit early if bridged call fails */
+ if(psDCBufferPinOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferPin_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hPinHandleInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DC_PIN_HANDLE,
+ hPinHandleInt,
+ (RESMAN_FREE_FN)&DCBufferUnpin);
+ if (hPinHandleInt2 == IMG_NULL)
+ {
+ psDCBufferPinOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DCBufferPin_exit;
+ }
+ psDCBufferPinOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDCBufferPinOUT->hPinHandle,
+ (IMG_HANDLE) hPinHandleInt2,
+ PVRSRV_HANDLE_TYPE_DC_PIN_HANDLE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDCBufferPinOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferPin_exit;
+ }
+
+
+DCBufferPin_exit:
+ if (psDCBufferPinOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPinHandleInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPinHandleInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (hPinHandleInt)
+ {
+ DCBufferUnpin(hPinHandleInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCBufferUnpin(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCBUFFERUNPIN *psDCBufferUnpinIN,
+ PVRSRV_BRIDGE_OUT_DCBUFFERUNPIN *psDCBufferUnpinOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hPinHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCBUFFERUNPIN);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCBufferUnpinOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPinHandleInt2,
+ psDCBufferUnpinIN->hPinHandle,
+ PVRSRV_HANDLE_TYPE_DC_PIN_HANDLE);
+ if(psDCBufferUnpinOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferUnpin_exit;
+ }
+
+ }
+
+ psDCBufferUnpinOUT->eError = DCBufferUnpinResManProxy(hPinHandleInt2);
+ /* Exit early if bridged call fails */
+ if(psDCBufferUnpinOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferUnpin_exit;
+ }
+
+ psDCBufferUnpinOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDCBufferUnpinIN->hPinHandle,
+ PVRSRV_HANDLE_TYPE_DC_PIN_HANDLE);
+
+
+DCBufferUnpin_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCBufferAcquire(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCBUFFERACQUIRE *psDCBufferAcquireIN,
+ PVRSRV_BRIDGE_OUT_DCBUFFERACQUIRE *psDCBufferAcquireOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DC_BUFFER * psBufferInt = IMG_NULL;
+ IMG_HANDLE hBufferInt2 = IMG_NULL;
+ PMR * psExtMemInt = IMG_NULL;
+ IMG_HANDLE hExtMemInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCBUFFERACQUIRE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCBufferAcquireOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hBufferInt2,
+ psDCBufferAcquireIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER);
+ if(psDCBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferAcquire_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDCBufferAcquireOUT->eError = ResManFindPrivateDataByPtr(hBufferInt2, (IMG_VOID **) &psBufferInt);
+
+ if(psDCBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferAcquire_exit;
+ }
+ }
+
+ psDCBufferAcquireOUT->eError =
+ DCBufferAcquire(
+ psBufferInt,
+ &psExtMemInt);
+ /* Exit early if bridged call fails */
+ if(psDCBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferAcquire_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hExtMemInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR,
+ psExtMemInt,
+ (RESMAN_FREE_FN)&DCBufferRelease);
+ if (hExtMemInt2 == IMG_NULL)
+ {
+ psDCBufferAcquireOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DCBufferAcquire_exit;
+ }
+ psDCBufferAcquireOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDCBufferAcquireOUT->hExtMem,
+ (IMG_HANDLE) hExtMemInt2,
+ PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDCBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferAcquire_exit;
+ }
+
+
+DCBufferAcquire_exit:
+ if (psDCBufferAcquireOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hExtMemInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hExtMemInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psExtMemInt)
+ {
+ DCBufferRelease(psExtMemInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDCBufferRelease(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DCBUFFERRELEASE *psDCBufferReleaseIN,
+ PVRSRV_BRIDGE_OUT_DCBUFFERRELEASE *psDCBufferReleaseOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hExtMemInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DC_DCBUFFERRELEASE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDCBufferReleaseOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hExtMemInt2,
+ psDCBufferReleaseIN->hExtMem,
+ PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
+ if(psDCBufferReleaseOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferRelease_exit;
+ }
+
+ }
+
+ psDCBufferReleaseOUT->eError = DCBufferReleaseResManProxy(hExtMemInt2);
+ /* Exit early if bridged call fails */
+ if(psDCBufferReleaseOUT->eError != PVRSRV_OK)
+ {
+ goto DCBufferRelease_exit;
+ }
+
+ psDCBufferReleaseOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDCBufferReleaseIN->hExtMem,
+ PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
+
+
+DCBufferRelease_exit:
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterDCFunctions(IMG_VOID);
+IMG_VOID UnregisterDCFunctions(IMG_VOID);
+
+/*
+ * Register all DC functions with services
+ */
+PVRSRV_ERROR RegisterDCFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCDEVICESQUERYCOUNT, PVRSRVBridgeDCDevicesQueryCount);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCDEVICESENUMERATE, PVRSRVBridgeDCDevicesEnumerate);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCDEVICEACQUIRE, PVRSRVBridgeDCDeviceAcquire);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCDEVICERELEASE, PVRSRVBridgeDCDeviceRelease);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCGETINFO, PVRSRVBridgeDCGetInfo);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCPANELQUERYCOUNT, PVRSRVBridgeDCPanelQueryCount);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCPANELQUERY, PVRSRVBridgeDCPanelQuery);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCFORMATQUERY, PVRSRVBridgeDCFormatQuery);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCDIMQUERY, PVRSRVBridgeDCDimQuery);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCSETBLANK, PVRSRVBridgeDCSetBlank);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCSETVSYNCREPORTING, PVRSRVBridgeDCSetVSyncReporting);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCLASTVSYNCQUERY, PVRSRVBridgeDCLastVSyncQuery);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCSYSTEMBUFFERACQUIRE, PVRSRVBridgeDCSystemBufferAcquire);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCSYSTEMBUFFERRELEASE, PVRSRVBridgeDCSystemBufferRelease);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTCREATE, PVRSRVBridgeDCDisplayContextCreate);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTCONFIGURECHECK, PVRSRVBridgeDCDisplayContextConfigureCheck);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTCONFIGURE, PVRSRVBridgeDCDisplayContextConfigure);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCDISPLAYCONTEXTDESTROY, PVRSRVBridgeDCDisplayContextDestroy);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCBUFFERALLOC, PVRSRVBridgeDCBufferAlloc);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCBUFFERIMPORT, PVRSRVBridgeDCBufferImport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCBUFFERFREE, PVRSRVBridgeDCBufferFree);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCBUFFERUNIMPORT, PVRSRVBridgeDCBufferUnimport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCBUFFERPIN, PVRSRVBridgeDCBufferPin);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCBUFFERUNPIN, PVRSRVBridgeDCBufferUnpin);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCBUFFERACQUIRE, PVRSRVBridgeDCBufferAcquire);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DC_DCBUFFERRELEASE, PVRSRVBridgeDCBufferRelease);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all dc functions with services
+ */
+IMG_VOID UnregisterDCFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/debugmisc_bridge/common_debugmisc_bridge.h b/drivers/gpu/rogue/generated/debugmisc_bridge/common_debugmisc_bridge.h
new file mode 100644
index 000000000000..e194537fb187
--- /dev/null
+++ b/drivers/gpu/rogue/generated/debugmisc_bridge/common_debugmisc_bridge.h
@@ -0,0 +1,160 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for debugmisc
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for debugmisc
+@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_DEBUGMISC_BRIDGE_H
+#define COMMON_DEBUGMISC_BRIDGE_H
+
+#include "devicemem_typedefs.h"
+#include "rgx_bridge.h"
+#include "pvrsrv_memallocflags.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST (PVRSRV_BRIDGE_DEBUGMISC_START)
+#define PVRSRV_BRIDGE_DEBUGMISC_DEBUGMISCSLCSETBYPASSSTATE PVRSRV_IOWR(PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETFWLOG PVRSRV_IOWR(PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCDUMPFREELISTPAGELIST PVRSRV_IOWR(PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_DEBUGMISC_PHYSMEMIMPORTSECBUF PVRSRV_IOWR(PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_DEBUGMISC_POWMONTESTIOCTL PVRSRV_IOWR(PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_DEBUGMISC_CMD_LAST (PVRSRV_BRIDGE_DEBUGMISC_CMD_FIRST+4)
+
+
+/*******************************************
+ DebugMiscSLCSetBypassState
+ *******************************************/
+
+/* Bridge in structure for DebugMiscSLCSetBypassState */
+typedef struct PVRSRV_BRIDGE_IN_DEBUGMISCSLCSETBYPASSSTATE_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32Flags;
+ IMG_BOOL bIsBypassed;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEBUGMISCSLCSETBYPASSSTATE;
+
+
+/* Bridge out structure for DebugMiscSLCSetBypassState */
+typedef struct PVRSRV_BRIDGE_OUT_DEBUGMISCSLCSETBYPASSSTATE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEBUGMISCSLCSETBYPASSSTATE;
+
+/*******************************************
+ RGXDebugMiscSetFWLog
+ *******************************************/
+
+/* Bridge in structure for RGXDebugMiscSetFWLog */
+typedef struct PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETFWLOG_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32RGXFWLogType;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETFWLOG;
+
+
+/* Bridge out structure for RGXDebugMiscSetFWLog */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETFWLOG_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETFWLOG;
+
+/*******************************************
+ RGXDebugMiscDumpFreelistPageList
+ *******************************************/
+
+/* Bridge in structure for RGXDebugMiscDumpFreelistPageList */
+typedef struct PVRSRV_BRIDGE_IN_RGXDEBUGMISCDUMPFREELISTPAGELIST_TAG
+{
+ IMG_HANDLE hDevNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDEBUGMISCDUMPFREELISTPAGELIST;
+
+
+/* Bridge out structure for RGXDebugMiscDumpFreelistPageList */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDEBUGMISCDUMPFREELISTPAGELIST_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDEBUGMISCDUMPFREELISTPAGELIST;
+
+/*******************************************
+ PhysmemImportSecBuf
+ *******************************************/
+
+/* Bridge in structure for PhysmemImportSecBuf */
+typedef struct PVRSRV_BRIDGE_IN_PHYSMEMIMPORTSECBUF_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_UINT32 ui32Log2PageSize;
+ PVRSRV_MEMALLOCFLAGS_T uiFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PHYSMEMIMPORTSECBUF;
+
+
+/* Bridge out structure for PhysmemImportSecBuf */
+typedef struct PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTSECBUF_TAG
+{
+ IMG_HANDLE hPMRPtr;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTSECBUF;
+
+/*******************************************
+ PowMonTestIoctl
+ *******************************************/
+
+/* Bridge in structure for PowMonTestIoctl */
+typedef struct PVRSRV_BRIDGE_IN_POWMONTESTIOCTL_TAG
+{
+ IMG_UINT32 ui32Cmd;
+ IMG_UINT32 ui32In1;
+ IMG_UINT32 ui32In2;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_POWMONTESTIOCTL;
+
+
+/* Bridge out structure for PowMonTestIoctl */
+typedef struct PVRSRV_BRIDGE_OUT_POWMONTESTIOCTL_TAG
+{
+ IMG_UINT32 ui32Out1;
+ IMG_UINT32 ui32Out2;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_POWMONTESTIOCTL;
+
+#endif /* COMMON_DEBUGMISC_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/debugmisc_bridge/server_debugmisc_bridge.c b/drivers/gpu/rogue/generated/debugmisc_bridge/server_debugmisc_bridge.c
new file mode 100644
index 000000000000..6a590d5ab268
--- /dev/null
+++ b/drivers/gpu/rogue/generated/debugmisc_bridge/server_debugmisc_bridge.c
@@ -0,0 +1,343 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for debugmisc
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for debugmisc
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "devicemem_server.h"
+#include "debugmisc_server.h"
+#include "pmr.h"
+#include "physmem_osmem.h"
+
+
+#include "common_debugmisc_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeDebugMiscSLCSetBypassState(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEBUGMISCSLCSETBYPASSSTATE *psDebugMiscSLCSetBypassStateIN,
+ PVRSRV_BRIDGE_OUT_DEBUGMISCSLCSETBYPASSSTATE *psDebugMiscSLCSetBypassStateOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DEBUGMISC_DEBUGMISCSLCSETBYPASSSTATE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDebugMiscSLCSetBypassStateOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psDebugMiscSLCSetBypassStateIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psDebugMiscSLCSetBypassStateOUT->eError != PVRSRV_OK)
+ {
+ goto DebugMiscSLCSetBypassState_exit;
+ }
+
+ }
+
+ psDebugMiscSLCSetBypassStateOUT->eError =
+ PVRSRVDebugMiscSLCSetBypassStateKM(
+ hDevNodeInt,
+ psDebugMiscSLCSetBypassStateIN->ui32Flags,
+ psDebugMiscSLCSetBypassStateIN->bIsBypassed);
+
+
+
+DebugMiscSLCSetBypassState_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDebugMiscSetFWLog(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDEBUGMISCSETFWLOG *psRGXDebugMiscSetFWLogIN,
+ PVRSRV_BRIDGE_OUT_RGXDEBUGMISCSETFWLOG *psRGXDebugMiscSetFWLogOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETFWLOG);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDebugMiscSetFWLogOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXDebugMiscSetFWLogIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXDebugMiscSetFWLogOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDebugMiscSetFWLog_exit;
+ }
+
+ }
+
+ psRGXDebugMiscSetFWLogOUT->eError =
+ PVRSRVRGXDebugMiscSetFWLogKM(
+ hDevNodeInt,
+ psRGXDebugMiscSetFWLogIN->ui32RGXFWLogType);
+
+
+
+RGXDebugMiscSetFWLog_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDebugMiscDumpFreelistPageList(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDEBUGMISCDUMPFREELISTPAGELIST *psRGXDebugMiscDumpFreelistPageListIN,
+ PVRSRV_BRIDGE_OUT_RGXDEBUGMISCDUMPFREELISTPAGELIST *psRGXDebugMiscDumpFreelistPageListOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCDUMPFREELISTPAGELIST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDebugMiscDumpFreelistPageListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXDebugMiscDumpFreelistPageListIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXDebugMiscDumpFreelistPageListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDebugMiscDumpFreelistPageList_exit;
+ }
+
+ }
+
+ psRGXDebugMiscDumpFreelistPageListOUT->eError =
+ PVRSRVRGXDebugMiscDumpFreelistPageListKM(
+ hDevNodeInt);
+
+
+
+RGXDebugMiscDumpFreelistPageList_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePhysmemImportSecBuf(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PHYSMEMIMPORTSECBUF *psPhysmemImportSecBufIN,
+ PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTSECBUF *psPhysmemImportSecBufOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ PMR * psPMRPtrInt = IMG_NULL;
+ IMG_HANDLE hPMRPtrInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DEBUGMISC_PHYSMEMIMPORTSECBUF);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPhysmemImportSecBufOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psPhysmemImportSecBufIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psPhysmemImportSecBufOUT->eError != PVRSRV_OK)
+ {
+ goto PhysmemImportSecBuf_exit;
+ }
+
+ }
+
+ psPhysmemImportSecBufOUT->eError =
+ PhysmemNewTDSecureBufPMR(
+ hDevNodeInt,
+ psPhysmemImportSecBufIN->uiSize,
+ psPhysmemImportSecBufIN->ui32Log2PageSize,
+ psPhysmemImportSecBufIN->uiFlags,
+ &psPMRPtrInt);
+ /* Exit early if bridged call fails */
+ if(psPhysmemImportSecBufOUT->eError != PVRSRV_OK)
+ {
+ goto PhysmemImportSecBuf_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hPMRPtrInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR,
+ psPMRPtrInt,
+ (RESMAN_FREE_FN)&PMRUnrefPMR);
+ if (hPMRPtrInt2 == IMG_NULL)
+ {
+ psPhysmemImportSecBufOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PhysmemImportSecBuf_exit;
+ }
+ psPhysmemImportSecBufOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psPhysmemImportSecBufOUT->hPMRPtr,
+ (IMG_HANDLE) hPMRPtrInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psPhysmemImportSecBufOUT->eError != PVRSRV_OK)
+ {
+ goto PhysmemImportSecBuf_exit;
+ }
+
+
+PhysmemImportSecBuf_exit:
+ if (psPhysmemImportSecBufOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPMRPtrInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPMRPtrInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPMRPtrInt)
+ {
+ PMRUnrefPMR(psPMRPtrInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePowMonTestIoctl(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_POWMONTESTIOCTL *psPowMonTestIoctlIN,
+ PVRSRV_BRIDGE_OUT_POWMONTESTIOCTL *psPowMonTestIoctlOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DEBUGMISC_POWMONTESTIOCTL);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ psPowMonTestIoctlOUT->eError =
+ PowMonTestIoctlKM(
+ psPowMonTestIoctlIN->ui32Cmd,
+ psPowMonTestIoctlIN->ui32In1,
+ psPowMonTestIoctlIN->ui32In2,
+ &psPowMonTestIoctlOUT->ui32Out1,
+ &psPowMonTestIoctlOUT->ui32Out2);
+
+
+
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterDEBUGMISCFunctions(IMG_VOID);
+IMG_VOID UnregisterDEBUGMISCFunctions(IMG_VOID);
+
+/*
+ * Register all DEBUGMISC functions with services
+ */
+PVRSRV_ERROR RegisterDEBUGMISCFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DEBUGMISC_DEBUGMISCSLCSETBYPASSSTATE, PVRSRVBridgeDebugMiscSLCSetBypassState);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCSETFWLOG, PVRSRVBridgeRGXDebugMiscSetFWLog);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DEBUGMISC_RGXDEBUGMISCDUMPFREELISTPAGELIST, PVRSRVBridgeRGXDebugMiscDumpFreelistPageList);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DEBUGMISC_PHYSMEMIMPORTSECBUF, PVRSRVBridgePhysmemImportSecBuf);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DEBUGMISC_POWMONTESTIOCTL, PVRSRVBridgePowMonTestIoctl);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all debugmisc functions with services
+ */
+IMG_VOID UnregisterDEBUGMISCFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/dmabuf_bridge/common_dmabuf_bridge.h b/drivers/gpu/rogue/generated/dmabuf_bridge/common_dmabuf_bridge.h
new file mode 100644
index 000000000000..a4000059a8d4
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dmabuf_bridge/common_dmabuf_bridge.h
@@ -0,0 +1,79 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for dmabuf
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for dmabuf
+@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_DMABUF_BRIDGE_H
+#define COMMON_DMABUF_BRIDGE_H
+
+#include "pvrsrv_memallocflags.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_DMABUF_CMD_FIRST (PVRSRV_BRIDGE_DMABUF_START)
+#define PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUF PVRSRV_IOWR(PVRSRV_BRIDGE_DMABUF_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DMABUF_CMD_LAST (PVRSRV_BRIDGE_DMABUF_CMD_FIRST+0)
+
+
+/*******************************************
+ PhysmemImportDmaBuf
+ *******************************************/
+
+/* Bridge in structure for PhysmemImportDmaBuf */
+typedef struct PVRSRV_BRIDGE_IN_PHYSMEMIMPORTDMABUF_TAG
+{
+ IMG_INT ifd;
+ PVRSRV_MEMALLOCFLAGS_T uiFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PHYSMEMIMPORTDMABUF;
+
+
+/* Bridge out structure for PhysmemImportDmaBuf */
+typedef struct PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTDMABUF_TAG
+{
+ IMG_HANDLE hPMRPtr;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_DEVMEM_ALIGN_T sAlign;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTDMABUF;
+
+#endif /* COMMON_DMABUF_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/dmabuf_bridge/server_dmabuf_bridge.c b/drivers/gpu/rogue/generated/dmabuf_bridge/server_dmabuf_bridge.c
new file mode 100644
index 000000000000..ef453223486e
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dmabuf_bridge/server_dmabuf_bridge.c
@@ -0,0 +1,174 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for dmabuf
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for dmabuf
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "physmem_dmabuf.h"
+#include "pmr.h"
+
+
+#include "common_dmabuf_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgePhysmemImportDmaBuf(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PHYSMEMIMPORTDMABUF *psPhysmemImportDmaBufIN,
+ PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTDMABUF *psPhysmemImportDmaBufOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRPtrInt = IMG_NULL;
+ IMG_HANDLE hPMRPtrInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUF);
+
+
+
+
+
+ psPhysmemImportDmaBufOUT->eError =
+ PhysmemImportDmaBuf(psConnection,
+ psPhysmemImportDmaBufIN->ifd,
+ psPhysmemImportDmaBufIN->uiFlags,
+ &psPMRPtrInt,
+ &psPhysmemImportDmaBufOUT->uiSize,
+ &psPhysmemImportDmaBufOUT->sAlign);
+ /* Exit early if bridged call fails */
+ if(psPhysmemImportDmaBufOUT->eError != PVRSRV_OK)
+ {
+ goto PhysmemImportDmaBuf_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hPMRPtrInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR,
+ psPMRPtrInt,
+ (RESMAN_FREE_FN)&PMRUnrefPMR);
+ if (hPMRPtrInt2 == IMG_NULL)
+ {
+ psPhysmemImportDmaBufOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PhysmemImportDmaBuf_exit;
+ }
+ psPhysmemImportDmaBufOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psPhysmemImportDmaBufOUT->hPMRPtr,
+ (IMG_HANDLE) hPMRPtrInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psPhysmemImportDmaBufOUT->eError != PVRSRV_OK)
+ {
+ goto PhysmemImportDmaBuf_exit;
+ }
+
+
+PhysmemImportDmaBuf_exit:
+ if (psPhysmemImportDmaBufOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPMRPtrInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPMRPtrInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPMRPtrInt)
+ {
+ PMRUnrefPMR(psPMRPtrInt);
+ }
+ }
+
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterDMABUFFunctions(IMG_VOID);
+IMG_VOID UnregisterDMABUFFunctions(IMG_VOID);
+
+/*
+ * Register all DMABUF functions with services
+ */
+PVRSRV_ERROR RegisterDMABUFFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUF, PVRSRVBridgePhysmemImportDmaBuf);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all dmabuf functions with services
+ */
+IMG_VOID UnregisterDMABUFFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/dmm_bridge/client_mm_bridge.c b/drivers/gpu/rogue/generated/dmm_bridge/client_mm_bridge.c
new file mode 100644
index 000000000000..0936f42e23f4
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dmm_bridge/client_mm_bridge.c
@@ -0,0 +1,535 @@
+/*************************************************************************/ /*!
+@Title Direct client bridge for mm
+@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 "client_mm_bridge.h"
+#include "img_defs.h"
+#include "pvr_debug.h"
+
+/* Module specific includes */
+#include "pvrsrv_memallocflags.h"
+#include "devicemem_typedefs.h"
+
+#include "devicemem_server.h"
+#include "pmr.h"
+#include "devicemem_heapcfg.h"
+#include "physmem.h"
+
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRExportPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_HANDLE *phPMRExport,
+ IMG_UINT64 *pui64Size,
+ IMG_UINT32 *pui32Log2Contig,
+ IMG_UINT64 *pui64Password)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PMR_EXPORT * psPMRExportInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMRExportPMR(
+ psPMRInt,
+ &psPMRExportInt,
+ pui64Size,
+ pui32Log2Contig,
+ pui64Password);
+
+ *phPMRExport = psPMRExportInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRUnexportPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRExport)
+{
+ PVRSRV_ERROR eError;
+ PMR_EXPORT * psPMRExportInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRExportInt = (PMR_EXPORT *) hPMRExport;
+
+ eError =
+ PMRUnexportPMR(
+ psPMRExportInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRGetUID(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_UINT64 *pui64UID)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMRGetUID(
+ psPMRInt,
+ pui64UID);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRMakeServerExportClientExport(IMG_HANDLE hBridge,
+ DEVMEM_SERVER_EXPORTCOOKIE hPMRServerExport,
+ IMG_HANDLE *phPMRExportOut,
+ IMG_UINT64 *pui64Size,
+ IMG_UINT32 *pui32Log2Contig,
+ IMG_UINT64 *pui64Password)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_EXPORTCOOKIE * psPMRServerExportInt;
+ PMR_EXPORT * psPMRExportOutInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRServerExportInt = (DEVMEM_EXPORTCOOKIE *) hPMRServerExport;
+
+ eError =
+ PMRMakeServerExportClientExport(
+ psPMRServerExportInt,
+ &psPMRExportOutInt,
+ pui64Size,
+ pui32Log2Contig,
+ pui64Password);
+
+ *phPMRExportOut = psPMRExportOutInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRUnmakeServerExportClientExport(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRExport)
+{
+ PVRSRV_ERROR eError;
+ PMR_EXPORT * psPMRExportInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRExportInt = (PMR_EXPORT *) hPMRExport;
+
+ eError =
+ PMRUnmakeServerExportClientExport(
+ psPMRExportInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRImportPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRExport,
+ IMG_UINT64 ui64uiPassword,
+ IMG_UINT64 ui64uiSize,
+ IMG_UINT32 ui32uiLog2Contig,
+ IMG_HANDLE *phPMR)
+{
+ PVRSRV_ERROR eError;
+ PMR_EXPORT * psPMRExportInt;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRExportInt = (PMR_EXPORT *) hPMRExport;
+
+ eError =
+ PMRImportPMR(
+ psPMRExportInt,
+ ui64uiPassword,
+ ui64uiSize,
+ ui32uiLog2Contig,
+ &psPMRInt);
+
+ *phPMR = psPMRInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntCtxCreate(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_HANDLE *phDevMemServerContext,
+ IMG_HANDLE *phPrivData)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceNodeInt;
+ DEVMEMINT_CTX * psDevMemServerContextInt;
+ IMG_HANDLE hPrivDataInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ hDeviceNodeInt = (IMG_HANDLE) hDeviceNode;
+
+ eError =
+ DevmemIntCtxCreate(
+ hDeviceNodeInt,
+ &psDevMemServerContextInt,
+ &hPrivDataInt);
+
+ *phDevMemServerContext = psDevMemServerContextInt;
+ *phPrivData = hPrivDataInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntCtxDestroy(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemServerContext)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_CTX * psDevmemServerContextInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psDevmemServerContextInt = (DEVMEMINT_CTX *) hDevmemServerContext;
+
+ eError =
+ DevmemIntCtxDestroy(
+ psDevmemServerContextInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntHeapCreate(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemCtx,
+ IMG_DEV_VIRTADDR sHeapBaseAddr,
+ IMG_DEVMEM_SIZE_T uiHeapLength,
+ IMG_UINT32 ui32Log2DataPageSize,
+ IMG_HANDLE *phDevmemHeapPtr)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_CTX * psDevmemCtxInt;
+ DEVMEMINT_HEAP * psDevmemHeapPtrInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psDevmemCtxInt = (DEVMEMINT_CTX *) hDevmemCtx;
+
+ eError =
+ DevmemIntHeapCreate(
+ psDevmemCtxInt,
+ sHeapBaseAddr,
+ uiHeapLength,
+ ui32Log2DataPageSize,
+ &psDevmemHeapPtrInt);
+
+ *phDevmemHeapPtr = psDevmemHeapPtrInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntHeapDestroy(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemHeap)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_HEAP * psDevmemHeapInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psDevmemHeapInt = (DEVMEMINT_HEAP *) hDevmemHeap;
+
+ eError =
+ DevmemIntHeapDestroy(
+ psDevmemHeapInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntMapPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemServerHeap,
+ IMG_HANDLE hReservation,
+ IMG_HANDLE hPMR,
+ PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
+ IMG_HANDLE *phMapping)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_HEAP * psDevmemServerHeapInt;
+ DEVMEMINT_RESERVATION * psReservationInt;
+ PMR * psPMRInt;
+ DEVMEMINT_MAPPING * psMappingInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psDevmemServerHeapInt = (DEVMEMINT_HEAP *) hDevmemServerHeap;
+ psReservationInt = (DEVMEMINT_RESERVATION *) hReservation;
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ DevmemIntMapPMR(
+ psDevmemServerHeapInt,
+ psReservationInt,
+ psPMRInt,
+ uiMapFlags,
+ &psMappingInt);
+
+ *phMapping = psMappingInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntUnmapPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hMapping)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_MAPPING * psMappingInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psMappingInt = (DEVMEMINT_MAPPING *) hMapping;
+
+ eError =
+ DevmemIntUnmapPMR(
+ psMappingInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntReserveRange(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemServerHeap,
+ IMG_DEV_VIRTADDR sAddress,
+ IMG_DEVMEM_SIZE_T uiLength,
+ IMG_HANDLE *phReservation)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_HEAP * psDevmemServerHeapInt;
+ DEVMEMINT_RESERVATION * psReservationInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psDevmemServerHeapInt = (DEVMEMINT_HEAP *) hDevmemServerHeap;
+
+ eError =
+ DevmemIntReserveRange(
+ psDevmemServerHeapInt,
+ sAddress,
+ uiLength,
+ &psReservationInt);
+
+ *phReservation = psReservationInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntUnreserveRange(IMG_HANDLE hBridge,
+ IMG_HANDLE hReservation)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_RESERVATION * psReservationInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psReservationInt = (DEVMEMINT_RESERVATION *) hReservation;
+
+ eError =
+ DevmemIntUnreserveRange(
+ psReservationInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePhysmemNewRamBackedPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pbMappingTable,
+ IMG_UINT32 ui32Log2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ IMG_HANDLE *phPMRPtr)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceNodeInt;
+ PMR * psPMRPtrInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ hDeviceNodeInt = (IMG_HANDLE) hDeviceNode;
+
+ eError =
+ PhysmemNewRamBackedPMR(
+ hDeviceNodeInt,
+ uiSize,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ pbMappingTable,
+ ui32Log2PageSize,
+ uiFlags,
+ &psPMRPtrInt);
+
+ *phPMRPtr = psPMRPtrInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRLocalImportPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hExtHandle,
+ IMG_HANDLE *phPMR,
+ IMG_DEVMEM_SIZE_T *puiSize,
+ IMG_DEVMEM_ALIGN_T *psAlign)
+{
+ PVRSRV_ERROR eError;
+ PMR * psExtHandleInt;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psExtHandleInt = (PMR *) hExtHandle;
+
+ eError =
+ PMRLocalImportPMR(
+ psExtHandleInt,
+ &psPMRInt,
+ puiSize,
+ psAlign);
+
+ *phPMR = psPMRInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRUnrefPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMRUnrefPMR(
+ psPMRInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemSLCFlushInvalRequest(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_HANDLE hPmr)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceNodeInt;
+ PMR * psPmrInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ hDeviceNodeInt = (IMG_HANDLE) hDeviceNode;
+ psPmrInt = (PMR *) hPmr;
+
+ eError =
+ DevmemSLCFlushInvalRequest(
+ hDeviceNodeInt,
+ psPmrInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeHeapCfgHeapConfigCount(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 *pui32NumHeapConfigs)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceNodeInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ hDeviceNodeInt = (IMG_HANDLE) hDeviceNode;
+
+ eError =
+ HeapCfgHeapConfigCount(
+ hDeviceNodeInt,
+ pui32NumHeapConfigs);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeHeapCfgHeapCount(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 ui32HeapConfigIndex,
+ IMG_UINT32 *pui32NumHeaps)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceNodeInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ hDeviceNodeInt = (IMG_HANDLE) hDeviceNode;
+
+ eError =
+ HeapCfgHeapCount(
+ hDeviceNodeInt,
+ ui32HeapConfigIndex,
+ pui32NumHeaps);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeHeapCfgHeapConfigName(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 ui32HeapConfigIndex,
+ IMG_UINT32 ui32HeapConfigNameBufSz,
+ IMG_CHAR *puiHeapConfigName)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceNodeInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ hDeviceNodeInt = (IMG_HANDLE) hDeviceNode;
+
+ eError =
+ HeapCfgHeapConfigName(
+ hDeviceNodeInt,
+ ui32HeapConfigIndex,
+ ui32HeapConfigNameBufSz,
+ puiHeapConfigName);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeHeapCfgHeapDetails(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 ui32HeapConfigIndex,
+ IMG_UINT32 ui32HeapIndex,
+ IMG_UINT32 ui32HeapNameBufSz,
+ IMG_CHAR *puiHeapNameOut,
+ IMG_DEV_VIRTADDR *psDevVAddrBase,
+ IMG_DEVMEM_SIZE_T *puiHeapLength,
+ IMG_UINT32 *pui32Log2DataPageSizeOut)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceNodeInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ hDeviceNodeInt = (IMG_HANDLE) hDeviceNode;
+
+ eError =
+ HeapCfgHeapDetails(
+ hDeviceNodeInt,
+ ui32HeapConfigIndex,
+ ui32HeapIndex,
+ ui32HeapNameBufSz,
+ puiHeapNameOut,
+ psDevVAddrBase,
+ puiHeapLength,
+ pui32Log2DataPageSizeOut);
+
+ return eError;
+}
+
diff --git a/drivers/gpu/rogue/generated/dmm_bridge/client_mm_bridge.h b/drivers/gpu/rogue/generated/dmm_bridge/client_mm_bridge.h
new file mode 100644
index 000000000000..451ba840fa8a
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dmm_bridge/client_mm_bridge.h
@@ -0,0 +1,165 @@
+/*************************************************************************/ /*!
+@Title Direct client bridge header for mm
+@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 CLIENT_MM_BRIDGE_H
+#define CLIENT_MM_BRIDGE_H
+
+#include "common_mm_bridge.h"
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRExportPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_HANDLE *phPMRExport,
+ IMG_UINT64 *pui64Size,
+ IMG_UINT32 *pui32Log2Contig,
+ IMG_UINT64 *pui64Password);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRUnexportPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRExport);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRGetUID(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_UINT64 *pui64UID);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRMakeServerExportClientExport(IMG_HANDLE hBridge,
+ DEVMEM_SERVER_EXPORTCOOKIE hPMRServerExport,
+ IMG_HANDLE *phPMRExportOut,
+ IMG_UINT64 *pui64Size,
+ IMG_UINT32 *pui32Log2Contig,
+ IMG_UINT64 *pui64Password);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRUnmakeServerExportClientExport(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRExport);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRImportPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRExport,
+ IMG_UINT64 ui64uiPassword,
+ IMG_UINT64 ui64uiSize,
+ IMG_UINT32 ui32uiLog2Contig,
+ IMG_HANDLE *phPMR);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntCtxCreate(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_HANDLE *phDevMemServerContext,
+ IMG_HANDLE *phPrivData);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntCtxDestroy(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemServerContext);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntHeapCreate(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemCtx,
+ IMG_DEV_VIRTADDR sHeapBaseAddr,
+ IMG_DEVMEM_SIZE_T uiHeapLength,
+ IMG_UINT32 ui32Log2DataPageSize,
+ IMG_HANDLE *phDevmemHeapPtr);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntHeapDestroy(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemHeap);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntMapPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemServerHeap,
+ IMG_HANDLE hReservation,
+ IMG_HANDLE hPMR,
+ PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
+ IMG_HANDLE *phMapping);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntUnmapPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hMapping);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntReserveRange(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemServerHeap,
+ IMG_DEV_VIRTADDR sAddress,
+ IMG_DEVMEM_SIZE_T uiLength,
+ IMG_HANDLE *phReservation);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntUnreserveRange(IMG_HANDLE hBridge,
+ IMG_HANDLE hReservation);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePhysmemNewRamBackedPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pbMappingTable,
+ IMG_UINT32 ui32Log2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ IMG_HANDLE *phPMRPtr);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRLocalImportPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hExtHandle,
+ IMG_HANDLE *phPMR,
+ IMG_DEVMEM_SIZE_T *puiSize,
+ IMG_DEVMEM_ALIGN_T *psAlign);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRUnrefPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemSLCFlushInvalRequest(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_HANDLE hPmr);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeHeapCfgHeapConfigCount(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 *pui32NumHeapConfigs);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeHeapCfgHeapCount(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 ui32HeapConfigIndex,
+ IMG_UINT32 *pui32NumHeaps);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeHeapCfgHeapConfigName(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 ui32HeapConfigIndex,
+ IMG_UINT32 ui32HeapConfigNameBufSz,
+ IMG_CHAR *puiHeapConfigName);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeHeapCfgHeapDetails(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 ui32HeapConfigIndex,
+ IMG_UINT32 ui32HeapIndex,
+ IMG_UINT32 ui32HeapNameBufSz,
+ IMG_CHAR *puiHeapNameOut,
+ IMG_DEV_VIRTADDR *psDevVAddrBase,
+ IMG_DEVMEM_SIZE_T *puiHeapLength,
+ IMG_UINT32 *pui32Log2DataPageSizeOut);
+
+
+#endif /* CLIENT_MM_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/dpdumpmm_bridge/client_pdumpmm_bridge.c b/drivers/gpu/rogue/generated/dpdumpmm_bridge/client_pdumpmm_bridge.c
new file mode 100644
index 000000000000..a6dc4d0a5505
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dpdumpmm_bridge/client_pdumpmm_bridge.c
@@ -0,0 +1,256 @@
+/*************************************************************************/ /*!
+@Title Direct client bridge for pdumpmm
+@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 "client_pdumpmm_bridge.h"
+#include "img_defs.h"
+#include "pvr_debug.h"
+
+/* Module specific includes */
+#include "pdump.h"
+#include "pdumpdefs.h"
+#include "pvrsrv_memallocflags.h"
+#include "devicemem_typedefs.h"
+
+#include "devicemem_server.h"
+#include "pmr.h"
+#include "physmem.h"
+
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpLoadMem(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_BOOL bbZero)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMRPDumpLoadMem(
+ psPMRInt,
+ uiOffset,
+ uiSize,
+ ui32PDumpFlags,
+ bbZero);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpLoadMemValue32(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMRPDumpLoadMemValue32(
+ psPMRInt,
+ uiOffset,
+ ui32Value,
+ ui32PDumpFlags);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpLoadMemValue64(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT64 ui64Value,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMRPDumpLoadMemValue64(
+ psPMRInt,
+ uiOffset,
+ ui64Value,
+ ui32PDumpFlags);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpSaveToFile(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 ui32ArraySize,
+ const IMG_CHAR *puiFileName)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMRPDumpSaveToFile(
+ psPMRInt,
+ uiOffset,
+ uiSize,
+ ui32ArraySize,
+ puiFileName);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpSymbolicAddr(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32MemspaceNameLen,
+ IMG_CHAR *puiMemspaceName,
+ IMG_UINT32 ui32SymbolicAddrLen,
+ IMG_CHAR *puiSymbolicAddr,
+ IMG_DEVMEM_OFFSET_T *puiNewOffset,
+ IMG_DEVMEM_OFFSET_T *puiNextSymName)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMR_PDumpSymbolicAddr(
+ psPMRInt,
+ uiOffset,
+ ui32MemspaceNameLen,
+ puiMemspaceName,
+ ui32SymbolicAddrLen,
+ puiSymbolicAddr,
+ puiNewOffset,
+ puiNextSymName);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpPol32(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMRPDumpPol32(
+ psPMRInt,
+ uiOffset,
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ ui32PDumpFlags);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpCBP(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRInt = (PMR *) hPMR;
+
+ eError =
+ PMRPDumpCBP(
+ psPMRInt,
+ uiReadOffset,
+ uiWriteOffset,
+ uiPacketSize,
+ uiBufferSize);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntPDumpSaveToFileVirtual(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemServerContext,
+ IMG_DEV_VIRTADDR sAddress,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 ui32ArraySize,
+ const IMG_CHAR *puiFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_CTX * psDevmemServerContextInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psDevmemServerContextInt = (DEVMEMINT_CTX *) hDevmemServerContext;
+
+ eError =
+ DevmemIntPDumpSaveToFileVirtual(
+ psDevmemServerContextInt,
+ sAddress,
+ uiSize,
+ ui32ArraySize,
+ puiFileName,
+ ui32FileOffset,
+ ui32PDumpFlags);
+
+ return eError;
+}
+
diff --git a/drivers/gpu/rogue/generated/dpvrtl_bridge/client_pvrtl_bridge.c b/drivers/gpu/rogue/generated/dpvrtl_bridge/client_pvrtl_bridge.c
new file mode 100644
index 000000000000..6e63c93e3cfc
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dpvrtl_bridge/client_pvrtl_bridge.c
@@ -0,0 +1,177 @@
+/*************************************************************************/ /*!
+@Title Direct client bridge for pvrtl
+@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 "client_pvrtl_bridge.h"
+#include "img_defs.h"
+#include "pvr_debug.h"
+
+/* Module specific includes */
+#include "devicemem_typedefs.h"
+#include "pvr_tl.h"
+#include "tltestdefs.h"
+
+#include "tlserver.h"
+
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLConnect(IMG_HANDLE hBridge)
+{
+ PVRSRV_ERROR eError;
+
+
+ eError =
+ TLServerConnectKM(hBridge
+ );
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLDisconnect(IMG_HANDLE hBridge)
+{
+ PVRSRV_ERROR eError;
+
+
+ eError =
+ TLServerDisconnectKM(hBridge
+ );
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLOpenStream(IMG_HANDLE hBridge,
+ IMG_CHAR *puiName,
+ IMG_UINT32 ui32Mode,
+ IMG_HANDLE *phSD,
+ DEVMEM_SERVER_EXPORTCOOKIE *phClientBUFExportCookie)
+{
+ PVRSRV_ERROR eError;
+ TL_STREAM_DESC * psSDInt;
+ DEVMEM_EXPORTCOOKIE * psClientBUFExportCookieInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+ eError =
+ TLServerOpenStreamKM(
+ puiName,
+ ui32Mode,
+ &psSDInt,
+ &psClientBUFExportCookieInt);
+
+ *phSD = psSDInt;
+ *phClientBUFExportCookie = psClientBUFExportCookieInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLCloseStream(IMG_HANDLE hBridge,
+ IMG_HANDLE hSD)
+{
+ PVRSRV_ERROR eError;
+ TL_STREAM_DESC * psSDInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSDInt = (TL_STREAM_DESC *) hSD;
+
+ eError =
+ TLServerCloseStreamKM(
+ psSDInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLAcquireData(IMG_HANDLE hBridge,
+ IMG_HANDLE hSD,
+ IMG_UINT32 *pui32ReadOffset,
+ IMG_UINT32 *pui32ReadLen)
+{
+ PVRSRV_ERROR eError;
+ TL_STREAM_DESC * psSDInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSDInt = (TL_STREAM_DESC *) hSD;
+
+ eError =
+ TLServerAcquireDataKM(
+ psSDInt,
+ pui32ReadOffset,
+ pui32ReadLen);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLReleaseData(IMG_HANDLE hBridge,
+ IMG_HANDLE hSD,
+ IMG_UINT32 ui32ReadOffset,
+ IMG_UINT32 ui32ReadLen)
+{
+ PVRSRV_ERROR eError;
+ TL_STREAM_DESC * psSDInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSDInt = (TL_STREAM_DESC *) hSD;
+
+ eError =
+ TLServerReleaseDataKM(
+ psSDInt,
+ ui32ReadOffset,
+ ui32ReadLen);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLTestIoctl(IMG_HANDLE hBridge,
+ IMG_UINT32 ui32Cmd,
+ IMG_BYTE *psIn1,
+ IMG_UINT32 ui32In2,
+ IMG_UINT32 *pui32Out1,
+ IMG_UINT32 *pui32Out2)
+{
+ PVRSRV_ERROR eError;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+ eError =
+ TLServerTestIoctlKM(
+ ui32Cmd,
+ psIn1,
+ ui32In2,
+ pui32Out1,
+ pui32Out2);
+
+ return eError;
+}
+
diff --git a/drivers/gpu/rogue/generated/dri_bridge/client_ri_bridge.c b/drivers/gpu/rogue/generated/dri_bridge/client_ri_bridge.c
new file mode 100644
index 000000000000..88b859fdb5cf
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dri_bridge/client_ri_bridge.c
@@ -0,0 +1,181 @@
+/*************************************************************************/ /*!
+@Title Direct client bridge for ri
+@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 "client_ri_bridge.h"
+#include "img_defs.h"
+#include "pvr_debug.h"
+
+/* Module specific includes */
+#include "ri_typedefs.h"
+
+#include "ri_server.h"
+
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIWritePMREntry(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRHandle,
+ IMG_UINT32 ui32TextASize,
+ const IMG_CHAR *puiTextA,
+ IMG_SIZE_T uiLogicalSize)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRHandleInt = (PMR *) hPMRHandle;
+
+ eError =
+ RIWritePMREntryKM(
+ psPMRHandleInt,
+ ui32TextASize,
+ puiTextA,
+ uiLogicalSize);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIWriteMEMDESCEntry(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRHandle,
+ IMG_UINT32 ui32TextBSize,
+ const IMG_CHAR *puiTextB,
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ IMG_BOOL bIsImport,
+ IMG_BOOL bIsExportable,
+ IMG_HANDLE *phRIHandle)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRHandleInt;
+ RI_HANDLE psRIHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRHandleInt = (PMR *) hPMRHandle;
+
+ eError =
+ RIWriteMEMDESCEntryKM(
+ psPMRHandleInt,
+ ui32TextBSize,
+ puiTextB,
+ uiOffset,
+ uiSize,
+ bIsImport,
+ bIsExportable,
+ &psRIHandleInt);
+
+ *phRIHandle = psRIHandleInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIUpdateMEMDESCAddr(IMG_HANDLE hBridge,
+ IMG_HANDLE hRIHandle,
+ IMG_DEV_VIRTADDR sAddr)
+{
+ PVRSRV_ERROR eError;
+ RI_HANDLE psRIHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psRIHandleInt = (RI_HANDLE) hRIHandle;
+
+ eError =
+ RIUpdateMEMDESCAddrKM(
+ psRIHandleInt,
+ sAddr);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIDeleteMEMDESCEntry(IMG_HANDLE hBridge,
+ IMG_HANDLE hRIHandle)
+{
+ PVRSRV_ERROR eError;
+ RI_HANDLE psRIHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psRIHandleInt = (RI_HANDLE) hRIHandle;
+
+ eError =
+ RIDeleteMEMDESCEntryKM(
+ psRIHandleInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIDumpList(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRHandle)
+{
+ PVRSRV_ERROR eError;
+ PMR * psPMRHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psPMRHandleInt = (PMR *) hPMRHandle;
+
+ eError =
+ RIDumpListKM(
+ psPMRHandleInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIDumpAll(IMG_HANDLE hBridge)
+{
+ PVRSRV_ERROR eError;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+ eError =
+ RIDumpAllKM(
+ );
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIDumpProcess(IMG_HANDLE hBridge,
+ IMG_PID ui32Pid)
+{
+ PVRSRV_ERROR eError;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+
+ eError =
+ RIDumpProcessKM(
+ ui32Pid);
+
+ return eError;
+}
+
diff --git a/drivers/gpu/rogue/generated/dsync_bridge/client_sync_bridge.c b/drivers/gpu/rogue/generated/dsync_bridge/client_sync_bridge.c
new file mode 100644
index 000000000000..36e757479a6b
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dsync_bridge/client_sync_bridge.c
@@ -0,0 +1,492 @@
+/*************************************************************************/ /*!
+@Title Direct client bridge for sync
+@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 "client_sync_bridge.h"
+#include "img_defs.h"
+#include "pvr_debug.h"
+
+/* Module specific includes */
+#include "pdump.h"
+#include "pdumpdefs.h"
+#include "devicemem_typedefs.h"
+
+#include "sync_server.h"
+#include "pdump.h"
+
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeAllocSyncPrimitiveBlock(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevNode,
+ IMG_HANDLE *phSyncHandle,
+ IMG_UINT32 *pui32SyncPrimVAddr,
+ IMG_UINT32 *pui32SyncPrimBlockSize,
+ DEVMEM_SERVER_EXPORTCOOKIE *phExportCookie)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevNodeInt;
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
+ DEVMEM_EXPORTCOOKIE * psExportCookieInt;
+
+ hDevNodeInt = (IMG_HANDLE) hDevNode;
+
+ eError =
+ PVRSRVAllocSyncPrimitiveBlockKM(hBridge
+ ,
+ hDevNodeInt,
+ &psSyncHandleInt,
+ pui32SyncPrimVAddr,
+ pui32SyncPrimBlockSize,
+ &psExportCookieInt);
+
+ *phSyncHandle = psSyncHandleInt;
+ *phExportCookie = psExportCookieInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeFreeSyncPrimitiveBlock(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle)
+{
+ PVRSRV_ERROR eError;
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SYNC_PRIMITIVE_BLOCK *) hSyncHandle;
+
+ eError =
+ PVRSRVFreeSyncPrimitiveBlockKM(
+ psSyncHandleInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimSet(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Index,
+ IMG_UINT32 ui32Value)
+{
+ PVRSRV_ERROR eError;
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SYNC_PRIMITIVE_BLOCK *) hSyncHandle;
+
+ eError =
+ PVRSRVSyncPrimSetKM(
+ psSyncHandleInt,
+ ui32Index,
+ ui32Value);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncPrimSet(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Value)
+{
+ PVRSRV_ERROR eError;
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SERVER_SYNC_PRIMITIVE *) hSyncHandle;
+
+ eError =
+ PVRSRVServerSyncPrimSetKM(
+ psSyncHandleInt,
+ ui32Value);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordRemoveByHandle(IMG_HANDLE hBridge,
+ IMG_HANDLE hhRecord)
+{
+ PVRSRV_ERROR eError;
+ SYNC_RECORD_HANDLE pshRecordInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ pshRecordInt = (SYNC_RECORD_HANDLE) hhRecord;
+
+ eError =
+ PVRSRVSyncRecordRemoveByHandleKM(
+ pshRecordInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordAdd(IMG_HANDLE hBridge,
+ IMG_HANDLE *phhRecord,
+ IMG_HANDLE hhServerSyncPrimBlock,
+ IMG_UINT32 ui32ui32FwBlockAddr,
+ IMG_UINT32 ui32ui32SyncOffset,
+ IMG_BOOL bbServerSync,
+ IMG_UINT32 ui32ClassNameSize,
+ const IMG_CHAR *puiClassName)
+{
+ PVRSRV_ERROR eError;
+ SYNC_RECORD_HANDLE pshRecordInt;
+ SYNC_PRIMITIVE_BLOCK * pshServerSyncPrimBlockInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ pshServerSyncPrimBlockInt = (SYNC_PRIMITIVE_BLOCK *) hhServerSyncPrimBlock;
+
+ eError =
+ PVRSRVSyncRecordAddKM(
+ &pshRecordInt,
+ pshServerSyncPrimBlockInt,
+ ui32ui32FwBlockAddr,
+ ui32ui32SyncOffset,
+ bbServerSync,
+ ui32ClassNameSize,
+ puiClassName);
+
+ *phhRecord = pshRecordInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncAlloc(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevNode,
+ IMG_HANDLE *phSyncHandle,
+ IMG_UINT32 *pui32SyncPrimVAddr,
+ IMG_UINT32 ui32ClassNameSize,
+ const IMG_CHAR *puiClassName)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevNodeInt;
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ hDevNodeInt = (IMG_HANDLE) hDevNode;
+
+ eError =
+ PVRSRVServerSyncAllocKM(
+ hDevNodeInt,
+ &psSyncHandleInt,
+ pui32SyncPrimVAddr,
+ ui32ClassNameSize,
+ puiClassName);
+
+ *phSyncHandle = psSyncHandleInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncFree(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle)
+{
+ PVRSRV_ERROR eError;
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SERVER_SYNC_PRIMITIVE *) hSyncHandle;
+
+ eError =
+ PVRSRVServerSyncFreeKM(
+ psSyncHandleInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncQueueHWOp(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_BOOL bbUpdate,
+ IMG_UINT32 *pui32FenceValue,
+ IMG_UINT32 *pui32UpdateValue)
+{
+ PVRSRV_ERROR eError;
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SERVER_SYNC_PRIMITIVE *) hSyncHandle;
+
+ eError =
+ PVRSRVServerSyncQueueHWOpKM(
+ psSyncHandleInt,
+ bbUpdate,
+ pui32FenceValue,
+ pui32UpdateValue);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncGetStatus(IMG_HANDLE hBridge,
+ IMG_UINT32 ui32SyncCount,
+ IMG_HANDLE *phSyncHandle,
+ IMG_UINT32 *pui32UID,
+ IMG_UINT32 *pui32FWAddr,
+ IMG_UINT32 *pui32CurrentOp,
+ IMG_UINT32 *pui32NextOp)
+{
+ PVRSRV_ERROR eError;
+ SERVER_SYNC_PRIMITIVE * *psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SERVER_SYNC_PRIMITIVE **) phSyncHandle;
+
+ eError =
+ PVRSRVServerSyncGetStatusKM(
+ ui32SyncCount,
+ psSyncHandleInt,
+ pui32UID,
+ pui32FWAddr,
+ pui32CurrentOp,
+ pui32NextOp);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpCreate(IMG_HANDLE hBridge,
+ IMG_UINT32 ui32SyncBlockCount,
+ IMG_HANDLE *phBlockList,
+ IMG_UINT32 ui32ClientSyncCount,
+ IMG_UINT32 *pui32SyncBlockIndex,
+ IMG_UINT32 *pui32Index,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_HANDLE *phServerSync,
+ IMG_HANDLE *phServerCookie)
+{
+ PVRSRV_ERROR eError;
+ SYNC_PRIMITIVE_BLOCK * *psBlockListInt;
+ SERVER_SYNC_PRIMITIVE * *psServerSyncInt;
+ SERVER_OP_COOKIE * psServerCookieInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psBlockListInt = (SYNC_PRIMITIVE_BLOCK **) phBlockList;
+ psServerSyncInt = (SERVER_SYNC_PRIMITIVE **) phServerSync;
+
+ eError =
+ PVRSRVSyncPrimOpCreateKM(
+ ui32SyncBlockCount,
+ psBlockListInt,
+ ui32ClientSyncCount,
+ pui32SyncBlockIndex,
+ pui32Index,
+ ui32ServerSyncCount,
+ psServerSyncInt,
+ &psServerCookieInt);
+
+ *phServerCookie = psServerCookieInt;
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpTake(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie,
+ IMG_UINT32 ui32ClientSyncCount,
+ IMG_UINT32 *pui32Flags,
+ IMG_UINT32 *pui32FenceValue,
+ IMG_UINT32 *pui32UpdateValue,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_UINT32 *pui32ServerFlags)
+{
+ PVRSRV_ERROR eError;
+ SERVER_OP_COOKIE * psServerCookieInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psServerCookieInt = (SERVER_OP_COOKIE *) hServerCookie;
+
+ eError =
+ PVRSRVSyncPrimOpTakeKM(
+ psServerCookieInt,
+ ui32ClientSyncCount,
+ pui32Flags,
+ pui32FenceValue,
+ pui32UpdateValue,
+ ui32ServerSyncCount,
+ pui32ServerFlags);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpReady(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie,
+ IMG_BOOL *pbReady)
+{
+ PVRSRV_ERROR eError;
+ SERVER_OP_COOKIE * psServerCookieInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psServerCookieInt = (SERVER_OP_COOKIE *) hServerCookie;
+
+ eError =
+ PVRSRVSyncPrimOpReadyKM(
+ psServerCookieInt,
+ pbReady);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpComplete(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie)
+{
+ PVRSRV_ERROR eError;
+ SERVER_OP_COOKIE * psServerCookieInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psServerCookieInt = (SERVER_OP_COOKIE *) hServerCookie;
+
+ eError =
+ PVRSRVSyncPrimOpCompleteKM(
+ psServerCookieInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpDestroy(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie)
+{
+ PVRSRV_ERROR eError;
+ SERVER_OP_COOKIE * psServerCookieInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psServerCookieInt = (SERVER_OP_COOKIE *) hServerCookie;
+
+ eError =
+ PVRSRVSyncPrimOpDestroyKM(
+ psServerCookieInt);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDump(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Offset)
+{
+ PVRSRV_ERROR eError;
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SYNC_PRIMITIVE_BLOCK *) hSyncHandle;
+
+ eError =
+ PVRSRVSyncPrimPDumpKM(
+ psSyncHandleInt,
+ ui32Offset);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDumpValue(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value)
+{
+ PVRSRV_ERROR eError;
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SYNC_PRIMITIVE_BLOCK *) hSyncHandle;
+
+ eError =
+ PVRSRVSyncPrimPDumpValueKM(
+ psSyncHandleInt,
+ ui32Offset,
+ ui32Value);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDumpPol(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SYNC_PRIMITIVE_BLOCK *) hSyncHandle;
+
+ eError =
+ PVRSRVSyncPrimPDumpPolKM(
+ psSyncHandleInt,
+ ui32Offset,
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ uiPDumpFlags);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpPDumpPol(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ SERVER_OP_COOKIE * psServerCookieInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psServerCookieInt = (SERVER_OP_COOKIE *) hServerCookie;
+
+ eError =
+ PVRSRVSyncPrimOpPDumpPolKM(
+ psServerCookieInt,
+ eOperator,
+ uiPDumpFlags);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDumpCBP(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize)
+{
+ PVRSRV_ERROR eError;
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt;
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ psSyncHandleInt = (SYNC_PRIMITIVE_BLOCK *) hSyncHandle;
+
+ eError =
+ PVRSRVSyncPrimPDumpCBPKM(
+ psSyncHandleInt,
+ ui32Offset,
+ uiWriteOffset,
+ uiPacketSize,
+ uiBufferSize);
+
+ return eError;
+}
+
diff --git a/drivers/gpu/rogue/generated/dsync_bridge/client_sync_bridge.h b/drivers/gpu/rogue/generated/dsync_bridge/client_sync_bridge.h
new file mode 100644
index 000000000000..e80501c9638f
--- /dev/null
+++ b/drivers/gpu/rogue/generated/dsync_bridge/client_sync_bridge.h
@@ -0,0 +1,161 @@
+/*************************************************************************/ /*!
+@Title Direct client bridge header for sync
+@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 CLIENT_SYNC_BRIDGE_H
+#define CLIENT_SYNC_BRIDGE_H
+
+#include "common_sync_bridge.h"
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeAllocSyncPrimitiveBlock(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevNode,
+ IMG_HANDLE *phSyncHandle,
+ IMG_UINT32 *pui32SyncPrimVAddr,
+ IMG_UINT32 *pui32SyncPrimBlockSize,
+ DEVMEM_SERVER_EXPORTCOOKIE *phExportCookie);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeFreeSyncPrimitiveBlock(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimSet(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Index,
+ IMG_UINT32 ui32Value);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncPrimSet(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Value);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordRemoveByHandle(IMG_HANDLE hBridge,
+ IMG_HANDLE hhRecord);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncRecordAdd(IMG_HANDLE hBridge,
+ IMG_HANDLE *phhRecord,
+ IMG_HANDLE hhServerSyncPrimBlock,
+ IMG_UINT32 ui32ui32FwBlockAddr,
+ IMG_UINT32 ui32ui32SyncOffset,
+ IMG_BOOL bbServerSync,
+ IMG_UINT32 ui32ClassNameSize,
+ const IMG_CHAR *puiClassName);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncAlloc(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevNode,
+ IMG_HANDLE *phSyncHandle,
+ IMG_UINT32 *pui32SyncPrimVAddr,
+ IMG_UINT32 ui32ClassNameSize,
+ const IMG_CHAR *puiClassName);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncFree(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncQueueHWOp(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_BOOL bbUpdate,
+ IMG_UINT32 *pui32FenceValue,
+ IMG_UINT32 *pui32UpdateValue);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeServerSyncGetStatus(IMG_HANDLE hBridge,
+ IMG_UINT32 ui32SyncCount,
+ IMG_HANDLE *phSyncHandle,
+ IMG_UINT32 *pui32UID,
+ IMG_UINT32 *pui32FWAddr,
+ IMG_UINT32 *pui32CurrentOp,
+ IMG_UINT32 *pui32NextOp);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpCreate(IMG_HANDLE hBridge,
+ IMG_UINT32 ui32SyncBlockCount,
+ IMG_HANDLE *phBlockList,
+ IMG_UINT32 ui32ClientSyncCount,
+ IMG_UINT32 *pui32SyncBlockIndex,
+ IMG_UINT32 *pui32Index,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_HANDLE *phServerSync,
+ IMG_HANDLE *phServerCookie);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpTake(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie,
+ IMG_UINT32 ui32ClientSyncCount,
+ IMG_UINT32 *pui32Flags,
+ IMG_UINT32 *pui32FenceValue,
+ IMG_UINT32 *pui32UpdateValue,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_UINT32 *pui32ServerFlags);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpReady(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie,
+ IMG_BOOL *pbReady);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpComplete(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpDestroy(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDump(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Offset);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDumpValue(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDumpPol(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimOpPDumpPol(IMG_HANDLE hBridge,
+ IMG_HANDLE hServerCookie,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeSyncPrimPDumpCBP(IMG_HANDLE hBridge,
+ IMG_HANDLE hSyncHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize);
+
+
+#endif /* CLIENT_SYNC_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/mm_bridge/common_mm_bridge.h b/drivers/gpu/rogue/generated/mm_bridge/common_mm_bridge.h
new file mode 100644
index 000000000000..119a04a5486c
--- /dev/null
+++ b/drivers/gpu/rogue/generated/mm_bridge/common_mm_bridge.h
@@ -0,0 +1,527 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for mm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for mm
+@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_MM_BRIDGE_H
+#define COMMON_MM_BRIDGE_H
+
+#include "pvrsrv_memallocflags.h"
+#include "devicemem_typedefs.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_MM_CMD_FIRST (PVRSRV_BRIDGE_MM_START)
+#define PVRSRV_BRIDGE_MM_PMREXPORTPMR PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_MM_PMRUNEXPORTPMR PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MM_PMRGETUID PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MM_PMRMAKESERVEREXPORTCLIENTEXPORT PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_MM_PMRUNMAKESERVEREXPORTCLIENTEXPORT PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_MM_PMRIMPORTPMR PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_MM_DEVMEMINTCTXCREATE PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_MM_DEVMEMINTCTXDESTROY PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_MM_DEVMEMINTHEAPCREATE PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_MM_DEVMEMINTHEAPDESTROY PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_MM_DEVMEMINTMAPPMR PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_MM_DEVMEMINTUNMAPPMR PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_MM_DEVMEMINTRESERVERANGE PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_MM_DEVMEMINTUNRESERVERANGE PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_MM_PHYSMEMNEWRAMBACKEDPMR PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_MM_PMRLOCALIMPORTPMR PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_MM_PMRUNREFPMR PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_MM_DEVMEMSLCFLUSHINVALREQUEST PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGCOUNT PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCOUNT PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGNAME PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_MM_HEAPCFGHEAPDETAILS PVRSRV_IOWR(PVRSRV_BRIDGE_MM_CMD_FIRST+21)
+#define PVRSRV_BRIDGE_MM_CMD_LAST (PVRSRV_BRIDGE_MM_CMD_FIRST+21)
+
+
+/*******************************************
+ PMRExportPMR
+ *******************************************/
+
+/* Bridge in structure for PMRExportPMR */
+typedef struct PVRSRV_BRIDGE_IN_PMREXPORTPMR_TAG
+{
+ IMG_HANDLE hPMR;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMREXPORTPMR;
+
+
+/* Bridge out structure for PMRExportPMR */
+typedef struct PVRSRV_BRIDGE_OUT_PMREXPORTPMR_TAG
+{
+ IMG_HANDLE hPMRExport;
+ IMG_UINT64 ui64Size;
+ IMG_UINT32 ui32Log2Contig;
+ IMG_UINT64 ui64Password;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMREXPORTPMR;
+
+/*******************************************
+ PMRUnexportPMR
+ *******************************************/
+
+/* Bridge in structure for PMRUnexportPMR */
+typedef struct PVRSRV_BRIDGE_IN_PMRUNEXPORTPMR_TAG
+{
+ IMG_HANDLE hPMRExport;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRUNEXPORTPMR;
+
+
+/* Bridge out structure for PMRUnexportPMR */
+typedef struct PVRSRV_BRIDGE_OUT_PMRUNEXPORTPMR_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRUNEXPORTPMR;
+
+/*******************************************
+ PMRGetUID
+ *******************************************/
+
+/* Bridge in structure for PMRGetUID */
+typedef struct PVRSRV_BRIDGE_IN_PMRGETUID_TAG
+{
+ IMG_HANDLE hPMR;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRGETUID;
+
+
+/* Bridge out structure for PMRGetUID */
+typedef struct PVRSRV_BRIDGE_OUT_PMRGETUID_TAG
+{
+ IMG_UINT64 ui64UID;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRGETUID;
+
+/*******************************************
+ PMRMakeServerExportClientExport
+ *******************************************/
+
+/* Bridge in structure for PMRMakeServerExportClientExport */
+typedef struct PVRSRV_BRIDGE_IN_PMRMAKESERVEREXPORTCLIENTEXPORT_TAG
+{
+ DEVMEM_SERVER_EXPORTCOOKIE hPMRServerExport;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRMAKESERVEREXPORTCLIENTEXPORT;
+
+
+/* Bridge out structure for PMRMakeServerExportClientExport */
+typedef struct PVRSRV_BRIDGE_OUT_PMRMAKESERVEREXPORTCLIENTEXPORT_TAG
+{
+ IMG_HANDLE hPMRExportOut;
+ IMG_UINT64 ui64Size;
+ IMG_UINT32 ui32Log2Contig;
+ IMG_UINT64 ui64Password;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRMAKESERVEREXPORTCLIENTEXPORT;
+
+/*******************************************
+ PMRUnmakeServerExportClientExport
+ *******************************************/
+
+/* Bridge in structure for PMRUnmakeServerExportClientExport */
+typedef struct PVRSRV_BRIDGE_IN_PMRUNMAKESERVEREXPORTCLIENTEXPORT_TAG
+{
+ IMG_HANDLE hPMRExport;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRUNMAKESERVEREXPORTCLIENTEXPORT;
+
+
+/* Bridge out structure for PMRUnmakeServerExportClientExport */
+typedef struct PVRSRV_BRIDGE_OUT_PMRUNMAKESERVEREXPORTCLIENTEXPORT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRUNMAKESERVEREXPORTCLIENTEXPORT;
+
+/*******************************************
+ PMRImportPMR
+ *******************************************/
+
+/* Bridge in structure for PMRImportPMR */
+typedef struct PVRSRV_BRIDGE_IN_PMRIMPORTPMR_TAG
+{
+ IMG_HANDLE hPMRExport;
+ IMG_UINT64 ui64uiPassword;
+ IMG_UINT64 ui64uiSize;
+ IMG_UINT32 ui32uiLog2Contig;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRIMPORTPMR;
+
+
+/* Bridge out structure for PMRImportPMR */
+typedef struct PVRSRV_BRIDGE_OUT_PMRIMPORTPMR_TAG
+{
+ IMG_HANDLE hPMR;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRIMPORTPMR;
+
+/*******************************************
+ DevmemIntCtxCreate
+ *******************************************/
+
+/* Bridge in structure for DevmemIntCtxCreate */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTCTXCREATE_TAG
+{
+ IMG_HANDLE hDeviceNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTCTXCREATE;
+
+
+/* Bridge out structure for DevmemIntCtxCreate */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTCTXCREATE_TAG
+{
+ IMG_HANDLE hDevMemServerContext;
+ IMG_HANDLE hPrivData;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTCTXCREATE;
+
+/*******************************************
+ DevmemIntCtxDestroy
+ *******************************************/
+
+/* Bridge in structure for DevmemIntCtxDestroy */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTCTXDESTROY_TAG
+{
+ IMG_HANDLE hDevmemServerContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTCTXDESTROY;
+
+
+/* Bridge out structure for DevmemIntCtxDestroy */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTCTXDESTROY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTCTXDESTROY;
+
+/*******************************************
+ DevmemIntHeapCreate
+ *******************************************/
+
+/* Bridge in structure for DevmemIntHeapCreate */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTHEAPCREATE_TAG
+{
+ IMG_HANDLE hDevmemCtx;
+ IMG_DEV_VIRTADDR sHeapBaseAddr;
+ IMG_DEVMEM_SIZE_T uiHeapLength;
+ IMG_UINT32 ui32Log2DataPageSize;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTHEAPCREATE;
+
+
+/* Bridge out structure for DevmemIntHeapCreate */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTHEAPCREATE_TAG
+{
+ IMG_HANDLE hDevmemHeapPtr;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTHEAPCREATE;
+
+/*******************************************
+ DevmemIntHeapDestroy
+ *******************************************/
+
+/* Bridge in structure for DevmemIntHeapDestroy */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTHEAPDESTROY_TAG
+{
+ IMG_HANDLE hDevmemHeap;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTHEAPDESTROY;
+
+
+/* Bridge out structure for DevmemIntHeapDestroy */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTHEAPDESTROY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTHEAPDESTROY;
+
+/*******************************************
+ DevmemIntMapPMR
+ *******************************************/
+
+/* Bridge in structure for DevmemIntMapPMR */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTMAPPMR_TAG
+{
+ IMG_HANDLE hDevmemServerHeap;
+ IMG_HANDLE hReservation;
+ IMG_HANDLE hPMR;
+ PVRSRV_MEMALLOCFLAGS_T uiMapFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTMAPPMR;
+
+
+/* Bridge out structure for DevmemIntMapPMR */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTMAPPMR_TAG
+{
+ IMG_HANDLE hMapping;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTMAPPMR;
+
+/*******************************************
+ DevmemIntUnmapPMR
+ *******************************************/
+
+/* Bridge in structure for DevmemIntUnmapPMR */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTUNMAPPMR_TAG
+{
+ IMG_HANDLE hMapping;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTUNMAPPMR;
+
+
+/* Bridge out structure for DevmemIntUnmapPMR */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTUNMAPPMR_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTUNMAPPMR;
+
+/*******************************************
+ DevmemIntReserveRange
+ *******************************************/
+
+/* Bridge in structure for DevmemIntReserveRange */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTRESERVERANGE_TAG
+{
+ IMG_HANDLE hDevmemServerHeap;
+ IMG_DEV_VIRTADDR sAddress;
+ IMG_DEVMEM_SIZE_T uiLength;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTRESERVERANGE;
+
+
+/* Bridge out structure for DevmemIntReserveRange */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTRESERVERANGE_TAG
+{
+ IMG_HANDLE hReservation;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTRESERVERANGE;
+
+/*******************************************
+ DevmemIntUnreserveRange
+ *******************************************/
+
+/* Bridge in structure for DevmemIntUnreserveRange */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTUNRESERVERANGE_TAG
+{
+ IMG_HANDLE hReservation;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTUNRESERVERANGE;
+
+
+/* Bridge out structure for DevmemIntUnreserveRange */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTUNRESERVERANGE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTUNRESERVERANGE;
+
+/*******************************************
+ PhysmemNewRamBackedPMR
+ *******************************************/
+
+/* Bridge in structure for PhysmemNewRamBackedPMR */
+typedef struct PVRSRV_BRIDGE_IN_PHYSMEMNEWRAMBACKEDPMR_TAG
+{
+ IMG_HANDLE hDeviceNode;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_DEVMEM_SIZE_T uiChunkSize;
+ IMG_UINT32 ui32NumPhysChunks;
+ IMG_UINT32 ui32NumVirtChunks;
+ IMG_BOOL * pbMappingTable;
+ IMG_UINT32 ui32Log2PageSize;
+ PVRSRV_MEMALLOCFLAGS_T uiFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PHYSMEMNEWRAMBACKEDPMR;
+
+
+/* Bridge out structure for PhysmemNewRamBackedPMR */
+typedef struct PVRSRV_BRIDGE_OUT_PHYSMEMNEWRAMBACKEDPMR_TAG
+{
+ IMG_HANDLE hPMRPtr;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PHYSMEMNEWRAMBACKEDPMR;
+
+/*******************************************
+ PMRLocalImportPMR
+ *******************************************/
+
+/* Bridge in structure for PMRLocalImportPMR */
+typedef struct PVRSRV_BRIDGE_IN_PMRLOCALIMPORTPMR_TAG
+{
+ IMG_HANDLE hExtHandle;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRLOCALIMPORTPMR;
+
+
+/* Bridge out structure for PMRLocalImportPMR */
+typedef struct PVRSRV_BRIDGE_OUT_PMRLOCALIMPORTPMR_TAG
+{
+ IMG_HANDLE hPMR;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_DEVMEM_ALIGN_T sAlign;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRLOCALIMPORTPMR;
+
+/*******************************************
+ PMRUnrefPMR
+ *******************************************/
+
+/* Bridge in structure for PMRUnrefPMR */
+typedef struct PVRSRV_BRIDGE_IN_PMRUNREFPMR_TAG
+{
+ IMG_HANDLE hPMR;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRUNREFPMR;
+
+
+/* Bridge out structure for PMRUnrefPMR */
+typedef struct PVRSRV_BRIDGE_OUT_PMRUNREFPMR_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRUNREFPMR;
+
+/*******************************************
+ DevmemSLCFlushInvalRequest
+ *******************************************/
+
+/* Bridge in structure for DevmemSLCFlushInvalRequest */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMSLCFLUSHINVALREQUEST_TAG
+{
+ IMG_HANDLE hDeviceNode;
+ IMG_HANDLE hPmr;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMSLCFLUSHINVALREQUEST;
+
+
+/* Bridge out structure for DevmemSLCFlushInvalRequest */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMSLCFLUSHINVALREQUEST_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMSLCFLUSHINVALREQUEST;
+
+/*******************************************
+ DevmemIntGetSystemLog2PageSize
+ *******************************************/
+
+/* Bridge in structure for DevmemIntGetSystemLog2PageSize */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTGETSYSTEMLOG2PAGESIZE_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTGETSYSTEMLOG2PAGESIZE;
+
+
+/* Bridge out structure for DevmemIntGetSystemLog2PageSize */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTGETSYSTEMLOG2PAGESIZE_TAG
+{
+ IMG_UINT32 ui32Log2PageSize;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTGETSYSTEMLOG2PAGESIZE;
+
+/*******************************************
+ HeapCfgHeapConfigCount
+ *******************************************/
+
+/* Bridge in structure for HeapCfgHeapConfigCount */
+typedef struct PVRSRV_BRIDGE_IN_HEAPCFGHEAPCONFIGCOUNT_TAG
+{
+ IMG_HANDLE hDeviceNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_HEAPCFGHEAPCONFIGCOUNT;
+
+
+/* Bridge out structure for HeapCfgHeapConfigCount */
+typedef struct PVRSRV_BRIDGE_OUT_HEAPCFGHEAPCONFIGCOUNT_TAG
+{
+ IMG_UINT32 ui32NumHeapConfigs;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_HEAPCFGHEAPCONFIGCOUNT;
+
+/*******************************************
+ HeapCfgHeapCount
+ *******************************************/
+
+/* Bridge in structure for HeapCfgHeapCount */
+typedef struct PVRSRV_BRIDGE_IN_HEAPCFGHEAPCOUNT_TAG
+{
+ IMG_HANDLE hDeviceNode;
+ IMG_UINT32 ui32HeapConfigIndex;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_HEAPCFGHEAPCOUNT;
+
+
+/* Bridge out structure for HeapCfgHeapCount */
+typedef struct PVRSRV_BRIDGE_OUT_HEAPCFGHEAPCOUNT_TAG
+{
+ IMG_UINT32 ui32NumHeaps;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_HEAPCFGHEAPCOUNT;
+
+/*******************************************
+ HeapCfgHeapConfigName
+ *******************************************/
+
+/* Bridge in structure for HeapCfgHeapConfigName */
+typedef struct PVRSRV_BRIDGE_IN_HEAPCFGHEAPCONFIGNAME_TAG
+{
+ IMG_HANDLE hDeviceNode;
+ IMG_UINT32 ui32HeapConfigIndex;
+ IMG_UINT32 ui32HeapConfigNameBufSz;
+ /* Output pointer puiHeapConfigName is also an implied input */
+ IMG_CHAR * puiHeapConfigName;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_HEAPCFGHEAPCONFIGNAME;
+
+
+/* Bridge out structure for HeapCfgHeapConfigName */
+typedef struct PVRSRV_BRIDGE_OUT_HEAPCFGHEAPCONFIGNAME_TAG
+{
+ IMG_CHAR * puiHeapConfigName;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_HEAPCFGHEAPCONFIGNAME;
+
+/*******************************************
+ HeapCfgHeapDetails
+ *******************************************/
+
+/* Bridge in structure for HeapCfgHeapDetails */
+typedef struct PVRSRV_BRIDGE_IN_HEAPCFGHEAPDETAILS_TAG
+{
+ IMG_HANDLE hDeviceNode;
+ IMG_UINT32 ui32HeapConfigIndex;
+ IMG_UINT32 ui32HeapIndex;
+ IMG_UINT32 ui32HeapNameBufSz;
+ /* Output pointer puiHeapNameOut is also an implied input */
+ IMG_CHAR * puiHeapNameOut;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_HEAPCFGHEAPDETAILS;
+
+
+/* Bridge out structure for HeapCfgHeapDetails */
+typedef struct PVRSRV_BRIDGE_OUT_HEAPCFGHEAPDETAILS_TAG
+{
+ IMG_CHAR * puiHeapNameOut;
+ IMG_DEV_VIRTADDR sDevVAddrBase;
+ IMG_DEVMEM_SIZE_T uiHeapLength;
+ IMG_UINT32 ui32Log2DataPageSizeOut;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_HEAPCFGHEAPDETAILS;
+
+#endif /* COMMON_MM_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/mm_bridge/server_mm_bridge.c b/drivers/gpu/rogue/generated/mm_bridge/server_mm_bridge.c
new file mode 100644
index 000000000000..2b42bcdc8a35
--- /dev/null
+++ b/drivers/gpu/rogue/generated/mm_bridge/server_mm_bridge.c
@@ -0,0 +1,1851 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for mm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for mm
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "devicemem_server.h"
+#include "pmr.h"
+#include "devicemem_heapcfg.h"
+#include "physmem.h"
+
+
+#include "common_mm_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+PMRUnexportPMRResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+PMRUnmakeServerExportClientExportResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DevmemIntCtxDestroyResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DevmemIntHeapDestroyResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DevmemIntUnmapPMRResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+DevmemIntUnreserveRangeResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+PMRUnrefPMRResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgePMRExportPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMREXPORTPMR *psPMRExportPMRIN,
+ PVRSRV_BRIDGE_OUT_PMREXPORTPMR *psPMRExportPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+ PMR_EXPORT * psPMRExportInt = IMG_NULL;
+ IMG_HANDLE hPMRExportInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_PMREXPORTPMR);
+
+
+
+
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psPMRExportPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRExportPMRIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRExportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRExportPMR_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRExportPMROUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRExportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRExportPMR_exit;
+ }
+ }
+
+ psPMRExportPMROUT->eError =
+ PMRExportPMR(
+ psPMRInt,
+ &psPMRExportInt,
+ &psPMRExportPMROUT->ui64Size,
+ &psPMRExportPMROUT->ui32Log2Contig,
+ &psPMRExportPMROUT->ui64Password);
+ /* Exit early if bridged call fails */
+ if(psPMRExportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRExportPMR_exit;
+ }
+
+ PMRUnlock();
+
+ /* Create a resman item and overwrite the handle with it */
+ hPMRExportInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR_EXPORT,
+ psPMRExportInt,
+ (RESMAN_FREE_FN)&PMRUnexportPMR);
+ if (hPMRExportInt2 == IMG_NULL)
+ {
+ psPMRExportPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PMRExportPMR_exit;
+ }
+ /* see if it's already exported */
+ psPMRExportPMROUT->eError =
+ PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &psPMRExportPMROUT->hPMRExport,
+ (IMG_HANDLE) hPMRExportInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+ if(psPMRExportPMROUT->eError == PVRSRV_OK)
+ {
+ /* It's already exported */
+ return 0;
+ }
+
+ psPMRExportPMROUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psPMRExportPMROUT->hPMRExport,
+ (IMG_HANDLE) hPMRExportInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psPMRExportPMROUT->eError != PVRSRV_OK)
+ {
+ goto PMRExportPMR_exit;
+ }
+
+
+PMRExportPMR_exit:
+ if (psPMRExportPMROUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPMRExportInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPMRExportInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPMRExportInt)
+ {
+ PMRUnexportPMR(psPMRExportInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRUnexportPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRUNEXPORTPMR *psPMRUnexportPMRIN,
+ PVRSRV_BRIDGE_OUT_PMRUNEXPORTPMR *psPMRUnexportPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hPMRExportInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_PMRUNEXPORTPMR);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psPMRUnexportPMROUT->eError =
+ PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE *) &hPMRExportInt2,
+ psPMRUnexportPMRIN->hPMRExport,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+ if(psPMRUnexportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRUnexportPMR_exit;
+ }
+
+ }
+ PMRUnlock();
+
+ psPMRUnexportPMROUT->eError = PMRUnexportPMRResManProxy(hPMRExportInt2);
+ /* Exit early if bridged call fails */
+ if(psPMRUnexportPMROUT->eError != PVRSRV_OK)
+ {
+ goto PMRUnexportPMR_exit;
+ }
+
+ psPMRUnexportPMROUT->eError =
+ PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE) psPMRUnexportPMRIN->hPMRExport,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+
+
+PMRUnexportPMR_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRGetUID(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRGETUID *psPMRGetUIDIN,
+ PVRSRV_BRIDGE_OUT_PMRGETUID *psPMRGetUIDOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_PMRGETUID);
+
+
+
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psPMRGetUIDOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRGetUIDIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRGetUIDOUT->eError != PVRSRV_OK)
+ {
+ goto PMRGetUID_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRGetUIDOUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRGetUIDOUT->eError != PVRSRV_OK)
+ {
+ goto PMRGetUID_exit;
+ }
+ }
+
+ psPMRGetUIDOUT->eError =
+ PMRGetUID(
+ psPMRInt,
+ &psPMRGetUIDOUT->ui64UID);
+
+
+
+PMRGetUID_exit:
+ PMRUnlock();
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRMakeServerExportClientExport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRMAKESERVEREXPORTCLIENTEXPORT *psPMRMakeServerExportClientExportIN,
+ PVRSRV_BRIDGE_OUT_PMRMAKESERVEREXPORTCLIENTEXPORT *psPMRMakeServerExportClientExportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DEVMEM_EXPORTCOOKIE * psPMRServerExportInt = IMG_NULL;
+ PMR_EXPORT * psPMRExportOutInt = IMG_NULL;
+ IMG_HANDLE hPMRExportOutInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_PMRMAKESERVEREXPORTCLIENTEXPORT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRMakeServerExportClientExportOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &psPMRServerExportInt,
+ psPMRMakeServerExportClientExportIN->hPMRServerExport,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE);
+ if(psPMRMakeServerExportClientExportOUT->eError != PVRSRV_OK)
+ {
+ goto PMRMakeServerExportClientExport_exit;
+ }
+
+ }
+
+ psPMRMakeServerExportClientExportOUT->eError =
+ PMRMakeServerExportClientExport(
+ psPMRServerExportInt,
+ &psPMRExportOutInt,
+ &psPMRMakeServerExportClientExportOUT->ui64Size,
+ &psPMRMakeServerExportClientExportOUT->ui32Log2Contig,
+ &psPMRMakeServerExportClientExportOUT->ui64Password);
+ /* Exit early if bridged call fails */
+ if(psPMRMakeServerExportClientExportOUT->eError != PVRSRV_OK)
+ {
+ goto PMRMakeServerExportClientExport_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hPMRExportOutInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR_EXPORT,
+ psPMRExportOutInt,
+ (RESMAN_FREE_FN)&PMRUnmakeServerExportClientExport);
+ if (hPMRExportOutInt2 == IMG_NULL)
+ {
+ psPMRMakeServerExportClientExportOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PMRMakeServerExportClientExport_exit;
+ }
+ /* see if it's already exported */
+ psPMRMakeServerExportClientExportOUT->eError =
+ PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &psPMRMakeServerExportClientExportOUT->hPMRExportOut,
+ (IMG_HANDLE) hPMRExportOutInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+ if(psPMRMakeServerExportClientExportOUT->eError == PVRSRV_OK)
+ {
+ /* It's already exported */
+ return 0;
+ }
+
+ psPMRMakeServerExportClientExportOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psPMRMakeServerExportClientExportOUT->hPMRExportOut,
+ (IMG_HANDLE) hPMRExportOutInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psPMRMakeServerExportClientExportOUT->eError != PVRSRV_OK)
+ {
+ goto PMRMakeServerExportClientExport_exit;
+ }
+
+
+PMRMakeServerExportClientExport_exit:
+ if (psPMRMakeServerExportClientExportOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPMRExportOutInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPMRExportOutInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPMRExportOutInt)
+ {
+ PMRUnmakeServerExportClientExport(psPMRExportOutInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRUnmakeServerExportClientExport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRUNMAKESERVEREXPORTCLIENTEXPORT *psPMRUnmakeServerExportClientExportIN,
+ PVRSRV_BRIDGE_OUT_PMRUNMAKESERVEREXPORTCLIENTEXPORT *psPMRUnmakeServerExportClientExportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hPMRExportInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_PMRUNMAKESERVEREXPORTCLIENTEXPORT);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRUnmakeServerExportClientExportOUT->eError =
+ PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE *) &hPMRExportInt2,
+ psPMRUnmakeServerExportClientExportIN->hPMRExport,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+ if(psPMRUnmakeServerExportClientExportOUT->eError != PVRSRV_OK)
+ {
+ goto PMRUnmakeServerExportClientExport_exit;
+ }
+
+ }
+
+ psPMRUnmakeServerExportClientExportOUT->eError = PMRUnmakeServerExportClientExportResManProxy(hPMRExportInt2);
+ /* Exit early if bridged call fails */
+ if(psPMRUnmakeServerExportClientExportOUT->eError != PVRSRV_OK)
+ {
+ goto PMRUnmakeServerExportClientExport_exit;
+ }
+
+ psPMRUnmakeServerExportClientExportOUT->eError =
+ PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE) psPMRUnmakeServerExportClientExportIN->hPMRExport,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+
+
+PMRUnmakeServerExportClientExport_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRImportPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRIMPORTPMR *psPMRImportPMRIN,
+ PVRSRV_BRIDGE_OUT_PMRIMPORTPMR *psPMRImportPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR_EXPORT * psPMRExportInt = IMG_NULL;
+ IMG_HANDLE hPMRExportInt2 = IMG_NULL;
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_PMRIMPORTPMR);
+
+
+
+
+#if defined (SUPPORT_AUTH)
+ psPMRImportPMROUT->eError = OSCheckAuthentication(psConnection, 1);
+ if (psPMRImportPMROUT->eError != PVRSRV_OK)
+ {
+ goto PMRImportPMR_exit;
+ }
+#endif
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psPMRImportPMROUT->eError =
+ PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE *) &hPMRExportInt2,
+ psPMRImportPMRIN->hPMRExport,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+ if(psPMRImportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRImportPMR_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRImportPMROUT->eError = ResManFindPrivateDataByPtr(hPMRExportInt2, (IMG_VOID **) &psPMRExportInt);
+
+ if(psPMRImportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRImportPMR_exit;
+ }
+ }
+
+ psPMRImportPMROUT->eError =
+ PMRImportPMR(
+ psPMRExportInt,
+ psPMRImportPMRIN->ui64uiPassword,
+ psPMRImportPMRIN->ui64uiSize,
+ psPMRImportPMRIN->ui32uiLog2Contig,
+ &psPMRInt);
+ /* Exit early if bridged call fails */
+ if(psPMRImportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRImportPMR_exit;
+ }
+
+ PMRUnlock();
+
+ /* Create a resman item and overwrite the handle with it */
+ hPMRInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR,
+ psPMRInt,
+ (RESMAN_FREE_FN)&PMRUnrefPMR);
+ if (hPMRInt2 == IMG_NULL)
+ {
+ psPMRImportPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PMRImportPMR_exit;
+ }
+ psPMRImportPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psPMRImportPMROUT->hPMR,
+ (IMG_HANDLE) hPMRInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psPMRImportPMROUT->eError != PVRSRV_OK)
+ {
+ goto PMRImportPMR_exit;
+ }
+
+
+PMRImportPMR_exit:
+ if (psPMRImportPMROUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPMRInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPMRInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPMRInt)
+ {
+ PMRUnrefPMR(psPMRInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntCtxCreate(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTCTXCREATE *psDevmemIntCtxCreateIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTCTXCREATE *psDevmemIntCtxCreateOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+ DEVMEMINT_CTX * psDevMemServerContextInt = IMG_NULL;
+ IMG_HANDLE hDevMemServerContextInt2 = IMG_NULL;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_DEVMEMINTCTXCREATE);
+
+
+
+ psDevmemIntCtxCreateOUT->hDevMemServerContext = IMG_NULL;
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntCtxCreateOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psDevmemIntCtxCreateIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psDevmemIntCtxCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxCreate_exit;
+ }
+
+ }
+
+ psDevmemIntCtxCreateOUT->eError =
+ DevmemIntCtxCreate(
+ hDeviceNodeInt,
+ &psDevMemServerContextInt,
+ &hPrivDataInt);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntCtxCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxCreate_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hDevMemServerContextInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DEVICEMEM2_CONTEXT,
+ psDevMemServerContextInt,
+ (RESMAN_FREE_FN)&DevmemIntCtxDestroy);
+ if (hDevMemServerContextInt2 == IMG_NULL)
+ {
+ psDevmemIntCtxCreateOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DevmemIntCtxCreate_exit;
+ }
+ psDevmemIntCtxCreateOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDevmemIntCtxCreateOUT->hDevMemServerContext,
+ (IMG_HANDLE) hDevMemServerContextInt2,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDevmemIntCtxCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxCreate_exit;
+ }
+ psDevmemIntCtxCreateOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+ &psDevmemIntCtxCreateOUT->hPrivData,
+ (IMG_HANDLE) hPrivDataInt,
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+ ,psDevmemIntCtxCreateOUT->hDevMemServerContext);
+ if (psDevmemIntCtxCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxCreate_exit;
+ }
+
+
+DevmemIntCtxCreate_exit:
+ if (psDevmemIntCtxCreateOUT->eError != PVRSRV_OK)
+ {
+ if (psDevmemIntCtxCreateOUT->hDevMemServerContext)
+ {
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDevmemIntCtxCreateOUT->hDevMemServerContext,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+ }
+
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hDevMemServerContextInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hDevMemServerContextInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psDevMemServerContextInt)
+ {
+ DevmemIntCtxDestroy(psDevMemServerContextInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntCtxDestroy(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTCTXDESTROY *psDevmemIntCtxDestroyIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTCTXDESTROY *psDevmemIntCtxDestroyOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevmemServerContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_DEVMEMINTCTXDESTROY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntCtxDestroyOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevmemServerContextInt2,
+ psDevmemIntCtxDestroyIN->hDevmemServerContext,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+ if(psDevmemIntCtxDestroyOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxDestroy_exit;
+ }
+
+ }
+
+ psDevmemIntCtxDestroyOUT->eError = DevmemIntCtxDestroyResManProxy(hDevmemServerContextInt2);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntCtxDestroyOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntCtxDestroy_exit;
+ }
+
+ psDevmemIntCtxDestroyOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDevmemIntCtxDestroyIN->hDevmemServerContext,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+
+
+DevmemIntCtxDestroy_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntHeapCreate(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTHEAPCREATE *psDevmemIntHeapCreateIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTHEAPCREATE *psDevmemIntHeapCreateOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DEVMEMINT_CTX * psDevmemCtxInt = IMG_NULL;
+ IMG_HANDLE hDevmemCtxInt2 = IMG_NULL;
+ DEVMEMINT_HEAP * psDevmemHeapPtrInt = IMG_NULL;
+ IMG_HANDLE hDevmemHeapPtrInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_DEVMEMINTHEAPCREATE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntHeapCreateOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevmemCtxInt2,
+ psDevmemIntHeapCreateIN->hDevmemCtx,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+ if(psDevmemIntHeapCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntHeapCreate_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemIntHeapCreateOUT->eError = ResManFindPrivateDataByPtr(hDevmemCtxInt2, (IMG_VOID **) &psDevmemCtxInt);
+
+ if(psDevmemIntHeapCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntHeapCreate_exit;
+ }
+ }
+
+ psDevmemIntHeapCreateOUT->eError =
+ DevmemIntHeapCreate(
+ psDevmemCtxInt,
+ psDevmemIntHeapCreateIN->sHeapBaseAddr,
+ psDevmemIntHeapCreateIN->uiHeapLength,
+ psDevmemIntHeapCreateIN->ui32Log2DataPageSize,
+ &psDevmemHeapPtrInt);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntHeapCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntHeapCreate_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hDevmemHeapPtrInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DEVICEMEM2_HEAP,
+ psDevmemHeapPtrInt,
+ (RESMAN_FREE_FN)&DevmemIntHeapDestroy);
+ if (hDevmemHeapPtrInt2 == IMG_NULL)
+ {
+ psDevmemIntHeapCreateOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DevmemIntHeapCreate_exit;
+ }
+ psDevmemIntHeapCreateOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDevmemIntHeapCreateOUT->hDevmemHeapPtr,
+ (IMG_HANDLE) hDevmemHeapPtrInt2,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDevmemIntHeapCreateOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntHeapCreate_exit;
+ }
+
+
+DevmemIntHeapCreate_exit:
+ if (psDevmemIntHeapCreateOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hDevmemHeapPtrInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hDevmemHeapPtrInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psDevmemHeapPtrInt)
+ {
+ DevmemIntHeapDestroy(psDevmemHeapPtrInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntHeapDestroy(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTHEAPDESTROY *psDevmemIntHeapDestroyIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTHEAPDESTROY *psDevmemIntHeapDestroyOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevmemHeapInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_DEVMEMINTHEAPDESTROY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntHeapDestroyOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevmemHeapInt2,
+ psDevmemIntHeapDestroyIN->hDevmemHeap,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+ if(psDevmemIntHeapDestroyOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntHeapDestroy_exit;
+ }
+
+ }
+
+ psDevmemIntHeapDestroyOUT->eError = DevmemIntHeapDestroyResManProxy(hDevmemHeapInt2);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntHeapDestroyOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntHeapDestroy_exit;
+ }
+
+ psDevmemIntHeapDestroyOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDevmemIntHeapDestroyIN->hDevmemHeap,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+
+
+DevmemIntHeapDestroy_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntMapPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTMAPPMR *psDevmemIntMapPMRIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTMAPPMR *psDevmemIntMapPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ DEVMEMINT_HEAP * psDevmemServerHeapInt = IMG_NULL;
+ IMG_HANDLE hDevmemServerHeapInt2 = IMG_NULL;
+ DEVMEMINT_RESERVATION * psReservationInt = IMG_NULL;
+ IMG_HANDLE hReservationInt2 = IMG_NULL;
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+ DEVMEMINT_MAPPING * psMappingInt = IMG_NULL;
+ IMG_HANDLE hMappingInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_DEVMEMINTMAPPMR);
+
+
+
+
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psDevmemIntMapPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevmemServerHeapInt2,
+ psDevmemIntMapPMRIN->hDevmemServerHeap,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+ if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto DevmemIntMapPMR_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemIntMapPMROUT->eError = ResManFindPrivateDataByPtr(hDevmemServerHeapInt2, (IMG_VOID **) &psDevmemServerHeapInt);
+
+ if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto DevmemIntMapPMR_exit;
+ }
+ }
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntMapPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hReservationInt2,
+ psDevmemIntMapPMRIN->hReservation,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+ if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto DevmemIntMapPMR_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemIntMapPMROUT->eError = ResManFindPrivateDataByPtr(hReservationInt2, (IMG_VOID **) &psReservationInt);
+
+ if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto DevmemIntMapPMR_exit;
+ }
+ }
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntMapPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psDevmemIntMapPMRIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto DevmemIntMapPMR_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemIntMapPMROUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto DevmemIntMapPMR_exit;
+ }
+ }
+
+ psDevmemIntMapPMROUT->eError =
+ DevmemIntMapPMR(
+ psDevmemServerHeapInt,
+ psReservationInt,
+ psPMRInt,
+ psDevmemIntMapPMRIN->uiMapFlags,
+ &psMappingInt);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntMapPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto DevmemIntMapPMR_exit;
+ }
+ PMRUnlock();
+
+ /* Create a resman item and overwrite the handle with it */
+ hMappingInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DEVICEMEM2_MAPPING,
+ psMappingInt,
+ (RESMAN_FREE_FN)&DevmemIntUnmapPMR);
+ if (hMappingInt2 == IMG_NULL)
+ {
+ psDevmemIntMapPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DevmemIntMapPMR_exit;
+ }
+ psDevmemIntMapPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDevmemIntMapPMROUT->hMapping,
+ (IMG_HANDLE) hMappingInt2,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDevmemIntMapPMROUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntMapPMR_exit;
+ }
+
+
+DevmemIntMapPMR_exit:
+ if (psDevmemIntMapPMROUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hMappingInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hMappingInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psMappingInt)
+ {
+ DevmemIntUnmapPMR(psMappingInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntUnmapPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTUNMAPPMR *psDevmemIntUnmapPMRIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTUNMAPPMR *psDevmemIntUnmapPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hMappingInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_DEVMEMINTUNMAPPMR);
+
+
+
+
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psDevmemIntUnmapPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hMappingInt2,
+ psDevmemIntUnmapPMRIN->hMapping,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING);
+ if(psDevmemIntUnmapPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto DevmemIntUnmapPMR_exit;
+ }
+
+ }
+
+ psDevmemIntUnmapPMROUT->eError = DevmemIntUnmapPMRResManProxy(hMappingInt2);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntUnmapPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto DevmemIntUnmapPMR_exit;
+ }
+ PMRUnlock();
+
+ psDevmemIntUnmapPMROUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDevmemIntUnmapPMRIN->hMapping,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING);
+
+
+DevmemIntUnmapPMR_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntReserveRange(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTRESERVERANGE *psDevmemIntReserveRangeIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTRESERVERANGE *psDevmemIntReserveRangeOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DEVMEMINT_HEAP * psDevmemServerHeapInt = IMG_NULL;
+ IMG_HANDLE hDevmemServerHeapInt2 = IMG_NULL;
+ DEVMEMINT_RESERVATION * psReservationInt = IMG_NULL;
+ IMG_HANDLE hReservationInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_DEVMEMINTRESERVERANGE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntReserveRangeOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevmemServerHeapInt2,
+ psDevmemIntReserveRangeIN->hDevmemServerHeap,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+ if(psDevmemIntReserveRangeOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntReserveRange_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemIntReserveRangeOUT->eError = ResManFindPrivateDataByPtr(hDevmemServerHeapInt2, (IMG_VOID **) &psDevmemServerHeapInt);
+
+ if(psDevmemIntReserveRangeOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntReserveRange_exit;
+ }
+ }
+
+ psDevmemIntReserveRangeOUT->eError =
+ DevmemIntReserveRange(
+ psDevmemServerHeapInt,
+ psDevmemIntReserveRangeIN->sAddress,
+ psDevmemIntReserveRangeIN->uiLength,
+ &psReservationInt);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntReserveRangeOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntReserveRange_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hReservationInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_DEVICEMEM2_RESERVATION,
+ psReservationInt,
+ (RESMAN_FREE_FN)&DevmemIntUnreserveRange);
+ if (hReservationInt2 == IMG_NULL)
+ {
+ psDevmemIntReserveRangeOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto DevmemIntReserveRange_exit;
+ }
+ psDevmemIntReserveRangeOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psDevmemIntReserveRangeOUT->hReservation,
+ (IMG_HANDLE) hReservationInt2,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psDevmemIntReserveRangeOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntReserveRange_exit;
+ }
+
+
+DevmemIntReserveRange_exit:
+ if (psDevmemIntReserveRangeOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hReservationInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hReservationInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psReservationInt)
+ {
+ DevmemIntUnreserveRange(psReservationInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntUnreserveRange(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTUNRESERVERANGE *psDevmemIntUnreserveRangeIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTUNRESERVERANGE *psDevmemIntUnreserveRangeOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hReservationInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_DEVMEMINTUNRESERVERANGE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntUnreserveRangeOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hReservationInt2,
+ psDevmemIntUnreserveRangeIN->hReservation,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+ if(psDevmemIntUnreserveRangeOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntUnreserveRange_exit;
+ }
+
+ }
+
+ psDevmemIntUnreserveRangeOUT->eError = DevmemIntUnreserveRangeResManProxy(hReservationInt2);
+ /* Exit early if bridged call fails */
+ if(psDevmemIntUnreserveRangeOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntUnreserveRange_exit;
+ }
+
+ psDevmemIntUnreserveRangeOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psDevmemIntUnreserveRangeIN->hReservation,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+
+
+DevmemIntUnreserveRange_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePhysmemNewRamBackedPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PHYSMEMNEWRAMBACKEDPMR *psPhysmemNewRamBackedPMRIN,
+ PVRSRV_BRIDGE_OUT_PHYSMEMNEWRAMBACKEDPMR *psPhysmemNewRamBackedPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+ IMG_BOOL *bMappingTableInt = IMG_NULL;
+ PMR * psPMRPtrInt = IMG_NULL;
+ IMG_HANDLE hPMRPtrInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_PHYSMEMNEWRAMBACKEDPMR);
+
+
+
+
+ if (psPhysmemNewRamBackedPMRIN->ui32NumVirtChunks != 0)
+ {
+ bMappingTableInt = OSAllocMem(psPhysmemNewRamBackedPMRIN->ui32NumVirtChunks * sizeof(IMG_BOOL));
+ if (!bMappingTableInt)
+ {
+ psPhysmemNewRamBackedPMROUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto PhysmemNewRamBackedPMR_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPhysmemNewRamBackedPMRIN->pbMappingTable, psPhysmemNewRamBackedPMRIN->ui32NumVirtChunks * sizeof(IMG_BOOL))
+ || (OSCopyFromUser(NULL, bMappingTableInt, psPhysmemNewRamBackedPMRIN->pbMappingTable,
+ psPhysmemNewRamBackedPMRIN->ui32NumVirtChunks * sizeof(IMG_BOOL)) != PVRSRV_OK) )
+ {
+ psPhysmemNewRamBackedPMROUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto PhysmemNewRamBackedPMR_exit;
+ }
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psPhysmemNewRamBackedPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psPhysmemNewRamBackedPMRIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psPhysmemNewRamBackedPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PhysmemNewRamBackedPMR_exit;
+ }
+
+ }
+
+ psPhysmemNewRamBackedPMROUT->eError =
+ PhysmemNewRamBackedPMR(
+ hDeviceNodeInt,
+ psPhysmemNewRamBackedPMRIN->uiSize,
+ psPhysmemNewRamBackedPMRIN->uiChunkSize,
+ psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks,
+ psPhysmemNewRamBackedPMRIN->ui32NumVirtChunks,
+ bMappingTableInt,
+ psPhysmemNewRamBackedPMRIN->ui32Log2PageSize,
+ psPhysmemNewRamBackedPMRIN->uiFlags,
+ &psPMRPtrInt);
+ /* Exit early if bridged call fails */
+ if(psPhysmemNewRamBackedPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PhysmemNewRamBackedPMR_exit;
+ }
+ PMRUnlock();
+
+ /* Create a resman item and overwrite the handle with it */
+ hPMRPtrInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR,
+ psPMRPtrInt,
+ (RESMAN_FREE_FN)&PMRUnrefPMR);
+ if (hPMRPtrInt2 == IMG_NULL)
+ {
+ psPhysmemNewRamBackedPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PhysmemNewRamBackedPMR_exit;
+ }
+ psPhysmemNewRamBackedPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psPhysmemNewRamBackedPMROUT->hPMRPtr,
+ (IMG_HANDLE) hPMRPtrInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psPhysmemNewRamBackedPMROUT->eError != PVRSRV_OK)
+ {
+ goto PhysmemNewRamBackedPMR_exit;
+ }
+
+
+PhysmemNewRamBackedPMR_exit:
+ if (psPhysmemNewRamBackedPMROUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPMRPtrInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPMRPtrInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPMRPtrInt)
+ {
+ PMRUnrefPMR(psPMRPtrInt);
+ }
+ }
+
+ if (bMappingTableInt)
+ OSFreeMem(bMappingTableInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRLocalImportPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRLOCALIMPORTPMR *psPMRLocalImportPMRIN,
+ PVRSRV_BRIDGE_OUT_PMRLOCALIMPORTPMR *psPMRLocalImportPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psExtHandleInt = IMG_NULL;
+ IMG_HANDLE hExtHandleInt2 = IMG_NULL;
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_PMRLOCALIMPORTPMR);
+
+
+
+
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psPMRLocalImportPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hExtHandleInt2,
+ psPMRLocalImportPMRIN->hExtHandle,
+ PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
+ if(psPMRLocalImportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRLocalImportPMR_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRLocalImportPMROUT->eError = ResManFindPrivateDataByPtr(hExtHandleInt2, (IMG_VOID **) &psExtHandleInt);
+
+ if(psPMRLocalImportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRLocalImportPMR_exit;
+ }
+ }
+
+ psPMRLocalImportPMROUT->eError =
+ PMRLocalImportPMR(
+ psExtHandleInt,
+ &psPMRInt,
+ &psPMRLocalImportPMROUT->uiSize,
+ &psPMRLocalImportPMROUT->sAlign);
+ /* Exit early if bridged call fails */
+ if(psPMRLocalImportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRLocalImportPMR_exit;
+ }
+ PMRUnlock();
+
+ /* Create a resman item and overwrite the handle with it */
+ hPMRInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR,
+ psPMRInt,
+ (RESMAN_FREE_FN)&PMRUnrefPMR);
+ if (hPMRInt2 == IMG_NULL)
+ {
+ psPMRLocalImportPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PMRLocalImportPMR_exit;
+ }
+ psPMRLocalImportPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psPMRLocalImportPMROUT->hPMR,
+ (IMG_HANDLE) hPMRInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psPMRLocalImportPMROUT->eError != PVRSRV_OK)
+ {
+ goto PMRLocalImportPMR_exit;
+ }
+
+
+PMRLocalImportPMR_exit:
+ if (psPMRLocalImportPMROUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPMRInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPMRInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPMRInt)
+ {
+ PMRUnrefPMR(psPMRInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRUnrefPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRUNREFPMR *psPMRUnrefPMRIN,
+ PVRSRV_BRIDGE_OUT_PMRUNREFPMR *psPMRUnrefPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_PMRUNREFPMR);
+
+
+
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psPMRUnrefPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRUnrefPMRIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRUnrefPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRUnrefPMR_exit;
+ }
+
+ }
+
+ psPMRUnrefPMROUT->eError = PMRUnrefPMRResManProxy(hPMRInt2);
+ /* Exit early if bridged call fails */
+ if(psPMRUnrefPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRUnrefPMR_exit;
+ }
+
+ PMRUnlock();
+
+ psPMRUnrefPMROUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psPMRUnrefPMRIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+
+
+PMRUnrefPMR_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemSLCFlushInvalRequest(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMSLCFLUSHINVALREQUEST *psDevmemSLCFlushInvalRequestIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMSLCFLUSHINVALREQUEST *psDevmemSLCFlushInvalRequestOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+ PMR * psPmrInt = IMG_NULL;
+ IMG_HANDLE hPmrInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_DEVMEMSLCFLUSHINVALREQUEST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psDevmemSLCFlushInvalRequestOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psDevmemSLCFlushInvalRequestIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psDevmemSLCFlushInvalRequestOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemSLCFlushInvalRequest_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psDevmemSLCFlushInvalRequestOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPmrInt2,
+ psDevmemSLCFlushInvalRequestIN->hPmr,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psDevmemSLCFlushInvalRequestOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemSLCFlushInvalRequest_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemSLCFlushInvalRequestOUT->eError = ResManFindPrivateDataByPtr(hPmrInt2, (IMG_VOID **) &psPmrInt);
+
+ if(psDevmemSLCFlushInvalRequestOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemSLCFlushInvalRequest_exit;
+ }
+ }
+
+ psDevmemSLCFlushInvalRequestOUT->eError =
+ DevmemSLCFlushInvalRequest(
+ hDeviceNodeInt,
+ psPmrInt);
+
+
+
+DevmemSLCFlushInvalRequest_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeHeapCfgHeapConfigCount(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_HEAPCFGHEAPCONFIGCOUNT *psHeapCfgHeapConfigCountIN,
+ PVRSRV_BRIDGE_OUT_HEAPCFGHEAPCONFIGCOUNT *psHeapCfgHeapConfigCountOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGCOUNT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psHeapCfgHeapConfigCountOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psHeapCfgHeapConfigCountIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psHeapCfgHeapConfigCountOUT->eError != PVRSRV_OK)
+ {
+ goto HeapCfgHeapConfigCount_exit;
+ }
+
+ }
+
+ psHeapCfgHeapConfigCountOUT->eError =
+ HeapCfgHeapConfigCount(
+ hDeviceNodeInt,
+ &psHeapCfgHeapConfigCountOUT->ui32NumHeapConfigs);
+
+
+
+HeapCfgHeapConfigCount_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeHeapCfgHeapCount(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_HEAPCFGHEAPCOUNT *psHeapCfgHeapCountIN,
+ PVRSRV_BRIDGE_OUT_HEAPCFGHEAPCOUNT *psHeapCfgHeapCountOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_HEAPCFGHEAPCOUNT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psHeapCfgHeapCountOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psHeapCfgHeapCountIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psHeapCfgHeapCountOUT->eError != PVRSRV_OK)
+ {
+ goto HeapCfgHeapCount_exit;
+ }
+
+ }
+
+ psHeapCfgHeapCountOUT->eError =
+ HeapCfgHeapCount(
+ hDeviceNodeInt,
+ psHeapCfgHeapCountIN->ui32HeapConfigIndex,
+ &psHeapCfgHeapCountOUT->ui32NumHeaps);
+
+
+
+HeapCfgHeapCount_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeHeapCfgHeapConfigName(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_HEAPCFGHEAPCONFIGNAME *psHeapCfgHeapConfigNameIN,
+ PVRSRV_BRIDGE_OUT_HEAPCFGHEAPCONFIGNAME *psHeapCfgHeapConfigNameOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+ IMG_CHAR *puiHeapConfigNameInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGNAME);
+
+
+ psHeapCfgHeapConfigNameOUT->puiHeapConfigName = psHeapCfgHeapConfigNameIN->puiHeapConfigName;
+
+
+ if (psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz != 0)
+ {
+ puiHeapConfigNameInt = OSAllocMem(psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR));
+ if (!puiHeapConfigNameInt)
+ {
+ psHeapCfgHeapConfigNameOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto HeapCfgHeapConfigName_exit;
+ }
+ }
+
+
+ {
+ /* Look up the address from the handle */
+ psHeapCfgHeapConfigNameOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psHeapCfgHeapConfigNameIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psHeapCfgHeapConfigNameOUT->eError != PVRSRV_OK)
+ {
+ goto HeapCfgHeapConfigName_exit;
+ }
+
+ }
+
+ psHeapCfgHeapConfigNameOUT->eError =
+ HeapCfgHeapConfigName(
+ hDeviceNodeInt,
+ psHeapCfgHeapConfigNameIN->ui32HeapConfigIndex,
+ psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz,
+ puiHeapConfigNameInt);
+
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psHeapCfgHeapConfigNameOUT->puiHeapConfigName, (psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR)))
+ || (OSCopyToUser(NULL, psHeapCfgHeapConfigNameOUT->puiHeapConfigName, puiHeapConfigNameInt,
+ (psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR))) != PVRSRV_OK) )
+ {
+ psHeapCfgHeapConfigNameOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto HeapCfgHeapConfigName_exit;
+ }
+
+
+HeapCfgHeapConfigName_exit:
+ if (puiHeapConfigNameInt)
+ OSFreeMem(puiHeapConfigNameInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeHeapCfgHeapDetails(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_HEAPCFGHEAPDETAILS *psHeapCfgHeapDetailsIN,
+ PVRSRV_BRIDGE_OUT_HEAPCFGHEAPDETAILS *psHeapCfgHeapDetailsOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+ IMG_CHAR *puiHeapNameOutInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MM_HEAPCFGHEAPDETAILS);
+
+
+ psHeapCfgHeapDetailsOUT->puiHeapNameOut = psHeapCfgHeapDetailsIN->puiHeapNameOut;
+
+
+ if (psHeapCfgHeapDetailsIN->ui32HeapNameBufSz != 0)
+ {
+ puiHeapNameOutInt = OSAllocMem(psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR));
+ if (!puiHeapNameOutInt)
+ {
+ psHeapCfgHeapDetailsOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto HeapCfgHeapDetails_exit;
+ }
+ }
+
+
+ {
+ /* Look up the address from the handle */
+ psHeapCfgHeapDetailsOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psHeapCfgHeapDetailsIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psHeapCfgHeapDetailsOUT->eError != PVRSRV_OK)
+ {
+ goto HeapCfgHeapDetails_exit;
+ }
+
+ }
+
+ psHeapCfgHeapDetailsOUT->eError =
+ HeapCfgHeapDetails(
+ hDeviceNodeInt,
+ psHeapCfgHeapDetailsIN->ui32HeapConfigIndex,
+ psHeapCfgHeapDetailsIN->ui32HeapIndex,
+ psHeapCfgHeapDetailsIN->ui32HeapNameBufSz,
+ puiHeapNameOutInt,
+ &psHeapCfgHeapDetailsOUT->sDevVAddrBase,
+ &psHeapCfgHeapDetailsOUT->uiHeapLength,
+ &psHeapCfgHeapDetailsOUT->ui32Log2DataPageSizeOut);
+
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psHeapCfgHeapDetailsOUT->puiHeapNameOut, (psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR)))
+ || (OSCopyToUser(NULL, psHeapCfgHeapDetailsOUT->puiHeapNameOut, puiHeapNameOutInt,
+ (psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR))) != PVRSRV_OK) )
+ {
+ psHeapCfgHeapDetailsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto HeapCfgHeapDetails_exit;
+ }
+
+
+HeapCfgHeapDetails_exit:
+ if (puiHeapNameOutInt)
+ OSFreeMem(puiHeapNameOutInt);
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterMMFunctions(IMG_VOID);
+IMG_VOID UnregisterMMFunctions(IMG_VOID);
+
+/*
+ * Register all MM functions with services
+ */
+PVRSRV_ERROR RegisterMMFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_PMREXPORTPMR, PVRSRVBridgePMRExportPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_PMRUNEXPORTPMR, PVRSRVBridgePMRUnexportPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_PMRGETUID, PVRSRVBridgePMRGetUID);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_PMRMAKESERVEREXPORTCLIENTEXPORT, PVRSRVBridgePMRMakeServerExportClientExport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_PMRUNMAKESERVEREXPORTCLIENTEXPORT, PVRSRVBridgePMRUnmakeServerExportClientExport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_PMRIMPORTPMR, PVRSRVBridgePMRImportPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_DEVMEMINTCTXCREATE, PVRSRVBridgeDevmemIntCtxCreate);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_DEVMEMINTCTXDESTROY, PVRSRVBridgeDevmemIntCtxDestroy);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_DEVMEMINTHEAPCREATE, PVRSRVBridgeDevmemIntHeapCreate);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_DEVMEMINTHEAPDESTROY, PVRSRVBridgeDevmemIntHeapDestroy);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_DEVMEMINTMAPPMR, PVRSRVBridgeDevmemIntMapPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_DEVMEMINTUNMAPPMR, PVRSRVBridgeDevmemIntUnmapPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_DEVMEMINTRESERVERANGE, PVRSRVBridgeDevmemIntReserveRange);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_DEVMEMINTUNRESERVERANGE, PVRSRVBridgeDevmemIntUnreserveRange);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_PHYSMEMNEWRAMBACKEDPMR, PVRSRVBridgePhysmemNewRamBackedPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_PMRLOCALIMPORTPMR, PVRSRVBridgePMRLocalImportPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_PMRUNREFPMR, PVRSRVBridgePMRUnrefPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_DEVMEMSLCFLUSHINVALREQUEST, PVRSRVBridgeDevmemSLCFlushInvalRequest);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGCOUNT, PVRSRVBridgeHeapCfgHeapConfigCount);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_HEAPCFGHEAPCOUNT, PVRSRVBridgeHeapCfgHeapCount);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGNAME, PVRSRVBridgeHeapCfgHeapConfigName);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MM_HEAPCFGHEAPDETAILS, PVRSRVBridgeHeapCfgHeapDetails);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all mm functions with services
+ */
+IMG_VOID UnregisterMMFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/pdump_bridge/common_pdump_bridge.h b/drivers/gpu/rogue/generated/pdump_bridge/common_pdump_bridge.h
new file mode 100644
index 000000000000..a2bedfad158d
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pdump_bridge/common_pdump_bridge.h
@@ -0,0 +1,208 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for pdump
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for pdump
+@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_PDUMP_BRIDGE_H
+#define COMMON_PDUMP_BRIDGE_H
+
+#include "services.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST (PVRSRV_BRIDGE_PDUMP_START)
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPISCAPTURING PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPCOMMENT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSETFRAME PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPGETFRAME PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPISLASTCAPTUREFRAME PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSTARTINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSTOPINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)
+
+
+/*******************************************
+ PVRSRVPDumpIsCapturing
+ *******************************************/
+
+/* Bridge in structure for PVRSRVPDumpIsCapturing */
+typedef struct PVRSRV_BRIDGE_IN_PVRSRVPDUMPISCAPTURING_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PVRSRVPDUMPISCAPTURING;
+
+
+/* Bridge out structure for PVRSRVPDumpIsCapturing */
+typedef struct PVRSRV_BRIDGE_OUT_PVRSRVPDUMPISCAPTURING_TAG
+{
+ IMG_BOOL bIsCapturing;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PVRSRVPDUMPISCAPTURING;
+
+/*******************************************
+ PVRSRVPDumpComment
+ *******************************************/
+
+/* Bridge in structure for PVRSRVPDumpComment */
+typedef struct PVRSRV_BRIDGE_IN_PVRSRVPDUMPCOMMENT_TAG
+{
+ IMG_CHAR * puiComment;
+ IMG_UINT32 ui32Flags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PVRSRVPDUMPCOMMENT;
+
+
+/* Bridge out structure for PVRSRVPDumpComment */
+typedef struct PVRSRV_BRIDGE_OUT_PVRSRVPDUMPCOMMENT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PVRSRVPDUMPCOMMENT;
+
+/*******************************************
+ PVRSRVPDumpSetFrame
+ *******************************************/
+
+/* Bridge in structure for PVRSRVPDumpSetFrame */
+typedef struct PVRSRV_BRIDGE_IN_PVRSRVPDUMPSETFRAME_TAG
+{
+ IMG_UINT32 ui32Frame;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PVRSRVPDUMPSETFRAME;
+
+
+/* Bridge out structure for PVRSRVPDumpSetFrame */
+typedef struct PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSETFRAME_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSETFRAME;
+
+/*******************************************
+ PVRSRVPDumpGetFrame
+ *******************************************/
+
+/* Bridge in structure for PVRSRVPDumpGetFrame */
+typedef struct PVRSRV_BRIDGE_IN_PVRSRVPDUMPGETFRAME_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PVRSRVPDUMPGETFRAME;
+
+
+/* Bridge out structure for PVRSRVPDumpGetFrame */
+typedef struct PVRSRV_BRIDGE_OUT_PVRSRVPDUMPGETFRAME_TAG
+{
+ IMG_UINT32 ui32Frame;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PVRSRVPDUMPGETFRAME;
+
+/*******************************************
+ PVRSRVPDumpSetDefaultCaptureParams
+ *******************************************/
+
+/* Bridge in structure for PVRSRVPDumpSetDefaultCaptureParams */
+typedef struct PVRSRV_BRIDGE_IN_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS_TAG
+{
+ IMG_UINT32 ui32Mode;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32End;
+ IMG_UINT32 ui32Interval;
+ IMG_UINT32 ui32MaxParamFileSize;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS;
+
+
+/* Bridge out structure for PVRSRVPDumpSetDefaultCaptureParams */
+typedef struct PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS;
+
+/*******************************************
+ PVRSRVPDumpIsLastCaptureFrame
+ *******************************************/
+
+/* Bridge in structure for PVRSRVPDumpIsLastCaptureFrame */
+typedef struct PVRSRV_BRIDGE_IN_PVRSRVPDUMPISLASTCAPTUREFRAME_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PVRSRVPDUMPISLASTCAPTUREFRAME;
+
+
+/* Bridge out structure for PVRSRVPDumpIsLastCaptureFrame */
+typedef struct PVRSRV_BRIDGE_OUT_PVRSRVPDUMPISLASTCAPTUREFRAME_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PVRSRVPDUMPISLASTCAPTUREFRAME;
+
+/*******************************************
+ PVRSRVPDumpStartInitPhase
+ *******************************************/
+
+/* Bridge in structure for PVRSRVPDumpStartInitPhase */
+typedef struct PVRSRV_BRIDGE_IN_PVRSRVPDUMPSTARTINITPHASE_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PVRSRVPDUMPSTARTINITPHASE;
+
+
+/* Bridge out structure for PVRSRVPDumpStartInitPhase */
+typedef struct PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSTARTINITPHASE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSTARTINITPHASE;
+
+/*******************************************
+ PVRSRVPDumpStopInitPhase
+ *******************************************/
+
+/* Bridge in structure for PVRSRVPDumpStopInitPhase */
+typedef struct PVRSRV_BRIDGE_IN_PVRSRVPDUMPSTOPINITPHASE_TAG
+{
+ IMG_MODULE_ID eModuleID;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PVRSRVPDUMPSTOPINITPHASE;
+
+
+/* Bridge out structure for PVRSRVPDumpStopInitPhase */
+typedef struct PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSTOPINITPHASE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSTOPINITPHASE;
+
+#endif /* COMMON_PDUMP_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/pdump_bridge/server_pdump_bridge.c b/drivers/gpu/rogue/generated/pdump_bridge/server_pdump_bridge.c
new file mode 100644
index 000000000000..ef38d519ee8e
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pdump_bridge/server_pdump_bridge.c
@@ -0,0 +1,332 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for pdump
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for pdump
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "pdump_km.h"
+
+
+#include "common_pdump_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgePVRSRVPDumpIsCapturing(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PVRSRVPDUMPISCAPTURING *psPVRSRVPDumpIsCapturingIN,
+ PVRSRV_BRIDGE_OUT_PVRSRVPDUMPISCAPTURING *psPVRSRVPDumpIsCapturingOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPISCAPTURING);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(psPVRSRVPDumpIsCapturingIN);
+
+
+
+
+ psPVRSRVPDumpIsCapturingOUT->eError =
+ PDumpIsCaptureFrameKM(
+ &psPVRSRVPDumpIsCapturingOUT->bIsCapturing);
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePVRSRVPDumpComment(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PVRSRVPDUMPCOMMENT *psPVRSRVPDumpCommentIN,
+ PVRSRV_BRIDGE_OUT_PVRSRVPDUMPCOMMENT *psPVRSRVPDumpCommentOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_CHAR *uiCommentInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPCOMMENT);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ {
+ uiCommentInt = OSAllocMem(PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR));
+ if (!uiCommentInt)
+ {
+ psPVRSRVPDumpCommentOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto PVRSRVPDumpComment_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPVRSRVPDumpCommentIN->puiComment, PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR))
+ || (OSCopyFromUser(NULL, uiCommentInt, psPVRSRVPDumpCommentIN->puiComment,
+ PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+ {
+ psPVRSRVPDumpCommentOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto PVRSRVPDumpComment_exit;
+ }
+
+ psPVRSRVPDumpCommentOUT->eError =
+ PDumpCommentKM(
+ uiCommentInt,
+ psPVRSRVPDumpCommentIN->ui32Flags);
+
+
+
+PVRSRVPDumpComment_exit:
+ if (uiCommentInt)
+ OSFreeMem(uiCommentInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePVRSRVPDumpSetFrame(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PVRSRVPDUMPSETFRAME *psPVRSRVPDumpSetFrameIN,
+ PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSETFRAME *psPVRSRVPDumpSetFrameOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSETFRAME);
+
+
+
+
+
+ psPVRSRVPDumpSetFrameOUT->eError =
+ PDumpSetFrameKM(psConnection,
+ psPVRSRVPDumpSetFrameIN->ui32Frame);
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePVRSRVPDumpGetFrame(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PVRSRVPDUMPGETFRAME *psPVRSRVPDumpGetFrameIN,
+ PVRSRV_BRIDGE_OUT_PVRSRVPDUMPGETFRAME *psPVRSRVPDumpGetFrameOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPGETFRAME);
+
+ PVR_UNREFERENCED_PARAMETER(psPVRSRVPDumpGetFrameIN);
+
+
+
+
+ psPVRSRVPDumpGetFrameOUT->eError =
+ PDumpGetFrameKM(psConnection,
+ &psPVRSRVPDumpGetFrameOUT->ui32Frame);
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePVRSRVPDumpSetDefaultCaptureParams(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS *psPVRSRVPDumpSetDefaultCaptureParamsIN,
+ PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS *psPVRSRVPDumpSetDefaultCaptureParamsOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ psPVRSRVPDumpSetDefaultCaptureParamsOUT->eError =
+ PDumpSetDefaultCaptureParamsKM(
+ psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32Mode,
+ psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32Start,
+ psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32End,
+ psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32Interval,
+ psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32MaxParamFileSize);
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePVRSRVPDumpIsLastCaptureFrame(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PVRSRVPDUMPISLASTCAPTUREFRAME *psPVRSRVPDumpIsLastCaptureFrameIN,
+ PVRSRV_BRIDGE_OUT_PVRSRVPDUMPISLASTCAPTUREFRAME *psPVRSRVPDumpIsLastCaptureFrameOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPISLASTCAPTUREFRAME);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(psPVRSRVPDumpIsLastCaptureFrameIN);
+
+
+
+
+ psPVRSRVPDumpIsLastCaptureFrameOUT->eError =
+ PDumpIsLastCaptureFrameKM(
+ );
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePVRSRVPDumpStartInitPhase(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PVRSRVPDUMPSTARTINITPHASE *psPVRSRVPDumpStartInitPhaseIN,
+ PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSTARTINITPHASE *psPVRSRVPDumpStartInitPhaseOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSTARTINITPHASE);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(psPVRSRVPDumpStartInitPhaseIN);
+
+
+
+
+ psPVRSRVPDumpStartInitPhaseOUT->eError =
+ PDumpStartInitPhaseKM(
+ );
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePVRSRVPDumpStopInitPhase(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PVRSRVPDUMPSTOPINITPHASE *psPVRSRVPDumpStopInitPhaseIN,
+ PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSTOPINITPHASE *psPVRSRVPDumpStopInitPhaseOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSTOPINITPHASE);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ psPVRSRVPDumpStopInitPhaseOUT->eError =
+ PDumpStopInitPhaseKM(
+ psPVRSRVPDumpStopInitPhaseIN->eModuleID);
+
+
+
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterPDUMPFunctions(IMG_VOID);
+IMG_VOID UnregisterPDUMPFunctions(IMG_VOID);
+
+/*
+ * Register all PDUMP functions with services
+ */
+PVRSRV_ERROR RegisterPDUMPFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPISCAPTURING, PVRSRVBridgePVRSRVPDumpIsCapturing);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPCOMMENT, PVRSRVBridgePVRSRVPDumpComment);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSETFRAME, PVRSRVBridgePVRSRVPDumpSetFrame);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPGETFRAME, PVRSRVBridgePVRSRVPDumpGetFrame);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS, PVRSRVBridgePVRSRVPDumpSetDefaultCaptureParams);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPISLASTCAPTUREFRAME, PVRSRVBridgePVRSRVPDumpIsLastCaptureFrame);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSTARTINITPHASE, PVRSRVBridgePVRSRVPDumpStartInitPhase);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSTOPINITPHASE, PVRSRVBridgePVRSRVPDumpStopInitPhase);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all pdump functions with services
+ */
+IMG_VOID UnregisterPDUMPFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/pdumpcmm_bridge/common_pdumpcmm_bridge.h b/drivers/gpu/rogue/generated/pdumpcmm_bridge/common_pdumpcmm_bridge.h
new file mode 100644
index 000000000000..8ca4936192b9
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pdumpcmm_bridge/common_pdumpcmm_bridge.h
@@ -0,0 +1,87 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for pdumpcmm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for pdumpcmm
+@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_PDUMPCMM_BRIDGE_H
+#define COMMON_PDUMPCMM_BRIDGE_H
+
+#include "devicemem_typedefs.h"
+#include "pdumpdefs.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_PDUMPCMM_CMD_FIRST (PVRSRV_BRIDGE_PDUMPCMM_START)
+#define PVRSRV_BRIDGE_PDUMPCMM_DEVMEMPDUMPBITMAP PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMPCMM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_PDUMPCMM_CMD_LAST (PVRSRV_BRIDGE_PDUMPCMM_CMD_FIRST+0)
+
+
+/*******************************************
+ DevmemPDumpBitmap
+ *******************************************/
+
+/* Bridge in structure for DevmemPDumpBitmap */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMPDUMPBITMAP_TAG
+{
+ IMG_HANDLE hDeviceNode;
+ 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;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMPDUMPBITMAP;
+
+
+/* Bridge out structure for DevmemPDumpBitmap */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMPDUMPBITMAP_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMPDUMPBITMAP;
+
+#endif /* COMMON_PDUMPCMM_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/pdumpcmm_bridge/server_pdumpcmm_bridge.c b/drivers/gpu/rogue/generated/pdumpcmm_bridge/server_pdumpcmm_bridge.c
new file mode 100644
index 000000000000..ee37ac7866cf
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pdumpcmm_bridge/server_pdumpcmm_bridge.c
@@ -0,0 +1,198 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for pdumpcmm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for pdumpcmm
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "devicemem_server.h"
+
+
+#include "common_pdumpcmm_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeDevmemPDumpBitmap(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMPDUMPBITMAP *psDevmemPDumpBitmapIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMPDUMPBITMAP *psDevmemPDumpBitmapOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+ IMG_CHAR *uiFileNameInt = IMG_NULL;
+ DEVMEMINT_CTX * psDevmemCtxInt = IMG_NULL;
+ IMG_HANDLE hDevmemCtxInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMPCMM_DEVMEMPDUMPBITMAP);
+
+
+
+
+
+ {
+ uiFileNameInt = OSAllocMem(PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR));
+ if (!uiFileNameInt)
+ {
+ psDevmemPDumpBitmapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DevmemPDumpBitmap_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDevmemPDumpBitmapIN->puiFileName, PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR))
+ || (OSCopyFromUser(NULL, uiFileNameInt, psDevmemPDumpBitmapIN->puiFileName,
+ PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+ {
+ psDevmemPDumpBitmapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DevmemPDumpBitmap_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psDevmemPDumpBitmapOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psDevmemPDumpBitmapIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psDevmemPDumpBitmapOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemPDumpBitmap_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psDevmemPDumpBitmapOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevmemCtxInt2,
+ psDevmemPDumpBitmapIN->hDevmemCtx,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+ if(psDevmemPDumpBitmapOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemPDumpBitmap_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemPDumpBitmapOUT->eError = ResManFindPrivateDataByPtr(hDevmemCtxInt2, (IMG_VOID **) &psDevmemCtxInt);
+
+ if(psDevmemPDumpBitmapOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemPDumpBitmap_exit;
+ }
+ }
+
+ psDevmemPDumpBitmapOUT->eError =
+ DevmemIntPDumpBitmap(
+ hDeviceNodeInt,
+ uiFileNameInt,
+ psDevmemPDumpBitmapIN->ui32FileOffset,
+ psDevmemPDumpBitmapIN->ui32Width,
+ psDevmemPDumpBitmapIN->ui32Height,
+ psDevmemPDumpBitmapIN->ui32StrideInBytes,
+ psDevmemPDumpBitmapIN->sDevBaseAddr,
+ psDevmemCtxInt,
+ psDevmemPDumpBitmapIN->ui32Size,
+ psDevmemPDumpBitmapIN->ePixelFormat,
+ psDevmemPDumpBitmapIN->ui32AddrMode,
+ psDevmemPDumpBitmapIN->ui32PDumpFlags);
+
+
+
+DevmemPDumpBitmap_exit:
+ if (uiFileNameInt)
+ OSFreeMem(uiFileNameInt);
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterPDUMPCMMFunctions(IMG_VOID);
+IMG_VOID UnregisterPDUMPCMMFunctions(IMG_VOID);
+
+/*
+ * Register all PDUMPCMM functions with services
+ */
+PVRSRV_ERROR RegisterPDUMPCMMFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPCMM_DEVMEMPDUMPBITMAP, PVRSRVBridgeDevmemPDumpBitmap);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all pdumpcmm functions with services
+ */
+IMG_VOID UnregisterPDUMPCMMFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/pdumpmm_bridge/client_pdumpmm_bridge.h b/drivers/gpu/rogue/generated/pdumpmm_bridge/client_pdumpmm_bridge.h
new file mode 100644
index 000000000000..fdcabc846085
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pdumpmm_bridge/client_pdumpmm_bridge.h
@@ -0,0 +1,113 @@
+/*************************************************************************/ /*!
+@File
+@Title Client bridge header for pdumpmm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Exports the client bridge functions for pdumpmm
+@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 CLIENT_PDUMPMM_BRIDGE_H
+#define CLIENT_PDUMPMM_BRIDGE_H
+
+#include "pvr_bridge_client.h"
+#include "pvr_bridge.h"
+
+#include "common_pdumpmm_bridge.h"
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpLoadMem(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_BOOL bbZero);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpLoadMemValue32(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32PDumpFlags);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpLoadMemValue64(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT64 ui64Value,
+ IMG_UINT32 ui32PDumpFlags);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpSaveToFile(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 ui32ArraySize,
+ const IMG_CHAR *puiFileName);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpSymbolicAddr(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32MemspaceNameLen,
+ IMG_CHAR *puiMemspaceName,
+ IMG_UINT32 ui32SymbolicAddrLen,
+ IMG_CHAR *puiSymbolicAddr,
+ IMG_DEVMEM_OFFSET_T *puiNewOffset,
+ IMG_DEVMEM_OFFSET_T *puiNextSymName);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpPol32(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32PDumpFlags);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgePMRPDumpCBP(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeDevmemIntPDumpSaveToFileVirtual(IMG_HANDLE hBridge,
+ IMG_HANDLE hDevmemServerContext,
+ IMG_DEV_VIRTADDR sAddress,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 ui32ArraySize,
+ const IMG_CHAR *puiFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32PDumpFlags);
+
+
+#endif /* CLIENT_PDUMPMM_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/pdumpmm_bridge/common_pdumpmm_bridge.h b/drivers/gpu/rogue/generated/pdumpmm_bridge/common_pdumpmm_bridge.h
new file mode 100644
index 000000000000..cb6b3b404156
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pdumpmm_bridge/common_pdumpmm_bridge.h
@@ -0,0 +1,244 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for pdumpmm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for pdumpmm
+@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_PDUMPMM_BRIDGE_H
+#define COMMON_PDUMPMM_BRIDGE_H
+
+#include "pdump.h"
+#include "pdumpdefs.h"
+#include "pvrsrv_memallocflags.h"
+#include "devicemem_typedefs.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST (PVRSRV_BRIDGE_PDUMPMM_START)
+#define PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEM PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEMVALUE32 PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEMVALUE64 PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPSAVETOFILE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPSYMBOLICADDR PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPPOL32 PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPCBP PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_PDUMPMM_DEVMEMINTPDUMPSAVETOFILEVIRTUAL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_PDUMPMM_CMD_LAST (PVRSRV_BRIDGE_PDUMPMM_CMD_FIRST+7)
+
+
+/*******************************************
+ PMRPDumpLoadMem
+ *******************************************/
+
+/* Bridge in structure for PMRPDumpLoadMem */
+typedef struct PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEM_TAG
+{
+ IMG_HANDLE hPMR;
+ IMG_DEVMEM_OFFSET_T uiOffset;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_UINT32 ui32PDumpFlags;
+ IMG_BOOL bbZero;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEM;
+
+
+/* Bridge out structure for PMRPDumpLoadMem */
+typedef struct PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEM_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEM;
+
+/*******************************************
+ PMRPDumpLoadMemValue32
+ *******************************************/
+
+/* Bridge in structure for PMRPDumpLoadMemValue32 */
+typedef struct PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEMVALUE32_TAG
+{
+ IMG_HANDLE hPMR;
+ IMG_DEVMEM_OFFSET_T uiOffset;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32PDumpFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEMVALUE32;
+
+
+/* Bridge out structure for PMRPDumpLoadMemValue32 */
+typedef struct PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEMVALUE32_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEMVALUE32;
+
+/*******************************************
+ PMRPDumpLoadMemValue64
+ *******************************************/
+
+/* Bridge in structure for PMRPDumpLoadMemValue64 */
+typedef struct PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEMVALUE64_TAG
+{
+ IMG_HANDLE hPMR;
+ IMG_DEVMEM_OFFSET_T uiOffset;
+ IMG_UINT64 ui64Value;
+ IMG_UINT32 ui32PDumpFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEMVALUE64;
+
+
+/* Bridge out structure for PMRPDumpLoadMemValue64 */
+typedef struct PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEMVALUE64_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEMVALUE64;
+
+/*******************************************
+ PMRPDumpSaveToFile
+ *******************************************/
+
+/* Bridge in structure for PMRPDumpSaveToFile */
+typedef struct PVRSRV_BRIDGE_IN_PMRPDUMPSAVETOFILE_TAG
+{
+ IMG_HANDLE hPMR;
+ IMG_DEVMEM_OFFSET_T uiOffset;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_UINT32 ui32ArraySize;
+ const IMG_CHAR * puiFileName;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRPDUMPSAVETOFILE;
+
+
+/* Bridge out structure for PMRPDumpSaveToFile */
+typedef struct PVRSRV_BRIDGE_OUT_PMRPDUMPSAVETOFILE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRPDUMPSAVETOFILE;
+
+/*******************************************
+ PMRPDumpSymbolicAddr
+ *******************************************/
+
+/* Bridge in structure for PMRPDumpSymbolicAddr */
+typedef struct PVRSRV_BRIDGE_IN_PMRPDUMPSYMBOLICADDR_TAG
+{
+ IMG_HANDLE hPMR;
+ IMG_DEVMEM_OFFSET_T uiOffset;
+ IMG_UINT32 ui32MemspaceNameLen;
+ IMG_UINT32 ui32SymbolicAddrLen;
+ /* Output pointer puiMemspaceName is also an implied input */
+ IMG_CHAR * puiMemspaceName;
+ /* Output pointer puiSymbolicAddr is also an implied input */
+ IMG_CHAR * puiSymbolicAddr;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRPDUMPSYMBOLICADDR;
+
+
+/* Bridge out structure for PMRPDumpSymbolicAddr */
+typedef struct PVRSRV_BRIDGE_OUT_PMRPDUMPSYMBOLICADDR_TAG
+{
+ IMG_CHAR * puiMemspaceName;
+ IMG_CHAR * puiSymbolicAddr;
+ IMG_DEVMEM_OFFSET_T uiNewOffset;
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRPDUMPSYMBOLICADDR;
+
+/*******************************************
+ PMRPDumpPol32
+ *******************************************/
+
+/* Bridge in structure for PMRPDumpPol32 */
+typedef struct PVRSRV_BRIDGE_IN_PMRPDUMPPOL32_TAG
+{
+ IMG_HANDLE hPMR;
+ IMG_DEVMEM_OFFSET_T uiOffset;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+ PDUMP_POLL_OPERATOR eOperator;
+ IMG_UINT32 ui32PDumpFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRPDUMPPOL32;
+
+
+/* Bridge out structure for PMRPDumpPol32 */
+typedef struct PVRSRV_BRIDGE_OUT_PMRPDUMPPOL32_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRPDUMPPOL32;
+
+/*******************************************
+ PMRPDumpCBP
+ *******************************************/
+
+/* Bridge in structure for PMRPDumpCBP */
+typedef struct PVRSRV_BRIDGE_IN_PMRPDUMPCBP_TAG
+{
+ IMG_HANDLE hPMR;
+ IMG_DEVMEM_OFFSET_T uiReadOffset;
+ IMG_DEVMEM_OFFSET_T uiWriteOffset;
+ IMG_DEVMEM_SIZE_T uiPacketSize;
+ IMG_DEVMEM_SIZE_T uiBufferSize;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRPDUMPCBP;
+
+
+/* Bridge out structure for PMRPDumpCBP */
+typedef struct PVRSRV_BRIDGE_OUT_PMRPDUMPCBP_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRPDUMPCBP;
+
+/*******************************************
+ DevmemIntPDumpSaveToFileVirtual
+ *******************************************/
+
+/* Bridge in structure for DevmemIntPDumpSaveToFileVirtual */
+typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTPDUMPSAVETOFILEVIRTUAL_TAG
+{
+ IMG_HANDLE hDevmemServerContext;
+ IMG_DEV_VIRTADDR sAddress;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_UINT32 ui32ArraySize;
+ const IMG_CHAR * puiFileName;
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32PDumpFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DEVMEMINTPDUMPSAVETOFILEVIRTUAL;
+
+
+/* Bridge out structure for DevmemIntPDumpSaveToFileVirtual */
+typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTPDUMPSAVETOFILEVIRTUAL_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DEVMEMINTPDUMPSAVETOFILEVIRTUAL;
+
+#endif /* COMMON_PDUMPMM_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/pdumpmm_bridge/server_pdumpmm_bridge.c b/drivers/gpu/rogue/generated/pdumpmm_bridge/server_pdumpmm_bridge.c
new file mode 100644
index 000000000000..f8df65557760
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pdumpmm_bridge/server_pdumpmm_bridge.c
@@ -0,0 +1,617 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for pdumpmm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for pdumpmm
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "devicemem_server.h"
+#include "pmr.h"
+#include "physmem.h"
+
+
+#include "common_pdumpmm_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgePMRPDumpLoadMem(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEM *psPMRPDumpLoadMemIN,
+ PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEM *psPMRPDumpLoadMemOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEM);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRPDumpLoadMemOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRPDumpLoadMemIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRPDumpLoadMemOUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpLoadMem_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRPDumpLoadMemOUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRPDumpLoadMemOUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpLoadMem_exit;
+ }
+ }
+
+ psPMRPDumpLoadMemOUT->eError =
+ PMRPDumpLoadMem(
+ psPMRInt,
+ psPMRPDumpLoadMemIN->uiOffset,
+ psPMRPDumpLoadMemIN->uiSize,
+ psPMRPDumpLoadMemIN->ui32PDumpFlags,
+ psPMRPDumpLoadMemIN->bbZero);
+
+
+
+PMRPDumpLoadMem_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRPDumpLoadMemValue32(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEMVALUE32 *psPMRPDumpLoadMemValue32IN,
+ PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEMVALUE32 *psPMRPDumpLoadMemValue32OUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEMVALUE32);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRPDumpLoadMemValue32OUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRPDumpLoadMemValue32IN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRPDumpLoadMemValue32OUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpLoadMemValue32_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRPDumpLoadMemValue32OUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRPDumpLoadMemValue32OUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpLoadMemValue32_exit;
+ }
+ }
+
+ psPMRPDumpLoadMemValue32OUT->eError =
+ PMRPDumpLoadMemValue32(
+ psPMRInt,
+ psPMRPDumpLoadMemValue32IN->uiOffset,
+ psPMRPDumpLoadMemValue32IN->ui32Value,
+ psPMRPDumpLoadMemValue32IN->ui32PDumpFlags);
+
+
+
+PMRPDumpLoadMemValue32_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRPDumpLoadMemValue64(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRPDUMPLOADMEMVALUE64 *psPMRPDumpLoadMemValue64IN,
+ PVRSRV_BRIDGE_OUT_PMRPDUMPLOADMEMVALUE64 *psPMRPDumpLoadMemValue64OUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEMVALUE64);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRPDumpLoadMemValue64OUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRPDumpLoadMemValue64IN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRPDumpLoadMemValue64OUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpLoadMemValue64_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRPDumpLoadMemValue64OUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRPDumpLoadMemValue64OUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpLoadMemValue64_exit;
+ }
+ }
+
+ psPMRPDumpLoadMemValue64OUT->eError =
+ PMRPDumpLoadMemValue64(
+ psPMRInt,
+ psPMRPDumpLoadMemValue64IN->uiOffset,
+ psPMRPDumpLoadMemValue64IN->ui64Value,
+ psPMRPDumpLoadMemValue64IN->ui32PDumpFlags);
+
+
+
+PMRPDumpLoadMemValue64_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRPDumpSaveToFile(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRPDUMPSAVETOFILE *psPMRPDumpSaveToFileIN,
+ PVRSRV_BRIDGE_OUT_PMRPDUMPSAVETOFILE *psPMRPDumpSaveToFileOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+ IMG_CHAR *uiFileNameInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPSAVETOFILE);
+
+
+
+
+ if (psPMRPDumpSaveToFileIN->ui32ArraySize != 0)
+ {
+ uiFileNameInt = OSAllocMem(psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR));
+ if (!uiFileNameInt)
+ {
+ psPMRPDumpSaveToFileOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto PMRPDumpSaveToFile_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPMRPDumpSaveToFileIN->puiFileName, psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR))
+ || (OSCopyFromUser(NULL, uiFileNameInt, psPMRPDumpSaveToFileIN->puiFileName,
+ psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+ {
+ psPMRPDumpSaveToFileOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto PMRPDumpSaveToFile_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psPMRPDumpSaveToFileOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRPDumpSaveToFileIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRPDumpSaveToFileOUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpSaveToFile_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRPDumpSaveToFileOUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRPDumpSaveToFileOUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpSaveToFile_exit;
+ }
+ }
+
+ psPMRPDumpSaveToFileOUT->eError =
+ PMRPDumpSaveToFile(
+ psPMRInt,
+ psPMRPDumpSaveToFileIN->uiOffset,
+ psPMRPDumpSaveToFileIN->uiSize,
+ psPMRPDumpSaveToFileIN->ui32ArraySize,
+ uiFileNameInt);
+
+
+
+PMRPDumpSaveToFile_exit:
+ if (uiFileNameInt)
+ OSFreeMem(uiFileNameInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRPDumpSymbolicAddr(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRPDUMPSYMBOLICADDR *psPMRPDumpSymbolicAddrIN,
+ PVRSRV_BRIDGE_OUT_PMRPDUMPSYMBOLICADDR *psPMRPDumpSymbolicAddrOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+ IMG_CHAR *puiMemspaceNameInt = IMG_NULL;
+ IMG_CHAR *puiSymbolicAddrInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPSYMBOLICADDR);
+
+
+ psPMRPDumpSymbolicAddrOUT->puiMemspaceName = psPMRPDumpSymbolicAddrIN->puiMemspaceName;
+ psPMRPDumpSymbolicAddrOUT->puiSymbolicAddr = psPMRPDumpSymbolicAddrIN->puiSymbolicAddr;
+
+
+ if (psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen != 0)
+ {
+ puiMemspaceNameInt = OSAllocMem(psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR));
+ if (!puiMemspaceNameInt)
+ {
+ psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto PMRPDumpSymbolicAddr_exit;
+ }
+ }
+
+ if (psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen != 0)
+ {
+ puiSymbolicAddrInt = OSAllocMem(psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR));
+ if (!puiSymbolicAddrInt)
+ {
+ psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto PMRPDumpSymbolicAddr_exit;
+ }
+ }
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRPDumpSymbolicAddrOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRPDumpSymbolicAddrIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRPDumpSymbolicAddrOUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpSymbolicAddr_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRPDumpSymbolicAddrOUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRPDumpSymbolicAddrOUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpSymbolicAddr_exit;
+ }
+ }
+
+ psPMRPDumpSymbolicAddrOUT->eError =
+ PMR_PDumpSymbolicAddr(
+ psPMRInt,
+ psPMRPDumpSymbolicAddrIN->uiOffset,
+ psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen,
+ puiMemspaceNameInt,
+ psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen,
+ puiSymbolicAddrInt,
+ &psPMRPDumpSymbolicAddrOUT->uiNewOffset,
+ &psPMRPDumpSymbolicAddrOUT->uiNextSymName);
+
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psPMRPDumpSymbolicAddrOUT->puiMemspaceName, (psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR)))
+ || (OSCopyToUser(NULL, psPMRPDumpSymbolicAddrOUT->puiMemspaceName, puiMemspaceNameInt,
+ (psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR))) != PVRSRV_OK) )
+ {
+ psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto PMRPDumpSymbolicAddr_exit;
+ }
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psPMRPDumpSymbolicAddrOUT->puiSymbolicAddr, (psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR)))
+ || (OSCopyToUser(NULL, psPMRPDumpSymbolicAddrOUT->puiSymbolicAddr, puiSymbolicAddrInt,
+ (psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR))) != PVRSRV_OK) )
+ {
+ psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto PMRPDumpSymbolicAddr_exit;
+ }
+
+
+PMRPDumpSymbolicAddr_exit:
+ if (puiMemspaceNameInt)
+ OSFreeMem(puiMemspaceNameInt);
+ if (puiSymbolicAddrInt)
+ OSFreeMem(puiSymbolicAddrInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRPDumpPol32(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRPDUMPPOL32 *psPMRPDumpPol32IN,
+ PVRSRV_BRIDGE_OUT_PMRPDUMPPOL32 *psPMRPDumpPol32OUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPPOL32);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRPDumpPol32OUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRPDumpPol32IN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRPDumpPol32OUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpPol32_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRPDumpPol32OUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRPDumpPol32OUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpPol32_exit;
+ }
+ }
+
+ psPMRPDumpPol32OUT->eError =
+ PMRPDumpPol32(
+ psPMRInt,
+ psPMRPDumpPol32IN->uiOffset,
+ psPMRPDumpPol32IN->ui32Value,
+ psPMRPDumpPol32IN->ui32Mask,
+ psPMRPDumpPol32IN->eOperator,
+ psPMRPDumpPol32IN->ui32PDumpFlags);
+
+
+
+PMRPDumpPol32_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRPDumpCBP(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRPDUMPCBP *psPMRPDumpCBPIN,
+ PVRSRV_BRIDGE_OUT_PMRPDUMPCBP *psPMRPDumpCBPOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPCBP);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPMRPDumpCBPOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRPDumpCBPIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRPDumpCBPOUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpCBP_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRPDumpCBPOUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRPDumpCBPOUT->eError != PVRSRV_OK)
+ {
+ goto PMRPDumpCBP_exit;
+ }
+ }
+
+ psPMRPDumpCBPOUT->eError =
+ PMRPDumpCBP(
+ psPMRInt,
+ psPMRPDumpCBPIN->uiReadOffset,
+ psPMRPDumpCBPIN->uiWriteOffset,
+ psPMRPDumpCBPIN->uiPacketSize,
+ psPMRPDumpCBPIN->uiBufferSize);
+
+
+
+PMRPDumpCBP_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDevmemIntPDumpSaveToFileVirtual(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DEVMEMINTPDUMPSAVETOFILEVIRTUAL *psDevmemIntPDumpSaveToFileVirtualIN,
+ PVRSRV_BRIDGE_OUT_DEVMEMINTPDUMPSAVETOFILEVIRTUAL *psDevmemIntPDumpSaveToFileVirtualOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DEVMEMINT_CTX * psDevmemServerContextInt = IMG_NULL;
+ IMG_HANDLE hDevmemServerContextInt2 = IMG_NULL;
+ IMG_CHAR *uiFileNameInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMPMM_DEVMEMINTPDUMPSAVETOFILEVIRTUAL);
+
+
+
+
+ if (psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize != 0)
+ {
+ uiFileNameInt = OSAllocMem(psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR));
+ if (!uiFileNameInt)
+ {
+ psDevmemIntPDumpSaveToFileVirtualOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto DevmemIntPDumpSaveToFileVirtual_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psDevmemIntPDumpSaveToFileVirtualIN->puiFileName, psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR))
+ || (OSCopyFromUser(NULL, uiFileNameInt, psDevmemIntPDumpSaveToFileVirtualIN->puiFileName,
+ psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+ {
+ psDevmemIntPDumpSaveToFileVirtualOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto DevmemIntPDumpSaveToFileVirtual_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psDevmemIntPDumpSaveToFileVirtualOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevmemServerContextInt2,
+ psDevmemIntPDumpSaveToFileVirtualIN->hDevmemServerContext,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+ if(psDevmemIntPDumpSaveToFileVirtualOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntPDumpSaveToFileVirtual_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psDevmemIntPDumpSaveToFileVirtualOUT->eError = ResManFindPrivateDataByPtr(hDevmemServerContextInt2, (IMG_VOID **) &psDevmemServerContextInt);
+
+ if(psDevmemIntPDumpSaveToFileVirtualOUT->eError != PVRSRV_OK)
+ {
+ goto DevmemIntPDumpSaveToFileVirtual_exit;
+ }
+ }
+
+ psDevmemIntPDumpSaveToFileVirtualOUT->eError =
+ DevmemIntPDumpSaveToFileVirtual(
+ psDevmemServerContextInt,
+ psDevmemIntPDumpSaveToFileVirtualIN->sAddress,
+ psDevmemIntPDumpSaveToFileVirtualIN->uiSize,
+ psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize,
+ uiFileNameInt,
+ psDevmemIntPDumpSaveToFileVirtualIN->ui32FileOffset,
+ psDevmemIntPDumpSaveToFileVirtualIN->ui32PDumpFlags);
+
+
+
+DevmemIntPDumpSaveToFileVirtual_exit:
+ if (uiFileNameInt)
+ OSFreeMem(uiFileNameInt);
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterPDUMPMMFunctions(IMG_VOID);
+IMG_VOID UnregisterPDUMPMMFunctions(IMG_VOID);
+
+/*
+ * Register all PDUMPMM functions with services
+ */
+PVRSRV_ERROR RegisterPDUMPMMFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEM, PVRSRVBridgePMRPDumpLoadMem);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEMVALUE32, PVRSRVBridgePMRPDumpLoadMemValue32);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEMVALUE64, PVRSRVBridgePMRPDumpLoadMemValue64);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPSAVETOFILE, PVRSRVBridgePMRPDumpSaveToFile);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPSYMBOLICADDR, PVRSRVBridgePMRPDumpSymbolicAddr);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPPOL32, PVRSRVBridgePMRPDumpPol32);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPCBP, PVRSRVBridgePMRPDumpCBP);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM_DEVMEMINTPDUMPSAVETOFILEVIRTUAL, PVRSRVBridgeDevmemIntPDumpSaveToFileVirtual);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all pdumpmm functions with services
+ */
+IMG_VOID UnregisterPDUMPMMFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/pvrtl_bridge/client_pvrtl_bridge.h b/drivers/gpu/rogue/generated/pvrtl_bridge/client_pvrtl_bridge.h
new file mode 100644
index 000000000000..d91040ff8c61
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pvrtl_bridge/client_pvrtl_bridge.h
@@ -0,0 +1,83 @@
+/*************************************************************************/ /*!
+@File
+@Title Client bridge header for pvrtl
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Exports the client bridge functions for pvrtl
+@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 CLIENT_PVRTL_BRIDGE_H
+#define CLIENT_PVRTL_BRIDGE_H
+
+#include "pvr_bridge_client.h"
+#include "pvr_bridge.h"
+
+#include "common_pvrtl_bridge.h"
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLConnect(IMG_HANDLE hBridge);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLDisconnect(IMG_HANDLE hBridge);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLOpenStream(IMG_HANDLE hBridge,
+ IMG_CHAR *puiName,
+ IMG_UINT32 ui32Mode,
+ IMG_HANDLE *phSD,
+ DEVMEM_SERVER_EXPORTCOOKIE *phClientBUFExportCookie);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLCloseStream(IMG_HANDLE hBridge,
+ IMG_HANDLE hSD);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLAcquireData(IMG_HANDLE hBridge,
+ IMG_HANDLE hSD,
+ IMG_UINT32 *pui32ReadOffset,
+ IMG_UINT32 *pui32ReadLen);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLReleaseData(IMG_HANDLE hBridge,
+ IMG_HANDLE hSD,
+ IMG_UINT32 ui32ReadOffset,
+ IMG_UINT32 ui32ReadLen);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeTLTestIoctl(IMG_HANDLE hBridge,
+ IMG_UINT32 ui32Cmd,
+ IMG_BYTE *psIn1,
+ IMG_UINT32 ui32In2,
+ IMG_UINT32 *pui32Out1,
+ IMG_UINT32 *pui32Out2);
+
+
+#endif /* CLIENT_PVRTL_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/pvrtl_bridge/common_pvrtl_bridge.h b/drivers/gpu/rogue/generated/pvrtl_bridge/common_pvrtl_bridge.h
new file mode 100644
index 000000000000..87010ed80684
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pvrtl_bridge/common_pvrtl_bridge.h
@@ -0,0 +1,196 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for pvrtl
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for pvrtl
+@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_PVRTL_BRIDGE_H
+#define COMMON_PVRTL_BRIDGE_H
+
+#include "devicemem_typedefs.h"
+#include "pvr_tl.h"
+#include "tltestdefs.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_PVRTL_CMD_FIRST (PVRSRV_BRIDGE_PVRTL_START)
+#define PVRSRV_BRIDGE_PVRTL_TLCONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_PVRTL_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_PVRTL_TLDISCONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_PVRTL_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PVRTL_TLOPENSTREAM PVRSRV_IOWR(PVRSRV_BRIDGE_PVRTL_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_PVRTL_TLCLOSESTREAM PVRSRV_IOWR(PVRSRV_BRIDGE_PVRTL_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_PVRTL_TLACQUIREDATA PVRSRV_IOWR(PVRSRV_BRIDGE_PVRTL_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_PVRTL_TLRELEASEDATA PVRSRV_IOWR(PVRSRV_BRIDGE_PVRTL_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_PVRTL_TLTESTIOCTL PVRSRV_IOWR(PVRSRV_BRIDGE_PVRTL_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_PVRTL_CMD_LAST (PVRSRV_BRIDGE_PVRTL_CMD_FIRST+6)
+
+
+/*******************************************
+ TLConnect
+ *******************************************/
+
+/* Bridge in structure for TLConnect */
+typedef struct PVRSRV_BRIDGE_IN_TLCONNECT_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLCONNECT;
+
+
+/* Bridge out structure for TLConnect */
+typedef struct PVRSRV_BRIDGE_OUT_TLCONNECT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLCONNECT;
+
+/*******************************************
+ TLDisconnect
+ *******************************************/
+
+/* Bridge in structure for TLDisconnect */
+typedef struct PVRSRV_BRIDGE_IN_TLDISCONNECT_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLDISCONNECT;
+
+
+/* Bridge out structure for TLDisconnect */
+typedef struct PVRSRV_BRIDGE_OUT_TLDISCONNECT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLDISCONNECT;
+
+/*******************************************
+ TLOpenStream
+ *******************************************/
+
+/* Bridge in structure for TLOpenStream */
+typedef struct PVRSRV_BRIDGE_IN_TLOPENSTREAM_TAG
+{
+ IMG_CHAR * puiName;
+ IMG_UINT32 ui32Mode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLOPENSTREAM;
+
+
+/* Bridge out structure for TLOpenStream */
+typedef struct PVRSRV_BRIDGE_OUT_TLOPENSTREAM_TAG
+{
+ IMG_HANDLE hSD;
+ DEVMEM_SERVER_EXPORTCOOKIE hClientBUFExportCookie;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLOPENSTREAM;
+
+/*******************************************
+ TLCloseStream
+ *******************************************/
+
+/* Bridge in structure for TLCloseStream */
+typedef struct PVRSRV_BRIDGE_IN_TLCLOSESTREAM_TAG
+{
+ IMG_HANDLE hSD;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLCLOSESTREAM;
+
+
+/* Bridge out structure for TLCloseStream */
+typedef struct PVRSRV_BRIDGE_OUT_TLCLOSESTREAM_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLCLOSESTREAM;
+
+/*******************************************
+ TLAcquireData
+ *******************************************/
+
+/* Bridge in structure for TLAcquireData */
+typedef struct PVRSRV_BRIDGE_IN_TLACQUIREDATA_TAG
+{
+ IMG_HANDLE hSD;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLACQUIREDATA;
+
+
+/* Bridge out structure for TLAcquireData */
+typedef struct PVRSRV_BRIDGE_OUT_TLACQUIREDATA_TAG
+{
+ IMG_UINT32 ui32ReadOffset;
+ IMG_UINT32 ui32ReadLen;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLACQUIREDATA;
+
+/*******************************************
+ TLReleaseData
+ *******************************************/
+
+/* Bridge in structure for TLReleaseData */
+typedef struct PVRSRV_BRIDGE_IN_TLRELEASEDATA_TAG
+{
+ IMG_HANDLE hSD;
+ IMG_UINT32 ui32ReadOffset;
+ IMG_UINT32 ui32ReadLen;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLRELEASEDATA;
+
+
+/* Bridge out structure for TLReleaseData */
+typedef struct PVRSRV_BRIDGE_OUT_TLRELEASEDATA_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLRELEASEDATA;
+
+/*******************************************
+ TLTestIoctl
+ *******************************************/
+
+/* Bridge in structure for TLTestIoctl */
+typedef struct PVRSRV_BRIDGE_IN_TLTESTIOCTL_TAG
+{
+ IMG_UINT32 ui32Cmd;
+ IMG_BYTE * psIn1;
+ IMG_UINT32 ui32In2;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_TLTESTIOCTL;
+
+
+/* Bridge out structure for TLTestIoctl */
+typedef struct PVRSRV_BRIDGE_OUT_TLTESTIOCTL_TAG
+{
+ IMG_UINT32 ui32Out1;
+ IMG_UINT32 ui32Out2;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_TLTESTIOCTL;
+
+#endif /* COMMON_PVRTL_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/pvrtl_bridge/server_pvrtl_bridge.c b/drivers/gpu/rogue/generated/pvrtl_bridge/server_pvrtl_bridge.c
new file mode 100644
index 000000000000..047bf67ea71f
--- /dev/null
+++ b/drivers/gpu/rogue/generated/pvrtl_bridge/server_pvrtl_bridge.c
@@ -0,0 +1,477 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for pvrtl
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for pvrtl
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "tlserver.h"
+
+
+#include "common_pvrtl_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+TLCloseStreamResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeTLConnect(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_TLCONNECT *psTLConnectIN,
+ PVRSRV_BRIDGE_OUT_TLCONNECT *psTLConnectOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PVRTL_TLCONNECT);
+
+ PVR_UNREFERENCED_PARAMETER(psTLConnectIN);
+
+
+
+
+ psTLConnectOUT->eError =
+ TLServerConnectKM(psConnection
+ );
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeTLDisconnect(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_TLDISCONNECT *psTLDisconnectIN,
+ PVRSRV_BRIDGE_OUT_TLDISCONNECT *psTLDisconnectOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PVRTL_TLDISCONNECT);
+
+ PVR_UNREFERENCED_PARAMETER(psTLDisconnectIN);
+
+
+
+
+ psTLDisconnectOUT->eError =
+ TLServerDisconnectKM(psConnection
+ );
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeTLOpenStream(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_TLOPENSTREAM *psTLOpenStreamIN,
+ PVRSRV_BRIDGE_OUT_TLOPENSTREAM *psTLOpenStreamOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_CHAR *uiNameInt = IMG_NULL;
+ TL_STREAM_DESC * psSDInt = IMG_NULL;
+ IMG_HANDLE hSDInt2 = IMG_NULL;
+ DEVMEM_EXPORTCOOKIE * psClientBUFExportCookieInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PVRTL_TLOPENSTREAM);
+
+
+
+ psTLOpenStreamOUT->hSD = IMG_NULL;
+
+
+ {
+ uiNameInt = OSAllocMem(PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR));
+ if (!uiNameInt)
+ {
+ psTLOpenStreamOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto TLOpenStream_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psTLOpenStreamIN->puiName, PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR))
+ || (OSCopyFromUser(NULL, uiNameInt, psTLOpenStreamIN->puiName,
+ PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+ {
+ psTLOpenStreamOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto TLOpenStream_exit;
+ }
+
+ psTLOpenStreamOUT->eError =
+ TLServerOpenStreamKM(
+ uiNameInt,
+ psTLOpenStreamIN->ui32Mode,
+ &psSDInt,
+ &psClientBUFExportCookieInt);
+ /* Exit early if bridged call fails */
+ if(psTLOpenStreamOUT->eError != PVRSRV_OK)
+ {
+ goto TLOpenStream_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hSDInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_TL_STREAM_DESC,
+ psSDInt,
+ (RESMAN_FREE_FN)&TLServerCloseStreamKM);
+ if (hSDInt2 == IMG_NULL)
+ {
+ psTLOpenStreamOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto TLOpenStream_exit;
+ }
+ psTLOpenStreamOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psTLOpenStreamOUT->hSD,
+ (IMG_HANDLE) hSDInt2,
+ PVRSRV_HANDLE_TYPE_PVR_TL_SD,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psTLOpenStreamOUT->eError != PVRSRV_OK)
+ {
+ goto TLOpenStream_exit;
+ }
+ psTLOpenStreamOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+ &psTLOpenStreamOUT->hClientBUFExportCookie,
+ (IMG_HANDLE) psClientBUFExportCookieInt,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ ,psTLOpenStreamOUT->hSD);
+ if (psTLOpenStreamOUT->eError != PVRSRV_OK)
+ {
+ goto TLOpenStream_exit;
+ }
+
+
+TLOpenStream_exit:
+ if (psTLOpenStreamOUT->eError != PVRSRV_OK)
+ {
+ if (psTLOpenStreamOUT->hSD)
+ {
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psTLOpenStreamOUT->hSD,
+ PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+ }
+
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hSDInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hSDInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psSDInt)
+ {
+ TLServerCloseStreamKM(psSDInt);
+ }
+ }
+
+ if (uiNameInt)
+ OSFreeMem(uiNameInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeTLCloseStream(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_TLCLOSESTREAM *psTLCloseStreamIN,
+ PVRSRV_BRIDGE_OUT_TLCLOSESTREAM *psTLCloseStreamOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hSDInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PVRTL_TLCLOSESTREAM);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psTLCloseStreamOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSDInt2,
+ psTLCloseStreamIN->hSD,
+ PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+ if(psTLCloseStreamOUT->eError != PVRSRV_OK)
+ {
+ goto TLCloseStream_exit;
+ }
+
+ }
+
+ psTLCloseStreamOUT->eError = TLCloseStreamResManProxy(hSDInt2);
+ /* Exit early if bridged call fails */
+ if(psTLCloseStreamOUT->eError != PVRSRV_OK)
+ {
+ goto TLCloseStream_exit;
+ }
+
+ psTLCloseStreamOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psTLCloseStreamIN->hSD,
+ PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+
+
+TLCloseStream_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeTLAcquireData(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_TLACQUIREDATA *psTLAcquireDataIN,
+ PVRSRV_BRIDGE_OUT_TLACQUIREDATA *psTLAcquireDataOUT,
+ CONNECTION_DATA *psConnection)
+{
+ TL_STREAM_DESC * psSDInt = IMG_NULL;
+ IMG_HANDLE hSDInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PVRTL_TLACQUIREDATA);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psTLAcquireDataOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSDInt2,
+ psTLAcquireDataIN->hSD,
+ PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+ if(psTLAcquireDataOUT->eError != PVRSRV_OK)
+ {
+ goto TLAcquireData_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psTLAcquireDataOUT->eError = ResManFindPrivateDataByPtr(hSDInt2, (IMG_VOID **) &psSDInt);
+
+ if(psTLAcquireDataOUT->eError != PVRSRV_OK)
+ {
+ goto TLAcquireData_exit;
+ }
+ }
+
+ psTLAcquireDataOUT->eError =
+ TLServerAcquireDataKM(
+ psSDInt,
+ &psTLAcquireDataOUT->ui32ReadOffset,
+ &psTLAcquireDataOUT->ui32ReadLen);
+
+
+
+TLAcquireData_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeTLReleaseData(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_TLRELEASEDATA *psTLReleaseDataIN,
+ PVRSRV_BRIDGE_OUT_TLRELEASEDATA *psTLReleaseDataOUT,
+ CONNECTION_DATA *psConnection)
+{
+ TL_STREAM_DESC * psSDInt = IMG_NULL;
+ IMG_HANDLE hSDInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PVRTL_TLRELEASEDATA);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psTLReleaseDataOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSDInt2,
+ psTLReleaseDataIN->hSD,
+ PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+ if(psTLReleaseDataOUT->eError != PVRSRV_OK)
+ {
+ goto TLReleaseData_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psTLReleaseDataOUT->eError = ResManFindPrivateDataByPtr(hSDInt2, (IMG_VOID **) &psSDInt);
+
+ if(psTLReleaseDataOUT->eError != PVRSRV_OK)
+ {
+ goto TLReleaseData_exit;
+ }
+ }
+
+ psTLReleaseDataOUT->eError =
+ TLServerReleaseDataKM(
+ psSDInt,
+ psTLReleaseDataIN->ui32ReadOffset,
+ psTLReleaseDataIN->ui32ReadLen);
+
+
+
+TLReleaseData_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeTLTestIoctl(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_TLTESTIOCTL *psTLTestIoctlIN,
+ PVRSRV_BRIDGE_OUT_TLTESTIOCTL *psTLTestIoctlOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_BYTE *psIn1Int = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PVRTL_TLTESTIOCTL);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ {
+ psIn1Int = OSAllocMem(PVR_TL_TEST_PARAM_MAX_SIZE * sizeof(IMG_BYTE));
+ if (!psIn1Int)
+ {
+ psTLTestIoctlOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto TLTestIoctl_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psTLTestIoctlIN->psIn1, PVR_TL_TEST_PARAM_MAX_SIZE * sizeof(IMG_BYTE))
+ || (OSCopyFromUser(NULL, psIn1Int, psTLTestIoctlIN->psIn1,
+ PVR_TL_TEST_PARAM_MAX_SIZE * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+ {
+ psTLTestIoctlOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto TLTestIoctl_exit;
+ }
+
+ psTLTestIoctlOUT->eError =
+ TLServerTestIoctlKM(
+ psTLTestIoctlIN->ui32Cmd,
+ psIn1Int,
+ psTLTestIoctlIN->ui32In2,
+ &psTLTestIoctlOUT->ui32Out1,
+ &psTLTestIoctlOUT->ui32Out2);
+
+
+
+TLTestIoctl_exit:
+ if (psIn1Int)
+ OSFreeMem(psIn1Int);
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterPVRTLFunctions(IMG_VOID);
+IMG_VOID UnregisterPVRTLFunctions(IMG_VOID);
+
+/*
+ * Register all PVRTL functions with services
+ */
+PVRSRV_ERROR RegisterPVRTLFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL_TLCONNECT, PVRSRVBridgeTLConnect);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL_TLDISCONNECT, PVRSRVBridgeTLDisconnect);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL_TLOPENSTREAM, PVRSRVBridgeTLOpenStream);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL_TLCLOSESTREAM, PVRSRVBridgeTLCloseStream);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL_TLACQUIREDATA, PVRSRVBridgeTLAcquireData);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL_TLRELEASEDATA, PVRSRVBridgeTLReleaseData);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL_TLTESTIOCTL, PVRSRVBridgeTLTestIoctl);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all pvrtl functions with services
+ */
+IMG_VOID UnregisterPVRTLFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/regconfig_bridge/common_regconfig_bridge.h b/drivers/gpu/rogue/generated/regconfig_bridge/common_regconfig_bridge.h
new file mode 100644
index 000000000000..fcce738e3f78
--- /dev/null
+++ b/drivers/gpu/rogue/generated/regconfig_bridge/common_regconfig_bridge.h
@@ -0,0 +1,150 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for regconfig
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for regconfig
+@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_REGCONFIG_BRIDGE_H
+#define COMMON_REGCONFIG_BRIDGE_H
+
+#include "rgx_bridge.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_REGCONFIG_CMD_FIRST (PVRSRV_BRIDGE_REGCONFIG_START)
+#define PVRSRV_BRIDGE_REGCONFIG_RGXSETREGCONFIGPI PVRSRV_IOWR(PVRSRV_BRIDGE_REGCONFIG_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_REGCONFIG_RGXADDREGCONFIG PVRSRV_IOWR(PVRSRV_BRIDGE_REGCONFIG_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_REGCONFIG_RGXCLEARREGCONFIG PVRSRV_IOWR(PVRSRV_BRIDGE_REGCONFIG_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_REGCONFIG_RGXENABLEREGCONFIG PVRSRV_IOWR(PVRSRV_BRIDGE_REGCONFIG_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_REGCONFIG_RGXDISABLEREGCONFIG PVRSRV_IOWR(PVRSRV_BRIDGE_REGCONFIG_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_REGCONFIG_CMD_LAST (PVRSRV_BRIDGE_REGCONFIG_CMD_FIRST+4)
+
+
+/*******************************************
+ RGXSetRegConfigPI
+ *******************************************/
+
+/* Bridge in structure for RGXSetRegConfigPI */
+typedef struct PVRSRV_BRIDGE_IN_RGXSETREGCONFIGPI_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT8 ui8RegPowerIsland;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXSETREGCONFIGPI;
+
+
+/* Bridge out structure for RGXSetRegConfigPI */
+typedef struct PVRSRV_BRIDGE_OUT_RGXSETREGCONFIGPI_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXSETREGCONFIGPI;
+
+/*******************************************
+ RGXAddRegconfig
+ *******************************************/
+
+/* Bridge in structure for RGXAddRegconfig */
+typedef struct PVRSRV_BRIDGE_IN_RGXADDREGCONFIG_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32RegAddr;
+ IMG_UINT64 ui64RegValue;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXADDREGCONFIG;
+
+
+/* Bridge out structure for RGXAddRegconfig */
+typedef struct PVRSRV_BRIDGE_OUT_RGXADDREGCONFIG_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXADDREGCONFIG;
+
+/*******************************************
+ RGXClearRegConfig
+ *******************************************/
+
+/* Bridge in structure for RGXClearRegConfig */
+typedef struct PVRSRV_BRIDGE_IN_RGXCLEARREGCONFIG_TAG
+{
+ IMG_HANDLE hDevNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCLEARREGCONFIG;
+
+
+/* Bridge out structure for RGXClearRegConfig */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCLEARREGCONFIG_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCLEARREGCONFIG;
+
+/*******************************************
+ RGXEnableRegConfig
+ *******************************************/
+
+/* Bridge in structure for RGXEnableRegConfig */
+typedef struct PVRSRV_BRIDGE_IN_RGXENABLEREGCONFIG_TAG
+{
+ IMG_HANDLE hDevNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXENABLEREGCONFIG;
+
+
+/* Bridge out structure for RGXEnableRegConfig */
+typedef struct PVRSRV_BRIDGE_OUT_RGXENABLEREGCONFIG_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXENABLEREGCONFIG;
+
+/*******************************************
+ RGXDisableRegConfig
+ *******************************************/
+
+/* Bridge in structure for RGXDisableRegConfig */
+typedef struct PVRSRV_BRIDGE_IN_RGXDISABLEREGCONFIG_TAG
+{
+ IMG_HANDLE hDevNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDISABLEREGCONFIG;
+
+
+/* Bridge out structure for RGXDisableRegConfig */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDISABLEREGCONFIG_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDISABLEREGCONFIG;
+
+#endif /* COMMON_REGCONFIG_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/regconfig_bridge/server_regconfig_bridge.c b/drivers/gpu/rogue/generated/regconfig_bridge/server_regconfig_bridge.c
new file mode 100644
index 000000000000..ac6c68e6345a
--- /dev/null
+++ b/drivers/gpu/rogue/generated/regconfig_bridge/server_regconfig_bridge.c
@@ -0,0 +1,304 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for regconfig
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for regconfig
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxregconfig.h"
+
+
+#include "common_regconfig_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeRGXSetRegConfigPI(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXSETREGCONFIGPI *psRGXSetRegConfigPIIN,
+ PVRSRV_BRIDGE_OUT_RGXSETREGCONFIGPI *psRGXSetRegConfigPIOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_REGCONFIG_RGXSETREGCONFIGPI);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXSetRegConfigPIOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXSetRegConfigPIIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXSetRegConfigPIOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSetRegConfigPI_exit;
+ }
+
+ }
+
+ psRGXSetRegConfigPIOUT->eError =
+ PVRSRVRGXSetRegConfigPIKM(
+ hDevNodeInt,
+ psRGXSetRegConfigPIIN->ui8RegPowerIsland);
+
+
+
+RGXSetRegConfigPI_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXAddRegconfig(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXADDREGCONFIG *psRGXAddRegconfigIN,
+ PVRSRV_BRIDGE_OUT_RGXADDREGCONFIG *psRGXAddRegconfigOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_REGCONFIG_RGXADDREGCONFIG);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXAddRegconfigOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXAddRegconfigIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXAddRegconfigOUT->eError != PVRSRV_OK)
+ {
+ goto RGXAddRegconfig_exit;
+ }
+
+ }
+
+ psRGXAddRegconfigOUT->eError =
+ PVRSRVRGXAddRegConfigKM(
+ hDevNodeInt,
+ psRGXAddRegconfigIN->ui32RegAddr,
+ psRGXAddRegconfigIN->ui64RegValue);
+
+
+
+RGXAddRegconfig_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXClearRegConfig(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCLEARREGCONFIG *psRGXClearRegConfigIN,
+ PVRSRV_BRIDGE_OUT_RGXCLEARREGCONFIG *psRGXClearRegConfigOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_REGCONFIG_RGXCLEARREGCONFIG);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXClearRegConfigOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXClearRegConfigIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXClearRegConfigOUT->eError != PVRSRV_OK)
+ {
+ goto RGXClearRegConfig_exit;
+ }
+
+ }
+
+ psRGXClearRegConfigOUT->eError =
+ PVRSRVRGXClearRegConfigKM(
+ hDevNodeInt);
+
+
+
+RGXClearRegConfig_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXEnableRegConfig(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXENABLEREGCONFIG *psRGXEnableRegConfigIN,
+ PVRSRV_BRIDGE_OUT_RGXENABLEREGCONFIG *psRGXEnableRegConfigOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_REGCONFIG_RGXENABLEREGCONFIG);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXEnableRegConfigOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXEnableRegConfigIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXEnableRegConfigOUT->eError != PVRSRV_OK)
+ {
+ goto RGXEnableRegConfig_exit;
+ }
+
+ }
+
+ psRGXEnableRegConfigOUT->eError =
+ PVRSRVRGXEnableRegConfigKM(
+ hDevNodeInt);
+
+
+
+RGXEnableRegConfig_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDisableRegConfig(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDISABLEREGCONFIG *psRGXDisableRegConfigIN,
+ PVRSRV_BRIDGE_OUT_RGXDISABLEREGCONFIG *psRGXDisableRegConfigOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_REGCONFIG_RGXDISABLEREGCONFIG);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDisableRegConfigOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXDisableRegConfigIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXDisableRegConfigOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDisableRegConfig_exit;
+ }
+
+ }
+
+ psRGXDisableRegConfigOUT->eError =
+ PVRSRVRGXDisableRegConfigKM(
+ hDevNodeInt);
+
+
+
+RGXDisableRegConfig_exit:
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterREGCONFIGFunctions(IMG_VOID);
+IMG_VOID UnregisterREGCONFIGFunctions(IMG_VOID);
+
+/*
+ * Register all REGCONFIG functions with services
+ */
+PVRSRV_ERROR RegisterREGCONFIGFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_REGCONFIG_RGXSETREGCONFIGPI, PVRSRVBridgeRGXSetRegConfigPI);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_REGCONFIG_RGXADDREGCONFIG, PVRSRVBridgeRGXAddRegconfig);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_REGCONFIG_RGXCLEARREGCONFIG, PVRSRVBridgeRGXClearRegConfig);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_REGCONFIG_RGXENABLEREGCONFIG, PVRSRVBridgeRGXEnableRegConfig);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_REGCONFIG_RGXDISABLEREGCONFIG, PVRSRVBridgeRGXDisableRegConfig);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all regconfig functions with services
+ */
+IMG_VOID UnregisterREGCONFIGFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/rgxcmp_bridge/common_rgxcmp_bridge.h b/drivers/gpu/rogue/generated/rgxcmp_bridge/common_rgxcmp_bridge.h
new file mode 100644
index 000000000000..43a5fda70663
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxcmp_bridge/common_rgxcmp_bridge.h
@@ -0,0 +1,200 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for rgxcmp
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for rgxcmp
+@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_RGXCMP_BRIDGE_H
+#define COMMON_RGXCMP_BRIDGE_H
+
+#include "rgx_bridge.h"
+#include "sync_external.h"
+#include "rgx_fwif_shared.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_RGXCMP_CMD_FIRST (PVRSRV_BRIDGE_RGXCMP_START)
+#define PVRSRV_BRIDGE_RGXCMP_RGXCREATECOMPUTECONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RGXCMP_RGXDESTROYCOMPUTECONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RGXCMP_RGXKICKCDM PVRSRV_IOWR(PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_RGXCMP_RGXFLUSHCOMPUTEDATA PVRSRV_IOWR(PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_RGXCMP_RGXSETCOMPUTECONTEXTPRIORITY PVRSRV_IOWR(PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_RGXCMP_RGXKICKSYNCCDM PVRSRV_IOWR(PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_RGXCMP_CMD_LAST (PVRSRV_BRIDGE_RGXCMP_CMD_FIRST+5)
+
+
+/*******************************************
+ RGXCreateComputeContext
+ *******************************************/
+
+/* Bridge in structure for RGXCreateComputeContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATECOMPUTECONTEXT_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32Priority;
+ IMG_DEV_VIRTADDR sMCUFenceAddr;
+ IMG_UINT32 ui32FrameworkCmdize;
+ IMG_BYTE * psFrameworkCmd;
+ IMG_HANDLE hPrivData;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATECOMPUTECONTEXT;
+
+
+/* Bridge out structure for RGXCreateComputeContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATECOMPUTECONTEXT_TAG
+{
+ IMG_HANDLE hComputeContext;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATECOMPUTECONTEXT;
+
+/*******************************************
+ RGXDestroyComputeContext
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyComputeContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYCOMPUTECONTEXT_TAG
+{
+ IMG_HANDLE hComputeContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYCOMPUTECONTEXT;
+
+
+/* Bridge out structure for RGXDestroyComputeContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYCOMPUTECONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYCOMPUTECONTEXT;
+
+/*******************************************
+ RGXKickCDM
+ *******************************************/
+
+/* Bridge in structure for RGXKickCDM */
+typedef struct PVRSRV_BRIDGE_IN_RGXKICKCDM_TAG
+{
+ IMG_HANDLE hComputeContext;
+ IMG_UINT32 ui32ClientFenceCount;
+ PRGXFWIF_UFO_ADDR * psClientFenceUFOAddress;
+ IMG_UINT32 * pui32ClientFenceValue;
+ IMG_UINT32 ui32ClientUpdateCount;
+ PRGXFWIF_UFO_ADDR * psClientUpdateUFOAddress;
+ IMG_UINT32 * pui32ClientUpdateValue;
+ IMG_UINT32 ui32ServerSyncCount;
+ IMG_UINT32 * pui32ServerSyncFlags;
+ IMG_HANDLE * phServerSyncs;
+ IMG_UINT32 ui32CmdSize;
+ IMG_BYTE * psDMCmd;
+ IMG_BOOL bbPDumpContinuous;
+ IMG_UINT32 ui32ExternalJobReference;
+ IMG_UINT32 ui32InternalJobReference;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKCDM;
+
+
+/* Bridge out structure for RGXKickCDM */
+typedef struct PVRSRV_BRIDGE_OUT_RGXKICKCDM_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXKICKCDM;
+
+/*******************************************
+ RGXFlushComputeData
+ *******************************************/
+
+/* Bridge in structure for RGXFlushComputeData */
+typedef struct PVRSRV_BRIDGE_IN_RGXFLUSHCOMPUTEDATA_TAG
+{
+ IMG_HANDLE hComputeContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXFLUSHCOMPUTEDATA;
+
+
+/* Bridge out structure for RGXFlushComputeData */
+typedef struct PVRSRV_BRIDGE_OUT_RGXFLUSHCOMPUTEDATA_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXFLUSHCOMPUTEDATA;
+
+/*******************************************
+ RGXSetComputeContextPriority
+ *******************************************/
+
+/* Bridge in structure for RGXSetComputeContextPriority */
+typedef struct PVRSRV_BRIDGE_IN_RGXSETCOMPUTECONTEXTPRIORITY_TAG
+{
+ IMG_HANDLE hComputeContext;
+ IMG_UINT32 ui32Priority;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXSETCOMPUTECONTEXTPRIORITY;
+
+
+/* Bridge out structure for RGXSetComputeContextPriority */
+typedef struct PVRSRV_BRIDGE_OUT_RGXSETCOMPUTECONTEXTPRIORITY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXSETCOMPUTECONTEXTPRIORITY;
+
+/*******************************************
+ RGXKickSyncCDM
+ *******************************************/
+
+/* Bridge in structure for RGXKickSyncCDM */
+typedef struct PVRSRV_BRIDGE_IN_RGXKICKSYNCCDM_TAG
+{
+ IMG_HANDLE hComputeContext;
+ IMG_UINT32 ui32ClientFenceCount;
+ PRGXFWIF_UFO_ADDR * psClientFenceUFOAddress;
+ IMG_UINT32 * pui32ClientFenceValue;
+ IMG_UINT32 ui32ClientUpdateCount;
+ PRGXFWIF_UFO_ADDR * psClientUpdateUFOAddress;
+ IMG_UINT32 * pui32ClientUpdateValue;
+ IMG_UINT32 ui32ServerSyncCount;
+ IMG_UINT32 * pui32ServerSyncFlags;
+ IMG_HANDLE * phServerSyncs;
+ IMG_UINT32 ui32NumFenceFDs;
+ IMG_INT32 * pi32FenceFDs;
+ IMG_BOOL bbPDumpContinuous;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKSYNCCDM;
+
+
+/* Bridge out structure for RGXKickSyncCDM */
+typedef struct PVRSRV_BRIDGE_OUT_RGXKICKSYNCCDM_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXKICKSYNCCDM;
+
+#endif /* COMMON_RGXCMP_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/rgxcmp_bridge/server_rgxcmp_bridge.c b/drivers/gpu/rogue/generated/rgxcmp_bridge/server_rgxcmp_bridge.c
new file mode 100644
index 000000000000..a174f0955ad3
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxcmp_bridge/server_rgxcmp_bridge.c
@@ -0,0 +1,905 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for rgxcmp
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for rgxcmp
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxcompute.h"
+
+
+#include "common_rgxcmp_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+RGXDestroyComputeContextResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeRGXCreateComputeContext(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCREATECOMPUTECONTEXT *psRGXCreateComputeContextIN,
+ PVRSRV_BRIDGE_OUT_RGXCREATECOMPUTECONTEXT *psRGXCreateComputeContextOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_BYTE *psFrameworkCmdInt = IMG_NULL;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+ RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = IMG_NULL;
+ IMG_HANDLE hComputeContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXCMP_RGXCREATECOMPUTECONTEXT);
+
+
+
+
+ if (psRGXCreateComputeContextIN->ui32FrameworkCmdize != 0)
+ {
+ psFrameworkCmdInt = OSAllocMem(psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE));
+ if (!psFrameworkCmdInt)
+ {
+ psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXCreateComputeContext_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXCreateComputeContextIN->psFrameworkCmd, psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE))
+ || (OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateComputeContextIN->psFrameworkCmd,
+ psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+ {
+ psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXCreateComputeContext_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateComputeContextOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCreateComputeContextIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCreateComputeContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateComputeContext_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateComputeContextOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPrivDataInt,
+ psRGXCreateComputeContextIN->hPrivData,
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+ if(psRGXCreateComputeContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateComputeContext_exit;
+ }
+
+ }
+
+ psRGXCreateComputeContextOUT->eError =
+ PVRSRVRGXCreateComputeContextKM(psConnection,
+ hDevNodeInt,
+ psRGXCreateComputeContextIN->ui32Priority,
+ psRGXCreateComputeContextIN->sMCUFenceAddr,
+ psRGXCreateComputeContextIN->ui32FrameworkCmdize,
+ psFrameworkCmdInt,
+ hPrivDataInt,
+ &psComputeContextInt);
+ /* Exit early if bridged call fails */
+ if(psRGXCreateComputeContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateComputeContext_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hComputeContextInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
+ psComputeContextInt,
+ (RESMAN_FREE_FN)&PVRSRVRGXDestroyComputeContextKM);
+ if (hComputeContextInt2 == IMG_NULL)
+ {
+ psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto RGXCreateComputeContext_exit;
+ }
+ psRGXCreateComputeContextOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXCreateComputeContextOUT->hComputeContext,
+ (IMG_HANDLE) hComputeContextInt2,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXCreateComputeContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateComputeContext_exit;
+ }
+
+
+RGXCreateComputeContext_exit:
+ if (psRGXCreateComputeContextOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hComputeContextInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hComputeContextInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psComputeContextInt)
+ {
+ PVRSRVRGXDestroyComputeContextKM(psComputeContextInt);
+ }
+ }
+
+ if (psFrameworkCmdInt)
+ OSFreeMem(psFrameworkCmdInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyComputeContext(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDESTROYCOMPUTECONTEXT *psRGXDestroyComputeContextIN,
+ PVRSRV_BRIDGE_OUT_RGXDESTROYCOMPUTECONTEXT *psRGXDestroyComputeContextOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hComputeContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXCMP_RGXDESTROYCOMPUTECONTEXT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDestroyComputeContextOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hComputeContextInt2,
+ psRGXDestroyComputeContextIN->hComputeContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+ if(psRGXDestroyComputeContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyComputeContext_exit;
+ }
+
+ }
+
+ psRGXDestroyComputeContextOUT->eError = RGXDestroyComputeContextResManProxy(hComputeContextInt2);
+ /* Exit early if bridged call fails */
+ if(psRGXDestroyComputeContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyComputeContext_exit;
+ }
+
+ psRGXDestroyComputeContextOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXDestroyComputeContextIN->hComputeContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+
+
+RGXDestroyComputeContext_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXKickCDM(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXKICKCDM *psRGXKickCDMIN,
+ PVRSRV_BRIDGE_OUT_RGXKICKCDM *psRGXKickCDMOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = IMG_NULL;
+ IMG_HANDLE hComputeContextInt2 = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientFenceUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientFenceValueInt = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientUpdateUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientUpdateValueInt = IMG_NULL;
+ IMG_UINT32 *ui32ServerSyncFlagsInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * *psServerSyncsInt = IMG_NULL;
+ IMG_HANDLE *hServerSyncsInt2 = IMG_NULL;
+ IMG_BYTE *psDMCmdInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXCMP_RGXKICKCDM);
+
+
+
+
+ if (psRGXKickCDMIN->ui32ClientFenceCount != 0)
+ {
+ sClientFenceUFOAddressInt = OSAllocMem(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientFenceUFOAddressInt)
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickCDMIN->psClientFenceUFOAddress, psRGXKickCDMIN->ui32ClientFenceCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientFenceUFOAddressInt, psRGXKickCDMIN->psClientFenceUFOAddress,
+ psRGXKickCDMIN->ui32ClientFenceCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickCDM_exit;
+ }
+ if (psRGXKickCDMIN->ui32ClientFenceCount != 0)
+ {
+ ui32ClientFenceValueInt = OSAllocMem(psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32));
+ if (!ui32ClientFenceValueInt)
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickCDMIN->pui32ClientFenceValue, psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientFenceValueInt, psRGXKickCDMIN->pui32ClientFenceValue,
+ psRGXKickCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickCDM_exit;
+ }
+ if (psRGXKickCDMIN->ui32ClientUpdateCount != 0)
+ {
+ sClientUpdateUFOAddressInt = OSAllocMem(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientUpdateUFOAddressInt)
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickCDMIN->psClientUpdateUFOAddress, psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientUpdateUFOAddressInt, psRGXKickCDMIN->psClientUpdateUFOAddress,
+ psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickCDM_exit;
+ }
+ if (psRGXKickCDMIN->ui32ClientUpdateCount != 0)
+ {
+ ui32ClientUpdateValueInt = OSAllocMem(psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32));
+ if (!ui32ClientUpdateValueInt)
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickCDMIN->pui32ClientUpdateValue, psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientUpdateValueInt, psRGXKickCDMIN->pui32ClientUpdateValue,
+ psRGXKickCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickCDM_exit;
+ }
+ if (psRGXKickCDMIN->ui32ServerSyncCount != 0)
+ {
+ ui32ServerSyncFlagsInt = OSAllocMem(psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32));
+ if (!ui32ServerSyncFlagsInt)
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickCDMIN->pui32ServerSyncFlags, psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickCDMIN->pui32ServerSyncFlags,
+ psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickCDM_exit;
+ }
+ if (psRGXKickCDMIN->ui32ServerSyncCount != 0)
+ {
+ psServerSyncsInt = OSAllocMem(psRGXKickCDMIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psServerSyncsInt)
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickCDM_exit;
+ }
+ hServerSyncsInt2 = OSAllocMem(psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE));
+ if (!hServerSyncsInt2)
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickCDMIN->phServerSyncs, psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hServerSyncsInt2, psRGXKickCDMIN->phServerSyncs,
+ psRGXKickCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickCDM_exit;
+ }
+ if (psRGXKickCDMIN->ui32CmdSize != 0)
+ {
+ psDMCmdInt = OSAllocMem(psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE));
+ if (!psDMCmdInt)
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickCDMIN->psDMCmd, psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE))
+ || (OSCopyFromUser(NULL, psDMCmdInt, psRGXKickCDMIN->psDMCmd,
+ psRGXKickCDMIN->ui32CmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+ {
+ psRGXKickCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickCDM_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXKickCDMOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hComputeContextInt2,
+ psRGXKickCDMIN->hComputeContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+ if(psRGXKickCDMOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickCDM_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickCDMOUT->eError = ResManFindPrivateDataByPtr(hComputeContextInt2, (IMG_VOID **) &psComputeContextInt);
+
+ if(psRGXKickCDMOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickCDM_exit;
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psRGXKickCDMIN->ui32ServerSyncCount;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psRGXKickCDMOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerSyncsInt2[i],
+ hServerSyncsInt2[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psRGXKickCDMOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickCDM_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickCDMOUT->eError = ResManFindPrivateDataByPtr(hServerSyncsInt2[i], (IMG_VOID **) &psServerSyncsInt[i]);
+
+ if(psRGXKickCDMOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickCDM_exit;
+ }
+ }
+ }
+ }
+
+ psRGXKickCDMOUT->eError =
+ PVRSRVRGXKickCDMKM(
+ psComputeContextInt,
+ psRGXKickCDMIN->ui32ClientFenceCount,
+ sClientFenceUFOAddressInt,
+ ui32ClientFenceValueInt,
+ psRGXKickCDMIN->ui32ClientUpdateCount,
+ sClientUpdateUFOAddressInt,
+ ui32ClientUpdateValueInt,
+ psRGXKickCDMIN->ui32ServerSyncCount,
+ ui32ServerSyncFlagsInt,
+ psServerSyncsInt,
+ psRGXKickCDMIN->ui32CmdSize,
+ psDMCmdInt,
+ psRGXKickCDMIN->bbPDumpContinuous,
+ psRGXKickCDMIN->ui32ExternalJobReference,
+ psRGXKickCDMIN->ui32InternalJobReference);
+
+
+
+RGXKickCDM_exit:
+ if (sClientFenceUFOAddressInt)
+ OSFreeMem(sClientFenceUFOAddressInt);
+ if (ui32ClientFenceValueInt)
+ OSFreeMem(ui32ClientFenceValueInt);
+ if (sClientUpdateUFOAddressInt)
+ OSFreeMem(sClientUpdateUFOAddressInt);
+ if (ui32ClientUpdateValueInt)
+ OSFreeMem(ui32ClientUpdateValueInt);
+ if (ui32ServerSyncFlagsInt)
+ OSFreeMem(ui32ServerSyncFlagsInt);
+ if (psServerSyncsInt)
+ OSFreeMem(psServerSyncsInt);
+ if (hServerSyncsInt2)
+ OSFreeMem(hServerSyncsInt2);
+ if (psDMCmdInt)
+ OSFreeMem(psDMCmdInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXFlushComputeData(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXFLUSHCOMPUTEDATA *psRGXFlushComputeDataIN,
+ PVRSRV_BRIDGE_OUT_RGXFLUSHCOMPUTEDATA *psRGXFlushComputeDataOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = IMG_NULL;
+ IMG_HANDLE hComputeContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXCMP_RGXFLUSHCOMPUTEDATA);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXFlushComputeDataOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hComputeContextInt2,
+ psRGXFlushComputeDataIN->hComputeContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+ if(psRGXFlushComputeDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXFlushComputeData_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXFlushComputeDataOUT->eError = ResManFindPrivateDataByPtr(hComputeContextInt2, (IMG_VOID **) &psComputeContextInt);
+
+ if(psRGXFlushComputeDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXFlushComputeData_exit;
+ }
+ }
+
+ psRGXFlushComputeDataOUT->eError =
+ PVRSRVRGXFlushComputeDataKM(
+ psComputeContextInt);
+
+
+
+RGXFlushComputeData_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXSetComputeContextPriority(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXSETCOMPUTECONTEXTPRIORITY *psRGXSetComputeContextPriorityIN,
+ PVRSRV_BRIDGE_OUT_RGXSETCOMPUTECONTEXTPRIORITY *psRGXSetComputeContextPriorityOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = IMG_NULL;
+ IMG_HANDLE hComputeContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXCMP_RGXSETCOMPUTECONTEXTPRIORITY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXSetComputeContextPriorityOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hComputeContextInt2,
+ psRGXSetComputeContextPriorityIN->hComputeContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+ if(psRGXSetComputeContextPriorityOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSetComputeContextPriority_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXSetComputeContextPriorityOUT->eError = ResManFindPrivateDataByPtr(hComputeContextInt2, (IMG_VOID **) &psComputeContextInt);
+
+ if(psRGXSetComputeContextPriorityOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSetComputeContextPriority_exit;
+ }
+ }
+
+ psRGXSetComputeContextPriorityOUT->eError =
+ PVRSRVRGXSetComputeContextPriorityKM(psConnection,
+ psComputeContextInt,
+ psRGXSetComputeContextPriorityIN->ui32Priority);
+
+
+
+RGXSetComputeContextPriority_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXKickSyncCDM(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXKICKSYNCCDM *psRGXKickSyncCDMIN,
+ PVRSRV_BRIDGE_OUT_RGXKICKSYNCCDM *psRGXKickSyncCDMOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_COMPUTE_CONTEXT * psComputeContextInt = IMG_NULL;
+ IMG_HANDLE hComputeContextInt2 = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientFenceUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientFenceValueInt = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientUpdateUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientUpdateValueInt = IMG_NULL;
+ IMG_UINT32 *ui32ServerSyncFlagsInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * *psServerSyncsInt = IMG_NULL;
+ IMG_HANDLE *hServerSyncsInt2 = IMG_NULL;
+ IMG_INT32 *i32FenceFDsInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXCMP_RGXKICKSYNCCDM);
+
+
+
+
+ if (psRGXKickSyncCDMIN->ui32ClientFenceCount != 0)
+ {
+ sClientFenceUFOAddressInt = OSAllocMem(psRGXKickSyncCDMIN->ui32ClientFenceCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientFenceUFOAddressInt)
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncCDMIN->psClientFenceUFOAddress, psRGXKickSyncCDMIN->ui32ClientFenceCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientFenceUFOAddressInt, psRGXKickSyncCDMIN->psClientFenceUFOAddress,
+ psRGXKickSyncCDMIN->ui32ClientFenceCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ if (psRGXKickSyncCDMIN->ui32ClientFenceCount != 0)
+ {
+ ui32ClientFenceValueInt = OSAllocMem(psRGXKickSyncCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32));
+ if (!ui32ClientFenceValueInt)
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncCDMIN->pui32ClientFenceValue, psRGXKickSyncCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientFenceValueInt, psRGXKickSyncCDMIN->pui32ClientFenceValue,
+ psRGXKickSyncCDMIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ if (psRGXKickSyncCDMIN->ui32ClientUpdateCount != 0)
+ {
+ sClientUpdateUFOAddressInt = OSAllocMem(psRGXKickSyncCDMIN->ui32ClientUpdateCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientUpdateUFOAddressInt)
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncCDMIN->psClientUpdateUFOAddress, psRGXKickSyncCDMIN->ui32ClientUpdateCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientUpdateUFOAddressInt, psRGXKickSyncCDMIN->psClientUpdateUFOAddress,
+ psRGXKickSyncCDMIN->ui32ClientUpdateCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ if (psRGXKickSyncCDMIN->ui32ClientUpdateCount != 0)
+ {
+ ui32ClientUpdateValueInt = OSAllocMem(psRGXKickSyncCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32));
+ if (!ui32ClientUpdateValueInt)
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncCDMIN->pui32ClientUpdateValue, psRGXKickSyncCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientUpdateValueInt, psRGXKickSyncCDMIN->pui32ClientUpdateValue,
+ psRGXKickSyncCDMIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ if (psRGXKickSyncCDMIN->ui32ServerSyncCount != 0)
+ {
+ ui32ServerSyncFlagsInt = OSAllocMem(psRGXKickSyncCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32));
+ if (!ui32ServerSyncFlagsInt)
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncCDMIN->pui32ServerSyncFlags, psRGXKickSyncCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickSyncCDMIN->pui32ServerSyncFlags,
+ psRGXKickSyncCDMIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ if (psRGXKickSyncCDMIN->ui32ServerSyncCount != 0)
+ {
+ psServerSyncsInt = OSAllocMem(psRGXKickSyncCDMIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psServerSyncsInt)
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ hServerSyncsInt2 = OSAllocMem(psRGXKickSyncCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE));
+ if (!hServerSyncsInt2)
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncCDMIN->phServerSyncs, psRGXKickSyncCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hServerSyncsInt2, psRGXKickSyncCDMIN->phServerSyncs,
+ psRGXKickSyncCDMIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ if (psRGXKickSyncCDMIN->ui32NumFenceFDs != 0)
+ {
+ i32FenceFDsInt = OSAllocMem(psRGXKickSyncCDMIN->ui32NumFenceFDs * sizeof(IMG_INT32));
+ if (!i32FenceFDsInt)
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncCDM_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncCDMIN->pi32FenceFDs, psRGXKickSyncCDMIN->ui32NumFenceFDs * sizeof(IMG_INT32))
+ || (OSCopyFromUser(NULL, i32FenceFDsInt, psRGXKickSyncCDMIN->pi32FenceFDs,
+ psRGXKickSyncCDMIN->ui32NumFenceFDs * sizeof(IMG_INT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncCDMOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncCDM_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXKickSyncCDMOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hComputeContextInt2,
+ psRGXKickSyncCDMIN->hComputeContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+ if(psRGXKickSyncCDMOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncCDM_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickSyncCDMOUT->eError = ResManFindPrivateDataByPtr(hComputeContextInt2, (IMG_VOID **) &psComputeContextInt);
+
+ if(psRGXKickSyncCDMOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncCDM_exit;
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psRGXKickSyncCDMIN->ui32ServerSyncCount;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psRGXKickSyncCDMOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerSyncsInt2[i],
+ hServerSyncsInt2[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psRGXKickSyncCDMOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncCDM_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickSyncCDMOUT->eError = ResManFindPrivateDataByPtr(hServerSyncsInt2[i], (IMG_VOID **) &psServerSyncsInt[i]);
+
+ if(psRGXKickSyncCDMOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncCDM_exit;
+ }
+ }
+ }
+ }
+
+ psRGXKickSyncCDMOUT->eError =
+ PVRSRVRGXKickSyncCDMKM(
+ psComputeContextInt,
+ psRGXKickSyncCDMIN->ui32ClientFenceCount,
+ sClientFenceUFOAddressInt,
+ ui32ClientFenceValueInt,
+ psRGXKickSyncCDMIN->ui32ClientUpdateCount,
+ sClientUpdateUFOAddressInt,
+ ui32ClientUpdateValueInt,
+ psRGXKickSyncCDMIN->ui32ServerSyncCount,
+ ui32ServerSyncFlagsInt,
+ psServerSyncsInt,
+ psRGXKickSyncCDMIN->ui32NumFenceFDs,
+ i32FenceFDsInt,
+ psRGXKickSyncCDMIN->bbPDumpContinuous);
+
+
+
+RGXKickSyncCDM_exit:
+ if (sClientFenceUFOAddressInt)
+ OSFreeMem(sClientFenceUFOAddressInt);
+ if (ui32ClientFenceValueInt)
+ OSFreeMem(ui32ClientFenceValueInt);
+ if (sClientUpdateUFOAddressInt)
+ OSFreeMem(sClientUpdateUFOAddressInt);
+ if (ui32ClientUpdateValueInt)
+ OSFreeMem(ui32ClientUpdateValueInt);
+ if (ui32ServerSyncFlagsInt)
+ OSFreeMem(ui32ServerSyncFlagsInt);
+ if (psServerSyncsInt)
+ OSFreeMem(psServerSyncsInt);
+ if (hServerSyncsInt2)
+ OSFreeMem(hServerSyncsInt2);
+ if (i32FenceFDsInt)
+ OSFreeMem(i32FenceFDsInt);
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterRGXCMPFunctions(IMG_VOID);
+IMG_VOID UnregisterRGXCMPFunctions(IMG_VOID);
+
+/*
+ * Register all RGXCMP functions with services
+ */
+PVRSRV_ERROR RegisterRGXCMPFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP_RGXCREATECOMPUTECONTEXT, PVRSRVBridgeRGXCreateComputeContext);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP_RGXDESTROYCOMPUTECONTEXT, PVRSRVBridgeRGXDestroyComputeContext);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP_RGXKICKCDM, PVRSRVBridgeRGXKickCDM);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP_RGXFLUSHCOMPUTEDATA, PVRSRVBridgeRGXFlushComputeData);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP_RGXSETCOMPUTECONTEXTPRIORITY, PVRSRVBridgeRGXSetComputeContextPriority);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP_RGXKICKSYNCCDM, PVRSRVBridgeRGXKickSyncCDM);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all rgxcmp functions with services
+ */
+IMG_VOID UnregisterRGXCMPFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/rgxhwperf_bridge/common_rgxhwperf_bridge.h b/drivers/gpu/rogue/generated/rgxhwperf_bridge/common_rgxhwperf_bridge.h
new file mode 100644
index 000000000000..296fa692d156
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxhwperf_bridge/common_rgxhwperf_bridge.h
@@ -0,0 +1,140 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for rgxhwperf
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for rgxhwperf
+@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_RGXHWPERF_BRIDGE_H
+#define COMMON_RGXHWPERF_BRIDGE_H
+
+#include "rgx_bridge.h"
+#include "rgx_hwperf_km.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST (PVRSRV_BRIDGE_RGXHWPERF_START)
+#define PVRSRV_BRIDGE_RGXHWPERF_RGXCTRLHWPERF PVRSRV_IOWR(PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGENABLEHWPERFCOUNTERS PVRSRV_IOWR(PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RGXHWPERF_RGXCTRLHWPERFCOUNTERS PVRSRV_IOWR(PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGCUSTOMCOUNTERS PVRSRV_IOWR(PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_RGXHWPERF_CMD_LAST (PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+3)
+
+
+/*******************************************
+ RGXCtrlHWPerf
+ *******************************************/
+
+/* Bridge in structure for RGXCtrlHWPerf */
+typedef struct PVRSRV_BRIDGE_IN_RGXCTRLHWPERF_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_BOOL bToggle;
+ IMG_UINT64 ui64Mask;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCTRLHWPERF;
+
+
+/* Bridge out structure for RGXCtrlHWPerf */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCTRLHWPERF_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCTRLHWPERF;
+
+/*******************************************
+ RGXConfigEnableHWPerfCounters
+ *******************************************/
+
+/* Bridge in structure for RGXConfigEnableHWPerfCounters */
+typedef struct PVRSRV_BRIDGE_IN_RGXCONFIGENABLEHWPERFCOUNTERS_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32ArrayLen;
+ RGX_HWPERF_CONFIG_CNTBLK * psBlockConfigs;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCONFIGENABLEHWPERFCOUNTERS;
+
+
+/* Bridge out structure for RGXConfigEnableHWPerfCounters */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCONFIGENABLEHWPERFCOUNTERS_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCONFIGENABLEHWPERFCOUNTERS;
+
+/*******************************************
+ RGXCtrlHWPerfCounters
+ *******************************************/
+
+/* Bridge in structure for RGXCtrlHWPerfCounters */
+typedef struct PVRSRV_BRIDGE_IN_RGXCTRLHWPERFCOUNTERS_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_BOOL bEnable;
+ IMG_UINT32 ui32ArrayLen;
+ IMG_UINT8 * pui8BlockIDs;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCTRLHWPERFCOUNTERS;
+
+
+/* Bridge out structure for RGXCtrlHWPerfCounters */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCTRLHWPERFCOUNTERS_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCTRLHWPERFCOUNTERS;
+
+/*******************************************
+ RGXConfigCustomCounters
+ *******************************************/
+
+/* Bridge in structure for RGXConfigCustomCounters */
+typedef struct PVRSRV_BRIDGE_IN_RGXCONFIGCUSTOMCOUNTERS_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT16 ui16CustomBlockID;
+ IMG_UINT16 ui16NumCustomCounters;
+ IMG_UINT32 * pui32CustomCounterIDs;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCONFIGCUSTOMCOUNTERS;
+
+
+/* Bridge out structure for RGXConfigCustomCounters */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCONFIGCUSTOMCOUNTERS_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCONFIGCUSTOMCOUNTERS;
+
+#endif /* COMMON_RGXHWPERF_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/rgxhwperf_bridge/server_rgxhwperf_bridge.c b/drivers/gpu/rogue/generated/rgxhwperf_bridge/server_rgxhwperf_bridge.c
new file mode 100644
index 000000000000..1546a1de7775
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxhwperf_bridge/server_rgxhwperf_bridge.c
@@ -0,0 +1,340 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for rgxhwperf
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for rgxhwperf
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxhwperf.h"
+
+
+#include "common_rgxhwperf_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeRGXCtrlHWPerf(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCTRLHWPERF *psRGXCtrlHWPerfIN,
+ PVRSRV_BRIDGE_OUT_RGXCTRLHWPERF *psRGXCtrlHWPerfOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXHWPERF_RGXCTRLHWPERF);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXCtrlHWPerfOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCtrlHWPerfIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCtrlHWPerfOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCtrlHWPerf_exit;
+ }
+
+ }
+
+ psRGXCtrlHWPerfOUT->eError =
+ PVRSRVRGXCtrlHWPerfKM(
+ hDevNodeInt,
+ psRGXCtrlHWPerfIN->bToggle,
+ psRGXCtrlHWPerfIN->ui64Mask);
+
+
+
+RGXCtrlHWPerf_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXConfigEnableHWPerfCounters(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCONFIGENABLEHWPERFCOUNTERS *psRGXConfigEnableHWPerfCountersIN,
+ PVRSRV_BRIDGE_OUT_RGXCONFIGENABLEHWPERFCOUNTERS *psRGXConfigEnableHWPerfCountersOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ RGX_HWPERF_CONFIG_CNTBLK *psBlockConfigsInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGENABLEHWPERFCOUNTERS);
+
+
+
+
+ if (psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen != 0)
+ {
+ psBlockConfigsInt = OSAllocMem(psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK));
+ if (!psBlockConfigsInt)
+ {
+ psRGXConfigEnableHWPerfCountersOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXConfigEnableHWPerfCounters_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXConfigEnableHWPerfCountersIN->psBlockConfigs, psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK))
+ || (OSCopyFromUser(NULL, psBlockConfigsInt, psRGXConfigEnableHWPerfCountersIN->psBlockConfigs,
+ psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK)) != PVRSRV_OK) )
+ {
+ psRGXConfigEnableHWPerfCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXConfigEnableHWPerfCounters_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXConfigEnableHWPerfCountersOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXConfigEnableHWPerfCountersIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXConfigEnableHWPerfCountersOUT->eError != PVRSRV_OK)
+ {
+ goto RGXConfigEnableHWPerfCounters_exit;
+ }
+
+ }
+
+ psRGXConfigEnableHWPerfCountersOUT->eError =
+ PVRSRVRGXConfigEnableHWPerfCountersKM(
+ hDevNodeInt,
+ psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen,
+ psBlockConfigsInt);
+
+
+
+RGXConfigEnableHWPerfCounters_exit:
+ if (psBlockConfigsInt)
+ OSFreeMem(psBlockConfigsInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXCtrlHWPerfCounters(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCTRLHWPERFCOUNTERS *psRGXCtrlHWPerfCountersIN,
+ PVRSRV_BRIDGE_OUT_RGXCTRLHWPERFCOUNTERS *psRGXCtrlHWPerfCountersOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_UINT8 *ui8BlockIDsInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXHWPERF_RGXCTRLHWPERFCOUNTERS);
+
+
+
+
+ if (psRGXCtrlHWPerfCountersIN->ui32ArrayLen != 0)
+ {
+ ui8BlockIDsInt = OSAllocMem(psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT8));
+ if (!ui8BlockIDsInt)
+ {
+ psRGXCtrlHWPerfCountersOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXCtrlHWPerfCounters_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXCtrlHWPerfCountersIN->pui8BlockIDs, psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT8))
+ || (OSCopyFromUser(NULL, ui8BlockIDsInt, psRGXCtrlHWPerfCountersIN->pui8BlockIDs,
+ psRGXCtrlHWPerfCountersIN->ui32ArrayLen * sizeof(IMG_UINT8)) != PVRSRV_OK) )
+ {
+ psRGXCtrlHWPerfCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXCtrlHWPerfCounters_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCtrlHWPerfCountersOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCtrlHWPerfCountersIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCtrlHWPerfCountersOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCtrlHWPerfCounters_exit;
+ }
+
+ }
+
+ psRGXCtrlHWPerfCountersOUT->eError =
+ PVRSRVRGXCtrlHWPerfCountersKM(
+ hDevNodeInt,
+ psRGXCtrlHWPerfCountersIN->bEnable,
+ psRGXCtrlHWPerfCountersIN->ui32ArrayLen,
+ ui8BlockIDsInt);
+
+
+
+RGXCtrlHWPerfCounters_exit:
+ if (ui8BlockIDsInt)
+ OSFreeMem(ui8BlockIDsInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXConfigCustomCounters(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCONFIGCUSTOMCOUNTERS *psRGXConfigCustomCountersIN,
+ PVRSRV_BRIDGE_OUT_RGXCONFIGCUSTOMCOUNTERS *psRGXConfigCustomCountersOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_UINT32 *ui32CustomCounterIDsInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGCUSTOMCOUNTERS);
+
+
+
+
+ if (psRGXConfigCustomCountersIN->ui16NumCustomCounters != 0)
+ {
+ ui32CustomCounterIDsInt = OSAllocMem(psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32));
+ if (!ui32CustomCounterIDsInt)
+ {
+ psRGXConfigCustomCountersOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXConfigCustomCounters_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXConfigCustomCountersIN->pui32CustomCounterIDs, psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32CustomCounterIDsInt, psRGXConfigCustomCountersIN->pui32CustomCounterIDs,
+ psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXConfigCustomCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXConfigCustomCounters_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXConfigCustomCountersOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXConfigCustomCountersIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXConfigCustomCountersOUT->eError != PVRSRV_OK)
+ {
+ goto RGXConfigCustomCounters_exit;
+ }
+
+ }
+
+ psRGXConfigCustomCountersOUT->eError =
+ PVRSRVRGXConfigCustomCountersKM(
+ hDevNodeInt,
+ psRGXConfigCustomCountersIN->ui16CustomBlockID,
+ psRGXConfigCustomCountersIN->ui16NumCustomCounters,
+ ui32CustomCounterIDsInt);
+
+
+
+RGXConfigCustomCounters_exit:
+ if (ui32CustomCounterIDsInt)
+ OSFreeMem(ui32CustomCounterIDsInt);
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterRGXHWPERFFunctions(IMG_VOID);
+IMG_VOID UnregisterRGXHWPERFFunctions(IMG_VOID);
+
+/*
+ * Register all RGXHWPERF functions with services
+ */
+PVRSRV_ERROR RegisterRGXHWPERFFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF_RGXCTRLHWPERF, PVRSRVBridgeRGXCtrlHWPerf);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGENABLEHWPERFCOUNTERS, PVRSRVBridgeRGXConfigEnableHWPerfCounters);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF_RGXCTRLHWPERFCOUNTERS, PVRSRVBridgeRGXCtrlHWPerfCounters);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGCUSTOMCOUNTERS, PVRSRVBridgeRGXConfigCustomCounters);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all rgxhwperf functions with services
+ */
+IMG_VOID UnregisterRGXHWPERFFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/rgxinit_bridge/common_rgxinit_bridge.h b/drivers/gpu/rogue/generated/rgxinit_bridge/common_rgxinit_bridge.h
new file mode 100644
index 000000000000..c729008e0318
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxinit_bridge/common_rgxinit_bridge.h
@@ -0,0 +1,174 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for rgxinit
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for rgxinit
+@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_RGXINIT_BRIDGE_H
+#define COMMON_RGXINIT_BRIDGE_H
+
+#include "rgx_bridge.h"
+#include "rgxscript.h"
+#include "devicemem_typedefs.h"
+#include "rgx_fwif_shared.h"
+#include "rgx_fwif.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_RGXINIT_CMD_FIRST (PVRSRV_BRIDGE_RGXINIT_START)
+#define PVRSRV_BRIDGE_RGXINIT_RGXINITALLOCFWIMGMEM PVRSRV_IOWR(PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RGXINIT_RGXINITFIRMWARE PVRSRV_IOWR(PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RGXINIT_RGXINITLOADFWIMAGE PVRSRV_IOWR(PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_RGXINIT_RGXINITDEVPART2 PVRSRV_IOWR(PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_RGXINIT_CMD_LAST (PVRSRV_BRIDGE_RGXINIT_CMD_FIRST+3)
+
+
+/*******************************************
+ RGXInitAllocFWImgMem
+ *******************************************/
+
+/* Bridge in structure for RGXInitAllocFWImgMem */
+typedef struct PVRSRV_BRIDGE_IN_RGXINITALLOCFWIMGMEM_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_DEVMEM_SIZE_T uiFWCodeLen;
+ IMG_DEVMEM_SIZE_T uiFWDataLen;
+ IMG_DEVMEM_SIZE_T uiFWCoremem;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXINITALLOCFWIMGMEM;
+
+
+/* Bridge out structure for RGXInitAllocFWImgMem */
+typedef struct PVRSRV_BRIDGE_OUT_RGXINITALLOCFWIMGMEM_TAG
+{
+ DEVMEM_SERVER_EXPORTCOOKIE hFWCodeAllocServerExportCookie;
+ IMG_DEV_VIRTADDR sFWCodeDevVAddrBase;
+ DEVMEM_SERVER_EXPORTCOOKIE hFWDataAllocServerExportCookie;
+ IMG_DEV_VIRTADDR sFWDataDevVAddrBase;
+ DEVMEM_SERVER_EXPORTCOOKIE hFWCorememAllocServerExportCookie;
+ IMG_DEV_VIRTADDR sFWCorememDevVAddrBase;
+ RGXFWIF_DEV_VIRTADDR sFWCorememMetaVAddrBase;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXINITALLOCFWIMGMEM;
+
+/*******************************************
+ RGXInitFirmware
+ *******************************************/
+
+/* Bridge in structure for RGXInitFirmware */
+typedef struct PVRSRV_BRIDGE_IN_RGXINITFIRMWARE_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_BOOL bEnableSignatureChecks;
+ IMG_UINT32 ui32SignatureChecksBufSize;
+ IMG_UINT32 ui32HWPerfFWBufSizeKB;
+ IMG_UINT64 ui64HWPerfFilter;
+ IMG_UINT32 ui32RGXFWAlignChecksSize;
+ IMG_UINT32 * pui32RGXFWAlignChecks;
+ IMG_UINT32 ui32ConfigFlags;
+ IMG_UINT32 ui32LogType;
+ IMG_UINT32 ui32FilterFlags;
+ RGXFWIF_COMPCHECKS_BVNC sClientBVNC;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXINITFIRMWARE;
+
+
+/* Bridge out structure for RGXInitFirmware */
+typedef struct PVRSRV_BRIDGE_OUT_RGXINITFIRMWARE_TAG
+{
+ RGXFWIF_DEV_VIRTADDR spsRGXFwInit;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXINITFIRMWARE;
+
+/*******************************************
+ RGXInitLoadFWImage
+ *******************************************/
+
+/* Bridge in structure for RGXInitLoadFWImage */
+typedef struct PVRSRV_BRIDGE_IN_RGXINITLOADFWIMAGE_TAG
+{
+ IMG_HANDLE hImgDestImport;
+ IMG_HANDLE hImgSrcImport;
+ IMG_UINT64 ui64ImgLen;
+ IMG_HANDLE hSigImport;
+ IMG_UINT64 ui64SigLen;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXINITLOADFWIMAGE;
+
+
+/* Bridge out structure for RGXInitLoadFWImage */
+typedef struct PVRSRV_BRIDGE_OUT_RGXINITLOADFWIMAGE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXINITLOADFWIMAGE;
+
+/*******************************************
+ RGXInitDevPart2
+ *******************************************/
+
+/* Bridge in structure for RGXInitDevPart2 */
+typedef struct PVRSRV_BRIDGE_IN_RGXINITDEVPART2_TAG
+{
+ IMG_HANDLE hDevNode;
+ RGX_INIT_COMMAND * psInitScript;
+ RGX_INIT_COMMAND * psDbgScript;
+ RGX_INIT_COMMAND * psDbgBusScript;
+ RGX_INIT_COMMAND * psDeinitScript;
+ IMG_UINT32 ui32ui32KernelCatBaseIdReg;
+ IMG_UINT32 ui32KernelCatBaseId;
+ IMG_UINT32 ui32KernelCatBaseReg;
+ IMG_UINT32 ui32KernelCatBaseWordSize;
+ IMG_UINT32 ui32KernelCatBaseAlignShift;
+ IMG_UINT32 ui32KernelCatBaseShift;
+ IMG_UINT64 ui64KernelCatBaseMask;
+ IMG_UINT32 ui32DeviceFlags;
+ IMG_UINT32 ui32RGXActivePMConf;
+ DEVMEM_SERVER_EXPORTCOOKIE hFWCodeAllocServerExportCookie;
+ DEVMEM_SERVER_EXPORTCOOKIE hFWDataAllocServerExportCookie;
+ DEVMEM_SERVER_EXPORTCOOKIE hFWCorememAllocServerExportCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXINITDEVPART2;
+
+
+/* Bridge out structure for RGXInitDevPart2 */
+typedef struct PVRSRV_BRIDGE_OUT_RGXINITDEVPART2_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXINITDEVPART2;
+
+#endif /* COMMON_RGXINIT_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/rgxinit_bridge/server_rgxinit_bridge.c b/drivers/gpu/rogue/generated/rgxinit_bridge/server_rgxinit_bridge.c
new file mode 100644
index 000000000000..b52586691e36
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxinit_bridge/server_rgxinit_bridge.c
@@ -0,0 +1,575 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for rgxinit
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for rgxinit
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxinit.h"
+
+
+#include "common_rgxinit_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeRGXInitAllocFWImgMem(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXINITALLOCFWIMGMEM *psRGXInitAllocFWImgMemIN,
+ PVRSRV_BRIDGE_OUT_RGXINITALLOCFWIMGMEM *psRGXInitAllocFWImgMemOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ DEVMEM_EXPORTCOOKIE * psFWCodeAllocServerExportCookieInt = IMG_NULL;
+ DEVMEM_EXPORTCOOKIE * psFWDataAllocServerExportCookieInt = IMG_NULL;
+ DEVMEM_EXPORTCOOKIE * psFWCorememAllocServerExportCookieInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXINIT_RGXINITALLOCFWIMGMEM);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXInitAllocFWImgMemOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXInitAllocFWImgMemIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitAllocFWImgMem_exit;
+ }
+
+ }
+
+ psRGXInitAllocFWImgMemOUT->eError =
+ PVRSRVRGXInitAllocFWImgMemKM(
+ hDevNodeInt,
+ psRGXInitAllocFWImgMemIN->uiFWCodeLen,
+ psRGXInitAllocFWImgMemIN->uiFWDataLen,
+ psRGXInitAllocFWImgMemIN->uiFWCoremem,
+ &psFWCodeAllocServerExportCookieInt,
+ &psRGXInitAllocFWImgMemOUT->sFWCodeDevVAddrBase,
+ &psFWDataAllocServerExportCookieInt,
+ &psRGXInitAllocFWImgMemOUT->sFWDataDevVAddrBase,
+ &psFWCorememAllocServerExportCookieInt,
+ &psRGXInitAllocFWImgMemOUT->sFWCorememDevVAddrBase,
+ &psRGXInitAllocFWImgMemOUT->sFWCorememMetaVAddrBase);
+ /* Exit early if bridged call fails */
+ if(psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitAllocFWImgMem_exit;
+ }
+
+ psRGXInitAllocFWImgMemOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXInitAllocFWImgMemOUT->hFWCodeAllocServerExportCookie,
+ (IMG_HANDLE) psFWCodeAllocServerExportCookieInt,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitAllocFWImgMem_exit;
+ }
+ psRGXInitAllocFWImgMemOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXInitAllocFWImgMemOUT->hFWDataAllocServerExportCookie,
+ (IMG_HANDLE) psFWDataAllocServerExportCookieInt,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitAllocFWImgMem_exit;
+ }
+ psRGXInitAllocFWImgMemOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXInitAllocFWImgMemOUT->hFWCorememAllocServerExportCookie,
+ (IMG_HANDLE) psFWCorememAllocServerExportCookieInt,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitAllocFWImgMem_exit;
+ }
+
+
+RGXInitAllocFWImgMem_exit:
+ if (psRGXInitAllocFWImgMemOUT->eError != PVRSRV_OK)
+ {
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXInitFirmware(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXINITFIRMWARE *psRGXInitFirmwareIN,
+ PVRSRV_BRIDGE_OUT_RGXINITFIRMWARE *psRGXInitFirmwareOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_UINT32 *ui32RGXFWAlignChecksInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXINIT_RGXINITFIRMWARE);
+
+
+
+
+ if (psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize != 0)
+ {
+ ui32RGXFWAlignChecksInt = OSAllocMem(psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize * sizeof(IMG_UINT32));
+ if (!ui32RGXFWAlignChecksInt)
+ {
+ psRGXInitFirmwareOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXInitFirmware_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXInitFirmwareIN->pui32RGXFWAlignChecks, psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32RGXFWAlignChecksInt, psRGXInitFirmwareIN->pui32RGXFWAlignChecks,
+ psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXInitFirmwareOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXInitFirmware_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXInitFirmwareOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXInitFirmwareIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXInitFirmwareOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitFirmware_exit;
+ }
+
+ }
+
+ psRGXInitFirmwareOUT->eError =
+ PVRSRVRGXInitFirmwareKM(
+ hDevNodeInt,
+ &psRGXInitFirmwareOUT->spsRGXFwInit,
+ psRGXInitFirmwareIN->bEnableSignatureChecks,
+ psRGXInitFirmwareIN->ui32SignatureChecksBufSize,
+ psRGXInitFirmwareIN->ui32HWPerfFWBufSizeKB,
+ psRGXInitFirmwareIN->ui64HWPerfFilter,
+ psRGXInitFirmwareIN->ui32RGXFWAlignChecksSize,
+ ui32RGXFWAlignChecksInt,
+ psRGXInitFirmwareIN->ui32ConfigFlags,
+ psRGXInitFirmwareIN->ui32LogType,
+ psRGXInitFirmwareIN->ui32FilterFlags,
+ &psRGXInitFirmwareIN->sClientBVNC);
+
+
+
+RGXInitFirmware_exit:
+ if (ui32RGXFWAlignChecksInt)
+ OSFreeMem(ui32RGXFWAlignChecksInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXInitLoadFWImage(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXINITLOADFWIMAGE *psRGXInitLoadFWImageIN,
+ PVRSRV_BRIDGE_OUT_RGXINITLOADFWIMAGE *psRGXInitLoadFWImageOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psImgDestImportInt = IMG_NULL;
+ IMG_HANDLE hImgDestImportInt2 = IMG_NULL;
+ PMR * psImgSrcImportInt = IMG_NULL;
+ IMG_HANDLE hImgSrcImportInt2 = IMG_NULL;
+ PMR * psSigImportInt = IMG_NULL;
+ IMG_HANDLE hSigImportInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXINIT_RGXINITLOADFWIMAGE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXInitLoadFWImageOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hImgDestImportInt2,
+ psRGXInitLoadFWImageIN->hImgDestImport,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psRGXInitLoadFWImageOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitLoadFWImage_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXInitLoadFWImageOUT->eError = ResManFindPrivateDataByPtr(hImgDestImportInt2, (IMG_VOID **) &psImgDestImportInt);
+
+ if(psRGXInitLoadFWImageOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitLoadFWImage_exit;
+ }
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXInitLoadFWImageOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hImgSrcImportInt2,
+ psRGXInitLoadFWImageIN->hImgSrcImport,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psRGXInitLoadFWImageOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitLoadFWImage_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXInitLoadFWImageOUT->eError = ResManFindPrivateDataByPtr(hImgSrcImportInt2, (IMG_VOID **) &psImgSrcImportInt);
+
+ if(psRGXInitLoadFWImageOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitLoadFWImage_exit;
+ }
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXInitLoadFWImageOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSigImportInt2,
+ psRGXInitLoadFWImageIN->hSigImport,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psRGXInitLoadFWImageOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitLoadFWImage_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXInitLoadFWImageOUT->eError = ResManFindPrivateDataByPtr(hSigImportInt2, (IMG_VOID **) &psSigImportInt);
+
+ if(psRGXInitLoadFWImageOUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitLoadFWImage_exit;
+ }
+ }
+
+ psRGXInitLoadFWImageOUT->eError =
+ PVRSRVRGXInitLoadFWImageKM(
+ psImgDestImportInt,
+ psImgSrcImportInt,
+ psRGXInitLoadFWImageIN->ui64ImgLen,
+ psSigImportInt,
+ psRGXInitLoadFWImageIN->ui64SigLen);
+
+
+
+RGXInitLoadFWImage_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXInitDevPart2(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXINITDEVPART2 *psRGXInitDevPart2IN,
+ PVRSRV_BRIDGE_OUT_RGXINITDEVPART2 *psRGXInitDevPart2OUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ RGX_INIT_COMMAND *psInitScriptInt = IMG_NULL;
+ RGX_INIT_COMMAND *psDbgScriptInt = IMG_NULL;
+ RGX_INIT_COMMAND *psDbgBusScriptInt = IMG_NULL;
+ RGX_INIT_COMMAND *psDeinitScriptInt = IMG_NULL;
+ DEVMEM_EXPORTCOOKIE * psFWCodeAllocServerExportCookieInt = IMG_NULL;
+ DEVMEM_EXPORTCOOKIE * psFWDataAllocServerExportCookieInt = IMG_NULL;
+ DEVMEM_EXPORTCOOKIE * psFWCorememAllocServerExportCookieInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXINIT_RGXINITDEVPART2);
+
+
+
+
+
+ {
+ psInitScriptInt = OSAllocMem(RGX_MAX_INIT_COMMANDS * sizeof(RGX_INIT_COMMAND));
+ if (!psInitScriptInt)
+ {
+ psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXInitDevPart2_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXInitDevPart2IN->psInitScript, RGX_MAX_INIT_COMMANDS * sizeof(RGX_INIT_COMMAND))
+ || (OSCopyFromUser(NULL, psInitScriptInt, psRGXInitDevPart2IN->psInitScript,
+ RGX_MAX_INIT_COMMANDS * sizeof(RGX_INIT_COMMAND)) != PVRSRV_OK) )
+ {
+ psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXInitDevPart2_exit;
+ }
+
+ {
+ psDbgScriptInt = OSAllocMem(RGX_MAX_INIT_COMMANDS * sizeof(RGX_INIT_COMMAND));
+ if (!psDbgScriptInt)
+ {
+ psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXInitDevPart2_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXInitDevPart2IN->psDbgScript, RGX_MAX_INIT_COMMANDS * sizeof(RGX_INIT_COMMAND))
+ || (OSCopyFromUser(NULL, psDbgScriptInt, psRGXInitDevPart2IN->psDbgScript,
+ RGX_MAX_INIT_COMMANDS * sizeof(RGX_INIT_COMMAND)) != PVRSRV_OK) )
+ {
+ psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXInitDevPart2_exit;
+ }
+
+ {
+ psDbgBusScriptInt = OSAllocMem(RGX_MAX_DBGBUS_COMMANDS * sizeof(RGX_INIT_COMMAND));
+ if (!psDbgBusScriptInt)
+ {
+ psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXInitDevPart2_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXInitDevPart2IN->psDbgBusScript, RGX_MAX_DBGBUS_COMMANDS * sizeof(RGX_INIT_COMMAND))
+ || (OSCopyFromUser(NULL, psDbgBusScriptInt, psRGXInitDevPart2IN->psDbgBusScript,
+ RGX_MAX_DBGBUS_COMMANDS * sizeof(RGX_INIT_COMMAND)) != PVRSRV_OK) )
+ {
+ psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXInitDevPart2_exit;
+ }
+
+ {
+ psDeinitScriptInt = OSAllocMem(RGX_MAX_DEINIT_COMMANDS * sizeof(RGX_INIT_COMMAND));
+ if (!psDeinitScriptInt)
+ {
+ psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXInitDevPart2_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXInitDevPart2IN->psDeinitScript, RGX_MAX_DEINIT_COMMANDS * sizeof(RGX_INIT_COMMAND))
+ || (OSCopyFromUser(NULL, psDeinitScriptInt, psRGXInitDevPart2IN->psDeinitScript,
+ RGX_MAX_DEINIT_COMMANDS * sizeof(RGX_INIT_COMMAND)) != PVRSRV_OK) )
+ {
+ psRGXInitDevPart2OUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXInitDevPart2_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXInitDevPart2OUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXInitDevPart2IN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXInitDevPart2OUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitDevPart2_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXInitDevPart2OUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &psFWCodeAllocServerExportCookieInt,
+ psRGXInitDevPart2IN->hFWCodeAllocServerExportCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE);
+ if(psRGXInitDevPart2OUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitDevPart2_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXInitDevPart2OUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &psFWDataAllocServerExportCookieInt,
+ psRGXInitDevPart2IN->hFWDataAllocServerExportCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE);
+ if(psRGXInitDevPart2OUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitDevPart2_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXInitDevPart2OUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &psFWCorememAllocServerExportCookieInt,
+ psRGXInitDevPart2IN->hFWCorememAllocServerExportCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE);
+ if(psRGXInitDevPart2OUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitDevPart2_exit;
+ }
+
+ }
+
+ psRGXInitDevPart2OUT->eError =
+ PVRSRVRGXInitDevPart2KM(
+ hDevNodeInt,
+ psInitScriptInt,
+ psDbgScriptInt,
+ psDbgBusScriptInt,
+ psDeinitScriptInt,
+ psRGXInitDevPart2IN->ui32ui32KernelCatBaseIdReg,
+ psRGXInitDevPart2IN->ui32KernelCatBaseId,
+ psRGXInitDevPart2IN->ui32KernelCatBaseReg,
+ psRGXInitDevPart2IN->ui32KernelCatBaseWordSize,
+ psRGXInitDevPart2IN->ui32KernelCatBaseAlignShift,
+ psRGXInitDevPart2IN->ui32KernelCatBaseShift,
+ psRGXInitDevPart2IN->ui64KernelCatBaseMask,
+ psRGXInitDevPart2IN->ui32DeviceFlags,
+ psRGXInitDevPart2IN->ui32RGXActivePMConf,
+ psFWCodeAllocServerExportCookieInt,
+ psFWDataAllocServerExportCookieInt,
+ psFWCorememAllocServerExportCookieInt);
+ /* Exit early if bridged call fails */
+ if(psRGXInitDevPart2OUT->eError != PVRSRV_OK)
+ {
+ goto RGXInitDevPart2_exit;
+ }
+
+ psRGXInitDevPart2OUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXInitDevPart2IN->hFWCodeAllocServerExportCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE);
+ psRGXInitDevPart2OUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXInitDevPart2IN->hFWDataAllocServerExportCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE);
+ psRGXInitDevPart2OUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXInitDevPart2IN->hFWCorememAllocServerExportCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE);
+
+
+RGXInitDevPart2_exit:
+ if (psInitScriptInt)
+ OSFreeMem(psInitScriptInt);
+ if (psDbgScriptInt)
+ OSFreeMem(psDbgScriptInt);
+ if (psDbgBusScriptInt)
+ OSFreeMem(psDbgBusScriptInt);
+ if (psDeinitScriptInt)
+ OSFreeMem(psDeinitScriptInt);
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterRGXINITFunctions(IMG_VOID);
+IMG_VOID UnregisterRGXINITFunctions(IMG_VOID);
+
+/*
+ * Register all RGXINIT functions with services
+ */
+PVRSRV_ERROR RegisterRGXINITFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXINIT_RGXINITALLOCFWIMGMEM, PVRSRVBridgeRGXInitAllocFWImgMem);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXINIT_RGXINITFIRMWARE, PVRSRVBridgeRGXInitFirmware);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXINIT_RGXINITLOADFWIMAGE, PVRSRVBridgeRGXInitLoadFWImage);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXINIT_RGXINITDEVPART2, PVRSRVBridgeRGXInitDevPart2);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all rgxinit functions with services
+ */
+IMG_VOID UnregisterRGXINITFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/rgxpdump_bridge/common_rgxpdump_bridge.h b/drivers/gpu/rogue/generated/rgxpdump_bridge/common_rgxpdump_bridge.h
new file mode 100644
index 000000000000..0b891ababa86
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxpdump_bridge/common_rgxpdump_bridge.h
@@ -0,0 +1,95 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for rgxpdump
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for rgxpdump
+@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_RGXPDUMP_BRIDGE_H
+#define COMMON_RGXPDUMP_BRIDGE_H
+
+#include "rgx_bridge.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_RGXPDUMP_CMD_FIRST (PVRSRV_BRIDGE_RGXPDUMP_START)
+#define PVRSRV_BRIDGE_RGXPDUMP_PDUMPTRACEBUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_RGXPDUMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RGXPDUMP_PDUMPSIGNATUREBUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_RGXPDUMP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RGXPDUMP_CMD_LAST (PVRSRV_BRIDGE_RGXPDUMP_CMD_FIRST+1)
+
+
+/*******************************************
+ PDumpTraceBuffer
+ *******************************************/
+
+/* Bridge in structure for PDumpTraceBuffer */
+typedef struct PVRSRV_BRIDGE_IN_PDUMPTRACEBUFFER_TAG
+{
+ IMG_HANDLE hDeviceNode;
+ IMG_UINT32 ui32PDumpFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PDUMPTRACEBUFFER;
+
+
+/* Bridge out structure for PDumpTraceBuffer */
+typedef struct PVRSRV_BRIDGE_OUT_PDUMPTRACEBUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PDUMPTRACEBUFFER;
+
+/*******************************************
+ PDumpSignatureBuffer
+ *******************************************/
+
+/* Bridge in structure for PDumpSignatureBuffer */
+typedef struct PVRSRV_BRIDGE_IN_PDUMPSIGNATUREBUFFER_TAG
+{
+ IMG_HANDLE hDeviceNode;
+ IMG_UINT32 ui32PDumpFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PDUMPSIGNATUREBUFFER;
+
+
+/* Bridge out structure for PDumpSignatureBuffer */
+typedef struct PVRSRV_BRIDGE_OUT_PDUMPSIGNATUREBUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PDUMPSIGNATUREBUFFER;
+
+#endif /* COMMON_RGXPDUMP_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/rgxpdump_bridge/server_rgxpdump_bridge.c b/drivers/gpu/rogue/generated/rgxpdump_bridge/server_rgxpdump_bridge.c
new file mode 100644
index 000000000000..5206d891ef9a
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxpdump_bridge/server_rgxpdump_bridge.c
@@ -0,0 +1,183 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for rgxpdump
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for rgxpdump
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxpdump.h"
+
+
+#include "common_rgxpdump_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgePDumpTraceBuffer(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMPTRACEBUFFER *psPDumpTraceBufferIN,
+ PVRSRV_BRIDGE_OUT_PDUMPTRACEBUFFER *psPDumpTraceBufferOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXPDUMP_PDUMPTRACEBUFFER);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPDumpTraceBufferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psPDumpTraceBufferIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psPDumpTraceBufferOUT->eError != PVRSRV_OK)
+ {
+ goto PDumpTraceBuffer_exit;
+ }
+
+ }
+
+ psPDumpTraceBufferOUT->eError =
+ PVRSRVPDumpTraceBufferKM(
+ hDeviceNodeInt,
+ psPDumpTraceBufferIN->ui32PDumpFlags);
+
+
+
+PDumpTraceBuffer_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePDumpSignatureBuffer(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMPSIGNATUREBUFFER *psPDumpSignatureBufferIN,
+ PVRSRV_BRIDGE_OUT_PDUMPSIGNATUREBUFFER *psPDumpSignatureBufferOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDeviceNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXPDUMP_PDUMPSIGNATUREBUFFER);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psPDumpSignatureBufferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDeviceNodeInt,
+ psPDumpSignatureBufferIN->hDeviceNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psPDumpSignatureBufferOUT->eError != PVRSRV_OK)
+ {
+ goto PDumpSignatureBuffer_exit;
+ }
+
+ }
+
+ psPDumpSignatureBufferOUT->eError =
+ PVRSRVPDumpSignatureBufferKM(
+ hDeviceNodeInt,
+ psPDumpSignatureBufferIN->ui32PDumpFlags);
+
+
+
+PDumpSignatureBuffer_exit:
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterRGXPDUMPFunctions(IMG_VOID);
+IMG_VOID UnregisterRGXPDUMPFunctions(IMG_VOID);
+
+/*
+ * Register all RGXPDUMP functions with services
+ */
+PVRSRV_ERROR RegisterRGXPDUMPFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXPDUMP_PDUMPTRACEBUFFER, PVRSRVBridgePDumpTraceBuffer);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXPDUMP_PDUMPSIGNATUREBUFFER, PVRSRVBridgePDumpSignatureBuffer);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all rgxpdump functions with services
+ */
+IMG_VOID UnregisterRGXPDUMPFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/rgxta3d_bridge/common_rgxta3d_bridge.h b/drivers/gpu/rogue/generated/rgxta3d_bridge/common_rgxta3d_bridge.h
new file mode 100644
index 000000000000..03351abe23db
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxta3d_bridge/common_rgxta3d_bridge.h
@@ -0,0 +1,519 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for rgxta3d
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for rgxta3d
+@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_RGXTA3D_BRIDGE_H
+#define COMMON_RGXTA3D_BRIDGE_H
+
+#include "rgx_bridge.h"
+#include "sync_external.h"
+#include "rgx_fwif_shared.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST (PVRSRV_BRIDGE_RGXTA3D_START)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXCREATEHWRTDATA PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYHWRTDATA PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXCREATERENDERTARGET PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYRENDERTARGET PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXCREATEZSBUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYZSBUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXPOPULATEZSBUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXUNPOPULATEZSBUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXCREATEFREELIST PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYFREELIST PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXADDBLOCKTOFREELIST PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXREMOVEBLOCKFROMFREELIST PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXCREATERENDERCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYRENDERCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXKICKTA3D PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXSETRENDERCONTEXTPRIORITY PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXGETLASTRENDERCONTEXTRESETREASON PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXGETPARTIALRENDERCOUNT PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_RGXTA3D_RGXKICKSYNCTA PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_RGXTA3D_CMD_LAST (PVRSRV_BRIDGE_RGXTA3D_CMD_FIRST+18)
+
+
+/*******************************************
+ RGXCreateHWRTData
+ *******************************************/
+
+/* Bridge in structure for RGXCreateHWRTData */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATEHWRTDATA_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32RenderTarget;
+ IMG_DEV_VIRTADDR sPMMlistDevVAddr;
+ IMG_DEV_VIRTADDR sVFPPageTableAddr;
+ IMG_HANDLE * phapsFreeLists;
+ IMG_UINT32 ui32PPPScreen;
+ IMG_UINT32 ui32PPPGridOffset;
+ IMG_UINT64 ui64PPPMultiSampleCtl;
+ 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 ui32ui32ISPMergeLowerX;
+ IMG_UINT32 ui32ui32ISPMergeLowerY;
+ IMG_UINT32 ui32ui32ISPMergeUpperX;
+ IMG_UINT32 ui32ui32ISPMergeUpperY;
+ IMG_UINT32 ui32ui32ISPMergeScaleX;
+ IMG_UINT32 ui32ui32ISPMergeScaleY;
+ IMG_UINT16 ui16MaxRTs;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATEHWRTDATA;
+
+
+/* Bridge out structure for RGXCreateHWRTData */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATEHWRTDATA_TAG
+{
+ IMG_HANDLE hCleanupCookie;
+ IMG_HANDLE hRTACtlMemDesc;
+ IMG_HANDLE hsHWRTDataMemDesc;
+ IMG_UINT32 ui32FWHWRTData;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATEHWRTDATA;
+
+/*******************************************
+ RGXDestroyHWRTData
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyHWRTData */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYHWRTDATA_TAG
+{
+ IMG_HANDLE hCleanupCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYHWRTDATA;
+
+
+/* Bridge out structure for RGXDestroyHWRTData */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYHWRTDATA_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYHWRTDATA;
+
+/*******************************************
+ RGXCreateRenderTarget
+ *******************************************/
+
+/* Bridge in structure for RGXCreateRenderTarget */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATERENDERTARGET_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_DEV_VIRTADDR spsVHeapTableDevVAddr;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATERENDERTARGET;
+
+
+/* Bridge out structure for RGXCreateRenderTarget */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATERENDERTARGET_TAG
+{
+ IMG_HANDLE hsRenderTargetMemDesc;
+ IMG_UINT32 ui32sRenderTargetFWDevVAddr;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATERENDERTARGET;
+
+/*******************************************
+ RGXDestroyRenderTarget
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyRenderTarget */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYRENDERTARGET_TAG
+{
+ IMG_HANDLE hsRenderTargetMemDesc;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYRENDERTARGET;
+
+
+/* Bridge out structure for RGXDestroyRenderTarget */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYRENDERTARGET_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYRENDERTARGET;
+
+/*******************************************
+ RGXCreateZSBuffer
+ *******************************************/
+
+/* Bridge in structure for RGXCreateZSBuffer */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATEZSBUFFER_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_HANDLE hReservation;
+ IMG_HANDLE hPMR;
+ PVRSRV_MEMALLOCFLAGS_T uiMapFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATEZSBUFFER;
+
+
+/* Bridge out structure for RGXCreateZSBuffer */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATEZSBUFFER_TAG
+{
+ IMG_HANDLE hsZSBufferKM;
+ IMG_UINT32 ui32sZSBufferFWDevVAddr;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATEZSBUFFER;
+
+/*******************************************
+ RGXDestroyZSBuffer
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyZSBuffer */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYZSBUFFER_TAG
+{
+ IMG_HANDLE hsZSBufferMemDesc;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYZSBUFFER;
+
+
+/* Bridge out structure for RGXDestroyZSBuffer */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYZSBUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYZSBUFFER;
+
+/*******************************************
+ RGXPopulateZSBuffer
+ *******************************************/
+
+/* Bridge in structure for RGXPopulateZSBuffer */
+typedef struct PVRSRV_BRIDGE_IN_RGXPOPULATEZSBUFFER_TAG
+{
+ IMG_HANDLE hsZSBufferKM;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXPOPULATEZSBUFFER;
+
+
+/* Bridge out structure for RGXPopulateZSBuffer */
+typedef struct PVRSRV_BRIDGE_OUT_RGXPOPULATEZSBUFFER_TAG
+{
+ IMG_HANDLE hsPopulation;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXPOPULATEZSBUFFER;
+
+/*******************************************
+ RGXUnpopulateZSBuffer
+ *******************************************/
+
+/* Bridge in structure for RGXUnpopulateZSBuffer */
+typedef struct PVRSRV_BRIDGE_IN_RGXUNPOPULATEZSBUFFER_TAG
+{
+ IMG_HANDLE hsPopulation;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXUNPOPULATEZSBUFFER;
+
+
+/* Bridge out structure for RGXUnpopulateZSBuffer */
+typedef struct PVRSRV_BRIDGE_OUT_RGXUNPOPULATEZSBUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXUNPOPULATEZSBUFFER;
+
+/*******************************************
+ RGXCreateFreeList
+ *******************************************/
+
+/* Bridge in structure for RGXCreateFreeList */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATEFREELIST_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32ui32MaxFLPages;
+ IMG_UINT32 ui32ui32InitFLPages;
+ IMG_UINT32 ui32ui32GrowFLPages;
+ IMG_BOOL bbFreeListCheck;
+ IMG_DEV_VIRTADDR spsFreeListDevVAddr;
+ IMG_HANDLE hsFreeListPMR;
+ IMG_DEVMEM_OFFSET_T uiPMROffset;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATEFREELIST;
+
+
+/* Bridge out structure for RGXCreateFreeList */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATEFREELIST_TAG
+{
+ IMG_HANDLE hCleanupCookie;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATEFREELIST;
+
+/*******************************************
+ RGXDestroyFreeList
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyFreeList */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYFREELIST_TAG
+{
+ IMG_HANDLE hCleanupCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYFREELIST;
+
+
+/* Bridge out structure for RGXDestroyFreeList */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYFREELIST_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYFREELIST;
+
+/*******************************************
+ RGXAddBlockToFreeList
+ *******************************************/
+
+/* Bridge in structure for RGXAddBlockToFreeList */
+typedef struct PVRSRV_BRIDGE_IN_RGXADDBLOCKTOFREELIST_TAG
+{
+ IMG_HANDLE hsFreeList;
+ IMG_UINT32 ui3232NumPages;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXADDBLOCKTOFREELIST;
+
+
+/* Bridge out structure for RGXAddBlockToFreeList */
+typedef struct PVRSRV_BRIDGE_OUT_RGXADDBLOCKTOFREELIST_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXADDBLOCKTOFREELIST;
+
+/*******************************************
+ RGXRemoveBlockFromFreeList
+ *******************************************/
+
+/* Bridge in structure for RGXRemoveBlockFromFreeList */
+typedef struct PVRSRV_BRIDGE_IN_RGXREMOVEBLOCKFROMFREELIST_TAG
+{
+ IMG_HANDLE hsFreeList;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXREMOVEBLOCKFROMFREELIST;
+
+
+/* Bridge out structure for RGXRemoveBlockFromFreeList */
+typedef struct PVRSRV_BRIDGE_OUT_RGXREMOVEBLOCKFROMFREELIST_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXREMOVEBLOCKFROMFREELIST;
+
+/*******************************************
+ RGXCreateRenderContext
+ *******************************************/
+
+/* Bridge in structure for RGXCreateRenderContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATERENDERCONTEXT_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32Priority;
+ IMG_DEV_VIRTADDR sMCUFenceAddr;
+ IMG_DEV_VIRTADDR sVDMCallStackAddr;
+ IMG_UINT32 ui32FrameworkCmdize;
+ IMG_BYTE * psFrameworkCmd;
+ IMG_HANDLE hPrivData;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATERENDERCONTEXT;
+
+
+/* Bridge out structure for RGXCreateRenderContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATERENDERCONTEXT_TAG
+{
+ IMG_HANDLE hRenderContext;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATERENDERCONTEXT;
+
+/*******************************************
+ RGXDestroyRenderContext
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyRenderContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYRENDERCONTEXT_TAG
+{
+ IMG_HANDLE hCleanupCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYRENDERCONTEXT;
+
+
+/* Bridge out structure for RGXDestroyRenderContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYRENDERCONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYRENDERCONTEXT;
+
+/*******************************************
+ RGXKickTA3D
+ *******************************************/
+
+/* Bridge in structure for RGXKickTA3D */
+typedef struct PVRSRV_BRIDGE_IN_RGXKICKTA3D_TAG
+{
+ IMG_HANDLE hRenderContext;
+ IMG_UINT32 ui32ClientTAFenceCount;
+ PRGXFWIF_UFO_ADDR * psClientTAFenceUFOAddress;
+ IMG_UINT32 * pui32ClientTAFenceValue;
+ IMG_UINT32 ui32ClientTAUpdateCount;
+ PRGXFWIF_UFO_ADDR * psClientTAUpdateUFOAddress;
+ IMG_UINT32 * pui32ClientTAUpdateValue;
+ IMG_UINT32 ui32ServerTASyncPrims;
+ IMG_UINT32 * pui32ServerTASyncFlags;
+ IMG_HANDLE * phServerTASyncs;
+ IMG_UINT32 ui32Client3DFenceCount;
+ PRGXFWIF_UFO_ADDR * psClient3DFenceUFOAddress;
+ IMG_UINT32 * pui32Client3DFenceValue;
+ IMG_UINT32 ui32Client3DUpdateCount;
+ PRGXFWIF_UFO_ADDR * psClient3DUpdateUFOAddress;
+ IMG_UINT32 * pui32Client3DUpdateValue;
+ IMG_UINT32 ui32Server3DSyncPrims;
+ IMG_UINT32 * pui32Server3DSyncFlags;
+ IMG_HANDLE * phServer3DSyncs;
+ PRGXFWIF_UFO_ADDR sPRFenceUFOAddress;
+ IMG_UINT32 ui32FRFenceValue;
+ IMG_UINT32 ui32NumFenceFds;
+ IMG_INT32 * pi32FenceFds;
+ IMG_UINT32 ui32TACmdSize;
+ IMG_BYTE * psTACmd;
+ IMG_UINT32 ui323DPRCmdSize;
+ IMG_BYTE * ps3DPRCmd;
+ IMG_UINT32 ui323DCmdSize;
+ IMG_BYTE * ps3DCmd;
+ IMG_UINT32 ui32ExternalJobReference;
+ IMG_UINT32 ui32InternalJobReference;
+ IMG_BOOL bbLastTAInScene;
+ IMG_BOOL bbKickTA;
+ IMG_BOOL bbKickPR;
+ IMG_BOOL bbKick3D;
+ IMG_BOOL bbAbort;
+ IMG_BOOL bbPDumpContinuous;
+ IMG_HANDLE hRTDataCleanup;
+ IMG_HANDLE hZBuffer;
+ IMG_HANDLE hSBuffer;
+ IMG_BOOL bbCommitRefCountsTA;
+ IMG_BOOL bbCommitRefCounts3D;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKTA3D;
+
+
+/* Bridge out structure for RGXKickTA3D */
+typedef struct PVRSRV_BRIDGE_OUT_RGXKICKTA3D_TAG
+{
+ IMG_BOOL bbCommittedRefCountsTA;
+ IMG_BOOL bbCommittedRefCounts3D;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXKICKTA3D;
+
+/*******************************************
+ RGXSetRenderContextPriority
+ *******************************************/
+
+/* Bridge in structure for RGXSetRenderContextPriority */
+typedef struct PVRSRV_BRIDGE_IN_RGXSETRENDERCONTEXTPRIORITY_TAG
+{
+ IMG_HANDLE hRenderContext;
+ IMG_UINT32 ui32Priority;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXSETRENDERCONTEXTPRIORITY;
+
+
+/* Bridge out structure for RGXSetRenderContextPriority */
+typedef struct PVRSRV_BRIDGE_OUT_RGXSETRENDERCONTEXTPRIORITY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXSETRENDERCONTEXTPRIORITY;
+
+/*******************************************
+ RGXGetLastRenderContextResetReason
+ *******************************************/
+
+/* Bridge in structure for RGXGetLastRenderContextResetReason */
+typedef struct PVRSRV_BRIDGE_IN_RGXGETLASTRENDERCONTEXTRESETREASON_TAG
+{
+ IMG_HANDLE hRenderContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXGETLASTRENDERCONTEXTRESETREASON;
+
+
+/* Bridge out structure for RGXGetLastRenderContextResetReason */
+typedef struct PVRSRV_BRIDGE_OUT_RGXGETLASTRENDERCONTEXTRESETREASON_TAG
+{
+ IMG_UINT32 ui32LastResetReason;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXGETLASTRENDERCONTEXTRESETREASON;
+
+/*******************************************
+ RGXGetPartialRenderCount
+ *******************************************/
+
+/* Bridge in structure for RGXGetPartialRenderCount */
+typedef struct PVRSRV_BRIDGE_IN_RGXGETPARTIALRENDERCOUNT_TAG
+{
+ IMG_HANDLE hHWRTDataMemDesc;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXGETPARTIALRENDERCOUNT;
+
+
+/* Bridge out structure for RGXGetPartialRenderCount */
+typedef struct PVRSRV_BRIDGE_OUT_RGXGETPARTIALRENDERCOUNT_TAG
+{
+ IMG_UINT32 ui32NumPartialRenders;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXGETPARTIALRENDERCOUNT;
+
+/*******************************************
+ RGXKickSyncTA
+ *******************************************/
+
+/* Bridge in structure for RGXKickSyncTA */
+typedef struct PVRSRV_BRIDGE_IN_RGXKICKSYNCTA_TAG
+{
+ IMG_HANDLE hRenderContext;
+ IMG_UINT32 ui32ClientTAFenceCount;
+ PRGXFWIF_UFO_ADDR * psClientTAFenceUFOAddress;
+ IMG_UINT32 * pui32ClientTAFenceValue;
+ IMG_UINT32 ui32ClientTAUpdateCount;
+ PRGXFWIF_UFO_ADDR * psClientTAUpdateUFOAddress;
+ IMG_UINT32 * pui32ClientTAUpdateValue;
+ IMG_UINT32 ui32ServerTASyncPrims;
+ IMG_UINT32 * pui32ServerTASyncFlags;
+ IMG_HANDLE * phServerTASyncs;
+ IMG_UINT32 ui32Client3DFenceCount;
+ PRGXFWIF_UFO_ADDR * psClient3DFenceUFOAddress;
+ IMG_UINT32 * pui32Client3DFenceValue;
+ IMG_UINT32 ui32Client3DUpdateCount;
+ PRGXFWIF_UFO_ADDR * psClient3DUpdateUFOAddress;
+ IMG_UINT32 * pui32Client3DUpdateValue;
+ IMG_UINT32 ui32Server3DSyncPrims;
+ IMG_UINT32 * pui32Server3DSyncFlags;
+ IMG_HANDLE * phServer3DSyncs;
+ IMG_UINT32 ui32NumFenceFDs;
+ IMG_INT32 * pi32FenceFDs;
+ IMG_BOOL bbPDumpContinuous;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKSYNCTA;
+
+
+/* Bridge out structure for RGXKickSyncTA */
+typedef struct PVRSRV_BRIDGE_OUT_RGXKICKSYNCTA_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXKICKSYNCTA;
+
+#endif /* COMMON_RGXTA3D_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/rgxta3d_bridge/server_rgxta3d_bridge.c b/drivers/gpu/rogue/generated/rgxta3d_bridge/server_rgxta3d_bridge.c
new file mode 100644
index 000000000000..18fbd589bdc4
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxta3d_bridge/server_rgxta3d_bridge.c
@@ -0,0 +1,2502 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for rgxta3d
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for rgxta3d
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxta3d.h"
+
+
+#include "common_rgxta3d_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+RGXDestroyHWRTDataResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+RGXDestroyRenderTargetResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+RGXDestroyZSBufferResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+RGXUnpopulateZSBufferResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+RGXDestroyFreeListResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+RGXDestroyRenderContextResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeRGXCreateHWRTData(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCREATEHWRTDATA *psRGXCreateHWRTDataIN,
+ PVRSRV_BRIDGE_OUT_RGXCREATEHWRTDATA *psRGXCreateHWRTDataOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ RGX_FREELIST * *psapsFreeListsInt = IMG_NULL;
+ IMG_HANDLE *hapsFreeListsInt2 = IMG_NULL;
+ RGX_RTDATA_CLEANUP_DATA * psCleanupCookieInt = IMG_NULL;
+ IMG_HANDLE hCleanupCookieInt2 = IMG_NULL;
+ DEVMEM_MEMDESC * psRTACtlMemDescInt = IMG_NULL;
+ DEVMEM_MEMDESC * pssHWRTDataMemDescInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXCREATEHWRTDATA);
+
+
+
+ psRGXCreateHWRTDataOUT->hCleanupCookie = IMG_NULL;
+
+
+ {
+ psapsFreeListsInt = OSAllocMem(RGXFW_MAX_FREELISTS * sizeof(RGX_FREELIST *));
+ if (!psapsFreeListsInt)
+ {
+ psRGXCreateHWRTDataOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXCreateHWRTData_exit;
+ }
+ hapsFreeListsInt2 = OSAllocMem(RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE));
+ if (!hapsFreeListsInt2)
+ {
+ psRGXCreateHWRTDataOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXCreateHWRTData_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXCreateHWRTDataIN->phapsFreeLists, RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hapsFreeListsInt2, psRGXCreateHWRTDataIN->phapsFreeLists,
+ RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psRGXCreateHWRTDataOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXCreateHWRTData_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateHWRTDataOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCreateHWRTDataIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateHWRTData_exit;
+ }
+
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<RGXFW_MAX_FREELISTS;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psRGXCreateHWRTDataOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hapsFreeListsInt2[i],
+ hapsFreeListsInt2[i],
+ PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+ if(psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateHWRTData_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXCreateHWRTDataOUT->eError = ResManFindPrivateDataByPtr(hapsFreeListsInt2[i], (IMG_VOID **) &psapsFreeListsInt[i]);
+
+ if(psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateHWRTData_exit;
+ }
+ }
+ }
+ }
+
+ psRGXCreateHWRTDataOUT->eError =
+ RGXCreateHWRTData(
+ hDevNodeInt,
+ psRGXCreateHWRTDataIN->ui32RenderTarget,
+ psRGXCreateHWRTDataIN->sPMMlistDevVAddr,
+ psRGXCreateHWRTDataIN->sVFPPageTableAddr,
+ psapsFreeListsInt,
+ &psCleanupCookieInt,
+ &psRTACtlMemDescInt,
+ psRGXCreateHWRTDataIN->ui32PPPScreen,
+ psRGXCreateHWRTDataIN->ui32PPPGridOffset,
+ psRGXCreateHWRTDataIN->ui64PPPMultiSampleCtl,
+ psRGXCreateHWRTDataIN->ui32TPCStride,
+ psRGXCreateHWRTDataIN->sTailPtrsDevVAddr,
+ psRGXCreateHWRTDataIN->ui32TPCSize,
+ psRGXCreateHWRTDataIN->ui32TEScreen,
+ psRGXCreateHWRTDataIN->ui32TEAA,
+ psRGXCreateHWRTDataIN->ui32TEMTILE1,
+ psRGXCreateHWRTDataIN->ui32TEMTILE2,
+ psRGXCreateHWRTDataIN->ui32MTileStride,
+ psRGXCreateHWRTDataIN->ui32ui32ISPMergeLowerX,
+ psRGXCreateHWRTDataIN->ui32ui32ISPMergeLowerY,
+ psRGXCreateHWRTDataIN->ui32ui32ISPMergeUpperX,
+ psRGXCreateHWRTDataIN->ui32ui32ISPMergeUpperY,
+ psRGXCreateHWRTDataIN->ui32ui32ISPMergeScaleX,
+ psRGXCreateHWRTDataIN->ui32ui32ISPMergeScaleY,
+ psRGXCreateHWRTDataIN->ui16MaxRTs,
+ &pssHWRTDataMemDescInt,
+ &psRGXCreateHWRTDataOUT->ui32FWHWRTData);
+ /* Exit early if bridged call fails */
+ if(psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateHWRTData_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hCleanupCookieInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_RGX_FWIF_HWRTDATA,
+ psCleanupCookieInt,
+ (RESMAN_FREE_FN)&RGXDestroyHWRTData);
+ if (hCleanupCookieInt2 == IMG_NULL)
+ {
+ psRGXCreateHWRTDataOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto RGXCreateHWRTData_exit;
+ }
+ psRGXCreateHWRTDataOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXCreateHWRTDataOUT->hCleanupCookie,
+ (IMG_HANDLE) hCleanupCookieInt2,
+ PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateHWRTData_exit;
+ }
+ psRGXCreateHWRTDataOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+ &psRGXCreateHWRTDataOUT->hRTACtlMemDesc,
+ (IMG_HANDLE) psRTACtlMemDescInt,
+ PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ ,psRGXCreateHWRTDataOUT->hCleanupCookie);
+ if (psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateHWRTData_exit;
+ }
+ psRGXCreateHWRTDataOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+ &psRGXCreateHWRTDataOUT->hsHWRTDataMemDesc,
+ (IMG_HANDLE) pssHWRTDataMemDescInt,
+ PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ ,psRGXCreateHWRTDataOUT->hCleanupCookie);
+ if (psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateHWRTData_exit;
+ }
+
+
+RGXCreateHWRTData_exit:
+ if (psRGXCreateHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ if (psRGXCreateHWRTDataOUT->hCleanupCookie)
+ {
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXCreateHWRTDataOUT->hCleanupCookie,
+ PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP);
+ }
+
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hCleanupCookieInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hCleanupCookieInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psCleanupCookieInt)
+ {
+ RGXDestroyHWRTData(psCleanupCookieInt);
+ }
+ }
+
+ if (psapsFreeListsInt)
+ OSFreeMem(psapsFreeListsInt);
+ if (hapsFreeListsInt2)
+ OSFreeMem(hapsFreeListsInt2);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyHWRTData(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDESTROYHWRTDATA *psRGXDestroyHWRTDataIN,
+ PVRSRV_BRIDGE_OUT_RGXDESTROYHWRTDATA *psRGXDestroyHWRTDataOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hCleanupCookieInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYHWRTDATA);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDestroyHWRTDataOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hCleanupCookieInt2,
+ psRGXDestroyHWRTDataIN->hCleanupCookie,
+ PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP);
+ if(psRGXDestroyHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyHWRTData_exit;
+ }
+
+ }
+
+ psRGXDestroyHWRTDataOUT->eError = RGXDestroyHWRTDataResManProxy(hCleanupCookieInt2);
+ /* Exit early if bridged call fails */
+ if(psRGXDestroyHWRTDataOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyHWRTData_exit;
+ }
+
+ psRGXDestroyHWRTDataOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXDestroyHWRTDataIN->hCleanupCookie,
+ PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP);
+
+
+RGXDestroyHWRTData_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXCreateRenderTarget(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCREATERENDERTARGET *psRGXCreateRenderTargetIN,
+ PVRSRV_BRIDGE_OUT_RGXCREATERENDERTARGET *psRGXCreateRenderTargetOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ RGX_RT_CLEANUP_DATA * pssRenderTargetMemDescInt = IMG_NULL;
+ IMG_HANDLE hsRenderTargetMemDescInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXCREATERENDERTARGET);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateRenderTargetOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCreateRenderTargetIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCreateRenderTargetOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateRenderTarget_exit;
+ }
+
+ }
+
+ psRGXCreateRenderTargetOUT->eError =
+ RGXCreateRenderTarget(
+ hDevNodeInt,
+ psRGXCreateRenderTargetIN->spsVHeapTableDevVAddr,
+ &pssRenderTargetMemDescInt,
+ &psRGXCreateRenderTargetOUT->ui32sRenderTargetFWDevVAddr);
+ /* Exit early if bridged call fails */
+ if(psRGXCreateRenderTargetOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateRenderTarget_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hsRenderTargetMemDescInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_RGX_FWIF_RENDERTARGET,
+ pssRenderTargetMemDescInt,
+ (RESMAN_FREE_FN)&RGXDestroyRenderTarget);
+ if (hsRenderTargetMemDescInt2 == IMG_NULL)
+ {
+ psRGXCreateRenderTargetOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto RGXCreateRenderTarget_exit;
+ }
+ psRGXCreateRenderTargetOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXCreateRenderTargetOUT->hsRenderTargetMemDesc,
+ (IMG_HANDLE) hsRenderTargetMemDescInt2,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_RENDERTARGET,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXCreateRenderTargetOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateRenderTarget_exit;
+ }
+
+
+RGXCreateRenderTarget_exit:
+ if (psRGXCreateRenderTargetOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hsRenderTargetMemDescInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hsRenderTargetMemDescInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (pssRenderTargetMemDescInt)
+ {
+ RGXDestroyRenderTarget(pssRenderTargetMemDescInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyRenderTarget(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDESTROYRENDERTARGET *psRGXDestroyRenderTargetIN,
+ PVRSRV_BRIDGE_OUT_RGXDESTROYRENDERTARGET *psRGXDestroyRenderTargetOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hsRenderTargetMemDescInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYRENDERTARGET);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDestroyRenderTargetOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hsRenderTargetMemDescInt2,
+ psRGXDestroyRenderTargetIN->hsRenderTargetMemDesc,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_RENDERTARGET);
+ if(psRGXDestroyRenderTargetOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyRenderTarget_exit;
+ }
+
+ }
+
+ psRGXDestroyRenderTargetOUT->eError = RGXDestroyRenderTargetResManProxy(hsRenderTargetMemDescInt2);
+ /* Exit early if bridged call fails */
+ if(psRGXDestroyRenderTargetOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyRenderTarget_exit;
+ }
+
+ psRGXDestroyRenderTargetOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXDestroyRenderTargetIN->hsRenderTargetMemDesc,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_RENDERTARGET);
+
+
+RGXDestroyRenderTarget_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXCreateZSBuffer(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCREATEZSBUFFER *psRGXCreateZSBufferIN,
+ PVRSRV_BRIDGE_OUT_RGXCREATEZSBUFFER *psRGXCreateZSBufferOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ DEVMEMINT_RESERVATION * psReservationInt = IMG_NULL;
+ IMG_HANDLE hReservationInt2 = IMG_NULL;
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+ RGX_ZSBUFFER_DATA * pssZSBufferKMInt = IMG_NULL;
+ IMG_HANDLE hsZSBufferKMInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXCREATEZSBUFFER);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateZSBufferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCreateZSBufferIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateZSBuffer_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateZSBufferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hReservationInt2,
+ psRGXCreateZSBufferIN->hReservation,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+ if(psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateZSBuffer_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXCreateZSBufferOUT->eError = ResManFindPrivateDataByPtr(hReservationInt2, (IMG_VOID **) &psReservationInt);
+
+ if(psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateZSBuffer_exit;
+ }
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateZSBufferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psRGXCreateZSBufferIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateZSBuffer_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXCreateZSBufferOUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateZSBuffer_exit;
+ }
+ }
+
+ psRGXCreateZSBufferOUT->eError =
+ RGXCreateZSBufferKM(
+ hDevNodeInt,
+ psReservationInt,
+ psPMRInt,
+ psRGXCreateZSBufferIN->uiMapFlags,
+ &pssZSBufferKMInt,
+ &psRGXCreateZSBufferOUT->ui32sZSBufferFWDevVAddr);
+ /* Exit early if bridged call fails */
+ if(psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateZSBuffer_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hsZSBufferKMInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_RGX_FWIF_ZSBUFFER,
+ pssZSBufferKMInt,
+ (RESMAN_FREE_FN)&RGXDestroyZSBufferKM);
+ if (hsZSBufferKMInt2 == IMG_NULL)
+ {
+ psRGXCreateZSBufferOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto RGXCreateZSBuffer_exit;
+ }
+ psRGXCreateZSBufferOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXCreateZSBufferOUT->hsZSBufferKM,
+ (IMG_HANDLE) hsZSBufferKMInt2,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateZSBuffer_exit;
+ }
+
+
+RGXCreateZSBuffer_exit:
+ if (psRGXCreateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hsZSBufferKMInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hsZSBufferKMInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (pssZSBufferKMInt)
+ {
+ RGXDestroyZSBufferKM(pssZSBufferKMInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyZSBuffer(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDESTROYZSBUFFER *psRGXDestroyZSBufferIN,
+ PVRSRV_BRIDGE_OUT_RGXDESTROYZSBUFFER *psRGXDestroyZSBufferOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hsZSBufferMemDescInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYZSBUFFER);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDestroyZSBufferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hsZSBufferMemDescInt2,
+ psRGXDestroyZSBufferIN->hsZSBufferMemDesc,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+ if(psRGXDestroyZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyZSBuffer_exit;
+ }
+
+ }
+
+ psRGXDestroyZSBufferOUT->eError = RGXDestroyZSBufferResManProxy(hsZSBufferMemDescInt2);
+ /* Exit early if bridged call fails */
+ if(psRGXDestroyZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyZSBuffer_exit;
+ }
+
+ psRGXDestroyZSBufferOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXDestroyZSBufferIN->hsZSBufferMemDesc,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+
+
+RGXDestroyZSBuffer_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXPopulateZSBuffer(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXPOPULATEZSBUFFER *psRGXPopulateZSBufferIN,
+ PVRSRV_BRIDGE_OUT_RGXPOPULATEZSBUFFER *psRGXPopulateZSBufferOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_ZSBUFFER_DATA * pssZSBufferKMInt = IMG_NULL;
+ IMG_HANDLE hsZSBufferKMInt2 = IMG_NULL;
+ RGX_POPULATION * pssPopulationInt = IMG_NULL;
+ IMG_HANDLE hsPopulationInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXPOPULATEZSBUFFER);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXPopulateZSBufferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hsZSBufferKMInt2,
+ psRGXPopulateZSBufferIN->hsZSBufferKM,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+ if(psRGXPopulateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXPopulateZSBuffer_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXPopulateZSBufferOUT->eError = ResManFindPrivateDataByPtr(hsZSBufferKMInt2, (IMG_VOID **) &pssZSBufferKMInt);
+
+ if(psRGXPopulateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXPopulateZSBuffer_exit;
+ }
+ }
+
+ psRGXPopulateZSBufferOUT->eError =
+ RGXPopulateZSBufferKM(
+ pssZSBufferKMInt,
+ &pssPopulationInt);
+ /* Exit early if bridged call fails */
+ if(psRGXPopulateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXPopulateZSBuffer_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hsPopulationInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_RGX_POPULATION,
+ pssPopulationInt,
+ (RESMAN_FREE_FN)&RGXUnpopulateZSBufferKM);
+ if (hsPopulationInt2 == IMG_NULL)
+ {
+ psRGXPopulateZSBufferOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto RGXPopulateZSBuffer_exit;
+ }
+ psRGXPopulateZSBufferOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXPopulateZSBufferOUT->hsPopulation,
+ (IMG_HANDLE) hsPopulationInt2,
+ PVRSRV_HANDLE_TYPE_RGX_POPULATION,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXPopulateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXPopulateZSBuffer_exit;
+ }
+
+
+RGXPopulateZSBuffer_exit:
+ if (psRGXPopulateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hsPopulationInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hsPopulationInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (pssPopulationInt)
+ {
+ RGXUnpopulateZSBufferKM(pssPopulationInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXUnpopulateZSBuffer(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXUNPOPULATEZSBUFFER *psRGXUnpopulateZSBufferIN,
+ PVRSRV_BRIDGE_OUT_RGXUNPOPULATEZSBUFFER *psRGXUnpopulateZSBufferOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hsPopulationInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXUNPOPULATEZSBUFFER);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXUnpopulateZSBufferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hsPopulationInt2,
+ psRGXUnpopulateZSBufferIN->hsPopulation,
+ PVRSRV_HANDLE_TYPE_RGX_POPULATION);
+ if(psRGXUnpopulateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXUnpopulateZSBuffer_exit;
+ }
+
+ }
+
+ psRGXUnpopulateZSBufferOUT->eError = RGXUnpopulateZSBufferResManProxy(hsPopulationInt2);
+ /* Exit early if bridged call fails */
+ if(psRGXUnpopulateZSBufferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXUnpopulateZSBuffer_exit;
+ }
+
+ psRGXUnpopulateZSBufferOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXUnpopulateZSBufferIN->hsPopulation,
+ PVRSRV_HANDLE_TYPE_RGX_POPULATION);
+
+
+RGXUnpopulateZSBuffer_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXCreateFreeList(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCREATEFREELIST *psRGXCreateFreeListIN,
+ PVRSRV_BRIDGE_OUT_RGXCREATEFREELIST *psRGXCreateFreeListOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ PMR * pssFreeListPMRInt = IMG_NULL;
+ IMG_HANDLE hsFreeListPMRInt2 = IMG_NULL;
+ RGX_FREELIST * psCleanupCookieInt = IMG_NULL;
+ IMG_HANDLE hCleanupCookieInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXCREATEFREELIST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateFreeListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCreateFreeListIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCreateFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateFreeList_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateFreeListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hsFreeListPMRInt2,
+ psRGXCreateFreeListIN->hsFreeListPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psRGXCreateFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateFreeList_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXCreateFreeListOUT->eError = ResManFindPrivateDataByPtr(hsFreeListPMRInt2, (IMG_VOID **) &pssFreeListPMRInt);
+
+ if(psRGXCreateFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateFreeList_exit;
+ }
+ }
+
+ psRGXCreateFreeListOUT->eError =
+ RGXCreateFreeList(
+ hDevNodeInt,
+ psRGXCreateFreeListIN->ui32ui32MaxFLPages,
+ psRGXCreateFreeListIN->ui32ui32InitFLPages,
+ psRGXCreateFreeListIN->ui32ui32GrowFLPages,
+ psRGXCreateFreeListIN->bbFreeListCheck,
+ psRGXCreateFreeListIN->spsFreeListDevVAddr,
+ pssFreeListPMRInt,
+ psRGXCreateFreeListIN->uiPMROffset,
+ &psCleanupCookieInt);
+ /* Exit early if bridged call fails */
+ if(psRGXCreateFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateFreeList_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hCleanupCookieInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_RGX_FWIF_FREELIST,
+ psCleanupCookieInt,
+ (RESMAN_FREE_FN)&RGXDestroyFreeList);
+ if (hCleanupCookieInt2 == IMG_NULL)
+ {
+ psRGXCreateFreeListOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto RGXCreateFreeList_exit;
+ }
+ psRGXCreateFreeListOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXCreateFreeListOUT->hCleanupCookie,
+ (IMG_HANDLE) hCleanupCookieInt2,
+ PVRSRV_HANDLE_TYPE_RGX_FREELIST,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXCreateFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateFreeList_exit;
+ }
+
+
+RGXCreateFreeList_exit:
+ if (psRGXCreateFreeListOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hCleanupCookieInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hCleanupCookieInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psCleanupCookieInt)
+ {
+ RGXDestroyFreeList(psCleanupCookieInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyFreeList(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDESTROYFREELIST *psRGXDestroyFreeListIN,
+ PVRSRV_BRIDGE_OUT_RGXDESTROYFREELIST *psRGXDestroyFreeListOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hCleanupCookieInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYFREELIST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDestroyFreeListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hCleanupCookieInt2,
+ psRGXDestroyFreeListIN->hCleanupCookie,
+ PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+ if(psRGXDestroyFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyFreeList_exit;
+ }
+
+ }
+
+ psRGXDestroyFreeListOUT->eError = RGXDestroyFreeListResManProxy(hCleanupCookieInt2);
+ /* Exit early if bridged call fails */
+ if(psRGXDestroyFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyFreeList_exit;
+ }
+
+ psRGXDestroyFreeListOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXDestroyFreeListIN->hCleanupCookie,
+ PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+
+
+RGXDestroyFreeList_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXAddBlockToFreeList(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXADDBLOCKTOFREELIST *psRGXAddBlockToFreeListIN,
+ PVRSRV_BRIDGE_OUT_RGXADDBLOCKTOFREELIST *psRGXAddBlockToFreeListOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_FREELIST * pssFreeListInt = IMG_NULL;
+ IMG_HANDLE hsFreeListInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXADDBLOCKTOFREELIST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXAddBlockToFreeListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hsFreeListInt2,
+ psRGXAddBlockToFreeListIN->hsFreeList,
+ PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+ if(psRGXAddBlockToFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXAddBlockToFreeList_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXAddBlockToFreeListOUT->eError = ResManFindPrivateDataByPtr(hsFreeListInt2, (IMG_VOID **) &pssFreeListInt);
+
+ if(psRGXAddBlockToFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXAddBlockToFreeList_exit;
+ }
+ }
+
+ psRGXAddBlockToFreeListOUT->eError =
+ RGXAddBlockToFreeListKM(
+ pssFreeListInt,
+ psRGXAddBlockToFreeListIN->ui3232NumPages);
+
+
+
+RGXAddBlockToFreeList_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXRemoveBlockFromFreeList(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXREMOVEBLOCKFROMFREELIST *psRGXRemoveBlockFromFreeListIN,
+ PVRSRV_BRIDGE_OUT_RGXREMOVEBLOCKFROMFREELIST *psRGXRemoveBlockFromFreeListOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_FREELIST * pssFreeListInt = IMG_NULL;
+ IMG_HANDLE hsFreeListInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXREMOVEBLOCKFROMFREELIST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXRemoveBlockFromFreeListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hsFreeListInt2,
+ psRGXRemoveBlockFromFreeListIN->hsFreeList,
+ PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+ if(psRGXRemoveBlockFromFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXRemoveBlockFromFreeList_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXRemoveBlockFromFreeListOUT->eError = ResManFindPrivateDataByPtr(hsFreeListInt2, (IMG_VOID **) &pssFreeListInt);
+
+ if(psRGXRemoveBlockFromFreeListOUT->eError != PVRSRV_OK)
+ {
+ goto RGXRemoveBlockFromFreeList_exit;
+ }
+ }
+
+ psRGXRemoveBlockFromFreeListOUT->eError =
+ RGXRemoveBlockFromFreeListKM(
+ pssFreeListInt);
+
+
+
+RGXRemoveBlockFromFreeList_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXCreateRenderContext(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCREATERENDERCONTEXT *psRGXCreateRenderContextIN,
+ PVRSRV_BRIDGE_OUT_RGXCREATERENDERCONTEXT *psRGXCreateRenderContextOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_BYTE *psFrameworkCmdInt = IMG_NULL;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+ RGX_SERVER_RENDER_CONTEXT * psRenderContextInt = IMG_NULL;
+ IMG_HANDLE hRenderContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXCREATERENDERCONTEXT);
+
+
+
+
+ if (psRGXCreateRenderContextIN->ui32FrameworkCmdize != 0)
+ {
+ psFrameworkCmdInt = OSAllocMem(psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE));
+ if (!psFrameworkCmdInt)
+ {
+ psRGXCreateRenderContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXCreateRenderContext_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXCreateRenderContextIN->psFrameworkCmd, psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE))
+ || (OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateRenderContextIN->psFrameworkCmd,
+ psRGXCreateRenderContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+ {
+ psRGXCreateRenderContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXCreateRenderContext_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateRenderContextOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCreateRenderContextIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCreateRenderContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateRenderContext_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateRenderContextOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPrivDataInt,
+ psRGXCreateRenderContextIN->hPrivData,
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+ if(psRGXCreateRenderContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateRenderContext_exit;
+ }
+
+ }
+
+ psRGXCreateRenderContextOUT->eError =
+ PVRSRVRGXCreateRenderContextKM(psConnection,
+ hDevNodeInt,
+ psRGXCreateRenderContextIN->ui32Priority,
+ psRGXCreateRenderContextIN->sMCUFenceAddr,
+ psRGXCreateRenderContextIN->sVDMCallStackAddr,
+ psRGXCreateRenderContextIN->ui32FrameworkCmdize,
+ psFrameworkCmdInt,
+ hPrivDataInt,
+ &psRenderContextInt);
+ /* Exit early if bridged call fails */
+ if(psRGXCreateRenderContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateRenderContext_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hRenderContextInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_RGX_SERVER_RENDER_CONTEXT,
+ psRenderContextInt,
+ (RESMAN_FREE_FN)&PVRSRVRGXDestroyRenderContextKM);
+ if (hRenderContextInt2 == IMG_NULL)
+ {
+ psRGXCreateRenderContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto RGXCreateRenderContext_exit;
+ }
+ psRGXCreateRenderContextOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXCreateRenderContextOUT->hRenderContext,
+ (IMG_HANDLE) hRenderContextInt2,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXCreateRenderContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateRenderContext_exit;
+ }
+
+
+RGXCreateRenderContext_exit:
+ if (psRGXCreateRenderContextOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hRenderContextInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hRenderContextInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psRenderContextInt)
+ {
+ PVRSRVRGXDestroyRenderContextKM(psRenderContextInt);
+ }
+ }
+
+ if (psFrameworkCmdInt)
+ OSFreeMem(psFrameworkCmdInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyRenderContext(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDESTROYRENDERCONTEXT *psRGXDestroyRenderContextIN,
+ PVRSRV_BRIDGE_OUT_RGXDESTROYRENDERCONTEXT *psRGXDestroyRenderContextOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hCleanupCookieInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYRENDERCONTEXT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDestroyRenderContextOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hCleanupCookieInt2,
+ psRGXDestroyRenderContextIN->hCleanupCookie,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+ if(psRGXDestroyRenderContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyRenderContext_exit;
+ }
+
+ }
+
+ psRGXDestroyRenderContextOUT->eError = RGXDestroyRenderContextResManProxy(hCleanupCookieInt2);
+ /* Exit early if bridged call fails */
+ if(psRGXDestroyRenderContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyRenderContext_exit;
+ }
+
+ psRGXDestroyRenderContextOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXDestroyRenderContextIN->hCleanupCookie,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+
+
+RGXDestroyRenderContext_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXKickTA3D(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXKICKTA3D *psRGXKickTA3DIN,
+ PVRSRV_BRIDGE_OUT_RGXKICKTA3D *psRGXKickTA3DOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_RENDER_CONTEXT * psRenderContextInt = IMG_NULL;
+ IMG_HANDLE hRenderContextInt2 = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientTAFenceUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientTAFenceValueInt = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientTAUpdateUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientTAUpdateValueInt = IMG_NULL;
+ IMG_UINT32 *ui32ServerTASyncFlagsInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * *psServerTASyncsInt = IMG_NULL;
+ IMG_HANDLE *hServerTASyncsInt2 = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClient3DFenceUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32Client3DFenceValueInt = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClient3DUpdateUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32Client3DUpdateValueInt = IMG_NULL;
+ IMG_UINT32 *ui32Server3DSyncFlagsInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * *psServer3DSyncsInt = IMG_NULL;
+ IMG_HANDLE *hServer3DSyncsInt2 = IMG_NULL;
+ IMG_INT32 *i32FenceFdsInt = IMG_NULL;
+ IMG_BYTE *psTACmdInt = IMG_NULL;
+ IMG_BYTE *ps3DPRCmdInt = IMG_NULL;
+ IMG_BYTE *ps3DCmdInt = IMG_NULL;
+ RGX_RTDATA_CLEANUP_DATA * psRTDataCleanupInt = IMG_NULL;
+ IMG_HANDLE hRTDataCleanupInt2 = IMG_NULL;
+ RGX_ZSBUFFER_DATA * psZBufferInt = IMG_NULL;
+ IMG_HANDLE hZBufferInt2 = IMG_NULL;
+ RGX_ZSBUFFER_DATA * psSBufferInt = IMG_NULL;
+ IMG_HANDLE hSBufferInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXKICKTA3D);
+
+
+
+
+ if (psRGXKickTA3DIN->ui32ClientTAFenceCount != 0)
+ {
+ sClientTAFenceUFOAddressInt = OSAllocMem(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientTAFenceUFOAddressInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->psClientTAFenceUFOAddress, psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientTAFenceUFOAddressInt, psRGXKickTA3DIN->psClientTAFenceUFOAddress,
+ psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32ClientTAFenceCount != 0)
+ {
+ ui32ClientTAFenceValueInt = OSAllocMem(psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32));
+ if (!ui32ClientTAFenceValueInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->pui32ClientTAFenceValue, psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientTAFenceValueInt, psRGXKickTA3DIN->pui32ClientTAFenceValue,
+ psRGXKickTA3DIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32ClientTAUpdateCount != 0)
+ {
+ sClientTAUpdateUFOAddressInt = OSAllocMem(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientTAUpdateUFOAddressInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->psClientTAUpdateUFOAddress, psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientTAUpdateUFOAddressInt, psRGXKickTA3DIN->psClientTAUpdateUFOAddress,
+ psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32ClientTAUpdateCount != 0)
+ {
+ ui32ClientTAUpdateValueInt = OSAllocMem(psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32));
+ if (!ui32ClientTAUpdateValueInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->pui32ClientTAUpdateValue, psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientTAUpdateValueInt, psRGXKickTA3DIN->pui32ClientTAUpdateValue,
+ psRGXKickTA3DIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32ServerTASyncPrims != 0)
+ {
+ ui32ServerTASyncFlagsInt = OSAllocMem(psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32));
+ if (!ui32ServerTASyncFlagsInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->pui32ServerTASyncFlags, psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ServerTASyncFlagsInt, psRGXKickTA3DIN->pui32ServerTASyncFlags,
+ psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32ServerTASyncPrims != 0)
+ {
+ psServerTASyncsInt = OSAllocMem(psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psServerTASyncsInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ hServerTASyncsInt2 = OSAllocMem(psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE));
+ if (!hServerTASyncsInt2)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->phServerTASyncs, psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hServerTASyncsInt2, psRGXKickTA3DIN->phServerTASyncs,
+ psRGXKickTA3DIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32Client3DFenceCount != 0)
+ {
+ sClient3DFenceUFOAddressInt = OSAllocMem(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClient3DFenceUFOAddressInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->psClient3DFenceUFOAddress, psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClient3DFenceUFOAddressInt, psRGXKickTA3DIN->psClient3DFenceUFOAddress,
+ psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32Client3DFenceCount != 0)
+ {
+ ui32Client3DFenceValueInt = OSAllocMem(psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32));
+ if (!ui32Client3DFenceValueInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->pui32Client3DFenceValue, psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32Client3DFenceValueInt, psRGXKickTA3DIN->pui32Client3DFenceValue,
+ psRGXKickTA3DIN->ui32Client3DFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32Client3DUpdateCount != 0)
+ {
+ sClient3DUpdateUFOAddressInt = OSAllocMem(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClient3DUpdateUFOAddressInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->psClient3DUpdateUFOAddress, psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClient3DUpdateUFOAddressInt, psRGXKickTA3DIN->psClient3DUpdateUFOAddress,
+ psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32Client3DUpdateCount != 0)
+ {
+ ui32Client3DUpdateValueInt = OSAllocMem(psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32));
+ if (!ui32Client3DUpdateValueInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->pui32Client3DUpdateValue, psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32Client3DUpdateValueInt, psRGXKickTA3DIN->pui32Client3DUpdateValue,
+ psRGXKickTA3DIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32Server3DSyncPrims != 0)
+ {
+ ui32Server3DSyncFlagsInt = OSAllocMem(psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32));
+ if (!ui32Server3DSyncFlagsInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->pui32Server3DSyncFlags, psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32Server3DSyncFlagsInt, psRGXKickTA3DIN->pui32Server3DSyncFlags,
+ psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32Server3DSyncPrims != 0)
+ {
+ psServer3DSyncsInt = OSAllocMem(psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psServer3DSyncsInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ hServer3DSyncsInt2 = OSAllocMem(psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE));
+ if (!hServer3DSyncsInt2)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->phServer3DSyncs, psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hServer3DSyncsInt2, psRGXKickTA3DIN->phServer3DSyncs,
+ psRGXKickTA3DIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32NumFenceFds != 0)
+ {
+ i32FenceFdsInt = OSAllocMem(psRGXKickTA3DIN->ui32NumFenceFds * sizeof(IMG_INT32));
+ if (!i32FenceFdsInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->pi32FenceFds, psRGXKickTA3DIN->ui32NumFenceFds * sizeof(IMG_INT32))
+ || (OSCopyFromUser(NULL, i32FenceFdsInt, psRGXKickTA3DIN->pi32FenceFds,
+ psRGXKickTA3DIN->ui32NumFenceFds * sizeof(IMG_INT32)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui32TACmdSize != 0)
+ {
+ psTACmdInt = OSAllocMem(psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE));
+ if (!psTACmdInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->psTACmd, psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE))
+ || (OSCopyFromUser(NULL, psTACmdInt, psRGXKickTA3DIN->psTACmd,
+ psRGXKickTA3DIN->ui32TACmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui323DPRCmdSize != 0)
+ {
+ ps3DPRCmdInt = OSAllocMem(psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE));
+ if (!ps3DPRCmdInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->ps3DPRCmd, psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE))
+ || (OSCopyFromUser(NULL, ps3DPRCmdInt, psRGXKickTA3DIN->ps3DPRCmd,
+ psRGXKickTA3DIN->ui323DPRCmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+ if (psRGXKickTA3DIN->ui323DCmdSize != 0)
+ {
+ ps3DCmdInt = OSAllocMem(psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE));
+ if (!ps3DCmdInt)
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickTA3DIN->ps3DCmd, psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE))
+ || (OSCopyFromUser(NULL, ps3DCmdInt, psRGXKickTA3DIN->ps3DCmd,
+ psRGXKickTA3DIN->ui323DCmdSize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+ {
+ psRGXKickTA3DOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickTA3D_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXKickTA3DOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hRenderContextInt2,
+ psRGXKickTA3DIN->hRenderContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickTA3DOUT->eError = ResManFindPrivateDataByPtr(hRenderContextInt2, (IMG_VOID **) &psRenderContextInt);
+
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psRGXKickTA3DIN->ui32ServerTASyncPrims;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psRGXKickTA3DOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerTASyncsInt2[i],
+ hServerTASyncsInt2[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickTA3DOUT->eError = ResManFindPrivateDataByPtr(hServerTASyncsInt2[i], (IMG_VOID **) &psServerTASyncsInt[i]);
+
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psRGXKickTA3DIN->ui32Server3DSyncPrims;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psRGXKickTA3DOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServer3DSyncsInt2[i],
+ hServer3DSyncsInt2[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickTA3DOUT->eError = ResManFindPrivateDataByPtr(hServer3DSyncsInt2[i], (IMG_VOID **) &psServer3DSyncsInt[i]);
+
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+ }
+ }
+ }
+
+ if (psRGXKickTA3DIN->hRTDataCleanup)
+ {
+ /* Look up the address from the handle */
+ psRGXKickTA3DOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hRTDataCleanupInt2,
+ psRGXKickTA3DIN->hRTDataCleanup,
+ PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP);
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickTA3DOUT->eError = ResManFindPrivateDataByPtr(hRTDataCleanupInt2, (IMG_VOID **) &psRTDataCleanupInt);
+
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ if (psRGXKickTA3DIN->hZBuffer)
+ {
+ /* Look up the address from the handle */
+ psRGXKickTA3DOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hZBufferInt2,
+ psRGXKickTA3DIN->hZBuffer,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickTA3DOUT->eError = ResManFindPrivateDataByPtr(hZBufferInt2, (IMG_VOID **) &psZBufferInt);
+
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ if (psRGXKickTA3DIN->hSBuffer)
+ {
+ /* Look up the address from the handle */
+ psRGXKickTA3DOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSBufferInt2,
+ psRGXKickTA3DIN->hSBuffer,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickTA3DOUT->eError = ResManFindPrivateDataByPtr(hSBufferInt2, (IMG_VOID **) &psSBufferInt);
+
+ if(psRGXKickTA3DOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickTA3D_exit;
+ }
+ }
+
+ psRGXKickTA3DOUT->eError =
+ PVRSRVRGXKickTA3DKM(
+ psRenderContextInt,
+ psRGXKickTA3DIN->ui32ClientTAFenceCount,
+ sClientTAFenceUFOAddressInt,
+ ui32ClientTAFenceValueInt,
+ psRGXKickTA3DIN->ui32ClientTAUpdateCount,
+ sClientTAUpdateUFOAddressInt,
+ ui32ClientTAUpdateValueInt,
+ psRGXKickTA3DIN->ui32ServerTASyncPrims,
+ ui32ServerTASyncFlagsInt,
+ psServerTASyncsInt,
+ psRGXKickTA3DIN->ui32Client3DFenceCount,
+ sClient3DFenceUFOAddressInt,
+ ui32Client3DFenceValueInt,
+ psRGXKickTA3DIN->ui32Client3DUpdateCount,
+ sClient3DUpdateUFOAddressInt,
+ ui32Client3DUpdateValueInt,
+ psRGXKickTA3DIN->ui32Server3DSyncPrims,
+ ui32Server3DSyncFlagsInt,
+ psServer3DSyncsInt,
+ psRGXKickTA3DIN->sPRFenceUFOAddress,
+ psRGXKickTA3DIN->ui32FRFenceValue,
+ psRGXKickTA3DIN->ui32NumFenceFds,
+ i32FenceFdsInt,
+ psRGXKickTA3DIN->ui32TACmdSize,
+ psTACmdInt,
+ psRGXKickTA3DIN->ui323DPRCmdSize,
+ ps3DPRCmdInt,
+ psRGXKickTA3DIN->ui323DCmdSize,
+ ps3DCmdInt,
+ psRGXKickTA3DIN->ui32ExternalJobReference,
+ psRGXKickTA3DIN->ui32InternalJobReference,
+ psRGXKickTA3DIN->bbLastTAInScene,
+ psRGXKickTA3DIN->bbKickTA,
+ psRGXKickTA3DIN->bbKickPR,
+ psRGXKickTA3DIN->bbKick3D,
+ psRGXKickTA3DIN->bbAbort,
+ psRGXKickTA3DIN->bbPDumpContinuous,
+ psRTDataCleanupInt,
+ psZBufferInt,
+ psSBufferInt,
+ psRGXKickTA3DIN->bbCommitRefCountsTA,
+ psRGXKickTA3DIN->bbCommitRefCounts3D,
+ &psRGXKickTA3DOUT->bbCommittedRefCountsTA,
+ &psRGXKickTA3DOUT->bbCommittedRefCounts3D);
+
+
+
+RGXKickTA3D_exit:
+ if (sClientTAFenceUFOAddressInt)
+ OSFreeMem(sClientTAFenceUFOAddressInt);
+ if (ui32ClientTAFenceValueInt)
+ OSFreeMem(ui32ClientTAFenceValueInt);
+ if (sClientTAUpdateUFOAddressInt)
+ OSFreeMem(sClientTAUpdateUFOAddressInt);
+ if (ui32ClientTAUpdateValueInt)
+ OSFreeMem(ui32ClientTAUpdateValueInt);
+ if (ui32ServerTASyncFlagsInt)
+ OSFreeMem(ui32ServerTASyncFlagsInt);
+ if (psServerTASyncsInt)
+ OSFreeMem(psServerTASyncsInt);
+ if (hServerTASyncsInt2)
+ OSFreeMem(hServerTASyncsInt2);
+ if (sClient3DFenceUFOAddressInt)
+ OSFreeMem(sClient3DFenceUFOAddressInt);
+ if (ui32Client3DFenceValueInt)
+ OSFreeMem(ui32Client3DFenceValueInt);
+ if (sClient3DUpdateUFOAddressInt)
+ OSFreeMem(sClient3DUpdateUFOAddressInt);
+ if (ui32Client3DUpdateValueInt)
+ OSFreeMem(ui32Client3DUpdateValueInt);
+ if (ui32Server3DSyncFlagsInt)
+ OSFreeMem(ui32Server3DSyncFlagsInt);
+ if (psServer3DSyncsInt)
+ OSFreeMem(psServer3DSyncsInt);
+ if (hServer3DSyncsInt2)
+ OSFreeMem(hServer3DSyncsInt2);
+ if (i32FenceFdsInt)
+ OSFreeMem(i32FenceFdsInt);
+ if (psTACmdInt)
+ OSFreeMem(psTACmdInt);
+ if (ps3DPRCmdInt)
+ OSFreeMem(ps3DPRCmdInt);
+ if (ps3DCmdInt)
+ OSFreeMem(ps3DCmdInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXSetRenderContextPriority(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXSETRENDERCONTEXTPRIORITY *psRGXSetRenderContextPriorityIN,
+ PVRSRV_BRIDGE_OUT_RGXSETRENDERCONTEXTPRIORITY *psRGXSetRenderContextPriorityOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_RENDER_CONTEXT * psRenderContextInt = IMG_NULL;
+ IMG_HANDLE hRenderContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXSETRENDERCONTEXTPRIORITY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXSetRenderContextPriorityOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hRenderContextInt2,
+ psRGXSetRenderContextPriorityIN->hRenderContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+ if(psRGXSetRenderContextPriorityOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSetRenderContextPriority_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXSetRenderContextPriorityOUT->eError = ResManFindPrivateDataByPtr(hRenderContextInt2, (IMG_VOID **) &psRenderContextInt);
+
+ if(psRGXSetRenderContextPriorityOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSetRenderContextPriority_exit;
+ }
+ }
+
+ psRGXSetRenderContextPriorityOUT->eError =
+ PVRSRVRGXSetRenderContextPriorityKM(psConnection,
+ psRenderContextInt,
+ psRGXSetRenderContextPriorityIN->ui32Priority);
+
+
+
+RGXSetRenderContextPriority_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXGetLastRenderContextResetReason(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXGETLASTRENDERCONTEXTRESETREASON *psRGXGetLastRenderContextResetReasonIN,
+ PVRSRV_BRIDGE_OUT_RGXGETLASTRENDERCONTEXTRESETREASON *psRGXGetLastRenderContextResetReasonOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_RENDER_CONTEXT * psRenderContextInt = IMG_NULL;
+ IMG_HANDLE hRenderContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXGETLASTRENDERCONTEXTRESETREASON);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXGetLastRenderContextResetReasonOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hRenderContextInt2,
+ psRGXGetLastRenderContextResetReasonIN->hRenderContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+ if(psRGXGetLastRenderContextResetReasonOUT->eError != PVRSRV_OK)
+ {
+ goto RGXGetLastRenderContextResetReason_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXGetLastRenderContextResetReasonOUT->eError = ResManFindPrivateDataByPtr(hRenderContextInt2, (IMG_VOID **) &psRenderContextInt);
+
+ if(psRGXGetLastRenderContextResetReasonOUT->eError != PVRSRV_OK)
+ {
+ goto RGXGetLastRenderContextResetReason_exit;
+ }
+ }
+
+ psRGXGetLastRenderContextResetReasonOUT->eError =
+ PVRSRVRGXGetLastRenderContextResetReasonKM(
+ psRenderContextInt,
+ &psRGXGetLastRenderContextResetReasonOUT->ui32LastResetReason);
+
+
+
+RGXGetLastRenderContextResetReason_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXGetPartialRenderCount(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXGETPARTIALRENDERCOUNT *psRGXGetPartialRenderCountIN,
+ PVRSRV_BRIDGE_OUT_RGXGETPARTIALRENDERCOUNT *psRGXGetPartialRenderCountOUT,
+ CONNECTION_DATA *psConnection)
+{
+ DEVMEM_MEMDESC * psHWRTDataMemDescInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXGETPARTIALRENDERCOUNT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXGetPartialRenderCountOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &psHWRTDataMemDescInt,
+ psRGXGetPartialRenderCountIN->hHWRTDataMemDesc,
+ PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC);
+ if(psRGXGetPartialRenderCountOUT->eError != PVRSRV_OK)
+ {
+ goto RGXGetPartialRenderCount_exit;
+ }
+
+ }
+
+ psRGXGetPartialRenderCountOUT->eError =
+ PVRSRVRGXGetPartialRenderCountKM(
+ psHWRTDataMemDescInt,
+ &psRGXGetPartialRenderCountOUT->ui32NumPartialRenders);
+
+
+
+RGXGetPartialRenderCount_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXKickSyncTA(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXKICKSYNCTA *psRGXKickSyncTAIN,
+ PVRSRV_BRIDGE_OUT_RGXKICKSYNCTA *psRGXKickSyncTAOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_RENDER_CONTEXT * psRenderContextInt = IMG_NULL;
+ IMG_HANDLE hRenderContextInt2 = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientTAFenceUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientTAFenceValueInt = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientTAUpdateUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientTAUpdateValueInt = IMG_NULL;
+ IMG_UINT32 *ui32ServerTASyncFlagsInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * *psServerTASyncsInt = IMG_NULL;
+ IMG_HANDLE *hServerTASyncsInt2 = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClient3DFenceUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32Client3DFenceValueInt = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClient3DUpdateUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32Client3DUpdateValueInt = IMG_NULL;
+ IMG_UINT32 *ui32Server3DSyncFlagsInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * *psServer3DSyncsInt = IMG_NULL;
+ IMG_HANDLE *hServer3DSyncsInt2 = IMG_NULL;
+ IMG_INT32 *i32FenceFDsInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTA3D_RGXKICKSYNCTA);
+
+
+
+
+ if (psRGXKickSyncTAIN->ui32ClientTAFenceCount != 0)
+ {
+ sClientTAFenceUFOAddressInt = OSAllocMem(psRGXKickSyncTAIN->ui32ClientTAFenceCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientTAFenceUFOAddressInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->psClientTAFenceUFOAddress, psRGXKickSyncTAIN->ui32ClientTAFenceCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientTAFenceUFOAddressInt, psRGXKickSyncTAIN->psClientTAFenceUFOAddress,
+ psRGXKickSyncTAIN->ui32ClientTAFenceCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32ClientTAFenceCount != 0)
+ {
+ ui32ClientTAFenceValueInt = OSAllocMem(psRGXKickSyncTAIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32));
+ if (!ui32ClientTAFenceValueInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->pui32ClientTAFenceValue, psRGXKickSyncTAIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientTAFenceValueInt, psRGXKickSyncTAIN->pui32ClientTAFenceValue,
+ psRGXKickSyncTAIN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32ClientTAUpdateCount != 0)
+ {
+ sClientTAUpdateUFOAddressInt = OSAllocMem(psRGXKickSyncTAIN->ui32ClientTAUpdateCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientTAUpdateUFOAddressInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->psClientTAUpdateUFOAddress, psRGXKickSyncTAIN->ui32ClientTAUpdateCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientTAUpdateUFOAddressInt, psRGXKickSyncTAIN->psClientTAUpdateUFOAddress,
+ psRGXKickSyncTAIN->ui32ClientTAUpdateCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32ClientTAUpdateCount != 0)
+ {
+ ui32ClientTAUpdateValueInt = OSAllocMem(psRGXKickSyncTAIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32));
+ if (!ui32ClientTAUpdateValueInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->pui32ClientTAUpdateValue, psRGXKickSyncTAIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientTAUpdateValueInt, psRGXKickSyncTAIN->pui32ClientTAUpdateValue,
+ psRGXKickSyncTAIN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32ServerTASyncPrims != 0)
+ {
+ ui32ServerTASyncFlagsInt = OSAllocMem(psRGXKickSyncTAIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32));
+ if (!ui32ServerTASyncFlagsInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->pui32ServerTASyncFlags, psRGXKickSyncTAIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ServerTASyncFlagsInt, psRGXKickSyncTAIN->pui32ServerTASyncFlags,
+ psRGXKickSyncTAIN->ui32ServerTASyncPrims * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32ServerTASyncPrims != 0)
+ {
+ psServerTASyncsInt = OSAllocMem(psRGXKickSyncTAIN->ui32ServerTASyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psServerTASyncsInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ hServerTASyncsInt2 = OSAllocMem(psRGXKickSyncTAIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE));
+ if (!hServerTASyncsInt2)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->phServerTASyncs, psRGXKickSyncTAIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hServerTASyncsInt2, psRGXKickSyncTAIN->phServerTASyncs,
+ psRGXKickSyncTAIN->ui32ServerTASyncPrims * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32Client3DFenceCount != 0)
+ {
+ sClient3DFenceUFOAddressInt = OSAllocMem(psRGXKickSyncTAIN->ui32Client3DFenceCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClient3DFenceUFOAddressInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->psClient3DFenceUFOAddress, psRGXKickSyncTAIN->ui32Client3DFenceCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClient3DFenceUFOAddressInt, psRGXKickSyncTAIN->psClient3DFenceUFOAddress,
+ psRGXKickSyncTAIN->ui32Client3DFenceCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32Client3DFenceCount != 0)
+ {
+ ui32Client3DFenceValueInt = OSAllocMem(psRGXKickSyncTAIN->ui32Client3DFenceCount * sizeof(IMG_UINT32));
+ if (!ui32Client3DFenceValueInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->pui32Client3DFenceValue, psRGXKickSyncTAIN->ui32Client3DFenceCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32Client3DFenceValueInt, psRGXKickSyncTAIN->pui32Client3DFenceValue,
+ psRGXKickSyncTAIN->ui32Client3DFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32Client3DUpdateCount != 0)
+ {
+ sClient3DUpdateUFOAddressInt = OSAllocMem(psRGXKickSyncTAIN->ui32Client3DUpdateCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClient3DUpdateUFOAddressInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->psClient3DUpdateUFOAddress, psRGXKickSyncTAIN->ui32Client3DUpdateCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClient3DUpdateUFOAddressInt, psRGXKickSyncTAIN->psClient3DUpdateUFOAddress,
+ psRGXKickSyncTAIN->ui32Client3DUpdateCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32Client3DUpdateCount != 0)
+ {
+ ui32Client3DUpdateValueInt = OSAllocMem(psRGXKickSyncTAIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32));
+ if (!ui32Client3DUpdateValueInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->pui32Client3DUpdateValue, psRGXKickSyncTAIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32Client3DUpdateValueInt, psRGXKickSyncTAIN->pui32Client3DUpdateValue,
+ psRGXKickSyncTAIN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32Server3DSyncPrims != 0)
+ {
+ ui32Server3DSyncFlagsInt = OSAllocMem(psRGXKickSyncTAIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32));
+ if (!ui32Server3DSyncFlagsInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->pui32Server3DSyncFlags, psRGXKickSyncTAIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32Server3DSyncFlagsInt, psRGXKickSyncTAIN->pui32Server3DSyncFlags,
+ psRGXKickSyncTAIN->ui32Server3DSyncPrims * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32Server3DSyncPrims != 0)
+ {
+ psServer3DSyncsInt = OSAllocMem(psRGXKickSyncTAIN->ui32Server3DSyncPrims * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psServer3DSyncsInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ hServer3DSyncsInt2 = OSAllocMem(psRGXKickSyncTAIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE));
+ if (!hServer3DSyncsInt2)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->phServer3DSyncs, psRGXKickSyncTAIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hServer3DSyncsInt2, psRGXKickSyncTAIN->phServer3DSyncs,
+ psRGXKickSyncTAIN->ui32Server3DSyncPrims * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+ if (psRGXKickSyncTAIN->ui32NumFenceFDs != 0)
+ {
+ i32FenceFDsInt = OSAllocMem(psRGXKickSyncTAIN->ui32NumFenceFDs * sizeof(IMG_INT32));
+ if (!i32FenceFDsInt)
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTAIN->pi32FenceFDs, psRGXKickSyncTAIN->ui32NumFenceFDs * sizeof(IMG_INT32))
+ || (OSCopyFromUser(NULL, i32FenceFDsInt, psRGXKickSyncTAIN->pi32FenceFDs,
+ psRGXKickSyncTAIN->ui32NumFenceFDs * sizeof(IMG_INT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTAOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTA_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXKickSyncTAOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hRenderContextInt2,
+ psRGXKickSyncTAIN->hRenderContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+ if(psRGXKickSyncTAOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTA_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickSyncTAOUT->eError = ResManFindPrivateDataByPtr(hRenderContextInt2, (IMG_VOID **) &psRenderContextInt);
+
+ if(psRGXKickSyncTAOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTA_exit;
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psRGXKickSyncTAIN->ui32ServerTASyncPrims;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psRGXKickSyncTAOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerTASyncsInt2[i],
+ hServerTASyncsInt2[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psRGXKickSyncTAOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTA_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickSyncTAOUT->eError = ResManFindPrivateDataByPtr(hServerTASyncsInt2[i], (IMG_VOID **) &psServerTASyncsInt[i]);
+
+ if(psRGXKickSyncTAOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTA_exit;
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psRGXKickSyncTAIN->ui32Server3DSyncPrims;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psRGXKickSyncTAOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServer3DSyncsInt2[i],
+ hServer3DSyncsInt2[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psRGXKickSyncTAOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTA_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickSyncTAOUT->eError = ResManFindPrivateDataByPtr(hServer3DSyncsInt2[i], (IMG_VOID **) &psServer3DSyncsInt[i]);
+
+ if(psRGXKickSyncTAOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTA_exit;
+ }
+ }
+ }
+ }
+
+ psRGXKickSyncTAOUT->eError =
+ PVRSRVRGXKickSyncTAKM(
+ psRenderContextInt,
+ psRGXKickSyncTAIN->ui32ClientTAFenceCount,
+ sClientTAFenceUFOAddressInt,
+ ui32ClientTAFenceValueInt,
+ psRGXKickSyncTAIN->ui32ClientTAUpdateCount,
+ sClientTAUpdateUFOAddressInt,
+ ui32ClientTAUpdateValueInt,
+ psRGXKickSyncTAIN->ui32ServerTASyncPrims,
+ ui32ServerTASyncFlagsInt,
+ psServerTASyncsInt,
+ psRGXKickSyncTAIN->ui32Client3DFenceCount,
+ sClient3DFenceUFOAddressInt,
+ ui32Client3DFenceValueInt,
+ psRGXKickSyncTAIN->ui32Client3DUpdateCount,
+ sClient3DUpdateUFOAddressInt,
+ ui32Client3DUpdateValueInt,
+ psRGXKickSyncTAIN->ui32Server3DSyncPrims,
+ ui32Server3DSyncFlagsInt,
+ psServer3DSyncsInt,
+ psRGXKickSyncTAIN->ui32NumFenceFDs,
+ i32FenceFDsInt,
+ psRGXKickSyncTAIN->bbPDumpContinuous);
+
+
+
+RGXKickSyncTA_exit:
+ if (sClientTAFenceUFOAddressInt)
+ OSFreeMem(sClientTAFenceUFOAddressInt);
+ if (ui32ClientTAFenceValueInt)
+ OSFreeMem(ui32ClientTAFenceValueInt);
+ if (sClientTAUpdateUFOAddressInt)
+ OSFreeMem(sClientTAUpdateUFOAddressInt);
+ if (ui32ClientTAUpdateValueInt)
+ OSFreeMem(ui32ClientTAUpdateValueInt);
+ if (ui32ServerTASyncFlagsInt)
+ OSFreeMem(ui32ServerTASyncFlagsInt);
+ if (psServerTASyncsInt)
+ OSFreeMem(psServerTASyncsInt);
+ if (hServerTASyncsInt2)
+ OSFreeMem(hServerTASyncsInt2);
+ if (sClient3DFenceUFOAddressInt)
+ OSFreeMem(sClient3DFenceUFOAddressInt);
+ if (ui32Client3DFenceValueInt)
+ OSFreeMem(ui32Client3DFenceValueInt);
+ if (sClient3DUpdateUFOAddressInt)
+ OSFreeMem(sClient3DUpdateUFOAddressInt);
+ if (ui32Client3DUpdateValueInt)
+ OSFreeMem(ui32Client3DUpdateValueInt);
+ if (ui32Server3DSyncFlagsInt)
+ OSFreeMem(ui32Server3DSyncFlagsInt);
+ if (psServer3DSyncsInt)
+ OSFreeMem(psServer3DSyncsInt);
+ if (hServer3DSyncsInt2)
+ OSFreeMem(hServer3DSyncsInt2);
+ if (i32FenceFDsInt)
+ OSFreeMem(i32FenceFDsInt);
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterRGXTA3DFunctions(IMG_VOID);
+IMG_VOID UnregisterRGXTA3DFunctions(IMG_VOID);
+
+/*
+ * Register all RGXTA3D functions with services
+ */
+PVRSRV_ERROR RegisterRGXTA3DFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXCREATEHWRTDATA, PVRSRVBridgeRGXCreateHWRTData);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYHWRTDATA, PVRSRVBridgeRGXDestroyHWRTData);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXCREATERENDERTARGET, PVRSRVBridgeRGXCreateRenderTarget);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYRENDERTARGET, PVRSRVBridgeRGXDestroyRenderTarget);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXCREATEZSBUFFER, PVRSRVBridgeRGXCreateZSBuffer);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYZSBUFFER, PVRSRVBridgeRGXDestroyZSBuffer);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXPOPULATEZSBUFFER, PVRSRVBridgeRGXPopulateZSBuffer);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXUNPOPULATEZSBUFFER, PVRSRVBridgeRGXUnpopulateZSBuffer);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXCREATEFREELIST, PVRSRVBridgeRGXCreateFreeList);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYFREELIST, PVRSRVBridgeRGXDestroyFreeList);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXADDBLOCKTOFREELIST, PVRSRVBridgeRGXAddBlockToFreeList);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXREMOVEBLOCKFROMFREELIST, PVRSRVBridgeRGXRemoveBlockFromFreeList);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXCREATERENDERCONTEXT, PVRSRVBridgeRGXCreateRenderContext);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXDESTROYRENDERCONTEXT, PVRSRVBridgeRGXDestroyRenderContext);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXKICKTA3D, PVRSRVBridgeRGXKickTA3D);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXSETRENDERCONTEXTPRIORITY, PVRSRVBridgeRGXSetRenderContextPriority);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXGETLASTRENDERCONTEXTRESETREASON, PVRSRVBridgeRGXGetLastRenderContextResetReason);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXGETPARTIALRENDERCOUNT, PVRSRVBridgeRGXGetPartialRenderCount);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D_RGXKICKSYNCTA, PVRSRVBridgeRGXKickSyncTA);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all rgxta3d functions with services
+ */
+IMG_VOID UnregisterRGXTA3DFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/rgxtq_bridge/common_rgxtq_bridge.h b/drivers/gpu/rogue/generated/rgxtq_bridge/common_rgxtq_bridge.h
new file mode 100644
index 000000000000..7dec5f5ee43d
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxtq_bridge/common_rgxtq_bridge.h
@@ -0,0 +1,185 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for rgxtq
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for rgxtq
+@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_RGXTQ_BRIDGE_H
+#define COMMON_RGXTQ_BRIDGE_H
+
+#include "rgx_bridge.h"
+#include "sync_external.h"
+#include "rgx_fwif_shared.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_RGXTQ_CMD_FIRST (PVRSRV_BRIDGE_RGXTQ_START)
+#define PVRSRV_BRIDGE_RGXTQ_RGXCREATETRANSFERCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RGXTQ_RGXDESTROYTRANSFERCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RGXTQ_RGXSUBMITTRANSFER PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_RGXTQ_RGXSETTRANSFERCONTEXTPRIORITY PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_RGXTQ_RGXKICKSYNCTRANSFER PVRSRV_IOWR(PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_RGXTQ_CMD_LAST (PVRSRV_BRIDGE_RGXTQ_CMD_FIRST+4)
+
+
+/*******************************************
+ RGXCreateTransferContext
+ *******************************************/
+
+/* Bridge in structure for RGXCreateTransferContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXCREATETRANSFERCONTEXT_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32Priority;
+ IMG_DEV_VIRTADDR sMCUFenceAddr;
+ IMG_UINT32 ui32FrameworkCmdize;
+ IMG_BYTE * psFrameworkCmd;
+ IMG_HANDLE hPrivData;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCREATETRANSFERCONTEXT;
+
+
+/* Bridge out structure for RGXCreateTransferContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCREATETRANSFERCONTEXT_TAG
+{
+ IMG_HANDLE hTransferContext;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCREATETRANSFERCONTEXT;
+
+/*******************************************
+ RGXDestroyTransferContext
+ *******************************************/
+
+/* Bridge in structure for RGXDestroyTransferContext */
+typedef struct PVRSRV_BRIDGE_IN_RGXDESTROYTRANSFERCONTEXT_TAG
+{
+ IMG_HANDLE hTransferContext;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXDESTROYTRANSFERCONTEXT;
+
+
+/* Bridge out structure for RGXDestroyTransferContext */
+typedef struct PVRSRV_BRIDGE_OUT_RGXDESTROYTRANSFERCONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXDESTROYTRANSFERCONTEXT;
+
+/*******************************************
+ RGXSubmitTransfer
+ *******************************************/
+
+/* Bridge in structure for RGXSubmitTransfer */
+typedef struct PVRSRV_BRIDGE_IN_RGXSUBMITTRANSFER_TAG
+{
+ IMG_HANDLE hTransferContext;
+ IMG_UINT32 ui32PrepareCount;
+ IMG_UINT32 * pui32ClientFenceCount;
+ PRGXFWIF_UFO_ADDR* * psFenceUFOAddress;
+ IMG_UINT32* * pui32FenceValue;
+ IMG_UINT32 * pui32ClientUpdateCount;
+ PRGXFWIF_UFO_ADDR* * psUpdateUFOAddress;
+ IMG_UINT32* * pui32UpdateValue;
+ IMG_UINT32 * pui32ServerSyncCount;
+ IMG_UINT32* * pui32ServerSyncFlags;
+ IMG_HANDLE* * phServerSync;
+ IMG_UINT32 ui32NumFenceFDs;
+ IMG_INT32 * pi32FenceFDs;
+ IMG_UINT32 * pui32CommandSize;
+ IMG_UINT8* * pui8FWCommand;
+ IMG_UINT32 * pui32TQPrepareFlags;
+ IMG_UINT32 ui32ExternalJobReference;
+ IMG_UINT32 ui32InternalJobReference;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXSUBMITTRANSFER;
+
+
+/* Bridge out structure for RGXSubmitTransfer */
+typedef struct PVRSRV_BRIDGE_OUT_RGXSUBMITTRANSFER_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXSUBMITTRANSFER;
+
+/*******************************************
+ RGXSetTransferContextPriority
+ *******************************************/
+
+/* Bridge in structure for RGXSetTransferContextPriority */
+typedef struct PVRSRV_BRIDGE_IN_RGXSETTRANSFERCONTEXTPRIORITY_TAG
+{
+ IMG_HANDLE hTransferContext;
+ IMG_UINT32 ui32Priority;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXSETTRANSFERCONTEXTPRIORITY;
+
+
+/* Bridge out structure for RGXSetTransferContextPriority */
+typedef struct PVRSRV_BRIDGE_OUT_RGXSETTRANSFERCONTEXTPRIORITY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXSETTRANSFERCONTEXTPRIORITY;
+
+/*******************************************
+ RGXKickSyncTransfer
+ *******************************************/
+
+/* Bridge in structure for RGXKickSyncTransfer */
+typedef struct PVRSRV_BRIDGE_IN_RGXKICKSYNCTRANSFER_TAG
+{
+ IMG_HANDLE hTransferContext;
+ IMG_UINT32 ui32ClientFenceCount;
+ PRGXFWIF_UFO_ADDR * psClientFenceUFOAddress;
+ IMG_UINT32 * pui32ClientFenceValue;
+ IMG_UINT32 ui32ClientUpdateCount;
+ PRGXFWIF_UFO_ADDR * psClientUpdateUFOAddress;
+ IMG_UINT32 * pui32ClientUpdateValue;
+ IMG_UINT32 ui32ServerSyncCount;
+ IMG_UINT32 * pui32ServerSyncFlags;
+ IMG_HANDLE * phServerSyncs;
+ IMG_UINT32 ui32NumFenceFDs;
+ IMG_INT32 * pi32FenceFDs;
+ IMG_UINT32 ui32TQPrepareFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXKICKSYNCTRANSFER;
+
+
+/* Bridge out structure for RGXKickSyncTransfer */
+typedef struct PVRSRV_BRIDGE_OUT_RGXKICKSYNCTRANSFER_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXKICKSYNCTRANSFER;
+
+#endif /* COMMON_RGXTQ_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/rgxtq_bridge/server_rgxtq_bridge.c b/drivers/gpu/rogue/generated/rgxtq_bridge/server_rgxtq_bridge.c
new file mode 100644
index 000000000000..84e26ea24931
--- /dev/null
+++ b/drivers/gpu/rogue/generated/rgxtq_bridge/server_rgxtq_bridge.c
@@ -0,0 +1,1411 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for rgxtq
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for rgxtq
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxtransfer.h"
+
+
+#include "common_rgxtq_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+RGXDestroyTransferContextResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeRGXCreateTransferContext(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCREATETRANSFERCONTEXT *psRGXCreateTransferContextIN,
+ PVRSRV_BRIDGE_OUT_RGXCREATETRANSFERCONTEXT *psRGXCreateTransferContextOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ IMG_BYTE *psFrameworkCmdInt = IMG_NULL;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+ RGX_SERVER_TQ_CONTEXT * psTransferContextInt = IMG_NULL;
+ IMG_HANDLE hTransferContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTQ_RGXCREATETRANSFERCONTEXT);
+
+
+
+
+ if (psRGXCreateTransferContextIN->ui32FrameworkCmdize != 0)
+ {
+ psFrameworkCmdInt = OSAllocMem(psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE));
+ if (!psFrameworkCmdInt)
+ {
+ psRGXCreateTransferContextOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXCreateTransferContext_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXCreateTransferContextIN->psFrameworkCmd, psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE))
+ || (OSCopyFromUser(NULL, psFrameworkCmdInt, psRGXCreateTransferContextIN->psFrameworkCmd,
+ psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) != PVRSRV_OK) )
+ {
+ psRGXCreateTransferContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXCreateTransferContext_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateTransferContextOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCreateTransferContextIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCreateTransferContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateTransferContext_exit;
+ }
+
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXCreateTransferContextOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPrivDataInt,
+ psRGXCreateTransferContextIN->hPrivData,
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
+ if(psRGXCreateTransferContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateTransferContext_exit;
+ }
+
+ }
+
+ psRGXCreateTransferContextOUT->eError =
+ PVRSRVRGXCreateTransferContextKM(psConnection,
+ hDevNodeInt,
+ psRGXCreateTransferContextIN->ui32Priority,
+ psRGXCreateTransferContextIN->sMCUFenceAddr,
+ psRGXCreateTransferContextIN->ui32FrameworkCmdize,
+ psFrameworkCmdInt,
+ hPrivDataInt,
+ &psTransferContextInt);
+ /* Exit early if bridged call fails */
+ if(psRGXCreateTransferContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateTransferContext_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hTransferContextInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_RGX_SERVER_TQ_CONTEXT,
+ psTransferContextInt,
+ (RESMAN_FREE_FN)&PVRSRVRGXDestroyTransferContextKM);
+ if (hTransferContextInt2 == IMG_NULL)
+ {
+ psRGXCreateTransferContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto RGXCreateTransferContext_exit;
+ }
+ psRGXCreateTransferContextOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRGXCreateTransferContextOUT->hTransferContext,
+ (IMG_HANDLE) hTransferContextInt2,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRGXCreateTransferContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCreateTransferContext_exit;
+ }
+
+
+RGXCreateTransferContext_exit:
+ if (psRGXCreateTransferContextOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hTransferContextInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hTransferContextInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psTransferContextInt)
+ {
+ PVRSRVRGXDestroyTransferContextKM(psTransferContextInt);
+ }
+ }
+
+ if (psFrameworkCmdInt)
+ OSFreeMem(psFrameworkCmdInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXDestroyTransferContext(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXDESTROYTRANSFERCONTEXT *psRGXDestroyTransferContextIN,
+ PVRSRV_BRIDGE_OUT_RGXDESTROYTRANSFERCONTEXT *psRGXDestroyTransferContextOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hTransferContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTQ_RGXDESTROYTRANSFERCONTEXT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXDestroyTransferContextOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hTransferContextInt2,
+ psRGXDestroyTransferContextIN->hTransferContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
+ if(psRGXDestroyTransferContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyTransferContext_exit;
+ }
+
+ }
+
+ psRGXDestroyTransferContextOUT->eError = RGXDestroyTransferContextResManProxy(hTransferContextInt2);
+ /* Exit early if bridged call fails */
+ if(psRGXDestroyTransferContextOUT->eError != PVRSRV_OK)
+ {
+ goto RGXDestroyTransferContext_exit;
+ }
+
+ psRGXDestroyTransferContextOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRGXDestroyTransferContextIN->hTransferContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
+
+
+RGXDestroyTransferContext_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXSubmitTransfer(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXSUBMITTRANSFER *psRGXSubmitTransferIN,
+ PVRSRV_BRIDGE_OUT_RGXSUBMITTRANSFER *psRGXSubmitTransferOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_TQ_CONTEXT * psTransferContextInt = IMG_NULL;
+ IMG_HANDLE hTransferContextInt2 = IMG_NULL;
+ IMG_UINT32 *ui32ClientFenceCountInt = IMG_NULL;
+ PRGXFWIF_UFO_ADDR **sFenceUFOAddressInt = IMG_NULL;
+ IMG_UINT32 **ui32FenceValueInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientUpdateCountInt = IMG_NULL;
+ PRGXFWIF_UFO_ADDR **sUpdateUFOAddressInt = IMG_NULL;
+ IMG_UINT32 **ui32UpdateValueInt = IMG_NULL;
+ IMG_UINT32 *ui32ServerSyncCountInt = IMG_NULL;
+ IMG_UINT32 **ui32ServerSyncFlagsInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * **psServerSyncInt = IMG_NULL;
+ IMG_HANDLE **hServerSyncInt2 = IMG_NULL;
+ IMG_INT32 *i32FenceFDsInt = IMG_NULL;
+ IMG_UINT32 *ui32CommandSizeInt = IMG_NULL;
+ IMG_UINT8 **ui8FWCommandInt = IMG_NULL;
+ IMG_UINT32 *ui32TQPrepareFlagsInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTQ_RGXSUBMITTRANSFER);
+
+
+
+
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ ui32ClientFenceCountInt = OSAllocMem(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
+ if (!ui32ClientFenceCountInt)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXSubmitTransferIN->pui32ClientFenceCount, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientFenceCountInt, psRGXSubmitTransferIN->pui32ClientFenceCount,
+ psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ IMG_UINT32 ui32Pass=0;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32AllocSize=0;
+ IMG_UINT32 ui32Size;
+ IMG_UINT8 *pui8Ptr = IMG_NULL;
+
+ /*
+ Two pass loop, 1st find out the size and 2nd allocation and set offsets.
+ Keeps allocation cost down and simplifies the free path
+ */
+ for (ui32Pass=0;ui32Pass<2;ui32Pass++)
+ {
+ ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(PRGXFWIF_UFO_ADDR *);
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ pui8Ptr = OSAllocMem(ui32AllocSize);
+ if (pui8Ptr == IMG_NULL)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto RGXSubmitTransfer_exit;
+ }
+ sFenceUFOAddressInt = (PRGXFWIF_UFO_ADDR **) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ ui32Size = ui32ClientFenceCountInt[i] * sizeof(PRGXFWIF_UFO_ADDR);
+ if (ui32Size)
+ {
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ sFenceUFOAddressInt[i] = (PRGXFWIF_UFO_ADDR *) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+ PRGXFWIF_UFO_ADDR **psPtr;
+
+ /* Loop over all the pointers in the array copying the data into the kernel */
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ /* Copy the pointer over from the client side */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) &psRGXSubmitTransferIN->psFenceUFOAddress[i], sizeof(PRGXFWIF_UFO_ADDR **))
+ || (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->psFenceUFOAddress[i],
+ sizeof(PRGXFWIF_UFO_ADDR **)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPtr, (psRGXSubmitTransferIN->pui32ClientFenceCount[i] * sizeof(PRGXFWIF_UFO_ADDR)))
+ || (OSCopyFromUser(NULL, (sFenceUFOAddressInt[i]), psPtr,
+ (psRGXSubmitTransferIN->pui32ClientFenceCount[i] * sizeof(PRGXFWIF_UFO_ADDR))) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ IMG_UINT32 ui32Pass=0;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32AllocSize=0;
+ IMG_UINT32 ui32Size;
+ IMG_UINT8 *pui8Ptr = IMG_NULL;
+
+ /*
+ Two pass loop, 1st find out the size and 2nd allocation and set offsets.
+ Keeps allocation cost down and simplifies the free path
+ */
+ for (ui32Pass=0;ui32Pass<2;ui32Pass++)
+ {
+ ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32 *);
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ pui8Ptr = OSAllocMem(ui32AllocSize);
+ if (pui8Ptr == IMG_NULL)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto RGXSubmitTransfer_exit;
+ }
+ ui32FenceValueInt = (IMG_UINT32 **) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ ui32Size = ui32ClientFenceCountInt[i] * sizeof(IMG_UINT32);
+ if (ui32Size)
+ {
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ ui32FenceValueInt[i] = (IMG_UINT32 *) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+ IMG_UINT32 **psPtr;
+
+ /* Loop over all the pointers in the array copying the data into the kernel */
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ /* Copy the pointer over from the client side */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) &psRGXSubmitTransferIN->pui32FenceValue[i], sizeof(IMG_UINT32 **))
+ || (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32FenceValue[i],
+ sizeof(IMG_UINT32 **)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPtr, (psRGXSubmitTransferIN->pui32ClientFenceCount[i] * sizeof(IMG_UINT32)))
+ || (OSCopyFromUser(NULL, (ui32FenceValueInt[i]), psPtr,
+ (psRGXSubmitTransferIN->pui32ClientFenceCount[i] * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ ui32ClientUpdateCountInt = OSAllocMem(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
+ if (!ui32ClientUpdateCountInt)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXSubmitTransferIN->pui32ClientUpdateCount, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientUpdateCountInt, psRGXSubmitTransferIN->pui32ClientUpdateCount,
+ psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ IMG_UINT32 ui32Pass=0;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32AllocSize=0;
+ IMG_UINT32 ui32Size;
+ IMG_UINT8 *pui8Ptr = IMG_NULL;
+
+ /*
+ Two pass loop, 1st find out the size and 2nd allocation and set offsets.
+ Keeps allocation cost down and simplifies the free path
+ */
+ for (ui32Pass=0;ui32Pass<2;ui32Pass++)
+ {
+ ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(PRGXFWIF_UFO_ADDR *);
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ pui8Ptr = OSAllocMem(ui32AllocSize);
+ if (pui8Ptr == IMG_NULL)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto RGXSubmitTransfer_exit;
+ }
+ sUpdateUFOAddressInt = (PRGXFWIF_UFO_ADDR **) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ ui32Size = ui32ClientUpdateCountInt[i] * sizeof(PRGXFWIF_UFO_ADDR);
+ if (ui32Size)
+ {
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ sUpdateUFOAddressInt[i] = (PRGXFWIF_UFO_ADDR *) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+ PRGXFWIF_UFO_ADDR **psPtr;
+
+ /* Loop over all the pointers in the array copying the data into the kernel */
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ /* Copy the pointer over from the client side */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) &psRGXSubmitTransferIN->psUpdateUFOAddress[i], sizeof(PRGXFWIF_UFO_ADDR **))
+ || (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->psUpdateUFOAddress[i],
+ sizeof(PRGXFWIF_UFO_ADDR **)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPtr, (psRGXSubmitTransferIN->pui32ClientUpdateCount[i] * sizeof(PRGXFWIF_UFO_ADDR)))
+ || (OSCopyFromUser(NULL, (sUpdateUFOAddressInt[i]), psPtr,
+ (psRGXSubmitTransferIN->pui32ClientUpdateCount[i] * sizeof(PRGXFWIF_UFO_ADDR))) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ IMG_UINT32 ui32Pass=0;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32AllocSize=0;
+ IMG_UINT32 ui32Size;
+ IMG_UINT8 *pui8Ptr = IMG_NULL;
+
+ /*
+ Two pass loop, 1st find out the size and 2nd allocation and set offsets.
+ Keeps allocation cost down and simplifies the free path
+ */
+ for (ui32Pass=0;ui32Pass<2;ui32Pass++)
+ {
+ ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32 *);
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ pui8Ptr = OSAllocMem(ui32AllocSize);
+ if (pui8Ptr == IMG_NULL)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto RGXSubmitTransfer_exit;
+ }
+ ui32UpdateValueInt = (IMG_UINT32 **) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ ui32Size = ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);
+ if (ui32Size)
+ {
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ ui32UpdateValueInt[i] = (IMG_UINT32 *) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+ IMG_UINT32 **psPtr;
+
+ /* Loop over all the pointers in the array copying the data into the kernel */
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ /* Copy the pointer over from the client side */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) &psRGXSubmitTransferIN->pui32UpdateValue[i], sizeof(IMG_UINT32 **))
+ || (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32UpdateValue[i],
+ sizeof(IMG_UINT32 **)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPtr, (psRGXSubmitTransferIN->pui32ClientUpdateCount[i] * sizeof(IMG_UINT32)))
+ || (OSCopyFromUser(NULL, (ui32UpdateValueInt[i]), psPtr,
+ (psRGXSubmitTransferIN->pui32ClientUpdateCount[i] * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ ui32ServerSyncCountInt = OSAllocMem(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
+ if (!ui32ServerSyncCountInt)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXSubmitTransferIN->pui32ServerSyncCount, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ServerSyncCountInt, psRGXSubmitTransferIN->pui32ServerSyncCount,
+ psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ IMG_UINT32 ui32Pass=0;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32AllocSize=0;
+ IMG_UINT32 ui32Size;
+ IMG_UINT8 *pui8Ptr = IMG_NULL;
+
+ /*
+ Two pass loop, 1st find out the size and 2nd allocation and set offsets.
+ Keeps allocation cost down and simplifies the free path
+ */
+ for (ui32Pass=0;ui32Pass<2;ui32Pass++)
+ {
+ ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32 *);
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ pui8Ptr = OSAllocMem(ui32AllocSize);
+ if (pui8Ptr == IMG_NULL)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto RGXSubmitTransfer_exit;
+ }
+ ui32ServerSyncFlagsInt = (IMG_UINT32 **) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ ui32Size = ui32ServerSyncCountInt[i] * sizeof(IMG_UINT32);
+ if (ui32Size)
+ {
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ ui32ServerSyncFlagsInt[i] = (IMG_UINT32 *) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+ IMG_UINT32 **psPtr;
+
+ /* Loop over all the pointers in the array copying the data into the kernel */
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ /* Copy the pointer over from the client side */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) &psRGXSubmitTransferIN->pui32ServerSyncFlags[i], sizeof(IMG_UINT32 **))
+ || (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui32ServerSyncFlags[i],
+ sizeof(IMG_UINT32 **)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPtr, (psRGXSubmitTransferIN->pui32ServerSyncCount[i] * sizeof(IMG_UINT32)))
+ || (OSCopyFromUser(NULL, (ui32ServerSyncFlagsInt[i]), psPtr,
+ (psRGXSubmitTransferIN->pui32ServerSyncCount[i] * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ IMG_UINT32 ui32Pass=0;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32AllocSize=0;
+ IMG_UINT32 ui32Size;
+ IMG_UINT8 *pui8Ptr = IMG_NULL;
+ IMG_UINT32 ui32AllocSize2=0;
+ IMG_UINT32 ui32Size2;
+ IMG_UINT8 *pui8Ptr2 = IMG_NULL;
+
+ /*
+ Two pass loop, 1st find out the size and 2nd allocation and set offsets.
+ Keeps allocation cost down and simplifies the free path
+ */
+ for (ui32Pass=0;ui32Pass<2;ui32Pass++)
+ {
+ ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(SERVER_SYNC_PRIMITIVE * *);
+ ui32Size2 = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_HANDLE *);
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ ui32AllocSize2 += ui32Size2;
+ }
+ else
+ {
+ pui8Ptr = OSAllocMem(ui32AllocSize);
+ if (pui8Ptr == IMG_NULL)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto RGXSubmitTransfer_exit;
+ }
+ psServerSyncInt = (SERVER_SYNC_PRIMITIVE * **) pui8Ptr;
+ pui8Ptr += ui32Size;
+ pui8Ptr2 = OSAllocMem(ui32AllocSize2);
+ if (pui8Ptr2 == IMG_NULL)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto RGXSubmitTransfer_exit;
+ }
+ hServerSyncInt2 = (IMG_HANDLE **) pui8Ptr2;
+ pui8Ptr2 += ui32Size2;
+ }
+
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ ui32Size = ui32ServerSyncCountInt[i] * sizeof(SERVER_SYNC_PRIMITIVE *);
+ ui32Size2 = ui32ServerSyncCountInt[i] * sizeof(IMG_HANDLE);
+ if (ui32Size)
+ {
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ ui32AllocSize2 += ui32Size2;
+ }
+ else
+ {
+ psServerSyncInt[i] = (SERVER_SYNC_PRIMITIVE * *) pui8Ptr;
+ pui8Ptr += ui32Size;
+ hServerSyncInt2[i] = (IMG_HANDLE *) pui8Ptr2;
+ pui8Ptr2 += ui32Size2;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+ IMG_HANDLE **psPtr;
+
+ /* Loop over all the pointers in the array copying the data into the kernel */
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ /* Copy the pointer over from the client side */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) &psRGXSubmitTransferIN->phServerSync[i], sizeof(IMG_HANDLE **))
+ || (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->phServerSync[i],
+ sizeof(IMG_HANDLE **)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPtr, (psRGXSubmitTransferIN->pui32ServerSyncCount[i] * sizeof(IMG_HANDLE)))
+ || (OSCopyFromUser(NULL, (hServerSyncInt2[i]), psPtr,
+ (psRGXSubmitTransferIN->pui32ServerSyncCount[i] * sizeof(IMG_HANDLE))) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+ }
+ if (psRGXSubmitTransferIN->ui32NumFenceFDs != 0)
+ {
+ i32FenceFDsInt = OSAllocMem(psRGXSubmitTransferIN->ui32NumFenceFDs * sizeof(IMG_INT32));
+ if (!i32FenceFDsInt)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXSubmitTransferIN->pi32FenceFDs, psRGXSubmitTransferIN->ui32NumFenceFDs * sizeof(IMG_INT32))
+ || (OSCopyFromUser(NULL, i32FenceFDsInt, psRGXSubmitTransferIN->pi32FenceFDs,
+ psRGXSubmitTransferIN->ui32NumFenceFDs * sizeof(IMG_INT32)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ ui32CommandSizeInt = OSAllocMem(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
+ if (!ui32CommandSizeInt)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXSubmitTransferIN->pui32CommandSize, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32CommandSizeInt, psRGXSubmitTransferIN->pui32CommandSize,
+ psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ IMG_UINT32 ui32Pass=0;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32AllocSize=0;
+ IMG_UINT32 ui32Size;
+ IMG_UINT8 *pui8Ptr = IMG_NULL;
+
+ /*
+ Two pass loop, 1st find out the size and 2nd allocation and set offsets.
+ Keeps allocation cost down and simplifies the free path
+ */
+ for (ui32Pass=0;ui32Pass<2;ui32Pass++)
+ {
+ ui32Size = psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT8 *);
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ pui8Ptr = OSAllocMem(ui32AllocSize);
+ if (pui8Ptr == IMG_NULL)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto RGXSubmitTransfer_exit;
+ }
+ ui8FWCommandInt = (IMG_UINT8 **) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ ui32Size = ui32CommandSizeInt[i] * sizeof(IMG_UINT8);
+ if (ui32Size)
+ {
+ if (ui32Pass == 0)
+ {
+ ui32AllocSize += ui32Size;
+ }
+ else
+ {
+ ui8FWCommandInt[i] = (IMG_UINT8 *) pui8Ptr;
+ pui8Ptr += ui32Size;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+ IMG_UINT8 **psPtr;
+
+ /* Loop over all the pointers in the array copying the data into the kernel */
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ /* Copy the pointer over from the client side */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) &psRGXSubmitTransferIN->pui8FWCommand[i], sizeof(IMG_UINT8 **))
+ || (OSCopyFromUser(NULL, &psPtr, &psRGXSubmitTransferIN->pui8FWCommand[i],
+ sizeof(IMG_UINT8 **)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psPtr, (psRGXSubmitTransferIN->pui32CommandSize[i] * sizeof(IMG_UINT8)))
+ || (OSCopyFromUser(NULL, (ui8FWCommandInt[i]), psPtr,
+ (psRGXSubmitTransferIN->pui32CommandSize[i] * sizeof(IMG_UINT8))) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+ }
+ if (psRGXSubmitTransferIN->ui32PrepareCount != 0)
+ {
+ ui32TQPrepareFlagsInt = OSAllocMem(psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32));
+ if (!ui32TQPrepareFlagsInt)
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXSubmitTransferIN->pui32TQPrepareFlags, psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32TQPrepareFlagsInt, psRGXSubmitTransferIN->pui32TQPrepareFlags,
+ psRGXSubmitTransferIN->ui32PrepareCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXSubmitTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXSubmitTransfer_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXSubmitTransferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hTransferContextInt2,
+ psRGXSubmitTransferIN->hTransferContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
+ if(psRGXSubmitTransferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSubmitTransfer_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXSubmitTransferOUT->eError = ResManFindPrivateDataByPtr(hTransferContextInt2, (IMG_VOID **) &psTransferContextInt);
+
+ if(psRGXSubmitTransferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psRGXSubmitTransferIN->ui32PrepareCount;i++)
+ {
+ IMG_UINT32 j;
+ for (j=0;j<ui32ServerSyncCountInt[i];j++)
+ {
+ {
+ /* Look up the address from the handle */
+ psRGXSubmitTransferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerSyncInt2[i][j],
+ hServerSyncInt2[i][j],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psRGXSubmitTransferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSubmitTransfer_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXSubmitTransferOUT->eError = ResManFindPrivateDataByPtr(hServerSyncInt2[i][j], (IMG_VOID **) &psServerSyncInt[i][j]);
+
+ if(psRGXSubmitTransferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSubmitTransfer_exit;
+ }
+ }
+ }
+ }
+ }
+
+ psRGXSubmitTransferOUT->eError =
+ PVRSRVRGXSubmitTransferKM(
+ psTransferContextInt,
+ psRGXSubmitTransferIN->ui32PrepareCount,
+ ui32ClientFenceCountInt,
+ sFenceUFOAddressInt,
+ ui32FenceValueInt,
+ ui32ClientUpdateCountInt,
+ sUpdateUFOAddressInt,
+ ui32UpdateValueInt,
+ ui32ServerSyncCountInt,
+ ui32ServerSyncFlagsInt,
+ psServerSyncInt,
+ psRGXSubmitTransferIN->ui32NumFenceFDs,
+ i32FenceFDsInt,
+ ui32CommandSizeInt,
+ ui8FWCommandInt,
+ ui32TQPrepareFlagsInt,
+ psRGXSubmitTransferIN->ui32ExternalJobReference,
+ psRGXSubmitTransferIN->ui32InternalJobReference);
+
+
+
+RGXSubmitTransfer_exit:
+ if (ui32ClientFenceCountInt)
+ OSFreeMem(ui32ClientFenceCountInt);
+ if (sFenceUFOAddressInt)
+ OSFreeMem(sFenceUFOAddressInt);
+ if (ui32FenceValueInt)
+ OSFreeMem(ui32FenceValueInt);
+ if (ui32ClientUpdateCountInt)
+ OSFreeMem(ui32ClientUpdateCountInt);
+ if (sUpdateUFOAddressInt)
+ OSFreeMem(sUpdateUFOAddressInt);
+ if (ui32UpdateValueInt)
+ OSFreeMem(ui32UpdateValueInt);
+ if (ui32ServerSyncCountInt)
+ OSFreeMem(ui32ServerSyncCountInt);
+ if (ui32ServerSyncFlagsInt)
+ OSFreeMem(ui32ServerSyncFlagsInt);
+ if (psServerSyncInt)
+ OSFreeMem(psServerSyncInt);
+ if (hServerSyncInt2)
+ OSFreeMem(hServerSyncInt2);
+ if (i32FenceFDsInt)
+ OSFreeMem(i32FenceFDsInt);
+ if (ui32CommandSizeInt)
+ OSFreeMem(ui32CommandSizeInt);
+ if (ui8FWCommandInt)
+ OSFreeMem(ui8FWCommandInt);
+ if (ui32TQPrepareFlagsInt)
+ OSFreeMem(ui32TQPrepareFlagsInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXSetTransferContextPriority(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXSETTRANSFERCONTEXTPRIORITY *psRGXSetTransferContextPriorityIN,
+ PVRSRV_BRIDGE_OUT_RGXSETTRANSFERCONTEXTPRIORITY *psRGXSetTransferContextPriorityOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_TQ_CONTEXT * psTransferContextInt = IMG_NULL;
+ IMG_HANDLE hTransferContextInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTQ_RGXSETTRANSFERCONTEXTPRIORITY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXSetTransferContextPriorityOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hTransferContextInt2,
+ psRGXSetTransferContextPriorityIN->hTransferContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
+ if(psRGXSetTransferContextPriorityOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSetTransferContextPriority_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXSetTransferContextPriorityOUT->eError = ResManFindPrivateDataByPtr(hTransferContextInt2, (IMG_VOID **) &psTransferContextInt);
+
+ if(psRGXSetTransferContextPriorityOUT->eError != PVRSRV_OK)
+ {
+ goto RGXSetTransferContextPriority_exit;
+ }
+ }
+
+ psRGXSetTransferContextPriorityOUT->eError =
+ PVRSRVRGXSetTransferContextPriorityKM(psConnection,
+ psTransferContextInt,
+ psRGXSetTransferContextPriorityIN->ui32Priority);
+
+
+
+RGXSetTransferContextPriority_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXKickSyncTransfer(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXKICKSYNCTRANSFER *psRGXKickSyncTransferIN,
+ PVRSRV_BRIDGE_OUT_RGXKICKSYNCTRANSFER *psRGXKickSyncTransferOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RGX_SERVER_TQ_CONTEXT * psTransferContextInt = IMG_NULL;
+ IMG_HANDLE hTransferContextInt2 = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientFenceUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientFenceValueInt = IMG_NULL;
+ PRGXFWIF_UFO_ADDR *sClientUpdateUFOAddressInt = IMG_NULL;
+ IMG_UINT32 *ui32ClientUpdateValueInt = IMG_NULL;
+ IMG_UINT32 *ui32ServerSyncFlagsInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * *psServerSyncsInt = IMG_NULL;
+ IMG_HANDLE *hServerSyncsInt2 = IMG_NULL;
+ IMG_INT32 *i32FenceFDsInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RGXTQ_RGXKICKSYNCTRANSFER);
+
+
+
+
+ if (psRGXKickSyncTransferIN->ui32ClientFenceCount != 0)
+ {
+ sClientFenceUFOAddressInt = OSAllocMem(psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientFenceUFOAddressInt)
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTransferIN->psClientFenceUFOAddress, psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientFenceUFOAddressInt, psRGXKickSyncTransferIN->psClientFenceUFOAddress,
+ psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ if (psRGXKickSyncTransferIN->ui32ClientFenceCount != 0)
+ {
+ ui32ClientFenceValueInt = OSAllocMem(psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32));
+ if (!ui32ClientFenceValueInt)
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTransferIN->pui32ClientFenceValue, psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientFenceValueInt, psRGXKickSyncTransferIN->pui32ClientFenceValue,
+ psRGXKickSyncTransferIN->ui32ClientFenceCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ if (psRGXKickSyncTransferIN->ui32ClientUpdateCount != 0)
+ {
+ sClientUpdateUFOAddressInt = OSAllocMem(psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(PRGXFWIF_UFO_ADDR));
+ if (!sClientUpdateUFOAddressInt)
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTransferIN->psClientUpdateUFOAddress, psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(PRGXFWIF_UFO_ADDR))
+ || (OSCopyFromUser(NULL, sClientUpdateUFOAddressInt, psRGXKickSyncTransferIN->psClientUpdateUFOAddress,
+ psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(PRGXFWIF_UFO_ADDR)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ if (psRGXKickSyncTransferIN->ui32ClientUpdateCount != 0)
+ {
+ ui32ClientUpdateValueInt = OSAllocMem(psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32));
+ if (!ui32ClientUpdateValueInt)
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTransferIN->pui32ClientUpdateValue, psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ClientUpdateValueInt, psRGXKickSyncTransferIN->pui32ClientUpdateValue,
+ psRGXKickSyncTransferIN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ if (psRGXKickSyncTransferIN->ui32ServerSyncCount != 0)
+ {
+ ui32ServerSyncFlagsInt = OSAllocMem(psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32));
+ if (!ui32ServerSyncFlagsInt)
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTransferIN->pui32ServerSyncFlags, psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ServerSyncFlagsInt, psRGXKickSyncTransferIN->pui32ServerSyncFlags,
+ psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ if (psRGXKickSyncTransferIN->ui32ServerSyncCount != 0)
+ {
+ psServerSyncsInt = OSAllocMem(psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psServerSyncsInt)
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ hServerSyncsInt2 = OSAllocMem(psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE));
+ if (!hServerSyncsInt2)
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTransferIN->phServerSyncs, psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hServerSyncsInt2, psRGXKickSyncTransferIN->phServerSyncs,
+ psRGXKickSyncTransferIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ if (psRGXKickSyncTransferIN->ui32NumFenceFDs != 0)
+ {
+ i32FenceFDsInt = OSAllocMem(psRGXKickSyncTransferIN->ui32NumFenceFDs * sizeof(IMG_INT32));
+ if (!i32FenceFDsInt)
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRGXKickSyncTransferIN->pi32FenceFDs, psRGXKickSyncTransferIN->ui32NumFenceFDs * sizeof(IMG_INT32))
+ || (OSCopyFromUser(NULL, i32FenceFDsInt, psRGXKickSyncTransferIN->pi32FenceFDs,
+ psRGXKickSyncTransferIN->ui32NumFenceFDs * sizeof(IMG_INT32)) != PVRSRV_OK) )
+ {
+ psRGXKickSyncTransferOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RGXKickSyncTransfer_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRGXKickSyncTransferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hTransferContextInt2,
+ psRGXKickSyncTransferIN->hTransferContext,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
+ if(psRGXKickSyncTransferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTransfer_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickSyncTransferOUT->eError = ResManFindPrivateDataByPtr(hTransferContextInt2, (IMG_VOID **) &psTransferContextInt);
+
+ if(psRGXKickSyncTransferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTransfer_exit;
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psRGXKickSyncTransferIN->ui32ServerSyncCount;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psRGXKickSyncTransferOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerSyncsInt2[i],
+ hServerSyncsInt2[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psRGXKickSyncTransferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTransfer_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRGXKickSyncTransferOUT->eError = ResManFindPrivateDataByPtr(hServerSyncsInt2[i], (IMG_VOID **) &psServerSyncsInt[i]);
+
+ if(psRGXKickSyncTransferOUT->eError != PVRSRV_OK)
+ {
+ goto RGXKickSyncTransfer_exit;
+ }
+ }
+ }
+ }
+
+ psRGXKickSyncTransferOUT->eError =
+ PVRSRVRGXKickSyncTransferKM(
+ psTransferContextInt,
+ psRGXKickSyncTransferIN->ui32ClientFenceCount,
+ sClientFenceUFOAddressInt,
+ ui32ClientFenceValueInt,
+ psRGXKickSyncTransferIN->ui32ClientUpdateCount,
+ sClientUpdateUFOAddressInt,
+ ui32ClientUpdateValueInt,
+ psRGXKickSyncTransferIN->ui32ServerSyncCount,
+ ui32ServerSyncFlagsInt,
+ psServerSyncsInt,
+ psRGXKickSyncTransferIN->ui32NumFenceFDs,
+ i32FenceFDsInt,
+ psRGXKickSyncTransferIN->ui32TQPrepareFlags);
+
+
+
+RGXKickSyncTransfer_exit:
+ if (sClientFenceUFOAddressInt)
+ OSFreeMem(sClientFenceUFOAddressInt);
+ if (ui32ClientFenceValueInt)
+ OSFreeMem(ui32ClientFenceValueInt);
+ if (sClientUpdateUFOAddressInt)
+ OSFreeMem(sClientUpdateUFOAddressInt);
+ if (ui32ClientUpdateValueInt)
+ OSFreeMem(ui32ClientUpdateValueInt);
+ if (ui32ServerSyncFlagsInt)
+ OSFreeMem(ui32ServerSyncFlagsInt);
+ if (psServerSyncsInt)
+ OSFreeMem(psServerSyncsInt);
+ if (hServerSyncsInt2)
+ OSFreeMem(hServerSyncsInt2);
+ if (i32FenceFDsInt)
+ OSFreeMem(i32FenceFDsInt);
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterRGXTQFunctions(IMG_VOID);
+IMG_VOID UnregisterRGXTQFunctions(IMG_VOID);
+
+/*
+ * Register all RGXTQ functions with services
+ */
+PVRSRV_ERROR RegisterRGXTQFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ_RGXCREATETRANSFERCONTEXT, PVRSRVBridgeRGXCreateTransferContext);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ_RGXDESTROYTRANSFERCONTEXT, PVRSRVBridgeRGXDestroyTransferContext);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ_RGXSUBMITTRANSFER, PVRSRVBridgeRGXSubmitTransfer);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ_RGXSETTRANSFERCONTEXTPRIORITY, PVRSRVBridgeRGXSetTransferContextPriority);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ_RGXKICKSYNCTRANSFER, PVRSRVBridgeRGXKickSyncTransfer);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all rgxtq functions with services
+ */
+IMG_VOID UnregisterRGXTQFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/ri_bridge/client_ri_bridge.h b/drivers/gpu/rogue/generated/ri_bridge/client_ri_bridge.h
new file mode 100644
index 000000000000..31cf3b70a0e4
--- /dev/null
+++ b/drivers/gpu/rogue/generated/ri_bridge/client_ri_bridge.h
@@ -0,0 +1,84 @@
+/*************************************************************************/ /*!
+@File
+@Title Client bridge header for ri
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Exports the client bridge functions for ri
+@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 CLIENT_RI_BRIDGE_H
+#define CLIENT_RI_BRIDGE_H
+
+#include "pvr_bridge_client.h"
+#include "pvr_bridge.h"
+
+#include "common_ri_bridge.h"
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIWritePMREntry(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRHandle,
+ IMG_UINT32 ui32TextASize,
+ const IMG_CHAR *puiTextA,
+ IMG_SIZE_T uiLogicalSize);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIWriteMEMDESCEntry(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRHandle,
+ IMG_UINT32 ui32TextBSize,
+ const IMG_CHAR *puiTextB,
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ IMG_BOOL bIsImport,
+ IMG_BOOL bIsExportable,
+ IMG_HANDLE *phRIHandle);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIUpdateMEMDESCAddr(IMG_HANDLE hBridge,
+ IMG_HANDLE hRIHandle,
+ IMG_DEV_VIRTADDR sAddr);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIDeleteMEMDESCEntry(IMG_HANDLE hBridge,
+ IMG_HANDLE hRIHandle);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIDumpList(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMRHandle);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIDumpAll(IMG_HANDLE hBridge);
+
+IMG_INTERNAL PVRSRV_ERROR IMG_CALLCONV BridgeRIDumpProcess(IMG_HANDLE hBridge,
+ IMG_PID ui32Pid);
+
+
+#endif /* CLIENT_RI_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/ri_bridge/common_ri_bridge.h b/drivers/gpu/rogue/generated/ri_bridge/common_ri_bridge.h
new file mode 100644
index 000000000000..e6cdec1c5bf6
--- /dev/null
+++ b/drivers/gpu/rogue/generated/ri_bridge/common_ri_bridge.h
@@ -0,0 +1,194 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for ri
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for ri
+@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_RI_BRIDGE_H
+#define COMMON_RI_BRIDGE_H
+
+#include "ri_typedefs.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_RI_CMD_FIRST (PVRSRV_BRIDGE_RI_START)
+#define PVRSRV_BRIDGE_RI_RIWRITEPMRENTRY PVRSRV_IOWR(PVRSRV_BRIDGE_RI_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RI_RIWRITEMEMDESCENTRY PVRSRV_IOWR(PVRSRV_BRIDGE_RI_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RI_RIUPDATEMEMDESCADDR PVRSRV_IOWR(PVRSRV_BRIDGE_RI_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_RI_RIDELETEMEMDESCENTRY PVRSRV_IOWR(PVRSRV_BRIDGE_RI_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_RI_RIDUMPLIST PVRSRV_IOWR(PVRSRV_BRIDGE_RI_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_RI_RIDUMPALL PVRSRV_IOWR(PVRSRV_BRIDGE_RI_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_RI_RIDUMPPROCESS PVRSRV_IOWR(PVRSRV_BRIDGE_RI_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_RI_CMD_LAST (PVRSRV_BRIDGE_RI_CMD_FIRST+6)
+
+
+/*******************************************
+ RIWritePMREntry
+ *******************************************/
+
+/* Bridge in structure for RIWritePMREntry */
+typedef struct PVRSRV_BRIDGE_IN_RIWRITEPMRENTRY_TAG
+{
+ IMG_HANDLE hPMRHandle;
+ IMG_UINT32 ui32TextASize;
+ const IMG_CHAR * puiTextA;
+ IMG_SIZE_T uiLogicalSize;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RIWRITEPMRENTRY;
+
+
+/* Bridge out structure for RIWritePMREntry */
+typedef struct PVRSRV_BRIDGE_OUT_RIWRITEPMRENTRY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RIWRITEPMRENTRY;
+
+/*******************************************
+ RIWriteMEMDESCEntry
+ *******************************************/
+
+/* Bridge in structure for RIWriteMEMDESCEntry */
+typedef struct PVRSRV_BRIDGE_IN_RIWRITEMEMDESCENTRY_TAG
+{
+ IMG_HANDLE hPMRHandle;
+ IMG_UINT32 ui32TextBSize;
+ const IMG_CHAR * puiTextB;
+ IMG_SIZE_T uiOffset;
+ IMG_SIZE_T uiSize;
+ IMG_BOOL bIsImport;
+ IMG_BOOL bIsExportable;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RIWRITEMEMDESCENTRY;
+
+
+/* Bridge out structure for RIWriteMEMDESCEntry */
+typedef struct PVRSRV_BRIDGE_OUT_RIWRITEMEMDESCENTRY_TAG
+{
+ IMG_HANDLE hRIHandle;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RIWRITEMEMDESCENTRY;
+
+/*******************************************
+ RIUpdateMEMDESCAddr
+ *******************************************/
+
+/* Bridge in structure for RIUpdateMEMDESCAddr */
+typedef struct PVRSRV_BRIDGE_IN_RIUPDATEMEMDESCADDR_TAG
+{
+ IMG_HANDLE hRIHandle;
+ IMG_DEV_VIRTADDR sAddr;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RIUPDATEMEMDESCADDR;
+
+
+/* Bridge out structure for RIUpdateMEMDESCAddr */
+typedef struct PVRSRV_BRIDGE_OUT_RIUPDATEMEMDESCADDR_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RIUPDATEMEMDESCADDR;
+
+/*******************************************
+ RIDeleteMEMDESCEntry
+ *******************************************/
+
+/* Bridge in structure for RIDeleteMEMDESCEntry */
+typedef struct PVRSRV_BRIDGE_IN_RIDELETEMEMDESCENTRY_TAG
+{
+ IMG_HANDLE hRIHandle;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RIDELETEMEMDESCENTRY;
+
+
+/* Bridge out structure for RIDeleteMEMDESCEntry */
+typedef struct PVRSRV_BRIDGE_OUT_RIDELETEMEMDESCENTRY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RIDELETEMEMDESCENTRY;
+
+/*******************************************
+ RIDumpList
+ *******************************************/
+
+/* Bridge in structure for RIDumpList */
+typedef struct PVRSRV_BRIDGE_IN_RIDUMPLIST_TAG
+{
+ IMG_HANDLE hPMRHandle;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RIDUMPLIST;
+
+
+/* Bridge out structure for RIDumpList */
+typedef struct PVRSRV_BRIDGE_OUT_RIDUMPLIST_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RIDUMPLIST;
+
+/*******************************************
+ RIDumpAll
+ *******************************************/
+
+/* Bridge in structure for RIDumpAll */
+typedef struct PVRSRV_BRIDGE_IN_RIDUMPALL_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RIDUMPALL;
+
+
+/* Bridge out structure for RIDumpAll */
+typedef struct PVRSRV_BRIDGE_OUT_RIDUMPALL_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RIDUMPALL;
+
+/*******************************************
+ RIDumpProcess
+ *******************************************/
+
+/* Bridge in structure for RIDumpProcess */
+typedef struct PVRSRV_BRIDGE_IN_RIDUMPPROCESS_TAG
+{
+ IMG_PID ui32Pid;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RIDUMPPROCESS;
+
+
+/* Bridge out structure for RIDumpProcess */
+typedef struct PVRSRV_BRIDGE_OUT_RIDUMPPROCESS_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RIDUMPPROCESS;
+
+#endif /* COMMON_RI_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/ri_bridge/server_ri_bridge.c b/drivers/gpu/rogue/generated/ri_bridge/server_ri_bridge.c
new file mode 100644
index 000000000000..ebe2fb56c9ab
--- /dev/null
+++ b/drivers/gpu/rogue/generated/ri_bridge/server_ri_bridge.c
@@ -0,0 +1,504 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for ri
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for ri
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "ri_server.h"
+
+
+#include "common_ri_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+RIDeleteMEMDESCEntryResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeRIWritePMREntry(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RIWRITEPMRENTRY *psRIWritePMREntryIN,
+ PVRSRV_BRIDGE_OUT_RIWRITEPMRENTRY *psRIWritePMREntryOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRHandleInt = IMG_NULL;
+ IMG_HANDLE hPMRHandleInt2 = IMG_NULL;
+ IMG_CHAR *uiTextAInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RI_RIWRITEPMRENTRY);
+
+
+
+
+ if (psRIWritePMREntryIN->ui32TextASize != 0)
+ {
+ uiTextAInt = OSAllocMem(psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR));
+ if (!uiTextAInt)
+ {
+ psRIWritePMREntryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RIWritePMREntry_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRIWritePMREntryIN->puiTextA, psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR))
+ || (OSCopyFromUser(NULL, uiTextAInt, psRIWritePMREntryIN->puiTextA,
+ psRIWritePMREntryIN->ui32TextASize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+ {
+ psRIWritePMREntryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RIWritePMREntry_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRIWritePMREntryOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRHandleInt2,
+ psRIWritePMREntryIN->hPMRHandle,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psRIWritePMREntryOUT->eError != PVRSRV_OK)
+ {
+ goto RIWritePMREntry_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRIWritePMREntryOUT->eError = ResManFindPrivateDataByPtr(hPMRHandleInt2, (IMG_VOID **) &psPMRHandleInt);
+
+ if(psRIWritePMREntryOUT->eError != PVRSRV_OK)
+ {
+ goto RIWritePMREntry_exit;
+ }
+ }
+
+ psRIWritePMREntryOUT->eError =
+ RIWritePMREntryKM(
+ psPMRHandleInt,
+ psRIWritePMREntryIN->ui32TextASize,
+ uiTextAInt,
+ psRIWritePMREntryIN->uiLogicalSize);
+
+
+
+RIWritePMREntry_exit:
+ if (uiTextAInt)
+ OSFreeMem(uiTextAInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRIWriteMEMDESCEntry(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RIWRITEMEMDESCENTRY *psRIWriteMEMDESCEntryIN,
+ PVRSRV_BRIDGE_OUT_RIWRITEMEMDESCENTRY *psRIWriteMEMDESCEntryOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRHandleInt = IMG_NULL;
+ IMG_HANDLE hPMRHandleInt2 = IMG_NULL;
+ IMG_CHAR *uiTextBInt = IMG_NULL;
+ RI_HANDLE psRIHandleInt = IMG_NULL;
+ IMG_HANDLE hRIHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RI_RIWRITEMEMDESCENTRY);
+
+
+
+
+ if (psRIWriteMEMDESCEntryIN->ui32TextBSize != 0)
+ {
+ uiTextBInt = OSAllocMem(psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR));
+ if (!uiTextBInt)
+ {
+ psRIWriteMEMDESCEntryOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto RIWriteMEMDESCEntry_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psRIWriteMEMDESCEntryIN->puiTextB, psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR))
+ || (OSCopyFromUser(NULL, uiTextBInt, psRIWriteMEMDESCEntryIN->puiTextB,
+ psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+ {
+ psRIWriteMEMDESCEntryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto RIWriteMEMDESCEntry_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psRIWriteMEMDESCEntryOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRHandleInt2,
+ psRIWriteMEMDESCEntryIN->hPMRHandle,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psRIWriteMEMDESCEntryOUT->eError != PVRSRV_OK)
+ {
+ goto RIWriteMEMDESCEntry_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRIWriteMEMDESCEntryOUT->eError = ResManFindPrivateDataByPtr(hPMRHandleInt2, (IMG_VOID **) &psPMRHandleInt);
+
+ if(psRIWriteMEMDESCEntryOUT->eError != PVRSRV_OK)
+ {
+ goto RIWriteMEMDESCEntry_exit;
+ }
+ }
+
+ psRIWriteMEMDESCEntryOUT->eError =
+ RIWriteMEMDESCEntryKM(
+ psPMRHandleInt,
+ psRIWriteMEMDESCEntryIN->ui32TextBSize,
+ uiTextBInt,
+ psRIWriteMEMDESCEntryIN->uiOffset,
+ psRIWriteMEMDESCEntryIN->uiSize,
+ psRIWriteMEMDESCEntryIN->bIsImport,
+ psRIWriteMEMDESCEntryIN->bIsExportable,
+ &psRIHandleInt);
+ /* Exit early if bridged call fails */
+ if(psRIWriteMEMDESCEntryOUT->eError != PVRSRV_OK)
+ {
+ goto RIWriteMEMDESCEntry_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hRIHandleInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_RI_HANDLE,
+ psRIHandleInt,
+ (RESMAN_FREE_FN)&RIDeleteMEMDESCEntryKM);
+ if (hRIHandleInt2 == IMG_NULL)
+ {
+ psRIWriteMEMDESCEntryOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto RIWriteMEMDESCEntry_exit;
+ }
+ psRIWriteMEMDESCEntryOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psRIWriteMEMDESCEntryOUT->hRIHandle,
+ (IMG_HANDLE) hRIHandleInt2,
+ PVRSRV_HANDLE_TYPE_RI_HANDLE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psRIWriteMEMDESCEntryOUT->eError != PVRSRV_OK)
+ {
+ goto RIWriteMEMDESCEntry_exit;
+ }
+
+
+RIWriteMEMDESCEntry_exit:
+ if (psRIWriteMEMDESCEntryOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hRIHandleInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hRIHandleInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psRIHandleInt)
+ {
+ RIDeleteMEMDESCEntryKM(psRIHandleInt);
+ }
+ }
+
+ if (uiTextBInt)
+ OSFreeMem(uiTextBInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRIUpdateMEMDESCAddr(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RIUPDATEMEMDESCADDR *psRIUpdateMEMDESCAddrIN,
+ PVRSRV_BRIDGE_OUT_RIUPDATEMEMDESCADDR *psRIUpdateMEMDESCAddrOUT,
+ CONNECTION_DATA *psConnection)
+{
+ RI_HANDLE psRIHandleInt = IMG_NULL;
+ IMG_HANDLE hRIHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RI_RIUPDATEMEMDESCADDR);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRIUpdateMEMDESCAddrOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hRIHandleInt2,
+ psRIUpdateMEMDESCAddrIN->hRIHandle,
+ PVRSRV_HANDLE_TYPE_RI_HANDLE);
+ if(psRIUpdateMEMDESCAddrOUT->eError != PVRSRV_OK)
+ {
+ goto RIUpdateMEMDESCAddr_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRIUpdateMEMDESCAddrOUT->eError = ResManFindPrivateDataByPtr(hRIHandleInt2, (IMG_VOID **) &psRIHandleInt);
+
+ if(psRIUpdateMEMDESCAddrOUT->eError != PVRSRV_OK)
+ {
+ goto RIUpdateMEMDESCAddr_exit;
+ }
+ }
+
+ psRIUpdateMEMDESCAddrOUT->eError =
+ RIUpdateMEMDESCAddrKM(
+ psRIHandleInt,
+ psRIUpdateMEMDESCAddrIN->sAddr);
+
+
+
+RIUpdateMEMDESCAddr_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRIDeleteMEMDESCEntry(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RIDELETEMEMDESCENTRY *psRIDeleteMEMDESCEntryIN,
+ PVRSRV_BRIDGE_OUT_RIDELETEMEMDESCENTRY *psRIDeleteMEMDESCEntryOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hRIHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RI_RIDELETEMEMDESCENTRY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRIDeleteMEMDESCEntryOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hRIHandleInt2,
+ psRIDeleteMEMDESCEntryIN->hRIHandle,
+ PVRSRV_HANDLE_TYPE_RI_HANDLE);
+ if(psRIDeleteMEMDESCEntryOUT->eError != PVRSRV_OK)
+ {
+ goto RIDeleteMEMDESCEntry_exit;
+ }
+
+ }
+
+ psRIDeleteMEMDESCEntryOUT->eError = RIDeleteMEMDESCEntryResManProxy(hRIHandleInt2);
+ /* Exit early if bridged call fails */
+ if(psRIDeleteMEMDESCEntryOUT->eError != PVRSRV_OK)
+ {
+ goto RIDeleteMEMDESCEntry_exit;
+ }
+
+ psRIDeleteMEMDESCEntryOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psRIDeleteMEMDESCEntryIN->hRIHandle,
+ PVRSRV_HANDLE_TYPE_RI_HANDLE);
+
+
+RIDeleteMEMDESCEntry_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRIDumpList(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RIDUMPLIST *psRIDumpListIN,
+ PVRSRV_BRIDGE_OUT_RIDUMPLIST *psRIDumpListOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRHandleInt = IMG_NULL;
+ IMG_HANDLE hPMRHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RI_RIDUMPLIST);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRIDumpListOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRHandleInt2,
+ psRIDumpListIN->hPMRHandle,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psRIDumpListOUT->eError != PVRSRV_OK)
+ {
+ goto RIDumpList_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psRIDumpListOUT->eError = ResManFindPrivateDataByPtr(hPMRHandleInt2, (IMG_VOID **) &psPMRHandleInt);
+
+ if(psRIDumpListOUT->eError != PVRSRV_OK)
+ {
+ goto RIDumpList_exit;
+ }
+ }
+
+ psRIDumpListOUT->eError =
+ RIDumpListKM(
+ psPMRHandleInt);
+
+
+
+RIDumpList_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRIDumpAll(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RIDUMPALL *psRIDumpAllIN,
+ PVRSRV_BRIDGE_OUT_RIDUMPALL *psRIDumpAllOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RI_RIDUMPALL);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(psRIDumpAllIN);
+
+
+
+
+ psRIDumpAllOUT->eError =
+ RIDumpAllKM(
+ );
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRIDumpProcess(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RIDUMPPROCESS *psRIDumpProcessIN,
+ PVRSRV_BRIDGE_OUT_RIDUMPPROCESS *psRIDumpProcessOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RI_RIDUMPPROCESS);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ psRIDumpProcessOUT->eError =
+ RIDumpProcessKM(
+ psRIDumpProcessIN->ui32Pid);
+
+
+
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterRIFunctions(IMG_VOID);
+IMG_VOID UnregisterRIFunctions(IMG_VOID);
+
+/*
+ * Register all RI functions with services
+ */
+PVRSRV_ERROR RegisterRIFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RI_RIWRITEPMRENTRY, PVRSRVBridgeRIWritePMREntry);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RI_RIWRITEMEMDESCENTRY, PVRSRVBridgeRIWriteMEMDESCEntry);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RI_RIUPDATEMEMDESCADDR, PVRSRVBridgeRIUpdateMEMDESCAddr);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RI_RIDELETEMEMDESCENTRY, PVRSRVBridgeRIDeleteMEMDESCEntry);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RI_RIDUMPLIST, PVRSRVBridgeRIDumpList);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RI_RIDUMPALL, PVRSRVBridgeRIDumpAll);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RI_RIDUMPPROCESS, PVRSRVBridgeRIDumpProcess);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all ri functions with services
+ */
+IMG_VOID UnregisterRIFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/smm_bridge/common_smm_bridge.h b/drivers/gpu/rogue/generated/smm_bridge/common_smm_bridge.h
new file mode 100644
index 000000000000..9ac4881c83d4
--- /dev/null
+++ b/drivers/gpu/rogue/generated/smm_bridge/common_smm_bridge.h
@@ -0,0 +1,114 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for smm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for smm
+@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_SMM_BRIDGE_H
+#define COMMON_SMM_BRIDGE_H
+
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_SMM_CMD_FIRST (PVRSRV_BRIDGE_SMM_START)
+#define PVRSRV_BRIDGE_SMM_PMRSECUREEXPORTPMR PVRSRV_IOWR(PVRSRV_BRIDGE_SMM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SMM_PMRSECUREUNEXPORTPMR PVRSRV_IOWR(PVRSRV_BRIDGE_SMM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_SMM_PMRSECUREIMPORTPMR PVRSRV_IOWR(PVRSRV_BRIDGE_SMM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SMM_CMD_LAST (PVRSRV_BRIDGE_SMM_CMD_FIRST+2)
+
+
+/*******************************************
+ PMRSecureExportPMR
+ *******************************************/
+
+/* Bridge in structure for PMRSecureExportPMR */
+typedef struct PVRSRV_BRIDGE_IN_PMRSECUREEXPORTPMR_TAG
+{
+ IMG_HANDLE hPMR;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRSECUREEXPORTPMR;
+
+
+/* Bridge out structure for PMRSecureExportPMR */
+typedef struct PVRSRV_BRIDGE_OUT_PMRSECUREEXPORTPMR_TAG
+{
+ IMG_SECURE_TYPE Export;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRSECUREEXPORTPMR;
+
+/*******************************************
+ PMRSecureUnexportPMR
+ *******************************************/
+
+/* Bridge in structure for PMRSecureUnexportPMR */
+typedef struct PVRSRV_BRIDGE_IN_PMRSECUREUNEXPORTPMR_TAG
+{
+ IMG_HANDLE hPMR;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRSECUREUNEXPORTPMR;
+
+
+/* Bridge out structure for PMRSecureUnexportPMR */
+typedef struct PVRSRV_BRIDGE_OUT_PMRSECUREUNEXPORTPMR_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRSECUREUNEXPORTPMR;
+
+/*******************************************
+ PMRSecureImportPMR
+ *******************************************/
+
+/* Bridge in structure for PMRSecureImportPMR */
+typedef struct PVRSRV_BRIDGE_IN_PMRSECUREIMPORTPMR_TAG
+{
+ IMG_SECURE_TYPE Export;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_PMRSECUREIMPORTPMR;
+
+
+/* Bridge out structure for PMRSecureImportPMR */
+typedef struct PVRSRV_BRIDGE_OUT_PMRSECUREIMPORTPMR_TAG
+{
+ IMG_HANDLE hPMR;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_DEVMEM_ALIGN_T sAlign;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_PMRSECUREIMPORTPMR;
+
+#endif /* COMMON_SMM_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/smm_bridge/server_smm_bridge.c b/drivers/gpu/rogue/generated/smm_bridge/server_smm_bridge.c
new file mode 100644
index 000000000000..3c8d297bf49e
--- /dev/null
+++ b/drivers/gpu/rogue/generated/smm_bridge/server_smm_bridge.c
@@ -0,0 +1,328 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for smm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for smm
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "pmr.h"
+#include "secure_export.h"
+
+
+#include "common_smm_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+PMRSecureUnexportPMRResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgePMRSecureExportPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRSECUREEXPORTPMR *psPMRSecureExportPMRIN,
+ PVRSRV_BRIDGE_OUT_PMRSECUREEXPORTPMR *psPMRSecureExportPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+ PMR * psPMROutInt = IMG_NULL;
+ IMG_HANDLE hPMROutInt2 = IMG_NULL;
+ CONNECTION_DATA *psSecureConnection;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SMM_PMRSECUREEXPORTPMR);
+
+
+
+
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psPMRSecureExportPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRSecureExportPMRIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRSecureExportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRSecureExportPMR_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psPMRSecureExportPMROUT->eError = ResManFindPrivateDataByPtr(hPMRInt2, (IMG_VOID **) &psPMRInt);
+
+ if(psPMRSecureExportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRSecureExportPMR_exit;
+ }
+ }
+
+ psPMRSecureExportPMROUT->eError =
+ PMRSecureExportPMR(psConnection,
+ psPMRInt,
+ &psPMRSecureExportPMROUT->Export,
+ &psPMROutInt, &psSecureConnection);
+ /* Exit early if bridged call fails */
+ if(psPMRSecureExportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRSecureExportPMR_exit;
+ }
+ PMRUnlock();
+
+ /* Create a resman item and overwrite the handle with it */
+ hPMROutInt2 = ResManRegisterRes(psSecureConnection->hResManContext,
+ RESMAN_TYPE_PMR,
+ psPMROutInt,
+ (RESMAN_FREE_FN)&PMRSecureUnexportPMR);
+ if (hPMROutInt2 == IMG_NULL)
+ {
+ psPMRSecureExportPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PMRSecureExportPMR_exit;
+ }
+
+
+PMRSecureExportPMR_exit:
+ if (psPMRSecureExportPMROUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPMROutInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPMROutInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPMROutInt)
+ {
+ PMRSecureUnexportPMR(psPMROutInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRSecureUnexportPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRSECUREUNEXPORTPMR *psPMRSecureUnexportPMRIN,
+ PVRSRV_BRIDGE_OUT_PMRSECUREUNEXPORTPMR *psPMRSecureUnexportPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SMM_PMRSECUREUNEXPORTPMR);
+
+
+
+
+ PMRLock();
+ {
+ /* Look up the address from the handle */
+ psPMRSecureUnexportPMROUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRInt2,
+ psPMRSecureUnexportPMRIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if(psPMRSecureUnexportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRSecureUnexportPMR_exit;
+ }
+
+ }
+
+ psPMRSecureUnexportPMROUT->eError = PMRSecureUnexportPMRResManProxy(hPMRInt2);
+ /* Exit early if bridged call fails */
+ if(psPMRSecureUnexportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRSecureUnexportPMR_exit;
+ }
+ PMRUnlock();
+
+ psPMRSecureUnexportPMROUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psPMRSecureUnexportPMRIN->hPMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+
+
+PMRSecureUnexportPMR_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgePMRSecureImportPMR(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PMRSECUREIMPORTPMR *psPMRSecureImportPMRIN,
+ PVRSRV_BRIDGE_OUT_PMRSECUREIMPORTPMR *psPMRSecureImportPMROUT,
+ CONNECTION_DATA *psConnection)
+{
+ PMR * psPMRInt = IMG_NULL;
+ IMG_HANDLE hPMRInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SMM_PMRSECUREIMPORTPMR);
+
+
+
+
+
+ PMRLock();
+ psPMRSecureImportPMROUT->eError =
+ PMRSecureImportPMR(
+ psPMRSecureImportPMRIN->Export,
+ &psPMRInt,
+ &psPMRSecureImportPMROUT->uiSize,
+ &psPMRSecureImportPMROUT->sAlign);
+ /* Exit early if bridged call fails */
+ if(psPMRSecureImportPMROUT->eError != PVRSRV_OK)
+ {
+ PMRUnlock();
+ goto PMRSecureImportPMR_exit;
+ }
+ PMRUnlock();
+
+ /* Create a resman item and overwrite the handle with it */
+ hPMRInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_PMR,
+ psPMRInt,
+ (RESMAN_FREE_FN)&PMRUnrefPMR);
+ if (hPMRInt2 == IMG_NULL)
+ {
+ psPMRSecureImportPMROUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto PMRSecureImportPMR_exit;
+ }
+ psPMRSecureImportPMROUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psPMRSecureImportPMROUT->hPMR,
+ (IMG_HANDLE) hPMRInt2,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psPMRSecureImportPMROUT->eError != PVRSRV_OK)
+ {
+ goto PMRSecureImportPMR_exit;
+ }
+
+
+PMRSecureImportPMR_exit:
+ if (psPMRSecureImportPMROUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hPMRInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hPMRInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psPMRInt)
+ {
+ PMRUnrefPMR(psPMRInt);
+ }
+ }
+
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterSMMFunctions(IMG_VOID);
+IMG_VOID UnregisterSMMFunctions(IMG_VOID);
+
+/*
+ * Register all SMM functions with services
+ */
+PVRSRV_ERROR RegisterSMMFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SMM_PMRSECUREEXPORTPMR, PVRSRVBridgePMRSecureExportPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SMM_PMRSECUREUNEXPORTPMR, PVRSRVBridgePMRSecureUnexportPMR);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SMM_PMRSECUREIMPORTPMR, PVRSRVBridgePMRSecureImportPMR);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all smm functions with services
+ */
+IMG_VOID UnregisterSMMFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/srvcore_bridge/common_srvcore_bridge.h b/drivers/gpu/rogue/generated/srvcore_bridge/common_srvcore_bridge.h
new file mode 100644
index 000000000000..ec38f5410890
--- /dev/null
+++ b/drivers/gpu/rogue/generated/srvcore_bridge/common_srvcore_bridge.h
@@ -0,0 +1,385 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for srvcore
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for srvcore
+@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_SRVCORE_BRIDGE_H
+#define COMMON_SRVCORE_BRIDGE_H
+
+#include "pvrsrv_device_types.h"
+#include "cache_external.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_SRVCORE_CMD_FIRST (PVRSRV_BRIDGE_SRVCORE_START)
+#define PVRSRV_BRIDGE_SRVCORE_CONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SRVCORE_DISCONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_SRVCORE_ENUMERATEDEVICES PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SRVCORE_ACQUIREDEVICEDATA PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SRVCORE_RELEASEDEVICEDATA PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_SRVCORE_INITSRVDISCONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_SRVCORE_ACQUIREGLOBALEVENTOBJECT PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_SRVCORE_RELEASEGLOBALEVENTOBJECT PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTOPEN PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTWAIT PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTCLOSE PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_SRVCORE_DUMPDEBUGINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_SRVCORE_GETDEVCLOCKSPEED PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_SRVCORE_HWOPTIMEOUT PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_SRVCORE_KICKDEVICES PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_SRVCORE_RESETHWRLOGS PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_SRVCORE_SOFTRESET PVRSRV_IOWR(PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_SRVCORE_CMD_LAST (PVRSRV_BRIDGE_SRVCORE_CMD_FIRST+16)
+
+
+/*******************************************
+ Connect
+ *******************************************/
+
+/* Bridge in structure for Connect */
+typedef struct PVRSRV_BRIDGE_IN_CONNECT_TAG
+{
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32ClientBuildOptions;
+ IMG_UINT32 ui32ClientDDKVersion;
+ IMG_UINT32 ui32ClientDDKBuild;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_CONNECT;
+
+
+/* Bridge out structure for Connect */
+typedef struct PVRSRV_BRIDGE_OUT_CONNECT_TAG
+{
+ IMG_UINT8 ui8KernelArch;
+ IMG_UINT32 ui32Log2PageSize;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_CONNECT;
+
+/*******************************************
+ Disconnect
+ *******************************************/
+
+/* Bridge in structure for Disconnect */
+typedef struct PVRSRV_BRIDGE_IN_DISCONNECT_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DISCONNECT;
+
+
+/* Bridge out structure for Disconnect */
+typedef struct PVRSRV_BRIDGE_OUT_DISCONNECT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DISCONNECT;
+
+/*******************************************
+ EnumerateDevices
+ *******************************************/
+
+/* Bridge in structure for EnumerateDevices */
+typedef struct PVRSRV_BRIDGE_IN_ENUMERATEDEVICES_TAG
+{
+ /* Output pointer peDeviceType is also an implied input */
+ PVRSRV_DEVICE_TYPE * peDeviceType;
+ /* Output pointer peDeviceClass is also an implied input */
+ PVRSRV_DEVICE_CLASS * peDeviceClass;
+ /* Output pointer pui32DeviceIndex is also an implied input */
+ IMG_UINT32 * pui32DeviceIndex;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_ENUMERATEDEVICES;
+
+
+/* Bridge out structure for EnumerateDevices */
+typedef struct PVRSRV_BRIDGE_OUT_ENUMERATEDEVICES_TAG
+{
+ IMG_UINT32 ui32NumDevices;
+ PVRSRV_DEVICE_TYPE * peDeviceType;
+ PVRSRV_DEVICE_CLASS * peDeviceClass;
+ IMG_UINT32 * pui32DeviceIndex;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_ENUMERATEDEVICES;
+
+/*******************************************
+ AcquireDeviceData
+ *******************************************/
+
+/* Bridge in structure for AcquireDeviceData */
+typedef struct PVRSRV_BRIDGE_IN_ACQUIREDEVICEDATA_TAG
+{
+ IMG_UINT32 ui32DevIndex;
+ PVRSRV_DEVICE_TYPE eDeviceType;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_ACQUIREDEVICEDATA;
+
+
+/* Bridge out structure for AcquireDeviceData */
+typedef struct PVRSRV_BRIDGE_OUT_ACQUIREDEVICEDATA_TAG
+{
+ IMG_HANDLE hDevCookie;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_ACQUIREDEVICEDATA;
+
+/*******************************************
+ ReleaseDeviceData
+ *******************************************/
+
+/* Bridge in structure for ReleaseDeviceData */
+typedef struct PVRSRV_BRIDGE_IN_RELEASEDEVICEDATA_TAG
+{
+ IMG_HANDLE hDevCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RELEASEDEVICEDATA;
+
+
+/* Bridge out structure for ReleaseDeviceData */
+typedef struct PVRSRV_BRIDGE_OUT_RELEASEDEVICEDATA_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RELEASEDEVICEDATA;
+
+/*******************************************
+ InitSrvDisconnect
+ *******************************************/
+
+/* Bridge in structure for InitSrvDisconnect */
+typedef struct PVRSRV_BRIDGE_IN_INITSRVDISCONNECT_TAG
+{
+ IMG_BOOL bInitSuccesful;
+ IMG_UINT32 ui32ClientBuildOptions;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_INITSRVDISCONNECT;
+
+
+/* Bridge out structure for InitSrvDisconnect */
+typedef struct PVRSRV_BRIDGE_OUT_INITSRVDISCONNECT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_INITSRVDISCONNECT;
+
+/*******************************************
+ AcquireGlobalEventObject
+ *******************************************/
+
+/* Bridge in structure for AcquireGlobalEventObject */
+typedef struct PVRSRV_BRIDGE_IN_ACQUIREGLOBALEVENTOBJECT_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_ACQUIREGLOBALEVENTOBJECT;
+
+
+/* Bridge out structure for AcquireGlobalEventObject */
+typedef struct PVRSRV_BRIDGE_OUT_ACQUIREGLOBALEVENTOBJECT_TAG
+{
+ IMG_HANDLE hGlobalEventObject;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_ACQUIREGLOBALEVENTOBJECT;
+
+/*******************************************
+ ReleaseGlobalEventObject
+ *******************************************/
+
+/* Bridge in structure for ReleaseGlobalEventObject */
+typedef struct PVRSRV_BRIDGE_IN_RELEASEGLOBALEVENTOBJECT_TAG
+{
+ IMG_HANDLE hGlobalEventObject;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RELEASEGLOBALEVENTOBJECT;
+
+
+/* Bridge out structure for ReleaseGlobalEventObject */
+typedef struct PVRSRV_BRIDGE_OUT_RELEASEGLOBALEVENTOBJECT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RELEASEGLOBALEVENTOBJECT;
+
+/*******************************************
+ EventObjectOpen
+ *******************************************/
+
+/* Bridge in structure for EventObjectOpen */
+typedef struct PVRSRV_BRIDGE_IN_EVENTOBJECTOPEN_TAG
+{
+ IMG_HANDLE hEventObject;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_EVENTOBJECTOPEN;
+
+
+/* Bridge out structure for EventObjectOpen */
+typedef struct PVRSRV_BRIDGE_OUT_EVENTOBJECTOPEN_TAG
+{
+ IMG_HANDLE hOSEvent;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_EVENTOBJECTOPEN;
+
+/*******************************************
+ EventObjectWait
+ *******************************************/
+
+/* Bridge in structure for EventObjectWait */
+typedef struct PVRSRV_BRIDGE_IN_EVENTOBJECTWAIT_TAG
+{
+ IMG_HANDLE hOSEventKM;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_EVENTOBJECTWAIT;
+
+
+/* Bridge out structure for EventObjectWait */
+typedef struct PVRSRV_BRIDGE_OUT_EVENTOBJECTWAIT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_EVENTOBJECTWAIT;
+
+/*******************************************
+ EventObjectClose
+ *******************************************/
+
+/* Bridge in structure for EventObjectClose */
+typedef struct PVRSRV_BRIDGE_IN_EVENTOBJECTCLOSE_TAG
+{
+ IMG_HANDLE hOSEventKM;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_EVENTOBJECTCLOSE;
+
+
+/* Bridge out structure for EventObjectClose */
+typedef struct PVRSRV_BRIDGE_OUT_EVENTOBJECTCLOSE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_EVENTOBJECTCLOSE;
+
+/*******************************************
+ DumpDebugInfo
+ *******************************************/
+
+/* Bridge in structure for DumpDebugInfo */
+typedef struct PVRSRV_BRIDGE_IN_DUMPDEBUGINFO_TAG
+{
+ IMG_UINT32 ui32ui32VerbLevel;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_DUMPDEBUGINFO;
+
+
+/* Bridge out structure for DumpDebugInfo */
+typedef struct PVRSRV_BRIDGE_OUT_DUMPDEBUGINFO_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_DUMPDEBUGINFO;
+
+/*******************************************
+ GetDevClockSpeed
+ *******************************************/
+
+/* Bridge in structure for GetDevClockSpeed */
+typedef struct PVRSRV_BRIDGE_IN_GETDEVCLOCKSPEED_TAG
+{
+ IMG_HANDLE hDevNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_GETDEVCLOCKSPEED;
+
+
+/* Bridge out structure for GetDevClockSpeed */
+typedef struct PVRSRV_BRIDGE_OUT_GETDEVCLOCKSPEED_TAG
+{
+ IMG_UINT32 ui32ui32RGXClockSpeed;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_GETDEVCLOCKSPEED;
+
+/*******************************************
+ HWOpTimeout
+ *******************************************/
+
+/* Bridge in structure for HWOpTimeout */
+typedef struct PVRSRV_BRIDGE_IN_HWOPTIMEOUT_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_HWOPTIMEOUT;
+
+
+/* Bridge out structure for HWOpTimeout */
+typedef struct PVRSRV_BRIDGE_OUT_HWOPTIMEOUT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_HWOPTIMEOUT;
+
+/*******************************************
+ KickDevices
+ *******************************************/
+
+/* Bridge in structure for KickDevices */
+typedef struct PVRSRV_BRIDGE_IN_KICKDEVICES_TAG
+{
+ IMG_UINT32 ui32EmptyStructPlaceholder;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_KICKDEVICES;
+
+
+/* Bridge out structure for KickDevices */
+typedef struct PVRSRV_BRIDGE_OUT_KICKDEVICES_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_KICKDEVICES;
+
+/*******************************************
+ ResetHWRLogs
+ *******************************************/
+
+/* Bridge in structure for ResetHWRLogs */
+typedef struct PVRSRV_BRIDGE_IN_RESETHWRLOGS_TAG
+{
+ IMG_HANDLE hDevNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RESETHWRLOGS;
+
+
+/* Bridge out structure for ResetHWRLogs */
+typedef struct PVRSRV_BRIDGE_OUT_RESETHWRLOGS_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RESETHWRLOGS;
+
+/*******************************************
+ SoftReset
+ *******************************************/
+
+/* Bridge in structure for SoftReset */
+typedef struct PVRSRV_BRIDGE_IN_SOFTRESET_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT64 ui64ResetValue;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SOFTRESET;
+
+
+/* Bridge out structure for SoftReset */
+typedef struct PVRSRV_BRIDGE_OUT_SOFTRESET_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SOFTRESET;
+
+#endif /* COMMON_SRVCORE_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/srvcore_bridge/server_srvcore_bridge.c b/drivers/gpu/rogue/generated/srvcore_bridge/server_srvcore_bridge.c
new file mode 100644
index 000000000000..f78c979518ff
--- /dev/null
+++ b/drivers/gpu/rogue/generated/srvcore_bridge/server_srvcore_bridge.c
@@ -0,0 +1,909 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for srvcore
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for srvcore
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "srvcore.h"
+#include "pvrsrv.h"
+
+
+#include "common_srvcore_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+ReleaseGlobalEventObjectResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+EventObjectCloseResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeConnect(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CONNECT *psConnectIN,
+ PVRSRV_BRIDGE_OUT_CONNECT *psConnectOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_CONNECT);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ psConnectOUT->eError =
+ PVRSRVConnectKM(psConnection,
+ psConnectIN->ui32Flags,
+ psConnectIN->ui32ClientBuildOptions,
+ psConnectIN->ui32ClientDDKVersion,
+ psConnectIN->ui32ClientDDKBuild,
+ &psConnectOUT->ui8KernelArch,
+ &psConnectOUT->ui32Log2PageSize);
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDisconnect(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DISCONNECT *psDisconnectIN,
+ PVRSRV_BRIDGE_OUT_DISCONNECT *psDisconnectOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_DISCONNECT);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(psDisconnectIN);
+
+
+
+
+ psDisconnectOUT->eError =
+ PVRSRVDisconnectKM(
+ );
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeEnumerateDevices(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUMERATEDEVICES *psEnumerateDevicesIN,
+ PVRSRV_BRIDGE_OUT_ENUMERATEDEVICES *psEnumerateDevicesOUT,
+ CONNECTION_DATA *psConnection)
+{
+ PVRSRV_DEVICE_TYPE *peDeviceTypeInt = IMG_NULL;
+ PVRSRV_DEVICE_CLASS *peDeviceClassInt = IMG_NULL;
+ IMG_UINT32 *pui32DeviceIndexInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_ENUMERATEDEVICES);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(psEnumerateDevicesIN);
+
+ psEnumerateDevicesOUT->peDeviceType = psEnumerateDevicesIN->peDeviceType;
+ psEnumerateDevicesOUT->peDeviceClass = psEnumerateDevicesIN->peDeviceClass;
+ psEnumerateDevicesOUT->pui32DeviceIndex = psEnumerateDevicesIN->pui32DeviceIndex;
+
+
+
+ {
+ peDeviceTypeInt = OSAllocMem(PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_TYPE));
+ if (!peDeviceTypeInt)
+ {
+ psEnumerateDevicesOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto EnumerateDevices_exit;
+ }
+ }
+
+
+ {
+ peDeviceClassInt = OSAllocMem(PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_CLASS));
+ if (!peDeviceClassInt)
+ {
+ psEnumerateDevicesOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto EnumerateDevices_exit;
+ }
+ }
+
+
+ {
+ pui32DeviceIndexInt = OSAllocMem(PVRSRV_MAX_DEVICES * sizeof(IMG_UINT32));
+ if (!pui32DeviceIndexInt)
+ {
+ psEnumerateDevicesOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto EnumerateDevices_exit;
+ }
+ }
+
+
+ psEnumerateDevicesOUT->eError =
+ PVRSRVEnumerateDevicesKM(
+ &psEnumerateDevicesOUT->ui32NumDevices,
+ peDeviceTypeInt,
+ peDeviceClassInt,
+ pui32DeviceIndexInt);
+
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psEnumerateDevicesOUT->peDeviceType, (PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_TYPE)))
+ || (OSCopyToUser(NULL, psEnumerateDevicesOUT->peDeviceType, peDeviceTypeInt,
+ (PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_TYPE))) != PVRSRV_OK) )
+ {
+ psEnumerateDevicesOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto EnumerateDevices_exit;
+ }
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psEnumerateDevicesOUT->peDeviceClass, (PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_CLASS)))
+ || (OSCopyToUser(NULL, psEnumerateDevicesOUT->peDeviceClass, peDeviceClassInt,
+ (PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_CLASS))) != PVRSRV_OK) )
+ {
+ psEnumerateDevicesOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto EnumerateDevices_exit;
+ }
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psEnumerateDevicesOUT->pui32DeviceIndex, (PVRSRV_MAX_DEVICES * sizeof(IMG_UINT32)))
+ || (OSCopyToUser(NULL, psEnumerateDevicesOUT->pui32DeviceIndex, pui32DeviceIndexInt,
+ (PVRSRV_MAX_DEVICES * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psEnumerateDevicesOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto EnumerateDevices_exit;
+ }
+
+
+EnumerateDevices_exit:
+ if (peDeviceTypeInt)
+ OSFreeMem(peDeviceTypeInt);
+ if (peDeviceClassInt)
+ OSFreeMem(peDeviceClassInt);
+ if (pui32DeviceIndexInt)
+ OSFreeMem(pui32DeviceIndexInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeAcquireDeviceData(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ACQUIREDEVICEDATA *psAcquireDeviceDataIN,
+ PVRSRV_BRIDGE_OUT_ACQUIREDEVICEDATA *psAcquireDeviceDataOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevCookieInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_ACQUIREDEVICEDATA);
+
+
+
+
+
+ psAcquireDeviceDataOUT->eError =
+ PVRSRVAcquireDeviceDataKM(
+ psAcquireDeviceDataIN->ui32DevIndex,
+ psAcquireDeviceDataIN->eDeviceType,
+ &hDevCookieInt);
+ /* Exit early if bridged call fails */
+ if(psAcquireDeviceDataOUT->eError != PVRSRV_OK)
+ {
+ goto AcquireDeviceData_exit;
+ }
+
+ psAcquireDeviceDataOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psAcquireDeviceDataOUT->hDevCookie,
+ (IMG_HANDLE) hDevCookieInt,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED
+ );
+ if (psAcquireDeviceDataOUT->eError != PVRSRV_OK)
+ {
+ goto AcquireDeviceData_exit;
+ }
+
+
+AcquireDeviceData_exit:
+ if (psAcquireDeviceDataOUT->eError != PVRSRV_OK)
+ {
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeReleaseDeviceData(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASEDEVICEDATA *psReleaseDeviceDataIN,
+ PVRSRV_BRIDGE_OUT_RELEASEDEVICEDATA *psReleaseDeviceDataOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevCookieInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_RELEASEDEVICEDATA);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psReleaseDeviceDataOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevCookieInt,
+ psReleaseDeviceDataIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psReleaseDeviceDataOUT->eError != PVRSRV_OK)
+ {
+ goto ReleaseDeviceData_exit;
+ }
+
+ }
+
+ psReleaseDeviceDataOUT->eError =
+ PVRSRVReleaseDeviceDataKM(
+ hDevCookieInt);
+ /* Exit early if bridged call fails */
+ if(psReleaseDeviceDataOUT->eError != PVRSRV_OK)
+ {
+ goto ReleaseDeviceData_exit;
+ }
+
+ psReleaseDeviceDataOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psReleaseDeviceDataIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+
+ReleaseDeviceData_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeInitSrvDisconnect(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_INITSRVDISCONNECT *psInitSrvDisconnectIN,
+ PVRSRV_BRIDGE_OUT_INITSRVDISCONNECT *psInitSrvDisconnectOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_INITSRVDISCONNECT);
+
+
+
+
+
+ psInitSrvDisconnectOUT->eError =
+ PVRSRVInitSrvDisconnectKM(psConnection,
+ psInitSrvDisconnectIN->bInitSuccesful,
+ psInitSrvDisconnectIN->ui32ClientBuildOptions);
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeAcquireGlobalEventObject(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ACQUIREGLOBALEVENTOBJECT *psAcquireGlobalEventObjectIN,
+ PVRSRV_BRIDGE_OUT_ACQUIREGLOBALEVENTOBJECT *psAcquireGlobalEventObjectOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hGlobalEventObjectInt = IMG_NULL;
+ IMG_HANDLE hGlobalEventObjectInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_ACQUIREGLOBALEVENTOBJECT);
+
+ PVR_UNREFERENCED_PARAMETER(psAcquireGlobalEventObjectIN);
+
+
+
+
+ psAcquireGlobalEventObjectOUT->eError =
+ AcquireGlobalEventObjectServer(
+ &hGlobalEventObjectInt);
+ /* Exit early if bridged call fails */
+ if(psAcquireGlobalEventObjectOUT->eError != PVRSRV_OK)
+ {
+ goto AcquireGlobalEventObject_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hGlobalEventObjectInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_SHARED_EVENT_OBJECT,
+ hGlobalEventObjectInt,
+ (RESMAN_FREE_FN)&ReleaseGlobalEventObjectServer);
+ if (hGlobalEventObjectInt2 == IMG_NULL)
+ {
+ psAcquireGlobalEventObjectOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto AcquireGlobalEventObject_exit;
+ }
+ psAcquireGlobalEventObjectOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psAcquireGlobalEventObjectOUT->hGlobalEventObject,
+ (IMG_HANDLE) hGlobalEventObjectInt2,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED
+ );
+ if (psAcquireGlobalEventObjectOUT->eError != PVRSRV_OK)
+ {
+ goto AcquireGlobalEventObject_exit;
+ }
+
+
+AcquireGlobalEventObject_exit:
+ if (psAcquireGlobalEventObjectOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hGlobalEventObjectInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hGlobalEventObjectInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (hGlobalEventObjectInt)
+ {
+ ReleaseGlobalEventObjectServer(hGlobalEventObjectInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeReleaseGlobalEventObject(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASEGLOBALEVENTOBJECT *psReleaseGlobalEventObjectIN,
+ PVRSRV_BRIDGE_OUT_RELEASEGLOBALEVENTOBJECT *psReleaseGlobalEventObjectOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hGlobalEventObjectInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_RELEASEGLOBALEVENTOBJECT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psReleaseGlobalEventObjectOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hGlobalEventObjectInt2,
+ psReleaseGlobalEventObjectIN->hGlobalEventObject,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+ if(psReleaseGlobalEventObjectOUT->eError != PVRSRV_OK)
+ {
+ goto ReleaseGlobalEventObject_exit;
+ }
+
+ }
+
+ psReleaseGlobalEventObjectOUT->eError = ReleaseGlobalEventObjectResManProxy(hGlobalEventObjectInt2);
+ /* Exit early if bridged call fails */
+ if(psReleaseGlobalEventObjectOUT->eError != PVRSRV_OK)
+ {
+ goto ReleaseGlobalEventObject_exit;
+ }
+
+ psReleaseGlobalEventObjectOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psReleaseGlobalEventObjectIN->hGlobalEventObject,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+
+
+ReleaseGlobalEventObject_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeEventObjectOpen(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENTOBJECTOPEN *psEventObjectOpenIN,
+ PVRSRV_BRIDGE_OUT_EVENTOBJECTOPEN *psEventObjectOpenOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hEventObjectInt = IMG_NULL;
+ IMG_HANDLE hEventObjectInt2 = IMG_NULL;
+ IMG_HANDLE hOSEventInt = IMG_NULL;
+ IMG_HANDLE hOSEventInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTOPEN);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psEventObjectOpenOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hEventObjectInt2,
+ psEventObjectOpenIN->hEventObject,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+ if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ goto EventObjectOpen_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psEventObjectOpenOUT->eError = ResManFindPrivateDataByPtr(hEventObjectInt2, (IMG_VOID **) &hEventObjectInt);
+
+ if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ goto EventObjectOpen_exit;
+ }
+ }
+
+ psEventObjectOpenOUT->eError =
+ OSEventObjectOpen(
+ hEventObjectInt,
+ &hOSEventInt);
+ /* Exit early if bridged call fails */
+ if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ goto EventObjectOpen_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hOSEventInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_EVENT_OBJECT,
+ hOSEventInt,
+ (RESMAN_FREE_FN)&OSEventObjectClose);
+ if (hOSEventInt2 == IMG_NULL)
+ {
+ psEventObjectOpenOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto EventObjectOpen_exit;
+ }
+ psEventObjectOpenOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psEventObjectOpenOUT->hOSEvent,
+ (IMG_HANDLE) hOSEventInt2,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+ );
+ if (psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ goto EventObjectOpen_exit;
+ }
+
+
+EventObjectOpen_exit:
+ if (psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hOSEventInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hOSEventInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (hOSEventInt)
+ {
+ OSEventObjectClose(hOSEventInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeEventObjectWait(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENTOBJECTWAIT *psEventObjectWaitIN,
+ PVRSRV_BRIDGE_OUT_EVENTOBJECTWAIT *psEventObjectWaitOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hOSEventKMInt = IMG_NULL;
+ IMG_HANDLE hOSEventKMInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTWAIT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psEventObjectWaitOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hOSEventKMInt2,
+ psEventObjectWaitIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+ if(psEventObjectWaitOUT->eError != PVRSRV_OK)
+ {
+ goto EventObjectWait_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psEventObjectWaitOUT->eError = ResManFindPrivateDataByPtr(hOSEventKMInt2, (IMG_VOID **) &hOSEventKMInt);
+
+ if(psEventObjectWaitOUT->eError != PVRSRV_OK)
+ {
+ goto EventObjectWait_exit;
+ }
+ }
+
+ psEventObjectWaitOUT->eError =
+ OSEventObjectWait(
+ hOSEventKMInt);
+
+
+
+EventObjectWait_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeEventObjectClose(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENTOBJECTCLOSE *psEventObjectCloseIN,
+ PVRSRV_BRIDGE_OUT_EVENTOBJECTCLOSE *psEventObjectCloseOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hOSEventKMInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTCLOSE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psEventObjectCloseOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hOSEventKMInt2,
+ psEventObjectCloseIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+ if(psEventObjectCloseOUT->eError != PVRSRV_OK)
+ {
+ goto EventObjectClose_exit;
+ }
+
+ }
+
+ psEventObjectCloseOUT->eError = EventObjectCloseResManProxy(hOSEventKMInt2);
+ /* Exit early if bridged call fails */
+ if(psEventObjectCloseOUT->eError != PVRSRV_OK)
+ {
+ goto EventObjectClose_exit;
+ }
+
+ psEventObjectCloseOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psEventObjectCloseIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+
+EventObjectClose_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeDumpDebugInfo(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DUMPDEBUGINFO *psDumpDebugInfoIN,
+ PVRSRV_BRIDGE_OUT_DUMPDEBUGINFO *psDumpDebugInfoOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_DUMPDEBUGINFO);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ psDumpDebugInfoOUT->eError =
+ PVRSRVDumpDebugInfoKM(
+ psDumpDebugInfoIN->ui32ui32VerbLevel);
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeGetDevClockSpeed(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETDEVCLOCKSPEED *psGetDevClockSpeedIN,
+ PVRSRV_BRIDGE_OUT_GETDEVCLOCKSPEED *psGetDevClockSpeedOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_GETDEVCLOCKSPEED);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psGetDevClockSpeedOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psGetDevClockSpeedIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psGetDevClockSpeedOUT->eError != PVRSRV_OK)
+ {
+ goto GetDevClockSpeed_exit;
+ }
+
+ }
+
+ psGetDevClockSpeedOUT->eError =
+ PVRSRVGetDevClockSpeedKM(
+ hDevNodeInt,
+ &psGetDevClockSpeedOUT->ui32ui32RGXClockSpeed);
+
+
+
+GetDevClockSpeed_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeHWOpTimeout(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_HWOPTIMEOUT *psHWOpTimeoutIN,
+ PVRSRV_BRIDGE_OUT_HWOPTIMEOUT *psHWOpTimeoutOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_HWOPTIMEOUT);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(psHWOpTimeoutIN);
+
+
+
+
+ psHWOpTimeoutOUT->eError =
+ PVRSRVHWOpTimeoutKM(
+ );
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeKickDevices(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_KICKDEVICES *psKickDevicesIN,
+ PVRSRV_BRIDGE_OUT_KICKDEVICES *psKickDevicesOUT,
+ CONNECTION_DATA *psConnection)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_KICKDEVICES);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(psKickDevicesIN);
+
+
+
+
+ psKickDevicesOUT->eError =
+ PVRSRVKickDevicesKM(
+ );
+
+
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeResetHWRLogs(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RESETHWRLOGS *psResetHWRLogsIN,
+ PVRSRV_BRIDGE_OUT_RESETHWRLOGS *psResetHWRLogsOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_RESETHWRLOGS);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psResetHWRLogsOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psResetHWRLogsIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psResetHWRLogsOUT->eError != PVRSRV_OK)
+ {
+ goto ResetHWRLogs_exit;
+ }
+
+ }
+
+ psResetHWRLogsOUT->eError =
+ PVRSRVResetHWRLogsKM(
+ hDevNodeInt);
+
+
+
+ResetHWRLogs_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSoftReset(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SOFTRESET *psSoftResetIN,
+ PVRSRV_BRIDGE_OUT_SOFTRESET *psSoftResetOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_SOFTRESET);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSoftResetOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psSoftResetIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSoftResetOUT->eError != PVRSRV_OK)
+ {
+ goto SoftReset_exit;
+ }
+
+ }
+
+ psSoftResetOUT->eError =
+ PVRSRVSoftResetKM(
+ hDevNodeInt,
+ psSoftResetIN->ui64ResetValue);
+
+
+
+SoftReset_exit:
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterSRVCOREFunctions(IMG_VOID);
+IMG_VOID UnregisterSRVCOREFunctions(IMG_VOID);
+
+/*
+ * Register all SRVCORE functions with services
+ */
+PVRSRV_ERROR RegisterSRVCOREFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_CONNECT, PVRSRVBridgeConnect);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_DISCONNECT, PVRSRVBridgeDisconnect);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_ENUMERATEDEVICES, PVRSRVBridgeEnumerateDevices);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_ACQUIREDEVICEDATA, PVRSRVBridgeAcquireDeviceData);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_RELEASEDEVICEDATA, PVRSRVBridgeReleaseDeviceData);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_INITSRVDISCONNECT, PVRSRVBridgeInitSrvDisconnect);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_ACQUIREGLOBALEVENTOBJECT, PVRSRVBridgeAcquireGlobalEventObject);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_RELEASEGLOBALEVENTOBJECT, PVRSRVBridgeReleaseGlobalEventObject);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTOPEN, PVRSRVBridgeEventObjectOpen);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTWAIT, PVRSRVBridgeEventObjectWait);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_EVENTOBJECTCLOSE, PVRSRVBridgeEventObjectClose);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_DUMPDEBUGINFO, PVRSRVBridgeDumpDebugInfo);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_GETDEVCLOCKSPEED, PVRSRVBridgeGetDevClockSpeed);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_HWOPTIMEOUT, PVRSRVBridgeHWOpTimeout);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_KICKDEVICES, PVRSRVBridgeKickDevices);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_RESETHWRLOGS, PVRSRVBridgeResetHWRLogs);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE_SOFTRESET, PVRSRVBridgeSoftReset);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all srvcore functions with services
+ */
+IMG_VOID UnregisterSRVCOREFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/sync_bridge/common_sync_bridge.h b/drivers/gpu/rogue/generated/sync_bridge/common_sync_bridge.h
new file mode 100644
index 000000000000..5210ad843d7c
--- /dev/null
+++ b/drivers/gpu/rogue/generated/sync_bridge/common_sync_bridge.h
@@ -0,0 +1,480 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for sync
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for sync
+@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_SYNC_BRIDGE_H
+#define COMMON_SYNC_BRIDGE_H
+
+#include "pdump.h"
+#include "pdumpdefs.h"
+#include "devicemem_typedefs.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_SYNC_CMD_FIRST (PVRSRV_BRIDGE_SYNC_START)
+#define PVRSRV_BRIDGE_SYNC_ALLOCSYNCPRIMITIVEBLOCK PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SYNC_FREESYNCPRIMITIVEBLOCK PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMSET PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SYNC_SERVERSYNCPRIMSET PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SYNC_SYNCRECORDREMOVEBYHANDLE PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_SYNC_SYNCRECORDADD PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_SYNC_SERVERSYNCALLOC PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_SYNC_SERVERSYNCFREE PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SYNC_SERVERSYNCQUEUEHWOP PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_SYNC_SERVERSYNCGETSTATUS PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCREATE PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPTAKE PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPREADY PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCOMPLETE PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPDESTROY PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMP PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPVALUE PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPPOL PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMOPPDUMPPOL PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPCBP PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_SYNC_CMD_LAST (PVRSRV_BRIDGE_SYNC_CMD_FIRST+19)
+
+
+/*******************************************
+ AllocSyncPrimitiveBlock
+ *******************************************/
+
+/* Bridge in structure for AllocSyncPrimitiveBlock */
+typedef struct PVRSRV_BRIDGE_IN_ALLOCSYNCPRIMITIVEBLOCK_TAG
+{
+ IMG_HANDLE hDevNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_ALLOCSYNCPRIMITIVEBLOCK;
+
+
+/* Bridge out structure for AllocSyncPrimitiveBlock */
+typedef struct PVRSRV_BRIDGE_OUT_ALLOCSYNCPRIMITIVEBLOCK_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32SyncPrimVAddr;
+ IMG_UINT32 ui32SyncPrimBlockSize;
+ DEVMEM_SERVER_EXPORTCOOKIE hExportCookie;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_ALLOCSYNCPRIMITIVEBLOCK;
+
+/*******************************************
+ FreeSyncPrimitiveBlock
+ *******************************************/
+
+/* Bridge in structure for FreeSyncPrimitiveBlock */
+typedef struct PVRSRV_BRIDGE_IN_FREESYNCPRIMITIVEBLOCK_TAG
+{
+ IMG_HANDLE hSyncHandle;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_FREESYNCPRIMITIVEBLOCK;
+
+
+/* Bridge out structure for FreeSyncPrimitiveBlock */
+typedef struct PVRSRV_BRIDGE_OUT_FREESYNCPRIMITIVEBLOCK_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_FREESYNCPRIMITIVEBLOCK;
+
+/*******************************************
+ SyncPrimSet
+ *******************************************/
+
+/* Bridge in structure for SyncPrimSet */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMSET_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32Index;
+ IMG_UINT32 ui32Value;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMSET;
+
+
+/* Bridge out structure for SyncPrimSet */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMSET_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMSET;
+
+/*******************************************
+ ServerSyncPrimSet
+ *******************************************/
+
+/* Bridge in structure for ServerSyncPrimSet */
+typedef struct PVRSRV_BRIDGE_IN_SERVERSYNCPRIMSET_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32Value;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SERVERSYNCPRIMSET;
+
+
+/* Bridge out structure for ServerSyncPrimSet */
+typedef struct PVRSRV_BRIDGE_OUT_SERVERSYNCPRIMSET_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SERVERSYNCPRIMSET;
+
+/*******************************************
+ SyncRecordRemoveByHandle
+ *******************************************/
+
+/* Bridge in structure for SyncRecordRemoveByHandle */
+typedef struct PVRSRV_BRIDGE_IN_SYNCRECORDREMOVEBYHANDLE_TAG
+{
+ IMG_HANDLE hhRecord;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCRECORDREMOVEBYHANDLE;
+
+
+/* Bridge out structure for SyncRecordRemoveByHandle */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCRECORDREMOVEBYHANDLE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCRECORDREMOVEBYHANDLE;
+
+/*******************************************
+ SyncRecordAdd
+ *******************************************/
+
+/* Bridge in structure for SyncRecordAdd */
+typedef struct PVRSRV_BRIDGE_IN_SYNCRECORDADD_TAG
+{
+ IMG_HANDLE hhServerSyncPrimBlock;
+ IMG_UINT32 ui32ui32FwBlockAddr;
+ IMG_UINT32 ui32ui32SyncOffset;
+ IMG_BOOL bbServerSync;
+ IMG_UINT32 ui32ClassNameSize;
+ const IMG_CHAR * puiClassName;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCRECORDADD;
+
+
+/* Bridge out structure for SyncRecordAdd */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCRECORDADD_TAG
+{
+ IMG_HANDLE hhRecord;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCRECORDADD;
+
+/*******************************************
+ ServerSyncAlloc
+ *******************************************/
+
+/* Bridge in structure for ServerSyncAlloc */
+typedef struct PVRSRV_BRIDGE_IN_SERVERSYNCALLOC_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32ClassNameSize;
+ const IMG_CHAR * puiClassName;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SERVERSYNCALLOC;
+
+
+/* Bridge out structure for ServerSyncAlloc */
+typedef struct PVRSRV_BRIDGE_OUT_SERVERSYNCALLOC_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32SyncPrimVAddr;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SERVERSYNCALLOC;
+
+/*******************************************
+ ServerSyncFree
+ *******************************************/
+
+/* Bridge in structure for ServerSyncFree */
+typedef struct PVRSRV_BRIDGE_IN_SERVERSYNCFREE_TAG
+{
+ IMG_HANDLE hSyncHandle;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SERVERSYNCFREE;
+
+
+/* Bridge out structure for ServerSyncFree */
+typedef struct PVRSRV_BRIDGE_OUT_SERVERSYNCFREE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SERVERSYNCFREE;
+
+/*******************************************
+ ServerSyncQueueHWOp
+ *******************************************/
+
+/* Bridge in structure for ServerSyncQueueHWOp */
+typedef struct PVRSRV_BRIDGE_IN_SERVERSYNCQUEUEHWOP_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_BOOL bbUpdate;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SERVERSYNCQUEUEHWOP;
+
+
+/* Bridge out structure for ServerSyncQueueHWOp */
+typedef struct PVRSRV_BRIDGE_OUT_SERVERSYNCQUEUEHWOP_TAG
+{
+ IMG_UINT32 ui32FenceValue;
+ IMG_UINT32 ui32UpdateValue;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SERVERSYNCQUEUEHWOP;
+
+/*******************************************
+ ServerSyncGetStatus
+ *******************************************/
+
+/* Bridge in structure for ServerSyncGetStatus */
+typedef struct PVRSRV_BRIDGE_IN_SERVERSYNCGETSTATUS_TAG
+{
+ IMG_UINT32 ui32SyncCount;
+ IMG_HANDLE * phSyncHandle;
+ /* Output pointer pui32UID is also an implied input */
+ IMG_UINT32 * pui32UID;
+ /* Output pointer pui32FWAddr is also an implied input */
+ IMG_UINT32 * pui32FWAddr;
+ /* Output pointer pui32CurrentOp is also an implied input */
+ IMG_UINT32 * pui32CurrentOp;
+ /* Output pointer pui32NextOp is also an implied input */
+ IMG_UINT32 * pui32NextOp;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SERVERSYNCGETSTATUS;
+
+
+/* Bridge out structure for ServerSyncGetStatus */
+typedef struct PVRSRV_BRIDGE_OUT_SERVERSYNCGETSTATUS_TAG
+{
+ IMG_UINT32 * pui32UID;
+ IMG_UINT32 * pui32FWAddr;
+ IMG_UINT32 * pui32CurrentOp;
+ IMG_UINT32 * pui32NextOp;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SERVERSYNCGETSTATUS;
+
+/*******************************************
+ SyncPrimOpCreate
+ *******************************************/
+
+/* Bridge in structure for SyncPrimOpCreate */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMOPCREATE_TAG
+{
+ IMG_UINT32 ui32SyncBlockCount;
+ IMG_HANDLE * phBlockList;
+ IMG_UINT32 ui32ClientSyncCount;
+ IMG_UINT32 * pui32SyncBlockIndex;
+ IMG_UINT32 * pui32Index;
+ IMG_UINT32 ui32ServerSyncCount;
+ IMG_HANDLE * phServerSync;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMOPCREATE;
+
+
+/* Bridge out structure for SyncPrimOpCreate */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMOPCREATE_TAG
+{
+ IMG_HANDLE hServerCookie;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMOPCREATE;
+
+/*******************************************
+ SyncPrimOpTake
+ *******************************************/
+
+/* Bridge in structure for SyncPrimOpTake */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMOPTAKE_TAG
+{
+ IMG_HANDLE hServerCookie;
+ IMG_UINT32 ui32ClientSyncCount;
+ IMG_UINT32 * pui32Flags;
+ IMG_UINT32 * pui32FenceValue;
+ IMG_UINT32 * pui32UpdateValue;
+ IMG_UINT32 ui32ServerSyncCount;
+ IMG_UINT32 * pui32ServerFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMOPTAKE;
+
+
+/* Bridge out structure for SyncPrimOpTake */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMOPTAKE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMOPTAKE;
+
+/*******************************************
+ SyncPrimOpReady
+ *******************************************/
+
+/* Bridge in structure for SyncPrimOpReady */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMOPREADY_TAG
+{
+ IMG_HANDLE hServerCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMOPREADY;
+
+
+/* Bridge out structure for SyncPrimOpReady */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMOPREADY_TAG
+{
+ IMG_BOOL bReady;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMOPREADY;
+
+/*******************************************
+ SyncPrimOpComplete
+ *******************************************/
+
+/* Bridge in structure for SyncPrimOpComplete */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMOPCOMPLETE_TAG
+{
+ IMG_HANDLE hServerCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMOPCOMPLETE;
+
+
+/* Bridge out structure for SyncPrimOpComplete */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMOPCOMPLETE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMOPCOMPLETE;
+
+/*******************************************
+ SyncPrimOpDestroy
+ *******************************************/
+
+/* Bridge in structure for SyncPrimOpDestroy */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMOPDESTROY_TAG
+{
+ IMG_HANDLE hServerCookie;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMOPDESTROY;
+
+
+/* Bridge out structure for SyncPrimOpDestroy */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMOPDESTROY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMOPDESTROY;
+
+/*******************************************
+ SyncPrimPDump
+ *******************************************/
+
+/* Bridge in structure for SyncPrimPDump */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMPDUMP_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32Offset;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMPDUMP;
+
+
+/* Bridge out structure for SyncPrimPDump */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMP_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMP;
+
+/*******************************************
+ SyncPrimPDumpValue
+ *******************************************/
+
+/* Bridge in structure for SyncPrimPDumpValue */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPVALUE_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPVALUE;
+
+
+/* Bridge out structure for SyncPrimPDumpValue */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPVALUE_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPVALUE;
+
+/*******************************************
+ SyncPrimPDumpPol
+ *******************************************/
+
+/* Bridge in structure for SyncPrimPDumpPol */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPPOL_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+ PDUMP_POLL_OPERATOR eOperator;
+ PDUMP_FLAGS_T uiPDumpFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPPOL;
+
+
+/* Bridge out structure for SyncPrimPDumpPol */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPPOL_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPPOL;
+
+/*******************************************
+ SyncPrimOpPDumpPol
+ *******************************************/
+
+/* Bridge in structure for SyncPrimOpPDumpPol */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMOPPDUMPPOL_TAG
+{
+ IMG_HANDLE hServerCookie;
+ PDUMP_POLL_OPERATOR eOperator;
+ PDUMP_FLAGS_T uiPDumpFlags;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMOPPDUMPPOL;
+
+
+/* Bridge out structure for SyncPrimOpPDumpPol */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMOPPDUMPPOL_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMOPPDUMPPOL;
+
+/*******************************************
+ SyncPrimPDumpCBP
+ *******************************************/
+
+/* Bridge in structure for SyncPrimPDumpCBP */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPCBP_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32Offset;
+ IMG_DEVMEM_OFFSET_T uiWriteOffset;
+ IMG_DEVMEM_SIZE_T uiPacketSize;
+ IMG_DEVMEM_SIZE_T uiBufferSize;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPCBP;
+
+
+/* Bridge out structure for SyncPrimPDumpCBP */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPCBP_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPCBP;
+
+#endif /* COMMON_SYNC_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/sync_bridge/server_sync_bridge.c b/drivers/gpu/rogue/generated/sync_bridge/server_sync_bridge.c
new file mode 100644
index 000000000000..bca7d27523f4
--- /dev/null
+++ b/drivers/gpu/rogue/generated/sync_bridge/server_sync_bridge.c
@@ -0,0 +1,1737 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for sync
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for sync
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "sync_server.h"
+#include "pdump.h"
+
+
+#include "common_sync_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+FreeSyncPrimitiveBlockResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+ServerSyncFreeResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+SyncPrimOpDestroyResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeAllocSyncPrimitiveBlock(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOCSYNCPRIMITIVEBLOCK *psAllocSyncPrimitiveBlockIN,
+ PVRSRV_BRIDGE_OUT_ALLOCSYNCPRIMITIVEBLOCK *psAllocSyncPrimitiveBlockOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+ DEVMEM_EXPORTCOOKIE * psExportCookieInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_ALLOCSYNCPRIMITIVEBLOCK);
+
+
+
+ psAllocSyncPrimitiveBlockOUT->hSyncHandle = IMG_NULL;
+
+
+ {
+ /* Look up the address from the handle */
+ psAllocSyncPrimitiveBlockOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psAllocSyncPrimitiveBlockIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
+ {
+ goto AllocSyncPrimitiveBlock_exit;
+ }
+
+ }
+
+ psAllocSyncPrimitiveBlockOUT->eError =
+ PVRSRVAllocSyncPrimitiveBlockKM(psConnection,
+ hDevNodeInt,
+ &psSyncHandleInt,
+ &psAllocSyncPrimitiveBlockOUT->ui32SyncPrimVAddr,
+ &psAllocSyncPrimitiveBlockOUT->ui32SyncPrimBlockSize,
+ &psExportCookieInt);
+ /* Exit early if bridged call fails */
+ if(psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
+ {
+ goto AllocSyncPrimitiveBlock_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hSyncHandleInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_SYNC_PRIMITIVE_BLOCK,
+ psSyncHandleInt,
+ (RESMAN_FREE_FN)&PVRSRVFreeSyncPrimitiveBlockKM);
+ if (hSyncHandleInt2 == IMG_NULL)
+ {
+ psAllocSyncPrimitiveBlockOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto AllocSyncPrimitiveBlock_exit;
+ }
+ psAllocSyncPrimitiveBlockOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psAllocSyncPrimitiveBlockOUT->hSyncHandle,
+ (IMG_HANDLE) hSyncHandleInt2,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
+ {
+ goto AllocSyncPrimitiveBlock_exit;
+ }
+ psAllocSyncPrimitiveBlockOUT->eError = PVRSRVAllocSubHandle(psConnection->psHandleBase,
+ &psAllocSyncPrimitiveBlockOUT->hExportCookie,
+ (IMG_HANDLE) psExportCookieInt,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ ,psAllocSyncPrimitiveBlockOUT->hSyncHandle);
+ if (psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
+ {
+ goto AllocSyncPrimitiveBlock_exit;
+ }
+
+
+AllocSyncPrimitiveBlock_exit:
+ if (psAllocSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
+ {
+ if (psAllocSyncPrimitiveBlockOUT->hSyncHandle)
+ {
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psAllocSyncPrimitiveBlockOUT->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+ }
+
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hSyncHandleInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hSyncHandleInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psSyncHandleInt)
+ {
+ PVRSRVFreeSyncPrimitiveBlockKM(psSyncHandleInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeFreeSyncPrimitiveBlock(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREESYNCPRIMITIVEBLOCK *psFreeSyncPrimitiveBlockIN,
+ PVRSRV_BRIDGE_OUT_FREESYNCPRIMITIVEBLOCK *psFreeSyncPrimitiveBlockOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_FREESYNCPRIMITIVEBLOCK);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psFreeSyncPrimitiveBlockOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psFreeSyncPrimitiveBlockIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+ if(psFreeSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
+ {
+ goto FreeSyncPrimitiveBlock_exit;
+ }
+
+ }
+
+ psFreeSyncPrimitiveBlockOUT->eError = FreeSyncPrimitiveBlockResManProxy(hSyncHandleInt2);
+ /* Exit early if bridged call fails */
+ if(psFreeSyncPrimitiveBlockOUT->eError != PVRSRV_OK)
+ {
+ goto FreeSyncPrimitiveBlock_exit;
+ }
+
+ psFreeSyncPrimitiveBlockOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psFreeSyncPrimitiveBlockIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+
+
+FreeSyncPrimitiveBlock_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimSet(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMSET *psSyncPrimSetIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMSET *psSyncPrimSetOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMSET);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimSetOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psSyncPrimSetIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+ if(psSyncPrimSetOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimSet_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimSetOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &psSyncHandleInt);
+
+ if(psSyncPrimSetOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimSet_exit;
+ }
+ }
+
+ psSyncPrimSetOUT->eError =
+ PVRSRVSyncPrimSetKM(
+ psSyncHandleInt,
+ psSyncPrimSetIN->ui32Index,
+ psSyncPrimSetIN->ui32Value);
+
+
+
+SyncPrimSet_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeServerSyncPrimSet(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SERVERSYNCPRIMSET *psServerSyncPrimSetIN,
+ PVRSRV_BRIDGE_OUT_SERVERSYNCPRIMSET *psServerSyncPrimSetOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SERVERSYNCPRIMSET);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psServerSyncPrimSetOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psServerSyncPrimSetIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psServerSyncPrimSetOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncPrimSet_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psServerSyncPrimSetOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &psSyncHandleInt);
+
+ if(psServerSyncPrimSetOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncPrimSet_exit;
+ }
+ }
+
+ psServerSyncPrimSetOUT->eError =
+ PVRSRVServerSyncPrimSetKM(
+ psSyncHandleInt,
+ psServerSyncPrimSetIN->ui32Value);
+
+
+
+ServerSyncPrimSet_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncRecordRemoveByHandle(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCRECORDREMOVEBYHANDLE *psSyncRecordRemoveByHandleIN,
+ PVRSRV_BRIDGE_OUT_SYNCRECORDREMOVEBYHANDLE *psSyncRecordRemoveByHandleOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hRecordHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCRECORDREMOVEBYHANDLE);
+
+ /* Look up the address from the handle */
+ psSyncRecordRemoveByHandleOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hRecordHandleInt2,
+ psSyncRecordRemoveByHandleIN->hhRecord,
+ PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE);
+ if(psSyncRecordRemoveByHandleOUT->eError != PVRSRV_OK)
+ {
+ goto SyncRecordRemoveByHandle_exit;
+ }
+
+ psSyncRecordRemoveByHandleOUT->eError = ServerSyncFreeResManProxy(hRecordHandleInt2);
+ /* Exit early if bridged call fails */
+ if(psSyncRecordRemoveByHandleOUT->eError != PVRSRV_OK)
+ {
+ goto SyncRecordRemoveByHandle_exit;
+ }
+
+ psSyncRecordRemoveByHandleOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psSyncRecordRemoveByHandleIN->hhRecord,
+ PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE);
+
+ if ((psSyncRecordRemoveByHandleOUT->eError != PVRSRV_OK) && (psSyncRecordRemoveByHandleOUT->eError != PVRSRV_ERROR_RETRY))
+ {
+ PVR_ASSERT(0);
+ goto SyncRecordRemoveByHandle_exit;
+ }
+
+SyncRecordRemoveByHandle_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncRecordAdd(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCRECORDADD *psSyncRecordAddIN,
+ PVRSRV_BRIDGE_OUT_SYNCRECORDADD *psSyncRecordAddOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SYNC_RECORD_HANDLE pshRecordInt = IMG_NULL;
+ IMG_HANDLE hRecordHandleInt2 = IMG_NULL;
+ SYNC_PRIMITIVE_BLOCK * pshServerSyncPrimBlockInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+ IMG_CHAR *uiClassNameInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCRECORDADD);
+
+ if (psSyncRecordAddIN->ui32ClassNameSize != 0)
+ {
+ uiClassNameInt = OSAllocMem(psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR));
+ if (!uiClassNameInt)
+ {
+ psSyncRecordAddOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto SyncRecordAdd_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncRecordAddIN->puiClassName, psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR))
+ || (OSCopyFromUser(NULL, uiClassNameInt, psSyncRecordAddIN->puiClassName,
+ psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+ {
+ psSyncRecordAddOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto SyncRecordAdd_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psSyncRecordAddOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psSyncRecordAddIN->hhServerSyncPrimBlock,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+ if(psSyncRecordAddOUT->eError != PVRSRV_OK)
+ {
+ goto SyncRecordAdd_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncRecordAddOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &pshServerSyncPrimBlockInt);
+
+ if(psSyncRecordAddOUT->eError != PVRSRV_OK)
+ {
+ goto SyncRecordAdd_exit;
+ }
+ }
+
+ psSyncRecordAddOUT->eError =
+ PVRSRVSyncRecordAddKM(
+ &pshRecordInt,
+ pshServerSyncPrimBlockInt,
+ psSyncRecordAddIN->ui32ui32FwBlockAddr,
+ psSyncRecordAddIN->ui32ui32SyncOffset,
+ psSyncRecordAddIN->bbServerSync,
+ psSyncRecordAddIN->ui32ClassNameSize,
+ uiClassNameInt);
+
+ /* Exit early if bridged call fails */
+ if(psSyncRecordAddOUT->eError != PVRSRV_OK)
+ {
+ goto SyncRecordAdd_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hRecordHandleInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_SYNC_RECORD_HANDLE,
+ pshRecordInt,
+ (RESMAN_FREE_FN)&PVRSRVSyncRecordRemoveByHandleKM);
+ if (hRecordHandleInt2 == IMG_NULL)
+ {
+ psSyncRecordAddOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto SyncRecordAdd_exit;
+ }
+
+ psSyncRecordAddOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psSyncRecordAddOUT->hhRecord,
+ (IMG_VOID *) hRecordHandleInt2,
+ PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psSyncRecordAddOUT->eError != PVRSRV_OK)
+ {
+ goto SyncRecordAdd_exit;
+ }
+
+SyncRecordAdd_exit:
+ if (psSyncRecordAddOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hRecordHandleInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hRecordHandleInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (pshRecordInt)
+ {
+ PVRSRVSyncRecordRemoveByHandleKM(pshRecordInt);
+ }
+ }
+
+ if (uiClassNameInt)
+ OSFreeMem(uiClassNameInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeServerSyncAlloc(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SERVERSYNCALLOC *psServerSyncAllocIN,
+ PVRSRV_BRIDGE_OUT_SERVERSYNCALLOC *psServerSyncAllocOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+ IMG_CHAR *uiClassNameInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SERVERSYNCALLOC);
+
+
+
+
+ if (psServerSyncAllocIN->ui32ClassNameSize != 0)
+ {
+ uiClassNameInt = OSAllocMem(psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR));
+ if (!uiClassNameInt)
+ {
+ psServerSyncAllocOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto ServerSyncAlloc_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psServerSyncAllocIN->puiClassName, psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR))
+ || (OSCopyFromUser(NULL, uiClassNameInt, psServerSyncAllocIN->puiClassName,
+ psServerSyncAllocIN->ui32ClassNameSize * sizeof(IMG_CHAR)) != PVRSRV_OK) )
+ {
+ psServerSyncAllocOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto ServerSyncAlloc_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psServerSyncAllocOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psServerSyncAllocIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psServerSyncAllocOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncAlloc_exit;
+ }
+
+ }
+
+ psServerSyncAllocOUT->eError =
+ PVRSRVServerSyncAllocKM(
+ hDevNodeInt,
+ &psSyncHandleInt,
+ &psServerSyncAllocOUT->ui32SyncPrimVAddr,
+ psServerSyncAllocIN->ui32ClassNameSize,
+ uiClassNameInt);
+ /* Exit early if bridged call fails */
+ if(psServerSyncAllocOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncAlloc_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hSyncHandleInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_SERVER_SYNC_PRIMITIVE,
+ psSyncHandleInt,
+ (RESMAN_FREE_FN)&PVRSRVServerSyncFreeKM);
+ if (hSyncHandleInt2 == IMG_NULL)
+ {
+ psServerSyncAllocOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto ServerSyncAlloc_exit;
+ }
+ psServerSyncAllocOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psServerSyncAllocOUT->hSyncHandle,
+ (IMG_HANDLE) hSyncHandleInt2,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psServerSyncAllocOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncAlloc_exit;
+ }
+
+
+ServerSyncAlloc_exit:
+ if (psServerSyncAllocOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hSyncHandleInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hSyncHandleInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psSyncHandleInt)
+ {
+ PVRSRVServerSyncFreeKM(psSyncHandleInt);
+ }
+ }
+
+ if (uiClassNameInt)
+ OSFreeMem(uiClassNameInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeServerSyncFree(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SERVERSYNCFREE *psServerSyncFreeIN,
+ PVRSRV_BRIDGE_OUT_SERVERSYNCFREE *psServerSyncFreeOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SERVERSYNCFREE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psServerSyncFreeOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psServerSyncFreeIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psServerSyncFreeOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncFree_exit;
+ }
+
+ }
+
+ psServerSyncFreeOUT->eError = ServerSyncFreeResManProxy(hSyncHandleInt2);
+ /* Exit early if bridged call fails */
+ if(psServerSyncFreeOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncFree_exit;
+ }
+
+ psServerSyncFreeOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psServerSyncFreeIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+
+
+ServerSyncFree_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeServerSyncQueueHWOp(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SERVERSYNCQUEUEHWOP *psServerSyncQueueHWOpIN,
+ PVRSRV_BRIDGE_OUT_SERVERSYNCQUEUEHWOP *psServerSyncQueueHWOpOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SERVERSYNCQUEUEHWOP);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psServerSyncQueueHWOpOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psServerSyncQueueHWOpIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psServerSyncQueueHWOpOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncQueueHWOp_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psServerSyncQueueHWOpOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &psSyncHandleInt);
+
+ if(psServerSyncQueueHWOpOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncQueueHWOp_exit;
+ }
+ }
+
+ psServerSyncQueueHWOpOUT->eError =
+ PVRSRVServerSyncQueueHWOpKM(
+ psSyncHandleInt,
+ psServerSyncQueueHWOpIN->bbUpdate,
+ &psServerSyncQueueHWOpOUT->ui32FenceValue,
+ &psServerSyncQueueHWOpOUT->ui32UpdateValue);
+
+
+
+ServerSyncQueueHWOp_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeServerSyncGetStatus(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SERVERSYNCGETSTATUS *psServerSyncGetStatusIN,
+ PVRSRV_BRIDGE_OUT_SERVERSYNCGETSTATUS *psServerSyncGetStatusOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_SYNC_PRIMITIVE * *psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE *hSyncHandleInt2 = IMG_NULL;
+ IMG_UINT32 *pui32UIDInt = IMG_NULL;
+ IMG_UINT32 *pui32FWAddrInt = IMG_NULL;
+ IMG_UINT32 *pui32CurrentOpInt = IMG_NULL;
+ IMG_UINT32 *pui32NextOpInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SERVERSYNCGETSTATUS);
+
+
+ psServerSyncGetStatusOUT->pui32UID = psServerSyncGetStatusIN->pui32UID;
+ psServerSyncGetStatusOUT->pui32FWAddr = psServerSyncGetStatusIN->pui32FWAddr;
+ psServerSyncGetStatusOUT->pui32CurrentOp = psServerSyncGetStatusIN->pui32CurrentOp;
+ psServerSyncGetStatusOUT->pui32NextOp = psServerSyncGetStatusIN->pui32NextOp;
+
+
+ if (psServerSyncGetStatusIN->ui32SyncCount != 0)
+ {
+ psSyncHandleInt = OSAllocMem(psServerSyncGetStatusIN->ui32SyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psSyncHandleInt)
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto ServerSyncGetStatus_exit;
+ }
+ hSyncHandleInt2 = OSAllocMem(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE));
+ if (!hSyncHandleInt2)
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto ServerSyncGetStatus_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psServerSyncGetStatusIN->phSyncHandle, psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hSyncHandleInt2, psServerSyncGetStatusIN->phSyncHandle,
+ psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto ServerSyncGetStatus_exit;
+ }
+ if (psServerSyncGetStatusIN->ui32SyncCount != 0)
+ {
+ pui32UIDInt = OSAllocMem(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32));
+ if (!pui32UIDInt)
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto ServerSyncGetStatus_exit;
+ }
+ }
+
+ if (psServerSyncGetStatusIN->ui32SyncCount != 0)
+ {
+ pui32FWAddrInt = OSAllocMem(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32));
+ if (!pui32FWAddrInt)
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto ServerSyncGetStatus_exit;
+ }
+ }
+
+ if (psServerSyncGetStatusIN->ui32SyncCount != 0)
+ {
+ pui32CurrentOpInt = OSAllocMem(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32));
+ if (!pui32CurrentOpInt)
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto ServerSyncGetStatus_exit;
+ }
+ }
+
+ if (psServerSyncGetStatusIN->ui32SyncCount != 0)
+ {
+ pui32NextOpInt = OSAllocMem(psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32));
+ if (!pui32NextOpInt)
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto ServerSyncGetStatus_exit;
+ }
+ }
+
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psServerSyncGetStatusIN->ui32SyncCount;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psServerSyncGetStatusOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2[i],
+ hSyncHandleInt2[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psServerSyncGetStatusOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncGetStatus_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psServerSyncGetStatusOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2[i], (IMG_VOID **) &psSyncHandleInt[i]);
+
+ if(psServerSyncGetStatusOUT->eError != PVRSRV_OK)
+ {
+ goto ServerSyncGetStatus_exit;
+ }
+ }
+ }
+ }
+
+ psServerSyncGetStatusOUT->eError =
+ PVRSRVServerSyncGetStatusKM(
+ psServerSyncGetStatusIN->ui32SyncCount,
+ psSyncHandleInt,
+ pui32UIDInt,
+ pui32FWAddrInt,
+ pui32CurrentOpInt,
+ pui32NextOpInt);
+
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psServerSyncGetStatusOUT->pui32UID, (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)))
+ || (OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32UID, pui32UIDInt,
+ (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto ServerSyncGetStatus_exit;
+ }
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psServerSyncGetStatusOUT->pui32FWAddr, (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)))
+ || (OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32FWAddr, pui32FWAddrInt,
+ (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto ServerSyncGetStatus_exit;
+ }
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psServerSyncGetStatusOUT->pui32CurrentOp, (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)))
+ || (OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32CurrentOp, pui32CurrentOpInt,
+ (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto ServerSyncGetStatus_exit;
+ }
+
+ if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psServerSyncGetStatusOUT->pui32NextOp, (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32)))
+ || (OSCopyToUser(NULL, psServerSyncGetStatusOUT->pui32NextOp, pui32NextOpInt,
+ (psServerSyncGetStatusIN->ui32SyncCount * sizeof(IMG_UINT32))) != PVRSRV_OK) )
+ {
+ psServerSyncGetStatusOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto ServerSyncGetStatus_exit;
+ }
+
+
+ServerSyncGetStatus_exit:
+ if (psSyncHandleInt)
+ OSFreeMem(psSyncHandleInt);
+ if (hSyncHandleInt2)
+ OSFreeMem(hSyncHandleInt2);
+ if (pui32UIDInt)
+ OSFreeMem(pui32UIDInt);
+ if (pui32FWAddrInt)
+ OSFreeMem(pui32FWAddrInt);
+ if (pui32CurrentOpInt)
+ OSFreeMem(pui32CurrentOpInt);
+ if (pui32NextOpInt)
+ OSFreeMem(pui32NextOpInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimOpCreate(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMOPCREATE *psSyncPrimOpCreateIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMOPCREATE *psSyncPrimOpCreateOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SYNC_PRIMITIVE_BLOCK * *psBlockListInt = IMG_NULL;
+ IMG_HANDLE *hBlockListInt2 = IMG_NULL;
+ IMG_UINT32 *ui32SyncBlockIndexInt = IMG_NULL;
+ IMG_UINT32 *ui32IndexInt = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * *psServerSyncInt = IMG_NULL;
+ IMG_HANDLE *hServerSyncInt2 = IMG_NULL;
+ SERVER_OP_COOKIE * psServerCookieInt = IMG_NULL;
+ IMG_HANDLE hServerCookieInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCREATE);
+
+
+
+
+ if (psSyncPrimOpCreateIN->ui32SyncBlockCount != 0)
+ {
+ psBlockListInt = OSAllocMem(psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(SYNC_PRIMITIVE_BLOCK *));
+ if (!psBlockListInt)
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpCreate_exit;
+ }
+ hBlockListInt2 = OSAllocMem(psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE));
+ if (!hBlockListInt2)
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpCreate_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpCreateIN->phBlockList, psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hBlockListInt2, psSyncPrimOpCreateIN->phBlockList,
+ psSyncPrimOpCreateIN->ui32SyncBlockCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto SyncPrimOpCreate_exit;
+ }
+ if (psSyncPrimOpCreateIN->ui32ClientSyncCount != 0)
+ {
+ ui32SyncBlockIndexInt = OSAllocMem(psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
+ if (!ui32SyncBlockIndexInt)
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpCreate_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpCreateIN->pui32SyncBlockIndex, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32SyncBlockIndexInt, psSyncPrimOpCreateIN->pui32SyncBlockIndex,
+ psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto SyncPrimOpCreate_exit;
+ }
+ if (psSyncPrimOpCreateIN->ui32ClientSyncCount != 0)
+ {
+ ui32IndexInt = OSAllocMem(psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
+ if (!ui32IndexInt)
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpCreate_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpCreateIN->pui32Index, psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32IndexInt, psSyncPrimOpCreateIN->pui32Index,
+ psSyncPrimOpCreateIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto SyncPrimOpCreate_exit;
+ }
+ if (psSyncPrimOpCreateIN->ui32ServerSyncCount != 0)
+ {
+ psServerSyncInt = OSAllocMem(psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(SERVER_SYNC_PRIMITIVE *));
+ if (!psServerSyncInt)
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpCreate_exit;
+ }
+ hServerSyncInt2 = OSAllocMem(psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE));
+ if (!hServerSyncInt2)
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpCreate_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpCreateIN->phServerSync, psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE))
+ || (OSCopyFromUser(NULL, hServerSyncInt2, psSyncPrimOpCreateIN->phServerSync,
+ psSyncPrimOpCreateIN->ui32ServerSyncCount * sizeof(IMG_HANDLE)) != PVRSRV_OK) )
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto SyncPrimOpCreate_exit;
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psSyncPrimOpCreateIN->ui32SyncBlockCount;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psSyncPrimOpCreateOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hBlockListInt2[i],
+ hBlockListInt2[i],
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+ if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpCreate_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimOpCreateOUT->eError = ResManFindPrivateDataByPtr(hBlockListInt2[i], (IMG_VOID **) &psBlockListInt[i]);
+
+ if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpCreate_exit;
+ }
+ }
+ }
+ }
+
+ {
+ IMG_UINT32 i;
+
+ for (i=0;i<psSyncPrimOpCreateIN->ui32ServerSyncCount;i++)
+ {
+ {
+ /* Look up the address from the handle */
+ psSyncPrimOpCreateOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerSyncInt2[i],
+ psSyncPrimOpCreateIN->phServerSync[i],
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpCreate_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimOpCreateOUT->eError = ResManFindPrivateDataByPtr(hServerSyncInt2[i], (IMG_VOID **) &psServerSyncInt[i]);
+
+ if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpCreate_exit;
+ }
+ }
+ }
+ }
+
+ psSyncPrimOpCreateOUT->eError =
+ PVRSRVSyncPrimOpCreateKM(
+ psSyncPrimOpCreateIN->ui32SyncBlockCount,
+ psBlockListInt,
+ psSyncPrimOpCreateIN->ui32ClientSyncCount,
+ ui32SyncBlockIndexInt,
+ ui32IndexInt,
+ psSyncPrimOpCreateIN->ui32ServerSyncCount,
+ psServerSyncInt,
+ &psServerCookieInt);
+ /* Exit early if bridged call fails */
+ if(psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpCreate_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hServerCookieInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_SERVER_OP_COOKIE,
+ psServerCookieInt,
+ (RESMAN_FREE_FN)&PVRSRVSyncPrimOpDestroyKM);
+ if (hServerCookieInt2 == IMG_NULL)
+ {
+ psSyncPrimOpCreateOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto SyncPrimOpCreate_exit;
+ }
+ psSyncPrimOpCreateOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psSyncPrimOpCreateOUT->hServerCookie,
+ (IMG_HANDLE) hServerCookieInt2,
+ PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpCreate_exit;
+ }
+
+
+SyncPrimOpCreate_exit:
+ if (psSyncPrimOpCreateOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hServerCookieInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hServerCookieInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psServerCookieInt)
+ {
+ PVRSRVSyncPrimOpDestroyKM(psServerCookieInt);
+ }
+ }
+
+ if (psBlockListInt)
+ OSFreeMem(psBlockListInt);
+ if (hBlockListInt2)
+ OSFreeMem(hBlockListInt2);
+ if (ui32SyncBlockIndexInt)
+ OSFreeMem(ui32SyncBlockIndexInt);
+ if (ui32IndexInt)
+ OSFreeMem(ui32IndexInt);
+ if (psServerSyncInt)
+ OSFreeMem(psServerSyncInt);
+ if (hServerSyncInt2)
+ OSFreeMem(hServerSyncInt2);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimOpTake(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMOPTAKE *psSyncPrimOpTakeIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMOPTAKE *psSyncPrimOpTakeOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_OP_COOKIE * psServerCookieInt = IMG_NULL;
+ IMG_HANDLE hServerCookieInt2 = IMG_NULL;
+ IMG_UINT32 *ui32FlagsInt = IMG_NULL;
+ IMG_UINT32 *ui32FenceValueInt = IMG_NULL;
+ IMG_UINT32 *ui32UpdateValueInt = IMG_NULL;
+ IMG_UINT32 *ui32ServerFlagsInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMOPTAKE);
+
+
+
+
+ if (psSyncPrimOpTakeIN->ui32ClientSyncCount != 0)
+ {
+ ui32FlagsInt = OSAllocMem(psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
+ if (!ui32FlagsInt)
+ {
+ psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpTake_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpTakeIN->pui32Flags, psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32FlagsInt, psSyncPrimOpTakeIN->pui32Flags,
+ psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto SyncPrimOpTake_exit;
+ }
+ if (psSyncPrimOpTakeIN->ui32ClientSyncCount != 0)
+ {
+ ui32FenceValueInt = OSAllocMem(psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
+ if (!ui32FenceValueInt)
+ {
+ psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpTake_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpTakeIN->pui32FenceValue, psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32FenceValueInt, psSyncPrimOpTakeIN->pui32FenceValue,
+ psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto SyncPrimOpTake_exit;
+ }
+ if (psSyncPrimOpTakeIN->ui32ClientSyncCount != 0)
+ {
+ ui32UpdateValueInt = OSAllocMem(psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32));
+ if (!ui32UpdateValueInt)
+ {
+ psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpTake_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpTakeIN->pui32UpdateValue, psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32UpdateValueInt, psSyncPrimOpTakeIN->pui32UpdateValue,
+ psSyncPrimOpTakeIN->ui32ClientSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto SyncPrimOpTake_exit;
+ }
+ if (psSyncPrimOpTakeIN->ui32ServerSyncCount != 0)
+ {
+ ui32ServerFlagsInt = OSAllocMem(psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32));
+ if (!ui32ServerFlagsInt)
+ {
+ psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto SyncPrimOpTake_exit;
+ }
+ }
+
+ /* Copy the data over */
+ if ( !OSAccessOK(PVR_VERIFY_READ, (IMG_VOID*) psSyncPrimOpTakeIN->pui32ServerFlags, psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32))
+ || (OSCopyFromUser(NULL, ui32ServerFlagsInt, psSyncPrimOpTakeIN->pui32ServerFlags,
+ psSyncPrimOpTakeIN->ui32ServerSyncCount * sizeof(IMG_UINT32)) != PVRSRV_OK) )
+ {
+ psSyncPrimOpTakeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+ goto SyncPrimOpTake_exit;
+ }
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimOpTakeOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerCookieInt2,
+ psSyncPrimOpTakeIN->hServerCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+ if(psSyncPrimOpTakeOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpTake_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimOpTakeOUT->eError = ResManFindPrivateDataByPtr(hServerCookieInt2, (IMG_VOID **) &psServerCookieInt);
+
+ if(psSyncPrimOpTakeOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpTake_exit;
+ }
+ }
+
+ psSyncPrimOpTakeOUT->eError =
+ PVRSRVSyncPrimOpTakeKM(
+ psServerCookieInt,
+ psSyncPrimOpTakeIN->ui32ClientSyncCount,
+ ui32FlagsInt,
+ ui32FenceValueInt,
+ ui32UpdateValueInt,
+ psSyncPrimOpTakeIN->ui32ServerSyncCount,
+ ui32ServerFlagsInt);
+
+
+
+SyncPrimOpTake_exit:
+ if (ui32FlagsInt)
+ OSFreeMem(ui32FlagsInt);
+ if (ui32FenceValueInt)
+ OSFreeMem(ui32FenceValueInt);
+ if (ui32UpdateValueInt)
+ OSFreeMem(ui32UpdateValueInt);
+ if (ui32ServerFlagsInt)
+ OSFreeMem(ui32ServerFlagsInt);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimOpReady(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMOPREADY *psSyncPrimOpReadyIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMOPREADY *psSyncPrimOpReadyOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_OP_COOKIE * psServerCookieInt = IMG_NULL;
+ IMG_HANDLE hServerCookieInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMOPREADY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimOpReadyOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerCookieInt2,
+ psSyncPrimOpReadyIN->hServerCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+ if(psSyncPrimOpReadyOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpReady_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimOpReadyOUT->eError = ResManFindPrivateDataByPtr(hServerCookieInt2, (IMG_VOID **) &psServerCookieInt);
+
+ if(psSyncPrimOpReadyOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpReady_exit;
+ }
+ }
+
+ psSyncPrimOpReadyOUT->eError =
+ PVRSRVSyncPrimOpReadyKM(
+ psServerCookieInt,
+ &psSyncPrimOpReadyOUT->bReady);
+
+
+
+SyncPrimOpReady_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimOpComplete(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMOPCOMPLETE *psSyncPrimOpCompleteIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMOPCOMPLETE *psSyncPrimOpCompleteOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_OP_COOKIE * psServerCookieInt = IMG_NULL;
+ IMG_HANDLE hServerCookieInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCOMPLETE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimOpCompleteOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerCookieInt2,
+ psSyncPrimOpCompleteIN->hServerCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+ if(psSyncPrimOpCompleteOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpComplete_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimOpCompleteOUT->eError = ResManFindPrivateDataByPtr(hServerCookieInt2, (IMG_VOID **) &psServerCookieInt);
+
+ if(psSyncPrimOpCompleteOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpComplete_exit;
+ }
+ }
+
+ psSyncPrimOpCompleteOUT->eError =
+ PVRSRVSyncPrimOpCompleteKM(
+ psServerCookieInt);
+
+
+
+SyncPrimOpComplete_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimOpDestroy(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMOPDESTROY *psSyncPrimOpDestroyIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMOPDESTROY *psSyncPrimOpDestroyOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hServerCookieInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMOPDESTROY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimOpDestroyOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerCookieInt2,
+ psSyncPrimOpDestroyIN->hServerCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+ if(psSyncPrimOpDestroyOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpDestroy_exit;
+ }
+
+ }
+
+ psSyncPrimOpDestroyOUT->eError = SyncPrimOpDestroyResManProxy(hServerCookieInt2);
+ /* Exit early if bridged call fails */
+ if(psSyncPrimOpDestroyOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpDestroy_exit;
+ }
+
+ psSyncPrimOpDestroyOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psSyncPrimOpDestroyIN->hServerCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+
+
+SyncPrimOpDestroy_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimPDump(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMPDUMP *psSyncPrimPDumpIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMP *psSyncPrimPDumpOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMP);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimPDumpOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psSyncPrimPDumpIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+ if(psSyncPrimPDumpOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimPDump_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimPDumpOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &psSyncHandleInt);
+
+ if(psSyncPrimPDumpOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimPDump_exit;
+ }
+ }
+
+ psSyncPrimPDumpOUT->eError =
+ PVRSRVSyncPrimPDumpKM(
+ psSyncHandleInt,
+ psSyncPrimPDumpIN->ui32Offset);
+
+
+
+SyncPrimPDump_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimPDumpValue(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPVALUE *psSyncPrimPDumpValueIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPVALUE *psSyncPrimPDumpValueOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPVALUE);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimPDumpValueOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psSyncPrimPDumpValueIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+ if(psSyncPrimPDumpValueOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimPDumpValue_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimPDumpValueOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &psSyncHandleInt);
+
+ if(psSyncPrimPDumpValueOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimPDumpValue_exit;
+ }
+ }
+
+ psSyncPrimPDumpValueOUT->eError =
+ PVRSRVSyncPrimPDumpValueKM(
+ psSyncHandleInt,
+ psSyncPrimPDumpValueIN->ui32Offset,
+ psSyncPrimPDumpValueIN->ui32Value);
+
+
+
+SyncPrimPDumpValue_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimPDumpPol(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPPOL *psSyncPrimPDumpPolIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPPOL *psSyncPrimPDumpPolOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPPOL);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimPDumpPolOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psSyncPrimPDumpPolIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+ if(psSyncPrimPDumpPolOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimPDumpPol_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimPDumpPolOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &psSyncHandleInt);
+
+ if(psSyncPrimPDumpPolOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimPDumpPol_exit;
+ }
+ }
+
+ psSyncPrimPDumpPolOUT->eError =
+ PVRSRVSyncPrimPDumpPolKM(
+ psSyncHandleInt,
+ psSyncPrimPDumpPolIN->ui32Offset,
+ psSyncPrimPDumpPolIN->ui32Value,
+ psSyncPrimPDumpPolIN->ui32Mask,
+ psSyncPrimPDumpPolIN->eOperator,
+ psSyncPrimPDumpPolIN->uiPDumpFlags);
+
+
+
+SyncPrimPDumpPol_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimOpPDumpPol(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMOPPDUMPPOL *psSyncPrimOpPDumpPolIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMOPPDUMPPOL *psSyncPrimOpPDumpPolOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_OP_COOKIE * psServerCookieInt = IMG_NULL;
+ IMG_HANDLE hServerCookieInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMOPPDUMPPOL);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimOpPDumpPolOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hServerCookieInt2,
+ psSyncPrimOpPDumpPolIN->hServerCookie,
+ PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE);
+ if(psSyncPrimOpPDumpPolOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpPDumpPol_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimOpPDumpPolOUT->eError = ResManFindPrivateDataByPtr(hServerCookieInt2, (IMG_VOID **) &psServerCookieInt);
+
+ if(psSyncPrimOpPDumpPolOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimOpPDumpPol_exit;
+ }
+ }
+
+ psSyncPrimOpPDumpPolOUT->eError =
+ PVRSRVSyncPrimOpPDumpPolKM(
+ psServerCookieInt,
+ psSyncPrimOpPDumpPolIN->eOperator,
+ psSyncPrimOpPDumpPolIN->uiPDumpFlags);
+
+
+
+SyncPrimOpPDumpPol_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimPDumpCBP(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMPDUMPCBP *psSyncPrimPDumpCBPIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMPDUMPCBP *psSyncPrimPDumpCBPOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SYNC_PRIMITIVE_BLOCK * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPCBP);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimPDumpCBPOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psSyncPrimPDumpCBPIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+ if(psSyncPrimPDumpCBPOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimPDumpCBP_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimPDumpCBPOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &psSyncHandleInt);
+
+ if(psSyncPrimPDumpCBPOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimPDumpCBP_exit;
+ }
+ }
+
+ psSyncPrimPDumpCBPOUT->eError =
+ PVRSRVSyncPrimPDumpCBPKM(
+ psSyncHandleInt,
+ psSyncPrimPDumpCBPIN->ui32Offset,
+ psSyncPrimPDumpCBPIN->uiWriteOffset,
+ psSyncPrimPDumpCBPIN->uiPacketSize,
+ psSyncPrimPDumpCBPIN->uiBufferSize);
+
+
+
+SyncPrimPDumpCBP_exit:
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterSYNCFunctions(IMG_VOID);
+IMG_VOID UnregisterSYNCFunctions(IMG_VOID);
+
+/*
+ * Register all SYNC functions with services
+ */
+PVRSRV_ERROR RegisterSYNCFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_ALLOCSYNCPRIMITIVEBLOCK, PVRSRVBridgeAllocSyncPrimitiveBlock);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_FREESYNCPRIMITIVEBLOCK, PVRSRVBridgeFreeSyncPrimitiveBlock);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMSET, PVRSRVBridgeSyncPrimSet);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SERVERSYNCPRIMSET, PVRSRVBridgeServerSyncPrimSet);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCRECORDREMOVEBYHANDLE, PVRSRVBridgeSyncRecordRemoveByHandle);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCRECORDADD, PVRSRVBridgeSyncRecordAdd);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SERVERSYNCALLOC, PVRSRVBridgeServerSyncAlloc);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SERVERSYNCFREE, PVRSRVBridgeServerSyncFree);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SERVERSYNCQUEUEHWOP, PVRSRVBridgeServerSyncQueueHWOp);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SERVERSYNCGETSTATUS, PVRSRVBridgeServerSyncGetStatus);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCREATE, PVRSRVBridgeSyncPrimOpCreate);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMOPTAKE, PVRSRVBridgeSyncPrimOpTake);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMOPREADY, PVRSRVBridgeSyncPrimOpReady);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMOPCOMPLETE, PVRSRVBridgeSyncPrimOpComplete);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMOPDESTROY, PVRSRVBridgeSyncPrimOpDestroy);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMP, PVRSRVBridgeSyncPrimPDump);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPVALUE, PVRSRVBridgeSyncPrimPDumpValue);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPPOL, PVRSRVBridgeSyncPrimPDumpPol);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMOPPDUMPPOL, PVRSRVBridgeSyncPrimOpPDumpPol);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_SYNCPRIMPDUMPCBP, PVRSRVBridgeSyncPrimPDumpCBP);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all sync functions with services
+ */
+IMG_VOID UnregisterSYNCFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/syncexport_bridge/common_syncexport_bridge.h b/drivers/gpu/rogue/generated/syncexport_bridge/common_syncexport_bridge.h
new file mode 100644
index 000000000000..1673d872a39b
--- /dev/null
+++ b/drivers/gpu/rogue/generated/syncexport_bridge/common_syncexport_bridge.h
@@ -0,0 +1,113 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for syncexport
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for syncexport
+@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_SYNCEXPORT_BRIDGE_H
+#define COMMON_SYNCEXPORT_BRIDGE_H
+
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_SYNCEXPORT_CMD_FIRST (PVRSRV_BRIDGE_SYNCEXPORT_START)
+#define PVRSRV_BRIDGE_SYNCEXPORT_SYNCPRIMSERVEREXPORT PVRSRV_IOWR(PVRSRV_BRIDGE_SYNCEXPORT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SYNCEXPORT_SYNCPRIMSERVERUNEXPORT PVRSRV_IOWR(PVRSRV_BRIDGE_SYNCEXPORT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_SYNCEXPORT_SYNCPRIMSERVERIMPORT PVRSRV_IOWR(PVRSRV_BRIDGE_SYNCEXPORT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SYNCEXPORT_CMD_LAST (PVRSRV_BRIDGE_SYNCEXPORT_CMD_FIRST+2)
+
+
+/*******************************************
+ SyncPrimServerExport
+ *******************************************/
+
+/* Bridge in structure for SyncPrimServerExport */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMSERVEREXPORT_TAG
+{
+ IMG_HANDLE hSyncHandle;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMSERVEREXPORT;
+
+
+/* Bridge out structure for SyncPrimServerExport */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMSERVEREXPORT_TAG
+{
+ IMG_HANDLE hExport;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMSERVEREXPORT;
+
+/*******************************************
+ SyncPrimServerUnexport
+ *******************************************/
+
+/* Bridge in structure for SyncPrimServerUnexport */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMSERVERUNEXPORT_TAG
+{
+ IMG_HANDLE hExport;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMSERVERUNEXPORT;
+
+
+/* Bridge out structure for SyncPrimServerUnexport */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERUNEXPORT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERUNEXPORT;
+
+/*******************************************
+ SyncPrimServerImport
+ *******************************************/
+
+/* Bridge in structure for SyncPrimServerImport */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMSERVERIMPORT_TAG
+{
+ IMG_HANDLE hImport;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMSERVERIMPORT;
+
+
+/* Bridge out structure for SyncPrimServerImport */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERIMPORT_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32SyncPrimVAddr;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERIMPORT;
+
+#endif /* COMMON_SYNCEXPORT_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/syncexport_bridge/server_syncexport_bridge.c b/drivers/gpu/rogue/generated/syncexport_bridge/server_syncexport_bridge.c
new file mode 100644
index 000000000000..8146ec30cfbf
--- /dev/null
+++ b/drivers/gpu/rogue/generated/syncexport_bridge/server_syncexport_bridge.c
@@ -0,0 +1,366 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for syncexport
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for syncexport
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "sync_server.h"
+
+
+#include "common_syncexport_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+SyncPrimServerUnexportResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeSyncPrimServerExport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMSERVEREXPORT *psSyncPrimServerExportIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMSERVEREXPORT *psSyncPrimServerExportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+ SERVER_SYNC_EXPORT * psExportInt = IMG_NULL;
+ IMG_HANDLE hExportInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNCEXPORT_SYNCPRIMSERVEREXPORT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimServerExportOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psSyncPrimServerExportIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psSyncPrimServerExportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerExport_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimServerExportOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &psSyncHandleInt);
+
+ if(psSyncPrimServerExportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerExport_exit;
+ }
+ }
+
+ psSyncPrimServerExportOUT->eError =
+ PVRSRVSyncPrimServerExportKM(
+ psSyncHandleInt,
+ &psExportInt);
+ /* Exit early if bridged call fails */
+ if(psSyncPrimServerExportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerExport_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hExportInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_SERVER_SYNC_EXPORT,
+ psExportInt,
+ (RESMAN_FREE_FN)&PVRSRVSyncPrimServerUnexportKM);
+ if (hExportInt2 == IMG_NULL)
+ {
+ psSyncPrimServerExportOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto SyncPrimServerExport_exit;
+ }
+ /* see if it's already exported */
+ psSyncPrimServerExportOUT->eError =
+ PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &psSyncPrimServerExportOUT->hExport,
+ (IMG_HANDLE) hExportInt2,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_EXPORT);
+ if(psSyncPrimServerExportOUT->eError == PVRSRV_OK)
+ {
+ /* It's already exported */
+ return 0;
+ }
+
+ psSyncPrimServerExportOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psSyncPrimServerExportOUT->hExport,
+ (IMG_HANDLE) hExportInt2,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_EXPORT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psSyncPrimServerExportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerExport_exit;
+ }
+
+
+SyncPrimServerExport_exit:
+ if (psSyncPrimServerExportOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hExportInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hExportInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psExportInt)
+ {
+ PVRSRVSyncPrimServerUnexportKM(psExportInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimServerUnexport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMSERVERUNEXPORT *psSyncPrimServerUnexportIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERUNEXPORT *psSyncPrimServerUnexportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hExportInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNCEXPORT_SYNCPRIMSERVERUNEXPORT);
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimServerUnexportOUT->eError =
+ PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE *) &hExportInt2,
+ psSyncPrimServerUnexportIN->hExport,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_EXPORT);
+ if(psSyncPrimServerUnexportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerUnexport_exit;
+ }
+
+ }
+
+ psSyncPrimServerUnexportOUT->eError = SyncPrimServerUnexportResManProxy(hExportInt2);
+ /* Exit early if bridged call fails */
+ if(psSyncPrimServerUnexportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerUnexport_exit;
+ }
+
+ psSyncPrimServerUnexportOUT->eError =
+ PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE) psSyncPrimServerUnexportIN->hExport,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_EXPORT);
+
+
+SyncPrimServerUnexport_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimServerImport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMSERVERIMPORT *psSyncPrimServerImportIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERIMPORT *psSyncPrimServerImportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_SYNC_EXPORT * psImportInt = IMG_NULL;
+ IMG_HANDLE hImportInt2 = IMG_NULL;
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNCEXPORT_SYNCPRIMSERVERIMPORT);
+
+
+
+
+#if defined (SUPPORT_AUTH)
+ psSyncPrimServerImportOUT->eError = OSCheckAuthentication(psConnection, 1);
+ if (psSyncPrimServerImportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerImport_exit;
+ }
+#endif
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimServerImportOUT->eError =
+ PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_HANDLE *) &hImportInt2,
+ psSyncPrimServerImportIN->hImport,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_EXPORT);
+ if(psSyncPrimServerImportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerImport_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimServerImportOUT->eError = ResManFindPrivateDataByPtr(hImportInt2, (IMG_VOID **) &psImportInt);
+
+ if(psSyncPrimServerImportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerImport_exit;
+ }
+ }
+
+ psSyncPrimServerImportOUT->eError =
+ PVRSRVSyncPrimServerImportKM(
+ psImportInt,
+ &psSyncHandleInt,
+ &psSyncPrimServerImportOUT->ui32SyncPrimVAddr);
+ /* Exit early if bridged call fails */
+ if(psSyncPrimServerImportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerImport_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hSyncHandleInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_SERVER_SYNC_PRIMITIVE,
+ psSyncHandleInt,
+ (RESMAN_FREE_FN)&PVRSRVServerSyncFreeKM);
+ if (hSyncHandleInt2 == IMG_NULL)
+ {
+ psSyncPrimServerImportOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto SyncPrimServerImport_exit;
+ }
+ psSyncPrimServerImportOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psSyncPrimServerImportOUT->hSyncHandle,
+ (IMG_HANDLE) hSyncHandleInt2,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psSyncPrimServerImportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerImport_exit;
+ }
+
+
+SyncPrimServerImport_exit:
+ if (psSyncPrimServerImportOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hSyncHandleInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hSyncHandleInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psSyncHandleInt)
+ {
+ PVRSRVServerSyncFreeKM(psSyncHandleInt);
+ }
+ }
+
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterSYNCEXPORTFunctions(IMG_VOID);
+IMG_VOID UnregisterSYNCEXPORTFunctions(IMG_VOID);
+
+/*
+ * Register all SYNCEXPORT functions with services
+ */
+PVRSRV_ERROR RegisterSYNCEXPORTFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCEXPORT_SYNCPRIMSERVEREXPORT, PVRSRVBridgeSyncPrimServerExport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCEXPORT_SYNCPRIMSERVERUNEXPORT, PVRSRVBridgeSyncPrimServerUnexport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCEXPORT_SYNCPRIMSERVERIMPORT, PVRSRVBridgeSyncPrimServerImport);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all syncexport functions with services
+ */
+IMG_VOID UnregisterSYNCEXPORTFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/syncsexport_bridge/common_syncsexport_bridge.h b/drivers/gpu/rogue/generated/syncsexport_bridge/common_syncsexport_bridge.h
new file mode 100644
index 000000000000..8c2b4cf6b92b
--- /dev/null
+++ b/drivers/gpu/rogue/generated/syncsexport_bridge/common_syncsexport_bridge.h
@@ -0,0 +1,113 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for syncsexport
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for syncsexport
+@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_SYNCSEXPORT_BRIDGE_H
+#define COMMON_SYNCSEXPORT_BRIDGE_H
+
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_SYNCSEXPORT_CMD_FIRST (PVRSRV_BRIDGE_SYNCSEXPORT_START)
+#define PVRSRV_BRIDGE_SYNCSEXPORT_SYNCPRIMSERVERSECUREEXPORT PVRSRV_IOWR(PVRSRV_BRIDGE_SYNCSEXPORT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SYNCSEXPORT_SYNCPRIMSERVERSECUREUNEXPORT PVRSRV_IOWR(PVRSRV_BRIDGE_SYNCSEXPORT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_SYNCSEXPORT_SYNCPRIMSERVERSECUREIMPORT PVRSRV_IOWR(PVRSRV_BRIDGE_SYNCSEXPORT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SYNCSEXPORT_CMD_LAST (PVRSRV_BRIDGE_SYNCSEXPORT_CMD_FIRST+2)
+
+
+/*******************************************
+ SyncPrimServerSecureExport
+ *******************************************/
+
+/* Bridge in structure for SyncPrimServerSecureExport */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMSERVERSECUREEXPORT_TAG
+{
+ IMG_HANDLE hSyncHandle;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMSERVERSECUREEXPORT;
+
+
+/* Bridge out structure for SyncPrimServerSecureExport */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERSECUREEXPORT_TAG
+{
+ IMG_SECURE_TYPE Export;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERSECUREEXPORT;
+
+/*******************************************
+ SyncPrimServerSecureUnexport
+ *******************************************/
+
+/* Bridge in structure for SyncPrimServerSecureUnexport */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMSERVERSECUREUNEXPORT_TAG
+{
+ IMG_HANDLE hExport;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMSERVERSECUREUNEXPORT;
+
+
+/* Bridge out structure for SyncPrimServerSecureUnexport */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERSECUREUNEXPORT_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERSECUREUNEXPORT;
+
+/*******************************************
+ SyncPrimServerSecureImport
+ *******************************************/
+
+/* Bridge in structure for SyncPrimServerSecureImport */
+typedef struct PVRSRV_BRIDGE_IN_SYNCPRIMSERVERSECUREIMPORT_TAG
+{
+ IMG_SECURE_TYPE Export;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_SYNCPRIMSERVERSECUREIMPORT;
+
+
+/* Bridge out structure for SyncPrimServerSecureImport */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERSECUREIMPORT_TAG
+{
+ IMG_HANDLE hSyncHandle;
+ IMG_UINT32 ui32SyncPrimVAddr;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERSECUREIMPORT;
+
+#endif /* COMMON_SYNCSEXPORT_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/syncsexport_bridge/server_syncsexport_bridge.c b/drivers/gpu/rogue/generated/syncsexport_bridge/server_syncsexport_bridge.c
new file mode 100644
index 000000000000..52751a16f632
--- /dev/null
+++ b/drivers/gpu/rogue/generated/syncsexport_bridge/server_syncsexport_bridge.c
@@ -0,0 +1,315 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for syncsexport
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for syncsexport
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "sync_server.h"
+
+
+#include "common_syncsexport_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+static PVRSRV_ERROR
+SyncPrimServerSecureUnexportResManProxy(IMG_HANDLE hResmanItem)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManFreeResByPtr(hResmanItem);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+ return eError;
+}
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeSyncPrimServerSecureExport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMSERVERSECUREEXPORT *psSyncPrimServerSecureExportIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERSECUREEXPORT *psSyncPrimServerSecureExportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+ SERVER_SYNC_EXPORT * psExportInt = IMG_NULL;
+ IMG_HANDLE hExportInt2 = IMG_NULL;
+ CONNECTION_DATA *psSecureConnection;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNCSEXPORT_SYNCPRIMSERVERSECUREEXPORT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimServerSecureExportOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hSyncHandleInt2,
+ psSyncPrimServerSecureExportIN->hSyncHandle,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE);
+ if(psSyncPrimServerSecureExportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerSecureExport_exit;
+ }
+
+ /* Look up the data from the resman address */
+ psSyncPrimServerSecureExportOUT->eError = ResManFindPrivateDataByPtr(hSyncHandleInt2, (IMG_VOID **) &psSyncHandleInt);
+
+ if(psSyncPrimServerSecureExportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerSecureExport_exit;
+ }
+ }
+
+ psSyncPrimServerSecureExportOUT->eError =
+ PVRSRVSyncPrimServerSecureExportKM(psConnection,
+ psSyncHandleInt,
+ &psSyncPrimServerSecureExportOUT->Export,
+ &psExportInt, &psSecureConnection);
+ /* Exit early if bridged call fails */
+ if(psSyncPrimServerSecureExportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerSecureExport_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hExportInt2 = ResManRegisterRes(psSecureConnection->hResManContext,
+ RESMAN_TYPE_SERVER_SYNC_EXPORT,
+ psExportInt,
+ (RESMAN_FREE_FN)&PVRSRVSyncPrimServerSecureUnexportKM);
+ if (hExportInt2 == IMG_NULL)
+ {
+ psSyncPrimServerSecureExportOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto SyncPrimServerSecureExport_exit;
+ }
+
+
+SyncPrimServerSecureExport_exit:
+ if (psSyncPrimServerSecureExportOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hExportInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hExportInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psExportInt)
+ {
+ PVRSRVSyncPrimServerSecureUnexportKM(psExportInt);
+ }
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimServerSecureUnexport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMSERVERSECUREUNEXPORT *psSyncPrimServerSecureUnexportIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERSECUREUNEXPORT *psSyncPrimServerSecureUnexportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hExportInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNCSEXPORT_SYNCPRIMSERVERSECUREUNEXPORT);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psSyncPrimServerSecureUnexportOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hExportInt2,
+ psSyncPrimServerSecureUnexportIN->hExport,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_EXPORT);
+ if(psSyncPrimServerSecureUnexportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerSecureUnexport_exit;
+ }
+
+ }
+
+ psSyncPrimServerSecureUnexportOUT->eError = SyncPrimServerSecureUnexportResManProxy(hExportInt2);
+ /* Exit early if bridged call fails */
+ if(psSyncPrimServerSecureUnexportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerSecureUnexport_exit;
+ }
+
+ psSyncPrimServerSecureUnexportOUT->eError =
+ PVRSRVReleaseHandle(psConnection->psHandleBase,
+ (IMG_HANDLE) psSyncPrimServerSecureUnexportIN->hExport,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_EXPORT);
+
+
+SyncPrimServerSecureUnexport_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncPrimServerSecureImport(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNCPRIMSERVERSECUREIMPORT *psSyncPrimServerSecureImportIN,
+ PVRSRV_BRIDGE_OUT_SYNCPRIMSERVERSECUREIMPORT *psSyncPrimServerSecureImportOUT,
+ CONNECTION_DATA *psConnection)
+{
+ SERVER_SYNC_PRIMITIVE * psSyncHandleInt = IMG_NULL;
+ IMG_HANDLE hSyncHandleInt2 = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNCSEXPORT_SYNCPRIMSERVERSECUREIMPORT);
+
+
+
+
+
+ psSyncPrimServerSecureImportOUT->eError =
+ PVRSRVSyncPrimServerSecureImportKM(
+ psSyncPrimServerSecureImportIN->Export,
+ &psSyncHandleInt,
+ &psSyncPrimServerSecureImportOUT->ui32SyncPrimVAddr);
+ /* Exit early if bridged call fails */
+ if(psSyncPrimServerSecureImportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerSecureImport_exit;
+ }
+
+ /* Create a resman item and overwrite the handle with it */
+ hSyncHandleInt2 = ResManRegisterRes(psConnection->hResManContext,
+ RESMAN_TYPE_SERVER_SYNC_PRIMITIVE,
+ psSyncHandleInt,
+ (RESMAN_FREE_FN)&PVRSRVServerSyncFreeKM);
+ if (hSyncHandleInt2 == IMG_NULL)
+ {
+ psSyncPrimServerSecureImportOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto SyncPrimServerSecureImport_exit;
+ }
+ psSyncPrimServerSecureImportOUT->eError = PVRSRVAllocHandle(psConnection->psHandleBase,
+ &psSyncPrimServerSecureImportOUT->hSyncHandle,
+ (IMG_HANDLE) hSyncHandleInt2,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE
+ );
+ if (psSyncPrimServerSecureImportOUT->eError != PVRSRV_OK)
+ {
+ goto SyncPrimServerSecureImport_exit;
+ }
+
+
+SyncPrimServerSecureImport_exit:
+ if (psSyncPrimServerSecureImportOUT->eError != PVRSRV_OK)
+ {
+ /* If we have a valid resman item we should undo the bridge function by freeing the resman item */
+ if (hSyncHandleInt2)
+ {
+ PVRSRV_ERROR eError = ResManFreeResByPtr(hSyncHandleInt2);
+
+ /* Freeing a resource should never fail... */
+ PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+ }
+ else if (psSyncHandleInt)
+ {
+ PVRSRVServerSyncFreeKM(psSyncHandleInt);
+ }
+ }
+
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterSYNCSEXPORTFunctions(IMG_VOID);
+IMG_VOID UnregisterSYNCSEXPORTFunctions(IMG_VOID);
+
+/*
+ * Register all SYNCSEXPORT functions with services
+ */
+PVRSRV_ERROR RegisterSYNCSEXPORTFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCSEXPORT_SYNCPRIMSERVERSECUREEXPORT, PVRSRVBridgeSyncPrimServerSecureExport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCSEXPORT_SYNCPRIMSERVERSECUREUNEXPORT, PVRSRVBridgeSyncPrimServerSecureUnexport);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCSEXPORT_SYNCPRIMSERVERSECUREIMPORT, PVRSRVBridgeSyncPrimServerSecureImport);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all syncsexport functions with services
+ */
+IMG_VOID UnregisterSYNCSEXPORTFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/generated/timerquery_bridge/common_timerquery_bridge.h b/drivers/gpu/rogue/generated/timerquery_bridge/common_timerquery_bridge.h
new file mode 100644
index 000000000000..4a810c6431ff
--- /dev/null
+++ b/drivers/gpu/rogue/generated/timerquery_bridge/common_timerquery_bridge.h
@@ -0,0 +1,134 @@
+/*************************************************************************/ /*!
+@File
+@Title Common bridge header for timerquery
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares common defines and structures that are used by both
+ the client and sever side of the bridge for timerquery
+@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_TIMERQUERY_BRIDGE_H
+#define COMMON_TIMERQUERY_BRIDGE_H
+
+#include "rgx_bridge.h"
+
+
+#include "pvr_bridge_io.h"
+
+#define PVRSRV_BRIDGE_TIMERQUERY_CMD_FIRST (PVRSRV_BRIDGE_TIMERQUERY_START)
+#define PVRSRV_BRIDGE_TIMERQUERY_RGXBEGINTIMERQUERY PVRSRV_IOWR(PVRSRV_BRIDGE_TIMERQUERY_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_TIMERQUERY_RGXENDTIMERQUERY PVRSRV_IOWR(PVRSRV_BRIDGE_TIMERQUERY_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_TIMERQUERY_RGXQUERYTIMER PVRSRV_IOWR(PVRSRV_BRIDGE_TIMERQUERY_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_TIMERQUERY_RGXCURRENTTIME PVRSRV_IOWR(PVRSRV_BRIDGE_TIMERQUERY_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_TIMERQUERY_CMD_LAST (PVRSRV_BRIDGE_TIMERQUERY_CMD_FIRST+3)
+
+
+/*******************************************
+ RGXBeginTimerQuery
+ *******************************************/
+
+/* Bridge in structure for RGXBeginTimerQuery */
+typedef struct PVRSRV_BRIDGE_IN_RGXBEGINTIMERQUERY_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32QueryId;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXBEGINTIMERQUERY;
+
+
+/* Bridge out structure for RGXBeginTimerQuery */
+typedef struct PVRSRV_BRIDGE_OUT_RGXBEGINTIMERQUERY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXBEGINTIMERQUERY;
+
+/*******************************************
+ RGXEndTimerQuery
+ *******************************************/
+
+/* Bridge in structure for RGXEndTimerQuery */
+typedef struct PVRSRV_BRIDGE_IN_RGXENDTIMERQUERY_TAG
+{
+ IMG_HANDLE hDevNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXENDTIMERQUERY;
+
+
+/* Bridge out structure for RGXEndTimerQuery */
+typedef struct PVRSRV_BRIDGE_OUT_RGXENDTIMERQUERY_TAG
+{
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXENDTIMERQUERY;
+
+/*******************************************
+ RGXQueryTimer
+ *******************************************/
+
+/* Bridge in structure for RGXQueryTimer */
+typedef struct PVRSRV_BRIDGE_IN_RGXQUERYTIMER_TAG
+{
+ IMG_HANDLE hDevNode;
+ IMG_UINT32 ui32QueryId;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXQUERYTIMER;
+
+
+/* Bridge out structure for RGXQueryTimer */
+typedef struct PVRSRV_BRIDGE_OUT_RGXQUERYTIMER_TAG
+{
+ IMG_UINT64 ui64StartTime;
+ IMG_UINT64 ui64EndTime;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXQUERYTIMER;
+
+/*******************************************
+ RGXCurrentTime
+ *******************************************/
+
+/* Bridge in structure for RGXCurrentTime */
+typedef struct PVRSRV_BRIDGE_IN_RGXCURRENTTIME_TAG
+{
+ IMG_HANDLE hDevNode;
+} __attribute__((packed)) PVRSRV_BRIDGE_IN_RGXCURRENTTIME;
+
+
+/* Bridge out structure for RGXCurrentTime */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCURRENTTIME_TAG
+{
+ IMG_UINT64 ui64Time;
+ PVRSRV_ERROR eError;
+} __attribute__((packed)) PVRSRV_BRIDGE_OUT_RGXCURRENTTIME;
+
+#endif /* COMMON_TIMERQUERY_BRIDGE_H */
diff --git a/drivers/gpu/rogue/generated/timerquery_bridge/server_timerquery_bridge.c b/drivers/gpu/rogue/generated/timerquery_bridge/server_timerquery_bridge.c
new file mode 100644
index 000000000000..84bebe47f720
--- /dev/null
+++ b/drivers/gpu/rogue/generated/timerquery_bridge/server_timerquery_bridge.c
@@ -0,0 +1,266 @@
+/*************************************************************************/ /*!
+@File
+@Title Server bridge for timerquery
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side of the bridge for timerquery
+@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 <stddef.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+
+#include "rgxtimerquery.h"
+
+
+#include "common_timerquery_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#include "rgx_bridge.h"
+#include "srvcore.h"
+#include "handle.h"
+
+#if defined (SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#include <linux/slab.h>
+
+/* ***************************************************************************
+ * Bridge proxy functions
+ */
+
+
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static IMG_INT
+PVRSRVBridgeRGXBeginTimerQuery(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXBEGINTIMERQUERY *psRGXBeginTimerQueryIN,
+ PVRSRV_BRIDGE_OUT_RGXBEGINTIMERQUERY *psRGXBeginTimerQueryOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_TIMERQUERY_RGXBEGINTIMERQUERY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXBeginTimerQueryOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXBeginTimerQueryIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXBeginTimerQueryOUT->eError != PVRSRV_OK)
+ {
+ goto RGXBeginTimerQuery_exit;
+ }
+
+ }
+
+ psRGXBeginTimerQueryOUT->eError =
+ PVRSRVRGXBeginTimerQueryKM(
+ hDevNodeInt,
+ psRGXBeginTimerQueryIN->ui32QueryId);
+
+
+
+RGXBeginTimerQuery_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXEndTimerQuery(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXENDTIMERQUERY *psRGXEndTimerQueryIN,
+ PVRSRV_BRIDGE_OUT_RGXENDTIMERQUERY *psRGXEndTimerQueryOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_TIMERQUERY_RGXENDTIMERQUERY);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXEndTimerQueryOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXEndTimerQueryIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXEndTimerQueryOUT->eError != PVRSRV_OK)
+ {
+ goto RGXEndTimerQuery_exit;
+ }
+
+ }
+
+ psRGXEndTimerQueryOUT->eError =
+ PVRSRVRGXEndTimerQueryKM(
+ hDevNodeInt);
+
+
+
+RGXEndTimerQuery_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXQueryTimer(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXQUERYTIMER *psRGXQueryTimerIN,
+ PVRSRV_BRIDGE_OUT_RGXQUERYTIMER *psRGXQueryTimerOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_TIMERQUERY_RGXQUERYTIMER);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXQueryTimerOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXQueryTimerIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXQueryTimerOUT->eError != PVRSRV_OK)
+ {
+ goto RGXQueryTimer_exit;
+ }
+
+ }
+
+ psRGXQueryTimerOUT->eError =
+ PVRSRVRGXQueryTimerKM(
+ hDevNodeInt,
+ psRGXQueryTimerIN->ui32QueryId,
+ &psRGXQueryTimerOUT->ui64StartTime,
+ &psRGXQueryTimerOUT->ui64EndTime);
+
+
+
+RGXQueryTimer_exit:
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeRGXCurrentTime(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RGXCURRENTTIME *psRGXCurrentTimeIN,
+ PVRSRV_BRIDGE_OUT_RGXCURRENTTIME *psRGXCurrentTimeOUT,
+ CONNECTION_DATA *psConnection)
+{
+ IMG_HANDLE hDevNodeInt = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_TIMERQUERY_RGXCURRENTTIME);
+
+
+
+
+
+ {
+ /* Look up the address from the handle */
+ psRGXCurrentTimeOUT->eError =
+ PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hDevNodeInt,
+ psRGXCurrentTimeIN->hDevNode,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRGXCurrentTimeOUT->eError != PVRSRV_OK)
+ {
+ goto RGXCurrentTime_exit;
+ }
+
+ }
+
+ psRGXCurrentTimeOUT->eError =
+ PVRSRVRGXCurrentTime(
+ hDevNodeInt,
+ &psRGXCurrentTimeOUT->ui64Time);
+
+
+
+RGXCurrentTime_exit:
+
+ return 0;
+}
+
+
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR RegisterTIMERQUERYFunctions(IMG_VOID);
+IMG_VOID UnregisterTIMERQUERYFunctions(IMG_VOID);
+
+/*
+ * Register all TIMERQUERY functions with services
+ */
+PVRSRV_ERROR RegisterTIMERQUERYFunctions(IMG_VOID)
+{
+ SetDispatchTableEntry(PVRSRV_BRIDGE_TIMERQUERY_RGXBEGINTIMERQUERY, PVRSRVBridgeRGXBeginTimerQuery);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_TIMERQUERY_RGXENDTIMERQUERY, PVRSRVBridgeRGXEndTimerQuery);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_TIMERQUERY_RGXQUERYTIMER, PVRSRVBridgeRGXQueryTimer);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_TIMERQUERY_RGXCURRENTTIME, PVRSRVBridgeRGXCurrentTime);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * Unregister all timerquery functions with services
+ */
+IMG_VOID UnregisterTIMERQUERYFunctions(IMG_VOID)
+{
+}
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.0.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.0.h
new file mode 100644
index 000000000000..f8864f6a5f9d
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.0.h
@@ -0,0 +1,67 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.2.0
+@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_1_V_2_0_H_
+#define _RGXCONFIG_KM_1_V_2_0_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 2
+#define RGX_BNC_KM_C 0
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (2)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_2_0_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.20.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.20.h
new file mode 100644
index 000000000000..0a4caa8ed5d2
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.20.h
@@ -0,0 +1,67 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.2.20
+@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_1_V_2_20_H_
+#define _RGXCONFIG_KM_1_V_2_20_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 2
+#define RGX_BNC_KM_C 20
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (2)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_2_20_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.30.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.30.h
new file mode 100644
index 000000000000..f73651310c6e
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.30.h
@@ -0,0 +1,67 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.2.30
+@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_1_V_2_30_H_
+#define _RGXCONFIG_KM_1_V_2_30_H_
+
+/***** Automatically generated file (11/24/2014 2:08:58 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:58 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 2
+#define RGX_BNC_KM_C 30
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (2)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_2_30_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.5.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.5.h
new file mode 100644
index 000000000000..f5f45b7826cd
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.2.5.h
@@ -0,0 +1,67 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.2.5
+@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_1_V_2_5_H_
+#define _RGXCONFIG_KM_1_V_2_5_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 2
+#define RGX_BNC_KM_C 5
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (2)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_2_5_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.12.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.12.h
new file mode 100644
index 000000000000..a9662208e4f2
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.12.h
@@ -0,0 +1,66 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.4.12
+@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_1_V_4_12_H_
+#define _RGXCONFIG_KM_1_V_4_12_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 4
+#define RGX_BNC_KM_C 12
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (4)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (256*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_4_12_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.15.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.15.h
new file mode 100644
index 000000000000..ec5ca494e6e4
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.15.h
@@ -0,0 +1,67 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.4.15
+@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_1_V_4_15_H_
+#define _RGXCONFIG_KM_1_V_4_15_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 4
+#define RGX_BNC_KM_C 15
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (4)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (256*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_4_15_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.19.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.19.h
new file mode 100644
index 000000000000..acfd425c2467
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.19.h
@@ -0,0 +1,67 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.4.19
+@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_1_V_4_19_H_
+#define _RGXCONFIG_KM_1_V_4_19_H_
+
+/***** Automatically generated file (11/24/2014 2:09:00 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:09:00 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 4
+#define RGX_BNC_KM_C 19
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (4)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_4_19_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.4.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.4.h
new file mode 100644
index 000000000000..38f0941344e8
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.4.h
@@ -0,0 +1,66 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.4.4
+@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_1_V_4_4_H_
+#define _RGXCONFIG_KM_1_V_4_4_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 4
+#define RGX_BNC_KM_C 4
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (4)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_4_4_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.5.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.5.h
new file mode 100644
index 000000000000..24f869a3e078
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.5.h
@@ -0,0 +1,66 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.4.5
+@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_1_V_4_5_H_
+#define _RGXCONFIG_KM_1_V_4_5_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 4
+#define RGX_BNC_KM_C 5
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (4)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_4_5_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.6.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.6.h
new file mode 100644
index 000000000000..e566590e66e2
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_1.V.4.6.h
@@ -0,0 +1,66 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 1.V.4.6
+@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_1_V_4_6_H_
+#define _RGXCONFIG_KM_1_V_4_6_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 1
+#define RGX_BNC_KM_N 4
+#define RGX_BNC_KM_C 6
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (4)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (3)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_1_V_4_6_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.20.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.20.h
new file mode 100644
index 000000000000..4f68912d23ee
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_12.V.1.20.h
@@ -0,0 +1,66 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 12.V.1.20
+@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_12_V_1_20_H_
+#define _RGXCONFIG_KM_12_V_1_20_H_
+
+/***** Automatically generated file (11/24/2014 2:08:58 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:58 PM)************************************************************/
+
+#define RGX_BNC_KM_B 12
+#define RGX_BNC_KM_N 1
+#define RGX_BNC_KM_C 20
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_NUM_CLUSTERS (1)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (1)
+#define RGX_FEATURE_META (LTP217)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (0*1024)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_12_V_1_20_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.51.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.51.h
new file mode 100644
index 000000000000..6464e705d7ae
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.2.51.h
@@ -0,0 +1,69 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 4.V.2.51
+@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_4_V_2_51_H_
+#define _RGXCONFIG_KM_4_V_2_51_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 4
+#define RGX_BNC_KM_N 2
+#define RGX_BNC_KM_C 51
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (2)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_CLUSTER_GROUPING
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
+#define RGX_FEATURE_META (LTP218)
+#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE
+#define RGX_FEATURE_META_COREMEM_SIZE (32)
+
+
+#endif /* _RGXCONFIG_4_V_2_51_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.4.53.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.4.53.h
new file mode 100644
index 000000000000..b3c59e53de26
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.4.53.h
@@ -0,0 +1,69 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 4.V.4.53
+@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_4_V_4_53_H_
+#define _RGXCONFIG_KM_4_V_4_53_H_
+
+/***** Automatically generated file (11/24/2014 2:08:59 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:08:59 PM)************************************************************/
+
+#define RGX_BNC_KM_B 4
+#define RGX_BNC_KM_N 4
+#define RGX_BNC_KM_C 53
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_NUM_CLUSTERS (4)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_CLUSTER_GROUPING
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
+#define RGX_FEATURE_META (LTP218)
+#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE
+#define RGX_FEATURE_META_COREMEM_SIZE (32)
+
+
+#endif /* _RGXCONFIG_4_V_4_53_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.6.61.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.6.61.h
new file mode 100644
index 000000000000..66e39df3e394
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_4.V.6.61.h
@@ -0,0 +1,70 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 4.V.6.61
+@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_4_V_6_61_H_
+#define _RGXCONFIG_KM_4_V_6_61_H_
+
+/***** Automatically generated file (11/24/2014 2:09:00 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:09:00 PM)************************************************************/
+
+#define RGX_BNC_KM_B 4
+#define RGX_BNC_KM_N 6
+#define RGX_BNC_KM_C 61
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_NUM_CLUSTERS (6)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_CLUSTER_GROUPING
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_SLC_BANKS (4)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (8)
+#define RGX_FEATURE_META (LTP218)
+#define RGX_FEATURE_XT_TOP_INFRASTRUCTURE
+#define RGX_FEATURE_META_COREMEM_SIZE (32)
+
+
+#endif /* _RGXCONFIG_4_V_6_61_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.16.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.16.h
new file mode 100644
index 000000000000..471d8fb13869
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.16.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 5.V.1.16
+@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_5_V_1_16_H_
+#define _RGXCONFIG_KM_5_V_1_16_H_
+
+/***** Automatically generated file (11/24/2014 2:09:00 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:09:00 PM)************************************************************/
+
+#define RGX_BNC_KM_B 5
+#define RGX_BNC_KM_N 1
+#define RGX_BNC_KM_C 16
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_NUM_CLUSTERS (1)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (16*1024)
+#define RGX_FEATURE_SLC_BANKS (1)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (1)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_5_V_1_16_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.17.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.17.h
new file mode 100644
index 000000000000..a4df5fc95831
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.17.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 5.V.1.17
+@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_5_V_1_17_H_
+#define _RGXCONFIG_KM_5_V_1_17_H_
+
+/***** Automatically generated file (11/24/2014 2:09:00 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:09:00 PM)************************************************************/
+
+#define RGX_BNC_KM_B 5
+#define RGX_BNC_KM_N 1
+#define RGX_BNC_KM_C 17
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (128*1024)
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_NUM_CLUSTERS (1)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_SLC_BANKS (1)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (1)
+#define RGX_FEATURE_META (MTP218)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_5_V_1_17_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.46.h b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.46.h
new file mode 100644
index 000000000000..71632a9e0ba0
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/configs/rgxconfig_km_5.V.1.46.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@Title RGX Config BVNC 5.V.1.46
+@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_5_V_1_46_H_
+#define _RGXCONFIG_KM_5_V_1_46_H_
+
+/***** Automatically generated file (11/24/2014 2:09:00 PM): Do not edit manually ********************/
+/***** Timestamp: (11/24/2014 2:09:00 PM)************************************************************/
+
+#define RGX_BNC_KM_B 5
+#define RGX_BNC_KM_N 1
+#define RGX_BNC_KM_C 46
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_PHYS_BUS_WIDTH (40)
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512)
+#define RGX_FEATURE_NUM_CLUSTERS (1)
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (16*1024)
+#define RGX_FEATURE_SLC_BANKS (1)
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (1)
+#define RGX_FEATURE_META (LTP217)
+#define RGX_FEATURE_META_COREMEM_SIZE (0)
+
+
+#endif /* _RGXCONFIG_5_V_1_46_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.14.4.4.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.14.4.4.h
new file mode 100644
index 000000000000..1eee2649d75b
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.14.4.4.h
@@ -0,0 +1,75 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.14.4.4
+@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 _RGXCORE_KM_1_14_4_4_H_
+#define _RGXCORE_KM_1_14_4_4_H_
+
+/***** Automatically generated file (10/28/2014 1:55:41 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:41 PM)************************************************************/
+/***** CS: @871575 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.14.4.4
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 14
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 4
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_36492
+#define FIX_HW_BRN_37200
+#define FIX_HW_BRN_38344
+#define FIX_HW_BRN_38835
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_14_4_4_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.31.2.0.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.31.2.0.h
new file mode 100644
index 000000000000..d79ebf387bbb
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.31.2.0.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.31.2.0
+@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 _RGXCORE_KM_1_31_2_0_H_
+#define _RGXCORE_KM_1_31_2_0_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2236231 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.31.2.0
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 31
+#define RGX_BVNC_KM_N 2
+#define RGX_BVNC_KM_C 0
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_31_2_0_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.32.4.19.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.32.4.19.h
new file mode 100644
index 000000000000..0aa5ae99573d
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.32.4.19.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.32.4.19
+@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 _RGXCORE_KM_1_32_4_19_H_
+#define _RGXCORE_KM_1_32_4_19_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2615289 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.32.4.19
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 32
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 19
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_32_4_19_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.33.2.5.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.33.2.5.h
new file mode 100644
index 000000000000..770590e2777e
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.33.2.5.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.33.2.5
+@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 _RGXCORE_KM_1_33_2_5_H_
+#define _RGXCORE_KM_1_33_2_5_H_
+
+/***** Automatically generated file (10/28/2014 1:55:47 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:47 PM)************************************************************/
+/***** CS: @2106753 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.33.2.5
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 33
+#define RGX_BVNC_KM_N 2
+#define RGX_BVNC_KM_C 5
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_33_2_5_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.39.4.19.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.39.4.19.h
new file mode 100644
index 000000000000..5eec9b327497
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.39.4.19.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.39.4.19
+@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 _RGXCORE_KM_1_39_4_19_H_
+#define _RGXCORE_KM_1_39_4_19_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2784771 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.39.4.19
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 39
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 19
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_39_4_19_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.48.2.0.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.48.2.0.h
new file mode 100644
index 000000000000..d018e98b6020
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.48.2.0.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.48.2.0
+@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 _RGXCORE_KM_1_48_2_0_H_
+#define _RGXCORE_KM_1_48_2_0_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2523218 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.48.2.0
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 48
+#define RGX_BVNC_KM_N 2
+#define RGX_BVNC_KM_C 0
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_48_2_0_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.49.4.15.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.49.4.15.h
new file mode 100644
index 000000000000..5782809e9e28
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.49.4.15.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.49.4.15
+@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 _RGXCORE_KM_1_49_4_15_H_
+#define _RGXCORE_KM_1_49_4_15_H_
+
+/***** Automatically generated file (10/28/2014 1:55:47 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:47 PM)************************************************************/
+/***** CS: @2232098 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.49.4.15
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 49
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 15
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_49_4_15_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.67.2.5.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.67.2.5.h
new file mode 100644
index 000000000000..c247200b5d64
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.67.2.5.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.67.2.5
+@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 _RGXCORE_KM_1_67_2_5_H_
+#define _RGXCORE_KM_1_67_2_5_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2363764 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.67.2.5
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 67
+#define RGX_BVNC_KM_N 2
+#define RGX_BVNC_KM_C 5
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_67_2_5_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.7.4.5.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.7.4.5.h
new file mode 100644
index 000000000000..5616389b3aa9
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.7.4.5.h
@@ -0,0 +1,75 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.7.4.5
+@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 _RGXCORE_KM_1_7_4_5_H_
+#define _RGXCORE_KM_1_7_4_5_H_
+
+/***** Automatically generated file (10/28/2014 1:55:40 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:40 PM)************************************************************/
+/***** CS: @871574 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.7.4.5
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 7
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 5
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_36492
+#define FIX_HW_BRN_37200
+#define FIX_HW_BRN_38344
+#define FIX_HW_BRN_38835
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_7_4_5_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.72.4.12.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.72.4.12.h
new file mode 100644
index 000000000000..a675ff644b2a
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.72.4.12.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.72.4.12
+@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 _RGXCORE_KM_1_72_4_12_H_
+#define _RGXCORE_KM_1_72_4_12_H_
+
+/***** Automatically generated file (10/28/2014 1:55:41 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:41 PM)************************************************************/
+/***** CS: @2646650 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.72.4.12
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 72
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 12
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_72_4_12_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.20.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.20.h
new file mode 100644
index 000000000000..e756869ca017
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.20.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.75.2.20
+@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 _RGXCORE_KM_1_75_2_20_H_
+#define _RGXCORE_KM_1_75_2_20_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2309075 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.75.2.20
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 75
+#define RGX_BVNC_KM_N 2
+#define RGX_BVNC_KM_C 20
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_75_2_20_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.30.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.30.h
new file mode 100644
index 000000000000..5b791bdf5627
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.75.2.30.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.75.2.30
+@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 _RGXCORE_KM_1_75_2_30_H_
+#define _RGXCORE_KM_1_75_2_30_H_
+
+/***** Automatically generated file (10/28/2014 1:55:39 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:39 PM)************************************************************/
+/***** CS: @2309075 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.75.2.30
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 75
+#define RGX_BVNC_KM_N 2
+#define RGX_BVNC_KM_C 30
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_75_2_30_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.76.4.6.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.76.4.6.h
new file mode 100644
index 000000000000..51d12ed5537f
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.76.4.6.h
@@ -0,0 +1,73 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.76.4.6
+@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 _RGXCORE_KM_1_76_4_6_H_
+#define _RGXCORE_KM_1_76_4_6_H_
+
+/***** Automatically generated file (10/28/2014 1:55:41 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:41 PM)************************************************************/
+/***** CS: @2318404 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.76.4.6
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 76
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 6
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+#define FIX_HW_BRN_42480
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_76_4_6_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.81.4.15.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.81.4.15.h
new file mode 100644
index 000000000000..51f9da00d650
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.81.4.15.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.81.4.15
+@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 _RGXCORE_KM_1_81_4_15_H_
+#define _RGXCORE_KM_1_81_4_15_H_
+
+/***** Automatically generated file (10/28/2014 1:55:47 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:47 PM)************************************************************/
+/***** CS: @2373516 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.81.4.15
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 81
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 15
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_81_4_15_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.82.4.5.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.82.4.5.h
new file mode 100644
index 000000000000..75fee8133df6
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.82.4.5.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.82.4.5
+@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 _RGXCORE_KM_1_82_4_5_H_
+#define _RGXCORE_KM_1_82_4_5_H_
+
+/***** Automatically generated file (10/28/2014 1:55:40 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:40 PM)************************************************************/
+/***** CS: @2503111 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.82.4.5
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 82
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 5
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_82_4_5_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.85.2.5.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.85.2.5.h
new file mode 100644
index 000000000000..a89ab6f9d1a9
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.85.2.5.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.85.2.5
+@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 _RGXCORE_KM_1_85_2_5_H_
+#define _RGXCORE_KM_1_85_2_5_H_
+
+/***** Automatically generated file (10/28/2014 1:55:47 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:47 PM)************************************************************/
+/***** CS: @2593573 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.85.2.5
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 85
+#define RGX_BVNC_KM_N 2
+#define RGX_BVNC_KM_C 5
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_85_2_5_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.86.4.12.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.86.4.12.h
new file mode 100644
index 000000000000..dfd1f0cc4819
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_1.86.4.12.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 1.86.4.12
+@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 _RGXCORE_KM_1_86_4_12_H_
+#define _RGXCORE_KM_1_86_4_12_H_
+
+/***** Automatically generated file (10/28/2014 1:55:41 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:41 PM)************************************************************/
+/***** CS: @2605542 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 1.86.4.12
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 1
+#define RGX_BVNC_KM_V 86
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 12
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_1_86_4_12_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_12.4.1.20.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_12.4.1.20.h
new file mode 100644
index 000000000000..ac825b1af995
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_12.4.1.20.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 12.4.1.20
+@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 _RGXCORE_KM_12_4_1_20_H_
+#define _RGXCORE_KM_12_4_1_20_H_
+
+/***** Automatically generated file (10/28/2014 1:55:39 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:39 PM)************************************************************/
+/***** CS: @2875741 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 12.4.1.20
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 12
+#define RGX_BVNC_KM_V 4
+#define RGX_BVNC_KM_N 1
+#define RGX_BVNC_KM_C 20
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_12_4_1_20_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.20.4.53.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.20.4.53.h
new file mode 100644
index 000000000000..ac4ecd245ef4
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.20.4.53.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 4.20.4.53
+@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 _RGXCORE_KM_4_20_4_53_H_
+#define _RGXCORE_KM_4_20_4_53_H_
+
+/***** Automatically generated file (10/28/2014 1:55:39 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:39 PM)************************************************************/
+/***** CS: @2849524 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 4.20.4.53
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 4
+#define RGX_BVNC_KM_V 20
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 53
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_4_20_4_53_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.24.6.61.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.24.6.61.h
new file mode 100644
index 000000000000..d7e66aa563aa
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.24.6.61.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 4.24.6.61
+@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 _RGXCORE_KM_4_24_6_61_H_
+#define _RGXCORE_KM_4_24_6_61_H_
+
+/***** Automatically generated file (9/1/2014 12:05:58 PM): Do not edit manually ********************/
+/***** Timestamp: (9/1/2014 12:05:58 PM)************************************************************/
+/***** CS: @2956365 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 4.24.6.61
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 4
+#define RGX_BVNC_KM_V 24
+#define RGX_BVNC_KM_N 6
+#define RGX_BVNC_KM_C 61
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_4_24_6_61_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.29.2.51.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.29.2.51.h
new file mode 100644
index 000000000000..e4ba9ee1e8ae
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.29.2.51.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 4.29.2.51
+@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 _RGXCORE_KM_4_29_2_51_H_
+#define _RGXCORE_KM_4_29_2_51_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2944502 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 4.29.2.51
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 4
+#define RGX_BVNC_KM_V 29
+#define RGX_BVNC_KM_N 2
+#define RGX_BVNC_KM_C 51
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_4_29_2_51_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.33.4.53.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.33.4.53.h
new file mode 100644
index 000000000000..6ecb626fd0ae
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_4.33.4.53.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 4.33.4.53
+@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 _RGXCORE_KM_4_33_4_53_H_
+#define _RGXCORE_KM_4_33_4_53_H_
+
+/***** Automatically generated file (10/28/2014 1:55:39 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:39 PM)************************************************************/
+/***** CS: @2947126 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 4.33.4.53
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 4
+#define RGX_BVNC_KM_V 33
+#define RGX_BVNC_KM_N 4
+#define RGX_BVNC_KM_C 53
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_4_33_4_53_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.5.1.17.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.5.1.17.h
new file mode 100644
index 000000000000..b4c3bb6e353f
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.5.1.17.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 5.5.1.17
+@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 _RGXCORE_KM_5_5_1_17_H_
+#define _RGXCORE_KM_5_5_1_17_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2546826 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 5.5.1.17
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 5
+#define RGX_BVNC_KM_V 5
+#define RGX_BVNC_KM_N 1
+#define RGX_BVNC_KM_C 17
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_5_5_1_17_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.6.1.17.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.6.1.17.h
new file mode 100644
index 000000000000..dbe36ddb56ca
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.6.1.17.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 5.6.1.17
+@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 _RGXCORE_KM_5_6_1_17_H_
+#define _RGXCORE_KM_5_6_1_17_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2608598 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 5.6.1.17
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 5
+#define RGX_BVNC_KM_V 6
+#define RGX_BVNC_KM_N 1
+#define RGX_BVNC_KM_C 17
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_5_6_1_17_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.8.1.16.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.8.1.16.h
new file mode 100644
index 000000000000..51988a47fb39
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.8.1.16.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 5.8.1.16
+@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 _RGXCORE_KM_5_8_1_16_H_
+#define _RGXCORE_KM_5_8_1_16_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2882464 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 5.8.1.16
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 5
+#define RGX_BVNC_KM_V 8
+#define RGX_BVNC_KM_N 1
+#define RGX_BVNC_KM_C 16
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_5_8_1_16_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.9.1.46.h b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.9.1.46.h
new file mode 100644
index 000000000000..048eadc40cdc
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/cores/rgxcore_km_5.9.1.46.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@Title RGX Core BVNC 5.9.1.46
+@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 _RGXCORE_KM_5_9_1_46_H_
+#define _RGXCORE_KM_5_9_1_46_H_
+
+/***** Automatically generated file (10/28/2014 1:55:48 PM): Do not edit manually ********************/
+/***** Timestamp: (10/28/2014 1:55:48 PM)************************************************************/
+/***** CS: @2967148 ******************************************************************/
+
+
+/******************************************************************************
+ * BVNC = 5.9.1.46
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 5
+#define RGX_BVNC_KM_V 9
+#define RGX_BVNC_KM_N 1
+#define RGX_BVNC_KM_C 46
+
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
+
+#define FIX_HW_BRN_38344
+
+
+
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+
+
+
+#endif /* _RGXCORE_KM_5_9_1_46_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/rgx_cr_defs_km.h b/drivers/gpu/rogue/hwdefs/km/rgx_cr_defs_km.h
new file mode 100644
index 000000000000..463a5ad6b620
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/rgx_cr_defs_km.h
@@ -0,0 +1,4069 @@
+/*************************************************************************/ /*!
+@Title Hardware definition file rgx_cr_defs_km.h
+@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.
+*/ /**************************************************************************/
+
+/* **** Autogenerated C -- do not edit **** */
+
+/*
+ * Generated by regconv version MAIN@2782796
+ * from files:
+ */
+
+#if !defined(__IMG_EXPLICIT_INCLUDE_HWDEFS)
+#error This file may only be included if explicitly defined
+#endif
+
+#ifndef _RGX_CR_DEFS_KM_H_
+#define _RGX_CR_DEFS_KM_H_
+
+#include "img_types.h"
+
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*
+
+ Core Module Clock Control Modes.
+
+
+ Allows individual domain clocks to be forced off, forced on or operate under automatic pipeline activity based clock gating. This register is generally controlled by the GPU firmware and should be set to AUTO. Clock gating reduces the power consumed by the device.
+
+*/
+/*
+ Register RGX_CR_CLK_CTRL
+*/
+#define RGX_CR_CLK_CTRL (0x0000U)
+#define RGX_CR_CLK_CTRL_MASKFULL (IMG_UINT64_C(0xFFFFC3003F3F3F0F))
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+/* BIF_TEXAS default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_SHIFT (62U)
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_CLRMSK (IMG_UINT64_C(0X3FFFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_ON (IMG_UINT64_C(0x4000000000000000))
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_AUTO (IMG_UINT64_C(0x8000000000000000))
+/* IPP default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_IPP_SHIFT (60U)
+#define RGX_CR_CLK_CTRL_IPP_CLRMSK (IMG_UINT64_C(0XCFFFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_IPP_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_IPP_ON (IMG_UINT64_C(0x1000000000000000))
+#define RGX_CR_CLK_CTRL_IPP_AUTO (IMG_UINT64_C(0x2000000000000000))
+#endif /* RGX_FEATURE_CLUSTER_GROUPING */
+
+/* FBC default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_FBC_SHIFT (58U)
+#define RGX_CR_CLK_CTRL_FBC_CLRMSK (IMG_UINT64_C(0XF3FFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_FBC_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_FBC_ON (IMG_UINT64_C(0x0400000000000000))
+#define RGX_CR_CLK_CTRL_FBC_AUTO (IMG_UINT64_C(0x0800000000000000))
+/* FBDC default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_FBDC_SHIFT (56U)
+#define RGX_CR_CLK_CTRL_FBDC_CLRMSK (IMG_UINT64_C(0XFCFFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_FBDC_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_FBDC_ON (IMG_UINT64_C(0x0100000000000000))
+#define RGX_CR_CLK_CTRL_FBDC_AUTO (IMG_UINT64_C(0x0200000000000000))
+/* FB_TLCACHE default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_SHIFT (54U)
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_CLRMSK (IMG_UINT64_C(0XFF3FFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_ON (IMG_UINT64_C(0x0040000000000000))
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_AUTO (IMG_UINT64_C(0x0080000000000000))
+/* USCS default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_USCS_SHIFT (52U)
+#define RGX_CR_CLK_CTRL_USCS_CLRMSK (IMG_UINT64_C(0XFFCFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_USCS_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_USCS_ON (IMG_UINT64_C(0x0010000000000000))
+#define RGX_CR_CLK_CTRL_USCS_AUTO (IMG_UINT64_C(0x0020000000000000))
+/* PBE default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_PBE_SHIFT (50U)
+#define RGX_CR_CLK_CTRL_PBE_CLRMSK (IMG_UINT64_C(0XFFF3FFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_PBE_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_PBE_ON (IMG_UINT64_C(0x0004000000000000))
+#define RGX_CR_CLK_CTRL_PBE_AUTO (IMG_UINT64_C(0x0008000000000000))
+/* MCU_l1 default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_MCU_L1_SHIFT (48U)
+#define RGX_CR_CLK_CTRL_MCU_L1_CLRMSK (IMG_UINT64_C(0XFFFCFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_MCU_L1_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_MCU_L1_ON (IMG_UINT64_C(0x0001000000000000))
+#define RGX_CR_CLK_CTRL_MCU_L1_AUTO (IMG_UINT64_C(0x0002000000000000))
+/* CDM default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_CDM_SHIFT (46U)
+#define RGX_CR_CLK_CTRL_CDM_CLRMSK (IMG_UINT64_C(0XFFFF3FFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_CDM_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_CDM_ON (IMG_UINT64_C(0x0000400000000000))
+#define RGX_CR_CLK_CTRL_CDM_AUTO (IMG_UINT64_C(0x0000800000000000))
+/* BIF default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_BIF_SHIFT (40U)
+#define RGX_CR_CLK_CTRL_BIF_CLRMSK (IMG_UINT64_C(0XFFFFFCFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_BIF_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_BIF_ON (IMG_UINT64_C(0x0000010000000000))
+#define RGX_CR_CLK_CTRL_BIF_AUTO (IMG_UINT64_C(0x0000020000000000))
+/* TPU_MCU_DEMUX default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_SHIFT (28U)
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_CLRMSK (IMG_UINT64_C(0XFFFFFFFFCFFFFFFF))
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_ON (IMG_UINT64_C(0x0000000010000000))
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_AUTO (IMG_UINT64_C(0x0000000020000000))
+/* MCU_L0 default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_MCU_L0_SHIFT (26U)
+#define RGX_CR_CLK_CTRL_MCU_L0_CLRMSK (IMG_UINT64_C(0XFFFFFFFFF3FFFFFF))
+#define RGX_CR_CLK_CTRL_MCU_L0_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_MCU_L0_ON (IMG_UINT64_C(0x0000000004000000))
+#define RGX_CR_CLK_CTRL_MCU_L0_AUTO (IMG_UINT64_C(0x0000000008000000))
+/* TPU default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_TPU_SHIFT (24U)
+#define RGX_CR_CLK_CTRL_TPU_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFCFFFFFF))
+#define RGX_CR_CLK_CTRL_TPU_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_TPU_ON (IMG_UINT64_C(0x0000000001000000))
+#define RGX_CR_CLK_CTRL_TPU_AUTO (IMG_UINT64_C(0x0000000002000000))
+/* USC default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_USC_SHIFT (20U)
+#define RGX_CR_CLK_CTRL_USC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFCFFFFF))
+#define RGX_CR_CLK_CTRL_USC_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_USC_ON (IMG_UINT64_C(0x0000000000100000))
+#define RGX_CR_CLK_CTRL_USC_AUTO (IMG_UINT64_C(0x0000000000200000))
+/* TLA default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_TLA_SHIFT (18U)
+#define RGX_CR_CLK_CTRL_TLA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFF3FFFF))
+#define RGX_CR_CLK_CTRL_TLA_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_TLA_ON (IMG_UINT64_C(0x0000000000040000))
+#define RGX_CR_CLK_CTRL_TLA_AUTO (IMG_UINT64_C(0x0000000000080000))
+/* SLC default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_SLC_SHIFT (16U)
+#define RGX_CR_CLK_CTRL_SLC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFCFFFF))
+#define RGX_CR_CLK_CTRL_SLC_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_SLC_ON (IMG_UINT64_C(0x0000000000010000))
+#define RGX_CR_CLK_CTRL_SLC_AUTO (IMG_UINT64_C(0x0000000000020000))
+/* PDS default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_PDS_SHIFT (12U)
+#define RGX_CR_CLK_CTRL_PDS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFCFFF))
+#define RGX_CR_CLK_CTRL_PDS_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_PDS_ON (IMG_UINT64_C(0x0000000000001000))
+#define RGX_CR_CLK_CTRL_PDS_AUTO (IMG_UINT64_C(0x0000000000002000))
+/* VDM default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_VDM_SHIFT (10U)
+#define RGX_CR_CLK_CTRL_VDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF3FF))
+#define RGX_CR_CLK_CTRL_VDM_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_VDM_ON (IMG_UINT64_C(0x0000000000000400))
+#define RGX_CR_CLK_CTRL_VDM_AUTO (IMG_UINT64_C(0x0000000000000800))
+/* PM default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_PM_SHIFT (8U)
+#define RGX_CR_CLK_CTRL_PM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
+#define RGX_CR_CLK_CTRL_PM_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_PM_ON (IMG_UINT64_C(0x0000000000000100))
+#define RGX_CR_CLK_CTRL_PM_AUTO (IMG_UINT64_C(0x0000000000000200))
+/* TSP default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_TSP_SHIFT (2U)
+#define RGX_CR_CLK_CTRL_TSP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF3))
+#define RGX_CR_CLK_CTRL_TSP_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_TSP_ON (IMG_UINT64_C(0x0000000000000004))
+#define RGX_CR_CLK_CTRL_TSP_AUTO (IMG_UINT64_C(0x0000000000000008))
+/* ISP default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_ISP_SHIFT (0U)
+#define RGX_CR_CLK_CTRL_ISP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
+#define RGX_CR_CLK_CTRL_ISP_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_ISP_ON (IMG_UINT64_C(0x0000000000000001))
+#define RGX_CR_CLK_CTRL_ISP_AUTO (IMG_UINT64_C(0x0000000000000002))
+#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
+
+
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*
+
+ Core Module Clock Control Modes.
+
+
+ Allows individual domain clocks to be forced off, forced on or operate under automatic pipeline activity based clock gating. This register is generally controlled by the GPU firmware and should be set to AUTO. Clock gating reduces the power consumed by the device.
+
+*/
+/*
+ Register RGX_CR_CLK_CTRL
+*/
+#define RGX_CR_CLK_CTRL (0x0000U)
+#define RGX_CR_CLK_CTRL_MASKFULL (IMG_UINT64_C(0xFFFFFF003F3FFFFF))
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+/* BIF_TEXAS default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_SHIFT (62U)
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_CLRMSK (IMG_UINT64_C(0X3FFFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_ON (IMG_UINT64_C(0x4000000000000000))
+#define RGX_CR_CLK_CTRL_BIF_TEXAS_AUTO (IMG_UINT64_C(0x8000000000000000))
+/* IPP default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_IPP_SHIFT (60U)
+#define RGX_CR_CLK_CTRL_IPP_CLRMSK (IMG_UINT64_C(0XCFFFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_IPP_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_IPP_ON (IMG_UINT64_C(0x1000000000000000))
+#define RGX_CR_CLK_CTRL_IPP_AUTO (IMG_UINT64_C(0x2000000000000000))
+#endif /* RGX_FEATURE_CLUSTER_GROUPING */
+
+/* FBC default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_FBC_SHIFT (58U)
+#define RGX_CR_CLK_CTRL_FBC_CLRMSK (IMG_UINT64_C(0XF3FFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_FBC_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_FBC_ON (IMG_UINT64_C(0x0400000000000000))
+#define RGX_CR_CLK_CTRL_FBC_AUTO (IMG_UINT64_C(0x0800000000000000))
+/* FBDC default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_FBDC_SHIFT (56U)
+#define RGX_CR_CLK_CTRL_FBDC_CLRMSK (IMG_UINT64_C(0XFCFFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_FBDC_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_FBDC_ON (IMG_UINT64_C(0x0100000000000000))
+#define RGX_CR_CLK_CTRL_FBDC_AUTO (IMG_UINT64_C(0x0200000000000000))
+/* FB_TLCACHE default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_SHIFT (54U)
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_CLRMSK (IMG_UINT64_C(0XFF3FFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_ON (IMG_UINT64_C(0x0040000000000000))
+#define RGX_CR_CLK_CTRL_FB_TLCACHE_AUTO (IMG_UINT64_C(0x0080000000000000))
+/* USCS default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_USCS_SHIFT (52U)
+#define RGX_CR_CLK_CTRL_USCS_CLRMSK (IMG_UINT64_C(0XFFCFFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_USCS_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_USCS_ON (IMG_UINT64_C(0x0010000000000000))
+#define RGX_CR_CLK_CTRL_USCS_AUTO (IMG_UINT64_C(0x0020000000000000))
+/* PBE default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_PBE_SHIFT (50U)
+#define RGX_CR_CLK_CTRL_PBE_CLRMSK (IMG_UINT64_C(0XFFF3FFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_PBE_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_PBE_ON (IMG_UINT64_C(0x0004000000000000))
+#define RGX_CR_CLK_CTRL_PBE_AUTO (IMG_UINT64_C(0x0008000000000000))
+/* MCU_l1 default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_MCU_L1_SHIFT (48U)
+#define RGX_CR_CLK_CTRL_MCU_L1_CLRMSK (IMG_UINT64_C(0XFFFCFFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_MCU_L1_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_MCU_L1_ON (IMG_UINT64_C(0x0001000000000000))
+#define RGX_CR_CLK_CTRL_MCU_L1_AUTO (IMG_UINT64_C(0x0002000000000000))
+/* CDM default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_CDM_SHIFT (46U)
+#define RGX_CR_CLK_CTRL_CDM_CLRMSK (IMG_UINT64_C(0XFFFF3FFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_CDM_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_CDM_ON (IMG_UINT64_C(0x0000400000000000))
+#define RGX_CR_CLK_CTRL_CDM_AUTO (IMG_UINT64_C(0x0000800000000000))
+/* SIDEKICK default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_SIDEKICK_SHIFT (44U)
+#define RGX_CR_CLK_CTRL_SIDEKICK_CLRMSK (IMG_UINT64_C(0XFFFFCFFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_SIDEKICK_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_SIDEKICK_ON (IMG_UINT64_C(0x0000100000000000))
+#define RGX_CR_CLK_CTRL_SIDEKICK_AUTO (IMG_UINT64_C(0x0000200000000000))
+/* BIF_SIDEKICK default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_SHIFT (42U)
+#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_CLRMSK (IMG_UINT64_C(0XFFFFF3FFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_ON (IMG_UINT64_C(0x0000040000000000))
+#define RGX_CR_CLK_CTRL_BIF_SIDEKICK_AUTO (IMG_UINT64_C(0x0000080000000000))
+/* BIF default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_BIF_SHIFT (40U)
+#define RGX_CR_CLK_CTRL_BIF_CLRMSK (IMG_UINT64_C(0XFFFFFCFFFFFFFFFF))
+#define RGX_CR_CLK_CTRL_BIF_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_BIF_ON (IMG_UINT64_C(0x0000010000000000))
+#define RGX_CR_CLK_CTRL_BIF_AUTO (IMG_UINT64_C(0x0000020000000000))
+/* TPU_MCU_DEMUX default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_SHIFT (28U)
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_CLRMSK (IMG_UINT64_C(0XFFFFFFFFCFFFFFFF))
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_ON (IMG_UINT64_C(0x0000000010000000))
+#define RGX_CR_CLK_CTRL_TPU_MCU_DEMUX_AUTO (IMG_UINT64_C(0x0000000020000000))
+/* MCU_L0 default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_MCU_L0_SHIFT (26U)
+#define RGX_CR_CLK_CTRL_MCU_L0_CLRMSK (IMG_UINT64_C(0XFFFFFFFFF3FFFFFF))
+#define RGX_CR_CLK_CTRL_MCU_L0_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_MCU_L0_ON (IMG_UINT64_C(0x0000000004000000))
+#define RGX_CR_CLK_CTRL_MCU_L0_AUTO (IMG_UINT64_C(0x0000000008000000))
+/* TPU default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_TPU_SHIFT (24U)
+#define RGX_CR_CLK_CTRL_TPU_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFCFFFFFF))
+#define RGX_CR_CLK_CTRL_TPU_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_TPU_ON (IMG_UINT64_C(0x0000000001000000))
+#define RGX_CR_CLK_CTRL_TPU_AUTO (IMG_UINT64_C(0x0000000002000000))
+/* USC default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_USC_SHIFT (20U)
+#define RGX_CR_CLK_CTRL_USC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFCFFFFF))
+#define RGX_CR_CLK_CTRL_USC_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_USC_ON (IMG_UINT64_C(0x0000000000100000))
+#define RGX_CR_CLK_CTRL_USC_AUTO (IMG_UINT64_C(0x0000000000200000))
+/* TLA default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_TLA_SHIFT (18U)
+#define RGX_CR_CLK_CTRL_TLA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFF3FFFF))
+#define RGX_CR_CLK_CTRL_TLA_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_TLA_ON (IMG_UINT64_C(0x0000000000040000))
+#define RGX_CR_CLK_CTRL_TLA_AUTO (IMG_UINT64_C(0x0000000000080000))
+/* SLC default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_SLC_SHIFT (16U)
+#define RGX_CR_CLK_CTRL_SLC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFCFFFF))
+#define RGX_CR_CLK_CTRL_SLC_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_SLC_ON (IMG_UINT64_C(0x0000000000010000))
+#define RGX_CR_CLK_CTRL_SLC_AUTO (IMG_UINT64_C(0x0000000000020000))
+/* UVS default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_UVS_SHIFT (14U)
+#define RGX_CR_CLK_CTRL_UVS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFF3FFF))
+#define RGX_CR_CLK_CTRL_UVS_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_UVS_ON (IMG_UINT64_C(0x0000000000004000))
+#define RGX_CR_CLK_CTRL_UVS_AUTO (IMG_UINT64_C(0x0000000000008000))
+/* PDS default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_PDS_SHIFT (12U)
+#define RGX_CR_CLK_CTRL_PDS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFCFFF))
+#define RGX_CR_CLK_CTRL_PDS_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_PDS_ON (IMG_UINT64_C(0x0000000000001000))
+#define RGX_CR_CLK_CTRL_PDS_AUTO (IMG_UINT64_C(0x0000000000002000))
+/* VDM default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_VDM_SHIFT (10U)
+#define RGX_CR_CLK_CTRL_VDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF3FF))
+#define RGX_CR_CLK_CTRL_VDM_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_VDM_ON (IMG_UINT64_C(0x0000000000000400))
+#define RGX_CR_CLK_CTRL_VDM_AUTO (IMG_UINT64_C(0x0000000000000800))
+/* PM default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_PM_SHIFT (8U)
+#define RGX_CR_CLK_CTRL_PM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
+#define RGX_CR_CLK_CTRL_PM_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_PM_ON (IMG_UINT64_C(0x0000000000000100))
+#define RGX_CR_CLK_CTRL_PM_AUTO (IMG_UINT64_C(0x0000000000000200))
+/* GPP default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_GPP_SHIFT (6U)
+#define RGX_CR_CLK_CTRL_GPP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFF3F))
+#define RGX_CR_CLK_CTRL_GPP_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_GPP_ON (IMG_UINT64_C(0x0000000000000040))
+#define RGX_CR_CLK_CTRL_GPP_AUTO (IMG_UINT64_C(0x0000000000000080))
+/* TE default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_TE_SHIFT (4U)
+#define RGX_CR_CLK_CTRL_TE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFCF))
+#define RGX_CR_CLK_CTRL_TE_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_TE_ON (IMG_UINT64_C(0x0000000000000010))
+#define RGX_CR_CLK_CTRL_TE_AUTO (IMG_UINT64_C(0x0000000000000020))
+/* TSP default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_TSP_SHIFT (2U)
+#define RGX_CR_CLK_CTRL_TSP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF3))
+#define RGX_CR_CLK_CTRL_TSP_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_TSP_ON (IMG_UINT64_C(0x0000000000000004))
+#define RGX_CR_CLK_CTRL_TSP_AUTO (IMG_UINT64_C(0x0000000000000008))
+/* ISP default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL_ISP_SHIFT (0U)
+#define RGX_CR_CLK_CTRL_ISP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
+#define RGX_CR_CLK_CTRL_ISP_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL_ISP_ON (IMG_UINT64_C(0x0000000000000001))
+#define RGX_CR_CLK_CTRL_ISP_AUTO (IMG_UINT64_C(0x0000000000000002))
+#endif /* !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) */
+
+
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*
+
+ Reports the current module clock status
+
+
+ Clock gating state reflects the condition of the clock for each module
+
+*/
+/*
+ Register RGX_CR_CLK_STATUS
+*/
+#define RGX_CR_CLK_STATUS (0x0008U)
+#define RGX_CR_CLK_STATUS_MASKFULL (IMG_UINT64_C(0x00000001FF907773))
+/* MCU_FBTC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_MCU_FBTC_SHIFT (32U)
+#define RGX_CR_CLK_STATUS_MCU_FBTC_CLRMSK (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
+#define RGX_CR_CLK_STATUS_MCU_FBTC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_MCU_FBTC_RUNNING (IMG_UINT64_C(0x0000000100000000))
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+/* BIF_TEXAS default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_SHIFT (31U)
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_CLRMSK (IMG_UINT64_C(0XFFFFFFFF7FFFFFFF))
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_RUNNING (IMG_UINT64_C(0x0000000080000000))
+/* IPP default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_IPP_SHIFT (30U)
+#define RGX_CR_CLK_STATUS_IPP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFBFFFFFFF))
+#define RGX_CR_CLK_STATUS_IPP_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_IPP_RUNNING (IMG_UINT64_C(0x0000000040000000))
+#endif /* RGX_FEATURE_CLUSTER_GROUPING */
+
+/* FBC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_FBC_SHIFT (29U)
+#define RGX_CR_CLK_STATUS_FBC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFDFFFFFFF))
+#define RGX_CR_CLK_STATUS_FBC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_FBC_RUNNING (IMG_UINT64_C(0x0000000020000000))
+/* FBDC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_FBDC_SHIFT (28U)
+#define RGX_CR_CLK_STATUS_FBDC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFEFFFFFFF))
+#define RGX_CR_CLK_STATUS_FBDC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_FBDC_RUNNING (IMG_UINT64_C(0x0000000010000000))
+/* FB_TLCACHE default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_SHIFT (27U)
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFF7FFFFFF))
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_RUNNING (IMG_UINT64_C(0x0000000008000000))
+/* USCS default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_USCS_SHIFT (26U)
+#define RGX_CR_CLK_STATUS_USCS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFBFFFFFF))
+#define RGX_CR_CLK_STATUS_USCS_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_USCS_RUNNING (IMG_UINT64_C(0x0000000004000000))
+/* PBE default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_PBE_SHIFT (25U)
+#define RGX_CR_CLK_STATUS_PBE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFDFFFFFF))
+#define RGX_CR_CLK_STATUS_PBE_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_PBE_RUNNING (IMG_UINT64_C(0x0000000002000000))
+/* MCU_L1 default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_MCU_L1_SHIFT (24U)
+#define RGX_CR_CLK_STATUS_MCU_L1_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFEFFFFFF))
+#define RGX_CR_CLK_STATUS_MCU_L1_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_MCU_L1_RUNNING (IMG_UINT64_C(0x0000000001000000))
+/* CDM default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_CDM_SHIFT (23U)
+#define RGX_CR_CLK_STATUS_CDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFF7FFFFF))
+#define RGX_CR_CLK_STATUS_CDM_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_CDM_RUNNING (IMG_UINT64_C(0x0000000000800000))
+/* BIF default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_BIF_SHIFT (20U)
+#define RGX_CR_CLK_STATUS_BIF_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFEFFFFF))
+#define RGX_CR_CLK_STATUS_BIF_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_BIF_RUNNING (IMG_UINT64_C(0x0000000000100000))
+/* TPU_MCU_DEMUX default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_SHIFT (14U)
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFBFFF))
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_RUNNING (IMG_UINT64_C(0x0000000000004000))
+/* MCU_L0 default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_MCU_L0_SHIFT (13U)
+#define RGX_CR_CLK_STATUS_MCU_L0_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFDFFF))
+#define RGX_CR_CLK_STATUS_MCU_L0_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_MCU_L0_RUNNING (IMG_UINT64_C(0x0000000000002000))
+/* TPU default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_TPU_SHIFT (12U)
+#define RGX_CR_CLK_STATUS_TPU_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFEFFF))
+#define RGX_CR_CLK_STATUS_TPU_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_TPU_RUNNING (IMG_UINT64_C(0x0000000000001000))
+/* USC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_USC_SHIFT (10U)
+#define RGX_CR_CLK_STATUS_USC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
+#define RGX_CR_CLK_STATUS_USC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_USC_RUNNING (IMG_UINT64_C(0x0000000000000400))
+/* TLA default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_TLA_SHIFT (9U)
+#define RGX_CR_CLK_STATUS_TLA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFDFF))
+#define RGX_CR_CLK_STATUS_TLA_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_TLA_RUNNING (IMG_UINT64_C(0x0000000000000200))
+/* SLC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_SLC_SHIFT (8U)
+#define RGX_CR_CLK_STATUS_SLC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
+#define RGX_CR_CLK_STATUS_SLC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_SLC_RUNNING (IMG_UINT64_C(0x0000000000000100))
+/* PDS default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_PDS_SHIFT (6U)
+#define RGX_CR_CLK_STATUS_PDS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFBF))
+#define RGX_CR_CLK_STATUS_PDS_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_PDS_RUNNING (IMG_UINT64_C(0x0000000000000040))
+/* VDM default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_VDM_SHIFT (5U)
+#define RGX_CR_CLK_STATUS_VDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_CLK_STATUS_VDM_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_VDM_RUNNING (IMG_UINT64_C(0x0000000000000020))
+/* PM default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_PM_SHIFT (4U)
+#define RGX_CR_CLK_STATUS_PM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
+#define RGX_CR_CLK_STATUS_PM_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_PM_RUNNING (IMG_UINT64_C(0x0000000000000010))
+/* TSP default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_TSP_SHIFT (1U)
+#define RGX_CR_CLK_STATUS_TSP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
+#define RGX_CR_CLK_STATUS_TSP_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_TSP_RUNNING (IMG_UINT64_C(0x0000000000000002))
+/* ISP default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_ISP_SHIFT (0U)
+#define RGX_CR_CLK_STATUS_ISP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_CLK_STATUS_ISP_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_ISP_RUNNING (IMG_UINT64_C(0x0000000000000001))
+#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
+
+
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*
+
+ Reports the current module clock status
+
+
+ Clock gating state reflects the condition of the clock for each module
+
+*/
+/*
+ Register RGX_CR_CLK_STATUS
+*/
+#define RGX_CR_CLK_STATUS (0x0008U)
+#define RGX_CR_CLK_STATUS_MASKFULL (IMG_UINT64_C(0x00000001FFF077FF))
+/* MCU_FBTC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_MCU_FBTC_SHIFT (32U)
+#define RGX_CR_CLK_STATUS_MCU_FBTC_CLRMSK (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
+#define RGX_CR_CLK_STATUS_MCU_FBTC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_MCU_FBTC_RUNNING (IMG_UINT64_C(0x0000000100000000))
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+/* BIF_TEXAS default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_SHIFT (31U)
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_CLRMSK (IMG_UINT64_C(0XFFFFFFFF7FFFFFFF))
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_BIF_TEXAS_RUNNING (IMG_UINT64_C(0x0000000080000000))
+/* IPP default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_IPP_SHIFT (30U)
+#define RGX_CR_CLK_STATUS_IPP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFBFFFFFFF))
+#define RGX_CR_CLK_STATUS_IPP_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_IPP_RUNNING (IMG_UINT64_C(0x0000000040000000))
+#endif /* RGX_FEATURE_CLUSTER_GROUPING */
+
+/* FBC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_FBC_SHIFT (29U)
+#define RGX_CR_CLK_STATUS_FBC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFDFFFFFFF))
+#define RGX_CR_CLK_STATUS_FBC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_FBC_RUNNING (IMG_UINT64_C(0x0000000020000000))
+/* FBDC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_FBDC_SHIFT (28U)
+#define RGX_CR_CLK_STATUS_FBDC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFEFFFFFFF))
+#define RGX_CR_CLK_STATUS_FBDC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_FBDC_RUNNING (IMG_UINT64_C(0x0000000010000000))
+/* FB_TLCACHE default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_SHIFT (27U)
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFF7FFFFFF))
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_FB_TLCACHE_RUNNING (IMG_UINT64_C(0x0000000008000000))
+/* USCS default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_USCS_SHIFT (26U)
+#define RGX_CR_CLK_STATUS_USCS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFBFFFFFF))
+#define RGX_CR_CLK_STATUS_USCS_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_USCS_RUNNING (IMG_UINT64_C(0x0000000004000000))
+/* PBE default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_PBE_SHIFT (25U)
+#define RGX_CR_CLK_STATUS_PBE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFDFFFFFF))
+#define RGX_CR_CLK_STATUS_PBE_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_PBE_RUNNING (IMG_UINT64_C(0x0000000002000000))
+/* MCU_L1 default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_MCU_L1_SHIFT (24U)
+#define RGX_CR_CLK_STATUS_MCU_L1_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFEFFFFFF))
+#define RGX_CR_CLK_STATUS_MCU_L1_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_MCU_L1_RUNNING (IMG_UINT64_C(0x0000000001000000))
+/* CDM default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_CDM_SHIFT (23U)
+#define RGX_CR_CLK_STATUS_CDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFF7FFFFF))
+#define RGX_CR_CLK_STATUS_CDM_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_CDM_RUNNING (IMG_UINT64_C(0x0000000000800000))
+/* SIDEKICK default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_SIDEKICK_SHIFT (22U)
+#define RGX_CR_CLK_STATUS_SIDEKICK_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFBFFFFF))
+#define RGX_CR_CLK_STATUS_SIDEKICK_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_SIDEKICK_RUNNING (IMG_UINT64_C(0x0000000000400000))
+/* BIF_SIDEKICK default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_SHIFT (21U)
+#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFDFFFFF))
+#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_BIF_SIDEKICK_RUNNING (IMG_UINT64_C(0x0000000000200000))
+/* BIF default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_BIF_SHIFT (20U)
+#define RGX_CR_CLK_STATUS_BIF_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFEFFFFF))
+#define RGX_CR_CLK_STATUS_BIF_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_BIF_RUNNING (IMG_UINT64_C(0x0000000000100000))
+/* TPU_MCU_DEMUX default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_SHIFT (14U)
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFBFFF))
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_TPU_MCU_DEMUX_RUNNING (IMG_UINT64_C(0x0000000000004000))
+/* MCU_L0 default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_MCU_L0_SHIFT (13U)
+#define RGX_CR_CLK_STATUS_MCU_L0_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFDFFF))
+#define RGX_CR_CLK_STATUS_MCU_L0_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_MCU_L0_RUNNING (IMG_UINT64_C(0x0000000000002000))
+/* TPU default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_TPU_SHIFT (12U)
+#define RGX_CR_CLK_STATUS_TPU_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFEFFF))
+#define RGX_CR_CLK_STATUS_TPU_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_TPU_RUNNING (IMG_UINT64_C(0x0000000000001000))
+/* USC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_USC_SHIFT (10U)
+#define RGX_CR_CLK_STATUS_USC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
+#define RGX_CR_CLK_STATUS_USC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_USC_RUNNING (IMG_UINT64_C(0x0000000000000400))
+/* TLA default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_TLA_SHIFT (9U)
+#define RGX_CR_CLK_STATUS_TLA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFDFF))
+#define RGX_CR_CLK_STATUS_TLA_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_TLA_RUNNING (IMG_UINT64_C(0x0000000000000200))
+/* SLC default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_SLC_SHIFT (8U)
+#define RGX_CR_CLK_STATUS_SLC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
+#define RGX_CR_CLK_STATUS_SLC_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_SLC_RUNNING (IMG_UINT64_C(0x0000000000000100))
+/* UVS default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_UVS_SHIFT (7U)
+#define RGX_CR_CLK_STATUS_UVS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFF7F))
+#define RGX_CR_CLK_STATUS_UVS_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_UVS_RUNNING (IMG_UINT64_C(0x0000000000000080))
+/* PDS default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_PDS_SHIFT (6U)
+#define RGX_CR_CLK_STATUS_PDS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFBF))
+#define RGX_CR_CLK_STATUS_PDS_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_PDS_RUNNING (IMG_UINT64_C(0x0000000000000040))
+/* VDM default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_VDM_SHIFT (5U)
+#define RGX_CR_CLK_STATUS_VDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_CLK_STATUS_VDM_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_VDM_RUNNING (IMG_UINT64_C(0x0000000000000020))
+/* PM default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_PM_SHIFT (4U)
+#define RGX_CR_CLK_STATUS_PM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
+#define RGX_CR_CLK_STATUS_PM_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_PM_RUNNING (IMG_UINT64_C(0x0000000000000010))
+/* GPP default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_GPP_SHIFT (3U)
+#define RGX_CR_CLK_STATUS_GPP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
+#define RGX_CR_CLK_STATUS_GPP_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_GPP_RUNNING (IMG_UINT64_C(0x0000000000000008))
+/* TE default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_TE_SHIFT (2U)
+#define RGX_CR_CLK_STATUS_TE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
+#define RGX_CR_CLK_STATUS_TE_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_TE_RUNNING (IMG_UINT64_C(0x0000000000000004))
+/* TSP default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_TSP_SHIFT (1U)
+#define RGX_CR_CLK_STATUS_TSP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
+#define RGX_CR_CLK_STATUS_TSP_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_TSP_RUNNING (IMG_UINT64_C(0x0000000000000002))
+/* ISP default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS_ISP_SHIFT (0U)
+#define RGX_CR_CLK_STATUS_ISP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_CLK_STATUS_ISP_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS_ISP_RUNNING (IMG_UINT64_C(0x0000000000000001))
+#endif /* !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) */
+
+
+/*
+
+ Reports the core ID
+
+
+ Core ID Register
+
+*/
+/*
+ Register RGX_CR_CORE_ID
+*/
+#define RGX_CR_CORE_ID (0x0018U)
+#define RGX_CR_CORE_ID_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* ID
+ Core ID
+*/
+#define RGX_CR_CORE_ID_ID_SHIFT (16U)
+#define RGX_CR_CORE_ID_ID_CLRMSK (0X0000FFFFU)
+/* CONFIG
+ Core Configuration
+*/
+#define RGX_CR_CORE_ID_CONFIG_SHIFT (0U)
+#define RGX_CR_CORE_ID_CONFIG_CLRMSK (0XFFFF0000U)
+
+
+/*
+
+ Reports the core revision
+
+
+ Core Revision Register identifies the specific core revision.
+ This is updated to reflect the formal release status of the core.
+
+*/
+/*
+ Register RGX_CR_CORE_REVISION
+*/
+#define RGX_CR_CORE_REVISION (0x0020U)
+#define RGX_CR_CORE_REVISION_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* DESIGNER
+ Designer Field
+*/
+#define RGX_CR_CORE_REVISION_DESIGNER_SHIFT (24U)
+#define RGX_CR_CORE_REVISION_DESIGNER_CLRMSK (0X00FFFFFFU)
+/* MAJOR default: 0x00000001
+ Major Revision
+*/
+#define RGX_CR_CORE_REVISION_MAJOR_SHIFT (16U)
+#define RGX_CR_CORE_REVISION_MAJOR_CLRMSK (0XFF00FFFFU)
+/* MINOR
+ Minor Revision
+*/
+#define RGX_CR_CORE_REVISION_MINOR_SHIFT (8U)
+#define RGX_CR_CORE_REVISION_MINOR_CLRMSK (0XFFFF00FFU)
+/* MAINTENANCE
+ Maintenance Revision
+*/
+#define RGX_CR_CORE_REVISION_MAINTENANCE_SHIFT (0U)
+#define RGX_CR_CORE_REVISION_MAINTENANCE_CLRMSK (0XFFFFFF00U)
+
+
+/*
+
+ SOC Specific reporting register.
+
+
+ Designer Revision Field
+ The SOC designer can use this register for their own revision control
+
+*/
+/*
+ Register RGX_CR_DESIGNER_REV_FIELD1
+*/
+#define RGX_CR_DESIGNER_REV_FIELD1 (0x0028U)
+#define RGX_CR_DESIGNER_REV_FIELD1_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* DESIGNER_REV_FIELD1
+ Designer field
+*/
+#define RGX_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT (0U)
+#define RGX_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_CLRMSK (00000000U)
+
+
+/*
+
+ SOC Specific reporting register.
+
+
+ Designer Revision Field
+ The SOC designer can use this register for their own revision control is required
+
+*/
+/*
+ Register RGX_CR_DESIGNER_REV_FIELD2
+*/
+#define RGX_CR_DESIGNER_REV_FIELD2 (0x0030U)
+#define RGX_CR_DESIGNER_REV_FIELD2_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* DESIGNER_REV_FIELD2
+ Designer field
+*/
+#define RGX_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT (0U)
+#define RGX_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_CLRMSK (00000000U)
+
+
+/*
+
+ Core Module Clock Control Modes.
+
+
+ Allows individual domain clocks to be forced off, forced on or operate under automatic pipeline activity based clock gating. This register is generally controlled by the GPU firmware and should be set to AUTO. Clock gating reduces the power consumed by the device.
+
+*/
+/*
+ Register RGX_CR_CLK_XTPLUS_CTRL
+*/
+#define RGX_CR_CLK_XTPLUS_CTRL (0x0080U)
+#define RGX_CR_CLK_XTPLUS_CTRL_MASKFULL (IMG_UINT64_C(0x00000003FFFFFFFF))
+/* IPF default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_IPF_SHIFT (32U)
+#define RGX_CR_CLK_XTPLUS_CTRL_IPF_CLRMSK (IMG_UINT64_C(0XFFFFFFFCFFFFFFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_IPF_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_IPF_ON (IMG_UINT64_C(0x0000000100000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_IPF_AUTO (IMG_UINT64_C(0x0000000200000000))
+/* COMPUTE default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_SHIFT (30U)
+#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_CLRMSK (IMG_UINT64_C(0XFFFFFFFF3FFFFFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_ON (IMG_UINT64_C(0x0000000040000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_COMPUTE_AUTO (IMG_UINT64_C(0x0000000080000000))
+/* PIXEL default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_SHIFT (28U)
+#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFCFFFFFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_ON (IMG_UINT64_C(0x0000000010000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_PIXEL_AUTO (IMG_UINT64_C(0x0000000020000000))
+/* VERTEX default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_SHIFT (26U)
+#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_CLRMSK (IMG_UINT64_C(0XFFFFFFFFF3FFFFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_ON (IMG_UINT64_C(0x0000000004000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_VERTEX_AUTO (IMG_UINT64_C(0x0000000008000000))
+/* USCPS default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_SHIFT (24U)
+#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFCFFFFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_ON (IMG_UINT64_C(0x0000000001000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_USCPS_AUTO (IMG_UINT64_C(0x0000000002000000))
+/* PDS_SHARED default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_SHIFT (22U)
+#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFF3FFFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_ON (IMG_UINT64_C(0x0000000000400000))
+#define RGX_CR_CLK_XTPLUS_CTRL_PDS_SHARED_AUTO (IMG_UINT64_C(0x0000000000800000))
+/* BIF_BLACKPEARL default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_SHIFT (20U)
+#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFCFFFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_ON (IMG_UINT64_C(0x0000000000100000))
+#define RGX_CR_CLK_XTPLUS_CTRL_BIF_BLACKPEARL_AUTO (IMG_UINT64_C(0x0000000000200000))
+/* USC_SHARED default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_SHIFT (18U)
+#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFF3FFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_ON (IMG_UINT64_C(0x0000000000040000))
+#define RGX_CR_CLK_XTPLUS_CTRL_USC_SHARED_AUTO (IMG_UINT64_C(0x0000000000080000))
+/* GEOMETRY default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_SHIFT (16U)
+#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFCFFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_ON (IMG_UINT64_C(0x0000000000010000))
+#define RGX_CR_CLK_XTPLUS_CTRL_GEOMETRY_AUTO (IMG_UINT64_C(0x0000000000020000))
+/* RAST default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_RAST_SHIFT (14U)
+#define RGX_CR_CLK_XTPLUS_CTRL_RAST_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFF3FFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_RAST_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_RAST_ON (IMG_UINT64_C(0x0000000000004000))
+#define RGX_CR_CLK_XTPLUS_CTRL_RAST_AUTO (IMG_UINT64_C(0x0000000000008000))
+/* UVB default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_UVB_SHIFT (12U)
+#define RGX_CR_CLK_XTPLUS_CTRL_UVB_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFCFFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_UVB_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_UVB_ON (IMG_UINT64_C(0x0000000000001000))
+#define RGX_CR_CLK_XTPLUS_CTRL_UVB_AUTO (IMG_UINT64_C(0x0000000000002000))
+/* GPP default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_GPP_SHIFT (10U)
+#define RGX_CR_CLK_XTPLUS_CTRL_GPP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF3FF))
+#define RGX_CR_CLK_XTPLUS_CTRL_GPP_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_GPP_ON (IMG_UINT64_C(0x0000000000000400))
+#define RGX_CR_CLK_XTPLUS_CTRL_GPP_AUTO (IMG_UINT64_C(0x0000000000000800))
+/* VDM_PIPE default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_PIPE_SHIFT (8U)
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_PIPE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_PIPE_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_PIPE_ON (IMG_UINT64_C(0x0000000000000100))
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_PIPE_AUTO (IMG_UINT64_C(0x0000000000000200))
+/* VDM default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_SHIFT (6U)
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFF3F))
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_ON (IMG_UINT64_C(0x0000000000000040))
+#define RGX_CR_CLK_XTPLUS_CTRL_VDM_AUTO (IMG_UINT64_C(0x0000000000000080))
+/* TE3 default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_TE3_SHIFT (4U)
+#define RGX_CR_CLK_XTPLUS_CTRL_TE3_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFCF))
+#define RGX_CR_CLK_XTPLUS_CTRL_TE3_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_TE3_ON (IMG_UINT64_C(0x0000000000000010))
+#define RGX_CR_CLK_XTPLUS_CTRL_TE3_AUTO (IMG_UINT64_C(0x0000000000000020))
+/* VCE default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_VCE_SHIFT (2U)
+#define RGX_CR_CLK_XTPLUS_CTRL_VCE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF3))
+#define RGX_CR_CLK_XTPLUS_CTRL_VCE_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_VCE_ON (IMG_UINT64_C(0x0000000000000004))
+#define RGX_CR_CLK_XTPLUS_CTRL_VCE_AUTO (IMG_UINT64_C(0x0000000000000008))
+/* VBS default: AUTO (0x00000002) */
+#define RGX_CR_CLK_XTPLUS_CTRL_VBS_SHIFT (0U)
+#define RGX_CR_CLK_XTPLUS_CTRL_VBS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
+#define RGX_CR_CLK_XTPLUS_CTRL_VBS_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_CTRL_VBS_ON (IMG_UINT64_C(0x0000000000000001))
+#define RGX_CR_CLK_XTPLUS_CTRL_VBS_AUTO (IMG_UINT64_C(0x0000000000000002))
+
+
+/*
+
+ Reports the current module clock status
+
+
+ Clock gating state reflects the condition of the clock for each module
+
+*/
+/*
+ Register RGX_CR_CLK_XTPLUS_STATUS
+*/
+#define RGX_CR_CLK_XTPLUS_STATUS (0x0088U)
+#define RGX_CR_CLK_XTPLUS_STATUS_MASKFULL (IMG_UINT64_C(0x000000000000007F))
+/* UVB default: GATED (0x00000000) */
+#define RGX_CR_CLK_XTPLUS_STATUS_UVB_SHIFT (6U)
+#define RGX_CR_CLK_XTPLUS_STATUS_UVB_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFBF))
+#define RGX_CR_CLK_XTPLUS_STATUS_UVB_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_STATUS_UVB_RUNNING (IMG_UINT64_C(0x0000000000000040))
+/* GPP default: GATED (0x00000000) */
+#define RGX_CR_CLK_XTPLUS_STATUS_GPP_SHIFT (5U)
+#define RGX_CR_CLK_XTPLUS_STATUS_GPP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_CLK_XTPLUS_STATUS_GPP_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_STATUS_GPP_RUNNING (IMG_UINT64_C(0x0000000000000020))
+/* VDM_PIPE default: GATED (0x00000000) */
+#define RGX_CR_CLK_XTPLUS_STATUS_VDM_PIPE_SHIFT (4U)
+#define RGX_CR_CLK_XTPLUS_STATUS_VDM_PIPE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
+#define RGX_CR_CLK_XTPLUS_STATUS_VDM_PIPE_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_STATUS_VDM_PIPE_RUNNING (IMG_UINT64_C(0x0000000000000010))
+/* VDM default: GATED (0x00000000) */
+#define RGX_CR_CLK_XTPLUS_STATUS_VDM_SHIFT (3U)
+#define RGX_CR_CLK_XTPLUS_STATUS_VDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
+#define RGX_CR_CLK_XTPLUS_STATUS_VDM_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_STATUS_VDM_RUNNING (IMG_UINT64_C(0x0000000000000008))
+/* TE3 default: GATED (0x00000000) */
+#define RGX_CR_CLK_XTPLUS_STATUS_TE3_SHIFT (2U)
+#define RGX_CR_CLK_XTPLUS_STATUS_TE3_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
+#define RGX_CR_CLK_XTPLUS_STATUS_TE3_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_STATUS_TE3_RUNNING (IMG_UINT64_C(0x0000000000000004))
+/* VCE default: GATED (0x00000000) */
+#define RGX_CR_CLK_XTPLUS_STATUS_VCE_SHIFT (1U)
+#define RGX_CR_CLK_XTPLUS_STATUS_VCE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
+#define RGX_CR_CLK_XTPLUS_STATUS_VCE_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_STATUS_VCE_RUNNING (IMG_UINT64_C(0x0000000000000002))
+/* VBS default: GATED (0x00000000) */
+#define RGX_CR_CLK_XTPLUS_STATUS_VBS_SHIFT (0U)
+#define RGX_CR_CLK_XTPLUS_STATUS_VBS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_CLK_XTPLUS_STATUS_VBS_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_XTPLUS_STATUS_VBS_RUNNING (IMG_UINT64_C(0x0000000000000001))
+
+
+/*
+
+ Core soft reset control register.
+
+
+ Write a '1' to reset and a '0' to clear
+ See the soft reset section in the TRM to understand how to use the soft reset register.
+
+*/
+/*
+ Register RGX_CR_SOFT_RESET
+*/
+#define RGX_CR_SOFT_RESET (0x0100U)
+#define RGX_CR_SOFT_RESET_MASKFULL (IMG_UINT64_C(0xFFE7FFFFFFFFFC1D))
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+/* PHANTOM3_CORE*/
+#define RGX_CR_SOFT_RESET_PHANTOM3_CORE_SHIFT (63U)
+#define RGX_CR_SOFT_RESET_PHANTOM3_CORE_CLRMSK (IMG_UINT64_C(0X7FFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_PHANTOM3_CORE_EN (IMG_UINT64_C(0X8000000000000000))
+/* PHANTOM2_CORE*/
+#define RGX_CR_SOFT_RESET_PHANTOM2_CORE_SHIFT (62U)
+#define RGX_CR_SOFT_RESET_PHANTOM2_CORE_CLRMSK (IMG_UINT64_C(0XBFFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_PHANTOM2_CORE_EN (IMG_UINT64_C(0X4000000000000000))
+/* BERNADO2_CORE*/
+#define RGX_CR_SOFT_RESET_BERNADO2_CORE_SHIFT (61U)
+#define RGX_CR_SOFT_RESET_BERNADO2_CORE_CLRMSK (IMG_UINT64_C(0XDFFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_BERNADO2_CORE_EN (IMG_UINT64_C(0X2000000000000000))
+#endif /* RGX_FEATURE_CLUSTER_GROUPING */
+
+/* JONES_CORE*/
+#define RGX_CR_SOFT_RESET_JONES_CORE_SHIFT (60U)
+#define RGX_CR_SOFT_RESET_JONES_CORE_CLRMSK (IMG_UINT64_C(0XEFFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_JONES_CORE_EN (IMG_UINT64_C(0X1000000000000000))
+/* TILING_CORE*/
+#define RGX_CR_SOFT_RESET_TILING_CORE_SHIFT (59U)
+#define RGX_CR_SOFT_RESET_TILING_CORE_CLRMSK (IMG_UINT64_C(0XF7FFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_TILING_CORE_EN (IMG_UINT64_C(0X0800000000000000))
+/* TE3*/
+#define RGX_CR_SOFT_RESET_TE3_SHIFT (58U)
+#define RGX_CR_SOFT_RESET_TE3_CLRMSK (IMG_UINT64_C(0XFBFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_TE3_EN (IMG_UINT64_C(0X0400000000000000))
+/* VCE*/
+#define RGX_CR_SOFT_RESET_VCE_SHIFT (57U)
+#define RGX_CR_SOFT_RESET_VCE_CLRMSK (IMG_UINT64_C(0XFDFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_VCE_EN (IMG_UINT64_C(0X0200000000000000))
+/* VBS*/
+#define RGX_CR_SOFT_RESET_VBS_SHIFT (56U)
+#define RGX_CR_SOFT_RESET_VBS_CLRMSK (IMG_UINT64_C(0XFEFFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_VBS_EN (IMG_UINT64_C(0X0100000000000000))
+#if defined(RGX_FEATURE_RAY_TRACING)
+/* DPX1_CORE*/
+#define RGX_CR_SOFT_RESET_DPX1_CORE_SHIFT (55U)
+#define RGX_CR_SOFT_RESET_DPX1_CORE_CLRMSK (IMG_UINT64_C(0XFF7FFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_DPX1_CORE_EN (IMG_UINT64_C(0X0080000000000000))
+/* DPX0_CORE*/
+#define RGX_CR_SOFT_RESET_DPX0_CORE_SHIFT (54U)
+#define RGX_CR_SOFT_RESET_DPX0_CORE_CLRMSK (IMG_UINT64_C(0XFFBFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_DPX0_CORE_EN (IMG_UINT64_C(0X0040000000000000))
+/* FBA*/
+#define RGX_CR_SOFT_RESET_FBA_SHIFT (53U)
+#define RGX_CR_SOFT_RESET_FBA_CLRMSK (IMG_UINT64_C(0XFFDFFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_FBA_EN (IMG_UINT64_C(0X0020000000000000))
+/* SH*/
+#define RGX_CR_SOFT_RESET_SH_SHIFT (50U)
+#define RGX_CR_SOFT_RESET_SH_CLRMSK (IMG_UINT64_C(0XFFFBFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_SH_EN (IMG_UINT64_C(0X0004000000000000))
+/* VRDM*/
+#define RGX_CR_SOFT_RESET_VRDM_SHIFT (49U)
+#define RGX_CR_SOFT_RESET_VRDM_CLRMSK (IMG_UINT64_C(0XFFFDFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_VRDM_EN (IMG_UINT64_C(0X0002000000000000))
+#endif /* RGX_FEATURE_RAY_TRACING */
+
+/* MCU_FBTC*/
+#define RGX_CR_SOFT_RESET_MCU_FBTC_SHIFT (48U)
+#define RGX_CR_SOFT_RESET_MCU_FBTC_CLRMSK (IMG_UINT64_C(0XFFFEFFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_MCU_FBTC_EN (IMG_UINT64_C(0X0001000000000000))
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+/* PHANTOM1_CORE*/
+#define RGX_CR_SOFT_RESET_PHANTOM1_CORE_SHIFT (47U)
+#define RGX_CR_SOFT_RESET_PHANTOM1_CORE_CLRMSK (IMG_UINT64_C(0XFFFF7FFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_PHANTOM1_CORE_EN (IMG_UINT64_C(0X0000800000000000))
+/* PHANTOM0_CORE*/
+#define RGX_CR_SOFT_RESET_PHANTOM0_CORE_SHIFT (46U)
+#define RGX_CR_SOFT_RESET_PHANTOM0_CORE_CLRMSK (IMG_UINT64_C(0XFFFFBFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_PHANTOM0_CORE_EN (IMG_UINT64_C(0X0000400000000000))
+/* BERNADO1_CORE*/
+#define RGX_CR_SOFT_RESET_BERNADO1_CORE_SHIFT (45U)
+#define RGX_CR_SOFT_RESET_BERNADO1_CORE_CLRMSK (IMG_UINT64_C(0XFFFFDFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_BERNADO1_CORE_EN (IMG_UINT64_C(0X0000200000000000))
+/* BERNADO0_CORE*/
+#define RGX_CR_SOFT_RESET_BERNADO0_CORE_SHIFT (44U)
+#define RGX_CR_SOFT_RESET_BERNADO0_CORE_CLRMSK (IMG_UINT64_C(0XFFFFEFFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_BERNADO0_CORE_EN (IMG_UINT64_C(0X0000100000000000))
+/* IPP*/
+#define RGX_CR_SOFT_RESET_IPP_SHIFT (43U)
+#define RGX_CR_SOFT_RESET_IPP_CLRMSK (IMG_UINT64_C(0XFFFFF7FFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_IPP_EN (IMG_UINT64_C(0X0000080000000000))
+/* BIF_TEXAS*/
+#define RGX_CR_SOFT_RESET_BIF_TEXAS_SHIFT (42U)
+#define RGX_CR_SOFT_RESET_BIF_TEXAS_CLRMSK (IMG_UINT64_C(0XFFFFFBFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_BIF_TEXAS_EN (IMG_UINT64_C(0X0000040000000000))
+/* TORNADO_CORE*/
+#define RGX_CR_SOFT_RESET_TORNADO_CORE_SHIFT (41U)
+#define RGX_CR_SOFT_RESET_TORNADO_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFDFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_TORNADO_CORE_EN (IMG_UINT64_C(0X0000020000000000))
+#endif /* RGX_FEATURE_CLUSTER_GROUPING */
+
+/* DUST_H_CORE*/
+#define RGX_CR_SOFT_RESET_DUST_H_CORE_SHIFT (40U)
+#define RGX_CR_SOFT_RESET_DUST_H_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFEFFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_DUST_H_CORE_EN (IMG_UINT64_C(0X0000010000000000))
+/* DUST_G_CORE*/
+#define RGX_CR_SOFT_RESET_DUST_G_CORE_SHIFT (39U)
+#define RGX_CR_SOFT_RESET_DUST_G_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFF7FFFFFFFFF))
+#define RGX_CR_SOFT_RESET_DUST_G_CORE_EN (IMG_UINT64_C(0X0000008000000000))
+/* DUST_F_CORE*/
+#define RGX_CR_SOFT_RESET_DUST_F_CORE_SHIFT (38U)
+#define RGX_CR_SOFT_RESET_DUST_F_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFFBFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_DUST_F_CORE_EN (IMG_UINT64_C(0X0000004000000000))
+/* DUST_E_CORE*/
+#define RGX_CR_SOFT_RESET_DUST_E_CORE_SHIFT (37U)
+#define RGX_CR_SOFT_RESET_DUST_E_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFFDFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_DUST_E_CORE_EN (IMG_UINT64_C(0X0000002000000000))
+/* DUST_D_CORE*/
+#define RGX_CR_SOFT_RESET_DUST_D_CORE_SHIFT (36U)
+#define RGX_CR_SOFT_RESET_DUST_D_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFFEFFFFFFFFF))
+#define RGX_CR_SOFT_RESET_DUST_D_CORE_EN (IMG_UINT64_C(0X0000001000000000))
+/* DUST_C_CORE*/
+#define RGX_CR_SOFT_RESET_DUST_C_CORE_SHIFT (35U)
+#define RGX_CR_SOFT_RESET_DUST_C_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFFF7FFFFFFFF))
+#define RGX_CR_SOFT_RESET_DUST_C_CORE_EN (IMG_UINT64_C(0X0000000800000000))
+/* MMU*/
+#define RGX_CR_SOFT_RESET_MMU_SHIFT (34U)
+#define RGX_CR_SOFT_RESET_MMU_CLRMSK (IMG_UINT64_C(0XFFFFFFFBFFFFFFFF))
+#define RGX_CR_SOFT_RESET_MMU_EN (IMG_UINT64_C(0X0000000400000000))
+/* BIF1
+Sidekick BIF
+*/
+#define RGX_CR_SOFT_RESET_BIF1_SHIFT (33U)
+#define RGX_CR_SOFT_RESET_BIF1_CLRMSK (IMG_UINT64_C(0XFFFFFFFDFFFFFFFF))
+#define RGX_CR_SOFT_RESET_BIF1_EN (IMG_UINT64_C(0X0000000200000000))
+/* GARTEN
+Includes MTS and META
+*/
+#define RGX_CR_SOFT_RESET_GARTEN_SHIFT (32U)
+#define RGX_CR_SOFT_RESET_GARTEN_CLRMSK (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
+#define RGX_CR_SOFT_RESET_GARTEN_EN (IMG_UINT64_C(0X0000000100000000))
+/* RASCAL_CORE
+Note that the RASL_CORE bit affects logic related to the reading and writing of registers. This soft reset should therefore be used with caution. Upon power down events it is necessary to reset every register, so this bit should be used, but it must be release before any other resets, or beofre anyu other registers are programmed
+*/
+#define RGX_CR_SOFT_RESET_RASCAL_CORE_SHIFT (31U)
+#define RGX_CR_SOFT_RESET_RASCAL_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFFFF7FFFFFFF))
+#define RGX_CR_SOFT_RESET_RASCAL_CORE_EN (IMG_UINT64_C(0X0000000080000000))
+/* DUST_B_CORE*/
+#define RGX_CR_SOFT_RESET_DUST_B_CORE_SHIFT (30U)
+#define RGX_CR_SOFT_RESET_DUST_B_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFBFFFFFFF))
+#define RGX_CR_SOFT_RESET_DUST_B_CORE_EN (IMG_UINT64_C(0X0000000040000000))
+/* DUST_A_CORE*/
+#define RGX_CR_SOFT_RESET_DUST_A_CORE_SHIFT (29U)
+#define RGX_CR_SOFT_RESET_DUST_A_CORE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFDFFFFFFF))
+#define RGX_CR_SOFT_RESET_DUST_A_CORE_EN (IMG_UINT64_C(0X0000000020000000))
+/* FB_TLCACHE*/
+#define RGX_CR_SOFT_RESET_FB_TLCACHE_SHIFT (28U)
+#define RGX_CR_SOFT_RESET_FB_TLCACHE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFEFFFFFFF))
+#define RGX_CR_SOFT_RESET_FB_TLCACHE_EN (IMG_UINT64_C(0X0000000010000000))
+/* SLC*/
+#define RGX_CR_SOFT_RESET_SLC_SHIFT (27U)
+#define RGX_CR_SOFT_RESET_SLC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFF7FFFFFF))
+#define RGX_CR_SOFT_RESET_SLC_EN (IMG_UINT64_C(0X0000000008000000))
+/* TLA*/
+#define RGX_CR_SOFT_RESET_TLA_SHIFT (26U)
+#define RGX_CR_SOFT_RESET_TLA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFBFFFFFF))
+#define RGX_CR_SOFT_RESET_TLA_EN (IMG_UINT64_C(0X0000000004000000))
+/* UVS*/
+#define RGX_CR_SOFT_RESET_UVS_SHIFT (25U)
+#define RGX_CR_SOFT_RESET_UVS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFDFFFFFF))
+#define RGX_CR_SOFT_RESET_UVS_EN (IMG_UINT64_C(0X0000000002000000))
+/* TE*/
+#define RGX_CR_SOFT_RESET_TE_SHIFT (24U)
+#define RGX_CR_SOFT_RESET_TE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFEFFFFFF))
+#define RGX_CR_SOFT_RESET_TE_EN (IMG_UINT64_C(0X0000000001000000))
+/* GPP*/
+#define RGX_CR_SOFT_RESET_GPP_SHIFT (23U)
+#define RGX_CR_SOFT_RESET_GPP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFF7FFFFF))
+#define RGX_CR_SOFT_RESET_GPP_EN (IMG_UINT64_C(0X0000000000800000))
+/* FBDC*/
+#define RGX_CR_SOFT_RESET_FBDC_SHIFT (22U)
+#define RGX_CR_SOFT_RESET_FBDC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFBFFFFF))
+#define RGX_CR_SOFT_RESET_FBDC_EN (IMG_UINT64_C(0X0000000000400000))
+/* FBC*/
+#define RGX_CR_SOFT_RESET_FBC_SHIFT (21U)
+#define RGX_CR_SOFT_RESET_FBC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFDFFFFF))
+#define RGX_CR_SOFT_RESET_FBC_EN (IMG_UINT64_C(0X0000000000200000))
+/* PM*/
+#define RGX_CR_SOFT_RESET_PM_SHIFT (20U)
+#define RGX_CR_SOFT_RESET_PM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFEFFFFF))
+#define RGX_CR_SOFT_RESET_PM_EN (IMG_UINT64_C(0X0000000000100000))
+/* PBE*/
+#define RGX_CR_SOFT_RESET_PBE_SHIFT (19U)
+#define RGX_CR_SOFT_RESET_PBE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFF7FFFF))
+#define RGX_CR_SOFT_RESET_PBE_EN (IMG_UINT64_C(0X0000000000080000))
+/* USC_SHARED*/
+#define RGX_CR_SOFT_RESET_USC_SHARED_SHIFT (18U)
+#define RGX_CR_SOFT_RESET_USC_SHARED_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFBFFFF))
+#define RGX_CR_SOFT_RESET_USC_SHARED_EN (IMG_UINT64_C(0X0000000000040000))
+/* MCU_L1*/
+#define RGX_CR_SOFT_RESET_MCU_L1_SHIFT (17U)
+#define RGX_CR_SOFT_RESET_MCU_L1_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFDFFFF))
+#define RGX_CR_SOFT_RESET_MCU_L1_EN (IMG_UINT64_C(0X0000000000020000))
+/* BIF
+Bifpmcache BIF
+*/
+#define RGX_CR_SOFT_RESET_BIF_SHIFT (16U)
+#define RGX_CR_SOFT_RESET_BIF_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFEFFFF))
+#define RGX_CR_SOFT_RESET_BIF_EN (IMG_UINT64_C(0X0000000000010000))
+/* CDM*/
+#define RGX_CR_SOFT_RESET_CDM_SHIFT (15U)
+#define RGX_CR_SOFT_RESET_CDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFF7FFF))
+#define RGX_CR_SOFT_RESET_CDM_EN (IMG_UINT64_C(0X0000000000008000))
+/* VDM*/
+#define RGX_CR_SOFT_RESET_VDM_SHIFT (14U)
+#define RGX_CR_SOFT_RESET_VDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFBFFF))
+#define RGX_CR_SOFT_RESET_VDM_EN (IMG_UINT64_C(0X0000000000004000))
+/* TESS*/
+#define RGX_CR_SOFT_RESET_TESS_SHIFT (13U)
+#define RGX_CR_SOFT_RESET_TESS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFDFFF))
+#define RGX_CR_SOFT_RESET_TESS_EN (IMG_UINT64_C(0X0000000000002000))
+/* PDS*/
+#define RGX_CR_SOFT_RESET_PDS_SHIFT (12U)
+#define RGX_CR_SOFT_RESET_PDS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFEFFF))
+#define RGX_CR_SOFT_RESET_PDS_EN (IMG_UINT64_C(0X0000000000001000))
+/* ISP*/
+#define RGX_CR_SOFT_RESET_ISP_SHIFT (11U)
+#define RGX_CR_SOFT_RESET_ISP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF7FF))
+#define RGX_CR_SOFT_RESET_ISP_EN (IMG_UINT64_C(0X0000000000000800))
+/* TSP*/
+#define RGX_CR_SOFT_RESET_TSP_SHIFT (10U)
+#define RGX_CR_SOFT_RESET_TSP_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
+#define RGX_CR_SOFT_RESET_TSP_EN (IMG_UINT64_C(0X0000000000000400))
+/* TPU_MCU_DEMUX*/
+#define RGX_CR_SOFT_RESET_TPU_MCU_DEMUX_SHIFT (4U)
+#define RGX_CR_SOFT_RESET_TPU_MCU_DEMUX_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
+#define RGX_CR_SOFT_RESET_TPU_MCU_DEMUX_EN (IMG_UINT64_C(0X0000000000000010))
+/* MCU_L0*/
+#define RGX_CR_SOFT_RESET_MCU_L0_SHIFT (3U)
+#define RGX_CR_SOFT_RESET_MCU_L0_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
+#define RGX_CR_SOFT_RESET_MCU_L0_EN (IMG_UINT64_C(0X0000000000000008))
+/* TPU*/
+#define RGX_CR_SOFT_RESET_TPU_SHIFT (2U)
+#define RGX_CR_SOFT_RESET_TPU_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
+#define RGX_CR_SOFT_RESET_TPU_EN (IMG_UINT64_C(0X0000000000000004))
+/* USC*/
+#define RGX_CR_SOFT_RESET_USC_SHIFT (0U)
+#define RGX_CR_SOFT_RESET_USC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_SOFT_RESET_USC_EN (IMG_UINT64_C(0X0000000000000001))
+
+
+/*
+
+ Core soft reset control register.
+
+
+ Write a '1' to reset and a '0' to clear
+ See the soft reset section in the TRM to understand how to use the soft reset register.
+
+*/
+/*
+ Register RGX_CR_SOFT_RESET2
+*/
+#define RGX_CR_SOFT_RESET2 (0x0108U)
+#define RGX_CR_SOFT_RESET2_MASKFULL (IMG_UINT64_C(0x00000000000001FF))
+/* USCPS*/
+#define RGX_CR_SOFT_RESET2_USCPS_SHIFT (8U)
+#define RGX_CR_SOFT_RESET2_USCPS_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_SOFT_RESET2_USCPS_EN (0X00000100U)
+/* IPF*/
+#define RGX_CR_SOFT_RESET2_IPF_SHIFT (7U)
+#define RGX_CR_SOFT_RESET2_IPF_CLRMSK (0XFFFFFF7FU)
+#define RGX_CR_SOFT_RESET2_IPF_EN (0X00000080U)
+/* GEOMETRY*/
+#define RGX_CR_SOFT_RESET2_GEOMETRY_SHIFT (6U)
+#define RGX_CR_SOFT_RESET2_GEOMETRY_CLRMSK (0XFFFFFFBFU)
+#define RGX_CR_SOFT_RESET2_GEOMETRY_EN (0X00000040U)
+/* USC_SHARED*/
+#define RGX_CR_SOFT_RESET2_USC_SHARED_SHIFT (5U)
+#define RGX_CR_SOFT_RESET2_USC_SHARED_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_SOFT_RESET2_USC_SHARED_EN (0X00000020U)
+/* PDS_SHARED*/
+#define RGX_CR_SOFT_RESET2_PDS_SHARED_SHIFT (4U)
+#define RGX_CR_SOFT_RESET2_PDS_SHARED_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_SOFT_RESET2_PDS_SHARED_EN (0X00000010U)
+/* BIF_BLACKPEARL*/
+#define RGX_CR_SOFT_RESET2_BIF_BLACKPEARL_SHIFT (3U)
+#define RGX_CR_SOFT_RESET2_BIF_BLACKPEARL_CLRMSK (0XFFFFFFF7U)
+#define RGX_CR_SOFT_RESET2_BIF_BLACKPEARL_EN (0X00000008U)
+/* PIXEL*/
+#define RGX_CR_SOFT_RESET2_PIXEL_SHIFT (2U)
+#define RGX_CR_SOFT_RESET2_PIXEL_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_SOFT_RESET2_PIXEL_EN (0X00000004U)
+/* COMPUTE*/
+#define RGX_CR_SOFT_RESET2_COMPUTE_SHIFT (1U)
+#define RGX_CR_SOFT_RESET2_COMPUTE_CLRMSK (0XFFFFFFFDU)
+#define RGX_CR_SOFT_RESET2_COMPUTE_EN (0X00000002U)
+/* VERTEX*/
+#define RGX_CR_SOFT_RESET2_VERTEX_SHIFT (0U)
+#define RGX_CR_SOFT_RESET2_VERTEX_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_SOFT_RESET2_VERTEX_EN (0X00000001U)
+
+
+/*
+
+ The event status register indicate the source of an interrupt generated by PowerVR RGX
+ These events only schedule an interrupt context thread to run on META when the appropriate enables are set in RGX_CR_DMn_INTERRUPT_ENABLE
+
+*/
+/*
+ Register RGX_CR_EVENT_STATUS
+*/
+#define RGX_CR_EVENT_STATUS (0x0130U)
+#define RGX_CR_EVENT_STATUS_MASKFULL (IMG_UINT64_C(0x000000001FFEFFFF))
+#if defined(RGX_FEATURE_RAY_TRACING)
+/* DPX_OUT_OF_MEMORY
+ The Doppler overflow FIFO in memory is full
+*/
+#define RGX_CR_EVENT_STATUS_DPX_OUT_OF_MEMORY_SHIFT (28U)
+#define RGX_CR_EVENT_STATUS_DPX_OUT_OF_MEMORY_CLRMSK (0XEFFFFFFFU)
+#define RGX_CR_EVENT_STATUS_DPX_OUT_OF_MEMORY_EN (0X10000000U)
+/* DPX_MMU_PAGE_FAULT
+ A Doppler MMU page fault has occurred
+*/
+#define RGX_CR_EVENT_STATUS_DPX_MMU_PAGE_FAULT_SHIFT (27U)
+#define RGX_CR_EVENT_STATUS_DPX_MMU_PAGE_FAULT_CLRMSK (0XF7FFFFFFU)
+#define RGX_CR_EVENT_STATUS_DPX_MMU_PAGE_FAULT_EN (0X08000000U)
+/* RPM_OUT_OF_MEMORY
+ The Ray Page Manager has run out of free pages
+*/
+#define RGX_CR_EVENT_STATUS_RPM_OUT_OF_MEMORY_SHIFT (26U)
+#define RGX_CR_EVENT_STATUS_RPM_OUT_OF_MEMORY_CLRMSK (0XFBFFFFFFU)
+#define RGX_CR_EVENT_STATUS_RPM_OUT_OF_MEMORY_EN (0X04000000U)
+/* FBA_FC3_FINISHED
+ All records for every attachment point of frame context 3 have been written out to memory
+*/
+#define RGX_CR_EVENT_STATUS_FBA_FC3_FINISHED_SHIFT (25U)
+#define RGX_CR_EVENT_STATUS_FBA_FC3_FINISHED_CLRMSK (0XFDFFFFFFU)
+#define RGX_CR_EVENT_STATUS_FBA_FC3_FINISHED_EN (0X02000000U)
+/* FBA_FC2_FINISHED
+ All records for every attachment point of frame context 2 have been written out to memory
+*/
+#define RGX_CR_EVENT_STATUS_FBA_FC2_FINISHED_SHIFT (24U)
+#define RGX_CR_EVENT_STATUS_FBA_FC2_FINISHED_CLRMSK (0XFEFFFFFFU)
+#define RGX_CR_EVENT_STATUS_FBA_FC2_FINISHED_EN (0X01000000U)
+/* FBA_FC1_FINISHED
+ All records for every attachment point of frame context 1 have been written out to memory
+*/
+#define RGX_CR_EVENT_STATUS_FBA_FC1_FINISHED_SHIFT (23U)
+#define RGX_CR_EVENT_STATUS_FBA_FC1_FINISHED_CLRMSK (0XFF7FFFFFU)
+#define RGX_CR_EVENT_STATUS_FBA_FC1_FINISHED_EN (0X00800000U)
+/* FBA_FC0_FINISHED
+ All records for every attachment point of frame context 0 have been written out to memory
+*/
+#define RGX_CR_EVENT_STATUS_FBA_FC0_FINISHED_SHIFT (22U)
+#define RGX_CR_EVENT_STATUS_FBA_FC0_FINISHED_CLRMSK (0XFFBFFFFFU)
+#define RGX_CR_EVENT_STATUS_FBA_FC0_FINISHED_EN (0X00400000U)
+/* RDM_FC3_FINISHED
+ All rays in frame context 3 have finished i.e RDM has encountered an interrupt command in the RT control stream
+*/
+#define RGX_CR_EVENT_STATUS_RDM_FC3_FINISHED_SHIFT (21U)
+#define RGX_CR_EVENT_STATUS_RDM_FC3_FINISHED_CLRMSK (0XFFDFFFFFU)
+#define RGX_CR_EVENT_STATUS_RDM_FC3_FINISHED_EN (0X00200000U)
+/* RDM_FC2_FINISHED
+ All rays in frame context 2 have finished i.e RDM has encountered an interrupt command in the RT control stream
+*/
+#define RGX_CR_EVENT_STATUS_RDM_FC2_FINISHED_SHIFT (20U)
+#define RGX_CR_EVENT_STATUS_RDM_FC2_FINISHED_CLRMSK (0XFFEFFFFFU)
+#define RGX_CR_EVENT_STATUS_RDM_FC2_FINISHED_EN (0X00100000U)
+/* RDM_FC1_FINISHED
+ All rays in frame context 1 have finished i.e RDM has encountered an interrupt command in the RT control stream
+*/
+#define RGX_CR_EVENT_STATUS_RDM_FC1_FINISHED_SHIFT (19U)
+#define RGX_CR_EVENT_STATUS_RDM_FC1_FINISHED_CLRMSK (0XFFF7FFFFU)
+#define RGX_CR_EVENT_STATUS_RDM_FC1_FINISHED_EN (0X00080000U)
+/* RDM_FC0_FINISHED
+ All rays in frame context 0 have finished i.e RDM has encountered an interrupt command in the RT control stream
+*/
+#define RGX_CR_EVENT_STATUS_RDM_FC0_FINISHED_SHIFT (18U)
+#define RGX_CR_EVENT_STATUS_RDM_FC0_FINISHED_CLRMSK (0XFFFBFFFFU)
+#define RGX_CR_EVENT_STATUS_RDM_FC0_FINISHED_EN (0X00040000U)
+/* SHG_FINISHED
+ SHG has completed the hierarchical voxelisation process and memory has been written
+*/
+#define RGX_CR_EVENT_STATUS_SHG_FINISHED_SHIFT (17U)
+#define RGX_CR_EVENT_STATUS_SHG_FINISHED_CLRMSK (0XFFFDFFFFU)
+#define RGX_CR_EVENT_STATUS_SHG_FINISHED_EN (0X00020000U)
+#endif /* RGX_FEATURE_RAY_TRACING */
+
+/* USC_TRIGGER
+ One or more USC has executed a nop.trigger instruction
+*/
+#define RGX_CR_EVENT_STATUS_USC_TRIGGER_SHIFT (15U)
+#define RGX_CR_EVENT_STATUS_USC_TRIGGER_CLRMSK (0XFFFF7FFFU)
+#define RGX_CR_EVENT_STATUS_USC_TRIGGER_EN (0X00008000U)
+/* ZLS_FINISHED
+ ZLS has finished all tiles in a Render
+*/
+#define RGX_CR_EVENT_STATUS_ZLS_FINISHED_SHIFT (14U)
+#define RGX_CR_EVENT_STATUS_ZLS_FINISHED_CLRMSK (0XFFFFBFFFU)
+#define RGX_CR_EVENT_STATUS_ZLS_FINISHED_EN (0X00004000U)
+/* GPIO_ACK
+ General Purpose ouput acknowledgement
+*/
+#define RGX_CR_EVENT_STATUS_GPIO_ACK_SHIFT (13U)
+#define RGX_CR_EVENT_STATUS_GPIO_ACK_CLRMSK (0XFFFFDFFFU)
+#define RGX_CR_EVENT_STATUS_GPIO_ACK_EN (0X00002000U)
+/* GPIO_REQ
+ General Purpose input request
+*/
+#define RGX_CR_EVENT_STATUS_GPIO_REQ_SHIFT (12U)
+#define RGX_CR_EVENT_STATUS_GPIO_REQ_CLRMSK (0XFFFFEFFFU)
+#define RGX_CR_EVENT_STATUS_GPIO_REQ_EN (0X00001000U)
+/* POWER_ABORT
+ The requested power operation has been denied.
+*/
+#define RGX_CR_EVENT_STATUS_POWER_ABORT_SHIFT (11U)
+#define RGX_CR_EVENT_STATUS_POWER_ABORT_CLRMSK (0XFFFFF7FFU)
+#define RGX_CR_EVENT_STATUS_POWER_ABORT_EN (0X00000800U)
+/* POWER_COMPLETE
+ The requested power operation has completed
+*/
+#define RGX_CR_EVENT_STATUS_POWER_COMPLETE_SHIFT (10U)
+#define RGX_CR_EVENT_STATUS_POWER_COMPLETE_CLRMSK (0XFFFFFBFFU)
+#define RGX_CR_EVENT_STATUS_POWER_COMPLETE_EN (0X00000400U)
+/* MMU_PAGE_FAULT
+ An MMU page fault has occurred
+*/
+#define RGX_CR_EVENT_STATUS_MMU_PAGE_FAULT_SHIFT (9U)
+#define RGX_CR_EVENT_STATUS_MMU_PAGE_FAULT_CLRMSK (0XFFFFFDFFU)
+#define RGX_CR_EVENT_STATUS_MMU_PAGE_FAULT_EN (0X00000200U)
+/* PM_3D_MEM_FREE
+ PM memory allocation completed for the current render
+*/
+#define RGX_CR_EVENT_STATUS_PM_3D_MEM_FREE_SHIFT (8U)
+#define RGX_CR_EVENT_STATUS_PM_3D_MEM_FREE_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_EVENT_STATUS_PM_3D_MEM_FREE_EN (0X00000100U)
+/* PM_OUT_OF_MEMORY
+ PM memory allocation failed for a macro-tile
+*/
+#define RGX_CR_EVENT_STATUS_PM_OUT_OF_MEMORY_SHIFT (7U)
+#define RGX_CR_EVENT_STATUS_PM_OUT_OF_MEMORY_CLRMSK (0XFFFFFF7FU)
+#define RGX_CR_EVENT_STATUS_PM_OUT_OF_MEMORY_EN (0X00000080U)
+/* TA_TERMINATE
+ The TE has aborted a macro tile after a failted PM allocation request
+*/
+#define RGX_CR_EVENT_STATUS_TA_TERMINATE_SHIFT (6U)
+#define RGX_CR_EVENT_STATUS_TA_TERMINATE_CLRMSK (0XFFFFFFBFU)
+#define RGX_CR_EVENT_STATUS_TA_TERMINATE_EN (0X00000040U)
+/* TA_FINISHED
+ The TA phase has completed
+*/
+#define RGX_CR_EVENT_STATUS_TA_FINISHED_SHIFT (5U)
+#define RGX_CR_EVENT_STATUS_TA_FINISHED_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_EVENT_STATUS_TA_FINISHED_EN (0X00000020U)
+/* ISP_END_MACROTILE
+ ISP End-of-Macrotile
+*/
+#define RGX_CR_EVENT_STATUS_ISP_END_MACROTILE_SHIFT (4U)
+#define RGX_CR_EVENT_STATUS_ISP_END_MACROTILE_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_EVENT_STATUS_ISP_END_MACROTILE_EN (0X00000010U)
+/* PIXELBE_END_RENDER
+ The 3D phase has completed
+*/
+#define RGX_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT (3U)
+#define RGX_CR_EVENT_STATUS_PIXELBE_END_RENDER_CLRMSK (0XFFFFFFF7U)
+#define RGX_CR_EVENT_STATUS_PIXELBE_END_RENDER_EN (0X00000008U)
+/* COMPUTE_FINISHED
+ The compute phase has completed
+*/
+#define RGX_CR_EVENT_STATUS_COMPUTE_FINISHED_SHIFT (2U)
+#define RGX_CR_EVENT_STATUS_COMPUTE_FINISHED_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_EVENT_STATUS_COMPUTE_FINISHED_EN (0X00000004U)
+/* KERNEL_FINISHED
+ A compute kernel has completed and updated the associated event object in external memory
+*/
+#define RGX_CR_EVENT_STATUS_KERNEL_FINISHED_SHIFT (1U)
+#define RGX_CR_EVENT_STATUS_KERNEL_FINISHED_CLRMSK (0XFFFFFFFDU)
+#define RGX_CR_EVENT_STATUS_KERNEL_FINISHED_EN (0X00000002U)
+/* TLA_COMPLETE
+ The 2D core has completed writing out all data to memory and it has received a complete signal from the memory interface
+*/
+#define RGX_CR_EVENT_STATUS_TLA_COMPLETE_SHIFT (0U)
+#define RGX_CR_EVENT_STATUS_TLA_COMPLETE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_EVENT_STATUS_TLA_COMPLETE_EN (0X00000001U)
+
+
+/*
+
+ This register contains the value of a 48-bit internal timer.
+ The timer runs continuously, and wraps at the top end.
+ It counts 256 cycles at the core clock frequency.
+
+
+ This means that at 100 MHz:
+ 1 count value = 1/100MHz = 256 * 10 * 10^-9 seconds = 2.56 us
+
+ 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.
+
+*/
+/*
+ Register RGX_CR_TIMER
+*/
+#define RGX_CR_TIMER (0x0160U)
+#define RGX_CR_TIMER_MASKFULL (IMG_UINT64_C(0x8000FFFFFFFFFFFF))
+/* BIT31*/
+#define RGX_CR_TIMER_BIT31_SHIFT (63U)
+#define RGX_CR_TIMER_BIT31_CLRMSK (IMG_UINT64_C(0X7FFFFFFFFFFFFFFF))
+#define RGX_CR_TIMER_BIT31_EN (IMG_UINT64_C(0X8000000000000000))
+/* VALUE*/
+#define RGX_CR_TIMER_VALUE_SHIFT (0U)
+#define RGX_CR_TIMER_VALUE_CLRMSK (IMG_UINT64_C(0XFFFF000000000000))
+
+
+/*
+ Register RGX_CR_META_SP_MSLVDATAX
+*/
+#define RGX_CR_META_SP_MSLVDATAX (0x0A00U)
+#define RGX_CR_META_SP_MSLVDATAX_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* MSLVDATAX
+This register holds the last data value read or written by the slave port
+*/
+#define RGX_CR_META_SP_MSLVDATAX_MSLVDATAX_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVDATAX_MSLVDATAX_CLRMSK (00000000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVDATAT
+*/
+#define RGX_CR_META_SP_MSLVDATAT (0x0A08U)
+#define RGX_CR_META_SP_MSLVDATAT_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* MSLVDATAT
+This register updates or returns the same value as MSLVDATAX. However each read/write transaction on this register also starts the corresponding transfer within the META Core
+*/
+#define RGX_CR_META_SP_MSLVDATAT_MSLVDATAT_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVDATAT_MSLVDATAT_CLRMSK (00000000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVCTRL0
+*/
+#define RGX_CR_META_SP_MSLVCTRL0 (0x0A10U)
+#define RGX_CR_META_SP_MSLVCTRL0_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* ADDR
+32-bit byte address specifying the address at which the next read or write access should be made within the META core memory map.
+*/
+#define RGX_CR_META_SP_MSLVCTRL0_ADDR_SHIFT (2U)
+#define RGX_CR_META_SP_MSLVCTRL0_ADDR_CLRMSK (0X00000003U)
+/* AUTOINCR
+Selects auto-increment addressing mode when set to 1. The address specified in ADDR (bits 31-2) will be incremented after each transaction is transmitted by the slave port.
+*/
+#define RGX_CR_META_SP_MSLVCTRL0_AUTOINCR_SHIFT (1U)
+#define RGX_CR_META_SP_MSLVCTRL0_AUTOINCR_CLRMSK (0XFFFFFFFDU)
+#define RGX_CR_META_SP_MSLVCTRL0_AUTOINCR_EN (0X00000002U)
+/* RD
+If written with the value 1 a read to the address specified (see below) will be issued and this bit will clear back to zero once the read transaction is transmitted by the slave port.
+*/
+#define RGX_CR_META_SP_MSLVCTRL0_RD_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVCTRL0_RD_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_META_SP_MSLVCTRL0_RD_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVCTRL1
+*/
+#define RGX_CR_META_SP_MSLVCTRL1 (0x0A18U)
+#define RGX_CR_META_SP_MSLVCTRL1_MASKFULL (IMG_UINT64_C(0x00000000F7F4003F))
+/* DEFERRTHREAD
+Deferred bus error thread ID. (Read only)
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_DEFERRTHREAD_SHIFT (30U)
+#define RGX_CR_META_SP_MSLVCTRL1_DEFERRTHREAD_CLRMSK (0X3FFFFFFFU)
+/* LOCK2_INTERLOCK
+Slave interface LOCK2 interlock active (Read only)
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_LOCK2_INTERLOCK_SHIFT (29U)
+#define RGX_CR_META_SP_MSLVCTRL1_LOCK2_INTERLOCK_CLRMSK (0XDFFFFFFFU)
+#define RGX_CR_META_SP_MSLVCTRL1_LOCK2_INTERLOCK_EN (0X20000000U)
+/* ATOMIC_INTERLOCK
+Atomic inter-lock active in MMU arbiter (Read only)
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_ATOMIC_INTERLOCK_SHIFT (28U)
+#define RGX_CR_META_SP_MSLVCTRL1_ATOMIC_INTERLOCK_CLRMSK (0XEFFFFFFFU)
+#define RGX_CR_META_SP_MSLVCTRL1_ATOMIC_INTERLOCK_EN (0X10000000U)
+/* GBLPORT_IDLE
+Global internal register access port idle (Read only)
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_SHIFT (26U)
+#define RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_CLRMSK (0XFBFFFFFFU)
+#define RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN (0X04000000U)
+/* COREMEM_IDLE
+Core memory update register idle (Read only)
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_COREMEM_IDLE_SHIFT (25U)
+#define RGX_CR_META_SP_MSLVCTRL1_COREMEM_IDLE_CLRMSK (0XFDFFFFFFU)
+#define RGX_CR_META_SP_MSLVCTRL1_COREMEM_IDLE_EN (0X02000000U)
+/* READY
+Slave port ready to issue a further read or write request (Read only)
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_READY_SHIFT (24U)
+#define RGX_CR_META_SP_MSLVCTRL1_READY_CLRMSK (0XFEFFFFFFU)
+#define RGX_CR_META_SP_MSLVCTRL1_READY_EN (0X01000000U)
+/* DEFERRID
+Deferred bus error code (Read only)
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_DEFERRID_SHIFT (21U)
+#define RGX_CR_META_SP_MSLVCTRL1_DEFERRID_CLRMSK (0XFF1FFFFFU)
+/* DEFERR
+This bit is set to '1' when a slave access generated a deferred bus error. Writing '0' to this bit clears this flag. Once this flag is set to '1', further bus errors would be ignored until it is cleared.
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_DEFERR_SHIFT (20U)
+#define RGX_CR_META_SP_MSLVCTRL1_DEFERR_CLRMSK (0XFFEFFFFFU)
+#define RGX_CR_META_SP_MSLVCTRL1_DEFERR_EN (0X00100000U)
+/* WR_ACTIVE
+If set means that a write is still in progress within the META core, else zero if write(s) have completed (Read only)
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_WR_ACTIVE_SHIFT (18U)
+#define RGX_CR_META_SP_MSLVCTRL1_WR_ACTIVE_CLRMSK (0XFFFBFFFFU)
+#define RGX_CR_META_SP_MSLVCTRL1_WR_ACTIVE_EN (0X00040000U)
+/* THREAD
+Specifies the thread identifier to be issued on read or write transactions within the META core.
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_THREAD_SHIFT (4U)
+#define RGX_CR_META_SP_MSLVCTRL1_THREAD_CLRMSK (0XFFFFFFCFU)
+/* TRANS_SIZE
+Selects the transaction size (number of byte lanes) generated within the META core for writes or reads. The following sizes are currently supported, 0 - 32-bit, 1 - 16-bit, and 2 - 8-bit.
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_TRANS_SIZE_SHIFT (2U)
+#define RGX_CR_META_SP_MSLVCTRL1_TRANS_SIZE_CLRMSK (0XFFFFFFF3U)
+/* BYTE_ROUND
+Byte routing/shift to be applied to data transfers performed on the MSLVDATAX and MSLVDATAT registers. Data will be duplicated in either direction so that 8-bit or 16-bit read or write operations can be performed using the lower part of the slave interface data bus.
+*/
+#define RGX_CR_META_SP_MSLVCTRL1_BYTE_ROUND_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVCTRL1_BYTE_ROUND_CLRMSK (0XFFFFFFFCU)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVHANDSHKE
+*/
+#define RGX_CR_META_SP_MSLVHANDSHKE (0x0A50U)
+#define RGX_CR_META_SP_MSLVHANDSHKE_MASKFULL (IMG_UINT64_C(0x000000000000000F))
+/* INPUT
+JTAG GPIO Input. Used for S/W handshake with the JTAG port.
+*/
+#define RGX_CR_META_SP_MSLVHANDSHKE_INPUT_SHIFT (2U)
+#define RGX_CR_META_SP_MSLVHANDSHKE_INPUT_CLRMSK (0XFFFFFFF3U)
+/* OUTPUT
+JTAG GPIO Output. Used for S/W handshake with the JTAG port.
+*/
+#define RGX_CR_META_SP_MSLVHANDSHKE_OUTPUT_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVHANDSHKE_OUTPUT_CLRMSK (0XFFFFFFFCU)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVT0KICK
+*/
+#define RGX_CR_META_SP_MSLVT0KICK (0x0A80U)
+#define RGX_CR_META_SP_MSLVT0KICK_MASKFULL (IMG_UINT64_C(0x000000000000FFFF))
+/* MSLVT0KICK
+Writing the unsigned integer value n to the bottom 16-bits of this register will cause n kicks to be accumulated by thread 0's 16-bit background kick accumulator. For read these bits are always read as '0' as this register is merely a conduit and has no associated store.
+*/
+#define RGX_CR_META_SP_MSLVT0KICK_MSLVT0KICK_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVT0KICK_MSLVT0KICK_CLRMSK (0XFFFF0000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVT0KICKI
+*/
+#define RGX_CR_META_SP_MSLVT0KICKI (0x0A88U)
+#define RGX_CR_META_SP_MSLVT0KICKI_MASKFULL (IMG_UINT64_C(0x000000000000FFFF))
+/* MSLVT0KICKI
+Writing the unsigned integer value n to the bottom 16-bits of this register will cause n kicks to be accumulated by thread 0's 16-bit interrupt kick accumulator. For read these bits are always read as '0' as this register is merely a conduit and has no associated store.
+*/
+#define RGX_CR_META_SP_MSLVT0KICKI_MSLVT0KICKI_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVT0KICKI_MSLVT0KICKI_CLRMSK (0XFFFF0000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVT1KICK
+*/
+#define RGX_CR_META_SP_MSLVT1KICK (0x0A90U)
+#define RGX_CR_META_SP_MSLVT1KICK_MASKFULL (IMG_UINT64_C(0x000000000000FFFF))
+/* MSLVT1KICK
+same behavior as MSLVT0KICK, but for thread1
+*/
+#define RGX_CR_META_SP_MSLVT1KICK_MSLVT1KICK_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVT1KICK_MSLVT1KICK_CLRMSK (0XFFFF0000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVT1KICKI
+*/
+#define RGX_CR_META_SP_MSLVT1KICKI (0x0A98U)
+#define RGX_CR_META_SP_MSLVT1KICKI_MASKFULL (IMG_UINT64_C(0x000000000000FFFF))
+/* MSLVT1KICKI
+same behavior as MSLVT0KICKI, but for thread1
+*/
+#define RGX_CR_META_SP_MSLVT1KICKI_MSLVT1KICKI_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVT1KICKI_MSLVT1KICKI_CLRMSK (0XFFFF0000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVT2KICK
+*/
+#define RGX_CR_META_SP_MSLVT2KICK (0x0AA0U)
+#define RGX_CR_META_SP_MSLVT2KICK_MASKFULL (IMG_UINT64_C(0x000000000000FFFF))
+/* MSLVT2KICK
+same behavior as MSLVT0KICK, but for thread2
+*/
+#define RGX_CR_META_SP_MSLVT2KICK_MSLVT2KICK_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVT2KICK_MSLVT2KICK_CLRMSK (0XFFFF0000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVT2KICKI
+*/
+#define RGX_CR_META_SP_MSLVT2KICKI (0x0AA8U)
+#define RGX_CR_META_SP_MSLVT2KICKI_MASKFULL (IMG_UINT64_C(0x000000000000FFFF))
+/* MSLVT2KICKI
+same behavior as MSLVT0KICKI, but for thread2
+*/
+#define RGX_CR_META_SP_MSLVT2KICKI_MSLVT2KICKI_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVT2KICKI_MSLVT2KICKI_CLRMSK (0XFFFF0000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVT3KICK
+*/
+#define RGX_CR_META_SP_MSLVT3KICK (0x0AB0U)
+#define RGX_CR_META_SP_MSLVT3KICK_MASKFULL (IMG_UINT64_C(0x000000000000FFFF))
+/* MSLVT3KICK
+same behavior as MSLVT0KICK, but for thread3
+*/
+#define RGX_CR_META_SP_MSLVT3KICK_MSLVT3KICK_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVT3KICK_MSLVT3KICK_CLRMSK (0XFFFF0000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVT3KICKI
+*/
+#define RGX_CR_META_SP_MSLVT3KICKI (0x0AB8U)
+#define RGX_CR_META_SP_MSLVT3KICKI_MASKFULL (IMG_UINT64_C(0x000000000000FFFF))
+/* MSLVT3KICKI
+same behavior as MSLVT0KICKI, but for thread3
+*/
+#define RGX_CR_META_SP_MSLVT3KICKI_MSLVT3KICKI_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVT3KICKI_MSLVT3KICKI_CLRMSK (0XFFFF0000U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVRST
+*/
+#define RGX_CR_META_SP_MSLVRST (0x0AC0U)
+#define RGX_CR_META_SP_MSLVRST_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* SOFTRESET
+This write only bit may be used to soft reset the core. If a value of '1' is written to bit 0 the core will be held in reset. The register must subsequently be cleared again to take the core out of reset. To ensure correct operation the core must be held in reset for at least 16 core clock cycles.
+*/
+#define RGX_CR_META_SP_MSLVRST_SOFTRESET_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVRST_SOFTRESET_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_META_SP_MSLVRST_SOFTRESET_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVIRQSTATUS
+*/
+#define RGX_CR_META_SP_MSLVIRQSTATUS (0x0AC8U)
+#define RGX_CR_META_SP_MSLVIRQSTATUS_MASKFULL (IMG_UINT64_C(0x000000000000000C))
+/* TRIGVECT3
+IRQ event occurred due to vectoring to an event inside META core to the host (set trigger vector to 3). This status bit can be written with '0' to clear the IRQ event
+*/
+#define RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT3_SHIFT (3U)
+#define RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT3_CLRMSK (0XFFFFFFF7U)
+#define RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT3_EN (0X00000008U)
+/* TRIGVECT2
+IRQ event occurred due to vectoring to an event inside META core to the host (set trigger vector to 2). This status bit can be written with '0' to clear the IRQ event.
+*/
+#define RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_SHIFT (2U)
+#define RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN (0X00000004U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVIRQENABLE
+*/
+#define RGX_CR_META_SP_MSLVIRQENABLE (0x0AD0U)
+#define RGX_CR_META_SP_MSLVIRQENABLE_MASKFULL (IMG_UINT64_C(0x000000000000000C))
+/* EVENT1
+Enable Slave interrupt event 1 to raise an output interrupt.
+*/
+#define RGX_CR_META_SP_MSLVIRQENABLE_EVENT1_SHIFT (3U)
+#define RGX_CR_META_SP_MSLVIRQENABLE_EVENT1_CLRMSK (0XFFFFFFF7U)
+#define RGX_CR_META_SP_MSLVIRQENABLE_EVENT1_EN (0X00000008U)
+/* EVENT0
+Enable Slave interrupt event 0 to raise an output interrupt.
+*/
+#define RGX_CR_META_SP_MSLVIRQENABLE_EVENT0_SHIFT (2U)
+#define RGX_CR_META_SP_MSLVIRQENABLE_EVENT0_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_META_SP_MSLVIRQENABLE_EVENT0_EN (0X00000004U)
+
+
+/*
+ Register RGX_CR_META_SP_MSLVIRQLEVEL
+*/
+#define RGX_CR_META_SP_MSLVIRQLEVEL (0x0AD8U)
+#define RGX_CR_META_SP_MSLVIRQLEVEL_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* MODE
+Level or edge mode for the META core output triggers.
+*/
+#define RGX_CR_META_SP_MSLVIRQLEVEL_MODE_SHIFT (0U)
+#define RGX_CR_META_SP_MSLVIRQLEVEL_MODE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_META_SP_MSLVIRQLEVEL_MODE_EN (0X00000001U)
+
+
+/*
+
+ This register allows firmware tasks to be scheduled on the META (Garten) core.
+
+*/
+/*
+ Register RGX_CR_MTS_SCHEDULE
+*/
+#define RGX_CR_MTS_SCHEDULE (0x0B00U)
+#define RGX_CR_MTS_SCHEDULE_MASKFULL (IMG_UINT64_C(0x00000000000001FF))
+/* HOST
+Host Interrupte kick
+*/
+#define RGX_CR_MTS_SCHEDULE_HOST_SHIFT (8U)
+#define RGX_CR_MTS_SCHEDULE_HOST_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_MTS_SCHEDULE_HOST_BG_TIMER (00000000U)
+#define RGX_CR_MTS_SCHEDULE_HOST_HOST (0X00000100U)
+/* PRIORITY
+DataMaster Priority
+*/
+#define RGX_CR_MTS_SCHEDULE_PRIORITY_SHIFT (6U)
+#define RGX_CR_MTS_SCHEDULE_PRIORITY_CLRMSK (0XFFFFFF3FU)
+#define RGX_CR_MTS_SCHEDULE_PRIORITY_PRT0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE_PRIORITY_PRT1 (0X00000040U)
+#define RGX_CR_MTS_SCHEDULE_PRIORITY_PRT2 (0X00000080U)
+#define RGX_CR_MTS_SCHEDULE_PRIORITY_PRT3 (0X000000C0U)
+/* CONTEXT default: BGCTX (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE_CONTEXT_SHIFT (5U)
+#define RGX_CR_MTS_SCHEDULE_CONTEXT_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_MTS_SCHEDULE_CONTEXT_BGCTX (00000000U)
+#define RGX_CR_MTS_SCHEDULE_CONTEXT_INTCTX (0X00000020U)
+/* TASK default: NON_COUNTED (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE_TASK_SHIFT (4U)
+#define RGX_CR_MTS_SCHEDULE_TASK_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_MTS_SCHEDULE_TASK_NON_COUNTED (00000000U)
+#define RGX_CR_MTS_SCHEDULE_TASK_COUNTED (0X00000010U)
+/* DM
+DataMaster Type
+*/
+#define RGX_CR_MTS_SCHEDULE_DM_SHIFT (0U)
+#define RGX_CR_MTS_SCHEDULE_DM_CLRMSK (0XFFFFFFF0U)
+#define RGX_CR_MTS_SCHEDULE_DM_DM0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE_DM_DM1 (0X00000001U)
+#define RGX_CR_MTS_SCHEDULE_DM_DM2 (0X00000002U)
+#define RGX_CR_MTS_SCHEDULE_DM_DM3 (0X00000003U)
+#define RGX_CR_MTS_SCHEDULE_DM_DM4 (0X00000004U)
+#define RGX_CR_MTS_SCHEDULE_DM_DM5 (0X00000005U)
+#define RGX_CR_MTS_SCHEDULE_DM_DM6 (0X00000006U)
+#define RGX_CR_MTS_SCHEDULE_DM_DM7 (0X00000007U)
+#define RGX_CR_MTS_SCHEDULE_DM_DM_ALL (0X0000000FU)
+
+
+/*
+
+ This register allows firmware tasks to be scheduled on the META (Garten) core.
+
+*/
+/*
+ Register RGX_CR_MTS_SCHEDULE1
+*/
+#define RGX_CR_MTS_SCHEDULE1 (0x10B00U)
+#define RGX_CR_MTS_SCHEDULE1_MASKFULL (IMG_UINT64_C(0x00000000000001FF))
+/* HOST
+Host Interrupte kick
+*/
+#define RGX_CR_MTS_SCHEDULE1_HOST_SHIFT (8U)
+#define RGX_CR_MTS_SCHEDULE1_HOST_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_MTS_SCHEDULE1_HOST_BG_TIMER (00000000U)
+#define RGX_CR_MTS_SCHEDULE1_HOST_HOST (0X00000100U)
+/* PRIORITY
+DataMaster Priority
+*/
+#define RGX_CR_MTS_SCHEDULE1_PRIORITY_SHIFT (6U)
+#define RGX_CR_MTS_SCHEDULE1_PRIORITY_CLRMSK (0XFFFFFF3FU)
+#define RGX_CR_MTS_SCHEDULE1_PRIORITY_PRT0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE1_PRIORITY_PRT1 (0X00000040U)
+#define RGX_CR_MTS_SCHEDULE1_PRIORITY_PRT2 (0X00000080U)
+#define RGX_CR_MTS_SCHEDULE1_PRIORITY_PRT3 (0X000000C0U)
+/* CONTEXT default: BGCTX (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE1_CONTEXT_SHIFT (5U)
+#define RGX_CR_MTS_SCHEDULE1_CONTEXT_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_MTS_SCHEDULE1_CONTEXT_BGCTX (00000000U)
+#define RGX_CR_MTS_SCHEDULE1_CONTEXT_INTCTX (0X00000020U)
+/* TASK default: NON_COUNTED (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE1_TASK_SHIFT (4U)
+#define RGX_CR_MTS_SCHEDULE1_TASK_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_MTS_SCHEDULE1_TASK_NON_COUNTED (00000000U)
+#define RGX_CR_MTS_SCHEDULE1_TASK_COUNTED (0X00000010U)
+/* DM
+DataMaster Type
+*/
+#define RGX_CR_MTS_SCHEDULE1_DM_SHIFT (0U)
+#define RGX_CR_MTS_SCHEDULE1_DM_CLRMSK (0XFFFFFFF0U)
+#define RGX_CR_MTS_SCHEDULE1_DM_DM0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE1_DM_DM1 (0X00000001U)
+#define RGX_CR_MTS_SCHEDULE1_DM_DM2 (0X00000002U)
+#define RGX_CR_MTS_SCHEDULE1_DM_DM3 (0X00000003U)
+#define RGX_CR_MTS_SCHEDULE1_DM_DM4 (0X00000004U)
+#define RGX_CR_MTS_SCHEDULE1_DM_DM5 (0X00000005U)
+#define RGX_CR_MTS_SCHEDULE1_DM_DM6 (0X00000006U)
+#define RGX_CR_MTS_SCHEDULE1_DM_DM7 (0X00000007U)
+#define RGX_CR_MTS_SCHEDULE1_DM_DM_ALL (0X0000000FU)
+
+
+/*
+
+ This register allows firmware tasks to be scheduled on the META (Garten) core.
+
+*/
+/*
+ Register RGX_CR_MTS_SCHEDULE2
+*/
+#define RGX_CR_MTS_SCHEDULE2 (0x20B00U)
+#define RGX_CR_MTS_SCHEDULE2_MASKFULL (IMG_UINT64_C(0x00000000000001FF))
+/* HOST
+Host Interrupte kick
+*/
+#define RGX_CR_MTS_SCHEDULE2_HOST_SHIFT (8U)
+#define RGX_CR_MTS_SCHEDULE2_HOST_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_MTS_SCHEDULE2_HOST_BG_TIMER (00000000U)
+#define RGX_CR_MTS_SCHEDULE2_HOST_HOST (0X00000100U)
+/* PRIORITY
+DataMaster Priority
+*/
+#define RGX_CR_MTS_SCHEDULE2_PRIORITY_SHIFT (6U)
+#define RGX_CR_MTS_SCHEDULE2_PRIORITY_CLRMSK (0XFFFFFF3FU)
+#define RGX_CR_MTS_SCHEDULE2_PRIORITY_PRT0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE2_PRIORITY_PRT1 (0X00000040U)
+#define RGX_CR_MTS_SCHEDULE2_PRIORITY_PRT2 (0X00000080U)
+#define RGX_CR_MTS_SCHEDULE2_PRIORITY_PRT3 (0X000000C0U)
+/* CONTEXT default: BGCTX (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE2_CONTEXT_SHIFT (5U)
+#define RGX_CR_MTS_SCHEDULE2_CONTEXT_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_MTS_SCHEDULE2_CONTEXT_BGCTX (00000000U)
+#define RGX_CR_MTS_SCHEDULE2_CONTEXT_INTCTX (0X00000020U)
+/* TASK default: NON_COUNTED (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE2_TASK_SHIFT (4U)
+#define RGX_CR_MTS_SCHEDULE2_TASK_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_MTS_SCHEDULE2_TASK_NON_COUNTED (00000000U)
+#define RGX_CR_MTS_SCHEDULE2_TASK_COUNTED (0X00000010U)
+/* DM
+DataMaster Type
+*/
+#define RGX_CR_MTS_SCHEDULE2_DM_SHIFT (0U)
+#define RGX_CR_MTS_SCHEDULE2_DM_CLRMSK (0XFFFFFFF0U)
+#define RGX_CR_MTS_SCHEDULE2_DM_DM0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE2_DM_DM1 (0X00000001U)
+#define RGX_CR_MTS_SCHEDULE2_DM_DM2 (0X00000002U)
+#define RGX_CR_MTS_SCHEDULE2_DM_DM3 (0X00000003U)
+#define RGX_CR_MTS_SCHEDULE2_DM_DM4 (0X00000004U)
+#define RGX_CR_MTS_SCHEDULE2_DM_DM5 (0X00000005U)
+#define RGX_CR_MTS_SCHEDULE2_DM_DM6 (0X00000006U)
+#define RGX_CR_MTS_SCHEDULE2_DM_DM7 (0X00000007U)
+#define RGX_CR_MTS_SCHEDULE2_DM_DM_ALL (0X0000000FU)
+
+
+/*
+
+ This register allows firmware tasks to be scheduled on the META (Garten) core.
+
+*/
+/*
+ Register RGX_CR_MTS_SCHEDULE3
+*/
+#define RGX_CR_MTS_SCHEDULE3 (0x30B00U)
+#define RGX_CR_MTS_SCHEDULE3_MASKFULL (IMG_UINT64_C(0x00000000000001FF))
+/* HOST
+Host Interrupte kick
+*/
+#define RGX_CR_MTS_SCHEDULE3_HOST_SHIFT (8U)
+#define RGX_CR_MTS_SCHEDULE3_HOST_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_MTS_SCHEDULE3_HOST_BG_TIMER (00000000U)
+#define RGX_CR_MTS_SCHEDULE3_HOST_HOST (0X00000100U)
+/* PRIORITY
+DataMaster Priority
+*/
+#define RGX_CR_MTS_SCHEDULE3_PRIORITY_SHIFT (6U)
+#define RGX_CR_MTS_SCHEDULE3_PRIORITY_CLRMSK (0XFFFFFF3FU)
+#define RGX_CR_MTS_SCHEDULE3_PRIORITY_PRT0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE3_PRIORITY_PRT1 (0X00000040U)
+#define RGX_CR_MTS_SCHEDULE3_PRIORITY_PRT2 (0X00000080U)
+#define RGX_CR_MTS_SCHEDULE3_PRIORITY_PRT3 (0X000000C0U)
+/* CONTEXT default: BGCTX (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE3_CONTEXT_SHIFT (5U)
+#define RGX_CR_MTS_SCHEDULE3_CONTEXT_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_MTS_SCHEDULE3_CONTEXT_BGCTX (00000000U)
+#define RGX_CR_MTS_SCHEDULE3_CONTEXT_INTCTX (0X00000020U)
+/* TASK default: NON_COUNTED (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE3_TASK_SHIFT (4U)
+#define RGX_CR_MTS_SCHEDULE3_TASK_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_MTS_SCHEDULE3_TASK_NON_COUNTED (00000000U)
+#define RGX_CR_MTS_SCHEDULE3_TASK_COUNTED (0X00000010U)
+/* DM
+DataMaster Type
+*/
+#define RGX_CR_MTS_SCHEDULE3_DM_SHIFT (0U)
+#define RGX_CR_MTS_SCHEDULE3_DM_CLRMSK (0XFFFFFFF0U)
+#define RGX_CR_MTS_SCHEDULE3_DM_DM0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE3_DM_DM1 (0X00000001U)
+#define RGX_CR_MTS_SCHEDULE3_DM_DM2 (0X00000002U)
+#define RGX_CR_MTS_SCHEDULE3_DM_DM3 (0X00000003U)
+#define RGX_CR_MTS_SCHEDULE3_DM_DM4 (0X00000004U)
+#define RGX_CR_MTS_SCHEDULE3_DM_DM5 (0X00000005U)
+#define RGX_CR_MTS_SCHEDULE3_DM_DM6 (0X00000006U)
+#define RGX_CR_MTS_SCHEDULE3_DM_DM7 (0X00000007U)
+#define RGX_CR_MTS_SCHEDULE3_DM_DM_ALL (0X0000000FU)
+
+
+/*
+
+ This register allows firmware tasks to be scheduled on the META (Garten) core.
+
+*/
+/*
+ Register RGX_CR_MTS_SCHEDULE4
+*/
+#define RGX_CR_MTS_SCHEDULE4 (0x40B00U)
+#define RGX_CR_MTS_SCHEDULE4_MASKFULL (IMG_UINT64_C(0x00000000000001FF))
+/* HOST
+Host Interrupte kick
+*/
+#define RGX_CR_MTS_SCHEDULE4_HOST_SHIFT (8U)
+#define RGX_CR_MTS_SCHEDULE4_HOST_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_MTS_SCHEDULE4_HOST_BG_TIMER (00000000U)
+#define RGX_CR_MTS_SCHEDULE4_HOST_HOST (0X00000100U)
+/* PRIORITY
+DataMaster Priority
+*/
+#define RGX_CR_MTS_SCHEDULE4_PRIORITY_SHIFT (6U)
+#define RGX_CR_MTS_SCHEDULE4_PRIORITY_CLRMSK (0XFFFFFF3FU)
+#define RGX_CR_MTS_SCHEDULE4_PRIORITY_PRT0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE4_PRIORITY_PRT1 (0X00000040U)
+#define RGX_CR_MTS_SCHEDULE4_PRIORITY_PRT2 (0X00000080U)
+#define RGX_CR_MTS_SCHEDULE4_PRIORITY_PRT3 (0X000000C0U)
+/* CONTEXT default: BGCTX (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE4_CONTEXT_SHIFT (5U)
+#define RGX_CR_MTS_SCHEDULE4_CONTEXT_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_MTS_SCHEDULE4_CONTEXT_BGCTX (00000000U)
+#define RGX_CR_MTS_SCHEDULE4_CONTEXT_INTCTX (0X00000020U)
+/* TASK default: NON_COUNTED (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE4_TASK_SHIFT (4U)
+#define RGX_CR_MTS_SCHEDULE4_TASK_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_MTS_SCHEDULE4_TASK_NON_COUNTED (00000000U)
+#define RGX_CR_MTS_SCHEDULE4_TASK_COUNTED (0X00000010U)
+/* DM
+DataMaster Type
+*/
+#define RGX_CR_MTS_SCHEDULE4_DM_SHIFT (0U)
+#define RGX_CR_MTS_SCHEDULE4_DM_CLRMSK (0XFFFFFFF0U)
+#define RGX_CR_MTS_SCHEDULE4_DM_DM0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE4_DM_DM1 (0X00000001U)
+#define RGX_CR_MTS_SCHEDULE4_DM_DM2 (0X00000002U)
+#define RGX_CR_MTS_SCHEDULE4_DM_DM3 (0X00000003U)
+#define RGX_CR_MTS_SCHEDULE4_DM_DM4 (0X00000004U)
+#define RGX_CR_MTS_SCHEDULE4_DM_DM5 (0X00000005U)
+#define RGX_CR_MTS_SCHEDULE4_DM_DM6 (0X00000006U)
+#define RGX_CR_MTS_SCHEDULE4_DM_DM7 (0X00000007U)
+#define RGX_CR_MTS_SCHEDULE4_DM_DM_ALL (0X0000000FU)
+
+
+/*
+
+ This register allows firmware tasks to be scheduled on the META (Garten) core.
+
+*/
+/*
+ Register RGX_CR_MTS_SCHEDULE5
+*/
+#define RGX_CR_MTS_SCHEDULE5 (0x50B00U)
+#define RGX_CR_MTS_SCHEDULE5_MASKFULL (IMG_UINT64_C(0x00000000000001FF))
+/* HOST
+Host Interrupte kick
+*/
+#define RGX_CR_MTS_SCHEDULE5_HOST_SHIFT (8U)
+#define RGX_CR_MTS_SCHEDULE5_HOST_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_MTS_SCHEDULE5_HOST_BG_TIMER (00000000U)
+#define RGX_CR_MTS_SCHEDULE5_HOST_HOST (0X00000100U)
+/* PRIORITY
+DataMaster Priority
+*/
+#define RGX_CR_MTS_SCHEDULE5_PRIORITY_SHIFT (6U)
+#define RGX_CR_MTS_SCHEDULE5_PRIORITY_CLRMSK (0XFFFFFF3FU)
+#define RGX_CR_MTS_SCHEDULE5_PRIORITY_PRT0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE5_PRIORITY_PRT1 (0X00000040U)
+#define RGX_CR_MTS_SCHEDULE5_PRIORITY_PRT2 (0X00000080U)
+#define RGX_CR_MTS_SCHEDULE5_PRIORITY_PRT3 (0X000000C0U)
+/* CONTEXT default: BGCTX (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE5_CONTEXT_SHIFT (5U)
+#define RGX_CR_MTS_SCHEDULE5_CONTEXT_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_MTS_SCHEDULE5_CONTEXT_BGCTX (00000000U)
+#define RGX_CR_MTS_SCHEDULE5_CONTEXT_INTCTX (0X00000020U)
+/* TASK default: NON_COUNTED (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE5_TASK_SHIFT (4U)
+#define RGX_CR_MTS_SCHEDULE5_TASK_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_MTS_SCHEDULE5_TASK_NON_COUNTED (00000000U)
+#define RGX_CR_MTS_SCHEDULE5_TASK_COUNTED (0X00000010U)
+/* DM
+DataMaster Type
+*/
+#define RGX_CR_MTS_SCHEDULE5_DM_SHIFT (0U)
+#define RGX_CR_MTS_SCHEDULE5_DM_CLRMSK (0XFFFFFFF0U)
+#define RGX_CR_MTS_SCHEDULE5_DM_DM0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE5_DM_DM1 (0X00000001U)
+#define RGX_CR_MTS_SCHEDULE5_DM_DM2 (0X00000002U)
+#define RGX_CR_MTS_SCHEDULE5_DM_DM3 (0X00000003U)
+#define RGX_CR_MTS_SCHEDULE5_DM_DM4 (0X00000004U)
+#define RGX_CR_MTS_SCHEDULE5_DM_DM5 (0X00000005U)
+#define RGX_CR_MTS_SCHEDULE5_DM_DM6 (0X00000006U)
+#define RGX_CR_MTS_SCHEDULE5_DM_DM7 (0X00000007U)
+#define RGX_CR_MTS_SCHEDULE5_DM_DM_ALL (0X0000000FU)
+
+
+/*
+
+ This register allows firmware tasks to be scheduled on the META (Garten) core.
+
+*/
+/*
+ Register RGX_CR_MTS_SCHEDULE6
+*/
+#define RGX_CR_MTS_SCHEDULE6 (0x60B00U)
+#define RGX_CR_MTS_SCHEDULE6_MASKFULL (IMG_UINT64_C(0x00000000000001FF))
+/* HOST
+Host Interrupte kick
+*/
+#define RGX_CR_MTS_SCHEDULE6_HOST_SHIFT (8U)
+#define RGX_CR_MTS_SCHEDULE6_HOST_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_MTS_SCHEDULE6_HOST_BG_TIMER (00000000U)
+#define RGX_CR_MTS_SCHEDULE6_HOST_HOST (0X00000100U)
+/* PRIORITY
+DataMaster Priority
+*/
+#define RGX_CR_MTS_SCHEDULE6_PRIORITY_SHIFT (6U)
+#define RGX_CR_MTS_SCHEDULE6_PRIORITY_CLRMSK (0XFFFFFF3FU)
+#define RGX_CR_MTS_SCHEDULE6_PRIORITY_PRT0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE6_PRIORITY_PRT1 (0X00000040U)
+#define RGX_CR_MTS_SCHEDULE6_PRIORITY_PRT2 (0X00000080U)
+#define RGX_CR_MTS_SCHEDULE6_PRIORITY_PRT3 (0X000000C0U)
+/* CONTEXT default: BGCTX (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE6_CONTEXT_SHIFT (5U)
+#define RGX_CR_MTS_SCHEDULE6_CONTEXT_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_MTS_SCHEDULE6_CONTEXT_BGCTX (00000000U)
+#define RGX_CR_MTS_SCHEDULE6_CONTEXT_INTCTX (0X00000020U)
+/* TASK default: NON_COUNTED (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE6_TASK_SHIFT (4U)
+#define RGX_CR_MTS_SCHEDULE6_TASK_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_MTS_SCHEDULE6_TASK_NON_COUNTED (00000000U)
+#define RGX_CR_MTS_SCHEDULE6_TASK_COUNTED (0X00000010U)
+/* DM
+DataMaster Type
+*/
+#define RGX_CR_MTS_SCHEDULE6_DM_SHIFT (0U)
+#define RGX_CR_MTS_SCHEDULE6_DM_CLRMSK (0XFFFFFFF0U)
+#define RGX_CR_MTS_SCHEDULE6_DM_DM0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE6_DM_DM1 (0X00000001U)
+#define RGX_CR_MTS_SCHEDULE6_DM_DM2 (0X00000002U)
+#define RGX_CR_MTS_SCHEDULE6_DM_DM3 (0X00000003U)
+#define RGX_CR_MTS_SCHEDULE6_DM_DM4 (0X00000004U)
+#define RGX_CR_MTS_SCHEDULE6_DM_DM5 (0X00000005U)
+#define RGX_CR_MTS_SCHEDULE6_DM_DM6 (0X00000006U)
+#define RGX_CR_MTS_SCHEDULE6_DM_DM7 (0X00000007U)
+#define RGX_CR_MTS_SCHEDULE6_DM_DM_ALL (0X0000000FU)
+
+
+/*
+
+ This register allows firmware tasks to be scheduled on the META (Garten) core.
+
+*/
+/*
+ Register RGX_CR_MTS_SCHEDULE7
+*/
+#define RGX_CR_MTS_SCHEDULE7 (0x70B00U)
+#define RGX_CR_MTS_SCHEDULE7_MASKFULL (IMG_UINT64_C(0x00000000000001FF))
+/* HOST
+Host Interrupte kick
+*/
+#define RGX_CR_MTS_SCHEDULE7_HOST_SHIFT (8U)
+#define RGX_CR_MTS_SCHEDULE7_HOST_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_MTS_SCHEDULE7_HOST_BG_TIMER (00000000U)
+#define RGX_CR_MTS_SCHEDULE7_HOST_HOST (0X00000100U)
+/* PRIORITY
+DataMaster Priority
+*/
+#define RGX_CR_MTS_SCHEDULE7_PRIORITY_SHIFT (6U)
+#define RGX_CR_MTS_SCHEDULE7_PRIORITY_CLRMSK (0XFFFFFF3FU)
+#define RGX_CR_MTS_SCHEDULE7_PRIORITY_PRT0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE7_PRIORITY_PRT1 (0X00000040U)
+#define RGX_CR_MTS_SCHEDULE7_PRIORITY_PRT2 (0X00000080U)
+#define RGX_CR_MTS_SCHEDULE7_PRIORITY_PRT3 (0X000000C0U)
+/* CONTEXT default: BGCTX (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE7_CONTEXT_SHIFT (5U)
+#define RGX_CR_MTS_SCHEDULE7_CONTEXT_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_MTS_SCHEDULE7_CONTEXT_BGCTX (00000000U)
+#define RGX_CR_MTS_SCHEDULE7_CONTEXT_INTCTX (0X00000020U)
+/* TASK default: NON_COUNTED (0x00000000) */
+#define RGX_CR_MTS_SCHEDULE7_TASK_SHIFT (4U)
+#define RGX_CR_MTS_SCHEDULE7_TASK_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_MTS_SCHEDULE7_TASK_NON_COUNTED (00000000U)
+#define RGX_CR_MTS_SCHEDULE7_TASK_COUNTED (0X00000010U)
+/* DM
+DataMaster Type
+*/
+#define RGX_CR_MTS_SCHEDULE7_DM_SHIFT (0U)
+#define RGX_CR_MTS_SCHEDULE7_DM_CLRMSK (0XFFFFFFF0U)
+#define RGX_CR_MTS_SCHEDULE7_DM_DM0 (00000000U)
+#define RGX_CR_MTS_SCHEDULE7_DM_DM1 (0X00000001U)
+#define RGX_CR_MTS_SCHEDULE7_DM_DM2 (0X00000002U)
+#define RGX_CR_MTS_SCHEDULE7_DM_DM3 (0X00000003U)
+#define RGX_CR_MTS_SCHEDULE7_DM_DM4 (0X00000004U)
+#define RGX_CR_MTS_SCHEDULE7_DM_DM5 (0X00000005U)
+#define RGX_CR_MTS_SCHEDULE7_DM_DM6 (0X00000006U)
+#define RGX_CR_MTS_SCHEDULE7_DM_DM7 (0X00000007U)
+#define RGX_CR_MTS_SCHEDULE7_DM_DM_ALL (0X0000000FU)
+
+
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*
+
+ This register contains the configuration options for the Garten wrapper.
+
+*/
+/*
+ Register RGX_CR_MTS_GARTEN_WRAPPER_CONFIG
+*/
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG (0x0B50U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_MASKFULL (IMG_UINT64_C(0x000FF0FFFFFFF001))
+/* FENCE_PC_BASE
+Page Catalogue base address number to be used for fence requests
+*/
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_SHIFT (44U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_CLRMSK (IMG_UINT64_C(0XFFF00FFFFFFFFFFF))
+/* FENCE_ADDR
+4k page address to be used for fence requests
+*/
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_ADDR_SHIFT (12U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_ADDR_CLRMSK (IMG_UINT64_C(0XFFFFFF0000000FFF))
+/* IDLE_CTRL default: MTS (0x00000001) */
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_SHIFT (0U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_MTS (IMG_UINT64_C(0x0000000000000001))
+#endif /* RGX_FEATURE_S7_TOP_INFRASTRUCTURE */
+
+
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*
+
+ This register contains the configuration options for the Garten wrapper.
+
+*/
+/*
+ Register RGX_CR_MTS_GARTEN_WRAPPER_CONFIG
+*/
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG (0x0B50U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_MASKFULL (IMG_UINT64_C(0x0000FFFFFFFFF001))
+/* FENCE_PC_BASE
+Page Catalogue base address number to be used for fence requests
+*/
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_SHIFT (44U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_CLRMSK (IMG_UINT64_C(0XFFFF0FFFFFFFFFFF))
+/* FENCE_DM
+Data master value to be used for fence requests
+*/
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_DM_SHIFT (40U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_DM_CLRMSK (IMG_UINT64_C(0XFFFFF0FFFFFFFFFF))
+/* FENCE_ADDR
+4k page address to be used for fence requests
+*/
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_ADDR_SHIFT (12U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_ADDR_CLRMSK (IMG_UINT64_C(0XFFFFFF0000000FFF))
+/* IDLE_CTRL default: MTS (0x00000001) */
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_SHIFT (0U)
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_MTS (IMG_UINT64_C(0x0000000000000001))
+#endif /* !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE) */
+
+
+/*
+ Register RGX_CR_META_BOOT
+*/
+#define RGX_CR_META_BOOT (0x0BF8U)
+#define RGX_CR_META_BOOT_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* MODE
+ 0 = Don't boot, 1 = Boot
+*/
+#define RGX_CR_META_BOOT_MODE_SHIFT (0U)
+#define RGX_CR_META_BOOT_MODE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_META_BOOT_MODE_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_GARTEN_SLC
+*/
+#define RGX_CR_GARTEN_SLC (0x0BB8U)
+#define RGX_CR_GARTEN_SLC_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* FORCE_COHERENCY default: 0x00000001
+ 0 = SLC control, 1 = SLC Coherency Forced
+*/
+#define RGX_CR_GARTEN_SLC_FORCE_COHERENCY_SHIFT (0U)
+#define RGX_CR_GARTEN_SLC_FORCE_COHERENCY_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_GARTEN_SLC_FORCE_COHERENCY_EN (0X00000001U)
+
+
+/*
+ Index registers per data master. Byte aligned fields to allow byte-masked access
+*/
+/*
+ Register RGX_CR_BIF_CAT_BASE_INDEX
+*/
+#define RGX_CR_BIF_CAT_BASE_INDEX (0x1240U)
+#define RGX_CR_BIF_CAT_BASE_INDEX_MASKFULL (IMG_UINT64_C(0x0007070707070707))
+#if defined(RGX_FEATURE_RAY_TRACING)
+/* RVTX
+Catalogue base address for VRDM, SHF, SHG and RPM
+*/
+#define RGX_CR_BIF_CAT_BASE_INDEX_RVTX_SHIFT (48U)
+#define RGX_CR_BIF_CAT_BASE_INDEX_RVTX_CLRMSK (IMG_UINT64_C(0XFFF8FFFFFFFFFFFF))
+/* RAY
+Catalogue base address for RDM and FBA
+*/
+#define RGX_CR_BIF_CAT_BASE_INDEX_RAY_SHIFT (40U)
+#define RGX_CR_BIF_CAT_BASE_INDEX_RAY_CLRMSK (IMG_UINT64_C(0XFFFFF8FFFFFFFFFF))
+#endif /* RGX_FEATURE_RAY_TRACING */
+
+/* HOST
+Catalogue Base number for HOST data master
+*/
+#define RGX_CR_BIF_CAT_BASE_INDEX_HOST_SHIFT (32U)
+#define RGX_CR_BIF_CAT_BASE_INDEX_HOST_CLRMSK (IMG_UINT64_C(0XFFFFFFF8FFFFFFFF))
+/* TLA
+Catalogue Base number for TLA data master
+*/
+#define RGX_CR_BIF_CAT_BASE_INDEX_TLA_SHIFT (24U)
+#define RGX_CR_BIF_CAT_BASE_INDEX_TLA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFF8FFFFFF))
+/* CDM
+Catalogue Base number for CDM data master
+*/
+#define RGX_CR_BIF_CAT_BASE_INDEX_CDM_SHIFT (16U)
+#define RGX_CR_BIF_CAT_BASE_INDEX_CDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFF8FFFF))
+/* PIXEL
+Catalogue Base number for PIXEL data master
+*/
+#define RGX_CR_BIF_CAT_BASE_INDEX_PIXEL_SHIFT (8U)
+#define RGX_CR_BIF_CAT_BASE_INDEX_PIXEL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF8FF))
+/* TA
+Catalogue Base number for TA data master
+*/
+#define RGX_CR_BIF_CAT_BASE_INDEX_TA_SHIFT (0U)
+#define RGX_CR_BIF_CAT_BASE_INDEX_TA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF8))
+
+
+/*
+
+Indicates a fault has occurred on bank 0 and provides details of fault
+
+*/
+/*
+ Register RGX_CR_BIF_FAULT_BANK0_MMU_STATUS
+*/
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS (0x12B0U)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_MASKFULL (IMG_UINT64_C(0x000000000000F775))
+/* CAT_BASE
+Catalogue base address number
+*/
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_SHIFT (12U)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_CLRMSK (0XFFFF0FFFU)
+/* PAGE_SIZE
+Page size
+*/
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_PAGE_SIZE_SHIFT (8U)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_PAGE_SIZE_CLRMSK (0XFFFFF8FFU)
+/* DATA_TYPE
+MMU data type that was invalid (on valid fault)
+*/
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_DATA_TYPE_SHIFT (5U)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_DATA_TYPE_CLRMSK (0XFFFFFF9FU)
+/* FAULT_RO
+Indicates read-only fault('1') or valid fault('0')
+*/
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_RO_SHIFT (4U)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_RO_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_RO_EN (0X00000010U)
+/* FAULT_PM_META_RO
+Indicates pm/meta protected region fault
+*/
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_PM_META_RO_SHIFT (2U)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_PM_META_RO_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_PM_META_RO_EN (0X00000004U)
+/* FAULT
+Indicates a fault has occured
+*/
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_SHIFT (0U)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_EN (0X00000001U)
+
+
+/*
+
+Provides details of the request that faulted on bank 0
+
+*/
+/*
+ Register RGX_CR_BIF_FAULT_BANK0_REQ_STATUS
+*/
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS (0x12B8U)
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_MASKFULL (IMG_UINT64_C(0x0007FFFFFFFFFFF0))
+/* RNW*/
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_RNW_SHIFT (50U)
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_RNW_CLRMSK (IMG_UINT64_C(0XFFFBFFFFFFFFFFFF))
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_RNW_EN (IMG_UINT64_C(0X0004000000000000))
+/* TAG_SB*/
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_SB_SHIFT (44U)
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_SB_CLRMSK (IMG_UINT64_C(0XFFFC0FFFFFFFFFFF))
+/* TAG_ID*/
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_ID_SHIFT (40U)
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_ID_CLRMSK (IMG_UINT64_C(0XFFFFF0FFFFFFFFFF))
+/* ADDRESS*/
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_SHIFT (4U)
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_CLRMSK (IMG_UINT64_C(0XFFFFFF000000000F))
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_ALIGNSHIFT (4U)
+#define RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_ALIGNSIZE (16U)
+
+
+/*
+
+Indicates a fault has occurred on bank 1 and provides details of fault
+
+*/
+/*
+ Register RGX_CR_BIF_FAULT_BANK1_MMU_STATUS
+*/
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS (0x12C0U)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_MASKFULL (IMG_UINT64_C(0x000000000000F775))
+/* CAT_BASE
+Catalogue base address number
+*/
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_CAT_BASE_SHIFT (12U)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_CAT_BASE_CLRMSK (0XFFFF0FFFU)
+/* PAGE_SIZE
+Page size
+*/
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_PAGE_SIZE_SHIFT (8U)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_PAGE_SIZE_CLRMSK (0XFFFFF8FFU)
+/* DATA_TYPE
+MMU data type that was invalid (on valid fault)
+*/
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_DATA_TYPE_SHIFT (5U)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_DATA_TYPE_CLRMSK (0XFFFFFF9FU)
+/* FAULT_RO
+Indicates read-only fault('1') of valid fault('0')
+*/
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_FAULT_RO_SHIFT (4U)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_FAULT_RO_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_FAULT_RO_EN (0X00000010U)
+/* FAULT_PM_META_RO
+Indicates pm/meta protected region fault
+*/
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_FAULT_PM_META_RO_SHIFT (2U)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_FAULT_PM_META_RO_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_FAULT_PM_META_RO_EN (0X00000004U)
+/* FAULT
+Indicates a fault has occured
+*/
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_FAULT_SHIFT (0U)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_FAULT_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_BIF_FAULT_BANK1_MMU_STATUS_FAULT_EN (0X00000001U)
+
+
+/*
+
+Provides details of the request that faulted on bank 1
+
+*/
+/*
+ Register RGX_CR_BIF_FAULT_BANK1_REQ_STATUS
+*/
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS (0x12C8U)
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_MASKFULL (IMG_UINT64_C(0x0007FFFFFFFFFFF0))
+/* RNW*/
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_RNW_SHIFT (50U)
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_RNW_CLRMSK (IMG_UINT64_C(0XFFFBFFFFFFFFFFFF))
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_RNW_EN (IMG_UINT64_C(0X0004000000000000))
+/* TAG_SB*/
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_TAG_SB_SHIFT (44U)
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_TAG_SB_CLRMSK (IMG_UINT64_C(0XFFFC0FFFFFFFFFFF))
+/* TAG_ID*/
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_TAG_ID_SHIFT (40U)
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_TAG_ID_CLRMSK (IMG_UINT64_C(0XFFFFF0FFFFFFFFFF))
+/* ADDRESS*/
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_ADDRESS_SHIFT (4U)
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_ADDRESS_CLRMSK (IMG_UINT64_C(0XFFFFFF000000000F))
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_ADDRESS_ALIGNSHIFT (4U)
+#define RGX_CR_BIF_FAULT_BANK1_REQ_STATUS_ADDRESS_ALIGNSIZE (16U)
+
+
+/*
+
+Specifies physical address to read from in the event of a faulting read request from BIF1
+
+*/
+/*
+ Register RGX_CR_BIF_FAULT_READ
+*/
+#define RGX_CR_BIF_FAULT_READ (0x13E0U)
+#define RGX_CR_BIF_FAULT_READ_MASKFULL (IMG_UINT64_C(0x000000FFFFFFFFF0))
+/* ADDRESS*/
+#define RGX_CR_BIF_FAULT_READ_ADDRESS_SHIFT (4U)
+#define RGX_CR_BIF_FAULT_READ_ADDRESS_CLRMSK (IMG_UINT64_C(0XFFFFFF000000000F))
+#define RGX_CR_BIF_FAULT_READ_ADDRESS_ALIGNSHIFT (4U)
+#define RGX_CR_BIF_FAULT_READ_ADDRESS_ALIGNSIZE (16U)
+
+
+/*
+
+Indicates a fault has occurred on bank 0 and provides details of fault
+
+*/
+/*
+ Register RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS
+*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS (0x1430U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_MASKFULL (IMG_UINT64_C(0x000000000000F775))
+/* CAT_BASE
+Catalogue base address number
+*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_SHIFT (12U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_CLRMSK (0XFFFF0FFFU)
+/* PAGE_SIZE
+Page size
+*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_PAGE_SIZE_SHIFT (8U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_PAGE_SIZE_CLRMSK (0XFFFFF8FFU)
+/* DATA_TYPE
+MMU data type that was invalid (on valid fault)
+*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_DATA_TYPE_SHIFT (5U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_DATA_TYPE_CLRMSK (0XFFFFFF9FU)
+/* FAULT_RO
+Indicates read-only fault('1') or valid fault('0')
+*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_FAULT_RO_SHIFT (4U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_FAULT_RO_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_FAULT_RO_EN (0X00000010U)
+/* FAULT_PM_META_RO
+Indicates pm/meta protected region fault
+*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_FAULT_PM_META_RO_SHIFT (2U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_FAULT_PM_META_RO_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_FAULT_PM_META_RO_EN (0X00000004U)
+/* FAULT
+Indicates a fault has occured
+*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_FAULT_SHIFT (0U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_FAULT_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS_FAULT_EN (0X00000001U)
+
+
+/*
+
+Provides details of the request that faulted on bank 0
+
+*/
+/*
+ Register RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS
+*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS (0x1438U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_MASKFULL (IMG_UINT64_C(0x0007FFFFFFFFFFF0))
+/* RNW*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_RNW_SHIFT (50U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_RNW_CLRMSK (IMG_UINT64_C(0XFFFBFFFFFFFFFFFF))
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_RNW_EN (IMG_UINT64_C(0X0004000000000000))
+/* TAG_SB*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_TAG_SB_SHIFT (44U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_TAG_SB_CLRMSK (IMG_UINT64_C(0XFFFC0FFFFFFFFFFF))
+/* TAG_ID*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_TAG_ID_SHIFT (40U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_TAG_ID_CLRMSK (IMG_UINT64_C(0XFFFFF0FFFFFFFFFF))
+/* ADDRESS*/
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_SHIFT (4U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_CLRMSK (IMG_UINT64_C(0XFFFFFF000000000F))
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_ALIGNSHIFT (4U)
+#define RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_ALIGNSIZE (16U)
+
+
+/*
+
+ SLC control registers
+
+*/
+/*
+ Register RGX_CR_SLC_CTRL_MISC
+*/
+#define RGX_CR_SLC_CTRL_MISC (0x3800U)
+#define RGX_CR_SLC_CTRL_MISC_MASKFULL (IMG_UINT64_C(0xFFFFFFFF00FF0105))
+/* SCRAMBLE_BITS
+ Pattern of bits used to determine the Cache Bank in Address Decode mode 0x21. The actual Cache Bank to use is determined by indexing into the 32 Scramble Bits using the 5 LSB's of the Hash result and then XORing this with Bit 6 of the incoming address to give a single bit result
+*/
+#define RGX_CR_SLC_CTRL_MISC_SCRAMBLE_BITS_SHIFT (32U)
+#define RGX_CR_SLC_CTRL_MISC_SCRAMBLE_BITS_CLRMSK (IMG_UINT64_C(0X00000000FFFFFFFF))
+/* ADDR_DECODE_MODE default: INTERLEAVED_64_BYTE (0x00000000)
+(null)
+*/
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_SHIFT (16U)
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFF00FFFF))
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_INTERLEAVED_64_BYTE (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_INTERLEAVED_128_BYTE (IMG_UINT64_C(0x0000000000010000))
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_SIMPLE_HASH1 (IMG_UINT64_C(0x0000000000100000))
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_SIMPLE_HASH2 (IMG_UINT64_C(0x0000000000110000))
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1 (IMG_UINT64_C(0x0000000000200000))
+#define RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH2_SCRAMBLE (IMG_UINT64_C(0x0000000000210000))
+/* PAUSE
+ Pause the SLC
+*/
+#define RGX_CR_SLC_CTRL_MISC_PAUSE_SHIFT (8U)
+#define RGX_CR_SLC_CTRL_MISC_PAUSE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
+#define RGX_CR_SLC_CTRL_MISC_PAUSE_EN (IMG_UINT64_C(0X0000000000000100))
+/* ENABLE_LINE_USE_LIMIT
+ Enable the use of cache line limits
+*/
+#define RGX_CR_SLC_CTRL_MISC_ENABLE_LINE_USE_LIMIT_SHIFT (2U)
+#define RGX_CR_SLC_CTRL_MISC_ENABLE_LINE_USE_LIMIT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
+#define RGX_CR_SLC_CTRL_MISC_ENABLE_LINE_USE_LIMIT_EN (IMG_UINT64_C(0X0000000000000004))
+/* BYPASS_BURST_COMBINER default: 0x00000001
+ Disable the burst combiner on the external memory interface
+*/
+#define RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_SHIFT (0U)
+#define RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_EN (IMG_UINT64_C(0X0000000000000001))
+
+
+/*
+
+ SLC Flush & Invalidate control.
+ Note that per Data Master operations will flush any cache lines that have been made dirty by any writes from the specified Data Master. Combined Invalidate operation then only invalidates entries that have been referenced solely by the specified Data Master, any cache lines referenced by multiple Data Masters will not be affected by a per Data Master invalidate operation and will remain valid.
+
+*/
+/*
+ Register RGX_CR_SLC_CTRL_FLUSH_INVAL
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL (0x3818U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_MASKFULL (IMG_UINT64_C(0x00000000800007FF))
+/* LAZY
+ Advanced mode of operation whereby other requestors are not blocked whilst the Flush Invalidate is in progress
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_LAZY_SHIFT (31U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_LAZY_CLRMSK (0X7FFFFFFFU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_LAZY_EN (0X80000000U)
+#if defined(RGX_FEATURE_RAY_TRACING)
+/* DM_RAY_VERTEX
+ When set, flush all SLC entries made dirty by the ray tracing VERTEX_RAY data master, then invalidate all SLC entries referenced solely by the ray tracing VERTEX_RAY
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_VERTEX_SHIFT (10U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_VERTEX_CLRMSK (0XFFFFFBFFU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_VERTEX_EN (0X00000400U)
+/* DM_RAY
+ When set, flush all SLC entries made dirty by the ray tracing RAY data master, then invalidate all SLC entries referenced solely by the ray tracing RAY
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_SHIFT (9U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_CLRMSK (0XFFFFFDFFU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_RAY_EN (0X00000200U)
+#endif /* RGX_FEATURE_RAY_TRACING */
+
+/* DM_FRC
+ When set, flush all SLC entries made dirty by the FRC Video Core, then invalidate all SLC entries referenced solely by the FRC Video Core (Optional feature)
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_FRC_SHIFT (8U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_FRC_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_FRC_EN (0X00000100U)
+/* DM_VXE
+ When set, flush all SLC entries made dirty by the VXE Video Core, then invalidate all SLC entries referenced solely by the VXE Video Core (Optional feature)
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_VXE_SHIFT (7U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_VXE_CLRMSK (0XFFFFFF7FU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_VXE_EN (0X00000080U)
+/* DM_VXD
+ When set, flush all SLC entries made dirty by the VXD Video Core, then invalidate all SLC entries referenced solely by the VXD Video Core (Optional feature)
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_VXD_SHIFT (6U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_VXD_CLRMSK (0XFFFFFFBFU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_VXD_EN (0X00000040U)
+/* DM_HOST_META
+ When set, flush all SLC entries made dirty by the HOST or META, then invalidate all SLC entries referenced solely by the HOST or META
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_HOST_META_SHIFT (5U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_HOST_META_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_HOST_META_EN (0X00000020U)
+/* DM_MMU
+ When set, flush all SLC entries made dirty by the MMU, then invalidate all SLC entries referenced solely by the MMU
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_MMU_SHIFT (4U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_MMU_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_MMU_EN (0X00000010U)
+/* DM_COMPUTE
+ When set, flush all SLC entries made dirty by the COMPUTE data master, then invalidate all SLC entries referenced solely by the COMPUTE data master
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_COMPUTE_SHIFT (3U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_COMPUTE_CLRMSK (0XFFFFFFF7U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_COMPUTE_EN (0X00000008U)
+/* DM_PIXEL
+ When set, flush all SLC entries made dirty by the PIXEL data master, then invalidate all SLC entries referenced solely by the PIXEL data master
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_PIXEL_SHIFT (2U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_PIXEL_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_PIXEL_EN (0X00000004U)
+/* DM_TA
+ When set, flush all SLC entries made dirty by the TA group which includes VERTEX, TESSELLATOR & STREAM_OUT data masters, then invalidate all SLC entries referenced solely by the TA group which includes VERTEX, TESSELLATOR & STREAM_OUT data masters
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_TA_SHIFT (1U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_TA_CLRMSK (0XFFFFFFFDU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_DM_TA_EN (0X00000002U)
+/* ALL
+ When set, flush all SLC entries, then invalidate all SLC entries
+*/
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_ALL_SHIFT (0U)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_ALL_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_SLC_CTRL_FLUSH_INVAL_ALL_EN (0X00000001U)
+
+
+/*
+
+ Current status of Flush / Invalidate operations within the SLC
+
+*/
+/*
+ Register RGX_CR_SLC_STATUS0
+*/
+#define RGX_CR_SLC_STATUS0 (0x3820U)
+#define RGX_CR_SLC_STATUS0_MASKFULL (IMG_UINT64_C(0x0000000000000007))
+/* FLUSH_INVAL_PENDING
+1 indicates there is a pending request to perform a combined Flush Invalidate on the SLC
+*/
+#define RGX_CR_SLC_STATUS0_FLUSH_INVAL_PENDING_SHIFT (2U)
+#define RGX_CR_SLC_STATUS0_FLUSH_INVAL_PENDING_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_SLC_STATUS0_FLUSH_INVAL_PENDING_EN (0X00000004U)
+/* INVAL_PENDING
+1 indicates there is a pending request to Invalidate the SLC
+*/
+#define RGX_CR_SLC_STATUS0_INVAL_PENDING_SHIFT (1U)
+#define RGX_CR_SLC_STATUS0_INVAL_PENDING_CLRMSK (0XFFFFFFFDU)
+#define RGX_CR_SLC_STATUS0_INVAL_PENDING_EN (0X00000002U)
+/* FLUSH_PENDING
+1 indicates there is a pending request to Flush the SLC
+*/
+#define RGX_CR_SLC_STATUS0_FLUSH_PENDING_SHIFT (0U)
+#define RGX_CR_SLC_STATUS0_FLUSH_PENDING_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_SLC_STATUS0_FLUSH_PENDING_EN (0X00000001U)
+
+
+/*
+
+ SLC Bypass control
+
+*/
+/*
+ Register RGX_CR_SLC_CTRL_BYPASS
+*/
+#define RGX_CR_SLC_CTRL_BYPASS (0x3828U)
+#define RGX_CR_SLC_CTRL_BYPASS_MASKFULL (IMG_UINT64_C(0x000000000FFFFFFF))
+#if defined(RGX_FEATURE_RAY_TRACING)
+/* DM_RAY_VERTEX
+ Bypass SLC for ray tracing VERTEX_RAY (CPF) requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_VERTEX_SHIFT (27U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_VERTEX_CLRMSK (0XF7FFFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_VERTEX_EN (0X08000000U)
+/* DM_RAY
+ Bypass SLC for ray tracing RAY requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_SHIFT (26U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_CLRMSK (0XFBFFFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_RAY_EN (0X04000000U)
+#endif /* RGX_FEATURE_RAY_TRACING */
+
+/* REQ_IPF_CPF
+ Bypass SLC for IPF (CPF) requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_SHIFT (25U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_CLRMSK (0XFDFFFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_EN (0X02000000U)
+/* REQ_TPU
+ Bypass SLC for TPU requests coming from the MCU requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TPU_SHIFT (24U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TPU_CLRMSK (0XFEFFFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TPU_EN (0X01000000U)
+/* REQ_FBDC
+ Bypass SLC for the FBDC requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_FBDC_SHIFT (23U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_FBDC_CLRMSK (0XFF7FFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_FBDC_EN (0X00800000U)
+/* REQ_TLA
+ Bypass SLC for the TLA requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TLA_SHIFT (22U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TLA_CLRMSK (0XFFBFFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TLA_EN (0X00400000U)
+/* BYP_CC_N
+ Bypass SLC when Cache Coherency bit is not set
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_BYP_CC_N_SHIFT (21U)
+#define RGX_CR_SLC_CTRL_BYPASS_BYP_CC_N_CLRMSK (0XFFDFFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_BYP_CC_N_EN (0X00200000U)
+/* BYP_CC
+ Bypass SLC when Cache Coherency bit is set
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_BYP_CC_SHIFT (20U)
+#define RGX_CR_SLC_CTRL_BYPASS_BYP_CC_CLRMSK (0XFFEFFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_BYP_CC_EN (0X00100000U)
+/* REQ_MCU
+ Bypass SLC for the MCU requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MCU_SHIFT (19U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MCU_CLRMSK (0XFFF7FFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MCU_EN (0X00080000U)
+/* REQ_PDS
+ Bypass SLC for the PDS requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_PDS_SHIFT (18U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_PDS_CLRMSK (0XFFFBFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_PDS_EN (0X00040000U)
+/* REQ_TPF
+ Bypass SLC for the TPF requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TPF_SHIFT (17U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TPF_CLRMSK (0XFFFDFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TPF_EN (0X00020000U)
+/* REQ_TA_TPC
+ Bypass SLC for the TA (Tail Pointer Cache data) requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TA_TPC_SHIFT (16U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TA_TPC_CLRMSK (0XFFFEFFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_TA_TPC_EN (0X00010000U)
+/* REQ_IPF_OBJ
+ Bypass SLC for the IPF (Object data) requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_OBJ_SHIFT (15U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_OBJ_CLRMSK (0XFFFF7FFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_OBJ_EN (0X00008000U)
+/* REQ_USC
+ Bypass SLC for the USC requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_USC_SHIFT (14U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_USC_CLRMSK (0XFFFFBFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_USC_EN (0X00004000U)
+/* REQ_META
+ Bypass SLC for the META requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_META_SHIFT (13U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_META_CLRMSK (0XFFFFDFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_META_EN (0X00002000U)
+/* REQ_HOST
+ Bypass SLC for the Host requestor
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_HOST_SHIFT (12U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_HOST_CLRMSK (0XFFFFEFFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_HOST_EN (0X00001000U)
+/* REQ_MMU_PT
+ Bypass SLC for the MMU requestor (Page Table data)
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MMU_PT_SHIFT (11U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MMU_PT_CLRMSK (0XFFFFF7FFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MMU_PT_EN (0X00000800U)
+/* REQ_MMU_PD
+ Bypass SLC for the MMU requestor (Page Directory data)
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MMU_PD_SHIFT (10U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MMU_PD_CLRMSK (0XFFFFFBFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MMU_PD_EN (0X00000400U)
+/* REQ_MMU_PC
+ Bypass SLC for the MMU requestor (Page Catalogue data)
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MMU_PC_SHIFT (9U)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MMU_PC_CLRMSK (0XFFFFFDFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_REQ_MMU_PC_EN (0X00000200U)
+/* DM_FRC
+ Bypass SLC for the FRC Video Core (Optional feature)
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_FRC_SHIFT (8U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_FRC_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_FRC_EN (0X00000100U)
+/* DM_VXE
+ Bypass SLC for the VXE Video Core (Optional feature)
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_VXE_SHIFT (7U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_VXE_CLRMSK (0XFFFFFF7FU)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_VXE_EN (0X00000080U)
+/* DM_VXD
+ Bypass SLC for the VXD Video Core (Optional feature)
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_VXD_SHIFT (6U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_VXD_CLRMSK (0XFFFFFFBFU)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_VXD_EN (0X00000040U)
+/* DM_HOST_META
+ Bypass SLC the HOST/META data master
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_HOST_META_SHIFT (5U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_HOST_META_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_HOST_META_EN (0X00000020U)
+/* DM_MMU
+ Bypass SLC the MMU data master
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_MMU_SHIFT (4U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_MMU_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_MMU_EN (0X00000010U)
+/* DM_COMPUTE
+ Bypass SLC the COMPUTE data master
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_COMPUTE_SHIFT (3U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_COMPUTE_CLRMSK (0XFFFFFFF7U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_COMPUTE_EN (0X00000008U)
+/* DM_PIXEL
+ Bypass SLC for the PIXEL data master
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_PIXEL_SHIFT (2U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_PIXEL_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_PIXEL_EN (0X00000004U)
+/* DM_TA
+ Bypass SLC for the TA group which includes VERTEX, TESSELLATOR & STREAM_OUT data masters
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_DM_TA_SHIFT (1U)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_TA_CLRMSK (0XFFFFFFFDU)
+#define RGX_CR_SLC_CTRL_BYPASS_DM_TA_EN (0X00000002U)
+/* ALL
+ Bypass SLC for all requesters
+*/
+#define RGX_CR_SLC_CTRL_BYPASS_ALL_SHIFT (0U)
+#define RGX_CR_SLC_CTRL_BYPASS_ALL_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_SLC_CTRL_BYPASS_ALL_EN (0X00000001U)
+
+
+/*
+
+ AXI ACE-LITE configuration registers
+
+*/
+/*
+ Register RGX_CR_AXI_ACE_LITE_CONFIGURATION
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION (0x38C0U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_MASKFULL (IMG_UINT64_C(0x0000001FFFFFFFFF))
+/* DISABLE_COHERENT_WRITELINEUNIQUE
+SET to 1 to disable coherent write line uniques
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITELINEUNIQUE_SHIFT (36U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITELINEUNIQUE_CLRMSK (IMG_UINT64_C(0XFFFFFFEFFFFFFFFF))
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITELINEUNIQUE_EN (IMG_UINT64_C(0X0000001000000000))
+/* DISABLE_COHERENT_WRITE
+SET to 1 to disable coherent writes
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITE_SHIFT (35U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITE_CLRMSK (IMG_UINT64_C(0XFFFFFFF7FFFFFFFF))
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITE_EN (IMG_UINT64_C(0X0000000800000000))
+/* DISABLE_COHERENT_READ
+SET to 1 to disable coherent reads
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_READ_SHIFT (34U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_READ_CLRMSK (IMG_UINT64_C(0XFFFFFFFBFFFFFFFF))
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_READ_EN (IMG_UINT64_C(0X0000000400000000))
+/* ARCACHE_CACHE_MAINTENANCE default: 0x00000002
+Read cache policy for cache maintenance transactions - bit[1] should be set to 1
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_CACHE_MAINTENANCE_SHIFT (30U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_CACHE_MAINTENANCE_CLRMSK (IMG_UINT64_C(0XFFFFFFFC3FFFFFFF))
+/* ARCACHE_COHERENT default: 0x00000002
+Read cache policy for coherent transactions - bit[1] should be set to 1
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_COHERENT_SHIFT (26U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_COHERENT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFC3FFFFFF))
+/* AWCACHE_COHERENT default: 0x00000002
+Write cache policy for coherent transactions - bit[1] should be set to 1
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWCACHE_COHERENT_SHIFT (22U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWCACHE_COHERENT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFC3FFFFF))
+/* ARDOMAIN_BARRIER
+Read shareability domain for barrier transactions
+ 00 = Non-Shareable
+ 01 = Inner Shareable
+ 10 = Outer Shareable
+ 11 = System
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_BARRIER_SHIFT (20U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_BARRIER_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFCFFFFF))
+/* AWDOMAIN_BARRIER
+Write shareability domain for barrier transactions
+ 00 = Non-Shareable
+ 01 = Inner Shareable
+ 10 = Outer Shareable
+ 11 = System
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_BARRIER_SHIFT (18U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_BARRIER_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFF3FFFF))
+/* ARDOMAIN_CACHE_MAINTENANCE
+Read shareability domain for cache maintenance transactions
+ 00 = Non-Shareable
+ 01 = Inner Shareable
+ 10 = Outer Shareable
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_CACHE_MAINTENANCE_SHIFT (16U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_CACHE_MAINTENANCE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFCFFFF))
+/* AWDOMAIN_COHERENT default: 0x00000001
+Write shareability domain for coherant transactions
+ 01 = Inner Shareable
+ 10 = Outer Shareable
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_COHERENT_SHIFT (14U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_COHERENT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFF3FFF))
+/* ARDOMAIN_COHERENT default: 0x00000001
+Read shareability domain for coherant transactions
+ 01 = Inner Shareable
+ 10 = Outer Shareable
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_COHERENT_SHIFT (12U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_COHERENT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFCFFF))
+/* ARDOMAIN_NON_SNOOPING
+Read shareability domain for non-snooping transactions
+ 00 = Non-Shareable
+ 11 = System
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_NON_SNOOPING_SHIFT (10U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_NON_SNOOPING_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF3FF))
+/* AWDOMAIN_NON_SNOOPING
+Write shareability domain for non-snooping transactions
+ 00 = Non-Shareable
+ 11 = System
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_NON_SNOOPING_SHIFT (8U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_NON_SNOOPING_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
+/* ARCACHE_NON_SNOOPING
+Read cache policy for non-snooping transactions
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_NON_SNOOPING_SHIFT (4U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_NON_SNOOPING_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFF0F))
+/* AWCACHE_NON_SNOOPING
+Write cache policy for non-snooping transactions
+*/
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWCACHE_NON_SNOOPING_SHIFT (0U)
+#define RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWCACHE_NON_SNOOPING_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF0))
+
+
+/*
+
+ SLC control registers
+
+*/
+/*
+ Register RGX_CR_SLC_CTRL_MISC2
+*/
+#define RGX_CR_SLC_CTRL_MISC2 (0x3930U)
+#define RGX_CR_SLC_CTRL_MISC2_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* SCRAMBLE_BITS
+ Pattern of bits used to determine the MSB of the Cache Bank in 4 Bank configurations in Address Decode mode 0x21. The actual Cache Bank to use is determined by indexing into the 32 Scramble Bits using the 5 LSB's of the Hash result and then XORing this with Bit 6 of the incoming address to give a single bit result
+*/
+#define RGX_CR_SLC_CTRL_MISC2_SCRAMBLE_BITS_SHIFT (0U)
+#define RGX_CR_SLC_CTRL_MISC2_SCRAMBLE_BITS_CLRMSK (00000000U)
+
+
+/*
+ Register RGX_CR_SLC_CROSSBAR_LOAD_BALANCE
+*/
+#define RGX_CR_SLC_CROSSBAR_LOAD_BALANCE (0x3938U)
+#define RGX_CR_SLC_CROSSBAR_LOAD_BALANCE_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* BYPASS
+ control register bit to bypass load balancing in SLC crossbar. In this case, the requests from
+ img-memif0 will go directly to ocp-memif0 and so on
+*/
+#define RGX_CR_SLC_CROSSBAR_LOAD_BALANCE_BYPASS_SHIFT (0U)
+#define RGX_CR_SLC_CROSSBAR_LOAD_BALANCE_BYPASS_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_SLC_CROSSBAR_LOAD_BALANCE_BYPASS_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_PERF_TA_PHASE
+*/
+#define RGX_CR_PERF_TA_PHASE (0x6008U)
+#define RGX_CR_PERF_TA_PHASE_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* COUNT
+The number of TA phases completed
+*/
+#define RGX_CR_PERF_TA_PHASE_COUNT_SHIFT (0U)
+#define RGX_CR_PERF_TA_PHASE_COUNT_CLRMSK (00000000U)
+
+
+/*
+ Register RGX_CR_PERF_3D_PHASE
+*/
+#define RGX_CR_PERF_3D_PHASE (0x6010U)
+#define RGX_CR_PERF_3D_PHASE_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* COUNT
+The number of 3D phases completed
+*/
+#define RGX_CR_PERF_3D_PHASE_COUNT_SHIFT (0U)
+#define RGX_CR_PERF_3D_PHASE_COUNT_CLRMSK (00000000U)
+
+
+/*
+ Register RGX_CR_PERF_COMPUTE_PHASE
+*/
+#define RGX_CR_PERF_COMPUTE_PHASE (0x6018U)
+#define RGX_CR_PERF_COMPUTE_PHASE_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* COUNT
+The number of Compute phases completed
+*/
+#define RGX_CR_PERF_COMPUTE_PHASE_COUNT_SHIFT (0U)
+#define RGX_CR_PERF_COMPUTE_PHASE_COUNT_CLRMSK (00000000U)
+
+
+/*
+ Register RGX_CR_PERF_TA_CYCLE
+*/
+#define RGX_CR_PERF_TA_CYCLE (0x6020U)
+#define RGX_CR_PERF_TA_CYCLE_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* COUNT
+The number of cycles spent in TA phases
+*/
+#define RGX_CR_PERF_TA_CYCLE_COUNT_SHIFT (0U)
+#define RGX_CR_PERF_TA_CYCLE_COUNT_CLRMSK (00000000U)
+
+
+/*
+ Register RGX_CR_PERF_3D_CYCLE
+*/
+#define RGX_CR_PERF_3D_CYCLE (0x6028U)
+#define RGX_CR_PERF_3D_CYCLE_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* COUNT
+The number of cycles spent in 3D phases
+*/
+#define RGX_CR_PERF_3D_CYCLE_COUNT_SHIFT (0U)
+#define RGX_CR_PERF_3D_CYCLE_COUNT_CLRMSK (00000000U)
+
+
+/*
+ Register RGX_CR_PERF_COMPUTE_CYCLE
+*/
+#define RGX_CR_PERF_COMPUTE_CYCLE (0x6030U)
+#define RGX_CR_PERF_COMPUTE_CYCLE_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* COUNT
+The number of cycles spent in Compute phases
+*/
+#define RGX_CR_PERF_COMPUTE_CYCLE_COUNT_SHIFT (0U)
+#define RGX_CR_PERF_COMPUTE_CYCLE_COUNT_CLRMSK (00000000U)
+
+
+/*
+ Register RGX_CR_PERF_3D_SPINUP
+*/
+#define RGX_CR_PERF_3D_SPINUP (0x6220U)
+#define RGX_CR_PERF_3D_SPINUP_MASKFULL (IMG_UINT64_C(0x00000000FFFFFFFF))
+/* CYCLES
+The number of cycles it takes the 3D pipeline to spin-up
+*/
+#define RGX_CR_PERF_3D_SPINUP_CYCLES_SHIFT (0U)
+#define RGX_CR_PERF_3D_SPINUP_CYCLES_CLRMSK (00000000U)
+
+
+/*
+
+ This defines the core revision and bus widths of the core. See IPG spec for more details.
+
+*/
+/*
+ Register RGX_CR_OCP_REVINFO
+*/
+#define RGX_CR_OCP_REVINFO (0x9000U)
+#define RGX_CR_OCP_REVINFO_MASKFULL (IMG_UINT64_C(0x00000007FFFFFFFF))
+/* HWINFO_SYSBUS default: 0x00000001
+System data bus width, 0: 32 bits, 1: 64 bits, 2: 128 bits
+*/
+#define RGX_CR_OCP_REVINFO_HWINFO_SYSBUS_SHIFT (33U)
+#define RGX_CR_OCP_REVINFO_HWINFO_SYSBUS_CLRMSK (IMG_UINT64_C(0XFFFFFFF9FFFFFFFF))
+/* HWINFO_MEMBUS
+Memory data bus width, 0: 128 bis, 1: 256 bits
+*/
+#define RGX_CR_OCP_REVINFO_HWINFO_MEMBUS_SHIFT (32U)
+#define RGX_CR_OCP_REVINFO_HWINFO_MEMBUS_CLRMSK (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
+#define RGX_CR_OCP_REVINFO_HWINFO_MEMBUS_EN (IMG_UINT64_C(0X0000000100000000))
+/* REVISION default: 0x40000000
+Core revision
+*/
+#define RGX_CR_OCP_REVINFO_REVISION_SHIFT (0U)
+#define RGX_CR_OCP_REVINFO_REVISION_CLRMSK (IMG_UINT64_C(0XFFFFFFFF00000000))
+
+
+/*
+
+ This defines the OCP Idle mode and OCP Standby mode for various power domains. See OCP-IPGeneric spec for more details.
+
+*/
+/*
+ Register RGX_CR_OCP_SYSCONFIG
+*/
+#define RGX_CR_OCP_SYSCONFIG (0x9010U)
+#define RGX_CR_OCP_SYSCONFIG_MASKFULL (IMG_UINT64_C(0x0000000000000FFF))
+/* DUST2_STANDBY_MODE default: 0x00000002
+Standby Mode for Dust2, 0: Force-Standby, 1: No-Standby, 2: Smart-Standby
+*/
+#define RGX_CR_OCP_SYSCONFIG_DUST2_STANDBY_MODE_SHIFT (10U)
+#define RGX_CR_OCP_SYSCONFIG_DUST2_STANDBY_MODE_CLRMSK (0XFFFFF3FFU)
+/* DUST1_STANDBY_MODE default: 0x00000002
+Standby Mode for Dust1, 0: Force-Standby, 1: No-Standby, 2: Smart-Standby
+*/
+#define RGX_CR_OCP_SYSCONFIG_DUST1_STANDBY_MODE_SHIFT (8U)
+#define RGX_CR_OCP_SYSCONFIG_DUST1_STANDBY_MODE_CLRMSK (0XFFFFFCFFU)
+/* DUST0_STANDBY_MODE default: 0x00000002
+Standby Mode for Dust0, 0: Force-Standby, 1: No-Standby, 2: Smart-Standby
+*/
+#define RGX_CR_OCP_SYSCONFIG_DUST0_STANDBY_MODE_SHIFT (6U)
+#define RGX_CR_OCP_SYSCONFIG_DUST0_STANDBY_MODE_CLRMSK (0XFFFFFF3FU)
+/* RASCAL_STANDBYMODE default: 0x00000002
+Standby Mode for Rascal, 0: Force-Standby, 1: No-Standby, 2: Smart-Standby
+*/
+#define RGX_CR_OCP_SYSCONFIG_RASCAL_STANDBYMODE_SHIFT (4U)
+#define RGX_CR_OCP_SYSCONFIG_RASCAL_STANDBYMODE_CLRMSK (0XFFFFFFCFU)
+/* STANDBY_MODE default: 0x00000002
+Standby Mode for SLC and Sidekick OCP Master, 0: Force-Standby, 1: No-Standby, 2: Smart-Standby
+*/
+#define RGX_CR_OCP_SYSCONFIG_STANDBY_MODE_SHIFT (2U)
+#define RGX_CR_OCP_SYSCONFIG_STANDBY_MODE_CLRMSK (0XFFFFFFF3U)
+/* IDLE_MODE default: 0x00000002
+Idle Mode for OCP slaves, 0: Force-Idle, 1: No-Idle, 2: Smart-Idle
+*/
+#define RGX_CR_OCP_SYSCONFIG_IDLE_MODE_SHIFT (0U)
+#define RGX_CR_OCP_SYSCONFIG_IDLE_MODE_CLRMSK (0XFFFFFFFCU)
+
+
+/*
+ Register RGX_CR_OCP_IRQSTATUS_RAW_0
+*/
+#define RGX_CR_OCP_IRQSTATUS_RAW_0 (0x9020U)
+#define RGX_CR_OCP_IRQSTATUS_RAW_0_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* Init_MInterrupt_raw
+Interrupt raw event for OCP Master Interfaces, W 0 : No action, W 1 - Set event, R 0 - No event pending, R 1 - Event pending
+*/
+#define RGX_CR_OCP_IRQSTATUS_RAW_0_INIT_MINTERRUPT_RAW_SHIFT (0U)
+#define RGX_CR_OCP_IRQSTATUS_RAW_0_INIT_MINTERRUPT_RAW_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQSTATUS_RAW_0_INIT_MINTERRUPT_RAW_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQSTATUS_RAW_1
+*/
+#define RGX_CR_OCP_IRQSTATUS_RAW_1 (0x9028U)
+#define RGX_CR_OCP_IRQSTATUS_RAW_1_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* Target_SInterrupt_raw
+Interrupt raw event for OCP Slave Interfaces, W 0 : No action, W 1 - Set event, R 0 - No event pending, R 1 - Event pending
+*/
+#define RGX_CR_OCP_IRQSTATUS_RAW_1_TARGET_SINTERRUPT_RAW_SHIFT (0U)
+#define RGX_CR_OCP_IRQSTATUS_RAW_1_TARGET_SINTERRUPT_RAW_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQSTATUS_RAW_1_TARGET_SINTERRUPT_RAW_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQSTATUS_RAW_2
+*/
+#define RGX_CR_OCP_IRQSTATUS_RAW_2 (0x9030U)
+#define RGX_CR_OCP_IRQSTATUS_RAW_2_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* rgx_irq_raw
+Interrupt raw event for core, W 0 : No action, W 1 - Set event, R 0 - No event pending, R 1 - Event pending
+*/
+#define RGX_CR_OCP_IRQSTATUS_RAW_2_RGX_IRQ_RAW_SHIFT (0U)
+#define RGX_CR_OCP_IRQSTATUS_RAW_2_RGX_IRQ_RAW_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQSTATUS_RAW_2_RGX_IRQ_RAW_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQSTATUS_0
+*/
+#define RGX_CR_OCP_IRQSTATUS_0 (0x9038U)
+#define RGX_CR_OCP_IRQSTATUS_0_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* Init_MInterrupt_status
+Interrupt status event for OCP Master Interfaces, W 0 : No action, W 1 - Clear event, R 0 - No event pending, R 1 - Event pending and interrupt enabled
+*/
+#define RGX_CR_OCP_IRQSTATUS_0_INIT_MINTERRUPT_STATUS_SHIFT (0U)
+#define RGX_CR_OCP_IRQSTATUS_0_INIT_MINTERRUPT_STATUS_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQSTATUS_0_INIT_MINTERRUPT_STATUS_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQSTATUS_1
+*/
+#define RGX_CR_OCP_IRQSTATUS_1 (0x9040U)
+#define RGX_CR_OCP_IRQSTATUS_1_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* target_SInterrupt_status
+Interrupt status event for OCP Slave Interfaces, W 0 : No action, W 1 - Clear event, R 0 - No event pending, R 1 - Event pending and interrupt enabled
+*/
+#define RGX_CR_OCP_IRQSTATUS_1_TARGET_SINTERRUPT_STATUS_SHIFT (0U)
+#define RGX_CR_OCP_IRQSTATUS_1_TARGET_SINTERRUPT_STATUS_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQSTATUS_1_TARGET_SINTERRUPT_STATUS_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQSTATUS_2
+*/
+#define RGX_CR_OCP_IRQSTATUS_2 (0x9048U)
+#define RGX_CR_OCP_IRQSTATUS_2_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* rgx_irq_status
+Interrupt status event for core, W 0 : No action, W 1 - Clear event, R 0 - No event pending, R 1 - Event pending and interrupt enabled
+*/
+#define RGX_CR_OCP_IRQSTATUS_2_RGX_IRQ_STATUS_SHIFT (0U)
+#define RGX_CR_OCP_IRQSTATUS_2_RGX_IRQ_STATUS_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQSTATUS_2_RGX_IRQ_STATUS_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQENABLE_SET_0
+*/
+#define RGX_CR_OCP_IRQENABLE_SET_0 (0x9050U)
+#define RGX_CR_OCP_IRQENABLE_SET_0_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* Init_MInterrupt_enable
+Interrupt enable for OCP Master Interfaces, W 0 : No action, W 1 - Enable Interrupt, R 0 - Interrupt is disabled, R 1 - Interrupt is enabled
+*/
+#define RGX_CR_OCP_IRQENABLE_SET_0_INIT_MINTERRUPT_ENABLE_SHIFT (0U)
+#define RGX_CR_OCP_IRQENABLE_SET_0_INIT_MINTERRUPT_ENABLE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQENABLE_SET_0_INIT_MINTERRUPT_ENABLE_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQENABLE_SET_1
+*/
+#define RGX_CR_OCP_IRQENABLE_SET_1 (0x9058U)
+#define RGX_CR_OCP_IRQENABLE_SET_1_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* Target_SInterrupt_enable
+Interrupt enable for OCP Slave Interfaces, W 0 : No action, W 1 - Enable Interrupt, R 0 - Interrupt is disabled, R 1 - Interrupt is enabled
+*/
+#define RGX_CR_OCP_IRQENABLE_SET_1_TARGET_SINTERRUPT_ENABLE_SHIFT (0U)
+#define RGX_CR_OCP_IRQENABLE_SET_1_TARGET_SINTERRUPT_ENABLE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQENABLE_SET_1_TARGET_SINTERRUPT_ENABLE_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQENABLE_SET_2
+*/
+#define RGX_CR_OCP_IRQENABLE_SET_2 (0x9060U)
+#define RGX_CR_OCP_IRQENABLE_SET_2_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* rgx_irq_enable
+Interrupt enable for core, W 0 : No action, W 1 - Enable Interrupt, R 0 - Interrupt is disabled, R 1 - Interrupt is enabled
+*/
+#define RGX_CR_OCP_IRQENABLE_SET_2_RGX_IRQ_ENABLE_SHIFT (0U)
+#define RGX_CR_OCP_IRQENABLE_SET_2_RGX_IRQ_ENABLE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQENABLE_SET_2_RGX_IRQ_ENABLE_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQENABLE_CLR_0
+*/
+#define RGX_CR_OCP_IRQENABLE_CLR_0 (0x9068U)
+#define RGX_CR_OCP_IRQENABLE_CLR_0_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* Init_MInterrupt_disable
+Interrupt disable for OCP Master Interfaces, W 0 : No action, W 1 - Disable Interrupt, R 0 - Interrupt is disabled, R 1 - Interrupt is enabled
+*/
+#define RGX_CR_OCP_IRQENABLE_CLR_0_INIT_MINTERRUPT_DISABLE_SHIFT (0U)
+#define RGX_CR_OCP_IRQENABLE_CLR_0_INIT_MINTERRUPT_DISABLE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQENABLE_CLR_0_INIT_MINTERRUPT_DISABLE_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQENABLE_CLR_1
+*/
+#define RGX_CR_OCP_IRQENABLE_CLR_1 (0x9070U)
+#define RGX_CR_OCP_IRQENABLE_CLR_1_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* Target_SInterrupt_disable
+Interrupt disable for OCP Slave Interfaces, W 0 : No action, W 1 - Disable Interrupt, R 0 - Interrupt is disabled, R 1 - Interrupt is enabled
+*/
+#define RGX_CR_OCP_IRQENABLE_CLR_1_TARGET_SINTERRUPT_DISABLE_SHIFT (0U)
+#define RGX_CR_OCP_IRQENABLE_CLR_1_TARGET_SINTERRUPT_DISABLE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQENABLE_CLR_1_TARGET_SINTERRUPT_DISABLE_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_OCP_IRQENABLE_CLR_2
+*/
+#define RGX_CR_OCP_IRQENABLE_CLR_2 (0x9078U)
+#define RGX_CR_OCP_IRQENABLE_CLR_2_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* rgx_irq_disable
+Interrupt disable for core, W 0 : No action, W 1 - Disable Interrupt, R 0 - Interrupt is disabled, R 1 - Interrupt is enabled
+*/
+#define RGX_CR_OCP_IRQENABLE_CLR_2_RGX_IRQ_DISABLE_SHIFT (0U)
+#define RGX_CR_OCP_IRQENABLE_CLR_2_RGX_IRQ_DISABLE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_IRQENABLE_CLR_2_RGX_IRQ_DISABLE_EN (0X00000001U)
+
+
+/*
+
+ This defines the interrupt disable for Core.
+
+*/
+/*
+ Register RGX_CR_OCP_IRQ_EVENT
+*/
+#define RGX_CR_OCP_IRQ_EVENT (0x9080U)
+#define RGX_CR_OCP_IRQ_EVENT_MASKFULL (IMG_UINT64_C(0x00000000000FFFFF))
+/* TARGETH_RCVD_UNEXPECTED_RDATA
+interrupt events from OCP host if - received unexpeted rdata from IMG if
+*/
+#define RGX_CR_OCP_IRQ_EVENT_TARGETH_RCVD_UNEXPECTED_RDATA_SHIFT (19U)
+#define RGX_CR_OCP_IRQ_EVENT_TARGETH_RCVD_UNEXPECTED_RDATA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFF7FFFF))
+#define RGX_CR_OCP_IRQ_EVENT_TARGETH_RCVD_UNEXPECTED_RDATA_EN (IMG_UINT64_C(0X0000000000080000))
+/* TARGETH_RCVD_UNSUPPORTED_MCMD
+interrupt events from OCP host if - received unsupported MCmd
+*/
+#define RGX_CR_OCP_IRQ_EVENT_TARGETH_RCVD_UNSUPPORTED_MCMD_SHIFT (18U)
+#define RGX_CR_OCP_IRQ_EVENT_TARGETH_RCVD_UNSUPPORTED_MCMD_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFBFFFF))
+#define RGX_CR_OCP_IRQ_EVENT_TARGETH_RCVD_UNSUPPORTED_MCMD_EN (IMG_UINT64_C(0X0000000000040000))
+/* TARGETS_RCVD_UNEXPECTED_RDATA
+interrupt events from OCP system if - received unexpeted rdata from IMG if
+*/
+#define RGX_CR_OCP_IRQ_EVENT_TARGETS_RCVD_UNEXPECTED_RDATA_SHIFT (17U)
+#define RGX_CR_OCP_IRQ_EVENT_TARGETS_RCVD_UNEXPECTED_RDATA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFDFFFF))
+#define RGX_CR_OCP_IRQ_EVENT_TARGETS_RCVD_UNEXPECTED_RDATA_EN (IMG_UINT64_C(0X0000000000020000))
+/* TARGETS_RCVD_UNSUPPORTED_MCMD
+interrupt events from OCP system if - received unsupported MCmd
+*/
+#define RGX_CR_OCP_IRQ_EVENT_TARGETS_RCVD_UNSUPPORTED_MCMD_SHIFT (16U)
+#define RGX_CR_OCP_IRQ_EVENT_TARGETS_RCVD_UNSUPPORTED_MCMD_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFEFFFF))
+#define RGX_CR_OCP_IRQ_EVENT_TARGETS_RCVD_UNSUPPORTED_MCMD_EN (IMG_UINT64_C(0X0000000000010000))
+/* INIT3_IMG_PAGE_BOUNDARY_CROSS
+interrupt events from Init3 - burst request from IMG cross 4k page boundary
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_IMG_PAGE_BOUNDARY_CROSS_SHIFT (15U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_IMG_PAGE_BOUNDARY_CROSS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFF7FFF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_IMG_PAGE_BOUNDARY_CROSS_EN (IMG_UINT64_C(0X0000000000008000))
+/* INIT3_RCVD_RESP_ERR_FAIL
+interrupt events from Init3 - received RESP_ERR or RESP_FAIL from SoC
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_RCVD_RESP_ERR_FAIL_SHIFT (14U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_RCVD_RESP_ERR_FAIL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFBFFF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_RCVD_RESP_ERR_FAIL_EN (IMG_UINT64_C(0X0000000000004000))
+/* INIT3_RCVD_UNUSED_TAGID
+interrupt events from Init3 - received unused ocp tag id from SoC
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_RCVD_UNUSED_TAGID_SHIFT (13U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_RCVD_UNUSED_TAGID_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFDFFF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_RCVD_UNUSED_TAGID_EN (IMG_UINT64_C(0X0000000000002000))
+/* INIT3_RDATA_FIFO_OVERFILL
+interrupt events from Init3 - return data fifo overfill
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_RDATA_FIFO_OVERFILL_SHIFT (12U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_RDATA_FIFO_OVERFILL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFEFFF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT3_RDATA_FIFO_OVERFILL_EN (IMG_UINT64_C(0X0000000000001000))
+/* INIT2_IMG_PAGE_BOUNDARY_CROSS
+interrupt events from Init2 - burst request from IMG cross 4k page boundary
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_IMG_PAGE_BOUNDARY_CROSS_SHIFT (11U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_IMG_PAGE_BOUNDARY_CROSS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF7FF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_IMG_PAGE_BOUNDARY_CROSS_EN (IMG_UINT64_C(0X0000000000000800))
+/* INIT2_RCVD_RESP_ERR_FAIL
+interrupt events from Init2 - received RESP_ERR or RESP_FAIL from SoC
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_RCVD_RESP_ERR_FAIL_SHIFT (10U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_RCVD_RESP_ERR_FAIL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_RCVD_RESP_ERR_FAIL_EN (IMG_UINT64_C(0X0000000000000400))
+/* INIT2_RCVD_UNUSED_TAGID
+interrupt events from Init2 - received unused ocp tag id from SoC
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_RCVD_UNUSED_TAGID_SHIFT (9U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_RCVD_UNUSED_TAGID_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFDFF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_RCVD_UNUSED_TAGID_EN (IMG_UINT64_C(0X0000000000000200))
+/* INIT2_RDATA_FIFO_OVERFILL
+interrupt events from Init2 - return data fifo overfill
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_RDATA_FIFO_OVERFILL_SHIFT (8U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_RDATA_FIFO_OVERFILL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFEFF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT2_RDATA_FIFO_OVERFILL_EN (IMG_UINT64_C(0X0000000000000100))
+/* INIT1_IMG_PAGE_BOUNDARY_CROSS
+interrupt events from Init1 - burst request from IMG cross 4k page boundary
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_IMG_PAGE_BOUNDARY_CROSS_SHIFT (7U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_IMG_PAGE_BOUNDARY_CROSS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFF7F))
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_IMG_PAGE_BOUNDARY_CROSS_EN (IMG_UINT64_C(0X0000000000000080))
+/* INIT1_RCVD_RESP_ERR_FAIL
+interrupt events from Init1 - received RESP_ERR or RESP_FAIL from SoC
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_RCVD_RESP_ERR_FAIL_SHIFT (6U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_RCVD_RESP_ERR_FAIL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFBF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_RCVD_RESP_ERR_FAIL_EN (IMG_UINT64_C(0X0000000000000040))
+/* INIT1_RCVD_UNUSED_TAGID
+interrupt events from Init1 - received unused ocp tag id from SoC
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_RCVD_UNUSED_TAGID_SHIFT (5U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_RCVD_UNUSED_TAGID_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_RCVD_UNUSED_TAGID_EN (IMG_UINT64_C(0X0000000000000020))
+/* INIT1_RDATA_FIFO_OVERFILL
+interrupt events from Init1 - return data fifo overfill
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_RDATA_FIFO_OVERFILL_SHIFT (4U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_RDATA_FIFO_OVERFILL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
+#define RGX_CR_OCP_IRQ_EVENT_INIT1_RDATA_FIFO_OVERFILL_EN (IMG_UINT64_C(0X0000000000000010))
+/* INIT0_IMG_PAGE_BOUNDARY_CROSS
+interrupt events from Init0 - burst request from IMG cross 4k page boundary
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_IMG_PAGE_BOUNDARY_CROSS_SHIFT (3U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_IMG_PAGE_BOUNDARY_CROSS_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_IMG_PAGE_BOUNDARY_CROSS_EN (IMG_UINT64_C(0X0000000000000008))
+/* INIT0_RCVD_RESP_ERR_FAIL
+interrupt events from Init0 - received RESP_ERR or RESP_FAIL from SoC
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_RCVD_RESP_ERR_FAIL_SHIFT (2U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_RCVD_RESP_ERR_FAIL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_RCVD_RESP_ERR_FAIL_EN (IMG_UINT64_C(0X0000000000000004))
+/* INIT0_RCVD_UNUSED_TAGID
+interrupt events from Init0 - received unused ocp tag id from SoC
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_RCVD_UNUSED_TAGID_SHIFT (1U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_RCVD_UNUSED_TAGID_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_RCVD_UNUSED_TAGID_EN (IMG_UINT64_C(0X0000000000000002))
+/* INIT0_RDATA_FIFO_OVERFILL
+interrupt events from Init0 - return data fifo overfill
+*/
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_RDATA_FIFO_OVERFILL_SHIFT (0U)
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_RDATA_FIFO_OVERFILL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_OCP_IRQ_EVENT_INIT0_RDATA_FIFO_OVERFILL_EN (IMG_UINT64_C(0X0000000000000001))
+
+
+/*
+ Register RGX_CR_OCP_DEBUG_CONFIG
+*/
+#define RGX_CR_OCP_DEBUG_CONFIG (0x9088U)
+#define RGX_CR_OCP_DEBUG_CONFIG_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* REG
+bypass rgx_irq from OCP wrapper and do not use OCP specific irq enable/disable
+*/
+#define RGX_CR_OCP_DEBUG_CONFIG_REG_SHIFT (0U)
+#define RGX_CR_OCP_DEBUG_CONFIG_REG_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_OCP_DEBUG_CONFIG_REG_EN (0X00000001U)
+
+
+/*
+
+ This defines the debug status of the OCP internal registers
+
+*/
+/*
+ Register RGX_CR_OCP_DEBUG_STATUS
+*/
+#define RGX_CR_OCP_DEBUG_STATUS (0x9090U)
+#define RGX_CR_OCP_DEBUG_STATUS_MASKFULL (IMG_UINT64_C(0x001F1F77FFFFFFFF))
+/* TARGETH_SDISCACK default: 0x00000003
+debug status from OCP host interface - acknowledge to Idle protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_SDISCACK_SHIFT (51U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_SDISCACK_CLRMSK (IMG_UINT64_C(0XFFE7FFFFFFFFFFFF))
+/* TARGETH_SCONNECT
+debug status from OCP host interface - Target SConnect state
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_SCONNECT_SHIFT (50U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_SCONNECT_CLRMSK (IMG_UINT64_C(0XFFFBFFFFFFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_SCONNECT_EN (IMG_UINT64_C(0X0004000000000000))
+/* TARGETH_MCONNECT
+debug status from OCP host interface - taget MConnect state
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_MCONNECT_SHIFT (48U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_MCONNECT_CLRMSK (IMG_UINT64_C(0XFFFCFFFFFFFFFFFF))
+/* TARGETS_SDISCACK default: 0x00000003
+debug status from OCP system interface - acknowledge to Idle protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_SDISCACK_SHIFT (43U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_SDISCACK_CLRMSK (IMG_UINT64_C(0XFFFFE7FFFFFFFFFF))
+/* TARGETS_SCONNECT
+debug status from OCP system interface - Target SConnect state
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_SCONNECT_SHIFT (42U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_SCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFBFFFFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_SCONNECT_EN (IMG_UINT64_C(0X0000040000000000))
+/* TARGETS_MCONNECT
+debug status from OCP system interface - taget MConnect state
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_MCONNECT_SHIFT (40U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_MCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFCFFFFFFFFFF))
+/* TARGETH_BUSY
+debug status from OCP host interface - ocp slave interface is busy
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_BUSY_SHIFT (38U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_BUSY_CLRMSK (IMG_UINT64_C(0XFFFFFFBFFFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_BUSY_EN (IMG_UINT64_C(0X0000004000000000))
+/* TARGETH_CMD_FIFO_FULL
+debug status from OCP host interface - command fifo full
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_CMD_FIFO_FULL_SHIFT (37U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_CMD_FIFO_FULL_CLRMSK (IMG_UINT64_C(0XFFFFFFDFFFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_CMD_FIFO_FULL_EN (IMG_UINT64_C(0X0000002000000000))
+/* TARGETH_SRESP_ERROR
+debug status from OCP host interface - error response due to non-supporting command
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_SRESP_ERROR_SHIFT (36U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_SRESP_ERROR_CLRMSK (IMG_UINT64_C(0XFFFFFFEFFFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETH_SRESP_ERROR_EN (IMG_UINT64_C(0X0000001000000000))
+/* TARGETS_BUSY
+debug status from OCP system interface - ocp slave interface is busy
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_BUSY_SHIFT (34U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_BUSY_CLRMSK (IMG_UINT64_C(0XFFFFFFFBFFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_BUSY_EN (IMG_UINT64_C(0X0000000400000000))
+/* TARGETS_CMD_FIFO_FULL
+debug status from OCP system interface - command fifo full
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_CMD_FIFO_FULL_SHIFT (33U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_CMD_FIFO_FULL_CLRMSK (IMG_UINT64_C(0XFFFFFFFDFFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_CMD_FIFO_FULL_EN (IMG_UINT64_C(0X0000000200000000))
+/* TARGETS_SRESP_ERROR
+debug status from OCP system interface - error response due to non-supporting command
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_SRESP_ERROR_SHIFT (32U)
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_SRESP_ERROR_CLRMSK (IMG_UINT64_C(0XFFFFFFFEFFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_TARGETS_SRESP_ERROR_EN (IMG_UINT64_C(0X0000000100000000))
+/* INIT3_RESERVED
+debug status from init3 - reserved
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_RESERVED_SHIFT (31U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_RESERVED_CLRMSK (IMG_UINT64_C(0XFFFFFFFF7FFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_RESERVED_EN (IMG_UINT64_C(0X0000000080000000))
+/* INIT3_SWAIT
+debug status from init3 - defines whether to wait in M_WAIT state for MConnect
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_SWAIT_SHIFT (30U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_SWAIT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFBFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_SWAIT_EN (IMG_UINT64_C(0X0000000040000000))
+/* INIT3_MDISCREQ default: 0x00000001
+debug status from init3 - request to disconnect from standby protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_MDISCREQ_SHIFT (29U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_MDISCREQ_CLRMSK (IMG_UINT64_C(0XFFFFFFFFDFFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_MDISCREQ_EN (IMG_UINT64_C(0X0000000020000000))
+/* INIT3_MDISCACK default: 0x00000003
+debug status from init3 - ack to MDiscReq from standby protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_MDISCACK_SHIFT (27U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_MDISCACK_CLRMSK (IMG_UINT64_C(0XFFFFFFFFE7FFFFFF))
+/* INIT3_SCONNECT
+debug status from init3 - disconnect state from slave
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_SCONNECT_SHIFT (26U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_SCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFBFFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_SCONNECT_EN (IMG_UINT64_C(0X0000000004000000))
+/* INIT3_MCONNECT
+debug status from init3 - initiator mconnect state
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_MCONNECT_SHIFT (24U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT3_MCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFCFFFFFF))
+/* INIT2_RESERVED
+debug status from init2 - reserved
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_RESERVED_SHIFT (23U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_RESERVED_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFF7FFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_RESERVED_EN (IMG_UINT64_C(0X0000000000800000))
+/* INIT2_SWAIT
+debug status from init2 - defines whether to wait in M_WAIT state for MConnect
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_SWAIT_SHIFT (22U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_SWAIT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFBFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_SWAIT_EN (IMG_UINT64_C(0X0000000000400000))
+/* INIT2_MDISCREQ default: 0x00000001
+debug status from init2 - request to disconnect from standby protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_MDISCREQ_SHIFT (21U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_MDISCREQ_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFDFFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_MDISCREQ_EN (IMG_UINT64_C(0X0000000000200000))
+/* INIT2_MDISCACK default: 0x00000003
+debug status from init2 - ack to MDiscReq from standby protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_MDISCACK_SHIFT (19U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_MDISCACK_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFE7FFFF))
+/* INIT2_SCONNECT
+debug status from init2 - disconnect state from slave
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_SCONNECT_SHIFT (18U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_SCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFBFFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_SCONNECT_EN (IMG_UINT64_C(0X0000000000040000))
+/* INIT2_MCONNECT
+debug status from init2 - initiator mconnect state
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_MCONNECT_SHIFT (16U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT2_MCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFCFFFF))
+/* INIT1_RESERVED
+debug status from init1 - reserved
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_RESERVED_SHIFT (15U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_RESERVED_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFF7FFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_RESERVED_EN (IMG_UINT64_C(0X0000000000008000))
+/* INIT1_SWAIT
+debug status from init1 - defines whether to wait in M_WAIT state for MConnect
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_SWAIT_SHIFT (14U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_SWAIT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFBFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_SWAIT_EN (IMG_UINT64_C(0X0000000000004000))
+/* INIT1_MDISCREQ default: 0x00000001
+debug status from init1 - request to disconnect from standby protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_MDISCREQ_SHIFT (13U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_MDISCREQ_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFDFFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_MDISCREQ_EN (IMG_UINT64_C(0X0000000000002000))
+/* INIT1_MDISCACK default: 0x00000003
+debug status from init1 - ack to MDiscReq from standby protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_MDISCACK_SHIFT (11U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_MDISCACK_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFE7FF))
+/* INIT1_SCONNECT
+debug status from init1 - disconnect state from slave
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_SCONNECT_SHIFT (10U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_SCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFBFF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_SCONNECT_EN (IMG_UINT64_C(0X0000000000000400))
+/* INIT1_MCONNECT
+debug status from init1 - initiator mconnect state
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_MCONNECT_SHIFT (8U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT1_MCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
+/* INIT0_RESERVED
+debug status from init0 - reserved
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_RESERVED_SHIFT (7U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_RESERVED_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFF7F))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_RESERVED_EN (IMG_UINT64_C(0X0000000000000080))
+/* INIT0_SWAIT
+debug status from init0 - defines whether to wait in M_WAIT state for MConnect
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_SWAIT_SHIFT (6U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_SWAIT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFBF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_SWAIT_EN (IMG_UINT64_C(0X0000000000000040))
+/* INIT0_MDISCREQ default: 0x00000001
+debug status from init0 - request to disconnect from standby protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_MDISCREQ_SHIFT (5U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_MDISCREQ_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_MDISCREQ_EN (IMG_UINT64_C(0X0000000000000020))
+/* INIT0_MDISCACK default: 0x00000003
+debug status from init0 - ack to MDiscReq from standby protocol
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_MDISCACK_SHIFT (3U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_MDISCACK_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFE7))
+/* INIT0_SCONNECT
+debug status from init0 - disconnect state from slave
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_SCONNECT_SHIFT (2U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_SCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_SCONNECT_EN (IMG_UINT64_C(0X0000000000000004))
+/* INIT0_MCONNECT
+debug status from init0 - initiator mconnect state
+*/
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_MCONNECT_SHIFT (0U)
+#define RGX_CR_OCP_DEBUG_STATUS_INIT0_MCONNECT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
+
+
+/* PM_ALIST*/
+#define RGX_CR_BIF_TRUST_DM_TYPE_PM_ALIST_SHIFT (6U)
+#define RGX_CR_BIF_TRUST_DM_TYPE_PM_ALIST_CLRMSK (0XFFFFFFBFU)
+#define RGX_CR_BIF_TRUST_DM_TYPE_PM_ALIST_EN (0X00000040U)
+/* HOST*/
+#define RGX_CR_BIF_TRUST_DM_TYPE_HOST_SHIFT (5U)
+#define RGX_CR_BIF_TRUST_DM_TYPE_HOST_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_BIF_TRUST_DM_TYPE_HOST_EN (0X00000020U)
+/* META*/
+#define RGX_CR_BIF_TRUST_DM_TYPE_META_SHIFT (4U)
+#define RGX_CR_BIF_TRUST_DM_TYPE_META_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_BIF_TRUST_DM_TYPE_META_EN (0X00000010U)
+/* PB_ZLS*/
+#define RGX_CR_BIF_TRUST_DM_TYPE_PB_ZLS_SHIFT (3U)
+#define RGX_CR_BIF_TRUST_DM_TYPE_PB_ZLS_CLRMSK (0XFFFFFFF7U)
+#define RGX_CR_BIF_TRUST_DM_TYPE_PB_ZLS_EN (0X00000008U)
+/* PB_TE*/
+#define RGX_CR_BIF_TRUST_DM_TYPE_PB_TE_SHIFT (2U)
+#define RGX_CR_BIF_TRUST_DM_TYPE_PB_TE_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_BIF_TRUST_DM_TYPE_PB_TE_EN (0X00000004U)
+/* PB_VCE*/
+#define RGX_CR_BIF_TRUST_DM_TYPE_PB_VCE_SHIFT (1U)
+#define RGX_CR_BIF_TRUST_DM_TYPE_PB_VCE_CLRMSK (0XFFFFFFFDU)
+#define RGX_CR_BIF_TRUST_DM_TYPE_PB_VCE_EN (0X00000002U)
+/* TLA*/
+#define RGX_CR_BIF_TRUST_DM_TYPE_TLA_SHIFT (0U)
+#define RGX_CR_BIF_TRUST_DM_TYPE_TLA_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_BIF_TRUST_DM_TYPE_TLA_EN (0X00000001U)
+
+
+#define RGX_CR_BIF_TRUST_DM_MASK (0x0000007FU)
+
+
+/*
+ Define Requestors/Data Masters which are Trusted/Untrusted and enable/disbale the Memory Bus Security feature within the Core
+
+ When enabled the GPU modifies the top 2 bits of the external memory address to indicate:
+ - Address[39] Trusted DM Access (according to the DM Trusted setup)
+ - Address[38] META Code Access
+
+ Setting this bit effectively reduces the external physical address range from 1TB to 256 GB, and should only be used where the SOC implementation has a corresponding trust implementation.
+
+*/
+/*
+ Register RGX_CR_BIF_TRUST
+*/
+#define RGX_CR_BIF_TRUST (0xA000U)
+#define RGX_CR_BIF_TRUST_MASKFULL (IMG_UINT64_C(0x000000000001FFFF))
+/* ENABLE
+Enable Security feature: 0x1 = Enabled, 0x0 = Disabled
+*/
+#define RGX_CR_BIF_TRUST_ENABLE_SHIFT (16U)
+#define RGX_CR_BIF_TRUST_ENABLE_CLRMSK (0XFFFEFFFFU)
+#define RGX_CR_BIF_TRUST_ENABLE_EN (0X00010000U)
+/* DM_TRUSTED
+Mask of bits which defines which of the remaining Data Masters are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_DM_TRUSTED_SHIFT (9U)
+#define RGX_CR_BIF_TRUST_DM_TRUSTED_CLRMSK (0XFFFF01FFU)
+/* OTHER_COMPUTE_DM_TRUSTED
+Defines whether other accesses with the Compute DM are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_OTHER_COMPUTE_DM_TRUSTED_SHIFT (8U)
+#define RGX_CR_BIF_TRUST_OTHER_COMPUTE_DM_TRUSTED_CLRMSK (0XFFFFFEFFU)
+#define RGX_CR_BIF_TRUST_OTHER_COMPUTE_DM_TRUSTED_EN (0X00000100U)
+/* MCU_COMPUTE_DM_TRUSTED
+Defines whether MCU accesses with the Compute DM are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_MCU_COMPUTE_DM_TRUSTED_SHIFT (7U)
+#define RGX_CR_BIF_TRUST_MCU_COMPUTE_DM_TRUSTED_CLRMSK (0XFFFFFF7FU)
+#define RGX_CR_BIF_TRUST_MCU_COMPUTE_DM_TRUSTED_EN (0X00000080U)
+/* PBE_COMPUTE_DM_TRUSTED
+Defines whether PBE accesses with the Compute DM are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_PBE_COMPUTE_DM_TRUSTED_SHIFT (6U)
+#define RGX_CR_BIF_TRUST_PBE_COMPUTE_DM_TRUSTED_CLRMSK (0XFFFFFFBFU)
+#define RGX_CR_BIF_TRUST_PBE_COMPUTE_DM_TRUSTED_EN (0X00000040U)
+/* OTHER_PIXEL_DM_TRUSTED
+Defines whether other accesses with the Pixel DM are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_OTHER_PIXEL_DM_TRUSTED_SHIFT (5U)
+#define RGX_CR_BIF_TRUST_OTHER_PIXEL_DM_TRUSTED_CLRMSK (0XFFFFFFDFU)
+#define RGX_CR_BIF_TRUST_OTHER_PIXEL_DM_TRUSTED_EN (0X00000020U)
+/* MCU_PIXEL_DM_TRUSTED
+Defines whether MCU accesses with the Pixel DM are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_MCU_PIXEL_DM_TRUSTED_SHIFT (4U)
+#define RGX_CR_BIF_TRUST_MCU_PIXEL_DM_TRUSTED_CLRMSK (0XFFFFFFEFU)
+#define RGX_CR_BIF_TRUST_MCU_PIXEL_DM_TRUSTED_EN (0X00000010U)
+/* PBE_PIXEL_DM_TRUSTED
+Defines whether PBE accesses with the Pixel DM are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_PBE_PIXEL_DM_TRUSTED_SHIFT (3U)
+#define RGX_CR_BIF_TRUST_PBE_PIXEL_DM_TRUSTED_CLRMSK (0XFFFFFFF7U)
+#define RGX_CR_BIF_TRUST_PBE_PIXEL_DM_TRUSTED_EN (0X00000008U)
+/* OTHER_VERTEX_DM_TRUSTED
+Defines whether other accesses with the Vertex DM are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_OTHER_VERTEX_DM_TRUSTED_SHIFT (2U)
+#define RGX_CR_BIF_TRUST_OTHER_VERTEX_DM_TRUSTED_CLRMSK (0XFFFFFFFBU)
+#define RGX_CR_BIF_TRUST_OTHER_VERTEX_DM_TRUSTED_EN (0X00000004U)
+/* MCU_VERTEX_DM_TRUSTED
+Defines whether MCU accesses with the Vertex DM are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_MCU_VERTEX_DM_TRUSTED_SHIFT (1U)
+#define RGX_CR_BIF_TRUST_MCU_VERTEX_DM_TRUSTED_CLRMSK (0XFFFFFFFDU)
+#define RGX_CR_BIF_TRUST_MCU_VERTEX_DM_TRUSTED_EN (0X00000002U)
+/* PBE_VERTEX_DM_TRUSTED
+Defines whether PBE accesses with the Vertex DM are trusted: 0x1 = Trusted, 0x0 = Untrusted
+*/
+#define RGX_CR_BIF_TRUST_PBE_VERTEX_DM_TRUSTED_SHIFT (0U)
+#define RGX_CR_BIF_TRUST_PBE_VERTEX_DM_TRUSTED_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_BIF_TRUST_PBE_VERTEX_DM_TRUSTED_EN (0X00000001U)
+
+
+/*
+ Register RGX_CR_SYS_BUS_SECURE
+*/
+#define RGX_CR_SYS_BUS_SECURE (0xA100U)
+#define RGX_CR_SYS_BUS_SECURE_MASKFULL (IMG_UINT64_C(0x0000000000000001))
+/* Enable
+0 = No System Bus Security1 = System Bus Restricted
+*/
+#define RGX_CR_SYS_BUS_SECURE_ENABLE_SHIFT (0U)
+#define RGX_CR_SYS_BUS_SECURE_ENABLE_CLRMSK (0XFFFFFFFEU)
+#define RGX_CR_SYS_BUS_SECURE_ENABLE_EN (0X00000001U)
+
+
+/*
+
+ Core Module Clock Control Modes.
+
+
+ Allows individual domain clocks to be forced off, forced on or operate under automatic pipeline activity based clock gating. This register is generally controlled by the GPU firmware and should be set to AUTO. Clock gating reduces the power consumed by the device.
+
+*/
+/*
+ Register RGX_CR_CLK_CTRL2
+*/
+#define RGX_CR_CLK_CTRL2 (0xD200U)
+#define RGX_CR_CLK_CTRL2_MASKFULL (IMG_UINT64_C(0x0000000000000F33))
+/* MCU_FBTC default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL2_MCU_FBTC_SHIFT (10U)
+#define RGX_CR_CLK_CTRL2_MCU_FBTC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF3FF))
+#define RGX_CR_CLK_CTRL2_MCU_FBTC_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL2_MCU_FBTC_ON (IMG_UINT64_C(0x0000000000000400))
+#define RGX_CR_CLK_CTRL2_MCU_FBTC_AUTO (IMG_UINT64_C(0x0000000000000800))
+#if defined(RGX_FEATURE_RAY_TRACING)
+/* VRDM default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL2_VRDM_SHIFT (8U)
+#define RGX_CR_CLK_CTRL2_VRDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFCFF))
+#define RGX_CR_CLK_CTRL2_VRDM_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL2_VRDM_ON (IMG_UINT64_C(0x0000000000000100))
+#define RGX_CR_CLK_CTRL2_VRDM_AUTO (IMG_UINT64_C(0x0000000000000200))
+/* SH default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL2_SH_SHIFT (4U)
+#define RGX_CR_CLK_CTRL2_SH_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFCF))
+#define RGX_CR_CLK_CTRL2_SH_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL2_SH_ON (IMG_UINT64_C(0x0000000000000010))
+#define RGX_CR_CLK_CTRL2_SH_AUTO (IMG_UINT64_C(0x0000000000000020))
+/* FBA default: AUTO (0x00000002) */
+#define RGX_CR_CLK_CTRL2_FBA_SHIFT (0U)
+#define RGX_CR_CLK_CTRL2_FBA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFC))
+#define RGX_CR_CLK_CTRL2_FBA_OFF (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_CTRL2_FBA_ON (IMG_UINT64_C(0x0000000000000001))
+#define RGX_CR_CLK_CTRL2_FBA_AUTO (IMG_UINT64_C(0x0000000000000002))
+
+
+#endif /* RGX_FEATURE_RAY_TRACING */
+
+/*
+
+ Reports the current module clock status
+
+
+ Clock gating state reflects the condition of the clock for each module
+
+*/
+/*
+ Register RGX_CR_CLK_STATUS2
+*/
+#define RGX_CR_CLK_STATUS2 (0xD208U)
+#define RGX_CR_CLK_STATUS2_MASKFULL (IMG_UINT64_C(0x0000000000000015))
+#if defined(RGX_FEATURE_RAY_TRACING)
+/* VRDM default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS2_VRDM_SHIFT (4U)
+#define RGX_CR_CLK_STATUS2_VRDM_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
+#define RGX_CR_CLK_STATUS2_VRDM_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS2_VRDM_RUNNING (IMG_UINT64_C(0x0000000000000010))
+/* SH default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS2_SH_SHIFT (2U)
+#define RGX_CR_CLK_STATUS2_SH_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
+#define RGX_CR_CLK_STATUS2_SH_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS2_SH_RUNNING (IMG_UINT64_C(0x0000000000000004))
+/* FBA default: GATED (0x00000000) */
+#define RGX_CR_CLK_STATUS2_FBA_SHIFT (0U)
+#define RGX_CR_CLK_STATUS2_FBA_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_CLK_STATUS2_FBA_GATED (IMG_UINT64_C(0000000000000000))
+#define RGX_CR_CLK_STATUS2_FBA_RUNNING (IMG_UINT64_C(0x0000000000000001))
+
+
+#endif /* RGX_FEATURE_RAY_TRACING */
+
+/*
+
+ Indicates a page fault has occurred due to a non-Meta request and gives details of faulting request. Any write to this register will clear the contents and allow a subsequent fault to be reported
+
+*/
+/*
+ Register RGX_CR_MMU_FAULT_STATUS
+*/
+#define RGX_CR_MMU_FAULT_STATUS (0xE150U)
+#define RGX_CR_MMU_FAULT_STATUS_MASKFULL (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
+/* ADDRESS
+Virtual address
+*/
+#define RGX_CR_MMU_FAULT_STATUS_ADDRESS_SHIFT (28U)
+#define RGX_CR_MMU_FAULT_STATUS_ADDRESS_CLRMSK (IMG_UINT64_C(0X000000000FFFFFFF))
+/* CONTEXT
+Context
+*/
+#define RGX_CR_MMU_FAULT_STATUS_CONTEXT_SHIFT (20U)
+#define RGX_CR_MMU_FAULT_STATUS_CONTEXT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFF00FFFFF))
+/* TAG_SB
+Sideband tag
+*/
+#define RGX_CR_MMU_FAULT_STATUS_TAG_SB_SHIFT (12U)
+#define RGX_CR_MMU_FAULT_STATUS_TAG_SB_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFF00FFF))
+/* REQ_ID
+Requester ID - see rgx_bif3_pack/documentation for encoding
+*/
+#define RGX_CR_MMU_FAULT_STATUS_REQ_ID_SHIFT (6U)
+#define RGX_CR_MMU_FAULT_STATUS_REQ_ID_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF03F))
+/* LEVEL
+MMU level that faulted: "00"=PT "01"=PD "10"=PC "11"=PC Base
+*/
+#define RGX_CR_MMU_FAULT_STATUS_LEVEL_SHIFT (4U)
+#define RGX_CR_MMU_FAULT_STATUS_LEVEL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFCF))
+/* RNW
+Indicates whether fault was caused by a read(1) or write(0) request
+*/
+#define RGX_CR_MMU_FAULT_STATUS_RNW_SHIFT (3U)
+#define RGX_CR_MMU_FAULT_STATUS_RNW_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
+#define RGX_CR_MMU_FAULT_STATUS_RNW_EN (IMG_UINT64_C(0X0000000000000008))
+/* TYPE
+Type of fault: "00"=valid "10"=read-only "11"=pm/meta protected
+*/
+#define RGX_CR_MMU_FAULT_STATUS_TYPE_SHIFT (1U)
+#define RGX_CR_MMU_FAULT_STATUS_TYPE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF9))
+/* FAULT
+Indicates a fault has occured
+*/
+#define RGX_CR_MMU_FAULT_STATUS_FAULT_SHIFT (0U)
+#define RGX_CR_MMU_FAULT_STATUS_FAULT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_MMU_FAULT_STATUS_FAULT_EN (IMG_UINT64_C(0X0000000000000001))
+
+
+/*
+
+ Indicates a page fault has occurred due to a Meta request and gives details of faulting request. Any write to this register will clear the contents and allow a subsequent fault to be reported
+
+*/
+/*
+ Register RGX_CR_MMU_FAULT_STATUS_META
+*/
+#define RGX_CR_MMU_FAULT_STATUS_META (0xE158U)
+#define RGX_CR_MMU_FAULT_STATUS_META_MASKFULL (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
+/* ADDRESS
+Virtual address
+*/
+#define RGX_CR_MMU_FAULT_STATUS_META_ADDRESS_SHIFT (28U)
+#define RGX_CR_MMU_FAULT_STATUS_META_ADDRESS_CLRMSK (IMG_UINT64_C(0X000000000FFFFFFF))
+/* CONTEXT
+Context
+*/
+#define RGX_CR_MMU_FAULT_STATUS_META_CONTEXT_SHIFT (20U)
+#define RGX_CR_MMU_FAULT_STATUS_META_CONTEXT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFF00FFFFF))
+/* TAG_SB
+Sideband tag
+*/
+#define RGX_CR_MMU_FAULT_STATUS_META_TAG_SB_SHIFT (12U)
+#define RGX_CR_MMU_FAULT_STATUS_META_TAG_SB_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFF00FFF))
+/* REQ_ID
+Requester ID - see rgx_bif3_pack/documentation for encoding
+*/
+#define RGX_CR_MMU_FAULT_STATUS_META_REQ_ID_SHIFT (6U)
+#define RGX_CR_MMU_FAULT_STATUS_META_REQ_ID_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF03F))
+/* LEVEL
+MMU level that faulted: "00"=PT "01"=PD "10"=PC "11"=PC Base
+*/
+#define RGX_CR_MMU_FAULT_STATUS_META_LEVEL_SHIFT (4U)
+#define RGX_CR_MMU_FAULT_STATUS_META_LEVEL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFCF))
+/* RNW
+Indicates whether fault was caused by a read(1) or write(0) request
+*/
+#define RGX_CR_MMU_FAULT_STATUS_META_RNW_SHIFT (3U)
+#define RGX_CR_MMU_FAULT_STATUS_META_RNW_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
+#define RGX_CR_MMU_FAULT_STATUS_META_RNW_EN (IMG_UINT64_C(0X0000000000000008))
+/* TYPE
+Type of fault: "00"=valid "10"=read-only "11"=pm/meta protected
+*/
+#define RGX_CR_MMU_FAULT_STATUS_META_TYPE_SHIFT (1U)
+#define RGX_CR_MMU_FAULT_STATUS_META_TYPE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF9))
+/* FAULT
+Indicates a fault has occured
+*/
+#define RGX_CR_MMU_FAULT_STATUS_META_FAULT_SHIFT (0U)
+#define RGX_CR_MMU_FAULT_STATUS_META_FAULT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_CR_MMU_FAULT_STATUS_META_FAULT_EN (IMG_UINT64_C(0X0000000000000001))
+
+
+/*
+
+ SLC Control registers
+
+*/
+/*
+ Register RGX_CR_SLC3_CTRL_MISC
+*/
+#define RGX_CR_SLC3_CTRL_MISC (0xE200U)
+#define RGX_CR_SLC3_CTRL_MISC_MASKFULL (IMG_UINT64_C(0x0000000000000003))
+/* ADDR_DECODE_MODE default: LINEAR (0x00000000)
+(null)
+*/
+#define RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_SHIFT (0U)
+#define RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_CLRMSK (0XFFFFFFFCU)
+#define RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_LINEAR (00000000U)
+#define RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_IN_PAGE_HASH (0X00000001U)
+#define RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_FIXED_PVR_HASH (0X00000002U)
+#define RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_SCRAMBLE_PVR_HASH (0X00000003U)
+
+
+/*
+
+ SLC Control registers
+
+*/
+/*
+ Register RGX_CR_SLC3_SCRAMBLE
+*/
+#define RGX_CR_SLC3_SCRAMBLE (0xE208U)
+#define RGX_CR_SLC3_SCRAMBLE_MASKFULL (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
+/* BITS
+ Pattern of bits used to determine the Cache Bank in Address Decode mode 0x3. The actual Cache Bank to use is determined by indexing into the Scramble Bits, see the SLC HW specification for more details
+*/
+#define RGX_CR_SLC3_SCRAMBLE_BITS_SHIFT (0U)
+#define RGX_CR_SLC3_SCRAMBLE_BITS_CLRMSK (IMG_UINT64_C(0000000000000000))
+
+
+/*
+
+ SLC Control registers
+
+*/
+/*
+ Register RGX_CR_SLC3_SCRAMBLE2
+*/
+#define RGX_CR_SLC3_SCRAMBLE2 (0xE210U)
+#define RGX_CR_SLC3_SCRAMBLE2_MASKFULL (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
+/* BITS
+ Pattern of bits used to determine the Cache Bank in Address Decode mode 0x3. The actual Cache Bank to use is determined by indexing into the Scramble Bits, see the SLC HW specification for more details
+*/
+#define RGX_CR_SLC3_SCRAMBLE2_BITS_SHIFT (0U)
+#define RGX_CR_SLC3_SCRAMBLE2_BITS_CLRMSK (IMG_UINT64_C(0000000000000000))
+
+
+#endif /* _RGX_CR_DEFS_KM_H_ */
+
+/*****************************************************************************
+ End of file (rgx_cr_defs_km.h)
+*****************************************************************************/
+
diff --git a/drivers/gpu/rogue/hwdefs/km/rgxdefs_km.h b/drivers/gpu/rogue/hwdefs/km/rgxdefs_km.h
new file mode 100644
index 000000000000..ed570ef85c3b
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/rgxdefs_km.h
@@ -0,0 +1,140 @@
+/*************************************************************************/ /*!
+@Title Rogue hw definitions (kernel mode)
+@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 _RGXDEFS_KM_H_
+#define _RGXDEFS_KM_H_
+
+#include RGX_BVNC_CORE_KM_HEADER
+#include RGX_BNC_CONFIG_KM_HEADER
+
+#define __IMG_EXPLICIT_INCLUDE_HWDEFS
+#include "rgx_cr_defs_km.h"
+#undef __IMG_EXPLICIT_INCLUDE_HWDEFS
+
+/******************************************************************************
+ * Check for valid B.X.N.C
+ *****************************************************************************/
+#if !defined(RGX_BVNC_KM_B) || !defined(RGX_BVNC_KM_V) || !defined(RGX_BVNC_KM_N) || !defined(RGX_BVNC_KM_C)
+#error "Need to specify BVNC (RGX_BVNC_KM_B, RGX_BVNC_KM_V, RGX_BVNC_KM_N and RGX_BVNC_C)"
+#endif
+
+/* Check core/config compatibility */
+#if (RGX_BVNC_KM_B != RGX_BNC_KM_B) || (RGX_BVNC_KM_N != RGX_BNC_KM_N) || (RGX_BVNC_KM_C != RGX_BNC_KM_C)
+#error "BVNC headers are mismatching (KM core/config)"
+#endif
+
+/******************************************************************************
+ * RGX Version name
+ *****************************************************************************/
+#define _RGX_BVNC_ST2(S) #S
+#define _RGX_BVNC_ST(S) _RGX_BVNC_ST2(S)
+#define RGX_BVNC_KM _RGX_BVNC_ST(RGX_BVNC_KM_B) "." _RGX_BVNC_ST(RGX_BVNC_KM_V) "." _RGX_BVNC_ST(RGX_BVNC_KM_N) "." _RGX_BVNC_ST(RGX_BVNC_KM_C)
+#define RGX_BVNC_KM_V_ST _RGX_BVNC_ST(RGX_BVNC_KM_V)
+
+/******************************************************************************
+ * RGX Defines
+ *****************************************************************************/
+
+/* META cores (required for the RGX_FEATURE_META) */
+#define MTP218 (1)
+#define MTP219 (2)
+#define LTP218 (3)
+#define LTP217 (4)
+
+/* ISP requires valid state on all three pipes regardless of the number of
+ * active pipes/tiles in flight.
+ */
+#define RGX_MAX_NUM_PIPES 3
+
+#define ROGUE_CACHE_LINE_SIZE ((RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS)/8)
+
+#define MAX_HW_TA3DCONTEXTS 2
+
+
+/* useful extra defines for clock ctrl*/
+#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)
+
+/* SOFT_RESET Rascal and DUSTs bits */
+#define RGX_CR_SOFT_RESET_RASCALDUSTS_EN (RGX_CR_SOFT_RESET_RASCAL_CORE_EN | \
+ RGX_CR_SOFT_RESET_DUST_A_CORE_EN | \
+ RGX_CR_SOFT_RESET_DUST_B_CORE_EN | \
+ RGX_CR_SOFT_RESET_DUST_C_CORE_EN | \
+ RGX_CR_SOFT_RESET_DUST_D_CORE_EN | \
+ RGX_CR_SOFT_RESET_DUST_E_CORE_EN | \
+ RGX_CR_SOFT_RESET_DUST_F_CORE_EN | \
+ RGX_CR_SOFT_RESET_DUST_G_CORE_EN | \
+ RGX_CR_SOFT_RESET_DUST_H_CORE_EN)
+
+#define RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT (12)
+#define RGX_BIF_PM_PHYSICAL_PAGE_SIZE (1 << RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT)
+
+#define RGX_BIF_PM_VIRTUAL_PAGE_ALIGNSHIFT (14)
+#define RGX_BIF_PM_VIRTUAL_PAGE_SIZE (1 << RGX_BIF_PM_VIRTUAL_PAGE_ALIGNSHIFT)
+
+#if defined(RGX_FEATURE_META_DMA_CHANNEL_COUNT)
+#define RGX_FEATURE_DMA (1)
+#define RGXFW_DMA_CH_PRIO_DEFAULT ( (RGXFW_DMA_PRIORITY_0 << RGX_CR_DMA_CONTROL_CH0_PRIORITY_SHIFT) | \
+ (RGXFW_DMA_PRIORITY_1 << RGX_CR_DMA_CONTROL_CH1_PRIORITY_SHIFT) )
+#endif
+
+/******************************************************************************
+ * WA HWBRNs
+ *****************************************************************************/
+#if defined(FIX_HW_BRN_36492)
+
+#undef RGX_CR_SOFT_RESET_SLC_EN
+#undef RGX_CR_SOFT_RESET_SLC_CLRMSK
+#undef RGX_CR_SOFT_RESET_SLC_SHIFT
+
+/* Remove the SOFT_RESET_SLC_EN bit from SOFT_RESET_MASKFULL */
+#undef RGX_CR_SOFT_RESET_MASKFULL
+#define RGX_CR_SOFT_RESET_MASKFULL IMG_UINT64_C(0x000001FFF7FFFC1D)
+
+#endif /* FIX_HW_BRN_36492 */
+
+#define DPX_MAX_RAY_CONTEXTS 4 /* */
+
+#if !defined(RGX_FEATURE_SLC_SIZE_IN_BYTES)
+#define RGX_FEATURE_SLC_SIZE_IN_BYTES (RGX_FEATURE_SLC_SIZE_IN_KILOBYTES * 1024)
+#endif
+
+#endif /* _RGXDEFS_KM_H_ */
diff --git a/drivers/gpu/rogue/hwdefs/km/rgxmmudefs_km.h b/drivers/gpu/rogue/hwdefs/km/rgxmmudefs_km.h
new file mode 100644
index 000000000000..7419db508105
--- /dev/null
+++ b/drivers/gpu/rogue/hwdefs/km/rgxmmudefs_km.h
@@ -0,0 +1,395 @@
+/*************************************************************************/ /*!
+@Title Hardware definition file rgxmmudefs_km.h
+@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.
+*/ /**************************************************************************/
+
+/* **** Autogenerated C -- do not edit **** */
+
+/*
+ * Generated by regconv version MAIN@2782796
+ * from files:
+ * rogue_bif.def
+ * rogue_bif.def
+ */
+
+
+#ifndef _RGXMMUDEFS_KM_H_
+#define _RGXMMUDEFS_KM_H_
+
+#include "img_types.h"
+
+/*
+
+ Encoding of DM (note value 0x6 not used)
+
+*/
+#define RGX_BIF_DM_ENCODING_VERTEX (0x00000000U)
+#define RGX_BIF_DM_ENCODING_PIXEL (0x00000001U)
+#define RGX_BIF_DM_ENCODING_COMPUTE (0x00000002U)
+#define RGX_BIF_DM_ENCODING_TLA (0x00000003U)
+#define RGX_BIF_DM_ENCODING_PB_VCE (0x00000004U)
+#define RGX_BIF_DM_ENCODING_PB_TE (0x00000005U)
+#define RGX_BIF_DM_ENCODING_META (0x00000007U)
+#define RGX_BIF_DM_ENCODING_HOST (0x00000008U)
+#define RGX_BIF_DM_ENCODING_PM_ALIST (0x00000009U)
+
+
+/*
+
+ Labelling of fields within virtual address
+
+*/
+/*
+Page Catalogue entry #
+*/
+#define RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT (30U)
+#define RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK (IMG_UINT64_C(0XFFFFFF003FFFFFFF))
+/*
+Page Directory entry #
+*/
+#define RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT (21U)
+#define RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK (IMG_UINT64_C(0XFFFFFFFFC01FFFFF))
+/*
+Page Table entry #
+*/
+#define RGX_MMUCTRL_VADDR_PT_INDEX_SHIFT (12U)
+#define RGX_MMUCTRL_VADDR_PT_INDEX_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFE00FFF))
+
+
+/*
+
+ Number of entries in a PC
+
+*/
+#define RGX_MMUCTRL_ENTRIES_PC_VALUE (0x00000400U)
+
+
+/*
+
+ Number of entries in a PD
+
+*/
+#define RGX_MMUCTRL_ENTRIES_PD_VALUE (0x00000200U)
+
+
+/*
+
+ Number of entries in a PT
+
+*/
+#define RGX_MMUCTRL_ENTRIES_PT_VALUE (0x00000200U)
+
+
+/*
+
+ Size in bits of the PC entries in memory
+
+*/
+#define RGX_MMUCTRL_ENTRY_SIZE_PC_VALUE (0x00000020U)
+
+
+/*
+
+ Size in bits of the PD entries in memory
+
+*/
+#define RGX_MMUCTRL_ENTRY_SIZE_PD_VALUE (0x00000040U)
+
+
+/*
+
+ Size in bits of the PT entries in memory
+
+*/
+#define RGX_MMUCTRL_ENTRY_SIZE_PT_VALUE (0x00000040U)
+
+
+/*
+
+ Encoding of page size field
+
+*/
+#define RGX_MMUCTRL_PAGE_SIZE_MASK (0x00000007U)
+#define RGX_MMUCTRL_PAGE_SIZE_4KB (0x00000000U)
+#define RGX_MMUCTRL_PAGE_SIZE_16KB (0x00000001U)
+#define RGX_MMUCTRL_PAGE_SIZE_64KB (0x00000002U)
+#define RGX_MMUCTRL_PAGE_SIZE_256KB (0x00000003U)
+#define RGX_MMUCTRL_PAGE_SIZE_1MB (0x00000004U)
+#define RGX_MMUCTRL_PAGE_SIZE_2MB (0x00000005U)
+
+
+/*
+
+ Range of bits used for 4KB Physical Page
+
+*/
+#define RGX_MMUCTRL_PAGE_4KB_RANGE_SHIFT (12U)
+#define RGX_MMUCTRL_PAGE_4KB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF0000000FFF))
+
+
+/*
+
+ Range of bits used for 16KB Physical Page
+
+*/
+#define RGX_MMUCTRL_PAGE_16KB_RANGE_SHIFT (14U)
+#define RGX_MMUCTRL_PAGE_16KB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF0000003FFF))
+
+
+/*
+
+ Range of bits used for 64KB Physical Page
+
+*/
+#define RGX_MMUCTRL_PAGE_64KB_RANGE_SHIFT (16U)
+#define RGX_MMUCTRL_PAGE_64KB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF000000FFFF))
+
+
+/*
+
+ Range of bits used for 256KB Physical Page
+
+*/
+#define RGX_MMUCTRL_PAGE_256KB_RANGE_SHIFT (18U)
+#define RGX_MMUCTRL_PAGE_256KB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF000003FFFF))
+
+
+/*
+
+ Range of bits used for 1MB Physical Page
+
+*/
+#define RGX_MMUCTRL_PAGE_1MB_RANGE_SHIFT (20U)
+#define RGX_MMUCTRL_PAGE_1MB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF00000FFFFF))
+
+
+/*
+
+ Range of bits used for 2MB Physical Page
+
+*/
+#define RGX_MMUCTRL_PAGE_2MB_RANGE_SHIFT (21U)
+#define RGX_MMUCTRL_PAGE_2MB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF00001FFFFF))
+
+
+/*
+
+ Range of bits used for PT Base Address for 4KB Physical Page
+
+*/
+#define RGX_MMUCTRL_PT_BASE_4KB_RANGE_SHIFT (12U)
+#define RGX_MMUCTRL_PT_BASE_4KB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF0000000FFF))
+
+
+/*
+
+ Range of bits used for PT Base Address for 16KB Physical Page
+
+*/
+#define RGX_MMUCTRL_PT_BASE_16KB_RANGE_SHIFT (10U)
+#define RGX_MMUCTRL_PT_BASE_16KB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF00000003FF))
+
+
+/*
+
+ Range of bits used for PT Base Address for 64KB Physical Page
+
+*/
+#define RGX_MMUCTRL_PT_BASE_64KB_RANGE_SHIFT (8U)
+#define RGX_MMUCTRL_PT_BASE_64KB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF00000000FF))
+
+
+/*
+
+ Range of bits used for PT Base Address for 256KB Physical Page
+
+*/
+#define RGX_MMUCTRL_PT_BASE_256KB_RANGE_SHIFT (6U)
+#define RGX_MMUCTRL_PT_BASE_256KB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF000000003F))
+
+
+/*
+
+ Range of bits used for PT Base Address for 1MB Physical Page
+
+*/
+#define RGX_MMUCTRL_PT_BASE_1MB_RANGE_SHIFT (5U)
+#define RGX_MMUCTRL_PT_BASE_1MB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF000000001F))
+
+
+/*
+
+ Range of bits used for PT Base Address for 2MB Physical Page
+
+*/
+#define RGX_MMUCTRL_PT_BASE_2MB_RANGE_SHIFT (5U)
+#define RGX_MMUCTRL_PT_BASE_2MB_RANGE_CLRMSK (IMG_UINT64_C(0XFFFFFF000000001F))
+
+
+/*
+
+ Format of Page Table data
+
+*/
+/*
+PM/Meta protect bit
+*/
+#define RGX_MMUCTRL_PT_DATA_PM_META_PROTECT_SHIFT (62U)
+#define RGX_MMUCTRL_PT_DATA_PM_META_PROTECT_CLRMSK (IMG_UINT64_C(0XBFFFFFFFFFFFFFFF))
+#define RGX_MMUCTRL_PT_DATA_PM_META_PROTECT_EN (IMG_UINT64_C(0X4000000000000000))
+/*
+Upper part of vp page field
+*/
+#define RGX_MMUCTRL_PT_DATA_VP_PAGE_HI_SHIFT (40U)
+#define RGX_MMUCTRL_PT_DATA_VP_PAGE_HI_CLRMSK (IMG_UINT64_C(0XC00000FFFFFFFFFF))
+/*
+Physical page address
+*/
+#define RGX_MMUCTRL_PT_DATA_PAGE_SHIFT (12U)
+#define RGX_MMUCTRL_PT_DATA_PAGE_CLRMSK (IMG_UINT64_C(0XFFFFFF0000000FFF))
+/*
+Lower part of vp page field
+*/
+#define RGX_MMUCTRL_PT_DATA_VP_PAGE_LO_SHIFT (6U)
+#define RGX_MMUCTRL_PT_DATA_VP_PAGE_LO_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFF03F))
+/*
+Entry pending
+*/
+#define RGX_MMUCTRL_PT_DATA_ENTRY_PENDING_SHIFT (5U)
+#define RGX_MMUCTRL_PT_DATA_ENTRY_PENDING_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFDF))
+#define RGX_MMUCTRL_PT_DATA_ENTRY_PENDING_EN (IMG_UINT64_C(0X0000000000000020))
+/*
+PM Src
+*/
+#define RGX_MMUCTRL_PT_DATA_PM_SRC_SHIFT (4U)
+#define RGX_MMUCTRL_PT_DATA_PM_SRC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFEF))
+#define RGX_MMUCTRL_PT_DATA_PM_SRC_EN (IMG_UINT64_C(0X0000000000000010))
+/*
+SLC Bypass Ctrl
+*/
+#define RGX_MMUCTRL_PT_DATA_SLC_BYPASS_CTRL_SHIFT (3U)
+#define RGX_MMUCTRL_PT_DATA_SLC_BYPASS_CTRL_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF7))
+#define RGX_MMUCTRL_PT_DATA_SLC_BYPASS_CTRL_EN (IMG_UINT64_C(0X0000000000000008))
+/*
+Cache Coherency bit
+*/
+#define RGX_MMUCTRL_PT_DATA_CC_SHIFT (2U)
+#define RGX_MMUCTRL_PT_DATA_CC_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFB))
+#define RGX_MMUCTRL_PT_DATA_CC_EN (IMG_UINT64_C(0X0000000000000004))
+/*
+Read only
+*/
+#define RGX_MMUCTRL_PT_DATA_READ_ONLY_SHIFT (1U)
+#define RGX_MMUCTRL_PT_DATA_READ_ONLY_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFD))
+#define RGX_MMUCTRL_PT_DATA_READ_ONLY_EN (IMG_UINT64_C(0X0000000000000002))
+/*
+Entry valid
+*/
+#define RGX_MMUCTRL_PT_DATA_VALID_SHIFT (0U)
+#define RGX_MMUCTRL_PT_DATA_VALID_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_MMUCTRL_PT_DATA_VALID_EN (IMG_UINT64_C(0X0000000000000001))
+
+
+/*
+
+ Format of Page Directory data
+
+*/
+/*
+Entry pending
+*/
+#define RGX_MMUCTRL_PD_DATA_ENTRY_PENDING_SHIFT (40U)
+#define RGX_MMUCTRL_PD_DATA_ENTRY_PENDING_CLRMSK (IMG_UINT64_C(0XFFFFFEFFFFFFFFFF))
+#define RGX_MMUCTRL_PD_DATA_ENTRY_PENDING_EN (IMG_UINT64_C(0X0000010000000000))
+/*
+Page Table base address
+*/
+#define RGX_MMUCTRL_PD_DATA_PT_BASE_SHIFT (5U)
+#define RGX_MMUCTRL_PD_DATA_PT_BASE_CLRMSK (IMG_UINT64_C(0XFFFFFF000000001F))
+/*
+Page Size
+*/
+#define RGX_MMUCTRL_PD_DATA_PAGE_SIZE_SHIFT (1U)
+#define RGX_MMUCTRL_PD_DATA_PAGE_SIZE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFF1))
+#define RGX_MMUCTRL_PD_DATA_PAGE_SIZE_4KB (IMG_UINT64_C(0000000000000000))
+#define RGX_MMUCTRL_PD_DATA_PAGE_SIZE_16KB (IMG_UINT64_C(0x0000000000000002))
+#define RGX_MMUCTRL_PD_DATA_PAGE_SIZE_64KB (IMG_UINT64_C(0x0000000000000004))
+#define RGX_MMUCTRL_PD_DATA_PAGE_SIZE_256KB (IMG_UINT64_C(0x0000000000000006))
+#define RGX_MMUCTRL_PD_DATA_PAGE_SIZE_1MB (IMG_UINT64_C(0x0000000000000008))
+#define RGX_MMUCTRL_PD_DATA_PAGE_SIZE_2MB (IMG_UINT64_C(0x000000000000000a))
+/*
+Entry valid
+*/
+#define RGX_MMUCTRL_PD_DATA_VALID_SHIFT (0U)
+#define RGX_MMUCTRL_PD_DATA_VALID_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define RGX_MMUCTRL_PD_DATA_VALID_EN (IMG_UINT64_C(0X0000000000000001))
+
+
+/*
+
+ Format of Page Catalogue data
+
+*/
+/*
+Page Catalogue base address
+*/
+#define RGX_MMUCTRL_PC_DATA_PD_BASE_SHIFT (4U)
+#define RGX_MMUCTRL_PC_DATA_PD_BASE_CLRMSK (0X0000000FU)
+#define RGX_MMUCTRL_PC_DATA_PD_BASE_ALIGNSHIFT (12U)
+#define RGX_MMUCTRL_PC_DATA_PD_BASE_ALIGNSIZE (4096U)
+/*
+Entry pending
+*/
+#define RGX_MMUCTRL_PC_DATA_ENTRY_PENDING_SHIFT (1U)
+#define RGX_MMUCTRL_PC_DATA_ENTRY_PENDING_CLRMSK (0XFFFFFFFDU)
+#define RGX_MMUCTRL_PC_DATA_ENTRY_PENDING_EN (0X00000002U)
+/*
+Entry valid
+*/
+#define RGX_MMUCTRL_PC_DATA_VALID_SHIFT (0U)
+#define RGX_MMUCTRL_PC_DATA_VALID_CLRMSK (0XFFFFFFFEU)
+#define RGX_MMUCTRL_PC_DATA_VALID_EN (0X00000001U)
+
+
+#endif /* _RGXMMUDEFS_KM_H_ */
+
+/*****************************************************************************
+ End of file (rgxmmudefs_km.h)
+*****************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/adf/adf_ext.h b/drivers/gpu/rogue/include/adf/adf_ext.h
new file mode 100644
index 000000000000..d730fe061d4d
--- /dev/null
+++ b/drivers/gpu/rogue/include/adf/adf_ext.h
@@ -0,0 +1,108 @@
+/*************************************************************************/ /*!
+@File adf_ext.h
+@Title IMG extension ioctls and ioctl packages for ADF
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+#ifndef __ADF_EXT_H__
+#define __ADF_EXT_H__
+
+#include <drm/drm.h>
+
+#define ADF_BUFFER_TRANSFORM_NONE_EXT (0 << 0)
+#define ADF_BUFFER_TRANSFORM_FLIP_H_EXT (1 << 0)
+#define ADF_BUFFER_TRANSFORM_FLIP_V_EXT (1 << 1)
+#define ADF_BUFFER_TRANSFORM_ROT_90_EXT (1 << 2)
+#define ADF_BUFFER_TRANSFORM_ROT_180_EXT ((1 << 0) + (1 << 1))
+#define ADF_BUFFER_TRANSFORM_ROT_270_EXT ((1 << 0) + (1 << 1) + (1 << 2))
+
+#define ADF_BUFFER_BLENDING_NONE_EXT 0
+#define ADF_BUFFER_BLENDING_PREMULT_EXT 1
+#define ADF_BUFFER_BLENDING_COVERAGE_EXT 2
+
+struct adf_buffer_config_ext {
+ /* Crop applied to surface (BEFORE transformation) */
+ struct drm_clip_rect crop;
+
+ /* Region of screen to display surface in (AFTER scaling) */
+ struct drm_clip_rect display;
+
+ /* Surface rotation / flip / mirror */
+ __u32 transform;
+
+ /* Alpha blending mode e.g. none / premult / coverage */
+ __u32 blend_type;
+
+ /* Plane alpha */
+ __u8 plane_alpha;
+ __u8 reserved[3];
+} __attribute__((packed, aligned(8)));
+
+struct adf_post_ext {
+ __u32 post_id;
+ struct adf_buffer_config_ext bufs_ext[];
+} __attribute__((packed, aligned(8)));
+
+struct adf_validate_config_ext {
+ __u32 n_interfaces;
+ __u32 __user *interfaces;
+
+ __u32 n_bufs;
+
+ struct adf_buffer_config __user *bufs;
+ struct adf_post_ext __user *post_ext;
+} __attribute__((packed, aligned(8)));
+
+/* These shouldn't be stripped by the uapi process in the bionic headers,
+ * but currently are being. Redefine them so the custom ioctl interface is
+ * actually useful.
+ */
+#ifndef ADF_IOCTL_TYPE
+#define ADF_IOCTL_TYPE 'D'
+#endif
+
+#ifndef ADF_IOCTL_NR_CUSTOM
+#define ADF_IOCTL_NR_CUSTOM 128
+#endif
+
+#define ADF_VALIDATE_CONFIG_EXT \
+ _IOW(ADF_IOCTL_TYPE, ADF_IOCTL_NR_CUSTOM + 0, struct adf_validate_config_ext)
+
+#endif /* __ADF_EXT_H__ */
diff --git a/drivers/gpu/rogue/include/cache_external.h b/drivers/gpu/rogue/include/cache_external.h
new file mode 100644
index 000000000000..2967f1ead23e
--- /dev/null
+++ b/drivers/gpu/rogue/include/cache_external.h
@@ -0,0 +1,75 @@
+/*************************************************************************/ /*!
+@File
+@Title Services cache management header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines for cache management which are visible internally
+ and externally
+@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 _CACHE_EXTERNAL_H_
+#define _CACHE_EXTERNAL_H_
+#include "img_types.h"
+
+typedef IMG_UINT32 PVRSRV_CACHE_OP;
+
+#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 */
+
+/*
+ If we get multiple cache operations before the operation which will
+ trigger the operation to happen then we need to make sure we do
+ the right thing.
+
+ Note: PVRSRV_CACHE_OP_INVALIDATE should never be passed into here
+*/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SetCacheOp)
+#endif
+static INLINE PVRSRV_CACHE_OP SetCacheOp(PVRSRV_CACHE_OP uiCurrent,
+ PVRSRV_CACHE_OP uiNew)
+{
+ PVRSRV_CACHE_OP uiRet;
+
+ uiRet = uiCurrent | uiNew;
+ return uiRet;
+}
+
+#endif /* _CACHE_EXTERNAL_H_ */
diff --git a/drivers/gpu/rogue/include/dbgdrvif_srv5.h b/drivers/gpu/rogue/include/dbgdrvif_srv5.h
new file mode 100644
index 000000000000..4f6135907bcd
--- /dev/null
+++ b/drivers/gpu/rogue/include/dbgdrvif_srv5.h
@@ -0,0 +1,264 @@
+/*************************************************************************/ /*!
+@File
+@Title Debug driver for Services 5
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Debug Driver Interface
+@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 _DBGDRVIF_SRV5_
+#define _DBGDRVIF_SRV5_
+
+#if defined(_MSC_VER)
+#pragma warning(disable:4200)
+#endif
+
+#if defined(__linux__)
+
+#define FILE_DEVICE_UNKNOWN 0
+#define METHOD_BUFFERED 0
+#define FILE_ANY_ACCESS 0
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) (Function)
+#define MAKEIOCTLINDEX(i) ((i) & 0xFFF)
+
+#else
+
+#include "ioctldef.h"
+
+#endif
+
+
+/*****************************************************************************
+ Stream mode stuff.
+*****************************************************************************/
+#define DEBUG_CAPMODE_FRAMED 0x00000001UL /* Default capture mode, set when streams created */
+#define DEBUG_CAPMODE_CONTINUOUS 0x00000002UL /* Only set in WDDM, streams created with it set to this mode */
+
+#define DEBUG_FLAGS_USE_NONPAGED_MEM 0x00000001UL /* Only set in WDDM */
+#define DEBUG_FLAGS_NO_BUF_EXPANDSION 0x00000002UL
+#define DEBUG_FLAGS_READONLY 0x00000008UL
+#define DEBUG_FLAGS_WRITEONLY 0x00000010UL
+#define DEBUG_FLAGS_CIRCULAR 0x00000020UL
+
+/*****************************************************************************
+ IOCTL values.
+*****************************************************************************/
+/* IOCTL values defined here so that the windows based OS layer of PDump
+ in the server can access the GetServiceTable method.
+ */
+#define DEBUG_SERVICE_IOCTL_BASE 0x800UL
+#define DEBUG_SERVICE_GETSERVICETABLE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETMARKER CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETMARKER CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WAITFOREVENT CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#if defined(__QNXNTO__)
+#define DEBUG_SERVICE_CREATESTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_MAX_API 8
+#else
+#define DEBUG_SERVICE_MAX_API 9
+#endif
+
+
+#if defined(_WIN32)
+/*****************************************************************************
+ Debug driver device name
+*****************************************************************************/
+#if defined (DBGDRV_MODULE_NAME)
+#define REGISTRY_PATH_TO_DEBUG_DRIVER \
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" DBGDRV_MODULE_NAME
+#define DBGDRV_NT_DEVICE_NAME L"\\Device\\" DBGDRV_MODULE_NAME
+#define DBGDRV_NT_SYMLINK L"\\DosDevices\\" DBGDRV_MODULE_NAME
+#else
+#error Debug driver name must be specified
+/*
+#define DBGDRV_NT_DEVICE_NAME L"\\Device\\VLDbgDrv"
+#define DBGDRV_NT_SYMLINK L"\\DosDevices\\VLDBGDRV"
+*/
+#endif
+
+/* symbolic link name */
+#define DBGDRV_WIN32_DEVICE_NAME "\\\\.\\VLDBGDRV"
+
+#define DBGDRV_WINCE_DEVICE_NAME L"DBD1:"
+#endif
+
+#ifdef __GNUC__
+#define DBG_ALIGN(n) __attribute__ ((aligned (n)))
+#else
+#define DBG_ALIGN(n)
+#endif
+
+/* A pointer type which is at least 64 bits wide. The fixed width ensures
+ * consistency in structures between 32 and 64-bit code.
+ * The UM code (be it 32 or 64 bit) can simply write to the native pointer type (pvPtr).
+ * 64-bit KM code must read ui32Ptr if in the case of a 32-bit client, otherwise it can
+ * just read pvPtr if the client is also 64-bit
+ *
+ * ui64Ptr ensures the union is 64-bits wide in a 32-bit client.
+ *
+ * The union is explicitly 64-bit aligned as it was found gcc on x32 only
+ * aligns it to 32-bit, as the ABI permits aligning 64-bit types to a 32-bit
+ * boundary.
+ */
+typedef union
+{
+ /* native pointer type for UM to write to */
+ IMG_VOID *pvPtr;
+ /* the pointer written by a 32-bit client */
+ IMG_UINT32 ui32Ptr;
+ /* force the union width */
+ IMG_UINT64 ui64Ptr;
+} DBG_WIDEPTR DBG_ALIGN(8);
+
+/* Helper macro for dbgdriv (KM) to get the pointer value from the WIDEPTR type,
+ * depending on whether the client is 32 or 64-bit.
+ *
+ * note: double cast is required to avoid
+ * 'cast to pointer from integer of different size' warning.
+ * this is solved by first casting to an integer type.
+ */
+
+#if defined(CONFIG_COMPAT)
+#define WIDEPTR_GET_PTR(p, bCompat) (bCompat ? \
+ (IMG_VOID *) (IMG_UINTPTR_T) (p).ui32Ptr : \
+ (p).pvPtr)
+#else
+#define WIDEPTR_GET_PTR(p, bCompat) (p).pvPtr
+#endif
+
+typedef enum _DBG_EVENT_
+{
+ DBG_EVENT_STREAM_DATA = 1
+} DBG_EVENT;
+
+
+/*****************************************************************************
+ In/Out Structures
+*****************************************************************************/
+#if defined(__QNXNTO__)
+typedef struct _DBG_IN_CREATESTREAM_
+{
+ union
+ {
+ IMG_CHAR *pszName;
+ IMG_UINT64 ui64Name;
+ } u;
+ IMG_UINT32 ui32Pages;
+ IMG_UINT32 ui32CapMode;
+ IMG_UINT32 ui32OutMode;
+}DBG_IN_CREATESTREAM, *PDBG_IN_CREATESTREAM;
+
+typedef struct _DBG_OUT_CREATESTREAM_
+{
+ IMG_HANDLE phInit;
+ IMG_HANDLE phMain;
+ IMG_HANDLE phDeinit;
+} DBG_OUT_CREATESTREAM, *PDBG_OUT_CREATESTREAM;
+#endif
+
+typedef struct _DBG_IN_FINDSTREAM_
+{
+ DBG_WIDEPTR pszName;
+ IMG_BOOL bResetStream;
+}DBG_IN_FINDSTREAM, *PDBG_IN_FINDSTREAM;
+
+#define DEBUG_READ_BUFID_MAIN 0
+#define DEBUG_READ_BUFID_INIT 1
+#define DEBUG_READ_BUFID_DEINIT 2
+
+typedef struct _DBG_IN_READ_
+{
+ DBG_WIDEPTR pui8OutBuffer;
+ IMG_SID hStream;
+ IMG_UINT32 ui32BufID;
+ IMG_UINT32 ui32OutBufferSize;
+} DBG_IN_READ, *PDBG_IN_READ;
+
+typedef struct _DBG_OUT_READ_
+{
+ IMG_UINT32 ui32DataRead;
+ IMG_UINT32 ui32SplitMarker;
+} DBG_OUT_READ, *PDBG_OUT_READ;
+
+typedef struct _DBG_IN_SETMARKER_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Marker;
+} DBG_IN_SETMARKER, *PDBG_IN_SETMARKER;
+
+/*
+ DBG STREAM abstract types
+*/
+
+typedef struct _DBG_STREAM_CONTROL_* PDBG_STREAM_CONTROL;
+typedef struct _DBG_STREAM_* PDBG_STREAM;
+
+/*
+ Lookup identifiers for the GetState method in the KM service table.
+ */
+#define DBG_GET_STATE_FLAG_IS_READONLY 0x03
+
+
+/*****************************************************************************
+ Kernel mode service table
+*****************************************************************************/
+typedef struct _DBGKM_SERVICE_TABLE_
+{
+ IMG_UINT32 ui32Size;
+ IMG_BOOL (IMG_CALLCONV *pfnCreateStream) (IMG_CHAR * pszName,IMG_UINT32 ui32Flags,IMG_UINT32 ui32Pages, IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit);
+ IMG_VOID (IMG_CALLCONV *pfnDestroyStream) (IMG_HANDLE hInit, IMG_HANDLE hMain, IMG_HANDLE hDeinit);
+ IMG_UINT32 (IMG_CALLCONV *pfnDBGDrivWrite2) (PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize);
+ IMG_VOID (IMG_CALLCONV *pfnSetMarker) (PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+ IMG_VOID (IMG_CALLCONV *pfnWaitForEvent) (DBG_EVENT eEvent);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetCtrlState) (PDBG_STREAM psStream, IMG_UINT32 ui32StateID);
+ IMG_VOID (IMG_CALLCONV *pfnSetFrame) (IMG_UINT32 ui32Frame);
+} DBGKM_SERVICE_TABLE, *PDBGKM_SERVICE_TABLE;
+
+#if defined(_MSC_VER)
+#pragma warning(default:4200)
+#endif
+
+#endif
+
+/*****************************************************************************
+ End of file
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/include/dc_external.h b/drivers/gpu/rogue/include/dc_external.h
new file mode 100644
index 000000000000..dd6422508981
--- /dev/null
+++ b/drivers/gpu/rogue/include/dc_external.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@File
+@Title Device class external
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines DC specific structures which are externally visible
+ (i.e. visible to clients of services), but are also required
+ within services.
+@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 _DC_EXTERNAL_H_
+#define _DC_EXTERNAL_H_
+
+#include "img_types.h"
+
+#define DC_NAME_SIZE 50
+typedef struct _DC_DISPLAY_INFO_
+{
+ IMG_CHAR szDisplayName[DC_NAME_SIZE];
+ IMG_UINT32 ui32MinDisplayPeriod;
+ IMG_UINT32 ui32MaxDisplayPeriod;
+ IMG_UINT32 ui32MaxPipes;
+ IMG_BOOL bUnlatchedSupported;
+} DC_DISPLAY_INFO;
+
+typedef struct _DC_BUFFER_IMPORT_INFO_
+{
+ IMG_UINT32 ePixFormat;
+ IMG_UINT32 ui32BPP;
+ IMG_UINT32 ui32Width[3];
+ IMG_UINT32 ui32Height[3];
+ IMG_UINT32 ui32ByteStride[3];
+ IMG_UINT32 ui32PrivData[3];
+} DC_BUFFER_IMPORT_INFO;
+
+#endif /* _DC_EXTERNAL_H_ */
diff --git a/drivers/gpu/rogue/include/devicemem_typedefs.h b/drivers/gpu/rogue/include/devicemem_typedefs.h
new file mode 100644
index 000000000000..cac0d7f0972c
--- /dev/null
+++ b/drivers/gpu/rogue/include/devicemem_typedefs.h
@@ -0,0 +1,104 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Client side part of device memory management -- this file
+ is forked from new_devmem_allocation.h as this one has to
+ reside in the top level include so that client code is able
+ to make use of the typedefs.
+@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 DEVICEMEM_TYPEDEFS_H
+#define DEVICEMEM_TYPEDEFS_H
+
+#include "img_types.h"
+#include "pvrsrv_memallocflags.h"
+
+typedef struct _DEVMEM_CONTEXT_ DEVMEM_CONTEXT; /*!< Convenience typedef for struct _DEVMEM_CONTEXT_ */
+typedef struct _DEVMEM_HEAP_ DEVMEM_HEAP; /*!< Convenience typedef for struct _DEVMEM_HEAP_ */
+typedef struct _DEVMEM_MEMDESC_ DEVMEM_MEMDESC; /*!< Convenience typedef for struct _DEVMEM_MEMDESC_ */
+typedef struct _DEVMEM_PAGELIST_ DEVMEM_PAGELIST; /*!< Convenience typedef for struct _DEVMEM_PAGELIST_ */
+typedef PVRSRV_MEMALLOCFLAGS_T DEVMEM_FLAGS_T; /*!< Conveneince typedef for PVRSRV_MEMALLOCFLAGS_T */
+
+typedef IMG_HANDLE /* */ DEVMEM_EXPORTHANDLE; /*!< Typedef for DeviceMem Export Handle */
+typedef IMG_UINT64 DEVMEM_EXPORTKEY; /*!< Typedef for DeviceMem Export Key */
+typedef IMG_DEVMEM_SIZE_T DEVMEM_SIZE_T; /*!< Typedef for DeviceMem SIZE_T */
+typedef IMG_DEVMEM_LOG2ALIGN_T DEVMEM_LOG2ALIGN_T; /*!< Typdef for DeviceMem LOG2 Alignment */
+
+/*! calling code needs all the info in this struct, to be able to pass it around */
+typedef struct
+{
+ /*! A handle to the PMR. Should be a SID.
+*/
+ IMG_HANDLE hPMRExportHandle;
+ /*! The "key" to prove we have authorization to use this PMR */
+ IMG_UINT64 uiPMRExportPassword;
+ /*! Size and alignment properties for this PMR. Note, these
+ numbers are not trusted in kernel, but we need to cache them
+ client-side in order to allocate from the VM arena. The kernel
+ will know the actual alignment and size of the PMR and thus
+ would prevent client code from breaching security here. Ditto
+ for physmem granularity (aka page size) if this is different
+ from alignment */
+ IMG_DEVMEM_SIZE_T uiSize;
+ /*! We call this "contiguity guarantee" to be more precise than
+ calling it "alignment" or "page size", terms which may seem
+ similar but have different emphasis. The number reported here
+ is the minimum contiguity guarantee from the creator of the
+ PMR. Now, there is no requirement to allocate that coarsely
+ from the RA. The alignment given to the RA simply needs to be
+ at least as coarse as the device page size for the heap we
+ ultimately intend to map into. What is important is that the
+ device MMU data page size is not greater than the minimum
+ contiguity guarantee from the PMR. This value is reported to
+ the client in order that it can choose to make early checks and
+ perhaps decide which heap (in a variable page size scenario) it
+ would be safe to map this PMR into. For convenience, the
+ client may choose to use this argument as the alignment of the
+ virtual range he chooses to allocate, but this is _not_
+ necessary and in many cases would be able to get away with a
+ finer alignment, should the heap into which this PMR will be
+ mapped support it. */
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2ContiguityGuarantee;
+} DEVMEM_EXPORTCOOKIE;
+
+typedef IMG_HANDLE DEVMEM_SERVER_EXPORTCOOKIE; /*!< typedef for DeviceMem Server Export Cookie */
+
+#endif /* #ifndef SRVCLIENT_NEW_DEVMEM_ALLOCATION_TYPEDEFS_H */
+
diff --git a/drivers/gpu/rogue/include/fbc_types.h b/drivers/gpu/rogue/include/fbc_types.h
new file mode 100644
index 000000000000..28be3474c801
--- /dev/null
+++ b/drivers/gpu/rogue/include/fbc_types.h
@@ -0,0 +1,64 @@
+/*************************************************************************/ /*!
+@File
+@Title Frame buffer compression definitions
+@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 _FBC_TYPES_H_
+#define _FBC_TYPES_H_
+
+/**
+ * Types of framebuffer compression available.
+ */
+typedef enum _FB_COMPRESSION_
+{
+ FB_COMPRESSION_NONE,
+ FB_COMPRESSION_DIRECT_8x8,
+ FB_COMPRESSION_DIRECT_16x4,
+ FB_COMPRESSION_DIRECT_32x2,
+ FB_COMPRESSION_INDIRECT_8x8,
+ FB_COMPRESSION_INDIRECT_16x4,
+ FB_COMPRESSION_INDIRECT_4TILE_8x8,
+ FB_COMPRESSION_INDIRECT_4TILE_16x4
+} FB_COMPRESSION;
+
+#endif /* _FBC_TYPES_H_ */
+
+/* EOF */
+
diff --git a/drivers/gpu/rogue/include/img_defs.h b/drivers/gpu/rogue/include/img_defs.h
new file mode 100644
index 000000000000..da4e6738b09c
--- /dev/null
+++ b/drivers/gpu/rogue/include/img_defs.h
@@ -0,0 +1,231 @@
+/*************************************************************************/ /*!
+@File
+@Title Common header containing type definitions for portability
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Contains variable and structure definitions. Any platform
+ specific types should be defined in this file.
+@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 (__IMG_DEFS_H__)
+#define __IMG_DEFS_H__
+
+#include <stddef.h>
+
+#include "img_types.h"
+
+#if defined (NO_INLINE_FUNCS)
+ #define INLINE
+ #define FORCE_INLINE
+#else
+#if defined (__cplusplus)
+ #define INLINE inline
+ #define FORCE_INLINE inline
+#else
+#if !defined(INLINE)
+ #define INLINE __inline
+#endif
+#if defined(UNDER_WDDM) && defined(_X86_)
+ #define FORCE_INLINE __forceinline
+#else
+ #define FORCE_INLINE static __inline
+#endif
+#endif
+#endif
+
+
+/* Use this in any file, or use attributes under GCC - see below */
+#ifndef PVR_UNREFERENCED_PARAMETER
+#define PVR_UNREFERENCED_PARAMETER(param) ((void)(param))
+#endif
+
+/*! Macro used to check structure size and alignment at compile time. */
+#define BLD_ASSERT(expr, file) _impl_ASSERT_LINE(expr,__LINE__,file)
+#define _impl_JOIN(a,b) a##b
+#define _impl_ASSERT_LINE(expr, line, file) \
+ typedef char _impl_JOIN(build_assertion_failed_##file##_,line)[2*!!(expr)-1];
+
+/*! Macro to calculate the n-byte aligned value from that supplied rounding up.
+ * n must be a power of two. */
+#define PVR_ALIGN(_x, _n) (((_x)+((_n)-1)) & ~((_n)-1))
+
+
+/* The best way to supress unused parameter warnings using GCC is to use a
+ * variable attribute. Place the unref__ between the type and name of an
+ * unused parameter in a function parameter list, eg `int unref__ var'. This
+ * should only be used in GCC build environments, for example, in files that
+ * compile only on Linux. Other files should use UNREFERENCED_PARAMETER */
+#ifdef __GNUC__
+#define unref__ __attribute__ ((unused))
+#else
+#define unref__
+#endif
+
+#if defined(_WIN32)
+#if defined(UNDER_CE)
+ #include "windowsce_img_defs.h"
+#else
+ #define IMG_CALLCONV __stdcall
+ #define IMG_INTERNAL
+ #define IMG_EXPORT __declspec(dllexport)
+ #define IMG_RESTRICT __restrict
+ #define C_CALLCONV __cdecl
+
+ /* IMG_IMPORT is defined as IMG_EXPORT so that headers and implementations match.
+ * Some compilers require the header to be declared IMPORT, while the implementation is declared EXPORT
+ */
+ #define IMG_IMPORT IMG_EXPORT
+
+#if defined(UNDER_WDDM)
+ #ifndef _INC_STDLIB
+ #if defined (UNDER_MSBUILD)
+ _CRTIMP __declspec(noreturn) void __cdecl abort(void);
+ #else
+ _CRTIMP void __cdecl abort(void);
+ #endif
+ #endif
+ #if defined(EXIT_ON_ABORT)
+ #define IMG_ABORT() exit(1);
+ #else
+ #define IMG_ABORT() abort();
+ #endif
+// #define IMG_ABORT() img_abort()
+#endif /* UNDER_WDDM */
+#endif /* UNDER_CE */
+#else
+ #if defined(LINUX) || defined(__METAG) || defined(__QNXNTO__)
+
+ #define IMG_CALLCONV
+ #define C_CALLCONV
+ #if defined(__linux__) || defined(__QNXNTO__)
+ #define IMG_INTERNAL __attribute__((visibility("hidden")))
+ #else
+ #define IMG_INTERNAL
+ #endif
+ #define IMG_EXPORT __attribute__((visibility("default")))
+ #define IMG_IMPORT
+ #define IMG_RESTRICT __restrict__
+
+ #else
+ #error("define an OS")
+ #endif
+#endif
+
+// Use default definition if not overridden
+#ifndef IMG_ABORT
+ #if defined(EXIT_ON_ABORT)
+ #define IMG_ABORT() exit(1)
+ #else
+#if defined UNDER_CE
+ /* WinCE / WinEC does not have an abort() function */
+ #define IMG_ABORT() exit(1)
+#else
+ #define IMG_ABORT() abort()
+#endif
+ #endif
+#endif
+
+#if defined(__GNUC__)
+#define IMG_FORMAT_PRINTF(x,y) __attribute__((format(printf,x,y)))
+#else
+#define IMG_FORMAT_PRINTF(x,y)
+#endif
+
+#if defined(__GNUC__)
+#define IMG_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+#define IMG_WARN_UNUSED_RESULT
+#endif
+
+#if defined(_MSC_VER) || defined(CC_ARM)
+ #define IMG_NORETURN __declspec(noreturn)
+#else
+ #if defined(__GNUC__)
+ #define IMG_NORETURN __attribute__((noreturn))
+ #else
+ #define IMG_NORETURN
+ #endif
+#endif
+
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+/* Get a structures address from the address of a member */
+#define IMG_CONTAINER_OF(ptr, type, member) \
+ (type *) ((IMG_UINT8 *) (ptr) - offsetof(type, member))
+
+/* The number of elements in a fixed-sized array */
+#define IMG_ARR_NUM_ELEMS(ARR) \
+ (sizeof(ARR) / sizeof((ARR)[0]))
+
+/* To guarantee that __func__ can be used, define it as a macro here if it
+ isn't already provided by the compiler. */
+#if defined(_MSC_VER)
+#define __func__ __FUNCTION__
+#endif
+
+#if defined(__cplusplus)
+/* C++ Specific:
+ * Disallow use of copy and assignment operator within a class.
+ * Should be placed under private. */
+#define IMG_DISALLOW_COPY_AND_ASSIGN(C) \
+ C(const C&); \
+ void operator=(const C&)
+#endif
+
+#if defined(SUPPORT_PVR_VALGRIND)
+ #if !defined(__METAG)
+ #include "/usr/include/valgrind/memcheck.h"
+
+ #define VALGRIND_HEADER_PRESENT
+
+ #define VG_MARK_INITIALIZED(pvData,ui32Size) VALGRIND_MAKE_MEM_DEFINED(pvData,ui32Size)
+ #else
+ #define VG_MARK_INITIALIZED(pvData,ui32Size) do { } while(0)
+ #endif
+#else
+
+ #define VG_MARK_INITIALIZED(pvData,ui32Size) do { } while(0)
+#endif
+
+
+#endif /* #if !defined (__IMG_DEFS_H__) */
+/*****************************************************************************
+ End of file (IMG_DEFS.H)
+*****************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/img_types.h b/drivers/gpu/rogue/include/img_types.h
new file mode 100644
index 000000000000..b882f4623c81
--- /dev/null
+++ b/drivers/gpu/rogue/include/img_types.h
@@ -0,0 +1,290 @@
+/*************************************************************************/ /*!
+@File
+@Title Global types for use by IMG APIs
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines type aliases for use by IMG APIs.
+@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_TYPES_H__
+#define __IMG_TYPES_H__
+#if defined (__cplusplus)
+extern "C" {
+#endif
+/* number of bits in the units returned by sizeof */
+#define IMG_CHAR_BIT 8
+
+/* define all address space bit depths: */
+/* CPU virtual address space defaults to 32bits */
+#if !defined(IMG_ADDRSPACE_CPUVADDR_BITS)
+#define IMG_ADDRSPACE_CPUVADDR_BITS 32
+#endif
+
+typedef unsigned int IMG_UINT, *IMG_PUINT;
+typedef signed int IMG_INT, *IMG_PINT;
+
+typedef unsigned char IMG_UINT8, *IMG_PUINT8;
+typedef unsigned char IMG_BYTE, *IMG_PBYTE;
+typedef signed char IMG_INT8, *IMG_PINT8;
+typedef char IMG_CHAR, *IMG_PCHAR;
+typedef IMG_CHAR const *IMG_PCCHAR;
+
+typedef unsigned short IMG_UINT16, *IMG_PUINT16;
+typedef signed short IMG_INT16, *IMG_PINT16;
+typedef unsigned int IMG_UINT32, *IMG_PUINT32;
+typedef signed int IMG_INT32, *IMG_PINT32;
+#if !defined(IMG_UINT32_MAX)
+ #define IMG_UINT32_MAX 0xFFFFFFFFUL
+#endif
+#if !defined(IMG_UINT16_MAX)
+ #define IMG_UINT16_MAX 0xFFFFU
+#endif
+
+typedef IMG_UINT16 const* IMG_PCUINT16;
+typedef IMG_INT16 const* IMG_PCINT16;
+typedef IMG_UINT32 const* IMG_PCUINT32;
+typedef IMG_INT32 const* IMG_PCINT32;
+
+#if defined(_WIN32)
+
+typedef unsigned __int64 IMG_UINT64, *IMG_PUINT64;
+typedef __int64 IMG_INT64, *IMG_PINT64;
+#define IMG_INT64_C(c) c ## LL
+#define IMG_UINT64_C(c) c ## ULL
+#if defined(_MSC_VER)
+#define strtoll _strtoi64
+#endif
+
+#else
+ #if defined(LINUX) || defined(__METAG) || defined(__QNXNTO__)
+ typedef unsigned long long IMG_UINT64, *IMG_PUINT64;
+ typedef long long IMG_INT64, *IMG_PINT64;
+ #define IMG_INT64_C(c) c ## LL
+ #define IMG_UINT64_C(c) c ## ULL
+ #else
+ #error("define an OS")
+ #endif
+#endif
+#if !defined(IMG_UINT64_MAX)
+ #define IMG_UINT64_MAX 0xFFFFFFFFFFFFFFFFULL
+#endif
+
+#if !(defined(LINUX) && defined (__KERNEL__))
+/* Linux kernel mode does not use floating point */
+typedef float IMG_FLOAT, *IMG_PFLOAT;
+typedef double IMG_DOUBLE, *IMG_PDOUBLE;
+
+typedef union _IMG_UINT32_FLOAT_
+{
+ IMG_UINT32 ui32;
+ IMG_FLOAT f;
+} IMG_UINT32_FLOAT;
+
+#endif
+
+typedef int IMG_SECURE_TYPE;
+
+typedef enum tag_img_bool
+{
+ IMG_FALSE = 0,
+ IMG_TRUE = 1,
+ IMG_FORCE_ALIGN = 0x7FFFFFFF
+} IMG_BOOL, *IMG_PBOOL;
+typedef IMG_BOOL const* IMG_PCBOOL;
+
+typedef void IMG_VOID, *IMG_PVOID;
+typedef IMG_VOID const* IMG_PCVOID;
+
+/* Figure out which headers to include to get uintptr_t. */
+#if !defined(_MSC_VER) && !defined(__KERNEL__)
+/* MSVC before VS2010 doesn't have <stdint.h>, but it has uintptr_t in
+ <stddef.h>. */
+#include <stdint.h>
+#endif
+#if defined(__QNXNTO__)
+#include <stdint.h>
+#endif
+#if defined(LINUX) && defined (__KERNEL__)
+#include <linux/types.h>
+#endif
+#include <stddef.h>
+
+typedef uintptr_t IMG_UINTPTR_T;
+typedef size_t IMG_SIZE_T;
+
+#define IMG_SIZE_T_MAX ((IMG_SIZE_T) -1)
+
+#if defined(_MSC_VER)
+#define IMG_SIZE_FMTSPEC "%Iu"
+#define IMG_SIZE_FMTSPECX "%Ix"
+#else
+#define IMG_SIZE_FMTSPEC "%zu"
+#define IMG_SIZE_FMTSPECX "%zx"
+#endif
+
+typedef IMG_PVOID IMG_HANDLE;
+
+#define IMG_NULL NULL
+
+/* services/stream ID */
+typedef IMG_UINT64 IMG_SID;
+
+/* Process IDs */
+typedef IMG_UINT32 IMG_PID;
+
+
+/*
+ * Address types.
+ * All types used to refer to a block of memory are wrapped in structures
+ * to enforce some degree of type safety, i.e. a IMG_DEV_VIRTADDR cannot
+ * be assigned to a variable of type IMG_DEV_PHYADDR because they are not the
+ * same thing.
+ *
+ * There is an assumption that the system contains at most one non-cpu mmu,
+ * and a memory block is only mapped by the MMU once.
+ *
+ * Different devices could have offset views of the physical address space.
+ *
+ */
+
+
+/*
+ *
+ * +------------+ +------------+ +------------+ +------------+
+ * | CPU | | DEV | | DEV | | DEV |
+ * +------------+ +------------+ +------------+ +------------+
+ * | | | |
+ * | PVOID |IMG_DEV_VIRTADDR |IMG_DEV_VIRTADDR |
+ * | \-------------------/ |
+ * | | |
+ * +------------+ +------------+ |
+ * | MMU | | MMU | |
+ * +------------+ +------------+ |
+ * | | |
+ * | | |
+ * | | |
+ * +--------+ +---------+ +--------+
+ * | Offset | | (Offset)| | Offset |
+ * +--------+ +---------+ +--------+
+ * | | IMG_DEV_PHYADDR |
+ * | | |
+ * | | IMG_DEV_PHYADDR |
+ * +---------------------------------------------------------------------+
+ * | System Address bus |
+ * +---------------------------------------------------------------------+
+ *
+ */
+
+typedef IMG_PVOID IMG_CPU_VIRTADDR;
+
+/* device virtual address */
+typedef struct _IMG_DEV_VIRTADDR
+{
+ IMG_UINT64 uiAddr;
+#define IMG_CAST_TO_DEVVADDR_UINT(var) (IMG_UINT64)(var)
+
+} IMG_DEV_VIRTADDR;
+
+typedef IMG_UINT64 IMG_DEVMEM_SIZE_T;
+typedef IMG_UINT64 IMG_DEVMEM_ALIGN_T;
+typedef IMG_UINT64 IMG_DEVMEM_OFFSET_T;
+typedef IMG_UINT32 IMG_DEVMEM_LOG2ALIGN_T;
+
+#define IMG_DEV_VIRTADDR_FMTSPEC "0x%010llX"
+#define IMG_DEVMEM_SIZE_FMTSPEC "0x%010llX"
+#define IMG_DEVMEM_ALIGN_FMTSPEC "0x%010llX"
+#define IMG_DEVMEM_OFFSET_FMTSPEC "0x%010llX"
+
+/* cpu physical address */
+typedef struct _IMG_CPU_PHYADDR
+{
+#if defined(UNDER_WDDM)
+ IMG_UINTPTR_T uiAddr;
+#define IMG_CAST_TO_CPUPHYADDR_UINT(var) (IMG_UINTPTR_T)(var)
+#else
+ IMG_UINT64 uiAddr;
+#define IMG_CAST_TO_CPUPHYADDR_UINT(var) (IMG_UINT64)(var)
+#endif
+} IMG_CPU_PHYADDR;
+
+/* device physical address */
+typedef struct _IMG_DEV_PHYADDR
+{
+ IMG_UINT64 uiAddr;
+} IMG_DEV_PHYADDR;
+
+/* system physical address */
+typedef struct _IMG_SYS_PHYADDR
+{
+#if defined(UNDER_WDDM)
+ IMG_UINTPTR_T uiAddr;
+#else
+ IMG_UINT64 uiAddr;
+#endif
+} IMG_SYS_PHYADDR;
+
+/*
+ rectangle structure
+*/
+typedef struct _IMG_RECT_
+{
+ IMG_INT32 x0;
+ IMG_INT32 y0;
+ IMG_INT32 x1;
+ IMG_INT32 y1;
+}IMG_RECT;
+
+typedef struct _IMG_RECT_16_
+{
+ IMG_INT16 x0;
+ IMG_INT16 y0;
+ IMG_INT16 x1;
+ IMG_INT16 y1;
+}IMG_RECT_16;
+
+#if defined (__cplusplus)
+}
+#endif
+
+#include "img_defs.h"
+
+#endif /* __IMG_TYPES_H__ */
+/******************************************************************************
+ End of file (img_types.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/imgpixfmts_km.h b/drivers/gpu/rogue/include/imgpixfmts_km.h
new file mode 100644
index 000000000000..ab683e47505a
--- /dev/null
+++ b/drivers/gpu/rogue/include/imgpixfmts_km.h
@@ -0,0 +1,78 @@
+/*************************************************************************/ /*!
+@File
+@Title Pixel formats
+@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.
+*/ /**************************************************************************/
+
+/****************************************************************************
+ **
+ ** WARNING: This file is autogenerated - DO NOT EDIT.
+ **
+ ** See fmts_systable.txt to add new formats.
+ ****************************************************************************/
+
+#include "imgyuv.h"
+#if !defined(_IMGPIXFMTS_KM_H_)
+#define _IMGPIXFMTS_KM_H_
+
+typedef enum _IMG_PIXFMT_
+{
+ IMG_PIXFMT_UNKNOWN = 0,
+ IMG_PIXFMT_R8G8B8A8_UNORM = 30,
+ IMG_PIXFMT_R8G8B8X8_UNORM = 35,
+ IMG_PIXFMT_B5G6R5_UNORM = 81,
+ IMG_PIXFMT_B5G5R5A1_UNORM = 82,
+ IMG_PIXFMT_B5G5R5X1_UNORM = 83,
+ IMG_PIXFMT_B8G8R8A8_UNORM = 84,
+ IMG_PIXFMT_B8G8R8X8_UNORM = 85,
+ IMG_PIXFMT_UYVY = 162,
+ IMG_PIXFMT_VYUY = 163,
+ IMG_PIXFMT_YUYV = 164,
+ IMG_PIXFMT_YVYU = 165,
+ IMG_PIXFMT_YVU420_2PLANE = 166,
+ IMG_PIXFMT_YUV420_2PLANE = 167,
+ IMG_PIXFMT_YVU420_2PLANE_MACRO_BLOCK = 168,
+ IMG_PIXFMT_YUV420_3PLANE = 169,
+ IMG_PIXFMT_YVU420_3PLANE = 170,
+ IMG_PIXFMT_V8U8Y8A8 = 175,
+} IMG_PIXFMT;
+
+
+
+#endif /* _IMGPIXFMTS_KM_H_ */
diff --git a/drivers/gpu/rogue/include/imgyuv.h b/drivers/gpu/rogue/include/imgyuv.h
new file mode 100644
index 000000000000..9359c355a66f
--- /dev/null
+++ b/drivers/gpu/rogue/include/imgyuv.h
@@ -0,0 +1,63 @@
+/*************************************************************************/ /*!
+@File
+@Title YUV 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.
+*/ /**************************************************************************/
+
+#if !defined(_IMGYUV_H_)
+#define _IMGYUV_H_
+
+typedef enum
+{
+ IMG_COLORSPACE_BT601_CONFORMANT_RANGE = 1,
+ IMG_COLORSPACE_BT601_FULL_RANGE = 2,
+ IMG_COLORSPACE_BT709_CONFORMANT_RANGE = 3,
+ IMG_COLORSPACE_BT709_FULL_RANGE = 4
+}IMG_YUV_COLORSPACE;
+
+typedef enum
+{
+ IMG_CHROMA_INTERP_ZERO = 1,
+ IMG_CHROMA_INTERP_QUARTER = 2,
+ IMG_CHROMA_INTERP_HALF = 3,
+ IMG_CHROMA_INTERP_THREEQUARTERS = 4
+}IMG_YUV_CHROMA_INTERP;
+
+
+#endif /* _IMGYUV_H_ */
diff --git a/drivers/gpu/rogue/include/lock_types.h b/drivers/gpu/rogue/include/lock_types.h
new file mode 100644
index 000000000000..dd8284554c03
--- /dev/null
+++ b/drivers/gpu/rogue/include/lock_types.h
@@ -0,0 +1,75 @@
+/*************************************************************************/ /*!
+@File lock_types.h
+@Title Locking types
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Locking specific enums, defines and structures
+@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 _LOCK_TYPES_H_
+#define _LOCK_TYPES_H_
+
+/* In Linux kernel mode we are using the kernel mutex implementation directly
+ * with macros. This allows us to use the kernel lockdep feature for lock
+ * debugging. */
+#if defined(LINUX) && defined(__KERNEL__)
+
+#include <linux/mutex.h>
+/* The mutex is defined as a pointer to be compatible with the other code. This
+ * isn't ideal and usually you wouldn't do that in kernel code. */
+typedef struct mutex *POS_LOCK;
+
+#else /* defined(LINUX) && defined(__KERNEL__) */
+
+typedef struct _OS_LOCK_ *POS_LOCK;
+
+#endif /* defined(LINUX) && defined(__KERNEL__) */
+
+typedef enum
+{
+ LOCK_TYPE_NONE = 0x00,
+
+ LOCK_TYPE_MASK = 0x0F,
+ LOCK_TYPE_PASSIVE = 0x01, /* Passive level lock e.g. mutex, system may promote to dispatch */
+ LOCK_TYPE_DISPATCH = 0x02, /* Dispatch level lock e.g. spin lock, may be used in ISR/MISR */
+
+ LOCK_TYPE_INSIST_FLAG = 0x80, /* When set caller can guarantee lock not used in ISR/MISR */
+ LOCK_TYPE_PASSIVE_ONLY = LOCK_TYPE_INSIST_FLAG | LOCK_TYPE_PASSIVE
+
+} LOCK_TYPE;
+#endif /* _LOCK_TYPES_H_ */
diff --git a/drivers/gpu/rogue/include/pdumpdefs.h b/drivers/gpu/rogue/include/pdumpdefs.h
new file mode 100644
index 000000000000..568f6f07f366
--- /dev/null
+++ b/drivers/gpu/rogue/include/pdumpdefs.h
@@ -0,0 +1,201 @@
+/*************************************************************************/ /*!
+@File
+@Title PDUMP definitions header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description PDUMP definitions header
+@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 (__PDUMPDEFS_H__)
+#define __PDUMPDEFS_H__
+
+/*! PDump Pixel Format Enumeration */
+typedef enum _PDUMP_PIXEL_FORMAT_
+{
+ PVRSRV_PDUMP_PIXEL_FORMAT_UNSUPPORTED = 0,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB8 = 1,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB332 = 2,
+ PVRSRV_PDUMP_PIXEL_FORMAT_KRGB555 = 3,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB565 = 4,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB4444 = 5,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB1555 = 6,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB888 = 7,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8888 = 8,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV8 = 9,
+// PVRSRV_PDUMP_PIXEL_FORMAT_AYUV4444 = 10,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VY0UY1_8888 = 11,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UY0VY1_8888 = 12,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0UY1V_8888 = 13,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0VY1U_8888 = 14,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV888 = 15,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UYVY10101010 = 16,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VYAUYA8888 = 17,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV8888 = 18,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV2101010 = 19,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV101010 = 20,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y8 = 21,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_IMC2 = 22,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV12 = 23,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL8 = 24,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL12 = 25,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV8 = 26,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV8 = 27,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y10 = 28,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV10 = 29,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV10 = 30,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ABGR8888 = 31,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGRA8888 = 32,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8332 = 33,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB555 = 34,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F16 = 35,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F32 = 36,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L16 = 37,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L32 = 38,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGBA8888 = 39,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ABGR4444 = 40,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGBA4444 = 41,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGRA4444 = 42,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ABGR1555 = 43,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGBA5551 = 44,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGRA5551 = 45,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGR565 = 46,
+ PVRSRV_PDUMP_PIXEL_FORMAT_A8 = 47,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F16F16F16F16 = 49,
+ PVRSRV_PDUMP_PIXEL_FORMAT_A4 = 50,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB2101010 = 51,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RSGSBS888 = 52,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F32F32F32F32 = 53,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F16F16 = 54,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F32F32 = 55,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F16F16F16 = 56,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F32F32F32 = 57,
+ PVRSRV_PDUMP_PIXEL_FORMAT_U8 = 58,
+ PVRSRV_PDUMP_PIXEL_FORMAT_U8U8 = 59,
+ PVRSRV_PDUMP_PIXEL_FORMAT_U16 = 60,
+ PVRSRV_PDUMP_PIXEL_FORMAT_U16U16 = 61,
+ PVRSRV_PDUMP_PIXEL_FORMAT_U16U16U16U16 = 62,
+ PVRSRV_PDUMP_PIXEL_FORMAT_U32 = 63,
+ PVRSRV_PDUMP_PIXEL_FORMAT_U32U32 = 64,
+ PVRSRV_PDUMP_PIXEL_FORMAT_U32U32U32U32 = 65,
+
+ PVRSRV_PDUMP_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PDUMP_PIXEL_FORMAT;
+
+/*! PDump addrmode */
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT 0
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_MASK 0x000000FF
+
+#define PVRSRV_PDUMP_ADDRMODE_STRIDESENSE_SHIFT 8
+#define PVRSRV_PDUMP_ADDRMODE_STRIDESENSE_NEGATIVE (1 << PVRSRV_PDUMP_ADDRMODE_STRIDESENSE_SHIFT)
+
+#define PVRSRV_PDUMP_ADDRMODE_BIFTILE_MODE_SHIFT 12
+#define PVRSRV_PDUMP_ADDRMODE_BIFTILE_MODE_MASK 0x000FF000
+
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_SHIFT 20
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_MASK 0x00F00000
+
+#define PVRSRV_PDUMP_ADDRMODE_FBCDECOR_SHIFT 24
+
+#define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT 28
+#define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_MASK 0xF0000000
+
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_STRIDE (0 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_BIFTILE_STRIDE1 (1 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_BIFTILE_STRIDE2 (2 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_BIFTILE_STRIDE3 (3 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_BIFTILE_STRIDE4 (4 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_BIFTILE_STRIDE5 (5 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_BIFTILE_STRIDE6 (6 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_BIFTILE_STRIDE7 (7 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_TWIDDLED (9 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_PAGETILED (11 << PVRSRV_PDUMP_ADDRMODE_MEMFORMAT_SHIFT)
+
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_NONE (0 << PVRSRV_PDUMP_ADDRMODE_FBCMODE_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_8X8_DIRECT (1 << PVRSRV_PDUMP_ADDRMODE_FBCMODE_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_16X4_DIRECT (2 << PVRSRV_PDUMP_ADDRMODE_FBCMODE_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_32X2_DIRECT (3 << PVRSRV_PDUMP_ADDRMODE_FBCMODE_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_8X8_INDIRECT (4 << PVRSRV_PDUMP_ADDRMODE_FBCMODE_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_16X4_INDIRECT (5 << PVRSRV_PDUMP_ADDRMODE_FBCMODE_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_8X8_INDIRECT_4TILE (6 << PVRSRV_PDUMP_ADDRMODE_FBCMODE_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCMODE_16X4_INDIRECT_4TILE (7 << PVRSRV_PDUMP_ADDRMODE_FBCMODE_SHIFT)
+
+#define PVRSRV_PDUMP_ADDRMODE_FBC_DECOR (1 << PVRSRV_PDUMP_ADDRMODE_FBCDECOR_SHIFT)
+
+#define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_BASE (1 << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_ENHANCED (2 << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V2 (3 << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
+
+/*! PDump Poll Operator */
+typedef enum _PDUMP_POLL_OPERATOR
+{
+ PDUMP_POLL_OPERATOR_EQUAL = 0,
+ PDUMP_POLL_OPERATOR_LESS = 1,
+ PDUMP_POLL_OPERATOR_LESSEQUAL = 2,
+ PDUMP_POLL_OPERATOR_GREATER = 3,
+ PDUMP_POLL_OPERATOR_GREATEREQUAL = 4,
+ PDUMP_POLL_OPERATOR_NOTEQUAL = 5,
+} PDUMP_POLL_OPERATOR;
+
+
+#define PVRSRV_PDUMP_MAX_FILENAME_SIZE 75 /*!< Max length of a pdump log file name */
+#define PVRSRV_PDUMP_MAX_COMMENT_SIZE 350 /*!< Max length of a pdump comment */
+
+/*!
+ PDump MMU type
+ (Maps to values listed in "PowerVR Tools.Pdump2 Script Functions.doc" Sec 2.13)
+*/
+typedef enum
+{
+ PDUMP_MMU_TYPE_4KPAGE_32BIT_STDTILE = 1,
+ PDUMP_MMU_TYPE_VARPAGE_32BIT_STDTILE = 2,
+ PDUMP_MMU_TYPE_4KPAGE_36BIT_EXTTILE = 3,
+ PDUMP_MMU_TYPE_4KPAGE_32BIT_EXTTILE = 4,
+ PDUMP_MMU_TYPE_4KPAGE_36BIT_STDTILE = 5,
+ PDUMP_MMU_TYPE_VARPAGE_40BIT = 6,
+ PDUMP_MMU_TYPE_VIDEO_40BIT_STDTILE = 7,
+ PDUMP_MMU_TYPE_VIDEO_40BIT_EXTTILE = 8,
+ PDUMP_MMU_TYPE_LAST
+} PDUMP_MMU_TYPE;
+
+#endif /* __PDUMPDEFS_H__ */
+
+/*****************************************************************************
+ End of file (pdumpdefs.h)
+*****************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/pvr_debug.h b/drivers/gpu/rogue/include/pvr_debug.h
new file mode 100755
index 000000000000..3b45f52b64a4
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvr_debug.h
@@ -0,0 +1,475 @@
+/*************************************************************************/ /*!
+@File
+@Title PVR Debug Declarations
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides debug 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 __PVR_DEBUG_H__
+#define __PVR_DEBUG_H__
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+
+#if defined(_MSC_VER)
+# define MSC_SUPPRESS_4127 __pragma(warning(suppress:4127))
+#else
+# define MSC_SUPPRESS_4127
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define PVR_MAX_DEBUG_MESSAGE_LEN (512) /*!< Max length of a Debug Message */
+
+/* These are privately used by pvr_debug, use the PVR_DBG_ defines instead */
+#define DBGPRIV_FATAL 0x001UL /*!< Debug-Fatal. Privately used by pvr_debug. */
+#define DBGPRIV_ERROR 0x002UL /*!< Debug-Error. Privately used by pvr_debug. */
+#define DBGPRIV_WARNING 0x004UL /*!< Debug-Warning. Privately used by pvr_debug. */
+#define DBGPRIV_MESSAGE 0x008UL /*!< Debug-Message. Privately used by pvr_debug. */
+#define DBGPRIV_VERBOSE 0x010UL /*!< Debug-Verbose. Privately used by pvr_debug. */
+#define DBGPRIV_CALLTRACE 0x020UL /*!< Debug-CallTrace. Privately used by pvr_debug. */
+#define DBGPRIV_ALLOC 0x040UL /*!< Debug-Alloc. Privately used by pvr_debug. */
+#define DBGPRIV_BUFFERED 0x080UL /*!< Debug-Buffered. Privately used by pvr_debug. */
+#define DBGPRIV_DEBUG 0x100UL /*!< Debug-AdHoc-Debug. Never submitted. Privately used by pvr_debug. */
+#define DBGPRIV_DBGDRV_MESSAGE 0x200UL /*!< Debug-DbgDrivMessage. Privately used by pvr_debug. */
+#define DBGPRIV_LAST 0x200UL /*!< Always set to highest mask value. Privately used by pvr_debug. */
+
+
+#if !defined(PVRSRV_NEED_PVR_ASSERT) && defined(DEBUG)
+#define PVRSRV_NEED_PVR_ASSERT
+#endif
+
+//zxl: Force open debug info. gPVRDebugLevel is defined in pvr_debug.c
+//#if defined(PVRSRV_NEED_PVR_ASSERT) && !defined(PVRSRV_NEED_PVR_DPF)
+#define PVRSRV_NEED_PVR_DPF
+//#endif
+
+#if !defined(PVRSRV_NEED_PVR_TRACE) && (defined(DEBUG) || defined(TIMING))
+#define PVRSRV_NEED_PVR_TRACE
+#endif
+
+#if defined(__KERNEL__)
+# define PVRSRVGETERRORSTRING PVRSRVGetErrorStringKM
+#else
+ IMG_IMPORT const IMG_CHAR *PVRSRVGetErrorString(PVRSRV_ERROR eError);
+# define PVRSRVGETERRORSTRING PVRSRVGetErrorString
+#endif
+
+/* PVR_ASSERT() and PVR_DBG_BREAK handling */
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+/* Unfortunately the klocworks static analysis checker doesn't understand our
+ * ASSERT macros. Thus it reports lots of false positive. Defining our Assert
+ * macros in a special way when the code is analysed by klocworks avoids
+ * them. */
+#if defined(__KLOCWORK__)
+ #define PVR_ASSERT(x) do { if (!(x)) abort(); } while (0)
+#else /* ! __KLOCWORKS__ */
+
+#if defined(_WIN32)
+#define PVR_ASSERT(expr) do \
+ { \
+ MSC_SUPPRESS_4127 \
+ if (!(expr)) \
+ { \
+ PVRSRVDebugPrintf(DBGPRIV_FATAL, __FILE__, __LINE__,\
+ "*** Debug assertion failed!"); \
+ __debugbreak(); \
+ } \
+ MSC_SUPPRESS_4127 \
+ } while (0)
+
+#else
+
+#if defined(LINUX) && defined(__KERNEL__)
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+/* In Linux kernel mode, use BUG() directly. This produces the correct
+ filename and line number in the panic message. */
+#define PVR_ASSERT(EXPR) do \
+ { \
+ if (!(EXPR)) \
+ { \
+ PVRSRVDebugPrintf(DBGPRIV_FATAL, __FILE__, __LINE__, \
+ "Debug assertion failed!"); \
+ BUG(); \
+ } \
+ } while (0)
+
+#else /* defined(LINUX) && defined(__KERNEL__) */
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR *pszAssertion)
+#if defined(__GNUC__)
+ __attribute__((noreturn))
+#endif
+ ;
+
+#if defined(_MSC_VER)
+/* This alternate definition is for MSVC, which warns about do {} while (0) */
+#define PVR_ASSERT(EXPR) MSC_SUPPRESS_4127 \
+ if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__)
+#else
+#define PVR_ASSERT(EXPR) do \
+ { \
+ if (!(EXPR)) \
+ PVRSRVDebugAssertFail(__FILE__, __LINE__, #EXPR); \
+ } while (0)
+#endif
+
+#endif /* defined(LINUX) && defined(__KERNEL__) */
+#endif /* __KLOCWORKS__ */
+#endif /* defined(PVRSRV_NEED_PVR_ASSERT)*/
+
+#if defined(__KLOCWORK__)
+ #define PVR_DBG_BREAK do { abort(); } while (0)
+#else
+ #if defined (WIN32)
+ #define PVR_DBG_BREAK __debugbreak(); /*!< Implementation of PVR_DBG_BREAK for (non-WinCE) Win32 */
+ #else
+ #if defined(PVR_DBG_BREAK_ASSERT_FAIL)
+ /*!< Implementation of PVR_DBG_BREAK that maps onto PVRSRVDebugAssertFail */
+ #if defined(_WIN32)
+ #define PVR_DBG_BREAK DBG_BREAK
+ #else
+ #if defined(LINUX) && defined(__KERNEL__)
+ #define PVR_DBG_BREAK BUG()
+ #else
+ #define PVR_DBG_BREAK PVRSRVDebugAssertFail(__FILE__, __LINE__, "PVR_DBG_BREAK")
+ #endif
+ #endif
+ #else
+ /*!< Null Implementation of PVR_DBG_BREAK (does nothing) */
+ #define PVR_DBG_BREAK
+ #endif
+ #endif
+#endif
+
+
+#else /* defined(PVRSRV_NEED_PVR_ASSERT) */
+ /* Unfortunately the klocworks static analysis checker doesn't understand our
+ * ASSERT macros. Thus it reports lots of false positive. Defining our Assert
+ * macros in a special way when the code is analysed by klocworks avoids
+ * them. */
+ #if defined(__KLOCWORK__)
+ #define PVR_ASSERT(EXPR) do { if (!(EXPR)) abort(); } while (0)
+ #else
+ #define PVR_ASSERT(EXPR) (IMG_VOID)(EXPR) /*!< Null Implementation of PVR_ASSERT (does nothing) */
+ #endif
+
+ #define PVR_DBG_BREAK /*!< Null Implementation of PVR_DBG_BREAK (does nothing) */
+
+#endif /* defined(PVRSRV_NEED_PVR_ASSERT) */
+
+
+/* PVR_DPF() handling */
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+ /* New logging mechanism */
+ #define PVR_DBG_FATAL DBGPRIV_FATAL
+ #define PVR_DBG_ERROR DBGPRIV_ERROR
+ #define PVR_DBG_WARNING DBGPRIV_WARNING
+ #define PVR_DBG_MESSAGE DBGPRIV_MESSAGE
+ #define PVR_DBG_VERBOSE DBGPRIV_VERBOSE
+ #define PVR_DBG_CALLTRACE DBGPRIV_CALLTRACE
+ #define PVR_DBG_ALLOC DBGPRIV_ALLOC
+ #define PVR_DBG_BUFFERED DBGPRIV_BUFFERED
+ #define PVR_DBG_DEBUG DBGPRIV_DEBUG
+ #define PVR_DBGDRIV_MESSAGE DBGPRIV_DBGDRV_MESSAGE
+
+ /* These levels are always on with PVRSRV_NEED_PVR_DPF */
+ #define __PVR_DPF_0x001UL(...) PVRSRVDebugPrintf(DBGPRIV_FATAL, __VA_ARGS__)
+ #define __PVR_DPF_0x002UL(...) PVRSRVDebugPrintf(DBGPRIV_ERROR, __VA_ARGS__)
+ #define __PVR_DPF_0x080UL(...) PVRSRVDebugPrintf(DBGPRIV_BUFFERED, __VA_ARGS__)
+
+ /*
+ The AdHoc-Debug level is only supported when enabled in the local
+ build environment and may need to be used in both debug and release
+ builds. An error is generated in the formal build if it is checked in.
+ */
+#if defined(PVR_DPF_ADHOC_DEBUG_ON)
+ #define __PVR_DPF_0x100UL(...) PVRSRVDebugPrintf(DBGPRIV_DEBUG, __VA_ARGS__)
+#else
+ /* Use an undefined token here to stop compilation dead in the offending module */
+ #define __PVR_DPF_0x100UL(...) __ERROR__PVR_DBG_DEBUG_is_in_use_but_has_not_been_enabled__Note_Debug_DPF_must_not_be_checked_in_
+#endif
+
+ /* Some are compiled out completely in release builds */
+#if defined(DEBUG)
+ #define __PVR_DPF_0x004UL(...) PVRSRVDebugPrintf(DBGPRIV_WARNING, __VA_ARGS__)
+ #define __PVR_DPF_0x008UL(...) PVRSRVDebugPrintf(DBGPRIV_MESSAGE, __VA_ARGS__)
+ #define __PVR_DPF_0x010UL(...) PVRSRVDebugPrintf(DBGPRIV_VERBOSE, __VA_ARGS__)
+ #define __PVR_DPF_0x020UL(...) PVRSRVDebugPrintf(DBGPRIV_CALLTRACE, __VA_ARGS__)
+ #define __PVR_DPF_0x040UL(...) PVRSRVDebugPrintf(DBGPRIV_ALLOC, __VA_ARGS__)
+ #define __PVR_DPF_0x200UL(...) PVRSRVDebugPrintf(DBGPRIV_DBGDRV_MESSAGE, __VA_ARGS__)
+#else
+ #define __PVR_DPF_0x004UL(...)
+ #define __PVR_DPF_0x008UL(...)
+ #define __PVR_DPF_0x010UL(...)
+ #define __PVR_DPF_0x020UL(...)
+ #define __PVR_DPF_0x040UL(...)
+ #define __PVR_DPF_0x200UL(...)
+#endif
+
+ /* Translate the different log levels to separate macros
+ * so they can each be compiled out.
+ */
+//zxl: Force open debug info. gPVRDebugLevel is defined in pvr_debug.c
+#if 1
+ #define __PVR_DPF(lvl, ...) __PVR_DPF_ ## lvl (__FILE__, __LINE__, __VA_ARGS__)
+#else
+ #define __PVR_DPF(lvl, ...) __PVR_DPF_ ## lvl ("", 0, __VA_ARGS__)
+#endif
+
+ /* Get rid of the double bracketing */
+ #define PVR_DPF(x) __PVR_DPF x
+
+ #define PVR_LOG_ERROR(_rc, _call) \
+ PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__));
+
+ #define PVR_LOG_IF_ERROR(_rc, _call) do \
+ { if (_rc != PVRSRV_OK) \
+ PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
+ MSC_SUPPRESS_4127\
+ } while (0)
+
+
+ #define PVR_LOGR_IF_ERROR(_rc, _call) do \
+ { if (_rc != PVRSRV_OK) { \
+ PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
+ return (_rc); }\
+ MSC_SUPPRESS_4127\
+ } while (0)
+
+ #define PVR_LOGRN_IF_ERROR(_rc, _call) do \
+ { if (_rc != PVRSRV_OK) { \
+ PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
+ return; }\
+ MSC_SUPPRESS_4127\
+ } while (0)
+
+ #define PVR_LOGG_IF_ERROR(_rc, _call, _go) do \
+ { if (_rc != PVRSRV_OK) { \
+ PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
+ goto _go; }\
+ MSC_SUPPRESS_4127\
+ } while (0)
+
+ #define PVR_LOG_IF_FALSE(_expr, _msg) do \
+ { if (!(_expr)) \
+ PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
+ MSC_SUPPRESS_4127\
+ } while (0)
+
+ #define PVR_LOGR_IF_FALSE(_expr, _msg, _rc) do \
+ { if (!(_expr)) { \
+ PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
+ return (_rc); }\
+ MSC_SUPPRESS_4127\
+ } while (0)
+
+ #define PVR_LOGG_IF_FALSE(_expr, _msg, _go) do \
+ { if (!(_expr)) { \
+ PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
+ goto _go; }\
+ MSC_SUPPRESS_4127\
+ } while (0)
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR *pszFormat,
+ ...) IMG_FORMAT_PRINTF(4, 5);
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
+
+#else /* defined(PVRSRV_NEED_PVR_DPF) */
+
+ #define PVR_DPF(X) /*!< Null Implementation of PowerVR Debug Printf (does nothing) */
+
+ #define PVR_LOG_ERROR(_rc, _call) (void)(_rc)
+ #define PVR_LOG_IF_ERROR(_rc, _call) (void)(_rc)
+ #define PVR_LOGR_IF_ERROR(_rc, _call) do { if (_rc != PVRSRV_OK) { return (_rc); } MSC_SUPPRESS_4127 } while(0)
+ #define PVR_LOGRN_IF_ERROR(_rc, _call) do { if (_rc != PVRSRV_OK) { return; } MSC_SUPPRESS_4127 } while(0)
+ #define PVR_LOGG_IF_ERROR(_rc, _call, _go) do { if (_rc != PVRSRV_OK) { goto _go; } MSC_SUPPRESS_4127 } while(0)
+
+ #define PVR_LOG_IF_FALSE(_expr, _msg) (void)(_expr)
+ #define PVR_LOGR_IF_FALSE(_expr, _msg, _rc) do { if (!(_expr)) { return (_rc); } MSC_SUPPRESS_4127 } while(0)
+ #define PVR_LOGG_IF_FALSE(_expr, _msg, _go) do { if (!(_expr)) { goto _go; } MSC_SUPPRESS_4127 } while(0)
+
+ #undef PVR_DPF_FUNCTION_TRACE_ON
+
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
+
+
+#if defined(PVR_DPF_FUNCTION_TRACE_ON)
+
+ #define PVR_DPF_ENTERED \
+ PVR_DPF((PVR_DBG_CALLTRACE, "--> %s:%d entered", __func__, __LINE__))
+
+ #define PVR_DPF_ENTERED1(p1) \
+ 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)
+
+ #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)
+
+ #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)
+
+ #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)
+
+ #define PVR_DPF_RETURN \
+ do { PVR_DPF((PVR_DBG_CALLTRACE, "-< %s:%d returned", __func__, __LINE__)); return; MSC_SUPPRESS_4127 } while (0)
+
+ #if !defined(DEBUG)
+ #error PVR DPF Function trace enabled in release build, rectify
+ #endif
+
+#else /* defined(PVR_DPF_FUNCTION_TRACE_ON) */
+
+ #define PVR_DPF_ENTERED
+ #define PVR_DPF_ENTERED1(p1)
+ #define PVR_DPF_RETURN_RC(a) return (a)
+ #define PVR_DPF_RETURN_RC1(a,p1) return (a)
+ #define PVR_DPF_RETURN_VAL(a) return (a)
+ #define PVR_DPF_RETURN_OK return PVRSRV_OK
+ #define PVR_DPF_RETURN return
+
+#endif /* defined(PVR_DPF_FUNCTION_TRACE_ON) */
+
+
+/* PVR_TRACE() handling */
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+ #define PVR_TRACE(X) PVRSRVTrace X /*!< PowerVR Debug Trace Macro */
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... )
+ IMG_FORMAT_PRINTF(1, 2);
+
+#else /* defined(PVRSRV_NEED_PVR_TRACE) */
+ /*! Null Implementation of PowerVR Debug Trace Macro (does nothing) */
+ #define PVR_TRACE(X)
+
+#endif /* defined(PVRSRV_NEED_PVR_TRACE) */
+
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(TRUNCATE_64BITS_TO_32BITS)
+#endif
+ INLINE static IMG_UINT32 TRUNCATE_64BITS_TO_32BITS(IMG_UINT64 uiInput)
+ {
+ IMG_UINT32 uiTruncated;
+
+ uiTruncated = (IMG_UINT32)uiInput;
+ PVR_ASSERT(uiInput == uiTruncated);
+ return uiTruncated;
+ }
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(TRUNCATE_64BITS_TO_SIZE_T)
+#endif
+ INLINE static IMG_SIZE_T TRUNCATE_64BITS_TO_SIZE_T(IMG_UINT64 uiInput)
+ {
+ IMG_SIZE_T uiTruncated;
+
+ uiTruncated = (IMG_SIZE_T)uiInput;
+ PVR_ASSERT(uiInput == uiTruncated);
+ return uiTruncated;
+ }
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(TRUNCATE_SIZE_T_TO_32BITS)
+#endif
+ INLINE static IMG_UINT32 TRUNCATE_SIZE_T_TO_32BITS(IMG_SIZE_T uiInput)
+ {
+ IMG_UINT32 uiTruncated;
+
+ uiTruncated = (IMG_UINT32)uiInput;
+ PVR_ASSERT(uiInput == uiTruncated);
+ return uiTruncated;
+ }
+
+
+#else /* defined(PVRSRV_NEED_PVR_ASSERT) */
+ #define TRUNCATE_64BITS_TO_32BITS(expr) ((IMG_UINT32)(expr))
+ #define TRUNCATE_64BITS_TO_SIZE_T(expr) ((IMG_SIZE_T)(expr))
+ #define TRUNCATE_SIZE_T_TO_32BITS(expr) ((IMG_UINT32)(expr))
+#endif /* defined(PVRSRV_NEED_PVR_ASSERT) */
+
+/* Macros used to trace calls */
+#if defined(DEBUG)
+ #define PVR_DBG_FILELINE , __FILE__, __LINE__
+ #define PVR_DBG_FILELINE_PARAM , const IMG_CHAR *pszaFile, IMG_UINT32 ui32Line
+ #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)
+#else
+ #define PVR_DBG_FILELINE
+ #define PVR_DBG_FILELINE_PARAM
+ #define PVR_DBG_FILELINE_ARG
+ #define PVR_DBG_FILELINE_FMT
+ #define PVR_DBG_FILELINE_UNREF()
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PVR_DEBUG_H__ */
+
+/******************************************************************************
+ End of file (pvr_debug.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/pvr_fd_sync_user.h b/drivers/gpu/rogue/include/pvr_fd_sync_user.h
new file mode 100644
index 000000000000..c63ebe0bc4d2
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvr_fd_sync_user.h
@@ -0,0 +1,160 @@
+/*************************************************************************/ /*!
+@File pvr_fd_sync_user.h
+@Title Userspace definitions to use the kernel sync driver
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+#ifndef _PVR_FD_SYNC_USER_H_
+#define _PVR_FD_SYNC_USER_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include "pvrsrv_error.h"
+
+#define PVR_SYNC_MAX_QUERY_FENCE_POINTS 14
+
+#define PVR_SYNC_IOC_MAGIC 'W'
+
+#define PVR_SYNC_IOC_CREATE_FENCE \
+ _IOWR(PVR_SYNC_IOC_MAGIC, 0, struct pvr_sync_create_fence_ioctl_data)
+
+#define PVR_SYNC_IOC_ENABLE_FENCING \
+ _IOWR(PVR_SYNC_IOC_MAGIC, 1, struct pvr_sync_enable_fencing_ioctl_data)
+
+#define PVR_SYNC_IOC_DEBUG_FENCE \
+ _IOWR(PVR_SYNC_IOC_MAGIC, 2, struct pvr_sync_debug_fence_ioctl_data)
+
+#define PVR_SYNC_IOC_ALLOC_FENCE \
+ _IOWR(PVR_SYNC_IOC_MAGIC, 3, struct pvr_sync_alloc_fence_ioctl_data)
+
+#define PVRSYNC_MODNAME "pvr_sync"
+
+struct pvr_sync_alloc_fence_ioctl_data
+{
+ /* Output */
+ int iFenceFd;
+ int bTimelineIdle;
+}
+__attribute__((packed, aligned(8)));
+
+struct pvr_sync_create_fence_ioctl_data
+{
+ /* Input */
+ int iAllocFenceFd;
+ char szName[32];
+
+ /* Output */
+ int iFenceFd;
+}
+__attribute__((packed, aligned(8)));
+
+struct pvr_sync_enable_fencing_ioctl_data
+{
+ /* Input */
+ int bFencingEnabled;
+}
+__attribute__((packed, aligned(8)));
+
+struct pvr_sync_debug_sync_data {
+ /* Output */
+ char szParentName[32];
+ __s32 i32Status;
+ __u8 ui8Foreign;
+ union
+ {
+ struct {
+ __u32 id;
+ __u32 ui32FWAddr;
+ __u32 ui32CurrOp;
+ __u32 ui32NextOp;
+ __u32 ui32TlTaken;
+ } s;
+ char szForeignVal[16];
+ };
+} __attribute__((packed, aligned(8)));
+
+struct pvr_sync_debug_fence_ioctl_data
+{
+ /* Input */
+ int iFenceFd;
+
+ /* Output */
+ char szName[32];
+ __s32 i32Status;
+ __u32 ui32NumSyncs;
+ struct pvr_sync_debug_sync_data aPts[PVR_SYNC_MAX_QUERY_FENCE_POINTS];
+}
+__attribute__((packed, aligned(8)));
+
+PVRSRV_ERROR PVRFDSyncOpen(int *piSyncFd);
+PVRSRV_ERROR PVRFDSyncClose(int iSyncFd);
+
+PVRSRV_ERROR PVRFDSyncWaitFence(int iFenceFd);
+PVRSRV_ERROR PVRFDSyncCheckFence(int iFenceFd);
+
+PVRSRV_ERROR PVRFDSyncMergeFences(const char *pcszName,
+ int iFenceFd1,
+ int iFenceFd2,
+ int *piNewFenceFd);
+
+PVRSRV_ERROR PVRFDSyncAllocFence(int iSyncFd,
+ int *piFenceFd,
+ int *pbTimelineIdle);
+
+PVRSRV_ERROR PVRFDSyncCreateFence(int iSyncFd,
+ const char *pcszName,
+ int iAllocFenceFd,
+ int *piFenceFd);
+
+PVRSRV_ERROR PVRFDSyncEnableFencing(int iSyncFd,
+ int bFencingEnabled);
+
+PVRSRV_ERROR PVRFDSyncQueryFence(int iSyncFd,
+ int iFenceFd,
+ struct pvr_sync_debug_fence_ioctl_data *psData);
+
+PVRSRV_ERROR PVRFDSyncDumpFence(int iSyncFd,
+ int iFenceFd,
+ const char *pcszModule,
+ const char *pcszFmt, ...)
+ __attribute__((format(printf,4,5)));
+
+#endif /* _PVR_FD_SYNC_USER_H_ */
diff --git a/drivers/gpu/rogue/include/pvrmodule.h b/drivers/gpu/rogue/include/pvrmodule.h
new file mode 100644
index 000000000000..267c7b687487
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvrmodule.h
@@ -0,0 +1,48 @@
+/*************************************************************************/ /*!
+@Title Module Author and License.
+@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 _PVRMODULE_H_
+#define _PVRMODULE_H_
+
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
+MODULE_LICENSE("Dual MIT/GPL");
+
+#endif /* _PVRMODULE_H_ */
diff --git a/drivers/gpu/rogue/include/pvrsrv_device_types.h b/drivers/gpu/rogue/include/pvrsrv_device_types.h
new file mode 100644
index 000000000000..1b4c5cdbb69f
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvrsrv_device_types.h
@@ -0,0 +1,112 @@
+/*************************************************************************/ /*!
+@File
+@Title PowerVR device type definitions
+@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(__PVRSRV_DEVICE_TYPES_H__)
+#define __PVRSRV_DEVICE_TYPES_H__
+
+#include "img_types.h"
+
+#define PVRSRV_MAX_DEVICES 16 /*!< Largest supported number of devices on the system */
+
+/*!
+ ******************************************************************************
+ * List of known device types.
+ *****************************************************************************/
+typedef enum PVRSRV_DEVICE_TYPE
+{
+ PVRSRV_DEVICE_TYPE_UNKNOWN = 0, /*!< Unknown device type */
+ PVRSRV_DEVICE_TYPE_MBX1 = 1, /*!< MBX1 */
+ PVRSRV_DEVICE_TYPE_MBX1_LITE = 2, /*!< MBX1 Lite */
+ PVRSRV_DEVICE_TYPE_M24VA = 3, /*!< M24VA */
+ PVRSRV_DEVICE_TYPE_MVDA2 = 4, /*!< MVDA2 */
+ PVRSRV_DEVICE_TYPE_MVED1 = 5, /*!< MVED1 */
+ PVRSRV_DEVICE_TYPE_MSVDX = 6, /*!< MSVDX */
+ PVRSRV_DEVICE_TYPE_SGX = 7, /*!< SGX */
+ PVRSRV_DEVICE_TYPE_VGX = 8, /*!< VGX */
+ PVRSRV_DEVICE_TYPE_EXT = 9, /*!< 3rd party devices take ext type */
+ PVRSRV_DEVICE_TYPE_RGX = 10, /*!< RGX */
+
+ PVRSRV_DEVICE_TYPE_LAST = 10, /*!< Last device type */
+
+ PVRSRV_DEVICE_TYPE_FORCE_I32 = 0x7fffffff /*!< Force enum to be 32-bit width */
+
+} PVRSRV_DEVICE_TYPE;
+
+
+/*!
+ *****************************************************************************
+ * List of known device classes.
+ *****************************************************************************/
+typedef enum _PVRSRV_DEVICE_CLASS_
+{
+ PVRSRV_DEVICE_CLASS_3D = 0 , /*!< 3D Device Class */
+ PVRSRV_DEVICE_CLASS_DISPLAY = 1 , /*!< Display Device Class */
+ PVRSRV_DEVICE_CLASS_BUFFER = 2 , /*!< Buffer Class */
+ PVRSRV_DEVICE_CLASS_VIDEO = 3 , /*!< Video Device Class */
+
+ PVRSRV_DEVICE_CLASS_FORCE_I32 = 0x7fffffff /* Force enum to be at least 32-bits wide */
+
+} PVRSRV_DEVICE_CLASS;
+
+
+/*!
+ ******************************************************************************
+ * Device identifier structure
+ *****************************************************************************/
+typedef struct _PVRSRV_DEVICE_IDENTIFIER_
+{
+ PVRSRV_DEVICE_TYPE eDeviceType; /*!< Identifies the type of the device */
+ PVRSRV_DEVICE_CLASS eDeviceClass; /*!< Identifies more general class of device - display/3d/mpeg etc */
+ IMG_UINT32 ui32DeviceIndex; /*!< Index of the device within the system */
+ IMG_CHAR *pszPDumpDevName; /*!< Pdump memory bank name */
+ IMG_CHAR *pszPDumpRegName; /*!< Pdump register bank name */
+
+} PVRSRV_DEVICE_IDENTIFIER;
+
+
+#if defined(KERNEL) && defined(ANDROID)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+
+#endif /* __PVRSRV_DEVICE_TYPES_H__ */
+
diff --git a/drivers/gpu/rogue/include/pvrsrv_devmem.h b/drivers/gpu/rogue/include/pvrsrv_devmem.h
new file mode 100644
index 000000000000..352f04bfbf7b
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvrsrv_devmem.h
@@ -0,0 +1,550 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management core
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Client side part of device memory management -- This
+ file defines the exposed Services API to core memory management
+ 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.
+*/ /**************************************************************************/
+
+#ifndef PVRSRV_DEVMEM_H
+#define PVRSRV_DEVMEM_H
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "devicemem_typedefs.h"
+#include "pdumpdefs.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+#include "services.h" /* For PVRSRV_DEV_DATA */
+#include "sync_external.h"
+
+/*
+ Device memory contexts, heaps and memory descriptors are passed
+ through to underlying memory APIs directly, but are to be regarded
+ as an opaque handle externally.
+*/
+typedef DEVMEM_CONTEXT *PVRSRV_DEVMEMCTX; /*!< Device-Mem Client-Side Interface: Typedef for Context Ptr */
+typedef DEVMEM_HEAP *PVRSRV_HEAP; /*!< Device-Mem Client-Side Interface: Typedef for Heap Ptr */
+typedef DEVMEM_MEMDESC *PVRSRV_MEMDESC; /*!< Device-Mem Client-Side Interface: Typedef for Memory Descriptor Ptr */
+typedef DEVMEM_EXPORTCOOKIE PVRSRV_DEVMEM_EXPORTCOOKIE; /*!< Device-Mem Client-Side Interface: Typedef for Export Cookie */
+typedef DEVMEM_FLAGS_T PVRSRV_MEMMAP_FLAGS_T; /*!< Device-Mem Client-Side Interface: Typedef for Memory-Mapping Flags Enum */
+typedef DEVMEM_SERVER_EXPORTCOOKIE PVRSRV_DEVMEM_SERVER_EXPORTCOOKIE; /*!< Device-Mem Client-Side Interface: Typedef for Server Export Cookie */
+
+/* N.B. Flags are now defined in pvrsrv_memallocflags.h as they need
+ to be omnipresent. */
+
+/*
+ *
+ * API functions
+ *
+ */
+
+/**************************************************************************/ /*!
+@Function PVRSRVCreateDeviceMemContext
+@Description Creates a device memory context. There is a one-to-one
+ correspondence between this context data structure and the top
+ level MMU page table (known as the Page Catalogue, in the case of a
+ 3-tier MMU). It is intended that a process with its own virtual
+ space on the CPU will also have its own virtual space on the GPU.
+ Thus there is loosely a one-to-one correspondence between process
+ and device memory context, but this is not enforced at this API.
+
+ Every process must create the device memory context before any
+ memory allocations are made, and is responsible for freeing all
+ such allocations before destroying the context
+
+ This is a wrapper function above the "bare-metal" device memory
+ context creation function which would create just a context and no
+ heaps. This function will also create the heaps, according to the
+ heap config that the device specific initialization code has
+ nominated for use by this API.
+
+ The number of heaps thus created is returned to the caller, such
+ that the caller can allocate an array and the call in to fetch
+ details of each heap, or look up the heap with the "Find Heap" API
+ described below.
+
+ In order to derive the details of the MMU configuration for the
+ device, and for retrieving the "bridge handle" for communication
+ internally in services, is is necessary to pass in the
+ PVRSRV_DEV_DATA object as populated with a prior call to
+ PVRSRVAcquireDeviceData()
+@Input psDev dev data
+@Output phCtxOut On success, the returned DevMem Context. The
+ caller is responsible for providing storage
+ for this.
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+extern IMG_IMPORT PVRSRV_ERROR
+PVRSRVCreateDeviceMemContext(const PVRSRV_DEV_DATA *psDev,
+ PVRSRV_DEVMEMCTX *phCtxOut);
+
+/**************************************************************************/ /*!
+@Function PVRSRVDestroyDeviceMemContext
+@Description Destroy cannot fail. Well. It shouldn't, assuming the caller
+ has obeyed the protocol, i.e. has freed all his allocations
+ beforehand.
+@Input hCtx Handle to a DevMem Context
+@Return None
+*/ /***************************************************************************/
+extern IMG_IMPORT IMG_VOID
+PVRSRVDestroyDeviceMemContext(PVRSRV_DEVMEMCTX hCtx);
+
+/**************************************************************************/ /*!
+@Function PVRSRVFindHeapByName
+@Description Returns the heap handle for the named heap which is assumed to
+ exist in this context. PVRSRV_HEAP *phHeapOut,
+
+ N.B. No need for acquire/release semantics here, as when using
+ this wrapper layer, the heaps are automatically instantiated at
+ context creation time and destroyed when the context is
+ destroyed.
+
+ The caller is required to know the heap names already as these
+ will vary from device to device and from purpose to purpose.
+@Input hCtx Handle to a DevMem Context
+@Input pszHeapName Name of the heap to look for
+@Output phHeapOut a handle to the heap, for use in future calls
+ to OpenAllocation / AllocDeviceMemory / Map
+ DeviceClassMemory, etc. (The PVRSRV_HEAP type
+ to be regarded by caller as an opaque, but
+ strongly typed, handle)
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+extern PVRSRV_ERROR
+PVRSRVFindHeapByName(PVRSRV_DEVMEMCTX hCtx,
+ const IMG_CHAR *pszHeapName,
+ PVRSRV_HEAP *phHeapOut);
+
+/**************************************************************************/ /*!
+@Function PVRSRVDevmemGetHeapBaseDevVAddr
+@Description returns the device virtual address of the base of the heap.
+@Input hHeap Handle to a Heap
+@Output pDevVAddr On success, the device virtual address of the
+ base of the heap.
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVDevmemGetHeapBaseDevVAddr(PVRSRV_HEAP hHeap,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+
+/**************************************************************************/ /*!
+@Function PVRSRVAllocDeviceMem
+@Description Allocate memory from the specified heap, acquiring physical
+ memory from OS as we go and mapping this into
+ the GPU (mandatorily) and CPU (optionally)
+
+ Size must be a positive integer multiple of alignment, or, to
+ put it another way, the uiLog2Align LSBs should all be zero, but
+ at least one other bit should not be.
+
+ Caller to take charge of the PVRSRV_MEMDESC (the memory
+ descriptor) which is to be regarded as an opaque handle.
+@Input hHeap Handle to the heap from which memory will be
+ allocated
+@Input uiSize Amount of memory to be allocated.
+@Input uiLog2Align LOG2 of the required alignment
+@Input uiMemAllocFlags Allocation Flags
+@Input pszText Text to describe the allocation
+@Output phMemDescOut On success, the resulting memory descriptor
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_ error code
+*/ /***************************************************************************/
+extern PVRSRV_ERROR
+PVRSRVAllocDeviceMem(PVRSRV_HEAP hHeap,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
+ PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags,
+ IMG_PCHAR pszText,
+ PVRSRV_MEMDESC *phMemDescOut);
+
+/**************************************************************************/ /*!
+@Function PVRSRVFreeDeviceMem
+@Description Free that allocated by PVRSRVAllocDeviceMem (Memory descriptor
+ will be destroyed)
+@Input hMemDesc Handle to the descriptor of the memory to be
+ freed
+@Return None
+*/ /***************************************************************************/
+extern IMG_VOID
+PVRSRVFreeDeviceMem(PVRSRV_MEMDESC hMemDesc);
+
+/**************************************************************************/ /*!
+@Function PVRSRVAcquireCPUMapping
+@Description Causes the allocation referenced by this memory descriptor to be
+ mapped into cpu virtual memory, if it wasn't already, and the
+ CPU virtual address returned in the caller-provided location.
+
+ The caller must call PVRSRVReleaseCPUMapping to advise when he
+ has finished with the mapping.
+@Input hMemDesc Handle to the memory descriptor for which a
+ CPU mapping is required
+@Output ppvCpuVirtAddrOut On success, the caller's ptr is set to the
+ new CPU mapping
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+extern PVRSRV_ERROR
+PVRSRVAcquireCPUMapping(PVRSRV_MEMDESC hMemDesc,
+ IMG_VOID **ppvCpuVirtAddrOut);
+
+/**************************************************************************/ /*!
+@Function PVRSRVReleaseCPUMapping
+@Description Relinquishes the cpu mapping acquired with
+ PVRSRVAcquireCPUMapping()
+@Input hMemDesc Handle of the memory descriptor
+@Return None
+*/ /***************************************************************************/
+extern IMG_VOID
+PVRSRVReleaseCPUMapping(PVRSRV_MEMDESC hMemDesc);
+
+
+/**************************************************************************/ /*!
+@Function PVRSRVMapToDevice
+@Description Map allocation into the device MMU. This function must only be
+ called once, any further calls will return
+ PVRSRV_ERROR_DEVICEMEM_ALREADY_MAPPED
+
+ The caller must call PVRSRVReleaseDeviceMapping when they
+ are finished with the mapping.
+
+@Input hMemDesc Handle of the memory descriptor
+@Input hHeap Device heap to map the allocation into
+@Output psDevVirtAddrOut Device virtual address
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+extern PVRSRV_ERROR
+PVRSRVMapToDevice(PVRSRV_MEMDESC hMemDesc,
+ PVRSRV_HEAP hHeap,
+ IMG_DEV_VIRTADDR *psDevVirtAddrOut);
+
+/**************************************************************************/ /*!
+@Function PVRSRVAcquireDeviceMapping
+@Description Acquire a reference on the device mapping the allocation.
+ If the allocation wasn't mapped into the device then
+ and the device virtual address returned in the
+ PVRSRV_ERROR_DEVICEMEM_NO_MAPPING will be returned as
+ PVRSRVMapToDevice must be called first.
+
+ The caller must call PVRSRVReleaseDeviceMapping when they
+ are finished with the mapping.
+@Input hMemDesc Handle to the memory descriptor for which a
+ device mapping is required
+@Output psDevVirtAddrOut On success, the caller's ptr is set to the
+ new device mapping
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+extern PVRSRV_ERROR
+PVRSRVAcquireDeviceMapping(PVRSRV_MEMDESC hMemDesc,
+ IMG_DEV_VIRTADDR *psDevVirtAddrOut);
+
+/**************************************************************************/ /*!
+@Function PVRSRVReleaseDeviceMapping
+@Description Relinquishes the device mapping acquired with
+ PVRSRVAcquireDeviceMapping or PVRSRVMapToDevice
+@Input hMemDesc Handle of the memory descriptor
+@Return None
+*/ /***************************************************************************/
+extern IMG_VOID
+PVRSRVReleaseDeviceMapping(PVRSRV_MEMDESC hMemDesc);
+
+/*************************************************************************/ /*!
+@Function PVRSRVDevmemLocalImport
+
+@Description Import a PMR that was created with this connection to services.
+
+@Input hExtHandle External memory handle
+
+@Input uiFlags Import flags
+
+@Output phMemDescPtr Created MemDesc
+
+@Output puiSizePtr Size of the created MemDesc
+
+@Return PVRSRV_OK is succesful
+*/
+/*****************************************************************************/
+PVRSRV_ERROR PVRSRVDevmemLocalImport(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hExtHandle,
+ PVRSRV_MEMMAP_FLAGS_T uiFlags,
+ PVRSRV_MEMDESC *phMemDescPtr,
+ IMG_DEVMEM_SIZE_T *puiSizePtr);
+
+/*************************************************************************/ /*!
+@Function PVRSRVDevmemGetImportUID
+
+@Description Get the UID of the import that backs this MemDesc
+
+@Input hMemDesc MemDesc
+
+@Return UID of import
+*/
+/*****************************************************************************/
+PVRSRV_ERROR PVRSRVDevmemGetImportUID(PVRSRV_MEMDESC hMemDesc,
+ IMG_UINT64 *pui64UID);
+
+/**************************************************************************/ /*!
+@Function PVRSRVAllocExportableDevMem
+@Description Allocate memory without mapping into device memory context. This
+ memory is exported and ready to be mapped into the device memory
+ context of other processes, or to CPU only with
+ PVRSRVMapMemoryToCPUOnly(). The caller agrees to later call
+ PVRSRVFreeUnmappedExportedMemory(). The caller must give the page
+ size of the heap into which this memory may be subsequently
+ mapped, or the largest of such page sizes if it may be mapped
+ into multiple places. This information is to be communicated in
+ the Log2Align field.
+
+ Size must be a positive integer multiple of the page size
+@Input uiLog2Align Log2 of the alignment required
+@Input uiSize the amount of memory to be allocated
+@Input uiFlags Allocation flags
+@Input pszText Text to describe the allocation
+@Output hMemDesc
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_ error code
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVAllocExportableDevMem(const PVRSRV_DEV_DATA *psDevData,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ IMG_PCHAR pszText,
+ PVRSRV_MEMDESC *hMemDesc);
+
+/**************************************************************************/ /*!
+@Function PVRSRVAllocSparseDevMem
+@Description Allocate sparse memory without mapping into device memory context.
+ Sparse memory is used where you have an allocation that has a
+ logical size (i.e. the amount of VM space it will need when
+ mapping it into a device) that is larger then the amount of
+ physical memory that allocation will use. An example of this
+ is a NPOT texture where the twiddling algorithm requires you
+ to round the width and height to next POT and so you know there
+ will be pages that are never accessed.
+
+ This memory is can to be exported and mapped into the device
+ memory context of other processes, or to CPU.
+
+ Size must be a positive integer multiple of the page size
+@Input psDevData Device to allocation the memory for
+@Input uiSize The logical size of allocation
+@Input uiChunkSize The size of the chunk
+@Input ui32NumPhysChunks The number of physical chunks required
+@Input ui32NumVirtChunks The number of virtual chunks required
+@Input pabMappingTable Mapping table
+@Input uiLog2Align Log2 of the required alignment
+@Input uiFlags Allocation flags
+@Input pszText Text to describe the allocation
+@Output hMemDesc
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_ error code
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVAllocSparseDevMem(const PVRSRV_DEV_DATA *psDevData,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2Align,
+ DEVMEM_FLAGS_T uiFlags,
+ IMG_PCHAR pszText,
+ PVRSRV_MEMDESC *hMemDesc);
+
+/**************************************************************************/ /*!
+@Function PVRSRVGetLog2PageSize
+@Description Just call AFTER setting up the connection to the kernel module
+ otherwise it will run into an assert.
+ Gives the log2 of the page size that is currently utilised by
+ devmem.
+
+@Return The page size
+*/ /***************************************************************************/
+
+IMG_UINT32 PVRSRVGetLog2PageSize(void);
+
+/**************************************************************************/ /*!
+@Function PVRSRVExport
+@Description Given a memory allocation allocated with Devmem_Allocate(),
+ create a "cookie" that can be passed intact by the caller's own
+ choice of secure IPC to another process and used as the argument
+ to "map" to map this memory into a heap in the target processes.
+ N.B. This can also be used to map into multiple heaps in one
+ process, though that's not the intention.
+
+ Note, the caller must later call Unexport before freeing the
+ memory.
+@Input hMemDesc handle to the descriptor of the memory to be
+ exported
+@Output phExportCookie On success, a handle to the exported cookie
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+PVRSRV_ERROR PVRSRVExportDevMem(PVRSRV_MEMDESC hMemDesc,
+ PVRSRV_DEVMEM_EXPORTCOOKIE *phExportCookie);
+
+/**************************************************************************/ /*!
+@Function DevmemMakeServerExportClientExport
+@Description This is a "special case" function for making a server export
+ cookie which went through the direct bridge into an export
+ cookie that can be passed through the client bridge.
+@Input psConnection Services connection
+@Input hServerExportCookie server export cookie
+@Output psExportCookie ptr to export cookie
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVMakeServerExportClientExport(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie,
+ PVRSRV_DEVMEM_EXPORTCOOKIE *psExportCookie);
+
+/**************************************************************************/ /*!
+@Function DevmemUnmakeServerExportClientExport
+@Description Remove any associated resource from the Make operation
+@Input psConnection Services connection
+@Output psExportCookie ptr to export cookie
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVUnmakeServerExportClientExport(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_DEVMEM_EXPORTCOOKIE *psExportCookie);
+
+/**************************************************************************/ /*!
+@Function PVRSRVUnexport
+@Description Undo the export caused by "PVRSRVExport" - note - it doesn't
+ actually tear down any mapping made by processes that received
+ the export cookie. It will simply make the cookie null and void
+ and prevent further mappings.
+@Input hMemDesc handle to the descriptor of the memory which
+ will no longer be exported
+@Output phExportCookie On success, the export cookie provided will be
+ set to null
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+PVRSRV_ERROR PVRSRVUnexportDevMem(PVRSRV_MEMDESC hMemDesc,
+ PVRSRV_DEVMEM_EXPORTCOOKIE *phExportCookie);
+
+/**************************************************************************/ /*!
+@Function PVRSRVImportDevMem
+@Description Import memory that was previously exported with PVRSRVExport()
+ into the current process.
+
+ Note: This call only makes the memory accessible to this
+ process, it doesn't map it into the device or CPU.
+
+@Input psConnection Connection to services
+@Input phExportCookie Ptr to the handle of the export-cookie
+ identifying
+@Output phMemDescOut On Success, a handle to a new memory descriptor
+ representing the memory as mapped into the
+ local process address space.
+@Input uiFlags Device memory mapping flags
+@Input pszText Text to describe the import
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+PVRSRV_ERROR PVRSRVImportDevMem(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_DEVMEM_EXPORTCOOKIE *phExportCookie,
+ PVRSRV_MEMMAP_FLAGS_T uiFlags,
+ PVRSRV_MEMDESC *phMemDescOut);
+
+#if defined (SUPPORT_EXPORTING_MEMORY_CONTEXT)
+/**************************************************************************/ /*!
+@Function PVRSRVExportDevmemContext
+@Description Export a device memory context to another process
+
+@Input hCtx Memory context to export
+@Output phExport On Success, a export handle that can be passed
+ to another process and used with
+ PVRSRVImportDeviceMemContext to import the
+ memory context
+@Return PVRSRV_ERROR: PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVExportDevmemContext(PVRSRV_DEVMEMCTX hCtx,
+ IMG_HANDLE *phExport);
+
+/**************************************************************************/ /*!
+@Function PVRSRVUnexportDevmemContext
+@Description Unexport an exported device memory context
+
+@Input psConnection Services connection
+@Input hExport Export handle created to be unexported
+
+@Return None
+*/ /***************************************************************************/
+IMG_VOID
+PVRSRVUnexportDevmemContext(PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hExport);
+
+/**************************************************************************/ /*!
+@Function PVRSRVImportDeviceMemContext
+@Description Import an exported device memory context
+
+ Note: The memory context created with this function is not
+ complete and can only be used with debugger related functions
+
+@Input psConnection Services connection
+@Input hExport Export handle to import
+@Output phCtxOut Device memory context
+
+@Return None
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVImportDeviceMemContext(PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hExport,
+ PVRSRV_DEVMEMCTX *phCtxOut);
+
+#endif /* SUPPORT_EXPORTING_MEMORY_CONTEXT */
+#if defined __cplusplus
+};
+#endif
+#endif /* PVRSRV_DEVMEM_H */
+
diff --git a/drivers/gpu/rogue/include/pvrsrv_error.h b/drivers/gpu/rogue/include/pvrsrv_error.h
new file mode 100644
index 000000000000..82ef82a46440
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvrsrv_error.h
@@ -0,0 +1,61 @@
+/*************************************************************************/ /*!
+@File pvrsrv_error.h
+@Title services error enumerant
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines error codes used by any/all services modules
+@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 (__PVRSRV_ERROR_H__)
+#define __PVRSRV_ERROR_H__
+
+/*!
+ *****************************************************************************
+ * Error values
+ *****************************************************************************/
+typedef enum PVRSRV_ERROR
+{
+ PVRSRV_OK,
+#define PVRE(x) x,
+#include "pvrsrv_errors.h"
+#undef PVRE
+ PVRSRV_ERROR_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_ERROR;
+
+#endif /* !defined (__PVRSRV_ERROR_H__) */
diff --git a/drivers/gpu/rogue/include/pvrsrv_errors.h b/drivers/gpu/rogue/include/pvrsrv_errors.h
new file mode 100644
index 000000000000..fe26246ea91a
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvrsrv_errors.h
@@ -0,0 +1,327 @@
+/*************************************************************************/ /*!
+@File pvrsrv_errors.h
+@Title services error codes
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines error codes used by any/all services modules
+@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.
+*/ /**************************************************************************/
+
+/* Don't add include guards to this file! */
+
+PVRE(PVRSRV_ERROR_OUT_OF_MEMORY)
+PVRE(PVRSRV_ERROR_TOO_FEW_BUFFERS)
+PVRE(PVRSRV_ERROR_INVALID_PARAMS)
+PVRE(PVRSRV_ERROR_INIT_FAILURE)
+PVRE(PVRSRV_ERROR_CANT_REGISTER_CALLBACK)
+PVRE(PVRSRV_ERROR_INVALID_DEVICE)
+PVRE(PVRSRV_ERROR_NOT_OWNER)
+PVRE(PVRSRV_ERROR_BAD_MAPPING)
+PVRE(PVRSRV_ERROR_TIMEOUT)
+PVRE(PVRSRV_ERROR_NOT_IMPLEMENTED)
+PVRE(PVRSRV_ERROR_FLIP_CHAIN_EXISTS)
+PVRE(PVRSRV_ERROR_INVALID_SWAPINTERVAL)
+PVRE(PVRSRV_ERROR_SCENE_INVALID)
+PVRE(PVRSRV_ERROR_STREAM_ERROR)
+PVRE(PVRSRV_ERROR_FAILED_DEPENDENCIES)
+PVRE(PVRSRV_ERROR_CMD_NOT_PROCESSED)
+PVRE(PVRSRV_ERROR_CMD_TOO_BIG)
+PVRE(PVRSRV_ERROR_DEVICE_REGISTER_FAILED)
+PVRE(PVRSRV_ERROR_TOOMANYBUFFERS)
+PVRE(PVRSRV_ERROR_NOT_SUPPORTED)
+PVRE(PVRSRV_ERROR_PROCESSING_BLOCKED)
+PVRE(PVRSRV_ERROR_CANNOT_FLUSH_QUEUE)
+PVRE(PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+PVRE(PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS)
+PVRE(PVRSRV_ERROR_RETRY)
+PVRE(PVRSRV_ERROR_DDK_VERSION_MISMATCH)
+PVRE(PVRSRV_ERROR_DDK_BUILD_MISMATCH)
+PVRE(PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH)
+PVRE(PVRSRV_ERROR_BVNC_MISMATCH)
+PVRE(PVRSRV_ERROR_META_MISMATCH)
+PVRE(PVRSRV_ERROR_UPLOAD_TOO_BIG)
+PVRE(PVRSRV_ERROR_INVALID_FLAGS)
+PVRE(PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS)
+PVRE(PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY)
+PVRE(PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR)
+PVRE(PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED)
+PVRE(PVRSRV_ERROR_BRIDGE_CALL_FAILED)
+PVRE(PVRSRV_ERROR_IOCTL_CALL_FAILED)
+PVRE(PVRSRV_ERROR_MMU_API_PROTOCOL_ERROR)
+PVRE(PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND)
+PVRE(PVRSRV_ERROR_MMU_FAILED_TO_ALLOCATE_PAGETABLES)
+PVRE(PVRSRV_ERROR_MMU_FAILED_TO_CREATE_HEAP)
+PVRE(PVRSRV_ERROR_MMU_FAILED_TO_MAP_PAGE_TABLE)
+PVRE(PVRSRV_ERROR_MMU_FAILED_TO_UNMAP_PAGE_TABLE)
+PVRE(PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE)
+PVRE(PVRSRV_ERROR_MMU_LIVE_ALLOCATIONS_IN_HEAP)
+PVRE(PVRSRV_ERROR_MMU_RESERVATION_NOT_INSIDE_HEAP)
+PVRE(PVRSRV_ERROR_PMR_CLIENT_NOT_TRUSTED)
+PVRE(PVRSRV_ERROR_PMR_FAILED_TO_ALLOC_PAGES)
+PVRE(PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY)
+PVRE(PVRSRV_ERROR_PMR_MISMATCHED_ATTRIBUTES)
+PVRE(PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE)
+PVRE(PVRSRV_ERROR_PMR_NOT_PERMITTED)
+PVRE(PVRSRV_ERROR_PMR_PMR_ALREADY_OCCUPIED)
+PVRE(PVRSRV_ERROR_PMR_UNRECOVERABLE_ERROR)
+PVRE(PVRSRV_ERROR_PMR_WRONG_PASSWORD_OR_STALE_PMR)
+PVRE(PVRSRV_ERROR_PMR_WRONG_PMR_TYPE)
+PVRE(PVRSRV_ERROR_PMR_HAS_BEEN_MAPPED)
+PVRE(PVRSRV_ERROR_PMR_BAD_MAPPINGTABLE_SIZE)
+PVRE(PVRSRV_ERROR_PMR_BAD_CHUNK_SIZE)
+PVRE(PVRSRV_ERROR_PMR_MAPPINGTABLE_MISMATCH)
+PVRE(PVRSRV_ERROR_PMR_INVALID_CHUNK)
+PVRE(PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING)
+PVRE(PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP)
+PVRE(PVRSRV_ERROR_DEVICEMEM_BAD_IMPORT_SIZE)
+PVRE(PVRSRV_ERROR_DEVICEMEM_CANT_EXPORT_SUBALLOCATION)
+PVRE(PVRSRV_ERROR_DEVICEMEM_INVALID_HEAP_CONFIG_INDEX)
+PVRE(PVRSRV_ERROR_DEVICEMEM_INVALID_HEAP_INDEX)
+PVRE(PVRSRV_ERROR_DEVICEMEM_MAP_FAILED)
+PVRE(PVRSRV_ERROR_DEVICEMEM_NON_ZERO_USAGE_COUNT)
+PVRE(PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE)
+PVRE(PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA)
+PVRE(PVRSRV_ERROR_DEVICEMEM_OUT_OF_DEVICE_VM)
+PVRE(PVRSRV_ERROR_DEVICEMEM_ALREADY_MAPPED)
+PVRE(PVRSRV_ERROR_DEVICEMEM_NO_MAPPING)
+PVRE(PVRSRV_ERROR_DEVICEMEM_INVALID_PMR_FLAGS)
+PVRE(PVRSRV_ERROR_INVALID_MMU_TYPE)
+PVRE(PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND)
+PVRE(PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT)
+PVRE(PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND)
+PVRE(PVRSRV_ERROR_PCI_CALL_FAILED)
+PVRE(PVRSRV_ERROR_PCI_REGION_TOO_SMALL)
+PVRE(PVRSRV_ERROR_PCI_REGION_UNAVAILABLE)
+PVRE(PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH)
+PVRE(PVRSRV_ERROR_REGISTER_BASE_NOT_SET)
+PVRE(PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM)
+PVRE(PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY)
+PVRE(PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC)
+PVRE(PVRSRV_ERROR_FAILED_TO_MAP_KERNELVIRTUAL)
+PVRE(PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR)
+PVRE(PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY)
+PVRE(PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY)
+PVRE(PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES)
+PVRE(PVRSRV_ERROR_FAILED_TO_FREE_PAGES)
+PVRE(PVRSRV_ERROR_FAILED_TO_COPY_PAGES)
+PVRE(PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES)
+PVRE(PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES)
+PVRE(PVRSRV_ERROR_STILL_MAPPED)
+PVRE(PVRSRV_ERROR_MAPPING_NOT_FOUND)
+PVRE(PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT)
+PVRE(PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE)
+PVRE(PVRSRV_ERROR_INVALID_SEGMENT_BLOCK)
+PVRE(PVRSRV_ERROR_INVALID_GFXDEVDEVDATA)
+PVRE(PVRSRV_ERROR_INVALID_DEVINFO)
+PVRE(PVRSRV_ERROR_INVALID_MEMINFO)
+PVRE(PVRSRV_ERROR_INVALID_MISCINFO)
+PVRE(PVRSRV_ERROR_UNKNOWN_IOCTL)
+PVRE(PVRSRV_ERROR_INVALID_CONTEXT)
+PVRE(PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT)
+PVRE(PVRSRV_ERROR_INVALID_HEAP)
+PVRE(PVRSRV_ERROR_INVALID_KERNELINFO)
+PVRE(PVRSRV_ERROR_UNKNOWN_POWER_STATE)
+PVRE(PVRSRV_ERROR_INVALID_HANDLE_TYPE)
+PVRE(PVRSRV_ERROR_INVALID_WRAP_TYPE)
+PVRE(PVRSRV_ERROR_INVALID_PHYS_ADDR)
+PVRE(PVRSRV_ERROR_INVALID_CPU_ADDR)
+PVRE(PVRSRV_ERROR_INVALID_HEAPINFO)
+PVRE(PVRSRV_ERROR_INVALID_PERPROC)
+PVRE(PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO)
+PVRE(PVRSRV_ERROR_INVALID_MAP_REQUEST)
+PVRE(PVRSRV_ERROR_INVALID_UNMAP_REQUEST)
+PVRE(PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP)
+PVRE(PVRSRV_ERROR_MAPPING_STILL_IN_USE)
+PVRE(PVRSRV_ERROR_EXCEEDED_HW_LIMITS)
+PVRE(PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED)
+PVRE(PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA)
+PVRE(PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT)
+PVRE(PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT)
+PVRE(PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT)
+PVRE(PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT)
+PVRE(PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD)
+PVRE(PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD)
+PVRE(PVRSRV_ERROR_THREAD_READ_ERROR)
+PVRE(PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER)
+PVRE(PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR)
+PVRE(PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR)
+PVRE(PVRSRV_ERROR_ISR_ALREADY_INSTALLED)
+PVRE(PVRSRV_ERROR_ISR_NOT_INSTALLED)
+PVRE(PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT)
+PVRE(PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO)
+PVRE(PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT)
+PVRE(PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES)
+PVRE(PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT)
+PVRE(PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE)
+PVRE(PVRSRV_ERROR_INVALID_CCB_COMMAND)
+PVRE(PVRSRV_ERROR_KERNEL_CCB_FULL)
+PVRE(PVRSRV_ERROR_FLIP_FAILED)
+PVRE(PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED)
+PVRE(PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE)
+PVRE(PVRSRV_ERROR_TIMEOUT_WAITING_FOR_CLIENT_CCB)
+PVRE(PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED)
+PVRE(PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG)
+PVRE(PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG)
+PVRE(PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG)
+PVRE(PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID)
+PVRE(PVRSRV_ERROR_BLIT_SETUP_FAILED)
+PVRE(PVRSRV_ERROR_SUBMIT_NEEDED)
+PVRE(PVRSRV_ERROR_PDUMP_NOT_AVAILABLE)
+PVRE(PVRSRV_ERROR_PDUMP_BUFFER_FULL)
+PVRE(PVRSRV_ERROR_PDUMP_BUF_OVERFLOW)
+PVRE(PVRSRV_ERROR_PDUMP_NOT_ACTIVE)
+PVRE(PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES)
+PVRE(PVRSRV_ERROR_MUTEX_DESTROY_FAILED)
+PVRE(PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR)
+PVRE(PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE)
+PVRE(PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND)
+PVRE(PVRSRV_ERROR_PROCESS_NOT_INITIALISED)
+PVRE(PVRSRV_ERROR_PROCESS_NOT_FOUND)
+PVRE(PVRSRV_ERROR_SRV_CONNECT_FAILED)
+PVRE(PVRSRV_ERROR_SRV_DISCONNECT_FAILED)
+PVRE(PVRSRV_ERROR_DEINT_PHASE_FAILED)
+PVRE(PVRSRV_ERROR_INIT2_PHASE_FAILED)
+PVRE(PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE)
+PVRE(PVRSRV_ERROR_NO_DC_DEVICES_FOUND)
+PVRE(PVRSRV_ERROR_DC_INVALID_MAXDEPTH)
+PVRE(PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_UNREGISTER_DEVICE)
+PVRE(PVRSRV_ERROR_NO_DEVICEDATA_FOUND)
+PVRE(PVRSRV_ERROR_NO_DEVICENODE_FOUND)
+PVRE(PVRSRV_ERROR_NO_CLIENTNODE_FOUND)
+PVRE(PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_INIT_TASK)
+PVRE(PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK)
+PVRE(PVRSRV_ERROR_UNABLE_TO_KILL_TASK)
+PVRE(PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER)
+PVRE(PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER)
+PVRE(PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER)
+PVRE(PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT)
+PVRE(PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION)
+PVRE(PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE)
+PVRE(PVRSRV_ERROR_HANDLE_NOT_ALLOCATED)
+PVRE(PVRSRV_ERROR_HANDLE_TYPE_MISMATCH)
+PVRE(PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE)
+PVRE(PVRSRV_ERROR_HANDLE_NOT_SHAREABLE)
+PVRE(PVRSRV_ERROR_HANDLE_NOT_FOUND)
+PVRE(PVRSRV_ERROR_INVALID_SUBHANDLE)
+PVRE(PVRSRV_ERROR_HANDLE_BATCH_IN_USE)
+PVRE(PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE)
+PVRE(PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED)
+PVRE(PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP)
+PVRE(PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE)
+PVRE(PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVAILABLE)
+PVRE(PVRSRV_ERROR_INVALID_DEVICEID)
+PVRE(PVRSRV_ERROR_DEVICEID_NOT_FOUND)
+PVRE(PVRSRV_ERROR_MEMORY_TEST_FAILED)
+PVRE(PVRSRV_ERROR_CPUPADDR_TEST_FAILED)
+PVRE(PVRSRV_ERROR_COPY_TEST_FAILED)
+PVRE(PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED)
+PVRE(PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK)
+PVRE(PVRSRV_ERROR_CLOCK_REQUEST_FAILED)
+PVRE(PVRSRV_ERROR_DISABLE_CLOCK_FAILURE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK)
+PVRE(PVRSRV_ERROR_UNABLE_TO_GET_CLOCK)
+PVRE(PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK)
+PVRE(PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK)
+PVRE(PVRSRV_ERROR_UNKNOWN_SGL_ERROR)
+PVRE(PVRSRV_ERROR_SYSTEM_POWER_CHANGE_FAILURE)
+PVRE(PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE)
+PVRE(PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED)
+PVRE(PVRSRV_ERROR_BAD_SYNC_STATE)
+PVRE(PVRSRV_ERROR_CACHEOP_FAILED)
+PVRE(PVRSRV_ERROR_UNABLE_TO_SET_CACHE_MODE)
+PVRE(PVRSRV_ERROR_FAILED_TO_ALLOC_MMUCONTEXT_ID)
+PVRE(PVRSRV_ERROR_PARAMETER_BUFFER_INVALID_ALIGNMENT)
+PVRE(PVRSRV_ERROR_UNABLE_TO_ACQUIRE_CONNECTION)
+PVRE(PVRSRV_ERROR_UNABLE_TO_RELEASE_CONNECTION)
+PVRE(PVRSRV_ERROR_PHYSHEAP_ID_IN_USE)
+PVRE(PVRSRV_ERROR_PHYSHEAP_ID_INVALID)
+PVRE(PVRSRV_ERROR_HP_REQUEST_TOO_LONG)
+PVRE(PVRSRV_ERROR_INVALID_SYNC_PRIM)
+PVRE(PVRSRV_ERROR_INVALID_SYNC_PRIM_OP)
+PVRE(PVRSRV_ERROR_INVALID_SYNC_CONTEXT)
+PVRE(PVRSRV_ERROR_BP_NOT_SET)
+PVRE(PVRSRV_ERROR_BP_ALREADY_SET)
+PVRE(PVRSRV_ERROR_REG_CONFIG_FEATURE_DISABLED)
+PVRE(PVRSRV_ERROR_REG_CONFIG_ENABLED)
+PVRE(PVRSRV_ERROR_REG_CONFIG_FULL)
+PVRE(PVRSRV_ERROR_REG_CONFIG_INVALID_PI)
+PVRE(PVRSRV_ERROR_MEMORY_ACCESS)
+PVRE(PVRSRV_ERROR_NO_SYSTEM_BUFFER)
+PVRE(PVRSRV_ERROR_DC_INVALID_CONFIG)
+PVRE(PVRSRV_ERROR_DC_INVALID_CROP_RECT)
+PVRE(PVRSRV_ERROR_DC_INVALID_DISPLAY_RECT)
+PVRE(PVRSRV_ERROR_DC_INVALID_BUFFER_DIMS)
+PVRE(PVRSRV_ERROR_DC_INVALID_TRANSFORM)
+PVRE(PVRSRV_ERROR_DC_INVALID_SCALE)
+PVRE(PVRSRV_ERROR_DC_INVALID_CUSTOM)
+PVRE(PVRSRV_ERROR_DC_TOO_MANY_PIPES)
+PVRE(PVRSRV_ERROR_DC_INVALID_PLANE_ALPHA)
+PVRE(PVRSRV_ERROR_NOT_READY)
+PVRE(PVRSRV_ERROR_RESOURCE_UNAVAILABLE)
+PVRE(PVRSRV_ERROR_UNSUPPORTED_PIXEL_FORMAT)
+PVRE(PVRSRV_ERROR_UNSUPPORTED_DIMS)
+PVRE(PVRSRV_ERROR_UNSUPPORTED_CACHE_MODE)
+PVRE(PVRSRV_ERROR_UNABLE_TO_ADD_TIMER)
+PVRE(PVRSRV_ERROR_NOT_FOUND)
+PVRE(PVRSRV_ERROR_ALREADY_OPEN)
+PVRE(PVRSRV_ERROR_STREAM_MISUSE)
+PVRE(PVRSRV_ERROR_STREAM_FULL)
+PVRE(PVRSRV_ERROR_PHYSMEM_NOT_ALLOCATED)
+PVRE(PVRSRV_ERROR_PBSIZE_ALREADY_MAX)
+PVRE(PVRSRV_ERROR_PBSIZE_ALREADY_MIN)
+PVRE(PVRSRV_ERROR_INVALID_PB_CONFIG)
+PVRE(PVRSRV_ERROR_META_THREAD0_NOT_ENABLED)
+PVRE(PVRSRV_ERROR_NOT_AUTHENTICATED)
+PVRE(PVRSRV_ERROR_REQUEST_TDMETACODE_PAGES_FAIL)
+PVRE(PVRSRV_ERROR_INIT_TDMETACODE_PAGES_FAIL)
+PVRE(PVRSRV_ERROR_MAP_TDMETACODE_PAGES_FAIL)
+PVRE(PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL)
+PVRE(PVRSRV_ERROR_INIT_TDSECUREBUF_PAGES_FAIL)
+PVRE(PVRSRV_ERROR_MAP_TDSECUREBUF_PAGES_FAIL)
+PVRE(PVRSRV_ERROR_MUTEX_ALREADY_CREATED)
+PVRE(PVRSRV_ERROR_DBGTABLE_ALREADY_REGISTERED)
+PVRE(PVRSRV_ERROR_ALREADY_EXISTS)
+PVRE(PVRSRV_ERROR_UNABLE_TO_SEND_PULSE)
+PVRE(PVRSRV_ERROR_TASK_FAILED)
+PVRE(PVRSRV_ERROR_INVALID_OFFSET)
+PVRE(PVRSRV_ERROR_CCCB_STALLED)
diff --git a/drivers/gpu/rogue/include/pvrsrv_memallocflags.h b/drivers/gpu/rogue/include/pvrsrv_memallocflags.h
new file mode 100644
index 000000000000..a14ea54c5ae6
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvrsrv_memallocflags.h
@@ -0,0 +1,492 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This file defines flags used on memory allocations and mappings
+ These flags are relevant throughout the memory management
+ software stack and are specified by users of services and
+ understood by all levels of the memory management in both
+ client and server.
+@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_MEMALLOCFLAGS_H
+#define PVRSRV_MEMALLOCFLAGS_H
+
+#include "img_types.h"
+#if defined(SUPPORT_RGX)
+#include "rgx_memallocflags.h"
+#endif
+typedef IMG_UINT32 PVRSRV_MEMALLOCFLAGS_T;
+
+/*!
+ * **********************************************************
+ * * *
+ * * MAPPING FLAGS *
+ * * *
+ * **********************************************************
+ *
+ * PVRSRV_MEMALLOCFLAG_GPU_READABLE
+ *
+ * This flag affects the device MMU protection flags, and specifies
+ * that the memory may be read by the GPU (is this always true?)
+ *
+ * Typically all device memory allocations would specify this flag.
+ *
+ * At the moment, memory allocations without this flag are not supported
+ *
+ * This flag will live with the PMR, thus subsequent mappings would
+ * honour this flag.
+ *
+ * This is a dual purpose flag. It specifies that memory is permitted
+ * to be read by the GPU, and also requests that the allocation is
+ * mapped into the GPU as a readable mapping
+ *
+ * To be clear:
+ * - When used as an argument on PMR creation; it specifies
+ * that GPU readable mappings will be _permitted_
+ * - When used as an argument to a "map" function: it specifies
+ * that a GPU readable mapping is _desired_
+ * - When used as an argument to "AllocDeviceMem": it specifies
+ * that the PMR will be created with permission to be mapped
+ * with a GPU readable mapping, _and_ that this PMR will be
+ * mapped with a GPU readble mapping.
+ * This distinction becomes important when (a) we export allocations;
+ * and (b) when we separate the creation of the PMR from the mapping.
+ */
+#define PVRSRV_MEMALLOCFLAG_GPU_READABLE (1U<<0)
+
+/*!
+ * PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE
+ *
+ * This flag affects the device MMU protection flags, and specifies
+ * that the memory may be written by the GPU
+ *
+ * Using this flag on an allocation signifies that the allocation is
+ * intended to be written by the GPU.
+ *
+ * Omitting this flag causes a read-only mapping.
+ *
+ * This flag will live with the PMR, thus subsequent mappings would
+ * honour this flag.
+ *
+ * This is a dual purpose flag. It specifies that memory is permitted
+ * to be written by the GPU, and also requests that the allocation is
+ * mapped into the GPU as a writeable mapping (see note above about
+ * permission vs. mapping mode, and why this flag causes permissions
+ * to be inferred from mapping mode on first allocation)
+ *
+ * N.B. This flag has no relevance to the CPU's MMU mapping, if any,
+ * and would therefore not enforce read-only mapping on CPU.
+ */
+#define PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE (1U<<1) /*!< mapped as writeable to the GPU */
+#define PVRSRV_MEMALLOCFLAG_GPU_READ_PERMITTED (1U<<2) /*!< can be mapped is GPU readable in another GPU mem context */
+#define PVRSRV_MEMALLOCFLAG_GPU_WRITE_PERMITTED (1U<<3) /*!< can be mapped is GPU writable in another GPU mem context */
+
+#define PVRSRV_MEMALLOCFLAG_CPU_READABLE (1U<<4) /*!< mapped as readable to the CPU */
+#define PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE (1U<<5) /*!< mapped as writeable to the CPU */
+#define PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED (1U<<6) /*!< can be mapped is CPU readable in another CPU mem context */
+#define PVRSRV_MEMALLOCFLAG_CPU_WRITE_PERMITTED (1U<<7) /*!< can be mapped is CPU writable in another CPU mem context */
+
+
+/*
+ * **********************************************************
+ * * *
+ * * CACHE CONTROL FLAGS *
+ * * *
+ * **********************************************************
+ */
+
+/*
+ GPU domain
+ ==========
+
+ The following defines are used to control the GPU cache bit field.
+ The defines are mutually exclusive.
+
+ A helper macro, GPU_CACHE_MODE, is provided to obtain just the GPU cache
+ bit field from the flags. This should be used whenever the GPU cache mode
+ needs to be determined.
+*/
+
+/*!
+ GPU domain. Request uncached memory. This means that any writes to memory
+ allocated with this flag are written straight to memory and thus are coherent
+ for any device in the system.
+*/
+#define PVRSRV_MEMALLOCFLAG_GPU_UNCACHED (0U<<8)
+
+/*!
+ GPU domain. Use write combiner (if supported) to combine sequential writes
+ together to reduce memory access by doing burst writes.
+*/
+#define PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE (1U<<8)
+/*!
+ GPU domain. This flag affects the device MMU protection flags.
+
+ This flag ensures that the GPU and the CPU will always be coherent.
+ This is done by either by snooping each others caches or, if this is
+ not supported, by making the allocation uncached. Please note that
+ this will _not_ guaranty coherency with memory so if this memory
+ is accessed by another device (eg display controller) a flush will
+ be required.
+*/
+#define PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT (2U<<8)
+
+/*!
+ GPU domain. Request cached memory, but not coherent (i.e. no cache snooping).
+ This means that if the allocation needs to transition from one device
+ to another services has to be informed so it can flush/invalidate the
+ appropriate caches.
+
+ Note: We reserve 3 bits in the CPU/GPU cache mode to allow for future
+ expansion.
+*/
+#define PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT (3U<<8)
+
+/*!
+ GPU domain.
+
+ Request cached cached coherent memory. This is like
+ PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT but doesn't fall back on
+ uncached memory if the system doesn't support cache-snooping
+ but rather returns an error.
+*/
+#define PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT (4U<<8)
+
+/*!
+ GPU domain.
+
+ This flag is for internal use only and is used to indicate
+ that the underlying allocation should be cached on the GPU
+ after all the snooping and coherent checks have been done
+*/
+#define PVRSRV_MEMALLOCFLAG_GPU_CACHED (7U<<8)
+
+/*!
+ GPU domain.
+
+ GPU cache mode mask
+*/
+#define PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK (7U<<8)
+
+#define GPU_CACHE_MODE(n) (n & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK)
+
+
+/*
+ CPU domain
+ ==========
+
+ The following defines are used to control the CPU cache bit field.
+ The defines are mutually exclusive.
+
+ A helper macro, CPU_CACHE_MODE, is provided to obtain just the CPU cache
+ bit field from the flags. This should be used whenever the CPU cache mode
+ needs to be determined.
+*/
+
+/*!
+ CPU domain. Request uncached memory. This means that any writes to memory
+ allocated with this flag are written straight to memory and thus are coherent
+ for any device in the system.
+*/
+#define PVRSRV_MEMALLOCFLAG_CPU_UNCACHED (0U<<11)
+
+/*!
+ CPU domain. Use write combiner (if supported) to combine sequential writes
+ together to reduce memory access by doing burst writes.
+*/
+#define PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE (1U<<11)
+
+/*!
+ CPU domain. This flag affects the device MMU protection flags.
+
+ This flag ensures that the GPU and the CPU will always be coherent.
+ This is done by either by snooping each others caches or, if this is
+ not supported, by making the allocation uncached. Please note that
+ this will _not_ guaranty coherency with memory so if this memory
+ is accessed by another device (eg display controller) a flush will
+ be required.
+*/
+#define PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT (2U<<11)
+
+/*!
+ CPU domain. Request cached memory, but not coherent (i.e. no cache snooping).
+ This means that if the allocation needs to transition from one device
+ to another services has to be informed so it can flush/invalidate the
+ appropriate caches.
+
+ Note: We reserve 3 bits in the CPU/GPU cache mode to allow for future
+ expansion.
+*/
+#define PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT (3U<<11)
+
+/*!
+ CPU domain.
+
+ Request cached cached coherent memory. This is like
+ PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT but doesn't fall back on
+ uncached memory if the system doesn't support cache-snooping
+ but rather returns an error.
+*/
+#define PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT (4U<<11)
+
+
+/*!
+ CPU domain.
+
+ This flag is for internal use only and is used to indicate
+ that the underlying allocation should be cached on the CPU
+ after all the snooping and coherent checks have been done
+*/
+#define PVRSRV_MEMALLOCFLAG_CPU_CACHED (7U<<11)
+
+/*!
+ CPU domain.
+
+ CPU cache mode mask
+*/
+#define PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK (7U<<11)
+
+#define CPU_CACHE_MODE(n) (n & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK)
+
+/* Helper flags for usual cases */
+#define PVRSRV_MEMALLOCFLAG_UNCACHED (PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | PVRSRV_MEMALLOCFLAG_CPU_UNCACHED) /*!< Memory will be uncached */
+#define PVRSRV_MEMALLOCFLAG_WRITE_COMBINE (PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE | PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE) /*!< Memory will be write-combined */
+#define PVRSRV_MEMALLOCFLAG_CACHE_COHERENT (PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT | PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT) /*!< Memory will be cache-coherent */
+#define PVRSRV_MEMALLOCFLAG_CACHE_INCOHERENT (PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT | PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT) /*!< Memory will be cache-incoherent */
+
+/*!
+ CPU MMU Flags mask -- intended for use internal to services only
+ */
+#define PVRSRV_MEMALLOCFLAGS_CPU_MMUFLAGSMASK (PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+ PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK)
+
+/*!
+ MMU Flags mask -- intended for use internal to services only - used
+ for partitioning the flags bits and determining which flags to pass
+ down to mmu_common.c
+ */
+#define PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK (PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+ PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK)
+
+/*!
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE
+
+ Indicates that the PMR created due to this allocation will support
+ in-kernel CPU mappings. Only privileged processes may use this
+ flag as it may cause wastage of precious kernel virtual memory on
+ some platforms.
+ */
+#define PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE (1U<<14)
+
+
+
+
+/*
+ *
+ * **********************************************************
+ * * *
+ * * ALLOC MEMORY FLAGS *
+ * * *
+ * **********************************************************
+ *
+ * (Bits 15)
+ *
+ */
+#define PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC (1U<<15)
+
+/*!
+ PVRSRV_MEMALLOCFLAG_CPU_LOCAL
+
+ Indicates that the allocation will primarily be accessed by
+ the CPU, so a UMA allocation (if available) is preferable.
+ If not set, the allocation will primarily be accessed by
+ the GPU, so LMA allocation (if available) is preferable.
+ */
+#define PVRSRV_MEMALLOCFLAG_CPU_LOCAL (1U<<16)
+
+/*
+ *
+ * **********************************************************
+ * * *
+ * * MEMORY ZEROING AND POISONING FLAGS *
+ * * *
+ * **********************************************************
+ *
+ * Zero / Poison, on alloc/free
+ *
+ * We think the following usecases are required:
+ *
+ * don't poison or zero on alloc or free
+ * (normal operation, also most efficient)
+ * poison on alloc
+ * (for helping to highlight bugs)
+ * poison on alloc and free
+ * (for helping to highlight bugs)
+ * zero on alloc
+ * (avoid highlighting security issues in other uses of memory)
+ * zero on alloc and poison on free
+ * (avoid highlighting security issues in other uses of memory,
+ * while helping to highlight a subset of bugs e.g. memory
+ * freed prematurely)
+ *
+ * Since there are more than 4, we can't encode this in just two bits,
+ * so we might as well have a separate flag for each of the three
+ * actions.
+ */
+
+/*!
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC
+ Ensures that the memory allocated is initialized with zeroes.
+ */
+#define PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC (1U<<31)
+
+/*!
+ VRSRV_MEMALLOCFLAG_POISON_ON_ALLOC
+
+ Scribbles over the allocated memory with a poison value
+
+ Not compatible with ZERO_ON_ALLOC
+
+ Poisoning is very deliberately _not_ reflected in PDump as we want
+ a simulation to cry loudly if the initialised data propogates to a
+ result.
+ */
+#define PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC (1U<<30)
+
+/*!
+ PVRSRV_MEMALLOCFLAG_POISON_ON_FREE
+
+ Causes memory to be trashed when freed, as a lazy man's security
+ measure.
+ */
+#define PVRSRV_MEMALLOCFLAG_POISON_ON_FREE (1U<<29)
+
+/*
+ *
+ * **********************************************************
+ * * *
+ * * Device specific MMU flags *
+ * * *
+ * **********************************************************
+ *
+ * (Bits 24 to 27)
+ *
+ * Some services controled devices have device specific control
+ * bits in their page table entries, we need to allow these flags
+ * to be passed down the memory managament layers so the user
+ * can control these bits.
+ */
+
+#define PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_OFFSET 24
+#define PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK 0x0f000000UL
+#define PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(n) \
+ (((n) << PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_OFFSET) & \
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK)
+
+/*!
+ 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.
+*/
+#define PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK (PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK | \
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+ PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC | \
+ PVRSRV_MEMALLOCFLAG_POISON_ON_FREE | \
+ PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK | \
+ PVRSRV_MEMALLOCFLAGS_CPU_MMUFLAGSMASK | \
+ PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC | \
+ PVRSRV_MEMALLOCFLAG_CPU_LOCAL)
+
+#if ((~(PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK) & PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK) != 0)
+#error PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK is not a subset of PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK
+#endif
+
+/*!
+ RA differentiation mask
+
+ for use internal to services
+
+ this is the set of flags bits that are able to determine whether a
+ pair of allocations are permitted to live in the same page table.
+ Allocations whose flags differ in any of these places would be
+ allocated from separate RA Imports and therefore would never coexist
+ in the same page
+*/
+#define PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK (PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+ PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK | \
+ PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK | \
+ PVRSRV_MEMALLOCFLAG_POISON_ON_FREE | \
+ PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK | \
+ PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
+
+#if ((~(PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK) & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK) != 0)
+#error PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK is not a subset of PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK
+#endif
+
+/*!
+ Flags that affect _allocation_
+*/
+#define PVRSRV_MEMALLOCFLAGS_PERALLOCFLAGSMASK (0xFFFFFFFFU)
+
+/*!
+ Flags that affect _mapping_
+*/
+#define PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK (PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK | \
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+ PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK | \
+ PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK | \
+ PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
+
+#if ((~(PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK) & PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK) != 0)
+#error PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK is not a subset of PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK
+#endif
+
+#endif /* #ifndef PVRSRV_MEMALLOCFLAGS_H */
+
diff --git a/drivers/gpu/rogue/include/pvrsrv_surface.h b/drivers/gpu/rogue/include/pvrsrv_surface.h
new file mode 100644
index 000000000000..fdd1328b1aa2
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvrsrv_surface.h
@@ -0,0 +1,150 @@
+/*************************************************************************/ /*!
+@File
+@Title Device class external
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines DC specific structures which are externally visible
+ (i.e. visible to clients of services), but are also required
+ within services.
+@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_SURFACE_H_
+#define _PVRSRV_SURFACE_H_
+
+#include "img_types.h"
+#include "fbc_types.h"
+
+#define PVRSRV_SURFACE_TRANSFORM_NONE (0 << 0)
+#define PVRSRV_SURFACE_TRANSFORM_FLIP_H (1 << 0)
+#define PVRSRV_SURFACE_TRANSFORM_FLIP_V (1 << 1)
+#define PVRSRV_SURFACE_TRANSFORM_ROT_90 (1 << 2)
+#define PVRSRV_SURFACE_TRANSFORM_ROT_180 ((1 << 0) + (1 << 1))
+#define PVRSRV_SURFACE_TRANSFORM_ROT_270 ((1 << 0) + (1 << 1) + (1 << 2))
+
+#define PVRSRV_SURFACE_BLENDING_NONE 0
+#define PVRSRV_SURFACE_BLENDING_PREMULT 1
+#define PVRSRV_SURFACE_BLENDING_COVERAGE 2
+
+typedef enum _PVRSRV_SURFACE_MEMLAYOUT_ {
+ PVRSRV_SURFACE_MEMLAYOUT_STRIDED = 0, /*!< Strided memory buffer */
+ PVRSRV_SURFACE_MEMLAYOUT_FBC, /*!< Frame buffer compressed buffer */
+ PVRSRV_SURFACE_MEMLAYOUT_BIF_PAGE_TILED, /*!< BIF page tiled buffer */
+} PVRSRV_SURFACE_MEMLAYOUT;
+
+typedef struct _PVRSRV_SURFACE_FBC_LAYOUT_ {
+ FB_COMPRESSION eFBCompressionMode;
+} PVRSRV_SURFACE_FBC_LAYOUT;
+
+typedef struct _PVRSRV_SURFACE_FORMAT_
+{
+ IMG_UINT32 ePixFormat;
+ PVRSRV_SURFACE_MEMLAYOUT eMemLayout;
+ union {
+ PVRSRV_SURFACE_FBC_LAYOUT sFBCLayout;
+ } u;
+} PVRSRV_SURFACE_FORMAT;
+
+typedef struct _PVRSRV_SURFACE_DIMS_
+{
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+} PVRSRV_SURFACE_DIMS;
+
+typedef struct _PVRSRV_SURFACE_INFO_
+{
+ PVRSRV_SURFACE_DIMS sDims;
+ PVRSRV_SURFACE_FORMAT sFormat;
+} PVRSRV_SURFACE_INFO;
+
+typedef struct _PVRSRV_SURFACE_RECT_
+{
+ IMG_INT32 i32XOffset;
+ IMG_INT32 i32YOffset;
+ PVRSRV_SURFACE_DIMS sDims;
+} PVRSRV_SURFACE_RECT;
+
+typedef struct _PVRSRV_SURFACE_CONFIG_INFO_
+{
+ /*!< Crop applied to surface (BEFORE transformation) */
+ PVRSRV_SURFACE_RECT sCrop;
+
+ /*!< Region of screen to display surface in (AFTER scaling) */
+ PVRSRV_SURFACE_RECT sDisplay;
+
+ /*!< Surface rotation / flip / mirror */
+ IMG_UINT32 ui32Transform;
+
+ /*!< Alpha blending mode e.g. none / premult / coverage */
+ IMG_UINT32 eBlendType;
+
+ /*!< Custom data for the display engine */
+ IMG_UINT32 ui32Custom;
+
+ /*!< Plane alpha */
+ IMG_UINT8 ui8PlaneAlpha;
+ IMG_UINT8 ui8Reserved1[3];
+} PVRSRV_SURFACE_CONFIG_INFO;
+
+typedef struct _PVRSRV_PANEL_INFO_
+{
+ PVRSRV_SURFACE_INFO sSurfaceInfo;
+ IMG_UINT32 ui32RefreshRate;
+ IMG_UINT32 ui32XDpi;
+ IMG_UINT32 ui32YDpi;
+} PVRSRV_PANEL_INFO;
+
+/*
+ Helper function to create a Config Info based on a Surface Info
+ to do a flip with no scale, transformation etc.
+*/
+static INLINE IMG_VOID SurfaceConfigFromSurfInfo(PVRSRV_SURFACE_INFO *psSurfaceInfo,
+ PVRSRV_SURFACE_CONFIG_INFO *psConfigInfo)
+{
+ psConfigInfo->sCrop.sDims = psSurfaceInfo->sDims;
+ psConfigInfo->sCrop.i32XOffset = 0;
+ psConfigInfo->sCrop.i32YOffset = 0;
+ psConfigInfo->sDisplay.sDims = psSurfaceInfo->sDims;
+ psConfigInfo->sDisplay.i32XOffset = 0;
+ psConfigInfo->sDisplay.i32YOffset = 0;
+ psConfigInfo->ui32Transform = PVRSRV_SURFACE_TRANSFORM_NONE;
+ psConfigInfo->eBlendType = PVRSRV_SURFACE_BLENDING_NONE;
+ psConfigInfo->ui32Custom = 0;
+ psConfigInfo->ui8PlaneAlpha = 0xff;
+}
+
+#endif /* _PVRSRV_SURFACE_H_ */
diff --git a/drivers/gpu/rogue/include/pvrversion.h b/drivers/gpu/rogue/include/pvrversion.h
new file mode 100755
index 000000000000..8310322605ee
--- /dev/null
+++ b/drivers/gpu/rogue/include/pvrversion.h
@@ -0,0 +1,74 @@
+/*************************************************************************/ /*!
+@File
+@Title Version numbers and strings.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Version numbers and strings for PVR Consumer services
+ components.
+@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 _PVRVERSION_H_
+#define _PVRVERSION_H_
+
+#define PVR_STR(X) #X
+#define PVR_STR2(X) PVR_STR(X)
+
+#define PVRVERSION_MAJ 1
+#define PVRVERSION_MIN 4
+
+#define PVRVERSION_FAMILY "rogueddk"
+#define PVRVERSION_BRANCHNAME "1.4"
+#define PVRVERSION_BUILD 3443629
+#define PVRVERSION_BSCONTROL "Rogue_DDK_Android_RSCompute"
+
+#define PVRVERSION_STRING "Rogue_DDK_Android_RSCompute rogueddk 1.4@" PVR_STR2(PVRVERSION_BUILD)
+#define PVRVERSION_STRING_SHORT "1.4@" PVR_STR2(PVRVERSION_BUILD) ""
+
+#define COPYRIGHT_TXT "Copyright (c) Imagination Technologies Ltd. All Rights Reserved."
+
+#define PVRVERSION_BUILD_HI 344
+#define PVRVERSION_BUILD_LO 3629
+#define PVRVERSION_STRING_NUMERIC PVR_STR2(PVRVERSION_MAJ) "." PVR_STR2(PVRVERSION_MIN) "." PVR_STR2(PVRVERSION_BUILD_HI) "." PVR_STR2(PVRVERSION_BUILD_LO)
+
+#define PVRVERSION_PACK(MAJ,MIN) ((((MAJ)&0xFFFF) << 16) | (((MIN)&0xFFFF) << 0))
+#define PVRVERSION_UNPACK_MAJ(VERSION) (((VERSION) >> 16) & 0xFFFF)
+#define PVRVERSION_UNPACK_MIN(VERSION) (((VERSION) >> 0) & 0xFFFF)
+
+//chenli:define rockchip version
+#define RKVERSION "L 0.10"
+#endif /* _PVRVERSION_H_ */
diff --git a/drivers/gpu/rogue/include/rgx_common.h b/drivers/gpu/rogue/include/rgx_common.h
new file mode 100644
index 000000000000..4e59c145c344
--- /dev/null
+++ b/drivers/gpu/rogue/include/rgx_common.h
@@ -0,0 +1,129 @@
+/*************************************************************************/ /*!
+@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_H_
+#define RGX_COMMON_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+
+/* Included to get the BVNC_KM_N defined and other feature defs */
+#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 (7)
+
+/*! Macro to test structure size alignment */
+#define RGX_FW_STRUCT_SIZE_ASSERT(_a) \
+ BLD_ASSERT((sizeof(_a)&RGX_FW_ALIGNMENT_LSB)==0, _a##struct_size)
+
+/*! Macro to test structure member alignment */
+#define RGX_FW_STRUCT_OFFSET_ASSERT(_a, _b) \
+ BLD_ASSERT((offsetof(_a, _b)&RGX_FW_ALIGNMENT_LSB)==0, _a##struct_offset)
+
+
+/*! The number of performance counters in each layout block */
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+#define RGX_HWPERF_CNTRS_IN_BLK 6
+#define RGX_HWPERF_CNTRS_IN_BLK_MIN 4
+#else
+#define RGX_HWPERF_CNTRS_IN_BLK 4
+#define RGX_HWPERF_CNTRS_IN_BLK_MIN 4
+#endif
+
+
+/*! The master definition for data masters known to the firmware of RGX.
+ * The DM in a V1 HWPerf packet uses this definition. */
+typedef enum _RGXFWIF_DM_
+{
+ RGXFWIF_DM_GP = 0,
+ RGXFWIF_DM_2D = 1,
+ RGXFWIF_DM_TA = 2,
+ RGXFWIF_DM_3D = 3,
+ RGXFWIF_DM_CDM = 4,
+#if defined(RGX_FEATURE_RAY_TRACING)
+ RGXFWIF_DM_RTU = 5,
+ RGXFWIF_DM_SHG = 6,
+#endif
+ RGXFWIF_DM_LAST,
+
+ RGXFWIF_DM_FORCE_I32 = 0x7fffffff /*!< Force enum to be at least 32-bits wide */
+} RGXFWIF_DM;
+
+#if defined(RGX_FEATURE_RAY_TRACING)
+#define RGXFWIF_DM_MAX_MTS 8
+#else
+#define RGXFWIF_DM_MAX_MTS 6
+#endif
+
+#if defined(RGX_FEATURE_RAY_TRACING)
+/* Maximum number of DM in use: GP, 2D, TA, 3D, CDM, SHG, RTU */
+#define RGXFWIF_DM_MAX (7)
+#else
+#define RGXFWIF_DM_MAX (5)
+#endif
+
+/* Min/Max number of HW DMs (all but GP) */
+#if defined(RGX_FEATURE_TLA)
+#define RGXFWIF_HWDM_MIN (1)
+#else
+#define RGXFWIF_HWDM_MIN (2)
+#endif
+#define RGXFWIF_HWDM_MAX (RGXFWIF_DM_MAX)
+
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* RGX_COMMON_H_ */
+
+/******************************************************************************
+ End of file
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/rgx_heaps.h b/drivers/gpu/rogue/include/rgx_heaps.h
new file mode 100644
index 000000000000..1472436db09a
--- /dev/null
+++ b/drivers/gpu/rogue/include/rgx_heaps.h
@@ -0,0 +1,85 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX heap definitions
+@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(__RGX_HEAPS_H__)
+#define __RGX_HEAPS_H__
+
+#include "km/rgxdefs_km.h"
+
+/* RGX Heap IDs, note: not all heaps are available to clients */
+/* N.B. Old heap identifiers are deprecated now that the old memory
+ management is. New heap identifiers should be suitably renamed */
+#define RGX_UNDEFINED_HEAP_ID (~0LU) /*!< RGX Undefined Heap ID */
+#define RGX_GENERAL_HEAP_ID 0 /*!< RGX General Heap ID */
+#define RGX_PDSCODEDATA_HEAP_ID 1 /*!< RGX PDS Code/Data Heap ID */
+//#define RGX_3DPARAMETERS_HEAP_ID 2 /*!< RGX 3D Parameters Heap ID */
+#define RGX_USCCODE_HEAP_ID 2 /*!< RGX USC Code Heap ID */
+#define RGX_FIRMWARE_HEAP_ID 3 /*!< RGX Firmware Heap ID */
+#define RGX_TQ3DPARAMETERS_HEAP_ID 4 /*!< RGX Firmware Heap ID */
+#define RGX_BIF_TILING_HEAP_1_ID 5 /*!< RGX BIF Tiling Heap 1 ID */
+#define RGX_BIF_TILING_HEAP_2_ID 6 /*!< RGX BIF Tiling Heap 2 ID */
+#define RGX_BIF_TILING_HEAP_3_ID 7 /*!< RGX BIF Tiling Heap 3 ID */
+#define RGX_BIF_TILING_HEAP_4_ID 8 /*!< RGX BIF Tiling Heap 4 ID */
+#define RGX_HWBRN37200_HEAP_ID 9 /*!< RGX HWBRN37200 */
+#define RGX_DOPPLER_HEAP_ID 10 /*!< Doppler Heap ID */
+#define RGX_DOPPLER_OVERFLOW_HEAP_ID 11 /*!< Doppler Overflow Heap ID */
+
+/*
+*/
+#define RGX_MAX_HEAP_ID (RGX_DOPPLER_OVERFLOW_HEAP_ID + 1) /*!< Max Valid Heap ID */
+
+/*
+ Identify heaps by their names
+*/
+#define RGX_GENERAL_HEAP_IDENT "General" /*!< RGX General Heap Identifier */
+#define RGX_PDSCODEDATA_HEAP_IDENT "PDS Code and Data" /*!< RGX PDS Code/Data Heap Identifier */
+#define RGX_USCCODE_HEAP_IDENT "USC Code" /*!< RGX USC Code Heap Identifier */
+#define RGX_TQ3DPARAMETERS_HEAP_IDENT "TQ3DParameters" /*!< RGX TQ 3D Parameters Heap Identifier */
+#define RGX_BIF_TILING_HEAP_1_IDENT "BIF Tiling Heap l" /*!< RGX BIF Tiling Heap 1 identifier */
+#define RGX_BIF_TILING_HEAP_2_IDENT "BIF Tiling Heap 2" /*!< RGX BIF Tiling Heap 2 identifier */
+#define RGX_BIF_TILING_HEAP_3_IDENT "BIF Tiling Heap 3" /*!< RGX BIF Tiling Heap 3 identifier */
+#define RGX_BIF_TILING_HEAP_4_IDENT "BIF Tiling Heap 4" /*!< RGX BIF Tiling Heap 4 identifier */
+#define RGX_DOPPLER_HEAP_IDENT "Doppler" /*!< Doppler Heap Identifier */
+#define RGX_DOPPLER_OVERFLOW_HEAP_IDENT "Doppler Overflow" /*!< Doppler Heap Identifier */
+
+#endif /* __RGX_HEAPS_H__ */
+
diff --git a/drivers/gpu/rogue/include/rgx_hwperf_km.h b/drivers/gpu/rogue/include/rgx_hwperf_km.h
new file mode 100644
index 000000000000..86b709c54370
--- /dev/null
+++ b/drivers/gpu/rogue/include/rgx_hwperf_km.h
@@ -0,0 +1,358 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX HWPerf 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_KM_H_
+#define RGX_HWPERF_KM_H_
+
+/*
+ * This header file holds the HWPerf related macros and types needed by the
+ * code in the Kernel Mode (KM) server/driver module and its content is
+ * intended to be suitable for distribution under a public software license.
+ * The definitions within are common and may be used in user-mode, kernel-mode
+ * and firmware compilation units.
+ */
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define RGX_HWPERF_V2_FORMAT 2
+
+#include "rgx_common.h"
+
+
+/******************************************************************************
+ * Data Stream Common Types
+ *****************************************************************************/
+
+/* 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. BLD_ASSERT() is used to check this.
+ */
+
+/*! Type used to encode the event that generated the HW performance packet.
+ * NOTE: When this type is updated the corresponding hwperfbin2json tool source
+ * needs to be updated as well. Also need to update the table in rgxhwperf.c.
+ * The RGX_HWPERF_EVENT_MASK_* macros will also need updating when adding new
+ * types.
+ */
+typedef enum
+{
+ RGX_HWPERF_INVALID = 0x00,
+ /* FW types 0x01..0x07 */
+ RGX_HWPERF_FW_BGSTART = 0x01,
+ RGX_HWPERF_FW_BGEND = 0x02,
+ RGX_HWPERF_FW_IRQSTART = 0x03,
+
+ RGX_HWPERF_FW_IRQEND = 0x04,
+ RGX_HWPERF_FW_DBGSTART = 0x05,
+ RGX_HWPERF_FW_DBGEND = 0x06,
+
+ /* HW types 0x08..0x18 */
+ RGX_HWPERF_HW_TAKICK = 0x08,
+ RGX_HWPERF_HW_TAFINISHED = 0x09,
+ RGX_HWPERF_HW_3DTQKICK = 0x0A,
+/* RGX_HWPERF_HW_3DTQFINISHED = 0x17, */
+/* RGX_HWPERF_HW_3DSPMKICK = 0x11, */
+/* RGX_HWPERF_HW_3DSPMFINISHED = 0x18, */
+ RGX_HWPERF_HW_3DKICK = 0x0B,
+
+ RGX_HWPERF_HW_3DFINISHED = 0x0C,
+ RGX_HWPERF_HW_CDMKICK = 0x0D,
+ RGX_HWPERF_HW_CDMFINISHED = 0x0E,
+ RGX_HWPERF_HW_TLAKICK = 0x0F,
+
+ RGX_HWPERF_HW_TLAFINISHED = 0x10,
+ RGX_HWPERF_HW_3DSPMKICK = 0x11,
+ RGX_HWPERF_HW_PERIODIC = 0x12,
+ RGX_HWPERF_HW_RTUKICK = 0x13,
+
+ RGX_HWPERF_HW_RTUFINISHED = 0x14,
+ RGX_HWPERF_HW_SHGKICK = 0x15,
+ RGX_HWPERF_HW_SHGFINISHED = 0x16,
+ RGX_HWPERF_HW_3DTQFINISHED = 0x17,
+
+ RGX_HWPERF_HW_3DSPMFINISHED = 0x18,
+
+ /* other types 0x1A..0x1F */
+ RGX_HWPERF_CLKS_CHG = 0x1A,
+ RGX_HWPERF_GPU_STATE_CHG = 0x1B,
+
+ /* power types 0x20..0x27 */
+ RGX_HWPERF_PWR_EST_REQUEST = 0x20,
+ RGX_HWPERF_PWR_EST_READY = 0x21,
+ RGX_HWPERF_PWR_EST_RESULT = 0x22,
+ RGX_HWPERF_PWR_CHG = 0x23,
+
+ /* context switch types 0x30..0x31 */
+ RGX_HWPERF_CSW_START = 0x30,
+ RGX_HWPERF_CSW_FINISHED = 0x31,
+
+ /* last */
+ RGX_HWPERF_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 64 bits long).
+ */
+ RGX_HWPERF_MAX_TYPE = 0x40
+} RGX_HWPERF_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 63 event types.
+ */
+BLD_ASSERT((RGX_HWPERF_LAST_TYPE<RGX_HWPERF_MAX_TYPE), rgx_hwperf_h)
+
+/*! Type obsolete and will be removed in a later release, use RGXFWIF_DM */
+typedef RGXFWIF_DM RGX_HWPERF_DM;
+#define RGX_HWPERF_DM_GP RGXFWIF_DM_GP
+#define RGX_HWPERF_DM_2D RGXFWIF_DM_2D
+#define RGX_HWPERF_DM_TA RGXFWIF_DM_TA
+#define RGX_HWPERF_DM_3D RGXFWIF_DM_3D
+#define RGX_HWPERF_DM_CDM RGXFWIF_DM_CDM
+#define RGX_HWPERF_DM_RTU RGXFWIF_DM_RTU
+#define RGX_HWPERF_DM_SHG RGXFWIF_DM_SHG
+#define RGX_HWPERF_DM_LAST RGXFWIF_DM_LAST
+
+
+/******************************************************************************
+ * Packet Format Version 2 Types
+ *****************************************************************************/
+
+/*! 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
+
+/*! This structure defines version 2 of the packet format which is
+ * based around a header and a variable length data payload structure.
+ * The address of the next packet can be found by adding the ui16Size field
+ * in the header to the current packet address.
+ * Producers of packets must always ensure the size field is a multiple of 8
+ * as packets must start on an 8-byte granular address.
+ */
+typedef struct
+{
+ /* HEADER - packet header fields common to all packet types */
+ IMG_UINT32 ui32Sig; /*!< Always the value HWPERF_PACKET_SIG */
+
+ IMG_UINT32 ui32Size; /*!< Overall packet size in bytes, includes
+ * header and payload. Size is a 16-bit field
+ * stored in the 16 LSb. 16 MSb reserved.
+ * Use RGX_HWPERF_MAKE_SIZE_* and RGX_HWPERF_GET_SIZE
+ * macros to set/get, never write directly. */
+
+ IMG_UINT32 eTypeId; /*!< Includes event type and META thread ID in
+ * the 16 LSb. 16 MSb reserved.
+ * Use RGX_HWPERF_MAKE_TYPEID and RGX_HWPERF_GET_*
+ * macros to set/get, never write directly. */
+
+ IMG_UINT32 ui32Ordinal; /*!< Sequential number of the packet */
+ IMG_UINT64 ui64RGXTimer; /*!< Value of RGX_CR_TIMER at event */
+
+ /* PAYLOAD - bytes from this point on in the buffer are from the
+ * RGX_HWPERF_V2_PACKET_DATA union which encodes the payload data specific
+ * to the event type set in the header. When the structure in the union
+ * has a variable length member e.g. HW packets the payload length
+ * varies.
+ */
+} RGX_HWPERF_V2_PACKET_HDR, *RGX_PHWPERF_V2_PACKET_HDR;
+
+RGX_FW_STRUCT_OFFSET_ASSERT(RGX_HWPERF_V2_PACKET_HDR, ui64RGXTimer)
+
+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
+
+/*! Macro which takes a structure name and provides the packet size for
+ * a fixed size payload packet for assignment to the ui16Size field. */
+#define RGX_HWPERF_MAKE_SIZE_FIXED(_struct) ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&(sizeof(RGX_HWPERF_V2_PACKET_HDR)+sizeof(_struct))))
+
+/*! Macro which takes the number of bytes written in the data payload of a
+ * packet for a variable size payload packet, rounds it up to 8 bytes where
+ * it may be assigned to the ui16Size field. */
+#define RGX_HWPERF_MAKE_SIZE_VARIABLE(_size) ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&(sizeof(RGX_HWPERF_V2_PACKET_HDR)+PVR_ALIGN(_size, 8))))
+
+/*! 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 0xFFFFU
+#define RGX_HWPERF_TYPEID_THREAD_MASK 0x8000U
+#define RGX_HWPERF_TYPEID_EVENT_MASK (RGX_HWPERF_MAX_TYPE-1)
+
+/*! 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
+#define RGX_HWPERF_META_THREAD_ID1 0x1U
+/*! Obsolete, kept for source compatibility */
+#define RGX_HWPERF_META_THREAD_MASK 0x1U
+
+/*! Macros used to set the packet type and encode meta thread ID (0|1) within */
+#define RGX_HWPERF_MAKE_TYPEID(_type,_thread) ((IMG_UINT32) ((RGX_HWPERF_TYPEID_THREAD_MASK&((_thread)<<RGX_HWPERF_META_THREAD_SHIFT)) | (RGX_HWPERF_TYPEID_EVENT_MASK&(_type))))
+
+/*! 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))
+
+/*! Macros to obtain a typed pointer to a packet or data structure given a packet address */
+#define RGX_HWPERF_GET_PACKET(_buffer_addr) ((RGX_HWPERF_V2_PACKET_HDR*) (_buffer_addr))
+#define RGX_HWPERF_GET_PACKET_DATA_BYTES(_packet_addr) ((IMG_BYTE*) ( ((IMG_BYTE*)(_packet_addr)) +sizeof(RGX_HWPERF_V2_PACKET_HDR) ) )
+#define RGX_HWPERF_GET_NEXT_PACKET(_packet_addr) ((RGX_HWPERF_V2_PACKET_HDR*) ( ((IMG_BYTE*)(_packet_addr))+(RGX_HWPERF_SIZE_MASK&(_packet_addr)->ui32Size)) )
+
+/*! Obtains a typed pointer to a packet header given the packed data address */
+#define RGX_HWPERF_GET_PACKET_HEADER(_packet_addr) ((RGX_HWPERF_V2_PACKET_HDR*) ( ((IMG_BYTE*)(_packet_addr)) - sizeof(RGX_HWPERF_V2_PACKET_HDR) ))
+
+
+/*! This structure holds the field data of a Hardware packet.
+ */
+#define RGX_HWPERF_HW_DATA_FIELDS_LIST \
+IMG_UINT32 ui32DMCyc; /*!< DataMaster cycle count register, 0 if none */\
+IMG_UINT32 ui32FrameNum; /*!< Frame number */\
+IMG_UINT32 ui32PID; /*!< Process identifier */\
+IMG_UINT32 ui32DMContext; /*!< RenderContext for a TA,3D, Compute context for CDM, etc. */\
+IMG_UINT32 ui32RenderTarget; /*!< RenderTarget for a TA,3D, 0x0 otherwise */\
+IMG_UINT32 ui32ExtJobRef; /*!< Externally provided job reference used to track work for debugging purposes */\
+IMG_UINT32 ui32IntJobRef; /*!< Internally provided job reference used to track work for debugging purposes */\
+IMG_UINT32 ui32TimeCorrIndex; /*!< Index to the time correlation at the time the packet was generated */
+
+typedef struct
+{
+ RGX_HWPERF_HW_DATA_FIELDS_LIST
+} RGX_HWPERF_HW_DATA_FIELDS;
+
+RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_HW_DATA_FIELDS)
+
+
+/******************************************************************************
+ * API Types
+ *****************************************************************************/
+
+
+/*! Mask macros for use with RGXCtrlHWPerf() API.
+ * RGX_HWPERF_EVENT_ALL is obsolete, use RGX_HWPERF_EVENT_MASK_ALL
+ */
+#define RGX_HWPERF_EVENT_MASK_NONE (IMG_UINT64_C(0x0000000000000000))
+#define RGX_HWPERF_EVENT_MASK_ALL (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
+#define RGX_HWPERF_EVENT_MASK_ALL_FW (IMG_UINT64_C(0x000000000000007E))
+#define RGX_HWPERF_EVENT_MASK_HW_KICKFINISH (IMG_UINT64_C(0x0000000001FBFF00))
+#define RGX_HWPERF_EVENT_MASK_HW_PERIODIC (IMG_UINT64_C(0x0000000000040000))
+#define RGX_HWPERF_EVENT_MASK_ALL_HW (RGX_HWPERF_EVENT_MASK_HW_KICKFINISH \
+ | RGX_HWPERF_EVENT_MASK_HW_PERIODIC)
+#define RGX_HWPERF_EVENT_MASK_ALL_PWR_EST (IMG_UINT64_C(0X0000000700000000))
+#define RGX_HWPERF_EVENT_MASK_ALL_PWR (IMG_UINT64_C(0X0000000800000000))
+#define RGX_HWPERF_EVENT_MASK_VALUE(e) (((IMG_UINT64)1)<<(e))
+
+/*! Type used in the RGX API RGXConfigureAndEnableHWPerfCounters()
+ * It is used to configure the performance counter module in a layout
+ * block and allows one or more counters in the block to be
+ * configured in one operation based on the counter select mask. The bit
+ * shifts for this are the values in RGX_HWPERF_CNTBLK_COUNTER_ID. This mask
+ * also encodes which values in the arrays are valid, for example, if bit 1 set
+ * then aui8Mode[1], aui16GroupSelect[1], aui16BitSelect[1], aui32BatchMax[1],
+ * and aui32BatchMin[1] must be set. If these array elements are all set to
+ * 0 then the counter will not count and will not be in the HW event,
+ * effectively disabling the counter from the callers point of view.
+ * If any are non zero then the counter will be included in the HW event.
+ *
+ * Each layout block has 4 or 6 counters that can be programmed independently to
+ * profile the performance of a HW block. Each counter can be configured to
+ * accumulate statistics from 1 of 32 counter groups defined for that block.
+ * Each counter group can have up to 16 signals/bits defined that can be
+ * selected. Each counter may accumulate in one of two modes.
+ * See hwdefs/regapiperf.h for block/group/signal definitions.
+ */
+ typedef struct _RGX_HWPERF_CONFIG_CNTBLK_
+{
+ /*! Counter block ID, see RGX_HWPERF_CNTBLK_ID */
+ IMG_UINT8 ui8BlockID;
+
+ /*! 4 or 6 LSBs are a mask of which counters to configure. Bit 0 is counter 0,
+ * bit 1 is counter 1 on so on. */
+ IMG_UINT8 ui8CounterSelect;
+
+ /*! 4 or 6 LSBs 0 for counting 1's in the group, 1 for treating the group
+ * signals as a number for unsigned addition. Bit 0 is counter 0, bit 1 is
+ * counter 1 on so on. This member relates to the MODE field
+ * in the RGX_CR_<N>_PERF_SELECTm register for each counter */
+ IMG_UINT8 ui8Mode;
+
+ /*! 5 or 6 LSBs used as the GROUP_SELECT field in the RGX_CR_<N>_PERF_SELECTm
+ * register. Array index 0 is counter 0, index 1 is counter 1 and so on. */
+ IMG_UINT8 aui8GroupSelect[RGX_HWPERF_CNTRS_IN_BLK];
+
+ /*! 16 LSBs used as the BIT_SELECT field in the RGX_CR_<N>_PERF_SELECTm
+ * register. Array indexes relate to counters as above. */
+ IMG_UINT16 aui16BitSelect[RGX_HWPERF_CNTRS_IN_BLK];
+
+ /*! 14 LSBs used as the BATCH_MAX field in the RGX_CR_<N>_PERF_SELECTm
+ * register. Array indexes relate to counters as above. */
+ IMG_UINT32 aui32BatchMax[RGX_HWPERF_CNTRS_IN_BLK];
+
+ /*! 14 LSBs used as the BATCH_MIN field in the RGX_CR_<N>_PERF_SELECTm
+ * register. Array indexes relate to counters as above. */
+ IMG_UINT32 aui32BatchMin[RGX_HWPERF_CNTRS_IN_BLK];
+} RGX_HWPERF_CONFIG_CNTBLK;
+
+RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_CONFIG_CNTBLK)
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* RGX_HWPERF_KM_H_ */
+
+/******************************************************************************
+ End of file
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/rgx_memallocflags.h b/drivers/gpu/rogue/include/rgx_memallocflags.h
new file mode 100644
index 000000000000..5fa19094c63e
--- /dev/null
+++ b/drivers/gpu/rogue/include/rgx_memallocflags.h
@@ -0,0 +1,49 @@
+/**************************************************************************/ /*!
+@File
+@Title RGX memory allocation flags
+@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 _RGX_MEMALLOCFLAGS_H_
+#define _RGX_MEMALLOCFLAGS_H_
+
+#define PMMETA_PROTECT (1 << 0) /* Memory that only the PM and Meta can access */
+#define META_CACHED (1 << 1) /* Memory that is cached in META */
+
+#endif
diff --git a/drivers/gpu/rogue/include/rgx_meta.h b/drivers/gpu/rogue/include/rgx_meta.h
new file mode 100644
index 000000000000..4548f9274333
--- /dev/null
+++ b/drivers/gpu/rogue/include/rgx_meta.h
@@ -0,0 +1,345 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX META definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX META helper definitions
+@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 (__RGX_META_H__)
+#define __RGX_META_H__
+
+
+/***** The META HW register definitions in the file are updated manually *****/
+
+
+#include "img_defs.h"
+
+/************************************************************************
+* META registers and MACROS
+************************************************************************/
+#define META_CR_CTRLREG_BASE(T) (0x04800000 + 0x1000*(T))
+
+#define META_CR_TXPRIVEXT (0x048000E8)
+#define META_CR_TXPRIVEXT_MINIM_EN (0x1<<7)
+
+#define META_CR_SYSC_JTAG_THREAD (0x04830030)
+#define META_CR_SYSC_JTAG_THREAD_PRIV_EN (0x00000004)
+
+#define META_CR_PERF_COUNT0 (0x0480FFE0)
+#define META_CR_PERF_COUNT1 (0x0480FFE8)
+#define META_CR_PERF_COUNT_CTRL_SHIFT (28)
+#define META_CR_PERF_COUNT_CTRL_MASK (0xF0000000)
+#define META_CR_PERF_COUNT_CTRL_DCACHEHITS (0x8 << META_CR_PERF_COUNT_CTRL_SHIFT)
+#define META_CR_PERF_COUNT_CTRL_ICACHEHITS (0x9 << META_CR_PERF_COUNT_CTRL_SHIFT)
+#define META_CR_PERF_COUNT_CTRL_ICACHEMISS (0xA << META_CR_PERF_COUNT_CTRL_SHIFT)
+#define META_CR_PERF_COUNT_CTRL_ICORE (0xD << META_CR_PERF_COUNT_CTRL_SHIFT)
+#define META_CR_PERF_COUNT_THR_SHIFT (24)
+#define META_CR_PERF_COUNT_THR_MASK (0x0F000000)
+#define META_CR_PERF_COUNT_THR_0 (0x1 << META_CR_PERF_COUNT_THR_SHIFT)
+#define META_CR_PERF_COUNT_THR_1 (0x2 << META_CR_PERF_COUNT_THR_1)
+
+#define META_CR_TxVECINT_BHALT (0x04820500)
+#define META_CR_PERF_ICORE0 (0x0480FFD0)
+#define META_CR_PERF_ICORE1 (0x0480FFD8)
+#define META_CR_PERF_ICORE_DCACHEMISS (0x8)
+
+typedef enum
+{
+ META_PERF_CONF_NONE = 0,
+ META_PERF_CONF_ICACHE = 1,
+ META_PERF_CONF_DCACHE = 2,
+ META_PERF_CONF_POLLS = 3,
+} META_PERF_CONF;
+
+#define META_CR_PERF_COUNT(CTRL, THR) ((META_CR_PERF_COUNT_CTRL_##CTRL << META_CR_PERF_COUNT_CTRL_SHIFT) | \
+ (THR << META_CR_PERF_COUNT_THR_SHIFT))
+
+#define META_CR_TXUXXRXDT_OFFSET (META_CR_CTRLREG_BASE(0) + 0x0000FFF0)
+#define META_CR_TXUXXRXRQ_OFFSET (META_CR_CTRLREG_BASE(0) + 0x0000FFF8)
+
+#define META_CR_TXUXXRXRQ_DREADY_BIT (0x80000000) /* Poll for done */
+#define META_CR_TXUXXRXRQ_RDnWR_BIT (0x00010000) /* Set for read */
+#define META_CR_TXUXXRXRQ_TX_S (12)
+#define META_CR_TXUXXRXRQ_RX_S (4)
+#define META_CR_TXUXXRXRQ_UXX_S (0)
+
+#define META_CR_TXUA0_ID (0x3) /* Address unit regs */
+#define META_CR_TXUPC_ID (0x5) /* PC registers */
+
+/* Macros to calculate register access values */
+#define META_CR_CORE_REG(Thr, RegNum, Unit) (((Thr) << META_CR_TXUXXRXRQ_TX_S ) | \
+ ((RegNum) << META_CR_TXUXXRXRQ_RX_S ) | \
+ ((Unit) << META_CR_TXUXXRXRQ_UXX_S))
+
+#define META_CR_THR0_PC META_CR_CORE_REG(0, 0, META_CR_TXUPC_ID)
+#define META_CR_THR0_PCX META_CR_CORE_REG(0, 1, META_CR_TXUPC_ID)
+#define META_CR_THR0_SP META_CR_CORE_REG(0, 0, META_CR_TXUA0_ID)
+
+#define META_CR_THR1_PC META_CR_CORE_REG(1, 0, META_CR_TXUPC_ID)
+#define META_CR_THR1_PCX META_CR_CORE_REG(1, 1, META_CR_TXUPC_ID)
+#define META_CR_THR1_SP META_CR_CORE_REG(1, 0, META_CR_TXUA0_ID)
+
+#define SP_ACCESS(Thread) META_CR_CORE_REG(Thread, 0, META_CR_TXUA0_ID)
+#define PC_ACCESS(Thread) META_CR_CORE_REG(Thread, 0, META_CR_TXUPC_ID)
+
+#define META_CR_COREREG_ENABLE (0x0000000)
+#define META_CR_COREREG_STATUS (0x0000010)
+#define META_CR_COREREG_DEFR (0x00000A0)
+
+#define META_CR_T0ENABLE_OFFSET (META_CR_CTRLREG_BASE(0) + META_CR_COREREG_ENABLE)
+#define META_CR_T0STATUS_OFFSET (META_CR_CTRLREG_BASE(0) + META_CR_COREREG_STATUS)
+#define META_CR_T0DEFR_OFFSET (META_CR_CTRLREG_BASE(0) + META_CR_COREREG_DEFR)
+
+#define META_CR_T1ENABLE_OFFSET (META_CR_CTRLREG_BASE(1) + META_CR_COREREG_ENABLE)
+#define META_CR_T1STATUS_OFFSET (META_CR_CTRLREG_BASE(1) + META_CR_COREREG_STATUS)
+#define META_CR_T1DEFR_OFFSET (META_CR_CTRLREG_BASE(1) + META_CR_COREREG_DEFR)
+
+#define META_CR_TXENABLE_ENABLE_BIT (0x00000001) /* Set if running */
+#define META_CR_TXSTATUS_PRIV (0x00020000)
+
+#define META_MEM_GLOBAL_RANGE_BIT (0x80000000)
+
+
+/************************************************************************
+* META LDR Format
+************************************************************************/
+/* Block header structure */
+typedef struct
+{
+ IMG_UINT32 ui32DevID;
+ IMG_UINT32 ui32SLCode;
+ IMG_UINT32 ui32SLData;
+ IMG_UINT16 ui16PLCtrl;
+ IMG_UINT16 ui16CRC;
+
+} RGX_META_LDR_BLOCK_HDR;
+
+/* High level data stream block structure */
+typedef struct
+{
+ IMG_UINT16 ui16Cmd;
+ IMG_UINT16 ui16Length;
+ IMG_UINT32 ui32Next;
+ IMG_UINT32 aui32CmdData[4];
+
+} RGX_META_LDR_L1_DATA_BLK;
+
+/* High level data stream block structure */
+typedef struct
+{
+ IMG_UINT16 ui16Tag;
+ IMG_UINT16 ui16Length;
+ IMG_UINT32 aui32BlockData[4];
+
+} RGX_META_LDR_L2_DATA_BLK;
+
+/* Config command structure */
+typedef struct
+{
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 aui32BlockData[4];
+
+} RGX_META_LDR_CFG_BLK;
+
+/* Block type definitions */
+#define RGX_META_LDR_COMMENT_TYPE_MASK (0x0010)
+#define RGX_META_LDR_BLK_IS_COMMENT(X) ((X & RGX_META_LDR_COMMENT_TYPE_MASK) != 0)
+
+/* Command definitions
+ Value Name Description
+ 0 LoadMem Load memory with binary data.
+ 1 LoadCore Load a set of core registers.
+ 2 LoadMMReg Load a set of memory mapped registers.
+ 3 StartThreads Set each thread PC and SP, then enable threads.
+ 4 ZeroMem Zeros a memory region.
+ 5 Config Perform a configuration command. */
+#define RGX_META_LDR_CMD_MASK (0x000F)
+
+#define RGX_META_LDR_CMD_LOADMEM (0x0000)
+#define RGX_META_LDR_CMD_LOADCORE (0x0001)
+#define RGX_META_LDR_CMD_LOADMMREG (0x0002)
+#define RGX_META_LDR_CMD_START_THREADS (0x0003)
+#define RGX_META_LDR_CMD_ZEROMEM (0x0004)
+#define RGX_META_LDR_CMD_CONFIG (0x0005)
+
+/* Config Command definitions
+ Value Name Description
+ 0 Pause Pause for x times 100 instructions
+ 1 Read Read a value from register - No value return needed.
+ Utilises effects of issuing reads to certain registers
+ 2 Write Write to mem location
+ 3 MemSet Set mem to value
+ 4 MemCheck check mem for specific value.*/
+#define RGX_META_LDR_CFG_PAUSE (0x0000)
+#define RGX_META_LDR_CFG_READ (0x0001)
+#define RGX_META_LDR_CFG_WRITE (0x0002)
+#define RGX_META_LDR_CFG_MEMSET (0x0003)
+#define RGX_META_LDR_CFG_MEMCHECK (0x0004)
+
+/************************************************************************
+* RGX FW segmented MMU definitions
+************************************************************************/
+/* All threads can access the segment */
+#define RGXFW_SEGMMU_ALLTHRS (0xf << 8)
+/* Writeable */
+#define RGXFW_SEGMMU_WRITEABLE (0x1 << 1)
+/* All threads can access and writeable */
+#define RGXFW_SEGMMU_ALLTHRS_WRITEABLE (RGXFW_SEGMMU_ALLTHRS | RGXFW_SEGMMU_WRITEABLE)
+
+/* Direct map regions mapping (8-10) */
+#define RGXFW_SEGMMU_DMAP_ID_START (8)
+#define RGXFW_SEGMMU_DMAP_ADDR_START (0x06000000U)
+#define RGXFW_SEGMMU_DMAP_ADDR_META (0x86000000U)
+#define RGXFW_SEGMMU_DMAP_SIZE (8*1024*1024) /* 8 MB */
+
+/* Direct map region 11 used for mapping GPU memory */
+#define RGXFW_SEGMMU_DMAP_GPU_ID (11)
+#define RGXFW_SEGMMU_DMAP_GPU_ADDR_START (RGXFW_SEGMMU_DMAP_ADDR_START + 3*RGXFW_SEGMMU_DMAP_SIZE)
+
+/* Segment IDs */
+#define RGXFW_SEGMMU_TEXT_ID (0)
+#define RGXFW_SEGMMU_SHARED_ID (1)
+#define RGXFW_SEGMMU_BOOTLDR_ID (2)
+#define RGXFW_SEGMMU_DATA_ID (3)
+
+#define RGXFW_SEGMMU_META_DM_ID (0x7)
+
+#if defined(HW_ERN_45914)
+/* SLC caching strategy is emitted through the segment MMU. All the segments configured
+ through this macro are CACHED in the SLC. The interface has been kept the same to
+ simplify the code changes. The bifdm argument is ignored (no longer relevant). */
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7(pers, coheren, mmu_ctx) ( (((IMG_UINT64) ((pers) & 0x3)) << 52) | \
+ (((IMG_UINT64) ((mmu_ctx) & 0xFF)) << 44) | \
+ (((IMG_UINT64) ((coheren) & 0x1)) << 40) )
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED(mmu_ctx) RGXFW_SEGMMU_OUTADDR_TOP_S7(0x3, 0x0, mmu_ctx)
+#define RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED(mmu_ctx) RGXFW_SEGMMU_OUTADDR_TOP_S7(0x0, 0x1, mmu_ctx)
+
+// Temporarily use uncached for everything:
+//#define RGXFW_SEGMMU_OUTADDR_TOP(mmu_ctx, bifdm) RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_CACHED(mmu_ctx)
+#define RGXFW_SEGMMU_OUTADDR_TOP(mmu_ctx, bifdm) RGXFW_SEGMMU_OUTADDR_TOP_S7_SLC_UNCACHED(mmu_ctx | (bifdm&0x0))
+#else
+/* To configure the Page Catalog and BIF-DM fed into the BIF for Garten accesses through this segment */
+#define RGXFW_SEGMMU_OUTADDR_TOP(pc, bifdm) ( (((IMG_UINT64) ((pc) & 0xF)) << 44) | \
+ (((IMG_UINT64) ((bifdm) & 0xF)) << 40) )
+#endif
+
+/* META segments have 4kB minimum size */
+#define RGXFW_SEGMMU_ALIGN (0x1000)
+
+/* Segmented MMU registers (n = segment id) */
+#define META_CR_MMCU_SEGMENTn_BASE(n) (0x04850000 + (n)*0x10)
+#define META_CR_MMCU_SEGMENTn_LIMIT(n) (0x04850004 + (n)*0x10)
+#define META_CR_MMCU_SEGMENTn_OUTA0(n) (0x04850008 + (n)*0x10)
+#define META_CR_MMCU_SEGMENTn_OUTA1(n) (0x0485000C + (n)*0x10)
+
+/* Win mode for data cache */
+#define RGXFW__SEGMMU_DMAP_DC_WIN (0x3)
+#define RGXFW__SEGMMU_DMAP_DC_SHIFT (0x6)
+
+/************************************************************************
+* RGX FW Bootloader defaults
+************************************************************************/
+#define RGXFW_BOOTLDR_META_ADDR (0x40000000)
+#define RGXFW_BOOTLDR_DEVV_ADDR_0 (0xC0000000)
+#if defined(HW_ERN_45914)
+#define RGXFW_BOOTLDR_DEVV_ADDR_1 (0x003000E1)
+#else
+#define RGXFW_BOOTLDR_DEVV_ADDR_1 (0x000007E1)
+#endif
+#define RGXFW_BOOTLDR_DEVV_ADDR ((((IMG_UINT64) RGXFW_BOOTLDR_DEVV_ADDR_1) << 32) | RGXFW_BOOTLDR_DEVV_ADDR_0)
+#define RGXFW_BOOTLDR_LIMIT (0x1FFFF000)
+
+/* Bootloader configuration offset is in dwords (512 bytes) */
+#define RGXFW_BOOTLDR_CONF_OFFSET (0x80)
+
+/************************************************************************
+* RGX META Stack
+************************************************************************/
+#define RGX_META_STACK_SIZE (0xC00)
+
+/************************************************************************
+* RGX META Core memory
+************************************************************************/
+#define RGX_META_COREMEM_BSS_SIZE (0x800)
+#define RGX_META_COREMEM_DATA_SIZE (RGX_META_COREMEM_BSS_SIZE + RGX_META_STACK_SIZE)
+#define RGX_META_COREMEM_CODE_SIZE (RGX_META_COREMEM_SIZE - RGX_META_COREMEM_DATA_SIZE)
+/* code and data both map to the same physical memory */
+#define RGX_META_COREMEM_CODE_ADDR (0x80000000)
+#define RGX_META_COREMEM_DATA_ADDR (0x82000000)
+#define RGX_META_COREMEM_STACK_ADDR (RGX_META_COREMEM_DATA_ADDR)
+#define RGX_META_COREMEM_BSS_ADDR (RGX_META_COREMEM_STACK_ADDR + RGX_META_STACK_SIZE)
+/* because data and code share the same memory, base address for code is offset by the data */
+#define RGX_META_COREMEM_CODE_BADDR (RGX_META_COREMEM_CODE_ADDR + RGX_META_COREMEM_DATA_SIZE)
+
+#define RGX_META_IS_COREMEM_CODE(A) (((A) >= RGX_META_COREMEM_CODE_BADDR) && ((A) < (RGX_META_COREMEM_CODE_ADDR + RGX_META_COREMEM_SIZE)))
+#define RGX_META_IS_COREMEM_DATA(A) (((A) >= RGX_META_COREMEM_DATA_ADDR) && ((A) < (RGX_META_COREMEM_DATA_ADDR + RGX_META_COREMEM_DATA_SIZE)))
+
+/************************************************************************
+* 2nd thread
+************************************************************************/
+#define RGXFW_THR1_PC (0x18930000)
+#define RGXFW_THR1_SP (0x78890000)
+
+/************************************************************************
+* META compatibility
+************************************************************************/
+
+#define META_CR_CORE_ID (0x04831000)
+#define META_CR_CORE_ID_VER_SHIFT (16U)
+#define META_CR_CORE_ID_VER_CLRMSK (0XFF00FFFFU)
+
+#if (RGX_FEATURE_META == MTP218)
+#define RGX_CR_META_CORE_ID_VALUE 0x19
+#elif (RGX_FEATURE_META == MTP219)
+#define RGX_CR_META_CORE_ID_VALUE 0x1E
+#elif (RGX_FEATURE_META == LTP218)
+#define RGX_CR_META_CORE_ID_VALUE 0x1C
+#elif (RGX_FEATURE_META == LTP217)
+#define RGX_CR_META_CORE_ID_VALUE 0x1F
+#else
+#error "Unknown META ID"
+#endif
+
+#endif /* __RGX_META_H__ */
+
+/******************************************************************************
+ End of file (rgx_meta.h)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/rogue/include/rgx_options_km.h b/drivers/gpu/rogue/include/rgx_options_km.h
new file mode 100644
index 000000000000..994d9e9b7dc4
--- /dev/null
+++ b/drivers/gpu/rogue/include/rgx_options_km.h
@@ -0,0 +1,204 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX KM build options
+@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.
+*/ /**************************************************************************/
+
+/* Each build option listed here is packed into a dword which
+ * provides up to log2(RGX_BUILD_OPTIONS_MASK_KM + 1) flags.
+ * The corresponding bit is set if the build option
+ * was enabled at compile time.
+ *
+ * In order to extract the enabled build flags the INTERNAL_TEST
+ * switch should be enabled in a client program which includes this
+ * header. Then the client can test specific build flags by reading
+ * the bit value at ##OPTIONNAME##_SET_OFFSET in RGX_BUILD_OPTIONS_KM.
+ *
+ * IMPORTANT: add new options to unused bits or define a new dword
+ * (e.g. RGX_BUILD_OPTIONS_KM2) so that the bitfield remains backwards
+ * compatible.
+ */
+
+#define RGX_BUILD_OPTIONS_MASK_KM 0x0000FFFFUL
+
+#if defined(NO_HARDWARE) || defined (INTERNAL_TEST)
+ #define NO_HARDWARE_SET_OFFSET OPTIONS_BIT0
+ #define OPTIONS_BIT0 (0x1ul << 0)
+ #if OPTIONS_BIT0 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT0 0x0
+#endif /* NO_HARDWARE */
+
+
+#if defined(PDUMP) || defined (INTERNAL_TEST)
+ #define PDUMP_SET_OFFSET OPTIONS_BIT1
+ #define OPTIONS_BIT1 (0x1ul << 1)
+ #if OPTIONS_BIT1 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT1 0x0
+#endif /* PDUMP */
+
+
+#if defined(SUPPORT_META_SLAVE_BOOT) || defined (INTERNAL_TEST)
+ #define SUPPORT_META_SLAVE_BOOT_SET_OFFSET OPTIONS_BIT2
+ #define OPTIONS_BIT2 (0x1ul << 2)
+ #if OPTIONS_BIT2 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT2 0x0
+#endif /* SUPPORT_META_SLAVE_BOOT */
+
+
+#if defined(SUPPORT_MMU_FREELIST) || defined (INTERNAL_TEST)
+ #define SUPPORT_MMU_FREELIST_SET_OFFSET OPTIONS_BIT3
+ #define OPTIONS_BIT3 (0x1ul << 3)
+ #if OPTIONS_BIT3 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT3 0x0
+#endif /* SUPPORT_MMU_FREELIST */
+
+
+#if defined(SUPPORT_PMMIF) || defined (INTERNAL_TEST)
+ #define SUPPORT_PMMIF_SET_OFFSET OPTIONS_BIT4
+ #define OPTIONS_BIT4 (0x1ul << 4)
+ #if OPTIONS_BIT4 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT4 0x0
+#endif /* SUPPORT_PMMIF */
+
+
+#if defined(SUPPORT_RGX) || defined (INTERNAL_TEST)
+ #define SUPPORT_RGX_SET_OFFSET OPTIONS_BIT5
+ #define OPTIONS_BIT5 (0x1ul << 5)
+ #if OPTIONS_BIT5 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT5 0x0
+#endif /* SUPPORT_RGX */
+
+
+#if defined(SUPPORT_SECURE_EXPORT) || defined (INTERNAL_TEST)
+ #define SUPPORT_SECURE_EXPORT_SET_OFFSET OPTIONS_BIT6
+ #define OPTIONS_BIT6 (0x1ul << 6)
+ #if OPTIONS_BIT6 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT6 0x0
+#endif /* SUPPORT_SECURE_EXPORT */
+
+
+#if defined(SUPPORT_INSECURE_EXPORT) || defined (INTERNAL_TEST)
+ #define SUPPORT_INSECURE_EXPORT_SET_OFFSET OPTIONS_BIT7
+ #define OPTIONS_BIT7 (0x1ul << 7)
+ #if OPTIONS_BIT7 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT7 0x0
+#endif /* SUPPORT_INSECURE_EXPORT */
+
+
+#if defined(SUPPORT_VFP) || defined (INTERNAL_TEST)
+ #define SUPPORT_VFP_SET_OFFSET OPTIONS_BIT8
+ #define OPTIONS_BIT8 (0x1ul << 8)
+ #if OPTIONS_BIT8 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT8 0x0
+#endif /* SUPPORT_VFP */
+
+
+#if defined(SUPPORT_DRM) || defined (INTERNAL_TEST)
+ #define SUPPORT_DRM_SET_OFFSET OPTIONS_BIT9
+ #define OPTIONS_BIT9 (0x1ul << 9)
+ #if OPTIONS_BIT9 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT9 0x0
+#endif /* SUPPORT_DRM */
+
+
+#if defined(SUPPORT_ION) || defined (INTERNAL_TEST)
+ #define SUPPORT_ION_SET_OFFSET OPTIONS_BIT10
+ #define OPTIONS_BIT10 (0x1ul << 10)
+ #if OPTIONS_BIT10 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT10 0x0
+#endif /* SUPPORT_ION */
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+ #define DEBUG_SET_OFFSET OPTIONS_BIT11
+ #define OPTIONS_BIT11 (0x1ul << 11)
+ #if OPTIONS_BIT11 > RGX_BUILD_OPTIONS_MASK_KM
+ #error "Bit exceeds reserved range"
+ #endif
+#else
+ #define OPTIONS_BIT11 0x0
+#endif /* DEBUG */
+
+
+#define RGX_BUILD_OPTIONS_KM \
+ OPTIONS_BIT0 |\
+ OPTIONS_BIT1 |\
+ OPTIONS_BIT2 |\
+ OPTIONS_BIT3 |\
+ OPTIONS_BIT4 |\
+ OPTIONS_BIT6 |\
+ OPTIONS_BIT7 |\
+ OPTIONS_BIT8 |\
+ OPTIONS_BIT9 |\
+ OPTIONS_BIT10 |\
+ OPTIONS_BIT11
+
+
diff --git a/drivers/gpu/rogue/include/rgxscript.h b/drivers/gpu/rogue/include/rgxscript.h
new file mode 100644
index 000000000000..43e7679192d5
--- /dev/null
+++ b/drivers/gpu/rogue/include/rgxscript.h
@@ -0,0 +1,178 @@
+/*************************************************************************/ /*!
+@File
+@Title rgx kernel services structues/functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX initialisation script definitions.
+@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 __RGXSCRIPT_H__
+#define __RGXSCRIPT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define RGX_MAX_INIT_COMMANDS (256)
+#define RGX_MAX_DBGBUS_COMMANDS (4096)
+#define RGX_MAX_DEINIT_COMMANDS (32)
+#define RGX_DBG_CMD_NAME_SIZE (32)
+
+typedef enum _RGX_INIT_OPERATION
+{
+ RGX_INIT_OP_ILLEGAL = 0,
+ RGX_INIT_OP_WRITE_HW_REG,
+ RGX_INIT_OP_POLL_64_HW_REG,
+ RGX_INIT_OP_POLL_HW_REG,
+ RGX_INIT_OP_COND_POLL_HW_REG,
+ RGX_INIT_OP_LOOP_POINT,
+ RGX_INIT_OP_COND_BRANCH,
+ RGX_INIT_OP_HALT,
+ RGX_INIT_OP_DBG_READ32_HW_REG,
+ RGX_INIT_OP_DBG_READ64_HW_REG,
+ RGX_INIT_OP_DBG_CALC,
+ RGX_INIT_OP_DBG_WAIT,
+ RGX_INIT_OP_DBG_STRING,
+ RGX_INIT_OP_PDUMP_HW_REG,
+} RGX_INIT_OPERATION;
+
+typedef union _RGX_INIT_COMMAND_
+{
+ RGX_INIT_OPERATION eOp;
+
+ struct {
+ RGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ } sWriteHWReg;
+
+ struct {
+ RGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ } sPDumpHWReg;
+
+ struct
+ {
+ RGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT64 ui64Value;
+ IMG_UINT64 ui64Mask;
+ } sPoll64HWReg;
+
+ struct
+ {
+ RGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+ } sPollHWReg;
+
+ struct
+ {
+ RGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32CondOffset;
+ IMG_UINT32 ui32CondValue;
+ IMG_UINT32 ui32CondMask;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+ } sCondPollHWReg;
+
+ struct
+ {
+ RGX_INIT_OPERATION eOp;
+ } sLoopPoint;
+
+ struct
+ {
+ RGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+
+ } sConditionalBranchPoint;
+
+ struct
+ {
+ RGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_CHAR aszName[RGX_DBG_CMD_NAME_SIZE];
+ } sDBGReadHWReg;
+
+ struct
+ {
+ RGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset1;
+ IMG_UINT32 ui32Offset2;
+ IMG_UINT32 ui32Offset3;
+ IMG_CHAR aszName[RGX_DBG_CMD_NAME_SIZE];
+ } sDBGCalc;
+
+ struct
+ {
+ RGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32WaitInUs;
+ } sDBGWait;
+
+ struct
+ {
+ RGX_INIT_OPERATION eOp;
+ IMG_CHAR aszString[RGX_DBG_CMD_NAME_SIZE];
+ } sDBGString;
+
+} RGX_INIT_COMMAND;
+
+typedef struct _RGX_INIT_SCRIPTS_
+{
+ RGX_INIT_COMMAND asInitCommands[RGX_MAX_INIT_COMMANDS];
+ RGX_INIT_COMMAND asDbgCommands[RGX_MAX_INIT_COMMANDS];
+ RGX_INIT_COMMAND asDbgBusCommands[RGX_MAX_DBGBUS_COMMANDS];
+ RGX_INIT_COMMAND asDeinitCommands[RGX_MAX_DEINIT_COMMANDS];
+} RGX_SCRIPTS;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __RGXSCRIPT_H__ */
+
+/*****************************************************************************
+ End of file (rgxscript.h)
+*****************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/ri_typedefs.h b/drivers/gpu/rogue/include/ri_typedefs.h
new file mode 100644
index 000000000000..c7e9a46ebf9b
--- /dev/null
+++ b/drivers/gpu/rogue/include/ri_typedefs.h
@@ -0,0 +1,55 @@
+/*************************************************************************/ /*!
+@File
+@Title Resource Information (RI) Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Client side part of RI management
+@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 RI_TYPEDEFS_H
+#define RI_TYPEDEFS_H
+
+#include "img_types.h"
+
+#define RI_MAX_TEXT_LEN 80
+
+typedef struct RI_SUBLIST_ENTRY RI_ENTRY;
+typedef RI_ENTRY* RI_HANDLE;
+
+#endif /* #ifndef RI_TYPEDEFS_H */
+
diff --git a/drivers/gpu/rogue/include/services.h b/drivers/gpu/rogue/include/services.h
new file mode 100644
index 000000000000..b1deb9c5cb58
--- /dev/null
+++ b/drivers/gpu/rogue/include/services.h
@@ -0,0 +1,1258 @@
+/*************************************************************************/ /*!
+@File
+@Title Services API Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Exported services API details
+@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 __SERVICES_H__
+#define __SERVICES_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "sync_external.h"
+#include "pdumpdefs.h"
+#include "lock_types.h"
+#include "pvr_debug.h"
+
+/*
+*/
+
+#if defined(LDDM)
+/* LDDM build needs to include this for the allocation structure */
+#include "umallocation.h"
+#endif
+
+#include "pvrsrv_device_types.h"
+
+/* The comment below is the front page for code-generated doxygen documentation */
+/*!
+ ******************************************************************************
+ @mainpage
+ This document details the APIs and implementation of the Consumer Services.
+ It is intended to be used in conjunction with the Consumer Services
+ Software Architectural Specification and the Consumer Services Software
+ Functional Specification.
+ *****************************************************************************/
+
+/******************************************************************************
+ * #defines
+ *****************************************************************************/
+
+/*! 4k page size definition */
+#define PVRSRV_4K_PAGE_SIZE 4096UL /*!< Size of a 4K Page */
+#define PVRSRV_4K_PAGE_SIZE_ALIGNSHIFT 12 /*!< Amount to shift an address by so that
+ it is always page-aligned */
+
+
+#define EVENTOBJNAME_MAXLENGTH (50) /*!< Max length of an event object name */
+
+
+/*!
+ Flags for Services connection.
+ Allows to define per-client policy for Services
+*/
+#define SRV_FLAGS_PERSIST (1U << 0) /*!< Persist client flag */
+#define SRV_FLAGS_INIT_PROCESS (1U << 1) /*!< Allows connect to succeed if SrvInit
+ * has not yet run (used by SrvInit itself) */
+#define SRV_FLAGS_PDUMPCTRL (1U << 31) /*!< PDump Ctrl client flag */
+
+/*
+ Pdump flags which are accessible to Services clients
+*/
+/*
+*/
+#define PVRSRV_PDUMP_FLAGS_CONTINUOUS 0x40000000UL /*!< pdump continuous */
+
+#define PVRSRV_UNDEFINED_HEAP_ID (~0LU)
+
+/*!
+ ******************************************************************************
+ * User Module type
+ *****************************************************************************/
+typedef enum
+{
+ IMG_EGL = 0x00000001, /*!< EGL Module */
+ IMG_OPENGLES1 = 0x00000002, /*!< OGLES1 Module */
+ IMG_OPENGLES3 = 0x00000003, /*!< OGLES3 Module */
+ IMG_D3DM = 0x00000004, /*!< D3DM Module */
+ IMG_SRV_UM = 0x00000005, /*!< Services User-Mode */
+ IMG_SRV_INIT = 0x00000006, /*!< Services initialisation */
+ IMG_SRVCLIENT = 0x00000007, /*!< Services Client */
+ IMG_WDDMKMD = 0x00000008, /*!< WDDM KMD */
+ IMG_WDDM3DNODE = 0x00000009, /*!< WDDM 3D Node */
+ IMG_WDDMMVIDEONODE = 0x0000000A, /*!< WDDM MVideo Node */
+ IMG_WDDMVPBNODE = 0x0000000B, /*!< WDDM VPB Node */
+ IMG_OPENGL = 0x0000000C, /*!< OpenGL */
+ IMG_D3D = 0x0000000D, /*!< D3D */
+ IMG_OPENCL = 0x0000000E, /*!< OpenCL */
+ IMG_ANDROID_HAL = 0x0000000F, /*!< Graphics HAL */
+ IMG_WEC_GPE = 0x00000010, /*!< WinEC-specific GPE */
+ IMG_PVRGPE = 0x00000011, /*!< WinEC/WinCE GPE */
+ IMG_RSCOMPUTE = 0x00000012, /*!< RenderScript Compute */
+ IMG_OPENRL = 0x00000013, /*!< OpenRL Module */
+ IMG_PDUMPCTRL = 0x00000014, /*!< PDump control client */
+
+} IMG_MODULE_ID;
+
+/*! Max length of an App-Hint string */
+#define APPHINT_MAX_STRING_SIZE 256
+
+/*!
+ ******************************************************************************
+ * IMG data types
+ *****************************************************************************/
+typedef enum
+{
+ IMG_STRING_TYPE = 1, /*!< String type */
+ IMG_FLOAT_TYPE , /*!< Float type */
+ IMG_UINT_TYPE , /*!< Unsigned Int type */
+ IMG_INT_TYPE , /*!< (Signed) Int type */
+ IMG_FLAG_TYPE /*!< Flag Type */
+}IMG_DATA_TYPE;
+
+
+/******************************************************************************
+ * Structure definitions.
+ *****************************************************************************/
+
+/*!
+ * Forward declaration
+ */
+typedef struct _PVRSRV_DEV_DATA_ *PPVRSRV_DEV_DATA;
+/*!
+ * Forward declaration (look on connection.h)
+ */
+typedef struct _PVRSRV_CONNECTION_ PVRSRV_CONNECTION;
+
+
+/*************************************************************************/ /*!
+ * Client dev info
+ */ /*************************************************************************/
+typedef struct _PVRSRV_CLIENT_DEV_DATA_
+{
+ IMG_UINT32 ui32NumDevices; /*!< Number of services-managed devices connected */
+ PVRSRV_DEVICE_IDENTIFIER asDevID[PVRSRV_MAX_DEVICES]; /*!< Device identifiers */
+ PVRSRV_ERROR (*apfnDevConnect[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA); /*!< device-specific connection callback */
+ PVRSRV_ERROR (*apfnDumpTrace[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA); /*!< device-specific debug trace callback */
+
+} PVRSRV_CLIENT_DEV_DATA;
+
+/*!
+ ******************************************************************************
+ * This structure allows the user mode glue code to have an OS independent
+ * set of prototypes.
+ *****************************************************************************/
+typedef struct _PVRSRV_DEV_DATA_
+{
+ PVRSRV_CONNECTION *psConnection; /*!< Services connection info */
+ IMG_HANDLE hDevCookie; /*!< Dev cookie */
+
+} PVRSRV_DEV_DATA;
+
+/*************************************************************************/ /*!
+ PVR Client Event handling in Services
+*/ /**************************************************************************/
+typedef enum _PVRSRV_CLIENT_EVENT_
+{
+ PVRSRV_CLIENT_EVENT_HWTIMEOUT = 0, /*!< hw timeout event */
+} PVRSRV_CLIENT_EVENT;
+
+/**************************************************************************/ /*!
+@Function PVRSRVClientEvent
+@Description Handles timeouts occurring in client drivers
+@Input eEvent event type
+@Input psDevData pointer to the PVRSRV_DEV_DATA context
+@Input pvData client-specific data
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVClientEvent(const PVRSRV_CLIENT_EVENT eEvent,
+ PVRSRV_DEV_DATA *psDevData,
+ IMG_PVOID pvData);
+
+/******************************************************************************
+ * PVR Services API prototypes.
+ *****************************************************************************/
+
+/**************************************************************************/ /*!
+@Function PVRSRVConnect
+@Description Creates a connection from an application to the services
+ module and initialises device-specific call-back functions.
+@Output ppsConnection on Success, *ppsConnection is set to the new
+ PVRSRV_CONNECTION instance.
+@Input ui32SrvFlags a bit-wise OR of the following:
+ SRV_FLAGS_PERSIST
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVConnect(PVRSRV_CONNECTION **ppsConnection, IMG_UINT32 ui32SrvFlags);
+
+/**************************************************************************/ /*!
+@Function PVRSRVDisconnect
+@Description Disconnects from the services module
+@Input psConnection the connection to be disconnected
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDisconnect(PVRSRV_CONNECTION *psConnection);
+
+/**************************************************************************/ /*!
+@Function PVRSRVEnumerateDevices
+@Description Enumerate all services managed devices in the
+ system.
+
+ The function returns a list of the device IDs stored either
+ in the services (or constructed in the user mode glue
+ component in certain environments). The number of devices
+ in the list is also returned.
+
+ The user is required to provide a buffer large enough to
+ receive an array of MAX_NUM_DEVICE_IDS *
+ PVRSRV_DEVICE_IDENTIFIER structures.
+
+ In a binary layered component which does not support dynamic
+ runtime selection, the glue code should compile to return
+ the supported devices statically, e.g. multiple instances of
+ the same device if multiple devices are supported
+
+ In the case of an environment (for instance) where one
+ services managed device may connect to two display devices
+ this code would enumerate all three devices and even
+ non-dynamic device selection code should retain the facility
+ to parse the list to find the index of a given device.}
+
+@Input psConnection Services connection
+@Output puiNumDevices Number of devices present in the system
+@Output puiDevIDs Pointer to called supplied array of
+ PVRSRV_DEVICE_IDENTIFIER structures. The
+ array is assumed to be at least
+ PVRSRV_MAX_DEVICES long.
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevices(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 *puiNumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *puiDevIDs);
+
+/**************************************************************************/ /*!
+@Function PVRSRVAcquireDeviceData
+@Description Returns device info structure pointer for the requested device.
+ This populates a PVRSRV_DEV_DATA structure with appropriate
+ pointers to the DevInfo structure for the device requested.
+
+ In a non-plug-and-play the first call to GetDeviceInfo for a
+ device causes device initialisation
+
+ Calls to GetDeviceInfo are reference counted
+@Input psConnection Services connection
+@Input uiDevIndex Index to the required device obtained from the
+ PVRSRVEnumerateDevice function
+@Output psDevData The returned Device Data
+@Input eDeviceType Required device type. If type is unknown use
+ uiDevIndex to locate device data
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceData(PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 uiDevIndex,
+ PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_DEVICE_TYPE eDeviceType);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPollForValue
+@Description Polls for a value to match a masked read of System Memory.
+ The function returns when either (1) the value read back
+ matches ui32Value, or (2) the maximum number of tries has
+ been reached.
+@Input psConnection Services connection
+@Input hOSEvent Handle to OS event object to wait for
+@Input pui32LinMemAddr the address of the memory to poll
+@Input ui32Value the required value
+@Input ui32Mask the mask to use
+@Input ui32Waitus interval between tries (us)
+@Input ui32Tries number of tries to make before giving up
+@Return PVRSRV_OK on success. Otherwise, a
+ PVRSRV_ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPollForValue(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hOSEvent,
+ volatile IMG_UINT32 *pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+
+/* this function is almost the same as PVRSRVPollForValue. The only difference
+ * is that it now handles the interval between tries itself. Therefore it can
+ * correctly handles the differences between the different platforms.
+ */
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVWaitForValue(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hOSEvent,
+ volatile IMG_UINT32 *pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask);
+
+
+/**************************************************************************/ /*!
+ @Function PVRSRVConditionCheckCallback
+ @Description Function prototype for use with the PVRSRVWaitForCondition()
+ API. Clients implement this callback to test if the condition
+ waited for has been met and become true.
+
+ @Input pvUserData Pointer to client user data needed for
+ the check
+ @Output pbCondMet Updated on exit with condition state
+
+ @Return PVRSRV_OK when condition tested without error
+ PVRSRV_* other system error that will lead to the
+ abnormal termination of the wait API.
+ */
+/******************************************************************************/
+typedef
+PVRSRV_ERROR (*PVRSRVConditionCheckCallback)(
+ IMG_PVOID pvUserData,
+ IMG_BOOL* pbCondMet);
+
+
+/**************************************************************************/ /*!
+@Function PVRSRVWaitForCondition
+@Description Wait using PVRSRVEventObjectWait() for a
+ condition (pfnCallback) to become true. It periodically
+ checks the condition state by employing a loop and
+ waiting on either the event supplied or sleeping for a brief
+ time (if hEvent is null) each time the condition is
+ checked and found not to be met. When the condition is true
+ the function returns. It will also return when the time
+ period has been exceeded or an error has occurred.
+
+@Input psConnection Services connection
+@Input hEvent Event to wait on or NULL not to use event
+ objects but OS wait for a short time.
+@Input pfnCallback Client condition check callback
+@Input pvUserData Client user data supplied to callback
+
+@Return PVRSRV_OK When condition met
+ PVRSRV_ERROR_TIMEOUT When condition not met and time is up
+ PVRSRV_* Otherwise, some other error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWaitForCondition(
+ const PVRSRV_CONNECTION* psConnection,
+ IMG_HANDLE hEvent,
+ PVRSRVConditionCheckCallback pfnCallback,
+ IMG_PVOID pvUserData);
+
+
+/**************************************************************************/ /*!
+@Function PVRSRVWaitUntilSyncPrimOpReady
+@Description Wait using PVRSRVWaitForCondition for a sync operation to
+ become ready.
+
+@Input psConnection Services connection
+@Input hEvent Event to wait on or NULL not to use event
+ objects but OS wait for a short time.
+@Input psOpCookie Sync operation cookie to test
+
+@Return PVRSRV_OK When condition met
+ PVRSRV_ERROR_TIMEOUT When condition not met and time is up
+ PVRSRV_* Otherwise, some other error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWaitUntilSyncPrimOpReady(
+ const PVRSRV_CONNECTION* psConnection,
+ IMG_HANDLE hEvent,
+ PSYNC_OP_COOKIE psOpCookie);
+
+
+/******************************************************************************
+ * PDUMP Function prototypes...
+ *****************************************************************************/
+#if defined(PDUMP)
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpInit
+@Description Pdump initialisation
+@Input psConnection Services connection
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpInit(const PVRSRV_CONNECTION *psConnection);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpStartInitPhase
+@Description Resume the pdump init phase state
+@Input psConnection Services connection
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStartInitPhase(const PVRSRV_CONNECTION *psConnection);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpStopInitPhase
+@Description Stop the pdump init phase state
+@Input psConnection Services connection
+@Input eModuleID Which module is requesting to stop the init phase
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStopInitPhase(const PVRSRV_CONNECTION *psConnection,
+ IMG_MODULE_ID eModuleID);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpSetFrame
+@Description Sets the pdump frame
+@Input psConnection Services connection
+@Input ui32Frame frame id
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+*/ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSetFrame(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Frame);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpGetFrame
+@Description Gets the current pdump frame
+@Input psConnection Services connection
+@Output pui32Frame frame id
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_error code
+*/ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpGetFrame(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 *pui32Frame);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpIsLastCaptureFrame
+@Description Returns whether this is the last frame of the capture range
+@Input psConnection Services connection
+@Return IMG_TRUE if last frame,
+ IMG_FALSE otherwise
+*/ /**************************************************************************/
+IMG_IMPORT
+IMG_BOOL IMG_CALLCONV PVRSRVPDumpIsLastCaptureFrame(const PVRSRV_CONNECTION *psConnection);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpAfterRender
+@Description Executes TraceBuffer and SignatureBuffer commands
+@Input psDevData Device data
+*/ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpAfterRender(PVRSRV_DEV_DATA *psDevData);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpComment
+@Description PDumps a comment
+@Input psConnection Services connection
+@Input pszComment Comment to be inserted
+@Input bContinuous pdump contiunous boolean
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpComment(const PVRSRV_CONNECTION *psConnection,
+ const IMG_CHAR *pszComment,
+ IMG_BOOL bContinuous);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpCommentf
+@Description PDumps a formatted comment
+@Input psConnection Services connection
+@Input bContinuous pdump continuous boolean
+@Input pszFormat Format string
+@Input ... vararg list
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentf(const PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL bContinuous,
+ const IMG_CHAR *pszFormat, ...)
+ IMG_FORMAT_PRINTF(3, 4);
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpCommentWithFlagsf
+@Description PDumps a formatted comment, passing in flags
+@Input psConnection Services connection
+@Input ui32Flags Flags
+@Input pszFormat Format string
+@Input ... vararg list
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentWithFlagsf(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Flags,
+ const IMG_CHAR *pszFormat, ...)
+ IMG_FORMAT_PRINTF(3, 4);
+
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpIsCapturing
+@Description Reports whether PDump is currently capturing or not
+@Input psConnection Services connection
+@Output pbIsCapturing Indicates whether PDump is currently
+ capturing
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpIsCapturing(const PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL *pbIsCapturing);
+
+
+/**************************************************************************/ /*!
+@Function PVRSRVPDumpIsCapturingTest
+@Description checks whether pdump is currently in frame capture range
+@Input psConnection Services connection
+@Return IMG_BOOL
+ */ /**************************************************************************/
+IMG_IMPORT
+IMG_BOOL IMG_CALLCONV PVRSRVPDumpIsCapturingTest(const PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSetDefaultCaptureParams(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Mode,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32End,
+ IMG_UINT32 ui32Interval,
+ IMG_UINT32 ui32MaxParamFileSize);
+
+#else /* PDUMP */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpInit)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpInit(const PVRSRV_CONNECTION *psConnection)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpStartInitPhase)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpStartInitPhase(const PVRSRV_CONNECTION *psConnection)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpStopInitPhase)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpStopInitPhase(const PVRSRV_CONNECTION *psConnection)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpSetFrame)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpSetFrame(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Frame)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(ui32Frame);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpGetFrame)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpGetFrame(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 *pui32Frame)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(pui32Frame);
+ return PVRSRV_OK;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpIsLastCaptureFrame)
+#endif
+static INLINE IMG_BOOL
+PVRSRVPDumpIsLastCaptureFrame(const PVRSRV_CONNECTION *psConnection)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpAfterRender)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpAfterRender(PVRSRV_DEV_DATA *psDevData)
+{
+ PVR_UNREFERENCED_PARAMETER(psDevData);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpComment)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpComment(const PVRSRV_CONNECTION *psConnection,
+ const IMG_CHAR *pszComment,
+ IMG_BOOL bContinuous)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(pszComment);
+ PVR_UNREFERENCED_PARAMETER(bContinuous);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpCommentf)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpCommentf(const PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL bContinuous,
+ const IMG_CHAR *pszFormat, ...)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(bContinuous);
+ PVR_UNREFERENCED_PARAMETER(pszFormat);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpCommentWithFlagsf)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpCommentWithFlagsf(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Flags,
+ const IMG_CHAR *pszFormat, ...)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(pszFormat);
+ return PVRSRV_OK;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpIsCapturing)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpIsCapturing(const PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL *pbIsCapturing)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ *pbIsCapturing = IMG_FALSE;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpIsCapturingTest)
+#endif
+static INLINE IMG_BOOL
+PVRSRVPDumpIsCapturingTest(const PVRSRV_CONNECTION *psConnection)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpSetPidCapRange)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpSetDefaultCaptureParams(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Mode,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32End,
+ IMG_UINT32 ui32Interval,
+ IMG_UINT32 ui32MaxParamFileSize)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(ui32Mode);
+ PVR_UNREFERENCED_PARAMETER(ui32Start);
+ PVR_UNREFERENCED_PARAMETER(ui32End);
+ PVR_UNREFERENCED_PARAMETER(ui32Interval);
+ PVR_UNREFERENCED_PARAMETER(ui32MaxParamFileSize);
+
+ return PVRSRV_OK;
+}
+
+
+#endif /* PDUMP */
+
+/**************************************************************************/ /*!
+@Function PVRSRVLoadLibrary
+@Description Load the named Dynamic-Link (Shared) Library. This will perform
+ reference counting in association with PVRSRVUnloadLibrary,
+ so for example if the same library is loaded twice and unloaded once,
+ a reference to the library will remain.
+@Input pszLibraryName the name of the library to load
+@Return On success, the handle of the newly-loaded
+ library. Otherwise, zero.
+ */ /**************************************************************************/
+IMG_IMPORT IMG_HANDLE PVRSRVLoadLibrary(const IMG_CHAR *pszLibraryName);
+
+/**************************************************************************/ /*!
+@Function PVRSRVUnloadLibrary
+@Description Unload the Dynamic-Link (Shared) Library which had previously been
+ loaded using PVRSRVLoadLibrary(). See PVRSRVLoadLibrary() for
+ information regarding reference counting.
+@Input hExtDrv handle of the Dynamic-Link / Shared library
+ to unload, as returned by PVRSRVLoadLibrary().
+@Return PVRSRV_OK if successful. Otherwise,
+ PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED.
+ */ /**************************************************************************/
+IMG_IMPORT PVRSRV_ERROR PVRSRVUnloadLibrary(IMG_HANDLE hExtDrv);
+
+/**************************************************************************/ /*!
+@Function PVRSRVGetLibFuncAddr
+@Description Returns the address of a function in a Dynamic-Link / Shared
+ Library.
+@Input hExtDrv handle of the Dynamic-Link / Shared Library
+ in which the function resides
+@Input pszFunctionName the name of the function
+@Output ppvFuncAddr on success, the address of the function
+ requested. Otherwise, NULL.
+@Return PVRSRV_OK if successful. Otherwise,
+ PVRSRV_ERROR_UNABLE_TO_GET_FUNC_ADDR.
+ */ /**************************************************************************/
+IMG_IMPORT PVRSRV_ERROR PVRSRVGetLibFuncAddr(IMG_HANDLE hExtDrv,
+ const IMG_CHAR *pszFunctionName,
+ IMG_VOID **ppvFuncAddr);
+
+/**************************************************************************/ /*!
+@Function PVRSRVClockus
+@Description Returns the current system clock time, in microseconds. Note
+ that this does not necessarily guarantee microsecond accuracy.
+@Return the curent system clock time, in
+ microseconds
+ */ /**************************************************************************/
+IMG_IMPORT IMG_UINT32 PVRSRVClockus (void);
+
+/**************************************************************************/ /*!
+@Function PVRSRVWaitus
+@Description Waits for the specified number of microseconds
+@Input ui32Timeus the time to wait for, in microseconds
+@Return None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID PVRSRVWaitus (IMG_UINT32 ui32Timeus);
+
+/**************************************************************************/ /*!
+@Function PVRSRVReleaseThreadQuanta
+@Description Releases thread quanta
+@Return None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID PVRSRVReleaseThreadQuanta (void);
+
+/**************************************************************************/ /*!
+@Function PVRSRVGetCurrentProcessID
+@Description Returns handle for current process
+@Return ID of current process
+ */ /**************************************************************************/
+IMG_IMPORT IMG_PID IMG_CALLCONV PVRSRVGetCurrentProcessID(void);
+
+/**************************************************************************/ /*!
+@Function PVRSRVSetLocale
+@Description Thin wrapper on posix setlocale
+@Input pszLocale
+@Return IMG_NULL (currently)
+ */ /**************************************************************************/
+IMG_IMPORT IMG_CHAR * IMG_CALLCONV PVRSRVSetLocale(const IMG_CHAR *pszLocale);
+
+
+/**************************************************************************/ /*!
+@Function PVRSRVCreateAppHintState
+@Description Create app hint state
+@Input eModuleID module id
+@Input pszAppName app name
+@Output ppvState state
+@Return None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVCreateAppHintState(IMG_MODULE_ID eModuleID,
+ const IMG_CHAR *pszAppName,
+ IMG_VOID **ppvState);
+/**************************************************************************/ /*!
+@Function PVRSRVFreeAppHintState
+@Description Free the app hint state, if it was created
+@Input eModuleID module id
+@Input pvHintState app hint state
+@Return None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeAppHintState(IMG_MODULE_ID eModuleID,
+ IMG_VOID *pvHintState);
+
+/**************************************************************************/ /*!
+@Function PVRSRVGetAppHint
+@Description Return the value of this hint from state or use default
+@Input pvHintState hint state
+@Input pszHintName hint name
+@Input eDataType data type
+@Input pvDefault default value
+@Output pvReturn hint value
+@Return True if hint read, False if used default
+ */ /**************************************************************************/
+IMG_IMPORT IMG_BOOL IMG_CALLCONV PVRSRVGetAppHint(IMG_VOID *pvHintState,
+ const IMG_CHAR *pszHintName,
+ IMG_DATA_TYPE eDataType,
+ const IMG_VOID *pvDefault,
+ IMG_VOID *pvReturn);
+
+/******************************************************************************
+ * Memory API(s)
+ *****************************************************************************/
+
+/* Exported APIs */
+/**************************************************************************/ /*!
+@Function PVRSRVAllocUserModeMem
+@Description Allocate a block of user-mode memory
+@Input ui32Size the amount of memory to allocate
+@Return On success, a pointer to the memory allocated.
+ Otherwise, NULL.
+ */ /**************************************************************************/
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMem (IMG_SIZE_T ui32Size);
+
+/**************************************************************************/ /*!
+@Function PVRSRVCallocUserModeMem
+@Description Allocate a block of user-mode memory
+@Input ui32Size the amount of memory to allocate
+@Return On success, a pointer to the memory allocated.
+ Otherwise, NULL.
+ */ /**************************************************************************/
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMem (IMG_SIZE_T ui32Size);
+
+/**************************************************************************/ /*!
+@Function PVRSRVReallocUserModeMem
+@Description Re-allocate a block of memory
+@Input pvBase the address of the existing memory, previously
+ allocated with PVRSRVAllocUserModeMem
+@Input uNewSize the newly-desired size of the memory chunk
+@Return On success, a pointer to the memory block. If the
+ size of the block could not be changed, the
+ return value is NULL.
+ */ /**************************************************************************/
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMem (IMG_PVOID pvBase, IMG_SIZE_T uNewSize);
+/**************************************************************************/ /*!
+@Function PVRSRVFreeUserModeMem
+@Description Free a block of memory previously allocated with
+ PVRSRVAllocUserModeMem
+@Input pvMem pointer to the block of memory to be freed
+@Return None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeUserModeMem (IMG_PVOID pvMem);
+
+/**************************************************************************/ /*!
+@Function PVRSRVMemCopy
+@Description Copy a block of memory
+ Safe implementation of memset for use with device memory.
+@Input pvDst Pointer to the destination
+@Input pvSrc Pointer to the source location
+@Input uiSize The amount of memory to copy in bytes
+@Return None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID PVRSRVMemCopy(IMG_VOID *pvDst, const IMG_VOID *pvSrc, IMG_SIZE_T uiSize);
+
+/**************************************************************************/ /*!
+@Function PVRSRVMemSet
+@Description Set all bytes in a region of memory to the specified value.
+ Safe implementation of memset for use with device memory.
+@Input pvDest 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 None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID PVRSRVMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T uiSize);
+
+/**************************************************************************/ /*!
+@Function PVRSRVLockProcessGlobalMutex
+@Description Locking function for non-recursive coarse-grained mutex shared
+ between all threads in a proccess.
+@Return None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockProcessGlobalMutex(void);
+
+/**************************************************************************/ /*!
+@Function PVRSRVUnlockProcessGlobalMutex
+@Description Unlocking function for non-recursive coarse-grained mutex shared
+ between all threads in a proccess.
+@Return None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockProcessGlobalMutex(void);
+
+
+typedef struct _OS_MUTEX_ *PVRSRV_MUTEX_HANDLE;
+
+/**************************************************************************/ /*!
+@Function PVRSRVCreateMutex
+@Description creates a mutex
+@Output phMutex ptr to mutex handle
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+#if !defined(PVR_DEBUG_MUTEXES)
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex);
+#else
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+#define PVRSRVCreateMutex(phMutex) \
+ PVRSRVCreateMutex(phMutex, #phMutex, __FILE__, __LINE__)
+#endif
+
+/**************************************************************************/ /*!
+@Function PVRSRVDestroyMutex
+@Description Create a mutex.
+@Input hMutex On success, filled with the new Mutex
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**********************************************************************/
+#if !defined(PVR_DEBUG_MUTEXES)
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex);
+#else
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+#define PVRSRVDestroyMutex(hMutex) \
+ PVRSRVDestroyMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#endif
+
+/**************************************************************************/ /*!
+@Function PVRSRVLockMutex
+@Description Lock the mutex passed
+@Input hMutex handle of the mutex to be locked
+@Return None
+ */ /**********************************************************************/
+#if !defined(PVR_DEBUG_MUTEXES)
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+#else
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+#define PVRSRVLockMutex(hMutex) \
+ PVRSRVLockMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#endif
+
+/**************************************************************************/ /*!
+@Function PVRSRVUnlockMutex
+@Description Unlock the mutex passed
+@Input hMutex handle of the mutex to be unlocked
+@Return None
+ */ /**********************************************************************/
+#if !defined(PVR_DEBUG_MUTEXES)
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+#else
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex,
+ IMG_CHAR pszMutexName[],
+ IMG_CHAR pszFilename[],
+ IMG_INT iLine);
+#define PVRSRVUnlockMutex(hMutex) \
+ PVRSRVUnlockMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#endif
+
+struct _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_ *PVRSRV_SEMAPHORE_HANDLE; /*!< Convenience typedef */
+
+
+#if defined(_MSC_VER)
+ /*!
+ Used when waiting for a semaphore to become unlocked. Indicates that
+ the caller is willing to wait forever.
+ */
+ #define IMG_SEMAPHORE_WAIT_INFINITE ((IMG_UINT64)0xFFFFFFFFFFFFFFFF)
+#else
+ /*!
+ Used when waiting for a semaphore to become unlocked. Indicates that
+ the caller is willing to wait forever.
+ */
+ #define IMG_SEMAPHORE_WAIT_INFINITE ((IMG_UINT64)0xFFFFFFFFFFFFFFFFull)
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCreateSemaphore)
+#endif
+/**************************************************************************/ /*!
+@Function PVRSRVCreateSemaphore
+@Description Create a semaphore with an initial count
+@Output phSemaphore on success, ptr to the handle of the new
+ semaphore. Otherwise, zero.
+@Input iInitialCount initial count
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+static INLINE PVRSRV_ERROR PVRSRVCreateSemaphore(PVRSRV_SEMAPHORE_HANDLE *phSemaphore,
+ IMG_INT iInitialCount)
+{
+ PVR_UNREFERENCED_PARAMETER(iInitialCount);
+ *phSemaphore = 0;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVDestroySemaphore)
+#endif
+/**************************************************************************/ /*!
+@Function PVRSRVDestroySemaphore
+@Description destroy the semaphore passed
+@Input hSemaphore the semaphore to be destroyed
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+static INLINE PVRSRV_ERROR PVRSRVDestroySemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore)
+{
+ PVR_UNREFERENCED_PARAMETER(hSemaphore);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVWaitSemaphore)
+#endif
+/**************************************************************************/ /*!
+@Function PVRSRVWaitSemaphore
+@Description wait on the specified semaphore
+@Input hSemaphore the semephore on which to wait
+@Input ui64TimeoutMicroSeconds the time to wait for the semaphore to
+ become unlocked, if locked when the function
+ is called.
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+static INLINE PVRSRV_ERROR PVRSRVWaitSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore,
+ IMG_UINT64 ui64TimeoutMicroSeconds)
+{
+ PVR_UNREFERENCED_PARAMETER(hSemaphore);
+ PVR_UNREFERENCED_PARAMETER(ui64TimeoutMicroSeconds);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPostSemaphore)
+#endif
+/**************************************************************************/ /*!
+@Function PVRSRVPostSemaphore
+@Description post semphore
+@Input hSemaphore handle to semaphore
+@Input iPostCount post count
+@Return None
+ */ /**************************************************************************/
+static INLINE IMG_VOID PVRSRVPostSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore, IMG_INT iPostCount)
+{
+ PVR_UNREFERENCED_PARAMETER(hSemaphore);
+ PVR_UNREFERENCED_PARAMETER(iPostCount);
+}
+
+/* Non-exported APIs */
+#if defined(DEBUG) && (defined(__linux__) || defined(_WIN32) || defined(__QNXNTO__))
+/**************************************************************************/ /*!
+@Function PVRSRVAllocUserModeMemTracking
+@Description Wrapper function for malloc, used for memory-leak detection
+@Input ui32Size number of bytes to be allocated
+@Input pszFileName filename of the calling code
+@Input ui32LineNumber line number of the calling code
+@Return On success, a ptr to the newly-allocated
+ memory. Otherwise, NULL.
+ */ /**************************************************************************/
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMemTracking(IMG_SIZE_T ui32Size,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32LineNumber);
+
+/**************************************************************************/ /*!
+@Function PVRSRVCallocUserModeMemTracking
+@Description Wrapper function for calloc, used for memory-leak detection
+@Input ui32Size number of bytes to be allocated
+@Input pszFileName filename of the calling code
+@Input ui32LineNumber line number of the calling code
+@Return On success, a ptr to the newly-allocated
+ memory. Otherwise, NULL.
+ */ /**************************************************************************/
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMemTracking(IMG_SIZE_T ui32Size,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32LineNumber);
+
+/**************************************************************************/ /*!
+@Function PVRSRVFreeUserModeMemTracking
+@Description Wrapper for free - see PVRSRVAllocUserModeMemTracking
+@Input pvMem pointer to the memory to be freed
+@Return None
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeUserModeMemTracking(IMG_VOID *pvMem);
+
+/**************************************************************************/ /*!
+@Function PVRSRVReallocUserModeMemTracking
+@Description Wrapper for realloc, used in memory-leak detection
+@Input pvMem pointer to the existing memory block
+@Input ui32NewSize the desired new size of the block
+@Input pszFileName the filename of the calling code
+@Input ui32LineNumber the line number of the calling code
+@Return on success, a pointer to the memory block.
+ This may not necessarily be the same
+ location as the block was at before the
+ call. On failure, NULL is returned.
+ */ /**************************************************************************/
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMemTracking(IMG_VOID *pvMem,
+ IMG_SIZE_T ui32NewSize,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32LineNumber);
+#endif /* defined(DEBUG) && (defined(__linux__) || defined(_WIN32)) */
+
+/**************************************************************************/ /*!
+@Function PVRSRVDumpDebugInfo
+@Description Dump debug information to kernel log
+@Input psConnection Services connection
+@Return IMG_VOID
+ */ /**************************************************************************/
+IMG_IMPORT IMG_VOID
+PVRSRVDumpDebugInfo(const PVRSRV_CONNECTION *psConnection, IMG_UINT32 ui32VerbLevel);
+
+/**************************************************************************/ /*!
+@Function PVRSRVGetDevClockSpeed
+@Description Gets the RGX clock speed
+@Input psConnection Services connection
+@Input psDevData Pointer to the PVRSRV_DEV_DATA context
+@Output pui32RGXClockSpeed Variable for storing clock speed
+@Return IMG_BOOL True if the operation was successful
+ */ /**************************************************************************/
+IMG_IMPORT IMG_BOOL IMG_CALLCONV PVRSRVGetDevClockSpeed(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_DEV_DATA *psDevData,
+ IMG_PUINT32 pui32RGXClockSpeed);
+
+/**************************************************************************/ /*!
+@Function PVRSRVResetHWRLogs
+@Description Resets the HWR Logs buffer (the hardware recovery count is not reset)
+@Input psConnection Services connection
+@Input psDevData Pointer to the PVRSRV_DEV_DATA context
+@Return PVRSRV_ERROR PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVResetHWRLogs(const PVRSRV_CONNECTION *psConnection, PVRSRV_DEV_DATA *psDevData);
+
+/******************************************************************************
+ * PVR Event Object API(s)
+ *****************************************************************************/
+
+/*****************************************************************************
+@Function PVRSRVAcquireGlobalEventObject
+@Description Gets a handle to an event
+ Outputs : phOSEvent Global eventobject event
+ Returns :
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+
+******************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVAcquireGlobalEventObject(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE *phOSEvent);
+
+/*****************************************************************************
+ Function Name : PVRSRVReleaseGlobalEventObject
+ Inputs : phOSEvent Global eventobject event
+ Outputs :
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+
+******************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVReleaseGlobalEventObject(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hOSEvent);
+
+/**************************************************************************/ /*!
+@Function PVRSRVEventObjectWait
+@Description Wait (block) on the OS-specific event object passed
+@Input psConnection Services connection
+@Input hOSEvent the event object to wait on
+@Return PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ */ /**************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVEventObjectWait(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hOSEvent);
+
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVKickDevices(const PVRSRV_CONNECTION *psConnection);
+
+
+/**************************************************************************/ /*!
+@Function RGXSoftReset
+@Description Resets some modules of the RGX device
+@Input psConnection Services connection
+@Input psDevData Pointer to the PVRSRV_DEV_DATA context
+@Output ui64ResetValue a mask for which each bit set correspond
+ to a module to reset.
+@Return PVRSRV_ERROR
+*/ /***************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVSoftReset(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_DEV_DATA *psDevData,
+ IMG_UINT64 ui64ResetValue);
+
+/*!
+ Time wrapping macro
+*/
+#define TIME_NOT_PASSED_UINT32(a,b,c) (((a) - (b)) < (c))
+
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __SERVICES_H__ */
+
+/******************************************************************************
+ End of file (services.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/servicesext.h b/drivers/gpu/rogue/include/servicesext.h
new file mode 100644
index 000000000000..09dd2243e9d0
--- /dev/null
+++ b/drivers/gpu/rogue/include/servicesext.h
@@ -0,0 +1,180 @@
+/*************************************************************************/ /*!
+@File
+@Title Services definitions required by external drivers
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides services data structures, defines and prototypes
+ required by external drivers
+@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 (__SERVICESEXT_H__)
+#define __SERVICESEXT_H__
+
+/* include/ */
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "pvrsrv_device_types.h"
+
+
+/*
+ * Lock buffer read/write flags
+ */
+#define PVRSRV_LOCKFLG_READONLY (1) /*!< The locking process will only read the locked surface */
+
+/*!
+ *****************************************************************************
+ * Services State
+ *****************************************************************************/
+typedef enum _PVRSRV_SERVICES_STATE_
+{
+ PVRSRV_SERVICES_STATE_OK = 0,
+ PVRSRV_SERVICES_STATE_BAD,
+} PVRSRV_SERVICES_STATE;
+
+
+/*!
+ *****************************************************************************
+ * States for power management
+ *****************************************************************************/
+/*!
+ System Power State Enum
+ */
+typedef enum _PVRSRV_SYS_POWER_STATE_
+{
+ PVRSRV_SYS_POWER_STATE_Unspecified = -1, /*!< Unspecified : Uninitialised */
+ PVRSRV_SYS_POWER_STATE_OFF = 0, /*!< Off */
+ PVRSRV_SYS_POWER_STATE_ON = 1, /*!< On */
+
+ PVRSRV_SYS_POWER_STATE_FORCE_I32 = 0x7fffffff /*!< Force enum to be at least 32-bits wide */
+
+} PVRSRV_SYS_POWER_STATE, *PPVRSRV_SYS_POWER_STATE; /*!< Typedef for ptr to 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 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.
+ */
+typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ IMG_BOOL bForced);
+
+/* Clock speed handler prototypes */
+
+/*!
+ Typedef for a pointer to a Function that will be caled before a transition
+ from one clockspeed to another. See also PFN_POST_CLOCKSPEED_CHANGE.
+ */
+typedef PVRSRV_ERROR (*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+/*!
+ Typedef for a pointer to a Function that will be caled after a transition
+ from one clockspeed to another. See also PFN_PRE_CLOCKSPEED_CHANGE.
+ */
+typedef PVRSRV_ERROR (*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+/*!
+ *****************************************************************************
+ * Enumeration of possible alpha types.
+ *****************************************************************************/
+typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
+ PVRSRV_COLOURSPACE_FORMAT_UNKNOWN = 0x00000000, /*!< Colourspace Format: Unknown */
+ PVRSRV_COLOURSPACE_FORMAT_LINEAR = 0x00010000, /*!< Colourspace Format: Linear */
+ PVRSRV_COLOURSPACE_FORMAT_NONLINEAR = 0x00020000, /*!< Colourspace Format: Non-Linear */
+ PVRSRV_COLOURSPACE_FORMAT_MASK = 0x000F0000, /*!< Colourspace Format Mask */
+} PVRSRV_COLOURSPACE_FORMAT;
+
+
+/*!
+ * Drawable orientation (in degrees clockwise).
+ */
+typedef enum _PVRSRV_ROTATION_ {
+ PVRSRV_ROTATE_0 = 0, /*!< Rotate by 0 degres */
+ PVRSRV_ROTATE_90 = 1, /*!< Rotate by 90 degrees */
+ PVRSRV_ROTATE_180 = 2, /*!< Rotate by 180 degrees */
+ PVRSRV_ROTATE_270 = 3, /*!< Rotate by 270 degrees */
+ PVRSRV_FLIP_Y = 4, /*!< Flip in Y axis */
+
+} PVRSRV_ROTATION;
+
+/*!
+ *****************************************************************************
+ * This structure is used for OS independent registry (profile) access
+ *****************************************************************************/
+
+typedef struct _PVRSRV_REGISTRY_INFO
+{
+ IMG_UINT32 ui32DevCookie;
+ IMG_PCHAR pszKey;
+ IMG_PCHAR pszValue;
+ IMG_PCHAR pszBuf;
+ IMG_UINT32 ui32BufSize;
+} PVRSRV_REGISTRY_INFO, *PPVRSRV_REGISTRY_INFO;
+
+#endif /* __SERVICESEXT_H__ */
+/*****************************************************************************
+ End of file (servicesext.h)
+*****************************************************************************/
+
diff --git a/drivers/gpu/rogue/include/sync_external.h b/drivers/gpu/rogue/include/sync_external.h
new file mode 100644
index 000000000000..efe5beb19c03
--- /dev/null
+++ b/drivers/gpu/rogue/include/sync_external.h
@@ -0,0 +1,78 @@
+/*************************************************************************/ /*!
+@File
+@Title Services external synchronisation interface header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines synchronisation structures that are visible internally
+ and externally
+@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"
+
+#ifndef _SYNC_EXTERNAL_
+#define _SYNC_EXTERNAL_
+
+#define SYNC_MAX_CLASS_NAME_LEN 32
+
+typedef IMG_HANDLE SYNC_BRIDGE_HANDLE;
+typedef struct SYNC_PRIM_CONTEXT *PSYNC_PRIM_CONTEXT;
+typedef struct _SYNC_OP_COOKIE_ *PSYNC_OP_COOKIE;
+
+typedef struct PVRSRV_CLIENT_SYNC_PRIM
+{
+ volatile IMG_UINT32 *pui32LinAddr; /*!< User pointer to the primitive */
+} PVRSRV_CLIENT_SYNC_PRIM;
+
+typedef IMG_HANDLE PVRSRV_CLIENT_SYNC_PRIM_HANDLE;
+
+typedef struct PVRSRV_CLIENT_SYNC_PRIM_OP
+{
+ IMG_UINT32 ui32Flags; /*!< Operation flags */
+#define PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK (1 << 0)
+#define PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE (1 << 1)
+ PVRSRV_CLIENT_SYNC_PRIM *psSync; /*!< Pointer to the client sync */
+ IMG_UINT32 ui32FenceValue; /*!< The Fence value (only used if PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK is set) */
+ IMG_UINT32 ui32UpdateValue; /*!< The Update value (only used if PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE is set) */
+} PVRSRV_CLIENT_SYNC_PRIM_OP;
+
+#if defined(KERNEL) && defined(ANDROID)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+
+#endif /* _SYNC_EXTERNAL_ */
diff --git a/drivers/gpu/rogue/include/system/rgx_tc/apollo_regs.h b/drivers/gpu/rogue/include/system/rgx_tc/apollo_regs.h
new file mode 100644
index 000000000000..5e04920b8a84
--- /dev/null
+++ b/drivers/gpu/rogue/include/system/rgx_tc/apollo_regs.h
@@ -0,0 +1,79 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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(__APOLLO_REGS_H__)
+#define __APOLLO_REGS_H__
+
+#if defined(TC_APOLLO_ES2)
+ /* TC ES2 */
+ #define RGX_TC_CORE_CLOCK_SPEED (90000000)
+ #define RGX_TC_MEM_CLOCK_SPEED (104000000)
+ #define TCF_TEMP_SENSOR_SPI_OFFSET 0xe
+ #define TCF_TEMP_SENSOR_TO_C(raw) (((raw) * 248 / 4096) - 54)
+#else
+ /* TC ES1 */
+ #define RGX_TC_CORE_CLOCK_SPEED (90000000)
+ #define RGX_TC_MEM_CLOCK_SPEED (65000000)
+#endif
+
+/* Apollo reg on base register 0 */
+#define SYS_APOLLO_REG_PCI_BASENUM (0)
+#define SYS_APOLLO_REG_REGION_SIZE (0x00010000)
+
+#define SYS_APOLLO_REG_SYS_OFFSET (0x0000)
+#define SYS_APOLLO_REG_SYS_SIZE (0x0400)
+
+#define SYS_APOLLO_REG_PLL_OFFSET (0x1000)
+#define SYS_APOLLO_REG_PLL_SIZE (0x0400)
+
+#define SYS_APOLLO_REG_HOST_OFFSET (0x4050)
+#define SYS_APOLLO_REG_HOST_SIZE (0x0014)
+
+#define SYS_APOLLO_REG_PDP_OFFSET (0xC000)
+#define SYS_APOLLO_REG_PDP_SIZE (0x0400)
+
+/* RGX reg on base register 1 */
+#define SYS_RGX_REG_PCI_BASENUM (1)
+#define SYS_RGX_REG_REGION_SIZE (0x00004000)
+
+#endif /* if !defined(__APOLLO_REGS_H__) */
diff --git a/drivers/gpu/rogue/include/system/rgx_tc/pdp_regs.h b/drivers/gpu/rogue/include/system/rgx_tc/pdp_regs.h
new file mode 100644
index 000000000000..bd26b0617f95
--- /dev/null
+++ b/drivers/gpu/rogue/include/system/rgx_tc/pdp_regs.h
@@ -0,0 +1,75 @@
+/*************************************************************************/ /*!
+@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(__PDP_REGS_H__)
+#define __PDP_REGS_H__
+
+/*************************************************************************/ /*!
+ PCI Device Information
+*/ /**************************************************************************/
+
+#define DCPDP_VENDOR_ID_POWERVR (0x1010)
+
+#define DCPDP_DEVICE_ID_PCI_APOLLO_FPGA (0x1CF1)
+#define DCPDP_DEVICE_ID_PCIE_APOLLO_FPGA (0x1CF2)
+
+/*************************************************************************/ /*!
+ PCI Device Base Address Information
+*/ /**************************************************************************/
+
+/* PLL and PDP registers on base address register 0 */
+#define DCPDP_REG_PCI_BASENUM (0)
+
+#define DCPDP_PCI_PLL_REG_OFFSET (0x1000)
+#define DCPDP_PCI_PLL_REG_SIZE (0x0400)
+
+#define DCPDP_PCI_PDP_REG_OFFSET (0xC000)
+#define DCPDP_PCI_PDP_REG_SIZE (0x2000)
+
+/*************************************************************************/ /*!
+ Misc register information
+*/ /**************************************************************************/
+
+/* This information isn't captured in tcf_rgbpdp_regs.h so define it here */
+#define DCPDP_STR1SURF_FORMAT_ARGB8888 (0xE)
+#define DCPDP_STR1ADDRCTRL_BASE_ADDR_SHIFT (4)
+#define DCPDP_STR1POSN_STRIDE_SHIFT (4)
+
+#endif /* !defined(__PDP_REGS_H__) */
diff --git a/drivers/gpu/rogue/include/system/rgx_tc/tcf_clk_ctrl.h b/drivers/gpu/rogue/include/system/rgx_tc/tcf_clk_ctrl.h
new file mode 100644
index 000000000000..a42d23e995dc
--- /dev/null
+++ b/drivers/gpu/rogue/include/system/rgx_tc/tcf_clk_ctrl.h
@@ -0,0 +1,808 @@
+/*************************************************************************/ /*!
+@Title Test Chip Framework system control register definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Autogenerated C -- do not edit
+ Generated from: tcf_clk_ctrl.def
+@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(_TCF_CLK_CTRL_H_)
+#define _TCF_CLK_CTRL_H_
+
+/*
+ Register FPGA_ID_REG
+*/
+#define TCF_CLK_CTRL_FPGA_ID_REG 0x0000
+#define FPGA_ID_REG_CORE_CFG_MASK 0x0000FFFFU
+#define FPGA_ID_REG_CORE_CFG_SHIFT 0
+#define FPGA_ID_REG_CORE_CFG_SIGNED 0
+
+#define FPGA_ID_REG_CORE_ID_MASK 0xFFFF0000U
+#define FPGA_ID_REG_CORE_ID_SHIFT 16
+#define FPGA_ID_REG_CORE_ID_SIGNED 0
+
+/*
+ Register FPGA_REV_REG
+*/
+#define TCF_CLK_CTRL_FPGA_REV_REG 0x0008
+#define FPGA_REV_REG_MAINT_MASK 0x000000FFU
+#define FPGA_REV_REG_MAINT_SHIFT 0
+#define FPGA_REV_REG_MAINT_SIGNED 0
+
+#define FPGA_REV_REG_MINOR_MASK 0x0000FF00U
+#define FPGA_REV_REG_MINOR_SHIFT 8
+#define FPGA_REV_REG_MINOR_SIGNED 0
+
+#define FPGA_REV_REG_MAJOR_MASK 0x00FF0000U
+#define FPGA_REV_REG_MAJOR_SHIFT 16
+#define FPGA_REV_REG_MAJOR_SIGNED 0
+
+#define FPGA_REV_REG_DESIGNER_MASK 0xFF000000U
+#define FPGA_REV_REG_DESIGNER_SHIFT 24
+#define FPGA_REV_REG_DESIGNER_SIGNED 0
+
+/*
+ Register FPGA_DES_REV_1
+*/
+#define TCF_CLK_CTRL_FPGA_DES_REV_1 0x0010
+#define FPGA_DES_REV_1_MASK 0xFFFFFFFFU
+#define FPGA_DES_REV_1_SHIFT 0
+#define FPGA_DES_REV_1_SIGNED 0
+
+/*
+ Register FPGA_DES_REV_2
+*/
+#define TCF_CLK_CTRL_FPGA_DES_REV_2 0x0018
+#define FPGA_DES_REV_2_MASK 0xFFFFFFFFU
+#define FPGA_DES_REV_2_SHIFT 0
+#define FPGA_DES_REV_2_SIGNED 0
+
+/*
+ Register TCF_CORE_ID_REG
+*/
+#define TCF_CLK_CTRL_TCF_CORE_ID_REG 0x0020
+#define TCF_CORE_ID_REG_CORE_CFG_MASK 0x0000FFFFU
+#define TCF_CORE_ID_REG_CORE_CFG_SHIFT 0
+#define TCF_CORE_ID_REG_CORE_CFG_SIGNED 0
+
+#define TCF_CORE_ID_REG_CORE_ID_MASK 0xFFFF0000U
+#define TCF_CORE_ID_REG_CORE_ID_SHIFT 16
+#define TCF_CORE_ID_REG_CORE_ID_SIGNED 0
+
+/*
+ Register TCF_CORE_REV_REG
+*/
+#define TCF_CLK_CTRL_TCF_CORE_REV_REG 0x0028
+#define TCF_CORE_REV_REG_MAINT_MASK 0x000000FFU
+#define TCF_CORE_REV_REG_MAINT_SHIFT 0
+#define TCF_CORE_REV_REG_MAINT_SIGNED 0
+
+#define TCF_CORE_REV_REG_MINOR_MASK 0x0000FF00U
+#define TCF_CORE_REV_REG_MINOR_SHIFT 8
+#define TCF_CORE_REV_REG_MINOR_SIGNED 0
+
+#define TCF_CORE_REV_REG_MAJOR_MASK 0x00FF0000U
+#define TCF_CORE_REV_REG_MAJOR_SHIFT 16
+#define TCF_CORE_REV_REG_MAJOR_SIGNED 0
+
+#define TCF_CORE_REV_REG_DESIGNER_MASK 0xFF000000U
+#define TCF_CORE_REV_REG_DESIGNER_SHIFT 24
+#define TCF_CORE_REV_REG_DESIGNER_SIGNED 0
+
+/*
+ Register TCF_CORE_DES_REV_1
+*/
+#define TCF_CLK_CTRL_TCF_CORE_DES_REV_1 0x0030
+#define TCF_CORE_DES_REV_1_MASK 0xFFFFFFFFU
+#define TCF_CORE_DES_REV_1_SHIFT 0
+#define TCF_CORE_DES_REV_1_SIGNED 0
+
+/*
+ Register TCF_CORE_DES_REV_2
+*/
+#define TCF_CLK_CTRL_TCF_CORE_DES_REV_2 0x0038
+#define TCF_CORE_DES_REV_2_MASK 0xFFFFFFFFU
+#define TCF_CORE_DES_REV_2_SHIFT 0
+#define TCF_CORE_DES_REV_2_SIGNED 0
+
+/*
+ Register SCB_GENERAL_CONTROL
+*/
+#define TCF_CLK_CTRL_SCB_GENERAL_CONTROL 0x0040
+#define SCB_GC_TRANS_HALT_MASK 0x00000200U
+#define SCB_GC_TRANS_HALT_SHIFT 9
+#define SCB_GC_TRANS_HALT_SIGNED 0
+
+#define SCB_GC_CKD_REGS_MASK 0x00000100U
+#define SCB_GC_CKD_REGS_SHIFT 8
+#define SCB_GC_CKD_REGS_SIGNED 0
+
+#define SCB_GC_CKD_SLAVE_MASK 0x00000080U
+#define SCB_GC_CKD_SLAVE_SHIFT 7
+#define SCB_GC_CKD_SLAVE_SIGNED 0
+
+#define SCB_GC_CKD_MASTER_MASK 0x00000040U
+#define SCB_GC_CKD_MASTER_SHIFT 6
+#define SCB_GC_CKD_MASTER_SIGNED 0
+
+#define SCB_GC_CKD_XDATA_MASK 0x00000020U
+#define SCB_GC_CKD_XDATA_SHIFT 5
+#define SCB_GC_CKD_XDATA_SIGNED 0
+
+#define SCB_GC_SFR_REG_MASK 0x00000010U
+#define SCB_GC_SFR_REG_SHIFT 4
+#define SCB_GC_SFR_REG_SIGNED 0
+
+#define SCB_GC_SFR_SLAVE_MASK 0x00000008U
+#define SCB_GC_SFR_SLAVE_SHIFT 3
+#define SCB_GC_SFR_SLAVE_SIGNED 0
+
+#define SCB_GC_SFR_MASTER_MASK 0x00000004U
+#define SCB_GC_SFR_MASTER_SHIFT 2
+#define SCB_GC_SFR_MASTER_SIGNED 0
+
+#define SCB_GC_SFR_DET_DATA_MASK 0x00000002U
+#define SCB_GC_SFR_DET_DATA_SHIFT 1
+#define SCB_GC_SFR_DET_DATA_SIGNED 0
+
+#define SCB_GC_SFR_GEN_DATA_MASK 0x00000001U
+#define SCB_GC_SFR_GEN_DATA_SHIFT 0
+#define SCB_GC_SFR_GEN_DATA_SIGNED 0
+
+/*
+ Register SCB_MASTER_READ_COUNT
+*/
+#define TCF_CLK_CTRL_SCB_MASTER_READ_COUNT 0x0048
+#define MASTER_READ_COUNT_MASK 0x0000FFFFU
+#define MASTER_READ_COUNT_SHIFT 0
+#define MASTER_READ_COUNT_SIGNED 0
+
+/*
+ Register SCB_MASTER_READ_DATA
+*/
+#define TCF_CLK_CTRL_SCB_MASTER_READ_DATA 0x0050
+#define MASTER_READ_DATA_MASK 0x000000FFU
+#define MASTER_READ_DATA_SHIFT 0
+#define MASTER_READ_DATA_SIGNED 0
+
+/*
+ Register SCB_MASTER_ADDRESS
+*/
+#define TCF_CLK_CTRL_SCB_MASTER_ADDRESS 0x0058
+#define SCB_MASTER_ADDRESS_MASK 0x000003FFU
+#define SCB_MASTER_ADDRESS_SHIFT 0
+#define SCB_MASTER_ADDRESS_SIGNED 0
+
+/*
+ Register SCB_MASTER_WRITE_DATA
+*/
+#define TCF_CLK_CTRL_SCB_MASTER_WRITE_DATA 0x0060
+#define MASTER_WRITE_DATA_MASK 0x000000FFU
+#define MASTER_WRITE_DATA_SHIFT 0
+#define MASTER_WRITE_DATA_SIGNED 0
+
+/*
+ Register SCB_MASTER_WRITE_COUNT
+*/
+#define TCF_CLK_CTRL_SCB_MASTER_WRITE_COUNT 0x0068
+#define MASTER_WRITE_COUNT_MASK 0x0000FFFFU
+#define MASTER_WRITE_COUNT_SHIFT 0
+#define MASTER_WRITE_COUNT_SIGNED 0
+
+/*
+ Register SCB_BUS_SELECT
+*/
+#define TCF_CLK_CTRL_SCB_BUS_SELECT 0x0070
+#define BUS_SELECT_MASK 0x00000003U
+#define BUS_SELECT_SHIFT 0
+#define BUS_SELECT_SIGNED 0
+
+/*
+ Register SCB_MASTER_FILL_STATUS
+*/
+#define TCF_CLK_CTRL_SCB_MASTER_FILL_STATUS 0x0078
+#define MASTER_WRITE_FIFO_EMPTY_MASK 0x00000008U
+#define MASTER_WRITE_FIFO_EMPTY_SHIFT 3
+#define MASTER_WRITE_FIFO_EMPTY_SIGNED 0
+
+#define MASTER_WRITE_FIFO_FULL_MASK 0x00000004U
+#define MASTER_WRITE_FIFO_FULL_SHIFT 2
+#define MASTER_WRITE_FIFO_FULL_SIGNED 0
+
+#define MASTER_READ_FIFO_EMPTY_MASK 0x00000002U
+#define MASTER_READ_FIFO_EMPTY_SHIFT 1
+#define MASTER_READ_FIFO_EMPTY_SIGNED 0
+
+#define MASTER_READ_FIFO_FULL_MASK 0x00000001U
+#define MASTER_READ_FIFO_FULL_SHIFT 0
+#define MASTER_READ_FIFO_FULL_SIGNED 0
+
+/*
+ Register CLK_AND_RST_CTRL
+*/
+#define TCF_CLK_CTRL_CLK_AND_RST_CTRL 0x0080
+#define GLB_CLKG_EN_MASK 0x00020000U
+#define GLB_CLKG_EN_SHIFT 17
+#define GLB_CLKG_EN_SIGNED 0
+
+#define CLK_GATE_CNTL_MASK 0x00010000U
+#define CLK_GATE_CNTL_SHIFT 16
+#define CLK_GATE_CNTL_SIGNED 0
+
+#define DUT_DCM_RESETN_MASK 0x00000400U
+#define DUT_DCM_RESETN_SHIFT 10
+#define DUT_DCM_RESETN_SIGNED 0
+
+#define MEM_RESYNC_BYPASS_MASK 0x00000200U
+#define MEM_RESYNC_BYPASS_SHIFT 9
+#define MEM_RESYNC_BYPASS_SIGNED 0
+
+#define SYS_RESYNC_BYPASS_MASK 0x00000100U
+#define SYS_RESYNC_BYPASS_SHIFT 8
+#define SYS_RESYNC_BYPASS_SIGNED 0
+
+#define SCB_RESETN_MASK 0x00000010U
+#define SCB_RESETN_SHIFT 4
+#define SCB_RESETN_SIGNED 0
+
+#define PDP2_RESETN_MASK 0x00000008U
+#define PDP2_RESETN_SHIFT 3
+#define PDP2_RESETN_SIGNED 0
+
+#define PDP1_RESETN_MASK 0x00000004U
+#define PDP1_RESETN_SHIFT 2
+#define PDP1_RESETN_SIGNED 0
+
+#define DDR_RESETN_MASK 0x00000002U
+#define DDR_RESETN_SHIFT 1
+#define DDR_RESETN_SIGNED 0
+
+#define DUT_RESETN_MASK 0x00000001U
+#define DUT_RESETN_SHIFT 0
+#define DUT_RESETN_SIGNED 0
+
+/*
+ Register TEST_REG_OUT
+*/
+#define TCF_CLK_CTRL_TEST_REG_OUT 0x0088
+#define TEST_REG_OUT_MASK 0xFFFFFFFFU
+#define TEST_REG_OUT_SHIFT 0
+#define TEST_REG_OUT_SIGNED 0
+
+/*
+ Register TEST_REG_IN
+*/
+#define TCF_CLK_CTRL_TEST_REG_IN 0x0090
+#define TEST_REG_IN_MASK 0xFFFFFFFFU
+#define TEST_REG_IN_SHIFT 0
+#define TEST_REG_IN_SIGNED 0
+
+/*
+ Register TEST_CTRL
+*/
+#define TCF_CLK_CTRL_TEST_CTRL 0x0098
+#define PCI_TEST_OFFSET_MASK 0xF8000000U
+#define PCI_TEST_OFFSET_SHIFT 27
+#define PCI_TEST_OFFSET_SIGNED 0
+
+#define HOST_PHY_MODE_MASK 0x00000100U
+#define HOST_PHY_MODE_SHIFT 8
+#define HOST_PHY_MODE_SIGNED 0
+
+#define HOST_ONLY_MODE_MASK 0x00000080U
+#define HOST_ONLY_MODE_SHIFT 7
+#define HOST_ONLY_MODE_SIGNED 0
+
+#define PCI_TEST_MODE_MASK 0x00000040U
+#define PCI_TEST_MODE_SHIFT 6
+#define PCI_TEST_MODE_SIGNED 0
+
+#define TURN_OFF_DDR_MASK 0x00000020U
+#define TURN_OFF_DDR_SHIFT 5
+#define TURN_OFF_DDR_SIGNED 0
+
+#define SYS_RD_CLK_INV_MASK 0x00000010U
+#define SYS_RD_CLK_INV_SHIFT 4
+#define SYS_RD_CLK_INV_SIGNED 0
+
+#define MEM_REQ_CLK_INV_MASK 0x00000008U
+#define MEM_REQ_CLK_INV_SHIFT 3
+#define MEM_REQ_CLK_INV_SIGNED 0
+
+#define BURST_SPLIT_MASK 0x00000004U
+#define BURST_SPLIT_SHIFT 2
+#define BURST_SPLIT_SIGNED 0
+
+#define CLK_INVERSION_MASK 0x00000002U
+#define CLK_INVERSION_SHIFT 1
+#define CLK_INVERSION_SIGNED 0
+
+#define ADDRESS_FORCE_MASK 0x00000001U
+#define ADDRESS_FORCE_SHIFT 0
+#define ADDRESS_FORCE_SIGNED 0
+
+/*
+ Register CLEAR_HOST_MEM_SIG
+*/
+#define TCF_CLK_CTRL_CLEAR_HOST_MEM_SIG 0x00A0
+#define SIGNATURE_TAG_ID_MASK 0x00000F00U
+#define SIGNATURE_TAG_ID_SHIFT 8
+#define SIGNATURE_TAG_ID_SIGNED 0
+
+#define CLEAR_HOST_MEM_SIGNATURE_MASK 0x00000001U
+#define CLEAR_HOST_MEM_SIGNATURE_SHIFT 0
+#define CLEAR_HOST_MEM_SIGNATURE_SIGNED 0
+
+/*
+ Register HOST_MEM_SIGNATURE
+*/
+#define TCF_CLK_CTRL_HOST_MEM_SIGNATURE 0x00A8
+#define HOST_MEM_SIGNATURE_MASK 0xFFFFFFFFU
+#define HOST_MEM_SIGNATURE_SHIFT 0
+#define HOST_MEM_SIGNATURE_SIGNED 0
+
+/*
+ Register INTERRUPT_STATUS
+*/
+#define TCF_CLK_CTRL_INTERRUPT_STATUS 0x00C8
+#define INTERRUPT_MASTER_STATUS_MASK 0x80000000U
+#define INTERRUPT_MASTER_STATUS_SHIFT 31
+#define INTERRUPT_MASTER_STATUS_SIGNED 0
+
+#define OTHER_INTS_MASK 0x7FFE0000U
+#define OTHER_INTS_SHIFT 17
+#define OTHER_INTS_SIGNED 0
+
+#define HOST_MST_NORESPONSE_MASK 0x00010000U
+#define HOST_MST_NORESPONSE_SHIFT 16
+#define HOST_MST_NORESPONSE_SIGNED 0
+
+#define PDP2_INT_MASK 0x00008000U
+#define PDP2_INT_SHIFT 15
+#define PDP2_INT_SIGNED 0
+
+#define PDP1_INT_MASK 0x00004000U
+#define PDP1_INT_SHIFT 14
+#define PDP1_INT_SIGNED 0
+
+#define EXT_INT_MASK 0x00002000U
+#define EXT_INT_SHIFT 13
+#define EXT_INT_SIGNED 0
+
+#define SCB_MST_HLT_BIT_MASK 0x00001000U
+#define SCB_MST_HLT_BIT_SHIFT 12
+#define SCB_MST_HLT_BIT_SIGNED 0
+
+#define SCB_SLV_EVENT_MASK 0x00000800U
+#define SCB_SLV_EVENT_SHIFT 11
+#define SCB_SLV_EVENT_SIGNED 0
+
+#define SCB_TDONE_RX_MASK 0x00000400U
+#define SCB_TDONE_RX_SHIFT 10
+#define SCB_TDONE_RX_SIGNED 0
+
+#define SCB_SLV_WT_RD_DAT_MASK 0x00000200U
+#define SCB_SLV_WT_RD_DAT_SHIFT 9
+#define SCB_SLV_WT_RD_DAT_SIGNED 0
+
+#define SCB_SLV_WT_PRV_RD_MASK 0x00000100U
+#define SCB_SLV_WT_PRV_RD_SHIFT 8
+#define SCB_SLV_WT_PRV_RD_SIGNED 0
+
+#define SCB_SLV_WT_WR_DAT_MASK 0x00000080U
+#define SCB_SLV_WT_WR_DAT_SHIFT 7
+#define SCB_SLV_WT_WR_DAT_SIGNED 0
+
+#define SCB_MST_WT_RD_DAT_MASK 0x00000040U
+#define SCB_MST_WT_RD_DAT_SHIFT 6
+#define SCB_MST_WT_RD_DAT_SIGNED 0
+
+#define SCB_ADD_ACK_ERR_MASK 0x00000020U
+#define SCB_ADD_ACK_ERR_SHIFT 5
+#define SCB_ADD_ACK_ERR_SIGNED 0
+
+#define SCB_WR_ACK_ERR_MASK 0x00000010U
+#define SCB_WR_ACK_ERR_SHIFT 4
+#define SCB_WR_ACK_ERR_SIGNED 0
+
+#define SCB_SDAT_LO_TIM_MASK 0x00000008U
+#define SCB_SDAT_LO_TIM_SHIFT 3
+#define SCB_SDAT_LO_TIM_SIGNED 0
+
+#define SCB_SCLK_LO_TIM_MASK 0x00000004U
+#define SCB_SCLK_LO_TIM_SHIFT 2
+#define SCB_SCLK_LO_TIM_SIGNED 0
+
+#define SCB_UNEX_START_BIT_MASK 0x00000002U
+#define SCB_UNEX_START_BIT_SHIFT 1
+#define SCB_UNEX_START_BIT_SIGNED 0
+
+#define SCB_BUS_INACTIVE_MASK 0x00000001U
+#define SCB_BUS_INACTIVE_SHIFT 0
+#define SCB_BUS_INACTIVE_SIGNED 0
+
+/*
+ Register INTERRUPT_OP_CFG
+*/
+#define TCF_CLK_CTRL_INTERRUPT_OP_CFG 0x00D0
+#define PULSE_NLEVEL_MASK 0x80000000U
+#define PULSE_NLEVEL_SHIFT 31
+#define PULSE_NLEVEL_SIGNED 0
+
+#define INT_SENSE_MASK 0x40000000U
+#define INT_SENSE_SHIFT 30
+#define INT_SENSE_SIGNED 0
+
+#define INTERRUPT_DEST_MASK 0x0000000FU
+#define INTERRUPT_DEST_SHIFT 0
+#define INTERRUPT_DEST_SIGNED 0
+
+/*
+ Register INTERRUPT_ENABLE
+*/
+#define TCF_CLK_CTRL_INTERRUPT_ENABLE 0x00D8
+#define INTERRUPT_MASTER_ENABLE_MASK 0x80000000U
+#define INTERRUPT_MASTER_ENABLE_SHIFT 31
+#define INTERRUPT_MASTER_ENABLE_SIGNED 0
+
+#define INTERRUPT_ENABLE_MASK 0x7FFFFFFFU
+#define INTERRUPT_ENABLE_SHIFT 0
+#define INTERRUPT_ENABLE_SIGNED 0
+
+/*
+ Register INTERRUPT_CLEAR
+*/
+#define TCF_CLK_CTRL_INTERRUPT_CLEAR 0x00E0
+#define INTERRUPT_MASTER_CLEAR_MASK 0x80000000U
+#define INTERRUPT_MASTER_CLEAR_SHIFT 31
+#define INTERRUPT_MASTER_CLEAR_SIGNED 0
+
+#define INTERRUPT_CLEAR_MASK 0x7FFFFFFFU
+#define INTERRUPT_CLEAR_SHIFT 0
+#define INTERRUPT_CLEAR_SIGNED 0
+
+/*
+ Register YCC_RGB_CTRL
+*/
+#define TCF_CLK_CTRL_YCC_RGB_CTRL 0x00E8
+#define RGB_CTRL1_MASK 0x000001FFU
+#define RGB_CTRL1_SHIFT 0
+#define RGB_CTRL1_SIGNED 0
+
+#define RGB_CTRL2_MASK 0x01FF0000U
+#define RGB_CTRL2_SHIFT 16
+#define RGB_CTRL2_SIGNED 0
+
+/*
+ Register EXP_BRD_CTRL
+*/
+#define TCF_CLK_CTRL_EXP_BRD_CTRL 0x00F8
+#define PDP1_DATA_EN_MASK 0x00000003U
+#define PDP1_DATA_EN_SHIFT 0
+#define PDP1_DATA_EN_SIGNED 0
+
+#define PDP2_DATA_EN_MASK 0x00000030U
+#define PDP2_DATA_EN_SHIFT 4
+#define PDP2_DATA_EN_SIGNED 0
+
+#define EXP_BRD_OUTPUT_MASK 0xFFFFFF00U
+#define EXP_BRD_OUTPUT_SHIFT 8
+#define EXP_BRD_OUTPUT_SIGNED 0
+
+/*
+ Register HOSTIF_CONTROL
+*/
+#define TCF_CLK_CTRL_HOSTIF_CONTROL 0x0100
+#define HOSTIF_CTRL_MASK 0x000000FFU
+#define HOSTIF_CTRL_SHIFT 0
+#define HOSTIF_CTRL_SIGNED 0
+
+/*
+ Register DUT_CONTROL_1
+*/
+#define TCF_CLK_CTRL_DUT_CONTROL_1 0x0108
+#define DUT_CTRL_1_MASK 0xFFFFFFFFU
+#define DUT_CTRL_1_SHIFT 0
+#define DUT_CTRL_1_SIGNED 0
+
+/* TC ES2 additional needs those: */
+#define DUT_CTRL_TEST_MODE_SHIFT 0
+#define DUT_CTRL_TEST_MODE_MASK 0x3
+
+#define DUT_CTRL_VCC_0V9EN (1<<12)
+#define DUT_CTRL_VCC_1V8EN (1<<13)
+#define DUT_CTRL_VCC_IO_INH (1<<14)
+#define DUT_CTRL_VCC_CORE_INH (1<<15)
+
+/*
+ Register DUT_STATUS_1
+*/
+#define TCF_CLK_CTRL_DUT_STATUS_1 0x0110
+#define DUT_STATUS_1_MASK 0xFFFFFFFFU
+#define DUT_STATUS_1_SHIFT 0
+#define DUT_STATUS_1_SIGNED 0
+
+/*
+ Register DUT_CTRL_NOT_STAT_1
+*/
+#define TCF_CLK_CTRL_DUT_CTRL_NOT_STAT_1 0x0118
+#define DUT_STAT_NOT_CTRL_1_MASK 0xFFFFFFFFU
+#define DUT_STAT_NOT_CTRL_1_SHIFT 0
+#define DUT_STAT_NOT_CTRL_1_SIGNED 0
+
+/*
+ Register DUT_CONTROL_2
+*/
+#define TCF_CLK_CTRL_DUT_CONTROL_2 0x0120
+#define DUT_CTRL_2_MASK 0xFFFFFFFFU
+#define DUT_CTRL_2_SHIFT 0
+#define DUT_CTRL_2_SIGNED 0
+
+/*
+ Register DUT_STATUS_2
+*/
+#define TCF_CLK_CTRL_DUT_STATUS_2 0x0128
+#define DUT_STATUS_2_MASK 0xFFFFFFFFU
+#define DUT_STATUS_2_SHIFT 0
+#define DUT_STATUS_2_SIGNED 0
+
+/*
+ Register DUT_CTRL_NOT_STAT_2
+*/
+#define TCF_CLK_CTRL_DUT_CTRL_NOT_STAT_2 0x0130
+#define DUT_CTRL_NOT_STAT_2_MASK 0xFFFFFFFFU
+#define DUT_CTRL_NOT_STAT_2_SHIFT 0
+#define DUT_CTRL_NOT_STAT_2_SIGNED 0
+
+/*
+ Register BUS_CAP_BASE_ADDR
+*/
+#define TCF_CLK_CTRL_BUS_CAP_BASE_ADDR 0x0138
+#define BUS_CAP_BASE_ADDR_MASK 0xFFFFFFFFU
+#define BUS_CAP_BASE_ADDR_SHIFT 0
+#define BUS_CAP_BASE_ADDR_SIGNED 0
+
+/*
+ Register BUS_CAP_ENABLE
+*/
+#define TCF_CLK_CTRL_BUS_CAP_ENABLE 0x0140
+#define BUS_CAP_ENABLE_MASK 0x00000001U
+#define BUS_CAP_ENABLE_SHIFT 0
+#define BUS_CAP_ENABLE_SIGNED 0
+
+/*
+ Register BUS_CAP_COUNT
+*/
+#define TCF_CLK_CTRL_BUS_CAP_COUNT 0x0148
+#define BUS_CAP_COUNT_MASK 0xFFFFFFFFU
+#define BUS_CAP_COUNT_SHIFT 0
+#define BUS_CAP_COUNT_SIGNED 0
+
+/*
+ Register DCM_LOCK_STATUS
+*/
+#define TCF_CLK_CTRL_DCM_LOCK_STATUS 0x0150
+#define DCM_LOCK_STATUS_MASK 0x00000007U
+#define DCM_LOCK_STATUS_SHIFT 0
+#define DCM_LOCK_STATUS_SIGNED 0
+
+/*
+ Register AUX_DUT_RESETNS
+*/
+#define TCF_CLK_CTRL_AUX_DUT_RESETNS 0x0158
+#define AUX_DUT_RESETNS_MASK 0x0000000FU
+#define AUX_DUT_RESETNS_SHIFT 0
+#define AUX_DUT_RESETNS_SIGNED 0
+
+/*
+ Register TCF_SPI_MST_ADDR_RDNWR
+*/
+#define TCF_CLK_CTRL_TCF_SPI_MST_ADDR_RDNWR 0x0160
+#define TCF_SPI_MST_ADDR_MASK 0x00000FFFU
+#define TCF_SPI_MST_ADDR_SHIFT 0
+#define TCF_SPI_MST_ADDR_SIGNED 0
+
+#define TCF_SPI_MST_RDNWR_MASK 0x00001000U
+#define TCF_SPI_MST_RDNWR_SHIFT 12
+#define TCF_SPI_MST_RDNWR_SIGNED 0
+
+#define TCF_SPI_MST_SLAVE_ID_MASK 0x00010000U
+#define TCF_SPI_MST_SLAVE_ID_SHIFT 16
+#define TCF_SPI_MST_SLAVE_ID_SIGNED 0
+
+/*
+ Register TCF_SPI_MST_WDATA
+*/
+#define TCF_CLK_CTRL_TCF_SPI_MST_WDATA 0x0168
+#define TCF_SPI_MST_WDATA_MASK 0xFFFFFFFFU
+#define TCF_SPI_MST_WDATA_SHIFT 0
+#define TCF_SPI_MST_WDATA_SIGNED 0
+
+/*
+ Register TCF_SPI_MST_RDATA
+*/
+#define TCF_CLK_CTRL_TCF_SPI_MST_RDATA 0x0170
+#define TCF_SPI_MST_RDATA_MASK 0xFFFFFFFFU
+#define TCF_SPI_MST_RDATA_SHIFT 0
+#define TCF_SPI_MST_RDATA_SIGNED 0
+
+/*
+ Register TCF_SPI_MST_STATUS
+*/
+#define TCF_CLK_CTRL_TCF_SPI_MST_STATUS 0x0178
+#define TCF_SPI_MST_STATUS_MASK 0x0000000FU
+#define TCF_SPI_MST_STATUS_SHIFT 0
+#define TCF_SPI_MST_STATUS_SIGNED 0
+
+/*
+ Register TCF_SPI_MST_GO
+*/
+#define TCF_CLK_CTRL_TCF_SPI_MST_GO 0x0180
+#define TCF_SPI_MST_GO_MASK 0x00000001U
+#define TCF_SPI_MST_GO_SHIFT 0
+#define TCF_SPI_MST_GO_SIGNED 0
+
+/*
+ Register EXT_SIG_CTRL
+*/
+#define TCF_CLK_CTRL_EXT_SIG_CTRL 0x0188
+#define EXT_SYS_REQ_SIG_START_MASK 0x00000001U
+#define EXT_SYS_REQ_SIG_START_SHIFT 0
+#define EXT_SYS_REQ_SIG_START_SIGNED 0
+
+#define EXT_SYS_RD_SIG_START_MASK 0x00000002U
+#define EXT_SYS_RD_SIG_START_SHIFT 1
+#define EXT_SYS_RD_SIG_START_SIGNED 0
+
+#define EXT_MEM_REQ_SIG_START_MASK 0x00000004U
+#define EXT_MEM_REQ_SIG_START_SHIFT 2
+#define EXT_MEM_REQ_SIG_START_SIGNED 0
+
+#define EXT_MEM_RD_SIG_START_MASK 0x00000008U
+#define EXT_MEM_RD_SIG_START_SHIFT 3
+#define EXT_MEM_RD_SIG_START_SIGNED 0
+
+/*
+ Register EXT_SYS_REQ_SIG
+*/
+#define TCF_CLK_CTRL_EXT_SYS_REQ_SIG 0x0190
+#define EXT_SYS_REQ_SIG_MASK 0xFFFFFFFFU
+#define EXT_SYS_REQ_SIG_SHIFT 0
+#define EXT_SYS_REQ_SIG_SIGNED 0
+
+/*
+ Register EXT_SYS_RD_SIG
+*/
+#define TCF_CLK_CTRL_EXT_SYS_RD_SIG 0x0198
+#define EXT_SYS_RD_SIG_MASK 0xFFFFFFFFU
+#define EXT_SYS_RD_SIG_SHIFT 0
+#define EXT_SYS_RD_SIG_SIGNED 0
+
+/*
+ Register EXT_MEM_REQ_SIG
+*/
+#define TCF_CLK_CTRL_EXT_MEM_REQ_SIG 0x01A0
+#define EXT_MEM_REQ_SIG_MASK 0xFFFFFFFFU
+#define EXT_MEM_REQ_SIG_SHIFT 0
+#define EXT_MEM_REQ_SIG_SIGNED 0
+
+/*
+ Register EXT_MEM_RD_SIG
+*/
+#define TCF_CLK_CTRL_EXT_MEM_RD_SIG 0x01A8
+#define EXT_MEM_RD_SIG_MASK 0xFFFFFFFFU
+#define EXT_MEM_RD_SIG_SHIFT 0
+#define EXT_MEM_RD_SIG_SIGNED 0
+
+/*
+ Register EXT_SYS_REQ_WR_CNT
+*/
+#define TCF_CLK_CTRL_EXT_SYS_REQ_WR_CNT 0x01B0
+#define EXT_SYS_REQ_WR_CNT_MASK 0xFFFFFFFFU
+#define EXT_SYS_REQ_WR_CNT_SHIFT 0
+#define EXT_SYS_REQ_WR_CNT_SIGNED 0
+
+/*
+ Register EXT_SYS_REQ_RD_CNT
+*/
+#define TCF_CLK_CTRL_EXT_SYS_REQ_RD_CNT 0x01B8
+#define EXT_SYS_REQ_RD_CNT_MASK 0xFFFFFFFFU
+#define EXT_SYS_REQ_RD_CNT_SHIFT 0
+#define EXT_SYS_REQ_RD_CNT_SIGNED 0
+
+/*
+ Register EXT_SYS_RD_CNT
+*/
+#define TCF_CLK_CTRL_EXT_SYS_RD_CNT 0x01C0
+#define EXT_SYS_RD_CNT_MASK 0xFFFFFFFFU
+#define EXT_SYS_RD_CNT_SHIFT 0
+#define EXT_SYS_RD_CNT_SIGNED 0
+
+/*
+ Register EXT_MEM_REQ_WR_CNT
+*/
+#define TCF_CLK_CTRL_EXT_MEM_REQ_WR_CNT 0x01C8
+#define EXT_MEM_REQ_WR_CNT_MASK 0xFFFFFFFFU
+#define EXT_MEM_REQ_WR_CNT_SHIFT 0
+#define EXT_MEM_REQ_WR_CNT_SIGNED 0
+
+/*
+ Register EXT_MEM_REQ_RD_CNT
+*/
+#define TCF_CLK_CTRL_EXT_MEM_REQ_RD_CNT 0x01D0
+#define EXT_MEM_REQ_RD_CNT_MASK 0xFFFFFFFFU
+#define EXT_MEM_REQ_RD_CNT_SHIFT 0
+#define EXT_MEM_REQ_RD_CNT_SIGNED 0
+
+/*
+ Register EXT_MEM_RD_CNT
+*/
+#define TCF_CLK_CTRL_EXT_MEM_RD_CNT 0x01D8
+#define EXT_MEM_RD_CNT_MASK 0xFFFFFFFFU
+#define EXT_MEM_RD_CNT_SHIFT 0
+#define EXT_MEM_RD_CNT_SIGNED 0
+
+/*
+ Register TCF_CORE_TARGET_BUILD_CFG
+*/
+#define TCF_CLK_CTRL_TCF_CORE_TARGET_BUILD_CFG 0x01E0
+#define TCF_CORE_TARGET_BUILD_ID_MASK 0x000000FFU
+#define TCF_CORE_TARGET_BUILD_ID_SHIFT 0
+#define TCF_CORE_TARGET_BUILD_ID_SIGNED 0
+
+/*
+ Register MEM_THROUGH_SYS
+*/
+#define TCF_CLK_CTRL_MEM_THROUGH_SYS 0x01E8
+#define MEM_THROUGH_SYS_MASK 0x00000001U
+#define MEM_THROUGH_SYS_SHIFT 0
+#define MEM_THROUGH_SYS_SIGNED 0
+
+/*
+ Register HOST_PHY_OFFSET
+*/
+#define TCF_CLK_CTRL_HOST_PHY_OFFSET 0x01F0
+#define HOST_PHY_OFFSET_MASK 0xFFFFFFFFU
+#define HOST_PHY_OFFSET_SHIFT 0
+#define HOST_PHY_OFFSET_SIGNED 0
+
+#endif /* !defined(_TCF_CLK_CTRL_H_) */
+
+/*****************************************************************************
+ End of file (tcf_clk_ctrl.h)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/include/system/rgx_tc/tcf_pll.h b/drivers/gpu/rogue/include/system/rgx_tc/tcf_pll.h
new file mode 100644
index 000000000000..fa0f823b7be2
--- /dev/null
+++ b/drivers/gpu/rogue/include/system/rgx_tc/tcf_pll.h
@@ -0,0 +1,311 @@
+/*************************************************************************/ /*!
+@Title Test Chip Framework PDP register definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Autogenerated C -- do not edit
+ Generated from tcf_pll.def
+@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(_TCF_PLL_H_)
+#define _TCF_PLL_H_
+
+/*
+ Register PLL_DDR2_CLK0
+*/
+#define TCF_PLL_PLL_DDR2_CLK0 0x0000
+#define DDR2_PLL_CLK0_PHS_MASK 0x00300000U
+#define DDR2_PLL_CLK0_PHS_SHIFT 20
+#define DDR2_PLL_CLK0_PHS_SIGNED 0
+
+#define DDR2_PLL_CLK0_MS_MASK 0x00030000U
+#define DDR2_PLL_CLK0_MS_SHIFT 16
+#define DDR2_PLL_CLK0_MS_SIGNED 0
+
+#define DDR2_PLL_CLK0_FREQ_MASK 0x000001FFU
+#define DDR2_PLL_CLK0_FREQ_SHIFT 0
+#define DDR2_PLL_CLK0_FREQ_SIGNED 0
+
+/*
+ Register PLL_DDR2_CLK1TO5
+*/
+#define TCF_PLL_PLL_DDR2_CLK1TO5 0x0008
+#define DDR2_PLL_CLK1TO5_PHS_MASK 0x3FF00000U
+#define DDR2_PLL_CLK1TO5_PHS_SHIFT 20
+#define DDR2_PLL_CLK1TO5_PHS_SIGNED 0
+
+#define DDR2_PLL_CLK1TO5_MS_MASK 0x000FFC00U
+#define DDR2_PLL_CLK1TO5_MS_SHIFT 10
+#define DDR2_PLL_CLK1TO5_MS_SIGNED 0
+
+#define DDR2_PLL_CLK1TO5_FREQ_MASK 0x000003FFU
+#define DDR2_PLL_CLK1TO5_FREQ_SHIFT 0
+#define DDR2_PLL_CLK1TO5_FREQ_SIGNED 0
+
+/*
+ Register PLL_DDR2_DRP_GO
+*/
+#define TCF_PLL_PLL_DDR2_DRP_GO 0x0010
+#define PLL_DDR2_DRP_GO_MASK 0x00000001U
+#define PLL_DDR2_DRP_GO_SHIFT 0
+#define PLL_DDR2_DRP_GO_SIGNED 0
+
+/*
+ Register PLL_PDP_CLK0
+*/
+#define TCF_PLL_PLL_PDP_CLK0 0x0018
+#define PDP_PLL_CLK0_PHS_MASK 0x00300000U
+#define PDP_PLL_CLK0_PHS_SHIFT 20
+#define PDP_PLL_CLK0_PHS_SIGNED 0
+
+#define PDP_PLL_CLK0_MS_MASK 0x00030000U
+#define PDP_PLL_CLK0_MS_SHIFT 16
+#define PDP_PLL_CLK0_MS_SIGNED 0
+
+#define PDP_PLL_CLK0_FREQ_MASK 0x000001FFU
+#define PDP_PLL_CLK0_FREQ_SHIFT 0
+#define PDP_PLL_CLK0_FREQ_SIGNED 0
+
+/*
+ Register PLL_PDP_CLK1TO5
+*/
+#define TCF_PLL_PLL_PDP_CLK1TO5 0x0020
+#define PDP_PLL_CLK1TO5_PHS_MASK 0x3FF00000U
+#define PDP_PLL_CLK1TO5_PHS_SHIFT 20
+#define PDP_PLL_CLK1TO5_PHS_SIGNED 0
+
+#define PDP_PLL_CLK1TO5_MS_MASK 0x000FFC00U
+#define PDP_PLL_CLK1TO5_MS_SHIFT 10
+#define PDP_PLL_CLK1TO5_MS_SIGNED 0
+
+#define PDP_PLL_CLK1TO5_FREQ_MASK 0x000003FFU
+#define PDP_PLL_CLK1TO5_FREQ_SHIFT 0
+#define PDP_PLL_CLK1TO5_FREQ_SIGNED 0
+
+/*
+ Register PLL_PDP_DRP_GO
+*/
+#define TCF_PLL_PLL_PDP_DRP_GO 0x0028
+#define PLL_PDP_DRP_GO_MASK 0x00000001U
+#define PLL_PDP_DRP_GO_SHIFT 0
+#define PLL_PDP_DRP_GO_SIGNED 0
+
+/*
+ Register PLL_PDP2_CLK0
+*/
+#define TCF_PLL_PLL_PDP2_CLK0 0x0030
+#define PDP2_PLL_CLK0_PHS_MASK 0x00300000U
+#define PDP2_PLL_CLK0_PHS_SHIFT 20
+#define PDP2_PLL_CLK0_PHS_SIGNED 0
+
+#define PDP2_PLL_CLK0_MS_MASK 0x00030000U
+#define PDP2_PLL_CLK0_MS_SHIFT 16
+#define PDP2_PLL_CLK0_MS_SIGNED 0
+
+#define PDP2_PLL_CLK0_FREQ_MASK 0x000001FFU
+#define PDP2_PLL_CLK0_FREQ_SHIFT 0
+#define PDP2_PLL_CLK0_FREQ_SIGNED 0
+
+/*
+ Register PLL_PDP2_CLK1TO5
+*/
+#define TCF_PLL_PLL_PDP2_CLK1TO5 0x0038
+#define PDP2_PLL_CLK1TO5_PHS_MASK 0x3FF00000U
+#define PDP2_PLL_CLK1TO5_PHS_SHIFT 20
+#define PDP2_PLL_CLK1TO5_PHS_SIGNED 0
+
+#define PDP2_PLL_CLK1TO5_MS_MASK 0x000FFC00U
+#define PDP2_PLL_CLK1TO5_MS_SHIFT 10
+#define PDP2_PLL_CLK1TO5_MS_SIGNED 0
+
+#define PDP2_PLL_CLK1TO5_FREQ_MASK 0x000003FFU
+#define PDP2_PLL_CLK1TO5_FREQ_SHIFT 0
+#define PDP2_PLL_CLK1TO5_FREQ_SIGNED 0
+
+/*
+ Register PLL_PDP2_DRP_GO
+*/
+#define TCF_PLL_PLL_PDP2_DRP_GO 0x0040
+#define PLL_PDP2_DRP_GO_MASK 0x00000001U
+#define PLL_PDP2_DRP_GO_SHIFT 0
+#define PLL_PDP2_DRP_GO_SIGNED 0
+
+/*
+ Register PLL_CORE_CLK0
+*/
+#define TCF_PLL_PLL_CORE_CLK0 0x0048
+#define CORE_PLL_CLK0_PHS_MASK 0x00300000U
+#define CORE_PLL_CLK0_PHS_SHIFT 20
+#define CORE_PLL_CLK0_PHS_SIGNED 0
+
+#define CORE_PLL_CLK0_MS_MASK 0x00030000U
+#define CORE_PLL_CLK0_MS_SHIFT 16
+#define CORE_PLL_CLK0_MS_SIGNED 0
+
+#define CORE_PLL_CLK0_FREQ_MASK 0x000001FFU
+#define CORE_PLL_CLK0_FREQ_SHIFT 0
+#define CORE_PLL_CLK0_FREQ_SIGNED 0
+
+/*
+ Register PLL_CORE_CLK1TO5
+*/
+#define TCF_PLL_PLL_CORE_CLK1TO5 0x0050
+#define CORE_PLL_CLK1TO5_PHS_MASK 0x3FF00000U
+#define CORE_PLL_CLK1TO5_PHS_SHIFT 20
+#define CORE_PLL_CLK1TO5_PHS_SIGNED 0
+
+#define CORE_PLL_CLK1TO5_MS_MASK 0x000FFC00U
+#define CORE_PLL_CLK1TO5_MS_SHIFT 10
+#define CORE_PLL_CLK1TO5_MS_SIGNED 0
+
+#define CORE_PLL_CLK1TO5_FREQ_MASK 0x000003FFU
+#define CORE_PLL_CLK1TO5_FREQ_SHIFT 0
+#define CORE_PLL_CLK1TO5_FREQ_SIGNED 0
+
+/*
+ Register PLL_CORE_DRP_GO
+*/
+#define TCF_PLL_PLL_CORE_DRP_GO 0x0058
+#define PLL_CORE_DRP_GO_MASK 0x00000001U
+#define PLL_CORE_DRP_GO_SHIFT 0
+#define PLL_CORE_DRP_GO_SIGNED 0
+
+/*
+ Register PLL_SYSIF_CLK0
+*/
+#define TCF_PLL_PLL_SYSIF_CLK0 0x0060
+#define SYSIF_PLL_CLK0_PHS_MASK 0x00300000U
+#define SYSIF_PLL_CLK0_PHS_SHIFT 20
+#define SYSIF_PLL_CLK0_PHS_SIGNED 0
+
+#define SYSIF_PLL_CLK0_MS_MASK 0x00030000U
+#define SYSIF_PLL_CLK0_MS_SHIFT 16
+#define SYSIF_PLL_CLK0_MS_SIGNED 0
+
+#define SYSIF_PLL_CLK0_FREQ_MASK 0x000001FFU
+#define SYSIF_PLL_CLK0_FREQ_SHIFT 0
+#define SYSIF_PLL_CLK0_FREQ_SIGNED 0
+
+/*
+ Register PLL_SYSIF_CLK1TO5
+*/
+#define TCF_PLL_PLL_SYSIF_CLK1TO5 0x0068
+#define SYSIF_PLL_CLK1TO5_PHS_MASK 0x3FF00000U
+#define SYSIF_PLL_CLK1TO5_PHS_SHIFT 20
+#define SYSIF_PLL_CLK1TO5_PHS_SIGNED 0
+
+#define SYSIF_PLL_CLK1TO5_MS_MASK 0x000FFC00U
+#define SYSIF_PLL_CLK1TO5_MS_SHIFT 10
+#define SYSIF_PLL_CLK1TO5_MS_SIGNED 0
+
+#define SYSIF_PLL_CLK1TO5_FREQ_MASK 0x000003FFU
+#define SYSIF_PLL_CLK1TO5_FREQ_SHIFT 0
+#define SYSIF_PLL_CLK1TO5_FREQ_SIGNED 0
+
+/*
+ Register PLL_SYS_DRP_GO
+*/
+#define TCF_PLL_PLL_SYS_DRP_GO 0x0070
+#define PLL_SYS_DRP_GO_MASK 0x00000001U
+#define PLL_SYS_DRP_GO_SHIFT 0
+#define PLL_SYS_DRP_GO_SIGNED 0
+
+/*
+ Register PLL_MEMIF_CLK0
+*/
+#define TCF_PLL_PLL_MEMIF_CLK0 0x0078
+#define MEMIF_PLL_CLK0_PHS_MASK 0x00300000U
+#define MEMIF_PLL_CLK0_PHS_SHIFT 20
+#define MEMIF_PLL_CLK0_PHS_SIGNED 0
+
+#define MEMIF_PLL_CLK0_MS_MASK 0x00030000U
+#define MEMIF_PLL_CLK0_MS_SHIFT 16
+#define MEMIF_PLL_CLK0_MS_SIGNED 0
+
+#define MEMIF_PLL_CLK0_FREQ_MASK 0x000001FFU
+#define MEMIF_PLL_CLK0_FREQ_SHIFT 0
+#define MEMIF_PLL_CLK0_FREQ_SIGNED 0
+
+/*
+ Register PLL_MEMIF_CLK1TO5
+*/
+#define TCF_PLL_PLL_MEMIF_CLK1TO5 0x0080
+#define MEMIF_PLL_CLK1TO5_PHS_MASK 0x3FF00000U
+#define MEMIF_PLL_CLK1TO5_PHS_SHIFT 20
+#define MEMIF_PLL_CLK1TO5_PHS_SIGNED 0
+
+#define MEMIF_PLL_CLK1TO5_MS_MASK 0x000FFC00U
+#define MEMIF_PLL_CLK1TO5_MS_SHIFT 10
+#define MEMIF_PLL_CLK1TO5_MS_SIGNED 0
+
+#define MEMIF_PLL_CLK1TO5_FREQ_MASK 0x000003FFU
+#define MEMIF_PLL_CLK1TO5_FREQ_SHIFT 0
+#define MEMIF_PLL_CLK1TO5_FREQ_SIGNED 0
+
+/*
+ Register PLL_MEM_DRP_GO
+*/
+#define TCF_PLL_PLL_MEM_DRP_GO 0x0088
+#define PLL_MEM_DRP_GO_MASK 0x00000001U
+#define PLL_MEM_DRP_GO_SHIFT 0
+#define PLL_MEM_DRP_GO_SIGNED 0
+
+/*
+ Register PLL_ALL_DRP_GO
+*/
+#define TCF_PLL_PLL_ALL_DRP_GO 0x0090
+#define PLL_ALL_DRP_GO_MASK 0x00000001U
+#define PLL_ALL_DRP_GO_SHIFT 0
+#define PLL_ALL_DRP_GO_SIGNED 0
+
+/*
+ Register PLL_DRP_STATUS
+*/
+#define TCF_PLL_PLL_DRP_STATUS 0x0098
+#define PLL_LOCKS_MASK 0x00003F00U
+#define PLL_LOCKS_SHIFT 8
+#define PLL_LOCKS_SIGNED 0
+
+#define PLL_DRP_GOOD_MASK 0x0000003FU
+#define PLL_DRP_GOOD_SHIFT 0
+#define PLL_DRP_GOOD_SIGNED 0
+
+#endif /* !defined(_TCF_PLL_H_) */
+
+/*****************************************************************************
+ End of file (tcf_pll.h)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/include/system/rgx_tc/tcf_rgbpdp_regs.h b/drivers/gpu/rogue/include/system/rgx_tc/tcf_rgbpdp_regs.h
new file mode 100644
index 000000000000..f3e6d54613d1
--- /dev/null
+++ b/drivers/gpu/rogue/include/system/rgx_tc/tcf_rgbpdp_regs.h
@@ -0,0 +1,559 @@
+/*************************************************************************/ /*!
+@Title Test Chip Framework PDP register definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Autogenerated C -- do not edit
+ Generated from: tcf_rgbpdp_regs.def
+@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(_TCF_RGBPDP_REGS_H_)
+#define _TCF_RGBPDP_REGS_H_
+
+/*
+ Register PVR_TCF_RGBPDP_STR1SURF
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_STR1SURF 0x0000
+#define STR1HEIGHT_MASK 0x000007FFU
+#define STR1HEIGHT_SHIFT 0
+#define STR1HEIGHT_SIGNED 0
+
+#define STR1WIDTH_MASK 0x003FF800U
+#define STR1WIDTH_SHIFT 11
+#define STR1WIDTH_SIGNED 0
+
+#define STR1PIXFMT_MASK 0x0F000000U
+#define STR1PIXFMT_SHIFT 24
+#define STR1PIXFMT_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_STR1ADDRCTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_STR1ADDRCTRL 0x0004
+#define STR1BASE_MASK 0x03FFFFFFU
+#define STR1BASE_SHIFT 0
+#define STR1BASE_SIGNED 0
+
+#define STR1INTFIELD_MASK 0x40000000U
+#define STR1INTFIELD_SHIFT 30
+#define STR1INTFIELD_SIGNED 0
+
+#define STR1STREN_MASK 0x80000000U
+#define STR1STREN_SHIFT 31
+#define STR1STREN_SIGNED 0
+
+/*
+ Register PVR_PDP_STR1POSN
+*/
+#define TCF_RGBPDP_PVR_PDP_STR1POSN 0x0008
+#define STR1STRIDE_MASK 0x000003FFU
+#define STR1STRIDE_SHIFT 0
+#define STR1STRIDE_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_MEMCTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_MEMCTRL 0x000C
+#define MEMREFRESH_MASK 0xC0000000U
+#define MEMREFRESH_SHIFT 30
+#define MEMREFRESH_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_STRCTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_STRCTRL 0x0010
+#define BURSTLEN_GFX_MASK 0x000000FFU
+#define BURSTLEN_GFX_SHIFT 0
+#define BURSTLEN_GFX_SIGNED 0
+
+#define THRESHOLD_GFX_MASK 0x0000FF00U
+#define THRESHOLD_GFX_SHIFT 8
+#define THRESHOLD_GFX_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_SYNCCTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_SYNCCTRL 0x0014
+#define HSDIS_MASK 0x00000001U
+#define HSDIS_SHIFT 0
+#define HSDIS_SIGNED 0
+
+#define HSPOL_MASK 0x00000002U
+#define HSPOL_SHIFT 1
+#define HSPOL_SIGNED 0
+
+#define VSDIS_MASK 0x00000004U
+#define VSDIS_SHIFT 2
+#define VSDIS_SIGNED 0
+
+#define VSPOL_MASK 0x00000008U
+#define VSPOL_SHIFT 3
+#define VSPOL_SIGNED 0
+
+#define BLNKDIS_MASK 0x00000010U
+#define BLNKDIS_SHIFT 4
+#define BLNKDIS_SIGNED 0
+
+#define BLNKPOL_MASK 0x00000020U
+#define BLNKPOL_SHIFT 5
+#define BLNKPOL_SIGNED 0
+
+#define HS_SLAVE_MASK 0x00000040U
+#define HS_SLAVE_SHIFT 6
+#define HS_SLAVE_SIGNED 0
+
+#define VS_SLAVE_MASK 0x00000080U
+#define VS_SLAVE_SHIFT 7
+#define VS_SLAVE_SIGNED 0
+
+#define INTERLACE_MASK 0x00000100U
+#define INTERLACE_SHIFT 8
+#define INTERLACE_SIGNED 0
+
+#define FIELDPOL_MASK 0x00000200U
+#define FIELDPOL_SHIFT 9
+#define FIELDPOL_SIGNED 0
+
+#define CLKPOL_MASK 0x00000800U
+#define CLKPOL_SHIFT 11
+#define CLKPOL_SIGNED 0
+
+#define CSYNC_EN_MASK 0x00001000U
+#define CSYNC_EN_SHIFT 12
+#define CSYNC_EN_SIGNED 0
+
+#define FIELD_EN_MASK 0x00002000U
+#define FIELD_EN_SHIFT 13
+#define FIELD_EN_SIGNED 0
+
+#define UPDWAIT_MASK 0x000F0000U
+#define UPDWAIT_SHIFT 16
+#define UPDWAIT_SIGNED 0
+
+#define UPDCTRL_MASK 0x01000000U
+#define UPDCTRL_SHIFT 24
+#define UPDCTRL_SIGNED 0
+
+#define UPDINTCTRL_MASK 0x02000000U
+#define UPDINTCTRL_SHIFT 25
+#define UPDINTCTRL_SIGNED 0
+
+#define UPDSYNCTRL_MASK 0x04000000U
+#define UPDSYNCTRL_SHIFT 26
+#define UPDSYNCTRL_SIGNED 0
+
+#define POWERDN_MASK 0x10000000U
+#define POWERDN_SHIFT 28
+#define POWERDN_SIGNED 0
+
+#define DISP_RST_MASK 0x20000000U
+#define DISP_RST_SHIFT 29
+#define DISP_RST_SIGNED 0
+
+#define SYNCACTIVE_MASK 0x80000000U
+#define SYNCACTIVE_SHIFT 31
+#define SYNCACTIVE_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_BORDCOL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_BORDCOL 0x0018
+#define BORDCOL_MASK 0x00FFFFFFU
+#define BORDCOL_SHIFT 0
+#define BORDCOL_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_UPDCTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_UPDCTRL 0x001C
+#define UPDFIELD_MASK 0x00000001U
+#define UPDFIELD_SHIFT 0
+#define UPDFIELD_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_HSYNC1
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_HSYNC1 0x0020
+#define HT_MASK 0x00000FFFU
+#define HT_SHIFT 0
+#define HT_SIGNED 0
+
+#define HBPS_MASK 0x0FFF0000U
+#define HBPS_SHIFT 16
+#define HBPS_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_HSYNC2
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_HSYNC2 0x0024
+#define HLBS_MASK 0x00000FFFU
+#define HLBS_SHIFT 0
+#define HLBS_SIGNED 0
+
+#define HAS_MASK 0x0FFF0000U
+#define HAS_SHIFT 16
+#define HAS_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_HSYNC3
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_HSYNC3 0x0028
+#define HRBS_MASK 0x00000FFFU
+#define HRBS_SHIFT 0
+#define HRBS_SIGNED 0
+
+#define HFPS_MASK 0x0FFF0000U
+#define HFPS_SHIFT 16
+#define HFPS_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_VSYNC1
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_VSYNC1 0x002C
+#define VT_MASK 0x00000FFFU
+#define VT_SHIFT 0
+#define VT_SIGNED 0
+
+#define VBPS_MASK 0x0FFF0000U
+#define VBPS_SHIFT 16
+#define VBPS_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_VSYNC2
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_VSYNC2 0x0030
+#define VTBS_MASK 0x00000FFFU
+#define VTBS_SHIFT 0
+#define VTBS_SIGNED 0
+
+#define VAS_MASK 0x0FFF0000U
+#define VAS_SHIFT 16
+#define VAS_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_VSYNC3
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_VSYNC3 0x0034
+#define VBBS_MASK 0x00000FFFU
+#define VBBS_SHIFT 0
+#define VBBS_SIGNED 0
+
+#define VFPS_MASK 0x0FFF0000U
+#define VFPS_SHIFT 16
+#define VFPS_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_HDECTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_HDECTRL 0x0038
+#define HDEF_MASK 0x00000FFFU
+#define HDEF_SHIFT 0
+#define HDEF_SIGNED 0
+
+#define HDES_MASK 0x0FFF0000U
+#define HDES_SHIFT 16
+#define HDES_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_VDECTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_VDECTRL 0x003C
+#define VDEF_MASK 0x00000FFFU
+#define VDEF_SHIFT 0
+#define VDEF_SIGNED 0
+
+#define VDES_MASK 0x0FFF0000U
+#define VDES_SHIFT 16
+#define VDES_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_VEVENT
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_VEVENT 0x0040
+#define VFETCH_MASK 0x00000FFFU
+#define VFETCH_SHIFT 0
+#define VFETCH_SIGNED 0
+
+#define VEVENT_MASK 0x0FFF0000U
+#define VEVENT_SHIFT 16
+#define VEVENT_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_OPMASK
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_OPMASK 0x0044
+#define MASKR_MASK 0x000000FFU
+#define MASKR_SHIFT 0
+#define MASKR_SIGNED 0
+
+#define MASKG_MASK 0x0000FF00U
+#define MASKG_SHIFT 8
+#define MASKG_SIGNED 0
+
+#define MASKB_MASK 0x00FF0000U
+#define MASKB_SHIFT 16
+#define MASKB_SIGNED 0
+
+#define BLANKLEVEL_MASK 0x40000000U
+#define BLANKLEVEL_SHIFT 30
+#define BLANKLEVEL_SIGNED 0
+
+#define MASKLEVEL_MASK 0x80000000U
+#define MASKLEVEL_SHIFT 31
+#define MASKLEVEL_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_INTSTAT
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_INTSTAT 0x0048
+#define INTS_HBLNK0_MASK 0x00000001U
+#define INTS_HBLNK0_SHIFT 0
+#define INTS_HBLNK0_SIGNED 0
+
+#define INTS_HBLNK1_MASK 0x00000002U
+#define INTS_HBLNK1_SHIFT 1
+#define INTS_HBLNK1_SIGNED 0
+
+#define INTS_VBLNK0_MASK 0x00000004U
+#define INTS_VBLNK0_SHIFT 2
+#define INTS_VBLNK0_SIGNED 0
+
+#define INTS_VBLNK1_MASK 0x00000008U
+#define INTS_VBLNK1_SHIFT 3
+#define INTS_VBLNK1_SIGNED 0
+
+#define INTS_STR1URUN_MASK 0x00000010U
+#define INTS_STR1URUN_SHIFT 4
+#define INTS_STR1URUN_SIGNED 0
+
+#define INTS_STR1ORUN_MASK 0x00000020U
+#define INTS_STR1ORUN_SHIFT 5
+#define INTS_STR1ORUN_SIGNED 0
+
+#define INTS_DISPURUN_MASK 0x00000040U
+#define INTS_DISPURUN_SHIFT 6
+#define INTS_DISPURUN_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_INTENAB
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB 0x004C
+#define INTEN_HBLNK0_MASK 0x00000001U
+#define INTEN_HBLNK0_SHIFT 0
+#define INTEN_HBLNK0_SIGNED 0
+
+#define INTEN_HBLNK1_MASK 0x00000002U
+#define INTEN_HBLNK1_SHIFT 1
+#define INTEN_HBLNK1_SIGNED 0
+
+#define INTEN_VBLNK0_MASK 0x00000004U
+#define INTEN_VBLNK0_SHIFT 2
+#define INTEN_VBLNK0_SIGNED 0
+
+#define INTEN_VBLNK1_MASK 0x00000008U
+#define INTEN_VBLNK1_SHIFT 3
+#define INTEN_VBLNK1_SIGNED 0
+
+#define INTEN_STR1URUN_MASK 0x00000010U
+#define INTEN_STR1URUN_SHIFT 4
+#define INTEN_STR1URUN_SIGNED 0
+
+#define INTEN_STR1ORUN_MASK 0x00000020U
+#define INTEN_STR1ORUN_SHIFT 5
+#define INTEN_STR1ORUN_SIGNED 0
+
+#define INTEN_DISPURUN_MASK 0x00000040U
+#define INTEN_DISPURUN_SHIFT 6
+#define INTEN_DISPURUN_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_INTCLEAR
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_INTCLEAR 0x0050
+#define INTCLR_HBLNK0_MASK 0x00000001U
+#define INTCLR_HBLNK0_SHIFT 0
+#define INTCLR_HBLNK0_SIGNED 0
+
+#define INTCLR_HBLNK1_MASK 0x00000002U
+#define INTCLR_HBLNK1_SHIFT 1
+#define INTCLR_HBLNK1_SIGNED 0
+
+#define INTCLR_VBLNK0_MASK 0x00000004U
+#define INTCLR_VBLNK0_SHIFT 2
+#define INTCLR_VBLNK0_SIGNED 0
+
+#define INTCLR_VBLNK1_MASK 0x00000008U
+#define INTCLR_VBLNK1_SHIFT 3
+#define INTCLR_VBLNK1_SIGNED 0
+
+#define INTCLR_STR1URUN_MASK 0x00000010U
+#define INTCLR_STR1URUN_SHIFT 4
+#define INTCLR_STR1URUN_SIGNED 0
+
+#define INTCLR_STR1ORUN_MASK 0x00000020U
+#define INTCLR_STR1ORUN_SHIFT 5
+#define INTCLR_STR1ORUN_SIGNED 0
+
+#define INTCLR_DISPURUN_MASK 0x00000040U
+#define INTCLR_DISPURUN_SHIFT 6
+#define INTCLR_DISPURUN_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_INTCTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_INTCTRL 0x0054
+#define HBLNK_LINENO_MASK 0x00000FFFU
+#define HBLNK_LINENO_SHIFT 0
+#define HBLNK_LINENO_SIGNED 0
+
+#define HBLNK_LINE_MASK 0x00010000U
+#define HBLNK_LINE_SHIFT 16
+#define HBLNK_LINE_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_SIGNAT
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_SIGNAT 0x0058
+#define SIGNATURE_MASK 0xFFFFFFFFU
+#define SIGNATURE_SHIFT 0
+#define SIGNATURE_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_LINESTAT
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_LINESTAT 0x005C
+#define LINENO_MASK 0x00000FFFU
+#define LINENO_SHIFT 0
+#define LINENO_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_DBGCTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_DBGCTRL 0x0060
+#define DBG_ENAB_MASK 0x00000001U
+#define DBG_ENAB_SHIFT 0
+#define DBG_ENAB_SIGNED 0
+
+#define DBG_READ_MASK 0x00000002U
+#define DBG_READ_SHIFT 1
+#define DBG_READ_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_DBGDATA
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_DBGDATA 0x0064
+#define DBG_DATA_MASK 0x00FFFFFFU
+#define DBG_DATA_SHIFT 0
+#define DBG_DATA_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_DBGSIDE
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_DBGSIDE 0x0068
+#define DBG_SIDE_MASK 0x00000007U
+#define DBG_SIDE_SHIFT 0
+#define DBG_SIDE_SIGNED 0
+
+#define DBG_VAL_MASK 0x00000008U
+#define DBG_VAL_SHIFT 3
+#define DBG_VAL_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_REGLD_STAT
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_REGLD_STAT 0x0070
+#define REGLD_ADDROUT_MASK 0x00FFFFFFU
+#define REGLD_ADDROUT_SHIFT 0
+#define REGLD_ADDROUT_SIGNED 0
+
+#define REGLD_ADDREN_MASK 0x80000000U
+#define REGLD_ADDREN_SHIFT 31
+#define REGLD_ADDREN_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_REGLD_CTRL
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_REGLD_CTRL 0x0074
+#define REGLD_ADDRIN_MASK 0x00FFFFFFU
+#define REGLD_ADDRIN_SHIFT 0
+#define REGLD_ADDRIN_SIGNED 0
+
+#define REGLD_VAL_MASK 0x01000000U
+#define REGLD_VAL_SHIFT 24
+#define REGLD_VAL_SIGNED 0
+
+#define REGLD_ADDRLEN_MASK 0xFE000000U
+#define REGLD_ADDRLEN_SHIFT 25
+#define REGLD_ADDRLEN_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_CORE_ID
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_CORE_ID 0x0078
+#define CONFIG_ID_MASK 0x0000FFFFU
+#define CONFIG_ID_SHIFT 0
+#define CONFIG_ID_SIGNED 0
+
+#define CORE_ID_MASK 0x00FF0000U
+#define CORE_ID_SHIFT 16
+#define CORE_ID_SIGNED 0
+
+#define GROUP_ID_MASK 0xFF000000U
+#define GROUP_ID_SHIFT 24
+#define GROUP_ID_SIGNED 0
+
+/*
+ Register PVR_TCF_RGBPDP_CORE_REV
+*/
+#define TCF_RGBPDP_PVR_TCF_RGBPDP_CORE_REV 0x007C
+#define MAINT_REV_MASK 0x000000FFU
+#define MAINT_REV_SHIFT 0
+#define MAINT_REV_SIGNED 0
+
+#define MINOR_REV_MASK 0x0000FF00U
+#define MINOR_REV_SHIFT 8
+#define MINOR_REV_SIGNED 0
+
+#define MAJOR_REV_MASK 0x00FF0000U
+#define MAJOR_REV_SHIFT 16
+#define MAJOR_REV_SIGNED 0
+
+#endif /* !defined(_TCF_RGBPDP_REGS_H_) */
+
+/*****************************************************************************
+ End of file (tcf_rgbpdp_regs.h)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/Kbuild.mk b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/Kbuild.mk
new file mode 100644
index 000000000000..45bf201fdb85
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/Kbuild.mk
@@ -0,0 +1,66 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+ccflags-y := \
+ -I$(TOP)/kernel/drivers/staging/imgtec \
+ -I$(TOP)/include/system/rgx_tc \
+ $(ccflags-y)
+
+# Avoid picking up the services version of 'sync.h'
+CFLAGS_adf_common.o := -Idrivers/staging/android
+CFLAGS_adf_fbdev.o := -Idrivers/staging/android
+CFLAGS_adf_pdp.o := -Idrivers/staging/android
+CFLAGS_adf_sunxi.o := -Idrivers/staging/android
+
+adf_fbdev-y += \
+ kernel/drivers/staging/imgtec/adf_fbdev.o \
+ kernel/drivers/staging/imgtec/adf_common.o
+
+adf_pdp-y += \
+ kernel/drivers/staging/imgtec/adf_pdp.o \
+ kernel/drivers/staging/imgtec/adf_common.o
+
+apollo-y += \
+ kernel/drivers/staging/imgtec/apollo.o \
+ kernel/drivers/staging/imgtec/ion_lma_heap.o
+
+adf_sunxi-y += \
+ kernel/drivers/staging/imgtec/adf_sunxi.o \
+ kernel/drivers/staging/imgtec/adf_common.o
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/Linux.mk b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/Linux.mk
new file mode 100644
index 000000000000..d83499d976af
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/Linux.mk
@@ -0,0 +1,57 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+modules := adf_fbdev adf_pdp apollo adf_sunxi
+
+adf_fbdev_type := kernel_module
+adf_fbdev_target := adf_fbdev.ko
+adf_fbdev_makefile := $(THIS_DIR)/Kbuild.mk
+
+adf_pdp_type := kernel_module
+adf_pdp_target := adf_pdp.ko
+adf_pdp_makefile := $(THIS_DIR)/Kbuild.mk
+
+apollo_type := kernel_module
+apollo_target := apollo.ko
+apollo_makefile := $(THIS_DIR)/Kbuild.mk
+
+adf_sunxi_type := kernel_module
+adf_sunxi_target := adf_sunxi.ko
+adf_sunxi_makefile := $(THIS_DIR)/Kbuild.mk
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_common.c b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_common.c
new file mode 100644
index 000000000000..5ca8872f4c65
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_common.c
@@ -0,0 +1,480 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+#include "adf_common.h"
+
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/dma-buf.h>
+
+#include <video/adf_client.h>
+
+#ifdef DEBUG_VALIDATE
+#define val_dbg(dev, fmt, x...) dev_dbg(dev, fmt, x)
+#else
+#define val_dbg(dev, fmt, x...) do { } while (0)
+#endif
+
+long adf_img_ioctl_validate(struct adf_device *dev,
+ struct adf_validate_config_ext __user *arg)
+{
+ struct adf_interface **intfs = NULL;
+ struct adf_buffer *bufs = NULL;
+ struct adf_post post_cfg;
+ u32 post_ext_size;
+ void *driver_state;
+ int err = 0;
+ size_t i, j;
+
+ if (!access_ok(VERIFY_READ, arg,
+ sizeof(struct adf_validate_config_ext))) {
+ err = -EFAULT;
+ goto err_out;
+ }
+
+ if (arg->n_interfaces > ADF_MAX_INTERFACES) {
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ if (arg->n_bufs > ADF_MAX_BUFFERS) {
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ post_ext_size = sizeof(struct adf_post_ext) +
+ arg->n_bufs * sizeof(struct adf_buffer_config_ext);
+
+ if (!access_ok(VERIFY_READ, arg->bufs,
+ sizeof(struct adf_buffer_config) * arg->n_bufs)) {
+ err = -EFAULT;
+ goto err_out;
+ }
+
+ if (!access_ok(VERIFY_READ, arg->post_ext,
+ post_ext_size)) {
+ err = -EFAULT;
+ goto err_out;
+ }
+
+ if (arg->n_interfaces) {
+ intfs = kmalloc(sizeof(intfs[0]) * arg->n_interfaces,
+ GFP_KERNEL);
+ if (!intfs) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ }
+
+ for (i = 0; i < arg->n_interfaces; i++) {
+ intfs[i] = idr_find(&dev->interfaces, arg->interfaces[i]);
+ if (!intfs[i]) {
+ err = -EINVAL;
+ goto err_out;
+ }
+ }
+
+ if (arg->n_bufs) {
+ bufs = kzalloc(sizeof(bufs[0]) * arg->n_bufs, GFP_KERNEL);
+ if (!bufs) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ }
+
+ for (i = 0; i < arg->n_bufs; i++) {
+ struct adf_buffer_config *config = &arg->bufs[i];
+
+ memset(&bufs[i], 0, sizeof(bufs[i]));
+
+ if (config->n_planes > ADF_MAX_PLANES) {
+ err = -EINVAL;
+ goto err_import;
+ }
+
+ bufs[i].overlay_engine = idr_find(&dev->overlay_engines,
+ config->overlay_engine);
+ if (!bufs[i].overlay_engine) {
+ err = -ENOENT;
+ goto err_import;
+ }
+
+ bufs[i].w = config->w;
+ bufs[i].h = config->h;
+ bufs[i].format = config->format;
+
+ for (j = 0; j < config->n_planes; j++) {
+ bufs[i].dma_bufs[j] = dma_buf_get(config->fd[j]);
+ if (IS_ERR_OR_NULL(bufs[i].dma_bufs[j])) {
+ err = PTR_ERR(bufs[i].dma_bufs[j]);
+ bufs[i].dma_bufs[j] = NULL;
+ goto err_import;
+ }
+ bufs[i].offset[j] = config->offset[j];
+ bufs[i].pitch[j] = config->pitch[j];
+ }
+ bufs[i].n_planes = config->n_planes;
+
+ bufs[i].acquire_fence = NULL;
+ }
+
+ /* Fake up a post configuration to validate */
+ post_cfg.custom_data_size = post_ext_size;
+ post_cfg.custom_data = arg->post_ext;
+ post_cfg.n_bufs = arg->n_bufs;
+ post_cfg.bufs = bufs;
+
+ /* Mapping dma bufs is too expensive for validate, and we don't
+ * need to do it at the moment.
+ */
+ post_cfg.mappings = NULL;
+
+ err = dev->ops->validate(dev, &post_cfg, &driver_state);
+ if (err)
+ goto err_import;
+
+ /* For the validate ioctl, we don't need the driver state. If it
+ * was allocated, free it immediately.
+ */
+ if (dev->ops->state_free)
+ dev->ops->state_free(dev, driver_state);
+
+err_import:
+ for (i = 0; i < arg->n_bufs; i++)
+ for (j = 0; j < ARRAY_SIZE(bufs[i].dma_bufs); j++)
+ if (bufs[i].dma_bufs[j])
+ dma_buf_put(bufs[i].dma_bufs[j]);
+err_out:
+ kfree(intfs);
+ kfree(bufs);
+ return err;
+}
+
+long adf_img_ioctl(struct adf_obj *obj, unsigned int cmd, unsigned long arg)
+{
+ struct adf_device *dev =
+ (struct adf_device *)obj->parent;
+
+ switch (cmd) {
+ case ADF_VALIDATE_CONFIG_EXT:
+ return adf_img_ioctl_validate(dev,
+ (struct adf_validate_config_ext __user *)arg);
+ }
+
+ return -ENOTTY;
+}
+
+/* Callers of this function should have taken the dev->client_lock */
+
+static struct adf_interface *
+get_interface_attached_to_overlay(struct adf_device *dev,
+ struct adf_overlay_engine *overlay)
+{
+ struct adf_interface *interface = NULL;
+ struct adf_attachment_list *entry;
+
+ /* We are open-coding adf_attachment_list_to_array. We can't use the
+ * adf_device_attachments helper because it takes the client lock,
+ * which is already held for calls to validate.
+ */
+ list_for_each_entry(entry, &dev->attached, head) {
+ /* If there are multiple interfaces attached to an overlay,
+ * this will return the last.
+ */
+ if (entry->attachment.overlay_engine == overlay)
+ interface = entry->attachment.interface;
+ }
+
+ return interface;
+}
+
+int adf_img_validate_simple(struct adf_device *dev, struct adf_post *cfg,
+ void **driver_state)
+{
+ struct adf_post_ext *post_ext = cfg->custom_data;
+ struct adf_overlay_engine *overlay;
+ struct adf_interface *interface;
+ struct adf_buffer *buffer;
+ int i = 0;
+ struct device *device = dev->dev;
+ size_t expected_custom_data_size;
+
+ /* "Null" flip handling */
+ if (cfg->n_bufs == 0)
+ return 0;
+
+ expected_custom_data_size = sizeof(struct adf_post_ext)
+ + cfg->n_bufs * sizeof(struct adf_buffer_config_ext);
+ if (cfg->custom_data_size != expected_custom_data_size) {
+ val_dbg(device, "Custom data size %zu not expected size %zu",
+ cfg->custom_data_size,
+ sizeof(struct adf_buffer_config_ext));
+ return -EINVAL;
+ }
+
+ if (cfg->n_bufs != 1) {
+ val_dbg(device, "Got %zu buffers in post. Should be 1.\n",
+ cfg->n_bufs);
+ return -EINVAL;
+ }
+
+ buffer = &cfg->bufs[0];
+ overlay = buffer->overlay_engine;
+ if (!overlay) {
+ dev_err(device, "Buffer without an overlay engine.\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < overlay->ops->n_supported_formats; i++) {
+ if (buffer->format == overlay->ops->supported_formats[i])
+ break;
+ }
+
+ if (i == overlay->ops->n_supported_formats) {
+ char req_format_str[ADF_FORMAT_STR_SIZE];
+
+ adf_format_str(buffer->format, req_format_str);
+
+ val_dbg(device, "Unsupported buffer format %s.\n",
+ req_format_str);
+ return -EINVAL;
+ }
+
+ interface = get_interface_attached_to_overlay(dev, overlay);
+ if (!interface) {
+ dev_err(device, "No interface attached to overlay\n");
+ return -EINVAL;
+ }
+
+ if (buffer->w != interface->current_mode.hdisplay) {
+ val_dbg(device, "Buffer width %u is not expected %u.\n",
+ buffer->w, interface->current_mode.hdisplay);
+ return -EINVAL;
+ }
+
+ if (buffer->h != interface->current_mode.vdisplay) {
+ val_dbg(device, "Buffer height %u is not expected %u.\n",
+ buffer->h, interface->current_mode.vdisplay);
+ return -EINVAL;
+ }
+
+ if (buffer->n_planes != 1) {
+ val_dbg(device, "Buffer n_planes %u is not 1.\n",
+ buffer->n_planes);
+ return -EINVAL;
+ }
+
+ if (buffer->offset[0] != 0) {
+ val_dbg(device, "Buffer offset %u is not 0.\n",
+ buffer->offset[0]);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cfg->n_bufs; i++) {
+ struct adf_buffer_config_ext *buf_ext = &post_ext->bufs_ext[i];
+ if (buf_ext->crop.x1 != 0 ||
+ buf_ext->crop.y1 != 0 ||
+ buf_ext->crop.x2 != interface->current_mode.hdisplay ||
+ buf_ext->crop.y2 != interface->current_mode.vdisplay) {
+ val_dbg(device, "Buffer crop {%u,%u,%u,%u} not expected {%u,%u,%u,%u}.\n",
+ buf_ext->crop.x1, buf_ext->crop.y1,
+ buf_ext->crop.x2, buf_ext->crop.y2,
+ 0, 0, interface->current_mode.hdisplay,
+ interface->current_mode.vdisplay);
+ return -EINVAL;
+ }
+
+ if (buf_ext->display.x1 != 0 ||
+ buf_ext->display.y1 != 0 ||
+ buf_ext->display.x2 != interface->current_mode.hdisplay ||
+ buf_ext->display.y2 != interface->current_mode.vdisplay) {
+ val_dbg(device, "Buffer display {%u,%u,%u,%u} not expected {%u,%u,%u,%u}.\n",
+ buf_ext->display.x1, buf_ext->display.y1,
+ buf_ext->display.x2, buf_ext->display.y2,
+ 0, 0, interface->current_mode.hdisplay,
+ interface->current_mode.vdisplay);
+ return -EINVAL;
+ }
+
+ if (buf_ext->transform != ADF_BUFFER_TRANSFORM_NONE_EXT) {
+ val_dbg(device, "Buffer transform 0x%x not expected transform 0x%x.\n",
+ buf_ext->transform, ADF_BUFFER_TRANSFORM_NONE_EXT);
+ return -EINVAL;
+ }
+
+ if (buf_ext->blend_type != ADF_BUFFER_BLENDING_PREMULT_EXT) {
+ val_dbg(device, "Buffer blend type %u not expected blend type %u.\n",
+ buf_ext->blend_type, ADF_BUFFER_BLENDING_PREMULT_EXT);
+ return -EINVAL;
+ }
+
+ if (buf_ext->plane_alpha != 0xff) {
+ val_dbg(device, "Buffer plane alpha %u not expected plane alpha %u.\n",
+ buf_ext->plane_alpha, 0xff);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+bool adf_img_buffer_sanity_check(const struct adf_interface *intf,
+ const struct adf_buffer *buf,
+ const struct adf_buffer_config_ext *buf_ext)
+{
+ int plane;
+ struct device *dev = intf->base.parent->dev;
+ if (buf->w == 0) {
+ dev_err(dev, "Buffer sanity failed: Zero width\n");
+ return false;
+ }
+ if (buf->h == 0) {
+ dev_err(dev, "Buffer sanity failed: Zero height\n");
+ return false;
+ }
+ if (buf->format == 0) {
+ dev_err(dev, "Buffer sanity failed: Zero format\n");
+ return false;
+ }
+ if (buf->pitch == 0) {
+ dev_err(dev, "Buffer sanity failed: Zero pitch\n");
+ return false;
+ }
+ if (buf->n_planes == 0) {
+ dev_err(dev, "Buffer sanity failed: Zero plane count\n");
+ return false;
+ }
+ if (buf->overlay_engine == NULL) {
+ dev_err(dev, "Buffer sanity failed: NULL assigned overlay\n");
+ return false;
+ }
+
+ for (plane = 0; plane < buf->n_planes; plane++) {
+ if (buf->dma_bufs[plane] == NULL) {
+ dev_err(dev, "Buffer sanity failed: NULL dma buf for plane %d\n",
+ plane);
+ return false;
+ }
+ if (buf->pitch[plane] == 0) {
+ dev_err(dev, "Buffer sanity failed: Zero pitch for plane %d\n",
+ plane);
+ return false;
+ }
+ /* The offset may be zero, so we can't check that here */
+ }
+
+ if (buf_ext->crop.x1 >= buf_ext->crop.x2 ||
+ buf_ext->crop.y1 >= buf_ext->crop.y2) {
+ dev_err(dev, "Buffer sanity failed: Invalid crop rect (%d,%d)(%d,%d)\n",
+ buf_ext->crop.x1, buf_ext->crop.y1,
+ buf_ext->crop.x2, buf_ext->crop.y2);
+ return false;
+ }
+
+ if (buf_ext->crop.x1 > buf->w ||
+ buf_ext->crop.x2 > buf->w ||
+ buf_ext->crop.y1 > buf->h ||
+ buf_ext->crop.y2 > buf->h) {
+ dev_err(dev, "Buffer sanity failed: Crop rect (%d,%d)(%d,%d) outside of %dx%d source buffer\n",
+ buf_ext->crop.x1, buf_ext->crop.y1,
+ buf_ext->crop.x2, buf_ext->crop.y2,
+ buf->w, buf->h);
+ return false;
+ }
+
+ if (buf_ext->display.x1 >= buf_ext->display.x2 ||
+ buf_ext->display.y1 >= buf_ext->display.y2) {
+ dev_err(dev, "Buffer sanity failed: Invalid display rect (%d,%d)(%d,%d)\n",
+ buf_ext->display.x1, buf_ext->display.y1,
+ buf_ext->display.x2, buf_ext->display.y2);
+ return false;
+ }
+
+ if (buf_ext->crop.x1 > buf->w ||
+ buf_ext->crop.x2 > buf->w ||
+ buf_ext->crop.y1 > buf->h ||
+ buf_ext->crop.y2 > buf->h) {
+ dev_err(dev, "Buffer sanity failed: Display rect (%d,%d)(%d,%d) outside of %dx%d current interface mode\n",
+ buf_ext->crop.x1, buf_ext->crop.y1,
+ buf_ext->crop.x2, buf_ext->crop.y2,
+ intf->current_mode.hdisplay,
+ intf->current_mode.vdisplay);
+ return false;
+ }
+
+ switch (buf_ext->transform) {
+ case ADF_BUFFER_TRANSFORM_NONE_EXT:
+ case ADF_BUFFER_TRANSFORM_FLIP_H_EXT:
+ case ADF_BUFFER_TRANSFORM_FLIP_V_EXT:
+ case ADF_BUFFER_TRANSFORM_ROT_90_EXT:
+ case ADF_BUFFER_TRANSFORM_ROT_180_EXT:
+ case ADF_BUFFER_TRANSFORM_ROT_270_EXT:
+ break;
+ default:
+ dev_err(dev, "Invalid transform 0x%x\n", buf_ext->transform);
+ return false;
+ }
+
+ switch (buf_ext->blend_type) {
+ case ADF_BUFFER_BLENDING_NONE_EXT:
+ case ADF_BUFFER_BLENDING_PREMULT_EXT:
+ case ADF_BUFFER_BLENDING_COVERAGE_EXT:
+ break;
+ default:
+ dev_err(dev, "Invalid blend type 0x%x\n", buf_ext->blend_type);
+ return false;
+ }
+ return true;
+}
+
+bool adf_img_rects_intersect(const struct drm_clip_rect *rect1,
+ const struct drm_clip_rect *rect2)
+{
+ if (rect1->x1 < rect2->x2 &&
+ rect1->x2 > rect2->x1 &&
+ rect1->y1 < rect2->y2 &&
+ rect1->y2 > rect2->y1)
+ return true;
+ return false;
+}
+
+
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_common.h b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_common.h
new file mode 100644
index 000000000000..ff00455b6cfd
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_common.h
@@ -0,0 +1,80 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+#include <video/adf.h>
+#include <adf/adf_ext.h>
+
+long
+adf_img_ioctl_validate(struct adf_device *dev,
+ struct adf_validate_config_ext __user *arg);
+
+long
+adf_img_ioctl(struct adf_obj *obj, unsigned int cmd, unsigned long arg);
+
+/* This validates a post config with a set of assumptions for simple display
+ * engines:
+ * - The config custom data is a struct adf_buffer_config_ext
+ * - There is a single interface with a single overlay attached
+ * - There is a single non-blended layer
+ * - There is a single full-screen buffer
+ * - The buffer is of a format supported by the overlay
+ */
+int
+adf_img_validate_simple(struct adf_device *dev, struct adf_post *cfg,
+ void **driver_state);
+
+/* This does a quick sanity check of the supplied buffer, returns true if it
+ * passes the sanity checks.
+ * The calling driver must still do any device-specific validation
+ * of the buffer arguments.
+ */
+bool
+adf_img_buffer_sanity_check(const struct adf_interface *intf,
+ const struct adf_buffer *buf,
+ const struct adf_buffer_config_ext *buf_ext);
+
+
+/* Returns true if the two clip rects intersect
+ */
+bool
+adf_img_rects_intersect(const struct drm_clip_rect *rect1,
+ const struct drm_clip_rect *rect2);
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_fbdev.c b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_fbdev.c
new file mode 100644
index 000000000000..ce9ae8c1c74b
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_fbdev.c
@@ -0,0 +1,849 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+#include <linux/version.h>
+#include <linux/console.h>
+#include <linux/dma-buf.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+
+#include <drm/drm_fourcc.h>
+
+#include <video/adf.h>
+#include <video/adf_fbdev.h>
+#include <video/adf_client.h>
+
+#include <adf/adf_ext.h>
+
+/* for sync_fence_put */
+#include PVR_ANDROID_SYNC_HEADER
+
+#include "adf_common.h"
+
+#ifndef CONFIG_FB
+#error adf_fbdev needs Linux framebuffer support. Enable it in your kernel.
+#endif
+
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
+MODULE_LICENSE("Dual MIT/GPL");
+
+/* NOTE: This is just an example of how to use adf. You should NOT use this
+ * module in a production environment. It is meaningless to layer adf
+ * on top of fbdev, as adf is more flexible than fbdev and adf itself
+ * provides fbdev emulation. Do not use this implementation generally!
+ */
+
+#define DRVNAME "adf_fbdev"
+
+#define FALLBACK_REFRESH_RATE 60
+#define FALLBACK_DPI 160
+
+#if defined(ADF_FBDEV_NUM_PREFERRED_BUFFERS)
+#define NUM_PREFERRED_BUFFERS ADF_FBDEV_NUM_PREFERRED_BUFFERS
+#else
+#define NUM_PREFERRED_BUFFERS 3
+#endif
+
+struct adf_fbdev_dmabuf {
+ struct sg_table sg_table;
+ unsigned long paddr;
+ size_t offset;
+ size_t length;
+ void *vaddr;
+
+ /* Used for cleanup of dmabuf private data */
+ spinlock_t *alloc_lock;
+ u8 *alloc_mask;
+ u8 id;
+};
+
+struct adf_fbdev_device {
+ struct adf_device base;
+ struct fb_info *fb_info;
+ atomic_t refcount;
+};
+
+struct adf_fbdev_interface {
+ struct adf_interface base;
+ struct drm_mode_modeinfo fb_mode;
+ u16 width_mm, height_mm;
+ struct fb_info *fb_info;
+ spinlock_t alloc_lock;
+ u8 alloc_mask;
+};
+
+/* SIMPLE BUFFER MANAGER *****************************************************/
+
+/* Handle alloc/free from the fbdev carveout (fix.smem_start -> fix.smem_size)
+ * region. This simple allocator sets a bit in the alloc_mask when a buffer is
+ * owned by dmabuf. When the dmabuf ->release() is called, the alloc_mask bit
+ * is cleared and the adf_fbdev_dmabuf object is freed.
+ *
+ * Since dmabuf relies on sg_table/scatterlists, and hence struct page*, this
+ * code may have problems if your framebuffer uses memory that is not in the
+ * kernel's page tables.
+ */
+
+static struct adf_fbdev_dmabuf *
+adf_fbdev_alloc_buffer(struct adf_fbdev_interface *interface)
+{
+ struct adf_fbdev_dmabuf *fbdev_dmabuf;
+ size_t unitary_size;
+ u32 id = 0;
+ int err;
+
+ spin_lock(&interface->alloc_lock);
+
+ for (id = 0; id < NUM_PREFERRED_BUFFERS; id++) {
+ if (!(interface->alloc_mask & (1UL << id))) {
+ interface->alloc_mask |= (1UL << id);
+ break;
+ }
+ }
+
+ spin_unlock(&interface->alloc_lock);
+
+ if (id == NUM_PREFERRED_BUFFERS)
+ return ERR_PTR(-ENOMEM);
+
+ unitary_size = interface->fb_info->fix.line_length *
+ interface->fb_info->var.yres;
+
+ /* PAGE_SIZE alignment has been checked already, do NOT allow it
+ * through here. We are about to allocate an sg_list.
+ */
+ BUG_ON((unitary_size % PAGE_SIZE) != 0);
+
+ fbdev_dmabuf = kmalloc(sizeof(struct adf_fbdev_dmabuf), GFP_KERNEL);
+ if (!fbdev_dmabuf)
+ return ERR_PTR(-ENOMEM);
+
+ /* We only need one scatterlist entry per buffer because fbdev memory
+ * is always physically contiguous.
+ */
+ err = sg_alloc_table(&fbdev_dmabuf->sg_table, 1, GFP_KERNEL);
+ if (err) {
+ kfree(fbdev_dmabuf);
+ return ERR_PTR(err);
+ }
+
+ /* Increment the reference count of this module as long as the
+ * adb_fbdev_dmabuf object exists. This prevents this module from
+ * being unloaded if the buffer is passed around by dmabuf.
+ */
+ if (!try_module_get(THIS_MODULE)) {
+ pr_err("try_module_get(THIS_MODULE) failed");
+ kfree(fbdev_dmabuf);
+ return ERR_PTR(-EFAULT);
+ }
+
+ fbdev_dmabuf->offset = id * unitary_size;
+ fbdev_dmabuf->length = unitary_size;
+ fbdev_dmabuf->vaddr = interface->fb_info->screen_base +
+ fbdev_dmabuf->offset;
+ fbdev_dmabuf->paddr = interface->fb_info->fix.smem_start +
+ fbdev_dmabuf->offset;
+
+ sg_set_page(fbdev_dmabuf->sg_table.sgl,
+ pfn_to_page(PFN_DOWN(fbdev_dmabuf->paddr)),
+ fbdev_dmabuf->length, 0);
+
+ fbdev_dmabuf->alloc_mask = &interface->alloc_mask;
+ fbdev_dmabuf->alloc_lock = &interface->alloc_lock;
+ fbdev_dmabuf->id = id;
+
+ return fbdev_dmabuf;
+}
+
+static void adf_fbdev_free_buffer(struct adf_fbdev_dmabuf *fbdev_dmabuf)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(fbdev_dmabuf->alloc_lock, flags);
+ (*fbdev_dmabuf->alloc_mask) &= ~(1UL << fbdev_dmabuf->id);
+ spin_unlock_irqrestore(fbdev_dmabuf->alloc_lock, flags);
+
+ sg_free_table(&fbdev_dmabuf->sg_table);
+ kfree(fbdev_dmabuf);
+
+ module_put(THIS_MODULE);
+}
+
+/* DMA BUF LAYER *************************************************************/
+
+static struct sg_table *
+adf_fbdev_d_map_dma_buf(struct dma_buf_attachment *attachment,
+ enum dma_data_direction direction)
+{
+ struct adf_fbdev_dmabuf *fbdev_dmabuf = attachment->dmabuf->priv;
+ return &fbdev_dmabuf->sg_table;
+}
+
+static void adf_fbdev_d_unmap_dma_buf(struct dma_buf_attachment *attachment,
+ struct sg_table *table,
+ enum dma_data_direction direction)
+{
+ /* No-op */
+}
+
+static int adf_fbdev_d_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+{
+ struct adf_fbdev_dmabuf *fbdev_dmabuf = dmabuf->priv;
+ return remap_pfn_range(vma, vma->vm_start,
+ PFN_DOWN(fbdev_dmabuf->paddr),
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
+static void adf_fbdev_d_release(struct dma_buf *dmabuf)
+{
+ adf_fbdev_free_buffer(dmabuf->priv);
+}
+
+static int
+adf_fbdev_d_begin_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
+ enum dma_data_direction dir)
+{
+ struct adf_fbdev_dmabuf *fbdev_dmabuf = dmabuf->priv;
+ if (start + len > fbdev_dmabuf->length)
+ return -EINVAL;
+ return 0;
+}
+
+static void adf_fbdev_d_end_cpu_access(struct dma_buf *dmabuf, size_t start,
+ size_t len, enum dma_data_direction dir)
+{
+ /* Framebuffer memory is cache coherent. No-op. */
+}
+
+static void *
+adf_fbdev_d_kmap(struct dma_buf *dmabuf, unsigned long page_offset)
+{
+ struct adf_fbdev_dmabuf *fbdev_dmabuf = dmabuf->priv;
+ void *vaddr;
+ if (page_offset * PAGE_SIZE >= fbdev_dmabuf->length)
+ return ERR_PTR(-EINVAL);
+ vaddr = fbdev_dmabuf->vaddr + page_offset * PAGE_SIZE;
+ return vaddr;
+}
+
+static void
+adf_fbdev_d_kunmap(struct dma_buf *dmabuf, unsigned long page_offset,
+ void *ptr)
+{
+ /* No-op */
+}
+
+static void *adf_fbdev_d_vmap(struct dma_buf *dmabuf)
+{
+ struct adf_fbdev_dmabuf *fbdev_dmabuf = dmabuf->priv;
+ return fbdev_dmabuf->vaddr;
+}
+
+static void adf_fbdev_d_vunmap(struct dma_buf *dmabuf, void *vaddr)
+{
+ /* No-op */
+}
+
+static const struct dma_buf_ops adf_fbdev_dma_buf_ops = {
+ .map_dma_buf = adf_fbdev_d_map_dma_buf,
+ .unmap_dma_buf = adf_fbdev_d_unmap_dma_buf,
+ .mmap = adf_fbdev_d_mmap,
+ .release = adf_fbdev_d_release,
+ .begin_cpu_access = adf_fbdev_d_begin_cpu_access,
+ .end_cpu_access = adf_fbdev_d_end_cpu_access,
+ .kmap_atomic = adf_fbdev_d_kmap,
+ .kunmap_atomic = adf_fbdev_d_kunmap,
+ .kmap = adf_fbdev_d_kmap,
+ .kunmap = adf_fbdev_d_kunmap,
+ .vmap = adf_fbdev_d_vmap,
+ .vunmap = adf_fbdev_d_vunmap,
+};
+
+/* ADF LAYER *****************************************************************/
+
+static u32 adf_fbdev_supported_format;
+
+static int adf_fbdev_validate(struct adf_device *dev, struct adf_post *cfg,
+ void **driver_state)
+{
+ int err = adf_img_validate_simple(dev, cfg, driver_state);
+
+ if (cfg->n_bufs == 0 || err != 0)
+ return err;
+
+ /* Everything checked out in the generic validation, but we
+ * additionally want to check that the dmabuf came from the
+ * adf_fbdev module, which the generic code can't check.
+ */
+ if (cfg->bufs[0].dma_bufs[0]->ops != &adf_fbdev_dma_buf_ops)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void adf_fbdev_post(struct adf_device *dev, struct adf_post *cfg,
+ void *driver_state)
+{
+ struct adf_fbdev_device *device = (struct adf_fbdev_device *)dev;
+ struct fb_var_screeninfo new_var = device->fb_info->var;
+ struct adf_fbdev_dmabuf *fbdev_dmabuf;
+ struct adf_buffer *buffer;
+ int err;
+
+ /* "Null" flip handling */
+ if (cfg->n_bufs == 0)
+ return;
+
+ if (!lock_fb_info(device->fb_info)) {
+ pr_err("Failed to lock fb_info structure.\n");
+ return;
+ }
+
+ console_lock();
+
+ buffer = &cfg->bufs[0];
+ fbdev_dmabuf = buffer->dma_bufs[0]->priv;
+ new_var.yoffset = new_var.yres * fbdev_dmabuf->id;
+
+ /* If we're supposed to be able to flip, but the yres_virtual has been
+ * changed to an unsupported (smaller) value, we need to change it back
+ * (this is a workaround for some Linux fbdev drivers that seem to lose
+ * any modifications to yres_virtual after a blank.)
+ */
+ if (new_var.yres_virtual < new_var.yres * NUM_PREFERRED_BUFFERS) {
+ new_var.activate = FB_ACTIVATE_NOW;
+ new_var.yres_virtual = new_var.yres * NUM_PREFERRED_BUFFERS;
+
+ err = fb_set_var(device->fb_info, &new_var);
+ if (err)
+ pr_err("fb_set_var failed (err=%d)\n", err);
+ } else {
+ err = fb_pan_display(device->fb_info, &new_var);
+ if (err)
+ pr_err("fb_pan_display failed (err=%d)\n", err);
+ }
+
+ console_unlock();
+
+ unlock_fb_info(device->fb_info);
+}
+
+static int
+adf_fbdev_open2(struct adf_obj *obj, struct inode *inode, struct file *file)
+{
+ struct adf_fbdev_device *dev =
+ (struct adf_fbdev_device *)obj->parent;
+ atomic_inc(&dev->refcount);
+ return 0;
+}
+
+static void
+adf_fbdev_release2(struct adf_obj *obj, struct inode *inode, struct file *file)
+{
+ struct adf_fbdev_device *dev =
+ (struct adf_fbdev_device *)obj->parent;
+ struct sync_fence *release_fence;
+
+ if (atomic_dec_return(&dev->refcount))
+ return;
+
+ /* This special "null" flip works around a problem with ADF
+ * which leaves buffers pinned by the display engine even
+ * after all ADF clients have closed.
+ *
+ * The "null" flip is pipelined like any other. The user won't
+ * be able to unload this module until it has been posted.
+ */
+ release_fence = adf_device_post(&dev->base, NULL, 0, NULL, 0, NULL, 0);
+ if (IS_ERR_OR_NULL(release_fence)) {
+ pr_err("Failed to queue null flip command (err=%d).\n",
+ (int)PTR_ERR(release_fence));
+ return;
+ }
+
+ sync_fence_put(release_fence);
+}
+
+static const struct adf_device_ops adf_fbdev_device_ops = {
+ .owner = THIS_MODULE,
+ .base = {
+ .open = adf_fbdev_open2,
+ .release = adf_fbdev_release2,
+ .ioctl = adf_img_ioctl,
+ },
+ .validate = adf_fbdev_validate,
+ .post = adf_fbdev_post,
+};
+
+static bool
+adf_fbdev_supports_event(struct adf_obj *obj, enum adf_event_type type)
+{
+ switch (type) {
+ case ADF_EVENT_VSYNC:
+ case ADF_EVENT_HOTPLUG:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void
+adf_fbdev_set_event(struct adf_obj *obj, enum adf_event_type type,
+ bool enabled)
+{
+ switch (type) {
+ case ADF_EVENT_VSYNC:
+ case ADF_EVENT_HOTPLUG:
+ break;
+ default:
+ BUG();
+ }
+}
+
+static int adf_fbdev_blank2(struct adf_interface *intf, u8 state)
+{
+ struct adf_fbdev_interface *interface =
+ (struct adf_fbdev_interface *)intf;
+ struct fb_info *fb_info = interface->fb_info;
+
+ if (!fb_info->fbops->fb_blank)
+ return -EOPNOTSUPP;
+
+ return fb_info->fbops->fb_blank(state, fb_info);
+}
+
+static int
+adf_fbdev_alloc_simple_buffer(struct adf_interface *intf, u16 w, u16 h,
+ u32 format, struct dma_buf **dma_buf,
+ u32 *offset, u32 *pitch)
+{
+ struct adf_fbdev_interface *interface =
+ (struct adf_fbdev_interface *)intf;
+ struct fb_var_screeninfo *var = &interface->fb_info->var;
+ struct adf_fbdev_dmabuf *fbdev_dmabuf;
+
+ if (w != var->xres) {
+ pr_err("Simple alloc request w=%u does not match w=%u.\n",
+ w, var->xres);
+ return -EINVAL;
+ }
+
+ if (h != var->yres) {
+ pr_err("Simple alloc request h=%u does not match h=%u.\n",
+ h, var->yres);
+ return -EINVAL;
+ }
+
+ if (format != adf_fbdev_supported_format) {
+ pr_err("Simple alloc request f=0x%x does not match f=0x%x.\n",
+ format, adf_fbdev_supported_format);
+ return -EINVAL;
+ }
+
+ fbdev_dmabuf = adf_fbdev_alloc_buffer(interface);
+ if (IS_ERR_OR_NULL(fbdev_dmabuf))
+ return PTR_ERR(fbdev_dmabuf);
+
+ *dma_buf = dma_buf_export(fbdev_dmabuf, &adf_fbdev_dma_buf_ops,
+ fbdev_dmabuf->length, O_RDWR);
+ if (IS_ERR(*dma_buf)) {
+ adf_fbdev_free_buffer(fbdev_dmabuf);
+ return PTR_ERR(*dma_buf);
+ }
+
+ *pitch = interface->fb_info->fix.line_length;
+ *offset = 0;
+ return 0;
+}
+
+static int
+adf_fbdev_screen_size(struct adf_interface *intf, u16 *width_mm,
+ u16 *height_mm)
+{
+ struct adf_fbdev_interface *interface =
+ (struct adf_fbdev_interface *)intf;
+ *width_mm = interface->width_mm;
+ *height_mm = interface->height_mm;
+ return 0;
+}
+
+static int adf_fbdev_modeset(struct adf_interface *intf,
+ struct drm_mode_modeinfo *mode)
+{
+ struct adf_fbdev_interface *interface =
+ (struct adf_fbdev_interface *)intf;
+ return mode == &interface->fb_mode ? 0 : -EINVAL;
+}
+
+static const struct adf_interface_ops adf_fbdev_interface_ops = {
+ .base = {
+ .supports_event = adf_fbdev_supports_event,
+ .set_event = adf_fbdev_set_event,
+ },
+ .blank = adf_fbdev_blank2,
+ .alloc_simple_buffer = adf_fbdev_alloc_simple_buffer,
+ .screen_size = adf_fbdev_screen_size,
+ .modeset = adf_fbdev_modeset,
+};
+
+struct adf_overlay_engine_ops adf_fbdev_overlay_engine_ops = {
+ .supported_formats = &adf_fbdev_supported_format,
+ .n_supported_formats = 1,
+};
+
+/* If we can flip, we need to make sure we have the memory to do so.
+ *
+ * We'll assume that the fbdev device provides extra space in
+ * yres_virtual for panning; xres_virtual is theoretically supported,
+ * but it involves more work.
+ *
+ * If the fbdev device doesn't have yres_virtual > yres, we'll try
+ * requesting it before bailing. Userspace applications commonly do
+ * this with an FBIOPUT_VSCREENINFO ioctl().
+ *
+ * Another problem is with a limitation in PowerVR services -- it
+ * needs framebuffers to be page aligned (this is a SW limitation,
+ * the HW can support non-page-aligned buffers). So we have to
+ * check that stride * height for a single buffer is page aligned.
+ */
+static bool adf_fbdev_flip_possible(struct fb_info *fb_info)
+{
+ struct fb_var_screeninfo var = fb_info->var;
+ int err;
+
+ if (!fb_info->fix.xpanstep && !fb_info->fix.ypanstep &&
+ !fb_info->fix.ywrapstep) {
+ pr_err("The fbdev device detected does not support ypan/ywrap.\n");
+ return false;
+ }
+
+ if ((fb_info->fix.line_length * var.yres) % PAGE_SIZE != 0) {
+ pr_err("Line length (in bytes) x yres is not a multiple of page size.\n");
+ return false;
+ }
+
+ /* We might already have enough space */
+ if (var.yres * NUM_PREFERRED_BUFFERS <= var.yres_virtual)
+ return true;
+
+ pr_err("No buffer space for flipping; asking for more.\n");
+
+ var.activate = FB_ACTIVATE_NOW;
+ var.yres_virtual = var.yres * NUM_PREFERRED_BUFFERS;
+
+ err = fb_set_var(fb_info, &var);
+ if (err) {
+ pr_err("fb_set_var failed (err=%d).\n", err);
+ return false;
+ }
+
+ if (var.yres * NUM_PREFERRED_BUFFERS > var.yres_virtual) {
+ pr_err("Failed to obtain additional buffer space.\n");
+ return false;
+ }
+
+ /* Some fbdev drivers allow the yres_virtual modification through,
+ * but don't actually update the fix. We need the fix to be updated
+ * and more memory allocated, so we can actually take advantage of
+ * the increased yres_virtual.
+ */
+ if (fb_info->fix.smem_len < fb_info->fix.line_length *
+ var.yres_virtual) {
+ pr_err("'fix' not re-allocated with sufficient buffer space.\n");
+ pr_err("Check NUM_PREFERRED_BUFFERS (%u) is as intended.\n",
+ NUM_PREFERRED_BUFFERS);
+ return false;
+ }
+
+ return true;
+}
+
+/* Could use devres here? */
+static struct {
+ struct adf_fbdev_device device;
+ struct adf_fbdev_interface interface;
+ struct adf_overlay_engine engine;
+} dev_data;
+
+static int __init init_adf_fbdev(void)
+{
+ struct drm_mode_modeinfo *mode = &dev_data.interface.fb_mode;
+ char format_str[ADF_FORMAT_STR_SIZE];
+ struct fb_info *fb_info;
+ int err = -ENODEV;
+
+ fb_info = registered_fb[0];
+ if (!fb_info) {
+ pr_err("No Linux framebuffer (fbdev) device is registered!\n");
+ pr_err("Check you have a framebuffer driver compiled into your kernel\n");
+ pr_err("and that it is enabled on the cmdline.\n");
+ goto err_out;
+ }
+
+ if (!lock_fb_info(fb_info))
+ goto err_out;
+
+ console_lock();
+
+ /* Filter out broken FB devices */
+ if (!fb_info->fix.smem_len || !fb_info->fix.line_length) {
+ pr_err("The fbdev device detected had a zero smem_len or line_length,\n");
+ pr_err("which suggests it is a broken driver.\n");
+ goto err_unlock;
+ }
+
+ if (fb_info->fix.type != FB_TYPE_PACKED_PIXELS ||
+ fb_info->fix.visual != FB_VISUAL_TRUECOLOR) {
+ pr_err("The fbdev device detected is not truecolor with packed pixels.\n");
+ goto err_unlock;
+ }
+
+ if (fb_info->var.bits_per_pixel == 32) {
+ if (fb_info->var.red.length != 8 ||
+ fb_info->var.green.length != 8 ||
+ fb_info->var.blue.length != 8 ||
+ fb_info->var.red.offset != 16 ||
+ fb_info->var.green.offset != 8 ||
+ fb_info->var.blue.offset != 0) {
+ pr_err("The fbdev device detected uses an unrecognized 32bit pixel format (%u/%u/%u, %u/%u/%u)\n",
+ fb_info->var.red.length,
+ fb_info->var.green.length,
+ fb_info->var.blue.length,
+ fb_info->var.red.offset,
+ fb_info->var.green.offset,
+ fb_info->var.blue.offset);
+ goto err_unlock;
+ }
+#if defined(ADF_FBDEV_FORCE_XRGB8888)
+ adf_fbdev_supported_format = DRM_FORMAT_BGRX8888;
+#else
+ adf_fbdev_supported_format = DRM_FORMAT_BGRA8888;
+#endif
+ } else if (fb_info->var.bits_per_pixel == 16) {
+ if (fb_info->var.red.length != 5 ||
+ fb_info->var.green.length != 6 ||
+ fb_info->var.blue.length != 5 ||
+ fb_info->var.red.offset != 11 ||
+ fb_info->var.green.offset != 5 ||
+ fb_info->var.blue.offset != 0) {
+ pr_err("The fbdev device detected uses an unrecognized 16bit pixel format (%u/%u/%u, %u/%u/%u)\n",
+ fb_info->var.red.length,
+ fb_info->var.green.length,
+ fb_info->var.blue.length,
+ fb_info->var.red.offset,
+ fb_info->var.green.offset,
+ fb_info->var.blue.offset);
+ goto err_unlock;
+ }
+ adf_fbdev_supported_format = DRM_FORMAT_BGR565;
+ } else {
+ pr_err("The fbdev device detected uses an unsupported bpp (%u).\n",
+ fb_info->var.bits_per_pixel);
+ goto err_unlock;
+ }
+
+ if (!try_module_get(fb_info->fbops->owner)) {
+ pr_err("try_module_get() failed");
+ goto err_unlock;
+ }
+
+ if (fb_info->fbops->fb_open &&
+ fb_info->fbops->fb_open(fb_info, 0) != 0) {
+ pr_err("fb_open() failed");
+ goto err_module_put;
+ }
+
+ if (!adf_fbdev_flip_possible(fb_info)) {
+ pr_err("Flipping must be supported for ADF. Aborting.\n");
+ goto err_fb_release;
+ }
+
+ err = adf_device_init(&dev_data.device.base, fb_info->dev,
+ &adf_fbdev_device_ops, "fbdev");
+ if (err) {
+ pr_err("adf_device_init failed (%d)", err);
+ goto err_fb_release;
+ }
+
+ dev_data.device.fb_info = fb_info;
+
+ err = adf_interface_init(&dev_data.interface.base,
+ &dev_data.device.base,
+ ADF_INTF_DVI, 0, ADF_INTF_FLAG_PRIMARY,
+ &adf_fbdev_interface_ops, "fbdev_interface");
+ if (err) {
+ pr_err("adf_interface_init failed (%d)", err);
+ goto err_device_destroy;
+ }
+
+ spin_lock_init(&dev_data.interface.alloc_lock);
+ dev_data.interface.fb_info = fb_info;
+
+ /* If the fbdev mode looks viable, try to inherit from it */
+ if (fb_info->mode)
+ adf_modeinfo_from_fb_videomode(fb_info->mode, mode);
+
+ /* Framebuffer drivers aren't always very good at filling out their
+ * mode information, so fake up anything that's missing so we don't
+ * need to accommodate it in userspace.
+ */
+
+ if (!mode->hdisplay)
+ mode->hdisplay = fb_info->var.xres;
+ if (!mode->vdisplay)
+ mode->vdisplay = fb_info->var.yres;
+ if (!mode->vrefresh)
+ mode->vrefresh = FALLBACK_REFRESH_RATE;
+
+ if (fb_info->var.width > 0 && fb_info->var.width < 1000) {
+ dev_data.interface.width_mm = fb_info->var.width;
+ } else {
+ dev_data.interface.width_mm = (fb_info->var.xres * 25400) /
+ (FALLBACK_DPI * 1000);
+ }
+
+ if (fb_info->var.height > 0 && fb_info->var.height < 1000) {
+ dev_data.interface.height_mm = fb_info->var.height;
+ } else {
+ dev_data.interface.height_mm = (fb_info->var.yres * 25400) /
+ (FALLBACK_DPI * 1000);
+ }
+
+ err = adf_hotplug_notify_connected(&dev_data.interface.base, mode, 1);
+ if (err) {
+ pr_err("adf_hotplug_notify_connected failed (%d)", err);
+ goto err_interface_destroy;
+ }
+
+ /* This doesn't really set the mode, it just updates current_mode */
+ err = adf_interface_set_mode(&dev_data.interface.base, mode);
+ if (err) {
+ pr_err("adf_interface_set_mode failed (%d)", err);
+ goto err_interface_destroy;
+ }
+
+ err = adf_overlay_engine_init(&dev_data.engine, &dev_data.device.base,
+ &adf_fbdev_overlay_engine_ops,
+ "fbdev_overlay_engine");
+ if (err) {
+ pr_err("adf_overlay_engine_init failed (%d)", err);
+ goto err_interface_destroy;
+ }
+
+ err = adf_attachment_allow(&dev_data.device.base,
+ &dev_data.engine,
+ &dev_data.interface.base);
+
+ if (err) {
+ pr_err("adf_attachment_allow failed (%d)", err);
+ goto err_overlay_engine_destroy;
+ }
+
+ adf_format_str(adf_fbdev_supported_format, format_str);
+ pr_info("Found usable fbdev device (%s):\n"
+ "range (physical) = 0x%lx-0x%lx\n"
+ "range (virtual) = %p-%p\n"
+ "size (bytes) = 0x%x\n"
+ "xres x yres = %ux%u\n"
+ "xres x yres (v) = %ux%u\n"
+ "physical (mm) = %ux%u\n"
+ "refresh (Hz) = %u\n"
+ "drm fourcc = %s (0x%x)\n",
+ fb_info->fix.id,
+ fb_info->fix.smem_start,
+ fb_info->fix.smem_start + fb_info->fix.smem_len,
+ fb_info->screen_base,
+ fb_info->screen_base + fb_info->screen_size,
+ fb_info->fix.smem_len,
+ mode->hdisplay, mode->vdisplay,
+ fb_info->var.xres_virtual, fb_info->var.yres_virtual,
+ dev_data.interface.width_mm, dev_data.interface.height_mm,
+ mode->vrefresh,
+ format_str, adf_fbdev_supported_format);
+ err = 0;
+err_unlock:
+ console_unlock();
+ unlock_fb_info(fb_info);
+err_out:
+ return err;
+err_overlay_engine_destroy:
+ adf_overlay_engine_destroy(&dev_data.engine);
+err_interface_destroy:
+ adf_interface_destroy(&dev_data.interface.base);
+err_device_destroy:
+ adf_device_destroy(&dev_data.device.base);
+err_fb_release:
+ if (fb_info->fbops->fb_release)
+ fb_info->fbops->fb_release(fb_info, 0);
+err_module_put:
+ module_put(fb_info->fbops->owner);
+ goto err_unlock;
+}
+
+static void __exit exit_adf_fbdev(void)
+{
+ struct fb_info *fb_info = dev_data.device.fb_info;
+
+ if (!lock_fb_info(fb_info)) {
+ pr_err("Failed to lock fb_info.\n");
+ return;
+ }
+
+ console_lock();
+
+ adf_overlay_engine_destroy(&dev_data.engine);
+ adf_interface_destroy(&dev_data.interface.base);
+ adf_device_destroy(&dev_data.device.base);
+
+ if (fb_info->fbops->fb_release)
+ fb_info->fbops->fb_release(fb_info, 0);
+
+ module_put(fb_info->fbops->owner);
+
+ console_unlock();
+ unlock_fb_info(fb_info);
+}
+
+module_init(init_adf_fbdev);
+module_exit(exit_adf_fbdev);
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_pdp.c b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_pdp.c
new file mode 100644
index 000000000000..8a325e14557b
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/adf_pdp.c
@@ -0,0 +1,1179 @@
+/*************************************************************************/ /*!
+@File adf_pdp.c
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+/*
+ * This is an example ADF display driver for the testchip's PDP output
+ */
+
+/* #define SUPPORT_ADF_PDP_FBDEV */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+
+#include <drm/drm_fourcc.h>
+
+#include <video/adf.h>
+#include <video/adf_client.h>
+
+#ifdef SUPPORT_ADF_PDP_FBDEV
+#include <video/adf_fbdev.h>
+#endif
+
+#include PVR_ANDROID_ION_HEADER
+
+/* for sync_fence_put */
+#include PVR_ANDROID_SYNC_HEADER
+
+#include "apollo_drv.h"
+#include "adf_common.h"
+
+#include "pdp_regs.h"
+#include "tcf_rgbpdp_regs.h"
+#include "tcf_pll.h"
+
+#include "pvrmodule.h"
+
+#define DRV_NAME APOLLO_DEVICE_NAME_PDP
+
+MODULE_DESCRIPTION("APOLLO PDP display driver");
+
+static int pdp_display_width = ADF_PDP_WIDTH;
+static int pdp_display_height = ADF_PDP_HEIGHT;
+module_param(pdp_display_width, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(pdp_display_width, "PDP display width");
+module_param(pdp_display_height, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(pdp_display_height, "PDP display height");
+
+struct pdp_timing_data {
+ u32 h_display;
+ u32 h_back_porch;
+ u32 h_total;
+ u32 h_active_start;
+ u32 h_left_border;
+ u32 h_right_border;
+ u32 h_front_porch;
+
+ u32 v_display;
+ u32 v_back_porch;
+ u32 v_total;
+ u32 v_active_start;
+ u32 v_top_border;
+ u32 v_bottom_border;
+ u32 v_front_porch;
+ u32 v_refresh;
+ u32 clock_freq;
+};
+
+static const struct pdp_timing_data pdp_supported_modes[] = {
+ {
+ .h_display = 640,
+ .h_back_porch = 64,
+ .h_total = 800,
+ .h_active_start = 144,
+ .h_left_border = 144,
+ .h_right_border = 784,
+ .h_front_porch = 784,
+
+ .v_display = 480,
+ .v_back_porch = 7,
+ .v_total = 497,
+ .v_active_start = 16,
+ .v_top_border = 16,
+ .v_bottom_border = 496,
+ .v_front_porch = 496,
+
+ .v_refresh = 60,
+ .clock_freq = 23856000,
+ },
+ {
+ .h_display = 800,
+ .h_back_porch = 80,
+ .h_total = 1024,
+ .h_active_start = 192,
+ .h_left_border = 192,
+ .h_right_border = 992,
+ .h_front_porch = 992,
+
+ .v_display = 600,
+ .v_back_porch = 7,
+ .v_total = 621,
+ .v_active_start = 20,
+ .v_top_border = 20,
+ .v_bottom_border = 620,
+ .v_front_porch = 620,
+
+ .v_refresh = 60,
+ .clock_freq = 38154000,
+ },
+ {
+ .h_display = 1024,
+ .h_back_porch = 104,
+ .h_total = 1344,
+ .h_active_start = 264,
+ .h_left_border = 264,
+ .h_right_border = 1288,
+ .h_front_porch = 1288,
+
+ .v_display = 768,
+ .v_back_porch = 7,
+ .v_total = 795,
+ .v_active_start = 26,
+ .v_top_border = 26,
+ .v_bottom_border = 794,
+ .v_front_porch = 794,
+
+ .v_refresh = 59,
+ .clock_freq = 64108000,
+ },
+ {
+ .h_display = 1280,
+ .h_back_porch = 136,
+ .h_total = 1664,
+ .h_active_start = 328,
+ .h_left_border = 328,
+ .h_right_border = 1608,
+ .h_front_porch = 1608,
+
+ .v_display = 720,
+ .v_back_porch = 7,
+ .v_total = 745,
+ .v_active_start = 24,
+ .v_top_border = 24,
+ .v_bottom_border = 744,
+ .v_front_porch = 744,
+
+ .v_refresh = 59,
+ .clock_freq = 74380000,
+ },
+ {
+ .h_display = 1280,
+ .h_back_porch = 136,
+ .h_total = 1680,
+ .h_active_start = 336,
+ .h_left_border = 336,
+ .h_right_border = 1616,
+ .h_front_porch = 1616,
+
+ .v_display = 768,
+ .v_back_porch = 7,
+ .v_total = 795,
+ .v_active_start = 26,
+ .v_top_border = 26,
+ .v_bottom_border = 794,
+ .v_front_porch = 794,
+
+ .v_refresh = 59,
+ .clock_freq = 80136000,
+ },
+ {
+ .h_display = 1280,
+ .h_back_porch = 136,
+ .h_total = 1680,
+ .h_active_start = 336,
+ .h_left_border = 336,
+ .h_right_border = 1616,
+ .h_front_porch = 1616,
+
+ .v_display = 800,
+ .v_back_porch = 7,
+ .v_total = 828,
+ .v_active_start = 27,
+ .v_top_border = 27,
+ .v_bottom_border = 827,
+ .v_front_porch = 827,
+
+ .v_refresh = 59,
+ .clock_freq = 83462000,
+ },
+ {
+ .h_display = 1280,
+ .h_back_porch = 136,
+ .h_total = 1712,
+ .h_active_start = 352,
+ .h_left_border = 352,
+ .h_right_border = 1632,
+ .h_front_porch = 1632,
+
+ .v_display = 1024,
+ .v_back_porch = 7,
+ .v_total = 1059,
+ .v_active_start = 34,
+ .v_top_border = 34,
+ .v_bottom_border = 1058,
+ .v_front_porch = 1058,
+
+ .v_refresh = 60,
+ .clock_freq = 108780000,
+ },
+ {}
+};
+
+
+struct adf_pdp_device {
+ struct ion_client *ion_client;
+
+ struct adf_device adf_device;
+ struct adf_interface adf_interface;
+ struct adf_overlay_engine adf_overlay;
+#ifdef SUPPORT_ADF_PDP_FBDEV
+ struct adf_fbdev adf_fbdev;
+#endif
+
+ struct platform_device *pdev;
+
+ struct apollo_pdp_platform_data *pdata;
+
+ void __iomem *regs;
+ resource_size_t regs_size;
+ resource_size_t regs_start;
+
+ void __iomem *pll_regs;
+ resource_size_t pll_regs_size;
+ resource_size_t pll_regs_start;
+
+ struct drm_mode_modeinfo *supported_modes;
+ int num_supported_modes;
+
+ const struct pdp_timing_data *current_timings;
+
+ atomic_t refcount;
+
+ atomic_t num_validates;
+ int num_posts;
+
+ atomic_t vsync_triggered;
+ wait_queue_head_t vsync_wait_queue;
+ atomic_t requested_vsync_state;
+ atomic_t vsync_state;
+};
+
+static const u32 pdp_supported_formats[] = {
+ DRM_FORMAT_BGRA8888,
+};
+#define NUM_SUPPORTED_FORMATS 1
+
+static const struct {
+ u32 drm_format;
+ u32 bytes_per_pixel;
+ u32 pixfmt_word;
+} pdp_format_table[] = {
+ { DRM_FORMAT_BGRA8888, 4, DCPDP_STR1SURF_FORMAT_ARGB8888 },
+ {},
+};
+
+static int pdp_mode_count(struct adf_pdp_device *pdp)
+{
+ int i = 0;
+ while (pdp_supported_modes[i].h_display)
+ i++;
+ return i;
+}
+
+static int pdp_mode_id(struct adf_pdp_device *pdp, u32 height, u32 width)
+{
+ int i;
+ for (i = 0; pdp_supported_modes[i].h_display; i++) {
+ const struct pdp_timing_data *tdata = &pdp_supported_modes[i];
+ if (tdata->h_display == width && tdata->v_display == height)
+ return i;
+ }
+ dev_err(&pdp->pdev->dev, "Failed to find matching mode for %dx%d\n",
+ width, height);
+ return -1;
+}
+
+static const struct pdp_timing_data *pdp_timing_data(
+ struct adf_pdp_device *pdp, int mode_id)
+{
+ if (mode_id >= pdp_mode_count(pdp) || mode_id < 0)
+ return NULL;
+ return &pdp_supported_modes[mode_id];
+}
+
+static void pdp_mode_to_drm_mode(struct adf_pdp_device *pdp, int mode_id,
+ struct drm_mode_modeinfo *drm_mode)
+{
+ const struct pdp_timing_data *pdp_mode = pdp_timing_data(pdp, mode_id);
+
+ BUG_ON(pdp_mode == NULL);
+ memset(drm_mode, 0, sizeof(*drm_mode));
+
+ drm_mode->hdisplay = pdp_mode->h_display;
+ drm_mode->vdisplay = pdp_mode->v_display;
+ drm_mode->vrefresh = pdp_mode->v_refresh;
+
+#if 0
+ /* We only currently set the bare-minimum of the drm_mode required
+ * by adf. We internally manage the timings etc. keyed on the
+ * height/width/refresh of the mode, so we don't need to set
+ * the following. */
+ drm_mode->hsync_start = pdp_mode->h_front_porch;
+ drm_mode->hsync_end = pdp_mode->h_total;
+ drm_mode->htotal = pdp_mode->h_total;
+
+ drm_mode->vsync_start = pdp_mode->v_bottom_border;
+ drm_mode->vsync_end = pdp_mode->v_total;
+ /* Clock speed converted from hz to khz */
+ drm_mode->clock = (pdp_mode->clock_freq + 500) / 1000;
+#endif
+ adf_modeinfo_set_name(drm_mode);
+}
+
+static u32 pdp_read_reg(struct adf_pdp_device *pdp, resource_size_t reg_offset)
+{
+ BUG_ON(reg_offset > pdp->regs_size-4);
+ return ioread32(pdp->regs + reg_offset);
+}
+
+static void pdp_write_reg(struct adf_pdp_device *pdp,
+ resource_size_t reg_offset, u32 reg_value)
+{
+ BUG_ON(reg_offset > pdp->regs_size-4);
+ iowrite32(reg_value, pdp->regs + reg_offset);
+}
+
+static void pll_write_reg(struct adf_pdp_device *pdp,
+ resource_size_t reg_offset, u32 reg_value)
+{
+ BUG_ON(reg_offset > pdp->pll_regs_size-4);
+ iowrite32(reg_value, pdp->pll_regs + reg_offset);
+}
+
+static void pdp_devres_release(struct device *dev, void *res)
+{
+ /* No extra cleanup needed */
+}
+
+static int request_pci_io_addr(struct pci_dev *dev, u32 index,
+ resource_size_t offset, resource_size_t length)
+{
+ resource_size_t start, end;
+ start = pci_resource_start(dev, index);
+ end = pci_resource_end(dev, index);
+
+ if ((start + offset + length - 1) > end)
+ return -EIO;
+ if (pci_resource_flags(dev, index) & IORESOURCE_IO) {
+ if (request_region(start + offset, length, DRV_NAME) == NULL)
+ return -EIO;
+ } else {
+ if (request_mem_region(start + offset, length, DRV_NAME)
+ == NULL)
+ return -EIO;
+ }
+ return 0;
+}
+
+static void release_pci_io_addr(struct pci_dev *dev, u32 index,
+ resource_size_t start, resource_size_t length)
+{
+ if (pci_resource_flags(dev, index) & IORESOURCE_IO)
+ release_region(start, length);
+ else
+ release_mem_region(start, length);
+}
+
+
+#ifdef SUPPORT_ADF_PDP_FBDEV
+static u32 pdp_format_bpp(u32 drm_format)
+{
+ int i;
+ for (i = 0; pdp_format_table[i].drm_format != 0; i++) {
+ if (pdp_format_table[i].drm_format == drm_format)
+ return pdp_format_table[i].bytes_per_pixel;
+ }
+ WARN(1, "Unsupported drm format");
+ return 0;
+}
+#endif /* SUPPORT_ADF_PDP_FBDDEV */
+
+static u32 pdp_format(u32 drm_format)
+{
+ int i;
+ for (i = 0; pdp_format_table[i].drm_format != 0; i++) {
+ if (pdp_format_table[i].drm_format == drm_format)
+ return pdp_format_table[i].pixfmt_word;
+ }
+ WARN(1, "Unsupported drm format");
+ return 0;
+}
+
+static void pdp_enable_scanout(struct adf_pdp_device *pdp)
+{
+ u32 reg_value;
+ /* Turn on scanout */
+ reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_STR1ADDRCTRL);
+ reg_value &= ~(STR1STREN_MASK);
+ reg_value |= 0x1 << STR1STREN_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_STR1ADDRCTRL, reg_value);
+}
+
+static void pdp_disable_scanout(struct adf_pdp_device *pdp)
+{
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_STR1ADDRCTRL, 0);
+}
+
+static bool pdp_vsync_triggered(struct adf_pdp_device *pdp)
+{
+ return atomic_read(&pdp->vsync_triggered) == 1;
+}
+
+static void pdp_post(struct adf_device *adf_dev, struct adf_post *cfg,
+ void *driver_state)
+{
+ int num_validates_snapshot = *(int *)driver_state;
+ dma_addr_t buf_addr;
+ u32 reg_value = 0;
+
+ /* Set vsync wait timeout to 4x expected vsync */
+ struct adf_pdp_device *pdp = devres_find(adf_dev->dev,
+ pdp_devres_release, NULL, NULL);
+ long timeout =
+ msecs_to_jiffies((1000 / pdp->current_timings->v_refresh) * 4);
+
+ /* Null-flip handling, used to push buffers off screen during an error
+ * state to stop them blocking subsequent rendering */
+ if (cfg->n_bufs == 0) {
+ pdp_disable_scanout(pdp);
+ return;
+ }
+
+ WARN_ON(cfg->n_bufs != 1);
+ WARN_ON(cfg->mappings->sg_tables[0]->nents != 1);
+
+ buf_addr = sg_phys(cfg->mappings->sg_tables[0]->sgl);
+ /* Convert the cpu address to a device address */
+ buf_addr -= pdp->pdata->apollo_memory_base;
+
+ /* Set surface register w/height, width & format */
+ reg_value = (cfg->bufs[0].w-1) << STR1WIDTH_SHIFT;
+ reg_value |= (cfg->bufs[0].h-1) << STR1HEIGHT_SHIFT;
+ reg_value |= pdp_format(cfg->bufs[0].format) << STR1PIXFMT_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_STR1SURF, reg_value);
+
+ /* Set stride register */
+ reg_value = (cfg->bufs[0].pitch[0] >> DCPDP_STR1POSN_STRIDE_SHIFT)-1;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_PDP_STR1POSN, reg_value);
+
+ /* Set surface address without resetting any other bits in the
+ * register */
+ reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_STR1ADDRCTRL);
+ reg_value &= ~(STR1BASE_MASK);
+ reg_value |= (buf_addr >> DCPDP_STR1ADDRCTRL_BASE_ADDR_SHIFT)
+ & STR1BASE_MASK;
+
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_STR1ADDRCTRL, reg_value);
+ pdp_enable_scanout(pdp);
+ atomic_set(&pdp->vsync_triggered, 0);
+
+ pdp->num_posts = num_validates_snapshot;
+
+ /* Wait until the buffer is on-screen, so we know the previous buffer
+ * has been retired and off-screen.
+ *
+ * If vsync was already off when this post was serviced, we don't need
+ * to wait for it (note: this will cause tearing if done when the
+ * display is not blanked).
+ */
+ if (atomic_read(&pdp->vsync_state)) {
+ if (wait_event_timeout(pdp->vsync_wait_queue,
+ pdp_vsync_triggered(pdp), timeout) == 0) {
+ /* Timeout - continue as if vsync was triggered, as
+ * possible tearing is better than wedging */
+ dev_err(&pdp->pdev->dev, "Post VSync wait timeout");
+ }
+ }
+}
+
+static bool pdp_supports_event(struct adf_obj *obj, enum adf_event_type type)
+{
+ switch (obj->type) {
+ case ADF_OBJ_INTERFACE:
+ {
+ switch (type) {
+ case ADF_EVENT_VSYNC:
+ return true;
+ default:
+ return false;
+ }
+ }
+ default:
+ return false;
+ }
+}
+
+static void pdp_disable_vsync(struct adf_pdp_device *pdp)
+{
+ int err = 0;
+ u32 reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB);
+ reg_value &= ~(0x1 << INTEN_VBLNK1_SHIFT);
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB, reg_value);
+
+ err = apollo_disable_interrupt(&pdp->pdata->pdev->dev,
+ APOLLO_INTERRUPT_PDP);
+ if (err) {
+ dev_err(&pdp->pdev->dev,
+ "apollo_disable_interrupt failed (%d)\n", err);
+ }
+}
+
+static void pdp_irq_handler(void *data)
+{
+ struct adf_pdp_device *pdp = data;
+ u32 int_status = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTSTAT);
+
+ if (int_status & INTS_VBLNK1_MASK)
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTCLEAR,
+ (0x1 << INTCLR_VBLNK1_SHIFT));
+
+ /* If we're idle, and a vsync disable was requested, do it now.
+ * This code assumes that the HWC will always re-enable vsync
+ * explicitly before posting new configurations.
+ */
+ if (atomic_read(&pdp->num_validates) == pdp->num_posts) {
+ if (!atomic_read(&pdp->requested_vsync_state)) {
+ pdp_disable_vsync(pdp);
+ atomic_set(&pdp->vsync_state, 0);
+ }
+ }
+
+ if (int_status & INTS_VBLNK1_MASK) {
+ adf_vsync_notify(&pdp->adf_interface, ktime_get());
+ atomic_set(&pdp->vsync_triggered, 1);
+ wake_up(&pdp->vsync_wait_queue);
+ }
+}
+
+static void pdp_enable_vsync(struct adf_pdp_device *pdp)
+{
+ int err = 0;
+ u32 reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB);
+ reg_value |= (0x1 << INTEN_VBLNK1_SHIFT);
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_INTENAB, reg_value);
+
+ err = apollo_enable_interrupt(&pdp->pdata->pdev->dev,
+ APOLLO_INTERRUPT_PDP);
+ if (err) {
+ dev_err(&pdp->pdev->dev,
+ "apollo_enable_interrupt failed (%d)\n", err);
+ }
+}
+
+static void pdp_set_event(struct adf_obj *obj, enum adf_event_type type,
+ bool enabled)
+{
+ struct adf_pdp_device *pdp;
+ bool old;
+
+ switch (type) {
+ case ADF_EVENT_VSYNC:
+ {
+ pdp = devres_find(obj->parent->dev, pdp_devres_release,
+ NULL, NULL);
+ atomic_set(&pdp->requested_vsync_state, enabled);
+ if (enabled) {
+ old = atomic_xchg(&pdp->vsync_state, enabled);
+ if (!old)
+ pdp_enable_vsync(pdp);
+ }
+ break;
+ }
+ default:
+ BUG();
+ }
+}
+
+static void pdp_set_clocks(struct adf_pdp_device *pdp, u32 clock_freq_hz)
+{
+ u32 clock_freq_mhz = (clock_freq_hz + 500000) / 1000000;
+
+ pll_write_reg(pdp, TCF_PLL_PLL_PDP_CLK0, clock_freq_mhz);
+ if (clock_freq_mhz >= 50)
+ pll_write_reg(pdp, TCF_PLL_PLL_PDP_CLK1TO5, 0);
+ else
+ pll_write_reg(pdp, TCF_PLL_PLL_PDP_CLK1TO5, 0x3);
+
+ pll_write_reg(pdp, TCF_PLL_PLL_PDP_DRP_GO, 1);
+ udelay(1000);
+ pll_write_reg(pdp, TCF_PLL_PLL_PDP_DRP_GO, 0);
+}
+
+static int pdp_modeset(struct adf_interface *intf,
+ struct drm_mode_modeinfo *mode)
+{
+ u32 reg_value = 0;
+ int err = 0;
+ struct adf_pdp_device *pdp = devres_find(intf->base.parent->dev,
+ pdp_devres_release, NULL, NULL);
+ int mode_id = pdp_mode_id(pdp, mode->vdisplay, mode->hdisplay);
+ const struct pdp_timing_data *tdata = pdp_timing_data(pdp, mode_id);
+
+
+ if (!tdata) {
+ dev_err(&pdp->pdev->dev, "Failed to find mode for %ux%u\n",
+ mode->hdisplay, mode->vdisplay);
+ err = -ENXIO;
+ goto err_out;
+ }
+ /* Disable scanout */
+ pdp_disable_scanout(pdp);
+ /* Disable sync gen */
+ reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_SYNCCTRL);
+ reg_value &= ~(SYNCACTIVE_MASK);
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_SYNCCTRL, reg_value);
+
+ pdp_set_clocks(pdp, tdata->clock_freq);
+
+ if (pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_STRCTRL)
+ != 0x0000C010) {
+ /* Buffer request threshold */
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_STRCTRL,
+ 0x00001C10);
+ }
+
+ /* Border colour */
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_BORDCOL, 0x00005544);
+
+ /* Update control */
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_UPDCTRL, 0);
+
+ /* Set hsync */
+ reg_value = tdata->h_back_porch << HBPS_SHIFT;
+ reg_value |= tdata->h_total << HT_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_HSYNC1, reg_value);
+
+ reg_value = tdata->h_active_start << HAS_SHIFT;
+ reg_value |= tdata->h_left_border << HLBS_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_HSYNC2, reg_value);
+
+ reg_value = tdata->h_front_porch << HFPS_SHIFT;
+ reg_value |= tdata->h_right_border << HRBS_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_HSYNC3, reg_value);
+
+ /* Set vsync */
+ reg_value = tdata->v_back_porch << VBPS_SHIFT;
+ reg_value |= tdata->v_total << VT_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_VSYNC1, reg_value);
+
+ reg_value = tdata->v_active_start << VAS_SHIFT;
+ reg_value |= tdata->v_top_border << VTBS_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_VSYNC2, reg_value);
+
+ reg_value = tdata->v_front_porch << VFPS_SHIFT;
+ reg_value |= tdata->v_bottom_border << VBBS_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_VSYNC3, reg_value);
+
+ /* Horizontal data enable */
+ reg_value = tdata->h_active_start << HDES_SHIFT;
+ reg_value |= tdata->h_front_porch << HDEF_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_HDECTRL, reg_value);
+
+ /* Vertical data enable */
+ reg_value = tdata->v_active_start << VDES_SHIFT;
+ reg_value |= tdata->v_front_porch << VDEF_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_VDECTRL, reg_value);
+
+ /* Vertical event start and vertical fetch start */
+ reg_value = tdata->v_back_porch << VFETCH_SHIFT;
+ reg_value |= tdata->v_front_porch << VEVENT_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_VEVENT, reg_value);
+
+ /* Enable sync gen last and set up polarities of sync/blank */
+ reg_value = 0x1 << SYNCACTIVE_SHIFT;
+ reg_value |= 0x1 << FIELDPOL_SHIFT;
+ reg_value |= 0x1 << BLNKPOL_SHIFT;
+ reg_value |= 0x1 << VSPOL_SHIFT;
+ reg_value |= 0x1 << HSPOL_SHIFT;
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_SYNCCTRL, reg_value);
+
+ intf->current_mode = *mode;
+ pdp->current_timings = tdata;
+
+err_out:
+ return err;
+}
+
+static int pdp_blank(struct adf_interface *intf,
+ u8 state)
+{
+ u32 reg_value;
+ struct adf_pdp_device *pdp = devres_find(intf->base.parent->dev,
+ pdp_devres_release, NULL, NULL);
+
+ if (state != DRM_MODE_DPMS_OFF &&
+ state != DRM_MODE_DPMS_ON)
+ return -EINVAL;
+
+ reg_value = pdp_read_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_SYNCCTRL);
+ switch (state) {
+ case DRM_MODE_DPMS_OFF:
+ reg_value |= 0x1 << POWERDN_SHIFT;
+ break;
+ case DRM_MODE_DPMS_ON:
+ reg_value &= ~(POWERDN_MASK);
+ break;
+ }
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_SYNCCTRL, reg_value);
+
+ return 0;
+}
+
+#ifdef SUPPORT_ADF_PDP_FBDEV
+
+static int pdp_alloc_simple_buffer(struct adf_interface *intf, u16 w, u16 h,
+ u32 format, struct dma_buf **dma_buf, u32 *offset, u32 *pitch)
+{
+ struct adf_pdp_device *pdp = devres_find(intf->base.parent->dev,
+ pdp_devres_release, NULL, NULL);
+ int err = 0;
+ u32 size = w * h * pdp_format_bpp(format);
+ struct ion_handle *hdl = ion_alloc(pdp->ion_client, size, 0,
+ (1 << pdp->pdata->ion_heap_id), 0);
+ if (IS_ERR(hdl)) {
+ err = PTR_ERR(hdl);
+ dev_err(&pdp->pdev->dev, "ion_alloc failed (%d)\n", err);
+ goto err_out;
+ }
+ *dma_buf = ion_share_dma_buf(pdp->ion_client, hdl);
+ if (IS_ERR(*dma_buf)) {
+ err = PTR_ERR(hdl);
+ dev_err(&pdp->pdev->dev,
+ "ion_share_dma_buf failed (%d)\n", err);
+ goto err_free_buffer;
+ }
+ *pitch = w * pdp_format_bpp(format);
+ *offset = 0;
+err_free_buffer:
+ ion_free(pdp->ion_client, hdl);
+err_out:
+ return err;
+}
+
+static int pdp_describe_simple_post(struct adf_interface *intf,
+ struct adf_buffer *fb, void *data, size_t *size)
+{
+ /* No data required for simple post? */
+ *size = 0;
+ return 0;
+}
+
+#endif /* SUPPORT_ADF_PDP_FBDEV */
+
+static int
+adf_pdp_open(struct adf_obj *obj, struct inode *inode, struct file *file)
+{
+ struct adf_device *dev =
+ (struct adf_device *)obj->parent;
+ struct adf_pdp_device *pdp = devres_find(dev->dev,
+ pdp_devres_release, NULL, NULL);
+ atomic_inc(&pdp->refcount);
+ return 0;
+}
+
+static void
+adf_pdp_release(struct adf_obj *obj, struct inode *inode, struct file *file)
+{
+ struct adf_device *dev =
+ (struct adf_device *)obj->parent;
+ struct adf_pdp_device *pdp = devres_find(dev->dev,
+ pdp_devres_release, NULL, NULL);
+ struct sync_fence *release_fence;
+
+ if (atomic_dec_return(&pdp->refcount))
+ return;
+
+ /* Make sure we have no outstanding posts waiting */
+ atomic_set(&pdp->vsync_triggered, 1);
+ wake_up_all(&pdp->vsync_wait_queue);
+ /* This special "null" flip works around a problem with ADF
+ * which leaves buffers pinned by the display engine even
+ * after all ADF clients have closed.
+ *
+ * The "null" flip is pipelined like any other. The user won't
+ * be able to unload this module until it has been posted.
+ */
+ release_fence = adf_device_post(dev, NULL, 0, NULL, 0, NULL, 0);
+ if (IS_ERR_OR_NULL(release_fence)) {
+ dev_err(dev->dev,
+ "Failed to queue null flip command (err=%d).\n",
+ (int)PTR_ERR(release_fence));
+ return;
+ }
+
+ sync_fence_put(release_fence);
+}
+
+static int pdp_validate(struct adf_device *dev, struct adf_post *cfg,
+ void **driver_state)
+{
+ struct adf_pdp_device *pdp = devres_find(dev->dev,
+ pdp_devres_release, NULL, NULL);
+ int err = adf_img_validate_simple(dev, cfg, driver_state);
+ if (err == 0 && cfg->mappings) {
+ /* We store a snapshot of num_validates in driver_state at the
+ * time validate was called, which will be passed to the post
+ * function. This snapshot is copied into (i.e. overwrites)
+ * num_posts, rather then simply incrementing num_posts, to
+ * handle cases e.g. during fence timeouts where validates
+ * are called without corresponding posts.
+ */
+ int *validates = kmalloc(sizeof(int), GFP_KERNEL);
+ *validates = atomic_inc_return(&pdp->num_validates);
+ *driver_state = validates;
+ } else {
+ *driver_state = NULL;
+ }
+ return err;
+}
+
+static void pdp_state_free(struct adf_device *dev, void *driver_state)
+{
+ kfree(driver_state);
+}
+
+static struct adf_device_ops adf_pdp_device_ops = {
+ .owner = THIS_MODULE,
+ .base = {
+ .open = adf_pdp_open,
+ .release = adf_pdp_release,
+ .ioctl = adf_img_ioctl,
+ },
+ .state_free = pdp_state_free,
+ .validate = pdp_validate,
+ .post = pdp_post,
+};
+
+static struct adf_interface_ops adf_pdp_interface_ops = {
+ .base = {
+ .supports_event = pdp_supports_event,
+ .set_event = pdp_set_event,
+ },
+ .modeset = pdp_modeset,
+ .blank = pdp_blank,
+#ifdef SUPPORT_ADF_PDP_FBDEV
+ .alloc_simple_buffer = pdp_alloc_simple_buffer,
+ .describe_simple_post = pdp_describe_simple_post,
+#endif
+};
+
+static struct adf_overlay_engine_ops adf_pdp_overlay_ops = {
+ .supported_formats = &pdp_supported_formats[0],
+ .n_supported_formats = NUM_SUPPORTED_FORMATS,
+};
+
+#ifdef SUPPORT_ADF_PDP_FBDEV
+static struct fb_ops adf_pdp_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = adf_fbdev_open,
+ .fb_release = adf_fbdev_release,
+ .fb_check_var = adf_fbdev_check_var,
+ .fb_set_par = adf_fbdev_set_par,
+ .fb_blank = adf_fbdev_blank,
+ .fb_pan_display = adf_fbdev_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_mmap = adf_fbdev_mmap,
+};
+#endif
+
+static int adf_pdp_probe_device(struct platform_device *pdev)
+{
+ struct adf_pdp_device *pdp;
+ int err = 0;
+ int i, default_mode_id;
+ struct apollo_pdp_platform_data *pdata = pdev->dev.platform_data;
+ pdp = devres_alloc(pdp_devres_release, sizeof(struct adf_pdp_device),
+ GFP_KERNEL);
+ if (!pdp) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ devres_add(&pdev->dev, pdp);
+
+ pdp->pdata = pdata;
+ pdp->pdev = pdev;
+
+ err = pci_enable_device(pdata->pdev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to enable PDP pci device (%d)\n", err);
+ goto err_out;
+ }
+
+ atomic_set(&pdp->refcount, 0);
+ atomic_set(&pdp->num_validates, 0);
+ pdp->num_posts = 0;
+
+ pdp->ion_client = ion_client_create(pdata->ion_device, "adf_pdp");
+ if (IS_ERR(pdp->ion_client)) {
+ err = PTR_ERR(pdp->ion_client);
+ dev_err(&pdev->dev,
+ "Failed to create PDP ION client (%d)\n", err);
+ goto err_disable_pci;
+ }
+
+ err = request_pci_io_addr(pdata->pdev, DCPDP_REG_PCI_BASENUM,
+ DCPDP_PCI_PDP_REG_OFFSET, DCPDP_PCI_PDP_REG_SIZE);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to request PDP registers (%d)\n", err);
+ goto err_destroy_ion_client;
+ }
+
+ pdp->regs_size = DCPDP_PCI_PDP_REG_SIZE;
+ pdp->regs_start =
+ pci_resource_start(pdata->pdev, DCPDP_REG_PCI_BASENUM)
+ + DCPDP_PCI_PDP_REG_OFFSET;
+
+ pdp->regs = ioremap_nocache(pdp->regs_start, pdp->regs_size);
+ if (!pdp->regs) {
+ dev_err(&pdev->dev, "Failed to map PDP registers\n");
+ err = -EIO;
+ goto err_release_registers;
+ }
+
+ err = request_pci_io_addr(pdata->pdev, DCPDP_REG_PCI_BASENUM,
+ DCPDP_PCI_PLL_REG_OFFSET, DCPDP_PCI_PLL_REG_SIZE);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to request PLL registers (%d)\n", err);
+ goto err_unmap_registers;
+ }
+ pdp->pll_regs_size = DCPDP_PCI_PLL_REG_SIZE;
+ pdp->pll_regs_start =
+ pci_resource_start(pdata->pdev, DCPDP_REG_PCI_BASENUM)
+ + DCPDP_PCI_PLL_REG_OFFSET;
+
+ pdp->pll_regs = ioremap_nocache(pdp->pll_regs_start,
+ pdp->pll_regs_size);
+ if (!pdp->pll_regs) {
+ dev_err(&pdev->dev, "Failed to map PLL registers\n");
+ err = -EIO;
+ goto err_release_pll_registers;
+ }
+
+ err = adf_device_init(&pdp->adf_device, &pdp->pdev->dev,
+ &adf_pdp_device_ops, "pdp_device");
+ if (err) {
+ dev_err(&pdev->dev, "Failed to init ADF device (%d)\n", err);
+ goto err_unmap_pll_registers;
+ }
+
+ err = adf_interface_init(&pdp->adf_interface, &pdp->adf_device,
+ ADF_INTF_DVI, 0, ADF_INTF_FLAG_PRIMARY, &adf_pdp_interface_ops,
+ "pdp_interface");
+ if (err) {
+ dev_err(&pdev->dev, "Failed to init ADF interface (%d)\n", err);
+ goto err_destroy_adf_device;
+ }
+
+ err = adf_overlay_engine_init(&pdp->adf_overlay, &pdp->adf_device,
+ &adf_pdp_overlay_ops, "pdp_overlay");
+ if (err) {
+ dev_err(&pdev->dev, "Failed to init ADF overlay (%d)\n", err);
+ goto err_destroy_adf_interface;
+ }
+
+ err = adf_attachment_allow(&pdp->adf_device, &pdp->adf_overlay,
+ &pdp->adf_interface);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to attach overlay (%d)\n", err);
+ goto err_destroy_adf_overlay;
+ }
+
+ pdp->num_supported_modes = pdp_mode_count(pdp);
+ pdp->supported_modes = kzalloc(sizeof(struct drm_mode_modeinfo)
+ * pdp->num_supported_modes, GFP_KERNEL);
+
+ if (!pdp->supported_modes) {
+ dev_err(&pdev->dev, "Failed to allocate supported modeinfo structs\n");
+ err = -ENOMEM;
+ goto err_destroy_adf_overlay;
+ }
+
+ for (i = 0; i < pdp->num_supported_modes; i++)
+ pdp_mode_to_drm_mode(pdp, i, &pdp->supported_modes[i]);
+
+ default_mode_id = pdp_mode_id(pdp, pdp_display_height,
+ pdp_display_width);
+ if (default_mode_id == -1) {
+ default_mode_id = 0;
+ dev_err(&pdev->dev, "No modeline found for requested display size (%dx%d)\n",
+ pdp_display_width, pdp_display_height);
+ }
+
+ /* Initial modeset... */
+ err = pdp_modeset(&pdp->adf_interface,
+ &pdp->supported_modes[default_mode_id]);
+ if (err) {
+ dev_err(&pdev->dev, "Initial modeset failed (%d)\n", err);
+ goto err_destroy_modelist;
+ }
+
+ err = adf_hotplug_notify_connected(&pdp->adf_interface,
+ pdp->supported_modes, pdp->num_supported_modes);
+ if (err) {
+ dev_err(&pdev->dev, "Initial hotplug notify failed (%d)\n",
+ err);
+ goto err_destroy_modelist;
+ }
+ err = apollo_set_interrupt_handler(&pdp->pdata->pdev->dev,
+ APOLLO_INTERRUPT_PDP,
+ pdp_irq_handler, pdp);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to set interrupt handler (%d)\n",
+ err);
+ goto err_destroy_modelist;
+ }
+#ifdef SUPPORT_ADF_PDP_FBDEV
+ err = adf_fbdev_init(&pdp->adf_fbdev, &pdp->adf_interface,
+ &pdp->adf_overlay, pdp_display_width,
+ pdp_display_height, DRM_FORMAT_BGRA8888,
+ &adf_pdp_fb_ops, "adf_pdp_fb");
+ if (err) {
+ dev_err(&pdev->dev, "Failed to init ADF fbdev (%d)\n", err);
+ goto err_destroy_modelist;
+ }
+#endif
+
+ init_waitqueue_head(&pdp->vsync_wait_queue);
+ atomic_set(&pdp->requested_vsync_state, 0);
+ atomic_set(&pdp->vsync_state, 0);
+
+ return err;
+err_destroy_modelist:
+ kfree(pdp->supported_modes);
+err_destroy_adf_overlay:
+ adf_overlay_engine_destroy(&pdp->adf_overlay);
+err_destroy_adf_interface:
+ adf_interface_destroy(&pdp->adf_interface);
+err_destroy_adf_device:
+ adf_device_destroy(&pdp->adf_device);
+err_unmap_pll_registers:
+ iounmap(pdp->pll_regs);
+err_release_pll_registers:
+ release_pci_io_addr(pdp->pdata->pdev, DCPDP_REG_PCI_BASENUM,
+ pdp->pll_regs_start, pdp->pll_regs_size);
+err_unmap_registers:
+ iounmap(pdp->regs);
+err_release_registers:
+ release_pci_io_addr(pdp->pdata->pdev, DCPDP_REG_PCI_BASENUM,
+ pdp->regs_start, pdp->regs_size);
+err_destroy_ion_client:
+ ion_client_destroy(pdp->ion_client);
+err_disable_pci:
+ pci_disable_device(pdata->pdev);
+err_out:
+ dev_err(&pdev->dev, "Failed to initialise PDP device\n");
+ return err;
+}
+
+static int adf_pdp_remove_device(struct platform_device *pdev)
+{
+ int err = 0;
+ struct adf_pdp_device *pdp = devres_find(&pdev->dev, pdp_devres_release,
+ NULL, NULL);
+
+ pdp_disable_scanout(pdp);
+
+ pdp_disable_vsync(pdp);
+ apollo_set_interrupt_handler(&pdp->pdata->pdev->dev,
+ APOLLO_INTERRUPT_PDP,
+ NULL, NULL);
+ /* Disable scanout */
+ pdp_write_reg(pdp, TCF_RGBPDP_PVR_TCF_RGBPDP_STR1ADDRCTRL, 0);
+ kfree(pdp->supported_modes);
+#ifdef SUPPORT_ADF_PDP_FBDEV
+ adf_fbdev_destroy(&pdp->adf_fbdev);
+#endif
+ adf_overlay_engine_destroy(&pdp->adf_overlay);
+ adf_interface_destroy(&pdp->adf_interface);
+ adf_device_destroy(&pdp->adf_device);
+ iounmap(pdp->pll_regs);
+ release_pci_io_addr(pdp->pdata->pdev, DCPDP_REG_PCI_BASENUM,
+ pdp->pll_regs_start, pdp->pll_regs_size);
+ iounmap(pdp->regs);
+ release_pci_io_addr(pdp->pdata->pdev, DCPDP_REG_PCI_BASENUM,
+ pdp->regs_start, pdp->regs_size);
+ ion_client_destroy(pdp->ion_client);
+ pci_disable_device(pdp->pdata->pdev);
+ return err;
+}
+
+static void adf_pdp_shutdown_device(struct platform_device *pdev)
+{
+ /* No cleanup needed, all done in remove_device */
+}
+
+static struct platform_device_id pdp_platform_device_id_table[] = {
+ { .name = APOLLO_DEVICE_NAME_PDP, .driver_data = 0 },
+ { },
+};
+
+static struct platform_driver pdp_platform_driver = {
+ .probe = adf_pdp_probe_device,
+ .remove = adf_pdp_remove_device,
+ .shutdown = adf_pdp_shutdown_device,
+ .driver = {
+ .name = DRV_NAME,
+ },
+ .id_table = pdp_platform_device_id_table,
+};
+
+static int __init adf_pdp_init(void)
+{
+ return platform_driver_register(&pdp_platform_driver);
+}
+
+static void __exit adf_pdp_exit(void)
+{
+ platform_driver_unregister(&pdp_platform_driver);
+}
+
+module_init(adf_pdp_init);
+module_exit(adf_pdp_exit);
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/apollo.c b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/apollo.c
new file mode 100644
index 000000000000..79429d411044
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/apollo.c
@@ -0,0 +1,1440 @@
+/*************************************************************************/ /*!
+@File apollo.c
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+/*
+ * This is a device driver for the apollo testchip framework. It creates
+ * platform devices for the pdp and rogue sub-devices, and exports functions
+ * to manage the shared interrupt handling
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+
+#include <asm/mtrr.h>
+
+#include "apollo_drv.h"
+
+#include "apollo_regs.h"
+#include "tcf_clk_ctrl.h"
+#include "tcf_pll.h"
+
+#include "pvrmodule.h"
+#include "rgxdefs_km.h"
+
+#include "ion_lma_heap.h"
+
+#define DRV_NAME "apollo"
+
+/* How much memory to allocate to ION (used for pdp buffers). */
+#define APOLLO_PDP_MEM_SIZE (384*1024*1024)
+
+/* Apparently, the last 1mb of the apollo memory is broken somehow */
+#define APOLLO_MEM_PCI_BROKEN_BYTES (64*1024*1024)
+
+#define PCI_VENDOR_ID_POWERVR 0x1010
+#define DEVICE_ID_PCI_APOLLO_FPGA 0x1CF1
+#define DEVICE_ID_PCIE_APOLLO_FPGA 0x1CF2
+
+#define DCPDP_REG_PCI_BASENUM (0)
+#define APOLLO_MEM_PCI_BASENUM (2)
+
+#define APOLLO_INTERRUPT_FLAG_PDP (1 << PDP1_INT_SHIFT)
+#define APOLLO_INTERRUPT_FLAG_ROGUE (1 << EXT_INT_SHIFT)
+
+MODULE_DESCRIPTION("APOLLO testchip framework driver");
+
+static int apollo_core_clock = RGX_TC_CORE_CLOCK_SPEED;
+static int apollo_mem_clock = RGX_TC_MEM_CLOCK_SPEED;
+
+module_param(apollo_core_clock, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(apollo_core_clock, "Apollo Rogue core clock speed");
+module_param(apollo_mem_clock, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(apollo_mem_clock, "Apollo memory clock speed");
+
+#define APOLLO_ION_HEAP_COUNT 3
+
+struct apollo_device {
+ struct pci_dev *pdev;
+ resource_size_t tcf_register_resource;
+ void __iomem *tcf_registers;
+ spinlock_t interrupt_handler_lock;
+ spinlock_t interrupt_enable_lock;
+
+ struct {
+ bool enabled;
+ void (*handler_function)(void *);
+ void *handler_data;
+ } interrupt_handlers[APOLLO_INTERRUPT_COUNT];
+
+ struct platform_device *pdp_dev;
+ struct platform_device *rogue_dev;
+
+
+ resource_size_t apollo_mem_base;
+ resource_size_t apollo_mem_size;
+
+ resource_size_t pdp_heap_mem_base;
+ resource_size_t pdp_heap_mem_size;
+ resource_size_t rogue_heap_mem_base;
+ resource_size_t rogue_heap_mem_size;
+
+ struct ion_device *ion_device;
+ struct ion_heap *ion_heaps[APOLLO_ION_HEAP_COUNT];
+ int ion_heap_count;
+};
+
+static int request_pci_io_addr(struct pci_dev *dev, u32 index,
+ resource_size_t offset, resource_size_t length)
+{
+ resource_size_t start, end;
+ start = pci_resource_start(dev, index);
+ end = pci_resource_end(dev, index);
+
+ if ((start + offset + length - 1) > end)
+ return -EIO;
+ if (pci_resource_flags(dev, index) & IORESOURCE_IO) {
+ if (request_region(start + offset, length, DRV_NAME) == NULL)
+ return -EIO;
+ } else {
+ if (request_mem_region(start + offset, length, DRV_NAME)
+ == NULL)
+ return -EIO;
+ }
+ return 0;
+}
+
+static void release_pci_io_addr(struct pci_dev *dev, u32 index,
+ resource_size_t start, resource_size_t length)
+{
+ if (pci_resource_flags(dev, index) & IORESOURCE_IO)
+ release_region(start, length);
+ else
+ release_mem_region(start, length);
+}
+
+static int apollo_set_clocks(struct apollo_device *apollo)
+{
+ int err = 0;
+ u32 val;
+
+ resource_size_t pll_clock_resource;
+ void __iomem *pll_regs;
+
+ err = request_pci_io_addr(apollo->pdev, SYS_APOLLO_REG_PCI_BASENUM,
+ SYS_APOLLO_REG_PLL_OFFSET, SYS_APOLLO_REG_PLL_SIZE);
+ if (err) {
+ dev_err(&apollo->pdev->dev,
+ "Failed to request apollo PLL register region\n");
+ goto err_out;
+ }
+ pll_clock_resource =
+ pci_resource_start(apollo->pdev, SYS_APOLLO_REG_PCI_BASENUM)
+ + SYS_APOLLO_REG_PLL_OFFSET;
+ pll_regs = ioremap_nocache(pll_clock_resource, SYS_APOLLO_REG_PLL_SIZE);
+ if (!pll_regs) {
+ dev_err(&apollo->pdev->dev,
+ "Failed to map apollo PLL registers\n");
+ err = -EIO;
+ goto err_release_registers;
+ }
+
+ dev_dbg(&apollo->pdev->dev, "Setting clocks to %uMHz/%uMHz\n",
+ apollo_core_clock / 1000000,
+ apollo_mem_clock / 1000000);
+
+#if !((RGX_BVNC_KM_B == 1) && (RGX_BVNC_KM_V == 82) && \
+ (RGX_BVNC_KM_N == 4) && (RGX_BVNC_KM_C == 5))
+ /* This is if 0 out since the current FPGA builds do not like their core
+ * clocks being set (it takes apollo down). */
+ val = apollo_core_clock / 1000000;
+ iowrite32(val, pll_regs + TCF_PLL_PLL_CORE_CLK0);
+ val = 0x1 << PLL_CORE_DRP_GO_SHIFT;
+ iowrite32(val, pll_regs + TCF_PLL_PLL_CORE_DRP_GO);
+#endif
+
+ val = apollo_mem_clock / 1000000;
+ iowrite32(val, pll_regs + TCF_PLL_PLL_MEMIF_CLK0);
+ val = 0x1 << PLL_MEM_DRP_GO_SHIFT;
+ iowrite32(val, pll_regs + TCF_PLL_PLL_MEM_DRP_GO);
+
+ iounmap(pll_regs);
+err_release_registers:
+ release_pci_io_addr(apollo->pdev, SYS_APOLLO_REG_PCI_BASENUM,
+ pll_clock_resource, SYS_APOLLO_REG_PLL_SIZE);
+err_out:
+ return err;
+}
+
+static int apollo_init_mtrr(struct apollo_device *apollo)
+{
+ int err = 0;
+ int mtrr;
+ resource_size_t mem_start, mem_end, mem_size;
+
+ /* Reset MTRR */
+ mem_start = pci_resource_start(apollo->pdev, APOLLO_MEM_PCI_BASENUM);
+ mem_end = pci_resource_end(apollo->pdev, APOLLO_MEM_PCI_BASENUM);
+
+ mem_size = mem_end - mem_start + 1;
+
+ mtrr = mtrr_add(mem_start, mem_size, MTRR_TYPE_UNCACHABLE, 0);
+ if (mtrr < 0) {
+ dev_err(&apollo->pdev->dev, "%d - %s: mtrr_add failed (%d)\n",
+ __LINE__, __func__, mtrr);
+ err = mtrr;
+ goto err_out;
+ }
+
+ err = mtrr_del(mtrr, mem_start, mem_size);
+ if (err < 0) {
+ dev_err(&apollo->pdev->dev, "%d - %s: mtrr_del failed (%d)\n",
+ __LINE__, __func__, err);
+ goto err_out;
+ }
+
+ mtrr = mtrr_add(mem_start, mem_size, MTRR_TYPE_WRBACK, 0);
+ if (mtrr < 0) {
+ /* Stop, but not an error as this may be already be setup */
+ dev_dbg(&apollo->pdev->dev, "%d - %s: mtrr_del failed (%d) - probably means the mtrr is already setup\n",
+ __LINE__, __func__, err);
+ err = 0;
+ goto err_out;
+ }
+
+ err = mtrr_del(mtrr, mem_start, mem_size);
+ if (err < 0) {
+ dev_err(&apollo->pdev->dev, "%d - %s: mtrr_del failed (%d)\n",
+ __LINE__, __func__, err);
+ goto err_out;
+ }
+
+ if (mtrr == 0) {
+ /* Replace 0 with a non-overlapping WRBACK mtrr */
+ err = mtrr_add(0, mem_start, MTRR_TYPE_WRBACK, 0);
+ if (err < 0) {
+ dev_err(&apollo->pdev->dev, "%d - %s: mtrr_add failed (%d)\n",
+ __LINE__, __func__, err);
+ goto err_out;
+ }
+ }
+
+ mtrr = mtrr_add(mem_start, mem_size, MTRR_TYPE_WRCOMB, 0);
+
+ if (mtrr < 0)
+ dev_err(&apollo->pdev->dev, "%d - %s: mtrr_add failed (%d)\n",
+ __LINE__, __func__, mtrr);
+ err = 0;
+
+err_out:
+ return err;
+}
+
+static int apollo_init_memory(struct apollo_device *apollo)
+{
+ int err = 0;
+ u32 val = 0;
+
+ err = apollo_init_mtrr(apollo);
+ if (err)
+ goto err_out;
+
+ val = ioread32(apollo->tcf_registers + TCF_CLK_CTRL_TEST_CTRL);
+ val &= ~(ADDRESS_FORCE_MASK | PCI_TEST_MODE_MASK | HOST_ONLY_MODE_MASK
+ | HOST_PHY_MODE_MASK);
+ val |= (0x1 << ADDRESS_FORCE_SHIFT);
+ iowrite32(val, apollo->tcf_registers + TCF_CLK_CTRL_TEST_CTRL);
+
+ apollo->apollo_mem_base =
+ pci_resource_start(apollo->pdev, APOLLO_MEM_PCI_BASENUM);
+ apollo->apollo_mem_size =
+ pci_resource_len(apollo->pdev, APOLLO_MEM_PCI_BASENUM)
+ - APOLLO_MEM_PCI_BROKEN_BYTES;
+
+ /* Setup ranges for the ION heaps */
+
+ apollo->pdp_heap_mem_size = APOLLO_PDP_MEM_SIZE;
+ apollo->rogue_heap_mem_size = apollo->apollo_mem_size
+ - apollo->pdp_heap_mem_size;
+
+ apollo->rogue_heap_mem_base = apollo->apollo_mem_base;
+ apollo->pdp_heap_mem_base = apollo->apollo_mem_base +
+ apollo->rogue_heap_mem_size;
+err_out:
+ return err;
+}
+
+static void apollo_deinit_memory(struct apollo_device *apollo)
+{
+ iowrite32(0x1 << ADDRESS_FORCE_SHIFT,
+ apollo->tcf_registers + TCF_CLK_CTRL_TEST_CTRL);
+}
+
+static void apollo_devres_release(struct device *dev, void *res)
+{
+ /* No extra cleanup needed */
+}
+
+#if (RGX_BVNC_KM_B == 1) && (RGX_BVNC_KM_V == 82) && \
+ (RGX_BVNC_KM_N == 4) && (RGX_BVNC_KM_C == 5)
+
+static int is_interface_aligned(u32 eyes, u32 clk_taps, u32 train_ack)
+{
+ u32 max_eye_start = eyes >> 16;
+ u32 min_eye_end = eyes & 0xffff;
+
+ /* If either the training or training ack failed, we haven't aligned */
+ if (!(clk_taps & 0x10000) || !(train_ack & 0x100))
+ return 0;
+
+ /* If the max eye >= min eye it means the readings are nonsense */
+ if (max_eye_start >= min_eye_end)
+ return 0;
+
+ /* If we failed the ack pattern more than 4 times */
+ if (((train_ack & 0xf0) >> 4) > 4)
+ return 0;
+
+ /* If there is less than 7 taps (240ps @40ps/tap, this number should be
+ * lower for the fpga, since its taps are bigger We should really
+ * calculate the "7" based on the interface clock speed. */
+ if ((min_eye_end - max_eye_start) < 7)
+ return 0;
+
+ return 1;
+}
+
+static u32 sai_read(struct apollo_device *apollo, u32 addr)
+{
+ iowrite32(0x200 | addr, apollo->tcf_registers + 0x300);
+ iowrite32(0x1 | addr, apollo->tcf_registers + 0x318);
+ return ioread32(apollo->tcf_registers + 0x310);
+}
+
+static void spi_write(struct apollo_device *apollo,
+ u32 off, u32 val)
+{
+ iowrite32(off, apollo->tcf_registers +
+ TCF_CLK_CTRL_TCF_SPI_MST_ADDR_RDNWR);
+ iowrite32(val, apollo->tcf_registers +
+ TCF_CLK_CTRL_TCF_SPI_MST_WDATA);
+ iowrite32(TCF_SPI_MST_GO_MASK, apollo->tcf_registers +
+ TCF_CLK_CTRL_TCF_SPI_MST_GO);
+ udelay(1000);
+}
+
+static int spi_read(struct apollo_device *apollo,
+ u32 off, u32 *val)
+{
+ int cnt = 0;
+
+ iowrite32(0x40000 | off, apollo->tcf_registers +
+ TCF_CLK_CTRL_TCF_SPI_MST_ADDR_RDNWR);
+ iowrite32(TCF_SPI_MST_GO_MASK, apollo->tcf_registers +
+ TCF_CLK_CTRL_TCF_SPI_MST_GO);
+ udelay(100);
+
+ while ((ioread32(apollo->tcf_registers +
+ TCF_CLK_CTRL_TCF_SPI_MST_STATUS) != 0x08) &&
+ (cnt < 10000))
+ ++cnt;
+
+ if (cnt == 10000) {
+ dev_err(&apollo->pdev->dev,
+ "spi_read: Time out reading SPI register (0x%x)\n",
+ off);
+ return -1;
+ }
+
+ *val = ioread32(apollo->tcf_registers + TCF_CLK_CTRL_TCF_SPI_MST_RDATA);
+
+ return 0;
+}
+
+static int apollo_hard_reset(struct apollo_device *apollo)
+{
+ u32 reg;
+ u32 reg_reset_n;
+
+ /* For displaying some build info */
+ u32 build_inc;
+ u32 build_owner;
+
+ int aligned = 0;
+ int reset_cnt = 0;
+
+ /* This is required for SPI reset which is not yet implemented. */
+ /*u32 aux_reset_n;*/
+
+ /* Power down */
+ reg = ioread32(apollo->tcf_registers + TCF_CLK_CTRL_DUT_CONTROL_1);
+ reg &= ~DUT_CTRL_VCC_0V9EN;
+ reg &= ~DUT_CTRL_VCC_1V8EN;
+ reg |= DUT_CTRL_VCC_IO_INH;
+ reg |= DUT_CTRL_VCC_CORE_INH;
+ iowrite32(reg, apollo->tcf_registers + TCF_CLK_CTRL_DUT_CONTROL_1);
+ msleep(500);
+
+ /* Set clock speed here, before reset. */
+ apollo_set_clocks(apollo);
+
+ /* Put DCM, DUT, DDR, PDP1, and PDP2 into reset */
+ reg_reset_n = (0x1 << GLB_CLKG_EN_SHIFT);
+ reg_reset_n |= (0x1 << SCB_RESETN_SHIFT);
+ iowrite32(reg_reset_n, apollo->tcf_registers +
+ TCF_CLK_CTRL_CLK_AND_RST_CTRL);
+ msleep(100);
+
+ /* Enable the voltage control regulators on DUT */
+ reg = ioread32(apollo->tcf_registers + TCF_CLK_CTRL_DUT_CONTROL_1);
+ reg |= DUT_CTRL_VCC_0V9EN;
+ reg |= DUT_CTRL_VCC_1V8EN;
+ reg &= ~DUT_CTRL_VCC_IO_INH;
+ reg &= ~DUT_CTRL_VCC_CORE_INH;
+ iowrite32(reg, apollo->tcf_registers + TCF_CLK_CTRL_DUT_CONTROL_1);
+ msleep(300);
+
+ /* Take DCM, DDR, PDP1, and PDP2 out of reset */
+ reg_reset_n |= (0x1 << DDR_RESETN_SHIFT);
+ reg_reset_n |= (0x1 << DUT_DCM_RESETN_SHIFT);
+ reg_reset_n |= (0x1 << PDP1_RESETN_SHIFT);
+ reg_reset_n |= (0x1 << PDP2_RESETN_SHIFT);
+ iowrite32(reg_reset_n, apollo->tcf_registers +
+ TCF_CLK_CTRL_CLK_AND_RST_CTRL);
+
+ /* Set ODT to a specific value that seems to provide the most stable
+ * signals. */
+ spi_write(apollo, 0x11, 0x413130);
+
+ /* Take DUT out of reset */
+ reg_reset_n |= (0x1 << DUT_RESETN_SHIFT);
+ iowrite32(reg_reset_n, apollo->tcf_registers +
+ TCF_CLK_CTRL_CLK_AND_RST_CTRL);
+ msleep(100);
+
+ /* Try to enable the core clock PLL */
+ spi_write(apollo, 0x1, 0x0);
+ reg = ioread32(apollo->tcf_registers + 0x320);
+ reg |= 0x1;
+ iowrite32(reg, apollo->tcf_registers + 0x320);
+ reg &= 0xfffffffe;
+ iowrite32(reg, apollo->tcf_registers + 0x320);
+ msleep(1000);
+
+ if (spi_read(apollo, 0x2, &reg))
+ dev_err(&apollo->pdev->dev,
+ "Unable to read PLL status\n");
+
+ if (reg == 0x1) {
+ /* Select DUT PLL as core clock */
+ reg = ioread32(apollo->tcf_registers + 0x108);
+ reg &= 0xfffffff7;
+ iowrite32(reg, apollo->tcf_registers + 0x108);
+ } else {
+ dev_err(&apollo->pdev->dev,
+ "PLL has failed to lock, status = %x\n", reg);
+ }
+
+ while (!aligned && reset_cnt < 10) {
+ int bank;
+ u32 eyes;
+ u32 clk_taps;
+ u32 train_ack;
+
+ ++reset_cnt;
+
+ /* Reset the DUT to allow the SAI to retrain */
+ reg_reset_n &= ~(0x1 << DUT_RESETN_SHIFT);
+ iowrite32(reg_reset_n, apollo->tcf_registers +
+ TCF_CLK_CTRL_CLK_AND_RST_CTRL);
+ udelay(100);
+ reg_reset_n |= (0x1 << DUT_RESETN_SHIFT);
+ iowrite32(reg_reset_n, apollo->tcf_registers +
+ TCF_CLK_CTRL_CLK_AND_RST_CTRL);
+ udelay(100);
+
+ /* Assume alignment passed, if any bank fails on either DUT or
+ * FPGA we will set this to false and try again for a max of 10
+ * times. */
+ aligned = 1;
+
+ /* For each of the banks */
+ for (bank = 0; bank < 10; bank++) {
+ /* Check alignment on the DUT */
+ u32 bank_base = 0x7000 + (0x1000 * bank);
+
+ spi_read(apollo, bank_base + 0x4, &eyes);
+ spi_read(apollo, bank_base + 0x3, &clk_taps);
+ spi_read(apollo, bank_base + 0x6, &train_ack);
+
+ if (!is_interface_aligned(eyes, clk_taps, train_ack)) {
+ dev_warn(&apollo->pdev->dev, "Alignment check failed, retrying\n");
+ aligned = 0;
+ break;
+ }
+
+ /* Check alignment on the FPGA */
+ bank_base = 0xb0 + (0x10 * bank);
+
+ eyes = sai_read(apollo, bank_base + 0x4);
+ clk_taps = sai_read(apollo, bank_base + 0x3);
+ train_ack = sai_read(apollo, bank_base + 0x6);
+
+ if (!is_interface_aligned(eyes, clk_taps, train_ack)) {
+ dev_warn(&apollo->pdev->dev, "Alignment check failed, retrying\n");
+ aligned = 0;
+ break;
+ }
+ }
+ }
+
+ if (!aligned) {
+ dev_err(&apollo->pdev->dev,
+ "Unable to intialise the testchip (interface alignment failure), "
+ "please restart the system.\n");
+ return -1;
+ }
+
+ if (reset_cnt > 1) {
+ dev_dbg(&apollo->pdev->dev, "Note: The testchip required more than one reset to find a good interface alignment!\n");
+ dev_dbg(&apollo->pdev->dev, " This should be harmless, but if you do suspect foul play, please reset the machine.\n");
+ dev_dbg(&apollo->pdev->dev, " If you continue to see this message you may want to report it to IMGWORKS.\n");
+ }
+
+ /* Enable the temperature sensor */
+ spi_write(apollo, 0xc, 0); /* power up */
+ spi_write(apollo, 0xc, 2); /* reset */
+ spi_write(apollo, 0xc, 6); /* init & run */
+
+ /* Check the build */
+ reg = ioread32(apollo->tcf_registers + 0x10);
+ build_inc = (reg >> 12) & 0xff;
+ build_owner = (reg >> 20) & 0xf;
+
+ if (build_inc) {
+ dev_alert(&apollo->pdev->dev, "BE WARNED: You are not running a tagged release of the FPGA image!\n");
+ dev_alert(&apollo->pdev->dev, "Owner: 0x%01x, Inc: 0x%02x\n",
+ build_owner, build_inc);
+ }
+
+ dev_dbg(&apollo->pdev->dev, "FPGA Release: %u.%02u\n", reg >> 8 & 0xf,
+ reg & 0xff);
+
+ return 0;
+}
+
+static int apollo_config(struct apollo_device *apollo)
+{
+ int err;
+
+ apollo_hard_reset(apollo);
+
+ err = apollo_init_memory(apollo);
+ if (err) {
+ dev_err(&apollo->pdev->dev, "Failed to init memory\n");
+ goto err_unmap_registers;
+ }
+
+ return err;
+
+err_unmap_registers:
+ iounmap(apollo->tcf_registers);
+ return err;
+}
+
+int apollo_sysinfo(struct device *dev, u32 *tmp, u32 *pll)
+{
+ int err = -ENODEV;
+ struct apollo_device *apollo = devres_find(dev, apollo_devres_release,
+ NULL, NULL);
+
+ if (!apollo) {
+ dev_err(dev, "No apollo device resources found\n");
+ goto err_out;
+ }
+
+ if (spi_read(apollo, TCF_TEMP_SENSOR_SPI_OFFSET, tmp)) {
+ dev_err(dev, "Failed to read apollo temperature sensor\n");
+ goto err_out;
+ }
+
+ *tmp = TCF_TEMP_SENSOR_TO_C(*tmp);
+
+ if (spi_read(apollo, 0x2, pll)) {
+ dev_err(dev, "Failed to read PLL status\n");
+ goto err_out;
+ }
+
+ err = 0;
+err_out:
+ return err;
+}
+EXPORT_SYMBOL(apollo_sysinfo);
+
+#else
+
+static int iopol32(u32 val, u32 mask, void __iomem *addr)
+{
+ int polnum;
+ for (polnum = 0; polnum < 500; polnum++) {
+ if ((ioread32(addr) & mask) == val)
+ break;
+ /* Apparently msleep() < 20 ms 'may' sleep up to 20ms, but that should
+ * be fine as sleeping longer should have no issues here */
+ msleep(1);
+ }
+ if (polnum == 500) {
+ pr_err(DRV_NAME " iopol32 timeout\n");
+ return -ETIME;
+ }
+ return 0;
+}
+
+
+static int apollo_rogue_bist(struct apollo_device *apollo)
+{
+ int err = 0;
+ void __iomem *rogue_regs;
+ resource_size_t regs_resource;
+ resource_size_t regs_resource_size;
+ int i;
+ int instance;
+
+ regs_resource =
+ pci_resource_start(apollo->pdev, SYS_RGX_REG_PCI_BASENUM);
+ regs_resource_size =
+ pci_resource_len(apollo->pdev, SYS_RGX_REG_PCI_BASENUM);
+
+ if (regs_resource_size < SYS_RGX_REG_REGION_SIZE) {
+ dev_err(&apollo->pdev->dev,
+ "Rogue register region too small\n");
+ err = -EIO;
+ goto err_out;
+ }
+
+ err = pci_request_region(apollo->pdev, SYS_RGX_REG_PCI_BASENUM,
+ DRV_NAME);
+ if (err) {
+ dev_err(&apollo->pdev->dev,
+ "Failed to request rogue register region\n");
+ goto err_out;
+ }
+ rogue_regs = ioremap_nocache(regs_resource, regs_resource_size);
+ if (!rogue_regs) {
+ dev_err(&apollo->pdev->dev,
+ "Failed to map rogue register region\n");
+ err = -EIO;
+ goto err_release_registers;
+ }
+ /* Force clocks on */
+ iowrite32(0x55555555, rogue_regs + 0);
+ iowrite32(0x55555555, rogue_regs + 4);
+
+ iopol32(0x05000000, 0x05000000, rogue_regs + 0xa18);
+ iowrite32(0x048000b0, rogue_regs + 0xa10);
+ iowrite32(0x55111111, rogue_regs + 0xa08);
+ iopol32(0x05000000, 0x05000000, rogue_regs + 0xa18);
+
+ /* Clear PDS CSRM and USRM to prevent ERRORs at end of test */
+ iowrite32(0x1, rogue_regs + 0x630);
+ iowrite32(0x1, rogue_regs + 0x648);
+ iowrite32(0x1, rogue_regs + 0x608);
+
+ /* Run BIST for SLC (43) */
+ /* Reset BIST */
+ iowrite32(0x8, rogue_regs + 0x7000);
+ udelay(100);
+
+ /* Clear BIST controller */
+ iowrite32(0x10, rogue_regs + 0x7000);
+ iowrite32(0, rogue_regs + 0x7000);
+ udelay(100);
+
+ for (i = 0; i < 3; i++) {
+ u32 polval = i == 2 ? 0x10000 : 0x20000;
+
+ /* Start BIST */
+ iowrite32(0x4, rogue_regs + 0x7000);
+
+ udelay(100);
+
+ /* Wait for pause */
+ iopol32(polval, polval, rogue_regs + 0x7000);
+ }
+ udelay(100);
+
+ /* Check results for 43 RAMs */
+ iopol32(0xffffffff, 0xffffffff, rogue_regs + 0x7010);
+ iopol32(0x7, 0x7, rogue_regs + 0x7014);
+
+ iowrite32(8, rogue_regs + 0x7000);
+ iowrite32(0, rogue_regs + 0x7008);
+ iowrite32(6, rogue_regs + 0x7000);
+ iopol32(0x00010000, 0x00010000, rogue_regs + 0x7000);
+ udelay(100);
+
+ iopol32(0, ~0U, rogue_regs + 0x75B0);
+ iopol32(0, ~0U, rogue_regs + 0x75B4);
+ iopol32(0, ~0U, rogue_regs + 0x75B8);
+ iopol32(0, ~0U, rogue_regs + 0x75BC);
+ iopol32(0, ~0U, rogue_regs + 0x75C0);
+ iopol32(0, ~0U, rogue_regs + 0x75C4);
+ iopol32(0, ~0U, rogue_regs + 0x75C8);
+ iopol32(0, ~0U, rogue_regs + 0x75CC);
+
+ /* Sidekick */
+ iowrite32(8, rogue_regs + 0x7040);
+ udelay(100);
+
+ iowrite32(0x10, rogue_regs + 0x7040);
+ udelay(100);
+
+ for (i = 0; i < 3; i++) {
+ u32 polval = i == 2 ? 0x10000 : 0x20000;
+
+ iowrite32(4, rogue_regs + 0x7040);
+ udelay(100);
+ iopol32(polval, polval, rogue_regs + 0x7040);
+ }
+
+ udelay(100);
+ iopol32(0xffffffff, 0xffffffff, rogue_regs + 0x7050);
+ iopol32(0xffffffff, 0xffffffff, rogue_regs + 0x7054);
+ iopol32(0x1, 0x1, rogue_regs + 0x7058);
+
+ /* USC */
+ for (instance = 0; instance < 4; instance++) {
+ iowrite32(instance, rogue_regs + 0x8010);
+
+ iowrite32(8, rogue_regs + 0x7088);
+ udelay(100);
+
+ iowrite32(0x10, rogue_regs + 0x7088);
+ udelay(100);
+
+ for (i = 0; i < 3; i++) {
+ u32 polval = i == 2 ? 0x10000 : 0x20000;
+
+ iowrite32(4, rogue_regs + 0x7088);
+ udelay(100);
+ iopol32(polval, polval, rogue_regs + 0x7088);
+ }
+
+ udelay(100);
+ iopol32(0xffffffff, 0xffffffff, rogue_regs + 0x7098);
+ iopol32(0xffffffff, 0xffffffff, rogue_regs + 0x709c);
+ iopol32(0x3f, 0x3f, rogue_regs + 0x70a0);
+ }
+
+ /* tpumcul0 DustA and DustB */
+ for (instance = 0; instance < 2; instance++) {
+ iowrite32(instance, rogue_regs + 0x8018);
+
+ iowrite32(8, rogue_regs + 0x7380);
+ udelay(100);
+
+ iowrite32(0x10, rogue_regs + 0x7380);
+ udelay(100);
+
+ for (i = 0; i < 3; i++) {
+ u32 polval = i == 2 ? 0x10000 : 0x20000;
+
+ iowrite32(4, rogue_regs + 0x7380);
+ udelay(100);
+ iopol32(polval, polval, rogue_regs + 0x7380);
+ }
+
+ udelay(100);
+ iopol32(0x1fff, 0x1fff, rogue_regs + 0x7390);
+ }
+
+ /* TA */
+ iowrite32(8, rogue_regs + 0x7500);
+ udelay(100);
+
+ iowrite32(0x10, rogue_regs + 0x7500);
+ udelay(100);
+
+ for (i = 0; i < 3; i++) {
+ u32 polval = i == 2 ? 0x10000 : 0x20000;
+
+ iowrite32(4, rogue_regs + 0x7500);
+ udelay(100);
+ iopol32(polval, polval, rogue_regs + 0x7500);
+ }
+
+ udelay(100);
+ iopol32(0x1fffffff, 0x1fffffff, rogue_regs + 0x7510);
+
+ /* Rasterisation */
+ iowrite32(8, rogue_regs + 0x7540);
+ udelay(100);
+
+ iowrite32(0x10, rogue_regs + 0x7540);
+ udelay(100);
+
+ for (i = 0; i < 3; i++) {
+ u32 polval = i == 2 ? 0x10000 : 0x20000;
+
+ iowrite32(4, rogue_regs + 0x7540);
+ udelay(100);
+ iopol32(polval, polval, rogue_regs + 0x7540);
+ }
+
+ udelay(100);
+ iopol32(0xffffffff, 0xffffffff, rogue_regs + 0x7550);
+ iopol32(0xffffffff, 0xffffffff, rogue_regs + 0x7554);
+ iopol32(0xf, 0xf, rogue_regs + 0x7558);
+
+ /* hub_bifpmache */
+ iowrite32(8, rogue_regs + 0x7588);
+ udelay(100);
+
+ iowrite32(0x10, rogue_regs + 0x7588);
+ udelay(100);
+
+ for (i = 0; i < 3; i++) {
+ u32 polval = i == 2 ? 0x10000 : 0x20000;
+
+ iowrite32(4, rogue_regs + 0x7588);
+ udelay(100);
+ iopol32(polval, polval, rogue_regs + 0x7588);
+ }
+
+ udelay(100);
+ iopol32(0xffffffff, 0xffffffff, rogue_regs + 0x7598);
+ iopol32(0xffffffff, 0xffffffff, rogue_regs + 0x759c);
+ iopol32(0x1111111f, 0x1111111f, rogue_regs + 0x75a0);
+
+ iounmap(rogue_regs);
+err_release_registers:
+ pci_release_region(apollo->pdev, SYS_RGX_REG_PCI_BASENUM);
+err_out:
+ return err;
+}
+
+static void apollo_hard_reset(struct apollo_device *apollo)
+{
+ u32 reg;
+
+ reg = (0x1 << GLB_CLKG_EN_SHIFT);
+ reg |= (0x1 << SCB_RESETN_SHIFT);
+ reg |= (0x1 << PDP2_RESETN_SHIFT);
+ reg |= (0x1 << PDP1_RESETN_SHIFT);
+ iowrite32(reg, apollo->tcf_registers + TCF_CLK_CTRL_CLK_AND_RST_CTRL);
+
+ reg |= (0x1 << DDR_RESETN_SHIFT);
+ iowrite32(reg, apollo->tcf_registers + TCF_CLK_CTRL_CLK_AND_RST_CTRL);
+
+ reg |= (0x1 << DUT_RESETN_SHIFT);
+ iowrite32(reg, apollo->tcf_registers + TCF_CLK_CTRL_CLK_AND_RST_CTRL);
+
+ reg |= (0x1 << DUT_DCM_RESETN_SHIFT);
+ iowrite32(reg, apollo->tcf_registers + TCF_CLK_CTRL_CLK_AND_RST_CTRL);
+
+ /* Apparently msleep() < 20 ms 'may' sleep up to 20ms, but that should
+ * be fine as sleeping longer should have no issues here */
+ msleep(4);
+ iopol32(0x7, DCM_LOCK_STATUS_MASK,
+ apollo->tcf_registers + TCF_CLK_CTRL_DCM_LOCK_STATUS);
+}
+
+static int apollo_set_rogue_pll(struct apollo_device *apollo)
+{
+ int err = 0;
+ /* Enable the rogue PLL (defaults to 3x), giving a Rogue clock of
+ * 3 x RGX_TC_CORE_CLOCK_SPEED */
+ u32 val = ioread32(apollo->tcf_registers + TCF_CLK_CTRL_DUT_CONTROL_1);
+ iowrite32(val & 0xFFFFFFFB,
+ apollo->tcf_registers + TCF_CLK_CTRL_DUT_CONTROL_1);
+
+ return err;
+}
+
+static int apollo_config(struct apollo_device *apollo)
+{
+ int err;
+
+ apollo_hard_reset(apollo);
+ err = apollo_rogue_bist(apollo);
+ if (err) {
+ dev_err(&apollo->pdev->dev, "Failed to run BIST on rogue\n");
+ goto err_unmap_registers;
+ }
+ apollo_hard_reset(apollo);
+
+ err = apollo_init_memory(apollo);
+ if (err) {
+ dev_err(&apollo->pdev->dev, "Failed to init memory\n");
+ goto err_unmap_registers;
+ }
+
+ err = apollo_set_clocks(apollo);
+ if (err) {
+ dev_err(&apollo->pdev->dev, "Failed to init clocks\n");
+ goto err_deinit_memory;
+ }
+
+ err = apollo_set_rogue_pll(apollo);
+ if (err) {
+ dev_err(&apollo->pdev->dev, "Failed to set rogue PLL\n");
+ goto err_deinit_memory;
+ }
+
+ return err;
+
+err_deinit_memory:
+ apollo_deinit_memory(apollo);
+err_unmap_registers:
+ iounmap(apollo->tcf_registers);
+ return err;
+}
+
+int apollo_sysinfo(struct device *dev, u32 *tmp, u32 *pll)
+{
+ /* Not implemented for TC1 */
+ return -1;
+}
+EXPORT_SYMBOL(apollo_sysinfo);
+
+#endif
+
+int apollo_core_clock_speed(struct device *dev)
+{
+ return apollo_core_clock;
+}
+EXPORT_SYMBOL(apollo_core_clock_speed);
+
+static irqreturn_t apollo_irq_handler(int irq, void *data)
+{
+ u32 interrupt_status;
+ u32 interrupt_clear = 0;
+ unsigned long flags;
+ irqreturn_t ret = IRQ_NONE;
+ struct apollo_device *apollo = (struct apollo_device *)data;
+
+ spin_lock_irqsave(&apollo->interrupt_handler_lock, flags);
+
+ interrupt_status = ioread32(apollo->tcf_registers
+ + TCF_CLK_CTRL_INTERRUPT_STATUS);
+
+ if (interrupt_status & APOLLO_INTERRUPT_FLAG_ROGUE) {
+ if (apollo->interrupt_handlers[APOLLO_INTERRUPT_ROGUE].enabled
+ && apollo->interrupt_handlers[APOLLO_INTERRUPT_ROGUE]
+ .handler_function) {
+ apollo->interrupt_handlers[APOLLO_INTERRUPT_ROGUE]
+ .handler_function(apollo->interrupt_handlers
+ [APOLLO_INTERRUPT_ROGUE].handler_data);
+ interrupt_clear |= APOLLO_INTERRUPT_FLAG_ROGUE;
+ }
+ ret = IRQ_HANDLED;
+ }
+ if (interrupt_status & APOLLO_INTERRUPT_FLAG_PDP) {
+ if (apollo->interrupt_handlers[APOLLO_INTERRUPT_PDP].enabled
+ && apollo->interrupt_handlers[APOLLO_INTERRUPT_PDP]
+ .handler_function) {
+ apollo->interrupt_handlers[APOLLO_INTERRUPT_PDP]
+ .handler_function(apollo->interrupt_handlers
+ [APOLLO_INTERRUPT_PDP].handler_data);
+ interrupt_clear |= APOLLO_INTERRUPT_FLAG_PDP;
+ }
+ ret = IRQ_HANDLED;
+ }
+
+ if (interrupt_clear)
+ iowrite32(0xffffffff,
+ apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_CLEAR);
+
+ spin_unlock_irqrestore(&apollo->interrupt_handler_lock, flags);
+
+ return ret;
+}
+
+static int apollo_enable_irq(struct apollo_device *apollo)
+{
+ int err = 0;
+ iowrite32(0, apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_ENABLE);
+ iowrite32(0xffffffff,
+ apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_CLEAR);
+ err = request_irq(apollo->pdev->irq, apollo_irq_handler, IRQF_SHARED,
+ DRV_NAME, apollo);
+ return err;
+}
+
+static void apollo_disable_irq(struct apollo_device *apollo)
+{
+ iowrite32(0, apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_ENABLE);
+ iowrite32(0xffffffff,
+ apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_CLEAR);
+ free_irq(apollo->pdev->irq, apollo);
+}
+
+static int register_pdp_device(struct apollo_device *apollo)
+{
+ int err = 0;
+ struct apollo_pdp_platform_data pdata = {
+ .pdev = apollo->pdev,
+ .ion_device = apollo->ion_device,
+ .ion_heap_id = ION_HEAP_APOLLO_PDP,
+ .apollo_memory_base = apollo->apollo_mem_base,
+ };
+ struct platform_device_info pdp_device_info = {
+ .parent = &apollo->pdev->dev,
+ .name = APOLLO_DEVICE_NAME_PDP,
+ .id = -1,
+ .res = NULL,
+ .num_res = 0,
+ .data = &pdata,
+ .size_data = sizeof(pdata),
+ .dma_mask = DMA_BIT_MASK(32),
+ };
+
+ apollo->pdp_dev = platform_device_register_full(&pdp_device_info);
+ if (IS_ERR(apollo->pdp_dev)) {
+ err = PTR_ERR(apollo->pdp_dev);
+ dev_err(&apollo->pdev->dev,
+ "Failed to register PDP device (%d)\n", err);
+ apollo->pdp_dev = NULL;
+ goto err;
+ }
+err:
+ return err;
+}
+
+static int register_rogue_device(struct apollo_device *apollo)
+{
+ int err = 0;
+ struct apollo_rogue_platform_data pdata = {
+ .pdev = apollo->pdev,
+ .ion_device = apollo->ion_device,
+ .ion_heap_id = ION_HEAP_APOLLO_ROGUE,
+ .apollo_memory_base = apollo->apollo_mem_base,
+ .pdp_heap_memory_base = apollo->pdp_heap_mem_base,
+ .pdp_heap_memory_size = apollo->pdp_heap_mem_size,
+ .rogue_heap_memory_base = apollo->rogue_heap_mem_base,
+ .rogue_heap_memory_size = apollo->rogue_heap_mem_size,
+ };
+ struct platform_device_info rogue_device_info = {
+ .parent = &apollo->pdev->dev,
+ .name = APOLLO_DEVICE_NAME_ROGUE,
+ .id = -1,
+ .res = NULL,
+ .num_res = 0,
+ .data = &pdata,
+ .size_data = sizeof(pdata),
+ .dma_mask = DMA_BIT_MASK(32),
+ };
+ apollo->rogue_dev = platform_device_register_full(&rogue_device_info);
+ if (IS_ERR(apollo->rogue_dev)) {
+ err = PTR_ERR(apollo->rogue_dev);
+ dev_err(&apollo->pdev->dev,
+ "Failed to register rogue device (%d)\n", err);
+ apollo->rogue_dev = NULL;
+ goto err;
+ }
+err:
+ return err;
+}
+
+static int apollo_ion_init(struct apollo_device *apollo)
+{
+ int i, err = 0;
+ struct ion_platform_heap ion_heap_data[APOLLO_ION_HEAP_COUNT] = {
+ {
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .id = ION_HEAP_TYPE_SYSTEM,
+ .name = "system",
+ },
+ {
+ .type = ION_HEAP_TYPE_CUSTOM,
+ .id = ION_HEAP_APOLLO_PDP,
+ .size = apollo->pdp_heap_mem_size,
+ .base = apollo->pdp_heap_mem_base,
+ .name = "apollo-pdp",
+ },
+ {
+ .type = ION_HEAP_TYPE_CUSTOM,
+ .id = ION_HEAP_APOLLO_ROGUE,
+ .size = apollo->rogue_heap_mem_size,
+ .base = apollo->rogue_heap_mem_base,
+ .name = "apollo-rogue",
+ }
+ };
+
+ apollo->ion_device = ion_device_create(NULL);
+ if (IS_ERR_OR_NULL(apollo->ion_device)) {
+ err = PTR_ERR(apollo->ion_device);
+ goto err_out;
+ }
+
+ err = request_pci_io_addr(apollo->pdev, APOLLO_MEM_PCI_BASENUM, 0,
+ apollo->apollo_mem_size);
+ if (err) {
+ dev_err(&apollo->pdev->dev,
+ "Failed to request APOLLO memory (%d)\n", err);
+ goto err_free_device;
+ }
+
+ apollo->ion_heaps[0] = ion_heap_create(&ion_heap_data[0]);
+ if (IS_ERR_OR_NULL(apollo->ion_heaps[0])) {
+ err = PTR_ERR(apollo->ion_heaps[0]);
+ apollo->ion_heaps[0] = NULL;
+ goto err_free_device;
+ }
+ ion_device_add_heap(apollo->ion_device, apollo->ion_heaps[0]);
+
+ for (i = 1; i < APOLLO_ION_HEAP_COUNT; i++) {
+ apollo->ion_heaps[i] = ion_lma_heap_create(&ion_heap_data[i]);
+ if (IS_ERR_OR_NULL(apollo->ion_heaps[i])) {
+ err = PTR_ERR(apollo->ion_heaps[i]);
+ apollo->ion_heaps[i] = NULL;
+ goto err_free_heaps;
+ }
+ ion_device_add_heap(apollo->ion_device, apollo->ion_heaps[i]);
+ }
+
+ return 0;
+
+err_free_heaps:
+ ion_heap_destroy(apollo->ion_heaps[0]);
+
+ for (i = 1; i < APOLLO_ION_HEAP_COUNT; i++) {
+ if (!apollo->ion_heaps[i])
+ break;
+ ion_lma_heap_destroy(apollo->ion_heaps[i]);
+ }
+
+ release_pci_io_addr(apollo->pdev, APOLLO_MEM_PCI_BASENUM,
+ apollo->apollo_mem_base, apollo->apollo_mem_size);
+err_free_device:
+ ion_device_destroy(apollo->ion_device);
+err_out:
+ /* If the ptr was NULL, it is possible that err is 0 in the err path */
+ if (err == 0)
+ err = -ENOMEM;
+ return err;
+}
+
+static void apollo_ion_deinit(struct apollo_device *apollo)
+{
+ int i = 0;
+ ion_device_destroy(apollo->ion_device);
+ ion_heap_destroy(apollo->ion_heaps[0]);
+ for (i = 1; i < APOLLO_ION_HEAP_COUNT; i++)
+ ion_lma_heap_destroy(apollo->ion_heaps[i]);
+ release_pci_io_addr(apollo->pdev, APOLLO_MEM_PCI_BASENUM,
+ apollo->apollo_mem_base, apollo->apollo_mem_size);
+}
+
+static int apollo_init(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct apollo_device *apollo;
+ int err = 0;
+ u32 val;
+
+ if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL))
+ return -ENOMEM;
+
+ apollo = devres_alloc(apollo_devres_release,
+ sizeof(struct apollo_device), GFP_KERNEL);
+ if (!apollo) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ devres_add(&pdev->dev, apollo);
+
+ apollo->pdev = pdev;
+ spin_lock_init(&apollo->interrupt_handler_lock);
+ spin_lock_init(&apollo->interrupt_enable_lock);
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "pci_enable_device returned %d\n", err);
+ goto err_out;
+ }
+
+ err = request_pci_io_addr(pdev, SYS_APOLLO_REG_PCI_BASENUM,
+ SYS_APOLLO_REG_SYS_OFFSET, SYS_APOLLO_REG_SYS_SIZE);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to request apollo registers (%d)\n", err);
+ goto err_disable_device;
+ }
+
+ apollo->tcf_register_resource =
+ pci_resource_start(pdev, SYS_APOLLO_REG_PCI_BASENUM)
+ + SYS_APOLLO_REG_SYS_OFFSET;
+
+ apollo->tcf_registers = ioremap_nocache(apollo->tcf_register_resource,
+ SYS_APOLLO_REG_SYS_SIZE);
+ if (!apollo->tcf_registers) {
+ dev_err(&pdev->dev, "Failed to map TCF registers\n");
+ err = -EIO;
+ goto err_release_registers;
+ }
+
+ err = apollo_config(apollo);
+ if (err)
+ goto err_release_registers;
+
+ err = apollo_enable_irq(apollo);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to initialise IRQ\n");
+ goto err_deinit_memory;
+ }
+
+ err = apollo_ion_init(apollo);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to initialise ION\n");
+ goto err_disable_irq;
+ }
+
+ /* Set sense to active high */
+ val = ioread32(apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_OP_CFG);
+ val &= ~(INT_SENSE_MASK);
+ iowrite32(val, apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_OP_CFG);
+
+ /* Register rogue and pdp platform devices
+ * Failures here aren't critical? */
+ register_pdp_device(apollo);
+ register_rogue_device(apollo);
+
+ devres_remove_group(&pdev->dev, NULL);
+
+ return err;
+err_disable_irq:
+ apollo_disable_irq(apollo);
+err_deinit_memory:
+ apollo_deinit_memory(apollo);
+ iounmap(apollo->tcf_registers);
+err_release_registers:
+ release_pci_io_addr(pdev, SYS_APOLLO_REG_PCI_BASENUM,
+ apollo->tcf_register_resource, SYS_APOLLO_REG_SYS_SIZE);
+err_disable_device:
+ pci_disable_device(pdev);
+err_out:
+ devres_release_group(&pdev->dev, NULL);
+ dev_err(&pdev->dev, "Failed to initialise apollo device\n");
+ return err;
+}
+
+static void apollo_exit(struct pci_dev *pdev)
+{
+ int i;
+ struct apollo_device *apollo = devres_find(&pdev->dev,
+ apollo_devres_release, NULL, NULL);
+
+ if (apollo->pdp_dev)
+ platform_device_unregister(apollo->pdp_dev);
+
+ if (apollo->rogue_dev)
+ platform_device_unregister(apollo->rogue_dev);
+
+ for (i = 0; i < APOLLO_INTERRUPT_COUNT; i++)
+ apollo_disable_interrupt(&pdev->dev, i);
+ apollo_disable_irq(apollo);
+ apollo_ion_deinit(apollo);
+ apollo_deinit_memory(apollo);
+ iounmap(apollo->tcf_registers);
+ release_pci_io_addr(pdev, SYS_APOLLO_REG_PCI_BASENUM,
+ apollo->tcf_register_resource, SYS_APOLLO_REG_SYS_SIZE);
+ pci_disable_device(pdev);
+}
+
+DEFINE_PCI_DEVICE_TABLE(apollo_pci_tbl) = {
+ { PCI_VDEVICE(POWERVR, 0x1CF1) },
+ { PCI_VDEVICE(POWERVR, 0x1CF2) },
+ { },
+};
+
+static struct pci_driver apollo_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = apollo_pci_tbl,
+ .probe = apollo_init,
+ .remove = apollo_exit,
+};
+
+module_pci_driver(apollo_pci_driver);
+
+MODULE_DEVICE_TABLE(pci, apollo_pci_tbl);
+
+static u32 apollo_interrupt_id_to_flag(int interrupt_id)
+{
+ switch (interrupt_id) {
+ case APOLLO_INTERRUPT_PDP:
+ return APOLLO_INTERRUPT_FLAG_PDP;
+ case APOLLO_INTERRUPT_ROGUE:
+ return APOLLO_INTERRUPT_FLAG_ROGUE;
+ default:
+ BUG();
+ }
+}
+
+static void apollo_enable_interrupt_register(struct apollo_device *apollo,
+ int interrupt_id)
+{
+ u32 val;
+ val = ioread32(apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_ENABLE);
+ val |= apollo_interrupt_id_to_flag(interrupt_id);
+ iowrite32(val, apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_ENABLE);
+
+}
+
+static void apollo_disable_interrupt_register(struct apollo_device *apollo,
+ int interrupt_id)
+{
+ u32 val;
+ val = ioread32(apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_ENABLE);
+ val &= ~(apollo_interrupt_id_to_flag(interrupt_id));
+ iowrite32(val, apollo->tcf_registers + TCF_CLK_CTRL_INTERRUPT_ENABLE);
+}
+
+int apollo_set_interrupt_handler(struct device *dev, int interrupt_id,
+ void (*handler_function)(void *), void *data)
+{
+ struct apollo_device *apollo = devres_find(dev, apollo_devres_release,
+ NULL, NULL);
+ int err = 0;
+ unsigned long flags;
+ if (!apollo) {
+ dev_err(dev, "No apollo device resources found\n");
+ err = -ENODEV;
+ goto err_out;
+ }
+
+ if (interrupt_id < 0 || interrupt_id >= APOLLO_INTERRUPT_COUNT) {
+ dev_err(dev, "Invalid interrupt ID (%d)\n", interrupt_id);
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ if (!handler_function) {
+ dev_err(dev, "Invalid handler function\n");
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ spin_lock_irqsave(&apollo->interrupt_handler_lock, flags);
+
+ apollo->interrupt_handlers[interrupt_id].handler_function =
+ handler_function;
+ apollo->interrupt_handlers[interrupt_id].handler_data = data;
+
+ spin_unlock_irqrestore(&apollo->interrupt_handler_lock, flags);
+
+err_out:
+ return err;
+}
+EXPORT_SYMBOL(apollo_set_interrupt_handler);
+
+int apollo_enable_interrupt(struct device *dev, int interrupt_id)
+{
+ struct apollo_device *apollo = devres_find(dev, apollo_devres_release,
+ NULL, NULL);
+ int err = 0;
+ unsigned long flags;
+ if (!apollo) {
+ dev_err(dev, "No apollo device resources found\n");
+ err = -ENODEV;
+ goto err_out;
+ }
+ if (interrupt_id < 0 || interrupt_id >= APOLLO_INTERRUPT_COUNT) {
+ dev_err(dev, "Invalid interrupt ID (%d)\n", interrupt_id);
+ err = -EINVAL;
+ goto err_out;
+ }
+ spin_lock_irqsave(&apollo->interrupt_enable_lock, flags);
+
+ if (apollo->interrupt_handlers[interrupt_id].enabled) {
+ dev_warn(dev, "Interrupt ID %d already enabled\n",
+ interrupt_id);
+ err = -EEXIST;
+ goto err_unlock;
+ }
+ apollo->interrupt_handlers[interrupt_id].enabled = true;
+
+ apollo_enable_interrupt_register(apollo, interrupt_id);
+
+err_unlock:
+ spin_unlock_irqrestore(&apollo->interrupt_enable_lock, flags);
+err_out:
+ return err;
+}
+EXPORT_SYMBOL(apollo_enable_interrupt);
+
+int apollo_disable_interrupt(struct device *dev, int interrupt_id)
+{
+ struct apollo_device *apollo = devres_find(dev, apollo_devres_release,
+ NULL, NULL);
+ int err = 0;
+ unsigned long flags;
+ if (!apollo) {
+ dev_err(dev, "No apollo device resources found\n");
+ err = -ENODEV;
+ goto err_out;
+ }
+ if (interrupt_id < 0 || interrupt_id >= APOLLO_INTERRUPT_COUNT) {
+ dev_err(dev, "Invalid interrupt ID (%d)\n", interrupt_id);
+ err = -EINVAL;
+ goto err_out;
+ }
+ spin_lock_irqsave(&apollo->interrupt_enable_lock, flags);
+
+ if (!apollo->interrupt_handlers[interrupt_id].enabled) {
+ dev_warn(dev, "Interrupt ID %d already disabled\n",
+ interrupt_id);
+ err = -EEXIST;
+ goto err_unlock;
+ }
+ apollo->interrupt_handlers[interrupt_id].enabled = false;
+
+ apollo_disable_interrupt_register(apollo, interrupt_id);
+
+err_unlock:
+ spin_unlock_irqrestore(&apollo->interrupt_enable_lock, flags);
+err_out:
+ return err;
+}
+EXPORT_SYMBOL(apollo_disable_interrupt);
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/apollo_drv.h b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/apollo_drv.h
new file mode 100644
index 000000000000..741e7bc47585
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/apollo_drv.h
@@ -0,0 +1,101 @@
+/*************************************************************************/ /*!
+@File apollo_drv.h
+@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 _APOLLO_DRV_H
+#define _APOLLO_DRV_H
+
+/*
+ * This contains the hooks for the apollo testchip driver, as used by the
+ * Rogue and PDP sub-devices, and the platform data passed to each of their
+ * drivers
+ */
+
+#include <linux/pci.h>
+#include <linux/device.h>
+
+#include PVR_ANDROID_ION_HEADER
+
+/* These heap defines must match buffer_generic.c */
+#define ION_HEAP_APOLLO_ROGUE (ION_HEAP_TYPE_CUSTOM+1)
+#define ION_HEAP_APOLLO_PDP (ION_HEAP_TYPE_CUSTOM+2)
+
+#define APOLLO_INTERRUPT_PDP 0
+#define APOLLO_INTERRUPT_ROGUE 1
+#define APOLLO_INTERRUPT_COUNT 2
+
+int apollo_enable_interrupt(struct device *dev, int interrupt_id);
+int apollo_disable_interrupt(struct device *dev, int interrupt_id);
+
+int apollo_set_interrupt_handler(struct device *dev, int interrupt_id, void (*handler_function)(void *), void *handler_data);
+
+int apollo_sysinfo(struct device *dev, u32 *tmp, u32 *pll);
+int apollo_core_clock_speed(struct device *dev);
+
+#define APOLLO_DEVICE_NAME_PDP "apollo_pdp"
+#define APOLLO_DEVICE_NAME_ROGUE "apollo_rogue"
+
+/* The following structs are initialised and passed down by the parent apollo
+ * driver to the respective sub-drivers */
+
+struct apollo_pdp_platform_data {
+ struct pci_dev *pdev;
+ struct ion_device *ion_device;
+ int ion_heap_id;
+ resource_size_t apollo_memory_base;
+};
+
+struct apollo_rogue_platform_data {
+ struct pci_dev *pdev;
+ struct ion_device *ion_device;
+ int ion_heap_id;
+
+ /* The base address of the testchip memory (CPU physical address) -
+ * used to convert from CPU-Physical to device-physical addresses */
+ resource_size_t apollo_memory_base;
+
+ /* The following is used to setup the services heaps that map to the
+ * ion heaps */
+ resource_size_t pdp_heap_memory_base;
+ resource_size_t pdp_heap_memory_size;
+ resource_size_t rogue_heap_memory_base;
+ resource_size_t rogue_heap_memory_size;
+};
+
+#endif /* _APOLLO_DRV_H */
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/ion_lma_heap.c b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/ion_lma_heap.c
new file mode 100644
index 000000000000..f86de4b4b89e
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/ion_lma_heap.c
@@ -0,0 +1,257 @@
+/*************************************************************************/ /*!
+@File ion_lma_heap.c
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+#include "ion_lma_heap.h"
+
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+#include <linux/scatterlist.h>
+
+/* Ion heap for LMA allocations. This heap is identical to CARVEOUT except
+ * that it does not do any CPU cache maintenance nor does it zero the memory
+ * using the CPU (this is handled with PVR_ANDROID_DEFER_CLEAR in userspace).
+ */
+
+struct ion_lma_heap {
+ struct ion_heap heap;
+ struct gen_pool *pool;
+ ion_phys_addr_t base;
+};
+
+static ion_phys_addr_t ion_lma_allocate(struct ion_heap *heap,
+ unsigned long size,
+ unsigned long align)
+{
+ struct ion_lma_heap *lma_heap =
+ container_of(heap, struct ion_lma_heap, heap);
+ unsigned long offset = gen_pool_alloc(lma_heap->pool, size);
+
+ if (!offset)
+ return ION_CARVEOUT_ALLOCATE_FAIL;
+
+ return offset;
+}
+
+static void ion_lma_free(struct ion_heap *heap, ion_phys_addr_t addr,
+ unsigned long size)
+{
+ struct ion_lma_heap *lma_heap =
+ container_of(heap, struct ion_lma_heap, heap);
+
+ if (addr == ION_CARVEOUT_ALLOCATE_FAIL)
+ return;
+
+ gen_pool_free(lma_heap->pool, addr, size);
+}
+
+static int ion_lma_heap_phys(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ ion_phys_addr_t *addr, size_t *len)
+{
+ struct sg_table *table = buffer->priv_virt;
+ struct page *page = sg_page(table->sgl);
+ ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
+
+ *addr = paddr;
+ *len = buffer->size;
+ return 0;
+}
+
+static int ion_lma_heap_allocate(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ unsigned long size, unsigned long align,
+ unsigned long flags)
+{
+ struct sg_table *table;
+ ion_phys_addr_t paddr;
+ int ret;
+
+ if (align > PAGE_SIZE)
+ return -EINVAL;
+
+ table = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ ret = sg_alloc_table(table, 1, GFP_KERNEL);
+ if (ret)
+ goto err_free;
+
+ paddr = ion_lma_allocate(heap, size, align);
+ if (paddr == ION_CARVEOUT_ALLOCATE_FAIL) {
+ ret = -ENOMEM;
+ goto err_free_table;
+ }
+
+ sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(paddr)), size, 0);
+ buffer->priv_virt = table;
+ return 0;
+
+err_free_table:
+ sg_free_table(table);
+err_free:
+ kfree(table);
+ return ret;
+}
+
+static void ion_lma_heap_free(struct ion_buffer *buffer)
+{
+ struct ion_heap *heap = buffer->heap;
+ struct sg_table *table = buffer->priv_virt;
+ struct page *page = sg_page(table->sgl);
+ ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
+
+ /* Do not zero the LMA heap from the CPU. This is very slow with
+ * the current TCF (w/ no DMA engine). We will use the TLA to clear
+ * the memory with Rogue in another place.
+ *
+ * We also skip the CPU cache maintenance for the heap space, as we
+ * statically know that the TCF PCI memory bar has UC/WC set by the
+ * MTRR/PAT subsystem.
+ */
+
+ ion_lma_free(heap, paddr, buffer->size);
+ sg_free_table(table);
+ kfree(table);
+}
+
+static struct sg_table *ion_lma_heap_map_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ return buffer->priv_virt;
+}
+
+static void ion_lma_heap_unmap_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ return;
+}
+
+static int ion_lma_heap_map_user(struct ion_heap *mapper,
+ struct ion_buffer *buffer,
+ struct vm_area_struct *vma)
+{
+ struct sg_table *table = buffer->priv_virt;
+ struct page *page = sg_page(table->sgl);
+ ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
+
+ return remap_pfn_range(vma, vma->vm_start,
+ PFN_DOWN(paddr) + vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ pgprot_writecombine(vma->vm_page_prot));
+}
+
+static void *ion_lma_heap_map_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct sg_table *table = buffer->priv_virt;
+ struct page *page = sg_page(table->sgl);
+ ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
+
+ return ioremap_wc(paddr, buffer->size);
+}
+
+static void ion_lma_heap_unmap_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ iounmap(buffer->vaddr);
+}
+
+static struct ion_heap_ops lma_heap_ops = {
+ .allocate = ion_lma_heap_allocate,
+ .free = ion_lma_heap_free,
+ .phys = ion_lma_heap_phys,
+ .map_dma = ion_lma_heap_map_dma,
+ .unmap_dma = ion_lma_heap_unmap_dma,
+ .map_user = ion_lma_heap_map_user,
+ .map_kernel = ion_lma_heap_map_kernel,
+ .unmap_kernel = ion_lma_heap_unmap_kernel,
+};
+
+struct ion_heap *ion_lma_heap_create(struct ion_platform_heap *heap_data)
+{
+ struct ion_lma_heap *lma_heap;
+ size_t size = heap_data->size;
+ struct page *page;
+
+ page = pfn_to_page(PFN_DOWN(heap_data->base));
+
+ /* Do not zero the LMA heap from the CPU. This is very slow with
+ * the current TCF (w/ no DMA engine). We will use the TLA to clear
+ * the memory with Rogue in another place.
+ *
+ * We also skip the CPU cache maintenance for the heap space, as we
+ * statically know that the TCF PCI memory bar has UC/WC set by the
+ * MTRR/PAT subsystem.
+ */
+
+ lma_heap = kzalloc(sizeof(struct ion_lma_heap), GFP_KERNEL);
+ if (!lma_heap)
+ return ERR_PTR(-ENOMEM);
+
+ lma_heap->pool = gen_pool_create(12, -1);
+ if (!lma_heap->pool) {
+ kfree(lma_heap);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ lma_heap->base = heap_data->base;
+ gen_pool_add(lma_heap->pool, lma_heap->base, size, -1);
+
+ lma_heap->heap.id = heap_data->id;
+ lma_heap->heap.ops = &lma_heap_ops;
+ lma_heap->heap.name = heap_data->name;
+ lma_heap->heap.type = ION_HEAP_TYPE_CUSTOM;
+ lma_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE;
+
+ return &lma_heap->heap;
+}
+
+void ion_lma_heap_destroy(struct ion_heap *heap)
+{
+ struct ion_lma_heap *lma_heap =
+ container_of(heap, struct ion_lma_heap, heap);
+ gen_pool_destroy(lma_heap->pool);
+ kfree(lma_heap);
+ lma_heap = NULL;
+}
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/ion_lma_heap.h b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/ion_lma_heap.h
new file mode 100644
index 000000000000..2e0b9bc5d22e
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/ion_lma_heap.h
@@ -0,0 +1,52 @@
+/*************************************************************************/ /*!
+@File ion_lma_heap.h
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+#ifndef __ION_LMA_HEAP__
+#define __ION_LMA_HEAP__
+
+#include PVR_ANDROID_ION_HEADER
+#include PVR_ANDROID_ION_PRIV_HEADER
+
+struct ion_heap *ion_lma_heap_create(struct ion_platform_heap *heap_data);
+void ion_lma_heap_destroy(struct ion_heap *heap);
+
+#endif /* __ION_LMA_HEAP__ */
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.c b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.c
new file mode 100644
index 000000000000..31cab2e359b0
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.c
@@ -0,0 +1,2119 @@
+/*************************************************************************/ /*!
+@File pvr_sync.c
+@Title Kernel driver for Android's sync mechanism
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+#include "pvr_sync.h"
+#include "pvr_fd_sync_user.h"
+#include "services_kernel_client.h"
+
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+#include <linux/syscalls.h>
+#include <linux/miscdevice.h>
+#include <linux/anon_inodes.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#include <linux/sync.h>
+#else
+#include <../drivers/staging/android/sync.h>
+#endif
+
+/* #define DEBUG_OUTPUT 1 */
+
+#ifdef DEBUG_OUTPUT
+#define DPF(fmt, ...) pr_err("pvr_sync: " fmt "\n", __VA_ARGS__)
+#else
+#define DPF(fmt, ...) do {} while (0)
+#endif
+
+#define PVR_DUMPDEBUG_LOG(pfnDumpDebugPrintf, fmt, ...) \
+ do { \
+ if (pfnDumpDebugPrintf) { \
+ pfnDumpDebugPrintf(fmt, __VA_ARGS__); \
+ } else { \
+ pr_info("pvr_sync: " fmt, __VA_ARGS__); \
+ } \
+ } while (0)
+
+#define SYNC_MAX_POOL_SIZE 10
+
+enum {
+ SYNC_TL_TYPE = 0,
+ SYNC_PT_FENCE_TYPE = 1,
+ SYNC_PT_CLEANUP_TYPE = 2,
+ SYNC_PT_FOREIGN_FENCE_TYPE = 3,
+ SYNC_PT_FOREIGN_CLEANUP_TYPE = 4,
+};
+
+/* Services client sync prim wrapper. This is used to hold debug information
+ * and make it possible to cache unused syncs. */
+struct pvr_sync_native_sync_prim {
+ /* List for the sync pool support. */
+ struct list_head list;
+
+ /* Base services sync prim structure */
+ struct PVRSRV_CLIENT_SYNC_PRIM *client_sync;
+
+ /* The next queued value which should be used */
+ u32 next_value;
+
+ /* Every sync data will get some unique id */
+ u32 id;
+
+ /* FWAddr used by the client sync */
+ u32 vaddr;
+
+ /* The type this sync is used for in our driver. Used in
+ * pvr_sync_debug_request. */
+ u8 type;
+
+ /* A debug class name also printed in pvr_sync_debug_request */
+ char class[32];
+};
+
+/* This is the IMG extension of a sync_timeline */
+struct pvr_sync_timeline {
+ /* Original timeline struct. Needs to come first. */
+ struct sync_timeline obj;
+
+ /* Global timeline list support */
+ struct list_head list;
+
+ /* Timeline sync */
+ struct pvr_sync_native_sync_prim *timeline_sync;
+
+ /* Should we do timeline idle detection when creating a new fence? */
+ bool fencing_enabled;
+};
+
+struct pvr_sync_tl_to_signal {
+ /* List entry support for the list of timelines which needs signaling */
+ struct list_head list;
+
+ /* The timeline to signal */
+ struct pvr_sync_timeline *timeline;
+};
+
+struct pvr_sync_kernel_pair {
+ /* Binary sync point representing the android native sync in hw. */
+ struct pvr_sync_native_sync_prim *fence_sync;
+
+ /* Cleanup sync structure.
+ * If the base sync prim is used for "checking" only within a gl stream,
+ * there is no way of knowing when this has happened. So use a second
+ * sync prim which just gets updated and check the update count when
+ * freeing this struct. */
+ struct pvr_sync_native_sync_prim *cleanup_sync;
+
+ /* Sync points can go away when there are deferred hardware operations
+ * still outstanding. We must not free the SERVER_SYNC_PRIMITIVE until
+ * the hardware is finished, so we add it to a defer list which is
+ * processed periodically ("defer-free").
+ *
+ * Note that the defer-free list is global, not per-timeline.
+ */
+ struct list_head list;
+};
+
+struct pvr_sync_data {
+ /* Every sync point has a services sync object. This object is used
+ * by the hardware to enforce ordering -- it is attached as a source
+ * dependency to various commands.
+ */
+ struct pvr_sync_kernel_pair *kernel;
+
+ /* The timeline fence value for this sync point. */
+ u32 timeline_fence_value;
+
+ /* The timeline update value for this sync point. */
+ u32 timeline_update_value;
+
+ /* This refcount is incremented at create and dup time, and decremented
+ * at free time. It ensures the object doesn't start the defer-free
+ * process until it is no longer referenced.
+ */
+ atomic_t refcount;
+};
+
+struct pvr_sync_alloc_data {
+ struct pvr_sync_data *sync_data;
+ struct file *file;
+ /* alloc syncs need a reference to the timeline for timeline sync
+ * access during the operation scheduling. There is currently no way
+ * to access the timeline's kref to take a reference count directly,
+ * which means there is a possibility of the timeline still having a
+ * reference after it has been free'd.
+ *
+ * We believe this is a non-issue, so long as the userspace application
+ * holds a fd open to the corresponding pvr_sync node for the length
+ * of time the alloc sync is alive. This holds the timeline open, and
+ * as alloc syncs are short lived, this should not be harmful.
+ *
+ * If an application is closed, it is not determined if the timeline
+ * fd will be closed (possibly destroying the timeline) before any
+ * alloc syncs are closed. Due to this, the alloc sync release method
+ * /must not/ assume this timeline pointer is valid */
+ struct pvr_sync_timeline *timeline;
+};
+
+/* This is the IMG extension of a sync_pt */
+struct pvr_sync_pt {
+ /* Original sync_pt structure. Needs to come first. */
+ struct sync_pt pt;
+
+ /* Private shared data */
+ struct pvr_sync_data *sync_data;
+};
+
+/* This is the IMG extension of a sync_fence */
+struct pvr_sync_fence {
+ /* Original sync_fence structure. Needs to come first. */
+ struct sync_fence *fence;
+
+ /* To ensure callbacks are always received for fences / sync_pts, even
+ * after the fence has been 'put' (freed), we must take a reference to
+ * the fence. We still need to 'put' the fence ourselves, but this might
+ * happen in irq context, where fput() is not allowed (in kernels <3.6).
+ * We must add the fence to a list which is processed in WQ context.
+ */
+ struct list_head list;
+};
+
+/* Any sync point from a foreign (non-PVR) timeline needs to have a "shadow"
+ * sync prim. This is modelled as a software operation. The foreign driver
+ * completes the operation by calling a callback we registered with it. */
+struct pvr_sync_fence_waiter {
+ /* Base sync driver waiter structure */
+ struct sync_fence_waiter waiter;
+
+ /* "Shadow" sync prim backing the foreign driver's sync_pt */
+ struct pvr_sync_kernel_pair *kernel;
+
+ /* Optimizes lookup of fence for defer-put operation */
+ struct pvr_sync_fence *sync_fence;
+};
+
+/* Global data for the sync driver */
+static struct {
+ /* Services connection */
+ void *device_cookie;
+
+ /* Complete notify handle */
+ void *command_complete_handle;
+
+ /* defer_free workqueue. Syncs may still be in use by the HW when freed,
+ * so we have to keep them around until the HW is done with them at
+ * some later time. This workqueue iterates over the list of free'd
+ * syncs, checks if they are in use, and frees the sync device memory
+ * when done with. */
+ 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;
+
+ /* Debug notify handle */
+ void *debug_notify_handle;
+
+ /* Unique id counter for the sync prims */
+ atomic_t sync_id;
+
+ /* The global event object (used to wait between checks for deferred-
+ * free sync status) */
+ void *event_object_handle;
+} pvr_sync_data;
+
+/* List of timelines created by this driver */
+static LIST_HEAD(timeline_list);
+static DEFINE_MUTEX(timeline_list_mutex);
+
+/* Sync pool support */
+static LIST_HEAD(sync_pool_free_list);
+static LIST_HEAD(sync_pool_active_list);
+static DEFINE_MUTEX(sync_pool_mutex);
+static s32 sync_pool_size;
+static u32 sync_pool_created;
+static u32 sync_pool_reused;
+
+/* The "defer-free" object list. Driver global. */
+static LIST_HEAD(sync_prim_free_list);
+static DEFINE_SPINLOCK(sync_prim_free_list_spinlock);
+
+/* The "defer-put" object list. Driver global. */
+static LIST_HEAD(sync_fence_put_list);
+static DEFINE_SPINLOCK(sync_fence_put_list_spinlock);
+
+static inline void set_sync_value(struct pvr_sync_native_sync_prim *sync,
+ u32 value)
+{
+ *(sync->client_sync->pui32LinAddr) = value;
+}
+
+static inline u32 get_sync_value(struct pvr_sync_native_sync_prim *sync)
+{
+ return *(sync->client_sync->pui32LinAddr);
+}
+
+static inline void complete_sync(struct pvr_sync_native_sync_prim *sync)
+{
+ *(sync->client_sync->pui32LinAddr) = sync->next_value;
+}
+
+static inline int is_sync_met(struct pvr_sync_native_sync_prim *sync)
+{
+ return *(sync->client_sync->pui32LinAddr) == sync->next_value;
+}
+
+static struct pvr_sync_alloc_data *pvr_sync_alloc_fence_fdget(int fd);
+
+#ifdef DEBUG_OUTPUT
+
+static char *debug_info_timeline(struct sync_timeline *tl)
+{
+ struct pvr_sync_timeline *timeline = (struct pvr_sync_timeline *)tl;
+ static char info[256];
+
+ info[0] = '\0';
+
+ snprintf(info, sizeof(info),
+ "n='%s' id=%u fw=0x%x tl_curr=%u tl_next=%u",
+ tl->name, timeline->timeline_sync->id,
+ timeline->timeline_sync->vaddr,
+ get_sync_value(timeline->timeline_sync),
+ timeline->timeline_sync->next_value);
+
+ return info;
+}
+
+static char *debug_info_sync_pt(struct sync_pt *pt)
+{
+ struct pvr_sync_pt *pvr_pt = (struct pvr_sync_pt *)pt;
+ struct pvr_sync_kernel_pair *kernel = pvr_pt->sync_data->kernel;
+ static char info[256], info1[256];
+
+ info[0] = '\0';
+ info1[0] = '\0';
+
+ if (kernel) {
+ struct pvr_sync_native_sync_prim *cleanup_sync =
+ kernel->cleanup_sync;
+
+ if (cleanup_sync) {
+ snprintf(info1, sizeof(info1),
+ " # cleanup: id=%u fw=0x%x curr=%u next=%u",
+ cleanup_sync->id,
+ cleanup_sync->vaddr,
+ get_sync_value(cleanup_sync),
+ cleanup_sync->next_value);
+ }
+
+ snprintf(info, sizeof(info),
+ "status=%d tl_taken=%u ref=%d "
+ "# sync: id=%u fw=0x%x curr=%u next=%u%s # tl: %s",
+ pt->status,
+ pvr_pt->sync_data->timeline_update_value,
+ atomic_read(&pvr_pt->sync_data->refcount),
+ kernel->fence_sync->id,
+ kernel->fence_sync->vaddr,
+ get_sync_value(kernel->fence_sync),
+ kernel->fence_sync->next_value,
+ info1, debug_info_timeline(pt->parent));
+ } else {
+ snprintf(info, sizeof(info),
+ "status=%d tl_taken=%u ref=%d "
+ "# sync: idle # tl: %s",
+ pt->status,
+ pvr_pt->sync_data->timeline_update_value,
+ atomic_read(&pvr_pt->sync_data->refcount),
+ debug_info_timeline(pt->parent));
+ }
+
+ return info;
+}
+
+#endif /* DEBUG_OUTPUT */
+
+static enum PVRSRV_ERROR
+sync_pool_get(struct pvr_sync_native_sync_prim **_sync,
+ const char *class_name, u8 type)
+{
+ struct pvr_sync_native_sync_prim *sync;
+ enum PVRSRV_ERROR error = PVRSRV_OK;
+
+ mutex_lock(&sync_pool_mutex);
+
+ if (list_empty(&sync_pool_free_list)) {
+ /* If there is nothing in the pool, create a new sync prim. */
+ sync = kmalloc(sizeof(struct pvr_sync_native_sync_prim),
+ GFP_KERNEL);
+ if (!sync) {
+ pr_err("pvr_sync: %s: Failed to allocate sync data",
+ __func__);
+ error = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_unlock;
+ }
+
+ error = SyncPrimAlloc(pvr_sync_data.sync_prim_context,
+ &sync->client_sync, class_name);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to allocate sync prim (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ goto err_free;
+ }
+
+ sync->vaddr = SyncPrimGetFirmwareAddr(sync->client_sync);
+
+ list_add_tail(&sync->list, &sync_pool_active_list);
+ ++sync_pool_created;
+ } else {
+ sync = list_first_entry(&sync_pool_free_list,
+ struct pvr_sync_native_sync_prim, list);
+ list_move_tail(&sync->list, &sync_pool_active_list);
+ --sync_pool_size;
+ ++sync_pool_reused;
+ }
+
+ sync->id = atomic_inc_return(&pvr_sync_data.sync_id);
+ sync->type = type;
+
+ strncpy(sync->class, class_name, sizeof(sync->class));
+ /* Its crucial to reset the sync to zero */
+ set_sync_value(sync, 0);
+ sync->next_value = 0;
+
+ *_sync = sync;
+err_unlock:
+ mutex_unlock(&sync_pool_mutex);
+ return error;
+
+err_free:
+ kfree(sync);
+ goto err_unlock;
+}
+
+static void sync_pool_put(struct pvr_sync_native_sync_prim *sync)
+{
+ mutex_lock(&sync_pool_mutex);
+
+ if (sync_pool_size < SYNC_MAX_POOL_SIZE) {
+ /* Mark it as unused */
+ set_sync_value(sync, 0xffffffff);
+
+ list_move(&sync->list, &sync_pool_free_list);
+ ++sync_pool_size;
+ } else {
+ /* Mark it as invalid */
+ set_sync_value(sync, 0xdeadbeef);
+
+ list_del(&sync->list);
+ SyncPrimFree(sync->client_sync);
+ kfree(sync);
+ }
+
+ mutex_unlock(&sync_pool_mutex);
+}
+
+static void sync_pool_clear(void)
+{
+ struct pvr_sync_native_sync_prim *sync, *n;
+
+ mutex_lock(&sync_pool_mutex);
+
+ list_for_each_entry_safe(sync, n, &sync_pool_free_list, list) {
+ /* Mark it as invalid */
+ set_sync_value(sync, 0xdeadbeef);
+
+ list_del(&sync->list);
+ SyncPrimFree(sync->client_sync);
+ kfree(sync);
+ --sync_pool_size;
+ }
+
+ mutex_unlock(&sync_pool_mutex);
+}
+
+static void pvr_sync_debug_request(void *hDebugRequestHandle,
+ u32 ui32VerbLevel)
+{
+ struct pvr_sync_native_sync_prim *sync;
+
+ static const char *const type_names[] = {
+ "Timeline", "Fence", "Cleanup",
+ "Foreign Fence", "Foreign Cleanup"
+ };
+
+ if (ui32VerbLevel == DEBUG_REQUEST_VERBOSITY_HIGH) {
+ mutex_lock(&sync_pool_mutex);
+
+ PVR_DUMPDEBUG_LOG(g_pfnDumpDebugPrintf,
+ "Dumping all pending android native syncs (Pool usage: %d%% - %d %d)",
+ sync_pool_reused ?
+ (10000 /
+ ((sync_pool_created + sync_pool_reused) *
+ 100 / sync_pool_reused)) : 0,
+ sync_pool_created, sync_pool_reused);
+
+ list_for_each_entry(sync, &sync_pool_active_list, list) {
+ if (is_sync_met(sync))
+ continue;
+
+ BUG_ON(sync->type >= ARRAY_SIZE(type_names));
+
+ PVR_DUMPDEBUG_LOG(g_pfnDumpDebugPrintf,
+ "\tID = %d, FWAddr = 0x%08x: Current = 0x%08x, Next = 0x%08x, %s (%s)",
+ sync->id, sync->vaddr,
+ get_sync_value(sync),
+ sync->next_value,
+ sync->class,
+ type_names[sync->type]);
+ }
+#if 0
+ PVR_DUMPDEBUG_LOG(g_pfnDumpDebugPrintf,
+ "Dumping all unused syncs");
+ list_for_each_entry(sync, &sync_pool_free_list, list) {
+ BUG_ON(sync->type >= ARRAY_SIZE(type_names));
+
+ PVR_DUMPDEBUG_LOG(g_pfnDumpDebugPrintf,
+ "\tID = %d, FWAddr = 0x%08x: Current = 0x%08x, Next = 0x%08x, %s (%s)",
+ sync->id, sync->vaddr,
+ get_sync_value(sync),
+ sync->next_value,
+ sync->class,
+ type_names[sync->type]);
+ }
+#endif
+ mutex_unlock(&sync_pool_mutex);
+ }
+}
+
+static struct sync_pt *pvr_sync_dup(struct sync_pt *sync_pt)
+{
+ struct pvr_sync_pt *pvr_pt_a = (struct pvr_sync_pt *)sync_pt;
+ struct pvr_sync_pt *pvr_pt_b = NULL;
+
+ DPF("%s: # %s", __func__, debug_info_sync_pt(sync_pt));
+
+ pvr_pt_b = (struct pvr_sync_pt *)
+ sync_pt_create(pvr_pt_a->pt.parent, sizeof(struct pvr_sync_pt));
+ if (!pvr_pt_b) {
+ pr_err("pvr_sync: %s: Failed to dup sync pt", __func__);
+ goto err_out;
+ }
+
+ atomic_inc(&pvr_pt_a->sync_data->refcount);
+
+ pvr_pt_b->sync_data = pvr_pt_a->sync_data;
+
+err_out:
+ return (struct sync_pt *)pvr_pt_b;
+}
+
+static int pvr_sync_has_signaled(struct sync_pt *sync_pt)
+{
+ struct pvr_sync_pt *pvr_pt = (struct pvr_sync_pt *)sync_pt;
+
+ DPF("%s: # %s", __func__, debug_info_sync_pt(sync_pt));
+
+ /* Idle syncs are always signaled */
+ if (!pvr_pt->sync_data->kernel)
+ return 1;
+
+ return is_sync_met(pvr_pt->sync_data->kernel->fence_sync);
+}
+
+static int pvr_sync_compare(struct sync_pt *a, struct sync_pt *b)
+{
+ u32 a1 = ((struct pvr_sync_pt *)a)->sync_data->timeline_update_value;
+ u32 b1 = ((struct pvr_sync_pt *)b)->sync_data->timeline_update_value;
+
+ DPF("%s: a # %s", __func__, debug_info_sync_pt(a));
+ DPF("%s: b # %s", __func__, debug_info_sync_pt(b));
+
+ if (a1 == b1)
+ return 0;
+
+ /* Take integer wrapping into account */
+ return ((s32)a1 - (s32)b1) < 0 ? -1 : 1;
+}
+
+static void wait_for_sync(struct pvr_sync_native_sync_prim *sync)
+{
+#ifndef NO_HARDWARE
+ void *event_object = NULL;
+ enum PVRSRV_ERROR error = PVRSRV_OK;
+
+ while (sync && !is_sync_met(sync)) {
+ if (!event_object) {
+ error = OSEventObjectOpen(
+ pvr_sync_data.event_object_handle,
+ &event_object);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Error opening event object (%s)\n",
+ __func__,
+ PVRSRVGetErrorStringKM(error));
+ break;
+ }
+ }
+ error = OSEventObjectWait(event_object);
+ if (error != PVRSRV_OK && error != PVRSRV_ERROR_TIMEOUT) {
+ pr_err("pvr_sync: %s: Error waiting on event object (%s)\n",
+ __func__,
+ PVRSRVGetErrorStringKM(error));
+ }
+ }
+
+ if (event_object)
+ OSEventObjectClose(event_object);
+#endif
+}
+
+static void pvr_sync_release_timeline(struct sync_timeline *psObj)
+{
+ struct pvr_sync_timeline *timeline = (struct pvr_sync_timeline *)psObj;
+
+ DPF("%s: # %s", __func__, debug_info_timeline(psObj));
+
+ wait_for_sync(timeline->timeline_sync);
+
+ /*
+ * If pvr_sync_open failed after calling sync_timeline_create, this
+ * can be called with a timeline that has not got a timeline sync
+ * or been added to our timeline list. Use a NULL timeline_sync
+ * to detect and handle this condition
+ */
+ if (timeline->timeline_sync) {
+
+ mutex_lock(&timeline_list_mutex);
+ list_del(&timeline->list);
+ mutex_unlock(&timeline_list_mutex);
+
+ OSAcquireBridgeLock();
+ sync_pool_put(timeline->timeline_sync);
+ OSReleaseBridgeLock();
+ }
+}
+
+static void pvr_sync_print_obj(struct seq_file *s,
+ struct sync_timeline *sync_timeline)
+{
+ struct pvr_sync_timeline *timeline =
+ (struct pvr_sync_timeline *)sync_timeline;
+
+ seq_printf(s, "id=%u fw=0x%x curr=%u next=%u",
+ timeline->timeline_sync->id,
+ timeline->timeline_sync->vaddr,
+ get_sync_value(timeline->timeline_sync),
+ timeline->timeline_sync->next_value);
+}
+
+static void pvr_sync_print_pt(struct seq_file *s, struct sync_pt *sync_pt)
+{
+ struct pvr_sync_pt *pvr_pt = (struct pvr_sync_pt *)sync_pt;
+ struct pvr_sync_kernel_pair *kernel;
+
+ if (!pvr_pt->sync_data)
+ return;
+
+ kernel = pvr_pt->sync_data->kernel;
+ if (kernel) {
+ if (!kernel->cleanup_sync) {
+ seq_printf(s, "tl_taken=%u ref=%d #" \
+ " sync: id=%u fw=0x%x curr=%u next=%u",
+ pvr_pt->sync_data->timeline_update_value,
+ atomic_read(&pvr_pt->sync_data->refcount),
+ kernel->fence_sync->id,
+ kernel->fence_sync->vaddr,
+ get_sync_value(kernel->fence_sync),
+ kernel->fence_sync->next_value);
+ } else {
+ seq_printf(s, "tl_taken=%u ref=%d #" \
+ " sync: id=%u fw=0x%x curr=%u next=%u\n" \
+ " cleanup: id=%u fw=0x%x curr=%u next=%u",
+ pvr_pt->sync_data->timeline_update_value,
+ atomic_read(&pvr_pt->sync_data->refcount),
+ kernel->fence_sync->id,
+ kernel->fence_sync->vaddr,
+ get_sync_value(kernel->fence_sync),
+ kernel->fence_sync->next_value,
+ kernel->cleanup_sync->id,
+ kernel->cleanup_sync->vaddr,
+ get_sync_value(kernel->cleanup_sync),
+ kernel->cleanup_sync->next_value);
+ }
+ } else {
+ seq_printf(s, "tl_taken=%u ref=%d #" \
+ " sync: idle",
+ pvr_pt->sync_data->timeline_update_value,
+ atomic_read(&pvr_pt->sync_data->refcount));
+ }
+}
+
+static struct pvr_sync_data*
+pvr_sync_create_sync_data(struct pvr_sync_timeline *timeline)
+{
+ struct pvr_sync_data *sync_data = NULL;
+ enum PVRSRV_ERROR error;
+
+ sync_data = kzalloc(sizeof(struct pvr_sync_data), GFP_KERNEL);
+ if (!sync_data)
+ goto err_out;
+
+ atomic_set(&sync_data->refcount, 1);
+
+ sync_data->kernel =
+ kzalloc(sizeof(struct pvr_sync_kernel_pair),
+ GFP_KERNEL);
+
+ if (!sync_data->kernel)
+ goto err_free_data;
+
+ OSAcquireBridgeLock();
+ error = sync_pool_get(&sync_data->kernel->fence_sync,
+ timeline->obj.name, SYNC_PT_FENCE_TYPE);
+ OSReleaseBridgeLock();
+
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to allocate sync prim (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ goto err_free_kernel;
+ }
+
+err_out:
+ return sync_data;
+
+err_free_kernel:
+ kfree(sync_data->kernel);
+err_free_data:
+ kfree(sync_data);
+ sync_data = NULL;
+ goto err_out;
+}
+
+static struct pvr_sync_pt *
+pvr_sync_create_sync(struct pvr_sync_timeline *timeline,
+ struct pvr_sync_data *sync_data)
+{
+ struct pvr_sync_pt *pvr_pt = NULL;
+
+ pvr_pt = (struct pvr_sync_pt *)
+ sync_pt_create(&timeline->obj, sizeof(struct pvr_sync_pt));
+ if (!pvr_pt) {
+ pr_err("pvr_sync: %s: Failed to create sync pt", __func__);
+ goto err_complete_sync;
+ }
+
+ /* Attach our sync data to the new sync point. */
+ pvr_pt->sync_data = sync_data;
+
+err_out:
+ return pvr_pt;
+
+err_complete_sync:
+ if (sync_data->kernel) {
+ /* Complete the sync taken on the TL sync and delete the
+ * new fence sync. */
+ complete_sync(timeline->timeline_sync);
+ OSAcquireBridgeLock();
+ sync_pool_put(sync_data->kernel->fence_sync);
+ OSReleaseBridgeLock();
+ }
+ kfree(sync_data->kernel);
+ kfree(sync_data);
+ goto err_out;
+}
+
+static void pvr_sync_defer_free(struct pvr_sync_kernel_pair *kernel)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sync_prim_free_list_spinlock, flags);
+ list_add_tail(&kernel->list, &sync_prim_free_list);
+ spin_unlock_irqrestore(&sync_prim_free_list_spinlock, flags);
+
+ queue_work(pvr_sync_data.defer_free_wq, &pvr_sync_data.defer_free_work);
+}
+
+static void pvr_sync_free_sync(struct sync_pt *sync_pt)
+{
+ struct pvr_sync_pt *pvr_pt = (struct pvr_sync_pt *)sync_pt;
+
+ DPF("%s: # %s", __func__, debug_info_sync_pt(sync_pt));
+
+ /* Only free on the last reference */
+ if (atomic_dec_return(&pvr_pt->sync_data->refcount) != 0)
+ return;
+
+ if (pvr_pt->sync_data->kernel)
+ pvr_sync_defer_free(pvr_pt->sync_data->kernel);
+
+ kfree(pvr_pt->sync_data);
+}
+
+static struct sync_timeline_ops pvr_sync_timeline_ops = {
+ .driver_name = PVRSYNC_MODNAME,
+ .dup = pvr_sync_dup,
+ .has_signaled = pvr_sync_has_signaled,
+ .compare = pvr_sync_compare,
+ .free_pt = pvr_sync_free_sync,
+ .release_obj = pvr_sync_release_timeline,
+ .print_obj = pvr_sync_print_obj,
+ .print_pt = pvr_sync_print_pt,
+};
+
+/* foreign sync handling */
+
+static void pvr_sync_foreign_sync_pt_signaled(struct sync_fence *fence,
+ struct sync_fence_waiter *_waiter)
+{
+ struct pvr_sync_fence_waiter *waiter =
+ (struct pvr_sync_fence_waiter *)_waiter;
+ unsigned long flags;
+
+ /* Complete the SW operation and free the sync if we can. If we can't,
+ * it will be checked by a later workqueue kick. */
+ complete_sync(waiter->kernel->fence_sync);
+
+ /* We can 'put' the fence now, but this function might be called in
+ * irq context so we must defer to WQ.
+ * This WQ is triggered in pvr_sync_defer_free, so adding it to the
+ * put list before that should guarantee it's cleaned up on the next
+ * wq run */
+ spin_lock_irqsave(&sync_fence_put_list_spinlock, flags);
+ list_add_tail(&waiter->sync_fence->list, &sync_fence_put_list);
+ spin_unlock_irqrestore(&sync_fence_put_list_spinlock, flags);
+
+ pvr_sync_defer_free(waiter->kernel);
+
+ /* 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,
+ &pvr_sync_data.check_status_work);
+
+ kfree(waiter);
+}
+
+static struct pvr_sync_kernel_pair *
+pvr_sync_create_waiter_for_foreign_sync(int fd)
+{
+ struct pvr_sync_kernel_pair *kernel = NULL;
+ struct pvr_sync_fence_waiter *waiter;
+ struct pvr_sync_fence *sync_fence;
+ struct sync_fence *fence;
+ enum PVRSRV_ERROR error;
+ int err;
+
+ fence = sync_fence_fdget(fd);
+ if (!fence) {
+ pr_err("pvr_sync: %s: Failed to take reference on fence",
+ __func__);
+ goto err_out;
+ }
+
+ kernel = kmalloc(sizeof(struct pvr_sync_kernel_pair), GFP_KERNEL);
+ if (!kernel) {
+ pr_err("pvr_sync: %s: Failed to allocate sync kernel",
+ __func__);
+ goto err_put_fence;
+ }
+
+ sync_fence = kmalloc(sizeof(struct pvr_sync_fence), GFP_KERNEL);
+ if (!sync_fence) {
+ pr_err("pvr_sync: %s: Failed to allocate pvr sync fence",
+ __func__);
+ goto err_free_kernel;
+ }
+
+ sync_fence->fence = fence;
+
+ error = sync_pool_get(&kernel->fence_sync,
+ fence->name, SYNC_PT_FOREIGN_FENCE_TYPE);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to allocate sync prim (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ goto err_free_sync_fence;
+ }
+
+ kernel->fence_sync->next_value++;
+
+ error = sync_pool_get(&kernel->cleanup_sync,
+ fence->name, SYNC_PT_FOREIGN_CLEANUP_TYPE);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to allocate cleanup sync prim (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ goto err_free_sync;
+ }
+
+ kernel->cleanup_sync->next_value++;
+
+ /* The custom waiter structure is freed in the waiter callback */
+ waiter = kmalloc(sizeof(struct pvr_sync_fence_waiter), GFP_KERNEL);
+ if (!waiter) {
+ pr_err("pvr_sync: %s: Failed to allocate waiter", __func__);
+ goto err_free_cleanup_sync;
+ }
+
+ waiter->kernel = kernel;
+ waiter->sync_fence = sync_fence;
+
+ sync_fence_waiter_init(&waiter->waiter,
+ pvr_sync_foreign_sync_pt_signaled);
+
+ err = sync_fence_wait_async(fence, &waiter->waiter);
+ if (err) {
+ if (err < 0) {
+ pr_err("pvr_sync: %s: Fence was in error state (%d)",
+ __func__, err);
+ /* Fall-thru */
+ }
+
+ /* -1 means the fence was broken, 1 means the fence already
+ * signalled. In either case, roll back what we've done and
+ * skip using this sync_pt for synchronization.
+ */
+ goto err_free_waiter;
+ }
+
+err_out:
+ return kernel;
+err_free_waiter:
+ kfree(waiter);
+err_free_cleanup_sync:
+ sync_pool_put(kernel->cleanup_sync);
+err_free_sync:
+ sync_pool_put(kernel->fence_sync);
+err_free_sync_fence:
+ kfree(sync_fence);
+err_free_kernel:
+ kfree(kernel);
+ kernel = NULL;
+err_put_fence:
+ sync_fence_put(fence);
+ goto err_out;
+}
+
+static int
+pvr_sync_debug_fence(s32 fd, char *name, u32 size_name, s32 *status,
+ u32 max_num_syncs, u32 *num_syncs,
+ struct pvr_sync_debug_sync_data *pt_debug)
+{
+ struct sync_fence *fence = sync_fence_fdget(fd);
+ int err = 0;
+ struct sync_pt *sync_pt;
+
+ if (!fence || !num_syncs || !status || !size_name)
+ return -EINVAL;
+
+ *num_syncs = 0;
+
+ strncpy(name, fence->name, size_name - 1);
+ name[size_name - 1] = '\0';
+
+ *status = fence->status;
+
+ list_for_each_entry(sync_pt, &fence->pt_list_head, pt_list) {
+ struct pvr_sync_pt *pvr_pt = (struct pvr_sync_pt *)sync_pt;
+
+ if (*num_syncs == max_num_syncs) {
+ pr_warn("pvr_sync: %s: Too little space on fence query for all the sync points in this fence",
+ __func__);
+ goto err_put;
+ }
+
+ /* Clear the entry */
+ memset(&pt_debug[*num_syncs], 0, sizeof(pt_debug[*num_syncs]));
+
+ /* Save this within the sync point. */
+ strncpy(pt_debug[*num_syncs].szParentName,
+ sync_pt->parent->name,
+ sizeof(pt_debug[*num_syncs].szParentName) - 1);
+
+ pt_debug[*num_syncs].i32Status = sync_pt->status;
+
+ if (sync_pt->parent->ops == &pvr_sync_timeline_ops) {
+ /* Fill in the sync info for this sync point. */
+ if (pvr_pt->sync_data->kernel) {
+ struct pvr_sync_kernel_pair *kernel =
+ pvr_pt->sync_data->kernel;
+ pt_debug[*num_syncs].s.id =
+ kernel->fence_sync->id;
+ pt_debug[*num_syncs].s.ui32CurrOp =
+ get_sync_value(kernel->fence_sync);
+ pt_debug[*num_syncs].s.ui32NextOp =
+ kernel->fence_sync->next_value;
+ pt_debug[*num_syncs].s.ui32FWAddr =
+ kernel->fence_sync->vaddr;
+ pt_debug[*num_syncs].s.ui32TlTaken =
+ pvr_pt->sync_data->timeline_update_value;
+ }
+ } else {
+ /* Handle foreign sync points. */
+ pt_debug[*num_syncs].ui8Foreign = 1;
+ if (sync_pt->parent->ops->pt_value_str) {
+ sync_pt->parent->ops->pt_value_str(sync_pt,
+ pt_debug[*num_syncs].szForeignVal,
+ sizeof(pt_debug[*num_syncs].szForeignVal));
+ }
+ }
+
+ ++*num_syncs;
+ }
+
+err_put:
+ sync_fence_put(fence);
+ return err;
+}
+
+enum PVRSRV_ERROR pvr_sync_append_fences(
+ const char *name,
+ const u32 nr_check_fences,
+ const s32 *check_fence_fds,
+ const s32 update_fence_fd,
+ const u32 nr_updates,
+ const PRGXFWIF_UFO_ADDR *update_ufo_addresses,
+ const u32 *update_values,
+ const u32 nr_checks,
+ const PRGXFWIF_UFO_ADDR *check_ufo_addresses,
+ const u32 *check_values,
+ struct pvr_sync_append_data **append_sync_data)
+{
+ struct pvr_sync_append_data *sync_data;
+ enum PVRSRV_ERROR err = PVRSRV_OK;
+ struct pvr_sync_native_sync_prim **cleanup_sync_pos;
+ PRGXFWIF_UFO_ADDR *update_address_pos;
+ PRGXFWIF_UFO_ADDR *check_address_pos;
+ u32 *update_value_pos;
+ u32 *check_value_pos;
+ unsigned num_used_sync_checks;
+ unsigned num_used_sync_updates;
+ struct pvr_sync_alloc_data *alloc_sync_data = NULL;
+ unsigned i;
+
+ sync_data =
+ kzalloc(sizeof(struct pvr_sync_append_data)
+ + nr_check_fences * sizeof(struct sync_fence*),
+ GFP_KERNEL);
+ if (!sync_data) {
+ err = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_out;
+ }
+
+ sync_data->nr_checks = nr_checks;
+ sync_data->nr_updates = nr_updates;
+
+ sync_data->nr_fences = nr_check_fences;
+
+
+ /* Loop through once to get the fences and count the total number of points */
+ for (i = 0; i < nr_check_fences; i++) {
+ unsigned points_on_fence = 0;
+ bool has_foreign_point = false;
+ struct sync_fence *fence = sync_fence_fdget(check_fence_fds[i]);
+ struct sync_pt *sync_pt;
+ struct pvr_sync_kernel_pair *sync_kernel;
+
+ if (!fence) {
+ pr_err("pvr_sync: %s: Failed to read sync private data for fd %d\n",
+ __func__, check_fence_fds[i]);
+ err = PVRSRV_ERROR_HANDLE_NOT_FOUND;
+ goto err_free_append_data;
+ }
+
+ sync_data->fences[i] = fence;
+
+ list_for_each_entry(sync_pt, &fence->pt_list_head, pt_list) {
+ struct pvr_sync_pt *pvr_pt;
+ if (sync_pt->parent->ops != &pvr_sync_timeline_ops) {
+ if (!sync_pt->status)
+ has_foreign_point = true;
+ continue;
+ }
+
+ pvr_pt = (struct pvr_sync_pt *)sync_pt;
+ sync_kernel = pvr_pt->sync_data->kernel;
+
+ if (!sync_kernel || is_sync_met(sync_kernel->fence_sync))
+ continue;
+ /* We will use the above sync for "check" only. In this
+ * case also insert a "cleanup" update command into the
+ * opengl stream. This can later be used for checking if
+ * the sync prim could be freed. */
+ if (!sync_kernel->cleanup_sync) {
+ err = sync_pool_get(&sync_kernel->cleanup_sync,
+ pvr_pt->pt.parent->name,
+ SYNC_PT_CLEANUP_TYPE);
+ if (err != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to allocate cleanup sync prim (%s)",
+ __func__,
+ PVRSRVGetErrorStringKM(err));
+ goto err_free_append_data;
+ }
+ }
+ points_on_fence++;
+ }
+
+ if (has_foreign_point)
+ points_on_fence++;
+
+ /* Each point has 1 check value, and 1 update value (for the cleanup fence) */
+ sync_data->nr_checks += points_on_fence;
+ sync_data->nr_updates += points_on_fence;
+ sync_data->nr_cleaup_syncs += points_on_fence;
+ }
+
+ if (update_fence_fd >= 0) {
+ alloc_sync_data = pvr_sync_alloc_fence_fdget(update_fence_fd);
+ if (!alloc_sync_data) {
+ pr_err("pvr_sync: %s: Failed to read alloc sync private data for fd %d\n",
+ __func__, update_fence_fd);
+ err = PVRSRV_ERROR_HANDLE_NOT_FOUND;
+ goto err_free_append_data;
+ }
+ /* Store the alloc sync data now, so it's correctly fput()
+ * even on error */
+ sync_data->update_sync_data = alloc_sync_data;
+ /* If an alloc-sync has already been appended to a kick that
+ * is an error (and the sync_data will be NULL */
+ if (!alloc_sync_data->sync_data) {
+ pr_err("pvr_sync: %s: Failed to read alloc sync sync_data for fd %d\n",
+ __func__, update_fence_fd);
+ err = PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
+ goto err_free_append_data;
+
+ }
+ /* A fence update requires 2 update values (fence and timeline)
+ * and one check (previous timeline value) */
+ sync_data->nr_checks += 1;
+ sync_data->nr_updates += 2;
+ }
+
+ sync_data->update_ufo_addresses =
+ kzalloc(sizeof(PRGXFWIF_UFO_ADDR) * sync_data->nr_updates,
+ GFP_KERNEL);
+ if (!sync_data->update_ufo_addresses) {
+ pr_err("pvr_sync: %s: Failed to allocate update UFO address list\n",
+ __func__);
+ err = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free_append_data;
+ }
+
+ sync_data->update_values =
+ kzalloc(sizeof(u32) * sync_data->nr_updates,
+ GFP_KERNEL);
+ if (!sync_data->update_values) {
+ pr_err("pvr_sync: %s: Failed to allocate update value list\n",
+ __func__);
+ err = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free_append_data;
+ }
+
+ sync_data->check_ufo_addresses =
+ kzalloc(sizeof(PRGXFWIF_UFO_ADDR) * sync_data->nr_checks,
+ GFP_KERNEL);
+ if (!sync_data->check_ufo_addresses) {
+ pr_err("pvr_sync: %s: Failed to allocate check UFO address list\n",
+ __func__);
+ err = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free_append_data;
+ }
+
+ sync_data->check_values =
+ kzalloc(sizeof(u32) * sync_data->nr_checks,
+ GFP_KERNEL);
+ if (!sync_data->check_values) {
+ pr_err("pvr_sync: %s: Failed to allocate check value list\n",
+ __func__);
+ err = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free_append_data;
+ }
+
+ sync_data->cleanup_syncs =
+ kzalloc(sizeof(struct pvr_sync_native_sync_prim*) * sync_data->nr_cleaup_syncs,
+ GFP_KERNEL);
+ if (!sync_data->cleanup_syncs) {
+ pr_err("pvr_sync: %s: Failed to allocate cleanup rollback list\n",
+ __func__);
+ err = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free_append_data;
+ }
+
+ update_address_pos = sync_data->update_ufo_addresses;
+ update_value_pos = sync_data->update_values;
+ check_address_pos = sync_data->check_ufo_addresses;
+ check_value_pos = sync_data->check_values;
+ cleanup_sync_pos = sync_data->cleanup_syncs;
+
+
+ /* Everything should be allocated/sanity checked. No errors are possible
+ * after this point */
+
+ /* Append any check syncs */
+ for (i = 0; i < nr_check_fences; i++) {
+ struct sync_fence *fence = sync_data->fences[i];
+ struct sync_pt *sync_pt;
+ bool has_foreign_point = false;
+
+ list_for_each_entry(sync_pt, &fence->pt_list_head, pt_list) {
+ struct pvr_sync_pt *pvr_pt;
+ struct pvr_sync_kernel_pair *sync_kernel;
+
+ if (sync_pt->parent->ops != &pvr_sync_timeline_ops) {
+ if (!sync_pt->status)
+ has_foreign_point = true;
+ continue;
+ }
+ pvr_pt = (struct pvr_sync_pt*) sync_pt;
+ sync_kernel = pvr_pt->sync_data->kernel;
+
+ if (!sync_kernel || is_sync_met(sync_kernel->fence_sync))
+ continue;
+
+ (*check_address_pos++).ui32Addr =
+ sync_kernel->fence_sync->vaddr;
+ *check_value_pos++ =
+ sync_kernel->fence_sync->next_value;
+
+ (*update_address_pos++).ui32Addr =
+ sync_kernel->cleanup_sync->vaddr;
+ *update_value_pos++ =
+ ++sync_kernel->cleanup_sync->next_value;
+ *cleanup_sync_pos++ = sync_kernel->cleanup_sync;
+ }
+
+ if (has_foreign_point) {
+ struct pvr_sync_kernel_pair *foreign_sync_kernel =
+ pvr_sync_create_waiter_for_foreign_sync(check_fence_fds[i]);
+
+ if (foreign_sync_kernel) {
+ (*check_address_pos++).ui32Addr =
+ foreign_sync_kernel->fence_sync->vaddr;
+ *check_value_pos++ =
+ foreign_sync_kernel->fence_sync->next_value;
+
+ (*update_address_pos++).ui32Addr =
+ foreign_sync_kernel->cleanup_sync->vaddr;
+ *update_value_pos++ =
+ ++foreign_sync_kernel->cleanup_sync->next_value;
+ *cleanup_sync_pos++ = foreign_sync_kernel->cleanup_sync;
+ }
+ }
+ }
+
+ /* Append the update sync (if supplied) */
+ if (sync_data->update_sync_data) {
+ struct pvr_sync_alloc_data *update_data =
+ sync_data->update_sync_data;
+ struct pvr_sync_timeline *timeline =
+ update_data->timeline;
+ struct pvr_sync_kernel_pair *sync_kernel =
+ update_data->sync_data->kernel;
+
+ (*update_address_pos++).ui32Addr =
+ sync_kernel->fence_sync->vaddr;
+ *update_value_pos++ =
+ ++sync_kernel->fence_sync->next_value;
+
+ (*check_address_pos++).ui32Addr =
+ timeline->timeline_sync->vaddr;
+
+ /* Copy the current timeline sync value... */
+ update_data->sync_data->timeline_fence_value =
+ timeline->timeline_sync->next_value;
+
+ /* ...and add it as a check dependency */
+ *check_value_pos++ =
+ update_data->sync_data->timeline_fence_value;
+
+ (*update_address_pos++).ui32Addr =
+ timeline->timeline_sync->vaddr;
+
+ /* Increment the timeline value... */
+ update_data->sync_data->timeline_update_value =
+ ++timeline->timeline_sync->next_value;
+
+ /* ...and set that to be updated when this kick is completed */
+ *update_value_pos++ =
+ update_data->sync_data->timeline_update_value;
+
+
+ /* Reset the fencing enabled flag. If nobody sets this to 1 until the
+ * next fence point is inserted, we will do timeline idle detection. */
+ timeline->fencing_enabled = false;
+ }
+ /* We count the total number of sync points we attach, as it's possible
+ * some have become complete since the first loop through, or a waiter for
+ * a foreign point skipped (But they can never become un-complete, so it
+ * will only ever be the same or less, so the allocated arrays should
+ * still be sufficiently sized) */
+ num_used_sync_updates =
+ update_address_pos - sync_data->update_ufo_addresses;
+ num_used_sync_checks =
+ check_address_pos - sync_data->check_ufo_addresses;
+
+
+ sync_data->nr_checks = nr_checks + num_used_sync_checks;
+ sync_data->nr_updates = nr_updates + num_used_sync_updates;
+ /* Append original check and update sync values/addresses */
+ memcpy(update_address_pos, update_ufo_addresses,
+ sizeof(PRGXFWIF_UFO_ADDR) * nr_updates);
+ memcpy(update_value_pos, update_values,
+ sizeof(u32) * nr_updates);
+
+ memcpy(check_address_pos, check_ufo_addresses,
+ sizeof(PRGXFWIF_UFO_ADDR) * nr_checks);
+ memcpy(check_value_pos, check_values,
+ sizeof(u32) * nr_checks);
+
+ *append_sync_data = sync_data;
+
+ return PVRSRV_OK;
+
+err_free_append_data:
+ pvr_sync_free_append_fences_data(sync_data);
+err_out:
+ return err;
+}
+
+void pvr_sync_rollback_append_fences(struct pvr_sync_append_data *sync_append_data)
+{
+ unsigned i;
+
+ if (!sync_append_data)
+ return;
+
+ for (i = 0; i < sync_append_data->nr_cleaup_syncs; i++) {
+ struct pvr_sync_native_sync_prim *cleanup_sync =
+ sync_append_data->cleanup_syncs[i];
+ /* If this cleanup was called on a partially-created data set
+ * it's possible to have NULL cleanup sync pointers */
+ if (!cleanup_sync)
+ continue;
+ cleanup_sync->next_value--;
+ }
+
+ if (sync_append_data->update_sync_data) {
+ struct pvr_sync_alloc_data *update_sync_data =
+ sync_append_data->update_sync_data;
+ /* We can get a NULL sync_data if the corresponding
+ * append failed with a re-used alloc sync */
+ if (update_sync_data->sync_data) {
+ update_sync_data->sync_data->kernel->fence_sync->next_value--;
+ update_sync_data->timeline->fencing_enabled = true;
+ update_sync_data->timeline->timeline_sync->next_value--;
+ }
+ }
+}
+
+void pvr_sync_free_append_fences_data(struct pvr_sync_append_data *sync_append_data)
+{
+ unsigned i;
+
+ if (!sync_append_data)
+ return;
+
+ for (i = 0; i < sync_append_data->nr_fences; i++) {
+ struct sync_fence *fence = sync_append_data->fences[i];
+ /* If this cleanup was called on a partially-created data set
+ * it's possible to have NULL sync data pointers */
+ if (!fence)
+ continue;
+ sync_fence_put(fence);
+ }
+ if (sync_append_data->update_sync_data) {
+ fput(sync_append_data->update_sync_data->file);
+ }
+ kfree(sync_append_data->update_ufo_addresses);
+ kfree(sync_append_data->update_values);
+ kfree(sync_append_data->check_ufo_addresses);
+ kfree(sync_append_data->check_values);
+ kfree(sync_append_data->cleanup_syncs);
+ kfree(sync_append_data);
+}
+
+void pvr_sync_nohw_complete_fences(struct pvr_sync_append_data *sync_append_data)
+{
+ unsigned i;
+
+ if (!sync_append_data)
+ return;
+
+ for (i = 0; i < sync_append_data->nr_cleaup_syncs; i++) {
+ struct pvr_sync_native_sync_prim *cleanup_sync =
+ sync_append_data->cleanup_syncs[i];
+
+ if (!cleanup_sync)
+ continue;
+
+ complete_sync(cleanup_sync);
+ }
+ if (sync_append_data->update_sync_data) {
+ /* Skip any invalid update syncs (should only be hit on error */
+ if (sync_append_data->update_sync_data->sync_data) {
+ complete_sync(sync_append_data->update_sync_data->sync_data->kernel->fence_sync);
+ set_sync_value(sync_append_data->update_sync_data->timeline->timeline_sync,
+ sync_append_data->update_sync_data->sync_data->timeline_update_value);
+ }
+ }
+}
+
+/* ioctl and fops handling */
+
+static int pvr_sync_open(struct inode *inode, struct file *file)
+{
+ struct pvr_sync_timeline *timeline;
+ enum PVRSRV_ERROR error;
+ char name[32] = {};
+ int err = -ENOMEM;
+
+ task_lock(current);
+ rcu_read_lock();
+
+ if (strncmp(current->group_leader->comm,
+ current->comm, TASK_COMM_LEN) == 0) {
+ snprintf(name, sizeof(name), "%.26s-%d",
+ current->group_leader->comm, current->pid);
+ } else {
+ snprintf(name, sizeof(name), "%.15s-%.10s-%d",
+ current->group_leader->comm, current->comm,
+ current->pid);
+ }
+
+ rcu_read_unlock();
+ task_unlock(current);
+
+ timeline = (struct pvr_sync_timeline *)
+ sync_timeline_create(&pvr_sync_timeline_ops,
+ sizeof(struct pvr_sync_timeline), name);
+ if (!timeline) {
+ pr_err("pvr_sync: %s: sync_timeline_create failed", __func__);
+ goto err_out;
+ }
+
+ OSAcquireBridgeLock();
+
+ error = sync_pool_get(&timeline->timeline_sync, name, SYNC_TL_TYPE);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to allocate sync prim (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ OSReleaseBridgeLock();
+
+ /*
+ * Use a NULL timeline_sync to detect this partially-setup
+ * timeline in the timeline release function (called by
+ * sync_timeline_destroy) and handle it appropriately
+ */
+ timeline->timeline_sync = NULL;
+ goto err_free_tl;
+ }
+
+ OSReleaseBridgeLock();
+
+ timeline->fencing_enabled = true;
+
+ DPF("%s: # %s", __func__,
+ debug_info_timeline((struct sync_timeline *)timeline));
+
+ mutex_lock(&timeline_list_mutex);
+ list_add_tail(&timeline->list, &timeline_list);
+ mutex_unlock(&timeline_list_mutex);
+
+ file->private_data = timeline;
+
+ err = 0;
+err_out:
+ return err;
+
+err_free_tl:
+ sync_timeline_destroy(&timeline->obj);
+ goto err_out;
+}
+
+static int pvr_sync_close(struct inode *inode, struct file *file)
+{
+ struct pvr_sync_timeline *timeline = file->private_data;
+
+ DPF("%s: # %s", __func__,
+ debug_info_timeline((struct sync_timeline *)timeline));
+
+ sync_timeline_destroy(&timeline->obj);
+ return 0;
+}
+
+static void pvr_sync_free_sync_data(struct pvr_sync_data *sync_data)
+{
+ if (sync_data && sync_data->kernel)
+ pvr_sync_defer_free(sync_data->kernel);
+ kfree(sync_data);
+}
+
+static int pvr_sync_alloc_release(struct inode *inode, struct file *file)
+{
+ struct pvr_sync_alloc_data *alloc_sync_data = file->private_data;
+ /* the sync_data may be null if a sync has been created using this
+ * alloc_sync data */
+ pvr_sync_free_sync_data(alloc_sync_data->sync_data);
+ kfree(alloc_sync_data);
+ return 0;
+}
+
+static const struct file_operations pvr_alloc_sync_fops = {
+ .release = pvr_sync_alloc_release,
+};
+
+static struct pvr_sync_alloc_data *pvr_sync_alloc_fence_fdget(int fd)
+{
+ struct file *file = fget(fd);
+
+ if (!file)
+ return NULL;
+ if (file->f_op != &pvr_alloc_sync_fops)
+ goto err;
+ return file->private_data;
+err:
+ fput(file);
+ return NULL;
+}
+
+static long
+pvr_sync_ioctl_create_fence(struct pvr_sync_timeline *timeline,
+ void __user *user_data)
+{
+ struct pvr_sync_create_fence_ioctl_data data;
+ struct pvr_sync_alloc_data *alloc_sync_data;
+ int err = -EFAULT, fd = get_unused_fd();
+ struct pvr_sync_data *sync_data;
+ struct sync_fence *fence;
+ struct sync_pt *sync_pt;
+
+ if (fd < 0) {
+ pr_err("pvr_sync: %s: Failed to find unused fd (%d)",
+ __func__, fd);
+ goto err_out;
+ }
+
+ if (!access_ok(VERIFY_READ, user_data, sizeof(data)))
+ goto err_put_fd;
+
+ if (copy_from_user(&data, user_data, sizeof(data)))
+ goto err_put_fd;
+
+ alloc_sync_data = pvr_sync_alloc_fence_fdget(data.iAllocFenceFd);
+ if (!alloc_sync_data) {
+ pr_err("pvr_sync: %s: Invalid alloc sync fd (%d)\n",
+ __func__, data.iAllocFenceFd);
+ goto err_put_fd;
+ }
+
+ if (alloc_sync_data->timeline != timeline) {
+ pr_err("pvr_sync: %s: Trying to create sync from alloc of timeline %p in timeline %p\n",
+ __func__, alloc_sync_data->timeline, timeline);
+ fput(alloc_sync_data->file);
+ goto err_put_fd;
+ }
+
+ sync_data = alloc_sync_data->sync_data;
+ alloc_sync_data->sync_data = NULL;
+
+ fput(alloc_sync_data->file);
+
+ sync_pt = (struct sync_pt *)
+ pvr_sync_create_sync(timeline, sync_data);
+ if (!sync_pt) {
+ pr_err("pvr_sync: %s: Failed to create a sync point (%d)",
+ __func__, fd);
+ err = -ENOMEM;
+ goto err_free_sync_data;
+ }
+
+ data.szName[sizeof(data.szName) - 1] = '\0';
+
+ DPF("%s: %d('%s') # %s", __func__,
+ fd, data.szName,
+ debug_info_timeline((struct sync_timeline *)timeline));
+
+ fence = sync_fence_create(data.szName, sync_pt);
+ if (!fence) {
+ pr_err("pvr_sync: %s: Failed to create a fence (%d)",
+ __func__, fd);
+ sync_pt_free(sync_pt);
+ err = -ENOMEM;
+ goto err_free_sync_data;
+ }
+
+ data.iFenceFd = fd;
+
+ if (!access_ok(VERIFY_WRITE, user_data, sizeof(data)))
+ goto err_put_fence;
+
+ if (copy_to_user(user_data, &data, sizeof(data)))
+ goto err_put_fence;
+
+ sync_fence_install(fence, fd);
+
+ err = 0;
+err_out:
+ return err;
+
+err_put_fence:
+ sync_fence_put(fence);
+err_free_sync_data:
+ pvr_sync_free_sync_data(sync_data);
+err_put_fd:
+ put_unused_fd(fd);
+ goto err_out;
+}
+
+static long
+pvr_sync_ioctl_alloc_fence(struct pvr_sync_timeline *timeline,
+ void __user *user_data) {
+ struct pvr_sync_alloc_fence_ioctl_data data;
+ int err = -EFAULT, fd = get_unused_fd();
+ struct pvr_sync_data *sync_data;
+ struct pvr_sync_alloc_data *alloc_sync_data;
+ struct file *file;
+
+ if (fd < 0) {
+ pr_err("pvr_sync: %s: Failed to find unused fd (%d)",
+ __func__, fd);
+ goto err_out;
+ }
+
+ if (!access_ok(VERIFY_READ, user_data, sizeof(data)))
+ goto err_put_fd;
+
+ if (!access_ok(VERIFY_WRITE, user_data, sizeof(data)))
+ goto err_put_fd;
+
+ alloc_sync_data =
+ kzalloc(sizeof(struct pvr_sync_alloc_data), GFP_KERNEL);
+ if (!alloc_sync_data) {
+ err = -ENOMEM;
+ pr_err("pvr_sync: %s: Failed to alloc sync data\n", __func__);
+ goto err_put_fd;
+ }
+
+ sync_data = pvr_sync_create_sync_data(timeline);
+ if (!sync_data) {
+ err = -ENOMEM;
+ pr_err("pvr_sync: %s: Failed to create sync data\n", __func__);
+ goto err_free_alloc_data;
+ }
+
+ file = anon_inode_getfile("pvr_sync_alloc", &pvr_alloc_sync_fops,
+ alloc_sync_data, 0);
+ if (!file) {
+ err = -ENOMEM;
+ pr_err("pvr_sync: %s: Failed to create alloc inode\n", __func__);
+ goto err_free_data;
+ }
+
+ alloc_sync_data->file = file;
+ alloc_sync_data->sync_data = sync_data;
+ alloc_sync_data->timeline = timeline;
+
+ data.bTimelineIdle = is_sync_met(timeline->timeline_sync) &&
+ timeline->fencing_enabled == false;
+
+ data.iFenceFd = fd;
+
+ if (!access_ok(VERIFY_WRITE, user_data, sizeof(data)))
+ goto err_free_data;
+
+ if (copy_to_user(user_data, &data, sizeof(data)))
+ goto err_free_data;
+
+ fd_install(fd, file);
+ err = 0;
+
+err_out:
+ return err;
+err_free_data:
+ pvr_sync_free_sync_data(sync_data);
+err_free_alloc_data:
+ kfree(alloc_sync_data);
+err_put_fd:
+ put_unused_fd(fd);
+ goto err_out;
+}
+
+static long
+pvr_sync_ioctl_enable_fencing(struct pvr_sync_timeline *timeline,
+ void __user *user_data)
+{
+ struct pvr_sync_enable_fencing_ioctl_data data;
+ int err = -EFAULT;
+
+ if (!access_ok(VERIFY_READ, user_data, sizeof(data)))
+ goto err_out;
+
+ if (copy_from_user(&data, user_data, sizeof(data)))
+ goto err_out;
+
+ timeline->fencing_enabled = data.bFencingEnabled;
+ err = 0;
+err_out:
+ return err;
+}
+
+static long
+pvr_sync_ioctl_debug_fence(struct pvr_sync_timeline *timeline,
+ void __user *user_data)
+{
+ struct pvr_sync_debug_fence_ioctl_data data;
+ int err = 0;
+
+ if (!access_ok(VERIFY_READ, user_data, sizeof(data))) {
+ err = -EFAULT;
+ goto err_out;
+ }
+
+ if (copy_from_user(&data, user_data, sizeof(data))) {
+ err = -EFAULT;
+ goto err_out;
+ }
+
+ err = pvr_sync_debug_fence(data.iFenceFd,
+ data.szName,
+ sizeof(data.szName),
+ &data.i32Status,
+ PVR_SYNC_MAX_QUERY_FENCE_POINTS,
+ &data.ui32NumSyncs,
+ data.aPts);
+ if (err)
+ goto err_out;
+
+ if (!access_ok(VERIFY_WRITE, user_data, sizeof(data))) {
+ err = -EFAULT;
+ goto err_out;
+ }
+
+ if (copy_to_user(user_data, &data, sizeof(data))) {
+ err = -EFAULT;
+ goto err_out;
+ }
+
+err_out:
+ return err;
+}
+
+static long
+pvr_sync_ioctl(struct file *file, unsigned int cmd, unsigned long __user arg)
+{
+ struct pvr_sync_timeline *timeline = file->private_data;
+ void __user *user_data = (void __user *)arg;
+ long err = -ENOTTY;
+
+ switch (cmd) {
+ case PVR_SYNC_IOC_CREATE_FENCE:
+ err = pvr_sync_ioctl_create_fence(timeline, user_data);
+ break;
+ case PVR_SYNC_IOC_ENABLE_FENCING:
+ err = pvr_sync_ioctl_enable_fencing(timeline, user_data);
+ break;
+ case PVR_SYNC_IOC_DEBUG_FENCE:
+ err = pvr_sync_ioctl_debug_fence(timeline, user_data);
+ break;
+ case PVR_SYNC_IOC_ALLOC_FENCE:
+ err = pvr_sync_ioctl_alloc_fence(timeline, user_data);
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
+static void
+pvr_sync_check_status_work_queue_function(struct work_struct *data)
+{
+ /* A completed SW operation may un-block the GPU */
+ PVRSRVCheckStatus(NULL);
+}
+
+/* Returns true if the freelist still has entries, else false if empty */
+static bool
+pvr_sync_clean_freelist(void)
+{
+ struct pvr_sync_kernel_pair *kernel, *k;
+ struct pvr_sync_fence *sync_fence, *f;
+ LIST_HEAD(unlocked_free_list);
+ unsigned long flags;
+ bool freelist_empty;
+
+ /* We can't call PVRSRVServerSyncFreeKM 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
+ * in a second loop. */
+
+ spin_lock_irqsave(&sync_prim_free_list_spinlock, flags);
+ list_for_each_entry_safe(kernel, k, &sync_prim_free_list, list) {
+ /* Check if this sync is not used anymore. */
+ if (!is_sync_met(kernel->fence_sync) ||
+ (kernel->cleanup_sync &&
+ !is_sync_met(kernel->cleanup_sync))) {
+ continue;
+ }
+
+ /* Remove the entry from the free list. */
+ list_move_tail(&kernel->list, &unlocked_free_list);
+ }
+
+ /* Wait and loop if there are still syncs on the free list (IE
+ * are still in use by the HW) */
+ freelist_empty = list_empty(&sync_prim_free_list);
+
+ spin_unlock_irqrestore(&sync_prim_free_list_spinlock, flags);
+
+ OSAcquireBridgeLock();
+
+ list_for_each_entry_safe(kernel, k, &unlocked_free_list, list) {
+ list_del(&kernel->list);
+
+ sync_pool_put(kernel->fence_sync);
+ if (kernel->cleanup_sync)
+ sync_pool_put(kernel->cleanup_sync);
+ kfree(kernel);
+ }
+
+ OSReleaseBridgeLock();
+
+ /* sync_fence_put() must be called from process/WQ context
+ * because it uses fput(), which is not allowed to be called
+ * from interrupt context in kernels <3.6.
+ */
+ INIT_LIST_HEAD(&unlocked_free_list);
+
+ spin_lock_irqsave(&sync_fence_put_list_spinlock, flags);
+ list_for_each_entry_safe(sync_fence, f, &sync_fence_put_list, list) {
+ list_move_tail(&sync_fence->list, &unlocked_free_list);
+ }
+ spin_unlock_irqrestore(&sync_fence_put_list_spinlock, flags);
+
+ list_for_each_entry_safe(sync_fence, f, &unlocked_free_list, list) {
+ list_del(&sync_fence->list);
+ sync_fence_put(sync_fence->fence);
+ kfree(sync_fence);
+ }
+
+ return !freelist_empty;
+}
+
+static void
+pvr_sync_defer_free_work_queue_function(struct work_struct *data)
+{
+ enum PVRSRV_ERROR error = PVRSRV_OK;
+ void *event_object;
+
+ error = OSEventObjectOpen(pvr_sync_data.event_object_handle,
+ &event_object);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Error opening event object (%s)\n",
+ __func__, PVRSRVGetErrorStringKM(error));
+ return;
+
+ }
+
+ while (pvr_sync_clean_freelist()) {
+
+ error = OSEventObjectWait(event_object);
+
+ switch (error) {
+
+ case PVRSRV_OK:
+ case PVRSRV_ERROR_TIMEOUT:
+ /* Timeout is normal behaviour */
+ continue;
+ default:
+ pr_err("pvr_sync: %s: Error waiting for event object (%s)\n",
+ __func__, PVRSRVGetErrorStringKM(error));
+ break;
+ }
+ }
+ error = OSEventObjectClose(event_object);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Error closing event object (%s)\n",
+ __func__, PVRSRVGetErrorStringKM(error));
+ }
+}
+
+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_update_all_timelines(void *command_complete_handle)
+{
+ struct pvr_sync_tl_to_signal *timeline_to_signal, *n;
+ struct pvr_sync_timeline *timeline;
+ LIST_HEAD(timeline_to_signal_list);
+ struct sync_pt *sync_pt;
+ unsigned long flags;
+ bool signal;
+
+ mutex_lock(&timeline_list_mutex);
+ list_for_each_entry(timeline, &timeline_list, list) {
+ signal = false;
+
+ spin_lock_irqsave(&timeline->obj.active_list_lock, flags);
+ list_for_each_entry(sync_pt, &timeline->obj.active_list_head,
+ active_list) {
+ if (sync_pt->parent->ops != &pvr_sync_timeline_ops)
+ continue;
+
+ DPF("%s: check # %s", __func__,
+ debug_info_sync_pt(sync_pt));
+
+ /* Check for any points which weren't signaled before,
+ * but are now. If so, mark it for signaling and stop
+ * processing this timeline. */
+ if (sync_pt->status != 0)
+ continue;
+
+ DPF("%s: signal # %s", __func__,
+ debug_info_sync_pt(sync_pt));
+
+ /* Create a new entry for the list of timelines which
+ * needs to be signaled. There are two reasons for not
+ * doing it right now: It is not possible to signal the
+ * timeline while holding the spinlock or the mutex.
+ * pvr_sync_release_timeline may be called by
+ * timeline_signal which will acquire the mutex as well
+ * and the spinlock itself is also used within
+ * timeline_signal. */
+ signal = true;
+ break;
+ }
+ spin_unlock_irqrestore(&timeline->obj.active_list_lock, flags);
+
+ if (signal) {
+ timeline_to_signal =
+ kmalloc(sizeof(struct pvr_sync_tl_to_signal),
+ GFP_KERNEL);
+ if (!timeline_to_signal)
+ break;
+
+ timeline_to_signal->timeline = timeline;
+ list_add_tail(&timeline_to_signal->list,
+ &timeline_to_signal_list);
+ }
+
+ }
+ mutex_unlock(&timeline_list_mutex);
+
+ /* It is safe to call timeline_signal at this point without holding the
+ * timeline mutex. We know the timeline can't go away until we have
+ * called timeline_signal cause the current active point still holds a
+ * kref to the parent. However, when timeline_signal returns the actual
+ * timeline structure may be invalid. */
+ list_for_each_entry_safe(timeline_to_signal, n,
+ &timeline_to_signal_list, list) {
+ struct sync_timeline *timeline =
+ (struct sync_timeline *)timeline_to_signal->timeline;
+ sync_timeline_signal(timeline);
+ list_del(&timeline_to_signal->list);
+ kfree(timeline_to_signal);
+ }
+}
+
+enum PVRSRV_ERROR pvr_sync_init(void)
+{
+ enum PVRSRV_ERROR error;
+ int err;
+
+ DPF("%s", __func__);
+
+ atomic_set(&pvr_sync_data.sync_id, 0);
+
+ error = PVRSRVAcquireDeviceDataKM(0, PVRSRV_DEVICE_TYPE_RGX,
+ &pvr_sync_data.device_cookie);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to initialise services (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ goto err_out;
+ }
+
+ error = AcquireGlobalEventObjectServer(
+ &pvr_sync_data.event_object_handle);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to acquire global event object (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ goto err_release_device_data;
+ }
+
+ OSAcquireBridgeLock();
+
+ error = SyncPrimContextCreate(0,
+ pvr_sync_data.device_cookie,
+ &pvr_sync_data.sync_prim_context);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to create sync prim context (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ OSReleaseBridgeLock();
+ goto err_release_event_object;
+ }
+
+ OSReleaseBridgeLock();
+
+ pvr_sync_data.defer_free_wq =
+ create_freezable_workqueue("pvr_sync_defer_free_workqueue");
+ if (!pvr_sync_data.defer_free_wq) {
+ pr_err("pvr_sync: %s: Failed to create pvr_sync defer_free workqueue",
+ __func__);
+ goto err_free_sync_context;
+ }
+
+ INIT_WORK(&pvr_sync_data.defer_free_work,
+ pvr_sync_defer_free_work_queue_function);
+
+ pvr_sync_data.check_status_wq =
+ create_freezable_workqueue("pvr_sync_check_status_workqueue");
+ if (!pvr_sync_data.check_status_wq) {
+ pr_err("pvr_sync: %s: Failed to create pvr_sync check_status workqueue",
+ __func__);
+ goto err_destroy_defer_free_wq;
+ }
+
+ INIT_WORK(&pvr_sync_data.check_status_work,
+ pvr_sync_check_status_work_queue_function);
+ error = PVRSRVRegisterCmdCompleteNotify(
+ &pvr_sync_data.command_complete_handle,
+ &pvr_sync_update_all_timelines,
+ &pvr_sync_data.device_cookie);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to register MISR notification (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ goto err_destroy_status_wq;
+ }
+
+ error = PVRSRVRegisterDbgRequestNotify(
+ &pvr_sync_data.debug_notify_handle,
+ pvr_sync_debug_request,
+ DEBUG_REQUEST_ANDROIDSYNC,
+ NULL);
+ if (error != PVRSRV_OK) {
+ pr_err("pvr_sync: %s: Failed to register debug notifier (%s)",
+ __func__, PVRSRVGetErrorStringKM(error));
+ goto err_unregister_cmd_complete;
+ }
+
+ err = misc_register(&pvr_sync_device);
+ if (err) {
+ pr_err("pvr_sync: %s: Failed to register pvr_sync device (%d)",
+ __func__, err);
+ error = PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
+ goto err_unregister_dbg;
+ }
+
+ error = PVRSRV_OK;
+ return error;
+
+err_unregister_dbg:
+ PVRSRVUnregisterDbgRequestNotify(pvr_sync_data.debug_notify_handle);
+err_unregister_cmd_complete:
+ PVRSRVUnregisterCmdCompleteNotify(
+ pvr_sync_data.command_complete_handle);
+err_destroy_status_wq:
+ destroy_workqueue(pvr_sync_data.check_status_wq);
+err_destroy_defer_free_wq:
+ destroy_workqueue(pvr_sync_data.defer_free_wq);
+err_free_sync_context:
+ OSAcquireBridgeLock();
+ SyncPrimContextDestroy(pvr_sync_data.sync_prim_context);
+ OSReleaseBridgeLock();
+err_release_event_object:
+ ReleaseGlobalEventObjectServer(pvr_sync_data.event_object_handle);
+err_release_device_data:
+ PVRSRVReleaseDeviceDataKM(pvr_sync_data.device_cookie);
+err_out:
+
+ return error;
+}
+
+void pvr_sync_deinit(void)
+{
+ DPF("%s", __func__);
+
+ misc_deregister(&pvr_sync_device);
+
+ PVRSRVUnregisterDbgRequestNotify(pvr_sync_data.debug_notify_handle);
+
+ PVRSRVUnregisterCmdCompleteNotify(
+ pvr_sync_data.command_complete_handle);
+
+ /* This will drain the workqueue, so we guarantee that all deferred
+ * syncs are free'd before returning */
+ destroy_workqueue(pvr_sync_data.defer_free_wq);
+ destroy_workqueue(pvr_sync_data.check_status_wq);
+
+ OSAcquireBridgeLock();
+
+ sync_pool_clear();
+
+ SyncPrimContextDestroy(pvr_sync_data.sync_prim_context);
+
+ OSReleaseBridgeLock();
+
+ ReleaseGlobalEventObjectServer(pvr_sync_data.event_object_handle);
+
+ PVRSRVReleaseDeviceDataKM(pvr_sync_data.device_cookie);
+}
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.h b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.h
new file mode 100644
index 000000000000..9fdd14b55ba0
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/pvr_sync.h
@@ -0,0 +1,91 @@
+/*************************************************************************/ /*!
+@File pvr_sync.h
+@Title Kernel driver for Android's sync mechanism
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+#ifndef _PVR_SYNC_H
+#define _PVR_SYNC_H
+
+#include "pvr_fd_sync_user.h"
+#include "rgx_fwif_shared.h"
+
+/* Services internal interface */
+enum PVRSRV_ERROR pvr_sync_init(void);
+void pvr_sync_deinit(void);
+
+struct pvr_sync_append_data
+{
+ u32 nr_updates;
+ PRGXFWIF_UFO_ADDR *update_ufo_addresses;
+ u32 *update_values;
+ u32 nr_checks;
+ PRGXFWIF_UFO_ADDR *check_ufo_addresses;
+ u32 *check_values;
+
+ /* The cleanup list is needed for rollback (as that's the only op taken) */
+ u32 nr_cleaup_syncs;
+ struct pvr_sync_native_sync_prim **cleanup_syncs;
+
+ /* Keep the sync points around for fput and if rollback is needed */
+ struct pvr_sync_alloc_data *update_sync_data;
+ u32 nr_fences;
+ struct sync_fence *fences[];
+};
+
+enum PVRSRV_ERROR
+pvr_sync_append_fences(
+ const char *name,
+ const u32 nr_check_fences,
+ const s32 *check_fence_fds,
+ const s32 update_fence_fd,
+ const u32 nr_updates,
+ const PRGXFWIF_UFO_ADDR *update_ufo_addresses,
+ const u32 *update_values,
+ const u32 nr_checks,
+ const PRGXFWIF_UFO_ADDR *check_ufo_addresses,
+ const u32 *check_values,
+ struct pvr_sync_append_data **append_sync_data);
+
+void pvr_sync_rollback_append_fences(struct pvr_sync_append_data *sync_check_data);
+void pvr_sync_nohw_complete_fences(struct pvr_sync_append_data *sync_check_data);
+void pvr_sync_free_append_fences_data(struct pvr_sync_append_data *sync_check_data);
+
+#endif /* _PVR_SYNC_H */
diff --git a/drivers/gpu/rogue/kernel/drivers/staging/imgtec/services_kernel_client.h b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/services_kernel_client.h
new file mode 100644
index 000000000000..74211b518ee7
--- /dev/null
+++ b/drivers/gpu/rogue/kernel/drivers/staging/imgtec/services_kernel_client.h
@@ -0,0 +1,152 @@
+/*************************************************************************/ /*!
+@File services_kernel_client.h
+@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.
+*/ /**************************************************************************/
+/* vi: set ts=8: */
+
+/* This file contains a partial redefinition of the PowerVR Services 5
+ * interface for use by components which are checkpatch clean. This
+ * header is included by the unrefined, non-checkpatch clean headers
+ * to ensure that prototype/typedef/macro changes break the build.
+ */
+
+#ifndef __SERVICES_KERNEL_CLIENT__
+#define __SERVICES_KERNEL_CLIENT__
+
+#include "debug_request_ids.h"
+#include "pvrsrv_error.h"
+
+#include <linux/types.h>
+
+#ifndef __pvrsrv_defined_struct_enum__
+
+/* pvrsrv_device_types.h */
+
+enum PVRSRV_DEVICE_TYPE {
+ PVRSRV_DEVICE_TYPE_RGX = 10,
+};
+
+/* sync_external.h */
+
+struct PVRSRV_CLIENT_SYNC_PRIM {
+ volatile __u32 *pui32LinAddr;
+};
+
+struct PVRSRV_CLIENT_SYNC_PRIM_OP {
+ __u32 ui32Flags;
+ struct pvrsrv_sync_prim *psSync;
+ __u32 ui32FenceValue;
+ __u32 ui32UpdateValue;
+};
+
+#else /* __pvrsrv_defined_struct_enum__ */
+
+enum PVRSRV_DEVICE_TYPE;
+struct PVRSRV_CLIENT_SYNC_PRIM;
+struct PVRSRV_CLIENT_SYNC_PRIM_OP;
+
+#endif /* __pvrsrv_defined_struct_enum__ */
+
+struct SYNC_PRIM_CONTEXT;
+
+/* pvrsrv.h */
+
+#define DEBUG_REQUEST_VERBOSITY_LOW 0
+#define DEBUG_REQUEST_VERBOSITY_MEDIUM 1
+#define DEBUG_REQUEST_VERBOSITY_HIGH 2
+#define DEBUG_REQUEST_VERBOSITY_MAX (DEBUG_REQUEST_VERBOSITY_HIGH)
+
+typedef void (DUMPDEBUG_PRINTF_FUNC)(const char *fmt, ...) __printf(1, 2);
+
+extern DUMPDEBUG_PRINTF_FUNC *g_pfnDumpDebugPrintf;
+
+typedef void (*PFN_CMDCOMP_NOTIFY)(void *hCmdCompHandle);
+enum PVRSRV_ERROR PVRSRVRegisterCmdCompleteNotify(void **phNotify,
+ PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify, void *hPrivData);
+enum PVRSRV_ERROR PVRSRVUnregisterCmdCompleteNotify(void *hNotify);
+
+typedef void (*PFN_DBGREQ_NOTIFY) (void *hDebugRequestHandle,
+ __u32 ui32VerbLevel);
+enum PVRSRV_ERROR PVRSRVRegisterDbgRequestNotify(void **phNotify,
+ PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
+ __u32 ui32RequesterID, void *hDbgReqeustHandle);
+enum PVRSRV_ERROR PVRSRVUnregisterDbgRequestNotify(void *hNotify);
+
+enum PVRSRV_ERROR PVRSRVAcquireDeviceDataKM(__u32 ui32DevIndex,
+ enum PVRSRV_DEVICE_TYPE eDeviceType, void **phDevCookie);
+enum PVRSRV_ERROR PVRSRVReleaseDeviceDataKM(void *hDevCookie);
+void PVRSRVCheckStatus(void *hCmdCompCallerHandle);
+enum PVRSRV_ERROR AcquireGlobalEventObjectServer(void **phGlobalEventObject);
+enum PVRSRV_ERROR ReleaseGlobalEventObjectServer(void *hGlobalEventObject);
+
+/* sync.h */
+
+enum PVRSRV_ERROR SyncPrimContextCreate(void *hBridge, void *hDeviceNode,
+ struct SYNC_PRIM_CONTEXT **phSyncPrimContext);
+void SyncPrimContextDestroy(struct SYNC_PRIM_CONTEXT *hSyncPrimContext);
+
+enum PVRSRV_ERROR SyncPrimAlloc(struct SYNC_PRIM_CONTEXT *hSyncPrimContext,
+ struct PVRSRV_CLIENT_SYNC_PRIM **ppsSync, const char * pszClassName);
+void SyncPrimFree(struct PVRSRV_CLIENT_SYNC_PRIM *psSync);
+__u32 SyncPrimGetFirmwareAddr(struct PVRSRV_CLIENT_SYNC_PRIM *psSync);
+
+/* pdump_km.h */
+
+#ifdef PDUMP
+enum PVRSRV_ERROR __printf(1, 2) PDumpComment(char *fmt, ...);
+#else
+static inline enum PVRSRV_ERROR __printf(1, 2) PDumpComment(char *fmt, ...)
+{
+ return PVRSRV_OK;
+}
+#endif
+
+/* osfunc.h */
+
+void OSAcquireBridgeLock(void);
+void OSReleaseBridgeLock(void);
+enum PVRSRV_ERROR OSEventObjectWait(void *hOSEventKM);
+enum PVRSRV_ERROR OSEventObjectOpen(void *hEventObject, void **phOSEventKM);
+enum PVRSRV_ERROR OSEventObjectClose(void *hOSEventKM);
+
+/* srvkm.h */
+
+const char *PVRSRVGetErrorStringKM(enum PVRSRV_ERROR eError);
+
+#endif /* __SERVICES_KERNEL_CLIENT__ */
diff --git a/drivers/gpu/rogue/services/include/cache_defines.h b/drivers/gpu/rogue/services/include/cache_defines.h
new file mode 100644
index 000000000000..7779e51d8886
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/cache_defines.h
@@ -0,0 +1,52 @@
+/*************************************************************************/ /*!
+@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 _CACHE_DEFINES_H_
+
+#define CACHEFLUSH_GENERIC 1
+#define CACHEFLUSH_X86 2
+
+#if CACHEFLUSH_TYPE == 0
+#error Unknown cache flush type, please addd to cache_defines.h
+#endif
+
+#endif /* _CACHE_DEFINES_H_ */
+
diff --git a/drivers/gpu/rogue/services/include/dc_common.h b/drivers/gpu/rogue/services/include/dc_common.h
new file mode 100644
index 000000000000..8b2b5943f37f
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/dc_common.h
@@ -0,0 +1,74 @@
+/*************************************************************************/ /*!
+@File
+@Title Common Display Class header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines DC specific structures which are shared within services
+ only
+@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 "services.h"
+
+#ifndef _DC_COMMON_H_
+#define _DC_COMMON_H_
+
+typedef struct _DC_FBC_CREATE_INFO_
+{
+ IMG_UINT32 ui32FBCWidth; /*!< Pixel width that the FBC module is working on */
+ IMG_UINT32 ui32FBCHeight; /*!< Pixel height that the FBC module is working on */
+ IMG_UINT32 ui32FBCStride; /*!< Pixel stride that the FBC module is working on */
+ IMG_UINT32 ui32Size; /*!< Size of the buffer to create */
+} DC_FBC_CREATE_INFO;
+
+typedef struct _DC_CREATE_INFO_
+{
+ union {
+ DC_FBC_CREATE_INFO sFBC;
+ } u;
+} DC_CREATE_INFO;
+
+typedef struct _DC_BUFFER_CREATE_INFO_
+{
+ PVRSRV_SURFACE_INFO sSurface; /*!< Surface properies, specificed by user */
+ IMG_UINT32 ui32BPP; /*!< Bits per pixel */
+ union {
+ DC_FBC_CREATE_INFO sFBC; /*!< Frame buffer compressed specific data */
+ } u;
+} DC_BUFFER_CREATE_INFO;
+
+#endif /* _DC_COMMON_H_ */
diff --git a/drivers/gpu/rogue/services/include/env/linux/ion_sys.h b/drivers/gpu/rogue/services/include/env/linux/ion_sys.h
new file mode 100644
index 000000000000..1e5a60d66a95
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/env/linux/ion_sys.h
@@ -0,0 +1,76 @@
+/*************************************************************************/ /*!
+@File ion_sys.c
+@Title System level interface for Ion
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This file defined the API between services and system layer
+ required for Ion integration.
+@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 _ION_SYS_H_
+#define _ION_SYS_H_
+
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include PVR_ANDROID_ION_HEADER
+
+
+PVRSRV_ERROR IonInit(void *phPrivateData);
+
+struct ion_device *IonDevAcquire(IMG_VOID);
+
+IMG_VOID IonDevRelease(struct ion_device *psIonDev);
+
+IMG_UINT32 IonPhysHeapID(IMG_VOID);
+
+#if defined(LMA)
+IMG_DEV_PHYADDR IonCPUPhysToDevPhys(IMG_CPU_PHYADDR sCPUPhysAddr,
+ IMG_UINT32 ui32Offset);
+#else
+/* This is a no-op for UMA systems. */
+static inline
+IMG_DEV_PHYADDR IonCPUPhysToDevPhys(IMG_CPU_PHYADDR sCPUPhysAddr,
+ IMG_UINT32 ui32Offset)
+{
+ return (IMG_DEV_PHYADDR){ .uiAddr = sCPUPhysAddr.uiAddr + ui32Offset };
+}
+#endif
+
+IMG_VOID IonDeinit(IMG_VOID);
+
+#endif /* _ION_SYS_H_ */
diff --git a/drivers/gpu/rogue/services/include/env/linux/pvr_bridge_io.h b/drivers/gpu/rogue/services/include/env/linux/pvr_bridge_io.h
new file mode 100644
index 000000000000..2944bb3109d0
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/env/linux/pvr_bridge_io.h
@@ -0,0 +1,69 @@
+/*************************************************************************/ /*!
+@File
+@Title PVR Bridge IO Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@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 __PVR_BRIDGE_IO_H__
+#define __PVR_BRIDGE_IO_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <linux/ioctl.h>
+#include "pvrsrv_error.h"
+
+/*!< Nov 2006: according to ioctl-number.txt 'g' wasn't in use. */
+#define PVRSRV_IOC_GID 'g'
+#define PVRSRV_IO(INDEX) _IO(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+#define PVRSRV_IOW(INDEX) _IOW(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+#define PVRSRV_IOR(INDEX) _IOR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+#define PVRSRV_IOWR(INDEX) _IOWR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PVR_BRIDGE_IO_H__ */
+
+/******************************************************************************
+ End of file (pvr_bridge_io.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/include/kerneldisplay.h b/drivers/gpu/rogue/services/include/kerneldisplay.h
new file mode 100644
index 000000000000..b1e7e99c6aec
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/kerneldisplay.h
@@ -0,0 +1,598 @@
+/*************************************************************************/ /*!
+@File
+@Title Interface for 3rd party display class (DC) drivers
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description API between services and the 3rd party DC driver and vice versa
+@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 (__KERNELDISPLAY_H__)
+#define __KERNELDISPLAY_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "pvrsrv_surface.h"
+#include "dc_external.h"
+#include "dc_common.h"
+
+/*************************************************************************/ /*!
+@Function GetInfo
+
+@Description Query the display controller for its information structure
+
+@Input hDeviceData Device private data
+
+@Output psDisplayInfo Display info structure
+
+@Return PVRSRV_OK if the query was successful
+*/
+/*****************************************************************************/
+typedef IMG_VOID (*GetInfo)(IMG_HANDLE hDeviceData,
+ DC_DISPLAY_INFO *psDisplayInfo);
+
+/*************************************************************************/ /*!
+@Function PanelQueryCount
+
+@Description Query the display controller for how many panels are
+ contented to it.
+
+@Input hDeviceData Device private data
+
+@Output pui32NumPanels Number of panels
+
+@Return PVRSRV_OK if the query was successful
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PanelQueryCount)(IMG_HANDLE hDeviceData,
+ IMG_UINT32 *ppui32NumPanels);
+
+/*************************************************************************/ /*!
+@Function PanelQuery
+
+@Description Query the display controller for information on what panel(s)
+ are connected to it and their properties.
+
+@Input hDeviceData Device private data
+
+@Input ui32PanelsArraySize Size of the format and dimension
+ array size (i.e. number of panels
+ that can be returned)
+
+@Output pui32NumPanels Number of panels returned
+
+@Output pasFormat Array of formats
+
+@Output pasDims Array of dimensions
+
+@Return PVRSRV_OK if the query was successful
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*PanelQuery)(IMG_HANDLE hDeviceData,
+ IMG_UINT32 ui32PanelsArraySize,
+ IMG_UINT32 *pui32NumPanels,
+ PVRSRV_PANEL_INFO *pasPanelInfo);
+
+/*************************************************************************/ /*!
+@Function FormatQuery
+
+@Description Query the display controller to see if it supports the specified
+ format(s).
+
+@Input hDeviceData Device private data
+
+@Input ui32NumFormats Number of formats to check
+
+@Input pasFormat Array of formats to check
+
+@Output pui32Supported For each format, the number of display
+ pipes that support that format
+
+@Return PVRSRV_OK if the query was successful
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*FormatQuery)(IMG_HANDLE hDeviceData,
+ IMG_UINT32 ui32NumFormats,
+ PVRSRV_SURFACE_FORMAT *pasFormat,
+ IMG_UINT32 *pui32Supported);
+
+/*************************************************************************/ /*!
+@Function DimQuery
+
+@Description Query the specificed display plane for the display dimensions
+ it supports.
+
+@Input hDeviceData Device private data
+
+@Input ui32NumDims Number of dimensions to check
+
+@Input pasDim Array of dimentations to check
+
+@Output pui32Supported For each dimension, the number of
+ display pipes that support that
+ dimension
+
+@Return PVRSRV_OK if the query was successful
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*DimQuery)(IMG_HANDLE hDeviceData,
+ IMG_UINT32 ui32NumDims,
+ PVRSRV_SURFACE_DIMS *psDim,
+ IMG_UINT32 *pui32Supported);
+
+
+/*************************************************************************/ /*!
+@Function SetBlank
+
+@Description Enable/disable blanking of the screen
+
+@Input psConnection Services connection
+
+@Input hDevice 3rd party display class device
+
+@Input bEnabled Enable/Disable the blanking
+
+@Return PVRSRV_OK on success
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*SetBlank)(IMG_HANDLE hDeviceData,
+ IMG_BOOL bEnabled);
+
+/*************************************************************************/ /*!
+@Function SetVSyncReporting
+
+@Description Enable VSync reporting by trigger the global event object on
+ every vsync happened.
+
+@Input psConnection Services connection
+
+@Input hDevice 3rd party display class device
+
+@Input bEnabled Enable/Disable the reporting
+
+@Return PVRSRV_OK on success
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*SetVSyncReporting)(IMG_HANDLE hDeviceData,
+ IMG_BOOL bEnabled);
+
+/*************************************************************************/ /*!
+@Function PVRSRVDCLastVSyncQuery
+
+@Description Query the time the last vsync happened.
+
+@Input psConnection Services connection
+
+@Input hDevice 3rd party display class device
+
+@Output pi64Timestamp the requested timestamp
+
+@Return PVRSRV_OK if the query was successful
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*LastVSyncQuery)(IMG_HANDLE hDeviceData,
+ IMG_INT64 *pi64Timestamp);
+
+typedef PVRSRV_ERROR (*BufferSystemAcquire)(IMG_HANDLE hDeviceData,
+ IMG_DEVMEM_LOG2ALIGN_T *puiLog2PageSize,
+ IMG_UINT32 *pui32PageCount,
+ IMG_UINT32 *pui32PhysHeapID,
+ IMG_UINT32 *pui32ByteStride,
+ IMG_HANDLE *phSystemBuffer);
+
+typedef IMG_VOID (*BufferSystemRelease)(IMG_HANDLE hSystemBuffer);
+
+/*************************************************************************/ /*!
+@Function ContextCreate
+
+@Description Create display context.
+
+@Input hDeviceData Device private data
+
+@Output hDisplayContext Created display context
+
+@Return PVRSRV_OK if the context was created
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*ContextCreate)(IMG_HANDLE hDeviceData,
+ IMG_HANDLE *hDisplayContext);
+
+/*************************************************************************/ /*!
+@Function ContextConfigureCheck
+
+@Description Check to see if a configuration is valid for the display
+ controller.
+
+ Note: This function is optional
+
+@Input hDisplayContext Display context
+
+@Input ui32PipeCount Number of display pipes to configure
+
+@Input pasSurfAttrib Array of surface attributes (one for
+ each display plane)
+
+@Input ahBuffers Array of buffers (one for
+ each display plane)
+
+@Return PVRSRV_OK if the configuration is valid
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*ContextConfigureCheck)(IMG_HANDLE hDisplayContext,
+ IMG_UINT32 ui32PipeCount,
+ PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+ IMG_HANDLE *ahBuffers);
+
+/*************************************************************************/ /*!
+@Function ContextConfigure
+
+@Description Configuration the display pipeline.
+
+@Input hDisplayContext Display context
+
+@Input ui32PipeCount Number of display pipes to configure
+
+@Input pasSurfAttrib Array of surface attributes (one for
+ each display plane)
+
+@Input ahBuffers Array of buffers (one for
+ each display plane)
+
+@Input ui32DisplayPeriod The number of VSync periods this
+ configuration should be displayed for
+
+@Input hConfigData Config handle which gets passed to
+ DisplayConfigurationRetired when this
+ configuration is retired
+
+@Return PVRSRV_OK if the configuration was successfully queued
+*/
+/*****************************************************************************/
+typedef IMG_VOID (*ContextConfigure)(IMG_HANDLE hDisplayContext,
+ IMG_UINT32 ui32PipeCount,
+ PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+ IMG_HANDLE *ahBuffers,
+ IMG_UINT32 ui32DisplayPeriod,
+ IMG_HANDLE hConfigData);
+
+/*************************************************************************/ /*!
+@Function ContextDestroy
+
+@Description Destroy a display context.
+
+@Input hDisplayContext Display context to destroy
+
+@Return None
+*/
+/*****************************************************************************/
+typedef IMG_VOID (*ContextDestroy)(IMG_HANDLE hDisplayContext);
+
+/*************************************************************************/ /*!
+@Function BufferAlloc
+
+@Description Allocate a display buffer. This is a request to the display
+ controller to allocate a buffer from memory that is addressable
+ by the display controller.
+
+ Note: The actual allocation of display memory can be deferred
+ until the first call to acquire, but the handle for the buffer
+ still needs to be created and returned to the caller as well
+ as some information about the buffer that's required upfront.
+
+@Input hDisplayContext Display context this buffer will be
+ used on
+
+@Input psSurfInfo Attributes of the buffer
+
+@Output puiLog2PageSize Log2 of the pagesize of the buffer
+
+@Output pui32PageCount Number of pages in the buffer
+
+@Output pui32PhysHeapID Physcial heap ID to use
+
+@Output pui32ByteStride Stride (in bytes) of allocated buffer
+
+@Output phBuffer Handle to allocated buffer
+
+@Return PVRSRV_OK if the buffer was successfully allocated
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*BufferAlloc)(IMG_HANDLE hDisplayContext,
+ DC_BUFFER_CREATE_INFO *psSurfInfo,
+ IMG_DEVMEM_LOG2ALIGN_T *puiLog2PageSize,
+ IMG_UINT32 *pui32PageCount,
+ IMG_UINT32 *pui32PhysHeapID,
+ IMG_UINT32 *pui32ByteStride,
+ IMG_HANDLE *phBuffer);
+
+/*************************************************************************/ /*!
+@Function BufferImport
+
+@Description Import memory allocated from an external source to the display
+ controller. The DC checks to see if the import is compatible
+ and potentially sets up HW to map the imported buffer, although
+ this isn't require to happen until the first call to DCBufferMap
+
+ Note: This is optional
+
+@Input hDisplayContext Display context this buffer will be
+ used on
+
+@Input ui32NumPlanes Number of planes
+
+@Input pahImport Array of handles (one per colour channel)
+
+@Input psSurfAttrib Surface attributes of the buffer
+
+@Output phBuffer Handle to imported buffer
+
+@Return PVRSRV_OK if the buffer was successfully imported
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*BufferImport)(IMG_HANDLE hDisplayContext,
+ IMG_UINT32 ui32NumPlanes,
+ IMG_HANDLE **paphImport,
+ DC_BUFFER_IMPORT_INFO *psSurfAttrib,
+ IMG_HANDLE *phBuffer);
+
+/*************************************************************************/ /*!
+@Function BufferAcquire
+
+@Description Acquire the buffer's physcial memory pages. If the buffer doesn't
+ have any memory backing it yet then this will trigger the 3rd
+ party driver to allocate it.
+
+ Note: The page count isn't passed back in this function as
+ services has already obtained it during BufferAlloc.
+
+@Input hBuffer Handle to the buffer
+
+@Output pasDevPAddr Array of device physical page address
+ of this buffer
+
+@Output pvLinAddr CPU virtual address of buffer. This is
+ optionial but if you have one you must
+ return it otherwise return NULL.
+
+@Return PVRSRV_OK if the buffer was successfully acquired
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*BufferAcquire)(IMG_HANDLE hBuffer,
+ IMG_DEV_PHYADDR *pasDevPAddr,
+ IMG_PVOID *ppvLinAddr);
+
+/*************************************************************************/ /*!
+@Function BufferRelease
+
+@Description Release the buffer's physcial memory pages.
+
+@Input hBuffer Handle to the buffer
+
+@Return None
+*/
+/*****************************************************************************/
+typedef IMG_VOID (*BufferRelease)(IMG_HANDLE hBuffer);
+
+/*************************************************************************/ /*!
+@Function BufferFree
+
+@Description Release a reference to the device buffer. If this was the last
+ reference the 3rd party driver is entitled to free the backing
+ memory.
+
+@Input hBuffer Buffer handle we're releasing
+
+@Return None
+*/
+/*****************************************************************************/
+typedef IMG_VOID (*BufferFree)(IMG_HANDLE hBuffer);
+
+/*************************************************************************/ /*!
+@Function BufferMap
+
+@Description Map the buffer into the display controller
+
+ Note: This function is optional
+
+@Input hBuffer Buffer to map
+
+@Return PVRSRV_OK if the buffer was successfully mapped
+*/
+/*****************************************************************************/
+typedef PVRSRV_ERROR (*BufferMap)(IMG_HANDLE hBuffer);
+
+/*************************************************************************/ /*!
+@Function BufferUnmap
+
+@Description Unmap a buffer from the display controller
+
+ Note: This function is optional
+
+@Input hBuffer Buffer to unmap
+
+@Return None
+*/
+/*****************************************************************************/
+typedef IMG_VOID (*BufferUnmap)(IMG_HANDLE hBuffer);
+
+
+/*
+ Function table for server->display
+*/
+typedef struct _DC_DEVICE_FUNCTIONS_
+{
+ /*! Mandatory query functions */
+ GetInfo pfnGetInfo;
+ PanelQueryCount pfnPanelQueryCount;
+ PanelQuery pfnPanelQuery;
+ FormatQuery pfnFormatQuery;
+ DimQuery pfnDimQuery;
+
+ /*! Optional blank/vsync function */
+ SetBlank pfnSetBlank;
+ SetVSyncReporting pfnSetVSyncReporting;
+ LastVSyncQuery pfnLastVSyncQuery;
+
+ /*! Mandatory configure function */
+ ContextCreate pfnContextCreate;
+ ContextDestroy pfnContextDestroy;
+ ContextConfigure pfnContextConfigure;
+
+ /*! Optional context function */
+ ContextConfigureCheck pfnContextConfigureCheck;
+
+ /*! Mandatory buffer functions */
+ BufferAlloc pfnBufferAlloc;
+ BufferAcquire pfnBufferAcquire;
+ BufferRelease pfnBufferRelease;
+ BufferFree pfnBufferFree;
+
+ /*! Optional buffer functions, pfnBufferMap and pfnBufferUnmap are paired
+ functions, provide both or neither */
+ BufferImport pfnBufferImport;
+ BufferMap pfnBufferMap;
+ BufferUnmap pfnBufferUnmap;
+ BufferSystemAcquire pfnBufferSystemAcquire;
+ BufferSystemRelease pfnBufferSystemRelease;
+} DC_DEVICE_FUNCTIONS;
+
+
+/*
+ functions exported by kernel services for use by 3rd party kernel display
+ class device driver
+*/
+
+/*************************************************************************/ /*!
+@Function DCRegisterDevice
+
+@Description Register a display class device
+
+@Input psFuncTable Callback function table
+
+@Input ui32MaxConfigsInFlight The maximum number of configs that this
+ display device can have in-flight.
+
+@Input hDeviceData 3rd party device handle, passed into
+ DC callbacks
+
+@Output phSrvHandle Services handle to pass back into
+ UnregisterDCDevice
+
+@Return PVRSRV_OK if the display class driver was successfully registered
+*/
+/*****************************************************************************/
+PVRSRV_ERROR DCRegisterDevice(DC_DEVICE_FUNCTIONS *psFuncTable,
+ IMG_UINT32 ui32MaxConfigsInFlight,
+ IMG_HANDLE hDeviceData,
+ IMG_HANDLE *phSrvHandle);
+
+/*************************************************************************/ /*!
+@Function DCUnregisterDevice
+
+@Description Unregister a display class device
+
+@Input hDevice Services device handle
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID DCUnregisterDevice(IMG_HANDLE hSrvHandle);
+
+/*************************************************************************/ /*!
+@Function DCDisplayConfigurationRetired
+
+@Description Called when a configuration as been retired due to a new
+ configuration now being active.
+
+@Input hConfigData ConfigData that is being retired
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID DCDisplayConfigurationRetired(IMG_HANDLE hConfigData);
+
+/*************************************************************************/ /*!
+@Function DCImportBufferAcquire
+
+@Description Acquire information about a buffer that was imported with
+ BufferImport.
+
+@Input hImport Import buffer
+
+@Input uiLog2PageSize Log 2 of the DC's page size
+
+@Output pui32PageCount Size of the buffer in pages
+
+@Output ppasDevPAddr Array of device physcial page address
+ of this buffer
+
+@Return PVRSRV_OK if the import buffer was successfully acquired
+*/
+/*****************************************************************************/
+PVRSRV_ERROR DCImportBufferAcquire(IMG_HANDLE hImport,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize,
+ IMG_UINT32 *pui32PageCount,
+ IMG_DEV_PHYADDR **ppasDevPAddr);
+
+/*************************************************************************/ /*!
+@Function DCImportBufferRelease
+
+@Description Release an imported buffer.
+
+@Input hImport Import handle we're releasing
+
+@Input pasDevPAddr Import data was returned from
+ DCImportBufferAcquire
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID DCImportBufferRelease(IMG_HANDLE hImport,
+ IMG_DEV_PHYADDR *pasDevPAddr);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif/* #if !defined (__KERNELDISPLAY_H__) */
+
+/******************************************************************************
+ End of file (kerneldisplay.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/include/pdump.h b/drivers/gpu/rogue/services/include/pdump.h
new file mode 100644
index 000000000000..9467c5dbd3b6
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/pdump.h
@@ -0,0 +1,76 @@
+/*************************************************************************/ /*!
+@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 _SERVICES_PDUMP_H_
+#define _SERVICES_PDUMP_H_
+
+#include "img_types.h"
+
+typedef IMG_UINT32 PDUMP_FLAGS_T;
+
+
+#define PDUMP_FLAGS_DEINIT 0x20000000UL /*<! Output this entry to the de-initialisation section */
+
+#define PDUMP_FLAGS_POWER 0x08000000UL /*<! Output this entry even when a power transition is ongoing */
+
+#define PDUMP_FLAGS_CONTINUOUS 0x40000000UL /*<! Output this entry always regardless of framed capture range,
+ used by client applications being dumped. */
+#define PDUMP_FLAGS_PERSISTENT 0x80000000UL /*<! Output this entry always regardless of app and range,
+ used by persistent processes e.g. compositor, window mgr etc/ */
+
+#define PDUMP_FLAGS_DEBUG 0x00010000U /*<! For internal debugging use */
+
+#define PDUMP_FLAGS_NOHW 0x00000001U /* For internal use: Skip sending instructions to the hardware */
+
+#define PDUMP_FILEOFFSET_FMTSPEC "0x%08X"
+typedef IMG_UINT32 PDUMP_FILEOFFSET_T;
+
+#define PDUMP_PARAM_CHANNEL_NAME "ParamChannel2"
+#define PDUMP_SCRIPT_CHANNEL_NAME "ScriptChannel2"
+
+#define PDUMP_CHANNEL_PARAM 0
+#define PDUMP_CHANNEL_SCRIPT 1
+#define PDUMP_NUM_CHANNELS 2
+
+#define PDUMP_PARAM_0_FILE_NAME "%%0%%.prm"
+#define PDUMP_PARAM_N_FILE_NAME "%%0%%_%02u.prm"
+
+
+#endif /* _SERVICES_PDUMP_H_ */
diff --git a/drivers/gpu/rogue/services/include/physheap.h b/drivers/gpu/rogue/services/include/physheap.h
new file mode 100644
index 000000000000..1f63969b11df
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/physheap.h
@@ -0,0 +1,120 @@
+/*************************************************************************/ /*!
+@File
+@Title Physcial heap management header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines the interface for the physical heap management
+@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"
+
+#ifndef _PHYSHEAP_H_
+#define _PHYSHEAP_H_
+
+typedef struct _PHYS_HEAP_ PHYS_HEAP;
+
+typedef IMG_VOID (*CpuPAddrToDevPAddr)(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr);
+
+typedef IMG_VOID (*DevPAddrToCpuPAddr)(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+typedef struct _PHYS_HEAP_FUNCTIONS_
+{
+ /*! Translate CPU physical address to device physical address */
+ CpuPAddrToDevPAddr pfnCpuPAddrToDevPAddr;
+ /*! Translate device physical address to CPU physical address */
+ DevPAddrToCpuPAddr pfnDevPAddrToCpuPAddr;
+} PHYS_HEAP_FUNCTIONS;
+
+typedef enum _PHYS_HEAP_TYPE_
+{
+ PHYS_HEAP_TYPE_UNKNOWN = 0,
+ PHYS_HEAP_TYPE_UMA,
+ PHYS_HEAP_TYPE_LMA,
+} PHYS_HEAP_TYPE;
+
+typedef struct _PHYS_HEAP_CONFIG_
+{
+ IMG_UINT32 ui32PhysHeapID;
+ PHYS_HEAP_TYPE eType;
+ /*
+ Note:
+ sStartAddr and uiSize are only required for LMA heaps
+ */
+ IMG_CPU_PHYADDR sStartAddr;
+ IMG_UINT64 uiSize;
+ IMG_CHAR *pszPDumpMemspaceName;
+ PHYS_HEAP_FUNCTIONS *psMemFuncs;
+ IMG_HANDLE hPrivData;
+} PHYS_HEAP_CONFIG;
+
+PVRSRV_ERROR PhysHeapRegister(PHYS_HEAP_CONFIG *psConfig,
+ PHYS_HEAP **ppsPhysHeap);
+
+IMG_VOID PhysHeapUnregister(PHYS_HEAP *psPhysHeap);
+
+PVRSRV_ERROR PhysHeapAcquire(IMG_UINT32 ui32PhysHeapID,
+ PHYS_HEAP **ppsPhysHeap);
+
+IMG_VOID PhysHeapRelease(PHYS_HEAP *psPhysHeap);
+
+PHYS_HEAP_TYPE PhysHeapGetType(PHYS_HEAP *psPhysHeap);
+
+PVRSRV_ERROR PhysHeapGetAddress(PHYS_HEAP *psPhysHeap,
+ IMG_CPU_PHYADDR *psCpuPAddr);
+
+PVRSRV_ERROR PhysHeapGetSize(PHYS_HEAP *psPhysHeap,
+ IMG_UINT64 *puiSize);
+
+IMG_VOID PhysHeapCpuPAddrToDevPAddr(PHYS_HEAP *psPhysHeap,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr);
+IMG_VOID PhysHeapDevPAddrToCpuPAddr(PHYS_HEAP *psPhysHeap,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+IMG_CHAR *PhysHeapPDumpMemspaceName(PHYS_HEAP *psPhysHeap);
+
+PVRSRV_ERROR PhysHeapInit(IMG_VOID);
+PVRSRV_ERROR PhysHeapDeinit(IMG_VOID);
+
+#endif /* _PHYSHEAP_H_ */
diff --git a/drivers/gpu/rogue/services/include/pvr_bridge.h b/drivers/gpu/rogue/services/include/pvr_bridge.h
new file mode 100644
index 000000000000..61805194811d
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/pvr_bridge.h
@@ -0,0 +1,213 @@
+/*************************************************************************/ /*!
+@File
+@Title PVR Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@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 __PVR_BRIDGE_H__
+#define __PVR_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "pvrsrv_error.h"
+#include "cache_defines.h"
+
+#if defined(SUPPORT_DISPLAY_CLASS)
+#include "common_dc_bridge.h"
+#endif
+#include "common_mm_bridge.h"
+#if defined(UNDER_CE)
+#include "common_mmpmr_bridge.h"
+#endif
+#if defined(SUPPORT_MMPLAT_BRIDGE)
+#include "common_mmplat_bridge.h"
+#endif
+#include "common_cmm_bridge.h"
+#include "common_pdumpmm_bridge.h"
+#include "common_pdumpcmm_bridge.h"
+#if defined(SUPPORT_PMMIF)
+#include "common_pmmif_bridge.h"
+#endif
+#if defined(SUPPORT_ION)
+#include "common_dmabuf_bridge.h"
+#endif
+#include "common_pdump_bridge.h"
+#include "common_srvcore_bridge.h"
+#include "common_sync_bridge.h"
+#if defined(SUPPORT_INSECURE_EXPORT)
+#include "common_syncexport_bridge.h"
+#endif
+#if defined(SUPPORT_SECURE_EXPORT)
+#include "common_syncsexport_bridge.h"
+#endif
+#if (CACHEFLUSH_TYPE == CACHEFLUSH_GENERIC)
+#include "common_cachegeneric_bridge.h"
+#endif
+#if defined(SUPPORT_SECURE_EXPORT)
+#include "common_smm_bridge.h"
+#endif
+#include "common_pvrtl_bridge.h"
+#if defined(PVR_RI_DEBUG)
+#include "common_ri_bridge.h"
+#endif
+
+#include "pvr_bridge_io.h"
+/*
+ * Bridge Cmd Ids
+ */
+
+
+/* Note: The pattern
+ * #if !defined(SUPPORT_FEATURE)
+ * #define PVRSRV_BRIDGE_FEATURE_CMD_LAST (PVRSRV_BRIDGE_FEATURE_START - 1)
+ * #endif
+ * is used in the macro definitions below to make PVRSRV_BRIDGE_FEATURE_*
+ * take up no command numbers if SUPPORT_FEATURE is disabled. If
+ * SUPPORT_FEATURE is enabled, the last command number will be provided by
+ * its header (common_feature_bridge.h).
+ */
+
+#define PVRSRV_BRIDGE_CORE_CMD_FIRST 0UL
+
+/* Core functions */
+#define PVRSRV_BRIDGE_SRVCORE_START (PVRSRV_BRIDGE_CORE_CMD_FIRST)
+
+/* Sync functions */
+#define PVRSRV_BRIDGE_SYNC_START (PVRSRV_BRIDGE_SRVCORE_CMD_LAST + 1)
+
+#define PVRSRV_BRIDGE_SYNCEXPORT_START (PVRSRV_BRIDGE_SYNC_CMD_LAST + 1)
+#if !defined(SUPPORT_INSECURE_EXPORT)
+#define PVRSRV_BRIDGE_SYNCEXPORT_CMD_LAST (PVRSRV_BRIDGE_SYNCEXPORT_START - 1)
+#endif
+#define PVRSRV_BRIDGE_SYNCSEXPORT_START (PVRSRV_BRIDGE_SYNCEXPORT_CMD_LAST + 1)
+#if !defined(SUPPORT_SECURE_EXPORT)
+#define PVRSRV_BRIDGE_SYNCSEXPORT_CMD_LAST (PVRSRV_BRIDGE_SYNCSEXPORT_START - 1)
+#endif
+
+/* PDUMP */
+#define PVRSRV_BRIDGE_PDUMP_START (PVRSRV_BRIDGE_SYNCSEXPORT_CMD_LAST + 1)
+
+/* Memory Management */
+#define PVRSRV_BRIDGE_MM_START (PVRSRV_BRIDGE_PDUMP_CMD_LAST + 1)
+
+#define PVRSRV_BRIDGE_MMPLAT_START (PVRSRV_BRIDGE_MM_CMD_LAST + 1)
+#if !defined(SUPPORT_MMPLAT_BRIDGE)
+#define PVRSRV_BRIDGE_MMPLAT_CMD_LAST (PVRSRV_BRIDGE_MMPLAT_START - 1)
+#endif
+
+#define PVRSRV_BRIDGE_MMPMR_START (PVRSRV_BRIDGE_MMPLAT_CMD_LAST + 1)
+#if !defined(UNDER_CE)
+#define PVRSRV_BRIDGE_MMPMR_CMD_LAST (PVRSRV_BRIDGE_MMPMR_START - 1)
+#endif
+
+#define PVRSRV_BRIDGE_CMM_START (PVRSRV_BRIDGE_MMPMR_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_PDUMPMM_START (PVRSRV_BRIDGE_CMM_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_PDUMPCMM_START (PVRSRV_BRIDGE_PDUMPMM_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_PMMIF_START (PVRSRV_BRIDGE_PDUMPCMM_CMD_LAST + 1)
+#if !defined(SUPPORT_PMMIF)
+#define PVRSRV_BRIDGE_PMMIF_CMD_LAST (PVRSRV_BRIDGE_PMMIF_START - 1)
+#endif
+#define PVRSRV_BRIDGE_DMABUF_START (PVRSRV_BRIDGE_PMMIF_CMD_LAST + 1)
+#if !defined(SUPPORT_ION)
+#define PVRSRV_BRIDGE_DMABUF_CMD_LAST (PVRSRV_BRIDGE_DMABUF_START - 1)
+#endif
+
+/* Display Class */
+#define PVRSRV_BRIDGE_DC_START (PVRSRV_BRIDGE_DMABUF_CMD_LAST + 1)
+#if !defined(SUPPORT_DISPLAY_CLASS)
+#define PVRSRV_BRIDGE_DC_CMD_LAST (PVRSRV_BRIDGE_DC_START - 1)
+#endif
+
+/* Generic cache interface */
+#define PVRSRV_BRIDGE_CACHEGENERIC_START (PVRSRV_BRIDGE_DC_CMD_LAST + 1)
+#if (CACHEFLUSH_TYPE != CACHEFLUSH_GENERIC)
+#define PVRSRV_BRIDGE_CACHEGENERIC_CMD_LAST (PVRSRV_BRIDGE_CACHEGENERIC_START - 1)
+#endif
+
+#define PVRSRV_BRIDGE_SMM_START (PVRSRV_BRIDGE_CACHEGENERIC_CMD_LAST + 1)
+#if !defined(SUPPORT_SECURE_EXPORT)
+#define PVRSRV_BRIDGE_SMM_CMD_LAST (PVRSRV_BRIDGE_SMM_START - 1)
+#endif
+
+
+/* Transport Layer interface */
+#define PVRSRV_BRIDGE_PVRTL_START (PVRSRV_BRIDGE_SMM_CMD_LAST + 1)
+
+/* RI interface */
+#define PVRSRV_BRIDGE_RI_START (PVRSRV_BRIDGE_PVRTL_CMD_LAST + 1)
+#if !defined(PVR_RI_DEBUG)
+#define PVRSRV_BRIDGE_RI_CMD_LAST (PVRSRV_BRIDGE_RI_START - 1)
+#endif
+
+
+/* For rgx_bridge.h. "last" below means last+1 (first beyond last) */
+#define PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD (PVRSRV_BRIDGE_RI_CMD_LAST)
+
+/******************************************************************************
+ * Generic bridge structures
+ *****************************************************************************/
+
+
+/******************************************************************************
+ * bridge packaging structure
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_PACKAGE_TAG
+{
+ IMG_UINT32 ui32BridgeID; /*!< ioctl/drvesc index */
+ IMG_UINT32 ui32Size; /*!< size of structure */
+ IMG_VOID *pvParamIn; /*!< input data buffer */
+ IMG_UINT32 ui32InBufferSize; /*!< size of input data buffer */
+ IMG_VOID *pvParamOut; /*!< output data buffer */
+ IMG_UINT32 ui32OutBufferSize; /*!< size of output data buffer */
+}PVRSRV_BRIDGE_PACKAGE;
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PVR_BRIDGE_H__ */
+
+/******************************************************************************
+ End of file (pvr_bridge.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/include/pvr_bridge_client.h b/drivers/gpu/rogue/services/include/pvr_bridge_client.h
new file mode 100644
index 000000000000..1bc193ea6a39
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/pvr_bridge_client.h
@@ -0,0 +1,80 @@
+/*************************************************************************/ /*!
+@File
+@Title PVR Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@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 __PVR_BRIDGE_U_H__
+#define __PVR_BRIDGE_U_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+
+/******************************************************************************
+ * Function prototypes
+ *****************************************************************************/
+#if(__SIZEOF_POINTER__ == 4)
+IMG_EXPORT IMG_BOOL PVRSRVIsKernel64Bit(void);
+#endif
+
+PVRSRV_ERROR OpenServices(IMG_HANDLE *phServices, IMG_UINT32 ui32SrvFlags);
+PVRSRV_ERROR CloseServices(IMG_HANDLE hServices);
+PVRSRV_ERROR PVRSRVBridgeCall(IMG_HANDLE hServices,
+ IMG_UINT32 ui32FunctionID,
+ IMG_VOID *pvParamIn,
+ IMG_UINT32 ui32InBufferSize,
+ IMG_VOID *pvParamOut,
+ IMG_UINT32 ui32OutBufferSize);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __PVR_BRIDGE_U_H__ */
+
+/******************************************************************************
+ End of file (pvr_bridge_u.h)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/rogue/services/include/pvr_tl.h b/drivers/gpu/rogue/services/include/pvr_tl.h
new file mode 100644
index 000000000000..c557d1df27f2
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/pvr_tl.h
@@ -0,0 +1,198 @@
+/*************************************************************************/ /*!
+@File
+@Title Services Transport Layer UM Client API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description User mode Transport layer API for clients.
+@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 __PVR_TL_H__
+#define __PVR_TL_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#include "img_defs.h"
+#include "pvrsrv_error.h"
+#include "services.h"
+
+#include "pvr_tlcommon.h"
+
+
+/**************************************************************************/ /*!
+ @Function PVRSRVTLConnect
+ @Description Initialise connection to Services kernel server transport layer
+ @Output ppsConnection Address of a pointer to a connection object
+ @Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVTLConnect(PVRSRV_CONNECTION **ppsConnection);
+
+
+/**************************************************************************/ /*!
+ @Function PVRSRVTLDisconnect
+ @Description Disconnect from the Services kernel server transport layer
+ @Input psConnection Pointer to connection object as returned from
+ PVRSRVTLConnect()
+ @Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVTLDisconnect(PVRSRV_CONNECTION* psConnection);
+
+
+/**************************************************************************/ /*!
+ @Function PVRSRVTLOpenStream
+ @Description Open a descriptor onto an existing PVR transport stream. If
+ the stream does not exist it returns a NOT_FOUND error unless
+ the OPEN_WAIT flag is supplied. In this case it will wait for
+ the stream to be created. If it is not created in the wait
+ period a TIMEOUT error is returned.
+ @Input psConnection Address of a pointer to a connection object
+ @Input pszName Address of the stream name string, no longer
+ than PRVSRVTL_MAX_STREAM_NAME_SIZE.
+ @Input ui32Mode Flags defined in pvr_tlcommon.h
+ ACQUIRE_NONBLOCKING: Results in non-blocking reads
+ on stream. Reads are blocking by default
+ OPEN_WAIT: Causes open to wait for a brief moment
+ if the stream does not exist
+ @Output phSD Address of a pointer to an stream object
+ @Return PVRSRV_ERROR_NOT_FOUND: when named stream not found
+ @Return PVRSRV_ERROR_ALREADY_OPEN: stream already open by another
+ @Return PVRSRV_ERROR_STREAM_ERROR: internal driver state error
+ @Return PVRSRV_ERROR_TIMEOUT: block timed out, stream not found
+ @Return PVRSRV_ERROR: for other system codes
+*/ /***************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVTLOpenStream(PVRSRV_CONNECTION* psConnection,
+ IMG_PCHAR pszName,
+ IMG_UINT32 ui32Mode,
+ PVRSRVTL_SD* phSD);
+
+
+/**************************************************************************/ /*!
+ @Function PVRSRVTLCloseStream
+ @Description Close and release the stream connection to Services kernel
+ server transport layer. Any outstanding Acquire will be
+ released.
+ @Input psConnection Address of a pointer to a connection object
+ @Input hSD Handle of the stream object to close
+ @Return PVRSRV_ERROR_HANDLE_NOT_FOUND: when SD handle is not known
+ @Return PVRSRV_ERROR_STREAM_ERROR: internal driver state error
+ @Return PVRSRV_ERROR: for system codes
+*/ /***************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVTLCloseStream(PVRSRV_CONNECTION* psConnection,
+ PVRSRVTL_SD hSD);
+
+
+/**************************************************************************/ /*!
+ @Function PVRSRVTLAcquireData
+ @Description When there is data available in the stream buffer this call
+ returns with the address and length of the data buffer the
+ client can safely read. This buffer may contain one or more
+ packets of data.
+ If no data is available then this call blocks until it becomes
+ available. However if the stream has been destroyed while
+ waiting then a resource unavailable error will be returned
+ to the caller. Clients must pair this call with a
+ ReleaseData call.
+ @Input psConnection Address of a pointer to a connection object
+ @Input hSD Handle of the stream object to read
+ @Output ppPacketBuf Address of a pointer to an byte buffer. On exit
+ pointer contains address of buffer to read from
+ @Output puiBufLen Pointer to an integer. On exit it is the size
+ of the data to read from the packet buffer
+ @Return PVRSRV_ERROR_RESOURCE_UNAVAILABLE: when stream no longer exists
+ @Return PVRSRV_ERROR_HANDLE_NOT_FOUND: when SD handle not known
+ @Return PVRSRV_ERROR_STREAM_ERROR: internal driver state error
+ @Return PVRSRV_ERROR_RETRY: release not called beforehand
+ @Return PVRSRV_ERROR_TIMEOUT: block timed out, no data
+ @Return PVRSRV_ERROR: for other system codes
+*/ /***************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVTLAcquireData(PVRSRV_CONNECTION* psConnection,
+ PVRSRVTL_SD hSD,
+ IMG_PBYTE* ppPacketBuf,
+ IMG_UINT32* puiBufLen);
+
+
+/**************************************************************************/ /*!
+ @Function PVRSRVTLReleaseData
+ @Description Called after client has read the stream data out of the buffer
+ The data is subsequently flushed from the stream buffer to make
+ room for more data packets from the stream source.
+ @Input psConnection Address of a pointer to a connection object
+ @Input hSD Handle of the stream object to read
+ @Return PVRSRV_ERROR_RESOURCE_UNAVAILABLE: when stream no longer exists
+ @Return PVRSRV_ERROR_HANDLE_NOT_FOUND: when SD handle not known to TL
+ @Return PVRSRV_ERROR_STREAM_ERROR: internal driver state error
+ @Return PVRSRV_ERROR_RETRY: acquire not called beforehand
+ @Return PVRSRV_ERROR: for system codes
+*/ /***************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVTLReleaseData(PVRSRV_CONNECTION* psConnection,
+ PVRSRVTL_SD hSD);
+
+
+
+
+
+
+/**************************************************************************/ /*!
+ @Function PVRSRVTLTestIoctl
+ @Description INTERNAL USE: DEBUG builds only
+*/ /***************************************************************************/
+IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVTLTestIoctl(
+ PVRSRV_CONNECTION* psConnection,
+ IMG_UINT32 uiCmd, IMG_BYTE* pbIn1, IMG_UINT32 uiIn2,
+ IMG_UINT32* puiOut1, IMG_UINT32* puiOut2);
+
+
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PVR_TL_H__ */
+
+/******************************************************************************
+ End of file (pvr_tl.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/include/pvr_tlcommon.h b/drivers/gpu/rogue/services/include/pvr_tlcommon.h
new file mode 100644
index 000000000000..63c31b2eb884
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/pvr_tlcommon.h
@@ -0,0 +1,193 @@
+/*************************************************************************/ /*!
+@File
+@Title Services Transport Layer common types and definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Transport layer common types and definitions included into
+ both user mode and kernel mode source.
+@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 __PVR_TLCOMMON_H__
+#define __PVR_TLCOMMON_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+
+
+/*! Handle type for stream descriptor objects as created by this API */
+typedef IMG_HANDLE PVRSRVTL_SD;
+
+
+/*! Maximum stream name length including the null byte */
+#define PRVSRVTL_MAX_STREAM_NAME_SIZE 20U
+
+/*! Packet lengths are always rounded up to a multiple of 4 bytes */
+#define PVRSRVTL_PACKET_ALIGNMENT 4U
+#define PVRSRVTL_ALIGN(x) ((x+PVRSRVTL_PACKET_ALIGNMENT-1) & ~(PVRSRVTL_PACKET_ALIGNMENT-1))
+
+
+/*! A packet is made up of a header structure followed by the data bytes.
+ * There are 3 types of packet: normal (has data), data lost and padding,
+ * see packet flags. Header kept small to reduce data overhead.
+ *
+ * if the ORDER of the structure members is changed, please UPDATE the
+ * PVRSRVTL_PACKET_FLAG_OFFSET macro.
+ */
+typedef struct _PVRSRVTL_PACKETHDR_
+{
+ IMG_UINT16 uiDataLen; /*!< Number of bytes following header */
+ IMG_UINT16 uiFlags; /*!< Packet flag word */
+
+ /* First bytes of data ... */
+ //IMG_UINT32 ui32Data; // ... variable length data array
+
+} PVRSRVTL_PACKETHDR, *PVRSRVTL_PPACKETHDR;
+
+/* Structure must always be a size multiple of 4 as stream buffer
+ * still an array of IMG_UINT32s.
+ */
+BLD_ASSERT((sizeof(PVRSRVTL_PACKETHDR)&3)==0, pvr_tlcommon_h)
+
+/*! Packet header mask used to extract the type from the uiFlags member.
+ * Do not use directly, \see TEST_PACKET_FLAG
+ */
+#define PVRSRVTL_PACKETHDR_TYPE_MASK 0x000f
+
+/*! Packet header mask used to extract the flags from the uiFlags member.
+ * Do not use directly, \see GET_PACKET_TYPE
+ */
+#define PVRSRVTL_PACKETHDR_FLAG_MASK 0xfff0
+
+/*! Packet type enumeration.
+ */
+typedef enum _PVRSRVTL_PACKETTYPE_
+{
+ /*! 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,
+
+ PVRSRVTL_PACKETTYPE_LAST = PVRSRVTL_PACKETTYPE_MARKER_EOS
+} PVRSRVTL_PACKETTYPE;
+
+/* 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_PACKET_FLAG_OFFSET (8 * sizeof( ((PVRSRVTL_PACKETHDR *)NULL)->uiDataLen ))
+#define PVRSRVTL_SET_PACKET_DATA(len) (len) | (PVRSRVTL_PACKETTYPE_DATA <<PVRSRVTL_PACKET_FLAG_OFFSET)
+#define PVRSRVTL_SET_PACKET_PADDING(len) (len) | (PVRSRVTL_PACKETTYPE_PADDING <<PVRSRVTL_PACKET_FLAG_OFFSET)
+#define PVRSRVTL_SET_PACKET_HDR(len,type) (len) | ((type) <<PVRSRVTL_PACKET_FLAG_OFFSET)
+#define PVRSRVTL_SET_PACKET_WRITE_FAILED (PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED <<PVRSRVTL_PACKET_FLAG_OFFSET)
+
+/*! Returns the number of bytes of data in the packet. p may be any address type
+ * */
+#define GET_PACKET_DATA_LEN(p) \
+ ((IMG_UINT32) ((PVRSRVTL_PPACKETHDR)(p))->uiDataLen )
+
+/*! Returns a IMG_BYTE* pointer to the first byte of data in the packet */
+#define GET_PACKET_DATA_PTR(p) \
+ ((IMG_PBYTE) ( ((IMG_SIZE_T)p) + sizeof(PVRSRVTL_PACKETHDR)) )
+
+/*! Given a PVRSRVTL_PPACKETHDR address, return the address of the next pack
+ * It is up to the caller to determine if the new address is within the packet
+ * buffer.
+ */
+#define GET_NEXT_PACKET_ADDR(p) \
+ ((PVRSRVTL_PPACKETHDR) ( ((IMG_UINT8 *)p) + sizeof(PVRSRVTL_PACKETHDR) + \
+ (((((PVRSRVTL_PPACKETHDR)p)->uiDataLen) + \
+ (PVRSRVTL_PACKET_ALIGNMENT-1)) & (~(PVRSRVTL_PACKET_ALIGNMENT-1)) ) ))
+
+/*! Turns the packet address p into a PVRSRVTL_PPACKETHDR pointer type
+ */
+#define GET_PACKET_HDR(p) ((PVRSRVTL_PPACKETHDR)(p))
+
+/*! Get the type of the packet. p is of type PVRSRVTL_PPACKETHDR
+ */
+#define GET_PACKET_TYPE(p) (((p)->uiFlags & PVRSRVTL_PACKETHDR_TYPE_MASK))
+
+/*! Tests if a packet flag is set or not. p is of type PVRSRVTL_PPACKETHDR and
+ * f is one of the flags
+ */
+#define TEST_PACKET_FLAG(p, f) ((p->uiFlags & (f)) ? IMG_TRUE : IMG_FALSE)
+
+
+/*! Flags for use with PVRSRVTLOpenStream
+ * 0x01 - Do not block in PVRSRVTLAcquireData() when no bytes are available
+ * 0x02 - When the stream does not exist wait for a bit (2s) in
+ * PVRSRVTLOpenStream() and then exit with a timeout error if it still
+ * does not exist.
+ */
+#define PVRSRV_STREAM_FLAG_NONE (1U<<0)
+#define PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING (1U<<1)
+#define PVRSRV_STREAM_FLAG_OPEN_WAIT (1U<<2)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PVR_TLCOMMON_H__ */
+/******************************************************************************
+ End of file (pvr_tlcommon.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/include/rgx_bridge.h b/drivers/gpu/rogue/services/include/rgx_bridge.h
new file mode 100644
index 000000000000..4482b9c4a668
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/rgx_bridge.h
@@ -0,0 +1,99 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the rgx Bridge code
+@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(__RGX_BRIDGE_H__)
+#define __RGX_BRIDGE_H__
+
+#include "pvr_bridge.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "common_rgxinit_bridge.h"
+#include "common_rgxta3d_bridge.h"
+#include "common_rgxcmp_bridge.h"
+#include "common_rgxtq_bridge.h"
+#include "common_breakpoint_bridge.h"
+#include "common_debugmisc_bridge.h"
+#include "common_rgxpdump_bridge.h"
+#include "common_rgxhwperf_bridge.h"
+#if defined(RGX_FEATURE_RAY_TRACING)
+#include "common_rgxray_bridge.h"
+#endif
+#include "common_regconfig_bridge.h"
+#include "common_timerquery_bridge.h"
+
+/*
+ * Bridge Cmd Ids
+ */
+
+/* *REMEMBER* to update PVRSRV_BRIDGE_LAST_RGX_CMD if you add/remove a command!
+ * Also you need to ensure all PVRSRV_BRIDGE_RGX_CMD_BASE+ offsets are sequential!
+ */
+
+#define PVRSRV_BRIDGE_RGX_CMD_BASE (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+
+/* "last" below actually means last, not plus 1 as elsewhere */
+#define PVRSRV_BRIDGE_RGXTQ_START (PVRSRV_BRIDGE_RGX_CMD_BASE + 0)
+#define PVRSRV_BRIDGE_RGXCMP_START (PVRSRV_BRIDGE_RGXTQ_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_RGXINIT_START (PVRSRV_BRIDGE_RGXCMP_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_RGXTA3D_START (PVRSRV_BRIDGE_RGXINIT_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_BREAKPOINT_START (PVRSRV_BRIDGE_RGXTA3D_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_DEBUGMISC_START (PVRSRV_BRIDGE_BREAKPOINT_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_RGXPDUMP_START (PVRSRV_BRIDGE_DEBUGMISC_CMD_LAST +1)
+#define PVRSRV_BRIDGE_RGXHWPERF_START (PVRSRV_BRIDGE_RGXPDUMP_CMD_LAST +1)
+#define PVRSRV_BRIDGE_RGXRAY_START (PVRSRV_BRIDGE_RGXHWPERF_CMD_LAST +1)
+#ifndef RGX_FEATURE_RAY_TRACING
+#define PVRSRV_BRIDGE_RGXRAY_CMD_LAST (PVRSRV_BRIDGE_RGXRAY_START -1)
+#endif
+#define PVRSRV_BRIDGE_REGCONFIG_START (PVRSRV_BRIDGE_RGXRAY_CMD_LAST +1)
+#define PVRSRV_BRIDGE_TIMERQUERY_START (PVRSRV_BRIDGE_REGCONFIG_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_LAST_RGX_CMD (PVRSRV_BRIDGE_TIMERQUERY_CMD_LAST)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __RGX_BRIDGE_H__ */
+
diff --git a/drivers/gpu/rogue/services/include/rgx_fwif.h b/drivers/gpu/rogue/services/include/rgx_fwif.h
new file mode 100644
index 000000000000..f68554c5dc0b
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/rgx_fwif.h
@@ -0,0 +1,467 @@
+/*************************************************************************/ /*!
+@File rgx_fwif.h
+@Title RGX firmware interface structures
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX firmware interface structures used by srvinit and server
+@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 (__RGX_FWIF_H__)
+#define __RGX_FWIF_H__
+
+#include "rgx_meta.h"
+#include "rgx_fwif_shared.h"
+
+#include "pvr_tlcommon.h"
+
+/*************************************************************************/ /*!
+ Logging type
+*/ /**************************************************************************/
+#define RGXFWIF_LOG_TYPE_NONE 0x00000000
+#define RGXFWIF_LOG_TYPE_TRACE 0x00000001
+#define RGXFWIF_LOG_TYPE_GROUP_MAIN 0x00000002
+#define RGXFWIF_LOG_TYPE_GROUP_MTS 0x00000004
+#define RGXFWIF_LOG_TYPE_GROUP_CLEANUP 0x00000008
+#define RGXFWIF_LOG_TYPE_GROUP_CSW 0x00000010
+#define RGXFWIF_LOG_TYPE_GROUP_BIF 0x00000020
+#define RGXFWIF_LOG_TYPE_GROUP_PM 0x00000040
+#define RGXFWIF_LOG_TYPE_GROUP_RTD 0x00000080
+#define RGXFWIF_LOG_TYPE_GROUP_SPM 0x00000100
+#define RGXFWIF_LOG_TYPE_GROUP_POW 0x00000200
+#define RGXFWIF_LOG_TYPE_GROUP_HWR 0x00000400
+#define RGXFWIF_LOG_TYPE_GROUP_HWP 0x00000800
+#define RGXFWIF_LOG_TYPE_GROUP_DEBUG 0x80000000
+#define RGXFWIF_LOG_TYPE_GROUP_MASK 0x80000FFE
+#define RGXFWIF_LOG_TYPE_MASK 0x80000FFF
+
+/* String used in pvrdebug -h output */
+#define RGXFWIF_LOG_GROUPS_STRING_LIST "main,mts,cleanup,csw,bif,pm,rtd,spm,pow,hwr,hwp"
+
+/* Table entry to map log group strings to log type value */
+typedef struct {
+ const IMG_CHAR* pszLogGroupName;
+ IMG_UINT32 ui32LogGroupType;
+} RGXFWIF_LOG_GROUP_MAP_ENTRY;
+
+/*
+ Macro for use with the RGXFWIF_LOG_GROUP_MAP_ENTRY type to create a lookup
+ table where needed. Keep log group names short, no more than 20 chars.
+*/
+#define RGXFWIF_LOG_GROUP_NAME_VALUE_MAP { "main", RGXFWIF_LOG_TYPE_GROUP_MAIN }, \
+ { "mts", RGXFWIF_LOG_TYPE_GROUP_MTS }, \
+ { "cleanup", RGXFWIF_LOG_TYPE_GROUP_CLEANUP }, \
+ { "csw", RGXFWIF_LOG_TYPE_GROUP_CSW }, \
+ { "bif", RGXFWIF_LOG_TYPE_GROUP_BIF }, \
+ { "pm", RGXFWIF_LOG_TYPE_GROUP_PM }, \
+ { "rtd", RGXFWIF_LOG_TYPE_GROUP_RTD }, \
+ { "spm", RGXFWIF_LOG_TYPE_GROUP_SPM }, \
+ { "pow", RGXFWIF_LOG_TYPE_GROUP_POW }, \
+ { "hwr", RGXFWIF_LOG_TYPE_GROUP_HWR }, \
+ { "hwp", RGXFWIF_LOG_TYPE_GROUP_HWP }, \
+ { "debug", RGXFWIF_LOG_TYPE_GROUP_DEBUG }
+
+
+/* Used in print statements to display log group state, one %s per group defined */
+#define RGXFWIF_LOG_ENABLED_GROUPS_LIST_PFSPEC "%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_DEBUG) ?("debug ") :(""))
+
+
+/*! Logging function */
+typedef IMG_VOID (*PFN_RGXFW_LOG) (const IMG_CHAR* pszFmt, ...);
+
+/*!
+ ******************************************************************************
+ * HWPERF
+ *****************************************************************************/
+/* Size of the Firmware L1 HWPERF buffer in bytes (256KB). Accessed by the
+ * Firmware and host driver. */
+#define RGXFW_HWPERF_L1_SIZE_MIN (0x004000)
+#define RGXFW_HWPERF_L1_SIZE_DEFAULT (0x040000)
+#define RGXFW_HWPERF_L1_SIZE_MAX (0xC00000)
+/* This padding value must always be greater than or equal to
+ * RGX_HWPERF_V2_MAX_PACKET_SIZE for all valid BVNCs. This is asserted in
+ * rgxsrvinit.c. This macro is defined with a constant to avoid a KM
+ * dependency */
+#define RGXFW_HWPERF_L1_PADDING_DEFAULT (0x800)
+
+/*!
+ ******************************************************************************
+ * Trace Buffer
+ *****************************************************************************/
+
+/*! Number of elements on each line when dumping the trace buffer */
+#define RGXFW_TRACE_BUFFER_LINESIZE (30)
+
+/*! Total size of RGXFWIF_TRACEBUF dword (needs to be a multiple of RGXFW_TRACE_BUFFER_LINESIZE) */
+#define RGXFW_TRACE_BUFFER_SIZE (400*RGXFW_TRACE_BUFFER_LINESIZE)
+#define RGXFW_TRACE_BUFFER_ASSERT_SIZE 200
+#define RGXFW_THREAD_NUM 1
+
+#define RGXFW_POLL_TYPE_SET 0x80000000
+
+typedef struct _RGXFWIF_ASSERTBUF_
+{
+ IMG_CHAR szPath[RGXFW_TRACE_BUFFER_ASSERT_SIZE];
+ IMG_CHAR szInfo[RGXFW_TRACE_BUFFER_ASSERT_SIZE];
+ IMG_UINT32 ui32LineNum;
+}RGXFWIF_ASSERTBUF;
+
+typedef struct _RGXFWIF_TRACEBUF_SPACE_
+{
+ IMG_UINT32 ui32TracePointer;
+ IMG_UINT32 aui32TraceBuffer[RGXFW_TRACE_BUFFER_SIZE];
+ RGXFWIF_ASSERTBUF sAssertBuf;
+} RGXFWIF_TRACEBUF_SPACE;
+
+#define RGXFWIF_POW_STATES \
+ X(RGXFWIF_POW_OFF) /* idle and handshaked with the host (ready to full power down) */ \
+ X(RGXFWIF_POW_ON) /* running HW mds */ \
+ X(RGXFWIF_POW_FORCED_IDLE) /* forced idle */ \
+ X(RGXFWIF_POW_IDLE) /* idle waiting for host handshake */
+
+typedef enum _RGXFWIF_POW_STATE_
+{
+#define X(NAME) NAME,
+ RGXFWIF_POW_STATES
+#undef X
+} RGXFWIF_POW_STATE;
+
+/* Firmware HWR states */
+#define RGXFWIF_HWR_HARDWARE_OK (0x1 << 0) /*!< Tells if the HW state is ok or locked up */
+#define RGXFWIF_HWR_FREELIST_OK (0x1 << 1) /*!< Tells if the freelists are ok or being reconstructed */
+#define RGXFWIF_HWR_ANALYSIS_DONE (0x1 << 2) /*!< Tells if the analysis of a GPU lockup has already been performed */
+#define RGXFWIF_HWR_GENERAL_LOCKUP (0x1 << 3) /*!< Tells if a DM unrelated lockup has been detected */
+typedef IMG_UINT32 RGXFWIF_HWR_STATEFLAGS;
+
+/* Firmware per-DM HWR states */
+#define RGXFWIF_DM_STATE_WORKING (0x00) /*!< DM is working if all flags are cleared */
+#define RGXFWIF_DM_STATE_READY_FOR_HWR (0x1 << 0) /*!< DM is idle and ready for HWR */
+#define RGXFWIF_DM_STATE_NEEDS_FL_RECONSTRUCTION (0x1 << 1) /*!< DM need FL reconstruction before resuming processing */
+#define RGXFWIF_DM_STATE_NEEDS_SKIP (0x1 << 2) /*!< DM need to skip to next cmd before resuming processing */
+#define RGXFWIF_DM_STATE_NEEDS_PR_CLEANUP (0x1 << 3) /*!< DM need partial render cleanup before resuming processing */
+#define RGXFWIF_DM_STATE_NEEDS_TRACE_CLEAR (0x1 << 4) /*!< DM need to increment Recovery Count once fully recovered */
+#define RGXFWIF_DM_STATE_GUILTY_LOCKUP (0x1 << 5) /*!< DM was identified as locking up and causing HWR */
+#define RGXFWIF_DM_STATE_INNOCENT_LOCKUP (0x1 << 6) /*!< DM was innocently affected by another lockup which caused HWR */
+#define RGXFWIF_DM_STATE_GUILTY_OVERRUNING (0x1 << 7) /*!< DM was identified as over-running and causing HWR */
+#define RGXFWIF_DM_STATE_INNOCENT_OVERRUNING (0x1 << 8) /*!< DM was innocently affected by another DM over-running which caused HWR */
+typedef IMG_UINT32 RGXFWIF_HWR_RECOVERYFLAGS;
+
+typedef struct _RGXFWIF_TRACEBUF_
+{
+ IMG_UINT32 ui32LogType;
+ RGXFWIF_POW_STATE ePowState;
+ RGXFWIF_TRACEBUF_SPACE sTraceBuf[RGXFW_THREAD_NUM];
+
+ IMG_UINT16 aui16HwrDmLockedUpCount[RGXFWIF_DM_MAX];
+ IMG_UINT16 aui16HwrDmOverranCount[RGXFWIF_DM_MAX];
+ IMG_UINT16 aui16HwrDmRecoveredCount[RGXFWIF_DM_MAX];
+ IMG_UINT16 aui16HwrDmFalseDetectCount[RGXFWIF_DM_MAX];
+ IMG_UINT32 ui32HwrCounter;
+ RGXFWIF_DEV_VIRTADDR apsHwrDmFWCommonContext[RGXFWIF_DM_MAX];
+
+ IMG_UINT32 aui32CrPollAddr[RGXFW_THREAD_NUM];
+ IMG_UINT32 aui32CrPollMask[RGXFW_THREAD_NUM];
+
+ RGXFWIF_HWR_STATEFLAGS ui32HWRStateFlags;
+ RGXFWIF_HWR_RECOVERYFLAGS aui32HWRRecoveryFlags[RGXFWIF_HWDM_MAX];
+
+ volatile IMG_UINT32 ui32HWPerfRIdx;
+ volatile IMG_UINT32 ui32HWPerfWIdx;
+ volatile IMG_UINT32 ui32HWPerfWrapCount;
+ IMG_UINT32 ui32HWPerfSize; /* Constant after setup, needed in FW */
+ IMG_UINT32 ui32HWPerfDropCount; /* The number of times the FW drops a packet due to buffer full */
+
+ /* These next three items are only valid at runtime when the FW is built
+ * with RGX_HWPERF_UTILIZATION defined in rgxfw_hwperf.c */
+ IMG_UINT32 ui32HWPerfUt; /* Buffer utilisation, high watermark of bytes in use */
+ IMG_UINT32 ui32FirstDropOrdinal;/* The ordinal of the first packet the FW dropped */
+ IMG_UINT32 ui32LastDropOrdinal; /* The ordinal of the last packet the FW dropped */
+
+ IMG_UINT32 ui32InterruptCount;
+ IMG_UINT32 ui32KCCBCmdsExecuted;
+ IMG_UINT64 RGXFW_ALIGN ui64StartIdleTime;
+} RGXFWIF_TRACEBUF;
+
+/*!
+ ******************************************************************************
+ * GPU Utilization FW CB
+ *****************************************************************************/
+#define RGXFWIF_GPU_STATS_WINDOW_SIZE_US 500000 /*!< Time window considered for active/idle/blocked statistics */
+#define RGXFWIF_GPU_STATS_STATE_CHG_PER_SEC 1000 /*!< Expected number of maximum GPU state changes per second */
+#define RGXFWIF_GPU_STATS_MAX_VALUE_OF_STATE 10000
+
+#define RGXFWIF_GPU_UTIL_FWCB_SIZE ((RGXFWIF_GPU_STATS_WINDOW_SIZE_US * RGXFWIF_GPU_STATS_STATE_CHG_PER_SEC) / 1000000)
+
+#define RGXFWIF_GPU_UTIL_FWCB_TYPE_CRTIME IMG_UINT64_C(0x0)
+#define RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON IMG_UINT64_C(0x1)
+#define RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_OFF IMG_UINT64_C(0x2)
+#define RGXFWIF_GPU_UTIL_FWCB_TYPE_END_CRTIME IMG_UINT64_C(0x3)
+#define RGXFWIF_GPU_UTIL_FWCB_TYPE_MASK IMG_UINT64_C(0xC000000000000000)
+#define RGXFWIF_GPU_UTIL_FWCB_TYPE_SHIFT (62)
+
+#define RGXFWIF_GPU_UTIL_FWCB_STATE_ACTIVE_LOW IMG_UINT64_C(0x0)
+#define RGXFWIF_GPU_UTIL_FWCB_STATE_IDLE IMG_UINT64_C(0x1)
+#define RGXFWIF_GPU_UTIL_FWCB_STATE_ACTIVE_HIGH IMG_UINT64_C(0x2)
+#define RGXFWIF_GPU_UTIL_FWCB_STATE_BLOCKED IMG_UINT64_C(0x3)
+#define RGXFWIF_GPU_UTIL_FWCB_STATE_MASK IMG_UINT64_C(0x3000000000000000)
+#define RGXFWIF_GPU_UTIL_FWCB_STATE_SHIFT (60)
+
+#define RGXFWIF_GPU_UTIL_FWCB_ID_MASK IMG_UINT64_C(0x0FFF000000000000)
+#define RGXFWIF_GPU_UTIL_FWCB_ID_SHIFT (48)
+
+#define RGXFWIF_GPU_UTIL_FWCB_CR_TIMER_MASK IMG_UINT64_C(0x0000FFFFFFFFFFFF)
+#define RGXFWIF_GPU_UTIL_FWCB_OS_TIMER_MASK IMG_UINT64_C(0x0FFFFFFFFFFFFFFF)
+#define RGXFWIF_GPU_UTIL_FWCB_TIMER_SHIFT (0)
+
+#define RGXFWIF_GPU_UTIL_FWCB_ENTRY_TYPE(entry) (((entry)&RGXFWIF_GPU_UTIL_FWCB_TYPE_MASK)>>RGXFWIF_GPU_UTIL_FWCB_TYPE_SHIFT)
+#define RGXFWIF_GPU_UTIL_FWCB_ENTRY_STATE(entry) (((entry)&RGXFWIF_GPU_UTIL_FWCB_STATE_MASK)>>RGXFWIF_GPU_UTIL_FWCB_STATE_SHIFT)
+#define RGXFWIF_GPU_UTIL_FWCB_ENTRY_ID(entry) (((entry)&RGXFWIF_GPU_UTIL_FWCB_ID_MASK)>>RGXFWIF_GPU_UTIL_FWCB_ID_SHIFT)
+#define RGXFWIF_GPU_UTIL_FWCB_ENTRY_CR_TIMER(entry) (((entry)&RGXFWIF_GPU_UTIL_FWCB_CR_TIMER_MASK)>>RGXFWIF_GPU_UTIL_FWCB_TIMER_SHIFT)
+#define RGXFWIF_GPU_UTIL_FWCB_ENTRY_OS_TIMER(entry) (((entry)&RGXFWIF_GPU_UTIL_FWCB_OS_TIMER_MASK)>>RGXFWIF_GPU_UTIL_FWCB_TIMER_SHIFT)
+
+/* It can never happen that the GPU is reported as powered off and active at the same time,
+ * use this combination to mark the entry as reserved */
+#define RGXFWIF_GPU_UTIL_FWCB_RESERVED \
+ ( (RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_OFF << RGXFWIF_GPU_UTIL_FWCB_TYPE_SHIFT) | \
+ (RGXFWIF_GPU_UTIL_FWCB_STATE_ACTIVE_LOW << RGXFWIF_GPU_UTIL_FWCB_STATE_SHIFT) )
+
+#define RGXFWIF_GPU_UTIL_FWCB_ENTRY_ADD(cb, crtimer, state) do { \
+ /* Combine all the information about current state transition into a single 64-bit word */ \
+ (cb)->aui64CB[(cb)->ui32WriteOffset] = \
+ (((IMG_UINT64)(crtimer) << RGXFWIF_GPU_UTIL_FWCB_TIMER_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_CR_TIMER_MASK) | \
+ (((IMG_UINT64)(state) << RGXFWIF_GPU_UTIL_FWCB_STATE_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_STATE_MASK) | \
+ (((IMG_UINT64)(cb)->ui32CurrentDVFSId << RGXFWIF_GPU_UTIL_FWCB_ID_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_ID_MASK); \
+ /* Make sure the value is written to the memory before advancing write offset */ \
+ RGXFW_MEM_FENCE(); \
+ /* Advance the CB write offset */ \
+ (cb)->ui32WriteOffset++; \
+ if((cb)->ui32WriteOffset >= RGXFWIF_GPU_UTIL_FWCB_SIZE) \
+ { \
+ (cb)->ui32WriteOffset = 0; \
+ } \
+ /* Cache current transition in cached memory */ \
+ (cb)->ui32LastGpuUtilState = (state); \
+ } while (0)
+
+
+/* The timer correlation array must be big enough to ensure old entries won't be
+ * overwritten before all the HWPerf events linked to those entries are processed
+ * by the MISR. The update frequency of this array depends on how fast the system
+ * can change state (basically how small the APM latency is) and perform DVFS transitions.
+ *
+ * The minimum size is 2 (not 1) to avoid race conditions between the FW reading
+ * an entry while the Host is updating it. With 2 entries in the worst case the FW
+ * will read old data, which is still quite ok if the Host is updating the timer
+ * correlation at that time.
+ */
+#define RGXFWIF_TIME_CORR_ARRAY_SIZE 256
+
+typedef IMG_UINT64 RGXFWIF_GPU_UTIL_FWCB_ENTRY;
+
+typedef struct _RGXFWIF_GPU_UTIL_FWCB_
+{
+ RGXFWIF_TIME_CORR sTimeCorr[RGXFWIF_TIME_CORR_ARRAY_SIZE];
+ IMG_UINT32 ui32TimeCorrCurrent;
+ IMG_UINT32 ui32WriteOffset;
+ IMG_UINT32 ui32LastGpuUtilState;
+ IMG_UINT32 ui32CurrentDVFSId;
+ RGXFWIF_GPU_UTIL_FWCB_ENTRY RGXFW_ALIGN aui64CB[RGXFWIF_GPU_UTIL_FWCB_SIZE];
+} RGXFWIF_GPU_UTIL_FWCB;
+
+/* HWR Data */
+typedef enum _RGX_HWRTYPE_
+{
+ RGX_HWRTYPE_UNKNOWNFAILURE = 0,
+ RGX_HWRTYPE_OVERRUN = 1,
+ RGX_HWRTYPE_POLLFAILURE = 2,
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+ RGX_HWRTYPE_BIF0FAULT = 3,
+ RGX_HWRTYPE_BIF1FAULT = 4,
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+ RGX_HWRTYPE_TEXASBIF0FAULT = 5,
+#endif
+#else
+ RGX_HWRTYPE_MMUFAULT = 6,
+ RGX_HWRTYPE_MMUMETAFAULT = 7,
+#endif
+} RGX_HWRTYPE;
+
+#define RGXFWIF_BIFFAULTBIT_GET(ui32BIFMMUStatus) \
+ ((ui32BIFMMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_CLRMSK) >> RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_SHIFT)
+#define RGXFWIF_MMUFAULTBIT_GET(ui32BIFMMUStatus) \
+ ((ui32BIFMMUStatus & ~RGX_CR_MMU_FAULT_STATUS_FAULT_CLRMSK) >> RGX_CR_MMU_FAULT_STATUS_FAULT_SHIFT)
+
+#define RGXFWIF_HWRTYPE_BIF_BANK_GET(eHWRType) ((eHWRType == RGX_HWRTYPE_BIF0FAULT) ? 0 : 1 )
+
+typedef struct _RGX_BIFINFO_
+{
+ IMG_UINT64 RGXFW_ALIGN ui64BIFReqStatus;
+ IMG_UINT64 RGXFW_ALIGN ui64BIFMMUStatus;
+} RGX_BIFINFO;
+
+typedef struct _RGX_MMUINFO_
+{
+ IMG_UINT64 RGXFW_ALIGN ui64MMUStatus;
+} RGX_MMUINFO;
+
+typedef struct _RGX_POLLINFO_
+{
+ IMG_UINT32 ui32ThreadNum;
+ IMG_UINT32 ui32CrPollAddr;
+ IMG_UINT32 ui32CrPollMask;
+} RGX_POLLINFO;
+
+typedef struct _RGX_HWRINFO_
+{
+ union
+ {
+ RGX_BIFINFO sBIFInfo;
+ RGX_MMUINFO sMMUInfo;
+ RGX_POLLINFO sPollInfo;
+ } uHWRData;
+
+ IMG_UINT64 RGXFW_ALIGN ui64CRTimer;
+ IMG_UINT32 ui32FrameNum;
+ IMG_UINT32 ui32PID;
+ IMG_UINT32 ui32ActiveHWRTData;
+ IMG_UINT32 ui32HWRNumber;
+ IMG_UINT32 ui32EventStatus;
+ IMG_UINT32 ui32HWRRecoveryFlags;
+ RGX_HWRTYPE eHWRType;
+
+ RGXFWIF_DM eDM;
+} RGX_HWRINFO;
+
+#define RGXFWIF_HWINFO_MAX_FIRST 8 /* Number of first HWR logs recorded (never overwritten by newer logs) */
+#define RGXFWIF_HWINFO_MAX_LAST 8 /* Number of latest HWR logs (older logs are overwritten by newer logs) */
+#define RGXFWIF_HWINFO_MAX (RGXFWIF_HWINFO_MAX_FIRST + RGXFWIF_HWINFO_MAX_LAST) /* Total number of HWR logs stored in a buffer */
+#define RGXFWIF_HWINFO_LAST_INDEX (RGXFWIF_HWINFO_MAX - 1) /* Index of the last log in the HWR log buffer */
+typedef struct _RGXFWIF_HWRINFOBUF_
+{
+ RGX_HWRINFO sHWRInfo[RGXFWIF_HWINFO_MAX];
+
+ IMG_UINT32 ui32FirstCrPollAddr[RGXFW_THREAD_NUM];
+ IMG_UINT32 ui32FirstCrPollMask[RGXFW_THREAD_NUM];
+ IMG_UINT32 ui32WriteIndex;
+ IMG_BOOL bDDReqIssued;
+} RGXFWIF_HWRINFOBUF;
+
+/*! RGX firmware Init Config Data */
+#define RGXFWIF_INICFG_CTXSWITCH_TA_EN (0x1 << 0)
+#define RGXFWIF_INICFG_CTXSWITCH_3D_EN (0x1 << 1)
+#define RGXFWIF_INICFG_CTXSWITCH_CDM_EN (0x1 << 2)
+#define RGXFWIF_INICFG_CTXSWITCH_MODE_RAND (0x1 << 3)
+#define RGXFWIF_INICFG_CTXSWITCH_SRESET_EN (0x1 << 4)
+#define RGXFWIF_INICFG_RSVD (0x1 << 5)
+#define RGXFWIF_INICFG_POW_RASCALDUST (0x1 << 6)
+#define RGXFWIF_INICFG_HWPERF_EN (0x1 << 7)
+#define RGXFWIF_INICFG_HWR_EN (0x1 << 8)
+#define RGXFWIF_INICFG_CHECK_MLIST_EN (0x1 << 9)
+#define RGXFWIF_INICFG_DISABLE_CLKGATING_EN (0x1 << 10)
+#define RGXFWIF_INICFG_POLL_COUNTERS_EN (0x1 << 11)
+#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INDEX (RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_INDEX << 12)
+#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INSTANCE (RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_INSTANCE << 12)
+#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_LIST (RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_LIST << 12)
+#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_CLRMSK (0xFFFFCFFFU)
+#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_SHIFT (12)
+#define RGXFWIF_INICFG_SHG_BYPASS_EN (0x1 << 14)
+#define RGXFWIF_INICFG_RTU_BYPASS_EN (0x1 << 15)
+#define RGXFWIF_INICFG_REGCONFIG_EN (0x1 << 16)
+#define RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY (0x1 << 17)
+#define RGXFWIF_INICFG_HWP_DISABLE_FILTER (0x1 << 18)
+#define RGXFWIF_INICFG_ALL (0x0007FFDFU)
+#define RGXFWIF_SRVCFG_DISABLE_PDP_EN (0x1 << 31)
+#define RGXFWIF_SRVCFG_ALL (0x80000000U)
+#define RGXFWIF_FILTCFG_TRUNCATE_HALF (0x1 << 3)
+#define RGXFWIF_FILTCFG_TRUNCATE_INT (0x1 << 2)
+#define RGXFWIF_FILTCFG_NEW_FILTER_MODE (0x1 << 1)
+
+#define RGXFWIF_INICFG_CTXSWITCH_DM_ALL (RGXFWIF_INICFG_CTXSWITCH_TA_EN | \
+ RGXFWIF_INICFG_CTXSWITCH_3D_EN | \
+ RGXFWIF_INICFG_CTXSWITCH_CDM_EN)
+
+#define RGXFWIF_INICFG_CTXSWITCH_CLRMSK ~(RGXFWIF_INICFG_CTXSWITCH_DM_ALL | \
+ RGXFWIF_INICFG_CTXSWITCH_MODE_RAND | \
+ RGXFWIF_INICFG_CTXSWITCH_SRESET_EN)
+
+typedef enum
+{
+ RGX_ACTIVEPM_FORCE_OFF = 0,
+ RGX_ACTIVEPM_FORCE_ON = 1,
+ RGX_ACTIVEPM_DEFAULT = 3
+} RGX_ACTIVEPM_CONF;
+
+/*!
+ ******************************************************************************
+ * Querying DM state
+ *****************************************************************************/
+
+typedef enum _RGXFWIF_DM_STATE_
+{
+ RGXFWIF_DM_STATE_NORMAL = 0,
+ RGXFWIF_DM_STATE_LOCKEDUP = 1,
+
+} RGXFWIF_DM_STATE;
+
+typedef struct
+{
+ IMG_UINT16 ui16RegNum; /*!< Register number */
+ IMG_UINT16 ui16IndirectRegNum; /*!< Indirect register number (or 0 if not used) */
+ IMG_UINT16 ui16IndirectStartVal; /*!< Start value for indirect register */
+ IMG_UINT16 ui16IndirectEndVal; /*!< End value for indirect register */
+} RGXFW_REGISTER_LIST;
+
+#endif /* __RGX_FWIF_H__ */
+
+/******************************************************************************
+ End of file (rgx_fwif.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/include/rgx_fwif_alignchecks_km.h b/drivers/gpu/rogue/services/include/rgx_fwif_alignchecks_km.h
new file mode 100644
index 000000000000..158abbab40bb
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/rgx_fwif_alignchecks_km.h
@@ -0,0 +1,86 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX fw interface alignment checks
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Checks to avoid disalignment in RGX fw data structures shared with the host
+@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 (__RGX_FWIF_ALIGNCHECKS_KM_H__)
+#define __RGX_FWIF_ALIGNCHECKS_KM_H__
+
+/* for the offsetof macro */
+#include <stddef.h>
+
+/*!
+ ******************************************************************************
+ * Alignment checks array
+ *****************************************************************************/
+
+#define RGXFW_ALIGN_CHECKS_INIT_KM \
+ sizeof(RGXFWIF_INIT), \
+ offsetof(RGXFWIF_INIT, sFaultPhysAddr), \
+ offsetof(RGXFWIF_INIT, sPDSExecBase), \
+ offsetof(RGXFWIF_INIT, sUSCExecBase), \
+ offsetof(RGXFWIF_INIT, psKernelCCBCtl), \
+ offsetof(RGXFWIF_INIT, psKernelCCB), \
+ offsetof(RGXFWIF_INIT, psFirmwareCCBCtl), \
+ offsetof(RGXFWIF_INIT, psFirmwareCCB), \
+ offsetof(RGXFWIF_INIT, eDM), \
+ offsetof(RGXFWIF_INIT, asSigBufCtl), \
+ offsetof(RGXFWIF_INIT, psTraceBufCtl), \
+ offsetof(RGXFWIF_INIT, sRGXCompChecks), \
+ \
+ /* RGXFWIF_FWRENDERCONTEXT checks */ \
+ sizeof(RGXFWIF_FWRENDERCONTEXT), \
+ offsetof(RGXFWIF_FWRENDERCONTEXT, sTAContext), \
+ offsetof(RGXFWIF_FWRENDERCONTEXT, s3DContext), \
+ \
+ sizeof(RGXFWIF_FWCOMMONCONTEXT), \
+ offsetof(RGXFWIF_FWCOMMONCONTEXT, psFWMemContext), \
+ offsetof(RGXFWIF_FWCOMMONCONTEXT, sRunNode), \
+ offsetof(RGXFWIF_FWCOMMONCONTEXT, psCCB), \
+ offsetof(RGXFWIF_FWCOMMONCONTEXT, ui64MCUFenceAddr)
+
+#endif /* __RGX_FWIF_ALIGNCHECKS_KM_H__ */
+
+/******************************************************************************
+ End of file (rgx_fwif_alignchecks_km.h)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/rogue/services/include/rgx_fwif_km.h b/drivers/gpu/rogue/services/include/rgx_fwif_km.h
new file mode 100644
index 000000000000..92ce2a46c366
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/rgx_fwif_km.h
@@ -0,0 +1,801 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX firmware interface structures used by pvrsrvkm
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX firmware interface structures used by pvrsrvkm
+@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 (__RGX_FWIF_KM_H__)
+#define __RGX_FWIF_KM_H__
+
+#include "img_types.h"
+#include "rgx_fwif_shared.h"
+#include "rgxdefs_km.h"
+#include "pvr_debug.h"
+#include "dllist.h"
+
+
+#if defined(RGX_FIRMWARE)
+/* Compiling the actual firmware - use a fully typed pointer */
+typedef struct _RGXFWIF_HOST_CTL_ *PRGXFWIF_HOST_CTL;
+typedef struct _RGXFWIF_CCB_CTL_ *PRGXFWIF_CCB_CTL;
+typedef IMG_UINT8 *PRGXFWIF_CCB;
+typedef struct _RGXFWIF_FWMEMCONTEXT_ *PRGXFWIF_FWMEMCONTEXT;
+typedef struct _RGXFWIF_FWRENDERCONTEXT_ *PRGXFWIF_FWRENDERCONTEXT;
+typedef struct _RGXFWIF_FWTQ2DCONTEXT_ *PRGXFWIF_FWTQ2DCONTEXT;
+typedef struct _RGXFWIF_FWTQ3DCONTEXT_ *PRGXFWIF_FWTQ3DCONTEXT;
+typedef struct _RGXFWIF_FWCOMPUTECONTEXT_ *PRGXFWIF_FWCOMPUTECONTEXT;
+typedef struct _RGXFWIF_FWCOMMONCONTEXT_ *PRGXFWIF_FWCOMMONCONTEXT;
+typedef struct _RGXFWIF_ZSBUFFER_ *PRGXFWIF_ZSBUFFER;
+typedef IMG_UINT32 *PRGXFWIF_SIGBUFFER;
+typedef struct _RGXFWIF_INIT_ *PRGXFWIF_INIT;
+typedef struct _RGXFWIF_RUNTIME_CFG *PRGXFWIF_RUNTIME_CFG;
+typedef struct _RGXFW_UNITTESTS_ *PRGXFW_UNITTESTS;
+typedef struct _RGXFWIF_TRACEBUF_ *PRGXFWIF_TRACEBUF;
+typedef IMG_UINT8 *PRGXFWIF_HWPERFINFO;
+typedef struct _RGXFWIF_HWRINFOBUF_ *PRGXFWIF_HWRINFOBUF;
+typedef struct _RGXFWIF_GPU_UTIL_FWCB_ *PRGXFWIF_GPU_UTIL_FWCB;
+typedef struct _RGXFWIF_REG_CFG_ *PRGXFWIF_REG_CFG;
+typedef IMG_UINT8 *PRGXFWIF_COMMONCTX_STATE;
+typedef struct _RGXFWIF_TACTX_STATE_ *PRGXFWIF_TACTX_STATE;
+typedef struct _RGXFWIF_3DCTX_STATE_ *PRGXFWIF_3DCTX_STATE;
+typedef struct _RGXFWIF_COMPUTECTX_STATE_ *PRGXFWIF_COMPUTECTX_STATE;
+typedef struct _RGXFWIF_VRDMCTX_STATE_ *PRGXFWIF_VRDMCTX_STATE;
+typedef IMG_UINT8 *PRGXFWIF_RF_CMD;
+typedef struct _RGXFWIF_COMPCHECKS_ *PRGXFWIF_COMPCHECKS;
+typedef struct _RGX_HWPERF_CONFIG_CNTBLK_ *PRGX_HWPERF_CONFIG_CNTBLK;
+typedef IMG_UINT32 *PRGX_HWPERF_SELECT_CUSTOM_CNTRS;
+typedef DLLIST_NODE RGXFWIF_DLLIST_NODE;
+#else
+/* Compiling the host driver - use a firmware device virtual pointer */
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_HOST_CTL;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_CCB_CTL;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_CCB;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_FWMEMCONTEXT;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_FWRENDERCONTEXT;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_FWTQ2DCONTEXT;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_FWTQ3DCONTEXT;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_FWCOMPUTECONTEXT;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_FWCOMMONCONTEXT;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_ZSBUFFER;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_SIGBUFFER;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_INIT;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_RUNTIME_CFG;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFW_UNITTESTS;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_TRACEBUF;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_HWPERFINFO;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_HWRINFOBUF;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_GPU_UTIL_FWCB;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_REG_CFG;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_COMMONCTX_STATE;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_RF_CMD;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_COMPCHECKS;
+typedef RGXFWIF_DEV_VIRTADDR PRGX_HWPERF_CONFIG_CNTBLK;
+typedef RGXFWIF_DEV_VIRTADDR PRGX_HWPERF_SELECT_CUSTOM_CNTRS;
+typedef struct {RGXFWIF_DEV_VIRTADDR p;
+ RGXFWIF_DEV_VIRTADDR n;} RGXFWIF_DLLIST_NODE;
+#endif /* RGX_FIRMWARE */
+
+
+/*!
+ Firmware memory context.
+*/
+typedef struct _RGXFWIF_FWMEMCONTEXT_
+{
+ IMG_DEV_PHYADDR RGXFW_ALIGN sPCDevPAddr; /*!< device physical address of context's page catalogue */
+ IMG_INT32 uiPageCatBaseRegID; /*!< associated page catalog base register (-1 == unallocated) */
+ IMG_UINT32 uiBreakpointAddr; /*!< breakpoint address */
+ IMG_UINT32 uiBPHandlerAddr; /*!< breakpoint handler address */
+ IMG_UINT32 uiBreakpointCtl; /*!< DM and enable control for BP */
+} RGXFWIF_FWMEMCONTEXT;
+
+
+/*!
+ * FW context state flags
+ */
+#define RGXFWIF_CONTEXT_TAFLAGS_NEED_RESUME (0x00000001)
+#define RGXFWIF_CONTEXT_RENDERFLAGS_NEED_RESUME (0x00000002)
+#define RGXFWIF_CONTEXT_CDMFLAGS_NEED_RESUME (0x00000004)
+#define RGXFWIF_CONTEXT_SHGFLAGS_NEED_RESUME (0x00000008)
+#define RGXFWIF_CONTEXT_ALLFLAGS_NEED_RESUME (0x0000000F)
+
+
+typedef struct _RGXFWIF_TACTX_STATE_
+{
+ /* 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;
+
+ /* Number of stores on this context */
+ IMG_UINT32 ui32NumStores;
+} RGXFWIF_TACTX_STATE;
+
+
+typedef struct _RGXFWIF_3DCTX_STATE_
+{
+ /* FW-accessible ISP state which must be written out to memory on context store */
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+ IMG_UINT32 RGXFW_ALIGN au3DReg_ISP_STORE[8];
+#else
+ IMG_UINT32 RGXFW_ALIGN au3DReg_ISP_STORE[32];
+#endif
+ IMG_UINT64 RGXFW_ALIGN u3DReg_PM_DEALLOCATED_MASK_STATUS;
+ IMG_UINT64 RGXFW_ALIGN u3DReg_PM_PDS_MTILEFREE_STATUS;
+
+ /* Number of stores on this context */
+ IMG_UINT32 ui32NumStores;
+} RGXFWIF_3DCTX_STATE;
+
+
+
+typedef struct _RGXFWIF_COMPUTECTX_STATE_
+{
+ IMG_UINT64 RGXFW_ALIGN ui64Padding;
+
+ /* Number of stores on this context */
+ IMG_UINT32 ui32NumStores;
+} RGXFWIF_COMPUTECTX_STATE;
+
+
+typedef struct _RGXFWIF_VRDMCTX_STATE_
+{
+ /* FW-accessible TA state which must be written out to memory on context store */
+ IMG_UINT64 RGXFW_ALIGN uVRDMReg_VRM_CALL_STACK_POINTER;
+ IMG_UINT64 RGXFW_ALIGN uVRDMReg_VRM_BATCH;
+
+ /* Number of stores on this context */
+ IMG_UINT32 ui32NumStores;
+} RGXFWIF_VRDMCTX_STATE;
+
+
+typedef struct _RGXFWIF_FWCOMMONCONTEXT_
+{
+ /*
+ Used by bg and irq context
+ */
+ /* CCB details for this firmware context */
+ PRGXFWIF_CCCB_CTL psCCBCtl; /*!< CCB control */
+ PRGXFWIF_CCCB psCCB; /*!< CCB base */
+
+ /*
+ Used by the bg context only
+ */
+ RGXFWIF_DLLIST_NODE RGXFW_ALIGN sWaitingNode; /*!< List entry for the waiting list */
+
+ /*
+ Used by the irq context only
+ */
+ RGXFWIF_DLLIST_NODE sRunNode; /*!< List entry for the run list */
+
+ 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
+ */
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32Priority;
+ IMG_UINT64 RGXFW_ALIGN ui64MCUFenceAddr;
+
+ /* Reference back to the Server Common Context */
+ IMG_UINT32 ui32ServerCommonContextID;
+
+} RGXFWIF_FWCOMMONCONTEXT;
+
+
+/*!
+ Firmware render context.
+*/
+typedef struct _RGXFWIF_FWRENDERCONTEXT_
+{
+ RGXFWIF_FWCOMMONCONTEXT sTAContext; /*!< Firmware context for the TA */
+ RGXFWIF_FWCOMMONCONTEXT s3DContext; /*!< Firmware context for the 3D */
+
+ /*
+ * Note: The following fields keep track of OOM and partial render statistics.
+ * Because these data structures are allocated cache-incoherent,
+ * and because these fields are updated by the firmware,
+ * the host will read valid values only after an SLC flush/inval.
+ * This is only guaranteed to happen while destroying the render-context.
+ */
+ IMG_UINT32 ui32TotalNumPartialRenders; /*!< Total number of partial renders */
+ IMG_UINT32 ui32TotalNumOutOfMemory; /*!< Total number of OOMs */
+
+} RGXFWIF_FWRENDERCONTEXT;
+
+/*!
+ Firmware render context.
+*/
+typedef struct _RGXFWIF_FWRAYCONTEXT_
+{
+ RGXFWIF_FWCOMMONCONTEXT sSHGContext; /*!< Firmware context for the SHG */
+ RGXFWIF_FWCOMMONCONTEXT sRTUContext; /*!< Firmware context for the RTU */
+ PRGXFWIF_CCCB_CTL psCCBCtl[DPX_MAX_RAY_CONTEXTS];
+ PRGXFWIF_CCCB psCCB[DPX_MAX_RAY_CONTEXTS];
+ IMG_UINT32 ui32NextFC;
+ IMG_UINT32 ui32ActiveFCMask;
+} RGXFWIF_FWRAYCONTEXT;
+
+#define RGXFWIF_INVALID_FRAME_CONTEXT (0xFFFFFFFF)
+
+/*!
+ BIF requester selection
+*/
+typedef enum _RGXFWIF_BIFREQ_
+{
+ RGXFWIF_BIFREQ_TA = 0,
+ RGXFWIF_BIFREQ_3D = 1,
+ RGXFWIF_BIFREQ_CDM = 2,
+ RGXFWIF_BIFREQ_2D = 3,
+ RGXFWIF_BIFREQ_HOST = 4,
+ RGXFWIF_BIFREQ_RTU = 5,
+ RGXFWIF_BIFREQ_SHG = 6,
+ RGXFWIF_BIFREQ_MAX = 7
+} RGXFWIF_BIFREQ;
+
+typedef enum _RGXFWIF_PM_DM_
+{
+ RGXFWIF_PM_DM_TA = 0,
+ RGXFWIF_PM_DM_3D = 1,
+} RGXFWIF_PM_DM;
+
+/*!
+ ******************************************************************************
+ * Kernel CCB control for RGX
+ *****************************************************************************/
+typedef struct _RGXFWIF_CCB_CTL_
+{
+ volatile IMG_UINT32 ui32WriteOffset; /*!< write offset into array of commands (MUST be aligned to 16 bytes!) */
+ volatile IMG_UINT32 ui32ReadOffset; /*!< read offset into array of commands */
+ IMG_UINT32 ui32WrapMask; /*!< Offset wrapping mask (Total capacity of the CCB - 1) */
+ IMG_UINT32 ui32CmdSize; /*!< size of each command in bytes */
+} RGXFWIF_CCB_CTL;
+
+/*!
+ ******************************************************************************
+ * Kernel CCB command structure for RGX
+ *****************************************************************************/
+#if !defined(RGX_FEATURE_SLC_VIVT)
+
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PT (0x1) /* BIF_CTRL_INVAL_PT_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PD (0x2) /* BIF_CTRL_INVAL_PD_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PC (0x4) /* BIF_CTRL_INVAL_PC_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB (0x10) /* can't use PM_TLB0 bit from BIFPM_CTRL reg because it collides with PT bit from BIF_CTRL reg */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_TLB (RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB | 0x8) /* BIF_CTRL_INVAL_TLB1_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_CTX(C) (0x0) /* not used */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL (0x0) /* not used */
+
+#define RGXFWIF_PMMMUCACHEDATA_FLAGS_INVAL (0x0) /* not used */
+#define RGXFWIF_PMMMUCACHEDATA_FLAGS_FLUSH (0x0) /* not used */
+#define RGXFWIF_PMMMUCACHEDATA_FLAGS_FLUSHINVAL (0x0) /* not used */
+
+#else /* RGX_FEATURE_SLC_VIVT */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PT (0x1) /* MMU_CTRL_INVAL_PT_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PD (0x2) /* MMU_CTRL_INVAL_PD_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PC (0x4) /* MMU_CTRL_INVAL_PC_EN */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB (0x0) /* not used */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_TLB (0x0) /* not used */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_CTX(C) (C << 0x3) /* MMU_CTRL_INVAL_CONTEXT_SHIFT */
+#define RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL (0x800) /* MMU_CTRL_INVAL_ALL_CONTEXTS_EN */
+
+#define RGXFWIF_PMMMUCACHEDATA_FLAGS_INVAL (0x1) /* RGX_CR_SLC3_CFI_INVALIDATE_EN */
+#define RGXFWIF_PMMMUCACHEDATA_FLAGS_FLUSH (0x2) /* RGX_CR_SLC3_CFI_FLUSH_EN */
+#define RGXFWIF_PMMMUCACHEDATA_FLAGS_FLUSHINVAL (0x3) /* RGX_CR_SLC3_CFI_FLUSH_EN|RGX_CR_SLC3_CFI_INVALIDATE_EN */
+#endif
+
+typedef struct _RGXFWIF_MMUCACHEDATA_
+{
+ PRGXFWIF_FWMEMCONTEXT psMemoryContext;
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32CacheSequenceNum;
+} RGXFWIF_MMUCACHEDATA;
+
+typedef struct _RGXFWIF_SLCBPCTLDATA_
+{
+ IMG_BOOL bSetBypassed; /*!< Should SLC be/not be bypassed for indicated units? */
+ IMG_UINT32 uiFlags; /*!< Units to enable/disable */
+} RGXFWIF_SLCBPCTLDATA;
+
+#define RGXFWIF_BPDATA_FLAGS_WRITE (1 << 0)
+#define RGXFWIF_BPDATA_FLAGS_CTL (1 << 1)
+#define RGXFWIF_BPDATA_FLAGS_REGS (1 << 2)
+
+typedef struct _RGXFWIF_FWBPDATA_
+{
+ PRGXFWIF_FWMEMCONTEXT psFWMemContext; /*!< Memory context */
+ IMG_UINT32 ui32BPAddr; /*!< Breakpoint address */
+ IMG_UINT32 ui32HandlerAddr; /*!< Breakpoint handler */
+ IMG_UINT32 ui32BPDM; /*!< Breakpoint control */
+ IMG_BOOL bEnable;
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32TempRegs; /*!< Number of temporary registers to overallocate */
+ IMG_UINT32 ui32SharedRegs; /*!< Number of shared registers to overallocate */
+} RGXFWIF_BPDATA;
+
+#define RGXFWIF_KCCB_CMD_KICK_DATA_MAX_NUM_CLEANUP_CTLS 4
+
+typedef struct _RGXFWIF_KCCB_CMD_KICK_DATA_
+{
+ PRGXFWIF_FWCOMMONCONTEXT psContext; /*!< address of the firmware context */
+ IMG_UINT32 ui32CWoffUpdate; /*!< Client CCB woff update */
+ IMG_UINT32 ui32NumCleanupCtl; /*!< number of CleanupCtl pointers attached */
+ PRGXFWIF_CLEANUP_CTL apsCleanupCtl[RGXFWIF_KCCB_CMD_KICK_DATA_MAX_NUM_CLEANUP_CTLS]; /*!< CleanupCtl structures associated with command */
+} RGXFWIF_KCCB_CMD_KICK_DATA;
+
+typedef struct _RGXFWIF_KCCB_CMD_FENCE_DATA_
+{
+ IMG_UINT32 uiSyncObjDevVAddr;
+ IMG_UINT32 uiUpdateVal;
+} RGXFWIF_KCCB_CMD_SYNC_DATA;
+
+typedef enum _RGXFWIF_CLEANUP_TYPE_
+{
+ RGXFWIF_CLEANUP_FWCOMMONCONTEXT, /*!< FW common context cleanup */
+ RGXFWIF_CLEANUP_HWRTDATA, /*!< FW HW RT data cleanup */
+ RGXFWIF_CLEANUP_FREELIST, /*!< FW freelist cleanup */
+ RGXFWIF_CLEANUP_ZSBUFFER, /*!< FW ZS Buffer cleanup */
+} RGXFWIF_CLEANUP_TYPE;
+
+#define RGXFWIF_CLEANUP_RUN (1 << 0) /*!< The requested cleanup command has run on the FW */
+#define RGXFWIF_CLEANUP_BUSY (1 << 1) /*!< The requested resource is busy */
+
+typedef struct _RGXFWIF_CLEANUP_REQUEST_
+{
+ RGXFWIF_CLEANUP_TYPE eCleanupType; /*!< Cleanup type */
+ union {
+ PRGXFWIF_FWCOMMONCONTEXT psContext; /*!< FW common context to cleanup */
+ PRGXFWIF_HWRTDATA psHWRTData; /*!< HW RT to cleanup */
+ PRGXFWIF_FREELIST psFreelist; /*!< Freelist to cleanup */
+ PRGXFWIF_ZSBUFFER psZSBuffer; /*!< ZS Buffer to cleanup */
+ } uCleanupData;
+ IMG_UINT32 uiSyncObjDevVAddr; /*!< sync primitive used to indicate state of the request */
+} RGXFWIF_CLEANUP_REQUEST;
+
+typedef enum _RGXFWIF_POWER_TYPE_
+{
+ RGXFWIF_POW_OFF_REQ = 1,
+ RGXFWIF_POW_FORCED_IDLE_REQ,
+ RGXFWIF_POW_NUMDUST_CHANGE,
+ RGXFWIF_POW_APM_LATENCY_CHANGE
+} RGXFWIF_POWER_TYPE;
+
+typedef struct _RGXFWIF_POWER_REQUEST_
+{
+ RGXFWIF_POWER_TYPE ePowType; /*!< Type of power request */
+ union
+ {
+ IMG_UINT32 ui32NumOfDusts; /*!< Number of active Dusts */
+ IMG_BOOL bForced; /*!< If the operation is mandatory */
+ IMG_BOOL bCancelForcedIdle; /*!< If the operation is to cancel previously forced idle */
+ IMG_UINT32 ui32ActivePMLatencyms; /* Number of milliseconds to set APM latency */
+ } uPoweReqData;
+} RGXFWIF_POWER_REQUEST;
+
+typedef struct _RGXFWIF_SLCFLUSHINVALDATA_
+{
+ PRGXFWIF_FWCOMMONCONTEXT psContext; /*!< Context to fence on */
+ IMG_BOOL bInval; /*!< invalidate the cache as well as flushing */
+ IMG_UINT32 eDM; /*!< DM to flush entries for */
+} RGXFWIF_SLCFLUSHINVALDATA;
+
+typedef struct _RGXFWIF_HWPERF_CTRL_
+{
+ IMG_BOOL bToggle; /*!< Toggle masked bits or apply full mask? */
+ IMG_UINT64 RGXFW_ALIGN ui64Mask; /*!< Mask of events to toggle */
+} RGXFWIF_HWPERF_CTRL;
+
+typedef struct _RGXFWIF_HWPERF_CONFIG_ENABLE_BLKS_
+{
+ IMG_UINT32 ui32NumBlocks; /*!< Number of RGX_HWPERF_CONFIG_CNTBLK in the array */
+ PRGX_HWPERF_CONFIG_CNTBLK pasBlockConfigs; /*!< Address of the RGX_HWPERF_CONFIG_CNTBLK array */
+} RGXFWIF_HWPERF_CONFIG_ENABLE_BLKS;
+
+typedef struct _RGXFWIF_CORECLKSPEEDCHANGE_DATA_
+{
+ IMG_UINT32 ui32NewClockSpeed; /*!< New clock speed */
+} RGXFWIF_CORECLKSPEEDCHANGE_DATA;
+
+/* This macro value must always be greater than or equal to
+ * RGX_HWPERF_MAX_BLKS for all valid BVNCs. This is asserted in
+ * rgxsrvinit.c. This macro is defined with a constant to avoid a KM
+ * dependency */
+ #define RGXFWIF_HWPERF_CTRL_BLKS_MAX 32
+
+typedef struct _RGXFWIF_HWPERF_CTRL_BLKS_
+{
+ IMG_BOOL bEnable;
+ IMG_UINT32 ui32NumBlocks; /*!< Number of block IDs in the array */
+ IMG_UINT8 aeBlockIDs[RGXFWIF_HWPERF_CTRL_BLKS_MAX]; /*!< Array of RGX_HWPERF_CNTBLK_ID values */
+} RGXFWIF_HWPERF_CTRL_BLKS;
+
+
+typedef struct _RGXFWIF_HWPERF_SELECT_CUSTOM_CNTRS_
+{
+ IMG_UINT16 ui16CustomBlock;
+ IMG_UINT16 ui16NumCounters;
+ PRGX_HWPERF_SELECT_CUSTOM_CNTRS pui32CustomCounterIDs;
+} RGXFWIF_HWPERF_SELECT_CUSTOM_CNTRS;
+
+typedef struct _RGXFWIF_ZSBUFFER_BACKING_DATA_
+{
+ IMG_UINT32 psZSBufferFWDevVAddr; /*!< ZS-Buffer FW address */
+ IMG_UINT32 bDone; /*!< action backing/unbacking succeeded */
+} RGXFWIF_ZSBUFFER_BACKING_DATA;
+
+typedef struct _RGXFWIF_FREELIST_GS_DATA_
+{
+ IMG_UINT32 psFreeListFWDevVAddr; /*!< Freelist FW address */
+ IMG_UINT32 ui32DeltaSize; /*!< Amount of the Freelist change */
+ IMG_UINT32 ui32NewSize; /*!< New amount of pages on the freelist */
+} RGXFWIF_FREELIST_GS_DATA;
+
+#define RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG 0x80000000
+
+typedef struct _RGXFWIF_FREELISTS_RECONSTRUCTION_DATA_
+{
+ IMG_UINT32 ui32FreelistsCount;
+ IMG_UINT32 aui32FreelistIDs[MAX_HW_TA3DCONTEXTS * RGXFW_MAX_FREELISTS];
+} RGXFWIF_FREELISTS_RECONSTRUCTION_DATA;
+
+/*!
+ ******************************************************************************
+ * Register configuration structures
+ *****************************************************************************/
+
+#define RGXFWIF_REG_CFG_MAX_SIZE 512
+
+typedef enum _RGXFWIF_REGDATA_CMD_TYPE_
+{
+ RGXFWIF_REGCFG_CMD_ADD = 101,
+ RGXFWIF_REGCFG_CMD_CLEAR = 102,
+ RGXFWIF_REGCFG_CMD_ENABLE = 103,
+ RGXFWIF_REGCFG_CMD_DISABLE = 104
+} RGXFWIF_REGDATA_CMD_TYPE;
+
+typedef struct _RGXFWIF_REGCONFIG_DATA_
+{
+ RGXFWIF_REGDATA_CMD_TYPE eCmdType;
+ RGXFWIF_REG_CFG_REC sRegConfig;
+ RGXFWIF_PWR_EVT eRegConfigPI;
+} RGXFWIF_REGCONFIG_DATA;
+
+typedef struct _RGXFWIF_REG_CFG_
+{
+ IMG_UINT32 ui32NumRegsSidekick;
+ IMG_UINT32 ui32NumRegsRascalDust;
+ RGXFWIF_REG_CFG_REC RGXFW_ALIGN asRegConfigs[RGXFWIF_REG_CFG_MAX_SIZE];
+} RGXFWIF_REG_CFG;
+
+typedef enum _RGXFWIF_KCCB_CMD_TYPE_
+{
+ RGXFWIF_KCCB_CMD_KICK = 101,
+ RGXFWIF_KCCB_CMD_MMUCACHE = 102,
+ RGXFWIF_KCCB_CMD_BP = 104,
+ RGXFWIF_KCCB_CMD_SLCBPCTL = 106, /*!< slc bypass control. Requires sSLCBPCtlData. For validation */
+ RGXFWIF_KCCB_CMD_SYNC = 107, /*!< host sync command. Requires sSyncData. */
+ RGXFWIF_KCCB_CMD_SLCFLUSHINVAL = 108, /*!< slc flush and invalidation request */
+ RGXFWIF_KCCB_CMD_CLEANUP = 109, /*!< Requests cleanup of a FW resource (type specified in the command data) */
+ RGXFWIF_KCCB_CMD_POW = 110, /*!< Power request */
+ RGXFWIF_KCCB_CMD_HWPERF_CTRL_EVENTS = 111, /*!< Control the HWPerf event generation behaviour */
+ RGXFWIF_KCCB_CMD_HWPERF_CONFIG_ENABLE_BLKS = 112, /*!< Configure, clear and enable multiple HWPerf blocks */
+ RGXFWIF_KCCB_CMD_HWPERF_CTRL_BLKS = 113, /*!< Enable or disable multiple HWPerf blocks (reusing existing configuration) */
+ RGXFWIF_KCCB_CMD_CORECLKSPEEDCHANGE = 114, /*!< CORE clock speed change event */
+ RGXFWIF_KCCB_CMD_ZSBUFFER_BACKING_UPDATE = 115, /*!< Backing for on-demand ZS-Buffer done */
+ RGXFWIF_KCCB_CMD_ZSBUFFER_UNBACKING_UPDATE = 116, /*!< Unbacking for on-demand ZS-Buffer done */
+ RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE = 117, /*!< Freelist Grow done */
+ RGXFWIF_KCCB_CMD_FREELIST_SHRINK_UPDATE = 118, /*!< Freelist Shrink done */
+ RGXFWIF_KCCB_CMD_FREELISTS_RECONSTRUCTION_UPDATE = 119, /*!< Freelists Reconstruction done */
+ RGXFWIF_KCCB_CMD_HEALTH_CHECK = 120, /*!< Health check request */
+ RGXFWIF_KCCB_CMD_REGCONFIG = 121,
+ RGXFWIF_KCCB_CMD_HWPERF_SELECT_CUSTOM_CNTRS = 122, /*!< Configure the custom counters for HWPerf */
+} RGXFWIF_KCCB_CMD_TYPE;
+
+/* Kernel CCB command packet */
+typedef struct _RGXFWIF_KCCB_CMD_
+{
+ RGXFWIF_KCCB_CMD_TYPE eCmdType; /*!< Command type */
+ union
+ {
+ RGXFWIF_KCCB_CMD_KICK_DATA sCmdKickData; /*!< Data for Kick command */
+ RGXFWIF_MMUCACHEDATA sMMUCacheData; /*!< Data for MMUCACHE command */
+ RGXFWIF_BPDATA sBPData; /*!< Data for Breakpoint Commands */
+ RGXFWIF_SLCBPCTLDATA sSLCBPCtlData; /*!< Data for SLC Bypass Control */
+ RGXFWIF_KCCB_CMD_SYNC_DATA sSyncData; /*!< Data for host sync commands */
+ RGXFWIF_SLCFLUSHINVALDATA sSLCFlushInvalData; /*!< Data for SLC Flush/Inval commands */
+ RGXFWIF_CLEANUP_REQUEST sCleanupData; /*!< Data for cleanup commands */
+ RGXFWIF_POWER_REQUEST sPowData; /*!< Data for power request commands */
+ 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_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 */
+ } uCmdData;
+} RGXFWIF_KCCB_CMD;
+
+RGX_FW_STRUCT_SIZE_ASSERT(RGXFWIF_KCCB_CMD);
+
+/*!
+ ******************************************************************************
+ * Firmware CCB command structure for RGX
+ *****************************************************************************/
+
+typedef struct _RGXFWIF_FWCCB_CMD_ZSBUFFER_BACKING_DATA_
+{
+ IMG_UINT32 ui32ZSBufferID;
+ IMG_BOOL bPopulate;
+} RGXFWIF_FWCCB_CMD_ZSBUFFER_BACKING_DATA;
+
+typedef struct _RGXFWIF_FWCCB_CMD_FREELIST_GS_DATA_
+{
+ IMG_UINT32 ui32FreelistID;
+} RGXFWIF_FWCCB_CMD_FREELIST_GS_DATA;
+
+typedef struct _RGXFWIF_FWCCB_CMD_FREELISTS_RECONSTRUCTION_DATA_
+{
+ IMG_UINT32 ui32FreelistsCount;
+ IMG_UINT32 aui32FreelistIDs[MAX_HW_TA3DCONTEXTS * RGXFW_MAX_FREELISTS];
+} RGXFWIF_FWCCB_CMD_FREELISTS_RECONSTRUCTION_DATA;
+
+typedef struct _RGXFWIF_FWCCB_CMD_CONTEXT_RESET_DATA_
+{
+ IMG_UINT32 ui32ServerCommonContextID; /*!< Context affected by the reset */
+ RGXFWIF_CONTEXT_RESET_REASON eResetReason; /*!< Reason for reset */
+} RGXFWIF_FWCCB_CMD_CONTEXT_RESET_DATA;
+
+
+typedef enum _RGXFWIF_FWCCB_CMD_TYPE_
+{
+ RGXFWIF_FWCCB_CMD_ZSBUFFER_BACKING = 101, /*!< Requests ZSBuffer to be backed with physical pages */
+ RGXFWIF_FWCCB_CMD_ZSBUFFER_UNBACKING = 102, /*!< Requests ZSBuffer to be unbacked */
+ RGXFWIF_FWCCB_CMD_FREELIST_GROW = 103, /*!< Requests an on-demand freelist grow/shrink */
+ RGXFWIF_FWCCB_CMD_FREELISTS_RECONSTRUCTION = 104, /*!< Requests freelists reconstruction */
+ RGXFWIF_FWCCB_CMD_CONTEXT_RESET_NOTIFICATION = 105, /*!< Notifies host of a HWR event on a context */
+ RGXFWIF_FWCCB_CMD_DEBUG_DUMP = 106, /*!< Requests an on-demand debug dump */
+ RGXFWIF_FWCCB_CMD_UPDATE_STATS = 107, /*!< Requests an on-demand update on process stats */
+} RGXFWIF_FWCCB_CMD_TYPE;
+
+typedef enum
+{
+ RGXFWIF_INCREASE_TOTAL_NUM_PARTIAL_RENDERS=1, /*!< PVRSRVStatsUpdateRenderContextStats should increase the value of the ui32TotalNumPartialRenders stat */
+ RGXFWIF_INCREASE_TOTAL_NUM_OUT_OF_MEMORY, /*!< PVRSRVStatsUpdateRenderContextStats should increase the value of the ui32TotalNumOutOfMemory stat */
+ RGXFWIF_INCREASE_NUM_TA_STORES, /*!< PVRSRVStatsUpdateRenderContextStats should increase the value of the ui32NumTAStores stat */
+ RGXFWIF_INCREASE_NUM_3D_STORES, /*!< PVRSRVStatsUpdateRenderContextStats should increase the value of the ui32Num3DStores stat */
+ RGXFWIF_INCREASE_NUM_SH_STORES, /*!< PVRSRVStatsUpdateRenderContextStats should increase the value of the ui32NumSHStores stat */
+ RGXFWIF_INCREASE_NUM_CDM_STORES /*!< PVRSRVStatsUpdateRenderContextStats should increase the value of the ui32NumCDMStores stat */
+} RGXFWIF_FWCCB_CMD_UPDATE_STATS_TYPE;
+
+
+/* Firmware CCB command packet */
+
+typedef struct
+{
+ IMG_UINT32 ui32ElementToUpdate; /*!< Element to update */
+ IMG_PID pidOwner; /*!< The pid of the process whose stats are being updated */
+} RGXFWIF_FWCCB_CMD_UPDATE_STATS_DATA;
+
+typedef struct _RGXFWIF_FWCCB_CMD_
+{
+ RGXFWIF_FWCCB_CMD_TYPE eCmdType; /*!< Command type */
+ union
+ {
+ RGXFWIF_FWCCB_CMD_ZSBUFFER_BACKING_DATA sCmdZSBufferBacking; /*!< Data for Z/S-Buffer on-demand (un)backing*/
+ RGXFWIF_FWCCB_CMD_FREELIST_GS_DATA sCmdFreeListGS; /*!< Data for on-demand freelist grow/shrink */
+ RGXFWIF_FWCCB_CMD_FREELISTS_RECONSTRUCTION_DATA sCmdFreeListsReconstruction; /*!< Data for freelists reconstruction */
+ RGXFWIF_FWCCB_CMD_CONTEXT_RESET_DATA sCmdContextResetNotification; /*!< Data for context reset notification */
+ RGXFWIF_FWCCB_CMD_UPDATE_STATS_DATA sCmdUpdateStatsData; /*!< Data for updating process stats */
+ IMG_UINT32 ui32Padding[7]; /*!< Force structure to be 8 words */
+ } uCmdData;
+} RGXFWIF_FWCCB_CMD;
+
+BLD_ASSERT(sizeof(RGXFWIF_FWCCB_CMD)==32, rgx_fwif_km_h);
+
+/*!
+ ******************************************************************************
+ * Signature and Checksums Buffer
+ *****************************************************************************/
+typedef struct _RGXFWIF_SIGBUF_CTL_
+{
+ PRGXFWIF_SIGBUFFER psBuffer; /*!< Ptr to Signature Buffer memory */
+ IMG_UINT32 ui32LeftSizeInRegs; /*!< Amount of space left for storing regs in the buffer */
+} RGXFWIF_SIGBUF_CTL;
+
+/*!
+ ******************************************************************************
+ * Updated configuration post FW data init.
+ *****************************************************************************/
+typedef struct _RGXFWIF_RUNTIME_CFG_
+{
+ IMG_UINT32 ui32ActivePMLatencyms; /* APM latency in ms before signalling IDLE to the host */
+ IMG_BOOL bActivePMLatencyPersistant; /* If set, APM latency does not reset to system default each GPU power transition */
+ IMG_UINT32 ui32CoreClockSpeed; /* Core clock speed, currently only used to calculate timer ticks */
+} RGXFWIF_RUNTIME_CFG;
+
+/*!
+ *****************************************************************************
+ * Control data for RGX
+ *****************************************************************************/
+
+typedef struct _RGXFWIF_INIT_
+{
+ IMG_DEV_PHYADDR RGXFW_ALIGN sFaultPhysAddr;
+
+ IMG_DEV_VIRTADDR RGXFW_ALIGN sPDSExecBase;
+ IMG_DEV_VIRTADDR RGXFW_ALIGN sUSCExecBase;
+ IMG_DEV_VIRTADDR RGXFW_ALIGN sResultDumpBase;
+ IMG_DEV_VIRTADDR RGXFW_ALIGN sDPXControlStreamBase;
+ IMG_DEV_VIRTADDR RGXFW_ALIGN sRTUHeapBase;
+
+ IMG_BOOL bFirstTA;
+ IMG_BOOL bFirstRender;
+ IMG_BOOL bFrameworkAfterInit;
+ IMG_BOOL bEnableHWPerf;
+ IMG_BOOL bDisableFilterHWPerfCustomCounter;
+ IMG_UINT32 uiPowerSync;
+ IMG_UINT32 ui32FilterFlags;
+
+ /* Kernel CCBs */
+ PRGXFWIF_CCB_CTL psKernelCCBCtl[RGXFWIF_DM_MAX];
+ PRGXFWIF_CCB psKernelCCB[RGXFWIF_DM_MAX];
+
+ /* Firmware CCBs */
+ PRGXFWIF_CCB_CTL psFirmwareCCBCtl[RGXFWIF_DM_MAX];
+ PRGXFWIF_CCB psFirmwareCCB[RGXFWIF_DM_MAX];
+
+ RGXFWIF_DM eDM[RGXFWIF_DM_MAX];
+
+ RGXFWIF_SIGBUF_CTL asSigBufCtl[RGXFWIF_DM_MAX];
+
+ IMG_BOOL bEnableLogging;
+ IMG_UINT32 ui32ConfigFlags; /*!< Configuration flags from host */
+ IMG_UINT32 ui32BreakpointTemps;
+ IMG_UINT32 ui32BreakpointShareds;
+ struct
+ {
+ IMG_UINT64 uiBase;
+ IMG_UINT64 uiLen;
+ IMG_UINT64 uiXStride;
+ } RGXFW_ALIGN sBifTilingCfg[RGXFWIF_NUM_BIF_TILING_CONFIGS];
+
+ PRGXFWIF_RUNTIME_CFG psRuntimeCfg;
+
+ PRGXFWIF_TRACEBUF psTraceBufCtl;
+ PRGXFWIF_HWPERFINFO psHWPerfInfoCtl;
+ IMG_UINT64 RGXFW_ALIGN ui64HWPerfFilter;
+
+ PRGXFWIF_HWRINFOBUF psRGXFWIfHWRInfoBufCtl;
+ PRGXFWIF_GPU_UTIL_FWCB psGpuUtilFWCbCtl;
+ PRGXFWIF_REG_CFG psRegCfg;
+
+
+#if defined(RGXFW_ALIGNCHECKS)
+#if defined(RGX_FIRMWARE)
+ IMG_UINT32* paui32AlignChecks;
+#else
+ RGXFWIF_DEV_VIRTADDR paui32AlignChecks;
+#endif
+#endif
+
+ /* Core clock speed at FW boot time */
+ IMG_UINT32 ui32InitialCoreClockSpeed;
+
+ /* APM latency in ms before signalling IDLE to the host */
+ IMG_UINT32 ui32ActivePMLatencyms;
+
+ /* Flag to be set by the Firmware after successful start */
+ IMG_BOOL bFirmwareStarted;
+
+ IMG_UINT32 ui32FirmwareStartedTimeStamp;
+
+ /* Compatibility checks to be populated by the Firmware */
+ RGXFWIF_COMPCHECKS sRGXCompChecks;
+
+ RGXFWIF_DMA_ADDR sCorememDataStore;
+
+#if defined(RGX_FEATURE_SLC_VIVT)
+ IMG_DEV_VIRTADDR RGXFW_ALIGN sSLC3FenceDevVAddr;
+#endif
+
+} RGXFWIF_INIT;
+
+
+/*!
+ ******************************************************************************
+ * Client CCB commands which are only required by the kernel
+ *****************************************************************************/
+typedef struct _RGXFWIF_CMD_PRIORITY_
+{
+ IMG_UINT32 ui32Priority;
+} RGXFWIF_CMD_PRIORITY;
+
+/*!
+ ******************************************************************************
+ * RGXFW Unittests declarations
+ *****************************************************************************/
+typedef struct _RGXFW_UNITTEST2_
+{
+ /* Irq events */
+ IMG_UINT32 ui32IrqKicksDM[RGXFWIF_DM_MAX_MTS];
+ IMG_UINT32 ui32IrqKicksBg;
+ IMG_UINT32 ui32IrqKicksTimer;
+
+ /* Bg events */
+ IMG_UINT32 ui32BgKicksDM[RGXFWIF_DM_MAX_MTS];
+ IMG_UINT32 ui32BgKicksCounted;
+
+} RGXFW_UNITTEST2;
+
+/*!
+ ******************************************************************************
+ * RGXFW_UNITTESTS declaration
+ *****************************************************************************/
+#define RGXFW_UNITTEST_FWPING (0x1)
+#define RGXFW_UNITTEST_FWPONG (0x2)
+
+#define RGXFW_UNITTEST_IS_BGKICK(DM) ((DM) & 0x1)
+
+typedef struct _RGXFW_UNITTESTS_
+{
+ IMG_UINT32 ui32Status;
+
+ RGXFW_UNITTEST2 sUnitTest2;
+
+} RGXFW_UNITTESTS;
+
+#endif /* __RGX_FWIF_KM_H__ */
+
+/******************************************************************************
+ End of file (rgx_fwif_km.h)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/rogue/services/include/rgx_fwif_resetframework.h b/drivers/gpu/rogue/services/include/rgx_fwif_resetframework.h
new file mode 100644
index 000000000000..25ee674406d4
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/rgx_fwif_resetframework.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@File rgx_fwif_resetframework.h
+@Title Post-reset work-around framework FW interface
+@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(_RGX_FWIF_RESETFRAMEWORK_H)
+#define _RGX_FWIF_RESETFRAMEWORK_H
+
+#include "img_types.h"
+#include "rgx_fwif_shared.h"
+
+typedef struct _RGXFWIF_RF_REGISTERS_
+{
+ IMG_UINT64 uCDMReg_CDM_CTRL_STREAM_BASE;
+} RGXFWIF_RF_REGISTERS;
+
+#define RGXFWIF_RF_FLAG_ENABLE 0x00000001 /*!< enables the reset framework in the firmware */
+
+typedef struct _RGXFWIF_RF_CMD_
+{
+ IMG_UINT32 ui32Flags;
+
+ /* THIS MUST BE THE LAST MEMBER OF THE CONTAINING STRUCTURE */
+ RGXFWIF_RF_REGISTERS RGXFW_ALIGN sFWRegisters;
+
+} RGXFWIF_RF_CMD;
+
+/* to opaquely allocate and copy in the kernel */
+#define RGXFWIF_RF_CMD_SIZE sizeof(RGXFWIF_RF_CMD)
+
+#endif /* _RGX_FWIF_RESETFRAMEWORK_H */
diff --git a/drivers/gpu/rogue/services/include/rgx_fwif_shared.h b/drivers/gpu/rogue/services/include/rgx_fwif_shared.h
new file mode 100644
index 000000000000..11f1f1415050
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/rgx_fwif_shared.h
@@ -0,0 +1,439 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX firmware interface structures
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX firmware interface structures shared by both host client
+ and host server
+@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 (__RGX_FWIF_SHARED_H__)
+#define __RGX_FWIF_SHARED_H__
+
+#include "img_types.h"
+#include "rgx_common.h"
+#include "devicemem_typedefs.h"
+
+
+/*!
+ ******************************************************************************
+ * Device state flags
+ *****************************************************************************/
+#define RGXKMIF_DEVICE_STATE_ZERO_FREELIST (0x1 << 0) /*!< Zeroing the physical pages of reconstructed free lists */
+#define RGXKMIF_DEVICE_STATE_FTRACE_EN (0x1 << 1) /*!< Used to enable device FTrace thread to consume HWPerf data */
+#define RGXKMIF_DEVICE_STATE_DISABLE_DW_LOGGING_EN (0x1 << 2) /*!< Used to disable the Devices Watchdog logging */
+
+
+/*!
+ ******************************************************************************
+ * RGXFW Compiler alignment definitions
+ *****************************************************************************/
+#if defined(__GNUC__)
+#define RGXFW_ALIGN __attribute__ ((aligned (8)))
+#elif defined(__MECC__)
+#define RGXFW_ALIGN _Pragma("align 8")
+#elif defined(_MSC_VER)
+#define RGXFW_ALIGN __declspec(align(8))
+#pragma warning (disable : 4324)
+#else
+#error "Align MACROS need to be defined for this compiler"
+#endif
+
+/* Required memory alignment for 64-bit variables accessible by Meta
+ (the gcc meta aligns 64-bit vars to 64-bit; therefore, mem shared between
+ the host and meta that contains 64-bit vars has to maintain this aligment)*/
+#define RGXFWIF_FWALLOC_ALIGN sizeof(IMG_UINT64)
+
+/*!
+ ******************************************************************************
+ * Force structure 8-byte alignment
+ * This was introduced to fix the ARM64 misalignment issue when accessing
+ * uncached memory.
+ * It is now applied unconditionally so alignment issues cannot arise on
+ * mixed 32/64-bit architectures by Customers failing to enable it.
+ *****************************************************************************/
+#define UNCACHED_ALIGN RGXFW_ALIGN
+
+typedef struct _RGXFWIF_DEV_VIRTADDR_
+{
+ IMG_UINT32 ui32Addr;
+} RGXFWIF_DEV_VIRTADDR;
+
+typedef struct _RGXFWIF_DMA_ADDR_
+{
+ IMG_DEV_VIRTADDR RGXFW_ALIGN psDevVirtAddr;
+
+#if defined(RGX_FIRMWARE)
+ IMG_PBYTE pbyFWAddr;
+#else
+ RGXFWIF_DEV_VIRTADDR pbyFWAddr;
+#endif
+} RGXFWIF_DMA_ADDR;
+
+typedef IMG_UINT8 RGXFWIF_CCCB;
+
+#if defined(RGX_FIRMWARE)
+/* Compiling the actual firmware - use a fully typed pointer */
+typedef RGXFWIF_CCCB *PRGXFWIF_CCCB;
+typedef struct _RGXFWIF_CCCB_CTL_ *PRGXFWIF_CCCB_CTL;
+typedef struct _RGXFWIF_RENDER_TARGET_ *PRGXFWIF_RENDER_TARGET;
+typedef struct _RGXFWIF_HWRTDATA_ *PRGXFWIF_HWRTDATA;
+typedef struct _RGXFWIF_FREELIST_ *PRGXFWIF_FREELIST;
+typedef struct _RGXFWIF_RTA_CTL_ *PRGXFWIF_RTA_CTL;
+typedef IMG_UINT32 *PRGXFWIF_UFO_ADDR;
+typedef IMG_UINT64 *PRGXFWIF_TIMESTAMP_ADDR;
+typedef struct _RGXFWIF_CLEANUP_CTL_ *PRGXFWIF_CLEANUP_CTL;
+#else
+/* Compiling the host driver - use a firmware device virtual pointer */
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_CCCB;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_CCCB_CTL;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_RENDER_TARGET;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_HWRTDATA;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_FREELIST;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_RTA_CTL;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_UFO_ADDR;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_TIMESTAMP_ADDR;
+typedef RGXFWIF_DEV_VIRTADDR PRGXFWIF_CLEANUP_CTL;
+#endif /* RGX_FIRMWARE */
+
+
+
+typedef struct _RGXFWIF_UFO_
+{
+ PRGXFWIF_UFO_ADDR puiAddrUFO;
+ IMG_UINT32 ui32Value;
+} RGXFWIF_UFO;
+
+
+/*!
+ Last reset reason for a context.
+*/
+typedef enum _RGXFWIF_CONTEXT_RESET_REASON_
+{
+ RGXFWIF_CONTEXT_RESET_REASON_NONE = 0, /*!< No reset reason recorded */
+ RGXFWIF_CONTEXT_RESET_REASON_GUILTY_LOCKUP = 1, /*!< Caused a reset due to locking up */
+ RGXFWIF_CONTEXT_RESET_REASON_INNOCENT_LOCKUP = 2, /*!< Affected by another context locking up */
+ RGXFWIF_CONTEXT_RESET_REASON_GUILTY_OVERRUNING = 3, /*!< Overran the global deadline */
+ RGXFWIF_CONTEXT_RESET_REASON_INNOCENT_OVERRUNING = 4, /*!< Affected by another context overrunning */
+} RGXFWIF_CONTEXT_RESET_REASON;
+
+
+/*!
+ HWRTData state the render is in
+*/
+typedef enum
+{
+ RGXFWIF_RTDATA_STATE_NONE = 0,
+ RGXFWIF_RTDATA_STATE_KICKTA,
+ RGXFWIF_RTDATA_STATE_KICKTAFIRST,
+ RGXFWIF_RTDATA_STATE_TAFINISHED,
+ RGXFWIF_RTDATA_STATE_KICK3D,
+ RGXFWIF_RTDATA_STATE_3DFINISHED,
+ RGXFWIF_RTDATA_STATE_TAOUTOFMEM,
+ RGXFWIF_RTDATA_STATE_PARTIALRENDERFINISHED,
+ RGXFWIF_RTDATA_STATE_HWR /*!< In case of HWR, we can't set the RTDATA state to NONE,
+ as this will cause any TA to become a first TA.
+ To ensure all related TA's are skipped, we use the HWR state */
+} RGXFWIF_RTDATA_STATE;
+
+typedef struct _RGXFWIF_CLEANUP_CTL_
+{
+ IMG_UINT32 ui32SubmittedCommands; /*!< Number of commands received by the FW */
+ IMG_UINT32 ui32ExecutedCommands; /*!< Number of commands executed by the FW */
+ IMG_UINT32 ui32SyncObjDevVAddr; /*!< SyncPrimitive to update after cleanup completion */
+}RGXFWIF_CLEANUP_CTL;
+
+
+/*!
+ ******************************************************************************
+ * Client CCB control for RGX
+ *****************************************************************************/
+typedef struct _RGXFWIF_CCCB_CTL_
+{
+ IMG_UINT32 ui32WriteOffset; /*!< write offset into array of commands (MUST be aligned to 16 bytes!) */
+ IMG_UINT32 ui32ReadOffset; /*!< read offset into array of commands */
+ IMG_UINT32 ui32DepOffset; /*!< Dependency offset */
+ IMG_UINT32 ui32WrapMask; /*!< Offset wrapping mask (Total capacity of the CCB - 1) */
+} RGXFWIF_CCCB_CTL;
+
+typedef enum
+{
+ RGXFW_LOCAL_FREELIST = 0,
+ RGXFW_GLOBAL_FREELIST = 1,
+#if defined(SUPPORT_MMU_FREELIST)
+ RGXFW_MMU_FREELIST = 2,
+#endif
+ RGXFW_MAX_FREELISTS
+} RGXFW_FREELIST_TYPE;
+
+typedef struct _RGXFWIF_RTA_CTL_
+{
+ IMG_UINT32 ui32RenderTargetIndex; //Render number
+ IMG_UINT32 ui32CurrentRenderTarget; //index in RTA
+ IMG_UINT32 ui32ActiveRenderTargets; //total active RTs
+#if defined(RGX_FIRMWARE)
+ IMG_UINT32 *paui32ValidRenderTargets; //Array of valid RT indices
+#else
+ RGXFWIF_DEV_VIRTADDR paui32ValidRenderTargets;
+#endif
+} RGXFWIF_RTA_CTL;
+
+typedef struct _RGXFWIF_FREELIST_
+{
+ IMG_DEV_VIRTADDR RGXFW_ALIGN psFreeListDevVAddr;
+ IMG_UINT64 RGXFW_ALIGN ui64CurrentDevVAddr;
+ IMG_UINT64 RGXFW_ALIGN ui64CurrentStackTop;
+ IMG_UINT32 ui32MaxPages;
+ IMG_UINT32 ui32GrowPages;
+ IMG_UINT32 ui32CurrentPages;
+ IMG_UINT32 ui32AllocatedPageCount;
+ IMG_UINT32 ui32AllocatedMMUPageCount;
+ IMG_UINT32 ui32HWRCounter;
+ IMG_UINT32 ui32FreeListID;
+ IMG_BOOL bGrowPending;
+} RGXFWIF_FREELIST;
+
+
+typedef struct _RGXFWIF_RENDER_TARGET_
+{
+ IMG_DEV_VIRTADDR RGXFW_ALIGN psVHeapTableDevVAddr; /*!< VHeap Data Store */
+ IMG_BOOL bTACachesNeedZeroing; /*!< Whether RTC and TPC caches (on mem) need to be zeroed on next first TA kick */
+
+} RGXFWIF_RENDER_TARGET;
+
+
+typedef struct _RGXFWIF_HWRTDATA_
+{
+ RGXFWIF_RTDATA_STATE eState;
+
+ IMG_UINT32 ui32NumPartialRenders; /*!< Number of partial renders. Used to setup ZLS bits correctly */
+ IMG_DEV_VIRTADDR RGXFW_ALIGN psPMMListDevVAddr; /*!< MList Data Store */
+
+#if defined(RGX_FEATURE_SCALABLE_TE_ARCH)
+ IMG_UINT64 RGXFW_ALIGN ui64VCECatBase[4];
+ IMG_UINT64 RGXFW_ALIGN ui64VCELastCatBase[4];
+ IMG_UINT64 RGXFW_ALIGN ui64TECatBase[4];
+ IMG_UINT64 RGXFW_ALIGN ui64TELastCatBase[4];
+#else
+ IMG_UINT64 RGXFW_ALIGN ui64VCECatBase;
+ IMG_UINT64 RGXFW_ALIGN ui64VCELastCatBase;
+ IMG_UINT64 RGXFW_ALIGN ui64TECatBase;
+ IMG_UINT64 RGXFW_ALIGN ui64TELastCatBase;
+#endif
+ IMG_UINT64 RGXFW_ALIGN ui64AlistCatBase;
+ IMG_UINT64 RGXFW_ALIGN ui64AlistLastCatBase;
+
+#if defined(SUPPORT_VFP)
+ IMG_DEV_VIRTADDR RGXFW_ALIGN sVFPPageTableAddr;
+#endif
+ IMG_UINT64 RGXFW_ALIGN ui64PMAListStackPointer;
+ IMG_UINT32 ui32PMMListStackPointer;
+
+ PRGXFWIF_FREELIST RGXFW_ALIGN apsFreeLists[RGXFW_MAX_FREELISTS];
+ IMG_UINT32 aui32FreeListHWRSnapshot[RGXFW_MAX_FREELISTS];
+
+ PRGXFWIF_RENDER_TARGET psParentRenderTarget;
+
+ RGXFWIF_CLEANUP_CTL sTACleanupState;
+ RGXFWIF_CLEANUP_CTL s3DCleanupState;
+ IMG_UINT32 ui32CleanupStatus;
+#define HWRTDATA_TA_CLEAN (1 << 0)
+#define HWRTDATA_3D_CLEAN (1 << 1)
+
+ PRGXFWIF_RTA_CTL psRTACtl;
+
+ IMG_UINT32 bHasLastTA;
+
+ IMG_UINT32 ui32PPPScreen;
+ IMG_UINT32 ui32PPPGridOffset;
+ IMG_UINT64 RGXFW_ALIGN ui64PPPMultiSampleCtl;
+ IMG_UINT32 ui32TPCStride;
+ IMG_DEV_VIRTADDR RGXFW_ALIGN sTailPtrsDevVAddr;
+ IMG_UINT32 ui32TPCSize;
+ IMG_UINT32 ui32TEScreen;
+ IMG_UINT32 ui32MTileStride;
+ IMG_UINT32 ui32TEAA;
+ IMG_UINT32 ui32TEMTILE1;
+ IMG_UINT32 ui32TEMTILE2;
+ IMG_UINT32 ui32ISPMergeLowerX;
+ IMG_UINT32 ui32ISPMergeLowerY;
+ IMG_UINT32 ui32ISPMergeUpperX;
+ IMG_UINT32 ui32ISPMergeUpperY;
+ IMG_UINT32 ui32ISPMergeScaleX;
+ IMG_UINT32 ui32ISPMergeScaleY;
+} RGXFWIF_HWRTDATA;
+
+typedef enum
+{
+ RGXFWIF_ZSBUFFER_UNBACKED = 0,
+ RGXFWIF_ZSBUFFER_BACKED,
+ RGXFWIF_ZSBUFFER_BACKING_PENDING,
+ RGXFWIF_ZSBUFFER_UNBACKING_PENDING,
+}RGXFWIF_ZSBUFFER_STATE;
+
+typedef struct _RGXFWIF_ZSBUFFER_
+{
+ IMG_UINT32 ui32ZSBufferID; /*!< Buffer ID*/
+ IMG_BOOL bOnDemand; /*!< Needs On-demand ZS Buffer allocation */
+ RGXFWIF_ZSBUFFER_STATE eState; /*!< Z/S-Buffer state */
+ RGXFWIF_CLEANUP_CTL sCleanupState; /*!< Cleanup state */
+} RGXFWIF_FWZSBUFFER;
+
+/* Number of BIF tiling configurations / heaps */
+#define RGXFWIF_NUM_BIF_TILING_CONFIGS 4
+
+/*!
+ *****************************************************************************
+ * RGX Compatibility checks
+ *****************************************************************************/
+/* WARNING: RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX can be increased only and
+ always equal to (N * sizeof(IMG_UINT32) - 1) */
+#define RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX 3 /* WARNING: Do not change this macro without changing
+ accesses from dword to byte in function rgx_bvnc_packed() */
+
+/* WARNING: Whenever the layout of RGXFWIF_COMPCHECKS_BVNC is a subject of change,
+ following define should be increased by 1 to indicate to compatibility logic,
+ that layout has changed */
+#define RGXFWIF_COMPCHECKS_LAYOUT_VERSION 1
+
+typedef struct _RGXFWIF_COMPCHECKS_BVNC_
+{
+ IMG_UINT32 ui32LayoutVersion; /* WARNING: This field must be defined as first one in this structure */
+ IMG_UINT32 ui32VLenMax;
+ IMG_UINT32 ui32BNC;
+ IMG_CHAR aszV[RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX + 1];
+} UNCACHED_ALIGN RGXFWIF_COMPCHECKS_BVNC;
+
+#define RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(name) RGXFWIF_COMPCHECKS_BVNC name = { RGXFWIF_COMPCHECKS_LAYOUT_VERSION, RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX }
+#define RGXFWIF_COMPCHECKS_BVNC_INIT(name) do { (name).ui32LayoutVersion = RGXFWIF_COMPCHECKS_LAYOUT_VERSION; \
+ (name).ui32VLenMax = RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX; } while (0)
+
+typedef struct _RGXFWIF_COMPCHECKS_
+{
+ RGXFWIF_COMPCHECKS_BVNC sHWBVNC; /*!< hardware BNC (from the RGX registers) */
+ RGXFWIF_COMPCHECKS_BVNC sFWBVNC; /*!< firmware BNC */
+ IMG_UINT32 ui32METAVersion;
+ IMG_UINT32 ui32DDKVersion; /*!< software DDK version */
+ IMG_UINT32 ui32DDKBuild; /*!< software DDK build no. */
+ IMG_UINT32 ui32BuildOptions; /*!< build options bit-field */
+ IMG_BOOL bUpdated; /*!< Information is valid */
+} UNCACHED_ALIGN RGXFWIF_COMPCHECKS;
+
+
+#define GET_CCB_SPACE(WOff, ROff, CCBSize) \
+ ((((ROff) - (WOff)) + ((CCBSize) - 1)) & ((CCBSize) - 1))
+
+#define UPDATE_CCB_OFFSET(Off, PacketSize, CCBSize) \
+ (Off) = (((Off) + (PacketSize)) & ((CCBSize) - 1))
+
+#define RESERVED_CCB_SPACE (sizeof(IMG_UINT32))
+
+
+/* Defines relating to the per-context CCBs */
+#define RGX_CCB_SIZE_LOG2 (16) /* 64kB */
+#define RGX_CCB_ALLOCGRAN (64)
+#define RGX_CCB_TYPE_TASK (1 << 31)
+#define RGX_CCB_FWALLOC_ALIGN(size) (((size) + (RGXFWIF_FWALLOC_ALIGN-1)) & ~(RGXFWIF_FWALLOC_ALIGN - 1))
+
+/*!
+ ******************************************************************************
+ * Client CCB commands for RGX
+ *****************************************************************************/
+typedef enum _RGXFWIF_CCB_CMD_TYPE_
+{
+ RGXFWIF_CCB_CMD_TYPE_TA = 201 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_3D = 202 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_CDM = 203 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_TQ_3D = 204 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_TQ_2D = 205 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_3D_PR = 206 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_NULL = 207 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_SHG = 208 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_RTU = 209 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_RTU_FC = 210 | RGX_CCB_TYPE_TASK,
+ RGXFWIF_CCB_CMD_TYPE_PRE_TIMESTAMP = 211 | RGX_CCB_TYPE_TASK,
+
+/* Leave a gap between CCB specific commands and generic commands */
+ RGXFWIF_CCB_CMD_TYPE_FENCE = 212,
+ RGXFWIF_CCB_CMD_TYPE_UPDATE = 213,
+ RGXFWIF_CCB_CMD_TYPE_RMW_UPDATE = 214,
+ RGXFWIF_CCB_CMD_TYPE_FENCE_PR = 215,
+ RGXFWIF_CCB_CMD_TYPE_PRIORITY = 216,
+/* Pre and Post timestamp commands are supposed to sandwich the DM cmd. The
+ padding code with the CCB wrap upsets the FW if we don't have the task type
+ bit cleared for POST_TIMESTAMPs. That's why we have 2 different cmd types.
+*/
+ RGXFWIF_CCB_CMD_TYPE_POST_TIMESTAMP = 217,
+
+ RGXFWIF_CCB_CMD_TYPE_PADDING = 220,
+} RGXFWIF_CCB_CMD_TYPE;
+
+typedef struct _RGXFWIF_CCB_CMD_HEADER_
+{
+ RGXFWIF_CCB_CMD_TYPE eCmdType;
+ IMG_UINT32 ui32CmdSize;
+} RGXFWIF_CCB_CMD_HEADER;
+
+typedef enum _RGXFWIF_PWR_EVT_
+{
+ RGXFWIF_PWR_EVT_PWR_ON, /* Sidekick power event */
+ RGXFWIF_PWR_EVT_DUST_CHANGE, /* Rascal / dust power event */
+ RGXFWIF_PWR_EVT_ALL /* Applies to all power events. Keep as last element */
+} RGXFWIF_PWR_EVT;
+
+typedef struct _RGXFWIF_REG_CFG_REC_
+{
+ IMG_UINT64 ui64Addr;
+ IMG_UINT64 ui64Value;
+} RGXFWIF_REG_CFG_REC;
+
+
+typedef struct _RGXFWIF_TIME_CORR_
+{
+ IMG_UINT64 RGXFW_ALIGN ui64OSTimeStamp;
+ IMG_UINT64 RGXFW_ALIGN ui64CRTimeStamp;
+ IMG_UINT32 ui32DVFSClock;
+} RGXFWIF_TIME_CORR;
+
+#endif /* __RGX_FWIF_SHARED_H__ */
+
+/******************************************************************************
+ End of file (rgx_fwif_shared.h)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/rogue/services/include/rgx_pdump_panics.h b/drivers/gpu/rogue/services/include/rgx_pdump_panics.h
new file mode 100644
index 000000000000..6bbe5b0262db
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/rgx_pdump_panics.h
@@ -0,0 +1,67 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX PDump panic definitions header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX PDump panic definitions header
+@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 (RGX_PDUMP_PANICS_H_)
+#define RGX_PDUMP_PANICS_H_
+
+
+/*! Unique device specific IMG_UINT16 panic IDs to identify the cause of a
+ * RGX PDump panic in a PDump script. */
+typedef enum
+{
+ RGX_PDUMP_PANIC_UNDEFINED = 0,
+
+ /* These panics occur when test parameters and driver configuration
+ * enable features that require the firmware and host driver to
+ * communicate. Such features are not supported with off-line playback.
+ */
+ RGX_PDUMP_PANIC_ZSBUFFER_BACKING = 101, /*!< Requests ZSBuffer to be backed with physical pages */
+ RGX_PDUMP_PANIC_ZSBUFFER_UNBACKING = 102, /*!< Requests ZSBuffer to be unbacked */
+ RGX_PDUMP_PANIC_FREELIST_GROW = 103, /*!< Requests an on-demand freelist grow/shrink */
+ RGX_PDUMP_PANIC_FREELISTS_RECONSTRUCTION = 104, /*!< Requests freelists reconstruction */
+} RGX_PDUMP_PANIC;
+
+
+#endif /* RGX_PDUMP_PANICS_H_ */
+
+
diff --git a/drivers/gpu/rogue/services/include/rgx_tq_shared.h b/drivers/gpu/rogue/services/include/rgx_tq_shared.h
new file mode 100644
index 000000000000..bd3460cca1a8
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/rgx_tq_shared.h
@@ -0,0 +1,63 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX transfer queue shared
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Shared definitions between client and server
+@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_TQ_SHARED_H__
+#define __RGX_TQ_SHARED_H__
+
+#define TQ_MAX_PREPARES_PER_SUBMIT 16
+
+#define TQ_PREP_FLAGS_COMMAND_3D 0x0
+#define TQ_PREP_FLAGS_COMMAND_2D 0x1
+#define TQ_PREP_FLAGS_COMMAND_MASK (0xf)
+#define TQ_PREP_FLAGS_COMMAND_SHIFT 0
+#define TQ_PREP_FLAGS_PDUMPCONTINUOUS (1 << 4)
+#define TQ_PREP_FLAGS_START (1 << 5)
+#define TQ_PREP_FLAGS_END (1 << 6)
+
+#define TQ_PREP_FLAGS_COMMAND_SET(m) \
+ ((TQ_PREP_FLAGS_COMMAND_##m << TQ_PREP_FLAGS_COMMAND_SHIFT) & TQ_PREP_FLAGS_COMMAND_MASK)
+
+#define TQ_PREP_FLAGS_COMMAND_IS(m,n) \
+ (((m & TQ_PREP_FLAGS_COMMAND_MASK) >> TQ_PREP_FLAGS_COMMAND_SHIFT) == TQ_PREP_FLAGS_COMMAND_##n)
+
+#endif /* __RGX_TQ_SHARED_H__ */
diff --git a/drivers/gpu/rogue/services/include/rgxapi_km.h b/drivers/gpu/rogue/services/include/rgxapi_km.h
new file mode 100644
index 000000000000..2b8acf47ce51
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/rgxapi_km.h
@@ -0,0 +1,186 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX API Header kernel mode
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Exported RGX API details
+@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 __RGXAPI_KM_H__
+#define __RGXAPI_KM_H__
+
+#if defined(SUPPORT_SHARED_SLC)
+/*!
+******************************************************************************
+
+ @Function RGXInitSLC
+
+ @Description Init the SLC after a power up. It is required to call this
+ function if using SUPPORT_SHARED_SLC. Otherwise, it shouldn't
+ be called.
+
+ @Input hDevHandle : RGX Device Node
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXInitSLC(IMG_HANDLE hDevHandle);
+#endif
+
+#if defined(SUPPORT_KERNEL_HWPERF)
+
+#include "rgx_hwperf_km.h"
+
+
+/******************************************************************************
+ * RGX HW Performance Profiling Control API(s)
+ *****************************************************************************/
+
+/**************************************************************************/ /*!
+@Function RGXHWPerfConnect
+@Description Obtain a connection object to the HWPerf device
+@Output phDevData Address of a handle to a connection object
+@Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+PVRSRV_ERROR RGXHWPerfConnect(
+ IMG_HANDLE* phDevData);
+
+
+/**************************************************************************/ /*!
+@Function RGXHWPerfDisconnect
+@Description Disconnect from the HWPerf device
+@Input hSrvHandle Handle to connection object as returned from
+ RGXHWPerfConnect()
+@Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+PVRSRV_ERROR RGXHWPerfDisconnect(
+ IMG_HANDLE hDevData);
+
+
+/**************************************************************************/ /*!
+@Function RGXHWPerfControl
+@Description Enable or disable the generation of RGX HWPerf event packets.
+ See RGXCtrlHWPerf().
+@Input hDevData Handle to connection object
+@Input bToggle Switch to toggle or apply mask.
+@Input ui64Mask Mask of events to control.
+@Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV RGXHWPerfControl(
+ IMG_HANDLE hDevData,
+ IMG_BOOL bToggle,
+ IMG_UINT64 ui64Mask);
+
+
+/**************************************************************************/ /*!
+@Function RGXHWPerfConfigureAndEnableCounters
+@Description Enable and configure the performance counter block for
+ one or more device layout modules.
+ See RGXConfigureAndEnableHWPerfCounters().
+@Input hDevData Handle to connection object
+@Input ui32NumBlocks Number of elements in the array
+@Input asBlockConfigs Address of the array of configuration blocks
+@Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV RGXHWPerfConfigureAndEnableCounters(
+ IMG_HANDLE hDevData,
+ IMG_UINT32 ui32NumBlocks,
+ RGX_HWPERF_CONFIG_CNTBLK* asBlockConfigs);
+
+
+/**************************************************************************/ /*!
+@Function RGXDisableHWPerfCounters
+@Description Disable the performance counter block for one or more
+ device layout modules. See RGXDisableHWPerfCounters().
+@Input hDevData Handle to connection/device object
+@Input ui32NumBlocks Number of elements in the array
+@Input aeBlockIDs An array of bytes with values taken from
+ the RGX_HWPERF_CNTBLK_ID enumeration.
+@Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV RGXHWPerfDisableCounters(
+ IMG_HANDLE hDevData,
+ IMG_UINT32 ui32NumBlocks,
+ IMG_UINT8* aeBlockIDs);
+
+
+/******************************************************************************
+ * RGX HW Performance Profiling Retrieval API(s)
+ *****************************************************************************/
+
+/**************************************************************************/ /*!
+@Function RGXHWPerfAcquireData
+@Description When there is data available to read this call returns with
+ the address and length of the data buffer the
+ client can safely read. This buffer may contain one or more
+ event packets. If no data is available then this call
+ returns OK and sets *puiBufLen to 0 on exit.
+ Clients must pair this call with a ReleaseData call.
+@Input hDevData Handle to connection/device object
+@Output ppBuf Address of a pointer to a byte buffer. On exit
+ it contains the address of buffer to read from
+@Output puiBufLen Pointer to an integer. On exit it is the size
+ of the data to read from the buffer
+@Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+PVRSRV_ERROR RGXHWPerfAcquireData(
+ IMG_HANDLE hDevData,
+ IMG_PBYTE* ppBuf,
+ IMG_UINT32* pui32BufLen);
+
+
+/**************************************************************************/ /*!
+@Function RGXHWPerfReleaseData
+@Description Called after client has read the event data out of the buffer
+ retrieved from the Acquire Data call to release resources.
+@Input hDevData Handle to connection/device object
+@Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR RGXHWPerfReleaseData(
+ IMG_HANDLE hDevData);
+
+
+#endif /* SUPPORT_KERNEL_HWPERF */
+
+
+#endif /* __RGXAPI_KM_H__ */
+
+/******************************************************************************
+ End of file (rgxapi_km.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/include/shared/allocmem.h b/drivers/gpu/rogue/services/include/shared/allocmem.h
new file mode 100644
index 000000000000..531d01159cf9
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/shared/allocmem.h
@@ -0,0 +1,79 @@
+/*************************************************************************/ /*!
+@File
+@Title memory allocation header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Memory-Allocation API definitions
+@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 __ALLOCMEM_H__
+#define __ALLOCMEM_H__
+
+#include "img_types.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+IMG_PVOID OSAllocMem(IMG_UINT32 ui32Size);
+
+IMG_PVOID OSAllocMemstatMem(IMG_UINT32 ui32Size);
+IMG_PVOID OSReallocMem(IMG_PVOID pvCpuVAddr, IMG_UINT32 ui32Size);
+
+IMG_PVOID OSAllocZMem(IMG_UINT32 ui32Size);
+
+IMG_VOID OSFreeMem(IMG_PVOID pvCpuVAddr);
+IMG_VOID OSFreeMemstatMem(IMG_PVOID pvCpuVAddr);
+
+#define OSFREEMEM(_ptr) do \
+ { OSFreeMem((_ptr)); \
+ (_ptr) = (IMG_VOID*)0; \
+ MSC_SUPPRESS_4127\
+ } while (0)
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __ALLOCMEM_H__ */
+
+/******************************************************************************
+ End of file (allocmem.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/include/shared/hash.h b/drivers/gpu/rogue/services/include/shared/hash.h
new file mode 100644
index 000000000000..abacd6940feb
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/shared/hash.h
@@ -0,0 +1,229 @@
+/*************************************************************************/ /*!
+@File
+@Title Self scaling hash tables
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements simple self scaling hash tables.
+@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 _HASH_H_
+#define _HASH_H_
+
+/* include5/ */
+#include "img_types.h"
+
+/* services/client/include/ or services/server/include/ */
+#include "osfunc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * Keys passed to the comparsion function are only guaranteed to
+ * be aligned on an IMG_UINTPTR_T boundary.
+ */
+typedef IMG_UINT32 HASH_FUNC(IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+typedef IMG_BOOL HASH_KEY_COMP(IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+typedef struct _HASH_TABLE_ HASH_TABLE;
+
+typedef PVRSRV_ERROR (*HASH_pfnCallback) (
+ IMG_UINTPTR_T k,
+ IMG_UINTPTR_T v
+);
+
+/*************************************************************************/ /*!
+@Function HASH_Func_Default
+@Description Hash function intended for hashing keys composed of
+ IMG_UINTPTR_T arrays.
+@Input uKeySize The size of the hash key, in bytes.
+@Input pKey A pointer to the key to hash.
+@Input uHashTabLen The length of the hash table.
+@Return The hash value.
+*/ /**************************************************************************/
+IMG_UINT32 HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+
+/*************************************************************************/ /*!
+@Function HASH_Key_Comp_Default
+@Description Compares keys composed of IMG_UINTPTR_T arrays.
+@Input uKeySize The size of the hash key, in bytes.
+@Input pKey1 Pointer to first hash key to compare.
+@Input pKey2 Pointer to second hash key to compare.
+@Return IMG_TRUE - the keys match.
+ IMG_FALSE - the keys don't match.
+*/ /**************************************************************************/
+IMG_BOOL HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+/*************************************************************************/ /*!
+@Function HASH_Create_Extended
+@Description Create a self scaling hash table, using the supplied
+ key size, and the supllied hash and key comparsion
+ functions.
+@Input uInitialLen Initial and minimum length of the
+ hash table, where the length refers to the number
+ of entries in the hash table, not its size in
+ bytes.
+@Input uKeySize The size of the key, in bytes.
+@Input pfnHashFunc Pointer to hash function.
+@Input pfnKeyComp Pointer to key comparsion function.
+@Return IMG_NULL or hash table handle.
+*/ /**************************************************************************/
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp);
+
+/*************************************************************************/ /*!
+@Function HASH_Create
+@Description Create a self scaling hash table with a key
+ consisting of a single IMG_UINTPTR_T, and using
+ the default hash and key comparison functions.
+@Input uInitialLen Initial and minimum length of the
+ hash table, where the length refers to the
+ number of entries in the hash table, not its size
+ in bytes.
+@Return IMG_NULL or hash table handle.
+*/ /**************************************************************************/
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen);
+
+/*************************************************************************/ /*!
+@Function HASH_Delete
+@Description Delete a hash table created by HASH_Create_Extended or
+ HASH_Create. All entries in the table must have been
+ removed before calling this function.
+@Input pHash Hash table
+*/ /**************************************************************************/
+IMG_VOID HASH_Delete (HASH_TABLE *pHash);
+
+/*************************************************************************/ /*!
+@Function HASH_Insert_Extended
+@Description Insert a key value pair into a hash table created
+ with HASH_Create_Extended.
+@Input pHash The hash table.
+@Input pKey Pointer to the key.
+@Input v The value associated with the key.
+@Return IMG_TRUE - success
+ IMG_FALSE - failure
+*/ /**************************************************************************/
+IMG_BOOL HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v);
+
+/*************************************************************************/ /*!
+@Function HASH_Insert
+
+@Description Insert a key value pair into a hash table created with
+ HASH_Create.
+@Input pHash The hash table.
+@Input k The key value.
+@Input v The value associated with the key.
+@Return IMG_TRUE - success.
+ IMG_FALSE - failure.
+*/ /**************************************************************************/
+IMG_BOOL HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+
+/*************************************************************************/ /*!
+@Function HASH_Remove_Extended
+@Description Remove a key from a hash table created with
+ HASH_Create_Extended.
+@Input pHash The hash table.
+@Input pKey Pointer to key.
+@Return 0 if the key is missing, or the value associated
+ with the key.
+*/ /**************************************************************************/
+IMG_UINTPTR_T HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey);
+
+/*************************************************************************/ /*!
+@Function HASH_Remove
+@Description Remove a key value pair from a hash table created
+ with HASH_Create.
+@Input pHash The hash table.
+@Input pKey Pointer to key.
+@Return 0 if the key is missing, or the value associated
+ with the key.
+*/ /**************************************************************************/
+IMG_UINTPTR_T HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+/*************************************************************************/ /*!
+@Function HASH_Retrieve_Extended
+@Description Retrieve a value from a hash table created with
+ HASH_Create_Extended.
+@Input pHash The hash table.
+@Input pKey Pointer to key.
+@Return 0 if the key is missing, or the value associated with
+ the key.
+*/ /**************************************************************************/
+IMG_UINTPTR_T HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey);
+
+/*************************************************************************/ /*!
+@Function HASH_Retrieve
+@Description Retrieve a value from a hash table created with
+ HASH_Create.
+@Input pHash The hash table.
+@Input pKey Pointer to key.
+@Return 0 if the key is missing, or the value associated with
+ the key.
+*/ /**************************************************************************/
+IMG_UINTPTR_T HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+/*************************************************************************/ /*!
+@Function HASH_Iterate
+@Description Iterate over every entry in the hash table
+@Input pHash Hash table to iterate
+@Input pfnCallback Callback to call with the key and data for
+ each entry in the hash table
+@Return Callback error if any, otherwise PVRSRV_OK
+*/ /**************************************************************************/
+PVRSRV_ERROR HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback);
+
+#ifdef HASH_TRACE
+/*************************************************************************/ /*!
+@Function HASH_Dump
+@Description Dump out some information about a hash table.
+@Input pHash The hash table.
+*/ /**************************************************************************/
+IMG_VOID HASH_Dump (HASH_TABLE *pHash);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* _HASH_H_ */
+
+/******************************************************************************
+ End of file (hash.h)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/rogue/services/include/shared/lock.h b/drivers/gpu/rogue/services/include/shared/lock.h
new file mode 100644
index 000000000000..d581614b72f6
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/shared/lock.h
@@ -0,0 +1,97 @@
+/*************************************************************************/ /*!
+@File lock.h
+@Title Locking interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Services internal locking interface
+@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 _LOCK_H_
+#define _LOCK_H_
+
+/* In Linux kernel mode we are using the kernel mutex implementation directly
+ * with macros. This allows us to use the kernel lockdep feature for lock
+ * debugging. */
+#include "lock_types.h"
+
+#if defined(LINUX) && defined(__KERNEL__)
+
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#define OSLockCreate(phLock, eLockType) ({ \
+ PVRSRV_ERROR e = PVRSRV_ERROR_OUT_OF_MEMORY; \
+ *(phLock) = kmalloc(sizeof(struct mutex), GFP_KERNEL); \
+ if (*(phLock)) { mutex_init(*(phLock)); e = PVRSRV_OK; }; \
+ e;})
+#define OSLockDestroy(hLock) ({mutex_destroy((hLock)); kfree((hLock)); PVRSRV_OK;})
+
+#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 OSLockIsLocked(hLock) ({IMG_BOOL b = ((mutex_is_locked((hLock)) == 1) ? IMG_TRUE : IMG_FALSE); b;})
+#define OSTryLockAcquire(hLock) ({IMG_BOOL b = ((mutex_trylock(hLock) == 1) ? IMG_TRUE : IMG_FALSE); b;})
+
+
+#else /* defined(LINUX) && defined(__KERNEL__) */
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+IMG_INTERNAL
+PVRSRV_ERROR OSLockCreate(POS_LOCK *phLock, LOCK_TYPE eLockType);
+
+IMG_INTERNAL
+IMG_VOID OSLockDestroy(POS_LOCK hLock);
+
+IMG_INTERNAL
+IMG_VOID OSLockAcquire(POS_LOCK hLock);
+
+/* Nested notation isn't used in UM or other OS's */
+#define OSLockAcquireNested(hLock, subclass) OSLockAcquire((hLock))
+
+IMG_INTERNAL
+IMG_VOID OSLockRelease(POS_LOCK hLock);
+
+IMG_INTERNAL
+IMG_BOOL OSLockIsLocked(POS_LOCK hLock);
+
+#endif /* defined(LINUX) && defined(__KERNEL__) */
+
+#endif /* _LOCK_H_ */
diff --git a/drivers/gpu/rogue/services/include/shared/ra.h b/drivers/gpu/rogue/services/include/shared/ra.h
new file mode 100644
index 000000000000..ed1f84a76b93
--- /dev/null
+++ b/drivers/gpu/rogue/services/include/shared/ra.h
@@ -0,0 +1,207 @@
+/*************************************************************************/ /*!
+@File
+@Title Resource Allocator API
+@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 _RA_H_
+#define _RA_H_
+
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+/** Resource arena.
+ * struct _RA_ARENA_ deliberately opaque
+ */
+typedef struct _RA_ARENA_ RA_ARENA; //PRQA S 3313
+
+/*
+ * Per-Arena handle - this is private data for the caller of the RA.
+ * The RA knows nothing about this data. It is given it upon
+ * RA_Create, and promises to pass it to calls to the ImportAlloc and
+ * ImportFree callbacks
+ */
+typedef IMG_HANDLE RA_PERARENA_HANDLE;
+/*
+ * Per-Import handle - this is private data for the caller of the RA.
+ * The RA knows nothing about this data. It is given it on a
+ * per-import basis, either the "initial" import at RA_Create time, or
+ * further imports via the ImportAlloc callback. It sends it back via
+ * the ImportFree callback, and also provides it in answer to any
+ * RA_Alloc request to signify from which "import" the allocation came
+ */
+typedef IMG_HANDLE RA_PERISPAN_HANDLE;
+
+typedef IMG_UINT64 RA_BASE_T;
+typedef IMG_UINT32 RA_LOG2QUANTUM_T;
+typedef IMG_UINT64 RA_LENGTH_T;
+
+#define RA_BASE_FMTSPEC "0x%010llx"
+#define RA_ALIGN_FMTSPEC "0x%llx"
+#define RA_LENGTH_FMTSPEC "0x%llx"
+
+/* Lock classes: describes the level of nesting between different arenas. */
+#define RA_LOCKCLASS_0 0
+#define RA_LOCKCLASS_1 1
+#define RA_LOCKCLASS_2 2
+
+/*
+ * Flags in an "import" must much the flags for an allocation
+ */
+typedef IMG_UINT32 RA_FLAGS_T;
+
+struct _RA_SEGMENT_DETAILS_
+{
+ RA_LENGTH_T uiSize;
+ IMG_CPU_PHYADDR sCpuPhyAddr;
+ IMG_HANDLE hSegment;
+};
+typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
+
+/**
+ * @Function RA_Create
+ *
+ * @Description
+ *
+ * To create a resource arena.
+ *
+ * @Input name - the name of the arena for diagnostic purposes.
+ * @Input uQuantum - the arena allocation quantum.
+ * @Input ui32LockClass - the lock class level this arena uses.
+ * @Input alloc - a resource allocation callback or 0.
+ * @Input free - a resource de-allocation callback or 0.
+ * @Input per_arena_handle - user private handle passed to alloc and free or 0.
+ * @Return pointer to arena, or IMG_NULL.
+ */
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+ /* subsequent imports: */
+ RA_LOG2QUANTUM_T uLog2Quantum,
+ IMG_UINT32 ui32LockClass,
+ IMG_BOOL (*imp_alloc)(RA_PERARENA_HANDLE _h,
+ RA_LENGTH_T uSize,
+ RA_FLAGS_T uFlags,
+ RA_BASE_T *pBase,
+ RA_LENGTH_T *pActualSize,
+ RA_PERISPAN_HANDLE *phPriv),
+ IMG_VOID (*imp_free) (RA_PERARENA_HANDLE,
+ RA_BASE_T,
+ RA_PERISPAN_HANDLE),
+ RA_PERARENA_HANDLE per_arena_handle);
+
+/**
+ * @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.
+ * @Return None
+ */
+IMG_VOID
+RA_Delete (RA_ARENA *pArena);
+
+/**
+ * @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 hPriv - handle associated to the span (reserved to user uses)
+ * @Return IMG_TRUE - success, IMG_FALSE - failure
+ */
+IMG_BOOL
+RA_Add (RA_ARENA *pArena,
+ RA_BASE_T base,
+ RA_LENGTH_T uSize,
+ RA_FLAGS_T uFlags,
+ RA_PERISPAN_HANDLE hPriv);
+
+/**
+ * @Function RA_Alloc
+ *
+ * @Description
+ *
+ * To allocate resource from an arena.
+ *
+ * @Input pArena - the arena
+ * @Input uRequestSize - the size of resource segment requested.
+ * @Output pActualSize - the actual_size of resource segment allocated,
+ * typcially rounded up by quantum.
+ * @Input uFlags - flags influencing allocation policy.
+ * @Input uAlignment - the alignment constraint required for the
+ * allocated segment, use 0 if alignment not required.
+ * @Output pBase - allocated base resource
+ * @Output phPriv - the user reference associated with allocated
+ * resource span.
+ * @Return IMG_TRUE - success, IMG_FALSE - failure
+ */
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+ RA_LENGTH_T uSize,
+ RA_FLAGS_T uFlags,
+ RA_LENGTH_T uAlignment,
+ RA_BASE_T *pBase,
+ RA_LENGTH_T *pActualSize,
+ RA_PERISPAN_HANDLE *phPriv);
+
+/**
+ * @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.
+ * @Input bFreeBackingStore - Should backing store memory be freed?
+ *
+ * @Return None
+ */
+IMG_VOID
+RA_Free (RA_ARENA *pArena, RA_BASE_T base);
+
+#endif
+
diff --git a/drivers/gpu/rogue/services/server/common/cache_generic.c b/drivers/gpu/rogue/services/server/common/cache_generic.c
new file mode 100644
index 000000000000..25f2dbaf73f4
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/cache_generic.c
@@ -0,0 +1,58 @@
+/*************************************************************************/ /*!
+@File
+@Title CPU generic cache management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements server side code for CPU cache management in a
+ CPU agnostic manner.
+@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 "cache_generic.h"
+#include "cache_internal.h"
+#include "device.h"
+#include "pvr_debug.h"
+#include "pvrsrv.h"
+#include "osfunc.h"
+#include "pmr.h"
+
+PVRSRV_ERROR CacheOpQueue(PVRSRV_CACHE_OP uiCacheOp)
+{
+ PVRSRV_DATA *psData = PVRSRVGetPVRSRVData();
+
+ psData->uiCacheOp = SetCacheOp(psData->uiCacheOp, uiCacheOp);
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/services/server/common/connection_server.c b/drivers/gpu/rogue/services/server/common/connection_server.c
new file mode 100644
index 000000000000..feec69483353
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/connection_server.c
@@ -0,0 +1,239 @@
+/*************************************************************************/ /*!
+@File
+@Title Server side connection management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Handles connections coming from the client and the management
+ connection based information
+@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 "resman.h"
+#include "handle.h"
+#include "pvrsrv.h"
+#include "connection_server.h"
+#include "osconnection_server.h"
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "sync_server.h"
+#include "process_stats.h"
+#include "pdump_km.h"
+
+/*!
+******************************************************************************
+
+ @Function FreeConnectionData
+
+ @Description Free a connection data area
+
+ @Input psConnection - pointer to connection data area
+
+ @Return Error code, or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR FreeConnectionData(CONNECTION_DATA *psConnection)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psConnection != IMG_NULL);
+
+ if (psConnection == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeConnectionData: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Free handle base for this connection */
+ if (psConnection->psHandleBase != IMG_NULL)
+ {
+ eError = PVRSRVFreeHandleBase(psConnection->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeConnectionData: Couldn't free handle base for connection (%d)", eError));
+ return eError;
+ }
+ }
+
+ /* Call environment specific per process deinit function */
+ eError = OSConnectionPrivateDataDeInit(psConnection->hOsPrivateData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeConnectionData: OSConnectionPrivateDataDeInit failed (%d)", eError));
+ return eError;
+ }
+
+ OSFreeMem(psConnection);
+
+ return PVRSRV_OK;
+}
+
+/* PVRSRVConnectionConnect*/
+PVRSRV_ERROR PVRSRVConnectionConnect(IMG_PVOID *ppvPrivData, IMG_PVOID pvOSData)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ CONNECTION_DATA *psConnection;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ /* Allocate per-process data area */
+ psConnection = OSAllocMem(sizeof(*psConnection));
+ if (psConnection == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't allocate per-process data (%d)", eError));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psConnection, 0, sizeof(*psConnection));
+
+ /* Call environment specific per process init function */
+ eError = OSConnectionPrivateDataInit(&psConnection->hOsPrivateData, pvOSData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: OSConnectionPrivateDataInit failed (%d)", eError));
+ goto failure;
+ }
+
+ /* Register this connection with the sync core */
+ eError = SyncRegisterConnection(&psConnection->psSyncConnectionData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't register the sync data"));
+ goto failure;
+ }
+
+ /*
+ Register this connection with the pdump core.
+ Pass in the sync connection data as it will be needed later when we
+ only get passed in the PDump connection data.
+ */
+ eError = PDumpRegisterConnection(psConnection->psSyncConnectionData,
+ &psConnection->psPDumpConnectionData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't register the PDump data"));
+ goto failure;
+ }
+
+ /* Allocate handle base for this process */
+ eError = PVRSRVAllocHandleBase(&psConnection->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't allocate handle base for process (%d)", eError));
+ goto failure;
+ }
+
+ /* Create a resource manager context for the process */
+ eError = PVRSRVResManConnect(psPVRSRVData->hResManDeferContext, &psConnection->hResManContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't register with the resource manager"));
+ goto failure;
+ }
+
+ /* Allocate process statistics */
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ eError = PVRSRVStatsRegisterProcess(&psConnection->hProcessStats);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't register process statistics (%d)", eError));
+ goto failure;
+ }
+#endif
+
+ *ppvPrivData = psConnection;
+
+ return eError;
+
+failure:
+ (IMG_VOID)FreeConnectionData(psConnection);
+ return eError;
+}
+
+/* PVRSRVConnectionDisconnect */
+IMG_VOID PVRSRVConnectionDisconnect(IMG_PVOID pvDataPtr)
+{
+ PVRSRV_ERROR eError;
+ CONNECTION_DATA *psConnection = pvDataPtr;
+
+ /* Close the process statistics */
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ PVRSRVStatsDeregisterProcess(psConnection->hProcessStats);
+ psConnection->hProcessStats = 0;
+#endif
+
+ /* Close the Resource Manager connection */
+ PVRSRVResManDisconnect(psConnection->hResManContext);
+
+ /*
+ Unregister with the sync core. Logically this is after resman to
+ ensure that any sync block that haven't been freed by the app will
+ be freed by resman 1st.
+ However, due to the fact the resman can defer the free the Sync core
+ needs to handle the case where the connection data is destroyed while
+ Sync blocks are still in it.
+ */
+ SyncUnregisterConnection(psConnection->psSyncConnectionData);
+
+ /*
+ Unregister with the PDump core, see the note above about logical order
+ and refcounting as it also applies to the PDump connection data
+ */
+ PDumpUnregisterConnection(psConnection->psPDumpConnectionData);
+
+ /* Free the connection data */
+ eError = FreeConnectionData(psConnection);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionDisconnect: Error freeing per-process data"));
+ }
+
+ eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionDisconnect: Purge of global handle pool failed (%d)", eError));
+ }
+}
+
+/* PVRSRVConnectionInit */
+PVRSRV_ERROR PVRSRVConnectionInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+/* PVRSRVConnectionDeInit */
+PVRSRV_ERROR PVRSRVConnectionDeInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/services/server/common/dc_server.c b/drivers/gpu/rogue/services/server/common/dc_server.c
new file mode 100644
index 000000000000..d86906b20eee
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/dc_server.c
@@ -0,0 +1,2288 @@
+/**************************************************************************/ /*!
+@File
+@Title Server side Display Class functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side functions of the Display Class
+ interface.
+@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 "allocmem.h"
+#include "lock.h"
+#include "osfunc.h"
+#include "img_types.h"
+#include "scp.h"
+#include "dc_server.h"
+#include "kerneldisplay.h"
+#include "pvr_debug.h"
+#include "pmr.h"
+#include "pdump_physmem.h"
+#include "sync_server.h"
+#include "pvrsrv.h"
+#include "debug_request_ids.h"
+
+#if defined(PVR_RI_DEBUG)
+#include "ri_server.h"
+#endif
+
+struct _DC_DISPLAY_CONTEXT_
+{
+ DC_DEVICE *psDevice;
+ SCP_CONTEXT *psSCPContext;
+ IMG_HANDLE hDisplayContext;
+ IMG_UINT32 ui32ConfigsInFlight;
+ IMG_UINT32 ui32RefCount;
+ POS_LOCK hLock;
+ POS_LOCK hConfigureLock; // Guard against concurrent calls to pfnContextConfigure during DisplayContextFlush
+ IMG_UINT32 ui32TokenOut;
+ IMG_UINT32 ui32TokenIn;
+
+ IMG_HANDLE hCmdCompNotify;
+
+ IMG_BOOL bIssuedNullFlip;
+ IMG_HANDLE hMISR;
+ IMG_HANDLE hDebugNotify;
+ IMG_PVOID hTimer;
+
+ IMG_BOOL bPauseMISR;
+ DLLIST_NODE sListNode;
+};
+
+struct _DC_DEVICE_
+{
+ const DC_DEVICE_FUNCTIONS *psFuncTable;
+ IMG_UINT32 ui32MaxConfigsInFlight;
+ IMG_HANDLE hDeviceData;
+ IMG_UINT32 ui32RefCount;
+ POS_LOCK hLock;
+ IMG_UINT32 ui32Index;
+ IMG_HANDLE psEventList;
+ IMG_HANDLE hSystemBuffer;
+ PMR *psSystemBufferPMR;
+ DC_DISPLAY_CONTEXT sSystemContext;
+ DC_DEVICE *psNext;
+};
+
+typedef enum _DC_BUFFER_TYPE_
+{
+ DC_BUFFER_TYPE_UNKNOWN = 0,
+ DC_BUFFER_TYPE_ALLOC,
+ DC_BUFFER_TYPE_IMPORT,
+ DC_BUFFER_TYPE_SYSTEM,
+} DC_BUFFER_TYPE;
+
+typedef struct _DC_BUFFER_ALLOC_DATA_
+{
+ PMR *psPMR;
+} DC_BUFFER_ALLOC_DATA;
+
+typedef struct _DC_BUFFER_IMPORT_DATA_
+{
+/*
+ Required as the DC doesn't need to map the PMR during the import call we
+ need to make sure that the PMR doesn't get freed before the DC maps it
+ by taking an ref on the PMR during the import and drop it on the unimport.
+*/
+ IMG_UINT32 ui32NumPlanes;
+ PMR *apsImport[3];
+} DC_BUFFER_IMPORT_DATA;
+
+struct _DC_BUFFER_
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext;
+ DC_BUFFER_TYPE eType;
+ union {
+ DC_BUFFER_ALLOC_DATA sAllocData;
+ DC_BUFFER_IMPORT_DATA sImportData;
+ } uBufferData;
+ IMG_HANDLE hBuffer;
+ IMG_UINT32 ui32MapCount;
+ IMG_UINT32 ui32RefCount;
+ POS_LOCK hLock;
+ POS_LOCK hMapLock;
+};
+
+typedef struct _DC_CMD_RDY_DATA_
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext;
+ IMG_UINT32 ui32BufferCount;
+ PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib;
+ IMG_HANDLE *pahBuffer;
+ IMG_UINT32 ui32DisplayPeriod;
+} DC_CMD_RDY_DATA;
+
+typedef struct _DC_CMD_COMP_DATA_
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext;
+ IMG_UINT32 ui32BufferCount;
+ DC_BUFFER **apsBuffer;
+ IMG_UINT32 ui32Token;
+ IMG_BOOL bDirectNullFlip;
+} DC_CMD_COMP_DATA;
+
+typedef struct _DC_BUFFER_PMR_DATA_
+{
+ DC_BUFFER *psBuffer; /*!< The buffer this PMR private data refers to */
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize; /*!< Log 2 of the buffers pagesize */
+ IMG_UINT32 ui32PageCount; /*!< Number of pages in this buffer */
+ PHYS_HEAP *psPhysHeap; /*!< The physical heap the memory resides on */
+ IMG_DEV_PHYADDR *pasDevPAddr; /*!< Pointer to an array of device physcial addresses */
+ IMG_PVOID pvLinAddr; /*!< CPU virtual pointer or NULL if the DC driver didn't have one */
+
+ IMG_HANDLE hPDumpAllocInfo; /*!< Handle to PDump alloc data */
+ IMG_BOOL bPDumpMalloced; /*!< Did we get as far as PDump alloc? */
+} DC_BUFFER_PMR_DATA;
+
+POS_LOCK g_hDCListLock;
+
+DC_DEVICE *g_psDCDeviceList;
+IMG_UINT32 g_ui32DCDeviceCount;
+IMG_UINT32 g_ui32DCNextIndex;
+static DLLIST_NODE g_sDisplayContextsList;
+
+
+#if defined(DC_DEBUG) && defined(REFCOUNT_DEBUG)
+#define DC_REFCOUNT_PRINT(fmt, ...) \
+ PVRSRVDebugPrintf(PVR_DBG_WARNING, \
+ __FILE__, \
+ __LINE__, \
+ fmt, \
+ __VA_ARGS__)
+#else
+#define DC_REFCOUNT_PRINT(fmt, ...)
+#endif
+
+#if defined(DC_DEBUG)
+#define DC_DEBUG_PRINT(fmt, ...) \
+ PVRSRVDebugPrintf(PVR_DBG_WARNING, \
+ __FILE__, \
+ __LINE__, \
+ fmt, \
+ __VA_ARGS__)
+#else
+#define DC_DEBUG_PRINT(fmt, ...)
+#endif
+
+/*****************************************************************************
+ * Private functions *
+ *****************************************************************************/
+
+static IMG_VOID _DCDeviceAcquireRef(DC_DEVICE *psDevice)
+{
+ OSLockAcquire(psDevice->hLock);
+ psDevice->ui32RefCount++;
+ DC_REFCOUNT_PRINT("%s: DC device %p, refcount = %d",
+ __FUNCTION__, psDevice, psDevice->ui32RefCount);
+ OSLockRelease(psDevice->hLock);
+}
+
+static IMG_VOID _DCDeviceReleaseRef(DC_DEVICE *psDevice)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psDevice->hLock);
+ ui32RefCount = --psDevice->ui32RefCount;
+ OSLockRelease(psDevice->hLock);
+
+ if (ui32RefCount == 0)
+ {
+ OSLockAcquire(g_hDCListLock);
+ if (psDevice == g_psDCDeviceList)
+ {
+ g_psDCDeviceList = psDevice->psNext;
+ }
+ else
+ {
+ DC_DEVICE *psTmp = g_psDCDeviceList;
+
+ while (psTmp->psNext != psDevice)
+ {
+ psTmp = psTmp->psNext;
+ }
+ psTmp->psNext = g_psDCDeviceList->psNext;
+ }
+
+ g_ui32DCDeviceCount--;
+ OSLockRelease(g_hDCListLock);
+ }
+ else
+ {
+ /* Signal this devices event list as the unload might be blocked on it */
+ OSEventObjectSignal(psDevice->psEventList);
+ }
+ DC_REFCOUNT_PRINT("%s: DC device %p, refcount = %d",
+ __FUNCTION__, psDevice, ui32RefCount);
+}
+
+static IMG_VOID _DCDisplayContextAcquireRef(DC_DISPLAY_CONTEXT *psDisplayContext)
+{
+ OSLockAcquire(psDisplayContext->hLock);
+ psDisplayContext->ui32RefCount++;
+ DC_REFCOUNT_PRINT("%s: DC display context %p, refcount = %d",
+ __FUNCTION__, psDisplayContext, psDisplayContext->ui32RefCount);
+ OSLockRelease(psDisplayContext->hLock);
+}
+
+static IMG_VOID _DCDisplayContextReleaseRef(DC_DISPLAY_CONTEXT *psDisplayContext)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psDisplayContext->hLock);
+ ui32RefCount = --psDisplayContext->ui32RefCount;
+ OSLockRelease(psDisplayContext->hLock);
+
+ if (ui32RefCount == 0)
+ {
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+
+ PVRSRVUnregisterDbgRequestNotify(psDisplayContext->hDebugNotify);
+
+ dllist_remove_node(&psDisplayContext->sListNode);
+
+ /* unregister the device from cmd complete notifications */
+ PVRSRVUnregisterCmdCompleteNotify(psDisplayContext->hCmdCompNotify);
+ psDisplayContext->hCmdCompNotify = IMG_NULL;
+
+ OSUninstallMISR(psDisplayContext->hMISR);
+ SCPDestroy(psDisplayContext->psSCPContext);
+ psDevice->psFuncTable->pfnContextDestroy(psDisplayContext->hDisplayContext);
+ _DCDeviceReleaseRef(psDevice);
+ OSLockDestroy(psDisplayContext->hConfigureLock);
+ OSLockDestroy(psDisplayContext->hLock);
+ OSFreeMem(psDisplayContext);
+ }
+
+ DC_REFCOUNT_PRINT("%s: DC display context %p, refcount = %d",
+ __FUNCTION__, psDisplayContext, ui32RefCount);
+}
+
+static IMG_VOID _DCBufferAcquireRef(DC_BUFFER *psBuffer)
+{
+ OSLockAcquire(psBuffer->hLock);
+ psBuffer->ui32RefCount++;
+ DC_REFCOUNT_PRINT("%s: DC buffer %p, refcount = %d",
+ __FUNCTION__, psBuffer, psBuffer->ui32RefCount);
+ OSLockRelease(psBuffer->hLock);
+}
+
+
+static IMG_VOID _DCFreeAllocedBuffer(DC_BUFFER *psBuffer)
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext = psBuffer->psDisplayContext;
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+
+ psDevice->psFuncTable->pfnBufferFree(psBuffer->hBuffer);
+ _DCDisplayContextReleaseRef(psDisplayContext);
+}
+
+static IMG_VOID _DCFreeImportedBuffer(DC_BUFFER *psBuffer)
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext = psBuffer->psDisplayContext;
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+ IMG_UINT32 i;
+
+ for (i=0;i<psBuffer->uBufferData.sImportData.ui32NumPlanes;i++)
+ {
+ PMRUnrefPMR(psBuffer->uBufferData.sImportData.apsImport[i]);
+ }
+ psDevice->psFuncTable->pfnBufferFree(psBuffer->hBuffer);
+ _DCDisplayContextReleaseRef(psDisplayContext);
+}
+
+static IMG_VOID _DCFreeSystemBuffer(DC_BUFFER *psBuffer)
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext = psBuffer->psDisplayContext;
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+
+ psDevice->psFuncTable->pfnBufferSystemRelease(psBuffer->hBuffer);
+ _DCDeviceReleaseRef(psDevice);
+}
+
+/*
+ Drop a reference on the buffer. Last person gets to free it
+*/
+static IMG_VOID _DCBufferReleaseRef(DC_BUFFER *psBuffer)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psBuffer->hLock);
+ ui32RefCount = --psBuffer->ui32RefCount;
+ OSLockRelease(psBuffer->hLock);
+
+ if (ui32RefCount == 0)
+ {
+ switch (psBuffer->eType)
+ {
+ case DC_BUFFER_TYPE_ALLOC:
+ _DCFreeAllocedBuffer(psBuffer);
+ break;
+ case DC_BUFFER_TYPE_IMPORT:
+ _DCFreeImportedBuffer(psBuffer);
+ break;
+ case DC_BUFFER_TYPE_SYSTEM:
+ _DCFreeSystemBuffer(psBuffer);
+ break;
+ default:
+ PVR_ASSERT(IMG_FALSE);
+ }
+ OSLockDestroy(psBuffer->hMapLock);
+ OSLockDestroy(psBuffer->hLock);
+ OSFreeMem(psBuffer);
+ }
+ DC_REFCOUNT_PRINT("%s: DC buffer %p, refcount = %d",
+ __FUNCTION__, psBuffer, ui32RefCount);
+}
+
+static PVRSRV_ERROR _DCBufferMap(DC_BUFFER *psBuffer)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ OSLockAcquire(psBuffer->hMapLock);
+ if (psBuffer->ui32MapCount++ == 0)
+ {
+ DC_DEVICE *psDevice = psBuffer->psDisplayContext->psDevice;
+
+ if(psDevice->psFuncTable->pfnBufferMap)
+ {
+ eError = psDevice->psFuncTable->pfnBufferMap(psBuffer->hBuffer);
+ if (eError != PVRSRV_OK)
+ {
+ goto out_unlock;
+ }
+ }
+
+ _DCBufferAcquireRef(psBuffer);
+ }
+
+ DC_REFCOUNT_PRINT("%s: DC buffer %p, MapCount = %d",
+ __FUNCTION__, psBuffer, psBuffer->ui32MapCount);
+
+out_unlock:
+ OSLockRelease(psBuffer->hMapLock);
+ return eError;
+}
+
+static IMG_VOID _DCBufferUnmap(DC_BUFFER *psBuffer)
+{
+ DC_DEVICE *psDevice = psBuffer->psDisplayContext->psDevice;
+ IMG_UINT32 ui32MapCount;
+
+ OSLockAcquire(psBuffer->hMapLock);
+ ui32MapCount = --psBuffer->ui32MapCount;
+ OSLockRelease(psBuffer->hMapLock);
+
+ if (ui32MapCount == 0)
+ {
+ if(psDevice->psFuncTable->pfnBufferUnmap)
+ {
+ psDevice->psFuncTable->pfnBufferUnmap(psBuffer->hBuffer);
+ }
+
+ _DCBufferReleaseRef(psBuffer);
+ }
+ DC_REFCOUNT_PRINT("%s: DC Buffer %p, MapCount = %d",
+ __FUNCTION__, psBuffer, ui32MapCount);
+}
+
+static PVRSRV_ERROR _DCDeviceBufferArrayCreate(IMG_UINT32 ui32BufferCount,
+ DC_BUFFER **papsBuffers,
+ IMG_HANDLE **pahDeviceBuffers)
+{
+ IMG_HANDLE *ahDeviceBuffers;
+ IMG_UINT32 i;
+
+ /* Create an array of the DC's private Buffer handles */
+ ahDeviceBuffers = OSAllocMem(sizeof(IMG_HANDLE) * ui32BufferCount);
+ if (ahDeviceBuffers == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(ahDeviceBuffers, 0, sizeof(IMG_HANDLE) * ui32BufferCount);
+
+ for (i=0;i<ui32BufferCount;i++)
+ {
+ ahDeviceBuffers[i] = papsBuffers[i]->hBuffer;
+ }
+
+ *pahDeviceBuffers = ahDeviceBuffers;
+
+ return PVRSRV_OK;
+}
+
+static IMG_VOID _DCDeviceBufferArrayDestroy(IMG_HANDLE ahDeviceBuffers)
+{
+ OSFreeMem(ahDeviceBuffers);
+}
+
+static IMG_BOOL _DCDisplayContextReady(IMG_PVOID hReadyData)
+{
+ DC_CMD_RDY_DATA *psReadyData = (DC_CMD_RDY_DATA *) hReadyData;
+ DC_DISPLAY_CONTEXT *psDisplayContext = psReadyData->psDisplayContext;
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+
+ if (psDisplayContext->ui32ConfigsInFlight >= psDevice->ui32MaxConfigsInFlight)
+ {
+ /*
+ We're at the DC's max commands in-flight so don't take this command
+ off the queue
+ */
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+#if defined SUPPORT_DC_COMPLETE_TIMEOUT_DEBUG
+static IMG_VOID _RetireTimeout(IMG_PVOID pvData)
+{
+ DC_CMD_COMP_DATA *psCompleteData = pvData;
+ DC_DISPLAY_CONTEXT *psDisplayContext = psCompleteData->psDisplayContext;
+
+ PVR_DPF((PVR_DBG_ERROR, "Timeout fired for operation %d", psCompleteData->ui32Token));
+ SCPDumpStatus(psDisplayContext->psSCPContext);
+
+ OSDisableTimer(psDisplayContext->hTimer);
+ OSRemoveTimer(psDisplayContext->hTimer);
+ psDisplayContext->hTimer = IMG_NULL;
+}
+#endif /* SUPPORT_DC_COMPLETE_TIMEOUT_DEBUG */
+
+static IMG_VOID _DCDisplayContextConfigure(IMG_PVOID hReadyData,
+ IMG_PVOID hCompleteData)
+{
+ DC_CMD_RDY_DATA *psReadyData = (DC_CMD_RDY_DATA *) hReadyData;
+ DC_DISPLAY_CONTEXT *psDisplayContext = psReadyData->psDisplayContext;
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+
+ OSLockAcquire(psDisplayContext->hLock);
+ psDisplayContext->ui32ConfigsInFlight++;
+
+#if defined SUPPORT_DC_COMPLETE_TIMEOUT_DEBUG
+ if (psDisplayContext->ui32ConfigsInFlight == psDevice->ui32MaxConfigsInFlight)
+ {
+ /*
+ We've just sent out a new config which has filled the DC's pipeline.
+ This means that we expect a retire within a VSync period, start
+ a timer that will print out a message if we haven't got a complete
+ within a reasonable period (200ms)
+ */
+ PVR_ASSERT(psDisplayContext->hTimer == IMG_NULL);
+ psDisplayContext->hTimer = OSAddTimer(_RetireTimeout, hCompleteData, 200);
+ OSEnableTimer(psDisplayContext->hTimer);
+ }
+#endif
+
+ OSLockRelease(psDisplayContext->hLock);
+
+#if defined(DC_DEBUG)
+ {
+ DC_DEBUG_PRINT("_DCDisplayContextConfigure: Send command (%d) out",
+ ((DC_CMD_COMP_DATA*) hCompleteData)->ui32Token);
+ }
+#endif /* DC_DEBUG */
+
+ /*
+ * Note: A risk exists that _DCDisplayContextConfigure may be called simultaneously
+ * from both SCPRun (MISR context) and DCDisplayContextFlush.
+ * This lock ensures no concurrent calls are made to pfnContextConfigure.
+ */
+ OSLockAcquire(psDisplayContext->hConfigureLock);
+ /*
+ Note: We've already done all the acquire refs at
+ DCDisplayContextConfigure time.
+ */
+ psDevice->psFuncTable->pfnContextConfigure(psDisplayContext->hDisplayContext,
+ psReadyData->ui32BufferCount,
+ psReadyData->pasSurfAttrib,
+ psReadyData->pahBuffer,
+ psReadyData->ui32DisplayPeriod,
+ hCompleteData);
+ OSLockRelease(psDisplayContext->hConfigureLock);
+
+}
+
+/*
+ _DCDisplayContextRun
+
+ Kick the MISR which will check for any commands which can be processed
+*/
+static INLINE IMG_VOID _DCDisplayContextRun(DC_DISPLAY_CONTEXT *psDisplayContext)
+{
+ OSScheduleMISR(psDisplayContext->hMISR);
+}
+
+/*
+ _DCDisplayContextMISR
+
+ This gets called when this MISR is fired
+*/
+static IMG_VOID _DCDisplayContextMISR(IMG_VOID *pvData)
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext = pvData;
+
+ if ( !psDisplayContext->bPauseMISR )
+ {
+ SCPRun(psDisplayContext->psSCPContext);
+ }
+}
+
+/*
+ * PMR related functions and structures
+ */
+
+/*
+ Callback function for locking the system physical page addresses.
+ As we acquire the display memory at PMR create time there is nothing
+ to do here.
+*/
+static PVRSRV_ERROR _DCPMRLockPhysAddresses(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_UINT32 uiLog2DevPageSize)
+{
+ DC_BUFFER_PMR_DATA *psPMRPriv = pvPriv;
+ DC_BUFFER *psBuffer = psPMRPriv->psBuffer;
+ DC_DEVICE *psDevice = psBuffer->psDisplayContext->psDevice;
+ PVRSRV_ERROR eError;
+
+ if (uiLog2DevPageSize < psPMRPriv->uiLog2PageSize)
+ {
+ eError = PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
+ goto fail_contigcheck;
+ }
+
+ psPMRPriv->pasDevPAddr = OSAllocMem(sizeof(IMG_DEV_PHYADDR) *
+ psPMRPriv->ui32PageCount);
+ if (psPMRPriv->pasDevPAddr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ OSMemSet(psPMRPriv->pasDevPAddr,
+ 0,
+ sizeof(IMG_DEV_PHYADDR) * psPMRPriv->ui32PageCount);
+
+ eError = psDevice->psFuncTable->pfnBufferAcquire(psBuffer->hBuffer,
+ psPMRPriv->pasDevPAddr,
+ &psPMRPriv->pvLinAddr);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_query;
+ }
+
+ return PVRSRV_OK;
+
+fail_query:
+ OSFreeMem(psPMRPriv->pasDevPAddr);
+fail_alloc:
+fail_contigcheck:
+ return eError;
+}
+
+static PVRSRV_ERROR _DCPMRUnlockPhysAddresses(PMR_IMPL_PRIVDATA pvPriv)
+{
+ DC_BUFFER_PMR_DATA *psPMRPriv = pvPriv;
+ DC_BUFFER *psBuffer = psPMRPriv->psBuffer;
+ DC_DEVICE *psDevice = psBuffer->psDisplayContext->psDevice;
+
+ psDevice->psFuncTable->pfnBufferRelease(psBuffer->hBuffer);
+ OSFreeMem(psPMRPriv->pasDevPAddr);
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _DCPMRDevPhysAddr(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEV_PHYADDR *psDevAddrPtr)
+{
+ DC_BUFFER_PMR_DATA *psPMRPriv = pvPriv;
+ IMG_UINT32 uiNumPages;
+ IMG_UINT32 uiLog2PageSize;
+ IMG_UINT32 uiPageSize;
+ IMG_UINT32 uiPageIndex;
+ IMG_UINT32 uiInPageOffset;
+ IMG_DEV_PHYADDR sDevAddr;
+
+ uiLog2PageSize = psPMRPriv->uiLog2PageSize;
+ uiNumPages = psPMRPriv->ui32PageCount;
+
+ uiPageSize = 1ULL << uiLog2PageSize;
+
+ uiPageIndex = (IMG_UINT32)(uiOffset >> uiLog2PageSize);
+ /* verify the cast */
+ /* N.B. Strictly... this could be triggered by an illegal
+ uiOffset arg too. */
+ PVR_ASSERT((IMG_DEVMEM_OFFSET_T)uiPageIndex << uiLog2PageSize == uiOffset);
+
+ uiInPageOffset = (IMG_UINT32)(uiOffset - ((IMG_DEVMEM_OFFSET_T)uiPageIndex << uiLog2PageSize));
+ PVR_ASSERT(uiOffset == ((IMG_DEVMEM_OFFSET_T)uiPageIndex << uiLog2PageSize) + uiInPageOffset);
+
+ PVR_ASSERT(uiPageIndex < uiNumPages);
+ PVR_ASSERT(uiInPageOffset < uiPageSize);
+
+ sDevAddr.uiAddr = psPMRPriv->pasDevPAddr[uiPageIndex].uiAddr;
+ PVR_ASSERT((sDevAddr.uiAddr & (uiPageSize - 1)) == 0);
+
+ *psDevAddrPtr = sDevAddr;
+ psDevAddrPtr->uiAddr += uiInPageOffset;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _DCPMRFinalize(PMR_IMPL_PRIVDATA pvPriv)
+{
+ DC_BUFFER_PMR_DATA *psPMRPriv = pvPriv;
+
+ /* Conditionally do the PDump free, because if CreatePMR failed we
+ won't have done the PDump MALLOC. */
+ if (psPMRPriv->bPDumpMalloced)
+ {
+ PDumpPMRFree(psPMRPriv->hPDumpAllocInfo);
+ }
+
+ PhysHeapRelease(psPMRPriv->psPhysHeap);
+ _DCBufferReleaseRef(psPMRPriv->psBuffer);
+ OSFreeMem(psPMRPriv);
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _DCPMRReadBytes(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes)
+{
+ DC_BUFFER_PMR_DATA *psPMRPriv = pvPriv;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_SIZE_T uiBytesCopied = 0;
+ IMG_SIZE_T uiBytesToCopy = uiBufSz;
+ IMG_SIZE_T uiBytesCopyableFromPage;
+ IMG_VOID *pvMapping;
+ IMG_UINT8 *pcKernelPointer;
+ IMG_SIZE_T uiBufferOffset = 0;
+ IMG_SIZE_T uiPageIndex;
+ IMG_SIZE_T uiInPageOffset;
+
+ /* If we already have a CPU mapping just us it */
+ if (psPMRPriv->pvLinAddr)
+ {
+ pcKernelPointer = psPMRPriv->pvLinAddr;
+ OSMemCopy(pcBuffer, &pcKernelPointer[uiOffset], uiBufSz);
+ *puiNumBytes = uiBufSz;
+ return PVRSRV_OK;
+ }
+
+ /* Copy the data page by page */
+ while (uiBytesToCopy > 0)
+ {
+ /* we have to kmap one page in at a time */
+ uiPageIndex = TRUNCATE_64BITS_TO_SIZE_T(uiOffset >> psPMRPriv->uiLog2PageSize);
+
+ uiInPageOffset = TRUNCATE_64BITS_TO_SIZE_T(uiOffset - ((IMG_DEVMEM_OFFSET_T)uiPageIndex << psPMRPriv->uiLog2PageSize));
+ uiBytesCopyableFromPage = uiBytesToCopy;
+ if (uiBytesCopyableFromPage + uiInPageOffset > (1U<<psPMRPriv->uiLog2PageSize))
+ {
+ uiBytesCopyableFromPage = (1 << psPMRPriv->uiLog2PageSize)-uiInPageOffset;
+ }
+
+ PhysHeapDevPAddrToCpuPAddr(psPMRPriv->psPhysHeap, &sCpuPAddr, &psPMRPriv->pasDevPAddr[uiPageIndex]);
+
+ pvMapping = OSMapPhysToLin(sCpuPAddr,
+ 1 << psPMRPriv->uiLog2PageSize,
+ 0);
+ PVR_ASSERT(pvMapping != IMG_NULL);
+ pcKernelPointer = pvMapping;
+ OSMemCopy(&pcBuffer[uiBufferOffset], &pcKernelPointer[uiInPageOffset], uiBytesCopyableFromPage);
+ OSUnMapPhysToLin(pvMapping, 1 << psPMRPriv->uiLog2PageSize, 0);
+
+ uiBufferOffset += uiBytesCopyableFromPage;
+ uiBytesToCopy -= uiBytesCopyableFromPage;
+ uiOffset += uiBytesCopyableFromPage;
+ uiBytesCopied += uiBytesCopyableFromPage;
+ }
+
+ *puiNumBytes = uiBytesCopied;
+ return PVRSRV_OK;
+}
+
+static PMR_IMPL_FUNCTAB sDCPMRFuncTab = {
+ _DCPMRLockPhysAddresses, /* .pfnLockPhysAddresses */
+ _DCPMRUnlockPhysAddresses, /* .pfnUnlockPhysAddresses */
+ _DCPMRDevPhysAddr, /* .pfnDevPhysAddr */
+ IMG_NULL, /* .pfnPDumpSymbolicAddr */
+ IMG_NULL, /* .pfnAcquireKernelMappingData */
+ IMG_NULL, /* .pfnReleaseKernelMappingData */
+ _DCPMRReadBytes, /* .pfnReadBytes */
+ IMG_NULL, /* .pfnWriteBytes */
+ _DCPMRFinalize /* .pfnFinalize */
+};
+
+static PVRSRV_ERROR _DCCreatePMR(IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize,
+ IMG_UINT32 ui32PageCount,
+ IMG_UINT32 ui32PhysHeapID,
+ DC_BUFFER *psBuffer,
+ PMR **ppsPMR)
+{
+ DC_BUFFER_PMR_DATA *psPMRPriv;
+ PHYS_HEAP *psPhysHeap;
+ IMG_DEVMEM_SIZE_T uiBufferSize;
+ IMG_HANDLE hPDumpAllocInfo;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bMappingTable = IMG_TRUE;
+
+ /*
+ Create the PMR for this buffer.
+
+ Note: At this stage we don't need to know the physical pages just
+ the page size and the size of the PMR. The 1st call that needs the
+ physcial pages will cause a request into the DC driver (pfnBufferQuery)
+ */
+ psPMRPriv = OSAllocMem(sizeof(DC_BUFFER_PMR_DATA));
+ if (psPMRPriv == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_privalloc;
+ }
+
+ OSMemSet(psPMRPriv, 0, sizeof(DC_BUFFER_PMR_DATA));
+
+ /* Acquire the physical heap the memory is on */
+ eError = PhysHeapAcquire(ui32PhysHeapID, &psPhysHeap);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_physheap;
+ }
+
+ /* Take a reference on the buffer (for the copy in the PMR) */
+ _DCBufferAcquireRef(psBuffer);
+
+ /* Fill in the private data for the PMR */
+ psPMRPriv->uiLog2PageSize = uiLog2PageSize;
+ psPMRPriv->ui32PageCount = ui32PageCount;
+ psPMRPriv->psPhysHeap = psPhysHeap;
+ psPMRPriv->pasDevPAddr = IMG_NULL;
+ psPMRPriv->psBuffer = psBuffer;
+
+ uiBufferSize = (1 << uiLog2PageSize) * ui32PageCount;
+
+ /* Create the PMR for the MM layer */
+ eError = PMRCreatePMR(psPhysHeap,
+ uiBufferSize,
+ uiBufferSize,
+ 1,
+ 1,
+ &bMappingTable,
+ uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAG_WRITE_COMBINE,
+ "DISPLAY",
+ &sDCPMRFuncTab,
+ psPMRPriv,
+ ppsPMR,
+ &hPDumpAllocInfo,
+ IMG_TRUE);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_pmrcreate;
+ }
+
+#if defined(PDUMP)
+ psPMRPriv->hPDumpAllocInfo = hPDumpAllocInfo;
+ psPMRPriv->bPDumpMalloced = IMG_TRUE;
+#endif
+ return PVRSRV_OK;
+
+fail_pmrcreate:
+ PhysHeapRelease(psPhysHeap);
+fail_physheap:
+ OSFreeMem(psPMRPriv);
+fail_privalloc:
+ return eError;
+}
+
+static IMG_VOID _DCDisplayContextNotify(PVRSRV_CMDCOMP_HANDLE hCmdCompHandle)
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext = (DC_DISPLAY_CONTEXT*) hCmdCompHandle;
+
+ _DCDisplayContextRun(psDisplayContext);
+}
+
+static IMG_VOID _DCDebugRequest(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel)
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext = (DC_DISPLAY_CONTEXT*) hDebugRequestHandle;
+
+ switch(ui32VerbLevel)
+ {
+ case DEBUG_REQUEST_VERBOSITY_LOW:
+ PVR_LOG(("Configs in-flight = %d", psDisplayContext->ui32ConfigsInFlight));
+ break;
+
+ case DEBUG_REQUEST_VERBOSITY_MEDIUM:
+ PVR_LOG(("Display context SCP status"));
+ SCPDumpStatus(psDisplayContext->psSCPContext);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*****************************************************************************
+ * Public interface functions exposed through the bridge to services client *
+ *****************************************************************************/
+
+PVRSRV_ERROR DCDevicesQueryCount(IMG_UINT32 *pui32DeviceCount)
+{
+ *pui32DeviceCount = g_ui32DCDeviceCount;
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCDevicesEnumerate(IMG_UINT32 ui32DeviceArraySize,
+ IMG_UINT32 *pui32DeviceCount,
+ IMG_UINT32 *paui32DeviceIndex)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 ui32LoopCount;
+ DC_DEVICE *psTmp = g_psDCDeviceList;
+
+ OSLockAcquire(g_hDCListLock);
+
+ if (g_ui32DCDeviceCount > ui32DeviceArraySize)
+ {
+ ui32LoopCount = ui32DeviceArraySize;
+ }
+ else
+ {
+ ui32LoopCount = g_ui32DCDeviceCount;
+ }
+
+ for (i=0;i<ui32LoopCount;i++)
+ {
+ PVR_ASSERT(psTmp != IMG_NULL);
+ paui32DeviceIndex[i] = psTmp->ui32Index;
+ psTmp = psTmp->psNext;
+ }
+
+ *pui32DeviceCount = ui32LoopCount;
+ OSLockRelease(g_hDCListLock);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCDeviceAcquire(IMG_UINT32 ui32DeviceIndex,
+ DC_DEVICE **ppsDevice)
+{
+ DC_DEVICE *psDevice = g_psDCDeviceList;
+
+ if (psDevice == IMG_NULL)
+ {
+ return PVRSRV_ERROR_NO_DC_DEVICES_FOUND;
+ }
+
+ while(psDevice->ui32Index != ui32DeviceIndex)
+ {
+ psDevice = psDevice->psNext;
+ if (psDevice == IMG_NULL)
+ {
+ return PVRSRV_ERROR_NO_DC_DEVICES_FOUND;
+ }
+ }
+
+ _DCDeviceAcquireRef(psDevice);
+ *ppsDevice = psDevice;
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCDeviceRelease(DC_DEVICE *psDevice)
+{
+ _DCDeviceReleaseRef(psDevice);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCGetInfo(DC_DEVICE *psDevice,
+ DC_DISPLAY_INFO *psDisplayInfo)
+{
+ psDevice->psFuncTable->pfnGetInfo(psDevice->hDeviceData,
+ psDisplayInfo);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCPanelQueryCount(DC_DEVICE *psDevice,
+ IMG_UINT32 *pui32NumPanels)
+{
+ psDevice->psFuncTable->pfnPanelQueryCount(psDevice->hDeviceData,
+ pui32NumPanels);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCPanelQuery(DC_DEVICE *psDevice,
+ IMG_UINT32 ui32PanelsArraySize,
+ IMG_UINT32 *pui32NumPanels,
+ PVRSRV_PANEL_INFO *pasPanelInfo)
+{
+ psDevice->psFuncTable->pfnPanelQuery(psDevice->hDeviceData,
+ ui32PanelsArraySize,
+ pui32NumPanels,
+ pasPanelInfo);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCFormatQuery(DC_DEVICE *psDevice,
+ IMG_UINT32 ui32FormatArraySize,
+ PVRSRV_SURFACE_FORMAT *pasFormat,
+ IMG_UINT32 *pui32Supported)
+{
+ psDevice->psFuncTable->pfnFormatQuery(psDevice->hDeviceData,
+ ui32FormatArraySize,
+ pasFormat,
+ pui32Supported);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCDimQuery(DC_DEVICE *psDevice,
+ IMG_UINT32 ui32DimSize,
+ PVRSRV_SURFACE_DIMS *pasDim,
+ IMG_UINT32 *pui32Supported)
+{
+ psDevice->psFuncTable->pfnDimQuery(psDevice->hDeviceData,
+ ui32DimSize,
+ pasDim,
+ pui32Supported);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR DCSetBlank(DC_DEVICE *psDevice,
+ IMG_BOOL bEnabled)
+{
+ PVRSRV_ERROR eError = PVRSRV_ERROR_NOT_IMPLEMENTED;
+ if (psDevice->psFuncTable->pfnSetBlank)
+ {
+ eError = psDevice->psFuncTable->pfnSetBlank(psDevice->hDeviceData,
+ bEnabled);
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR DCSetVSyncReporting(DC_DEVICE *psDevice,
+ IMG_BOOL bEnabled)
+{
+ PVRSRV_ERROR eError = PVRSRV_ERROR_NOT_IMPLEMENTED;
+ if (psDevice->psFuncTable->pfnSetVSyncReporting)
+ {
+ eError = psDevice->psFuncTable->pfnSetVSyncReporting(psDevice->hDeviceData,
+ bEnabled);
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR DCLastVSyncQuery(DC_DEVICE *psDevice,
+ IMG_INT64 *pi64Timestamp)
+{
+ PVRSRV_ERROR eError = PVRSRV_ERROR_NOT_IMPLEMENTED;
+ if (psDevice->psFuncTable->pfnLastVSyncQuery)
+ {
+ eError = psDevice->psFuncTable->pfnLastVSyncQuery(psDevice->hDeviceData,
+ pi64Timestamp);
+ }
+
+ return eError;
+}
+
+/*
+ The system buffer breaks the rule of only calling DC callbacks on first
+ ref and last deref. For the pfnBufferSystemAcquire this is expected
+ as each call could get back a different buffer, but calls to
+ pfnBufferAcquire and pfnBufferRelease could happen multiple times
+ for the same buffer
+*/
+PVRSRV_ERROR DCSystemBufferAcquire(DC_DEVICE *psDevice,
+ IMG_UINT32 *pui32ByteStride,
+ DC_BUFFER **ppsBuffer)
+{
+ DC_BUFFER *psNew;
+ PMR *psPMR;
+ PVRSRV_ERROR eError;
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize;
+ IMG_UINT32 ui32PageCount;
+ IMG_UINT32 ui32PhysHeapID;
+
+ if (psDevice->psFuncTable->pfnBufferSystemAcquire == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_NO_SYSTEM_BUFFER;
+ goto fail_nopfn;
+ }
+
+ psNew = OSAllocMem(sizeof(DC_BUFFER));
+ if (psNew == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ OSMemSet(psNew, 0, sizeof(DC_BUFFER));
+
+ eError = OSLockCreate(&psNew->hLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_lock;
+ }
+
+ eError = OSLockCreate(&psNew->hMapLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_maplock;
+ }
+
+ eError = psDevice->psFuncTable->pfnBufferSystemAcquire(psDevice->hDeviceData,
+ &uiLog2PageSize,
+ &ui32PageCount,
+ &ui32PhysHeapID,
+ pui32ByteStride,
+ &psNew->hBuffer);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_bufferacquire;
+ }
+
+ psNew->psDisplayContext = &psDevice->sSystemContext;
+ psNew->eType = DC_BUFFER_TYPE_SYSTEM;
+ psNew->ui32MapCount = 0;
+ psNew->ui32RefCount = 1;
+
+ /*
+ Creating the PMR for the system buffer is a bit tricky as there is no
+ "create" call for it.
+ We should only ever have one PMR for the same buffer and so we can't
+ just create one every call to this function. We also have to deal with
+ the system buffer changing (mode change) so we can't just create the PMR
+ once at DC driver register time.
+ So what we do is cache the DC's handle to the system buffer and check if
+ this call the handle has changed (indicating a mode change) and create
+ a new PMR in this case.
+ */
+ if (psNew->hBuffer != psDevice->hSystemBuffer)
+ {
+ if (psDevice->psSystemBufferPMR)
+ {
+ /*
+ Mode change:
+ We've already got a system buffer but the DC has given us a new
+ one so we need to drop the 2nd reference we took on it as a
+ different system buffer will be freed as DC unregister time
+ */
+ PMRUnrefPMR(psDevice->psSystemBufferPMR);
+ }
+
+ eError = _DCCreatePMR(uiLog2PageSize,
+ ui32PageCount,
+ ui32PhysHeapID,
+ psNew,
+ &psPMR);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_createpmr;
+ }
+
+#if defined(PVR_RI_DEBUG)
+ {
+ /* Dummy handle - we don't need to store the reference to the PMR RI entry. Its deletion is handled internally. */
+ DC_DISPLAY_INFO sDisplayInfo;
+ IMG_INT32 i32RITextSize;
+ IMG_CHAR pszRIText[RI_MAX_TEXT_LEN];
+
+ DCGetInfo(psDevice, &sDisplayInfo);
+ i32RITextSize = OSSNPrintf((IMG_CHAR *)pszRIText, RI_MAX_TEXT_LEN, "%s: DisplayContext 0x%p SystemBuffer", (IMG_CHAR *)sDisplayInfo.szDisplayName, &psDevice->sSystemContext);
+ if (i32RITextSize < 0) {
+ pszRIText[0] = '\0';
+ i32RITextSize = 0;
+ }
+ else
+ {
+ pszRIText[RI_MAX_TEXT_LEN-1] = '\0';
+ }
+ eError = RIWritePMREntryKM (psPMR,
+ (IMG_UINT32)i32RITextSize,
+ (IMG_CHAR *)pszRIText,
+ (uiLog2PageSize*ui32PageCount));
+ }
+#endif
+
+ psNew->uBufferData.sAllocData.psPMR = psPMR;
+ psDevice->hSystemBuffer = psNew->hBuffer;
+ psDevice->psSystemBufferPMR = psPMR;
+
+ /*
+ Take a 2nd reference on the PMR as we always drop a reference
+ in the release call but we don't want the PMR to be freed until
+ either a new system buffer as been acquired or the DC device gets
+ unregistered
+ */
+ PMRRefPMR(psDevice->psSystemBufferPMR);
+ }
+ else
+ {
+ /*
+ A PMR for the system buffer as already been created so just
+ take a reference to the PMR to make sure it doesn't go away
+ */
+ PMRRefPMR(psDevice->psSystemBufferPMR);
+ psNew->uBufferData.sAllocData.psPMR = psDevice->psSystemBufferPMR;
+ }
+
+ /*
+ The system buffer is tied to the device unlike all other buffers
+ which are tied to a display context.
+ */
+ _DCDeviceAcquireRef(psDevice);
+
+ *ppsBuffer = psNew;
+
+ return PVRSRV_OK;
+
+fail_createpmr:
+fail_bufferacquire:
+ OSLockDestroy(psNew->hMapLock);
+fail_maplock:
+ OSLockDestroy(psNew->hLock);
+fail_lock:
+ OSFreeMem(psNew);
+fail_alloc:
+fail_nopfn:
+ return eError;
+}
+
+PVRSRV_ERROR DCSystemBufferRelease(DC_BUFFER *psBuffer)
+{
+ PMRUnrefPMR(psBuffer->uBufferData.sAllocData.psPMR);
+ _DCBufferReleaseRef(psBuffer);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCDisplayContextCreate(DC_DEVICE *psDevice,
+ DC_DISPLAY_CONTEXT **ppsDisplayContext)
+{
+ DC_DISPLAY_CONTEXT *psDisplayContext;
+ PVRSRV_ERROR eError;
+
+ psDisplayContext = OSAllocMem(sizeof(DC_DISPLAY_CONTEXT));
+ if (psDisplayContext == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ psDisplayContext->psDevice = psDevice;
+ psDisplayContext->hDisplayContext = IMG_NULL;
+ psDisplayContext->ui32TokenOut = 0;
+ psDisplayContext->ui32TokenIn = 0;
+ psDisplayContext->ui32RefCount = 1;
+ psDisplayContext->ui32ConfigsInFlight = 0;
+ psDisplayContext->bIssuedNullFlip = IMG_FALSE;
+ psDisplayContext->hTimer = IMG_NULL;
+ psDisplayContext->bPauseMISR = IMG_FALSE;
+
+ eError = OSLockCreate(&psDisplayContext->hLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailLock;
+ }
+ eError = OSLockCreate(&psDisplayContext->hConfigureLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailLock2;
+ }
+
+ /* Create a Software Command Processor with 4K CCB size.
+ * With the HWC it might be possible to reach the limit off the buffer.
+ * This could be bad when the buffers currently on the screen can't be
+ * flipped to the new one, cause the command for them doesn't fit into the
+ * queue (Deadlock). This situation should properly detected to make at
+ * least the debugging easier. */
+ eError = SCPCreate(12, &psDisplayContext->psSCPContext);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailSCP;
+ }
+
+ eError = psDevice->psFuncTable->pfnContextCreate(psDevice->hDeviceData,
+ &psDisplayContext->hDisplayContext);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto FailDCDeviceContext;
+ }
+
+ _DCDeviceAcquireRef(psDevice);
+
+ /* Create an MISR for our display context */
+ eError = OSInstallMISR(&psDisplayContext->hMISR,
+ _DCDisplayContextMISR,
+ psDisplayContext);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailMISR;
+ }
+ /*
+ Register for the command complete callback.
+
+ Note:
+ After calling this function our MISR can be called at any point.
+ */
+ eError = PVRSRVRegisterCmdCompleteNotify(&psDisplayContext->hCmdCompNotify, _DCDisplayContextNotify, psDisplayContext);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailRegisterCmdComplete;
+ }
+
+ /* Register our debug request notify callback */
+ eError = PVRSRVRegisterDbgRequestNotify(&psDisplayContext->hDebugNotify,
+ _DCDebugRequest,
+ DEBUG_REQUEST_DC,
+ psDisplayContext);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailRegisterDbgRequest;
+ }
+
+ *ppsDisplayContext = psDisplayContext;
+
+ /* store pointer to first/only display context, required for DCDisplayContextFlush */
+ dllist_add_to_tail(&g_sDisplayContextsList, &psDisplayContext->sListNode);
+
+ return PVRSRV_OK;
+
+FailRegisterDbgRequest:
+ PVRSRVUnregisterCmdCompleteNotify(psDisplayContext->hCmdCompNotify);
+FailRegisterCmdComplete:
+ OSUninstallMISR(psDisplayContext->hMISR);
+FailMISR:
+ _DCDeviceReleaseRef(psDevice);
+ psDevice->psFuncTable->pfnContextDestroy(psDisplayContext->hDisplayContext);
+FailDCDeviceContext:
+ SCPDestroy(psDisplayContext->psSCPContext);
+FailSCP:
+ OSLockDestroy(psDisplayContext->hConfigureLock);
+FailLock2:
+ OSLockDestroy(psDisplayContext->hLock);
+FailLock:
+ OSFreeMem(psDisplayContext);
+ return eError;
+}
+
+PVRSRV_ERROR DCDisplayContextConfigureCheck(DC_DISPLAY_CONTEXT *psDisplayContext,
+ IMG_UINT32 ui32PipeCount,
+ PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+ DC_BUFFER **papsBuffers)
+{
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE *ahBuffers;
+
+ _DCDisplayContextAcquireRef(psDisplayContext);
+
+ /* Create an array of private device specific buffer handles */
+ eError = _DCDeviceBufferArrayCreate(ui32PipeCount,
+ papsBuffers,
+ &ahBuffers);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailBufferArrayCreate;
+ }
+
+ /* Do we need to check if this is valid config? */
+ if (psDevice->psFuncTable->pfnContextConfigureCheck)
+ {
+
+ eError = psDevice->psFuncTable->pfnContextConfigureCheck(psDisplayContext->hDisplayContext,
+ ui32PipeCount,
+ pasSurfAttrib,
+ ahBuffers);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailConfigCheck;
+ }
+ }
+
+ _DCDeviceBufferArrayDestroy(ahBuffers);
+ _DCDisplayContextReleaseRef(psDisplayContext);
+ return PVRSRV_OK;
+
+FailConfigCheck:
+ _DCDeviceBufferArrayDestroy(ahBuffers);
+FailBufferArrayCreate:
+ _DCDisplayContextReleaseRef(psDisplayContext);
+
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+static IMG_BOOL _DCDisplayContextFlush( PDLLIST_NODE psNode, IMG_PVOID pvCallbackData )
+{
+ DC_CMD_RDY_DATA sReadyData;
+ DC_CMD_COMP_DATA sCompleteData;
+
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_DATA *psData;
+ IMG_UINT32 ui32NumConfigsInSCP, ui32GoodRuns, ui32LoopCount;
+
+ DC_DISPLAY_CONTEXT * psDisplayContext = IMG_CONTAINER_OF(psNode, DC_DISPLAY_CONTEXT, sListNode);
+
+ PVR_UNREFERENCED_PARAMETER(pvCallbackData);
+
+ /* Make the NULL flip command data */
+ sReadyData.psDisplayContext = psDisplayContext;
+ sReadyData.ui32DisplayPeriod = 0;
+ sReadyData.ui32BufferCount = 0;
+ sReadyData.pasSurfAttrib = IMG_NULL;
+ sReadyData.pahBuffer = IMG_NULL;
+
+ sCompleteData.psDisplayContext = psDisplayContext;
+ sCompleteData.ui32BufferCount = 0;
+ sCompleteData.ui32Token = 0;
+ sCompleteData.bDirectNullFlip = IMG_TRUE;
+
+ /* Stop the MISR to stop the SCP from running outside of our control */
+ psDisplayContext->bPauseMISR = IMG_TRUE;
+
+ /*
+ * Flush loop control:
+ * take the total number of Configs owned by the SCP including those
+ * "in-flight" with the DC, then multiply by 2 to account for any padding
+ * commands in the SCP buffer
+ */
+ ui32NumConfigsInSCP = psDisplayContext->ui32TokenOut - psDisplayContext->ui32TokenIn;
+ ui32NumConfigsInSCP *= 2;
+ ui32GoodRuns = 0;
+ ui32LoopCount = 0;
+
+ /*
+ * Calling SCPRun first, ensures that any call to SCPRun from the MISR
+ * context completes before we insert any NULL flush direct to the DC.
+ * SCPRun returns PVRSRV_OK (0) if the run command (Configure) executes OR there
+ * is no work to do OR it consumes a padding command.
+ * By counting a "good" SCPRun for each of the ui32NumConfigsInSCP we ensure
+ * that all Configs currently in the SCP are flushed to the DC.
+ *
+ * In the case where we fail dependencies (PVRSRV_ERROR_FAILED_DEPENDENCIES (15))
+ * but there are outstanding ui32ConfigsInFlight that may satisfy them,
+ * we just loop and try again.
+ * In the case where there is still work to do but the DC is full
+ * (PVRSRV_ERROR_NOT_READY (254)) we just loop and try again
+ *
+ * During a flush, NULL flips may be inserted if waiting for the 3D (not
+ * actually deadlocked), but this should be benign
+ */
+ while ( ui32GoodRuns < ui32NumConfigsInSCP && ui32LoopCount < 500 )
+ {
+ eError = SCPRun( psDisplayContext->psSCPContext );
+
+ if ( 0 == ui32LoopCount && PVRSRV_ERROR_FAILED_DEPENDENCIES != eError && 1 != psDisplayContext->ui32ConfigsInFlight )
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DCDisplayContextFlush: called when not required"));
+ break;
+ }
+
+ if ( PVRSRV_OK == eError )
+ {
+ ui32GoodRuns++;
+ }
+ else if ( PVRSRV_ERROR_FAILED_DEPENDENCIES == eError && 1 == psDisplayContext->ui32ConfigsInFlight )
+ {
+ PVR_DPF((PVR_DBG_WARNING, "DCDisplayContextFlush: inserting NULL flip"));
+
+ /* Check if we need to do any CPU cache operations before sending the NULL flip */
+ psData = PVRSRVGetPVRSRVData();
+ OSCPUOperation(psData->uiCacheOp);
+ psData->uiCacheOp = PVRSRV_CACHE_OP_NONE;
+
+ /* The next Config may be dependent on the single Config currently in the DC */
+ /* Issue a NULL flip to free it */
+ _DCDisplayContextAcquireRef(psDisplayContext);
+ _DCDisplayContextConfigure( (IMG_PVOID)&sReadyData, (IMG_PVOID)&sCompleteData );
+ }
+
+ /* Give up the timeslice to let something happen */
+ OSSleepms(1);
+ ui32LoopCount++;
+ }
+
+ if ( ui32LoopCount >= 500 )
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DCDisplayContextFlush: Failed to flush after > 500 milliseconds"));
+ }
+
+ PVR_DPF((PVR_DBG_WARNING, "DCDisplayContextFlush: inserting final NULL flip"));
+
+ /* Check if we need to do any CPU cache operations before sending the NULL flip */
+ psData = PVRSRVGetPVRSRVData();
+ OSCPUOperation(psData->uiCacheOp);
+ psData->uiCacheOp = PVRSRV_CACHE_OP_NONE;
+
+ /* The next Config may be dependent on the single Config currently in the DC */
+ /* Issue a NULL flip to free it */
+ _DCDisplayContextAcquireRef(psDisplayContext);
+ _DCDisplayContextConfigure( (IMG_PVOID)&sReadyData, (IMG_PVOID)&sCompleteData );
+
+ /* re-enable the MISR/SCP */
+ psDisplayContext->bPauseMISR = IMG_FALSE;
+
+ return IMG_TRUE;
+}
+
+
+PVRSRV_ERROR DCDisplayContextFlush( IMG_VOID )
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if ( !dllist_is_empty(&g_sDisplayContextsList) )
+ {
+ dllist_foreach_node(&g_sDisplayContextsList, _DCDisplayContextFlush, IMG_NULL);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DCDisplayContextFlush: No display contexts found"));
+ eError = PVRSRV_ERROR_INVALID_CONTEXT;
+ }
+
+ return eError;
+}
+
+
+PVRSRV_ERROR DCDisplayContextConfigure(DC_DISPLAY_CONTEXT *psDisplayContext,
+ IMG_UINT32 ui32PipeCount,
+ PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+ DC_BUFFER **papsBuffers,
+ IMG_UINT32 ui32SyncOpCount,
+ SERVER_SYNC_PRIMITIVE **papsSync,
+ IMG_BOOL *pabUpdate,
+ IMG_UINT32 ui32DisplayPeriod,
+ IMG_UINT32 ui32MaxDepth,
+ IMG_INT32 i32AcquireFenceFd,
+ IMG_INT32 *pi32ReleaseFenceFd)
+{
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE *ahBuffers;
+ IMG_UINT32 ui32BuffersMapped = 0;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32CmdRdySize;
+ IMG_UINT32 ui32CmdCompSize;
+ IMG_UINT32 ui32CopySize;
+ IMG_PUINT8 pui8ReadyData;
+ IMG_PVOID pvCompleteData;
+ DC_CMD_RDY_DATA *psReadyData;
+ DC_CMD_COMP_DATA *psCompleteData;
+ PVRSRV_DATA *psData = PVRSRVGetPVRSRVData();
+
+ _DCDisplayContextAcquireRef(psDisplayContext);
+
+ if (ui32MaxDepth == 1)
+ {
+ eError = PVRSRV_ERROR_DC_INVALID_MAXDEPTH;
+ goto FailMaxDepth;
+ }
+ else if (ui32MaxDepth > 0)
+ {
+ /* ui32TokenOut/In wrap-around case takes care of itself. */
+ if (psDisplayContext->ui32TokenOut - psDisplayContext->ui32TokenIn >= ui32MaxDepth)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ goto FailMaxDepth;
+ }
+ }
+
+ /* Reset the release fd */
+ if (pi32ReleaseFenceFd)
+ *pi32ReleaseFenceFd = -1;
+
+ /* If we get sent a NULL flip then we don't need to do the check or map */
+ if (ui32PipeCount != 0)
+ {
+ /* Create an array of private device specific buffer handles */
+ eError = _DCDeviceBufferArrayCreate(ui32PipeCount,
+ papsBuffers,
+ &ahBuffers);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailBufferArrayCreate;
+ }
+
+ /* Do we need to check if this is valid config? */
+ if (psDevice->psFuncTable->pfnContextConfigureCheck)
+ {
+
+ eError = psDevice->psFuncTable->pfnContextConfigureCheck(psDisplayContext->hDisplayContext,
+ ui32PipeCount,
+ pasSurfAttrib,
+ ahBuffers);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailConfigCheck;
+ }
+ }
+
+ /* Map all the buffers that are going to be used */
+ for (i=0;i<ui32PipeCount;i++)
+ {
+ eError = _DCBufferMap(papsBuffers[i]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DCDisplayContextConfigure: Failed to map buffer"));
+ goto FailMapBuffer;
+ }
+ ui32BuffersMapped++;
+ }
+ }
+
+ ui32CmdRdySize = sizeof(DC_CMD_RDY_DATA) +
+ ((sizeof(IMG_HANDLE) + sizeof(PVRSRV_SURFACE_CONFIG_INFO))
+ * ui32PipeCount);
+ ui32CmdCompSize = sizeof(DC_CMD_COMP_DATA) +
+ (sizeof(DC_BUFFER *) * ui32PipeCount);
+
+ /* Allocate a command */
+ eError = SCPAllocCommand(psDisplayContext->psSCPContext,
+ ui32SyncOpCount,
+ papsSync,
+ pabUpdate,
+ i32AcquireFenceFd,
+ _DCDisplayContextReady,
+ _DCDisplayContextConfigure,
+ ui32CmdRdySize,
+ ui32CmdCompSize,
+ (IMG_PVOID *)&pui8ReadyData,
+ &pvCompleteData,
+ pi32ReleaseFenceFd);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto FailCommandAlloc;
+ }
+
+ /*
+ Set up command ready data
+ */
+ psReadyData = (DC_CMD_RDY_DATA *)pui8ReadyData;
+ pui8ReadyData += sizeof(DC_CMD_RDY_DATA);
+
+ psReadyData->ui32DisplayPeriod = ui32DisplayPeriod;
+ psReadyData->psDisplayContext = psDisplayContext;
+ psReadyData->ui32BufferCount = ui32PipeCount;
+
+ /* Copy over surface atrribute array */
+ if (ui32PipeCount != 0)
+ {
+ psReadyData->pasSurfAttrib = (PVRSRV_SURFACE_CONFIG_INFO *)pui8ReadyData;
+ ui32CopySize = sizeof(PVRSRV_SURFACE_CONFIG_INFO) * ui32PipeCount;
+ OSMemCopy(psReadyData->pasSurfAttrib, pasSurfAttrib, ui32CopySize);
+ pui8ReadyData = pui8ReadyData + ui32CopySize;
+ }
+ else
+ {
+ psReadyData->pasSurfAttrib = IMG_NULL;
+ }
+
+ /* Copy over device buffer handle buffer array */
+ if (ui32PipeCount != 0)
+ {
+ psReadyData->pahBuffer = (IMG_HANDLE)pui8ReadyData;
+ ui32CopySize = sizeof(IMG_HANDLE) * ui32PipeCount;
+ OSMemCopy(psReadyData->pahBuffer, ahBuffers, ui32CopySize);
+ }
+ else
+ {
+ psReadyData->pahBuffer = IMG_NULL;
+ }
+
+ /*
+ Set up command complete data
+ */
+ psCompleteData = pvCompleteData;
+ pvCompleteData = (IMG_PUINT8)pvCompleteData + sizeof(DC_CMD_COMP_DATA);
+
+ psCompleteData->psDisplayContext = psDisplayContext;
+ psCompleteData->ui32Token = psDisplayContext->ui32TokenOut++;
+ psCompleteData->ui32BufferCount = ui32PipeCount;
+ psCompleteData->bDirectNullFlip = IMG_FALSE;
+
+ if (ui32PipeCount != 0)
+ {
+ /* Copy the buffer pointers */
+ psCompleteData->apsBuffer = pvCompleteData;
+ for (i=0;i<ui32PipeCount;i++)
+ {
+ psCompleteData->apsBuffer[i] = papsBuffers[i];
+ }
+ }
+
+ /* Check if we need to do any CPU cache operations before sending the config */
+ OSCPUOperation(psData->uiCacheOp);
+ psData->uiCacheOp = PVRSRV_CACHE_OP_NONE;
+
+ /* Submit the command */
+ eError = SCPSubmitCommand(psDisplayContext->psSCPContext);
+
+ /* Check for new work on this display context */
+ _DCDisplayContextRun(psDisplayContext);
+
+ /* The only way this submit can fail is if there is a bug in this module */
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ if (ui32PipeCount != 0)
+ {
+ _DCDeviceBufferArrayDestroy(ahBuffers);
+ }
+
+ return PVRSRV_OK;
+
+FailCommandAlloc:
+FailMapBuffer:
+ if (ui32PipeCount != 0)
+ {
+ for (i=0;i<ui32BuffersMapped;i++)
+ {
+ _DCBufferUnmap(papsBuffers[i]);
+ }
+ }
+FailConfigCheck:
+ if (ui32PipeCount != 0)
+ {
+ _DCDeviceBufferArrayDestroy(ahBuffers);
+ }
+FailBufferArrayCreate:
+FailMaxDepth:
+ _DCDisplayContextReleaseRef(psDisplayContext);
+
+ return eError;
+}
+
+PVRSRV_ERROR DCDisplayContextDestroy(DC_DISPLAY_CONTEXT *psDisplayContext)
+{
+ PVRSRV_ERROR eError;
+
+ /*
+ On the first cleanup request try to issue the NULL flip.
+ If we fail then we should get retry which we pass back to
+ the caller who will try again later.
+ */
+ if (!psDisplayContext->bIssuedNullFlip)
+ {
+ eError = DCDisplayContextConfigure(psDisplayContext,
+ 0,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ 0,
+ -1,
+ IMG_NULL);
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ psDisplayContext->bIssuedNullFlip = IMG_TRUE;
+ }
+
+ /*
+ Flush out everything from SCP
+
+ This will ensure that the MISR isn't dropping the last reference
+ which would cause a deadlock during cleanup
+ */
+ eError = SCPFlush(psDisplayContext->psSCPContext);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ _DCDisplayContextReleaseRef(psDisplayContext);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCBufferAlloc(DC_DISPLAY_CONTEXT *psDisplayContext,
+ DC_BUFFER_CREATE_INFO *psSurfInfo,
+ IMG_UINT32 *pui32ByteStride,
+ DC_BUFFER **ppsBuffer)
+{
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+ DC_BUFFER *psNew;
+ PMR *psPMR;
+ PVRSRV_ERROR eError;
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize;
+ IMG_UINT32 ui32PageCount;
+ IMG_UINT32 ui32PhysHeapID;
+
+ psNew = OSAllocMem(sizeof(DC_BUFFER));
+ if (psNew == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psNew, 0, sizeof(DC_BUFFER));
+
+ eError = OSLockCreate(&psNew->hLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_lock;
+ }
+
+ eError = OSLockCreate(&psNew->hMapLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_maplock;
+ }
+
+ eError = psDevice->psFuncTable->pfnBufferAlloc(psDisplayContext->hDisplayContext,
+ psSurfInfo,
+ &uiLog2PageSize,
+ &ui32PageCount,
+ &ui32PhysHeapID,
+ pui32ByteStride,
+ &psNew->hBuffer);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_bufferalloc;
+ }
+
+ /*
+ Fill in the basic info for our buffer
+ (must be before _DCCreatePMR)
+ */
+ psNew->psDisplayContext = psDisplayContext;
+ psNew->eType = DC_BUFFER_TYPE_ALLOC;
+ psNew->ui32MapCount = 0;
+ psNew->ui32RefCount = 1;
+
+ eError = _DCCreatePMR(uiLog2PageSize,
+ ui32PageCount,
+ ui32PhysHeapID,
+ psNew,
+ &psPMR);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_createpmr;
+ }
+
+#if defined(PVR_RI_DEBUG)
+ {
+ /* Dummy handle - we don't need to store the reference to the PMR RI entry. Its deletion is handled internally. */
+ DC_DISPLAY_INFO sDisplayInfo;
+ IMG_INT32 i32RITextSize;
+ IMG_CHAR pszRIText[RI_MAX_TEXT_LEN];
+
+ DCGetInfo(psDevice, &sDisplayInfo);
+ i32RITextSize = OSSNPrintf((IMG_CHAR *)pszRIText, RI_MAX_TEXT_LEN, "%s: DisplayContext 0x%p BufferAlloc", (IMG_CHAR *)sDisplayInfo.szDisplayName, &psDevice->sSystemContext);
+ if (i32RITextSize < 0)
+ {
+ pszRIText[0] = '\0';
+ i32RITextSize = 0;
+ }
+ else
+ {
+ pszRIText[RI_MAX_TEXT_LEN-1] = '\0';
+ }
+ eError = RIWritePMREntryKM (psPMR,
+ (IMG_UINT32)i32RITextSize,
+ (IMG_CHAR *)pszRIText,
+ (uiLog2PageSize*ui32PageCount));
+ }
+#endif
+
+ psNew->uBufferData.sAllocData.psPMR = psPMR;
+ _DCDisplayContextAcquireRef(psDisplayContext);
+
+ *ppsBuffer = psNew;
+
+ return PVRSRV_OK;
+
+fail_createpmr:
+ psDevice->psFuncTable->pfnBufferFree(psNew->hBuffer);
+fail_bufferalloc:
+ OSLockDestroy(psNew->hMapLock);
+fail_maplock:
+ OSLockDestroy(psNew->hLock);
+fail_lock:
+ OSFreeMem(psNew);
+ return eError;
+}
+
+PVRSRV_ERROR DCBufferFree(DC_BUFFER *psBuffer)
+{
+ /*
+ Only drop the reference on the PMR if this is a DC allocated
+ buffer. In the case of imported buffers the 3rd party DC
+ driver manages the PMR's "directly"
+ */
+ if (psBuffer->eType == DC_BUFFER_TYPE_ALLOC)
+ {
+ PMRUnrefPMR(psBuffer->uBufferData.sAllocData.psPMR);
+ }
+ _DCBufferReleaseRef(psBuffer);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCBufferImport(DC_DISPLAY_CONTEXT *psDisplayContext,
+ IMG_UINT32 ui32NumPlanes,
+ PMR **papsImport,
+ DC_BUFFER_IMPORT_INFO *psSurfAttrib,
+ DC_BUFFER **ppsBuffer)
+{
+ DC_DEVICE *psDevice = psDisplayContext->psDevice;
+ DC_BUFFER *psNew;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+
+ if(psDevice->psFuncTable->pfnBufferImport == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_NOT_SUPPORTED;
+ goto FailEarlyError;
+ }
+
+ psNew = OSAllocMem(sizeof(DC_BUFFER));
+ if (psNew == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto FailEarlyError;
+ }
+ OSMemSet(psNew, 0, sizeof(DC_BUFFER));
+
+ eError = OSLockCreate(&psNew->hLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailLock;
+ }
+
+ eError = OSLockCreate(&psNew->hMapLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailMapLock;
+ }
+
+ eError = psDevice->psFuncTable->pfnBufferImport(psDisplayContext->hDisplayContext,
+ ui32NumPlanes,
+ (IMG_HANDLE **)papsImport,
+ psSurfAttrib,
+ &psNew->hBuffer);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailBufferImport;
+ }
+
+ /*
+ Take a reference on the PMR to make sure it can't be released before
+ we've finished with it
+ */
+ for (i=0;i<ui32NumPlanes;i++)
+ {
+ PMRRefPMR(papsImport[i]);
+ psNew->uBufferData.sImportData.apsImport[i] = papsImport[i];
+ }
+
+ _DCDisplayContextAcquireRef(psDisplayContext);
+ psNew->psDisplayContext = psDisplayContext;
+ psNew->eType = DC_BUFFER_TYPE_IMPORT;
+ psNew->uBufferData.sImportData.ui32NumPlanes = ui32NumPlanes;
+ psNew->ui32MapCount = 0;
+ psNew->ui32RefCount = 1;
+
+ *ppsBuffer = psNew;
+
+ return PVRSRV_OK;
+
+FailBufferImport:
+ OSLockDestroy(psNew->hMapLock);
+FailMapLock:
+ OSLockDestroy(psNew->hLock);
+FailLock:
+ OSFreeMem(psNew);
+
+FailEarlyError:
+ return eError;
+}
+
+PVRSRV_ERROR DCBufferUnimport(DC_BUFFER *psBuffer)
+{
+ _DCBufferReleaseRef(psBuffer);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR DCBufferAcquire(DC_BUFFER *psBuffer, PMR **ppsPMR)
+{
+ PMR *psPMR = psBuffer->uBufferData.sAllocData.psPMR;
+ PVRSRV_ERROR eError;
+
+ if (psBuffer->eType == DC_BUFFER_TYPE_IMPORT)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DCBufferAcquire: Invalid request, DC buffer is an import"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto fail_typecheck;
+ }
+ PMRRefPMR(psPMR);
+
+ *ppsPMR = psPMR;
+ return PVRSRV_OK;
+
+fail_typecheck:
+ return eError;
+}
+
+PVRSRV_ERROR DCBufferRelease(PMR *psPMR)
+{
+ /*
+ Drop our reference on the PMR. If we're the last one then the PMR
+ will be freed and are _DCPMRFinalize function will be called where
+ we drop our reference on the buffer
+ */
+ PMRUnrefPMR(psPMR);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR DCBufferPin(DC_BUFFER *psBuffer, DC_PIN_HANDLE *phPin)
+{
+ *phPin = psBuffer;
+ return _DCBufferMap(psBuffer);
+}
+
+PVRSRV_ERROR DCBufferUnpin(DC_PIN_HANDLE hPin)
+{
+ DC_BUFFER *psBuffer = hPin;
+
+ _DCBufferUnmap(psBuffer);
+ return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ * Public interface functions for 3rd party display class devices *
+ *****************************************************************************/
+
+PVRSRV_ERROR DCRegisterDevice(DC_DEVICE_FUNCTIONS *psFuncTable,
+ IMG_UINT32 ui32MaxConfigsInFlight,
+ IMG_HANDLE hDeviceData,
+ IMG_HANDLE *phSrvHandle)
+{
+ DC_DEVICE *psNew;
+ PVRSRV_ERROR eError;
+
+ psNew = OSAllocMem(sizeof(DC_DEVICE));
+ if (psNew == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto FailAlloc;
+ }
+
+ eError = OSLockCreate(&psNew->hLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailLockCreate;
+ }
+
+ psNew->psFuncTable = psFuncTable;
+ psNew->ui32MaxConfigsInFlight = ui32MaxConfigsInFlight;
+ psNew->hDeviceData = hDeviceData;
+ psNew->ui32RefCount = 1;
+ psNew->hSystemBuffer = IMG_NULL;
+ psNew->ui32Index = g_ui32DCNextIndex++;
+ eError = OSEventObjectCreate("DC_EVENT_OBJ", &psNew->psEventList);
+ if (eError != PVRSRV_OK)
+ {
+ goto FailEventObject;
+ }
+
+ /* Init state required for system surface */
+ psNew->hSystemBuffer = IMG_NULL;
+ psNew->psSystemBufferPMR = IMG_NULL;
+ psNew->sSystemContext.psDevice = psNew;
+ psNew->sSystemContext.hDisplayContext = hDeviceData;
+
+ OSLockAcquire(g_hDCListLock);
+ psNew->psNext = g_psDCDeviceList;
+
+ g_psDCDeviceList = psNew;
+ g_ui32DCDeviceCount++;
+ OSLockRelease(g_hDCListLock);
+
+ *phSrvHandle = (IMG_HANDLE) psNew;
+
+ return PVRSRV_OK;
+
+FailEventObject:
+ OSLockDestroy(psNew->hLock);
+FailLockCreate:
+ OSFreeMem(psNew);
+FailAlloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_VOID DCUnregisterDevice(IMG_HANDLE hSrvHandle)
+{
+ DC_DEVICE *psDevice = (DC_DEVICE *) hSrvHandle;
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_ERROR eError;
+
+ /*
+ If the system buffer was acquired and a PMR created for it, release
+ it before releasing the device as the PMR will have a reference to
+ the device
+ */
+ if (psDevice->psSystemBufferPMR)
+ {
+ PMRUnrefPMR(psDevice->psSystemBufferPMR);
+ }
+
+ /*
+ * At this stage the DC driver wants to unload, if other things have
+ * reference to the DC device we need to block here until they have
+ * been release as when this function returns the DC driver code could
+ * be unloaded.
+ */
+
+ /* If the driver is in a bad state we just free resources regardless */
+ if (psPVRSRVData->eServicesState == PVRSRV_SERVICES_STATE_OK)
+ {
+ volatile IMG_UINT32 * ref_count_ptr = &(psDevice->ui32RefCount);
+
+ /* Skip the wait if we're the last reference holder */
+ if (*ref_count_ptr != 1)
+ {
+ IMG_HANDLE hEvent;
+
+ eError = OSEventObjectOpen(psDevice->psEventList, &hEvent);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Failed to open event object (%d), will busy wait",
+ __FUNCTION__, eError));
+ hEvent = IMG_NULL;
+ }
+
+ while(*ref_count_ptr != 1)
+ {
+ if (hEvent != IMG_NULL)
+ {
+ OSEventObjectWait(hEvent);
+ }
+ }
+ if (hEvent != IMG_NULL)
+ {
+ OSEventObjectClose(hEvent);
+ }
+ }
+ }
+ else
+ {
+ /* We're in a bad state, force the refcount */
+ psDevice->ui32RefCount = 1;
+ }
+
+ _DCDeviceReleaseRef(psDevice);
+
+ PVR_ASSERT(psDevice->ui32RefCount == 0);
+ OSEventObjectDestroy(psDevice->psEventList);
+ OSLockDestroy(psDevice->hLock);
+ OSFreeMem(psDevice);
+}
+
+IMG_VOID DCDisplayConfigurationRetired(IMG_HANDLE hConfigData)
+{
+ DC_CMD_COMP_DATA *psData = hConfigData;
+ DC_DISPLAY_CONTEXT *psDisplayContext = psData->psDisplayContext;
+ IMG_UINT32 i;
+
+ DC_DEBUG_PRINT("DCDisplayConfigurationRetired: Command (%d) received", psData->ui32Token);
+ /* Sanity check */
+ if (!psData->bDirectNullFlip && psData->ui32Token != psDisplayContext->ui32TokenIn)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Display config retired in unexpected order (was %d, expecting %d)",
+ psData->ui32Token, psDisplayContext->ui32TokenIn));
+ PVR_ASSERT(IMG_FALSE);
+ }
+
+ OSLockAcquire(psDisplayContext->hLock);
+ if ( !psData->bDirectNullFlip )
+ {
+ psDisplayContext->ui32TokenIn++;
+ }
+
+#if defined SUPPORT_DC_COMPLETE_TIMEOUT_DEBUG
+ if (psDisplayContext->hTimer)
+ {
+ OSDisableTimer(psDisplayContext->hTimer);
+ OSRemoveTimer(psDisplayContext->hTimer);
+ psDisplayContext->hTimer = IMG_NULL;
+ }
+#endif /* SUPPORT_DC_COMPLETE_TIMEOUT_DEBUG */
+
+ psDisplayContext->ui32ConfigsInFlight--;
+ OSLockRelease(psDisplayContext->hLock);
+
+ for (i = 0; i < psData->ui32BufferCount; i++)
+ {
+ _DCBufferUnmap(psData->apsBuffer[i]);
+ }
+
+ _DCDisplayContextReleaseRef(psDisplayContext);
+
+ /*
+ Note:
+
+ We must call SCPCommandComplete here and not before as we need
+ to ensure that we're not the last to hold the reference as
+ we can't destroy the display context from the MISR which we
+ can be called from.
+ */
+ SCPCommandComplete(psDisplayContext->psSCPContext);
+
+ /* Notify devices (including ourself) in case some item has been unblocked */
+ PVRSRVCheckStatus(IMG_NULL);
+}
+
+PVRSRV_ERROR DCImportBufferAcquire(IMG_HANDLE hImport,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize,
+ IMG_UINT32 *pui32PageCount,
+ IMG_DEV_PHYADDR **ppasDevPAddr)
+{
+ PMR *psPMR = hImport;
+ IMG_DEV_PHYADDR *pasDevPAddr;
+ IMG_DEVMEM_SIZE_T uiLogicalSize;
+ IMG_SIZE_T uiPageCount;
+ IMG_DEVMEM_OFFSET_T uiOffset = 0;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+
+ eError = PMR_LogicalSize(psPMR, &uiLogicalSize);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_getsize;
+ }
+
+ uiPageCount = TRUNCATE_64BITS_TO_SIZE_T(uiLogicalSize >> uiLog2PageSize);
+
+ pasDevPAddr = OSAllocMem(sizeof(IMG_DEV_PHYADDR) * uiPageCount);
+ if (pasDevPAddr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ OSMemSet(pasDevPAddr, 0, sizeof(IMG_DEV_PHYADDR) * uiPageCount);
+
+ /* Lock the pages */
+ eError = PMRLockSysPhysAddresses(psPMR, uiLog2PageSize);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_lock;
+ }
+
+ /* Get each page one by one */
+ for (i=0;i<uiPageCount;i++)
+ {
+ IMG_BOOL bValid;
+
+ eError = PMR_DevPhysAddr(psPMR, uiOffset, &pasDevPAddr[i], &bValid);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_getphysaddr;
+ }
+
+ /* The DC import function doesn't support sparse allocations */
+ PVR_ASSERT(bValid);
+ uiOffset += 1ULL << uiLog2PageSize;
+ }
+
+ *pui32PageCount = TRUNCATE_SIZE_T_TO_32BITS(uiPageCount);
+ *ppasDevPAddr = pasDevPAddr;
+ return PVRSRV_OK;
+
+fail_getphysaddr:
+ PMRUnlockSysPhysAddresses(psPMR);
+fail_lock:
+ OSFreeMem(pasDevPAddr);
+fail_alloc:
+fail_getsize:
+ return eError;
+}
+
+IMG_VOID DCImportBufferRelease(IMG_HANDLE hImport,
+ IMG_DEV_PHYADDR *pasDevPAddr)
+{
+ PMR *psPMR = hImport;
+
+ /* Unlock the pages */
+ PMRUnlockSysPhysAddresses(psPMR);
+ OSFreeMem(pasDevPAddr);
+}
+
+/*****************************************************************************
+ * Public interface functions for services *
+ *****************************************************************************/
+PVRSRV_ERROR DCInit()
+{
+ g_psDCDeviceList = IMG_NULL;
+ g_ui32DCNextIndex = 0;
+ dllist_init(&g_sDisplayContextsList);
+ return OSLockCreate(&g_hDCListLock, LOCK_TYPE_NONE);
+}
+
+PVRSRV_ERROR DCDeInit()
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ if (psPVRSRVData->eServicesState == PVRSRV_SERVICES_STATE_OK)
+ {
+ PVR_ASSERT(g_psDCDeviceList == IMG_NULL);
+ }
+
+ OSLockDestroy(g_hDCListLock);
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/services/server/common/devicemem_heapcfg.c b/drivers/gpu/rogue/services/server/common/devicemem_heapcfg.c
new file mode 100644
index 000000000000..9e8504490276
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/devicemem_heapcfg.c
@@ -0,0 +1,133 @@
+/*************************************************************************/ /*!
+@File devicemem_heapcfg.c
+@Title Temporary Device Memory 2 stuff
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Device memory management
+@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.
+*/ /***************************************************************************/
+
+/* our exported API */
+#include "devicemem_heapcfg.h"
+
+#include "device.h"
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "osfunc.h"
+
+
+PVRSRV_ERROR
+HeapCfgHeapConfigCount(
+ const PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 *puiNumHeapConfigsOut
+)
+{
+
+ *puiNumHeapConfigsOut = psDeviceNode->sDevMemoryInfo.uiNumHeapConfigs;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+HeapCfgHeapCount(
+ const PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 *puiNumHeapsOut
+)
+{
+ if (uiHeapConfigIndex >= psDeviceNode->sDevMemoryInfo.uiNumHeapConfigs)
+ {
+ return PVRSRV_ERROR_DEVICEMEM_INVALID_HEAP_CONFIG_INDEX;
+ }
+
+ *puiNumHeapsOut = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeapConfigArray[uiHeapConfigIndex].uiNumHeaps;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+HeapCfgHeapConfigName(
+ const PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 uiHeapConfigNameBufSz,
+ IMG_CHAR *pszHeapConfigNameOut
+)
+{
+ if (uiHeapConfigIndex >= psDeviceNode->sDevMemoryInfo.uiNumHeapConfigs)
+ {
+ return PVRSRV_ERROR_DEVICEMEM_INVALID_HEAP_CONFIG_INDEX;
+ }
+
+ OSSNPrintf(pszHeapConfigNameOut, uiHeapConfigNameBufSz, "%s", psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeapConfigArray[uiHeapConfigIndex].pszName);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+HeapCfgHeapDetails(
+ const PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 uiHeapIndex,
+ IMG_UINT32 uiHeapNameBufSz,
+ IMG_CHAR *pszHeapNameOut,
+ IMG_DEV_VIRTADDR *psDevVAddrBaseOut,
+ IMG_DEVMEM_SIZE_T *puiHeapLengthOut,
+ IMG_UINT32 *puiLog2DataPageSizeOut
+)
+{
+ DEVMEM_HEAP_BLUEPRINT *psHeapBlueprint;
+
+ if (uiHeapConfigIndex >= psDeviceNode->sDevMemoryInfo.uiNumHeapConfigs)
+ {
+ return PVRSRV_ERROR_DEVICEMEM_INVALID_HEAP_CONFIG_INDEX;
+ }
+
+ if (uiHeapIndex >= psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeapConfigArray[uiHeapConfigIndex].uiNumHeaps)
+ {
+ return PVRSRV_ERROR_DEVICEMEM_INVALID_HEAP_INDEX;
+ }
+
+ psHeapBlueprint = &psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeapConfigArray[uiHeapConfigIndex].psHeapBlueprintArray[uiHeapIndex];
+
+ OSSNPrintf(pszHeapNameOut, uiHeapNameBufSz, "%s", psHeapBlueprint->pszName);
+ *psDevVAddrBaseOut = psHeapBlueprint->sHeapBaseAddr;
+ *puiHeapLengthOut = psHeapBlueprint->uiHeapLength;
+ *puiLog2DataPageSizeOut = psHeapBlueprint->uiLog2DataPageSize;
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/services/server/common/devicemem_server.c b/drivers/gpu/rogue/services/server/common/devicemem_server.c
new file mode 100644
index 000000000000..5e5feece87e7
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/devicemem_server.c
@@ -0,0 +1,764 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Server-side component of the Device Memory Management.
+@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.
+*/ /**************************************************************************/
+/* our exported API */
+#include "devicemem_server.h"
+#include "devicemem_utils.h"
+#include "devicemem.h"
+
+#include "device.h" /* For device node */
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+
+#include "mmu_common.h"
+#include "pdump_km.h"
+#include "pmr.h"
+
+#include "allocmem.h"
+#include "osfunc.h"
+
+struct _DEVMEMINT_CTX_
+{
+ PVRSRV_DEVICE_NODE *psDevNode;
+
+ /* MMU common code needs to have a context. There's a one-to-one
+ correspondence between device memory context and MMU context,
+ but we have the abstraction here so that we don't need to care
+ what the MMU does with its context, and the MMU code need not
+ know about us at all. */
+ MMU_CONTEXT *psMMUContext;
+
+ IMG_UINT32 ui32RefCount;
+
+ /* Lock for this memory context */
+ POS_LOCK hLock;
+
+ /* This handle is for devices that require notification when a new
+ memory context is created and they need to store private data that
+ is associated with the context. */
+ IMG_HANDLE hPrivData;
+};
+
+struct _DEVMEMINT_CTX_EXPORT_
+{
+ DEVMEMINT_CTX *psDevmemCtx;
+};
+
+struct _DEVMEMINT_HEAP_
+{
+ struct _DEVMEMINT_CTX_ *psDevmemCtx;
+ IMG_UINT32 ui32RefCount;
+ /* Lock for this heap */
+ POS_LOCK hLock;
+};
+
+struct _DEVMEMINT_RESERVATION_
+{
+ struct _DEVMEMINT_HEAP_ *psDevmemHeap;
+ IMG_DEV_VIRTADDR sBase;
+ IMG_DEVMEM_SIZE_T uiLength;
+};
+
+struct _DEVMEMINT_MAPPING_
+{
+ struct _DEVMEMINT_RESERVATION_ *psReservation;
+ PMR *psPMR;
+ IMG_UINT32 uiNumPages;
+ IMG_UINT32 uiLog2PageSize;
+};
+
+/*************************************************************************/ /*!
+@Function _DevmemIntCtxAcquire
+@Description Acquire a reference to the provided device memory context.
+@Return None
+*/ /**************************************************************************/
+static INLINE IMG_VOID _DevmemIntCtxAcquire(DEVMEMINT_CTX *psDevmemCtx)
+{
+ OSLockAcquire(psDevmemCtx->hLock);
+ psDevmemCtx->ui32RefCount++;
+ OSLockRelease(psDevmemCtx->hLock);
+}
+
+/*************************************************************************/ /*!
+@Function _DevmemIntCtxRelease
+@Description Release the reference to the provided device memory context.
+ If this is the last reference which was taken then the
+ memory context will be freed.
+@Return None
+*/ /**************************************************************************/
+static INLINE IMG_VOID _DevmemIntCtxRelease(DEVMEMINT_CTX *psDevmemCtx)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psDevmemCtx->hLock);
+ ui32RefCount = --psDevmemCtx->ui32RefCount;
+ OSLockRelease(psDevmemCtx->hLock);
+
+ if (ui32RefCount == 0)
+ {
+ /* The last reference has gone, destroy the context */
+ PVRSRV_DEVICE_NODE *psDevNode = psDevmemCtx->psDevNode;
+
+ if (psDevNode->pfnUnregisterMemoryContext)
+ {
+ psDevNode->pfnUnregisterMemoryContext(psDevmemCtx->hPrivData);
+ }
+ MMU_ContextDestroy(psDevmemCtx->psMMUContext);
+ OSLockDestroy(psDevmemCtx->hLock);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Freed memory context %p", __FUNCTION__, psDevmemCtx));
+ OSFreeMem(psDevmemCtx);
+ }
+}
+
+/*************************************************************************/ /*!
+@Function _DevmemIntHeapAcquire
+@Description Acquire a reference to the provided device memory heap.
+@Return None
+*/ /**************************************************************************/
+static INLINE IMG_VOID _DevmemIntHeapAcquire(DEVMEMINT_HEAP *psDevmemHeap)
+{
+ OSLockAcquire(psDevmemHeap->hLock);
+ psDevmemHeap->ui32RefCount++;
+ OSLockRelease(psDevmemHeap->hLock);
+}
+
+/*************************************************************************/ /*!
+@Function _DevmemIntHeapRelease
+@Description Release the reference to the provided device memory heap.
+ If this is the last reference which was taken then the
+ memory context will be freed.
+@Return None
+*/ /**************************************************************************/
+static INLINE IMG_VOID _DevmemIntHeapRelease(DEVMEMINT_HEAP *psDevmemHeap)
+{
+ OSLockAcquire(psDevmemHeap->hLock);
+ psDevmemHeap->ui32RefCount--;
+ OSLockRelease(psDevmemHeap->hLock);
+}
+
+/*************************************************************************/ /*!
+@Function DevmemServerGetImportHandle
+@Description For given exportable memory descriptor returns PMR handle.
+@Return Memory is exportable - Success
+ PVRSRV_ERROR failure code
+*/ /**************************************************************************/
+PVRSRV_ERROR
+DevmemServerGetImportHandle(DEVMEM_MEMDESC *psMemDesc,
+ IMG_HANDLE *phImport)
+{
+ PVRSRV_ERROR eError;
+
+ if (psMemDesc->psImport->bExportable == IMG_FALSE)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_CANT_EXPORT_SUBALLOCATION;
+ goto e0;
+ }
+
+ *phImport = psMemDesc->psImport->hPMR;
+ return PVRSRV_OK;
+
+e0:
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function DevmemServerGetHeapHandle
+@Description For given reservation returns the Heap handle.
+@Return PVRSRV_ERROR failure code
+*/ /**************************************************************************/
+PVRSRV_ERROR
+DevmemServerGetHeapHandle(DEVMEMINT_RESERVATION *psReservation,
+ IMG_HANDLE *phHeap)
+{
+ *phHeap = psReservation->psDevmemHeap;
+ return PVRSRV_OK;
+}
+
+
+
+/*************************************************************************/ /*!
+@Function DevmemIntCtxCreate
+@Description Creates and initialises a device memory context.
+@Return valid Device Memory context handle - Success
+ PVRSRV_ERROR failure code
+*/ /**************************************************************************/
+PVRSRV_ERROR
+DevmemIntCtxCreate(
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ DEVMEMINT_CTX **ppsDevmemCtxPtr,
+ IMG_HANDLE *hPrivData
+ )
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_CTX *psDevmemCtx;
+ IMG_HANDLE hPrivDataInt = IMG_NULL;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s", __FUNCTION__));
+
+ /* allocate a Devmem context */
+ psDevmemCtx = OSAllocMem(sizeof *psDevmemCtx);
+ if (psDevmemCtx == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ PVR_DPF ((PVR_DBG_ERROR, "%s: Alloc failed", __FUNCTION__));
+ goto fail_alloc;
+ }
+
+ eError = OSLockCreate(&psDevmemCtx->hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create lock", __FUNCTION__));
+ goto fail_lock;
+ }
+
+ psDevmemCtx->ui32RefCount = 1;
+ psDevmemCtx->psDevNode = psDeviceNode;
+
+ /* Call down to MMU context creation */
+
+ eError = MMU_ContextCreate(psDeviceNode,
+ &psDevmemCtx->psMMUContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: MMU_ContextCreate failed", __FUNCTION__));
+ goto fail_mmucontext;
+ }
+
+
+ if (psDeviceNode->pfnRegisterMemoryContext)
+ {
+ eError = psDeviceNode->pfnRegisterMemoryContext(psDeviceNode, psDevmemCtx->psMMUContext, &hPrivDataInt);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to register MMU context", __FUNCTION__));
+ goto fail_register;
+ }
+ }
+
+ /* Store the private data as it is required to unregister the memory context */
+ psDevmemCtx->hPrivData = hPrivDataInt;
+ *hPrivData = hPrivDataInt;
+ *ppsDevmemCtxPtr = psDevmemCtx;
+
+ return PVRSRV_OK;
+
+fail_register:
+ MMU_ContextDestroy(psDevmemCtx->psMMUContext);
+
+fail_mmucontext:
+ OSLockDestroy(psDevmemCtx->hLock);
+
+fail_lock:
+ OSFreeMem(psDevmemCtx);
+
+fail_alloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function DevmemIntCtxCreate
+@Description Creates and initialises a device memory context.
+@Return valid Device Memory context handle - Success
+ PVRSRV_ERROR failure code
+*/ /**************************************************************************/
+PVRSRV_ERROR
+DevmemIntHeapCreate(
+ DEVMEMINT_CTX *psDevmemCtx,
+ IMG_DEV_VIRTADDR sHeapBaseAddr,
+ IMG_DEVMEM_SIZE_T uiHeapLength,
+ IMG_UINT32 uiLog2DataPageSize,
+ DEVMEMINT_HEAP **ppsDevmemHeapPtr
+ )
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_HEAP *psDevmemHeap;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: DevmemIntHeap_Create", __FUNCTION__));
+
+ /* allocate a Devmem context */
+ psDevmemHeap = OSAllocMem(sizeof *psDevmemHeap);
+ if (psDevmemHeap == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ PVR_DPF ((PVR_DBG_ERROR, "%s: Alloc failed", __FUNCTION__));
+ goto fail_alloc;
+ }
+
+ eError = OSLockCreate(&psDevmemHeap->hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create lock", __FUNCTION__));
+ goto fail_lock;
+ }
+
+ psDevmemHeap->psDevmemCtx = psDevmemCtx;
+
+ _DevmemIntCtxAcquire(psDevmemHeap->psDevmemCtx);
+
+ psDevmemHeap->ui32RefCount = 1;
+
+ *ppsDevmemHeapPtr = psDevmemHeap;
+
+ return PVRSRV_OK;
+
+fail_lock:
+ OSFreeMem(psDevmemHeap);
+
+fail_alloc:
+ return eError;
+}
+
+PVRSRV_ERROR
+DevmemIntMapPMR(DEVMEMINT_HEAP *psDevmemHeap,
+ DEVMEMINT_RESERVATION *psReservation,
+ PMR *psPMR,
+ PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
+ DEVMEMINT_MAPPING **ppsMappingPtr)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_MAPPING *psMapping;
+ /* number of pages (device pages) that allocation spans */
+ IMG_UINT32 ui32NumDevPages;
+ /* device virtual address of start of allocation */
+ IMG_DEV_VIRTADDR sAllocationDevVAddr;
+ /* and its length */
+ IMG_DEVMEM_SIZE_T uiAllocationSize;
+
+ /* allocate memory to record the mapping info */
+ psMapping = OSAllocMem(sizeof *psMapping);
+ if (psMapping == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ PVR_DPF ((PVR_DBG_ERROR, "DevmemIntMapPMR: Alloc failed"));
+ goto e0;
+ }
+
+ uiAllocationSize = psReservation->uiLength;
+
+
+ ui32NumDevPages = 0xffffffffU & (((uiAllocationSize - 1)
+ >> GET_LOG2_PAGESIZE()) + 1);
+ PVR_ASSERT(ui32NumDevPages << GET_LOG2_PAGESIZE() == uiAllocationSize);
+
+ eError = PMRLockSysPhysAddresses(psPMR,
+ GET_LOG2_PAGESIZE());
+ if (eError != PVRSRV_OK)
+ {
+ goto e2;
+ }
+
+ sAllocationDevVAddr = psReservation->sBase;
+
+ /* N.B. We pass mapping permission flags to MMU_MapPMR and let
+ it reject the mapping if the permissions on the PMR are not compatible. */
+
+ eError = MMU_MapPMR (psDevmemHeap->psDevmemCtx->psMMUContext,
+ sAllocationDevVAddr,
+ psPMR,
+ ui32NumDevPages << GET_LOG2_PAGESIZE(),
+ uiMapFlags,
+ GET_LOG2_PAGESIZE());
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ psMapping->psReservation = psReservation;
+ psMapping->uiNumPages = ui32NumDevPages;
+ psMapping->uiLog2PageSize = GET_LOG2_PAGESIZE();
+ 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;
+
+ e2:
+ OSFreeMem(psMapping);
+
+ e0:
+ PVR_ASSERT (eError != PVRSRV_OK);
+ return eError;
+}
+
+
+PVRSRV_ERROR
+DevmemIntUnmapPMR(DEVMEMINT_MAPPING *psMapping)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_HEAP *psDevmemHeap;
+ /* device virtual address of start of allocation */
+ IMG_DEV_VIRTADDR sAllocationDevVAddr;
+ /* number of pages (device pages) that allocation spans */
+ IMG_UINT32 ui32NumDevPages;
+
+ psDevmemHeap = psMapping->psReservation->psDevmemHeap;
+
+ ui32NumDevPages = psMapping->uiNumPages;
+ sAllocationDevVAddr = psMapping->psReservation->sBase;
+
+
+ MMU_UnmapPages (psDevmemHeap->psDevmemCtx->psMMUContext,
+ sAllocationDevVAddr,
+ ui32NumDevPages,
+ GET_LOG2_PAGESIZE());
+
+ 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 */
+ _DevmemIntHeapRelease(psDevmemHeap);
+
+ OSFreeMem(psMapping);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+DevmemIntReserveRange(DEVMEMINT_HEAP *psDevmemHeap,
+ IMG_DEV_VIRTADDR sAllocationDevVAddr,
+ IMG_DEVMEM_SIZE_T uiAllocationSize,
+ DEVMEMINT_RESERVATION **ppsReservationPtr)
+{
+ PVRSRV_ERROR eError;
+ DEVMEMINT_RESERVATION *psReservation;
+
+ /* allocate memory to record the reservation info */
+ psReservation = OSAllocMem(sizeof *psReservation);
+ if (psReservation == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ PVR_DPF ((PVR_DBG_ERROR, "DevmemIntReserveRange: Alloc failed"));
+ goto e0;
+ }
+
+ psReservation->sBase = sAllocationDevVAddr;
+ psReservation->uiLength = uiAllocationSize;
+
+
+ eError = MMU_Alloc (psDevmemHeap->psDevmemCtx->psMMUContext,
+ uiAllocationSize,
+ &uiAllocationSize,
+ 0, /* IMG_UINT32 uiProtFlags */
+ 0, /* alignment is n/a since we supply devvaddr */
+ &sAllocationDevVAddr,
+ GET_LOG2_PAGESIZE());
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ /* 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;
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+ e1:
+ OSFreeMem(psReservation);
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR
+DevmemIntUnreserveRange(DEVMEMINT_RESERVATION *psReservation)
+{
+
+ MMU_Free (psReservation->psDevmemHeap->psDevmemCtx->psMMUContext,
+ psReservation->sBase,
+ psReservation->uiLength,
+ GET_LOG2_PAGESIZE());
+
+ _DevmemIntHeapRelease(psReservation->psDevmemHeap);
+ OSFreeMem(psReservation);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+DevmemIntHeapDestroy(
+ DEVMEMINT_HEAP *psDevmemHeap
+ )
+{
+ if (psDevmemHeap->ui32RefCount != 1)
+ {
+ 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",
+ __FUNCTION__,
+ psDevmemHeap->ui32RefCount));
+ /*
+ Try again later when you've freed all the memory
+
+ Note:
+ While we don't expect the application to retry (after all this call
+ would succeed if the client had freed all the memory which it should
+ have done before calling this function) resman will retry at which
+ point any allocations leaked by the client will have also been cleaned
+ up by resman and so this call would then succeed.
+ */
+ return PVRSRV_ERROR_RETRY;
+ }
+
+ PVR_ASSERT(psDevmemHeap->ui32RefCount == 1);
+
+ _DevmemIntCtxRelease(psDevmemHeap->psDevmemCtx);
+
+ OSLockDestroy(psDevmemHeap->hLock);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Freed heap %p", __FUNCTION__, psDevmemHeap));
+ OSFreeMem(psDevmemHeap);
+
+ return PVRSRV_OK;
+}
+
+
+/*************************************************************************/ /*!
+@Function DevmemIntCtxDestroy
+@Description Destroy that created by DevmemIntCtxCreate
+@Input psDevmemCtx Device Memory context
+@Return cannot fail.
+*/ /**************************************************************************/
+PVRSRV_ERROR
+DevmemIntCtxDestroy(
+ DEVMEMINT_CTX *psDevmemCtx
+ )
+{
+ /*
+ We can't determine if we should be freeing the context here
+ as it refcount!=1 could be due to either the fact that heap(s)
+ remain with allocations on them, or that this memory context
+ has been exported.
+ As the client couldn’t do anything useful with this information
+ anyway and the fact that the refcount will ensure we only
+ free the context when _all_ references have been released
+ don't bother checking and just return OK regardless.
+ */
+ _DevmemIntCtxRelease(psDevmemCtx);
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function DevmemIntCtxExport
+@Description Exports a device memory context.
+@Return valid Device Memory context handle - Success
+ PVRSRV_ERROR failure code
+*/ /**************************************************************************/
+PVRSRV_ERROR
+DevmemIntCtxExport(DEVMEMINT_CTX *psDevmemCtx,
+ DEVMEMINT_CTX_EXPORT **ppsExport)
+{
+ DEVMEMINT_CTX_EXPORT *psExport;
+
+ psExport = OSAllocMem(sizeof(*psExport));
+ if (psExport == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ _DevmemIntCtxAcquire(psDevmemCtx);
+ psExport->psDevmemCtx = psDevmemCtx;
+
+ *ppsExport = psExport;
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function DevmemIntCtxUnexport
+@Description Unexport an exported a device memory context.
+@Return None
+*/ /**************************************************************************/
+PVRSRV_ERROR
+DevmemIntCtxUnexport(DEVMEMINT_CTX_EXPORT *psExport)
+{
+ _DevmemIntCtxRelease(psExport->psDevmemCtx);
+ OSFreeMem(psExport);
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function DevmemIntCtxImport
+@Description Import an exported a device memory context.
+@Return valid Device Memory context handle - Success
+ PVRSRV_ERROR failure code
+*/ /**************************************************************************/
+PVRSRV_ERROR
+DevmemIntCtxImport(DEVMEMINT_CTX_EXPORT *psExport,
+ DEVMEMINT_CTX **ppsDevmemCtxPtr,
+ IMG_HANDLE *hPrivData)
+{
+ DEVMEMINT_CTX *psDevmemCtx = psExport->psDevmemCtx;
+
+ _DevmemIntCtxAcquire(psDevmemCtx);
+
+ *ppsDevmemCtxPtr = psDevmemCtx;
+ *hPrivData = psDevmemCtx->hPrivData;
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function DevmemSLCFlushInvalRequest
+@Description Requests a SLC Flush and Invalidate
+@Input psDeviceNode Device node
+@Input psPmr PMR
+@Return PVRSRV_OK
+*/ /**************************************************************************/
+PVRSRV_ERROR
+DevmemSLCFlushInvalRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+ PMR *psPmr)
+{
+
+ /* invoke SLC flush and invalidate request */
+ psDeviceNode->pfnSLCCacheInvalidateRequest(psDeviceNode, psPmr);
+
+ return PVRSRV_OK;
+}
+
+
+#if defined (PDUMP)
+IMG_UINT32 DevmemIntMMUContextID(DEVMEMINT_CTX *psDevMemContext)
+{
+ IMG_UINT32 ui32MMUContextID;
+ MMU_AcquirePDumpMMUContext(psDevMemContext->psMMUContext, &ui32MMUContextID);
+ return ui32MMUContextID;
+}
+
+PVRSRV_ERROR
+DevmemIntPDumpSaveToFileVirtual(DEVMEMINT_CTX *psDevmemCtx,
+ IMG_DEV_VIRTADDR sDevAddrStart,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 ui32ArraySize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 uiPDumpMMUCtx;
+
+ PVR_UNREFERENCED_PARAMETER(ui32ArraySize);
+
+ eError = MMU_AcquirePDumpMMUContext(psDevmemCtx->psMMUContext,
+ &uiPDumpMMUCtx);
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /*
+ The following SYSMEM refers to the 'MMU Context', hence it
+ should be the MMU context, not the PMR, that says what the PDump
+ MemSpace tag is?
+ 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,
+ uiPDumpMMUCtx,
+ sDevAddrStart,
+ uiSize,
+ pszFilename,
+ ui32FileOffset,
+ ui32PDumpFlags);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ MMU_ReleasePDumpMMUContext(psDevmemCtx->psMMUContext);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+DevmemIntPDumpBitmap(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;
+
+ eError = MMU_AcquirePDumpMMUContext(psDevMemContext->psMMUContext, &ui32ContextID);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevmemIntPDumpBitmap: Failed to acquire MMU context"));
+ 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);
+
+ return eError;
+}
+#endif
diff --git a/drivers/gpu/rogue/services/server/common/handle.c b/drivers/gpu/rogue/services/server/common/handle.c
new file mode 100644
index 000000000000..1fa3ff05382e
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/handle.c
@@ -0,0 +1,1933 @@
+/*************************************************************************/ /*!
+@File
+@Title Resource Handle Manager
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource handle management
+@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.
+*/ /***************************************************************************/
+
+#ifdef PVR_SECURE_HANDLES
+/* See handle.h for a description of the handle API. */
+
+/*
+ * The implmentation supports movable handle structures, allowing the address
+ * of a handle structure to change without having to fix up pointers in
+ * any of the handle structures. For example, the linked list mechanism
+ * used to link subhandles together uses handle array indices rather than
+ * pointers to the structures themselves.
+ */
+
+#include <stddef.h>
+
+#include "handle.h"
+#include "handle_impl.h"
+#include "allocmem.h"
+#include "pvr_debug.h"
+
+#define HANDLE_HASH_TAB_INIT_SIZE 32
+
+#define SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
+#define CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= (IMG_UINT)~(f)))
+#define TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
+
+#define TEST_ALLOC_FLAG(psHandleData, f) TEST_FLAG((psHandleData)->eFlag, f)
+
+
+/* Linked list structure. Used for both the list head and list items */
+typedef struct _HANDLE_LIST_
+{
+ IMG_HANDLE hPrev;
+ IMG_HANDLE hNext;
+ IMG_HANDLE hParent;
+} HANDLE_LIST;
+
+typedef struct _HANDLE_DATA_
+{
+ /* The handle that represents this structure */
+ IMG_HANDLE hHandle;
+
+ /* Handle type */
+ PVRSRV_HANDLE_TYPE eType;
+
+ /* Flags specified when the handle was allocated */
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag;
+
+ /* Pointer to the data that the handle represents */
+ IMG_VOID *pvData;
+
+ /* List head for subhandles of this handle */
+ HANDLE_LIST sChildren;
+
+ /* List entry for sibling subhandles */
+ HANDLE_LIST sSiblings;
+
+ /* Reference count, always 1 unless handle is shared */
+ IMG_UINT32 ui32Refs;
+} HANDLE_DATA;
+
+struct _HANDLE_BASE_
+{
+ /* Pointer to a handle implementations base structure */
+ HANDLE_IMPL_BASE *psImplBase;
+
+ /*
+ * Pointer to handle hash table.
+ * The hash table is used to do reverse lookups, converting data
+ * pointers to handles.
+ */
+ HASH_TABLE *psHashTab;
+};
+
+/*
+ * The key for the handle hash table is an array of three elements, the
+ * pointer to the resource, the resource type and the parent handle (or
+ * IMG_NULL if there is no parent). The eHandKey enumeration gives the
+ * array indices of the elements making up the key.
+ */
+enum eHandKey
+{
+ HAND_KEY_DATA = 0,
+ HAND_KEY_TYPE,
+ HAND_KEY_PARENT,
+ HAND_KEY_LEN /* Must be last item in list */
+};
+
+/* HAND_KEY is the type of the hash table key */
+typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
+
+/* Stores a pointer to the function table of the handle back-end in use */
+static HANDLE_IMPL_FUNCTAB const *gpsHandleFuncs = IMG_NULL;
+
+/*
+ * Global lock added to avoid to call the handling functions
+ * only in a single threaded context.
+ */
+
+static POS_LOCK gHandleLock;
+
+static void LockHandle(void)
+{
+ OSLockAcquire(gHandleLock);
+}
+
+static void UnlockHandle(void)
+{
+ OSLockRelease(gHandleLock);
+}
+
+/*
+ * Kernel handle base structure. This is used for handles that are not
+ * allocated on behalf of a particular process.
+ */
+PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
+
+/*!
+******************************************************************************
+
+ @Function GetHandleData
+
+ @Description Get the handle data structure for a given handle
+
+ @Input psBase - pointer to handle base structure
+ ppsHandleData - location to return pointer to handle data structure
+ hHandle - handle from client
+ eType - handle type or PVRSRV_HANDLE_TYPE_NONE if the
+ handle type is not to be checked.
+
+ @Output ppsHandleData - points to a pointer to the handle data structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(GetHandleData)
+#endif
+static INLINE
+PVRSRV_ERROR GetHandleData(PVRSRV_HANDLE_BASE *psBase,
+ HANDLE_DATA **ppsHandleData,
+ IMG_HANDLE hHandle,
+ PVRSRV_HANDLE_TYPE eType)
+{
+ HANDLE_DATA *psHandleData;
+ PVRSRV_ERROR eError;
+
+ eError = gpsHandleFuncs->pfnGetHandleData(psBase->psImplBase,
+ hHandle,
+ (IMG_VOID **)&psHandleData);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ /*
+ * Unless PVRSRV_HANDLE_TYPE_NONE was passed in to this function,
+ * check handle is of the correct type.
+ */
+ if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandleData->eType)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "GetHandleData: Handle type mismatch (%d != %d)",
+ eType, psHandleData->eType));
+ return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
+ }
+
+ /* Return the handle structure */
+ *ppsHandleData = psHandleData;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function HandleListInit
+
+ @Description Initialise a linked list structure embedded in a handle
+ structure.
+
+ @Input hHandle - handle containing the linked list structure
+ psList - pointer to linked list structure
+ hParent - parent handle or IMG_NULL
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInit)
+#endif
+static INLINE
+IMG_VOID HandleListInit(IMG_HANDLE hHandle, HANDLE_LIST *psList, IMG_HANDLE hParent)
+{
+ psList->hPrev = hHandle;
+ psList->hNext = hHandle;
+ psList->hParent = hParent;
+}
+
+/*!
+******************************************************************************
+
+ @Function InitParentList
+
+ @Description Initialise the children list head in a handle structure.
+ The children are the subhandles of this handle.
+
+ @Input psHandleData - pointer to handle data structure
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitParentList)
+#endif
+static INLINE
+IMG_VOID InitParentList(HANDLE_DATA *psHandleData)
+{
+ IMG_HANDLE hParent = psHandleData->hHandle;
+
+ HandleListInit(hParent, &psHandleData->sChildren, hParent);
+}
+
+/*!
+******************************************************************************
+
+ @Function InitChildEntry
+
+ @Description Initialise the child list entry in a handle structure.
+ The list entry is used to link together subhandles of
+ a given handle.
+
+ @Input psHandleData - pointer to handle data structure
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitChildEntry)
+#endif
+static INLINE
+IMG_VOID InitChildEntry(HANDLE_DATA *psHandleData)
+{
+ HandleListInit(psHandleData->hHandle, &psHandleData->sSiblings, IMG_NULL);
+}
+
+/*!
+******************************************************************************
+
+ @Function HandleListIsEmpty
+
+ @Description Determine whether a given linked list is empty.
+
+ @Input hHandle - handle containing the list head
+ psList - pointer to the list head
+
+ @Return IMG_TRUE if the list is empty, IMG_FALSE if it isn't.
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIsEmpty)
+#endif
+static INLINE
+IMG_BOOL HandleListIsEmpty(IMG_HANDLE hHandle, HANDLE_LIST *psList) /* Instead of passing in the handle can we not just do (psList->hPrev == psList->hNext) ? IMG_TRUE : IMG_FALSE ??? */
+{
+ IMG_BOOL bIsEmpty;
+
+ bIsEmpty = (IMG_BOOL)(psList->hNext == hHandle);
+
+#ifdef DEBUG
+ {
+ IMG_BOOL bIsEmpty2;
+
+ bIsEmpty2 = (IMG_BOOL)(psList->hPrev == hHandle);
+ PVR_ASSERT(bIsEmpty == bIsEmpty2);
+ }
+#endif
+
+ return bIsEmpty;
+}
+
+#ifdef DEBUG
+/*!
+******************************************************************************
+
+ @Function NoChildren
+
+ @Description Determine whether a handle has any subhandles
+
+ @Input psHandleData - pointer to handle data structure
+
+ @Return IMG_TRUE if the handle has no subhandles, IMG_FALSE if it does.
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoChildren)
+#endif
+static INLINE
+IMG_BOOL NoChildren(HANDLE_DATA *psHandleData)
+{
+ PVR_ASSERT(psHandleData->sChildren.hParent == psHandleData->hHandle);
+
+ return HandleListIsEmpty(psHandleData->hHandle, &psHandleData->sChildren);
+}
+
+/*!
+******************************************************************************
+
+ @Function NoParent
+
+ @Description Determine whether a handle is a subhandle
+
+ @Input psHandleData - pointer to handle data structure
+
+ @Return IMG_TRUE if the handle is not a subhandle, IMG_FALSE if it is.
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoParent)
+#endif
+static INLINE
+IMG_BOOL NoParent(HANDLE_DATA *psHandleData)
+{
+ if (HandleListIsEmpty(psHandleData->hHandle, &psHandleData->sSiblings))
+ {
+ PVR_ASSERT(psHandleData->sSiblings.hParent == IMG_NULL);
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ PVR_ASSERT(psHandleData->sSiblings.hParent != IMG_NULL);
+ }
+ return IMG_FALSE;
+}
+#endif /*DEBUG*/
+
+/*!
+******************************************************************************
+
+ @Function ParentHandle
+
+ @Description Determine the parent of a handle
+
+ @Input psHandleData - pointer to handle data structure
+
+ @Return Parent handle, or IMG_NULL if the handle is not a subhandle.
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentHandle)
+#endif
+static INLINE
+IMG_HANDLE ParentHandle(HANDLE_DATA *psHandleData)
+{
+ return psHandleData->sSiblings.hParent;
+}
+
+/*
+ * GetHandleListFromHandleAndOffset is used to generate either a
+ * pointer to the subhandle list head, or a pointer to the linked list
+ * structure of an item on a subhandle list.
+ * The list head is itself on the list, but is at a different offset
+ * in the handle structure to the linked list structure for items on
+ * the list. The two linked list structures are differentiated by
+ * the third parameter, containing the parent handle. The parent field
+ * in the list head structure references the handle structure that contains
+ * it. For items on the list, the parent field in the linked list structure
+ * references the parent handle, which will be different from the handle
+ * containing the linked list structure.
+ */
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(GetHandleListFromHandleAndOffset)
+#endif
+static INLINE
+HANDLE_LIST *GetHandleListFromHandleAndOffset(PVRSRV_HANDLE_BASE *psBase,
+ IMG_HANDLE hEntry,
+ IMG_HANDLE hParent,
+ IMG_SIZE_T uiParentOffset,
+ IMG_SIZE_T uiEntryOffset)
+{
+ HANDLE_DATA *psHandleData = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psBase != IMG_NULL);
+
+ eError = GetHandleData(psBase,
+ &psHandleData,
+ hEntry,
+ PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ if (hEntry == hParent)
+ {
+ return (HANDLE_LIST *)((IMG_CHAR *)psHandleData + uiParentOffset);
+ }
+ else
+ {
+ return (HANDLE_LIST *)((IMG_CHAR *)psHandleData + uiEntryOffset);
+ }
+}
+
+/*!
+******************************************************************************
+
+ @Function HandleListInsertBefore
+
+ @Description Insert a handle before a handle currently on the list.
+
+ @Input hEntry - handle to be inserted after
+ psEntry - pointer to handle structure to be inserted after
+ uiParentOffset - offset to list head struct in handle structure
+ hNewEntry - handle to be inserted
+ psNewEntry - pointer to handle structure of item to be inserted
+ uiEntryOffset - offset of list item struct in handle structure
+ hParent - parent handle of hNewEntry
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInsertBefore)
+#endif
+static INLINE
+PVRSRV_ERROR HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase,
+ IMG_HANDLE hEntry,
+ HANDLE_LIST *psEntry,
+ IMG_SIZE_T uiParentOffset,
+ IMG_HANDLE hNewEntry,
+ HANDLE_LIST *psNewEntry,
+ IMG_SIZE_T uiEntryOffset,
+ IMG_HANDLE hParent)
+{
+ HANDLE_LIST *psPrevEntry;
+
+ if (psBase == IMG_NULL || psEntry == IMG_NULL || psNewEntry == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psPrevEntry = GetHandleListFromHandleAndOffset(psBase,
+ psEntry->hPrev,
+ hParent,
+ uiParentOffset,
+ uiEntryOffset);
+ if (psPrevEntry == IMG_NULL)
+ {
+ return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+ }
+
+ PVR_ASSERT(psNewEntry->hParent == IMG_NULL);
+ PVR_ASSERT(hEntry == psPrevEntry->hNext);
+
+#if defined(DEBUG)
+ {
+ HANDLE_LIST *psParentList;
+
+ psParentList = GetHandleListFromHandleAndOffset(psBase,
+ hParent,
+ hParent,
+ uiParentOffset,
+ uiParentOffset);
+ PVR_ASSERT(psParentList && psParentList->hParent == hParent);
+ }
+#endif /* defined(DEBUG) */
+
+ psNewEntry->hPrev = psEntry->hPrev;
+ psEntry->hPrev = hNewEntry;
+
+ psNewEntry->hNext = hEntry;
+ psPrevEntry->hNext = hNewEntry;
+
+ psNewEntry->hParent = hParent;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function AdoptChild
+
+ @Description Assign a subhandle to a handle
+
+ @Input psParentData - pointer to handle structure of parent handle
+ psChildData - pointer to handle structure of child subhandle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(AdoptChild)
+#endif
+static INLINE
+PVRSRV_ERROR AdoptChild(PVRSRV_HANDLE_BASE *psBase,
+ HANDLE_DATA *psParentData,
+ HANDLE_DATA *psChildData)
+{
+ IMG_HANDLE hParent = psParentData->sChildren.hParent;
+
+ PVR_ASSERT(hParent == psParentData->hHandle);
+
+ return HandleListInsertBefore(psBase,
+ hParent,
+ &psParentData->sChildren,
+ offsetof(HANDLE_DATA, sChildren),
+ psChildData->hHandle,
+ &psChildData->sSiblings,
+ offsetof(HANDLE_DATA, sSiblings),
+ hParent);
+}
+
+/*!
+******************************************************************************
+
+ @Function HandleListRemove
+
+ @Description Remove a handle from a list
+
+ @Input hEntry - handle to be removed
+ psEntry - pointer to handle structure of item to be removed
+ uiEntryOffset - offset of list item struct in handle structure
+ uiParentOffset - offset to list head struct in handle structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListRemove)
+#endif
+static INLINE
+PVRSRV_ERROR HandleListRemove(PVRSRV_HANDLE_BASE *psBase,
+ IMG_HANDLE hEntry,
+ HANDLE_LIST *psEntry,
+ IMG_SIZE_T uiEntryOffset,
+ IMG_SIZE_T uiParentOffset)
+{
+ if (psBase == IMG_NULL || psEntry == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (!HandleListIsEmpty(hEntry, psEntry))
+ {
+ HANDLE_LIST *psPrev;
+ HANDLE_LIST *psNext;
+
+ psPrev = GetHandleListFromHandleAndOffset(psBase,
+ psEntry->hPrev,
+ psEntry->hParent,
+ uiParentOffset,
+ uiEntryOffset);
+ if (psPrev == IMG_NULL)
+ {
+ return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+ }
+
+ psNext = GetHandleListFromHandleAndOffset(psBase,
+ psEntry->hNext,
+ psEntry->hParent,
+ uiParentOffset,
+ uiEntryOffset);
+ if (psNext == IMG_NULL)
+ {
+ return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+ }
+
+ /*
+ * The list head is on the list, and we don't want to
+ * remove it.
+ */
+ PVR_ASSERT(psEntry->hParent != IMG_NULL);
+
+ psPrev->hNext = psEntry->hNext;
+ psNext->hPrev = psEntry->hPrev;
+
+ HandleListInit(hEntry, psEntry, IMG_NULL);
+ }
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function UnlinkFromParent
+
+ @Description Remove a subhandle from its parents list
+
+ @Input psHandleData - pointer to handle data structure of child subhandle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(UnlinkFromParent)
+#endif
+static INLINE
+PVRSRV_ERROR UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase,
+ HANDLE_DATA *psHandleData)
+{
+ return HandleListRemove(psBase,
+ psHandleData->hHandle,
+ &psHandleData->sSiblings,
+ offsetof(HANDLE_DATA, sSiblings),
+ offsetof(HANDLE_DATA, sChildren));
+}
+
+/*!
+******************************************************************************
+
+ @Function HandleListIterate
+
+ @Description Iterate over the items in a list
+
+ @Input psHead - pointer to list head
+ uiParentOffset - offset to list head struct in handle structure
+ uiEntryOffset - offset of list item struct in handle structure
+ pfnIterFunc - function to be called for each handle in the list
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIterate)
+#endif
+static INLINE
+PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase,
+ HANDLE_LIST *psHead,
+ IMG_SIZE_T uiParentOffset,
+ IMG_SIZE_T uiEntryOffset,
+ PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, IMG_HANDLE))
+{
+ IMG_HANDLE hHandle = psHead->hNext;
+ IMG_HANDLE hParent = psHead->hParent;
+ IMG_HANDLE hNext;
+
+ PVR_ASSERT(psHead->hParent != IMG_NULL);
+
+ /*
+ * Follow the next chain from the list head until we reach
+ * the list head again, which signifies the end of the list.
+ */
+ while (hHandle != hParent)
+ {
+ HANDLE_LIST *psEntry;
+ PVRSRV_ERROR eError;
+
+ psEntry = GetHandleListFromHandleAndOffset(psBase,
+ hHandle,
+ hParent,
+ uiParentOffset,
+ uiEntryOffset);
+ if (psEntry == IMG_NULL)
+ {
+ return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+ }
+
+ PVR_ASSERT(psEntry->hParent == psHead->hParent);
+
+ /*
+ * Get the next index now, in case the list item is
+ * modified by the iteration function.
+ */
+ hNext = psEntry->hNext;
+
+ eError = (*pfnIterFunc)(psBase, hHandle);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ hHandle = hNext;
+ }
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function IterateOverChildren
+
+ @Description Iterate over the subhandles of a parent handle
+
+ @Input psParentData - pointer to parent handle structure
+ pfnIterFunc - function to be called for each subhandle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(IterateOverChildren)
+#endif
+static INLINE
+PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase,
+ HANDLE_DATA *psParentData,
+ PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, IMG_HANDLE))
+{
+ return HandleListIterate(psBase,
+ &psParentData->sChildren,
+ offsetof(HANDLE_DATA, sChildren),
+ offsetof(HANDLE_DATA, sSiblings),
+ pfnIterFunc);
+}
+
+/*!
+******************************************************************************
+
+ @Function ParentIfPrivate
+
+ @Description Return the parent handle if the handle was allocated
+ with PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE, else return
+ IMG_NULL
+
+ @Input psHandleData - pointer to handle data structure
+
+ @Return Parent handle, or IMG_NULL
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentIfPrivate)
+#endif
+static INLINE
+IMG_HANDLE ParentIfPrivate(HANDLE_DATA *psHandleData)
+{
+ return TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ ParentHandle(psHandleData) : IMG_NULL;
+}
+
+/*!
+******************************************************************************
+
+ @Function InitKey
+
+ @Description Initialise a hash table key for the current process
+
+ @Input psBase - pointer to handle base structure
+ aKey - pointer to key
+ pvData - pointer to the resource the handle represents
+ eType - type of resource
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitKey)
+#endif
+static INLINE
+IMG_VOID InitKey(HAND_KEY aKey,
+ PVRSRV_HANDLE_BASE *psBase,
+ IMG_VOID *pvData,
+ PVRSRV_HANDLE_TYPE eType,
+ IMG_HANDLE hParent)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
+ aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
+ aKey[HAND_KEY_PARENT] = (IMG_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 data that was 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,
+ IMG_VOID **ppvData)
+{
+ HANDLE_DATA *psHandleData = IMG_NULL;
+ HANDLE_DATA *psReleasedHandleData;
+ PVRSRV_ERROR eError;
+
+ eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ PVR_ASSERT(psHandleData->ui32Refs>0);
+
+ psHandleData->ui32Refs--;
+ if (psHandleData->ui32Refs > 0)
+ {
+ /* Reference count still positive, only possible for shared handles */
+ PVR_ASSERT(TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_SHARED));
+ return PVRSRV_OK;
+ }
+ /* else reference count zero, time to clean up */
+
+ 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 != IMG_NULL);
+ PVR_ASSERT(hRemovedHandle == psHandleData->hHandle);
+ PVR_UNREFERENCED_PARAMETER(hRemovedHandle);
+ }
+
+ eError = UnlinkFromParent(psBase, psHandleData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeHandle: Error whilst unlinking from parent handle (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ return eError;
+ }
+
+ /* Free children */
+ eError = IterateOverChildren(psBase, psHandleData, FreeHandleWrapper);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeHandle: Error whilst freeing subhandles (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ return eError;
+ }
+
+ eError = gpsHandleFuncs->pfnReleaseHandle(psBase->psImplBase, psHandleData->hHandle, (IMG_VOID **)&psReleasedHandleData);
+ if (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, IMG_NULL);
+}
+
+/*!
+******************************************************************************
+
+ @Function FindHandle
+
+ @Description Find handle corresponding to a resource pointer
+
+ @Input psBase - pointer to handle base structure
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+
+ @Return the handle, or IMG_NULL if not found
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(FindHandle)
+#endif
+static INLINE
+IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_VOID *pvData,
+ PVRSRV_HANDLE_TYPE eType,
+ IMG_HANDLE hParent)
+{
+ HAND_KEY aKey;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+ return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+}
+
+/*!
+******************************************************************************
+
+ @Function AllocHandle
+
+ @Description Allocate a new handle
+
+ @Input phHandle - location for new handle
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+ hParent - parent handle or IMG_NULL
+
+ @Output phHandle - points to new handle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_HANDLE *phHandle,
+ IMG_VOID *pvData,
+ PVRSRV_HANDLE_TYPE eType,
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag,
+ IMG_HANDLE hParent)
+{
+ HANDLE_DATA *psNewHandleData;
+ IMG_HANDLE hHandle;
+ PVRSRV_ERROR eError;
+
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(psBase != IMG_NULL && psBase->psHashTab != IMG_NULL);
+ PVR_ASSERT(gpsHandleFuncs);
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+ /* Handle must not already exist */
+ PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL);
+ }
+
+ psNewHandleData = OSAllocZMem(sizeof(*psNewHandleData));
+ if (psNewHandleData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't allocate handle data"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ eError = gpsHandleFuncs->pfnAcquireHandle(psBase->psImplBase, &hHandle, psNewHandleData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Failed to acquire a handle"));
+ goto ErrorFreeHandleData;
+ }
+
+ /*
+ * If a data pointer can be associated with multiple handles, we
+ * don't put the handle in the hash table, as the data pointer
+ * may not map to a unique handle
+ */
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+ HAND_KEY aKey;
+
+ /* Initialise hash key */
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+ /* Put the new handle in the hash table */
+ if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
+ eError = PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE;
+ goto ErrorReleaseHandle;
+ }
+ }
+
+ psNewHandleData->hHandle = hHandle;
+ psNewHandleData->eType = eType;
+ psNewHandleData->eFlag = eFlag;
+ psNewHandleData->pvData = pvData;
+ psNewHandleData->ui32Refs = 1;
+
+ InitParentList(psNewHandleData);
+#if defined(DEBUG)
+ PVR_ASSERT(NoChildren(psNewHandleData));
+#endif
+
+ InitChildEntry(psNewHandleData);
+#if defined(DEBUG)
+ PVR_ASSERT(NoParent(psNewHandleData));
+#endif
+
+ /* Return the new handle to the client */
+ *phHandle = psNewHandleData->hHandle;
+
+ return PVRSRV_OK;
+
+ErrorReleaseHandle:
+ (IMG_VOID)gpsHandleFuncs->pfnReleaseHandle(psBase->psImplBase, hHandle, IMG_NULL);
+
+ErrorFreeHandleData:
+ OSFreeMem(psNewHandleData);
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocHandle
+
+ @Description Allocate a handle
+
+ @Input phHandle - location for new handle
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+
+ @Output phHandle - points to new handle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_HANDLE *phHandle,
+ IMG_VOID *pvData,
+ PVRSRV_HANDLE_TYPE eType,
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+ IMG_HANDLE hHandle;
+ PVRSRV_ERROR eError;
+
+ *phHandle = IMG_NULL;
+
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit_AllocHandle;
+ }
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+ /* See if there is already a handle for this data pointer */
+ hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
+ if (hHandle != IMG_NULL)
+ {
+ HANDLE_DATA *psHandleData = IMG_NULL;
+
+ eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAllocHandle: Lookup of existing handle failed (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto exit_AllocHandle;
+ }
+
+ /*
+ * If the client is willing to share a handle, and the
+ * existing handle is marked as shareable, return the
+ * existing handle.
+ */
+ if (TEST_FLAG(psHandleData->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
+ {
+ psHandleData->ui32Refs++;
+ *phHandle = hHandle;
+ eError = PVRSRV_OK;
+ goto exit_AllocHandle;
+ }
+ eError = PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+ goto exit_AllocHandle;
+ }
+ }
+
+ eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
+
+ exit_AllocHandle:
+ UnlockHandle();
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocSubHandle
+
+ @Description Allocate a subhandle
+
+ @Input phHandle - location for new subhandle
+ pvData - pointer to resource to be associated with the subhandle
+ eType - the type of resource
+ hParent - parent handle
+
+ @Output phHandle - points to new subhandle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_HANDLE *phHandle,
+ IMG_VOID *pvData,
+ PVRSRV_HANDLE_TYPE eType,
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag,
+ IMG_HANDLE hParent)
+{
+ HANDLE_DATA *psPHandleData = IMG_NULL;
+ HANDLE_DATA *psCHandleData = IMG_NULL;
+ IMG_HANDLE hParentKey;
+ IMG_HANDLE hHandle;
+ PVRSRV_ERROR eError;
+
+ *phHandle = IMG_NULL;
+
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err;
+ }
+
+ hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ? hParent : IMG_NULL;
+
+ /* Lookup the parent handle */
+ eError = GetHandleData(psBase, &psPHandleData, hParent, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Failed to get parent handle structure"));
+ goto err;
+ }
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+ /* See if there is already a handle for this data pointer */
+ hHandle = FindHandle(psBase, pvData, eType, hParentKey);
+ if (hHandle != IMG_NULL)
+ {
+ eError = GetHandleData(psBase, &psCHandleData, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
+ goto err;
+ }
+
+ PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(psCHandleData) == hParent);
+
+ /*
+ * If the client is willing to share a handle, the
+ * existing handle is marked as shareable, and the
+ * existing handle has the same parent, return the
+ * existing handle.
+ */
+ if (TEST_FLAG(psCHandleData->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) &&
+ ParentHandle(psCHandleData) == hParent)
+ {
+ psCHandleData->ui32Refs++;
+ *phHandle = hHandle;
+ eError = PVRSRV_OK;
+ goto err;
+ }
+ eError = PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+ goto err;
+ }
+ }
+
+ eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
+ if (eError != PVRSRV_OK)
+ {
+ goto err;
+ }
+
+ eError = GetHandleData(psBase, &psCHandleData, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Failed to get parent handle structure"));
+
+ /* If we were able to allocate the handle then there should be no reason why we
+ can't also get it's handle structure. Otherwise something has gone badly wrong. */
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ goto err;
+ }
+
+ /*
+ * Get the parent handle structure again, in case the handle
+ * structure has moved (depending on the implementation
+ * of AllocHandle).
+ */
+ eError = GetHandleData(psBase, &psPHandleData, hParent, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Failed to get parent handle structure"));
+
+ FreeHandle(psBase, hHandle, eType, IMG_NULL);
+ goto err;
+ }
+
+ eError = AdoptChild(psBase, psPHandleData, psCHandleData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Parent handle failed to adopt subhandle"));
+
+ FreeHandle(psBase, hHandle, eType, IMG_NULL);
+ goto err;
+ }
+
+ *phHandle = hHandle;
+
+ eError = PVRSRV_OK;
+
+ err:
+ UnlockHandle();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVFindHandle
+
+ @Description Find handle corresponding to a resource pointer
+
+ @Input phHandle - location for returned handle
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+
+ @Output phHandle - points to handle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_HANDLE *phHandle,
+ IMG_VOID *pvData,
+ PVRSRV_HANDLE_TYPE eType)
+{
+ IMG_HANDLE hHandle;
+ PVRSRV_ERROR eError;
+
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFindHandle: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err;
+ }
+
+ /* See if there is a handle for this data pointer */
+ hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
+ if (hHandle == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_HANDLE_NOT_FOUND;
+ goto err;
+ }
+
+ *phHandle = hHandle;
+
+ eError = PVRSRV_OK;
+
+ err:
+ UnlockHandle();
+ return eError;
+
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupHandleAnyType
+
+ @Description Lookup the data pointer and type corresponding to a handle
+
+ @Input ppvData - location to return data pointer
+ peType - location to return handle type
+ hHandle - handle from client
+
+ @Output ppvData - points to the data pointer
+ peType - points to handle type
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase,
+ IMG_PVOID *ppvData,
+ PVRSRV_HANDLE_TYPE *peType,
+ IMG_HANDLE hHandle)
+{
+ HANDLE_DATA *psHandleData = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err;
+ }
+
+ eError = GetHandleData(psBase, &psHandleData, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVLookupHandleAnyType: Error looking up handle (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ OSDumpStack();
+ goto err;
+ }
+
+ *ppvData = psHandleData->pvData;
+ *peType = psHandleData->eType;
+
+ eError = PVRSRV_OK;
+
+ err:
+ UnlockHandle();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupHandle
+
+ @Description Lookup the data pointer corresponding to a handle
+
+ @Input ppvData - location to return data pointer
+ hHandle - handle from client
+ eType - handle type
+
+ @Output ppvData - points to the data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_PVOID *ppvData,
+ IMG_HANDLE hHandle,
+ PVRSRV_HANDLE_TYPE eType)
+{
+ HANDLE_DATA *psHandleData = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err;
+ }
+
+ eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVLookupHandle: Error looking up handle (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ OSDumpStack();
+ goto err;
+ }
+
+ *ppvData = psHandleData->pvData;
+
+ eError = PVRSRV_OK;
+
+ err:
+ UnlockHandle();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupSubHandle
+
+ @Description Lookup the data pointer corresponding to a subhandle
+
+ @Input ppvData - location to return data pointer
+ hHandle - handle from client
+ eType - handle type
+ hAncestor - ancestor handle
+
+ @Output ppvData - points to the data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_PVOID *ppvData,
+ IMG_HANDLE hHandle,
+ PVRSRV_HANDLE_TYPE eType,
+ IMG_HANDLE hAncestor)
+{
+ HANDLE_DATA *psPHandleData = IMG_NULL;
+ HANDLE_DATA *psCHandleData = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err;
+ }
+
+ eError = GetHandleData(psBase, &psCHandleData, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVLookupSubHandle: Error looking up subhandle (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ OSDumpStack();
+ goto err;
+ }
+
+ /* Look for hAncestor among the handle's ancestors */
+ for (psPHandleData = psCHandleData; ParentHandle(psPHandleData) != hAncestor; )
+ {
+ eError = GetHandleData(psBase, &psPHandleData, ParentHandle(psPHandleData), PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
+ eError = PVRSRV_ERROR_INVALID_SUBHANDLE;
+ goto err;
+ }
+ }
+
+ *ppvData = psCHandleData->pvData;
+
+ eError = PVRSRV_OK;
+
+ err:
+ UnlockHandle();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetParentHandle
+
+ @Description Lookup the parent of a handle
+
+ @Input phParent - location for returning parent handle
+ hHandle - handle for which the parent handle is required
+ eType - handle type
+ hParent - parent handle
+
+ @Output *phParent - parent handle, or IMG_NULL if there is no parent
+
+ @Return Error code or PVRSRV_OK. Note that not having a parent is
+ not regarded as an error.
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_HANDLE *phParent,
+ IMG_HANDLE hHandle,
+ PVRSRV_HANDLE_TYPE eType)
+{
+ HANDLE_DATA *psHandleData = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err;
+ }
+
+ eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetParentHandle: Error looking up subhandle (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ OSDumpStack();
+ goto err;
+ }
+
+ *phParent = ParentHandle(psHandleData);
+
+ eError = PVRSRV_OK;
+
+ err:
+ UnlockHandle();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupAndReleaseHandle
+
+ @Description Lookup the data pointer corresponding to a handle
+
+ @Input ppvData - location to return data pointer
+ hHandle - handle from client
+ eType - handle type
+ eFlag - lookup flags
+
+ @Output ppvData - points to the data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_PVOID *ppvData,
+ IMG_HANDLE hHandle,
+ PVRSRV_HANDLE_TYPE eType)
+{
+ PVRSRV_ERROR eError;
+
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit_LookupAndReleaseHandle;
+ }
+
+ eError = FreeHandle(psBase, hHandle, eType, ppvData);
+
+ exit_LookupAndReleaseHandle:
+ UnlockHandle();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVReleaseHandle
+
+ @Description Release a handle that is no longer needed
+
+ @Input hHandle - handle from client
+ eType - handle type
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ IMG_HANDLE hHandle,
+ PVRSRV_HANDLE_TYPE eType)
+{
+
+ PVRSRV_ERROR eError;
+
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit_ReleaseHandle;
+ }
+
+ eError = FreeHandle(psBase, hHandle, eType, IMG_NULL);
+
+exit_ReleaseHandle:
+ UnlockHandle();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVPurgeHandles
+
+ @Description Purge handles for a given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Missing handle base"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit_PVRSRVPurgeHandles;
+ }
+
+ eError = gpsHandleFuncs->pfnPurgeHandles(psBase->psImplBase);
+
+ exit_PVRSRVPurgeHandles:
+ UnlockHandle();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocHandleBase
+
+ @Description Allocate a handle base structure for a process
+
+ @Input ppsBase - pointer to handle base structure pointer
+
+ @Output ppsBase - points to handle base structure pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+ PVRSRV_HANDLE_BASE *psBase;
+ PVRSRV_ERROR eError;
+
+ if (gpsHandleFuncs == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Handle management not initialised"));
+ return PVRSRV_ERROR_NOT_READY;
+ }
+
+ LockHandle();
+ if (ppsBase == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err;
+ }
+
+ psBase = OSAllocZMem(sizeof(*psBase));
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+
+ eError = gpsHandleFuncs->pfnCreateHandleBase(&psBase->psImplBase);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorFreeHandleBase;
+ }
+
+ psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE,
+ sizeof(HAND_KEY),
+ HASH_Func_Default,
+ HASH_Key_Comp_Default);
+ if (psBase->psHashTab == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table"));
+ eError = PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+ goto ErrorDestroyHandleBase;
+ }
+
+ *ppsBase = psBase;
+
+ UnlockHandle();
+ return PVRSRV_OK;
+
+ErrorDestroyHandleBase:
+ (IMG_VOID)gpsHandleFuncs->pfnDestroyHandleBase(psBase->psImplBase);
+
+ErrorFreeHandleBase:
+ OSFreeMem(psBase);
+
+err:
+ UnlockHandle();
+ return eError;
+}
+
+static PVRSRV_ERROR FreeHandleDataWrapper(IMG_HANDLE hHandle, IMG_VOID *pvData)
+{
+ PVRSRV_HANDLE_BASE *psBase = (PVRSRV_HANDLE_BASE *)pvData;
+ HANDLE_DATA *psHandleData = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleDataWrapper: Handle base missing"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = GetHandleData(psBase,
+ &psHandleData,
+ hHandle,
+ PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleDataWrapper: Couldn't get handle data for handle"));
+ 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 != IMG_NULL);
+ PVR_ASSERT(hRemovedHandle == psHandleData->hHandle);
+ PVR_UNREFERENCED_PARAMETER(hRemovedHandle);
+ }
+
+ OSFreeMem(psHandleData);
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVFreeHandleBase
+
+ @Description Free a handle base structure
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(gpsHandleFuncs);
+
+ LockHandle();
+ /* Make sure all handles have been freed before destroying the handle base */
+ eError = gpsHandleFuncs->pfnIterateOverHandles(psBase->psImplBase,
+ &FreeHandleDataWrapper,
+ (IMG_VOID *)psBase);
+ if (eError != PVRSRV_OK)
+ {
+ goto err;
+ }
+
+ if (psBase->psHashTab != IMG_NULL)
+ {
+ HASH_Delete(psBase->psHashTab);
+ }
+
+ eError = gpsHandleFuncs->pfnDestroyHandleBase(psBase->psImplBase);
+ if (eError != PVRSRV_OK)
+ {
+ goto err;
+ }
+
+ OSFreeMem(psBase);
+
+ eError = PVRSRV_OK;
+err:
+ UnlockHandle();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVHandleInit
+
+ @Description Initialise handle management
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
+ PVR_ASSERT(gpsHandleFuncs == IMG_NULL);
+
+ eError = OSLockCreate(&gHandleLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleInit: Creation of handle global lock failed (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto error;
+ }
+
+ eError = PVRSRVHandleGetFuncTable(&gpsHandleFuncs);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleInit: PVRSRVHandleGetFuncTable failed (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto error;
+ }
+
+ eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto error;
+ }
+
+ eError = gpsHandleFuncs->pfnEnableHandlePurging(gpsKernelHandleBase->psImplBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto error;
+ }
+
+ return PVRSRV_OK;
+
+error:
+ (IMG_VOID) PVRSRVHandleDeInit();
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVHandleDeInit
+
+ @Description De-initialise handle management
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (gpsHandleFuncs != IMG_NULL)
+ {
+ if (gpsKernelHandleBase != IMG_NULL)
+ {
+ eError = PVRSRVFreeHandleBase(gpsKernelHandleBase);
+ if (eError == PVRSRV_OK)
+ {
+ gpsKernelHandleBase = IMG_NULL;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleDeInit: FreeHandleBase failed (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ }
+ }
+
+ OSLockDestroy(gHandleLock);
+
+ if (eError == PVRSRV_OK)
+ {
+ gpsHandleFuncs = IMG_NULL;
+ }
+ }
+ else
+ {
+ /* If we don't have a handle function table we shouldn't have a handle base either */
+ PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
+ }
+
+ return eError;
+}
+#else
+/* disable warning about empty module */
+#ifdef _WIN32
+#pragma warning (disable:4206)
+#endif
+#endif /* #ifdef PVR_SECURE_HANDLES */
+
diff --git a/drivers/gpu/rogue/services/server/common/handle_generic.c b/drivers/gpu/rogue/services/server/common/handle_generic.c
new file mode 100644
index 000000000000..2d711e845bd6
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/handle_generic.c
@@ -0,0 +1,1018 @@
+/*************************************************************************/ /*!
+@File
+@Title Resource Handle Manager - Generic Back-end
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide generic resource handle management back-end
+@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(PVR_SECURE_HANDLES)
+
+#include <stddef.h>
+
+#include "handle_impl.h"
+#include "allocmem.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+
+
+/* Valid handles are never NULL. Therefore, this value should never be 0! */
+#define HANDLE_OFFSET_FROM_INDEX 1
+
+#if defined(DEBUG)
+#define HANDLE_BLOCK_SHIFT 2
+#else
+#define HANDLE_BLOCK_SHIFT 8
+#endif
+
+#define DIVIDE_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) >> HANDLE_BLOCK_SHIFT)
+#define MULTIPLY_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) << HANDLE_BLOCK_SHIFT)
+
+#define HANDLE_BLOCK_SIZE MULTIPLY_BY_BLOCK_SIZE(1)
+#define HANDLE_SUB_BLOCK_MASK (HANDLE_BLOCK_SIZE - 1)
+#define HANDLE_BLOCK_MASK (~(HANDLE_SUB_BLOCK_MASK))
+
+#define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+
+#define INDEX_TO_HANDLE(i) ((IMG_HANDLE)((IMG_UINTPTR_T)(i) + HANDLE_OFFSET_FROM_INDEX))
+#define HANDLE_TO_INDEX(h) ((IMG_UINT32)((IMG_UINTPTR_T)(h) - HANDLE_OFFSET_FROM_INDEX))
+
+#define INDEX_TO_BLOCK_INDEX(i) DIVIDE_BY_BLOCK_SIZE(i)
+#define BLOCK_INDEX_TO_INDEX(i) MULTIPLY_BY_BLOCK_SIZE(i)
+#define INDEX_TO_SUB_BLOCK_INDEX(i) ((i) & HANDLE_SUB_BLOCK_MASK)
+
+#define BLOCK_ARRAY_AND_INDEX_TO_HANDLE_BLOCK(psArray, i) (&((psArray)[INDEX_TO_BLOCK_INDEX(i)]))
+#define BASE_AND_INDEX_TO_HANDLE_BLOCK(psBase, i) BLOCK_ARRAY_AND_INDEX_TO_HANDLE_BLOCK((psBase)->psHandleBlockArray, i)
+#define BASE_TO_TOTAL_INDICES(psBase) (HANDLE_TO_INDEX((psBase)->ui32MaxHandleValue) + 1)
+
+#define INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, i) (BASE_AND_INDEX_TO_HANDLE_BLOCK(psBase, i)->ui32FreeHandCount)
+#define INDEX_TO_HANDLE_DATA(psBase, i) (BASE_AND_INDEX_TO_HANDLE_BLOCK(psBase, i)->psHandleDataArray + INDEX_TO_SUB_BLOCK_INDEX(i))
+
+#define ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(a) (HANDLE_BLOCK_MASK & (a))
+#define ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(a) ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE((a) + HANDLE_BLOCK_SIZE - 1)
+
+#define INDEX_MIN 0x0u
+#define INDEX_MAX (ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(0x7fffffffu) - 1)
+
+#define HANDLE_VALUE_MIN ((IMG_UINT32)(IMG_UINTPTR_T)INDEX_TO_HANDLE(INDEX_MIN))
+#define HANDLE_VALUE_MAX ((IMG_UINT32)(IMG_UINTPTR_T)INDEX_TO_HANDLE(INDEX_MAX))
+
+#define HANDLE_BLOCK_ARRAY_SIZE(uiNumHandles) DIVIDE_BY_BLOCK_SIZE(ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(uiNumHandles))
+
+#define HANDLE_DATA_TO_HANDLE(psHandleData) ((psHandleData)->hHandle)
+#define HANDLE_DATA_TO_INDEX(psHandleData) HANDLE_TO_INDEX(HANDLE_DATA_TO_HANDLE(psHandleData))
+
+#if defined(MIN)
+#undef MIN
+#endif
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+typedef struct _HANDLE_IMPL_DATA_
+{
+ /* Handle which represents this handle structure */
+ IMG_HANDLE hHandle;
+
+ /* Pointer to the data that the handle represents */
+ IMG_VOID *pvData;
+
+ /*
+ * When handles are on the free list, the value of the "next index
+ * plus one field" has the following meaning:
+ * zero - next handle is the one that follows this one,
+ * nonzero - the index of the next handle is the value minus one.
+ * This scheme means handle space can be initialised to all zeros.
+ *
+ * When this field is used to link together handles on a list
+ * other than the free list, zero indicates the end of the
+ * list, with nonzero the same as above.
+ */
+ IMG_UINT32 ui32NextIndexPlusOne;
+} HANDLE_IMPL_DATA;
+
+typedef struct _HANDLE_BLOCK_
+{
+ /* Pointer to an array of handle data structures */
+ HANDLE_IMPL_DATA *psHandleDataArray;
+
+ /* Number of free handle data structures in block */
+ IMG_UINT32 ui32FreeHandCount;
+} HANDLE_BLOCK;
+
+struct _HANDLE_IMPL_BASE_
+{
+ /* Pointer to array of handle block structures */
+ HANDLE_BLOCK *psHandleBlockArray;
+
+ /* Maximum handle value */
+ IMG_UINT32 ui32MaxHandleValue;
+
+ /* Total number of handles (this may include allocated but unused handles) */
+ IMG_UINT32 ui32TotalHandCount;
+
+ /* Number of free handles */
+ IMG_UINT32 ui32TotalFreeHandCount;
+
+ /* Purging enabled.
+ * If purging is enabled, the size of the table can be reduced
+ * by removing free space at the end of the table. To make
+ * purging more likely to succeed, handles are allocated as
+ * far to the front of the table as possible. The first free
+ * handle is found by a linear search from the start of the table,
+ * and so no free handle list management is done.
+ */
+ IMG_BOOL bPurgingEnabled;
+
+ /*
+ * If purging is not enabled, this is the array index of first free
+ * handle.
+ * If purging is enabled, this is the index to start searching for
+ * a free handle from. In this case it is usually zero, unless
+ * the handle array size has been increased due to lack of
+ * handles.
+ */
+ IMG_UINT32 ui32FirstFreeIndex;
+
+ /*
+ * Index of the last free index, plus one. Not used if purging
+ * is enabled.
+ */
+ IMG_UINT32 ui32LastFreeIndexPlusOne;
+};
+
+
+/*!
+******************************************************************************
+
+ @Function ReallocHandleBlockArray
+
+ @Description Reallocate the handle block array
+
+ @Input psBase - Pointer to handle base structure
+ ui32NewCount - The new total number of handles
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR ReallocHandleBlockArray(HANDLE_IMPL_BASE *psBase,
+ IMG_UINT32 ui32NewCount)
+{
+ HANDLE_BLOCK *psOldArray = psBase->psHandleBlockArray;
+ IMG_UINT32 ui32OldCount = psBase->ui32TotalHandCount;
+ HANDLE_BLOCK *psNewArray = IMG_NULL;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 ui32Index;
+
+ if (ui32NewCount == ui32OldCount)
+ {
+ return PVRSRV_OK;
+ }
+
+ if (ui32NewCount != 0 &&
+ !psBase->bPurgingEnabled &&
+ ui32NewCount < ui32OldCount)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
+ ((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
+ {
+ PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0);
+ PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0);
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32NewCount != 0)
+ {
+ /* Allocate new handle array */
+ psNewArray = OSAllocMem(HANDLE_BLOCK_ARRAY_SIZE(ui32NewCount) * sizeof(HANDLE_BLOCK));
+ if (psNewArray == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate new handle array", __FUNCTION__));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+
+ if (ui32OldCount != 0)
+ {
+ OSMemCopy(psNewArray, psOldArray, HANDLE_BLOCK_ARRAY_SIZE(MIN(ui32NewCount, ui32OldCount)) * sizeof(HANDLE_BLOCK));
+ }
+ }
+
+ /*
+ * If the new handle array is smaller than the old one, free
+ * unused handle data structure arrays
+ */
+ for (ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
+ {
+ HANDLE_BLOCK *psHandleBlock = BLOCK_ARRAY_AND_INDEX_TO_HANDLE_BLOCK(psOldArray, ui32Index);
+
+ OSFreeMem(psHandleBlock->psHandleDataArray);
+ }
+
+ /*
+ * If the new handle array is bigger than the old one, allocate
+ * new handle data structure arrays
+ */
+ for (ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+ {
+ /* PRQA S 0505 1 */ /* psNewArray is never NULL, see assert earlier */
+ HANDLE_BLOCK *psHandleBlock = BLOCK_ARRAY_AND_INDEX_TO_HANDLE_BLOCK(psNewArray, ui32Index);
+
+ psHandleBlock->psHandleDataArray = OSAllocMem(sizeof(HANDLE_IMPL_DATA) * HANDLE_BLOCK_SIZE);
+ if (psHandleBlock->psHandleDataArray != IMG_NULL)
+ {
+ IMG_UINT32 ui32SubIndex;
+
+ psHandleBlock->ui32FreeHandCount = HANDLE_BLOCK_SIZE;
+
+ for (ui32SubIndex = 0; ui32SubIndex < HANDLE_BLOCK_SIZE; ui32SubIndex++)
+ {
+ HANDLE_IMPL_DATA *psHandleData = psHandleBlock->psHandleDataArray + ui32SubIndex;
+
+ psHandleData->hHandle = INDEX_TO_HANDLE(ui32SubIndex + ui32Index);
+ psHandleData->pvData = IMG_NULL;
+ psHandleData->ui32NextIndexPlusOne = 0;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate handle structures", __FUNCTION__));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ if (eError != PVRSRV_OK)
+ {
+ goto error;
+ }
+
+#if defined(DEBUG_MAX_HANDLE_COUNT)
+ /* Force handle failure to test error exit code */
+ if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Max handle count (%u) reached", __FUNCTION__, DEBUG_MAX_HANDLE_COUNT));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+#endif /* defined(DEBUG_MAX_HANDLE_COUNT) */
+
+ if (psOldArray != IMG_NULL)
+ {
+ /* Free old handle array */
+ OSFreeMem(psOldArray);
+ }
+
+ psBase->psHandleBlockArray = psNewArray;
+ psBase->ui32TotalHandCount = ui32NewCount;
+
+ if (ui32NewCount > ui32OldCount)
+ {
+ /* Check for wraparound */
+ PVR_ASSERT(psBase->ui32TotalFreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32TotalFreeHandCount);
+
+ /* PRQA S 3382 1 */ /* ui32NewCount always > ui32OldCount */
+ psBase->ui32TotalFreeHandCount += (ui32NewCount - ui32OldCount);
+
+ /*
+ * If purging is enabled, there is no free handle list
+ * management, but as an optimization, when allocating
+ * new handles, we use ui32FirstFreeIndex to point to
+ * the first handle in a newly allocated block.
+ */
+ if (psBase->ui32FirstFreeIndex == 0)
+ {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+ psBase->ui32FirstFreeIndex = ui32OldCount;
+ }
+ else
+ {
+ if (!psBase->bPurgingEnabled)
+ {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+ PVR_ASSERT(INDEX_TO_HANDLE_DATA(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+
+ INDEX_TO_HANDLE_DATA(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
+ }
+ }
+
+ if (!psBase->bPurgingEnabled)
+ {
+ psBase->ui32LastFreeIndexPlusOne = ui32NewCount;
+ }
+ }
+ else
+ {
+ if (ui32NewCount == 0)
+ {
+ psBase->ui32TotalFreeHandCount = 0;
+ psBase->ui32FirstFreeIndex = 0;
+ psBase->ui32LastFreeIndexPlusOne = 0;
+ }
+ else
+ {
+ PVR_ASSERT(psBase->bPurgingEnabled);
+ PVR_ASSERT(psBase->ui32FirstFreeIndex <= ui32NewCount);
+ PVR_ASSERT(psBase->ui32TotalFreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32TotalFreeHandCount);
+
+ /* PRQA S 3382 1 */ /* ui32OldCount always >= ui32NewCount */
+ psBase->ui32TotalFreeHandCount -= (ui32OldCount - ui32NewCount);
+ }
+ }
+
+ PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount);
+
+ return PVRSRV_OK;
+
+error:
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ if (psNewArray != IMG_NULL)
+ {
+ /* Free any new handle structures that were allocated */
+ for (ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+ {
+ HANDLE_BLOCK *psHandleBlock = BLOCK_ARRAY_AND_INDEX_TO_HANDLE_BLOCK(psNewArray, ui32Index);
+ if (psHandleBlock->psHandleDataArray != IMG_NULL)
+ {
+ OSFreeMem(psHandleBlock->psHandleDataArray);
+ }
+ }
+
+ /* Free new handle array */
+ OSFreeMem(psNewArray);
+ }
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function IncreaseHandleArraySize
+
+ @Description Allocate some more free handles
+
+ @Input psBase - pointer to handle base structure
+ ui32Delta - number of new handles required
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR IncreaseHandleArraySize(HANDLE_IMPL_BASE *psBase,
+ IMG_UINT32 ui32Delta)
+{
+ IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta);
+ IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
+ IMG_UINT32 ui32TotalIndices = BASE_TO_TOTAL_INDICES(psBase);
+
+ PVR_ASSERT(ui32Delta != 0);
+
+ /* Check new count against max handle array size and check for wrap around */
+ if (ui32NewTotalHandCount > ui32TotalIndices || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
+ {
+ ui32NewTotalHandCount = ui32TotalIndices;
+
+ ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
+
+ if (ui32DeltaAdjusted < ui32Delta)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Maximum handle limit reached (%u)",
+ __FUNCTION__, psBase->ui32MaxHandleValue));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
+
+ /* Realloc handle pointer array */
+ return ReallocHandleBlockArray(psBase, ui32NewTotalHandCount);
+}
+
+/*!
+******************************************************************************
+
+ @Function EnsureFreeHandles
+
+ @Description Ensure there are enough free handles
+
+ @Input psBase - Pointer to handle base structure
+ ui32Free - Number of free handles required
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR EnsureFreeHandles(HANDLE_IMPL_BASE *psBase,
+ IMG_UINT32 ui32Free)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (ui32Free > psBase->ui32TotalFreeHandCount)
+ {
+ IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32TotalFreeHandCount;
+
+ eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate %u handles to ensure %u free "
+ "handles (IncreaseHandleArraySize failed with error %s)",
+ __FUNCTION__, ui32FreeHandDelta, ui32Free, PVRSRVGetErrorStringKM(eError)));
+ }
+ }
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function AcquireHandle
+
+ @Description Acquire a new handle
+
+ @Input psBase - Pointer to handle base structure
+ phHandle - Points to a handle pointer
+ pvData - Pointer to resource to be associated with the handle
+
+ @Output phHandle - Points to a handle pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR AcquireHandle(HANDLE_IMPL_BASE *psBase,
+ IMG_HANDLE *phHandle,
+ IMG_VOID *pvData)
+{
+ IMG_UINT32 ui32NewIndex = BASE_TO_TOTAL_INDICES(psBase);
+ HANDLE_IMPL_DATA *psNewHandleData = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psBase != IMG_NULL);
+ PVR_ASSERT(phHandle != IMG_NULL);
+ PVR_ASSERT(pvData != IMG_NULL);
+
+ /* Ensure there is a free handle */
+ eError = EnsureFreeHandles(psBase, 1);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: EnsureFreeHandles failed (%s)",
+ __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+ return eError;
+ }
+ PVR_ASSERT(psBase->ui32TotalFreeHandCount != 0);
+
+ if (!psBase->bPurgingEnabled)
+ {
+ /* Array index of first free handle */
+ ui32NewIndex = psBase->ui32FirstFreeIndex;
+
+ /* Get handle array entry */
+ psNewHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32NewIndex);
+ }
+ else
+ {
+ IMG_UINT32 ui32BlockedIndex;
+
+ /*
+ * If purging is enabled, we always try to allocate handles
+ * at the front of the array, to increase the chances that
+ * the size of the handle array can be reduced by a purge.
+ * No linked list of free handles is kept; we search for
+ * free handles as required.
+ */
+
+ /*
+ * ui32FirstFreeIndex should only be set when a new batch of
+ * handle structures is allocated, and should always be a
+ * multiple of the block size.
+ */
+ PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0);
+
+ for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+ {
+ HANDLE_BLOCK *psHandleBlock = BASE_AND_INDEX_TO_HANDLE_BLOCK(psBase, ui32BlockedIndex);
+
+ if (psHandleBlock->ui32FreeHandCount == 0)
+ {
+ continue;
+ }
+
+ for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++)
+ {
+ psNewHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32NewIndex);
+ if (psNewHandleData->pvData == IMG_NULL)
+ {
+ break;
+ }
+ }
+ }
+ psBase->ui32FirstFreeIndex = 0;
+ PVR_ASSERT(INDEX_IS_VALID(psBase, ui32NewIndex));
+ }
+ PVR_ASSERT(psNewHandleData != IMG_NULL);
+
+ psBase->ui32TotalFreeHandCount--;
+
+ PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE);
+ PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex) > 0);
+
+ INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex)--;
+
+ /* No free list management if purging is enabled */
+ if (!psBase->bPurgingEnabled)
+ {
+ /* Check whether the last free handle has been allocated */
+ if (psBase->ui32TotalFreeHandCount == 0)
+ {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
+
+ psBase->ui32LastFreeIndexPlusOne = 0;
+ psBase->ui32FirstFreeIndex = 0;
+ }
+ else
+ {
+ /*
+ * Update the first free handle index.
+ * If the "next free index plus one" field in the new
+ * handle structure is zero, the next free index is
+ * the index of the new handle plus one. This
+ * convention has been adopted to simplify the
+ * initialisation of freshly allocated handle
+ * space.
+ */
+ if (psNewHandleData->ui32NextIndexPlusOne == 0)
+ {
+ psBase->ui32FirstFreeIndex = ui32NewIndex + 1;
+ }
+ else
+ {
+ psBase->ui32FirstFreeIndex = psNewHandleData->ui32NextIndexPlusOne - 1;
+ }
+ }
+ }
+
+ PVR_ASSERT(HANDLE_DATA_TO_HANDLE(psNewHandleData) == INDEX_TO_HANDLE(ui32NewIndex));
+
+ psNewHandleData->pvData = pvData;
+ psNewHandleData->ui32NextIndexPlusOne = 0;
+
+ /* Return the new handle to the client */
+ *phHandle = INDEX_TO_HANDLE(ui32NewIndex);
+
+#if defined(DEBUG_HANDLEALLOC_KM)
+ PVR_DPF((PVR_DBG_MESSAGE, "Handle acquire base %p hdl %p", psBase, *phHandle));
+#endif
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function ReleaseHandle
+
+ @Description Release a handle that is no longer needed.
+
+ @Input psBase - Pointer to handle base structure
+ hHandle - Handle to release
+ ppvData - Points to a void data pointer
+
+ @Output ppvData - Points to a void data pointer
+
+ @Return PVRSRV_OK or PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR ReleaseHandle(HANDLE_IMPL_BASE *psBase,
+ IMG_HANDLE hHandle,
+ IMG_VOID **ppvData)
+{
+ IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
+ HANDLE_IMPL_DATA *psHandleData;
+ IMG_VOID *pvData;
+
+ PVR_ASSERT(psBase);
+
+ /* Check handle index is in range */
+ if (!INDEX_IS_VALID(psBase, ui32Index))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Handle index out of range (%u >= %u)",
+ __FUNCTION__, ui32Index, psBase->ui32TotalHandCount));
+ return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+ }
+
+ psHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32Index);
+
+ pvData = psHandleData->pvData;
+ psHandleData->pvData = IMG_NULL;
+
+ /* No free list management if purging is enabled */
+ if (!psBase->bPurgingEnabled)
+ {
+ if (psBase->ui32TotalFreeHandCount == 0)
+ {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+ psBase->ui32FirstFreeIndex = ui32Index;
+ }
+ else
+ {
+ /*
+ * Put the handle pointer on the end of the the free
+ * handle pointer linked list.
+ */
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+ PVR_ASSERT(INDEX_TO_HANDLE_DATA(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+ INDEX_TO_HANDLE_DATA(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1;
+ }
+
+ PVR_ASSERT(psHandleData->ui32NextIndexPlusOne == 0);
+
+ /* Update the end of the free handle linked list */
+ psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
+ }
+
+ psBase->ui32TotalFreeHandCount++;
+ INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32Index)++;
+
+ PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE);
+
+#if defined(DEBUG)
+ {
+ IMG_UINT32 ui32BlockedIndex;
+ IMG_UINT32 ui32TotalFreeHandCount = 0;
+
+ for (ui32BlockedIndex = 0; ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+ {
+ ui32TotalFreeHandCount += INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32BlockedIndex);
+ }
+
+ PVR_ASSERT(ui32TotalFreeHandCount == psBase->ui32TotalFreeHandCount);
+ }
+#endif /* defined(DEBUG) */
+
+ if (ppvData)
+ {
+ *ppvData = pvData;
+ }
+
+#if defined(DEBUG_HANDLEALLOC_KM)
+ PVR_DPF((PVR_DBG_MESSAGE, "Handle release base %p hdl %p", psBase, hHandle));
+#endif
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function GetHandleData
+
+ @Description Get the data associated with the given handle
+
+ @Input psBase - Pointer to handle base structure
+ hHandle - Handle from which data should be retrieved
+ ppvData - Points to a void data pointer
+
+ @Output ppvData - Points to a void data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR GetHandleData(HANDLE_IMPL_BASE *psBase,
+ IMG_HANDLE hHandle,
+ IMG_VOID **ppvData)
+{
+ IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
+ HANDLE_IMPL_DATA *psHandleData;
+
+ PVR_ASSERT(psBase);
+ PVR_ASSERT(ppvData);
+
+ /* Check handle index is in range */
+ if (!INDEX_IS_VALID(psBase, ui32Index))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Handle index out of range (%u >= %u)",
+ __FUNCTION__, ui32Index, psBase->ui32TotalHandCount));
+ OSDumpStack();
+ return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+ }
+
+ psHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32Index);
+ if (psHandleData == IMG_NULL || psHandleData->pvData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
+ }
+
+ *ppvData = psHandleData->pvData;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR IterateOverHandles(HANDLE_IMPL_BASE *psBase, PFN_HANDLE_ITER pfnHandleIter, IMG_VOID *pvHandleIterData)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 i;
+
+ PVR_ASSERT(psBase);
+ PVR_ASSERT(pfnHandleIter);
+
+ if (psBase->ui32TotalFreeHandCount == psBase->ui32TotalHandCount)
+ {
+ return PVRSRV_OK;
+ }
+
+ for (i = 0; i < psBase->ui32TotalHandCount; i++)
+ {
+ HANDLE_IMPL_DATA *psHandleData = INDEX_TO_HANDLE_DATA(psBase, i);
+
+ if (psHandleData->pvData != IMG_NULL)
+ {
+ eError = pfnHandleIter(HANDLE_DATA_TO_HANDLE(psHandleData), pvHandleIterData);
+ if (eError != PVRSRV_OK)
+ {
+ break;
+ }
+
+ if (psBase->ui32TotalFreeHandCount == psBase->ui32TotalHandCount)
+ {
+ break;
+ }
+ }
+ }
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function EnableHandlePurging
+
+ @Description Enable purging for a given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR EnableHandlePurging(HANDLE_IMPL_BASE *psBase)
+{
+ PVR_ASSERT(psBase);
+
+ if (psBase->bPurgingEnabled)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Purging already enabled", __FUNCTION__));
+ return PVRSRV_OK;
+ }
+
+ /* Purging can only be enabled if no handles have been allocated */
+ if (psBase->ui32TotalHandCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Handles have already been allocated", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBase->bPurgingEnabled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PurgeHandles
+
+ @Description Purge handles for a given handle base
+
+ @Input psBase - Pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR PurgeHandles(HANDLE_IMPL_BASE *psBase)
+{
+ IMG_UINT32 ui32BlockIndex;
+ IMG_UINT32 ui32NewHandCount;
+
+ PVR_ASSERT(psBase);
+
+ if (!psBase->bPurgingEnabled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Purging not enabled for this handle base", __FUNCTION__));
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+
+ PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0);
+
+ for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--)
+ {
+ if (psBase->psHandleBlockArray[ui32BlockIndex - 1].ui32FreeHandCount != HANDLE_BLOCK_SIZE)
+ {
+ break;
+ }
+ }
+ ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex);
+
+ /* Check for a suitable decrease in the handle count */
+ if (ui32NewHandCount <= (psBase->ui32TotalHandCount / 2))
+ {
+ return ReallocHandleBlockArray(psBase, ui32NewHandCount);
+ }
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function CreateHandleBase
+
+ @Description Create a handle base structure
+
+ @Input ppsBase - pointer to handle base structure pointer
+
+ @Output ppsBase - points to handle base structure pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR CreateHandleBase(HANDLE_IMPL_BASE **ppsBase)
+{
+ HANDLE_IMPL_BASE *psBase;
+
+ PVR_ASSERT(ppsBase);
+
+ psBase = OSAllocZMem(sizeof(*psBase));
+ if (psBase == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate generic handle base", __FUNCTION__));
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psBase->psHandleBlockArray = IMG_NULL;
+ psBase->ui32MaxHandleValue = HANDLE_VALUE_MAX;
+ psBase->bPurgingEnabled = IMG_FALSE;
+
+ *ppsBase = psBase;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function DestroyHandleBase
+
+ @Description Destroy a handle base structure
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR DestroyHandleBase(HANDLE_IMPL_BASE *psBase)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psBase);
+
+ if (psBase->ui32TotalHandCount != psBase->ui32TotalFreeHandCount)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Handles still exist (%u found)",
+ __FUNCTION__,
+ psBase->ui32TotalHandCount - psBase->ui32TotalFreeHandCount));
+
+#if defined(DEBUG_HANDLEALLOC_INFO_KM)
+ {
+ IMG_UINT32 i;
+
+ for (i = 0; i < psBase->ui32TotalHandCount; i++)
+ {
+ HANDLE_IMPL_DATA *psHandleData = INDEX_TO_HANDLE_DATA(psBase, i);
+
+ if (psHandleData->pvData != IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%d: handle[%p] data[%p] still allocated",
+ i, psHandleData->hHandle, psHandleData->pvData));
+
+ }
+ }
+ }
+#endif /* DEBUG_HANDLEALLOC_INFO_KM */
+
+ }
+
+ eError = ReallocHandleBlockArray(psBase, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't free handle array (%s)",
+ __FUNCTION__,
+ PVRSRVGetErrorStringKM(eError)));
+
+ return eError;
+ }
+
+ OSFreeMem(psBase);
+
+ return PVRSRV_OK;
+}
+
+
+static const HANDLE_IMPL_FUNCTAB g_sHandleFuncTab =
+{
+ /* pfnAcquireHandle */
+ &AcquireHandle,
+
+ /* pfnReleaseHandle */
+ &ReleaseHandle,
+
+ /* pfnGetHandleData */
+ &GetHandleData,
+
+ /* pfnIterateOverHandles */
+ &IterateOverHandles,
+
+ /* pfnEnableHandlePurging */
+ &EnableHandlePurging,
+
+ /* pfnPurgeHandles */
+ &PurgeHandles,
+
+ /* pfnCreateHandleBase */
+ &CreateHandleBase,
+
+ /* pfnDestroyHandleBase */
+ &DestroyHandleBase
+};
+
+PVRSRV_ERROR PVRSRVHandleGetFuncTable(HANDLE_IMPL_FUNCTAB const **ppsFuncs)
+{
+ static IMG_BOOL bAcquired = IMG_FALSE;
+
+ if (bAcquired)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Function table already acquired",
+ __FUNCTION__));
+ return PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
+ }
+
+ if (ppsFuncs == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *ppsFuncs = &g_sHandleFuncTab;
+
+ bAcquired = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+#else
+/* Disable warning about an empty file */
+#if defined(_WIN32)
+#pragma warning (disable:4206)
+#endif
+#endif /* defined(PVR_SECURE_HANDLES) */
+
diff --git a/drivers/gpu/rogue/services/server/common/lists.c b/drivers/gpu/rogue/services/server/common/lists.c
new file mode 100644
index 000000000000..b106d16ce00f
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/lists.c
@@ -0,0 +1,135 @@
+/*************************************************************************/ /*!
+@File
+@Title Linked list shared functions implementation.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implementation of the list iterators for types shared among
+ more than one file in the services code.
+@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 "lists.h"
+
+/*===================================================================
+ LIST ITERATOR FUNCTIONS USED IN MORE THAN ONE FILE (those used just
+ once are implemented locally).
+ ===================================================================*/
+
+IMPLEMENT_LIST_ANY(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_INSERT(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_REMOVE(PVRSRV_DEVICE_NODE)
+
+IMPLEMENT_LIST_ANY_VA(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+
+
+/*===================================================================
+ BELOW ARE IMPLEMENTED SOME COMMON CALLBACKS USED IN DIFFERENT FILES
+ ===================================================================*/
+
+
+/*************************************************************************/ /*!
+@Function MatchDeviceKM_AnyVaCb
+@Description Matchs a device node with an id and optionally a class.
+@Input psDeviceNode Pointer to the device node.
+@Input va Variable argument list, with te following values:
+ ui32DevIndex Index of de device to match.
+ bIgnoreClass Flag indicating if there's
+ no need to check the device class.
+ eDevClass Device class, ONLY present if
+ bIgnoreClass was IMG_FALSE.
+@Return The pointer to the device node if it matchs, IMG_NULL
+ otherwise.
+*/ /**************************************************************************/
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
+{
+ IMG_UINT32 ui32DevIndex;
+ IMG_BOOL bIgnoreClass;
+ PVRSRV_DEVICE_CLASS eDevClass;
+
+ ui32DevIndex = va_arg(va, IMG_UINT32);
+ bIgnoreClass = va_arg(va, IMG_BOOL);
+ if (!bIgnoreClass)
+ {
+ eDevClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+ }
+ else
+ {
+ /*this value will never be used, since the short circuit evaluation
+ of the first clause will stop because bIgnoreClass is true, but the
+ compiler complains if it's not initialized.*/
+ eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
+ }
+
+ if ((bIgnoreClass || psDeviceNode->sDevId.eDeviceClass == eDevClass) &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
+ {
+ return psDeviceNode;
+ }
+ return IMG_NULL;
+}
+
+/*!
+******************************************************************************
+@Function MatchPowerDeviceIndex_AnyVaCb
+@Description Matches a power device with its device index.
+@Input va Variable argument list
+ ui32DeviceIndex Device index
+@Return The pointer to the device it matched, IMG_NULL otherwise.
+******************************************************************************/
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
+{
+ IMG_UINT32 ui32DeviceIndex;
+
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+
+ if (psPowerDev->ui32DeviceIndex == ui32DeviceIndex)
+ {
+ return psPowerDev;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
diff --git a/drivers/gpu/rogue/services/server/common/mmu_common.c b/drivers/gpu/rogue/services/server/common/mmu_common.c
new file mode 100644
index 000000000000..f4bf65d2f62c
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/mmu_common.c
@@ -0,0 +1,2895 @@
+/*************************************************************************/ /*!
+@File
+@Title Common MMU Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements basic low level control of MMU.
+@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 "devicemem_server_utils.h"
+
+/* Our own interface */
+#include "mmu_common.h"
+
+/*
+Interfaces to other modules:
+
+Let's keep this graph up-to-date:
+
+ +-----------+
+ | devicemem |
+ +-----------+
+ |
+ +============+
+ | mmu_common |
+ +============+
+ |
+ +-----------------+
+ | |
+ +---------+ +----------+
+ | pmr | | device |
+ +---------+ +----------+
+*/
+
+#include "img_types.h"
+#include "osfunc.h"
+#include "allocmem.h"
+#if defined(PDUMP)
+#include "pdump_km.h"
+#endif
+#include "pmr.h"
+/* include/ */
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv.h"
+
+// #define MMU_OBJECT_REFCOUNT_DEBUGING 1
+#if defined (MMU_OBJECT_REFCOUNT_DEBUGING)
+#define MMU_OBJ_DBG(x) PVR_DPF(x);
+#else
+#define MMU_OBJ_DBG(x)
+#endif
+
+typedef IMG_UINT32 MMU_FLAGS_T;
+
+typedef enum _MMU_MOD_
+{
+ MMU_MOD_UNKNOWN = 0,
+ MMU_MOD_MAP,
+ MMU_MOD_UNMAP,
+} MMU_MOD;
+
+#if defined(SUPPORT_MMU_MODIFICATION_LOGGING)
+#define MMU_MODIFICATION_HISTORY 10
+#define MMU_MODIFICATION_MAX_ENTRIES 1024
+typedef struct _MMU_MOD_INFO_
+{
+ IMG_UINT32 ui32NextEntry;
+ MMU_MOD eModificationHistory[MMU_MODIFICATION_HISTORY];
+ IMG_UINT64 ui64Value[MMU_MODIFICATION_HISTORY];
+} MMU_MOD_INFO;
+#endif
+/*!
+ All physical allocations and frees are relative to this context, so
+ we would get all the allocations of PCs, PDs, and PTs from the same
+ RA.
+
+ We have one per MMU context in case we have mixed UMA/LMA devices
+ within the same system.
+*/
+typedef struct _MMU_PHYSMEM_CONTEXT_
+{
+ /*! Parent device node */
+ PVRSRV_DEVICE_NODE *psDevNode;
+
+ /*! Refcount so we know when to free up the arena */
+ IMG_UINT32 uiNumAllocations;
+
+ /*! Arena from which physical memory is derived */
+ RA_ARENA *psPhysMemRA;
+ /*! Arena name */
+ IMG_CHAR *pszPhysMemRAName;
+ /*! Size of arena name string */
+ IMG_SIZE_T uiPhysMemRANameAllocSize;
+
+} MMU_PHYSMEM_CONTEXT;
+
+/*!
+ Mapping structure for MMU memory allocation
+*/
+typedef struct _MMU_MEMORY_MAPPING_
+{
+ /*! Physmem context to allocate from */
+ MMU_PHYSMEM_CONTEXT *psContext;
+ /*! OS/system Handle for this allocation */
+ Px_HANDLE sMemHandle;
+ /*! CPU virtual address of this allocation */
+ IMG_VOID *pvCpuVAddr;
+ /*! Device physical address of this allocation */
+ IMG_DEV_PHYADDR sDevPAddr;
+ /*! Size of this allocation */
+ IMG_SIZE_T uiSize;
+ /*! Number of current mappings of this allocation */
+ IMG_UINT32 uiCpuVAddrRefCount;
+} MMU_MEMORY_MAPPING;
+
+/*!
+ Memory descriptor for MMU objects. There can be more then one memory
+ descriptor per MMU memory allocation.
+*/
+typedef struct _MMU_MEMORY_DESC_
+{
+ /* NB: bValid is set if this descriptor describes physical
+ memory. This allows "empty" descriptors to exist, such that we
+ can allocate them in batches. */
+ /*! Does this MMU object have physical backing */
+ IMG_BOOL bValid;
+ /*! Device Physical address of physical backing */
+ IMG_DEV_PHYADDR sDevPAddr;
+ /*! CPU virtual address of physical backing */
+ IMG_VOID *pvCpuVAddr;
+ /*! Mapping data for this MMU object */
+ MMU_MEMORY_MAPPING *psMapping;
+} MMU_MEMORY_DESC;
+
+/*!
+ MMU levelx structure. This is generic and is used
+ for all levels (PC, PD, PT).
+*/
+typedef struct _MMU_Levelx_INFO_
+{
+ /*! The Number of entries in this level */
+ IMG_UINT32 ui32NumOfEntries;
+
+ /*! Number of times this level has been reference. Note: For Level1 (PTE)
+ we still take/drop the reference when setting up the page tables rather
+ then at map/unmap time as this simplifies things */
+ IMG_UINT32 ui32RefCount;
+
+ /*! MemDesc for this level */
+ MMU_MEMORY_DESC sMemDesc;
+
+#if defined(SUPPORT_MMU_MODIFICATION_LOGGING)
+ MMU_MOD_INFO asModifications[MMU_MODIFICATION_MAX_ENTRIES];
+#endif
+
+ /*! Array of infos for the next level. Must be last member in structure */
+ struct _MMU_Levelx_INFO_ *apsNextLevel[1];
+} MMU_Levelx_INFO;
+
+/*!
+ MMU context structure
+*/
+struct _MMU_CONTEXT_
+{
+ /*! Parent device node */
+ PVRSRV_DEVICE_NODE *psDevNode;
+
+ MMU_DEVICEATTRIBS *psDevAttrs;
+
+ /*! For allocation and deallocation of the physical memory where
+ the pagetables live */
+ struct _MMU_PHYSMEM_CONTEXT_ *psPhysMemCtx;
+
+#if defined(PDUMP)
+ /*! PDump context ID (required for PDump commands with virtual addresses) */
+ IMG_UINT32 uiPDumpContextID;
+
+ /*! The refcount of the PDump context ID */
+ IMG_UINT32 ui32PDumpContextIDRefCount;
+#endif
+
+ /*! Data that is passed back during device specific callbacks */
+ IMG_HANDLE hDevData;
+
+ /*! Base level info structure. Must be last member in structure */
+ MMU_Levelx_INFO sBaseLevelInfo;
+};
+
+/* useful macros */
+/* units represented in a bitfield */
+#define UNITS_IN_BITFIELD(Mask, Shift) ((Mask >> Shift) + 1)
+
+#define MMU_BAD_PHYS_ADDR 0xbadbad00badULL
+static const IMG_DEV_PHYADDR gsBadDevPhyAddr = {MMU_BAD_PHYS_ADDR};
+
+#if defined(DEBUG)
+static IMG_UINT32 FloorLog2(IMG_UINT64 ui64Val)
+{
+ IMG_UINT32 ui32Ret = 0;
+
+ while (ui64Val >>= 1)
+ {
+ ui32Ret++;
+ }
+
+ return ui32Ret;
+}
+#endif
+
+/*****************************************************************************
+ * Utility functions *
+ *****************************************************************************/
+
+/*************************************************************************/ /*!
+@Function _CalcPCEIdx
+
+@Description Calculate the page catalogue index
+
+@Input sDevVAddr Device virtual address
+
+@Input psDevVAddrConfig Configuration of the virtual address
+
+@Input bRoundUp Round up the index
+
+@Return The page catalogue index
+*/
+/*****************************************************************************/
+static IMG_UINT32 _CalcPCEIdx(IMG_DEV_VIRTADDR sDevVAddr,
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig,
+ IMG_BOOL bRoundUp)
+{
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_UINT32 ui32RetVal;
+
+ sTmpDevVAddr = sDevVAddr;
+
+ if (bRoundUp)
+ {
+ sTmpDevVAddr.uiAddr --;
+ }
+ ui32RetVal = (IMG_UINT32) ((sTmpDevVAddr.uiAddr & psDevVAddrConfig->uiPCIndexMask)
+ >> psDevVAddrConfig->uiPCIndexShift);
+
+ if (bRoundUp)
+ {
+ ui32RetVal ++;
+ }
+
+ return ui32RetVal;
+}
+
+
+/*************************************************************************/ /*!
+@Function _CalcPCEIdx
+
+@Description Calculate the page directory index
+
+@Input sDevVAddr Device virtual address
+
+@Input psDevVAddrConfig Configuration of the virtual address
+
+@Input bRoundUp Round up the index
+
+@Return The page directory index
+*/
+/*****************************************************************************/
+static IMG_UINT32 _CalcPDEIdx(IMG_DEV_VIRTADDR sDevVAddr,
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig,
+ IMG_BOOL bRoundUp)
+{
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_UINT32 ui32RetVal;
+
+ sTmpDevVAddr = sDevVAddr;
+
+ if (bRoundUp)
+ {
+ sTmpDevVAddr.uiAddr --;
+ }
+ ui32RetVal = (IMG_UINT32) ((sTmpDevVAddr.uiAddr & psDevVAddrConfig->uiPDIndexMask)
+ >> psDevVAddrConfig->uiPDIndexShift);
+
+ if (bRoundUp)
+ {
+ ui32RetVal ++;
+ }
+
+ return ui32RetVal;
+}
+
+
+/*************************************************************************/ /*!
+@Function _CalcPCEIdx
+
+@Description Calculate the page entry index
+
+@Input sDevVAddr Device virtual address
+
+@Input psDevVAddrConfig Configuration of the virtual address
+
+@Input bRoundUp Round up the index
+
+@Return The page entry index
+*/
+/*****************************************************************************/
+static IMG_UINT32 _CalcPTEIdx(IMG_DEV_VIRTADDR sDevVAddr,
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig,
+ IMG_BOOL bRoundUp)
+{
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_UINT32 ui32RetVal;
+
+ sTmpDevVAddr = sDevVAddr;
+
+ if (bRoundUp)
+ {
+ sTmpDevVAddr.uiAddr --;
+ }
+ ui32RetVal = (IMG_UINT32) ((sTmpDevVAddr.uiAddr & psDevVAddrConfig->uiPTIndexMask)
+ >> psDevVAddrConfig->uiPTIndexShift);
+
+ if (bRoundUp)
+ {
+ ui32RetVal ++;
+ }
+
+ return ui32RetVal;
+}
+
+/*****************************************************************************
+ * MMU memory allocation/management functions (mem desc) *
+ *****************************************************************************/
+
+/*************************************************************************/ /*!
+@Function _MMU_PhysMem_RAImportAlloc
+
+@Description Imports MMU Px memory into the RA. This is where the
+ actual allocation of physical memory happens.
+
+@Input hArenaHandle Handle that was passed in during the
+ creation of the RA
+
+@Input uiSize Size of the memory to import
+
+@Input uiFlags Flags that where passed in the allocation.
+
+@Output puiBase The address of where to insert this import
+
+@Output puiActualSize The actual size of the import
+
+@Output phPriv Handle which will be passed back when
+ this import is freed
+
+@Return IMG_TRUE if import alloc was successful, otherwise IMG_FALSE
+*/
+/*****************************************************************************/
+static IMG_BOOL _MMU_PhysMem_RAImportAlloc(RA_PERARENA_HANDLE hArenaHandle,
+ RA_LENGTH_T uiSize,
+ RA_FLAGS_T uiFlags,
+ RA_BASE_T *puiBase,
+ RA_LENGTH_T *puiActualSize,
+ RA_PERISPAN_HANDLE *phPriv)
+{
+ MMU_PHYSMEM_CONTEXT *psCtx = (MMU_PHYSMEM_CONTEXT *) hArenaHandle;
+ PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *) psCtx->psDevNode;
+ MMU_MEMORY_MAPPING *psMapping;
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(uiFlags);
+
+ psMapping = OSAllocMem(sizeof(MMU_MEMORY_MAPPING));
+ if (psMapping == IMG_NULL)
+ {
+ goto e0;
+ }
+
+ eError = psDevNode->pfnMMUPxAlloc(psDevNode, TRUNCATE_64BITS_TO_SIZE_T(uiSize), &psMapping->sMemHandle,
+ &psMapping->sDevPAddr);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ psMapping->psContext = psCtx;
+ psMapping->uiSize = TRUNCATE_64BITS_TO_SIZE_T(uiSize);
+
+ psMapping->uiCpuVAddrRefCount = 0;
+
+ *phPriv = (RA_PERISPAN_HANDLE) psMapping;
+
+ /* Note: This assumes this memory never gets paged out */
+ *puiBase = (RA_BASE_T)psMapping->sDevPAddr.uiAddr;
+ *puiActualSize = uiSize;
+
+ return IMG_TRUE;
+
+e1:
+ OSFreeMem(psMapping);
+e0:
+ return IMG_FALSE;
+}
+
+/*************************************************************************/ /*!
+@Function _MMU_PhysMem_RAImportFree
+
+@Description Imports MMU Px memory into the RA. This is where the
+ actual free of physical memory happens.
+
+@Input hArenaHandle Handle that was passed in during the
+ creation of the RA
+
+@Input puiBase The address of where to insert this import
+
+@Output phPriv Private data that the import alloc provided
+
+@Return None
+*/
+/*****************************************************************************/
+static IMG_VOID _MMU_PhysMem_RAImportFree(RA_PERARENA_HANDLE hArenaHandle,
+ RA_BASE_T uiBase,
+ RA_PERISPAN_HANDLE hPriv)
+{
+ MMU_MEMORY_MAPPING *psMapping = (MMU_MEMORY_MAPPING *) hPriv;
+ MMU_PHYSMEM_CONTEXT *psCtx = (MMU_PHYSMEM_CONTEXT *) hArenaHandle;
+ PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *) psCtx->psDevNode;
+
+ PVR_UNREFERENCED_PARAMETER(uiBase);
+
+ /* Check we have dropped all CPU mappings */
+ PVR_ASSERT(psMapping->uiCpuVAddrRefCount == 0);
+
+ psDevNode->pfnMMUPxFree(psDevNode, &psMapping->sMemHandle);
+ OSFreeMem(psMapping);
+}
+
+/*************************************************************************/ /*!
+@Function _MMU_PhysMemAlloc
+
+@Description Allocates physical memory for MMU objects
+
+@Input psCtx Physmem context to do the allocation from
+
+@Output psMemDesc Allocation description
+
+@Input uiBytes Size of the allocation in bytes
+
+@Input uiAlignment Alignment requirement of this allocation
+
+@Return PVRSRV_OK if allocation was successful
+*/
+/*****************************************************************************/
+
+static PVRSRV_ERROR _MMU_PhysMemAlloc(MMU_PHYSMEM_CONTEXT *psCtx,
+ MMU_MEMORY_DESC *psMemDesc,
+ IMG_SIZE_T uiBytes,
+ IMG_SIZE_T uiAlignment)
+{
+ RA_BASE_T uiPhysAddr;
+ IMG_BOOL bStatus;
+
+ if (!psMemDesc || psMemDesc->bValid)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ bStatus = RA_Alloc(psCtx->psPhysMemRA,
+ uiBytes,
+ 0, // flags
+ uiAlignment,
+ &uiPhysAddr,
+ IMG_NULL,
+ (RA_PERISPAN_HANDLE *) &psMemDesc->psMapping);
+ if(!bStatus)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_MMU_PhysMemAlloc: ERROR call to RA_Alloc() failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psMemDesc->bValid = IMG_TRUE;
+ psMemDesc->pvCpuVAddr = IMG_NULL;
+ psMemDesc->sDevPAddr.uiAddr = (IMG_UINTPTR_T) uiPhysAddr;
+
+#if !defined(SUPPORT_MMU_PxE_MAP_ON_DEMAND)
+ {
+ PVRSRV_ERROR eError;
+
+ eError = psCtx->psDevNode->pfnMMUPxMap(psCtx->psDevNode,
+ &psMemDesc->psMapping->sMemHandle,
+ psMemDesc->psMapping->uiSize,
+ &psMemDesc->psMapping->sDevPAddr,
+ &psMemDesc->psMapping->pvCpuVAddr);
+ if (eError != PVRSRV_OK)
+ {
+ RA_Free(psCtx->psPhysMemRA, psMemDesc->sDevPAddr.uiAddr);
+ return eError;
+ }
+
+ PVR_ASSERT(psMemDesc->psMapping->pvCpuVAddr != IMG_NULL);
+
+ /* Work out the address for this mem desc */
+ psMemDesc->pvCpuVAddr = ((IMG_UINT8 *) psMemDesc->psMapping->pvCpuVAddr) +
+ (psMemDesc->psMapping->sDevPAddr.uiAddr -
+ psMemDesc->psMapping->sDevPAddr.uiAddr);
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function _MMU_PhysMemFree
+
+@Description Allocates physical memory for MMU objects
+
+@Input psCtx Physmem context to do the free on
+
+@Input psMemDesc Allocation description
+
+@Return None
+*/
+/*****************************************************************************/
+static IMG_VOID _MMU_PhysMemFree(MMU_PHYSMEM_CONTEXT *psCtx,
+ MMU_MEMORY_DESC *psMemDesc)
+{
+ RA_BASE_T uiPhysAddr;
+
+ PVR_ASSERT(psMemDesc->bValid);
+
+#if !defined(SUPPORT_MMU_PxE_MAP_ON_DEMAND)
+ psCtx->psDevNode->pfnMMUPxUnmap(psCtx->psDevNode, &psMemDesc->psMapping->sMemHandle,
+ psMemDesc->pvCpuVAddr);
+
+ psMemDesc->pvCpuVAddr = IMG_NULL;
+#endif
+
+ uiPhysAddr = psMemDesc->sDevPAddr.uiAddr;
+ RA_Free(psCtx->psPhysMemRA, uiPhysAddr);
+
+ psMemDesc->bValid = IMG_FALSE;
+}
+
+/*************************************************************************/ /*!
+@Function _MMU_MapCPUVAddr
+
+@Description Map an allocation of physical memory for MMU objects
+ into the CPU address space
+
+@Input psMemDesc Allocation description
+
+@Return PVRSRV_OK if map was successful
+*/
+/*****************************************************************************/
+static PVRSRV_ERROR _MMU_MapCPUVAddr(MMU_MEMORY_DESC *psMMUMemDesc)
+{
+#if defined(SUPPORT_MMU_PxE_MAP_ON_DEMAND)
+ MMU_MEMORY_MAPPING *psMapping = psMMUMemDesc->psMapping;
+ MMU_PHYSMEM_CONTEXT *psCtx = psMapping->psContext;
+ PVRSRV_DEVICE_NODE *psDevNode = psCtx->psDevNode;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ /* There should only be one call to map */
+ PVR_ASSERT(psMMUMemDesc->pvCpuVAddr == IMG_NULL);
+
+ if (psMapping->uiCpuVAddrRefCount == 0)
+ {
+
+ eError = psDevNode->pfnMMUPxMap(psDevNode,
+ &psMapping->sMemHandle,
+ psMapping->uiSize,
+ &psMapping->sDevPAddr,
+ &psMapping->pvCpuVAddr);
+ }
+ psMapping->uiCpuVAddrRefCount++;
+
+ PVR_ASSERT(psMapping->pvCpuVAddr != IMG_NULL);
+
+ /* Workout the address for this mem desc */
+ psMMUMemDesc->pvCpuVAddr = ((IMG_UINT8 *) psMapping->pvCpuVAddr) +
+ (psMMUMemDesc->psMapping->sDevPAddr.uiAddr -
+ psMapping->sDevPAddr.uiAddr);
+
+ return eError;
+#else
+ return PVRSRV_OK;
+#endif
+}
+
+/*************************************************************************/ /*!
+@Function _MMU_UnmapCPUVAddr
+
+@Description Unmap an allocation of physical memory for MMU objects
+ from the CPU address space
+
+@Input psMemDesc Allocation description
+
+@Return PVRSRV_OK if map was successful
+*/
+/*****************************************************************************/
+static PVRSRV_ERROR _MMU_UnmapCPUVAddr(MMU_MEMORY_DESC *psMMUMemDesc)
+{
+#if defined(SUPPORT_MMU_PxE_MAP_ON_DEMAND)
+ MMU_MEMORY_MAPPING *psMapping = psMMUMemDesc->psMapping;
+ MMU_PHYSMEM_CONTEXT *psCtx = psMapping->psContext;
+ PVRSRV_DEVICE_NODE *psDevNode = psCtx->psDevNode;
+
+ if (--psMapping->uiCpuVAddrRefCount == 0)
+ {
+ psDevNode->pfnMMUPxUnmap(psDevNode, &psMapping->sMemHandle,
+ psMMUMemDesc->pvCpuVAddr);
+ }
+
+ psMMUMemDesc->pvCpuVAddr = IMG_NULL;
+#endif
+ return PVRSRV_OK;
+}
+
+
+/*****************************************************************************
+ * MMU object allocation/management functions *
+ *****************************************************************************/
+
+#if defined(SUPPORT_MMU_MODIFICATION_LOGGING)
+static IMG_CHAR *_MMU_LogPxEModificationToString(MMU_MOD eMMUMod)
+{
+ switch(eMMUMod)
+ {
+ case MMU_MOD_UNKNOWN:
+ return "Unknown";
+ case MMU_MOD_MAP:
+ return "Map";
+ case MMU_MOD_UNMAP:
+ return "Unmap";
+ default:
+ break;
+ }
+ return "Bad enum";
+}
+
+static INLINE IMG_VOID _MMU_LogPxEModification(MMU_Levelx_INFO *psLevel, IMG_UINT32 ui32Index, MMU_MOD eMMUMod, IMG_UINT64 ui64Value)
+{
+ IMG_UINT32 ui32NextEntry = psLevel->asModifications[ui32Index].ui32NextEntry;
+
+ PVR_ASSERT(ui32Index < MMU_MODIFICATION_MAX_ENTRIES);
+ if (ui32Index < MMU_MODIFICATION_MAX_ENTRIES)
+ {
+ psLevel->asModifications[ui32Index].eModificationHistory[ui32NextEntry] = eMMUMod;
+ psLevel->asModifications[ui32Index].ui64Value[ui32NextEntry] = ui64Value;
+ psLevel->asModifications[ui32Index].ui32NextEntry = (ui32NextEntry + 1) % MMU_MODIFICATION_HISTORY;
+ }
+}
+
+static INLINE IMG_VOID _MMU_LogPxEDump(MMU_Levelx_INFO *psLevel, IMG_UINT32 ui32Index)
+{
+ IMG_UINT32 i;
+
+ PVR_ASSERT(ui32Index < MMU_MODIFICATION_MAX_ENTRIES);
+ if (ui32Index < MMU_MODIFICATION_MAX_ENTRIES)
+ {
+ for (i=0;i<MMU_MODIFICATION_HISTORY;i++)
+ {
+ IMG_UINT32 ui32Tmp = (psLevel->asModifications[ui32Index].ui32NextEntry-1-i+MMU_MODIFICATION_HISTORY)%MMU_MODIFICATION_HISTORY;
+ PVR_LOG(("Mod last - %d (index %d): Op = %s, Value = 0x%016llx",
+ i,
+ ui32Tmp,
+ _MMU_LogPxEModificationToString(psLevel->asModifications[ui32Index].eModificationHistory[ui32Tmp]),
+ psLevel->asModifications[ui32Index].ui64Value[ui32Tmp]));
+
+ }
+ }
+}
+#else // defined(SUPPORT_MMU_MODIFICATION_LOGGING)
+static INLINE IMG_VOID _MMU_LogPxEModification(MMU_Levelx_INFO *psLevel, IMG_UINT32 ui32Index, MMU_MOD eMMUMod, IMG_UINT64 ui64Value)
+{
+ PVR_UNREFERENCED_PARAMETER(psLevel);
+ PVR_UNREFERENCED_PARAMETER(ui32Index);
+ PVR_UNREFERENCED_PARAMETER(eMMUMod);
+}
+
+static INLINE IMG_VOID _MMU_LogPxEDump(MMU_Levelx_INFO *psLevel, IMG_UINT32 ui32Index)
+{
+ PVR_UNREFERENCED_PARAMETER(psLevel);
+}
+#endif // defined(SUPPORT_MMU_MODIFICATION_LOGGING)
+
+/*************************************************************************/ /*!
+@Function _PxMemAlloc
+
+@Description Allocates physical memory for MMU objects, initialises
+ and PDumps it.
+
+@Input psMMUContext MMU context
+
+@Input uiNumEntries Number of entries to allocate
+
+@Input psConfig MMU Px config
+
+@Input eMMULevel MMU level that that allocation is for
+
+@Output psMemDesc Description of allocation
+
+@Return PVRSRV_OK if allocation was successful
+*/
+/*****************************************************************************/
+static PVRSRV_ERROR _PxMemAlloc(MMU_CONTEXT *psMMUContext,
+ IMG_UINT32 uiNumEntries,
+ const MMU_PxE_CONFIG *psConfig,
+ MMU_LEVEL eMMULevel,
+ MMU_MEMORY_DESC *psMemDesc,
+ IMG_UINT8 uiLog2Align)
+{
+ PVRSRV_ERROR eError;
+ IMG_SIZE_T uiBytes;
+ IMG_SIZE_T uiAlign;
+#if defined(PDUMP)
+ PVRSRV_DEVICE_NODE *psDevNode = psMMUContext->psDevNode;
+#endif
+ PVR_ASSERT(psConfig->uiBytesPerEntry != 0);
+
+ uiBytes = uiNumEntries * psConfig->uiBytesPerEntry;
+ /* We need here the alignment of the previous level because that is the entry for we generate here */
+ uiAlign = 1 << uiLog2Align;
+
+ /* allocate the object */
+ eError = _MMU_PhysMemAlloc(psMMUContext->psPhysMemCtx,
+ psMemDesc, uiBytes, uiAlign);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_PxMemAlloc: failed to allocate memory for the MMU object"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+
+ /*
+ some OS's can alloc memory without a CPU ptr.
+ Map the memory to the CPU (may be a no-op)
+ */
+ eError = _MMU_MapCPUVAddr(psMemDesc);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_PxMemAlloc: failed to map MMU object to CPU"));
+ eError = PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ goto e1;
+ }
+
+ /*
+ Clear the object
+ Note: if any MMUs are cleared with non-zero values then will need a custom
+ clear function
+ */
+ OSMemSet(psMemDesc->pvCpuVAddr, 0, uiBytes);
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Alloc MMU object");
+
+ PDumpMMUMalloc(psDevNode->pszMMUPxPDumpMemSpaceName,
+ eMMULevel,
+ &psMemDesc->sDevPAddr,
+ uiBytes,
+ uiAlign);
+
+ PDumpMMUDumpPxEntries(eMMULevel,
+ psDevNode->pszMMUPxPDumpMemSpaceName,
+ psMemDesc->pvCpuVAddr,
+ psMemDesc->sDevPAddr,
+ 0,
+ uiNumEntries,
+ IMG_NULL, IMG_NULL, 0, /* pdump symbolic info is irrelevant here */
+ psConfig->uiBytesPerEntry,
+ uiLog2Align,
+ psConfig->uiAddrShift,
+ psConfig->uiAddrMask,
+ psConfig->uiProtMask,
+ 0);
+#endif
+
+ /* unmap the memory from the CPU (may be a no-op) */
+ _MMU_UnmapCPUVAddr(psMemDesc);
+
+ return PVRSRV_OK;
+
+e1:
+ _MMU_PhysMemFree(psMMUContext->psPhysMemCtx, psMemDesc);
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function _PxMemFree
+
+@Description Frees physical memory for MMU objects, de-initialises
+ and PDumps it.
+
+@Input psMemDesc Description of allocation
+
+@Return PVRSRV_OK if allocation was successful
+*/
+/*****************************************************************************/
+
+static IMG_VOID _PxMemFree(MMU_CONTEXT *psMMUContext,
+ MMU_MEMORY_DESC *psMemDesc, MMU_LEVEL eMMULevel)
+{
+#if defined(PDUMP)
+ PVRSRV_DEVICE_NODE *psDevNode = psMMUContext->psDevNode;
+#endif
+#if defined(MMU_CLEARMEM_ON_FREE)
+ PVRSRV_ERROR eError;
+ /*
+ some OS's can alloc memory without a CPU ptr.
+ Map the memory to the CPU (may be a no-op)
+ */
+ eError = _MMU_MapCPUVAddr(psMemDesc);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_PxMemFree: failed to map MMU object to CPU"));
+ PVR_ASSERT(0);
+ }
+
+ /*
+ Clear the MMU object
+ Note: if any MMUs are cleared with non-zero values then will need a custom
+ clear function
+ */
+ OSMemSet(psMemDesc->pvCpuVAddr, 0, psMemDesc->ui32Bytes);
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Clear MMU object before freeing it");
+#endif
+
+ /* unmap the memory from the CPU (may be a no-op) */
+ _MMU_UnmapCPUVAddr(psMemDesc);
+#endif/* MMU_CLEARMEM_ON_FREE */
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Free MMU object");
+ {
+ PDumpMMUFree(psDevNode->pszMMUPxPDumpMemSpaceName, eMMULevel, &psMemDesc->sDevPAddr);
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(eMMULevel);
+#endif
+ /* free the PC */
+ _MMU_PhysMemFree(psMMUContext->psPhysMemCtx, psMemDesc);
+}
+
+
+
+/*************************************************************************/ /*!
+@Function _SetupPxE
+
+@Description Sets up an entry of an MMU object to point to the
+ provided address
+
+@Input psMMUContext MMU context to operate on
+
+@Input psLevel Level info for MMU object
+
+@Input uiIndex Index into the MMU object to setup
+
+@Input psConfig MMU Px config
+
+@Input eMMULevel Level of MMU object
+
+@Input psDevPAddr Address to setup the MMU object to point to
+
+@Input pszMemspaceName Name of the PDump memory space that the entry
+ will point to
+
+@Input pszSymbolicAddr PDump symbolic address that the entry will
+ point to
+
+@Input uiProtFlags MMU protection flags
+
+@Return PVRSRV_OK if the setup was successful
+*/
+/*****************************************************************************/
+static PVRSRV_ERROR _SetupPxE(MMU_CONTEXT *psMMUContext,
+ MMU_Levelx_INFO *psLevel,
+ IMG_UINT32 uiIndex,
+ const MMU_PxE_CONFIG *psConfig,
+ MMU_LEVEL eMMULevel,
+ const IMG_DEV_PHYADDR *psDevPAddr,
+#if defined(PDUMP)
+ const IMG_CHAR *pszMemspaceName,
+ const IMG_CHAR *pszSymbolicAddr,
+ IMG_DEVMEM_OFFSET_T uiSymbolicAddrOffset,
+#endif
+ MMU_FLAGS_T uiProtFlags,
+ IMG_UINT8 uiLog2PageSize)
+{
+ PVRSRV_DEVICE_NODE *psDevNode = psMMUContext->psDevNode;
+ MMU_MEMORY_DESC *psMemDesc = &psLevel->sMemDesc;
+ PVRSRV_ERROR eError;
+
+ IMG_UINT32 (*pfnDerivePxEProt4)(IMG_UINT32);
+ IMG_UINT64 (*pfnDerivePxEProt8)(IMG_UINT32, IMG_UINT8);
+
+ if (!psDevPAddr)
+ {
+ /* Invalidate entry */
+ if (~uiProtFlags & MMU_PROTFLAGS_INVALID)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Error, no physical address specified, but not invalidating entry"));
+ uiProtFlags |= MMU_PROTFLAGS_INVALID;
+ }
+ psDevPAddr = &gsBadDevPhyAddr;
+ }
+ else
+ {
+ if (uiProtFlags & MMU_PROTFLAGS_INVALID)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "A physical address was specified when requesting invalidation of entry"));
+ uiProtFlags |= MMU_PROTFLAGS_INVALID;
+ }
+ }
+
+ switch(eMMULevel)
+ {
+ case MMU_LEVEL_3:
+ pfnDerivePxEProt4 = psMMUContext->psDevAttrs->pfnDerivePCEProt4;
+ pfnDerivePxEProt8 = psMMUContext->psDevAttrs->pfnDerivePCEProt8;
+ break;
+
+ case MMU_LEVEL_2:
+ pfnDerivePxEProt4 = psMMUContext->psDevAttrs->pfnDerivePDEProt4;
+ pfnDerivePxEProt8 = psMMUContext->psDevAttrs->pfnDerivePDEProt8;
+ break;
+
+ case MMU_LEVEL_1:
+ pfnDerivePxEProt4 = psMMUContext->psDevAttrs->pfnDerivePTEProt4;
+ pfnDerivePxEProt8 = psMMUContext->psDevAttrs->pfnDerivePTEProt8;
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: invalid MMU level", __func__));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Map the Page Catalogue into CPU virtual memory */
+ eError = _MMU_MapCPUVAddr(psMemDesc);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: failed to map Px to CPU", __func__));
+ return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ }
+
+ /* How big is a PxE in bytes? */
+ /* Filling the actual Px entry with an address */
+ switch(psConfig->uiBytesPerEntry)
+ {
+ case 4:
+ {
+ IMG_UINT32 *pui32Px;
+ IMG_UINT64 ui64PxE64;
+
+ pui32Px = psMemDesc->pvCpuVAddr; /* Give the virtual base address of Px */
+
+ ui64PxE64 = psDevPAddr->uiAddr /* Calculate the offset to that base */
+ >> psConfig->uiLog2Align /* Shift away the useless bits, because the alignment is very coarse and we address by alignment */
+ << psConfig->uiAddrShift /* Shift back to fit address in the Px entry */
+ & psConfig->uiAddrMask; /* Delete unused bits */
+
+ ui64PxE64 |= (IMG_UINT64)pfnDerivePxEProt4(uiProtFlags);
+ /* assert that the result fits into 32 bits before writing
+ it into the 32-bit array with a cast */
+ PVR_ASSERT(ui64PxE64 == (ui64PxE64 & 0xffffffffU));
+
+ /* We should never invalidate an invalid page */
+ if (uiProtFlags & MMU_PROTFLAGS_INVALID)
+ {
+ PVR_ASSERT(pui32Px[uiIndex] != ui64PxE64);
+ }
+ pui32Px[uiIndex] = (IMG_UINT32) ui64PxE64;
+ _MMU_LogPxEModification(psLevel,
+ uiIndex,
+ (uiProtFlags & MMU_PROTFLAGS_INVALID)?MMU_MOD_UNMAP:MMU_MOD_MAP,
+ ui64PxE64);
+ break;
+ }
+ case 8:
+ {
+ IMG_UINT64 *pui64Px = psMemDesc->pvCpuVAddr; /* Give the virtual base address of Px */
+
+ pui64Px[uiIndex] = psDevPAddr->uiAddr /* Calculate the offset to that base */
+ >> psConfig->uiLog2Align
+ << psConfig->uiAddrShift
+ & psConfig->uiAddrMask;
+ pui64Px[uiIndex] |= pfnDerivePxEProt8(uiProtFlags, uiLog2PageSize);
+
+ _MMU_LogPxEModification(psLevel,
+ uiIndex,
+ (uiProtFlags & MMU_PROTFLAGS_INVALID)?MMU_MOD_UNMAP:MMU_MOD_MAP,
+ pui64Px[uiIndex]);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: PxE size not supported (%d) for level %d",
+ __func__, psConfig->uiBytesPerEntry, eMMULevel));
+
+ _MMU_UnmapCPUVAddr(psMemDesc);
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#if defined (PDUMP)
+ PDumpMMUDumpPxEntries(eMMULevel,
+ psDevNode->pszMMUPxPDumpMemSpaceName,
+ psMemDesc->pvCpuVAddr,
+ psMemDesc->sDevPAddr,
+ uiIndex,
+ 1,
+ pszMemspaceName,
+ pszSymbolicAddr,
+ uiSymbolicAddrOffset,
+ psConfig->uiBytesPerEntry,
+ psConfig->uiLog2Align,
+ psConfig->uiAddrShift,
+ psConfig->uiAddrMask,
+ psConfig->uiProtMask,
+ 0);
+#endif
+
+ psDevNode->pfnMMUCacheInvalidate(psDevNode, psMMUContext->hDevData,
+ eMMULevel,
+ (uiProtFlags & MMU_PROTFLAGS_INVALID)?IMG_TRUE:IMG_FALSE);
+
+
+ /* unmap the memory from the CPU (may be a no-op) */
+ eError = _MMU_UnmapCPUVAddr(psMemDesc);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: failed to release the CPU mapping", __func__));
+ return PVRSRV_ERROR_MMU_FAILED_TO_UNMAP_PAGE_TABLE;
+ }
+
+ return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ * MMU host control functions (Level Info) *
+ *****************************************************************************/
+
+
+/*************************************************************************/ /*!
+@Function _MMU_FreeLevel
+
+@Description Recursively frees the specified range of Px entries. If any
+ level has its last reference dropped then the MMU object
+ memory and the MMU_Levelx_Info will be freed.
+
+ At each level we might be crossing a boundary from one Px to
+ another. The values for auiStartArray should be by used for
+ the first call into each level and the values in auiEndArray
+ should only be used in the last call for each level.
+ In order to determine if this is the first/last call we pass
+ in bFirst and bLast.
+ When one level calls down to the next only if bFirst/bLast is set
+ and it's the first/last iteration of the loop at its level will
+ bFirst/bLast set for the next recursion.
+ This means that each iteration has the knowledge of the previous
+ level which is required.
+
+@Input psMMUContext MMU context to operate on
+
+@Input psLevel Level info on which to to free the
+ specified range
+
+@Input auiStartArray Array of start indexes (one for each level)
+
+@Input auiEndArray Array of end indexes (one for each level)
+
+@Input auiEntriesPerPxArray Array of number of entries for the Px
+ (one for each level)
+
+@Input apsConfig Array of PxE configs (one for each level)
+
+@Input aeMMULevel Array of MMU levels (one for each level)
+
+@Input pui32CurrentLevel Pointer to a variable which is set to our
+ current level
+
+@Input uiStartIndex Start index of the range to free
+
+@Input uiEndIndex End index of the range to free
+
+@Input bFirst This is the first call for this level
+
+@Input bLast This is the last call for this level
+
+@Return IMG_TRUE if the last reference to psLevel was dropped
+*/
+/*****************************************************************************/
+static IMG_BOOL _MMU_FreeLevel(MMU_CONTEXT *psMMUContext,
+ MMU_Levelx_INFO *psLevel,
+ IMG_UINT32 auiStartArray[],
+ IMG_UINT32 auiEndArray[],
+ IMG_UINT32 auiEntriesPerPxArray[],
+ const MMU_PxE_CONFIG *apsConfig[],
+ MMU_LEVEL aeMMULevel[],
+ IMG_UINT32 *pui32CurrentLevel,
+ IMG_UINT32 uiStartIndex,
+ IMG_UINT32 uiEndIndex,
+ IMG_BOOL bFirst,
+ IMG_BOOL bLast)
+{
+ IMG_UINT32 uiThisLevel = *pui32CurrentLevel;
+ const MMU_PxE_CONFIG *psConfig = apsConfig[uiThisLevel];
+ IMG_UINT32 i;
+ IMG_BOOL bFreed = IMG_FALSE;
+ IMG_UINT8 uiLog2PageSize;
+
+ /* Sanity check */
+ PVR_ASSERT(*pui32CurrentLevel < MMU_MAX_LEVEL);
+ PVR_ASSERT(psLevel != IMG_NULL);
+
+ MMU_OBJ_DBG((PVR_DBG_ERROR, "_MMU_FreeLevel: level = %d, range %d - %d, refcount = %d",
+ aeMMULevel[uiThisLevel], uiStartIndex,
+ uiEndIndex, psLevel->ui32RefCount));
+
+ for (i = uiStartIndex;(i < uiEndIndex) && (psLevel != IMG_NULL);i++)
+ {
+ if (aeMMULevel[uiThisLevel] != MMU_LEVEL_1)
+ {
+ MMU_Levelx_INFO *psNextLevel = psLevel->apsNextLevel[i];
+ IMG_UINT32 uiNextStartIndex;
+ IMG_UINT32 uiNextEndIndex;
+ IMG_BOOL bNextFirst;
+ IMG_BOOL bNextLast;
+
+ /* If we're crossing a Px then the start index changes */
+ if (bFirst & (i == uiStartIndex))
+ {
+ uiNextStartIndex = auiStartArray[uiThisLevel + 1];
+ bNextFirst = IMG_TRUE;
+ }
+ else
+ {
+ uiNextStartIndex = 0;
+ bNextFirst = IMG_FALSE;
+ }
+
+ /* If we're crossing a Px then the end index changes */
+ if (bLast & (i == (uiEndIndex - 1)))
+ {
+ uiNextEndIndex = auiEndArray[uiThisLevel + 1];
+ bNextLast = IMG_TRUE;
+ }
+ else
+ {
+ uiNextEndIndex = auiEntriesPerPxArray[uiThisLevel + 1];
+ bNextLast = IMG_FALSE;
+ }
+
+ /* Recurse into the next level */
+ (*pui32CurrentLevel)++;
+ if (_MMU_FreeLevel(psMMUContext, psNextLevel, auiStartArray,
+ auiEndArray, auiEntriesPerPxArray,
+ apsConfig, aeMMULevel, pui32CurrentLevel,
+ uiNextStartIndex, uiNextEndIndex,
+ bNextFirst, bNextLast))
+ {
+ /* The level below us is empty, drop the refcount and clear the pointer */
+ psLevel->ui32RefCount--;
+ psLevel->apsNextLevel[i] = IMG_NULL;
+
+ /* Level 1 PTE reprogramming is done in the unmap */
+ if (aeMMULevel[uiThisLevel] != MMU_LEVEL_1)
+ {
+ PVRSRV_ERROR eError;
+ /* Take the page size from the page table configs.
+ Calculate array entry for PT config dependent on max MMU level */
+ uiLog2PageSize = apsConfig[MMU_MAX_LEVEL-1]->uiLog2Align;
+ /* Un-wire the entry */
+ eError = _SetupPxE(psMMUContext,
+ psLevel,
+ i,
+ psConfig,
+ aeMMULevel[uiThisLevel],
+ IMG_NULL,
+#if defined(PDUMP)
+ IMG_NULL, /* Only required for data page */
+ IMG_NULL, /* Only required for data page */
+ 0, /* Only required for data page */
+#endif
+ MMU_PROTFLAGS_INVALID,
+ uiLog2PageSize);
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+
+
+ /* Check we haven't wrapped around */
+ PVR_ASSERT(psLevel->ui32RefCount <= psLevel->ui32NumOfEntries);
+ }
+ (*pui32CurrentLevel)--;
+ }
+ else
+ {
+ psLevel->ui32RefCount--;
+ }
+
+ /*
+ Free this level if it is no longer referenced, unless it's the base
+ level in which case it's part of the MMU context and should be freed
+ when the MMU context is freed
+ */
+ if ((psLevel->ui32RefCount == 0) && (psLevel != &psMMUContext->sBaseLevelInfo))
+ {
+ _PxMemFree(psMMUContext, &psLevel->sMemDesc, aeMMULevel[uiThisLevel]);
+ OSFreeMem(psLevel);
+ psLevel = IMG_NULL;
+ bFreed = IMG_TRUE;
+ }
+ }
+ MMU_OBJ_DBG((PVR_DBG_ERROR, "_MMU_FreeLevel end: level = %d, refcount = %d",
+ aeMMULevel[uiThisLevel], bFreed?0:psLevel->ui32RefCount));
+
+ return bFreed;
+}
+
+/*************************************************************************/ /*!
+@Function _MMU_AllocLevel
+
+@Description Recursively allocates the specified range of Px entries. If any
+ level has its last reference dropped then the MMU object
+ memory and the MMU_Levelx_Info will be freed.
+
+ At each level we might be crossing a boundary from one Px to
+ another. The values for auiStartArray should be by used for
+ the first call into each level and the values in auiEndArray
+ should only be used in the last call for each level.
+ In order to determine if this is the first/last call we pass
+ in bFirst and bLast.
+ When one level calls down to the next only if bFirst/bLast is set
+ and it's the first/last iteration of the loop at its level will
+ bFirst/bLast set for the next recursion.
+ This means that each iteration has the knowledge of the previous
+ level which is required.
+
+@Input psMMUContext MMU context to operate on
+
+@Input psLevel Level info on which to to free the
+ specified range
+
+@Input auiStartArray Array of start indexes (one for each level)
+
+@Input auiEndArray Array of end indexes (one for each level)
+
+@Input auiEntriesPerPxArray Array of number of entries for the Px
+ (one for each level)
+
+@Input apsConfig Array of PxE configs (one for each level)
+
+@Input aeMMULevel Array of MMU levels (one for each level)
+
+@Input pui32CurrentLevel Pointer to a variable which is set to our
+ current level
+
+@Input uiStartIndex Start index of the range to free
+
+@Input uiEndIndex End index of the range to free
+
+@Input bFirst This is the first call for this level
+
+@Input bLast This is the last call for this level
+
+@Return IMG_TRUE if the last reference to psLevel was dropped
+*/
+/*****************************************************************************/
+static PVRSRV_ERROR _MMU_AllocLevel(MMU_CONTEXT *psMMUContext,
+ MMU_Levelx_INFO *psLevel,
+ IMG_UINT32 auiStartArray[],
+ IMG_UINT32 auiEndArray[],
+ IMG_UINT32 auiEntriesPerPxArray[],
+ const MMU_PxE_CONFIG *apsConfig[],
+ MMU_LEVEL aeMMULevel[],
+ IMG_UINT32 *pui32CurrentLevel,
+ IMG_UINT32 uiStartIndex,
+ IMG_UINT32 uiEndIndex,
+ IMG_BOOL bFirst,
+ IMG_BOOL bLast)
+{
+ IMG_UINT32 uiThisLevel = *pui32CurrentLevel; /* Starting with 0 */
+ const MMU_PxE_CONFIG *psConfig = apsConfig[uiThisLevel]; /* The table config for the current level */
+ PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ IMG_UINT32 uiAllocState = 99; /* Debug info to check what progress was made in the function. Updated during this function. */
+ IMG_UINT32 i;
+
+ /* Sanity check */
+ PVR_ASSERT(*pui32CurrentLevel < MMU_MAX_LEVEL);
+
+ MMU_OBJ_DBG((PVR_DBG_ERROR, "_MMU_AllocLevel: level = %d, range %d - %d, refcount = %d",
+ aeMMULevel[uiThisLevel], uiStartIndex,
+ uiEndIndex, psLevel->ui32RefCount));
+
+ /* Go from uiStartIndex to uiEndIndex through the Px */
+ for (i = uiStartIndex;i < uiEndIndex;i++)
+ {
+ /* Only try an allocation if this is not the last level */
+ /*Because a PT allocation is already done while setting the entry in PD */
+ if (aeMMULevel[uiThisLevel] != MMU_LEVEL_1)
+ {
+ IMG_UINT32 uiNextStartIndex;
+ IMG_UINT32 uiNextEndIndex;
+ IMG_BOOL bNextFirst;
+ IMG_BOOL bNextLast;
+ IMG_UINT8 uiLog2PageSize;
+
+ /* If there is already a next Px level existing, do not allocate it */
+ if (!psLevel->apsNextLevel[i])
+ {
+ MMU_Levelx_INFO *psNextLevel;
+ IMG_UINT32 ui32AllocSize;
+ IMG_UINT32 uiNextEntries;
+
+ /* Allocate and setup the next level */
+ uiNextEntries = auiEntriesPerPxArray[uiThisLevel + 1];
+ ui32AllocSize = sizeof(MMU_Levelx_INFO);
+ if (aeMMULevel[uiThisLevel + 1] != MMU_LEVEL_1)
+ {
+ ui32AllocSize += sizeof(MMU_Levelx_INFO *) * (uiNextEntries - 1);
+ }
+ psNextLevel = OSAllocMem(ui32AllocSize);
+ if (psNextLevel == IMG_NULL)
+ {
+ uiAllocState = 0;
+ goto e0;
+ }
+ OSMemSet(psNextLevel, 0, ui32AllocSize);
+
+ /* Hook in this level for next time */
+ psLevel->apsNextLevel[i] = psNextLevel;
+
+ psNextLevel->ui32NumOfEntries = uiNextEntries;
+ psNextLevel->ui32RefCount = 0;
+ /* Allocate Px memory for a sub level*/
+ eError = _PxMemAlloc(psMMUContext, uiNextEntries, apsConfig[uiThisLevel + 1],
+ aeMMULevel[uiThisLevel + 1],
+ &psNextLevel->sMemDesc,
+ psConfig->uiLog2Align);
+ if (eError != PVRSRV_OK)
+ {
+ uiAllocState = 1;
+ goto e0;
+ }
+
+ uiLog2PageSize = apsConfig[MMU_MAX_LEVEL-1]->uiLog2Align;
+ /* Wire up the entry */
+ eError = _SetupPxE(psMMUContext,
+ psLevel,
+ i,
+ psConfig,
+ aeMMULevel[uiThisLevel],
+ &psNextLevel->sMemDesc.sDevPAddr,
+#if defined(PDUMP)
+ IMG_NULL, /* Only required for data page */
+ IMG_NULL, /* Only required for data page */
+ 0, /* Only required for data page */
+#endif
+ 0,
+ uiLog2PageSize);
+
+ if (eError != PVRSRV_OK)
+ {
+ uiAllocState = 2;
+ goto e0;
+ }
+
+ psLevel->ui32RefCount++;
+ }
+
+ /* If we're crossing a Px then the start index changes */
+ if (bFirst & (i == uiStartIndex))
+ {
+ uiNextStartIndex = auiStartArray[uiThisLevel + 1];
+ bNextFirst = IMG_TRUE;
+ }
+ else
+ {
+ uiNextStartIndex = 0;
+ bNextFirst = IMG_FALSE;
+ }
+
+ /* If we're crossing a Px then the end index changes */
+ if (bLast & (i == (uiEndIndex - 1)))
+ {
+ uiNextEndIndex = auiEndArray[uiThisLevel + 1];
+ bNextLast = IMG_TRUE;
+ }
+ else
+ {
+ uiNextEndIndex = auiEntriesPerPxArray[uiThisLevel + 1];
+ bNextLast = IMG_FALSE;
+ }
+
+ /* Recurse into the next level */
+ (*pui32CurrentLevel)++;
+ eError = _MMU_AllocLevel(psMMUContext, psLevel->apsNextLevel[i],
+ auiStartArray,
+ auiEndArray,
+ auiEntriesPerPxArray,
+ apsConfig,
+ aeMMULevel,
+ pui32CurrentLevel,
+ uiNextStartIndex,
+ uiNextEndIndex,
+ bNextFirst,
+ bNextLast);
+ (*pui32CurrentLevel)--;
+ if (eError != PVRSRV_OK)
+ {
+ uiAllocState = 2;
+ goto e0;
+ }
+ }
+ else
+ {
+ /* All we need to do for level 1 is bump the refcount */
+ psLevel->ui32RefCount++;
+ }
+ PVR_ASSERT(psLevel->ui32RefCount <= psLevel->ui32NumOfEntries);
+ }
+ MMU_OBJ_DBG((PVR_DBG_ERROR, "_MMU_AllocLevel end: level = %d, refcount = %d",
+ aeMMULevel[uiThisLevel], psLevel->ui32RefCount));
+ return PVRSRV_OK;
+
+e0:
+ /* Sanity check that we've not come down this route unexpectedly */
+ PVR_ASSERT(uiAllocState!=99);
+ PVR_DPF((PVR_DBG_ERROR, "_MMU_AllocLevel: Error %d allocating Px for level %d in stage %d"
+ ,eError, aeMMULevel[uiThisLevel], uiAllocState));
+
+ /* the start value of index variable i is nor initialized on purpose
+ indeed this for loop deinitialize what has already been initialized
+ just before failing in reverse order. So the i index has already the
+ right value. */
+ for (/* i already set */ ; i>= uiStartIndex && i< uiEndIndex; i--)
+ {
+ switch(uiAllocState)
+ {
+ IMG_UINT32 uiNextStartIndex;
+ IMG_UINT32 uiNextEndIndex;
+ IMG_BOOL bNextFirst;
+ IMG_BOOL bNextLast;
+
+ case 3:
+ /* If we're crossing a Px then the start index changes */
+ if (bFirst & (i == uiStartIndex))
+ {
+ uiNextStartIndex = auiStartArray[uiThisLevel + 1];
+ bNextFirst = IMG_TRUE;
+ }
+ else
+ {
+ uiNextStartIndex = 0;
+ bNextFirst = IMG_FALSE;
+ }
+
+ /* If we're crossing a Px then the end index changes */
+ if (bLast & (i == (uiEndIndex - 1)))
+ {
+ uiNextEndIndex = auiEndArray[uiThisLevel + 1];
+ bNextLast = IMG_TRUE;
+ }
+ else
+ {
+ uiNextEndIndex = auiEntriesPerPxArray[uiThisLevel + 1];
+ bNextLast = IMG_FALSE;
+ }
+
+ if (aeMMULevel[uiThisLevel] != MMU_LEVEL_1)
+ {
+ (*pui32CurrentLevel)++;
+ if (_MMU_FreeLevel(psMMUContext, psLevel->apsNextLevel[i],
+ auiStartArray, auiEndArray,
+ auiEntriesPerPxArray, apsConfig,
+ aeMMULevel, pui32CurrentLevel,
+ uiNextStartIndex, uiNextEndIndex,
+ bNextFirst, bNextLast))
+ {
+ psLevel->ui32RefCount--;
+ psLevel->apsNextLevel[i] = IMG_NULL;
+
+ /* Check we haven't wrapped around */
+ PVR_ASSERT(psLevel->ui32RefCount <= psLevel->ui32NumOfEntries);
+ }
+ (*pui32CurrentLevel)--;
+ }
+ else
+ {
+ /* We should never come down this path, but it's here
+ for completeness */
+ psLevel->ui32RefCount--;
+
+ /* Check we haven't wrapped around */
+ PVR_ASSERT(psLevel->ui32RefCount <= psLevel->ui32NumOfEntries);
+ }
+ case 2:
+ if (psLevel->apsNextLevel[i] != IMG_NULL &&
+ psLevel->apsNextLevel[i]->ui32RefCount == 0)
+ {
+ _PxMemFree(psMMUContext, &psLevel->sMemDesc,
+ aeMMULevel[uiThisLevel]);
+ }
+ case 1:
+ if (psLevel->apsNextLevel[i] != IMG_NULL &&
+ psLevel->apsNextLevel[i]->ui32RefCount == 0)
+ {
+ OSFreeMem(psLevel->apsNextLevel[i]);
+ psLevel->apsNextLevel[i] = IMG_NULL;
+ }
+ case 0:
+ uiAllocState = 3;
+ break;
+ }
+ }
+ return eError;
+}
+
+/*****************************************************************************
+ * MMU page table functions *
+ *****************************************************************************/
+
+/*************************************************************************/ /*!
+@Function _MMU_GetLevelData
+
+@Description Get the all the level data and calculates the indexes for the
+ specified address range
+
+@Input psMMUContext MMU context to operate on
+
+@Input sDevVAddrStart Start device virtual address
+
+@Input sDevVAddrEnd End device virtual address
+
+@Input uiLog2DataPageSize Log2 of the page size to use
+
+@Input auiStartArray Array of start indexes (one for each level)
+
+@Input auiEndArray Array of end indexes (one for each level)
+
+@Input uiEntriesPerPxArray Array of number of entries for the Px
+ (one for each level)
+
+@Input apsConfig Array of PxE configs (one for each level)
+
+@Input aeMMULevel Array of MMU levels (one for each level)
+@Input apsConfig Array of PxE configs (one for each level)
+
+@Input aeMMULevel Array of MMU levels (one for each level)
+
+@Input pui32CurrentLevel Pointer to a variable which is set to our
+ current level
+
+@Input uiStartIndex Start index of the range to free
+
+@Input uiEndIndex End index of the range to free
+
+@Return IMG_TRUE if the last reference to psLevel was dropped
+*/
+/*****************************************************************************/
+static IMG_VOID _MMU_GetLevelData(MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddrStart,
+ IMG_DEV_VIRTADDR sDevVAddrEnd,
+ IMG_UINT32 uiLog2DataPageSize,
+ IMG_UINT32 auiStartArray[],
+ IMG_UINT32 auiEndArray[],
+ IMG_UINT32 auiEntriesPerPx[],
+ const MMU_PxE_CONFIG *apsConfig[],
+ MMU_LEVEL aeMMULevel[],
+ const MMU_DEVVADDR_CONFIG **ppsMMUDevVAddrConfig,
+ IMG_HANDLE *phPriv)
+{
+ const MMU_PxE_CONFIG *psMMUPDEConfig;
+ const MMU_PxE_CONFIG *psMMUPTEConfig;
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig;
+ MMU_DEVICEATTRIBS *psDevAttrs = psMMUContext->psDevAttrs;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i = 0;
+
+ eError = psDevAttrs->pfnGetPageSizeConfiguration(uiLog2DataPageSize,
+ &psMMUPDEConfig,
+ &psMMUPTEConfig,
+ ppsMMUDevVAddrConfig,
+ phPriv);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ psDevVAddrConfig = *ppsMMUDevVAddrConfig;
+
+ if (psDevVAddrConfig->uiPCIndexMask != 0)
+ {
+ auiStartArray[i] = _CalcPCEIdx(sDevVAddrStart, psDevVAddrConfig, IMG_FALSE);
+ auiEndArray[i] = _CalcPCEIdx(sDevVAddrEnd, psDevVAddrConfig, IMG_TRUE);
+ auiEntriesPerPx[i] = (IMG_UINT32)UNITS_IN_BITFIELD(psDevVAddrConfig->uiPCIndexMask,
+ psDevVAddrConfig->uiPCIndexShift);
+ apsConfig[i] = psDevAttrs->psBaseConfig;
+ aeMMULevel[i] = MMU_LEVEL_3;
+ i++;
+ }
+
+ if (psDevVAddrConfig->uiPDIndexMask != 0)
+ {
+ auiStartArray[i] = _CalcPDEIdx(sDevVAddrStart, psDevVAddrConfig, IMG_FALSE);
+ auiEndArray[i] = _CalcPDEIdx(sDevVAddrEnd, psDevVAddrConfig, IMG_TRUE);
+ auiEntriesPerPx[i] = (IMG_UINT32)UNITS_IN_BITFIELD(psDevVAddrConfig->uiPDIndexMask,
+ psDevVAddrConfig->uiPDIndexShift);
+ if (i == 0)
+ {
+ apsConfig[i] = psDevAttrs->psBaseConfig;
+ }
+ else
+ {
+ apsConfig[i] = psMMUPDEConfig;
+ }
+ aeMMULevel[i] = MMU_LEVEL_2;
+ i++;
+ }
+
+ if (psDevVAddrConfig->uiPTIndexMask != 0)
+ {
+ auiStartArray[i] = _CalcPTEIdx(sDevVAddrStart, psDevVAddrConfig, IMG_FALSE);
+ auiEndArray[i] = _CalcPTEIdx(sDevVAddrEnd, psDevVAddrConfig, IMG_TRUE);
+ auiEntriesPerPx[i] = (IMG_UINT32)UNITS_IN_BITFIELD(psDevVAddrConfig->uiPTIndexMask,
+ psDevVAddrConfig->uiPTIndexShift);
+ if (i == 0)
+ {
+ apsConfig[i] = psDevAttrs->psBaseConfig;
+ }
+ else
+ {
+ apsConfig[i] = psMMUPTEConfig;
+ }
+ aeMMULevel[i] = MMU_LEVEL_1;
+ i++;
+ }
+
+ PVR_ASSERT(i!=0);
+}
+
+static IMG_VOID _MMU_PutLevelData(MMU_CONTEXT *psMMUContext, IMG_HANDLE hPriv)
+{
+ MMU_DEVICEATTRIBS *psDevAttrs = psMMUContext->psDevAttrs;
+
+ psDevAttrs->pfnPutPageSizeConfiguration(hPriv);
+}
+
+/*************************************************************************/ /*!
+@Function _AllocPageTables
+
+@Description Allocate page tables and any higher level MMU objects required
+ for the specified virtual range
+
+@Input psMMUContext MMU context to operate on
+
+@Input sDevVAddrStart Start device virtual address
+
+@Input sDevVAddrEnd End device virtual address
+
+@Input uiProtFlags Generic MMU protection flags
+
+@Return PVRSRV_OK if the allocation was successful
+*/
+/*****************************************************************************/
+static PVRSRV_ERROR
+_AllocPageTables(MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddrStart,
+ IMG_DEV_VIRTADDR sDevVAddrEnd,
+ MMU_FLAGS_T uiProtFlags,
+ IMG_UINT8 uiLog2PageSize)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 auiStartArray[MMU_MAX_LEVEL];
+ IMG_UINT32 auiEndArray[MMU_MAX_LEVEL];
+ IMG_UINT32 auiEntriesPerPx[MMU_MAX_LEVEL];
+ MMU_LEVEL aeMMULevel[MMU_MAX_LEVEL];
+ const MMU_PxE_CONFIG *apsConfig[MMU_MAX_LEVEL];
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig;
+ IMG_HANDLE hPriv;
+ IMG_UINT32 ui32CurrentLevel = 0;
+
+
+ PVR_DPF((PVR_DBG_ALLOC,
+ "_AllocPageTables: vaddr range: 0x%010llx:0x%010llx",
+ sDevVAddrStart.uiAddr,
+ sDevVAddrEnd.uiAddr
+ ));
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Allocating page tables for %llu bytes virtual range: 0x%010llX to 0x%010llX",
+ (IMG_UINT64)sDevVAddrEnd.uiAddr - (IMG_UINT64)sDevVAddrStart.uiAddr,
+ (IMG_UINT64)sDevVAddrStart.uiAddr,
+ (IMG_UINT64)sDevVAddrEnd.uiAddr);
+#endif
+
+ _MMU_GetLevelData(psMMUContext, sDevVAddrStart, sDevVAddrEnd,
+ (IMG_UINT32) uiLog2PageSize, auiStartArray, auiEndArray,
+ auiEntriesPerPx, apsConfig, aeMMULevel,
+ &psDevVAddrConfig, &hPriv);
+
+ eError = _MMU_AllocLevel(psMMUContext, &psMMUContext->sBaseLevelInfo,
+ auiStartArray, auiEndArray, auiEntriesPerPx,
+ apsConfig, aeMMULevel, &ui32CurrentLevel,
+ auiStartArray[0], auiEndArray[0],
+ IMG_TRUE, IMG_TRUE);
+
+ _MMU_PutLevelData(psMMUContext, hPriv);
+
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function _FreePageTables
+
+@Description Free page tables and any higher level MMU objects at are no
+ longer referenced for the specified virtual range
+
+@Input psMMUContext MMU context to operate on
+
+@Input sDevVAddrStart Start device virtual address
+
+@Input sDevVAddrEnd End device virtual address
+
+@Return None
+*/
+/*****************************************************************************/
+static IMG_VOID _FreePageTables(MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddrStart,
+ IMG_DEV_VIRTADDR sDevVAddrEnd,
+ IMG_UINT8 uiLog2PageSize)
+{
+ IMG_UINT32 auiStartArray[MMU_MAX_LEVEL];
+ IMG_UINT32 auiEndArray[MMU_MAX_LEVEL];
+ IMG_UINT32 auiEntriesPerPx[MMU_MAX_LEVEL];
+ MMU_LEVEL aeMMULevel[MMU_MAX_LEVEL];
+ const MMU_PxE_CONFIG *apsConfig[MMU_MAX_LEVEL];
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig;
+ IMG_UINT32 ui32CurrentLevel = 0;
+ IMG_HANDLE hPriv;
+
+
+ PVR_DPF((PVR_DBG_ALLOC,
+ "_FreePageTables: vaddr range: 0x%010llx:0x%010llx",
+ sDevVAddrStart.uiAddr,
+ sDevVAddrEnd.uiAddr
+ ));
+
+ _MMU_GetLevelData(psMMUContext, sDevVAddrStart, sDevVAddrEnd,
+ uiLog2PageSize, auiStartArray, auiEndArray,
+ auiEntriesPerPx, apsConfig, aeMMULevel,
+ &psDevVAddrConfig, &hPriv);
+
+ _MMU_FreeLevel(psMMUContext, &psMMUContext->sBaseLevelInfo,
+ auiStartArray, auiEndArray, auiEntriesPerPx,
+ apsConfig, aeMMULevel, &ui32CurrentLevel,
+ auiStartArray[0], auiEndArray[0],
+ IMG_TRUE, IMG_TRUE);
+
+ _MMU_PutLevelData(psMMUContext, hPriv);
+}
+
+
+/*************************************************************************/ /*!
+@Function _MMU_GetPTEInfo
+
+@Description Get the PTE config and level information for the specified
+ virtual address
+
+@Input psMMUContext MMU context to operate on
+
+@Input psDevVAddr Device virtual address to get the PTE info
+ for
+
+@Input uiLog2DataPageSize Log 2 of the page size
+
+@Output psLevel Level info of the PT
+
+@Output pui32PTEIndex Index into the PT the address corresponds to
+
+@Output ppsConfig Config of the PTE
+
+@Output phPriv Private data handle to be passed back
+ when the info is put
+
+@Return None
+*/
+/*****************************************************************************/
+static IMG_VOID _MMU_GetPTEInfo(MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 uiLog2DataPageSize,
+ MMU_Levelx_INFO **psLevel,
+ IMG_UINT32 *pui32PTEIndex,
+ const MMU_PxE_CONFIG **ppsConfig,
+ IMG_HANDLE *phPriv)
+{
+ MMU_DEVICEATTRIBS *psDevAttrs = psMMUContext->psDevAttrs;
+ MMU_Levelx_INFO *psLocalLevel = IMG_NULL;
+
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig;
+ const MMU_PxE_CONFIG *psPDEConfig;
+ const MMU_PxE_CONFIG *psPTEConfig;
+
+ IMG_UINT32 uiPCEIndex;
+ IMG_UINT32 uiPDEIndex;
+
+
+ if (psDevAttrs->pfnGetPageSizeConfiguration(uiLog2DataPageSize,
+ &psPDEConfig,
+ &psPTEConfig,
+ &psDevVAddrConfig,
+ phPriv) != PVRSRV_OK)
+ {
+ /*
+ There should be no way we got here unless uiLog2DataPageSize
+ has changed after the MMU_Alloc call (in which case it's a bug in
+ the MM code)
+ */
+ PVR_ASSERT(0);
+ }
+
+ switch(psMMUContext->psDevAttrs->eTopLevel)
+ {
+ case MMU_LEVEL_3:
+ /* find the page directory containing the PCE */
+ uiPCEIndex = _CalcPCEIdx(sDevVAddr, psDevVAddrConfig, IMG_FALSE);
+ psLocalLevel = psMMUContext->sBaseLevelInfo.apsNextLevel[uiPCEIndex];
+
+ case MMU_LEVEL_2:
+ /* find the page table containing the PDE */
+ uiPDEIndex = _CalcPDEIdx(sDevVAddr, psDevVAddrConfig, IMG_FALSE);
+ if (psLocalLevel != IMG_NULL)
+ {
+ psLocalLevel = psLocalLevel->apsNextLevel[uiPDEIndex];
+ }
+ else
+ {
+ psLocalLevel = psMMUContext->sBaseLevelInfo.apsNextLevel[uiPDEIndex];
+ }
+
+ case MMU_LEVEL_1:
+ /* find PTE index into page table */
+ *pui32PTEIndex = _CalcPTEIdx(sDevVAddr, psDevVAddrConfig, IMG_FALSE);
+ if (psLocalLevel == IMG_NULL)
+ {
+ psLocalLevel = &psMMUContext->sBaseLevelInfo;
+ }
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "_MMU_GetPTEInfo: Invalid MMU level"));
+ return;
+ }
+
+ *psLevel = psLocalLevel;
+ *ppsConfig = psPTEConfig;
+}
+
+/*************************************************************************/ /*!
+@Function _MMU_PutPTEInfo
+
+@Description Put the level info.
+
+@Input psMMUContext MMU context to operate on
+
+@Input phPriv Private data handle
+
+@Return None
+*/
+/*****************************************************************************/
+static IMG_VOID _MMU_PutPTEInfo(MMU_CONTEXT *psMMUContext,
+ IMG_HANDLE hPriv)
+{
+ MMU_DEVICEATTRIBS *psDevAttrs = psMMUContext->psDevAttrs;
+
+ psDevAttrs->pfnPutPageSizeConfiguration(hPriv);
+}
+
+/*************************************************************************/ /*!
+@Function _MMU_MapPage
+
+@Description Map a page into the MMU. MMU_Alloc must have been called before
+ this function to allocate the page tables.
+
+@Input psMMUContext MMU context to operate on
+
+@Input psDevVAddr Device virtual address to map the page
+ into
+
+@Input sDevPAddr Device physical address of the memory
+ to map
+
+@Output pszMemspaceName PDump memory space name of the memory
+ to map
+
+@Output pszSymbolicAddr PDump symbolic address of the memory to
+ map
+
+@Output uiSymbolicAddrOffset Offset from the PDump symbolic address
+ of the memory to map
+
+@Output uiProtFlags Generic MMU protection flags
+
+@Return None
+*/
+/*****************************************************************************/
+static IMG_VOID
+_MMU_MapPage (MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_DEV_PHYADDR sDevPAddr,
+#if defined(PDUMP)
+ const IMG_CHAR *pszMemspaceName,
+ const IMG_CHAR *pszSymbolicAddr,
+ IMG_DEVMEM_OFFSET_T uiSymbolicAddrOffset,
+#endif
+ MMU_FLAGS_T uiProtFlags,
+ IMG_UINT8 uiLog2PageSize)
+{
+ const MMU_PxE_CONFIG *psConfig;
+ MMU_Levelx_INFO *psLevel;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 uiPTEIndex;
+ IMG_HANDLE hPriv;
+
+#if defined(DEBUG)
+{
+ IMG_UINT32 ui32BitLength=FloorLog2(sDevPAddr.uiAddr);
+ if (ui32BitLength > RGX_FEATURE_PHYS_BUS_WIDTH )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"_MMU_MapPage Failed. The physical address bitlength (%d) is greater than what the chip can handle (%d).",
+ ui32BitLength, RGX_FEATURE_PHYS_BUS_WIDTH));
+
+ PVR_ASSERT(ui32BitLength<=RGX_FEATURE_PHYS_BUS_WIDTH );
+ return ;
+ }
+}
+#endif
+
+ _MMU_GetPTEInfo(psMMUContext, sDevVAddr,
+ (IMG_UINT32) uiLog2PageSize, &psLevel, &uiPTEIndex, &psConfig,
+ &hPriv);
+
+ eError = _SetupPxE(psMMUContext, psLevel, uiPTEIndex,
+ psConfig, MMU_LEVEL_1, &sDevPAddr,
+#if defined(PDUMP)
+ pszMemspaceName, pszSymbolicAddr, uiSymbolicAddrOffset,
+#endif
+ uiProtFlags,
+ uiLog2PageSize);
+
+ _MMU_PutPTEInfo(psMMUContext, hPriv);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_MMU_MapPage: _SetupPxE failed"));
+ PVR_ASSERT(0);
+ return;
+ }
+
+ PVR_ASSERT(psLevel->ui32RefCount <= psLevel->ui32NumOfEntries);
+}
+
+/*************************************************************************/ /*!
+@Function _MMU_UnmapPage
+
+@Description Unmap a page from the MMU.
+
+@Input psMMUContext MMU context to operate on
+
+@Input psDevVAddr Device virtual address to unmap the page
+ from
+
+@Return None
+*/
+/*****************************************************************************/
+static IMG_VOID
+_MMU_UnmapPage (MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT8 uiLog2PageSize)
+{
+ const MMU_PxE_CONFIG *psConfig = IMG_NULL;
+ MMU_Levelx_INFO *psLevel;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 uiPTEIndex;
+ IMG_HANDLE hPriv;
+
+
+
+ _MMU_GetPTEInfo(psMMUContext, sDevVAddr, (IMG_UINT32) uiLog2PageSize,
+ &psLevel, &uiPTEIndex, &psConfig, &hPriv);
+
+ eError = _SetupPxE(psMMUContext, psLevel, uiPTEIndex, psConfig,
+ MMU_LEVEL_1, IMG_NULL,
+#if defined(PDUMP)
+ IMG_NULL, IMG_NULL, 0U,
+#endif
+ MMU_PROTFLAGS_INVALID,
+ uiLog2PageSize);
+
+ _MMU_PutPTEInfo(psMMUContext, hPriv);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPage: _SetupPxE failed"));
+ PVR_ASSERT(0);
+ return; //eError;
+ }
+
+ /* Check we haven't wrapped around */
+ PVR_ASSERT(psLevel->ui32RefCount <= psLevel->ui32NumOfEntries);
+}
+
+/*****************************************************************************
+ * Public interface functions *
+ *****************************************************************************/
+
+/*
+ MMU_ContextCreate
+*/
+PVRSRV_ERROR
+MMU_ContextCreate(PVRSRV_DEVICE_NODE *psDevNode,
+ MMU_CONTEXT **ppsMMUContext)
+{
+ MMU_CONTEXT *psMMUContext;
+ MMU_DEVICEATTRIBS *psDevAttrs;
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig;
+ const MMU_PxE_CONFIG *psConfig;
+ MMU_PHYSMEM_CONTEXT *psCtx;
+ IMG_UINT32 ui32BaseObjects;
+ IMG_UINT32 ui32Size;
+ IMG_CHAR sBuf[40];
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ psDevAttrs = psDevNode->psMMUDevAttrs;
+ psConfig = psDevAttrs->psBaseConfig;
+ psDevVAddrConfig = psDevAttrs->psTopLevelDevVAddrConfig;
+
+ switch(psDevAttrs->eTopLevel)
+ {
+ case MMU_LEVEL_3: ui32BaseObjects = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(psDevVAddrConfig->uiPCIndexMask,
+ psDevVAddrConfig->uiPCIndexShift));
+ break;
+
+ case MMU_LEVEL_2: ui32BaseObjects = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(psDevVAddrConfig->uiPDIndexMask,
+ psDevVAddrConfig->uiPDIndexShift));
+ break;
+
+ case MMU_LEVEL_1: ui32BaseObjects = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(psDevVAddrConfig->uiPTIndexMask,
+ psDevVAddrConfig->uiPTIndexShift));
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: Invalid MMU config"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ /* Allocate the MMU context with the Level 1 Px info's */
+ ui32Size = sizeof(MMU_CONTEXT) +
+ ((ui32BaseObjects - 1) * sizeof(MMU_Levelx_INFO *));
+
+ psMMUContext = OSAllocMem(ui32Size);
+ if (psMMUContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: ERROR call to OSAllocMem failed"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+
+ OSMemSet (psMMUContext, 0, ui32Size);
+
+#if defined(PDUMP)
+ /* Clear the refcount */
+ psMMUContext->ui32PDumpContextIDRefCount = 0;
+#endif
+ /* Record Device specific attributes in the context for subsequent use */
+ psMMUContext->psDevAttrs = psDevAttrs;
+ psMMUContext->psDevNode = psDevNode;
+
+ /*
+ Allocate physmem context and set it up
+ */
+ psCtx = OSAllocMem(sizeof (MMU_PHYSMEM_CONTEXT));
+ if (psCtx == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: ERROR call to OSAllocMem failed"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e1;
+ }
+ psMMUContext->psPhysMemCtx = psCtx;
+
+ OSMemSet (psCtx, 0, sizeof(MMU_PHYSMEM_CONTEXT));
+ psCtx->psDevNode = psDevNode;
+
+ OSSNPrintf(sBuf, sizeof(sBuf)-1, "pgtables %p", psCtx);
+ psCtx->uiPhysMemRANameAllocSize = OSStringLength(sBuf)+1;
+ psCtx->pszPhysMemRAName = OSAllocMem(psCtx->uiPhysMemRANameAllocSize);
+ if (psCtx->pszPhysMemRAName == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: Out of memory"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e2;
+ }
+
+ OSStringCopy(psCtx->pszPhysMemRAName, sBuf);
+
+ psCtx->psPhysMemRA = RA_Create(psCtx->pszPhysMemRAName,
+ /* subsequent import */
+ psDevNode->uiMMUPxLog2AllocGran,
+ RA_LOCKCLASS_1,
+ _MMU_PhysMem_RAImportAlloc,
+ _MMU_PhysMem_RAImportFree,
+ psCtx /* priv */);
+ if (psCtx->psPhysMemRA == IMG_NULL)
+ {
+ OSFreeMem(psCtx->pszPhysMemRAName);
+ psCtx->pszPhysMemRAName = IMG_NULL;
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e3;
+ }
+
+ /* allocate the base level object */
+ /*
+ Note: Although this is not required by the this file until
+ the 1st allocation is made, a device specific callback
+ might request the base object address so we allocate
+ it up front.
+ */
+ if (_PxMemAlloc(psMMUContext,
+ ui32BaseObjects,
+ psConfig,
+ psDevAttrs->eTopLevel,
+ &psMMUContext->sBaseLevelInfo.sMemDesc,
+ psConfig->uiLog2Align))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_ContextCreate: Failed to alloc level 1 object"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e4;
+ }
+
+ psMMUContext->sBaseLevelInfo.ui32NumOfEntries = ui32BaseObjects;
+ psMMUContext->sBaseLevelInfo.ui32RefCount = 0;
+
+ /* return context */
+ *ppsMMUContext = psMMUContext;
+
+ return PVRSRV_OK;
+
+e4:
+ RA_Delete(psCtx->psPhysMemRA);
+e3:
+ OSFreeMem(psCtx->pszPhysMemRAName);
+e2:
+ OSFreeMem(psCtx);
+e1:
+ OSFreeMem(psMMUContext);
+e0:
+ return eError;
+}
+
+/*
+ MMU_ContextDestroy
+*/
+IMG_VOID
+MMU_ContextDestroy (MMU_CONTEXT *psMMUContext)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_ContextDestroy: Enter"));
+
+ if (psPVRSRVData->eServicesState == PVRSRV_SERVICES_STATE_OK)
+ {
+ /* There should be no way to get here with live pages unless
+ there is a bug in this module or the MM code */
+ PVR_ASSERT(psMMUContext->sBaseLevelInfo.ui32RefCount == 0);
+ }
+
+ /* Free the top level MMU object */
+ _PxMemFree(psMMUContext,
+ &psMMUContext->sBaseLevelInfo.sMemDesc,
+ psMMUContext->psDevAttrs->eTopLevel);
+
+ /* Free physmem context */
+ RA_Delete(psMMUContext->psPhysMemCtx->psPhysMemRA);
+ psMMUContext->psPhysMemCtx->psPhysMemRA = IMG_NULL;
+ OSFreeMem(psMMUContext->psPhysMemCtx->pszPhysMemRAName);
+ psMMUContext->psPhysMemCtx->pszPhysMemRAName = IMG_NULL;
+
+ OSFreeMem(psMMUContext->psPhysMemCtx);
+
+ /* free the context itself. */
+ OSFreeMem(psMMUContext);
+ /*not nulling pointer, copy on stack*/
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_ContextDestroy: Exit"));
+}
+
+/*
+ MMU_Alloc
+*/
+PVRSRV_ERROR
+MMU_Alloc (MMU_CONTEXT *psMMUContext,
+ IMG_DEVMEM_SIZE_T uSize,
+ IMG_DEVMEM_SIZE_T *puActualSize,
+ IMG_UINT32 uiProtFlags,
+ IMG_DEVMEM_SIZE_T uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_UINT8 uiLog2PageSize)
+{
+ PVRSRV_ERROR eError;
+ IMG_DEV_VIRTADDR sDevVAddrEnd;
+
+
+ const MMU_PxE_CONFIG *psPDEConfig;
+ const MMU_PxE_CONFIG *psPTEConfig;
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig;
+
+ MMU_DEVICEATTRIBS *psDevAttrs;
+ IMG_HANDLE hPriv;
+
+#if !defined (DEBUG)
+ PVR_UNREFERENCED_PARAMETER(uDevVAddrAlignment);
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Alloc: uSize=0x%010llx, uiProtFlags=0x%x, align=0x%010llx", uSize, uiProtFlags, uDevVAddrAlignment));
+
+ /* check params */
+ if (!psMMUContext || !psDevVAddr || !puActualSize)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevAttrs = psMMUContext->psDevAttrs;
+
+ eError = psDevAttrs->pfnGetPageSizeConfiguration(uiLog2PageSize,
+ &psPDEConfig,
+ &psPTEConfig,
+ &psDevVAddrConfig,
+ &hPriv);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Failed to get config info (%d)", eError));
+ return eError;
+ }
+
+ /* size and alignment must be datapage granular */
+ if(((psDevVAddr->uiAddr & psDevVAddrConfig->uiPageOffsetMask) != 0)
+ || ((uSize & psDevVAddrConfig->uiPageOffsetMask) != 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: invalid address or size granularity"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ sDevVAddrEnd = *psDevVAddr;
+ sDevVAddrEnd.uiAddr += uSize;
+ eError = _AllocPageTables(psMMUContext, *psDevVAddr, sDevVAddrEnd, uiProtFlags, uiLog2PageSize);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: _DeferredAllocPagetables failed"));
+ return PVRSRV_ERROR_MMU_FAILED_TO_ALLOCATE_PAGETABLES;
+ }
+
+ psDevAttrs->pfnPutPageSizeConfiguration(hPriv);
+
+ return PVRSRV_OK;
+}
+
+/*
+ MMU_Free
+*/
+IMG_VOID
+MMU_Free (MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT8 uiLog2PageSize)
+{
+ IMG_DEV_VIRTADDR sDevVAddrEnd;
+
+ if (psMMUContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Free: invalid parameter"));
+ return;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_Free: Freeing DevVAddr 0x%010llX",
+ sDevVAddr.uiAddr));
+
+ /* ensure the address range to free is inside the heap */
+ sDevVAddrEnd = sDevVAddr;
+ sDevVAddrEnd.uiAddr += uiSize;
+
+ _FreePageTables(psMMUContext, sDevVAddr, sDevVAddrEnd, uiLog2PageSize);
+}
+
+/*
+ MMU_UnmapPages
+*/
+IMG_VOID
+MMU_UnmapPages (MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_UINT8 uiLog2PageSize)
+{
+
+ IMG_UINT32 uiPageSize = 1 << uiLog2PageSize;
+
+#if defined PDUMP
+ PDUMPCOMMENT("Invalidate the entry in %d page tables for virtual range: 0x%010llX to 0x%010llX",
+ ui32PageCount, (IMG_UINT64)sDevVAddr.uiAddr, ((IMG_UINT64)sDevVAddr.uiAddr)+(uiPageSize*ui32PageCount));
+#endif
+ while (ui32PageCount !=0)
+ {
+ _MMU_UnmapPage(psMMUContext, sDevVAddr, uiLog2PageSize);
+ sDevVAddr.uiAddr += uiPageSize;
+ ui32PageCount--;
+ }
+}
+
+/*
+ MMU_MapPMR
+*/
+PVRSRV_ERROR
+MMU_MapPMR (MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ const PMR *psPMR,
+ IMG_DEVMEM_SIZE_T uiSizeBytes,
+ PVRSRV_MEMALLOCFLAGS_T uiMappingFlags,
+ IMG_UINT8 uiLog2PageSize)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 uiCount, i;
+ IMG_UINT32 ui32MappedCount = 0;
+#if defined (MAPPING_PRIV_CHECK)
+ PMR_FLAGS_T uiPMRFlags;
+#endif
+#if defined (MAPPING_PRIV_CHECK)
+ MMU_PROTFLAGS_T uiProtFlags;
+#endif
+ IMG_DEV_PHYADDR sDevPAddr;
+#if defined(PDUMP)
+ IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
+ IMG_CHAR aszSymbolicAddress[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+ IMG_DEVMEM_OFFSET_T uiSymbolicAddrOffset;
+#endif /*PDUMP*/
+ PVRSRV_MEMALLOCFLAGS_T uiMMUProtFlags = 0;
+ IMG_UINT32 ui32GPUCacheFlags;
+ IMG_UINT32 uiPageSize = 1 << uiLog2PageSize;
+
+ PVR_ASSERT (psMMUContext != IMG_NULL);
+
+
+#if defined (MAPPING_PRIV_CHECK)
+ /* N.B. The caller _must_ have already called
+ "PMRLockSysPhysAddr()" on this PMR _before_ calling MMU_MapPMR.
+ Why? (i) Because we really want this module to concentrate on
+ page table management, and interacts the absolute minimum with
+ the PMR; and (ii) because in the future we may map PMRs in
+ partially (e.g. demand-paging scenario) and it would not be
+ right to call locksysphysaddr on each individual mapping; and
+ (iii) we've already got "unmap pages" where we don't have the
+ PMR handle (we could change the API, but I can't justify this
+ just for this). However, it may be worth re-thinking this,
+ because we'll eventually want to support mixed page sizes
+ within one allocation (rather than it being a heap attribute)
+ so we may have to move more logic into the mmu code. */
+
+ eError = PMR_Flags(psPMR, &uiPMRFlags);
+ /* guaranteed to not error as we've called Lock already */
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ uiProtFlags = (MMU_PROTFLAGS_T)(uiMapFlags & uiPMRFlags & MMU_PROTFLAGS_MASK);
+ /* check that interesting bits don't get lost in cast (due to
+ differing flag widths in s/w stack) */
+ PVR_ASSERT(uiProtFlags == (uiMapFlags & uiPMRFlags & MMU_PROTFLAGS_MASK));
+
+ /* Check that the requested mapping mode can be honoured, after
+ applying the permissions */
+ if (uiProtFlags != (uiMapFlags & MMU_PROTFLAGS_MASK))
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+#endif
+
+ /* Do flag conversion between devmem flags and MMU generic flags */
+
+ uiMMUProtFlags |= ((uiMappingFlags & PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK)
+ >> PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_OFFSET)
+ << MMU_PROTFLAGS_DEVICE_OFFSET;
+
+ if (uiMappingFlags & PVRSRV_MEMALLOCFLAG_GPU_READABLE)
+ {
+ uiMMUProtFlags |= MMU_PROTFLAGS_READABLE;
+ }
+ if (uiMappingFlags & PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE)
+ {
+ uiMMUProtFlags |= MMU_PROTFLAGS_WRITEABLE;
+ }
+ ui32GPUCacheFlags = DevmemDeviceCacheMode(uiMappingFlags);
+ switch (ui32GPUCacheFlags)
+ {
+ case PVRSRV_MEMALLOCFLAG_GPU_UNCACHED:
+ case PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE:
+ break;
+ case PVRSRV_MEMALLOCFLAG_GPU_CACHED:
+ uiMMUProtFlags |= MMU_PROTFLAGS_CACHED;
+ break;
+ default:
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ if (DevmemDeviceCacheCoherency(uiMappingFlags))
+ {
+ uiMMUProtFlags |= MMU_PROTFLAGS_CACHE_COHERENT;
+ }
+
+ /* should we verify the size and contiguity when supporting variable page size */
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Wire up Page Table entries to point to the Data Pages (%lld bytes)", uiSizeBytes);
+#endif
+
+ for (i=0, uiCount=0;
+ uiCount<uiSizeBytes;
+ i++, uiCount+=uiPageSize)
+ {
+#if defined(PDUMP)
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+#endif
+ IMG_BOOL bValid;
+ /* "uiSize" is the amount of contiguity in the underlying
+ page. Normally this would be constant for the system, but,
+ that constant needs to be communicated, in case it's ever
+ different. */
+ /* Caller guarantees that PMRLockSysPhysAddr() has already
+ been called */
+ eError = PMR_DevPhysAddr(psPMR, uiCount, &sDevPAddr, &bValid);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /* check the physical alignment of the memory to map */
+ PVR_ASSERT((sDevPAddr.uiAddr & (uiPageSize-1)) == 0);
+
+ if (bValid)
+ {
+#if defined(PDUMP)
+ eError = PMR_PDumpSymbolicAddr(psPMR, uiCount,
+ sizeof(aszMemspaceName), &aszMemspaceName[0],
+ sizeof(aszSymbolicAddress), &aszSymbolicAddress[0],
+ &uiSymbolicAddrOffset,
+ &uiNextSymName);
+ PVR_ASSERT(eError == PVRSRV_OK);
+#endif
+ _MMU_MapPage (/* Map this page into this heap: */
+ psMMUContext,
+ /* To this virtual address */
+ sDevVAddr,
+ /* Here's the physical address */
+ sDevPAddr,
+#if defined(PDUMP)
+ /* PDump symbolic address */
+ aszMemspaceName, aszSymbolicAddress, uiSymbolicAddrOffset,
+#endif
+ /* and with these flags: */
+ uiMMUProtFlags,
+ uiLog2PageSize);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapPMR: devVAddr=%10llX, size=0x%x/0x%010llx", sDevVAddr.uiAddr, uiCount, uiSizeBytes));
+
+ ui32MappedCount++;
+ }
+ /*
+ The default value of the entry is invalid so we don't need to mark
+ it as such if the page wasn't valid, we just advance pass that address
+ */
+ sDevVAddr.uiAddr += uiPageSize;
+ }
+#if defined(PDUMP)
+ PDUMPCOMMENT("Wired up %d Page Table entries (out of %d)", ui32MappedCount, i);
+#endif
+
+ return PVRSRV_OK;
+
+ /*
+ error paths follow
+ */
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*
+ MMU_AcquireBaseAddr
+*/
+PVRSRV_ERROR
+MMU_AcquireBaseAddr(MMU_CONTEXT *psMMUContext, IMG_DEV_PHYADDR *psPhysAddr)
+{
+ if (!psMMUContext)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ *psPhysAddr = psMMUContext->sBaseLevelInfo.sMemDesc.sDevPAddr;
+ return PVRSRV_OK;
+}
+
+/*
+ MMU_ReleaseBaseAddr
+*/
+IMG_VOID
+MMU_ReleaseBaseAddr(MMU_CONTEXT *psMMUContext)
+{
+ PVR_UNREFERENCED_PARAMETER(psMMUContext);
+}
+
+/*
+ MMU_SetDeviceData
+*/
+IMG_VOID MMU_SetDeviceData(MMU_CONTEXT *psMMUContext, IMG_HANDLE hDevData)
+{
+ psMMUContext->hDevData = hDevData;
+}
+
+/*
+ MMU_CheckFaultAddress
+*/
+IMG_VOID MMU_CheckFaultAddress(MMU_CONTEXT *psMMUContext, IMG_DEV_VIRTADDR *psDevVAddr)
+{
+ MMU_DEVICEATTRIBS *psDevAttrs = psMMUContext->psDevAttrs;
+ const MMU_PxE_CONFIG *psConfig;
+ const MMU_PxE_CONFIG *psMMUPDEConfig;
+ const MMU_PxE_CONFIG *psMMUPTEConfig;
+ const MMU_DEVVADDR_CONFIG *psMMUDevVAddrConfig;
+ IMG_HANDLE hPriv;
+ MMU_Levelx_INFO *psLevel;
+ PVRSRV_ERROR eError;
+ IMG_UINT64 uiIndex;
+ IMG_UINT32 ui32PCIndex;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 ui32Log2PageSize;
+
+ /*
+ At this point we don't know the page size so assume it's 4K.
+ When we get the the PD level (MMU_LEVEL_2) we can check to see
+ if this assumption is correct.
+ */
+ eError = psDevAttrs->pfnGetPageSizeConfiguration(12,
+ &psMMUPDEConfig,
+ &psMMUPTEConfig,
+ &psMMUDevVAddrConfig,
+ &hPriv);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOG(("Failed to get the page size info for log2 page sizeof 12"));
+ }
+
+ psLevel = &psMMUContext->sBaseLevelInfo;
+ psConfig = psDevAttrs->psBaseConfig;
+
+ switch(psMMUContext->psDevAttrs->eTopLevel)
+ {
+ case MMU_LEVEL_3:
+ /* Determine the PC index */
+ uiIndex = psDevVAddr->uiAddr & psDevAttrs->psTopLevelDevVAddrConfig->uiPCIndexMask;
+ uiIndex = uiIndex >> psDevAttrs->psTopLevelDevVAddrConfig->uiPCIndexShift;
+ ui32PCIndex = (IMG_UINT32) uiIndex;
+ PVR_ASSERT(uiIndex == ((IMG_UINT64) ui32PCIndex));
+
+ if (ui32PCIndex >= psLevel->ui32NumOfEntries)
+ {
+ PVR_LOG(("PC index (%d) out of bounds (%d)", ui32PCIndex, psLevel->ui32NumOfEntries));
+ break;
+ }
+
+ if (_MMU_MapCPUVAddr(&psLevel->sMemDesc) != PVRSRV_OK)
+ {
+ PVR_LOG(("Failed to map MMU MemDesc"));
+ }
+
+ if (psConfig->uiBytesPerEntry == 4)
+ {
+ IMG_UINT32 *pui32Ptr = psLevel->sMemDesc.pvCpuVAddr;
+
+ PVR_LOG(("PCE for index %d = 0x%08x and %s be valid",
+ ui32PCIndex,
+ pui32Ptr[ui32PCIndex],
+ psLevel->apsNextLevel[ui32PCIndex]?"should":"should not"));
+ }
+ else
+ {
+ IMG_UINT64 *pui64Ptr = psLevel->sMemDesc.pvCpuVAddr;
+
+ PVR_LOG(("PCE for index %d = 0x%016llx and %s be valid",
+ ui32PCIndex,
+ pui64Ptr[ui32PCIndex],
+ psLevel->apsNextLevel[ui32PCIndex]?"should":"should not"));
+ }
+
+ _MMU_UnmapCPUVAddr(&psLevel->sMemDesc);
+ _MMU_LogPxEDump(psLevel, ui32PCIndex);
+
+ psLevel = psLevel->apsNextLevel[ui32PCIndex];
+ if (!psLevel)
+ {
+ break;
+ }
+ psConfig = psMMUPDEConfig;
+ /* Fall through */
+
+ case MMU_LEVEL_2:
+ /* Determine the PD index */
+ uiIndex = psDevVAddr->uiAddr & psDevAttrs->psTopLevelDevVAddrConfig->uiPDIndexMask;
+ uiIndex = uiIndex >> psDevAttrs->psTopLevelDevVAddrConfig->uiPDIndexShift;
+ ui32PDIndex = (IMG_UINT32) uiIndex;
+ PVR_ASSERT(uiIndex == ((IMG_UINT64) ui32PDIndex));
+
+ if (ui32PDIndex >= psLevel->ui32NumOfEntries)
+ {
+ PVR_LOG(("PD index (%d) out of bounds (%d)", ui32PDIndex, psLevel->ui32NumOfEntries));
+ break;
+ }
+
+ if (_MMU_MapCPUVAddr(&psLevel->sMemDesc) != PVRSRV_OK)
+ {
+ PVR_LOG(("Failed to map MMU MemDesc"));
+ }
+
+ if (psConfig->uiBytesPerEntry == 4)
+ {
+ IMG_UINT32 *pui32Ptr = psLevel->sMemDesc.pvCpuVAddr;
+
+ PVR_LOG(("PDE for index %d = 0x%08x and %s be valid",
+ ui32PDIndex,
+ pui32Ptr[ui32PDIndex],
+ psLevel->apsNextLevel[ui32PDIndex]?"should":"should not"));
+
+ if (psDevAttrs->pfnGetPageSizeFromPDE4(pui32Ptr[ui32PDIndex], &ui32Log2PageSize) != PVRSRV_OK)
+ {
+ PVR_LOG(("Failed to get the page size from the PDE"));
+ }
+ }
+ else
+ {
+ IMG_UINT64 *pui64Ptr = psLevel->sMemDesc.pvCpuVAddr;
+
+ PVR_LOG(("PDE for index %d = 0x%016llx and %s be valid",
+ ui32PDIndex,
+ pui64Ptr[ui32PDIndex],
+ psLevel->apsNextLevel[ui32PDIndex]?"should":"should not"));
+
+ if (psDevAttrs->pfnGetPageSizeFromPDE8(pui64Ptr[ui32PDIndex], &ui32Log2PageSize) != PVRSRV_OK)
+ {
+ PVR_LOG(("Failed to get the page size from the PDE"));
+ }
+ }
+
+ _MMU_UnmapCPUVAddr(&psLevel->sMemDesc);
+ _MMU_LogPxEDump(psLevel, ui32PDIndex);
+
+ /*
+ We assumed the page size was 4K, now we have the actual size
+ from the PDE we can confirm if our assumption was correct.
+ Until now it hasn't mattered as the PC and PD are the same
+ regardless of the page size
+ */
+ if (ui32Log2PageSize != 12)
+ {
+ /* Put the 4K page size data */
+ psDevAttrs->pfnPutPageSizeConfiguration(hPriv);
+
+ /* Get the correct size data */
+ eError = psDevAttrs->pfnGetPageSizeConfiguration(ui32Log2PageSize,
+ &psMMUPDEConfig,
+ &psMMUPTEConfig,
+ &psMMUDevVAddrConfig,
+ &hPriv);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOG(("Failed to get the page size info for log2 page sizeof %d", ui32Log2PageSize));
+ break;
+ }
+ }
+ psLevel = psLevel->apsNextLevel[ui32PDIndex];
+ if (!psLevel)
+ {
+ break;
+ }
+ psConfig = psMMUPTEConfig;
+ /* Fall through */
+
+ case MMU_LEVEL_1:
+ /* Determine the PT index */
+ uiIndex = psDevVAddr->uiAddr & psMMUDevVAddrConfig->uiPTIndexMask;
+ uiIndex = uiIndex >> psMMUDevVAddrConfig->uiPTIndexShift;
+ ui32PTIndex = (IMG_UINT32) uiIndex;
+ PVR_ASSERT(uiIndex == ((IMG_UINT64) ui32PTIndex));
+
+ if (ui32PTIndex >= psLevel->ui32NumOfEntries)
+ {
+ PVR_LOG(("PT index (%d) out of bounds (%d)", ui32PTIndex, psLevel->ui32NumOfEntries));
+ break;
+ }
+
+ if (_MMU_MapCPUVAddr(&psLevel->sMemDesc) != PVRSRV_OK)
+ {
+ PVR_LOG(("Failed to map MMU MemDesc"));
+ }
+
+ if (psConfig->uiBytesPerEntry == 4)
+ {
+ IMG_UINT32 *pui32Ptr = psLevel->sMemDesc.pvCpuVAddr;
+
+ PVR_LOG(("PTE for index %d = 0x%08x",
+ ui32PTIndex,
+ pui32Ptr[ui32PTIndex]));
+ }
+ else
+ {
+ IMG_UINT64 *pui64Ptr = psLevel->sMemDesc.pvCpuVAddr;
+
+ PVR_LOG(("PTE for index %d = 0x%016llx",
+ ui32PTIndex,
+ pui64Ptr[ui32PTIndex]));
+ }
+
+ _MMU_UnmapCPUVAddr(&psLevel->sMemDesc);
+ _MMU_LogPxEDump(psLevel, ui32PTIndex);
+
+ break;
+ default:
+ PVR_LOG(("Unsupported MMU setup"));
+ break;
+ }
+}
+
+#if defined(PDUMP)
+/*
+ MMU_ContextDerivePCPDumpSymAddr
+*/
+PVRSRV_ERROR MMU_ContextDerivePCPDumpSymAddr(MMU_CONTEXT *psMMUContext,
+ IMG_CHAR *pszPDumpSymbolicNameBuffer,
+ IMG_SIZE_T uiPDumpSymbolicNameBufferSize)
+{
+ IMG_SIZE_T uiCount;
+ IMG_UINT64 ui64PhysAddr;
+ PVRSRV_DEVICE_IDENTIFIER *psDevId = &psMMUContext->psDevNode->sDevId;
+
+ if (!psMMUContext->sBaseLevelInfo.sMemDesc.bValid)
+ {
+ /* We don't have any allocations. You're not allowed to ask
+ for the page catalogue base address until you've made at
+ least one allocation */
+ return PVRSRV_ERROR_MMU_API_PROTOCOL_ERROR;
+ }
+
+ ui64PhysAddr = (IMG_UINT64)psMMUContext->sBaseLevelInfo.sMemDesc.sDevPAddr.uiAddr;
+
+ PVR_ASSERT(uiPDumpSymbolicNameBufferSize >= (IMG_UINT32)(21 + OSStringLength(psDevId->pszPDumpDevName)));
+
+ /* Page table Symbolic Name is formed from page table phys addr
+ prefixed with MMUPT_. */
+
+ uiCount = OSSNPrintf(pszPDumpSymbolicNameBuffer,
+ uiPDumpSymbolicNameBufferSize,
+ ":%s:%s%016llX",
+ psDevId->pszPDumpDevName,
+ psMMUContext->sBaseLevelInfo.sMemDesc.bValid?"MMUPC_":"XXX",
+ ui64PhysAddr);
+
+ if (uiCount + 1 > uiPDumpSymbolicNameBufferSize)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+/*
+ MMU_PDumpWritePageCatBase
+*/
+PVRSRV_ERROR
+MMU_PDumpWritePageCatBase(MMU_CONTEXT *psMMUContext,
+ const IMG_CHAR *pszSpaceName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32WordSize,
+ IMG_UINT32 ui32AlignShift,
+ IMG_UINT32 ui32Shift,
+ PDUMP_FLAGS_T uiPdumpFlags)
+{
+ PVRSRV_ERROR eError;
+ IMG_CHAR aszPageCatBaseSymbolicAddr[100];
+ const IMG_CHAR *pszPDumpDevName = psMMUContext->psDevNode->pszMMUPxPDumpMemSpaceName;
+
+
+ eError = MMU_ContextDerivePCPDumpSymAddr(psMMUContext,
+ &aszPageCatBaseSymbolicAddr[0],
+ sizeof(aszPageCatBaseSymbolicAddr));
+ if (eError == PVRSRV_OK)
+ {
+ eError = PDumpWriteSymbAddress(pszSpaceName,
+ uiOffset,
+ aszPageCatBaseSymbolicAddr,
+ 0, /* offset -- Could be non-zero for var. pgsz */
+ pszPDumpDevName,
+ ui32WordSize,
+ ui32AlignShift,
+ ui32Shift,
+ uiPdumpFlags | PDUMP_FLAGS_CONTINUOUS);
+ }
+
+ return eError;
+}
+
+/*
+ MMU_AcquirePDumpMMUContext
+*/
+PVRSRV_ERROR MMU_AcquirePDumpMMUContext(MMU_CONTEXT *psMMUContext,
+ IMG_UINT32 *pui32PDumpMMUContextID)
+{
+ PVRSRV_DEVICE_IDENTIFIER *psDevId = &psMMUContext->psDevNode->sDevId;
+
+ if (!psMMUContext->ui32PDumpContextIDRefCount)
+ {
+ PDUMP_MMU_ALLOC_MMUCONTEXT(psDevId->pszPDumpDevName,
+ psMMUContext->sBaseLevelInfo.sMemDesc.sDevPAddr,
+ psMMUContext->psDevAttrs->eMMUType,
+ &psMMUContext->uiPDumpContextID);
+ }
+
+ psMMUContext->ui32PDumpContextIDRefCount++;
+ *pui32PDumpMMUContextID = psMMUContext->uiPDumpContextID;
+
+ return PVRSRV_OK;
+}
+
+/*
+ MMU_ReleasePDumpMMUContext
+*/
+PVRSRV_ERROR MMU_ReleasePDumpMMUContext(MMU_CONTEXT *psMMUContext)
+{
+ PVRSRV_DEVICE_IDENTIFIER *psDevId = &psMMUContext->psDevNode->sDevId;
+
+ PVR_ASSERT(psMMUContext->ui32PDumpContextIDRefCount != 0);
+ psMMUContext->ui32PDumpContextIDRefCount--;
+
+ if (psMMUContext->ui32PDumpContextIDRefCount == 0)
+ {
+ PDUMP_MMU_FREE_MMUCONTEXT(psDevId->pszPDumpDevName,
+ psMMUContext->uiPDumpContextID);
+ }
+
+ return PVRSRV_OK;
+}
+#endif
+
+/******************************************************************************
+ End of file (mmu_common.c)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/rogue/services/server/common/pdump_common.c b/drivers/gpu/rogue/services/server/common/pdump_common.c
new file mode 100644
index 000000000000..a6341e6ab4d0
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/pdump_common.c
@@ -0,0 +1,2671 @@
+/*************************************************************************/ /*!
+@File
+@Title Common Server PDump functions layer
+@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(PDUMP)
+#include <stdarg.h>
+
+#include "pvrversion.h"
+#include "allocmem.h"
+#include "osfunc.h"
+#include "pvrsrv.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "pdump_physmem.h"
+#include "hash.h"
+#include "connection_server.h"
+#include "sync_server.h"
+
+/* pdump headers */
+#include "dbgdrvif_srv5.h"
+#include "pdump_osfunc.h"
+#include "pdump_km.h"
+
+/* Allow temporary buffer size override */
+#if !defined(PDUMP_TEMP_BUFFER_SIZE)
+#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024U)
+#endif
+
+/* DEBUG */
+#if 0
+#define PDUMP_DBG(a) PDumpOSDebugPrintf (a)
+#else
+#define PDUMP_DBG(a)
+#endif
+
+
+#define PTR_PLUS(t, p, x) ((t)(((IMG_CHAR *)(p)) + (x)))
+#define VPTR_PLUS(p, x) PTR_PLUS(IMG_VOID *, p, x)
+#define VPTR_INC(p, x) ((p) = VPTR_PLUS(p, x))
+#define MAX_PDUMP_MMU_CONTEXTS (32)
+static IMG_VOID *gpvTempBuffer = IMG_NULL;
+
+#define PERSISTANT_MAGIC ((IMG_UINTPTR_T) 0xe33ee33e)
+#define PDUMP_PERSISTENT_HASH_SIZE 10
+
+#define PDUMP_PRM_FILE_NAME_MAX 32 /*|< Size of parameter name used*/
+#define PDUMP_PRM_FILE_SIZE_MAX 0x7FDFFFFF /*!< Default maximum file size to split output files, 2GB-2MB as fwrite limits it to 2GB-1 on 32bit systems */
+
+
+static HASH_TABLE *g_psPersistentHash = IMG_NULL;
+
+static IMG_BOOL g_PDumpInitialised = IMG_FALSE;
+static IMG_UINT32 g_ConnectionCount = 0;
+
+
+typedef struct
+{
+ PDUMP_CHANNEL sCh; /*!< Channel handles */
+} PDUMP_SCRIPT;
+
+typedef struct
+{
+ IMG_UINT32 ui32Init; /*|< Count of bytes written to the init phase stream */
+ IMG_UINT32 ui32Main; /*!< Count of bytes written to the main stream */
+ IMG_UINT32 ui32Deinit; /*!< Count of bytes written to the deinit stream */
+} PDUMP_CHANNEL_WOFFSETS;
+
+typedef struct
+{
+ PDUMP_CHANNEL sCh; /*!< Channel handles */
+ PDUMP_CHANNEL_WOFFSETS sWOff; /*!< Channel file write offsets */
+ IMG_UINT32 ui32FileIdx; /*!< File index used when file size limit reached and a new file is started, parameter channel only */
+ IMG_UINT32 ui32MaxFileSize; /*!< Maximum file size for parameter files */
+
+ PDUMP_FILEOFFSET_T uiZeroPageOffset; /*!< Offset of the zero page in the parameter file */
+ IMG_SIZE_T uiZeroPageSize; /*!< Size of the zero page in the parameter file */
+ IMG_CHAR szZeroPageFilename[PDUMP_PRM_FILE_NAME_MAX]; /*< PRM file name where the zero page was pdumped */
+} PDUMP_PARAMETERS;
+
+static PDUMP_SCRIPT g_PDumpScript = { { 0, 0, 0} };
+static PDUMP_PARAMETERS g_PDumpParameters = { { 0, 0, 0}, {0, 0, 0}, 0, PDUMP_PRM_FILE_SIZE_MAX};
+
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+/* counter increments each time debug write is called */
+IMG_UINT32 g_ui32EveryLineCounter = 1U;
+#endif
+
+#if defined(PDUMP_DEBUG) || defined(REFCOUNT_DEBUG)
+#define PDUMP_REFCOUNT_PRINT(fmt, ...) PVRSRVDebugPrintf(PVR_DBG_WARNING, __FILE__, __LINE__, fmt, __VA_ARGS__)
+#else
+#define PDUMP_REFCOUNT_PRINT(fmt, ...)
+#endif
+
+/* Prototype for the test/debug state dump rotuine used in debugging */
+IMG_VOID PDumpCommonDumpState(IMG_BOOL bDumpOSLayerState);
+#undef PDUMP_TRACE_STATE
+
+
+/*****************************************************************************/
+/* PDump Control Module Definitions */
+/*****************************************************************************/
+
+typedef struct _PDUMP_CAPTURE_RANGE_
+{
+ IMG_UINT32 ui32Start; /*!< Start frame number of range */
+ IMG_UINT32 ui32End; /*!< Send frame number of range */
+ IMG_UINT32 ui32Interval; /*!< Frame sample rate interval */
+} PDUMP_CAPTURE_RANGE;
+
+/* No direct access to members from outside the control module - please */
+typedef struct _PDUMP_CTRL_STATE_
+{
+ IMG_BOOL bInitPhaseActive; /*!< State of driver initialisation phase */
+ IMG_UINT32 ui32Flags; /*!< Unused */
+
+ IMG_UINT32 ui32DefaultCapMode; /*!< Capture mode of the dump */
+ PDUMP_CAPTURE_RANGE sDefaultRange; /*|< The default capture range */
+ IMG_UINT32 ui32CurrentFrame; /*!< Current frame number */
+
+ IMG_BOOL bCaptureOn; /*!< Current capture status, is current frame in range */
+ IMG_BOOL bSuspended; /*!< Suspend flag set on unrecoverable error */
+ IMG_BOOL bInPowerTransition; /*!< Device power transition state */
+} PDUMP_CTRL_STATE;
+
+static PDUMP_CTRL_STATE g_PDumpCtrl =
+{
+ IMG_TRUE,
+ 0,
+
+ 0, /*!< Value obtained from OS PDump layer during initialisation */
+ {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 1
+ },
+ 0,
+
+ IMG_FALSE,
+ IMG_FALSE,
+ IMG_FALSE
+};
+
+IMG_VOID PDumpCtrlInit(IMG_UINT32 ui32InitCapMode)
+{
+ g_PDumpCtrl.ui32DefaultCapMode = ui32InitCapMode;
+ PVR_ASSERT(g_PDumpCtrl.ui32DefaultCapMode != 0);
+}
+
+static IMG_VOID PDumpCtrlUpdateCaptureStatus(IMG_VOID)
+{
+ if (g_PDumpCtrl.ui32DefaultCapMode == DEBUG_CAPMODE_FRAMED)
+ {
+ if ((g_PDumpCtrl.ui32CurrentFrame >= g_PDumpCtrl.sDefaultRange.ui32Start) &&
+ (g_PDumpCtrl.ui32CurrentFrame <= g_PDumpCtrl.sDefaultRange.ui32End) &&
+ (((g_PDumpCtrl.ui32CurrentFrame - g_PDumpCtrl.sDefaultRange.ui32Start) % g_PDumpCtrl.sDefaultRange.ui32Interval) == 0))
+ {
+ g_PDumpCtrl.bCaptureOn = IMG_TRUE;
+ }
+ else
+ {
+ g_PDumpCtrl.bCaptureOn = IMG_FALSE;
+ }
+ }
+ else if (g_PDumpCtrl.ui32DefaultCapMode == DEBUG_CAPMODE_CONTINUOUS)
+ {
+ g_PDumpCtrl.bCaptureOn = IMG_TRUE;
+ }
+ else
+ {
+ g_PDumpCtrl.bCaptureOn = IMG_FALSE;
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCtrlSetCurrentFrame: Unexpected capture mode (%x)", g_PDumpCtrl.ui32DefaultCapMode));
+ }
+
+}
+
+IMG_VOID PDumpCtrlSetDefaultCaptureParams(IMG_UINT32 ui32Mode, IMG_UINT32 ui32Start, IMG_UINT32 ui32End, IMG_UINT32 ui32Interval)
+{
+ PVR_ASSERT(ui32Interval > 0);
+ PVR_ASSERT(ui32End >= ui32Start);
+ PVR_ASSERT((ui32Mode == DEBUG_CAPMODE_FRAMED) || (ui32Mode == DEBUG_CAPMODE_CONTINUOUS));
+
+ /*
+ Set the default capture range to that supplied by the PDump client tool
+ */
+ g_PDumpCtrl.ui32DefaultCapMode = ui32Mode;
+ g_PDumpCtrl.sDefaultRange.ui32Start = ui32Start;
+ g_PDumpCtrl.sDefaultRange.ui32End = ui32End;
+ g_PDumpCtrl.sDefaultRange.ui32Interval = ui32Interval;
+
+ /*
+ Reset the current frame on reset of the default capture range, helps
+ avoid inter-pdump start frame issues when the driver is not reloaded.
+ */
+ PDumpCtrlSetCurrentFrame(0);
+}
+
+INLINE IMG_BOOL PDumpCtrlCapModIsFramed(IMG_VOID)
+{
+ return g_PDumpCtrl.ui32DefaultCapMode == DEBUG_CAPMODE_FRAMED;
+}
+
+INLINE IMG_BOOL PDumpCtrlCapModIsContinuous(IMG_VOID)
+{
+ return g_PDumpCtrl.ui32DefaultCapMode == DEBUG_CAPMODE_CONTINUOUS;
+}
+
+IMG_UINT32 PDumpCtrlGetCurrentFrame(IMG_VOID)
+{
+ return g_PDumpCtrl.ui32CurrentFrame;
+}
+
+IMG_VOID PDumpCtrlSetCurrentFrame(IMG_UINT32 ui32Frame)
+{
+ g_PDumpCtrl.ui32CurrentFrame = ui32Frame;
+ /* Mirror the value into the debug driver */
+ PDumpOSSetFrame(ui32Frame);
+
+ PDumpCtrlUpdateCaptureStatus();
+
+#if defined(PDUMP_TRACE_STATE)
+ PDumpCommonDumpState(IMG_FALSE);
+#endif
+}
+
+INLINE IMG_BOOL PDumpCtrlCaptureOn(IMG_VOID)
+{
+ return !g_PDumpCtrl.bSuspended && g_PDumpCtrl.bCaptureOn;
+}
+
+INLINE IMG_BOOL PDumpCtrlCaptureRangePast(IMG_VOID)
+{
+ return (g_PDumpCtrl.ui32CurrentFrame > g_PDumpCtrl.sDefaultRange.ui32End);
+}
+
+/* Used to imply if the PDump client is connected or not. */
+INLINE IMG_BOOL PDumpCtrlCaptureRangeUnset(IMG_VOID)
+{
+ return ((g_PDumpCtrl.sDefaultRange.ui32Start == 0xFFFFFFFFU) &&
+ (g_PDumpCtrl.sDefaultRange.ui32End == 0xFFFFFFFFU));
+}
+
+IMG_BOOL PDumpCtrIsLastCaptureFrame(IMG_VOID)
+{
+ if (g_PDumpCtrl.ui32DefaultCapMode == DEBUG_CAPMODE_FRAMED)
+ {
+ /* Is the next capture frame within the range end limit? */
+ if ((g_PDumpCtrl.ui32CurrentFrame + g_PDumpCtrl.sDefaultRange.ui32Interval) > g_PDumpCtrl.sDefaultRange.ui32End)
+ {
+ return IMG_TRUE;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCtrIsLastCaptureFrame: Unexpected capture mode (%x)", g_PDumpCtrl.ui32DefaultCapMode));
+ }
+
+ /* Return false for continuous capture mode or when in framed mode */
+ return IMG_FALSE;
+}
+
+INLINE IMG_BOOL PDumpCtrlInitPhaseComplete(IMG_VOID)
+{
+ return !g_PDumpCtrl.bInitPhaseActive;
+}
+
+INLINE IMG_VOID PDumpCtrlSetInitPhaseComplete(IMG_BOOL bIsComplete)
+{
+ if (bIsComplete)
+ {
+ g_PDumpCtrl.bInitPhaseActive = IMG_FALSE;
+ PDUMP_HEREA(102);
+ }
+ else
+ {
+ g_PDumpCtrl.bInitPhaseActive = IMG_TRUE;
+ PDUMP_HEREA(103);
+ }
+}
+
+INLINE IMG_VOID PDumpCtrlSuspend(IMG_VOID)
+{
+ PDUMP_HEREA(104);
+ g_PDumpCtrl.bSuspended = IMG_TRUE;
+}
+
+INLINE IMG_VOID PDumpCtrlResume(IMG_VOID)
+{
+ PDUMP_HEREA(105);
+ g_PDumpCtrl.bSuspended = IMG_FALSE;
+}
+
+INLINE IMG_BOOL PDumpCtrlIsDumpSuspended(IMG_VOID)
+{
+ return g_PDumpCtrl.bSuspended;
+}
+
+IMG_VOID PDumpCtrlPowerTransitionStart(IMG_VOID)
+{
+ g_PDumpCtrl.bInPowerTransition = IMG_TRUE;
+}
+
+IMG_VOID PDumpCtrlPowerTransitionEnd(IMG_VOID)
+{
+ g_PDumpCtrl.bInPowerTransition = IMG_FALSE;
+}
+
+INLINE IMG_BOOL PDumpCtrlInPowerTransition(IMG_VOID)
+{
+ return g_PDumpCtrl.bInPowerTransition;
+}
+
+
+/*****************************************************************************/
+/* PDump Common Write Layer just above PDump OS Layer */
+/*****************************************************************************/
+
+
+/*
+ Checks in this method were seeded from the original PDumpWriteILock()
+ and DBGDrivWriteCM() and have grown since to ensure PDump output
+ matches legacy output.
+ 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)
+{
+ /* No writes if in framed mode and range pasted */
+ if (PDumpCtrlCaptureRangePast())
+ {
+ PDUMP_HERE(10);
+ return IMG_FALSE;
+ }
+
+ /* No writes while writing is suspended */
+ if (PDumpCtrlIsDumpSuspended())
+ {
+ PDUMP_HERE(11);
+ return IMG_FALSE;
+ }
+
+ /* Prevent PDumping during a power transition */
+ if (PDumpCtrlInPowerTransition())
+ { /* except when it's flagged */
+ if (ui32Flags & PDUMP_FLAGS_POWER)
+ {
+ PDUMP_HERE(20);
+ return IMG_TRUE;
+ }
+ PDUMP_HERE(16);
+ return IMG_FALSE;
+ }
+
+ /* Always allow dumping in init phase and when persistent flagged */
+ if (ui32Flags & PDUMP_FLAGS_PERSISTENT)
+ {
+ PDUMP_HERE(12);
+ return IMG_TRUE;
+ }
+ if (!PDumpCtrlInitPhaseComplete())
+ {
+ PDUMP_HERE(15);
+ return IMG_TRUE;
+ }
+
+ /* The following checks are made when the driver has completed initialisation */
+
+ /* If PDump client connected allow continuous flagged writes */
+ if (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ {
+ if (PDumpCtrlCaptureRangeUnset()) /* Is client connected? */
+ {
+ PDUMP_HERE(13);
+ return IMG_FALSE;
+ }
+ PDUMP_HERE(14);
+ return IMG_TRUE;
+ }
+
+ /* No last/deinit statements allowed when not in initialisation phase */
+ if (ui32Flags & PDUMP_FLAGS_DEINIT)
+ {
+ if (PDumpCtrlInitPhaseComplete())
+ {
+ PDUMP_HERE(17);
+ PVR_DPF((PVR_DBG_ERROR, "PDumpWriteAllowed: DEINIT flag used at the wrong time outside of initialisation!"));
+ return IMG_FALSE;
+ }
+ }
+
+ /*
+ If no flags are provided then it is FRAMED output and the frame
+ range must be checked matching expected behaviour.
+ */
+ if (PDumpCtrlCapModIsFramed() && !PDumpCtrlCaptureOn())
+ {
+ PDUMP_HERE(18);
+ return IMG_FALSE;
+ }
+
+ PDUMP_HERE(19);
+
+ /* Allow the write to take place */
+ return IMG_TRUE;
+}
+
+#undef PDUMP_DEBUG_SCRIPT_LINES
+
+#if defined(PDUMP_DEBUG_SCRIPT_LINES)
+#define PDUMPOSDEBUGDRIVERWRITE(a,b,c,d) _PDumpOSDebugDriverWrite(a,b,c,d)
+static IMG_UINT32 _PDumpOSDebugDriverWrite( IMG_HANDLE psStream,
+ IMG_UINT8 *pui8Data,
+ IMG_UINT32 ui32BCount,
+ IMG_UINT32 ui32Flags)
+{
+ IMG_CHAR tmp1[80];
+ IMG_CHAR* streamName = "unkn";
+
+ if (g_PDumpScript.sCh.hDeinit == psStream)
+ streamName = "dein";
+ else if (g_PDumpScript.sCh.hInit == psStream)
+ streamName = "init";
+ else if (g_PDumpScript.sCh.hMain == psStream)
+ streamName = "main";
+
+ (void) PDumpOSSprintf(tmp1, 80, "-- %s, %x\n", streamName, ui32Flags);
+ (void) PDumpOSDebugDriverWrite(psStream, tmp1, OSStringLength(tmp1));
+
+ return PDumpOSDebugDriverWrite(psStream, pui8Data, ui32BCount);
+}
+#else
+#define PDUMPOSDEBUGDRIVERWRITE(a,b,c,d) PDumpOSDebugDriverWrite(a,b,c)
+#endif
+
+
+/**************************************************************************/ /*!
+ @Function PDumpWriteToBuffer
+ @Description Write the supplied data to the PDump stream buffer and attempt
+ to handle any buffer full conditions to ensure all the data
+ requested to be written, is.
+
+ @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
+ @Input ui32Flags PDump statement flags.
+
+ @Return IMG_UINT32 Actual number of bytes written, may be less than
+ ui32BCount when buffer full condition could not
+ be avoided.
+*/ /***************************************************************************/
+static IMG_UINT32 PDumpWriteToBuffer(IMG_HANDLE psStream, IMG_UINT8 *pui8Data,
+ IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32BytesWritten = 0;
+ IMG_UINT32 ui32Off = 0;
+
+ while (ui32BCount > 0)
+ {
+ ui32BytesWritten = PDUMPOSDEBUGDRIVERWRITE(psStream, &pui8Data[ui32Off], ui32BCount, ui32Flags);
+
+ if (ui32BytesWritten == 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "PDumpWriteToBuffer: Zero bytes written - release execution"));
+ PDumpOSReleaseExecution();
+ }
+
+ if (ui32BytesWritten != 0xFFFFFFFFU)
+ {
+ if (ui32BCount != ui32BytesWritten)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "PDumpWriteToBuffer: partial write of %d bytes of %d bytes", ui32BytesWritten, ui32BCount));
+ }
+ ui32Off += ui32BytesWritten;
+ ui32BCount -= ui32BytesWritten;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpWriteToBuffer: Unrecoverable error received from the debug driver"));
+ if( PDumpOSGetCtrlState(psStream, DBG_GET_STATE_FLAG_IS_READONLY) )
+ {
+ /* Fatal -suspend PDump to prevent flooding kernel log buffer */
+ PVR_LOG(("PDump suspended, debug driver out of memory"));
+ PDumpCtrlSuspend();
+ }
+ return 0;
+ }
+ }
+
+ /* reset buffer counters */
+ ui32BCount = ui32Off; ui32Off = 0; ui32BytesWritten = 0;
+
+ return ui32BCount;
+}
+
+
+/**************************************************************************/ /*!
+ @Function PDumpWriteToChannel
+ @Description Write the supplied data to the PDump channel specified obeying
+ flags to write to the necessary channel buffers.
+
+ @Input psChannel The address of the script or parameter channel object
+ @Input/Output psWOff The address of the channel write offsets object to
+ update on successful writing
+ @Input pui8Data Pointer to the data to be written
+ @Input ui32Size Number of bytes to write
+ @Input ui32Flags PDump statement flags, they may be clear (no flags)
+ which implies framed data, continuous flagged,
+ persistent flagged, or continuous AND persistent
+ flagged and they determine how the data is output.
+ On the first test app run after driver load, the
+ Display Controller dumps a resource that is both
+ continuous and persistent and this needs writing to
+ both the init (persistent) and main (continuous)
+ channel buffers to ensure the data is dumped in
+ subsequent test runs without reloading the driver.
+ In subsequent runs the PDump client 'freezes' the
+ init buffer so that only one dump of persistent data
+ for the "extended init phase" is captured to 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)
+{
+ IMG_UINT32 ui32BytesWritten = 0;
+
+ PDUMP_HERE(210);
+
+ /* Dump data to deinit buffer when flagged as deinit */
+ if (ui32Flags & PDUMP_FLAGS_DEINIT)
+ {
+ PDUMP_HERE(211);
+ ui32BytesWritten = PDumpWriteToBuffer(psChannel->hDeinit, 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));
+ PDUMP_HERE(212);
+ return IMG_FALSE;
+ }
+
+ if (psWOff)
+ {
+ psWOff->ui32Deinit += ui32Size;
+ }
+
+ }
+ else
+ {
+ IMG_BOOL bDumpedToInitAlready = IMG_FALSE;
+ IMG_HANDLE* phStream = IMG_NULL;
+ IMG_UINT32* pui32Offset = IMG_NULL;
+
+ /* Always append persistent data to init phase so it's available on
+ * subsequent app runs, but also to the main stream if client connected */
+ if (ui32Flags & PDUMP_FLAGS_PERSISTENT)
+ {
+ PDUMP_HERE(213);
+ ui32BytesWritten = PDumpWriteToBuffer( psChannel->hInit, 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));
+ PDUMP_HERE(214);
+ return IMG_FALSE;
+ }
+
+ bDumpedToInitAlready = IMG_TRUE;
+ if (psWOff)
+ {
+ psWOff->ui32Init += ui32Size;
+ }
+
+ /* Don't write continuous data if client not connected */
+ if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) && PDumpCtrlCaptureRangeUnset())
+ {
+ return IMG_TRUE;
+ }
+ }
+
+ /* Prepare to write the data to the main stream for
+ * persistent, continuous or framed data. Override and use init
+ * stream if driver still in init phase and we have not written
+ * to it yet.*/
+ if (!PDumpCtrlInitPhaseComplete() && !bDumpedToInitAlready)
+ {
+ PDUMP_HERE(215);
+ phStream = &psChannel->hInit;
+ if (psWOff)
+ {
+ pui32Offset = &psWOff->ui32Init;
+ }
+ }
+ else
+ {
+ PDUMP_HERE(216);
+ phStream = &psChannel->hMain;
+ if (psWOff)
+ {
+ pui32Offset = &psWOff->ui32Main;
+ }
+ }
+
+ /* Write the data to the stream */
+ ui32BytesWritten = PDumpWriteToBuffer(*phStream, 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));
+ PDUMP_HERE(217);
+ return IMG_FALSE;
+ }
+
+ if (pui32Offset)
+ {
+ *pui32Offset += ui32BytesWritten;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+
+PVRSRV_ERROR PDumpWriteParameter(IMG_UINT8 *pui8Data, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags,
+ IMG_UINT32* pui32FileOffset, IMG_CHAR* aszFilenameStr)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(pui8Data && (ui32Size!=0));
+ PVR_ASSERT(pui32FileOffset && aszFilenameStr);
+
+ PDUMP_HERE(1);
+
+ if (!PDumpWriteAllowed(ui32Flags))
+ {
+ /* Abort write for the above reasons but indicated it was OK to
+ * caller to avoid disrupting the driver */
+ return PVRSRV_OK;
+ }
+
+ PDUMP_HERE(2);
+
+ if (!PDumpCtrlInitPhaseComplete() || (ui32Flags & PDUMP_FLAGS_PERSISTENT))
+ {
+ PDUMP_HERE(3);
+
+ /* Init phase stream not expected to get above the file size max */
+ PVR_ASSERT(g_PDumpParameters.sWOff.ui32Init < g_PDumpParameters.ui32MaxFileSize);
+
+ /* Return the file write offset at which the parameter data was dumped */
+ *pui32FileOffset = g_PDumpParameters.sWOff.ui32Init;
+ }
+ else
+ {
+ PDUMP_HERE(4);
+
+ /* Do we need to signal the PDump client that a split is required? */
+ if (g_PDumpParameters.sWOff.ui32Main + ui32Size > g_PDumpParameters.ui32MaxFileSize)
+ {
+ PDUMP_HERE(5);
+ PDumpOSSetSplitMarker(g_PDumpParameters.sCh.hMain, g_PDumpParameters.sWOff.ui32Main);
+ g_PDumpParameters.ui32FileIdx++;
+ g_PDumpParameters.sWOff.ui32Main = 0;
+ }
+
+ /* Return the file write offset at which the parameter data was dumped */
+ *pui32FileOffset = g_PDumpParameters.sWOff.ui32Main;
+ }
+
+ /* Create the parameter file name, based on index, to be used in the script */
+ if (g_PDumpParameters.ui32FileIdx == 0)
+ {
+ eError = PDumpOSSprintf(aszFilenameStr, PDUMP_PRM_FILE_NAME_MAX, PDUMP_PARAM_0_FILE_NAME);
+ }
+ else
+ {
+ PDUMP_HERE(6);
+ eError = PDumpOSSprintf(aszFilenameStr, PDUMP_PRM_FILE_NAME_MAX, PDUMP_PARAM_N_FILE_NAME, g_PDumpParameters.ui32FileIdx);
+ }
+ PVR_LOGG_IF_ERROR(eError, "PDumpOSSprintf", errExit);
+
+ /* 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))
+ {
+ PDUMP_HERE(7);
+ PVR_LOGG_IF_ERROR(eError, "PDumpWrite", errExit);
+ }
+
+ return PVRSRV_OK;
+
+errExit:
+ return eError;
+}
+
+
+IMG_BOOL PDumpWriteScript(IMG_HANDLE hString, IMG_UINT32 ui32Flags)
+{
+ PVR_ASSERT(hString);
+
+ PDUMP_HERE(201);
+
+ if (!PDumpWriteAllowed(ui32Flags))
+ {
+ /* Abort write for the above reasons but indicated it was OK to
+ * caller to avoid disrupting the driver */
+ return IMG_TRUE;
+ }
+
+ return PDumpWriteToChannel(&g_PDumpScript.sCh, IMG_NULL, (IMG_UINT8*) hString, (IMG_UINT32) OSStringLength((IMG_CHAR*) hString), ui32Flags);
+}
+
+
+/*****************************************************************************/
+
+
+
+
+
+
+struct _PDUMP_CONNECTION_DATA_ {
+ IMG_UINT32 ui32RefCount;
+ POS_LOCK hLock;
+ DLLIST_NODE sListHead;
+ IMG_BOOL bLastInto;
+ IMG_UINT32 ui32LastSetFrameNumber;
+ IMG_BOOL bWasInCaptureRange;
+ IMG_BOOL bIsInCaptureRange;
+ IMG_BOOL bLastTransitionFailed;
+ SYNC_CONNECTION_DATA *psSyncConnectionData;
+};
+
+static PDUMP_CONNECTION_DATA * _PDumpConnectionAcquire(PDUMP_CONNECTION_DATA *psPDumpConnectionData)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psPDumpConnectionData->hLock);
+ ui32RefCount = ++psPDumpConnectionData->ui32RefCount;
+ OSLockRelease(psPDumpConnectionData->hLock);
+
+ PDUMP_REFCOUNT_PRINT("%s: PDump connection %p, refcount = %d",
+ __FUNCTION__, psPDumpConnectionData, ui32RefCount);
+
+ return psPDumpConnectionData;
+}
+
+static IMG_VOID _PDumpConnectionRelease(PDUMP_CONNECTION_DATA *psPDumpConnectionData)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psPDumpConnectionData->hLock);
+ ui32RefCount = --psPDumpConnectionData->ui32RefCount;
+ OSLockRelease(psPDumpConnectionData->hLock);
+
+ if (ui32RefCount == 0)
+ {
+ OSLockDestroy(psPDumpConnectionData->hLock);
+ PVR_ASSERT(dllist_is_empty(&psPDumpConnectionData->sListHead));
+ OSFreeMem(psPDumpConnectionData);
+ }
+
+ PDUMP_REFCOUNT_PRINT("%s: PDump connection %p, refcount = %d",
+ __FUNCTION__, psPDumpConnectionData, ui32RefCount);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpIsPersistent)
+#endif
+
+IMG_BOOL PDumpIsPersistent(IMG_VOID)
+{
+ IMG_PID uiPID = OSGetCurrentProcessIDKM();
+ IMG_UINTPTR_T puiRetrieve;
+
+ puiRetrieve = HASH_Retrieve(g_psPersistentHash, uiPID);
+ if (puiRetrieve != 0)
+ {
+ PVR_ASSERT(puiRetrieve == PERSISTANT_MAGIC);
+ PDUMP_HEREA(110);
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+
+/**************************************************************************
+ * Function Name : GetTempBuffer
+ * Inputs : None
+ * Outputs : None
+ * Returns : Temporary buffer address, or IMG_NULL
+ * Description : Get temporary buffer address.
+**************************************************************************/
+static IMG_VOID *GetTempBuffer(IMG_VOID)
+{
+ /*
+ * Allocate the temporary buffer, it it hasn't been allocated already.
+ * Return the address of the temporary buffer, or IMG_NULL if it
+ * couldn't be allocated.
+ * It is expected that the buffer will be allocated once, at driver
+ * load time, and left in place until the driver unloads.
+ */
+
+ if (gpvTempBuffer == IMG_NULL)
+ {
+ gpvTempBuffer = OSAllocMem(PDUMP_TEMP_BUFFER_SIZE);
+ if (gpvTempBuffer == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetTempBuffer: OSAllocMem failed"));
+ }
+ }
+
+ return gpvTempBuffer;
+}
+
+static IMG_VOID FreeTempBuffer(IMG_VOID)
+{
+
+ if (gpvTempBuffer != IMG_NULL)
+ {
+ OSFreeMem(gpvTempBuffer);
+ gpvTempBuffer = IMG_NULL;
+ }
+}
+
+/**************************************************************************
+ * Function Name : PDumpParameterChannelZeroedPageBlock
+ * Inputs : None
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Set up the zero page block in the parameter stream
+**************************************************************************/
+static PVRSRV_ERROR PDumpParameterChannelZeroedPageBlock(IMG_VOID)
+{
+ IMG_UINT8 aui8Zero[32] = { 0 };
+ IMG_SIZE_T uiBytesToWrite;
+ PVRSRV_ERROR eError;
+
+ g_PDumpParameters.uiZeroPageSize = OSGetPageSize();
+
+ /* ensure the zero page size of a multiple of the zero source on the stack */
+ PVR_ASSERT(g_PDumpParameters.uiZeroPageSize % sizeof(aui8Zero) == 0);
+
+ /* the first write gets the parameter file name and stream offset,
+ * then subsequent writes do not need to know this as the data is
+ * contiguous in the stream
+ */
+ PDUMP_LOCK();
+ eError = PDumpWriteParameter(aui8Zero,
+ sizeof(aui8Zero),
+ 0,
+ &g_PDumpParameters.uiZeroPageOffset,
+ g_PDumpParameters.szZeroPageFilename);
+
+ if(eError != PVRSRV_OK)
+ {
+ goto err_write;
+ }
+
+ uiBytesToWrite = g_PDumpParameters.uiZeroPageSize - sizeof(aui8Zero);
+
+ while(uiBytesToWrite)
+ {
+ IMG_BOOL bOK;
+
+ bOK = PDumpWriteToChannel(&g_PDumpParameters.sCh, &g_PDumpParameters.sWOff,
+ aui8Zero,
+ sizeof(aui8Zero), 0);
+
+ if(!bOK)
+ {
+ eError = PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ goto err_write;
+ }
+
+ uiBytesToWrite -= sizeof(aui8Zero);
+ }
+
+err_write:
+ PDUMP_UNLOCK();
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Failed to initialise parameter stream zero block"));
+ }
+
+ return eError;
+}
+
+/**************************************************************************
+ * Function Name : PDumpGetParameterZeroPageInfo
+ * Inputs : None
+ * Outputs : puiZeroPageOffset: will be set to the offset of the zero page
+ * : puiZeroPageSize: will be set to the size of the zero page
+ * : ppszZeroPageFilename: will be set to a pointer to the PRM file name
+ * : containing the zero page
+ * Returns : None
+ * Description : Get information about the zero page
+**************************************************************************/
+IMG_VOID PDumpGetParameterZeroPageInfo(PDUMP_FILEOFFSET_T *puiZeroPageOffset,
+ IMG_SIZE_T *puiZeroPageSize,
+ const IMG_CHAR **ppszZeroPageFilename)
+{
+ *puiZeroPageOffset = g_PDumpParameters.uiZeroPageOffset;
+ *puiZeroPageSize = g_PDumpParameters.uiZeroPageSize;
+ *ppszZeroPageFilename = g_PDumpParameters.szZeroPageFilename;
+}
+
+PVRSRV_ERROR PDumpInitCommon(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32InitCapMode = 0;
+ IMG_CHAR* pszEnvComment = IMG_NULL;
+
+ PDUMP_HEREA(2010);
+
+ /* Allocate temporary buffer for copying from user space */
+ (IMG_VOID) GetTempBuffer();
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ g_psPersistentHash = HASH_Create(PDUMP_PERSISTENT_HASH_SIZE);
+ PVR_LOGG_IF_FALSE((g_psPersistentHash != IMG_NULL), "Failed to create persistent process hash", errExit);
+
+ /* create the global PDump lock */
+ eError = PDumpCreateLockKM();
+ PVR_LOGG_IF_ERROR(eError, "PDumpCreateLockKM", errExit);
+
+ /* Call environment specific PDump initialisation */
+ eError = PDumpOSInit(&g_PDumpParameters.sCh, &g_PDumpScript.sCh, &ui32InitCapMode, &pszEnvComment);
+ PVR_LOGG_IF_ERROR(eError, "PDumpOSInit", errExitLock);
+
+ /* Initialise PDump control module in common layer */
+ PDumpCtrlInit(ui32InitCapMode);
+
+ /* Test PDump initialised and ready by logging driver details */
+ eError = PDumpComment("Driver Product Name: %s", PVRSRVGetSystemName());
+ PVR_LOGG_IF_ERROR(eError, "PDumpComment", errExitCtrl);
+ eError = PDumpComment("Driver Product Version: %s - %s (%s)", PVRVERSION_STRING, PVR_BUILD_DIR, PVR_BUILD_TYPE);
+ PVR_LOGG_IF_ERROR(eError, "PDumpComment", errExitCtrl);
+ if (pszEnvComment != IMG_NULL)
+ {
+ eError = PDumpComment("%s", pszEnvComment);
+ PVR_LOGG_IF_ERROR(eError, "PDumpComment", errExitCtrl);
+ }
+ eError = PDumpComment("Start of Init Phase");
+ PVR_LOGG_IF_ERROR(eError, "PDumpComment", errExitCtrl);
+
+ eError = PDumpParameterChannelZeroedPageBlock();
+ PVR_LOGG_IF_ERROR(eError, "PDumpParameterChannelZeroedPageBlock", errExitCtrl);
+
+ g_PDumpInitialised = IMG_TRUE;
+
+ PDUMP_HEREA(2011);
+
+ return PVRSRV_OK;
+
+errExitCtrl:
+ /* No PDumpCtrlDeInit at present */
+ PDUMP_HEREA(2018);
+ PDumpOSDeInit(&g_PDumpParameters.sCh, &g_PDumpScript.sCh);
+errExitLock:
+ PDUMP_HEREA(2019);
+ PDumpDestroyLockKM();
+errExit:
+ return eError;
+}
+
+IMG_VOID PDumpDeInitCommon(IMG_VOID)
+{
+ PDUMP_HEREA(2020);
+
+ g_PDumpInitialised = IMG_FALSE;
+
+ /* Free temporary buffer */
+ FreeTempBuffer();
+
+ /* Call environment specific PDump Deinitialisation */
+ PDumpOSDeInit(&g_PDumpParameters.sCh, &g_PDumpScript.sCh);
+
+ /* take down the global PDump lock */
+ PDumpDestroyLockKM();
+}
+
+IMG_BOOL PDumpReady(IMG_VOID)
+{
+ return g_PDumpInitialised;
+}
+
+
+PVRSRV_ERROR PDumpAddPersistantProcess(IMG_VOID)
+{
+ IMG_PID uiPID = OSGetCurrentProcessIDKM();
+ IMG_UINTPTR_T puiRetrieve;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PDUMP_HEREA(121);
+
+ puiRetrieve = HASH_Retrieve(g_psPersistentHash, uiPID);
+ if (puiRetrieve == 0)
+ {
+ if (!HASH_Insert(g_psPersistentHash, uiPID, PERSISTANT_MAGIC))
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ PVR_ASSERT(puiRetrieve == PERSISTANT_MAGIC);
+ }
+ PDUMP_HEREA(122);
+
+ return eError;
+}
+
+PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
+{
+ PDUMPCOMMENT("Start Init Phase");
+ PDumpCtrlSetInitPhaseComplete(IMG_FALSE);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_MODULE_ID eModuleID)
+{
+ /* Check with the OS we a running on */
+ if (PDumpOSAllowInitPhaseToComplete(eModuleID))
+ {
+ PDUMPCOMMENT("Stop Init Phase");
+ PDumpCtrlSetInitPhaseComplete(IMG_TRUE);
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+ return PDumpCtrIsLastCaptureFrame();
+}
+
+
+
+typedef struct _PDUMP_Transition_DATA_ {
+ PFN_PDUMP_TRANSITION pfnCallback;
+ IMG_PVOID hPrivData;
+ PDUMP_CONNECTION_DATA *psPDumpConnectionData;
+ DLLIST_NODE sNode;
+} PDUMP_Transition_DATA;
+
+PVRSRV_ERROR PDumpRegisterTransitionCallback(PDUMP_CONNECTION_DATA *psPDumpConnectionData,
+ PFN_PDUMP_TRANSITION pfnCallback,
+ IMG_PVOID hPrivData,
+ IMG_PVOID *ppvHandle)
+{
+ PDUMP_Transition_DATA *psData;
+ PVRSRV_ERROR eError;
+
+ psData = OSAllocMem(sizeof(*psData));
+ if (psData == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ /* Setup the callback and add it to the list for this process */
+ psData->pfnCallback = pfnCallback;
+ psData->hPrivData = hPrivData;
+ dllist_add_to_head(&psPDumpConnectionData->sListHead, &psData->sNode);
+
+ /* Take a reference on the connection so it doesn't get freed too early */
+ psData->psPDumpConnectionData =_PDumpConnectionAcquire(psPDumpConnectionData);
+ *ppvHandle = psData;
+
+ return PVRSRV_OK;
+
+fail_alloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_VOID PDumpUnregisterTransitionCallback(IMG_PVOID pvHandle)
+{
+ PDUMP_Transition_DATA *psData = pvHandle;
+
+ dllist_remove_node(&psData->sNode);
+ _PDumpConnectionRelease(psData->psPDumpConnectionData);
+ OSFreeMem(psData);
+}
+
+typedef struct _PTCB_DATA_ {
+ IMG_BOOL bInto;
+ IMG_BOOL bContinuous;
+ PVRSRV_ERROR eError;
+} PTCB_DATA;
+
+static IMG_BOOL _PDumpTransition(DLLIST_NODE *psNode, IMG_PVOID hData)
+{
+ PDUMP_Transition_DATA *psData = IMG_CONTAINER_OF(psNode, PDUMP_Transition_DATA, sNode);
+ PTCB_DATA *psPTCBData = (PTCB_DATA *) hData;
+
+ psPTCBData->eError = psData->pfnCallback(psData->hPrivData, psPTCBData->bInto, psPTCBData->bContinuous);
+ if (psPTCBData->eError != PVRSRV_OK)
+ {
+ /* Got an error, break out of the loop */
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, IMG_BOOL bInto, IMG_BOOL bContinuous)
+{
+ PTCB_DATA sPTCBData;
+
+ /* Only call the callbacks if we've really done a Transition */
+ if (bInto != psPDumpConnectionData->bLastInto)
+ {
+ /* We're Transitioning either into or out of capture range */
+ sPTCBData.bInto = bInto;
+ sPTCBData.bContinuous = bContinuous;
+ sPTCBData.eError = PVRSRV_OK;
+ dllist_foreach_node(&psPDumpConnectionData->sListHead, _PDumpTransition, &sPTCBData);
+ if (sPTCBData.eError != PVRSRV_OK)
+ {
+ /* We failed so bail out leaving the state as it is ready for the retry */
+ return sPTCBData.eError;
+ }
+
+ if (bInto)
+ {
+ SyncConnectionPDumpSyncBlocks(psPDumpConnectionData->psSyncConnectionData);
+ }
+ psPDumpConnectionData->bLastInto = bInto;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpIsCaptureFrameKM(IMG_BOOL *bIsCapturing)
+{
+ /* WDDM has an extended init phase to work around RA suballocs not
+ * having a PDump MALLOC.
+ * As a consequence, the WDDM init phase contains some FW command submissions.
+ * These commands were discarded due to being outside a capture range. In order
+ * to correctly PDump these commands the init phase is considered to be a
+ * capture range.
+ * Note that PDumpCtrlInitPhasecCmplete was invented for
+ * this purpose. They are not otherwise required.
+ */
+ if(!PDumpCtrlInitPhaseComplete())
+ {
+ *bIsCapturing = IMG_TRUE;
+ }
+ else
+ {
+ *bIsCapturing = PDumpCtrlCaptureOn();
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _PDumpSetFrameKM(CONNECTION_DATA *psConnection, IMG_UINT32 ui32Frame)
+{
+ PDUMP_CONNECTION_DATA *psPDumpConnectionData = psConnection->psPDumpConnectionData;
+ IMG_BOOL bWasInCaptureRange = IMG_FALSE;
+ IMG_BOOL bIsInCaptureRange = IMG_FALSE;
+ PVRSRV_ERROR eError;
+
+ /*
+ Note:
+ As we can't test to see if the new frame will be in capture range
+ before we set the frame number and we don't want to roll back
+ the frame number if we fail then we have to save the "transient"
+ data which decides if we're entering or exiting capture range
+ along with a failure boolean so we know what to do on a retry
+ */
+ if (psPDumpConnectionData->ui32LastSetFrameNumber != ui32Frame)
+ {
+ PDumpIsCaptureFrameKM(&bWasInCaptureRange);
+ PDumpCtrlSetCurrentFrame(ui32Frame);
+ PDumpIsCaptureFrameKM(&bIsInCaptureRange);
+ psPDumpConnectionData->ui32LastSetFrameNumber = ui32Frame;
+
+ /* Save the Transition data incase we fail the Transition */
+ psPDumpConnectionData->bWasInCaptureRange = bWasInCaptureRange;
+ psPDumpConnectionData->bIsInCaptureRange = bIsInCaptureRange;
+ }
+ else if (psPDumpConnectionData->bLastTransitionFailed)
+ {
+ /* Load the Transition data so we can try again */
+ bWasInCaptureRange = psPDumpConnectionData->bWasInCaptureRange;
+ bIsInCaptureRange = psPDumpConnectionData->bIsInCaptureRange;
+ }
+ else
+ {
+ /* New frame is the same as the last fame set and the last
+ * transition succeeded, no need to perform another transition.
+ */
+ return PVRSRV_OK;
+ }
+
+ if (!bWasInCaptureRange && bIsInCaptureRange)
+ {
+ eError = PDumpTransition(psPDumpConnectionData, IMG_TRUE, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_Transition;
+ }
+ }
+ else if (bWasInCaptureRange && !bIsInCaptureRange)
+ {
+ eError = PDumpTransition(psPDumpConnectionData, IMG_FALSE, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_Transition;
+ }
+ }
+ else
+ {
+ /* Here both previous and current frames are in or out of range */
+ /* Should never reach here due to the above goto success */
+ }
+
+ psPDumpConnectionData->bLastTransitionFailed = IMG_FALSE;
+ return PVRSRV_OK;
+
+fail_Transition:
+ psPDumpConnectionData->bLastTransitionFailed = IMG_TRUE;
+ return eError;
+}
+
+PVRSRV_ERROR PDumpSetFrameKM(CONNECTION_DATA *psConnection, IMG_UINT32 ui32Frame)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+
+#if defined(PDUMP_TRACE_STATE)
+ PVR_DPF((PVR_DBG_WARNING, "PDumpSetFrameKM: ui32Frame( %d )", ui32Frame));
+#endif
+
+ /* Ignore errors as it is not fatal if the comments do not appear */
+ (void) PDumpComment("Set pdump frame %u (pre)", ui32Frame);
+
+ eError = _PDumpSetFrameKM(psConnection, ui32Frame);
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+ {
+ PVR_LOG_ERROR(eError, "_PDumpSetFrameKM");
+ }
+
+ (void) PDumpComment("Set pdump frame %u (post)", ui32Frame);
+
+ return eError;
+}
+
+PVRSRV_ERROR PDumpGetFrameKM(CONNECTION_DATA *psConnection, IMG_UINT32* pui32Frame)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+ *pui32Frame = PDumpCtrlGetCurrentFrame();
+ return eError;
+}
+
+PVRSRV_ERROR PDumpSetDefaultCaptureParamsKM(IMG_UINT32 ui32Mode,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32End,
+ IMG_UINT32 ui32Interval,
+ IMG_UINT32 ui32MaxParamFileSize)
+{
+ PDumpCtrlSetDefaultCaptureParams(ui32Mode, ui32Start, ui32End, ui32Interval);
+ if (ui32MaxParamFileSize == 0)
+ {
+ g_PDumpParameters.ui32MaxFileSize = PDUMP_PRM_FILE_SIZE_MAX;
+ }
+ else
+ {
+ g_PDumpParameters.ui32MaxFileSize = ui32MaxParamFileSize;
+ }
+ return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpReg32
+ * Inputs : pszPDumpDevName, Register offset, and value to write
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Create a PDUMP string, which represents a register write
+**************************************************************************/
+PVRSRV_ERROR PDumpReg32(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+ PDUMP_DBG(("PDumpReg32"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW :%s:0x%08X 0x%08X", pszPDumpRegName, ui32Reg, ui32Data);
+
+ if (eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpReg64
+ * Inputs : pszPDumpDevName, Register offset, and value to write
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Create a PDUMP string, which represents a register write
+**************************************************************************/
+PVRSRV_ERROR PDumpReg64(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT64 ui64Data,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+ PDUMP_DBG(("PDumpRegKM"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW64 :%s:0x%08X 0x%010llX", pszPDumpRegName, ui32Reg, ui64Data);
+
+ if (eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpLDW
+ * Inputs : pcBuffer -- buffer to send to register bank
+ * ui32NumLoadBytes -- number of bytes in pcBuffer
+ * pszDevSpaceName -- devspace for register bank
+ * ui32Offset -- value of offset control register
+ * ui32PDumpFlags -- flags to pass to PDumpOSWriteScript
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Dumps the contents of pcBuffer to a .prm file and
+ * writes an LDW directive to the pdump output.
+ * NB: ui32NumLoadBytes must be divisible by 4
+**************************************************************************/
+PVRSRV_ERROR PDumpLDW(IMG_CHAR *pcBuffer,
+ IMG_CHAR *pszDevSpaceName,
+ IMG_UINT32 ui32OffsetBytes,
+ IMG_UINT32 ui32NumLoadBytes,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ IMG_CHAR aszParamStreamFilename[PMR_MAX_PARAMSTREAM_FILENAME_LENGTH_DEFAULT];
+ IMG_UINT32 ui32ParamStreamFileOffset;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+ eError = PDumpWriteBuffer((IMG_UINT8 *)pcBuffer,
+ ui32NumLoadBytes,
+ uiPDumpFlags,
+ &aszParamStreamFilename[0],
+ sizeof(aszParamStreamFilename),
+ &ui32ParamStreamFileOffset);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "LDW :%s:0x%x 0x%x 0x%x %s\n",
+ pszDevSpaceName,
+ ui32OffsetBytes,
+ ui32NumLoadBytes / (IMG_UINT32)sizeof(IMG_UINT32),
+ ui32ParamStreamFileOffset,
+ aszParamStreamFilename);
+
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name : PDumpSAW
+ * Inputs : pszDevSpaceName -- device space from which to output
+ * ui32Offset -- offset value from register base
+ * ui32NumSaveBytes -- number of bytes to output
+ * pszOutfileName -- name of file to output to
+ * ui32OutfileOffsetByte -- offset into output file to write
+ * uiPDumpFlags -- flags to pass to PDumpOSWriteScript
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * 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 eError;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+ PVR_DPF((PVR_DBG_ERROR, "PDumpSAW\n"));
+
+ uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAW :%s:0x%x 0x%x 0x%x %s\n",
+ pszDevSpaceName,
+ ui32HPOffsetBytes,
+ ui32NumSaveBytes / (IMG_UINT32)sizeof(IMG_UINT32),
+ ui32OutfileOffsetByte,
+ pszOutfileName);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpSAW PDumpOSBufprintf failed: eError=%u\n", eError));
+ return eError;
+ }
+
+ PDUMP_LOCK();
+ if(! PDumpWriteScript(hScript, uiPDumpFlags))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpSAW PDumpWriteScript failed!\n"));
+ }
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpRegPolKM
+ * Inputs : Description of what this register read is trying to do
+ * pszPDumpDevName
+ * Register offset
+ * expected value
+ * mask for that value
+ * Outputs : None
+ * Returns : None
+ * Description : Create a PDUMP string which represents a register read
+ * with the expected value
+**************************************************************************/
+PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags,
+ PDUMP_POLL_OPERATOR eOperator)
+{
+ /* Timings correct for linux and XP */
+ /* Timings should be passed in */
+ #define POLL_DELAY 1000U
+ #define POLL_COUNT_LONG (2000000000U / POLL_DELAY)
+ #define POLL_COUNT_SHORT (1000000U / POLL_DELAY)
+
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PollCount;
+
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpRegPolKM"));
+ if ( PDumpIsPersistent() )
+ {
+ /* Don't pdump-poll if the process is persistent */
+ return PVRSRV_OK;
+ }
+
+ ui32PollCount = POLL_COUNT_LONG;
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "POL :%s:0x%08X 0x%08X 0x%08X %d %u %d",
+ pszPDumpRegName, ui32RegAddr, ui32RegValue,
+ ui32Mask, eOperator, ui32PollCount, POLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpCommentKM
+ * Inputs : pszComment, ui32Flags
+ * Outputs : None
+ * Returns : None
+ * Description : Dumps a comment
+**************************************************************************/
+PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+#if defined(PDUMP_DEBUG_OUTFILES)
+ IMG_CHAR pszTemp[256];
+#endif
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpCommentKM"));
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+ /* include comments in the "extended" init phase.
+ * default is to ignore them.
+ */
+ ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+ if((pszComment == IMG_NULL) || (PDumpOSBuflen(pszComment, ui32MaxLen) == 0))
+ {
+ /* PDumpOSVerifyLineEnding silently fails if pszComment is too short to
+ actually hold the line endings that it's trying to enforce, so
+ short circuit it and force safety */
+ pszComment = "\n";
+ }
+ else
+ {
+ /* Put line ending sequence at the end if it isn't already there */
+ PDumpOSVerifyLineEnding(pszComment, ui32MaxLen);
+ }
+
+ PDUMP_LOCK();
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+ /* Prefix comment with PID and line number */
+ eErr = PDumpOSSprintf(pszTemp, 256, "%u %u:%lu %s: %s",
+ g_ui32EveryLineCounter,
+ OSGetCurrentProcessIDKM(),
+ (unsigned long)OSGetCurrentThreadIDKM(),
+ OSGetCurrentProcessNameKM(),
+ pszComment);
+
+ /* Append the comment to the script stream */
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- %s",
+ pszTemp);
+#else
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- %s",
+ pszComment);
+#endif
+ if( (eErr != PVRSRV_OK) &&
+ (eErr != PVRSRV_ERROR_PDUMP_BUF_OVERFLOW))
+ {
+ PVR_LOGG_IF_ERROR(eErr, "PDumpOSBufprintf", ErrUnlock);
+ }
+
+ if (!PDumpWriteScript(hScript, ui32Flags))
+ {
+ if(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ {
+ eErr = PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ PVR_LOGG_IF_ERROR(eErr, "PDumpWriteScript", ErrUnlock);
+ }
+ else
+ {
+ eErr = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ PVR_LOGG_IF_ERROR(eErr, "PDumpWriteScript", ErrUnlock);
+ }
+ }
+
+ErrUnlock:
+ PDUMP_UNLOCK();
+ return eErr;
+}
+
+/**************************************************************************
+ * Function Name : PDumpCommentWithFlags
+ * Inputs : psPDev - PDev for PDump device
+ * : pszFormat - format string for comment
+ * : ... - args for format string
+ * Outputs : None
+ * Returns : None
+ * Description : PDumps a comments
+**************************************************************************/
+PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+ /* Construct the string */
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ return PDumpCommentKM(pszMsg, ui32Flags);
+}
+
+/**************************************************************************
+ * Function Name : PDumpComment
+ * Inputs : psPDev - PDev for PDump device
+ * : pszFormat - format string for comment
+ * : ... - args for format string
+ * Outputs : None
+ * Returns : None
+ * Description : PDumps a comments
+**************************************************************************/
+PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+ /* Construct the string */
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+ PVR_LOGR_IF_ERROR(eErr, "PDumpOSVSprintf");
+
+ return PDumpCommentKM(pszMsg, PDUMP_FLAGS_CONTINUOUS);
+}
+
+/*************************************************************************/ /*!
+ * Function Name : PDumpPanic
+ * Inputs : ui32PanicNo - Unique number for panic condition
+ * : pszPanicMsg - Panic reason message limited to ~90 chars
+ * : pszPPFunc - Function name string where panic occurred
+ * : ui32PPline - Source line number where panic occurred
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : PDumps a panic assertion. Used when the host driver
+ * : detects a condition that will lead to an invalid PDump
+ * : script that cannot be played back off-line.
+ */ /*************************************************************************/
+PVRSRV_ERROR PDumpPanic(IMG_UINT32 ui32PanicNo,
+ IMG_CHAR* pszPanicMsg,
+ const IMG_CHAR* pszPPFunc,
+ IMG_UINT32 ui32PPline)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PDUMP_FLAGS_T uiPDumpFlags = PDUMP_FLAGS_CONTINUOUS;
+ IMG_CHAR pszConsoleMsg[] =
+"COM ***************************************************************************\n"
+"COM Script invalid and not compatible with off-line playback. Check test \n"
+"COM parameters and driver configuration, stop imminent.\n"
+"COM ***************************************************************************\n";
+ PDUMP_GET_SCRIPT_STRING();
+
+ /* Log the panic condition to the live kern.log in both REL and DEB mode
+ * to aid user PDump trouble shooting. */
+ PVR_LOG(("PDUMP PANIC %08x: %s", ui32PanicNo, pszPanicMsg));
+ PVR_DPF((PVR_DBG_MESSAGE, "PDUMP PANIC start %s:%d", pszPPFunc, ui32PPline));
+
+ /* Check the supplied panic reason string is within length limits */
+ PVR_ASSERT(OSStringLength(pszPanicMsg)+sizeof("PANIC ") < PVRSRV_PDUMP_MAX_COMMENT_SIZE-1);
+
+ /* Add persistent flag if required and obtain lock to keep the multi-line
+ * panic statement together in a single atomic write */
+ uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
+ PDUMP_LOCK();
+
+ /* Write -- Panic start (Function:line) */
+ eError = PDumpOSBufprintf(hScript, ui32MaxLen, "-- Panic start (%s:%d)", pszPPFunc, ui32PPline);
+ PVR_LOGG_IF_ERROR(eError, "PDumpOSBufprintf", e1);
+ (IMG_VOID)PDumpWriteScript(hScript, uiPDumpFlags);
+
+ /* Write COM <message> x4 */
+ eError = PDumpOSBufprintf(hScript, ui32MaxLen, pszConsoleMsg);
+ PVR_LOGG_IF_ERROR(eError, "PDumpOSBufprintf", e1);
+ (IMG_VOID)PDumpWriteScript(hScript, uiPDumpFlags);
+
+ /* Write PANIC no msg command */
+ eError = PDumpOSBufprintf(hScript, ui32MaxLen, "PANIC %08x %s", ui32PanicNo, pszPanicMsg);
+ PVR_LOGG_IF_ERROR(eError, "PDumpOSBufprintf", e1);
+ (IMG_VOID)PDumpWriteScript(hScript, uiPDumpFlags);
+
+ /* Write -- Panic end */
+ eError = PDumpOSBufprintf(hScript, ui32MaxLen, "-- Panic end");
+ PVR_LOGG_IF_ERROR(eError, "PDumpOSBufprintf", e1);
+ (IMG_VOID)PDumpWriteScript(hScript, uiPDumpFlags);
+
+e1:
+ PDUMP_UNLOCK();
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @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=0;
+ PDUMP_GET_SCRIPT_STRING();
+
+ if ( PDumpIsPersistent() )
+ {
+ return PVRSRV_OK;
+ }
+
+ PDumpCommentWithFlags(ui32PDumpFlags, "Dump bitmap of render.");
+
+ switch (ePixelFormat)
+ {
+ case PVRSRV_PDUMP_PIXEL_FORMAT_YUV8:
+ {
+ PDumpCommentWithFlags(ui32PDumpFlags, "YUV data. Switching from SII to SAB. Width=0x%08X Height=0x%08X Stride=0x%08X",
+ ui32Width, ui32Height, ui32StrideInBytes);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:v%x:0x%010llX 0x%08X 0x%08X %s.bin\n",
+ psDevId->pszPDumpDevName,
+ ui32MMUContextID,
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ pszFileName);
+
+ if (eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript( hScript, ui32PDumpFlags);
+ PDUMP_UNLOCK();
+ 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;
+
+ PDumpCommentWithFlags(ui32PDumpFlags, "YUV420 2-plane. Width=0x%08X Height=0x%08X Stride=0x%08X",
+ ui32Width, ui32Height, ui32StrideInBytes);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :%s:v%x:0x%010llX 0x%08X 0x%08X :%s:v%x:0x%010llX 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);
+
+ if (eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript( hScript, ui32PDumpFlags);
+ PDUMP_UNLOCK();
+ 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;
+
+ PDumpCommentWithFlags(ui32PDumpFlags, "YUV420 3-plane. Width=0x%08X Height=0x%08X Stride=0x%08X",
+ ui32Width, ui32Height, ui32StrideInBytes);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :%s:v%x:0x%010llX 0x%08X 0x%08X :%s:v%x:0x%010llX 0x%08X 0x%08X :%s:v%x:0x%010llX 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);
+
+ if (eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript( hScript, ui32PDumpFlags);
+ PDUMP_UNLOCK();
+ break;
+ }
+
+ default: // Single plane formats
+ {
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :%s:v%x:0x%010llX 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);
+
+ if (eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript( hScript, ui32PDumpFlags);
+ PDUMP_UNLOCK();
+ break;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PDumpReadRegKM
+
+ @Description
+
+ Dumps a read from a device register to a file
+
+ @Input psConnection : connection info
+ @Input pszFileName
+ @Input ui32FileOffset
+ @Input ui32Address
+ @Input ui32Size
+ @Input ui32PDumpFlags
+
+ @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 eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:0x%08X 0x%08X %s",
+ pszPDumpRegName,
+ ui32Address,
+ ui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript( hScript, ui32PDumpFlags);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ @name PDumpRegRead32
+ @brief Dump 32-bit register read to script
+ @param pszPDumpDevName - pdump device name
+ @param ui32RegOffset - register offset
+ @param ui32Flags - pdump flags
+ @return Error
+*****************************************************************************/
+PVRSRV_ERROR PDumpRegRead32(IMG_CHAR *pszPDumpRegName,
+ const IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :%s:0x%X",
+ pszPDumpRegName,
+ ui32RegOffset);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDUMP_UNLOCK();
+ return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ @name PDumpRegRead64
+ @brief Dump 64-bit register read to script
+ @param pszPDumpDevName - pdump device name
+ @param ui32RegOffset - register offset
+ @param ui32Flags - pdump flags
+ @return Error
+*****************************************************************************/
+PVRSRV_ERROR PDumpRegRead64(IMG_CHAR *pszPDumpRegName,
+ const IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW64 :%s:0x%X",
+ pszPDumpRegName,
+ ui32RegOffset);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDUMP_UNLOCK();
+ return PVRSRV_OK;
+}
+
+
+/*****************************************************************************
+ FUNCTION : PDumpWriteShiftedMaskedValue
+
+ PURPOSE : Emits the PDump commands for writing a masked shifted address
+ into another location
+
+ PARAMETERS : PDump symbolic name and offset of target word
+ PDump symbolic name and offset of source address
+ right shift amount
+ left shift amount
+ mask
+
+ RETURNS : None
+*****************************************************************************/
+PVRSRV_ERROR
+PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
+ const IMG_CHAR *pszDestSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiDestOffset,
+ const IMG_CHAR *pszRefRegspaceName,
+ const IMG_CHAR *pszRefSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiRefOffset,
+ IMG_UINT32 uiSHRAmount,
+ IMG_UINT32 uiSHLAmount,
+ IMG_UINT32 uiMask,
+ IMG_DEVMEM_SIZE_T uiWordSize,
+ IMG_UINT32 uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ /* Suffix of WRW command in PDump (i.e. WRW or WRW64) */
+ const IMG_CHAR *pszWrwSuffix;
+
+ /* Internal PDump register used for interim calculation */
+ const IMG_CHAR *pszPDumpIntRegSpace;
+ IMG_UINT32 uiPDumpIntRegNum;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ if ((uiWordSize != 4) && (uiWordSize != 8))
+ {
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+
+ pszWrwSuffix = (uiWordSize == 8) ? "64" : "";
+
+ /* Should really "Acquire" a pdump register here */
+ pszPDumpIntRegSpace = pszDestRegspaceName;
+ uiPDumpIntRegNum = 1;
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ /* Should this be "MOV" instead? */
+ "WRW :%s:$%d :%s:%s:" IMG_DEVMEM_OFFSET_FMTSPEC "\n",
+ /* dest */
+ pszPDumpIntRegSpace,
+ uiPDumpIntRegNum,
+ /* src */
+ pszRefRegspaceName,
+ pszRefSymbolicName,
+ uiRefOffset);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrOut;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, uiPDumpFlags);
+
+ if (uiSHRAmount > 0)
+ {
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SHR :%s:$%d :%s:$%d 0x%X\n",
+ /* dest */
+ pszPDumpIntRegSpace,
+ uiPDumpIntRegNum,
+ /* src A */
+ pszPDumpIntRegSpace,
+ uiPDumpIntRegNum,
+ /* src B */
+ uiSHRAmount);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ }
+
+ if (uiSHLAmount > 0)
+ {
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SHL :%s:$%d :%s:$%d 0x%X\n",
+ /* dest */
+ pszPDumpIntRegSpace,
+ uiPDumpIntRegNum,
+ /* src A */
+ pszPDumpIntRegSpace,
+ uiPDumpIntRegNum,
+ /* src B */
+ uiSHLAmount);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ }
+
+ if (uiMask != (1ULL << (8*uiWordSize))-1)
+ {
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "AND :%s:$%d :%s:$%d 0x%X\n",
+ /* dest */
+ pszPDumpIntRegSpace,
+ uiPDumpIntRegNum,
+ /* src A */
+ pszPDumpIntRegSpace,
+ uiPDumpIntRegNum,
+ /* src B */
+ uiMask);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ }
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW%s :%s:%s:" IMG_DEVMEM_OFFSET_FMTSPEC " :%s:$%d\n",
+ pszWrwSuffix,
+ /* dest */
+ pszDestRegspaceName,
+ pszDestSymbolicName,
+ uiDestOffset,
+ /* src */
+ pszPDumpIntRegSpace,
+ uiPDumpIntRegNum);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, uiPDumpFlags);
+
+ErrUnlock:
+ PDUMP_UNLOCK();
+ErrOut:
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PDumpWriteSymbAddress(const IMG_CHAR *pszDestSpaceName,
+ IMG_DEVMEM_OFFSET_T uiDestOffset,
+ const IMG_CHAR *pszRefSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiRefOffset,
+ const IMG_CHAR *pszPDumpDevName,
+ IMG_UINT32 ui32WordSize,
+ IMG_UINT32 ui32AlignShift,
+ IMG_UINT32 ui32Shift,
+ IMG_UINT32 uiPDumpFlags)
+{
+ const IMG_CHAR *pszWrwSuffix = "";
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ if (ui32WordSize == 8)
+ {
+ pszWrwSuffix = "64";
+ }
+
+ PDUMP_LOCK();
+
+ if (ui32AlignShift != ui32Shift)
+ {
+ /* Write physical address into a variable */
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW%s :%s:$1 %s:" IMG_DEVMEM_OFFSET_FMTSPEC "\n",
+ pszWrwSuffix,
+ /* dest */
+ pszPDumpDevName,
+ /* src */
+ pszRefSymbolicName,
+ uiRefOffset);
+ if (eError != PVRSRV_OK)
+ {
+ goto symbAddress_error;
+ }
+ PDumpWriteScript(hScript, uiPDumpFlags);
+
+ /* apply address alignment */
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SHR :%s:$1 :%s:$1 0x%X",
+ /* dest */
+ pszPDumpDevName,
+ /* src A */
+ pszPDumpDevName,
+ /* src B */
+ ui32AlignShift);
+ if (eError != PVRSRV_OK)
+ {
+ goto symbAddress_error;
+ }
+ PDumpWriteScript(hScript, uiPDumpFlags);
+
+ /* apply address shift */
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SHL :%s:$1 :%s:$1 0x%X",
+ /* dest */
+ pszPDumpDevName,
+ /* src A */
+ pszPDumpDevName,
+ /* src B */
+ ui32Shift);
+ if (eError != PVRSRV_OK)
+ {
+ goto symbAddress_error;
+ }
+ PDumpWriteScript(hScript, uiPDumpFlags);
+
+
+ /* write result to register */
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW%s :%s:0x%08X :%s:$1",
+ pszWrwSuffix,
+ pszDestSpaceName,
+ (IMG_UINT32)uiDestOffset,
+ pszPDumpDevName);
+ if (eError != PVRSRV_OK)
+ {
+ goto symbAddress_error;
+ }
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ }
+ else
+ {
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW%s :%s:" IMG_DEVMEM_OFFSET_FMTSPEC " %s:" IMG_DEVMEM_OFFSET_FMTSPEC "\n",
+ pszWrwSuffix,
+ /* dest */
+ pszDestSpaceName,
+ uiDestOffset,
+ /* src */
+ pszRefSymbolicName,
+ uiRefOffset);
+ if (eError != PVRSRV_OK)
+ {
+ goto symbAddress_error;
+ }
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ }
+
+symbAddress_error:
+
+ PDUMP_UNLOCK();
+
+ return eError;
+}
+
+/**************************************************************************
+ * Function Name : PDumpIDLWithFlags
+ * Inputs : Idle time in clocks
+ * Outputs : None
+ * Returns : Error
+ * Description : Dump IDL command to script
+**************************************************************************/
+PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpIDLWithFlags"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "IDL %u", ui32Clocks);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDUMP_UNLOCK();
+ return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpIDL
+ * Inputs : Idle time in clocks
+ * Outputs : None
+ * Returns : Error
+ * Description : Dump IDL command to script
+**************************************************************************/
+PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
+{
+ return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+
+/*****************************************************************************
+ FUNCTION : PDumpRegBasedCBP
+
+ PURPOSE : Dump CBP command to script
+
+ PARAMETERS :
+
+ RETURNS : None
+*****************************************************************************/
+PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags)
+{
+ PDUMP_GET_SCRIPT_STRING();
+
+ PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "CBP :%s:0x%08X 0x%08X 0x%08X 0x%08X",
+ pszPDumpRegName,
+ ui32RegOffset,
+ ui32WPosVal,
+ ui32PacketSize,
+ ui32BufferSize);
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpTRG(IMG_CHAR *pszMemSpace,
+ IMG_UINT32 ui32MMUCtxID,
+ IMG_UINT32 ui32RegionID,
+ IMG_BOOL bEnable,
+ IMG_UINT64 ui64VAddr,
+ IMG_UINT64 ui64LenBytes,
+ IMG_UINT32 ui32XStride,
+ IMG_UINT32 ui32Flags)
+{
+ PDUMP_GET_SCRIPT_STRING();
+
+ if(bEnable)
+ {
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "TRG :%s:v%u %u 0x%08llX 0x%08llX %u",
+ pszMemSpace, ui32MMUCtxID, ui32RegionID,
+ ui64VAddr, ui64LenBytes, ui32XStride);
+ }
+ else
+ {
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "TRG :%s:v%u %u",
+ pszMemSpace, ui32MMUCtxID, ui32RegionID);
+
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name : PDumpConnectionNotify
+ * Description : Called by the srvcore to tell PDump core that the
+ * PDump capture and control client has connected
+ **************************************************************************/
+IMG_VOID PDumpConnectionNotify(IMG_VOID)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_DEVICE_NODE *psThis;
+
+ if (PDumpOSAllowInitPhaseToComplete(IMG_PDUMPCTRL))
+ {
+ /* No 'Stop Init Phase' comment here as in this case as the PDump
+ * client can connect multiple times and we don't want the comment
+ * appearing multiple times in out files.
+ */
+ PDumpCtrlSetInitPhaseComplete(IMG_TRUE);
+ }
+
+ g_ConnectionCount++;
+ PVR_LOG(("PDump has connected (%u)", g_ConnectionCount));
+
+ /* Reset the parameter file attributes */
+ g_PDumpParameters.sWOff.ui32Main = g_PDumpParameters.sWOff.ui32Init;
+ g_PDumpParameters.ui32FileIdx = 0;
+
+ /* Loop over all known devices */
+ psThis = psPVRSRVData->psDeviceNodeList;
+ while (psThis)
+ {
+ if (psThis->pfnPDumpInitDevice)
+ {
+ /* Reset pdump according to connected device */
+ psThis->pfnPDumpInitDevice(psThis);
+ }
+ psThis = psThis->psNext;
+ }
+}
+
+/**************************************************************************
+ * Function Name : PDumpIfKM
+ * Inputs : pszPDumpCond - string for condition
+ * Outputs : None
+ * Returns : None
+ * Description : Create a PDUMP string which represents IF command
+ with condition.
+**************************************************************************/
+PVRSRV_ERROR PDumpIfKM(IMG_CHAR *pszPDumpCond)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+ PDUMP_DBG(("PDumpIfKM"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "IF %s\n", pszPDumpCond);
+
+ if (eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, PDUMP_FLAGS_CONTINUOUS);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name : PDumpElseKM
+ * Inputs : pszPDumpCond - string for condition
+ * Outputs : None
+ * Returns : None
+ * Description : Create a PDUMP string which represents ELSE command
+ with condition.
+**************************************************************************/
+PVRSRV_ERROR PDumpElseKM(IMG_CHAR *pszPDumpCond)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+ PDUMP_DBG(("PDumpElseKM"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "ELSE %s\n", pszPDumpCond);
+
+ if (eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, PDUMP_FLAGS_CONTINUOUS);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name : PDumpFiKM
+ * Inputs : pszPDumpCond - string for condition
+ * Outputs : None
+ * Returns : None
+ * Description : Create a PDUMP string which represents FI command
+ with condition.
+**************************************************************************/
+PVRSRV_ERROR PDumpFiKM(IMG_CHAR *pszPDumpCond)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+ PDUMP_DBG(("PDumpFiKM"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FI %s\n", pszPDumpCond);
+
+ if (eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDUMP_LOCK();
+ PDumpWriteScript(hScript, PDUMP_FLAGS_CONTINUOUS);
+ PDUMP_UNLOCK();
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCreateLockKM(IMG_VOID)
+{
+ return PDumpOSCreateLock();
+}
+
+IMG_VOID PDumpDestroyLockKM(IMG_VOID)
+{
+ PDumpOSDestroyLock();
+}
+
+IMG_VOID PDumpLockKM(IMG_VOID)
+{
+ PDumpOSLock();
+}
+
+IMG_VOID PDumpUnlockKM(IMG_VOID)
+{
+ PDumpOSUnlock();
+}
+
+#if defined(PVR_TESTING_UTILS)
+extern IMG_VOID PDumpOSDumpState(IMG_VOID);
+
+#if !defined(LINUX)
+IMG_VOID PDumpOSDumpState(IMG_BOOL bDumpOSLayerState)
+{
+ PVR_UNREFERENCED_PARAMETER(bDumpOSLayerState);
+}
+#endif
+
+IMG_VOID PDumpCommonDumpState(IMG_BOOL bDumpOSLayerState)
+{
+ IMG_UINT32* ui32HashData = (IMG_UINT32*)g_psPersistentHash;
+
+ PVR_LOG(("--- PDUMP COMMON: g_PDumpInitialised( %d )",
+ g_PDumpInitialised) );
+ PVR_LOG(("--- PDUMP COMMON: g_psPersistentHash( %p ) uSize( %d ) uCount( %d )",
+ g_psPersistentHash, ui32HashData[0], ui32HashData[1]) );
+ PVR_LOG(("--- PDUMP COMMON: g_PDumpScript.sCh.hInit( %p ) g_PDumpScript.sCh.hMain( %p ) g_PDumpScript.sCh.hDeinit( %p )",
+ g_PDumpScript.sCh.hInit, g_PDumpScript.sCh.hMain, g_PDumpScript.sCh.hDeinit) );
+ PVR_LOG(("--- PDUMP COMMON: g_PDumpParameters.sCh.hInit( %p ) g_PDumpParameters.sCh.hMain( %p ) g_PDumpParameters.sCh.hDeinit( %p )",
+ g_PDumpParameters.sCh.hInit, g_PDumpParameters.sCh.hMain, g_PDumpParameters.sCh.hDeinit) );
+ PVR_LOG(("--- PDUMP COMMON: g_PDumpParameters.sWOff.ui32Init( %d ) g_PDumpParameters.sWOff.ui32Main( %d ) g_PDumpParameters.sWOff.ui32Deinit( %d )",
+ g_PDumpParameters.sWOff.ui32Init, g_PDumpParameters.sWOff.ui32Main, g_PDumpParameters.sWOff.ui32Deinit) );
+ PVR_LOG(("--- PDUMP COMMON: g_PDumpParameters.ui32FileIdx( %d )",
+ g_PDumpParameters.ui32FileIdx) );
+
+ PVR_LOG(("--- PDUMP COMMON: g_PDumpCtrl( %p ) bInitPhaseActive( %d ) ui32Flags( %x )",
+ &g_PDumpCtrl, g_PDumpCtrl.bInitPhaseActive, g_PDumpCtrl.ui32Flags) );
+ PVR_LOG(("--- PDUMP COMMON: ui32DefaultCapMode( %d ) ui32CurrentFrame( %d )",
+ g_PDumpCtrl.ui32DefaultCapMode, g_PDumpCtrl.ui32CurrentFrame) );
+ PVR_LOG(("--- PDUMP COMMON: sDefaultRange.ui32Start( %d ) sDefaultRange.ui32End( %d ) sDefaultRange.ui32Interval( %d )",
+ g_PDumpCtrl.sDefaultRange.ui32Start, g_PDumpCtrl.sDefaultRange.ui32End, g_PDumpCtrl.sDefaultRange.ui32Interval) );
+ PVR_LOG(("--- PDUMP COMMON: bCaptureOn( %d ) bSuspended( %d ) bInPowerTransition( %d )",
+ g_PDumpCtrl.bCaptureOn, g_PDumpCtrl.bSuspended, g_PDumpCtrl.bInPowerTransition) );
+
+ if (bDumpOSLayerState)
+ {
+ PDumpOSDumpState();
+ }
+}
+#endif
+
+
+PVRSRV_ERROR PDumpRegisterConnection(SYNC_CONNECTION_DATA *psSyncConnectionData,
+ PDUMP_CONNECTION_DATA **ppsPDumpConnectionData)
+{
+ PDUMP_CONNECTION_DATA *psPDumpConnectionData;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(ppsPDumpConnectionData != IMG_NULL);
+
+ psPDumpConnectionData = OSAllocMem(sizeof(*psPDumpConnectionData));
+ if (psPDumpConnectionData == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ eError = OSLockCreate(&psPDumpConnectionData->hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_lockcreate;
+ }
+
+ dllist_init(&psPDumpConnectionData->sListHead);
+ psPDumpConnectionData->ui32RefCount = 1;
+ psPDumpConnectionData->bLastInto = IMG_FALSE;
+ psPDumpConnectionData->ui32LastSetFrameNumber = 0xFFFFFFFFU;
+ psPDumpConnectionData->bLastTransitionFailed = IMG_FALSE;
+ /*
+ Although we don't take a refcount here resman will ensure that
+ any resource which might trigger use to do a Transition will
+ have been freed before the sync blocks which are keeping the
+ sync connection data alive
+ */
+ psPDumpConnectionData->psSyncConnectionData = psSyncConnectionData;
+ *ppsPDumpConnectionData = psPDumpConnectionData;
+
+ return PVRSRV_OK;
+
+fail_lockcreate:
+ OSFreeMem(psPDumpConnectionData);
+fail_alloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_VOID PDumpUnregisterConnection(PDUMP_CONNECTION_DATA *psPDumpConnectionData)
+{
+ _PDumpConnectionRelease(psPDumpConnectionData);
+}
+
+#else /* defined(PDUMP) */
+/* disable warning about empty module */
+#ifdef _WIN32
+#pragma warning (disable:4206)
+#endif
+#endif /* defined(PDUMP) */
+/*****************************************************************************
+ End of file (pdump_common.c)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/common/pdump_mmu.c b/drivers/gpu/rogue/services/server/common/pdump_mmu.c
new file mode 100644
index 000000000000..96d188b1b539
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/pdump_mmu.c
@@ -0,0 +1,1008 @@
+/*************************************************************************/ /*!
+@File
+@Title MMU PDump functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Common PDump (MMU 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 (PDUMP)
+
+#include "img_types.h"
+#include "pdump_mmu.h"
+#include "pdump_osfunc.h"
+#include "pdump_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+
+#define MAX_PDUMP_MMU_CONTEXTS (10)
+static IMG_UINT32 guiPDumpMMUContextAvailabilityMask = (1<<MAX_PDUMP_MMU_CONTEXTS)-1;
+
+/* arbitrary buffer length here. */
+#define MAX_SYMBOLIC_ADDRESS_LENGTH 40
+
+#define MMUPX_FMT(X) ((X<3) ? ((X<2) ? "MMUPT_\0" : "MMUPD_\0") : "MMUPC_\0")
+
+
+/* Array used to look-up debug strings from MMU_LEVEL */
+static IMG_CHAR ai8MMULevelStringLookup[MMU_LEVEL_LAST][15] =
+ {
+ "MMU_LEVEL_0",
+ "PAGE_TABLE",
+ "PAGE_DIRECTORY",
+ "PAGE_CATALOGUE",
+ };
+
+static PVRSRV_ERROR
+_ContiguousPDumpBytes(const IMG_CHAR *pszSymbolicName,
+ IMG_UINT32 ui32SymAddrOffset,
+ IMG_BOOL bFlush,
+ IMG_UINT32 uiNumBytes,
+ IMG_VOID *pvBytes,
+ IMG_UINT32 ui32Flags)
+{
+ static const IMG_CHAR *pvBeyondLastPointer;
+ static const IMG_CHAR *pvBasePointer;
+ static IMG_UINT32 ui32BeyondLastOffset;
+ static IMG_UINT32 ui32BaseOffset;
+ static IMG_UINT32 uiAccumulatedBytes = 0;
+ IMG_UINT32 ui32ParamOutPos;
+ PVRSRV_ERROR eErr = PVRSRV_OK;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+ PVR_UNREFERENCED_PARAMETER(ui32MaxLenFileName);
+
+ if (!bFlush && uiAccumulatedBytes > 0)
+ {
+ /* do some tests for contiguity. If it fails, we flush anyway */
+
+ if (pvBeyondLastPointer != pvBytes ||
+ ui32SymAddrOffset != ui32BeyondLastOffset
+ /* NB: ought to check that symbolic name agrees too, but
+ we know this always to be the case in the current use-case */
+ )
+ {
+ bFlush = IMG_TRUE;
+ }
+ }
+
+ /* Flush if necessary */
+ if (bFlush && uiAccumulatedBytes > 0)
+ {
+ eErr = PDumpWriteParameter((IMG_UINT8 *)(IMG_UINTPTR_T)pvBasePointer,
+ uiAccumulatedBytes, ui32Flags,
+ &ui32ParamOutPos, pszFileName);
+ PVR_LOGG_IF_ERROR(eErr, "PDumpWriteParameter", ErrOut);
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript,
+ "LDB %s:0x%X 0x%X 0x%X %s",
+ /* dest */
+ pszSymbolicName,
+ ui32BaseOffset,
+ /* size */
+ uiAccumulatedBytes,
+ /* file offset */
+ ui32ParamOutPos,
+ /* filename */
+ pszFileName);
+ PVR_LOGG_IF_ERROR(eErr, "PDumpOSBufprintf", ErrOut);
+
+ PDumpWriteScript(hScript, ui32Flags);
+
+ uiAccumulatedBytes = 0;
+ }
+
+ /* Initialise offsets and pointers if necessary */
+ if (uiAccumulatedBytes == 0)
+ {
+ ui32BaseOffset = ui32BeyondLastOffset = ui32SymAddrOffset;
+ pvBeyondLastPointer = pvBasePointer = (const IMG_CHAR *)pvBytes;
+ }
+
+ /* Accumulate some bytes */
+ ui32BeyondLastOffset += uiNumBytes;
+ pvBeyondLastPointer += uiNumBytes;
+ uiAccumulatedBytes += uiNumBytes;
+
+ErrOut:
+ return eErr;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpMMUMalloc
+ * Inputs :
+ * Outputs :
+ * Returns : PVRSRV_ERROR
+ * Description :
+**************************************************************************/
+PVRSRV_ERROR PDumpMMUMalloc(const IMG_CHAR *pszPDumpDevName,
+ MMU_LEVEL eMMULevel,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Align)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+ IMG_UINT64 ui64SymbolicAddr;
+ IMG_CHAR *pszMMUPX;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ if (eMMULevel >= MMU_LEVEL_LAST)
+ {
+ eErr = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ErrOut;
+ }
+
+ /*
+ Write a comment to the PDump2 script streams indicating the memory allocation
+ */
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "-- MALLOC :%s:%s Size=0x%08X Alignment=0x%08X DevPAddr=0x%08llX",
+ pszPDumpDevName,
+ ai8MMULevelStringLookup[eMMULevel],
+ ui32Size,
+ ui32Align,
+ psDevPAddr->uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrOut;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, ui32Flags);
+
+ /*
+ construct the symbolic address
+ */
+ ui64SymbolicAddr = (IMG_UINT64)psDevPAddr->uiAddr;
+
+ /*
+ Write to the MMU script stream indicating the memory allocation
+ */
+ pszMMUPX = MMUPX_FMT(eMMULevel);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:%s%016llX 0x%X 0x%X",
+ pszPDumpDevName,
+ pszMMUPX,
+ ui64SymbolicAddr,
+ ui32Size,
+ ui32Align
+ /* don't need this sDevPAddr.uiAddr*/);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags);
+
+ErrUnlock:
+ PDumpOSUnlock();
+ErrOut:
+ return eErr;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpMMUFree
+ * Inputs :
+ * Outputs :
+ * Returns : PVRSRV_ERROR
+ * Description :
+**************************************************************************/
+PVRSRV_ERROR PDumpMMUFree(const IMG_CHAR *pszPDumpDevName,
+ MMU_LEVEL eMMULevel,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT64 ui64SymbolicAddr;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+ IMG_CHAR *pszMMUPX;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ if (eMMULevel >= MMU_LEVEL_LAST)
+ {
+ eErr = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ErrOut;
+ }
+
+ /*
+ Write a comment to the PDUMP2 script streams indicating the memory free
+ */
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:%s",
+ pszPDumpDevName, ai8MMULevelStringLookup[eMMULevel]);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrOut;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, ui32Flags);
+
+ /*
+ construct the symbolic address
+ */
+ ui64SymbolicAddr = (IMG_UINT64)psDevPAddr->uiAddr;
+
+ /*
+ Write to the MMU script stream indicating the memory free
+ */
+ pszMMUPX = MMUPX_FMT(eMMULevel);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:%s%016llX",
+ pszPDumpDevName,
+ pszMMUPX,
+ ui64SymbolicAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags);
+
+ErrUnlock:
+ PDumpOSUnlock();
+ErrOut:
+ return eErr;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpMMUMalloc2
+ * Inputs :
+ * Outputs :
+ * Returns : PVRSRV_ERROR
+ * Description :
+**************************************************************************/
+PVRSRV_ERROR PDumpMMUMalloc2(const IMG_CHAR *pszPDumpDevName,
+ const IMG_CHAR *pszTableType,/* PAGE_CATALOGUE, PAGE_DIRECTORY, PAGE_TABLE */
+ const IMG_CHAR *pszSymbolicAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Align)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ /*
+ Write a comment to the PDump2 script streams indicating the memory allocation
+ */
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "-- MALLOC :%s:%s Size=0x%08X Alignment=0x%08X\n",
+ pszPDumpDevName,
+ pszTableType,
+ ui32Size,
+ ui32Align);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrOut;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, ui32Flags);
+
+ /*
+ Write to the MMU script stream indicating the memory allocation
+ */
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:%s 0x%X 0x%X\n",
+ pszPDumpDevName,
+ pszSymbolicAddr,
+ ui32Size,
+ ui32Align
+ /* don't need this sDevPAddr.uiAddr*/);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags);
+
+ErrUnlock:
+ PDumpOSUnlock();
+ErrOut:
+ return eErr;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpMMUFree2
+ * Inputs :
+ * Outputs :
+ * Returns : PVRSRV_ERROR
+ * Description :
+**************************************************************************/
+PVRSRV_ERROR PDumpMMUFree2(const IMG_CHAR *pszPDumpDevName,
+ const IMG_CHAR *pszTableType,/* PAGE_CATALOGUE, PAGE_DIRECTORY, PAGE_TABLE */
+ const IMG_CHAR *pszSymbolicAddr)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ /*
+ Write a comment to the PDUMP2 script streams indicating the memory free
+ */
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:%s\n",
+ pszPDumpDevName, pszTableType);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrOut;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, ui32Flags);
+
+ /*
+ Write to the MMU script stream indicating the memory free
+ */
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:%s\n",
+ pszPDumpDevName,
+ pszSymbolicAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags);
+
+ErrUnlock:
+ PDumpOSUnlock();
+ErrOut:
+ return eErr;
+}
+
+/**************************************************************************
+ * Function Name : PDumpMMUDumpPxEntries
+ * Inputs :
+ * Outputs :
+ * Returns : PVRSRV_ERROR
+ * Description :
+**************************************************************************/
+PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
+ const IMG_CHAR *pszPDumpDevName,
+ IMG_VOID *pvPxMem,
+ IMG_DEV_PHYADDR sPxDevPAddr,
+ IMG_UINT32 uiFirstEntry,
+ IMG_UINT32 uiNumEntries,
+ const IMG_CHAR *pszMemspaceName,
+ const IMG_CHAR *pszSymbolicAddr,
+ IMG_UINT64 uiSymbolicAddrOffset,
+ IMG_UINT32 uiBytesPerEntry,
+ IMG_UINT32 uiLog2Align,
+ IMG_UINT32 uiAddrShift,
+ IMG_UINT64 uiAddrMask,
+ IMG_UINT64 uiPxEProtMask,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr = PVRSRV_OK;
+ IMG_UINT64 ui64PxSymAddr;
+ IMG_UINT64 ui64PxEValueSymAddr;
+ IMG_UINT32 ui32SymAddrOffset = 0;
+ IMG_UINT32 *pui32PxMem;
+ IMG_UINT64 *pui64PxMem;
+ IMG_BOOL bPxEValid;
+ IMG_UINT32 uiPxEIdx;
+ IMG_INT32 iShiftAmount;
+ IMG_CHAR *pszWrwSuffix = 0;
+ IMG_VOID *pvRawBytes = 0;
+ IMG_CHAR aszPxSymbolicAddr[MAX_SYMBOLIC_ADDRESS_LENGTH];
+ IMG_UINT64 ui64PxE64;
+ IMG_UINT64 ui64Protflags64;
+ IMG_CHAR *pszMMUPX;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ if (!PDumpReady())
+ {
+ eErr = PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ goto ErrOut;
+ }
+
+
+ if (PDumpCtrlIsDumpSuspended())
+ {
+ eErr = PVRSRV_OK;
+ goto ErrOut;
+ }
+
+ if (pvPxMem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDUMPMMUDUMPPxENTRIES: PxMem is Null"));
+ eErr = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ErrOut;
+ }
+
+
+ /*
+ create the symbolic address of the Px
+ */
+ ui64PxSymAddr = sPxDevPAddr.uiAddr;
+
+ pszMMUPX = MMUPX_FMT(eMMULevel);
+ OSSNPrintf(aszPxSymbolicAddr,
+ MAX_SYMBOLIC_ADDRESS_LENGTH,
+ ":%s:%s%016llX",
+ pszPDumpDevName,
+ pszMMUPX,
+ ui64PxSymAddr);
+
+ PDumpOSLock();
+
+ /*
+ traverse PxEs, dumping entries
+ */
+ for(uiPxEIdx = uiFirstEntry;
+ uiPxEIdx < uiFirstEntry + uiNumEntries;
+ uiPxEIdx++)
+ {
+ /* Calc the symbolic address offset of the PxE location
+ This is what we have to add to the table address to get to a certain entry */
+ ui32SymAddrOffset = (uiPxEIdx*uiBytesPerEntry);
+
+ /* Calc the symbolic address of the PxE value and HW protflags */
+ /* just read it here */
+ switch(uiBytesPerEntry)
+ {
+ case 4:
+ {
+ pui32PxMem = pvPxMem;
+ ui64PxE64 = pui32PxMem[uiPxEIdx];
+ pszWrwSuffix = "";
+ pvRawBytes = &pui32PxMem[uiPxEIdx];
+ break;
+ }
+ case 8:
+ {
+ pui64PxMem = pvPxMem;
+ ui64PxE64 = pui64PxMem[uiPxEIdx];
+ pszWrwSuffix = "64";
+ pvRawBytes = &pui64PxMem[uiPxEIdx];
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMMUPxEntries: error"));
+ ui64PxE64 = 0;
+ //!!error
+ break;
+ }
+ }
+
+ ui64PxEValueSymAddr = (ui64PxE64 & uiAddrMask) >> uiAddrShift << uiLog2Align;
+ ui64Protflags64 = ui64PxE64 & uiPxEProtMask;
+
+ bPxEValid = (ui64Protflags64 & 1) ? IMG_TRUE : IMG_FALSE;
+
+ if(bPxEValid)
+ {
+ _ContiguousPDumpBytes(aszPxSymbolicAddr, ui32SymAddrOffset, IMG_TRUE,
+ 0, 0,
+ ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+
+ iShiftAmount = (IMG_INT32)(uiLog2Align - uiAddrShift);
+
+ /* First put the symbolic representation of the actual
+ address of the entry into a pdump internal register */
+ /* MOV seemed cleaner here, since (a) it's 64-bit; (b) the
+ target is not memory. However, MOV cannot do the
+ "reference" of the symbolic address. Apparently WRW is
+ correct. */
+
+ if (pszSymbolicAddr == IMG_NULL)
+ {
+ pszSymbolicAddr = "none";
+ }
+
+ if (eMMULevel == MMU_LEVEL_1)
+ {
+ if (iShiftAmount == 0)
+ {
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW%s :%s:%s%016llX:0x%08X :%s:%s:0x%llx | 0x%llX\n",
+ pszWrwSuffix,
+ /* dest */
+ pszPDumpDevName,
+ pszMMUPX,
+ ui64PxSymAddr,
+ ui32SymAddrOffset,
+ /* src */
+ pszMemspaceName,
+ pszSymbolicAddr,
+ uiSymbolicAddrOffset,
+ /* ORing prot flags */
+ ui64Protflags64);
+ }
+ else
+ {
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :%s:$1 :%s:%s:0x%llx\n",
+ /* dest */
+ pszPDumpDevName,
+ /* src */
+ pszMemspaceName,
+ pszSymbolicAddr,
+ uiSymbolicAddrOffset);
+ }
+ }
+ else
+ {
+ pszMMUPX = MMUPX_FMT(eMMULevel-1);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :%s:$1 :%s:%s%016llX:0x0",
+ /* dest */
+ pszPDumpDevName,
+ /* src */
+ pszPDumpDevName,
+ pszMMUPX,
+ ui64PxEValueSymAddr);
+ pszMMUPX = MMUPX_FMT(eMMULevel);
+ }
+ if (eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+
+ /* Now shift it to the right place, if necessary: */
+ /* Now shift that value down, by the "Align shift"
+ amount, to get it into units (ought to assert that
+ we get an integer - i.e. we don't shift any bits
+ off the bottom, don't know how to do PDUMP
+ assertions yet) and then back up by the right
+ amount to get it into the position of the field.
+ This is optimised into a single shift right by the
+ difference between the two. */
+ if (iShiftAmount > 0)
+ {
+ /* Page X Address is specified in units larger
+ than the position in the PxE would suggest. */
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SHR :%s:$1 :%s:$1 0x%X",
+ /* dest */
+ pszPDumpDevName,
+ /* src A */
+ pszPDumpDevName,
+ /* src B */
+ iShiftAmount);
+ if (eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ }
+ else if (iShiftAmount < 0)
+ {
+ /* Page X Address is specified in units smaller
+ than the position in the PxE would suggest. */
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SHL :%s:$1 :%s:$1 0x%X",
+ /* dest */
+ pszPDumpDevName,
+ /* src A */
+ pszPDumpDevName,
+ /* src B */
+ -iShiftAmount);
+ if (eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ }
+
+ if (eMMULevel == MMU_LEVEL_1)
+ {
+ if( iShiftAmount != 0)
+ {
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW%s :%s:%s%016llX:0x%08X :%s:$1 | 0x%llX",
+ pszWrwSuffix,
+ /* dest */
+ pszPDumpDevName,
+ pszMMUPX,
+ ui64PxSymAddr,
+ ui32SymAddrOffset,
+ /* src */
+ pszPDumpDevName,
+ /* ORing prot flags */
+ ui64Protflags64);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+ else
+ {
+ /* Now we can "or" in the protection flags */
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "OR :%s:$1 :%s:$1 0x%llX",
+ /* dest */
+ pszPDumpDevName,
+ /* src A */
+ pszPDumpDevName,
+ /* src B */
+ ui64Protflags64);
+ if (eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+
+ /* Finally, we write the register into the actual PxE */
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW%s :%s:%s%016llX:0x%08X :%s:$1",
+ pszWrwSuffix,
+ /* dest */
+ pszPDumpDevName,
+ pszMMUPX,
+ ui64PxSymAddr,
+ ui32SymAddrOffset,
+ /* src */
+ pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+ else
+ {
+ /* If the entry was "invalid", simply write the actual
+ value found to the memory location */
+ eErr = _ContiguousPDumpBytes(aszPxSymbolicAddr, ui32SymAddrOffset, IMG_FALSE,
+ uiBytesPerEntry, pvRawBytes,
+ ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ if (eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ }
+ }
+
+ /* flush out any partly accumulated stuff for LDB */
+ _ContiguousPDumpBytes(aszPxSymbolicAddr, ui32SymAddrOffset, IMG_TRUE,
+ 0, 0,
+ ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+
+ErrUnlock:
+ PDumpOSUnlock();
+ErrOut:
+ return eErr;
+}
+
+
+/**************************************************************************
+ * Function Name : _PdumpAllocMMUContext
+ * Inputs : pui32MMUContextID
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : pdump util to allocate MMU contexts
+**************************************************************************/
+static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
+{
+ IMG_UINT32 i;
+
+ /* there are MAX_PDUMP_MMU_CONTEXTS contexts available, find one */
+ for(i=0; i<MAX_PDUMP_MMU_CONTEXTS; i++)
+ {
+ if((guiPDumpMMUContextAvailabilityMask & (1U << i)))
+ {
+ /* mark in use */
+ guiPDumpMMUContextAvailabilityMask &= ~(1U << i);
+ *pui32MMUContextID = i;
+ return PVRSRV_OK;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "_PdumpAllocMMUContext: no free MMU context ids"));
+
+ return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+/**************************************************************************
+ * Function Name : _PdumpFreeMMUContext
+ * Inputs : ui32MMUContextID
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : pdump util to free MMU contexts
+**************************************************************************/
+static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
+{
+ if(ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS)
+ {
+ /* free the id */
+ PVR_ASSERT (!(guiPDumpMMUContextAvailabilityMask & (1U << ui32MMUContextID)));
+ guiPDumpMMUContextAvailabilityMask |= (1U << ui32MMUContextID);
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "_PdumpFreeMMUContext: MMU context ids invalid"));
+
+ return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpSetMMUContext
+ * Inputs :
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Set MMU Context
+**************************************************************************/
+PVRSRV_ERROR PDumpMMUAllocMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
+ IMG_DEV_PHYADDR sPCDevPAddr,
+ PDUMP_MMU_TYPE eMMUType,
+ IMG_UINT32 *pui32MMUContextID)
+{
+ IMG_UINT64 ui64PCSymAddr;
+ IMG_CHAR *pszMMUPX;
+
+ IMG_UINT32 ui32MMUContextID;
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = _PdumpAllocMMUContext(&ui32MMUContextID);
+ if(eErr != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d", eErr));
+ PVR_DBG_BREAK;
+ goto ErrOut;
+ }
+
+ /*
+ create the symbolic address of the PC
+ */
+ ui64PCSymAddr = sPCDevPAddr.uiAddr;
+
+ pszMMUPX = MMUPX_FMT(3);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "MMU :%s:v%d %d :%s:%s%016llX",
+ /* mmu context */
+ pszPDumpMemSpaceName,
+ ui32MMUContextID,
+ /* mmu type */
+ eMMUType,
+ /* PC base address */
+ pszPDumpMemSpaceName,
+ pszMMUPX,
+ ui64PCSymAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ PVR_DBG_BREAK;
+ goto ErrOut;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, PDUMP_FLAGS_CONTINUOUS);
+ PDumpOSUnlock();
+
+ /* return the MMU Context ID */
+ *pui32MMUContextID = ui32MMUContextID;
+
+ErrOut:
+ return eErr;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpClearMMUContext
+ * Inputs :
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Clear MMU Context
+**************************************************************************/
+PVRSRV_ERROR PDumpMMUFreeMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
+ IMG_UINT32 ui32MMUContextID)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "-- Clear MMU Context for memory space %s", pszPDumpMemSpaceName);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrOut;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "MMU :%s:v%d",
+ pszPDumpMemSpaceName,
+ ui32MMUContextID);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+
+ PDumpWriteScript(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr = _PdumpFreeMMUContext(ui32MMUContextID);
+ if(eErr != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d", eErr));
+ goto ErrUnlock;
+ }
+
+ErrUnlock:
+ PDumpOSUnlock();
+ErrOut:
+ return eErr;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpMMUActivateCatalog
+ * Inputs :
+ * Outputs :
+ * Returns : PVRSRV_ERROR
+ * Description :
+**************************************************************************/
+PVRSRV_ERROR PDumpMMUActivateCatalog(const IMG_CHAR *pszPDumpRegSpaceName,
+ const IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 uiRegAddr,
+ const IMG_CHAR *pszPDumpPCSymbolicName)
+{
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+ PVRSRV_ERROR eErr;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ if (!PDumpReady())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ }
+
+
+ if (PDumpCtrlIsDumpSuspended())
+ {
+ return PVRSRV_OK;
+ }
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+ "-- Write Page Catalogue Address to %s",
+ pszPDumpRegName);
+ if(eErr != PVRSRV_OK)
+ {
+ goto ErrOut;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, ui32Flags);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :%s:0x%04X %s:0",
+ /* dest */
+ pszPDumpRegSpaceName,
+ uiRegAddr,
+ /* src */
+ pszPDumpPCSymbolicName);
+ if (eErr != PVRSRV_OK)
+ {
+ goto ErrUnlock;
+ }
+ PDumpWriteScript(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+
+ErrUnlock:
+ PDumpOSUnlock();
+ErrOut:
+ return eErr;
+}
+
+
+PVRSRV_ERROR
+PDumpMMUSAB(const IMG_CHAR *pszPDumpMemNamespace,
+ IMG_UINT32 uiPDumpMMUCtx,
+ IMG_DEV_VIRTADDR sDevAddrStart,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 uiFileOffset,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ // "SAB :%s:v%x:0x%010llX 0x%08X 0x%08X %s.bin",
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ ui32PDumpFlags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ if (!PDumpReady())
+ {
+ eError = PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ goto ErrOut;
+ }
+
+
+ if (PDumpCtrlIsDumpSuspended())
+ {
+ eError = PVRSRV_OK;
+ goto ErrOut;
+ }
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:v%x:" IMG_DEV_VIRTADDR_FMTSPEC " "
+ IMG_DEVMEM_SIZE_FMTSPEC " "
+ "0x%x %s.bin\n",
+ pszPDumpMemNamespace,
+ uiPDumpMMUCtx,
+ sDevAddrStart.uiAddr,
+ uiSize,
+ uiFileOffset,
+ pszFilename);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ PDumpOSLock();
+ PDumpWriteScript(hScript, ui32PDumpFlags);
+ PDumpOSUnlock();
+
+ErrOut:
+ return eError;
+}
+
+#endif /* #if defined (PDUMP) */
+
diff --git a/drivers/gpu/rogue/services/server/common/pdump_physmem.c b/drivers/gpu/rogue/services/server/common/pdump_physmem.c
new file mode 100644
index 000000000000..c90dd6916c94
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/pdump_physmem.c
@@ -0,0 +1,479 @@
+/*************************************************************************/ /*!
+@File
+@Title Physmem PDump functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Common PDump (PMR 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(PDUMP)
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+
+#include "pdump_physmem.h"
+#include "pdump_osfunc.h"
+#include "pdump_km.h"
+
+#include "allocmem.h"
+#include "osfunc.h"
+
+/* #define MAX_PDUMP_MMU_CONTEXTS (10) */
+/* static IMG_UINT32 guiPDumpMMUContextAvailabilityMask = (1<<MAX_PDUMP_MMU_CONTEXTS)-1; */
+
+
+/* arbitrary buffer length here. */
+#define MAX_SYMBOLIC_ADDRESS_LENGTH 40
+
+struct _PDUMP_PHYSMEM_INFO_T_
+{
+ IMG_CHAR aszSymbolicAddress[MAX_SYMBOLIC_ADDRESS_LENGTH];
+ IMG_UINT64 ui64Size;
+ IMG_UINT32 ui32Align;
+ IMG_UINT32 ui32SerialNum;
+};
+
+
+/**************************************************************************
+ * Function Name : PDumpPMRMalloc
+ * Inputs :
+ * Outputs :
+ * Returns : PVRSRV_ERROR
+ * Description :
+**************************************************************************/
+PVRSRV_ERROR PDumpPMRMalloc(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicAddress,
+ IMG_UINT64 ui64Size,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ IMG_BOOL bForcePersistent,
+ IMG_HANDLE *phHandlePtr)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+
+ PDUMP_PHYSMEM_INFO_T *psPDumpAllocationInfo;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+ psPDumpAllocationInfo = OSAllocMem(sizeof*psPDumpAllocationInfo);
+ PVR_ASSERT(psPDumpAllocationInfo != IMG_NULL);
+
+ if (bForcePersistent)
+ {
+ ui32Flags |= PDUMP_FLAGS_PERSISTENT;
+ }
+ else
+ {
+ ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+ }
+
+ /*
+ construct the symbolic address
+ */
+
+ OSSNPrintf(psPDumpAllocationInfo->aszSymbolicAddress,
+ sizeof(psPDumpAllocationInfo->aszSymbolicAddress),
+ ":%s:%s",
+ pszDevSpace,
+ pszSymbolicAddress);
+
+ /*
+ Write to the MMU script stream indicating the memory allocation
+ */
+ eError = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC %s 0x%llX 0x%llX\n",
+ psPDumpAllocationInfo->aszSymbolicAddress,
+ ui64Size,
+ uiAlign);
+ if(eError != PVRSRV_OK)
+ {
+ OSFreeMem(psPDumpAllocationInfo);
+ return eError;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDumpOSUnlock();
+
+ psPDumpAllocationInfo->ui64Size = ui64Size;
+ psPDumpAllocationInfo->ui32Align = TRUNCATE_64BITS_TO_32BITS(uiAlign);
+
+ *phHandlePtr = (IMG_HANDLE)psPDumpAllocationInfo;
+
+ return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name : PDumpPMRFree
+ * Inputs :
+ * Outputs :
+ * Returns : PVRSRV_ERROR
+ * Description :
+**************************************************************************/
+PVRSRV_ERROR PDumpPMRFree(IMG_HANDLE hPDumpAllocationInfoHandle)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+
+ PDUMP_PHYSMEM_INFO_T *psPDumpAllocationInfo;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+ psPDumpAllocationInfo = (PDUMP_PHYSMEM_INFO_T *)hPDumpAllocationInfoHandle;
+
+ ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ /*
+ Write to the MMU script stream indicating the memory free
+ */
+ eError = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE %s\n",
+ psPDumpAllocationInfo->aszSymbolicAddress);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ PDumpOSLock();
+ PDumpWriteScript(hScript, ui32Flags);
+ PDumpOSUnlock();
+
+ OSFreeMem(psPDumpAllocationInfo);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PDumpPMRWRW32(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+ uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :%s:%s:" IMG_DEVMEM_OFFSET_FMTSPEC " "
+ PMR_VALUE32_FMTSPEC " ",
+ pszDevSpace,
+ pszSymbolicName,
+ uiOffset,
+ ui32Value);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ PDumpOSUnlock();
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PDumpPMRWRW64(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT64 ui64Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+ uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW64 :%s:%s:" IMG_DEVMEM_OFFSET_FMTSPEC " "
+ PMR_VALUE64_FMTSPEC " ",
+ pszDevSpace,
+ pszSymbolicName,
+ uiOffset,
+ ui64Value);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ PDumpOSUnlock();
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PDumpPMRLDB(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 uiFileOffset,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+ uiPDumpFlags |= (PDumpIsPersistent()) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "LDB :%s:%s:" IMG_DEVMEM_OFFSET_FMTSPEC " "
+ IMG_DEVMEM_SIZE_FMTSPEC " "
+ PDUMP_FILEOFFSET_FMTSPEC " %s\n",
+ pszDevSpace,
+ pszSymbolicName,
+ uiOffset,
+ uiSize,
+ uiFileOffset,
+ pszFilename);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ PDumpOSUnlock();
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPMRSAB(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFileName,
+ IMG_UINT32 uiFileOffset)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 uiPDumpFlags;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+ uiPDumpFlags = 0; //PDUMP_FLAGS_CONTINUOUS;
+ uiPDumpFlags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:%s:" IMG_DEVMEM_OFFSET_FMTSPEC " "
+ IMG_DEVMEM_SIZE_FMTSPEC " "
+ "0x%08X %s.bin\n",
+ pszDevSpace,
+ pszSymbolicName,
+ uiOffset,
+ uiSize,
+ uiFileOffset,
+ pszFileName);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ PDumpOSUnlock();
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PDumpPMRPOL(const IMG_CHAR *pszMemspaceName,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 uiCount,
+ IMG_UINT32 uiDelay,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+
+ uiPDumpFlags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "POL :%s:%s:" IMG_DEVMEM_OFFSET_FMTSPEC " "
+ "0x%08X 0x%08X %d %d %d\n",
+ pszMemspaceName,
+ pszSymbolicName,
+ uiOffset,
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ uiCount,
+ uiDelay);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ PDumpOSUnlock();
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PDumpPMRCBP(const IMG_CHAR *pszMemspaceName,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize)
+{
+ PVRSRV_ERROR eError;
+ PDUMP_FLAGS_T uiPDumpFlags = 0;
+
+ PDUMP_GET_SCRIPT_STRING()
+
+ uiPDumpFlags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ eError = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "CBP :%s:%s:" IMG_DEVMEM_OFFSET_FMTSPEC " "
+ IMG_DEVMEM_OFFSET_FMTSPEC " " IMG_DEVMEM_SIZE_FMTSPEC " " IMG_DEVMEM_SIZE_FMTSPEC "\n",
+ pszMemspaceName,
+ pszSymbolicName,
+ uiReadOffset,
+ uiWriteOffset,
+ uiPacketSize,
+ uiBufferSize);
+
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ PDumpOSLock();
+ PDumpWriteScript(hScript, uiPDumpFlags);
+ PDumpOSUnlock();
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PDumpWriteBuffer(IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiNumBytes,
+ PDUMP_FLAGS_T uiPDumpFlags,
+ IMG_CHAR *pszFilenameOut,
+ IMG_SIZE_T uiFilenameBufSz,
+ PDUMP_FILEOFFSET_T *puiOffsetOut)
+{
+ PVRSRV_ERROR eError;
+ PVR_UNREFERENCED_PARAMETER(uiFilenameBufSz);
+
+ if (!PDumpReady())
+ {
+ eError = PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ goto e0;
+ }
+
+ PVR_ASSERT(uiNumBytes > 0);
+
+ /* PRQA S 3415 1 */ /* side effects desired */
+ if (PDumpCtrlIsDumpSuspended())
+ {
+ return PVRSRV_OK;
+ }
+
+ PDumpOSLock();
+
+ eError = PDumpWriteParameter(pcBuffer, uiNumBytes, uiPDumpFlags, puiOffsetOut, pszFilenameOut);
+
+ PDumpOSUnlock();
+
+ PVR_LOGG_IF_ERROR(eError, "PDumpWriteParameter", e0);
+
+ return PVRSRV_OK;
+
+ e0:
+ /* Die on debug builds */
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_INTERNAL IMG_VOID
+PDumpPMRMallocPMR(const PMR *psPMR,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiBlockSize,
+ IMG_BOOL bForcePersistent,
+ IMG_HANDLE *phPDumpAllocInfoPtr)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hPDumpAllocInfo;
+ IMG_CHAR aszMemspaceName[30];
+ IMG_CHAR aszSymbolicName[30];
+ IMG_DEVMEM_OFFSET_T uiOffset;
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+
+ uiOffset = 0;
+ eError = PMR_PDumpSymbolicAddr(psPMR,
+ uiOffset,
+ sizeof(aszMemspaceName),
+ &aszMemspaceName[0],
+ sizeof(aszSymbolicName),
+ &aszSymbolicName[0],
+ &uiOffset,
+ &uiNextSymName);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ PVR_ASSERT(uiOffset == 0);
+ PVR_ASSERT((uiOffset + uiSize) <= uiNextSymName);
+
+ PDumpPMRMalloc(aszMemspaceName,
+ aszSymbolicName,
+ uiSize,
+ uiBlockSize,
+ bForcePersistent,
+ &hPDumpAllocInfo);
+
+ *phPDumpAllocInfoPtr = hPDumpAllocInfo;
+}
+#endif /* PDUMP */
diff --git a/drivers/gpu/rogue/services/server/common/physheap.c b/drivers/gpu/rogue/services/server/common/physheap.c
new file mode 100644
index 000000000000..9a9bde5b8047
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/physheap.c
@@ -0,0 +1,271 @@
+/*************************************************************************/ /*!
+@File physheap.c
+@Title Physical heap management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Management functions for the physical heap(s). A heap contains
+ all the information required by services when using memory from
+ that heap (such as CPU <> Device physical address translation).
+ A system must register one heap but can have more then one which
+ is why a heap must register with a (system) unique ID.
+@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 "physheap.h"
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+
+struct _PHYS_HEAP_
+{
+ /*! ID of this physcial memory heap */
+ IMG_UINT32 ui32PhysHeapID;
+ /*! The type of this heap */
+ PHYS_HEAP_TYPE eType;
+
+ /*! Start address of the physcial memory heap (LMA only) */
+ IMG_CPU_PHYADDR sStartAddr;
+ /*! Size of the physcial memory heap (LMA only) */
+ IMG_UINT64 uiSize;
+
+ /*! PDump name of this physcial memory heap */
+ IMG_CHAR *pszPDumpMemspaceName;
+ /*! Private data for the translate routines */
+ IMG_HANDLE hPrivData;
+ /*! Function callbacks */
+ PHYS_HEAP_FUNCTIONS *psMemFuncs;
+
+
+ /*! Refcount */
+ IMG_UINT32 ui32RefCount;
+ /*! Pointer to next physcial heap */
+ struct _PHYS_HEAP_ *psNext;
+};
+
+PHYS_HEAP *g_psPhysHeapList;
+
+#if defined(REFCOUNT_DEBUG)
+#define PHYSHEAP_REFCOUNT_PRINT(fmt, ...) \
+ PVRSRVDebugPrintf(PVR_DBG_WARNING, \
+ __FILE__, \
+ __LINE__, \
+ fmt, \
+ __VA_ARGS__)
+#else
+#define PHYSHEAP_REFCOUNT_PRINT(fmt, ...)
+#endif
+
+
+PVRSRV_ERROR PhysHeapRegister(PHYS_HEAP_CONFIG *psConfig,
+ PHYS_HEAP **ppsPhysHeap)
+{
+ PHYS_HEAP *psNew;
+ PHYS_HEAP *psTmp;
+
+ PVR_DPF_ENTERED;
+
+ if (psConfig->eType == PHYS_HEAP_TYPE_UNKNOWN)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Check this heap ID isn't already in use */
+ psTmp = g_psPhysHeapList;
+ while (psTmp)
+ {
+ if (psTmp->ui32PhysHeapID == psConfig->ui32PhysHeapID)
+ {
+ return PVRSRV_ERROR_PHYSHEAP_ID_IN_USE;
+ }
+ psTmp = psTmp->psNext;
+ }
+
+ psNew = OSAllocMem(sizeof(PHYS_HEAP));
+ if (psNew == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psNew->ui32PhysHeapID = psConfig->ui32PhysHeapID;
+ psNew->eType = psConfig->eType;
+ psNew->sStartAddr = psConfig->sStartAddr;
+ psNew->uiSize = psConfig->uiSize;
+ psNew->psMemFuncs = psConfig->psMemFuncs;
+ psNew->hPrivData = psConfig->hPrivData;
+ psNew->ui32RefCount = 0;
+ psNew->pszPDumpMemspaceName = psConfig->pszPDumpMemspaceName;
+
+ psNew->psNext = g_psPhysHeapList;
+ g_psPhysHeapList = psNew;
+
+ *ppsPhysHeap = psNew;
+
+ PVR_DPF_RETURN_RC1(PVRSRV_OK, *ppsPhysHeap);
+}
+
+IMG_VOID PhysHeapUnregister(PHYS_HEAP *psPhysHeap)
+{
+ PVR_DPF_ENTERED1(psPhysHeap);
+
+ PVR_ASSERT(psPhysHeap->ui32RefCount == 0);
+
+ if (g_psPhysHeapList == psPhysHeap)
+ {
+ g_psPhysHeapList = psPhysHeap->psNext;
+ }
+ else
+ {
+ PHYS_HEAP *psTmp = g_psPhysHeapList;
+
+ while(psTmp->psNext != psPhysHeap)
+ {
+ psTmp = psTmp->psNext;
+ }
+ psTmp->psNext = psPhysHeap->psNext;
+ }
+
+ OSFreeMem(psPhysHeap);
+
+ PVR_DPF_RETURN;
+}
+
+PVRSRV_ERROR PhysHeapAcquire(IMG_UINT32 ui32PhysHeapID,
+ PHYS_HEAP **ppsPhysHeap)
+{
+ PHYS_HEAP *psTmp = g_psPhysHeapList;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_DPF_ENTERED1(ui32PhysHeapID);
+
+ while (psTmp)
+ {
+ if (psTmp->ui32PhysHeapID == ui32PhysHeapID)
+ {
+ break;
+ }
+ psTmp = psTmp->psNext;
+ }
+
+ if (psTmp == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_PHYSHEAP_ID_INVALID;
+ }
+ else
+ {
+ psTmp->ui32RefCount++;
+ PHYSHEAP_REFCOUNT_PRINT("%s: Heap %p, refcount = %d", __FUNCTION__, psTmp, psTmp->ui32RefCount);
+ }
+
+ *ppsPhysHeap = psTmp;
+ PVR_DPF_RETURN_RC1(eError, *ppsPhysHeap);
+}
+
+IMG_VOID PhysHeapRelease(PHYS_HEAP *psPhysHeap)
+{
+ PVR_DPF_ENTERED1(psPhysHeap);
+
+ psPhysHeap->ui32RefCount--;
+ PHYSHEAP_REFCOUNT_PRINT("%s: Heap %p, refcount = %d", __FUNCTION__, psPhysHeap, psPhysHeap->ui32RefCount);
+
+ PVR_DPF_RETURN;
+}
+
+PHYS_HEAP_TYPE PhysHeapGetType(PHYS_HEAP *psPhysHeap)
+{
+ return psPhysHeap->eType;
+}
+
+PVRSRV_ERROR PhysHeapGetAddress(PHYS_HEAP *psPhysHeap,
+ IMG_CPU_PHYADDR *psCpuPAddr)
+{
+ if (psPhysHeap->eType == PHYS_HEAP_TYPE_LMA)
+ {
+ *psCpuPAddr = psPhysHeap->sStartAddr;
+ return PVRSRV_OK;
+ }
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+PVRSRV_ERROR PhysHeapGetSize(PHYS_HEAP *psPhysHeap,
+ IMG_UINT64 *puiSize)
+{
+ if (psPhysHeap->eType == PHYS_HEAP_TYPE_LMA)
+ {
+ *puiSize = psPhysHeap->uiSize;
+ return PVRSRV_OK;
+ }
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+IMG_VOID PhysHeapCpuPAddrToDevPAddr(PHYS_HEAP *psPhysHeap,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr)
+{
+ psPhysHeap->psMemFuncs->pfnCpuPAddrToDevPAddr(psPhysHeap->hPrivData,
+ psDevPAddr,
+ psCpuPAddr);
+}
+
+IMG_VOID PhysHeapDevPAddrToCpuPAddr(PHYS_HEAP *psPhysHeap,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ psPhysHeap->psMemFuncs->pfnDevPAddrToCpuPAddr(psPhysHeap->hPrivData,
+ psCpuPAddr,
+ psDevPAddr);
+}
+
+IMG_CHAR *PhysHeapPDumpMemspaceName(PHYS_HEAP *psPhysHeap)
+{
+ return psPhysHeap->pszPDumpMemspaceName;
+}
+
+PVRSRV_ERROR PhysHeapInit(IMG_VOID)
+{
+ g_psPhysHeapList = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PhysHeapDeinit(IMG_VOID)
+{
+ PVR_ASSERT(g_psPhysHeapList == IMG_NULL);
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/services/server/common/physmem.c b/drivers/gpu/rogue/services/server/common/physmem.c
new file mode 100644
index 000000000000..59629baa1540
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/physmem.c
@@ -0,0 +1,107 @@
+/*************************************************************************/ /*!
+@File physmem.c
+@Title Physmem
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Common entry point for creation of RAM backed PMR's
+@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 "pvrsrv_memallocflags.h"
+#include "device.h"
+#include "physmem.h"
+#include "pvrsrv.h"
+
+PVRSRV_ERROR
+PhysmemNewRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ PMR_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr)
+{
+ PVRSRV_DEVICE_PHYS_HEAP ePhysHeapIdx = (uiFlags & PVRSRV_MEMALLOCFLAG_CPU_LOCAL) ? 1: 0;
+ PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE pfnCheckMemAllocSize = \
+ psDevNode->psDevConfig->pfnCheckMemAllocSize;
+ /********************************
+ * Sanity check the cache flags *
+ ********************************/
+ /* Check if we can honour cached cache-coherent allocations */
+ if ((CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT) &&
+ (!PVRSRVSystemHasCacheSnooping()))
+ {
+ return PVRSRV_ERROR_UNSUPPORTED_CACHE_MODE;
+ }
+
+ /* Both or neither have to be cache-coherent */
+ if ((CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT) ^
+ (GPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT))
+ {
+ return PVRSRV_ERROR_UNSUPPORTED_CACHE_MODE;
+ }
+
+ if ((CPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT) ^
+ (GPU_CACHE_MODE(uiFlags) == PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT))
+ {
+ return PVRSRV_ERROR_UNSUPPORTED_CACHE_MODE;
+ }
+
+ /* Apply memory budgeting policy */
+ if (pfnCheckMemAllocSize)
+ {
+ PVRSRV_ERROR eError = \
+ pfnCheckMemAllocSize(psDevNode, (IMG_UINT64)uiChunkSize*ui32NumPhysChunks);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ return psDevNode->pfnCreateRamBackedPMR[ePhysHeapIdx](psDevNode,
+ uiSize,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ pabMappingTable,
+ uiLog2PageSize,
+ uiFlags,
+ ppsPMRPtr);
+}
diff --git a/drivers/gpu/rogue/services/server/common/physmem_lma.c b/drivers/gpu/rogue/services/server/common/physmem_lma.c
new file mode 100644
index 000000000000..39e9927342d3
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/physmem_lma.c
@@ -0,0 +1,952 @@
+/*************************************************************************/ /*!
+@File physmem_lma.c
+@Title Local card memory allocator
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is responsible for
+ implementing the function callbacks for local card memory.
+@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 "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+
+#include "allocmem.h"
+#include "osfunc.h"
+#include "pvrsrv.h"
+#include "physmem_lma.h"
+#include "pdump_physmem.h"
+#include "pdump_km.h"
+#include "pmr.h"
+#include "pmr_impl.h"
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#include "process_stats.h"
+#endif
+
+typedef struct _PMR_LMALLOCARRAY_DATA_ {
+ PVRSRV_DEVICE_NODE *psDevNode;
+ IMG_UINT32 uiNumAllocs;
+ IMG_UINT32 uiLog2AllocSize;
+ IMG_UINT32 uiAllocSize;
+ IMG_DEV_PHYADDR *pasDevPAddr;
+
+ IMG_BOOL bZeroOnAlloc;
+ IMG_BOOL bPoisonOnAlloc;
+
+ /* Tells if allocation is physically backed */
+ IMG_BOOL bHasLMPages;
+ IMG_BOOL bOnDemand;
+
+ /*
+ for pdump...
+ */
+ IMG_BOOL bPDumpMalloced;
+ IMG_HANDLE hPDumpAllocInfo;
+
+ /*
+ record at alloc time whether poisoning will be required when the
+ PMR is freed.
+ */
+ IMG_BOOL bPoisonOnFree;
+} PMR_LMALLOCARRAY_DATA;
+
+static PVRSRV_ERROR _MapAlloc(PVRSRV_DEVICE_NODE *psDevNode, IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_SIZE_T uiSize, IMG_VOID **pvPtr, PMR_FLAGS_T ulFlags)
+{
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PhysHeapDevPAddrToCpuPAddr(psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &sCpuPAddr, psDevPAddr);
+ *pvPtr = OSMapPhysToLin(sCpuPAddr,
+ uiSize,
+ ulFlags);
+
+ if (*pvPtr == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+ return PVRSRV_OK;
+ }
+}
+
+static IMG_VOID _UnMapAlloc(PVRSRV_DEVICE_NODE *psDevNode, IMG_SIZE_T uiSize, IMG_VOID *pvPtr)
+{
+ OSUnMapPhysToLin(pvPtr, uiSize, 0);
+}
+
+static PVRSRV_ERROR
+_PoisonAlloc(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_UINT32 uiAllocSize,
+ const IMG_CHAR *pacPoisonData,
+ IMG_SIZE_T uiPoisonSize)
+{
+ IMG_UINT32 uiSrcByteIndex;
+ IMG_UINT32 uiDestByteIndex;
+ IMG_VOID *pvKernLin = IMG_NULL;
+ IMG_CHAR *pcDest = IMG_NULL;
+
+ PVRSRV_ERROR eError;
+
+ eError = _MapAlloc(psDevNode, psDevPAddr, uiAllocSize, &pvKernLin, 0);
+ if (eError != PVRSRV_OK)
+ {
+ goto map_failed;
+ }
+ pcDest = pvKernLin;
+
+ uiSrcByteIndex = 0;
+ for(uiDestByteIndex=0; uiDestByteIndex<uiAllocSize; uiDestByteIndex++)
+ {
+ pcDest[uiDestByteIndex] = pacPoisonData[uiSrcByteIndex];
+ uiSrcByteIndex++;
+ if (uiSrcByteIndex == uiPoisonSize)
+ {
+ uiSrcByteIndex = 0;
+ }
+ }
+
+ _UnMapAlloc(psDevNode, uiAllocSize, pvKernLin);
+ return PVRSRV_OK;
+
+map_failed:
+ PVR_DPF((PVR_DBG_ERROR, "Failed to poison allocation"));
+ return eError;
+}
+
+static PVRSRV_ERROR
+_ZeroAlloc(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_UINT32 uiAllocSize)
+{
+ IMG_VOID *pvKernLin = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ eError = _MapAlloc(psDevNode, psDevPAddr, uiAllocSize, &pvKernLin, 0);
+ if (eError != PVRSRV_OK)
+ {
+ goto map_failed;
+ }
+
+ OSMemSet(pvKernLin, 0, uiAllocSize);
+
+ _UnMapAlloc(psDevNode, uiAllocSize, pvKernLin);
+ return PVRSRV_OK;
+
+map_failed:
+ PVR_DPF((PVR_DBG_ERROR, "Failed to zero allocation"));
+ return eError;
+}
+
+static const IMG_CHAR _AllocPoison[] = "^PoIsOn";
+static const IMG_UINT32 _AllocPoisonSize = 7;
+static const IMG_CHAR _FreePoison[] = "<DEAD-BEEF>";
+static const IMG_UINT32 _FreePoisonSize = 11;
+
+static PVRSRV_ERROR
+_AllocLMPageArray(PVRSRV_DEVICE_NODE *psDevNode,
+ PMR_SIZE_T uiSize,
+ PMR_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_UINT32 uiLog2PageSize,
+ IMG_BOOL bZero,
+ IMG_BOOL bPoisonOnAlloc,
+ IMG_BOOL bPoisonOnFree,
+ IMG_BOOL bContig,
+ IMG_BOOL bOnDemand,
+ PMR_LMALLOCARRAY_DATA **ppsPageArrayDataPtr
+ )
+{
+ PMR_LMALLOCARRAY_DATA *psPageArrayData = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(!bZero || !bPoisonOnAlloc);
+
+ if (uiSize >= 0x1000000000ULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "physmem_lma.c: Do you really want 64GB of physical memory in one go? This is likely a bug"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto errorOnParam;
+ }
+
+ PVR_ASSERT(OSGetPageShift() <= uiLog2PageSize);
+
+ if ((uiSize & ((1ULL << uiLog2PageSize) - 1)) != 0)
+ {
+ eError = PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE;
+ goto errorOnParam;
+ }
+
+ psPageArrayData = OSAllocMem(sizeof(PMR_LMALLOCARRAY_DATA));
+ if (psPageArrayData == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto errorOnAllocArray;
+ }
+ OSMemSet(psPageArrayData, 0, sizeof(PMR_LMALLOCARRAY_DATA));
+
+ if (bContig)
+ {
+ /*
+ Some allocations require kernel mappings in which case in order
+ to be virtually contiguous we also have to be physically contiguous.
+ */
+ psPageArrayData->uiNumAllocs = 1;
+ psPageArrayData->uiAllocSize = TRUNCATE_64BITS_TO_32BITS(uiSize);
+ psPageArrayData->uiLog2AllocSize = uiLog2PageSize;
+ }
+ else
+ {
+ IMG_UINT32 uiNumPages;
+
+ /* Use of cast below is justified by the assertion that follows to
+ prove that no significant bits have been truncated */
+ uiNumPages = (IMG_UINT32)(((uiSize-1)>>uiLog2PageSize) + 1);
+ PVR_ASSERT(((PMR_SIZE_T)uiNumPages << uiLog2PageSize) == uiSize);
+
+ psPageArrayData->uiNumAllocs = uiNumPages;
+ psPageArrayData->uiAllocSize = 1 << uiLog2PageSize;
+ psPageArrayData->uiLog2AllocSize = uiLog2PageSize;
+ }
+ psPageArrayData->psDevNode = psDevNode;
+ psPageArrayData->pasDevPAddr = OSAllocMem(sizeof(IMG_DEV_PHYADDR)*
+ psPageArrayData->uiNumAllocs);
+ if (psPageArrayData->pasDevPAddr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto errorOnAllocAddr;
+ }
+ OSMemSet(psPageArrayData->pasDevPAddr, 0, sizeof(IMG_DEV_PHYADDR)*
+ psPageArrayData->uiNumAllocs);
+
+ /* N.B. We have a window of opportunity where a failure in
+ createPMR the finalize function can be called before the PMR
+ MALLOC and thus the hPDumpAllocInfo won't be set. So we have
+ to conditionally call the PDumpFree function. */
+ psPageArrayData->bPDumpMalloced = IMG_FALSE;
+
+ psPageArrayData->bZeroOnAlloc = bZero;
+ psPageArrayData->bPoisonOnAlloc = bPoisonOnAlloc;
+ psPageArrayData->bPoisonOnFree = bPoisonOnFree;
+ psPageArrayData->bHasLMPages = IMG_FALSE;
+ psPageArrayData->bOnDemand = bOnDemand;
+
+ *ppsPageArrayDataPtr = psPageArrayData;
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow:
+ */
+
+errorOnAllocAddr:
+ OSFreeMem(psPageArrayData);
+
+errorOnAllocArray:
+errorOnParam:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+static PVRSRV_ERROR
+_AllocLMPages(PMR_LMALLOCARRAY_DATA *psPageArrayDataPtr)
+{
+ IMG_UINT32 uiAllocSize = psPageArrayDataPtr->uiAllocSize;
+ IMG_UINT32 uiLog2AllocSize = psPageArrayDataPtr->uiLog2AllocSize;
+ PVRSRV_DEVICE_NODE *psDevNode = psPageArrayDataPtr->psDevNode;
+ IMG_BOOL bPoisonOnAlloc = psPageArrayDataPtr->bPoisonOnAlloc;
+ IMG_BOOL bZeroOnAlloc = psPageArrayDataPtr->bZeroOnAlloc;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bAllocResult;
+ RA_BASE_T uiCardAddr;
+ RA_LENGTH_T uiActualSize;
+ IMG_UINT32 i;
+
+ PVR_ASSERT(!psPageArrayDataPtr->bHasLMPages);
+
+ for(i=0;i<psPageArrayDataPtr->uiNumAllocs;i++)
+ {
+ bAllocResult = RA_Alloc(psDevNode->psLocalDevMemArena,
+ uiAllocSize,
+ 0, /* No flags */
+ 1ULL << uiLog2AllocSize,
+ &uiCardAddr,
+ &uiActualSize,
+ IMG_NULL); /* No private handle */
+
+ if (!bAllocResult)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto errorOnRAAlloc;
+ }
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Allocation is done a page at a time */
+ PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES, uiActualSize);
+#else
+ {
+ IMG_CPU_PHYADDR sLocalCpuPAddr;
+ sLocalCpuPAddr.uiAddr = (IMG_UINT64)uiCardAddr;
+ PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES,
+ IMG_NULL,
+ sLocalCpuPAddr,
+ uiActualSize,
+ IMG_NULL);
+ }
+#endif
+#endif
+ psPageArrayDataPtr->pasDevPAddr[i].uiAddr = uiCardAddr;
+
+ if (bPoisonOnAlloc)
+ {
+ eError = _PoisonAlloc(psDevNode,
+ &psPageArrayDataPtr->pasDevPAddr[i],
+ uiAllocSize,
+ _AllocPoison,
+ _AllocPoisonSize);
+ if (eError !=PVRSRV_OK)
+ {
+ goto errorOnPoison;
+ }
+ }
+
+ if (bZeroOnAlloc)
+ {
+ eError = _ZeroAlloc(psDevNode,
+ &psPageArrayDataPtr->pasDevPAddr[i],
+ uiAllocSize);
+ if (eError !=PVRSRV_OK)
+ {
+ goto errorOnZero;
+ }
+ }
+ }
+
+ psPageArrayDataPtr->bHasLMPages = IMG_TRUE;
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow:
+ */
+errorOnZero:
+errorOnPoison:
+errorOnRAAlloc:
+ while (i)
+ {
+ i--;
+ RA_Free(psDevNode->psLocalDevMemArena,
+ psPageArrayDataPtr->pasDevPAddr[i].uiAddr);
+ }
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+static PVRSRV_ERROR
+_FreeLMPageArray(PMR_LMALLOCARRAY_DATA *psPageArrayData)
+{
+ OSFreeMem(psPageArrayData->pasDevPAddr);
+ OSFreeMem(psPageArrayData);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "physmem_lma.c: freed local memory array structure for PMR @0x%p", psPageArrayData));
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_FreeLMPages(PMR_LMALLOCARRAY_DATA *psPageArrayData)
+{
+ IMG_UINT32 uiAllocSize;
+ IMG_UINT32 i;
+
+ PVR_ASSERT(psPageArrayData->bHasLMPages);
+
+ uiAllocSize = psPageArrayData->uiAllocSize;
+
+ for (i = 0;i < psPageArrayData->uiNumAllocs;i++)
+ {
+ if (psPageArrayData->bPoisonOnFree)
+ {
+ _PoisonAlloc(psPageArrayData->psDevNode,
+ &psPageArrayData->pasDevPAddr[i],
+ uiAllocSize,
+ _FreePoison,
+ _FreePoisonSize);
+ }
+ RA_Free(psPageArrayData->psDevNode->psLocalDevMemArena,
+ psPageArrayData->pasDevPAddr[i].uiAddr);
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Allocation is done a page at a time */
+ PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES, uiAllocSize);
+#else
+ {
+ PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES, psPageArrayData->pasDevPAddr[i].uiAddr);
+ }
+#endif
+#endif
+ }
+
+ psPageArrayData->bHasLMPages = IMG_FALSE;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "physmem_lma.c: freed local memory for PMR @0x%p", psPageArrayData));
+
+ return PVRSRV_OK;
+}
+
+/*
+ *
+ * Implementation of callback functions
+ *
+ */
+
+/* destructor func is called after last reference disappears, but
+ before PMR itself is freed. */
+static PVRSRV_ERROR
+PMRFinalizeLocalMem(PMR_IMPL_PRIVDATA pvPriv
+ )
+{
+ PVRSRV_ERROR eError;
+ PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = IMG_NULL;
+
+ psLMAllocArrayData = pvPriv;
+
+ /* Conditionally do the PDump free, because if CreatePMR failed we
+ won't have done the PDump MALLOC. */
+ if (psLMAllocArrayData->bPDumpMalloced)
+ {
+ PDumpPMRFree(psLMAllocArrayData->hPDumpAllocInfo);
+ }
+
+ /* We can't free pages until now. */
+ if (psLMAllocArrayData->bHasLMPages)
+ {
+ eError = _FreeLMPages(psLMAllocArrayData);
+ PVR_ASSERT (eError == PVRSRV_OK); /* can we do better? */
+ }
+
+ eError = _FreeLMPageArray(psLMAllocArrayData);
+ PVR_ASSERT (eError == PVRSRV_OK); /* can we do better? */
+
+ return PVRSRV_OK;
+}
+
+/* callback function for locking the system physical page addresses.
+ As we are LMA there is nothing to do as we control physical memory. */
+static PVRSRV_ERROR
+PMRLockSysPhysAddressesLocalMem(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_UINT32 uiLog2DevPageSize)
+{
+
+ PVRSRV_ERROR eError;
+ PMR_LMALLOCARRAY_DATA *psLMAllocArrayData;
+
+ psLMAllocArrayData = pvPriv;
+
+ if (psLMAllocArrayData->bOnDemand)
+ {
+ /* Allocate Memory for deferred allocation */
+ eError = _AllocLMPages(psLMAllocArrayData);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ PVR_UNREFERENCED_PARAMETER(uiLog2DevPageSize);
+
+ return PVRSRV_OK;
+
+}
+
+static PVRSRV_ERROR
+PMRUnlockSysPhysAddressesLocalMem(PMR_IMPL_PRIVDATA pvPriv
+ )
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PMR_LMALLOCARRAY_DATA *psLMAllocArrayData;
+
+ psLMAllocArrayData = pvPriv;
+
+ if (psLMAllocArrayData->bOnDemand)
+ {
+ /* Free Memory for deferred allocation */
+ eError = _FreeLMPages(psLMAllocArrayData);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+ return eError;
+}
+
+/* N.B. It is assumed that PMRLockSysPhysAddressesLocalMem() is called _before_ this function! */
+static PVRSRV_ERROR
+PMRSysPhysAddrLocalMem(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEV_PHYADDR *psDevPAddr
+ )
+{
+ IMG_UINT32 uiLog2AllocSize;
+ IMG_UINT32 uiNumAllocs;
+ IMG_UINT64 uiAllocIndex;
+ IMG_DEVMEM_OFFSET_T uiInAllocOffset;
+ PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = IMG_NULL;
+
+ psLMAllocArrayData = pvPriv;
+
+ uiNumAllocs = psLMAllocArrayData->uiNumAllocs;
+ if (uiNumAllocs > 1)
+ {
+ PVR_ASSERT(psLMAllocArrayData->uiLog2AllocSize != 0);
+ uiLog2AllocSize = psLMAllocArrayData->uiLog2AllocSize;
+
+ uiAllocIndex = uiOffset >> uiLog2AllocSize;
+ uiInAllocOffset = uiOffset - (uiAllocIndex << uiLog2AllocSize);
+ PVR_ASSERT(uiAllocIndex < uiNumAllocs);
+ PVR_ASSERT(uiInAllocOffset < (1ULL << uiLog2AllocSize));
+
+ psDevPAddr->uiAddr = psLMAllocArrayData->pasDevPAddr[uiAllocIndex].uiAddr + uiInAllocOffset;
+ }
+ else
+ {
+ psDevPAddr->uiAddr = psLMAllocArrayData->pasDevPAddr[0].uiAddr + uiOffset;
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PMRAcquireKernelMappingDataLocalMem(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ IMG_VOID **ppvKernelAddressOut,
+ IMG_HANDLE *phHandleOut,
+ PMR_FLAGS_T ulFlags)
+{
+ PVRSRV_ERROR eError;
+ PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = IMG_NULL;
+ IMG_VOID *pvKernLinAddr = IMG_NULL;
+ IMG_UINT32 ui32PageIndex = 0;
+
+ PVR_UNREFERENCED_PARAMETER(ulFlags);
+
+ psLMAllocArrayData = pvPriv;
+
+ /* Check that we can map this in contiguously */
+ if (psLMAllocArrayData->uiNumAllocs != 1)
+ {
+ IMG_SIZE_T uiStart = uiOffset;
+ IMG_SIZE_T uiEnd = uiOffset + uiSize - 1;
+ IMG_SIZE_T uiPageMask = ~((1 << psLMAllocArrayData->uiLog2AllocSize) - 1);
+
+ /* We can still map if only one page is required */
+ if ((uiStart & uiPageMask) != (uiEnd & uiPageMask))
+ {
+ eError = PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
+ goto e0;
+ }
+
+ /* Locate the desired physical page to map in */
+ ui32PageIndex = uiOffset >> psLMAllocArrayData->uiLog2AllocSize;
+ }
+
+ PVR_ASSERT(ui32PageIndex < psLMAllocArrayData->uiNumAllocs);
+
+ eError = _MapAlloc(psLMAllocArrayData->psDevNode,
+ &psLMAllocArrayData->pasDevPAddr[ui32PageIndex],
+ psLMAllocArrayData->uiAllocSize,
+ &pvKernLinAddr,
+ ulFlags);
+
+ *ppvKernelAddressOut = ((IMG_CHAR *) pvKernLinAddr) + (uiOffset & ((1U << psLMAllocArrayData->uiLog2AllocSize) - 1));
+ *phHandleOut = pvKernLinAddr;
+
+ return eError;
+
+ /*
+ error exit paths follow
+ */
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+static IMG_VOID PMRReleaseKernelMappingDataLocalMem(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_HANDLE hHandle)
+{
+ PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = IMG_NULL;
+ IMG_VOID *pvKernLinAddr = IMG_NULL;
+
+ psLMAllocArrayData = (PMR_LMALLOCARRAY_DATA *) pvPriv;
+ pvKernLinAddr = (IMG_VOID *) hHandle;
+
+ _UnMapAlloc(psLMAllocArrayData->psDevNode,
+ psLMAllocArrayData->uiAllocSize, pvKernLinAddr);
+}
+
+
+static PVRSRV_ERROR
+CopyBytesLocalMem(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes,
+ IMG_VOID (*pfnCopyBytes)(IMG_UINT8 *pcBuffer,
+ IMG_UINT8 *pcPMR,
+ IMG_SIZE_T uiSize))
+{
+ PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = IMG_NULL;
+ IMG_SIZE_T uiBytesCopied;
+ IMG_SIZE_T uiBytesToCopy;
+ IMG_SIZE_T uiBytesCopyableFromAlloc;
+ IMG_VOID *pvMapping = IMG_NULL;
+ IMG_UINT8 *pcKernelPointer = IMG_NULL;
+ IMG_SIZE_T uiBufferOffset;
+ IMG_UINT64 uiAllocIndex;
+ IMG_DEVMEM_OFFSET_T uiInAllocOffset;
+ PVRSRV_ERROR eError;
+
+ psLMAllocArrayData = pvPriv;
+
+ uiBytesCopied = 0;
+ uiBytesToCopy = uiBufSz;
+ uiBufferOffset = 0;
+
+ if (psLMAllocArrayData->uiNumAllocs > 1)
+ {
+ while (uiBytesToCopy > 0)
+ {
+ /* we have to map one alloc in at a time */
+ PVR_ASSERT(psLMAllocArrayData->uiLog2AllocSize != 0);
+ uiAllocIndex = uiOffset >> psLMAllocArrayData->uiLog2AllocSize;
+ uiInAllocOffset = uiOffset - (uiAllocIndex << psLMAllocArrayData->uiLog2AllocSize);
+ uiBytesCopyableFromAlloc = uiBytesToCopy;
+ if (uiBytesCopyableFromAlloc + uiInAllocOffset > (1ULL << psLMAllocArrayData->uiLog2AllocSize))
+ {
+ uiBytesCopyableFromAlloc = TRUNCATE_64BITS_TO_SIZE_T((1ULL << psLMAllocArrayData->uiLog2AllocSize)-uiInAllocOffset);
+ }
+
+ PVR_ASSERT(uiBytesCopyableFromAlloc != 0);
+ PVR_ASSERT(uiAllocIndex < psLMAllocArrayData->uiNumAllocs);
+ PVR_ASSERT(uiInAllocOffset < (1ULL << psLMAllocArrayData->uiLog2AllocSize));
+
+ eError = _MapAlloc(psLMAllocArrayData->psDevNode,
+ &psLMAllocArrayData->pasDevPAddr[uiAllocIndex],
+ psLMAllocArrayData->uiAllocSize,
+ &pvMapping, 0);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+ pcKernelPointer = pvMapping;
+ pfnCopyBytes(&pcBuffer[uiBufferOffset], &pcKernelPointer[uiInAllocOffset], uiBytesCopyableFromAlloc);
+ _UnMapAlloc(psLMAllocArrayData->psDevNode, psLMAllocArrayData->uiAllocSize, pvMapping);
+ uiBufferOffset += uiBytesCopyableFromAlloc;
+ uiBytesToCopy -= uiBytesCopyableFromAlloc;
+ uiOffset += uiBytesCopyableFromAlloc;
+ uiBytesCopied += uiBytesCopyableFromAlloc;
+ }
+ }
+ else
+ {
+ PVR_ASSERT((uiOffset + uiBufSz) <= psLMAllocArrayData->uiAllocSize);
+ PVR_ASSERT(psLMAllocArrayData->uiAllocSize != 0);
+ eError = _MapAlloc(psLMAllocArrayData->psDevNode,
+ &psLMAllocArrayData->pasDevPAddr[0],
+ psLMAllocArrayData->uiAllocSize,
+ &pvMapping, 0);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+ pcKernelPointer = pvMapping;
+ pfnCopyBytes(pcBuffer, &pcKernelPointer[uiOffset], uiBufSz);
+ _UnMapAlloc(psLMAllocArrayData->psDevNode, psLMAllocArrayData->uiAllocSize, pvMapping);
+ uiBytesCopied = uiBufSz;
+ }
+ *puiNumBytes = uiBytesCopied;
+ return PVRSRV_OK;
+e0:
+ *puiNumBytes = uiBytesCopied;
+ return eError;
+}
+
+static IMG_VOID ReadLocalMem(IMG_UINT8 *pcBuffer,
+ IMG_UINT8 *pcPMR,
+ IMG_SIZE_T uiSize)
+{
+ OSMemCopy(pcBuffer, pcPMR, uiSize);
+}
+
+static PVRSRV_ERROR
+PMRReadBytesLocalMem(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes)
+{
+ return CopyBytesLocalMem(pvPriv,
+ uiOffset,
+ pcBuffer,
+ uiBufSz,
+ puiNumBytes,
+ ReadLocalMem);
+}
+
+static IMG_VOID WriteLocalMem(IMG_UINT8 *pcBuffer,
+ IMG_UINT8 *pcPMR,
+ IMG_SIZE_T uiSize)
+{
+ OSMemCopy(pcPMR, pcBuffer, uiSize);
+}
+
+static PVRSRV_ERROR
+PMRWriteBytesLocalMem(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes)
+{
+ return CopyBytesLocalMem(pvPriv,
+ uiOffset,
+ pcBuffer,
+ uiBufSz,
+ puiNumBytes,
+ WriteLocalMem);
+}
+
+static PMR_IMPL_FUNCTAB _sPMRLMAFuncTab = {
+ /* pfnLockPhysAddresses */
+ &PMRLockSysPhysAddressesLocalMem,
+ /* pfnUnlockPhysAddresses */
+ &PMRUnlockSysPhysAddressesLocalMem,
+ /* pfnDevPhysAddr */
+ &PMRSysPhysAddrLocalMem,
+ /* pfnPDumpSymbolicAddr */
+ IMG_NULL,
+ /* pfnAcquireKernelMappingData */
+ &PMRAcquireKernelMappingDataLocalMem,
+ /* pfnReleaseKernelMappingData */
+ &PMRReleaseKernelMappingDataLocalMem,
+ /* pfnReadBytes */
+ &PMRReadBytesLocalMem,
+ /* pfnWriteBytes */
+ &PMRWriteBytesLocalMem,
+ /* pfnFinalize */
+ &PMRFinalizeLocalMem
+};
+
+PVRSRV_ERROR
+PhysmemNewLocalRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError2;
+ PMR *psPMR = IMG_NULL;
+ PMR_LMALLOCARRAY_DATA *psPrivData = IMG_NULL;
+ IMG_HANDLE hPDumpAllocInfo = IMG_NULL;
+ PMR_FLAGS_T uiPMRFlags;
+ IMG_BOOL bZero;
+ IMG_BOOL bPoisonOnAlloc;
+ IMG_BOOL bPoisonOnFree;
+ IMG_BOOL bOnDemand = ((uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) > 0);
+ IMG_BOOL bContig;
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+ {
+ bZero = IMG_TRUE;
+ }
+ else
+ {
+ bZero = IMG_FALSE;
+ }
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC)
+ {
+ bPoisonOnAlloc = IMG_TRUE;
+ }
+ else
+ {
+ bPoisonOnAlloc = IMG_FALSE;
+ }
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE)
+ {
+ bPoisonOnFree = IMG_TRUE;
+ }
+ else
+ {
+ bPoisonOnFree = IMG_FALSE;
+ }
+
+#if defined (UNDER_WDDM)
+ bContig = IMG_TRUE;
+#else
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE)
+ {
+ bContig = IMG_TRUE;
+ }
+ else
+ {
+ bContig = IMG_FALSE;
+ }
+#endif
+
+ if ((uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &&
+ (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
+ {
+ /* Zero on Alloc and Poison on Alloc are mutually exclusive */
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto errorOnParam;
+ }
+
+ /* Silently round up alignment/pagesize if request was less that
+ PAGE_SHIFT, because it would never be harmful for memory to be
+ _more_ contiguous that was desired */
+
+ uiLog2PageSize = OSGetPageShift() > uiLog2PageSize
+ ? OSGetPageShift()
+ : uiLog2PageSize;
+
+ /* Create Array structure that holds the physical pages */
+ eError = _AllocLMPageArray(psDevNode,
+ uiChunkSize * ui32NumPhysChunks,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ pabMappingTable,
+ uiLog2PageSize,
+ bZero,
+ bPoisonOnAlloc,
+ bPoisonOnFree,
+ bContig,
+ bOnDemand,
+ &psPrivData);
+ if (eError != PVRSRV_OK)
+ {
+ goto errorOnAllocPageArray;
+ }
+
+
+ if (!bOnDemand)
+ {
+ /* Allocate the physical pages */
+ eError = _AllocLMPages(psPrivData);
+ if (eError != PVRSRV_OK)
+ {
+ goto errorOnAllocPages;
+ }
+ }
+
+ /* In this instance, we simply pass flags straight through.
+
+ Generically, uiFlags can include things that control the PMR
+ factory, but we don't need any such thing (at the time of
+ writing!), and our caller specifies all PMR flags so we don't
+ need to meddle with what was given to us.
+ */
+ uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
+ /* check no significant bits were lost in cast due to different
+ bit widths for flags */
+ PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
+
+ if (bOnDemand)
+ {
+ PDUMPCOMMENT("Deferred Allocation PMR (LMA)");
+ }
+ eError = PMRCreatePMR(psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL],
+ uiSize,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ pabMappingTable,
+ uiLog2PageSize,
+ uiPMRFlags,
+ "PMRLMA",
+ &_sPMRLMAFuncTab,
+ psPrivData,
+ &psPMR,
+ &hPDumpAllocInfo,
+ IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ goto errorOnCreate;
+ }
+
+ psPrivData->hPDumpAllocInfo = hPDumpAllocInfo;
+ psPrivData->bPDumpMalloced = IMG_TRUE;
+
+ *ppsPMRPtr = psPMR;
+ return PVRSRV_OK;
+
+errorOnCreate:
+ if(!bOnDemand)
+ {
+ eError2 = _FreeLMPages(psPrivData);
+ PVR_ASSERT(eError2 == PVRSRV_OK);
+ }
+
+errorOnAllocPages:
+ eError2 = _FreeLMPageArray(psPrivData);
+ PVR_ASSERT(eError2 == PVRSRV_OK);
+
+errorOnAllocPageArray:
+errorOnParam:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
diff --git a/drivers/gpu/rogue/services/server/common/pmr.c b/drivers/gpu/rogue/services/server/common/pmr.c
new file mode 100644
index 000000000000..503afe9b219c
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/pmr.c
@@ -0,0 +1,2653 @@
+/*************************************************************************/ /*!
+@File
+@Title Physmem (PMR) abstraction
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is responsible for
+ the "PMR" abstraction. A PMR (Physical Memory Resource)
+ represents some unit of physical memory which is
+ allocated/freed/mapped/unmapped as an indivisible unit
+ (higher software levels provide an abstraction above that
+ to deal with dividing this down into smaller manageable units).
+ Importantly, this module knows nothing of virtual memory, or
+ of MMUs etc., with one excuseable exception. We have the
+ concept of a "page size", which really means nothing in
+ physical memory, but represents a "contiguity quantum" such
+ that the higher level modules which map this memory are able
+ to verify that it matches the needs of the page size for the
+ virtual realm into which it is being mapped.
+@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 "pvr_debug.h"
+#include "pvrsrv_error.h"
+
+#include "pdump.h"
+
+#include "osfunc.h"
+#include "pdump_km.h"
+#include "pdump_physmem.h"
+#include "pmr_impl.h"
+#include "pvrsrv.h"
+
+#include "allocmem.h"
+#include "lock.h"
+
+#if defined(SUPPORT_SECURE_EXPORT)
+#include "secure_export.h"
+#include "ossecure_export.h"
+#endif
+
+#if defined(PVR_RI_DEBUG)
+#include "ri_server.h"
+#endif
+
+/* ourselves */
+#include "pmr.h"
+
+/* A "context" for the physical memory block resource allocator.
+
+ Context is probably the wrong word.
+
+ There is almost certainly only one of these, ever, in the system.
+ But, let's keep the notion of a context anyway, "just-in-case".
+*/
+struct _PMR_CTX_
+{
+ /* For debugging, and PDump, etc., let's issue a forever
+ incrementing serial number to each allocation. */
+ IMG_UINT64 uiNextSerialNum;
+
+ /* For security, we only allow a PMR to be mapped if the caller
+ knows its key. We can pseudo-randomly generate keys */
+ IMG_UINT64 uiNextKey;
+
+ /* For debugging only, I guess: Number of live PMRs */
+ IMG_UINT32 uiNumLivePMRs;
+
+ /* Lock for this structure */
+ POS_LOCK hLock;
+
+ /* In order to seed the uiNextKey, we enforce initialisation at
+ driver load time. Also, we can debug check at driver unload
+ that the PMR count is zero. */
+ IMG_BOOL bModuleInitialised;
+} _gsSingletonPMRContext = { 1, 0, 0, IMG_NULL, IMG_FALSE };
+
+
+typedef struct _PMR_MAPPING_TABLE_
+{
+ PMR_SIZE_T uiChunkSize; /*!< Size of a "chunk" */
+ IMG_UINT32 ui32NumPhysChunks; /*!< Number of physical chunks that are valid */
+ IMG_UINT32 ui32NumVirtChunks; /*!< Number of virtual chunks in the mapping */
+ /* Must be last */
+ IMG_UINT32 aui32Translation[1]; /*!< Translation mapping for "logical" to physical */
+} PMR_MAPPING_TABLE;
+
+#define TRANSLATION_INVALID 0xFFFFFFFFL
+
+/* A PMR. One per physical allocation. May be "shared".
+
+ "shared" is ambiguous. We need to be careful with terminology.
+ There are two ways in which a PMR may be "shared" and we need to be
+ sure that we are clear which we mean.
+
+ i) multiple small allocations living together inside one PMR;
+
+ ii) one single allocation filling a PMR but mapped into multiple
+ memory contexts.
+
+ This is more important further up the stack - at this level, all we
+ care is that the PMR is being referenced multiple times.
+*/
+struct _PMR_
+{
+ /* This object is strictly refcounted. References include:
+ - mapping
+ - live handles (to this object)
+ - live export handles
+ (thus it is normal for allocated and exported memory to have a refcount of 3)
+ The object is destroyed when and only when the refcount reaches 0
+ */
+ /*
+ Physical address translation (device <> cpu) is done on a per device
+ basis which means we need the physcial heap info
+ */
+ PHYS_HEAP *psPhysHeap;
+
+ IMG_UINT32 uiRefCount;
+
+ /* lock count - this is the number of times
+ PMRLockSysPhysAddresses() has been called, less the number of
+ PMRUnlockSysPhysAddresses() calls. This is arguably here for
+ debug reasons only, as the refcount is already incremented as a
+ matter of course. Really, this just allows us to trap protocol
+ errors: i.e. calling PMRSysPhysAddr(),
+ without a lock, or calling PMRUnlockSysPhysAddresses() too many
+ or too few times. */
+ IMG_UINT32 uiLockCount;
+
+ /* 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;
+
+ /* And for pdump */
+ const IMG_CHAR *pszPDumpDefaultMemspaceName;
+ const IMG_CHAR *pszPDumpFlavour;
+
+ /* Logical size of allocation. "logical", because a PMR can
+ represent memory that will never physically exist. This is the
+ amount of virtual space that the PMR would consume when it's
+ mapped into a virtual allocation. */
+ PMR_SIZE_T uiLogicalSize;
+
+ /* Mapping table for the allocation.
+ PMR's can be sparse in which case not all the "logic" addresses
+ in it are valid. We need to know which addresses are and aren't
+ valid when mapping or reading the PMR.
+ The mapping table translates "logical" offsets into physical
+ offsets which is what we always pass to the PMR factory
+ (so it doesn't have to be concerned about sparseness issues) */
+ PMR_MAPPING_TABLE *psMappingTable;
+
+ /* Minimum Physical Contiguity Guarantee. Might be called "page
+ size", but that would be incorrect, as page size is something
+ meaningful only in virtual realm. This contiguity guarantee
+ provides an inequality that can be verified/asserted/whatever
+ to ensure that this PMR conforms to the page size requirement
+ of the place the PMR gets mapped. (May be used to select an
+ appropriate heap in variable page size systems)
+
+ The absolutely necessary condition is this:
+
+ device MMU page size <= actual physical contiguity.
+
+ We go one step further in order to be able to provide an early warning / early compatibility check and say this:
+
+ device MMU page size <= 2**(uiLog2ContiguityGuarantee) <= actual physical contiguity.
+
+ In this way, it is possible to make the page table reservation
+ in the device MMU without even knowing the granularity of the
+ physical memory (i.e. useful for being able to allocate virtual
+ before physical)
+ */
+ PMR_LOG2ALIGN_T uiLog2ContiguityGuarantee;
+
+ /* Flags. We store a copy of the "PMR flags" (usually a subset of
+ the flags given at allocation time) and return them to any
+ caller of PMR_Flags(). The intention of these flags is that
+ the ones stored here are used to represent permissions, such
+ that noone is able to map a PMR in a mode in which they are not
+ allowed, e.g. writeable for a read-only PMR, etc. */
+ PMR_FLAGS_T uiFlags;
+
+ /* Do we really need this? For now we'll keep it, until we know we don't. */
+ /* NB: this is not the "memory context" in client terms - this is
+ _purely_ the "PMR" context, of which there is almost certainly only
+ ever one per system as a whole, but we'll keep the concept
+ anyway, just-in-case. */
+ struct _PMR_CTX_ *psContext;
+
+#if defined(PVR_RI_DEBUG)
+ /*
+ * Stored handle to PMR RI entry
+ */
+ IMG_PVOID hRIHandle;
+#endif
+
+ /* Whether PDumping of this PMR must be persistent
+ * (i.e. it must be present in every future PDump stream as well)
+ */
+ IMG_BOOL bForcePersistent;
+};
+
+/* do we need a struct for the export handle? I'll use one for now, but if nothing goes in it, we'll lose it */
+struct _PMR_EXPORT_
+{
+ struct _PMR_ *psPMR;
+};
+
+struct _PMR_PAGELIST_
+{
+ struct _PMR_ *psReferencePMR;
+};
+
+/*
+ * This Lock is used to protect the sequence of operation used in MMapPMR and in
+ * the memory management bridge. This should make possible avoid the use of the bridge
+ * lock in mmap.c avoiding regressions.
+ */
+
+/* this structure tracks the current owner of the PMR lock, avoiding use of
+ * the Linux (struct mutex).owner field which is not guaranteed to be up to date.
+ * there is Linux-specific code to provide an opimised approach for Linux,
+ * using the kernel (struct task_struct *) instead of a PID/TID combination.
+ */
+typedef struct _PMR_LOCK_OWNER_
+{
+#if defined(LINUX)
+ struct task_struct *task;
+#else
+ POS_LOCK hPIDTIDLock;
+ IMG_PID uiPID;
+ IMG_UINTPTR_T uiTID;
+#endif
+} PMR_LOCK_OWNER;
+
+POS_LOCK gGlobalLookupPMRLock;
+static PMR_LOCK_OWNER gsPMRLockOwner;
+
+static IMG_VOID _SetPMRLockOwner(IMG_VOID)
+{
+#if defined(LINUX)
+ gsPMRLockOwner.task = current;
+#else
+ OSLockAcquire(gsPMRLockOwner.hPIDTIDLock);
+ gsPMRLockOwner.uiPID = OSGetCurrentProcessIDKM();
+ gsPMRLockOwner.uiTID = OSGetCurrentThreadIDKM();
+ OSLockRelease(gsPMRLockOwner.hPIDTIDLock);
+#endif
+}
+
+/* Must only be called by the thread which owns the PMR lock */
+static IMG_VOID _ClearPMRLockOwner(IMG_VOID)
+{
+#if defined(LINUX)
+ gsPMRLockOwner.task = IMG_NULL;
+#else
+ OSLockAcquire(gsPMRLockOwner.hPIDTIDLock);
+ gsPMRLockOwner.uiPID = 0;
+ gsPMRLockOwner.uiTID = 0;
+ OSLockRelease(gsPMRLockOwner.hPIDTIDLock);
+#endif
+}
+
+static IMG_BOOL _ComparePMRLockOwner(IMG_VOID)
+{
+#if defined(LINUX)
+ return gsPMRLockOwner.task == current;
+#else
+ IMG_BOOL bRet;
+
+ OSLockAcquire(gsPMRLockOwner.hPIDTIDLock);
+ bRet = (gsPMRLockOwner.uiPID == OSGetCurrentProcessIDKM()) &&
+ (gsPMRLockOwner.uiTID == OSGetCurrentThreadIDKM());
+ OSLockRelease(gsPMRLockOwner.hPIDTIDLock);
+ return bRet;
+#endif
+}
+
+IMG_VOID PMRLock()
+{
+ OSLockAcquire(gGlobalLookupPMRLock);
+ _SetPMRLockOwner();
+}
+
+IMG_VOID PMRUnlock()
+{
+ _ClearPMRLockOwner();
+ OSLockRelease(gGlobalLookupPMRLock);
+}
+
+IMG_BOOL PMRIsLocked(void)
+{
+ return OSLockIsLocked(gGlobalLookupPMRLock);
+}
+
+
+IMG_BOOL PMRIsLockedByMe(void)
+{
+ return PMRIsLocked() && _ComparePMRLockOwner();
+}
+
+#define MIN3(a,b,c) (((a) < (b)) ? (((a) < (c)) ? (a):(c)) : (((b) < (c)) ? (b):(c)))
+
+static PVRSRV_ERROR
+_PMRCreate(PMR_SIZE_T uiLogicalSize,
+ PMR_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ PMR_LOG2ALIGN_T uiLog2ContiguityGuarantee,
+ PMR_FLAGS_T uiFlags,
+ PMR **ppsPMR)
+{
+ IMG_VOID *pvLinAddr;
+ PMR *psPMR;
+ PMR_MAPPING_TABLE *psMappingTable;
+ struct _PMR_CTX_ *psContext;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32ValidCount = 0;
+ IMG_UINT32 ui32Remainder;
+
+ psContext = &_gsSingletonPMRContext;
+
+
+ /* Extra checks required for sparse PMRs */
+ if (uiLogicalSize != uiChunkSize)
+ {
+ /* Check the logical size and chunk information agree with each other */
+ if (uiLogicalSize != (uiChunkSize * ui32NumVirtChunks))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Bad mapping size (uiLogicalSize = "IMG_DEVMEM_SIZE_FMTSPEC", uiChunkSize = "IMG_DEVMEM_OFFSET_FMTSPEC", ui32NumVirtChunks = %d)",
+ __FUNCTION__, uiLogicalSize, uiChunkSize, ui32NumVirtChunks));
+ return PVRSRV_ERROR_PMR_BAD_MAPPINGTABLE_SIZE;
+ }
+
+ /* Check that the chunk size is a multiple of the contiguity */
+ OSDivide64(uiChunkSize, (1<< uiLog2ContiguityGuarantee), &ui32Remainder);
+ if (ui32Remainder)
+ {
+ return PVRSRV_ERROR_PMR_BAD_CHUNK_SIZE;
+ }
+
+ /* Check the mapping table */
+ for (i = 0; i<ui32NumVirtChunks;i++)
+ {
+ if (pabMappingTable[i])
+ {
+ ui32ValidCount++;
+ }
+ }
+
+ if (ui32ValidCount != ui32NumPhysChunks)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Mismatch in mapping table, expecting %d valid entries but found %d",
+ __FUNCTION__,
+ ui32NumPhysChunks,
+ ui32ValidCount));
+ return PVRSRV_ERROR_PMR_MAPPINGTABLE_MISMATCH;
+ }
+ }
+
+ pvLinAddr = OSAllocMem(sizeof(*psPMR) + sizeof(*psMappingTable) + (sizeof(IMG_BOOL) * ui32NumVirtChunks));
+ if (pvLinAddr == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32PhysIndex = 0;
+ psPMR = (PMR *)pvLinAddr;
+ psMappingTable = (PMR_MAPPING_TABLE *) (((IMG_CHAR *) pvLinAddr) + sizeof(*psPMR));
+
+ eError = OSLockCreate(&psPMR->hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ OSFreeMem(psPMR);
+ return eError;
+ }
+
+ /* Setup the mapping table */
+ psMappingTable->uiChunkSize = uiChunkSize;
+ psMappingTable->ui32NumVirtChunks = ui32NumVirtChunks;
+ psMappingTable->ui32NumPhysChunks = ui32NumPhysChunks;
+ for (i=0;i<ui32NumVirtChunks;i++)
+ {
+ if (pabMappingTable[i])
+ {
+ psMappingTable->aui32Translation[i] = ui32PhysIndex++;
+ }
+ else
+ {
+ psMappingTable->aui32Translation[i] = TRANSLATION_INVALID;
+ }
+ }
+
+ /* Setup the PMR */
+ psPMR->uiRefCount = 0;
+ psPMR->uiLockCount = 0;
+ psPMR->psContext = psContext;
+ psPMR->uiLogicalSize = uiLogicalSize;
+ psPMR->uiLog2ContiguityGuarantee = uiLog2ContiguityGuarantee;
+ psPMR->uiFlags = uiFlags;
+ psPMR->psMappingTable = psMappingTable;
+ psPMR->uiKey = psContext->uiNextKey;
+ psPMR->uiSerialNum = psContext->uiNextSerialNum;
+
+#if defined(PVR_RI_DEBUG)
+ psPMR->hRIHandle = IMG_NULL;
+#endif
+
+ OSLockAcquire(psContext->hLock);
+ psContext->uiNextKey = (0x80200003 * psContext->uiNextKey)
+ ^ (0xf00f0081 * (IMG_UINTPTR_T)pvLinAddr);
+ psContext->uiNextSerialNum ++;
+ OSLockRelease(psContext->hLock);
+
+ *ppsPMR = psPMR;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "pmr.c: created PMR @0x%p", psPMR));
+
+ /* Increment live PMR count */
+ OSLockAcquire(psContext->hLock);
+ psContext->uiNumLivePMRs ++;
+ OSLockRelease(psContext->hLock);
+
+ return PVRSRV_OK;
+ }
+}
+
+static IMG_UINT32
+_RefNoLock(PMR *psPMR)
+{
+ psPMR->uiRefCount++;
+ return psPMR->uiRefCount;
+}
+
+static IMG_UINT32
+_UnrefNoLock(PMR *psPMR)
+{
+ PVR_ASSERT(psPMR->uiRefCount > 0);
+ psPMR->uiRefCount--;
+ return psPMR->uiRefCount;
+}
+
+static IMG_VOID
+_Ref(PMR *psPMR)
+{
+ OSLockAcquire(psPMR->hLock);
+ _RefNoLock(psPMR);
+ OSLockRelease(psPMR->hLock);
+}
+
+static IMG_VOID
+_UnrefAndMaybeDestroy(PMR *psPMR)
+{
+ PVRSRV_ERROR eError2;
+ struct _PMR_CTX_ *psCtx;
+ IMG_UINT32 uiRefCount;
+
+ PVR_ASSERT(psPMR != IMG_NULL);
+ PVR_ASSERT(psPMR->uiRefCount > 0);
+
+ OSLockAcquire(psPMR->hLock);
+ uiRefCount = _UnrefNoLock(psPMR);
+ OSLockRelease(psPMR->hLock);
+
+ if (uiRefCount == 0)
+ {
+ if (psPMR->psFuncTab->pfnFinalize != IMG_NULL)
+ {
+ eError2 = psPMR->psFuncTab->pfnFinalize(psPMR->pvFlavourData);
+ PVR_ASSERT (eError2 == PVRSRV_OK); /* can we do better? */
+ }
+
+#ifdef PVRSRV_NEED_PVR_ASSERT
+ OSLockAcquire(psPMR->hLock);
+ PVR_ASSERT(psPMR->uiLockCount == 0);
+ OSLockRelease(psPMR->hLock);
+#endif
+
+#if defined(PVR_RI_DEBUG)
+ {
+ PVRSRV_ERROR eError;
+
+ /* Delete RI entry */
+ if (psPMR->hRIHandle)
+ {
+ eError = RIDeletePMREntryKM (psPMR->hRIHandle);
+ }
+ }
+#endif /* if defined(PVR_RI_DEBUG) */
+ psCtx = psPMR->psContext;
+
+ OSLockDestroy(psPMR->hLock);
+ OSFreeMem(psPMR);
+
+ /* Decrement live PMR count. Probably only of interest for debugging */
+ PVR_ASSERT(psCtx->uiNumLivePMRs > 0);
+
+ OSLockAcquire(psCtx->hLock);
+ psCtx->uiNumLivePMRs --;
+ OSLockRelease(psCtx->hLock);
+ }
+}
+
+static IMG_BOOL _PMRIsSparse(const PMR *psPMR)
+{
+ if (psPMR->psMappingTable->ui32NumVirtChunks == psPMR->psMappingTable->ui32NumPhysChunks)
+ {
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+PVRSRV_ERROR
+PMRCreatePMR(PHYS_HEAP *psPhysHeap,
+ PMR_SIZE_T uiLogicalSize,
+ PMR_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ PMR_LOG2ALIGN_T uiLog2ContiguityGuarantee,
+ PMR_FLAGS_T uiFlags,
+ const IMG_CHAR *pszPDumpFlavour,
+ const PMR_IMPL_FUNCTAB *psFuncTab,
+ PMR_IMPL_PRIVDATA pvPrivData,
+ PMR **ppsPMRPtr,
+ IMG_HANDLE *phPDumpAllocInfo,
+ IMG_BOOL bForcePersistent)
+{
+ PMR *psPMR = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ eError = _PMRCreate(uiLogicalSize,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ pabMappingTable,
+ uiLog2ContiguityGuarantee,
+ uiFlags,
+ &psPMR);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ psPMR->psPhysHeap = psPhysHeap;
+ psPMR->psFuncTab = psFuncTab;
+ psPMR->pszPDumpDefaultMemspaceName = PhysHeapPDumpMemspaceName(psPhysHeap);
+ psPMR->pszPDumpFlavour = pszPDumpFlavour;
+ psPMR->pvFlavourData = pvPrivData;
+ psPMR->uiRefCount = 1;
+ psPMR->bForcePersistent = bForcePersistent;
+
+ *ppsPMRPtr = psPMR;
+
+
+ if (phPDumpAllocInfo)
+ {
+ PDumpPMRMallocPMR(psPMR,
+ (uiChunkSize * ui32NumPhysChunks),
+ 1ULL<<uiLog2ContiguityGuarantee,
+ bForcePersistent,
+ phPDumpAllocInfo);
+ }
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR PMRLockSysPhysAddressesNested(PMR *psPMR,
+ IMG_UINT32 uiLog2RequiredContiguity,
+ IMG_UINT32 ui32NestingLevel)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psPMR != IMG_NULL);
+
+ if (uiLog2RequiredContiguity > psPMR->uiLog2ContiguityGuarantee)
+ {
+ eError = PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
+ goto e0;
+ }
+
+ OSLockAcquireNested(psPMR->hLock, ui32NestingLevel);
+ /* We also count the locks as references, so that the PMR is not
+ freed while someone is using a physical address. */
+ /* "lock" here simply means incrementing the refcount. It means
+ the refcount is multipurpose, but that's okay. We only have to
+ promise that physical addresses are valid after this point, and
+ remain valid until the corresponding
+ PMRUnlockSysPhysAddressesOSMem() */
+ _RefNoLock(psPMR);
+
+ /* Also count locks separately from other types of references, to
+ allow for debug assertions */
+ psPMR->uiLockCount++;
+
+ /* Only call callback if lockcount transitions from 0 to 1 */
+ if (psPMR->uiLockCount == 1)
+ {
+ if (psPMR->psFuncTab->pfnLockPhysAddresses != IMG_NULL)
+ {
+ /* must always have lock and unlock in pairs! */
+ PVR_ASSERT(psPMR->psFuncTab->pfnUnlockPhysAddresses != IMG_NULL);
+
+ eError = psPMR->psFuncTab->pfnLockPhysAddresses(psPMR->pvFlavourData,
+ uiLog2RequiredContiguity);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+ }
+ }
+ OSLockRelease(psPMR->hLock);
+
+ return PVRSRV_OK;
+
+ e1:
+ psPMR->uiLockCount--;
+ _UnrefNoLock(psPMR);
+ PVR_ASSERT(psPMR->uiRefCount != 0);
+ OSLockRelease(psPMR->hLock);
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR
+PMRLockSysPhysAddresses(PMR *psPMR,
+ IMG_UINT32 uiLog2RequiredContiguity)
+{
+ return PMRLockSysPhysAddressesNested(psPMR, uiLog2RequiredContiguity, 0);
+}
+
+PVRSRV_ERROR
+PMRUnlockSysPhysAddresses(PMR *psPMR)
+{
+ PVRSRV_ERROR eError2;
+
+ PVR_ASSERT(psPMR != IMG_NULL);
+
+ OSLockAcquire(psPMR->hLock);
+ PVR_ASSERT(psPMR->uiLockCount > 0);
+ psPMR->uiLockCount--;
+
+ if (psPMR->uiLockCount == 0)
+ {
+ if (psPMR->psFuncTab->pfnUnlockPhysAddresses != IMG_NULL)
+ {
+ PVR_ASSERT(psPMR->psFuncTab->pfnLockPhysAddresses != IMG_NULL);
+
+ eError2 = psPMR->psFuncTab->pfnUnlockPhysAddresses(psPMR->pvFlavourData);
+ /* must never fail */
+ PVR_ASSERT(eError2 == PVRSRV_OK);
+ }
+ }
+
+ OSLockRelease(psPMR->hLock);
+
+ /* We also count the locks as references, so that the PMR is not
+ freed while someone is using a physical address. */
+ _UnrefAndMaybeDestroy(psPMR);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMRExportPMR(PMR *psPMR,
+ PMR_EXPORT **ppsPMRExportPtr,
+ PMR_SIZE_T *puiSize,
+ PMR_LOG2ALIGN_T *puiLog2Contig,
+ PMR_PASSWORD_T *puiPassword)
+{
+ IMG_UINT64 uiPassword;
+ PMR_EXPORT *psPMRExport;
+
+ uiPassword = psPMR->uiKey;
+
+ psPMRExport = OSAllocMem(sizeof(*psPMRExport));
+ if (psPMRExport == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psPMRExport->psPMR = psPMR;
+ _Ref(psPMR);
+
+ *ppsPMRExportPtr = psPMRExport;
+ *puiSize = psPMR->uiLogicalSize;
+ *puiLog2Contig = psPMR->uiLog2ContiguityGuarantee;
+ *puiPassword = uiPassword;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMRMakeServerExportClientExport(DEVMEM_EXPORTCOOKIE *psPMRExportIn,
+ PMR_EXPORT **ppsPMRExportPtr,
+ PMR_SIZE_T *puiSize,
+ PMR_LOG2ALIGN_T *puiLog2Contig,
+ PMR_PASSWORD_T *puiPassword)
+{
+ *ppsPMRExportPtr = (PMR_EXPORT *) psPMRExportIn->hPMRExportHandle;
+ *puiSize = psPMRExportIn->uiSize;
+ *puiLog2Contig = psPMRExportIn->uiLog2ContiguityGuarantee;
+ *puiPassword = psPMRExportIn->uiPMRExportPassword;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMRUnmakeServerExportClientExport(PMR_EXPORT *psPMRExport)
+{
+ PVR_UNREFERENCED_PARAMETER(psPMRExport);
+
+ /*
+ There is nothing to do here, the server will call unexport
+ regardless of the type of shutdown. In order to play ball
+ with resman (where it's used) we need to pair functions
+ and this is PMRMakeServerExportClientExport counter part.
+ */
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMRUnexportPMR(PMR_EXPORT *psPMRExport)
+{
+
+ PVR_ASSERT(psPMRExport != IMG_NULL);
+ PVR_ASSERT(psPMRExport->psPMR != IMG_NULL);
+ PVR_ASSERT(psPMRExport->psPMR->uiRefCount > 0);
+
+ _UnrefAndMaybeDestroy(psPMRExport->psPMR);
+
+ OSFreeMem(psPMRExport);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+PMRImportPMR(PMR_EXPORT *psPMRExport,
+ PMR_PASSWORD_T uiPassword,
+ PMR_SIZE_T uiSize,
+ PMR_LOG2ALIGN_T uiLog2Contig,
+ PMR **ppsPMR)
+{
+ PMR *psPMR;
+
+
+ PVR_ASSERT(psPMRExport != IMG_NULL);
+ PVR_ASSERT(psPMRExport->psPMR != IMG_NULL);
+ PVR_ASSERT(psPMRExport->psPMR->uiRefCount > 0);
+
+ psPMR = psPMRExport->psPMR;
+
+ if (psPMR->uiKey != uiPassword)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PMRImport: password given = %016llx, expected = %016llx\n",
+ uiPassword,
+ psPMR->uiKey));
+ return PVRSRV_ERROR_PMR_WRONG_PASSWORD_OR_STALE_PMR;
+ }
+
+ if (psPMR->uiLogicalSize != uiSize || psPMR->uiLog2ContiguityGuarantee != uiLog2Contig)
+ {
+ return PVRSRV_ERROR_PMR_MISMATCHED_ATTRIBUTES;
+ }
+
+ _Ref(psPMR);
+
+ *ppsPMR = psPMR;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMRUnimportPMR(PMR *psPMR)
+{
+ _UnrefAndMaybeDestroy(psPMR);
+
+ return PVRSRV_OK;
+}
+
+/*
+ Note:
+ We pass back the PMR as it was passed in as a different handle type
+ (DEVMEM_MEM_IMPORT) and it allows us to change the import structure
+ type if we should need to embed any meta data in it.
+*/
+PVRSRV_ERROR
+PMRLocalImportPMR(PMR *psPMR,
+ PMR **ppsPMR,
+ IMG_DEVMEM_SIZE_T *puiSize,
+ IMG_DEVMEM_ALIGN_T *puiAlign)
+{
+ _Ref(psPMR);
+
+ /* Return the PMR */
+ *ppsPMR = psPMR;
+ *puiSize = psPMR->uiLogicalSize;
+ *puiAlign = 1ULL << psPMR->uiLog2ContiguityGuarantee;
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMRGetUID(PMR *psPMR,
+ IMG_UINT64 *pui64UID)
+{
+ PVR_ASSERT(psPMR != IMG_NULL);
+
+ *pui64UID = psPMR->uiSerialNum;
+
+ return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_SECURE_EXPORT)
+PVRSRV_ERROR PMRSecureExportPMR(CONNECTION_DATA *psConnection,
+ PMR *psPMR,
+ IMG_SECURE_TYPE *phSecure,
+ PMR **ppsPMR,
+ CONNECTION_DATA **ppsSecureConnection)
+{
+ PVRSRV_ERROR eError;
+
+ /* We are acquiring reference to PMR here because OSSecureExport
+ * releases bridge lock and PMR lock for a moment and we don't want PMR
+ * to be removed by other thread in the meantime. */
+ _Ref(psPMR);
+
+ eError = OSSecureExport(psConnection,
+ (IMG_PVOID) psPMR,
+ phSecure,
+ ppsSecureConnection);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ /* Pass back the PMR for resman */
+ *ppsPMR = psPMR;
+
+ return PVRSRV_OK;
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ _UnrefAndMaybeDestroy(psPMR);
+ return eError;
+}
+
+PVRSRV_ERROR PMRSecureUnexportPMR(PMR *psPMR)
+{
+ _UnrefAndMaybeDestroy(psPMR);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PMRSecureImportPMR(IMG_SECURE_TYPE hSecure,
+ PMR **ppsPMR,
+ IMG_DEVMEM_SIZE_T *puiSize,
+ IMG_DEVMEM_ALIGN_T *puiAlign)
+{
+ PVRSRV_ERROR eError;
+ PMR *psPMR;
+
+ eError = OSSecureImport(hSecure, (IMG_PVOID *) &psPMR);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ _Ref(psPMR);
+
+ /* Return the PMR */
+ *ppsPMR = psPMR;
+ *puiSize = psPMR->uiLogicalSize;
+ *puiAlign = 1 << psPMR->uiLog2ContiguityGuarantee;
+ return PVRSRV_OK;
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR PMRSecureUnimportPMR(PMR *psPMR)
+{
+ _UnrefAndMaybeDestroy(psPMR);
+ return PVRSRV_OK;
+}
+#endif
+
+#if defined(PVR_RI_DEBUG)
+PVRSRV_ERROR
+PMRStoreRIHandle(PMR *psPMR,
+ IMG_PVOID hRIHandle)
+{
+ PVR_ASSERT(psPMR != IMG_NULL);
+
+ psPMR->hRIHandle = hRIHandle;
+ return PVRSRV_OK;
+}
+#endif
+
+PVRSRV_ERROR
+PMRAcquireKernelMappingData(PMR *psPMR,
+ IMG_SIZE_T uiLogicalOffset,
+ IMG_SIZE_T uiSize,
+ IMG_VOID **ppvKernelAddressOut,
+ IMG_SIZE_T *puiLengthOut,
+ IMG_HANDLE *phPrivOut)
+{
+ PVRSRV_ERROR eError;
+ IMG_VOID *pvKernelAddress;
+ IMG_HANDLE hPriv;
+ PMR_FLAGS_T ulFlags;
+
+ PVR_ASSERT(psPMR != IMG_NULL);
+
+ if (_PMRIsSparse(psPMR))
+ {
+ /* We don't support mapping of sparse allocations into the kernel.
+ Although the callback is supported by the PMR it will always map
+ the physical 1:1 as sparseness issues are handled here in the core */
+ return PVRSRV_ERROR_PMR_NOT_PERMITTED;
+ }
+
+ /* Acquire/Release functions must be overridden in pairs */
+ if (psPMR->psFuncTab->pfnAcquireKernelMappingData == IMG_NULL)
+ {
+ PVR_ASSERT (psPMR->psFuncTab->pfnReleaseKernelMappingData == IMG_NULL);
+
+ /* If PMR implementation does not supply this pair of
+ functions, it means they do not permit the PMR to be mapped
+ into kernel memory at all */
+ eError = PVRSRV_ERROR_PMR_NOT_PERMITTED;
+ goto e0;
+ }
+ PVR_ASSERT (psPMR->psFuncTab->pfnReleaseKernelMappingData != IMG_NULL);
+
+ PMR_Flags(psPMR, &ulFlags);
+
+ eError = psPMR->psFuncTab->pfnAcquireKernelMappingData(psPMR->pvFlavourData,
+ uiLogicalOffset,
+ uiSize,
+ &pvKernelAddress,
+ &hPriv,
+ ulFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ *ppvKernelAddressOut = pvKernelAddress;
+ if (uiSize == 0)
+ {
+ /* Zero size means map the whole PMR in ...*/
+ *puiLengthOut = (IMG_SIZE_T)psPMR->uiLogicalSize;
+ }
+ else
+ {
+ /* ... otherwise we just map in one page */
+ *puiLengthOut = 1 << psPMR->uiLog2ContiguityGuarantee;
+ }
+ *phPrivOut = hPriv;
+
+ return PVRSRV_OK;
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR
+PMRReleaseKernelMappingData(PMR *psPMR,
+ IMG_HANDLE hPriv)
+{
+ PVR_ASSERT (psPMR->psFuncTab->pfnAcquireKernelMappingData != IMG_NULL);
+ PVR_ASSERT (psPMR->psFuncTab->pfnReleaseKernelMappingData != IMG_NULL);
+
+ psPMR->psFuncTab->pfnReleaseKernelMappingData(psPMR->pvFlavourData,
+ hPriv);
+
+ return PVRSRV_OK;
+}
+
+/*
+ _PMRLogicalOffsetToPhysicalOffset
+
+ Translate between the "logical" offset which the upper levels
+ provide and the physical offset which is what the PMR
+ factory’s work on.
+
+ As well as returning the physical offset we return the number of
+ bytes remaining till the next chunk and if this chunk is valid.
+*/
+
+static IMG_BOOL
+_PMRLogicalOffsetToPhysicalOffset(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_DEVMEM_OFFSET_T *puiPhysicalOffset,
+ IMG_UINT32 *pui32BytesRemain)
+{
+ PMR_MAPPING_TABLE *psMappingTable = psPMR->psMappingTable;
+ IMG_UINT64 ui64ChunkIndex;
+ IMG_UINT32 ui32Remain;
+ IMG_BOOL bReturn;
+
+ /* Fast path the common case */
+ if (psMappingTable->ui32NumPhysChunks == psMappingTable->ui32NumVirtChunks)
+ {
+ bReturn = IMG_TRUE;
+ *puiPhysicalOffset = uiLogicalOffset;
+ *pui32BytesRemain = TRUNCATE_64BITS_TO_32BITS(psPMR->uiLogicalSize - uiLogicalOffset);
+ }
+ else
+ {
+ ui64ChunkIndex = OSDivide64(
+ uiLogicalOffset,
+
+ TRUNCATE_64BITS_TO_32BITS(psMappingTable->uiChunkSize),
+ &ui32Remain);
+
+ if (psMappingTable->aui32Translation[ui64ChunkIndex] == TRANSLATION_INVALID)
+ {
+ bReturn = IMG_FALSE;
+ }
+ else
+ {
+ bReturn = IMG_TRUE;
+ }
+
+ if (ui32Remain == 0)
+ {
+ /* Start of chunk so return the chunk size */
+ *pui32BytesRemain = TRUNCATE_64BITS_TO_32BITS(psMappingTable->uiChunkSize);
+ }
+ else
+ {
+ *pui32BytesRemain = TRUNCATE_64BITS_TO_32BITS(psMappingTable->uiChunkSize - ui32Remain);
+ }
+
+ *puiPhysicalOffset = (psMappingTable->aui32Translation[ui64ChunkIndex] * psMappingTable->uiChunkSize) +
+ ui32Remain;
+ }
+ return bReturn;
+}
+
+static PVRSRV_ERROR
+_PMR_ReadBytesPhysical(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiPhysicalOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes)
+{
+ PVRSRV_ERROR eError;
+
+ if (psPMR->psFuncTab->pfnReadBytes != IMG_NULL)
+ {
+ /* defer to callback if present */
+
+ eError = PMRLockSysPhysAddresses(psPMR,
+ psPMR->uiLog2ContiguityGuarantee);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ eError = psPMR->psFuncTab->pfnReadBytes(psPMR->pvFlavourData,
+ uiPhysicalOffset,
+ pcBuffer,
+ uiBufSz,
+ puiNumBytes);
+ PMRUnlockSysPhysAddresses(psPMR);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+ }
+ else if (psPMR->psFuncTab->pfnAcquireKernelMappingData)
+ {
+ /* "default" handler for reading bytes */
+
+ IMG_HANDLE hKernelMappingHandle;
+ IMG_UINT8 *pcKernelAddress;
+ PMR_FLAGS_T ulFlags;
+
+ PMR_Flags(psPMR, &ulFlags);
+
+ eError = psPMR->psFuncTab->pfnAcquireKernelMappingData(psPMR->pvFlavourData,
+ (IMG_SIZE_T) uiPhysicalOffset,
+ uiBufSz,
+ (IMG_VOID **)&pcKernelAddress,
+ &hKernelMappingHandle,
+ ulFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ OSMemCopy(&pcBuffer[0], pcKernelAddress, uiBufSz);
+ *puiNumBytes = uiBufSz;
+
+ psPMR->psFuncTab->pfnReleaseKernelMappingData(psPMR->pvFlavourData,
+ hKernelMappingHandle);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PMR_ReadBytes: can't read from this PMR"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ OSPanic();
+ goto e0;
+ }
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ OSPanic();
+ return eError;
+}
+
+PVRSRV_ERROR
+PMR_ReadBytes(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_DEVMEM_OFFSET_T uiPhysicalOffset;
+ IMG_SIZE_T uiBytesCopied = 0;
+
+ if (uiLogicalOffset + uiBufSz > psPMR->uiLogicalSize)
+ {
+ uiBufSz = TRUNCATE_64BITS_TO_32BITS(psPMR->uiLogicalSize - uiLogicalOffset);
+ }
+ PVR_ASSERT(uiBufSz > 0);
+ PVR_ASSERT(uiBufSz <= psPMR->uiLogicalSize);
+
+ /*
+ PMR implementations can override this. If they don't, a
+ "default" handler uses kernel virtual mappings. If the kernel
+ can't provide a kernel virtual mapping, this function fails
+ */
+ PVR_ASSERT(psPMR->psFuncTab->pfnAcquireKernelMappingData != IMG_NULL ||
+ psPMR->psFuncTab->pfnReadBytes != IMG_NULL);
+
+ while (uiBytesCopied != uiBufSz)
+ {
+ IMG_UINT32 ui32Remain;
+ IMG_SIZE_T uiBytesToCopy;
+ IMG_SIZE_T uiRead;
+ IMG_BOOL bValid;
+
+ bValid = _PMRLogicalOffsetToPhysicalOffset(psPMR,
+ uiLogicalOffset,
+ &uiPhysicalOffset,
+ &ui32Remain);
+
+ /*
+ Copy till either then end of the
+ chunk or end end of the buffer
+ */
+ uiBytesToCopy = MIN(uiBufSz - uiBytesCopied, ui32Remain);
+
+ if (bValid)
+ {
+ /* Read the data from the PMR */
+ eError = _PMR_ReadBytesPhysical(psPMR,
+ uiPhysicalOffset,
+ &pcBuffer[uiBytesCopied],
+ uiBytesToCopy,
+ &uiRead);
+ if ((eError != PVRSRV_OK) || (uiRead != uiBytesToCopy))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Failed to read chunk (eError = %s, uiRead = "IMG_SIZE_FMTSPEC" uiBytesToCopy = "IMG_SIZE_FMTSPEC")",
+ __FUNCTION__,
+ PVRSRVGetErrorStringKM(eError),
+ uiRead,
+ uiBytesToCopy));
+ /* Bail out as soon as we hit an error */
+ break;
+ }
+ }
+ else
+ {
+ /* Fill invalid chunks with 0 */
+ OSMemSet(&pcBuffer[uiBytesCopied], 0, uiBytesToCopy);
+ uiRead = uiBytesToCopy;
+ }
+ uiLogicalOffset += uiRead;
+ uiBytesCopied += uiRead;
+ }
+
+ *puiNumBytes = uiBytesCopied;
+ return eError;
+}
+
+static PVRSRV_ERROR
+_PMR_WriteBytesPhysical(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiPhysicalOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes)
+{
+ PVRSRV_ERROR eError;
+
+ if (psPMR->psFuncTab->pfnWriteBytes != IMG_NULL)
+ {
+ /* defer to callback if present */
+
+ eError = PMRLockSysPhysAddresses(psPMR,
+ psPMR->uiLog2ContiguityGuarantee);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ eError = psPMR->psFuncTab->pfnWriteBytes(psPMR->pvFlavourData,
+ uiPhysicalOffset,
+ pcBuffer,
+ uiBufSz,
+ puiNumBytes);
+ PMRUnlockSysPhysAddresses(psPMR);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+ }
+ else if (psPMR->psFuncTab->pfnAcquireKernelMappingData)
+ {
+ /* "default" handler for reading bytes */
+
+ IMG_HANDLE hKernelMappingHandle;
+ IMG_UINT8 *pcKernelAddress;
+ PMR_FLAGS_T ulFlags;
+
+ PMR_Flags(psPMR, &ulFlags);
+
+ eError = psPMR->psFuncTab->pfnAcquireKernelMappingData(psPMR->pvFlavourData,
+ (IMG_SIZE_T) uiPhysicalOffset,
+ uiBufSz,
+ (IMG_VOID **)&pcKernelAddress,
+ &hKernelMappingHandle,
+ ulFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ OSMemCopy(pcKernelAddress, &pcBuffer[0], uiBufSz);
+ *puiNumBytes = uiBufSz;
+
+ psPMR->psFuncTab->pfnReleaseKernelMappingData(psPMR->pvFlavourData,
+ hKernelMappingHandle);
+ }
+ else
+ {
+ /*
+ The write callback is optional as it's only required by the debug
+ tools
+ */
+ PVR_DPF((PVR_DBG_ERROR, "_PMR_WriteBytesPhysical: can't write to this PMR"));
+ eError = PVRSRV_ERROR_PMR_NOT_PERMITTED;
+ goto e0;
+ }
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ OSPanic();
+ return eError;
+}
+
+PVRSRV_ERROR
+PMR_WriteBytes(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ #if 0
+ PMR_FLAGS_T uiFlags;
+ #endif
+ IMG_DEVMEM_OFFSET_T uiPhysicalOffset;
+ IMG_SIZE_T uiBytesCopied = 0;
+
+
+ #if 0
+ /* Check that writes are allowed */
+ PMR_Flags(psPMR, &uiFlags);
+ if (!(uiFlags & PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE))
+ {
+ return PVRSRV_ERROR_PMR_NOT_PERMITTED;
+ }
+ #endif
+
+ if (uiLogicalOffset + uiBufSz > psPMR->uiLogicalSize)
+ {
+ uiBufSz = TRUNCATE_64BITS_TO_32BITS(psPMR->uiLogicalSize - uiLogicalOffset);
+ }
+ PVR_ASSERT(uiBufSz > 0);
+ PVR_ASSERT(uiBufSz <= psPMR->uiLogicalSize);
+
+ /*
+ PMR implementations can override this. If they don't, a
+ "default" handler uses kernel virtual mappings. If the kernel
+ can't provide a kernel virtual mapping, this function fails
+ */
+ PVR_ASSERT(psPMR->psFuncTab->pfnAcquireKernelMappingData != IMG_NULL ||
+ psPMR->psFuncTab->pfnWriteBytes != IMG_NULL);
+
+ while (uiBytesCopied != uiBufSz)
+ {
+ IMG_UINT32 ui32Remain;
+ IMG_SIZE_T uiBytesToCopy;
+ IMG_SIZE_T uiWrite;
+ IMG_BOOL bValid;
+
+ bValid = _PMRLogicalOffsetToPhysicalOffset(psPMR,
+ uiLogicalOffset,
+ &uiPhysicalOffset,
+ &ui32Remain);
+
+ /*
+ Copy till either then end of the
+ chunk or end end of the buffer
+ */
+ uiBytesToCopy = MIN(uiBufSz - uiBytesCopied, ui32Remain);
+
+ if (bValid)
+ {
+ /* Write the data to the PMR */
+ eError = _PMR_WriteBytesPhysical(psPMR,
+ uiPhysicalOffset,
+ &pcBuffer[uiBytesCopied],
+ uiBytesToCopy,
+ &uiWrite);
+ if ((eError != PVRSRV_OK) || (uiWrite != uiBytesToCopy))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Failed to read chunk (eError = %s, uiWrite = "IMG_SIZE_FMTSPEC" uiBytesToCopy = "IMG_SIZE_FMTSPEC")",
+ __FUNCTION__,
+ PVRSRVGetErrorStringKM(eError),
+ uiWrite,
+ uiBytesToCopy));
+ /* Bail out as soon as we hit an error */
+ break;
+ }
+ }
+ else
+ {
+ /* Ignore writes to invalid pages */
+ uiWrite = uiBytesToCopy;
+ }
+ uiLogicalOffset += uiWrite;
+ uiBytesCopied += uiWrite;
+ }
+
+ *puiNumBytes = uiBytesCopied;
+ return eError;
+}
+
+IMG_VOID
+PMRRefPMR(PMR *psPMR)
+{
+ PVR_ASSERT(psPMR != IMG_NULL);
+ _Ref(psPMR);
+}
+
+PVRSRV_ERROR
+PMRUnrefPMR(PMR *psPMR)
+{
+ _UnrefAndMaybeDestroy(psPMR);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMR_Flags(const PMR *psPMR,
+ PMR_FLAGS_T *puiPMRFlags)
+{
+ PVR_ASSERT(psPMR != IMG_NULL);
+
+ *puiPMRFlags = psPMR->uiFlags;
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMR_LogicalSize(const PMR *psPMR,
+ IMG_DEVMEM_SIZE_T *puiLogicalSize)
+{
+ PVR_ASSERT(psPMR != IMG_NULL);
+
+ *puiLogicalSize = psPMR->uiLogicalSize;
+ return PVRSRV_OK;
+}
+
+/* must have called PMRLockSysPhysAddresses() before calling this! */
+PVRSRV_ERROR
+PMR_DevPhysAddr(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_DEV_PHYADDR *psDevAddrPtr,
+ IMG_BOOL *pbValid)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_DEVMEM_OFFSET_T uiPhysicalOffset;
+ IMG_UINT32 ui32Remain;
+
+ PVR_ASSERT(psPMR != IMG_NULL);
+ PVR_ASSERT(psPMR->psFuncTab->pfnDevPhysAddr != IMG_NULL);
+
+#ifdef PVRSRV_NEED_PVR_ASSERT
+ OSLockAcquire(psPMR->hLock);
+ PVR_ASSERT(psPMR->uiLockCount > 0);
+ OSLockRelease(psPMR->hLock);
+#endif
+
+ *pbValid = _PMRLogicalOffsetToPhysicalOffset(psPMR,
+ uiLogicalOffset,
+ &uiPhysicalOffset,
+ &ui32Remain);
+
+ if (*pbValid)
+ {
+ eError = psPMR->psFuncTab->pfnDevPhysAddr(psPMR->pvFlavourData,
+ uiPhysicalOffset,
+ psDevAddrPtr);
+ }
+
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ return PVRSRV_OK;
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR
+PMR_CpuPhysAddr(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_CPU_PHYADDR *psCpuAddrPtr,
+ IMG_BOOL *pbValid)
+{
+ IMG_DEV_PHYADDR sDevPAddr;
+ PVRSRV_ERROR eError;
+
+ eError = PMR_DevPhysAddr(psPMR, uiLogicalOffset, &sDevPAddr, pbValid);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+ PhysHeapDevPAddrToCpuPAddr(psPMR->psPhysHeap, psCpuAddrPtr, &sDevPAddr);
+
+ return PVRSRV_OK;
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+#if defined(PDUMP)
+
+static PVRSRV_ERROR
+_PMR_PDumpSymbolicAddrPhysical(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiPhysicalOffset,
+ IMG_UINT32 ui32MemspaceNameLen,
+ IMG_CHAR *pszMemspaceName,
+ IMG_UINT32 ui32SymbolicAddrLen,
+ IMG_CHAR *pszSymbolicAddr,
+ IMG_DEVMEM_OFFSET_T *puiNewOffset,
+ IMG_DEVMEM_OFFSET_T *puiNextSymName)
+{
+ const IMG_CHAR *pszPrefix;
+
+ if (psPMR->psFuncTab->pfnPDumpSymbolicAddr != IMG_NULL)
+ {
+ /* defer to callback if present */
+ return psPMR->psFuncTab->pfnPDumpSymbolicAddr(psPMR->pvFlavourData,
+ uiPhysicalOffset,
+ pszMemspaceName,
+ ui32MemspaceNameLen,
+ pszSymbolicAddr,
+ ui32SymbolicAddrLen,
+ puiNewOffset,
+ puiNextSymName);
+ }
+ else
+ {
+ OSSNPrintf(pszMemspaceName, ui32MemspaceNameLen, "%s",
+ psPMR->pszPDumpDefaultMemspaceName);
+
+ if (psPMR->pszPDumpFlavour != IMG_NULL)
+ {
+ pszPrefix = psPMR->pszPDumpFlavour;
+ }
+ else
+ {
+ pszPrefix = PMR_DEFAULT_PREFIX;
+ }
+ OSSNPrintf(pszSymbolicAddr, ui32SymbolicAddrLen, PMR_SYMBOLICADDR_FMTSPEC,
+ pszPrefix, psPMR->uiSerialNum);
+ *puiNewOffset = uiPhysicalOffset;
+ *puiNextSymName = (IMG_DEVMEM_OFFSET_T) psPMR->uiLogicalSize;
+
+ return PVRSRV_OK;
+ }
+}
+
+
+PVRSRV_ERROR
+PMR_PDumpSymbolicAddr(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT32 ui32MemspaceNameLen,
+ IMG_CHAR *pszMemspaceName,
+ IMG_UINT32 ui32SymbolicAddrLen,
+ IMG_CHAR *pszSymbolicAddr,
+ IMG_DEVMEM_OFFSET_T *puiNewOffset,
+ IMG_DEVMEM_OFFSET_T *puiNextSymName
+ )
+{
+ IMG_DEVMEM_OFFSET_T uiPhysicalOffset;
+ IMG_UINT32 ui32Remain;
+ IMG_BOOL bValid;
+
+ PVR_ASSERT(uiLogicalOffset < psPMR->uiLogicalSize);
+
+ bValid = _PMRLogicalOffsetToPhysicalOffset(psPMR,
+ uiLogicalOffset,
+ &uiPhysicalOffset,
+ &ui32Remain);
+
+ if (!bValid)
+ {
+ /* We should never be asked a symbolic address of an invalid chunk */
+ return PVRSRV_ERROR_PMR_INVALID_CHUNK;
+ }
+
+ return _PMR_PDumpSymbolicAddrPhysical(psPMR,
+ uiPhysicalOffset,
+ ui32MemspaceNameLen,
+ pszMemspaceName,
+ ui32SymbolicAddrLen,
+ pszSymbolicAddr,
+ puiNewOffset,
+ puiNextSymName);
+}
+
+/*!
+ * @brief Writes a WRW command to the script2 buffer, representing a
+ * dword write to a physical allocation. Size is always
+ * sizeof(IMG_UINT32).
+ * @param psPMR - PMR object representing allocation
+ * @param uiLogicalOffset - offset
+ * @param ui32Value - value to write
+ * @param uiPDumpFlags - pdump flags
+ * @return PVRSRV_ERROR
+ */
+PVRSRV_ERROR
+PMRPDumpLoadMemValue32(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT32 ui32Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
+ IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+ IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+
+ PVR_ASSERT(uiLogicalOffset + sizeof(IMG_UINT32) <= psPMR->uiLogicalSize);
+
+ eError = PMRLockSysPhysAddresses(psPMR,
+ psPMR->uiLog2ContiguityGuarantee);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /* Get the symbolic address of the PMR */
+ eError = PMR_PDumpSymbolicAddr(psPMR,
+ uiLogicalOffset,
+ sizeof(aszMemspaceName),
+ &aszMemspaceName[0],
+ sizeof(aszSymbolicName),
+ &aszSymbolicName[0],
+ &uiPDumpSymbolicOffset,
+ &uiNextSymName);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /* Write the WRW script command */
+ eError = PDumpPMRWRW32(aszMemspaceName,
+ aszSymbolicName,
+ uiPDumpSymbolicOffset,
+ ui32Value,
+ uiPDumpFlags);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ eError = PMRUnlockSysPhysAddresses(psPMR);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ return PVRSRV_OK;
+}
+
+/*!
+ * @brief Writes a WRW64 command to the script2 buffer, representing a
+ * dword write to a physical allocation. Size is always
+ * sizeof(IMG_UINT64).
+ * @param psPMR - PMR object representing allocation
+ * @param uiLogicalOffset - offset
+ * @param ui64Value - value to write
+ * @param uiPDumpFlags - pdump flags
+ * @return PVRSRV_ERROR
+ */
+PVRSRV_ERROR
+PMRPDumpLoadMemValue64(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT64 ui64Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
+ IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+ IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+
+ PVR_ASSERT(uiLogicalOffset + sizeof(IMG_UINT64) <= psPMR->uiLogicalSize);
+
+ eError = PMRLockSysPhysAddresses(psPMR,
+ psPMR->uiLog2ContiguityGuarantee);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /* Get the symbolic address of the PMR */
+ eError = PMR_PDumpSymbolicAddr(psPMR,
+ uiLogicalOffset,
+ sizeof(aszMemspaceName),
+ &aszMemspaceName[0],
+ sizeof(aszSymbolicName),
+ &aszSymbolicName[0],
+ &uiPDumpSymbolicOffset,
+ &uiNextSymName);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /* Write the WRW script command */
+ eError = PDumpPMRWRW64(aszMemspaceName,
+ aszSymbolicName,
+ uiPDumpSymbolicOffset,
+ ui64Value,
+ uiPDumpFlags);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ eError = PMRUnlockSysPhysAddresses(psPMR);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ return PVRSRV_OK;
+}
+
+/*!
+ * @brief PDumps the contents of the given allocation.
+ * If bZero is IMG_TRUE then the zero page in the parameter stream is used
+ * as the source of data, rather than the allocation's actual backing.
+ * @param psPMR - PMR object representing allocation
+ * @param uiLogicalOffset - Offset to write at
+ * @param uiSize - Number of bytes to write
+ * @param uiPDumpFlags - PDump flags
+ * @param bZero - Use the PDump zero page as the source
+ * @return PVRSRV_ERROR
+ */
+PVRSRV_ERROR
+PMRPDumpLoadMem(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ PDUMP_FLAGS_T uiPDumpFlags,
+ IMG_BOOL bZero)
+{
+ /* common variables */
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
+ IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+ IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
+ PDUMP_FILEOFFSET_T uiParamStreamFileOffset;
+ IMG_SIZE_T uiBufSz;
+ IMG_SIZE_T uiNumBytes;
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+ const IMG_CHAR *pszParamStreamFileName;
+
+ /* required when !bZero */
+ #define PMR_MAX_PDUMP_BUFSZ 16384
+ IMG_CHAR aszParamStreamFilename[PMR_MAX_PARAMSTREAM_FILENAME_LENGTH_DEFAULT];
+ IMG_UINT8 *pcBuffer = IMG_NULL;
+
+ PVR_ASSERT(uiLogicalOffset + uiSize <= psPMR->uiLogicalSize);
+
+ if(bZero)
+ {
+ /* Check if this PMR needs to be persistent:
+ * If the allocation is persistent then it will be present in every
+ * pdump stream after its allocation. We must ensure the zeroing is also
+ * persistent so that every PDump MALLOC is accompanied by the initialisation
+ * to zero.
+ */
+ if(psPMR->bForcePersistent)
+ {
+ uiPDumpFlags = PDUMP_FLAGS_PERSISTENT;
+ }
+
+ PDumpCommentWithFlags(uiPDumpFlags, "Zeroing allocation (%llu bytes)",
+ (unsigned long long) uiSize);
+
+ /* get the zero page information. it is constant for this function */
+ PDumpGetParameterZeroPageInfo(&uiParamStreamFileOffset, &uiBufSz, &pszParamStreamFileName);
+ }
+ else
+ {
+ uiBufSz = PMR_MAX_PDUMP_BUFSZ;
+ if (uiBufSz > uiSize)
+ {
+ uiBufSz = TRUNCATE_64BITS_TO_SIZE_T(uiSize);
+ }
+
+ pcBuffer = OSAllocMem(uiBufSz);
+ PVR_ASSERT(pcBuffer != IMG_NULL);
+
+ eError = PMRLockSysPhysAddresses(psPMR,
+ psPMR->uiLog2ContiguityGuarantee);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ pszParamStreamFileName = aszParamStreamFilename;
+ }
+
+ while (uiSize > 0)
+ {
+ IMG_DEVMEM_OFFSET_T uiPhysicalOffset;
+ IMG_UINT32 ui32Remain;
+ IMG_BOOL bValid;
+
+ bValid = _PMRLogicalOffsetToPhysicalOffset(psPMR,
+ uiLogicalOffset,
+ &uiPhysicalOffset,
+ &ui32Remain);
+
+ if (bValid)
+ {
+ eError = _PMR_PDumpSymbolicAddrPhysical(psPMR,
+ uiPhysicalOffset,
+ sizeof(aszMemspaceName),
+ &aszMemspaceName[0],
+ sizeof(aszSymbolicName),
+ &aszSymbolicName[0],
+ &uiPDumpSymbolicOffset,
+ &uiNextSymName);
+ if(eError != PVRSRV_OK)
+ {
+ goto err_unlock_phys;
+ }
+
+ if(bZero)
+ {
+ uiNumBytes = TRUNCATE_64BITS_TO_SIZE_T(MIN(uiSize, uiBufSz));
+ }
+ else
+ {
+
+ /* Reads enough to fill buffer, or until next chunk,
+ or until end of PMR, whichever comes first */
+ eError = _PMR_ReadBytesPhysical(psPMR,
+ uiPhysicalOffset,
+ pcBuffer,
+ TRUNCATE_64BITS_TO_SIZE_T(MIN3(uiBufSz, uiSize, ui32Remain)),
+ &uiNumBytes);
+ if(eError != PVRSRV_OK)
+ {
+ goto err_unlock_phys;
+ }
+ PVR_ASSERT(uiNumBytes > 0);
+
+ eError = PDumpWriteBuffer(pcBuffer,
+ uiNumBytes,
+ uiPDumpFlags,
+ &aszParamStreamFilename[0],
+ sizeof(aszParamStreamFilename),
+ &uiParamStreamFileOffset);
+ if(eError != PVRSRV_OK)
+ {
+ goto err_unlock_phys;
+ }
+ }
+
+ eError = PDumpPMRLDB(aszMemspaceName,
+ aszSymbolicName,
+ uiPDumpSymbolicOffset,
+ uiNumBytes,
+ pszParamStreamFileName,
+ uiParamStreamFileOffset,
+ uiPDumpFlags);
+
+ if(eError != PVRSRV_OK)
+ {
+ goto err_unlock_phys;
+ }
+ }
+ else
+ {
+ /* Skip over invalid chunks */
+ uiNumBytes = TRUNCATE_64BITS_TO_SIZE_T(MIN(ui32Remain, uiSize));
+ }
+
+ uiLogicalOffset += uiNumBytes;
+ PVR_ASSERT(uiNumBytes <= uiSize);
+ uiSize -= uiNumBytes;
+ }
+
+err_unlock_phys:
+
+ if(!bZero)
+ {
+ eError = PMRUnlockSysPhysAddresses(psPMR);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ OSFreeMem(pcBuffer);
+ }
+ return eError;
+}
+
+
+
+PVRSRV_ERROR
+PMRPDumpSaveToFile(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 uiArraySize,
+ const IMG_CHAR *pszFilename)
+{
+ PVRSRV_ERROR eError;
+ IMG_CHAR aszMemspaceName[PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT];
+ IMG_CHAR aszSymbolicName[PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT];
+ IMG_DEVMEM_OFFSET_T uiOutOffset;
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+
+ PVR_UNREFERENCED_PARAMETER(uiArraySize);
+
+ PVR_ASSERT(uiLogicalOffset + uiSize <= psPMR->uiLogicalSize);
+
+ eError = PMR_PDumpSymbolicAddr(psPMR,
+ uiLogicalOffset,
+ sizeof(aszMemspaceName),
+ &aszMemspaceName[0],
+ sizeof(aszSymbolicName),
+ &aszSymbolicName[0],
+ &uiOutOffset,
+ &uiNextSymName);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ PVR_ASSERT(uiLogicalOffset + uiSize <= uiNextSymName);
+
+ eError = PDumpPMRSAB(aszMemspaceName,
+ aszSymbolicName,
+ uiOutOffset,
+ uiSize,
+ pszFilename,
+ 0);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ return PVRSRV_OK;
+}
+#endif /* PDUMP */
+
+
+
+IMG_VOID *PMRGetPrivateDataHack(const PMR *psPMR,
+ const PMR_IMPL_FUNCTAB *psFuncTab)
+{
+ PVR_ASSERT(psFuncTab == psPMR->psFuncTab);
+
+ return psPMR->pvFlavourData;
+}
+
+PVRSRV_ERROR
+PMRWritePMPageList(/* Target PMR, offset, and length */
+ PMR *psPageListPMR,
+ IMG_DEVMEM_OFFSET_T uiTableOffset,
+ IMG_DEVMEM_SIZE_T uiTableLength,
+ /* Referenced PMR, and "page" granularity */
+ PMR *psReferencePMR,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize,
+ PMR_PAGELIST **ppsPageList,
+ IMG_UINT64 *pui64CheckSum)
+{
+ PVRSRV_ERROR eError;
+ IMG_DEVMEM_SIZE_T uiWordSize;
+ IMG_UINT32 uiNumPages;
+ IMG_UINT32 uiPageIndex;
+ IMG_UINT32 ui32CheckSumXor = 0;
+ IMG_UINT32 ui32CheckSumAdd = 0;
+ PMR_FLAGS_T uiFlags;
+ PMR_PAGELIST *psPageList;
+#if defined(PDUMP)
+ IMG_CHAR aszTableEntryMemspaceName[100];
+ IMG_CHAR aszTableEntrySymbolicName[100];
+ IMG_DEVMEM_OFFSET_T uiTableEntryPDumpOffset;
+ IMG_CHAR aszPageMemspaceName[100];
+ IMG_CHAR aszPageSymbolicName[100];
+ IMG_DEVMEM_OFFSET_T uiPagePDumpOffset;
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+#endif
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 uiPageListPageSize = 1 << psPageListPMR->uiLog2ContiguityGuarantee;
+ IMG_BOOL bPageIsMapped = IMG_FALSE;
+ IMG_UINT64 uiPageListPMRPage = 0;
+ IMG_UINT64 uiPrevPageListPMRPage = 0;
+ IMG_HANDLE hPrivData = IMG_NULL;
+ IMG_VOID *pvKernAddr = IMG_NULL;
+ IMG_UINT32 *pui32DataPtr;
+#endif
+
+ uiWordSize = 4;
+
+ /* check we're being asked to write the same number of 4-byte units as there are pages */
+ uiNumPages = (IMG_UINT32)(psReferencePMR->uiLogicalSize >> uiLog2PageSize);
+
+ if ((PMR_SIZE_T)uiNumPages << uiLog2PageSize != psReferencePMR->uiLogicalSize)
+ {
+ /* Strictly speaking, it's possible to provoke this error in two ways:
+ (i) if it's not a whole multiple of the page size; or
+ (ii) if there are more than 4 billion pages.
+ The latter is unlikely. :) but the check is required in order to justify the cast.
+ */
+ eError = PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE;
+ goto e0;
+ }
+ uiWordSize = (IMG_UINT32)uiTableLength / uiNumPages;
+ if (uiNumPages * uiWordSize != uiTableLength)
+ {
+ eError = PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE;
+ goto e0;
+ }
+
+ /* Check we're not being asked to write off the end of the PMR */
+ if (uiTableOffset + uiTableLength > psPageListPMR->uiLogicalSize)
+ {
+ /* table memory insufficient to store all the entries */
+ /* table insufficient to store addresses of whole block */
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ /* the PMR into which we are writing must not be user CPU mappable: */
+ eError = PMR_Flags(psPageListPMR, &uiFlags);
+ if ((eError != PVRSRV_OK) ||
+ ((uiFlags & (PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE)) != 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "eError = %d", eError));
+ PVR_DPF((PVR_DBG_ERROR, "masked flags = 0x%08x", (uiFlags & (PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE))));
+ PVR_DPF((PVR_DBG_ERROR, "Page list PMR allows CPU mapping (0x%08x)", uiFlags));
+ eError = PVRSRV_ERROR_DEVICEMEM_INVALID_PMR_FLAGS;
+ goto e0;
+ }
+
+ if (_PMRIsSparse(psPageListPMR))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PageList PMR is sparse"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ if (_PMRIsSparse(psReferencePMR))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Reference PMR is sparse"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ psPageList = OSAllocMem(sizeof(PMR_PAGELIST));
+ if (psPageList == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Failed to allocation PMR page list"));
+ goto e0;
+ }
+ psPageList->psReferencePMR = psReferencePMR;
+
+ /* Need to lock down the physical addresses of the reference PMR */
+ /* N.B. This also checks that the requested "contiguity" is achievable */
+ eError = PMRLockSysPhysAddresses(psReferencePMR,
+ uiLog2PageSize);
+ if(eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ for (uiPageIndex = 0; uiPageIndex < uiNumPages; uiPageIndex++)
+ {
+#if !defined(NO_HARDWARE)
+ IMG_DEV_PHYADDR sDevAddrPtr;
+ IMG_DEV_PHYADDR sOldDevAddrPtr = {1}; //Set to non-aligned non-valid page
+ IMG_BOOL bPageIsValid;
+#endif
+ IMG_DEVMEM_OFFSET_T uiPMROffset = uiTableOffset + (uiWordSize * uiPageIndex);
+#if defined(PDUMP)
+ eError = PMR_PDumpSymbolicAddr(psPageListPMR,
+ uiPMROffset,
+ sizeof(aszTableEntryMemspaceName),
+ &aszTableEntryMemspaceName[0],
+ sizeof(aszTableEntrySymbolicName),
+ &aszTableEntrySymbolicName[0],
+ &uiTableEntryPDumpOffset,
+ &uiNextSymName);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ eError = PMR_PDumpSymbolicAddr(psReferencePMR,
+ (IMG_DEVMEM_OFFSET_T)uiPageIndex << uiLog2PageSize,
+ sizeof(aszPageMemspaceName),
+ &aszPageMemspaceName[0],
+ sizeof(aszPageSymbolicName),
+ &aszPageSymbolicName[0],
+ &uiPagePDumpOffset,
+ &uiNextSymName);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ eError = PDumpWriteShiftedMaskedValue(/* destination */
+ aszTableEntryMemspaceName,
+ aszTableEntrySymbolicName,
+ uiTableEntryPDumpOffset,
+ /* source */
+ aszPageMemspaceName,
+ aszPageSymbolicName,
+ uiPagePDumpOffset,
+ /* shift right */
+ uiLog2PageSize,
+ /* shift left */
+ 0,
+ /* mask */
+ 0xffffffff,
+ /* word size */
+ uiWordSize,
+ /* flags */
+ PDUMP_FLAGS_CONTINUOUS);
+ PVR_ASSERT(eError == PVRSRV_OK);
+#else
+ PVR_UNREFERENCED_PARAMETER(uiPMROffset);
+#endif
+#if !defined(NO_HARDWARE)
+ PMR_DevPhysAddr(psReferencePMR,
+ (IMG_DEVMEM_OFFSET_T)uiPageIndex << uiLog2PageSize,
+ &sDevAddrPtr,
+ &bPageIsValid);
+
+ /*
+ We check for sparse PMR's at function entry, but as we can,
+ check that every page is valid
+ */
+ PVR_ASSERT(bPageIsValid);
+
+ uiPageListPMRPage = uiPMROffset >> psReferencePMR->uiLog2ContiguityGuarantee;
+
+ if ((bPageIsMapped == IMG_FALSE) || (uiPageListPMRPage != uiPrevPageListPMRPage))
+ {
+ IMG_SIZE_T uiMappingOffset = uiPMROffset & (~(uiPageListPageSize - 1));
+ IMG_SIZE_T uiMappedSize;
+
+ if (bPageIsMapped == IMG_TRUE)
+ {
+ PMRReleaseKernelMappingData(psPageListPMR, hPrivData);
+ }
+
+ eError = PMRAcquireKernelMappingData(psPageListPMR,
+ uiMappingOffset,
+ uiPageListPageSize,
+ &pvKernAddr,
+ &uiMappedSize,
+ &hPrivData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Error mapping page list PMR page (%llu) into kernel (%d)",
+ uiPageListPMRPage, eError));
+ goto e2;
+ }
+
+ bPageIsMapped = IMG_TRUE;
+ uiPrevPageListPMRPage = uiPageListPMRPage;
+ PVR_ASSERT(uiMappedSize >= uiPageListPageSize);
+ PVR_ASSERT(pvKernAddr != IMG_NULL);
+ }
+
+ PVR_ASSERT(((sDevAddrPtr.uiAddr >> uiLog2PageSize) & 0xFFFFFFFF00000000ll) == 0);
+
+ /* Write the physcial page index into the page list PMR */
+ pui32DataPtr = (IMG_UINT32 *) (((IMG_CHAR *) pvKernAddr) + (uiPMROffset & (uiPageListPageSize - 1)));
+ *pui32DataPtr = TRUNCATE_64BITS_TO_32BITS(sDevAddrPtr.uiAddr >> uiLog2PageSize);
+ ui32CheckSumXor ^= TRUNCATE_64BITS_TO_32BITS(sDevAddrPtr.uiAddr >> uiLog2PageSize);
+ ui32CheckSumAdd += TRUNCATE_64BITS_TO_32BITS(sDevAddrPtr.uiAddr >> uiLog2PageSize);
+ PVR_ASSERT(sDevAddrPtr.uiAddr != 0);
+ PVR_ASSERT(sDevAddrPtr.uiAddr != sOldDevAddrPtr.uiAddr);
+ sOldDevAddrPtr.uiAddr = sDevAddrPtr.uiAddr;
+ /* Last page so unmap */
+ if (uiPageIndex == (uiNumPages - 1))
+ {
+ PMRReleaseKernelMappingData(psPageListPMR, hPrivData);
+ }
+#endif
+ }
+
+ *pui64CheckSum = ((IMG_UINT64)ui32CheckSumXor << 32) | ui32CheckSumAdd;
+ *ppsPageList = psPageList;
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+#if !defined(NO_HARDWARE)
+ e2:
+ PMRUnlockSysPhysAddresses(psReferencePMR);
+#endif
+ e1:
+ OSFreeMem(psPageList);
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PMRUnwritePMPageList(PMR_PAGELIST *psPageList)
+{
+ PVRSRV_ERROR eError2;
+
+ eError2 = PMRUnlockSysPhysAddresses(psPageList->psReferencePMR);
+ PVR_ASSERT(eError2 == PVRSRV_OK);
+ OSFreeMem(psPageList);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMRZeroingPMR(PMR *psPMR,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize)
+{
+ IMG_UINT32 uiNumPages;
+ IMG_UINT32 uiPageIndex;
+ IMG_UINT32 ui32PageSize = 1 << uiLog2PageSize;
+ IMG_HANDLE hPrivData = IMG_NULL;
+ IMG_VOID *pvKernAddr = IMG_NULL;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_SIZE_T uiMapedSize;
+
+ PVR_ASSERT(psPMR);
+
+ /* Calculate number of pages in this PMR */
+ uiNumPages = (IMG_UINT32)(psPMR->uiLogicalSize >> uiLog2PageSize);
+
+ /* Verify the logical Size is a multiple or the physical page size */
+ if ((PMR_SIZE_T)uiNumPages << uiLog2PageSize != psPMR->uiLogicalSize)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PMRZeroingPMR: PMR is not a multiple of %u",ui32PageSize));
+ eError = PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE;
+ goto MultiPage_Error;
+ }
+
+ if (_PMRIsSparse(psPMR))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PMRZeroingPMR: PMR is sparse"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto Sparse_Error;
+ }
+
+ /* Scan through all pages of the PMR */
+ for (uiPageIndex = 0; uiPageIndex < uiNumPages; uiPageIndex++)
+ {
+ /* map the physical page (for a given PMR offset) into kernel space */
+ eError = PMRAcquireKernelMappingData(psPMR,
+ (IMG_SIZE_T)uiPageIndex << uiLog2PageSize,
+ ui32PageSize,
+ &pvKernAddr,
+ &uiMapedSize,
+ &hPrivData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PMRZeroingPMR: AcquireKernelMapping failed with error %u", eError));
+ goto AcquireKernelMapping_Error;
+ }
+
+ /* ensure the mapped page size is the same as the physical page size */
+ if (uiMapedSize != ui32PageSize)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PMRZeroingPMR: Physical Page size = 0x%08x, Size of Mapping = 0x%016llx",
+ ui32PageSize,
+ (IMG_UINT64)uiMapedSize));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto MappingSize_Error;
+ }
+
+ /* zeroing page content */
+ OSMemSet(pvKernAddr, 0, ui32PageSize);
+
+ /* release mapping */
+ PMRReleaseKernelMappingData(psPMR, hPrivData);
+
+ }
+
+ PVR_DPF((PVR_DBG_WARNING,"PMRZeroingPMR: Zeroing PMR %p done (num pages %u, page size %u)",
+ psPMR,
+ uiNumPages,
+ ui32PageSize));
+
+ return PVRSRV_OK;
+
+
+ /* Error handling */
+
+MappingSize_Error:
+ PMRReleaseKernelMappingData(psPMR, hPrivData);
+
+AcquireKernelMapping_Error:
+Sparse_Error:
+MultiPage_Error:
+
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR
+PMRDumpPageList(PMR *psPMR,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize)
+{
+ IMG_DEV_PHYADDR sDevAddrPtr;
+ IMG_UINT32 uiNumPages;
+ IMG_UINT32 uiPageIndex;
+ IMG_BOOL bPageIsValid;
+ IMG_UINT32 ui32Col = 16;
+ IMG_UINT32 ui32SizePerCol = 11;
+ IMG_UINT32 ui32ByteCount = 0;
+ IMG_CHAR pszBuffer[16 /* ui32Col */ * 11 /* ui32SizePerCol */ + 1];
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ /* Get number of pages */
+ uiNumPages = (IMG_UINT32)(psPMR->uiLogicalSize >> uiLog2PageSize);
+
+ /* Verify the logical Size is a multiple or the physical page size */
+ if ((PMR_SIZE_T)uiNumPages << uiLog2PageSize != psPMR->uiLogicalSize)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PMRPrintPageList: PMR is not a multiple of %u", 1 << uiLog2PageSize));
+ eError = PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE;
+ goto MultiPage_Error;
+ }
+
+ if (_PMRIsSparse(psPMR))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PMRPrintPageList: PMR is sparse"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto Sparse_Error;
+ }
+
+ PVR_LOG((" PMR %p, Number of pages %u, Log2PageSize %d", psPMR, uiNumPages, uiLog2PageSize));
+
+ /* Print the address of the physical pages */
+ for (uiPageIndex = 0; uiPageIndex < uiNumPages; uiPageIndex++)
+ {
+ /* Get Device physical Address */
+ eError = PMR_DevPhysAddr(psPMR,
+ (IMG_DEVMEM_OFFSET_T)uiPageIndex << uiLog2PageSize,
+ &sDevAddrPtr,
+ &bPageIsValid);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PMRPrintPageList: PMR %p failed to get DevPhysAddr with error %u",
+ psPMR,
+ eError));
+ goto DevPhysAddr_Error;
+ }
+
+ ui32ByteCount += OSSNPrintf(pszBuffer + ui32ByteCount, ui32SizePerCol + 1, "%08x ", (IMG_UINT32)(sDevAddrPtr.uiAddr >> uiLog2PageSize));
+ PVR_ASSERT(ui32ByteCount < ui32Col * ui32SizePerCol);
+
+ if (uiPageIndex % ui32Col == ui32Col -1)
+ {
+ PVR_LOG((" Phys Page: %s", pszBuffer));
+ ui32ByteCount = 0;
+ }
+ }
+ if (ui32ByteCount > 0)
+ {
+ PVR_LOG((" Phys Page: %s", pszBuffer));
+ }
+
+ return PVRSRV_OK;
+
+ /* Error handling */
+DevPhysAddr_Error:
+Sparse_Error:
+MultiPage_Error:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR
+PMRWriteVFPPageList(/* Target PMR, offset, and length */
+ PMR *psFreeListPMR,
+ IMG_DEVMEM_OFFSET_T uiTableOffset,
+ IMG_DEVMEM_SIZE_T uiTableLength,
+ IMG_UINT32 ui32TableBase,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize)
+{
+ PVRSRV_ERROR eError;
+ IMG_DEVMEM_SIZE_T uiWordSize = 4;
+ IMG_UINT32 i;
+ PMR_FLAGS_T uiFlags;
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 uiPageListPageSize = 1 << psFreeListPMR->uiLog2ContiguityGuarantee;
+ IMG_BOOL bPageIsMapped = IMG_FALSE;
+ IMG_UINT64 uiPageListPMRPage = 0;
+ IMG_UINT64 uiPrevPageListPMRPage = 0;
+ IMG_HANDLE hPrivData = IMG_NULL;
+ IMG_VOID *pvKernAddr = IMG_NULL;
+ IMG_UINT32 *pui32DataPtr;
+#endif
+
+#if defined(PDUMP)
+ PDumpComment("Write VFP into freelist");
+#endif
+ /* Check we're not being asked to write off the end of the PMR */
+ if (uiTableOffset + (uiTableLength*uiWordSize) > psFreeListPMR->uiLogicalSize)
+ {
+ /* table memory insufficient to store all the entries */
+ /* table insufficient to store addresses of whole block */
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ /* the PMR into which we are writing must not be user CPU mappable: */
+ eError = PMR_Flags(psFreeListPMR, &uiFlags);
+ if ((eError != PVRSRV_OK) ||
+ ((uiFlags & (PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE)) != 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "eError = %d", eError));
+ PVR_DPF((PVR_DBG_ERROR, "masked flags = 0x%08x", (uiFlags & (PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE))));
+ PVR_DPF((PVR_DBG_ERROR, "Page list PMR allows CPU mapping (0x%08x)", uiFlags));
+ eError = PVRSRV_ERROR_DEVICEMEM_INVALID_PMR_FLAGS;
+ goto e0;
+ }
+
+ if (_PMRIsSparse(psFreeListPMR))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeList PMR is sparse"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ for (i = 0; i < uiTableLength; i++)
+ {
+ IMG_DEVMEM_OFFSET_T uiPMROffset = uiTableOffset + (uiWordSize * i);
+#if defined(PDUMP)
+ eError = PMRPDumpLoadMemValue32(psFreeListPMR,
+ uiPMROffset,
+ i + ui32TableBase,
+ PDUMP_FLAGS_CONTINUOUS);
+ PVR_ASSERT(eError == PVRSRV_OK);
+#else
+ PVR_UNREFERENCED_PARAMETER(uiPMROffset);
+#endif
+#if !defined(NO_HARDWARE)
+
+ uiPageListPMRPage = uiPMROffset >> uiLog2PageSize;
+
+ if ((bPageIsMapped == IMG_FALSE) || (uiPageListPMRPage != uiPrevPageListPMRPage))
+ {
+ IMG_SIZE_T uiMappingOffset = uiPMROffset & (~(uiPageListPageSize - 1));
+ IMG_SIZE_T uiMappedSize;
+
+ if (bPageIsMapped == IMG_TRUE)
+ {
+ PMRReleaseKernelMappingData(psFreeListPMR, hPrivData);
+ }
+
+ eError = PMRAcquireKernelMappingData(psFreeListPMR,
+ uiMappingOffset,
+ uiPageListPageSize,
+ &pvKernAddr,
+ &uiMappedSize,
+ &hPrivData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Error mapping page list PMR page (%llu) into kernel (%d)",
+ uiPageListPMRPage, eError));
+ goto e0;
+ }
+
+ bPageIsMapped = IMG_TRUE;
+ uiPrevPageListPMRPage = uiPageListPMRPage;
+ PVR_ASSERT(uiMappedSize >= uiPageListPageSize);
+ PVR_ASSERT(pvKernAddr != IMG_NULL);
+ }
+
+ /* Write the physcial page index into the page list PMR */
+ pui32DataPtr = (IMG_UINT32 *) (((IMG_CHAR *) pvKernAddr) + (uiPMROffset & (uiPageListPageSize - 1)));
+ *pui32DataPtr = i + ui32TableBase;
+
+ /* Last page so unmap */
+ if (i == (uiTableLength - 1))
+ {
+ PMRReleaseKernelMappingData(psFreeListPMR, hPrivData);
+ }
+#endif
+ }
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+#if defined(PDUMP)
+extern PVRSRV_ERROR
+PMRPDumpPol32(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ IMG_CHAR aszMemspaceName[100];
+ IMG_CHAR aszSymbolicName[100];
+ IMG_DEVMEM_OFFSET_T uiPDumpOffset;
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+
+ eError = PMR_PDumpSymbolicAddr(psPMR,
+ uiLogicalOffset,
+ sizeof(aszMemspaceName),
+ &aszMemspaceName[0],
+ sizeof(aszSymbolicName),
+ &aszSymbolicName[0],
+ &uiPDumpOffset,
+ &uiNextSymName);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+#define _MEMPOLL_DELAY (1000)
+#define _MEMPOLL_COUNT (2000000000 / _MEMPOLL_DELAY)
+
+ eError = PDumpPMRPOL(aszMemspaceName,
+ aszSymbolicName,
+ uiPDumpOffset,
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ _MEMPOLL_COUNT,
+ _MEMPOLL_DELAY,
+ uiPDumpFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR
+PMRPDumpCBP(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize)
+{
+ PVRSRV_ERROR eError;
+ IMG_CHAR aszMemspaceName[100];
+ IMG_CHAR aszSymbolicName[100];
+ IMG_DEVMEM_OFFSET_T uiPDumpOffset;
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+
+ eError = PMR_PDumpSymbolicAddr(psPMR,
+ uiReadOffset,
+ sizeof(aszMemspaceName),
+ &aszMemspaceName[0],
+ sizeof(aszSymbolicName),
+ &aszSymbolicName[0],
+ &uiPDumpOffset,
+ &uiNextSymName);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ eError = PDumpPMRCBP(aszMemspaceName,
+ aszSymbolicName,
+ uiPDumpOffset,
+ uiWriteOffset,
+ uiPacketSize,
+ uiBufferSize);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+#endif
+
+PVRSRV_ERROR
+PMRInit()
+{
+ PVRSRV_ERROR eError;
+
+ if (_gsSingletonPMRContext.bModuleInitialised)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "pmr.c: oops, already initialized"));
+ return PVRSRV_ERROR_PMR_UNRECOVERABLE_ERROR;
+ }
+
+ eError = OSLockCreate(&_gsSingletonPMRContext.hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = OSLockCreate(&gGlobalLookupPMRLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ _gsSingletonPMRContext.uiNextSerialNum = 1;
+
+ _gsSingletonPMRContext.uiNextKey = 0x8300f001 * (IMG_UINTPTR_T)&_gsSingletonPMRContext;
+
+ _gsSingletonPMRContext.bModuleInitialised = IMG_TRUE;
+
+ _gsSingletonPMRContext.uiNumLivePMRs = 0;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PMRDeInit()
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+ {
+ return PVRSRV_OK;
+ }
+
+ PVR_ASSERT(_gsSingletonPMRContext.bModuleInitialised);
+ if (!_gsSingletonPMRContext.bModuleInitialised)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "pmr.c: oops, not initialized"));
+ return PVRSRV_ERROR_PMR_UNRECOVERABLE_ERROR;
+ }
+
+ PVR_ASSERT(_gsSingletonPMRContext.uiNumLivePMRs == 0);
+ if (_gsSingletonPMRContext.uiNumLivePMRs != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "pmr.c: %d live PMR(s) remain(s)", _gsSingletonPMRContext.uiNumLivePMRs));
+ PVR_DPF((PVR_DBG_ERROR, "pmr.c: This is an unrecoverable error; a subsequent crash is inevitable"));
+ return PVRSRV_ERROR_PMR_UNRECOVERABLE_ERROR;
+ }
+
+ OSLockDestroy(_gsSingletonPMRContext.hLock);
+ OSLockDestroy(gGlobalLookupPMRLock);
+
+ _gsSingletonPMRContext.bModuleInitialised = IMG_FALSE;
+
+
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/services/server/common/power.c b/drivers/gpu/rogue/services/server/common/power.c
new file mode 100755
index 000000000000..8b0d7f4d3dbb
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/power.c
@@ -0,0 +1,942 @@
+/*************************************************************************/ /*!
+@File power.c
+@Title Power management functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for power management 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 "allocmem.h"
+#include "osfunc.h"
+
+#include "lists.h"
+#include "pvrsrv.h"
+#include "pvr_debug.h"
+#include "process_stats.h"
+#include "rk_init.h"
+
+static IMG_BOOL gbInitServerRunning = IMG_FALSE;
+static IMG_BOOL gbInitServerRan = IMG_FALSE;
+static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetInitServerState
+
+ @Description Sets given services init state.
+
+ @Input eInitServerState : a services init state
+ @Input bState : a state to set
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState)
+{
+
+ switch(eInitServerState)
+ {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ gbInitServerRunning = bState;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ gbInitServerRan = bState;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ gbInitSuccessful = bState;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetInitServerState : Unknown state %x", eInitServerState));
+ return PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE;
+ }
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetInitServerState
+
+ @Description Tests whether a given services init state was run.
+
+ @Input eInitServerState : a services init state
+
+ @Return IMG_BOOL
+
+******************************************************************************/
+IMG_EXPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
+{
+ IMG_BOOL bReturnVal;
+
+ switch(eInitServerState)
+ {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ bReturnVal = gbInitServerRunning;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ bReturnVal = gbInitServerRan;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ bReturnVal = gbInitSuccessful;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetInitServerState : Unknown state %x", eInitServerState));
+ bReturnVal = IMG_FALSE;
+ }
+
+ return bReturnVal;
+}
+
+/*!
+******************************************************************************
+
+ @Function _IsSystemStatePowered
+
+ @Description Tests whether a given system state represents powered-up.
+
+ @Input eSystemPowerState : a system power state
+
+ @Return IMG_BOOL
+
+******************************************************************************/
+static IMG_BOOL _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
+{
+ return (eSystemPowerState == PVRSRV_SYS_POWER_STATE_ON);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVPowerLock
+
+ @Description Obtain the mutex for power transitions. Only allowed when
+ system power is on.
+
+ @Return PVRSRV_ERROR_RETRY or PVRSRV_OK
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerLock()
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ /* Only allow to take powerlock when the system power is on */
+ if (_IsSystemStatePowered(psPVRSRVData->eCurrentPowerState))
+ {
+ OSLockAcquire(psPVRSRVData->hPowerLock);
+ eError = PVRSRV_OK;
+ }
+ else
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVForcedPowerLock
+
+ @Description Obtain the mutex for power transitions regardless of
+ system power state
+
+ @Return PVRSRV_ERROR_RETRY or PVRSRV_OK
+
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID PVRSRVForcedPowerLock()
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ OSLockAcquire(psPVRSRVData->hPowerLock);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVPowerUnlock
+
+ @Description Release the mutex for power transitions
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID PVRSRVPowerUnlock()
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ OSLockRelease(psPVRSRVData->hPowerLock);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePrePowerStateKM_AnyVaCb
+
+ @Description
+
+ Perform device-specific processing required before a power transition
+
+ @Input psPowerDevice : the device
+ @Input va : variable argument list with:
+ bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ ui32DeviceIndex : device index
+ eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+ /*Variable Argument variables*/
+ IMG_BOOL bAllDevices;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+ IMG_BOOL bForced;
+ IMG_UINT64 ui32SysTimer1=0, ui32SysTimer2=0, ui32DevTimer1=0, ui32DevTimer2=0;
+
+ /*WARNING! if types were not aligned to 4 bytes, this could be dangerous!!!*/
+ bAllDevices = va_arg(va, IMG_BOOL);
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+ bForced = va_arg(va, IMG_BOOL);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+ {
+ eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+ psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+ {
+ if (psPowerDevice->pfnDevicePrePower != IMG_NULL)
+ {
+ /* Call the device's power callback. */
+
+ ui32DevTimer1=OSClockns64();
+
+ eError = psPowerDevice->pfnDevicePrePower(psPowerDevice->hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState,
+ bForced);
+
+ ui32DevTimer2=OSClockns64();
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ /* Do any required system-layer processing. */
+ if (psPowerDevice->pfnSystemPrePower != IMG_NULL)
+ {
+
+ ui32SysTimer1=OSClockus();
+
+ eError = psPowerDevice->pfnSystemPrePower(eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState,
+ bForced);
+
+ ui32SysTimer2=OSClockus();
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ }
+ }
+
+
+ InsertPowerTimeStatistic(PVRSRV_POWER_ENTRY_TYPE_PRE,
+ psPowerDevice->eCurrentPowerState, eNewPowerState,
+ ui32SysTimer1,ui32SysTimer2,
+ ui32DevTimer1,ui32DevTimer2,
+ bForced);
+
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePrePowerStateKM
+
+ @Description
+
+ Perform device-specific processing required before a power transition
+
+ @Input bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ @Input ui32DeviceIndex : device index
+ @Input eNewPowerState : New power state
+ @Input bForced : TRUE if the transition should not fail (e.g. OS request)
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
+ IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_BOOL bForced)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ /* Loop through the power devices. */
+ eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psPVRSRVData->psPowerDeviceList,
+ &PVRSRVDevicePrePowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState,
+ bForced);
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePostPowerStateKM_AnyVaCb
+
+ @Description
+
+ Perform device-specific processing required after a power transition
+
+ @Input psPowerDevice : the device
+ @Input va : variable argument list with:
+ bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ ui32DeviceIndex : device index
+ eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+ /*Variable Argument variables*/
+ IMG_BOOL bAllDevices;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+ IMG_BOOL bForced;
+ IMG_UINT64 ui32SysTimer1=0, ui32SysTimer2=0, ui32DevTimer1=0, ui32DevTimer2=0;
+
+ /*WARNING! if types were not aligned to 4 bytes, this could be dangerous!!!*/
+ bAllDevices = va_arg(va, IMG_BOOL);
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+ bForced = va_arg(va, IMG_BOOL);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+ {
+ eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+ psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+ {
+ /* Do any required system-layer processing. */
+ if (psPowerDevice->pfnSystemPostPower != IMG_NULL)
+ {
+
+ ui32SysTimer1=OSClockns64();
+
+ eError = psPowerDevice->pfnSystemPostPower(eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState,
+ bForced);
+
+ ui32SysTimer2=OSClockns64();
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ if (psPowerDevice->pfnDevicePostPower != IMG_NULL)
+ {
+ /* Call the device's power callback. */
+
+ ui32DevTimer1=OSClockus();
+
+ eError = psPowerDevice->pfnDevicePostPower(psPowerDevice->hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState,
+ bForced);
+
+ ui32DevTimer2=OSClockus();
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ psPowerDevice->eCurrentPowerState = eNewDevicePowerState;
+ }
+ }
+
+
+ InsertPowerTimeStatistic(PVRSRV_POWER_ENTRY_TYPE_POST,
+ psPowerDevice->eCurrentPowerState, eNewPowerState,
+ ui32SysTimer1,ui32SysTimer2,
+ ui32DevTimer1,ui32DevTimer2,
+ bForced);
+
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePostPowerStateKM
+
+ @Description
+
+ Perform device-specific processing required after a power transition
+
+ @Input bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ @Input ui32DeviceIndex : device index
+ @Input eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
+ IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_BOOL bForced)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ /* Loop through the power devices. */
+ eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psPVRSRVData->psPowerDeviceList,
+ &PVRSRVDevicePostPowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState,
+ bForced);
+
+ return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetDevicePowerStateKM
+
+ @Description Set the Device into a new state
+
+ @Input ui32DeviceIndex : device index
+ @Input eNewPowerState : New power state
+ @Input bForced : TRUE if the transition should not fail (e.g. OS request)
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_BOOL bForced)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DATA* psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_DEV_POWER_STATE eOldPowerState;
+
+ eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &eOldPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVSetDevicePowerStateKM: Couldn't read power state."));
+ eOldPowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+ }
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced);
+ if(eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced);
+
+ /* Signal Device Watchdog Thread about power mode change. */
+ if (eOldPowerState != eNewPowerState && eNewPowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ psPVRSRVData->ui32DevicesWatchdogPwrTrans++;
+
+ if (psPVRSRVData->ui32DevicesWatchdogTimeout == DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT)
+ {
+ if (psPVRSRVData->hDevicesWatchdogEvObj)
+ {
+ eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj);
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+ }
+ }
+ }
+
+Exit:
+
+ if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVSetDevicePowerStateKM : Transition to %d was denied, Forced=%d", eNewPowerState, bForced));
+ }
+ else if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED (%s)", eNewPowerState, PVRSRVGetErrorStringKM(eError)));
+ }
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetPowerStateKM
+
+ @Description Set the system into a new state
+
+ @Input eNewPowerState :
+ @Input bForced : TRUE if the transition should not fail (e.g. OS request)
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState, IMG_BOOL bForced)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ IMG_UINT uiStage = 0;
+
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState =
+ _IsSystemStatePowered(eNewSysPowerState)? PVRSRV_DEV_POWER_STATE_DEFAULT : PVRSRV_DEV_POWER_STATE_OFF;
+
+ /* require a proper power state */
+ if (eNewSysPowerState == PVRSRV_SYS_POWER_STATE_Unspecified)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* no power transition requested, so do nothing */
+ if (eNewSysPowerState == psPVRSRVData->eCurrentPowerState)
+ {
+ return PVRSRV_OK;
+ }
+
+ /* Prevent simultaneous SetPowerStateKM calls */
+ PVRSRVForcedPowerLock();
+
+ /* Perform pre transitions: first device and then sys layer */
+ eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced);
+ if (eError != PVRSRV_OK)
+ {
+ uiStage++;
+ goto ErrorExit;
+ }
+ eError = PVRSRVSysPrePowerState(eNewSysPowerState, bForced);
+ if (eError != PVRSRV_OK)
+ {
+ uiStage++;
+ goto ErrorExit;
+ }
+
+ /* Perform system-specific post power transitions: first sys layer and then device */
+ eError = PVRSRVSysPostPowerState(eNewSysPowerState, bForced);
+ if (eError != PVRSRV_OK)
+ {
+ uiStage++;
+ goto ErrorExit;
+ }
+ eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced);
+ if (eError != PVRSRV_OK)
+ {
+ uiStage++;
+ goto ErrorExit;
+ }
+
+ psPVRSRVData->eCurrentPowerState = eNewSysPowerState;
+ psPVRSRVData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+ PVRSRVPowerUnlock();
+
+ /*
+ Reprocess the devices' queues in case commands were blocked during
+ the power transition.
+ */
+ if (_IsSystemStatePowered(eNewSysPowerState) &&
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ {
+ PVRSRVCheckStatus(IMG_NULL);
+ }
+
+ return PVRSRV_OK;
+
+ErrorExit:
+ /* save the power state for the re-attempt */
+ psPVRSRVData->eFailedPowerState = eNewSysPowerState;
+
+ PVRSRVPowerUnlock();
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetPowerStateKM: Transition from %d to %d FAILED (%s) at stage %d, forced: %d. Dumping debug info.",
+ psPVRSRVData->eCurrentPowerState, eNewSysPowerState, PVRSRVGetErrorStringKM(eError), uiStage, bForced));
+
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
+ PFN_PRE_POWER pfnDevicePrePower,
+ PFN_POST_POWER pfnDevicePostPower,
+ PFN_SYS_DEV_PRE_POWER pfnSystemPrePower,
+ PFN_SYS_DEV_POST_POWER pfnSystemPostPower,
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange,
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ if (pfnDevicePrePower == IMG_NULL &&
+ pfnDevicePostPower == IMG_NULL)
+ {
+ return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+ }
+
+ psPowerDevice = OSAllocMem(sizeof(PVRSRV_POWER_DEV));
+ if (psPowerDevice == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* setup device for power manager */
+ psPowerDevice->pfnDevicePrePower = pfnDevicePrePower;
+ psPowerDevice->pfnDevicePostPower = pfnDevicePostPower;
+ psPowerDevice->pfnSystemPrePower = pfnSystemPrePower;
+ psPowerDevice->pfnSystemPostPower = pfnSystemPostPower;
+ psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
+ psPowerDevice->pfnPostClockSpeedChange = pfnPostClockSpeedChange;
+ psPowerDevice->hDevCookie = hDevCookie;
+ psPowerDevice->ui32DeviceIndex = ui32DeviceIndex;
+ psPowerDevice->eCurrentPowerState = eCurrentPowerState;
+ psPowerDevice->eDefaultPowerState = eDefaultPowerState;
+
+ /* insert into power device list */
+ List_PVRSRV_POWER_DEV_Insert(&(psPVRSRVData->psPowerDeviceList), psPowerDevice);
+
+ //zxl:set device node to get pfnGetGpuUtilStats in rk_init.c
+ rk33_set_device_node(hDevCookie);
+
+ return (PVRSRV_OK);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVRemovePowerDevice
+
+ @Description
+
+ Removes device from power management register. Device is located by Device Index
+
+ @Input ui32DeviceIndex : device index
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_POWER_DEV *psPowerDev;
+
+ /* find device in list and remove it */
+ psPowerDev = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDev)
+ {
+ List_PVRSRV_POWER_DEV_Remove(psPowerDev);
+ OSFreeMem(psPowerDev);
+ /*not nulling pointer, copy on stack*/
+ }
+
+ //zxl:clear device node
+ rk33_clear_device_node();
+
+ return (PVRSRV_OK);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetDevicePowerState
+
+ @Description
+
+ Return the device power state
+
+ @Input ui32DeviceIndex : device index
+ @Output psPowerState : Current power state
+
+ @Return PVRSRV_ERROR_UNKNOWN_POWER_STATE if device could not be found. PVRSRV_OK otherwise.
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDevicePowerState(IMG_UINT32 ui32DeviceIndex, PPVRSRV_DEV_POWER_STATE pePowerState)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+ if (psPowerDevice == IMG_NULL)
+ {
+ return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+ }
+
+ *pePowerState = psPowerDevice->eCurrentPowerState;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVIsDevicePowered
+
+ @Description
+
+ Whether the device is powered, for the purposes of lockup detection.
+
+ @Input ui32DeviceIndex : device index
+
+ @Return IMG_BOOL
+
+******************************************************************************/
+IMG_EXPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_DEV_POWER_STATE ePowerState;
+
+ if (OSLockIsLocked(psPVRSRVData->hPowerLock))
+ {
+ return IMG_FALSE;
+ }
+
+ if (PVRSRVGetDevicePowerState(ui32DeviceIndex, &ePowerState) != PVRSRV_OK)
+ {
+ return IMG_FALSE;
+ }
+
+ return (ePowerState == PVRSRV_DEV_POWER_STATE_ON);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePreClockSpeedChange
+
+ @Description
+
+ Notification from system layer that a device clock speed change is about to happen.
+
+ @Input ui32DeviceIndex : device index
+ @Input bIdleDevice : whether the device should be idled
+ @Input pvInfo
+
+ @Return IMG_VOID
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ /*search the device and then do the pre clock speed change*/
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ do
+ {
+ /* This mutex is released in PVRSRVDevicePostClockSpeedChange. */
+ eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%x", eError));
+ return eError;
+ }
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+ {
+ eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie,
+ bIdleDevice,
+ psPowerDevice->eCurrentPowerState);
+
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePreClockSpeedChange : Device %u failed, error:0x%x",
+ ui32DeviceIndex, eError));
+ }
+ else if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVDevicePreClockSpeedChange : Device %u denied transition to IDLE",
+ ui32DeviceIndex));
+
+ PVRSRVPowerUnlock();
+ OSSleepms(1);
+ }
+ }
+ else
+ {
+ /* In the case of no pfnPostClockSpeedChange call being made, eError remains PVRSRV_OK... */
+ }
+ }
+ while (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVRSRVPowerUnlock();
+ }
+
+ return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePostClockSpeedChange
+
+ @Description
+
+ Notification from system layer that a device clock speed change has just happened.
+
+ @Input ui32DeviceIndex : device index
+ @Input bIdleDevice : whether the device had been idled
+ @Input pvInfo
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ /*search the device and then do the post clock speed change*/
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+ {
+ eError = psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->hDevCookie,
+ bIdleDevice,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePostClockSpeedChange : Device %u failed, error:0x%x",
+ ui32DeviceIndex, eError));
+ }
+ }
+
+
+ /* This mutex was acquired in PVRSRVDevicePreClockSpeedChange. */
+ PVRSRVPowerUnlock();
+}
+
+/******************************************************************************
+ End of file (power.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/common/process_stats.c b/drivers/gpu/rogue/services/server/common/process_stats.c
new file mode 100755
index 000000000000..d0e4b4d3fab0
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/process_stats.c
@@ -0,0 +1,2757 @@
+/*************************************************************************/ /*!
+@File
+@Title Process based statistics
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Manages a collection of statistics based around a process
+ and referenced via OS agnostic methods.
+@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 <stddef.h>
+
+#include "img_defs.h"
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "lock.h"
+#include "allocmem.h"
+#include "osfunc.h"
+#include "lists.h"
+#include "process_stats.h"
+#include "ri_server.h"
+#include "hash.h"
+
+#define DBGTIMEDIFF(T0, T1) ((IMG_UINT64) ( (T0) <= (T1) ? (T1) - (T0): IMG_UINT64_MAX - (T0) + (T1) ))
+#define MEAN_TIME(A, B) ( ((3*(A))/4) + ((1 * (B))/4) )
+
+
+/*
+ * Maximum history of process statistics that will be kept.
+ */
+#define MAX_DEAD_LIST_PROCESSES (10)
+
+void *pvOSPowerStatsEntryData=NULL;
+
+
+/*
+ * Definition of all process based statistics and the strings used to
+ * format them.
+ */
+typedef enum
+{
+ /* Stats that are per process... */
+ PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_CONNECTIONS,
+
+ PVRSRV_PROCESS_STAT_TYPE_RC_OOMS,
+ PVRSRV_PROCESS_STAT_TYPE_RC_PRS,
+ PVRSRV_PROCESS_STAT_TYPE_RC_GROWS,
+ PVRSRV_PROCESS_STAT_TYPE_RC_PUSH_GROWS,
+ PVRSRV_PROCESS_STAT_TYPE_RC_TA_STORES,
+ PVRSRV_PROCESS_STAT_TYPE_RC_3D_STORES,
+ PVRSRV_PROCESS_STAT_TYPE_RC_SH_STORES,
+ PVRSRV_PROCESS_STAT_TYPE_RC_CDM_STORES,
+ PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_APP,
+ PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_FW,
+ PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_APP,
+ PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_FW,
+ PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT,
+ PVRSRV_PROCESS_STAT_TYPE_FREELIST_MAX_PAGES,
+ PVRSRV_PROCESS_STAT_TYPE_KMALLOC,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_KMALLOC,
+ PVRSRV_PROCESS_STAT_TYPE_VMALLOC,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_VMALLOC,
+ PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_PAGES_PT_UMA,
+ PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_VMAP_PT_UMA,
+ PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_PAGES_PT_LMA,
+ PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_IOREMAP_PT_LMA,
+ PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_LMA_PAGES,
+ PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_UMA_PAGES,
+ PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_MAP_UMA_LMA_PAGES,
+
+ //zxl: count total data
+ PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_ALLOC,
+ PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP,
+ PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_MAP,
+
+ /* Must be the last enum...*/
+ PVRSRV_PROCESS_STAT_TYPE_COUNT
+} PVRSRV_PROCESS_STAT_TYPE;
+
+
+typedef enum
+{
+ PVRSRV_POWER_TIMING_STAT_FORCED_POWER_TRANSITION=0,
+ PVRSRV_POWER_TIMING_STAT_PRE_DEVICE,
+ PVRSRV_POWER_TIMING_STAT_PRE_SYSTEM,
+ PVRSRV_POWER_TIMING_STAT_POST_DEVICE,
+ PVRSRV_POWER_TIMING_STAT_POST_SYSTEM,
+ PVRSRV_POWER_TIMING_STAT_NEWLINE1,
+ PVRSRV_POWER_TIMING_STAT_NOT_FORCED_POWER_TRANSITION,
+ PVRSRV_POWER_TIMING_STAT_NON_PRE_DEVICE,
+ PVRSRV_POWER_TIMING_STAT_NON_PRE_SYSTEM,
+ PVRSRV_POWER_TIMING_STAT_NON_POST_DEVICE,
+ PVRSRV_POWER_TIMING_STAT_NON_POST_SYSTEM,
+ PVRSRV_POWER_TIMING_STAT_NEWLINE2,
+ PVRSRV_POWER_TIMING_STAT_FW_BOOTUP_TIME,
+ PVRSRV_POWER_TIMING_STAT_HOST_ACK
+} PVR_SRV_OTHER_STAT_TYPE;
+
+
+static IMG_CHAR* pszProcessStatFmt[PVRSRV_PROCESS_STAT_TYPE_COUNT] = {
+ "Connections %10d\n", /* PVRSRV_STAT_TYPE_CONNECTIONS */
+ "ConnectionsMax %10d\n", /* PVRSRV_STAT_TYPE_MAXCONNECTIONS */
+
+ "RenderContextOutOfMemoryEvents %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_OOMS */
+ "RenderContextPartialRenders %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_PRS */
+ "RenderContextGrows %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_GROWS */
+ "RenderContextPushGrows %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_PUSH_GROWS */
+ "RenderContextTAStores %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_TA_STORES */
+ "RenderContext3DStores %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_3D_STORES */
+ "RenderContextSHStores %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_SH_STORES */
+ "RenderContextCDMStores %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_CDM_STORES */
+ "ZSBufferRequestsByApp %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_APP */
+ "ZSBufferRequestsByFirmware %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_FW */
+ "FreeListGrowRequestsByApp %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_APP */
+ "FreeListGrowRequestsByFirmware %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_FW */
+ "FreeListInitialPages %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT */
+ "FreeListMaxPages %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_MAX_PAGES */
+ "MemoryUsageKMalloc %10d\n", /* PVRSRV_STAT_TYPE_KMALLOC */
+ "MemoryUsageKMallocMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_KMALLOC */
+ "MemoryUsageVMalloc %10d\n", /* PVRSRV_STAT_TYPE_VMALLOC */
+ "MemoryUsageVMallocMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_VMALLOC */
+ "MemoryUsageAllocPTMemoryUMA %10d\n", /* PVRSRV_STAT_TYPE_ALLOC_PAGES_PT_UMA */
+ "MemoryUsageAllocPTMemoryUMAMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_ALLOC_PAGES_PT_UMA */
+ "MemoryUsageVMapPTUMA %10d\n", /* PVRSRV_STAT_TYPE_VMAP_PT_UMA */
+ "MemoryUsageVMapPTUMAMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_VMAP_PT_UMA */
+ "MemoryUsageAllocPTMemoryLMA %10d\n", /* PVRSRV_STAT_TYPE_ALLOC_PAGES_PT_LMA */
+ "MemoryUsageAllocPTMemoryLMAMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_ALLOC_PAGES_PT_LMA */
+ "MemoryUsageIORemapPTLMA %10d\n", /* PVRSRV_STAT_TYPE_IOREMAP_PT_LMA */
+ "MemoryUsageIORemapPTLMAMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_IOREMAP_PT_LMA */
+ "MemoryUsageAllocGPUMemLMA %10d\n", /* PVRSRV_STAT_TYPE_ALLOC_LMA_PAGES */
+ "MemoryUsageAllocGPUMemLMAMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_ALLOC_LMA_PAGES */
+ "MemoryUsageAllocGPUMemUMA %10d\n", /* PVRSRV_STAT_TYPE_ALLOC_UMA_PAGES */
+ "MemoryUsageAllocGPUMemUMAMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_ALLOC_UMA_PAGES */
+ "MemoryUsageMappedGPUMemUMA/LMA %10d\n", /* PVRSRV_STAT_TYPE_MAP_UMA_LMA_PAGES */
+ "MemoryUsageMappedGPUMemUMA/LMAMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_MAP_UMA_LMA_PAGES */
+
+ //zxl: count total data
+ "MemoryUsageTotalAlloc %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC */
+ "MemoryUsageTotalAllocMax %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_ALLOC */
+ "MemoryUsageTotalMap %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP */
+ "MemoryUsageTotalMapMax %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_MAP */
+};
+
+
+/*
+ * Macro for updating maximum stat values.
+ */
+#define UPDATE_MAX_VALUE(a,b) do { if ((b) > (a)) {(a) = (b);} } while(0)
+
+/*
+ * Structures for holding statistics...
+ */
+typedef enum
+{
+ PVRSRV_STAT_STRUCTURE_PROCESS = 1,
+ PVRSRV_STAT_STRUCTURE_RENDER_CONTEXT = 2,
+ PVRSRV_STAT_STRUCTURE_MEMORY = 3,
+ PVRSRV_STAT_STRUCTURE_RIMEMORY = 4,
+ PVRSRV_STAT_STRUCTURE_POWER=5
+} PVRSRV_STAT_STRUCTURE_TYPE;
+
+#define MAX_PROC_NAME_LENGTH (32)
+
+typedef struct _PVRSRV_PROCESS_STATS_ {
+ /* Structure type (must be first!) */
+ PVRSRV_STAT_STRUCTURE_TYPE eStructureType;
+
+ /* Linked list pointers */
+ struct _PVRSRV_PROCESS_STATS_* psNext;
+ struct _PVRSRV_PROCESS_STATS_* psPrev;
+
+ /* OS level process ID */
+ IMG_PID pid;
+ IMG_UINT32 ui32RefCount;
+
+ /* Folder name used to store the statistic */
+ IMG_CHAR szFolderName[MAX_PROC_NAME_LENGTH];
+
+ /* OS specific data */
+ IMG_PVOID pvOSPidFolderData;
+ IMG_PVOID pvOSPidEntryData;
+
+ /* Stats... */
+ IMG_INT32 i32StatValue[PVRSRV_PROCESS_STAT_TYPE_COUNT];
+
+ /* Other statistics structures */
+ struct _PVRSRV_RENDER_STATS_* psRenderLiveList;
+ struct _PVRSRV_RENDER_STATS_* psRenderDeadList;
+
+ struct _PVRSRV_MEMORY_STATS_* psMemoryStats;
+ struct _PVRSRV_RI_MEMORY_STATS_* psRIMemoryStats;
+} PVRSRV_PROCESS_STATS;
+
+typedef struct _PVRSRV_RENDER_STATS_ {
+ /* Structure type (must be first!) */
+ PVRSRV_STAT_STRUCTURE_TYPE eStructureType;
+
+ /* Linked list pointers */
+ struct _PVRSRV_RENDER_STATS_* psNext;
+ struct _PVRSRV_RENDER_STATS_* psPrev;
+
+ /* OS specific data */
+ IMG_PVOID pvOSData;
+
+ /* Stats... */
+ IMG_INT32 i32StatValue[4];
+} PVRSRV_RENDER_STATS;
+
+typedef struct _PVRSRV_MEM_ALLOC_REC_
+{
+ PVRSRV_MEM_ALLOC_TYPE eAllocType;
+ IMG_UINT64 ui64Key;
+ IMG_VOID *pvCpuVAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_SIZE_T uiBytes;
+ IMG_PVOID pvPrivateData;
+
+ struct _PVRSRV_MEM_ALLOC_REC_ *psNext;
+ struct _PVRSRV_MEM_ALLOC_REC_ **ppsThis;
+} PVRSRV_MEM_ALLOC_REC;
+
+typedef struct _PVRSRV_MEMORY_STATS_ {
+ /* Structure type (must be first!) */
+ PVRSRV_STAT_STRUCTURE_TYPE eStructureType;
+
+ /* OS specific data */
+ IMG_PVOID pvOSMemEntryData;
+
+ /* Cached position in the linked list when obtaining all items... */
+ IMG_UINT32 ui32LastStatNumberRequested;
+ PVRSRV_MEM_ALLOC_REC *psLastStatMemoryRecordFound;
+
+ /* Stats... */
+ PVRSRV_MEM_ALLOC_REC *psMemoryRecords;
+} PVRSRV_MEMORY_STATS;
+
+typedef struct _PVRSRV_RI_MEMORY_STATS_ {
+ /* Structure type (must be first!) */
+ PVRSRV_STAT_STRUCTURE_TYPE eStructureType;
+
+ /* OS level process ID */
+ IMG_PID pid;
+
+ /* Handle used when querying the RI server... */
+ IMG_HANDLE *pRIHandle;
+
+ /* OS specific data */
+ IMG_PVOID pvOSRIMemEntryData;
+} PVRSRV_RI_MEMORY_STATS;
+
+typedef struct _PVRSRV_GLOBAL_MEMORY_STATS_
+{
+ IMG_UINT32 ui32MemoryUsageKMalloc;
+ IMG_UINT32 ui32MemoryUsageKMallocMax;
+ IMG_UINT32 ui32MemoryUsageVMalloc;
+ IMG_UINT32 ui32MemoryUsageVMallocMax;
+ IMG_UINT32 ui32MemoryUsageAllocPTMemoryUMA;
+ IMG_UINT32 ui32MemoryUsageAllocPTMemoryUMAMax;
+ IMG_UINT32 ui32MemoryUsageVMapPTUMA;
+ IMG_UINT32 ui32MemoryUsageVMapPTUMAMax;
+ IMG_UINT32 ui32MemoryUsageAllocPTMemoryLMA;
+ IMG_UINT32 ui32MemoryUsageAllocPTMemoryLMAMax;
+ IMG_UINT32 ui32MemoryUsageIORemapPTLMA;
+ IMG_UINT32 ui32MemoryUsageIORemapPTLMAMax;
+ IMG_UINT32 ui32MemoryUsageAllocGPUMemLMA;
+ IMG_UINT32 ui32MemoryUsageAllocGPUMemLMAMax;
+ IMG_UINT32 ui32MemoryUsageAllocGPUMemUMA;
+ IMG_UINT32 ui32MemoryUsageAllocGPUMemUMAMax;
+ IMG_UINT32 ui32MemoryUsageMappedGPUMemUMA_LMA;
+ IMG_UINT32 ui32MemoryUsageMappedGPUMemUMA_LMAMax;
+
+ //zxl: count total data
+ IMG_UINT32 ui32MemoryUsageTotalAlloc;
+ IMG_UINT32 ui32MemoryUsageTotalAllocMax;
+ IMG_UINT32 ui32MemoryUsageTotalMap;
+ IMG_UINT32 ui32MemoryUsageTotalMapMax;
+} PVRSRV_GLOBAL_MEMORY_STATS;
+
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+static IMPLEMENT_LIST_INSERT(PVRSRV_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_REMOVE(PVRSRV_MEM_ALLOC_REC)
+#endif
+
+
+/*
+ * Global Boolean to flag when the statistics are ready to monitor
+ * memory allocations.
+ */
+static IMG_BOOL bProcessStatsInitialised = IMG_FALSE;
+
+/*
+ * Linked lists for process stats. Live stats are for processes which are still running
+ * and the dead list holds those that have exited.
+ */
+static PVRSRV_PROCESS_STATS* psLiveList = IMG_NULL;
+static PVRSRV_PROCESS_STATS* psDeadList = IMG_NULL;
+
+POS_LOCK psLinkedListLock = IMG_NULL;
+
+
+/*
+ * Pointer to OS folder to hold PID folders.
+ */
+IMG_CHAR* pszOSLivePidFolderName = "pid";
+IMG_CHAR* pszOSDeadPidFolderName = "pids_retired";
+IMG_PVOID pvOSLivePidFolder = IMG_NULL;
+IMG_PVOID pvOSDeadPidFolder = IMG_NULL;
+
+/*Power Statistics List */
+
+static IMG_UINT64 ui64TotalForcedEntries=0,ui64TotalNotForcedEntries=0;
+
+static IMG_UINT64 ui64ForcedPreDevice=0, ui64ForcedPreSystem=0, ui64ForcedPostDevice=0, ui64ForcedPostSystem=0;
+static IMG_UINT64 ui64NotForcedPreDevice=0, ui64NotForcedPreSystem=0, ui64NotForcedPostDevice=0, ui64NotForcedPostSystem=0;
+
+/* global driver-data folders */
+static IMG_PVOID pvOSGlobalMemEntryRef = IMG_NULL;
+static IMG_CHAR* const pszDriverStatFilename = "driver_stats";
+static PVRSRV_GLOBAL_MEMORY_STATS gsGlobalStats;
+
+#define HASH_INITIAL_SIZE 5
+static HASH_TABLE* gpsTrackingTable;
+
+static IMG_BOOL
+_PVRSRVGetGlobalMemStat(IMG_PVOID pvStatPtr,
+ IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData,
+ IMG_CHAR** ppszStatFmtText);
+
+
+IMG_VOID InsertPowerTimeStatistic(PVRSRV_POWER_ENTRY_TYPE bType,
+ IMG_INT32 i32CurrentState, IMG_INT32 i32NextState,
+ IMG_UINT64 ui64SysStartTime, IMG_UINT64 ui64SysEndTime,
+ IMG_UINT64 ui64DevStartTime, IMG_UINT64 ui64DevEndTime,
+ IMG_BOOL bForced)
+{
+ IMG_UINT64 ui64Device;
+ IMG_UINT64 ui64System;
+
+ if (i32CurrentState==i32NextState) return ;
+
+ ui64Device=ui64DevEndTime-ui64DevStartTime;
+ ui64System=ui64SysEndTime-ui64SysStartTime;
+
+ if (bForced)
+ {
+ ui64TotalForcedEntries++;
+ if (bType==PVRSRV_POWER_ENTRY_TYPE_POST)
+ {
+ ui64ForcedPostDevice+=ui64Device;
+ ui64ForcedPostSystem+=ui64System;
+ }
+ else
+ {
+ ui64ForcedPreDevice+=ui64Device;
+ ui64ForcedPreSystem+=ui64System;
+ }
+ }
+ else
+ {
+ ui64TotalNotForcedEntries++;
+ if (bType==PVRSRV_POWER_ENTRY_TYPE_POST)
+ {
+ ui64NotForcedPostDevice+=ui64Device;
+ ui64NotForcedPostSystem+=ui64System;
+ }
+ else
+ {
+ ui64NotForcedPreDevice+=ui64Device;
+ ui64NotForcedPreSystem+=ui64System;
+ }
+ }
+
+ return;
+}
+
+/*************************************************************************/ /*!
+@Function _RemoveRenderStatsFromList
+@Description Detaches a process from either the live or dead list.
+@Input psProcessStats Process to remove the stats from.
+@Input psRenderStats Render stats to remove.
+*/ /**************************************************************************/
+static IMG_VOID
+_RemoveRenderStatsFromList(PVRSRV_PROCESS_STATS* psProcessStats,
+ PVRSRV_RENDER_STATS* psRenderStats)
+{
+ PVR_ASSERT(psProcessStats != IMG_NULL);
+ PVR_ASSERT(psRenderStats != IMG_NULL);
+
+ /* Remove the item from the linked lists... */
+ if (psProcessStats->psRenderLiveList == psRenderStats)
+ {
+ psProcessStats->psRenderLiveList = psRenderStats->psNext;
+
+ if (psProcessStats->psRenderLiveList != IMG_NULL)
+ {
+ psProcessStats->psRenderLiveList->psPrev = IMG_NULL;
+ }
+ }
+ else if (psProcessStats->psRenderDeadList == psRenderStats)
+ {
+ psProcessStats->psRenderDeadList = psRenderStats->psNext;
+
+ if (psProcessStats->psRenderDeadList != IMG_NULL)
+ {
+ psProcessStats->psRenderDeadList->psPrev = IMG_NULL;
+ }
+ }
+ else
+ {
+ PVRSRV_RENDER_STATS* psNext = psRenderStats->psNext;
+ PVRSRV_RENDER_STATS* psPrev = psRenderStats->psPrev;
+
+ if (psRenderStats->psNext != IMG_NULL)
+ {
+ psRenderStats->psNext->psPrev = psPrev;
+ }
+ if (psRenderStats->psPrev != IMG_NULL)
+ {
+ psRenderStats->psPrev->psNext = psNext;
+ }
+ }
+
+ /* Reset the pointers in this cell, as it is not attached to anything */
+ psRenderStats->psNext = IMG_NULL;
+ psRenderStats->psPrev = IMG_NULL;
+} /* _RemoveRenderStatsFromList */
+
+
+/*************************************************************************/ /*!
+@Function _DestoryRenderStat
+@Description Frees memory and resources held by a render statistic.
+@Input psRenderStats Render stats to destroy.
+*/ /**************************************************************************/
+static IMG_VOID
+_DestoryRenderStat(PVRSRV_RENDER_STATS* psRenderStats)
+{
+ PVR_ASSERT(psRenderStats != IMG_NULL);
+
+ /* Remove the statistic from the OS... */
+ OSRemoveStatisticEntry(psRenderStats->pvOSData);
+
+ /* Free the memory... */
+ OSFreeMem(psRenderStats);
+} /* _DestoryRenderStat */
+
+
+/*************************************************************************/ /*!
+@Function _FindProcessStatsInLiveList
+@Description Searches the Live Process List for a statistics structure that
+ matches the PID given.
+@Input pid Process to search for.
+@Return Pointer to stats structure for the process.
+*/ /**************************************************************************/
+static PVRSRV_PROCESS_STATS*
+_FindProcessStatsInLiveList(IMG_PID pid)
+{
+ PVRSRV_PROCESS_STATS* psProcessStats = psLiveList;
+
+ while (psProcessStats != IMG_NULL)
+ {
+ if (psProcessStats->pid == pid)
+ {
+ return psProcessStats;
+ }
+
+ psProcessStats = psProcessStats->psNext;
+ }
+
+ return IMG_NULL;
+} /* _FindProcessStatsInLiveList */
+
+
+/*************************************************************************/ /*!
+@Function _FindProcessStatsInDeadList
+@Description Searches the Dead Process List for a statistics structure that
+ matches the PID given.
+@Input pid Process to search for.
+@Return Pointer to stats structure for the process.
+*/ /**************************************************************************/
+static PVRSRV_PROCESS_STATS*
+_FindProcessStatsInDeadList(IMG_PID pid)
+{
+ PVRSRV_PROCESS_STATS* psProcessStats = psDeadList;
+
+ while (psProcessStats != IMG_NULL)
+ {
+ if (psProcessStats->pid == pid)
+ {
+ return psProcessStats;
+ }
+
+ psProcessStats = psProcessStats->psNext;
+ }
+
+ return IMG_NULL;
+} /* _FindProcessStatsInDeadList */
+
+
+/*************************************************************************/ /*!
+@Function _FindProcessStats
+@Description Searches the Live and Dead Process Lists for a statistics
+ structure that matches the PID given.
+@Input pid Process to search for.
+@Return Pointer to stats structure for the process.
+*/ /**************************************************************************/
+static PVRSRV_PROCESS_STATS*
+_FindProcessStats(IMG_PID pid)
+{
+ PVRSRV_PROCESS_STATS* psProcessStats = _FindProcessStatsInLiveList(pid);
+
+ if (psProcessStats == IMG_NULL)
+ {
+ psProcessStats = _FindProcessStatsInDeadList(pid);
+ }
+
+ return psProcessStats;
+} /* _FindProcessStats */
+
+
+/*************************************************************************/ /*!
+@Function _AddProcessStatsToFrontOfLiveList
+@Description Add a statistic to the live list head.
+@Input psProcessStats Process stats to add.
+*/ /**************************************************************************/
+static IMG_VOID
+_AddProcessStatsToFrontOfLiveList(PVRSRV_PROCESS_STATS* psProcessStats)
+{
+ PVR_ASSERT(psProcessStats != IMG_NULL);
+
+ if (psLiveList != IMG_NULL)
+ {
+ psLiveList->psPrev = psProcessStats;
+ psProcessStats->psNext = psLiveList;
+ }
+
+ psLiveList = psProcessStats;
+} /* _AddProcessStatsToFrontOfLiveList */
+
+
+/*************************************************************************/ /*!
+@Function _AddProcessStatsToFrontOfDeadList
+@Description Add a statistic to the dead list head.
+@Input psProcessStats Process stats to add.
+*/ /**************************************************************************/
+static IMG_VOID
+_AddProcessStatsToFrontOfDeadList(PVRSRV_PROCESS_STATS* psProcessStats)
+{
+ PVR_ASSERT(psProcessStats != IMG_NULL);
+
+ if (psDeadList != IMG_NULL)
+ {
+ psDeadList->psPrev = psProcessStats;
+ psProcessStats->psNext = psDeadList;
+ }
+
+ psDeadList = psProcessStats;
+} /* _AddProcessStatsToFrontOfDeadList */
+
+
+/*************************************************************************/ /*!
+@Function _RemoveProcessStatsFromList
+@Description Detaches a process from either the live or dead list.
+@Input psProcessStats Process stats to remove.
+*/ /**************************************************************************/
+static IMG_VOID
+_RemoveProcessStatsFromList(PVRSRV_PROCESS_STATS* psProcessStats)
+{
+ PVR_ASSERT(psProcessStats != IMG_NULL);
+
+ /* Remove the item from the linked lists... */
+ if (psLiveList == psProcessStats)
+ {
+ psLiveList = psProcessStats->psNext;
+
+ if (psLiveList != IMG_NULL)
+ {
+ psLiveList->psPrev = IMG_NULL;
+ }
+ }
+ else if (psDeadList == psProcessStats)
+ {
+ psDeadList = psProcessStats->psNext;
+
+ if (psDeadList != IMG_NULL)
+ {
+ psDeadList->psPrev = IMG_NULL;
+ }
+ }
+ else
+ {
+ PVRSRV_PROCESS_STATS* psNext = psProcessStats->psNext;
+ PVRSRV_PROCESS_STATS* psPrev = psProcessStats->psPrev;
+
+ if (psProcessStats->psNext != IMG_NULL)
+ {
+ psProcessStats->psNext->psPrev = psPrev;
+ }
+ if (psProcessStats->psPrev != IMG_NULL)
+ {
+ psProcessStats->psPrev->psNext = psNext;
+ }
+ }
+
+ /* Reset the pointers in this cell, as it is not attached to anything */
+ psProcessStats->psNext = IMG_NULL;
+ psProcessStats->psPrev = IMG_NULL;
+} /* _RemoveProcessStatsFromList */
+
+
+/*************************************************************************/ /*!
+@Function _CreateOSStatisticEntries
+@Description Create all OS entries for this statistic.
+@Input psProcessStats Process stats to destroy.
+@Input pvOSPidFolder Pointer to OS folder to place the entrys in.
+*/ /**************************************************************************/
+static IMG_VOID
+_CreateOSStatisticEntries(PVRSRV_PROCESS_STATS* psProcessStats,
+ IMG_PVOID pvOSPidFolder)
+{
+ PVR_ASSERT(psProcessStats != IMG_NULL);
+
+ psProcessStats->pvOSPidFolderData = OSCreateStatisticFolder(psProcessStats->szFolderName, pvOSPidFolder);
+ psProcessStats->pvOSPidEntryData = OSCreateStatisticEntry("process_stats",
+ psProcessStats->pvOSPidFolderData,
+ PVRSRVStatsObtainElement,
+ (IMG_PVOID) psProcessStats);
+
+ if (pvOSPowerStatsEntryData==NULL)
+ {
+ pvOSPowerStatsEntryData = OSCreateStatisticEntry("power_timings_stats",
+ NULL,
+ PVRSRVPowerStatsObtainElement,
+ (IMG_PVOID) psProcessStats);
+ }
+
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+ psProcessStats->psMemoryStats->pvOSMemEntryData = OSCreateStatisticEntry("mem_area",
+ psProcessStats->pvOSPidFolderData,
+ PVRSRVStatsObtainElement,
+ (IMG_PVOID) psProcessStats->psMemoryStats);
+#endif
+
+#if defined(PVR_RI_DEBUG)
+ psProcessStats->psRIMemoryStats->pvOSRIMemEntryData = OSCreateStatisticEntry("ri_mem_area",
+ psProcessStats->pvOSPidFolderData,
+ PVRSRVStatsObtainElement,
+ (IMG_PVOID) psProcessStats->psRIMemoryStats);
+#endif
+} /* _CreateOSStatisticEntries */
+
+
+/*************************************************************************/ /*!
+@Function _RemoveOSStatisticEntries
+@Description Removed all OS entries used by this statistic.
+@Input psProcessStats Process stats to destroy.
+*/ /**************************************************************************/
+static IMG_VOID
+_RemoveOSStatisticEntries(PVRSRV_PROCESS_STATS* psProcessStats)
+{
+ PVR_ASSERT(psProcessStats != IMG_NULL);
+
+#if defined(PVR_RI_DEBUG)
+ OSRemoveStatisticEntry(psProcessStats->psRIMemoryStats->pvOSRIMemEntryData);
+#endif
+
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+ OSRemoveStatisticEntry(psProcessStats->psMemoryStats->pvOSMemEntryData);
+#endif
+
+ OSRemoveStatisticEntry(psProcessStats->pvOSPidEntryData);
+ OSRemoveStatisticFolder(psProcessStats->pvOSPidFolderData);
+} /* _RemoveOSStatisticEntries */
+
+
+/*************************************************************************/ /*!
+@Function _DestoryProcessStat
+@Description Frees memory and resources held by a process statistic.
+@Input psProcessStats Process stats to destroy.
+*/ /**************************************************************************/
+static IMG_VOID
+_DestoryProcessStat(PVRSRV_PROCESS_STATS* psProcessStats)
+{
+ PVR_ASSERT(psProcessStats != IMG_NULL);
+
+ /* Remove this statistic from the OS... */
+ _RemoveOSStatisticEntries(psProcessStats);
+
+ /* Free the live and dead render statistic lists... */
+ while (psProcessStats->psRenderLiveList != IMG_NULL)
+ {
+ PVRSRV_RENDER_STATS* psRenderStats = psProcessStats->psRenderLiveList;
+
+ _RemoveRenderStatsFromList(psProcessStats, psRenderStats);
+ _DestoryRenderStat(psRenderStats);
+ }
+
+ while (psProcessStats->psRenderDeadList != IMG_NULL)
+ {
+ PVRSRV_RENDER_STATS* psRenderStats = psProcessStats->psRenderDeadList;
+
+ _RemoveRenderStatsFromList(psProcessStats, psRenderStats);
+ _DestoryRenderStat(psRenderStats);
+ }
+
+ /* Free the memory statistics... */
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+ while (psProcessStats->psMemoryStats->psMemoryRecords)
+ {
+ List_PVRSRV_MEM_ALLOC_REC_Remove(psProcessStats->psMemoryStats->psMemoryRecords);
+ }
+ OSFreeMem(psProcessStats->psMemoryStats);
+#endif
+
+ /* Free the memory... */
+ OSFreeMem(psProcessStats);
+} /* _DestoryProcessStat */
+
+
+/*************************************************************************/ /*!
+@Function _CompressMemoryUsage
+@Description Reduces memory usage by deleting old statistics data.
+ This function requires that the list lock is not held!
+*/ /**************************************************************************/
+static IMG_VOID
+_CompressMemoryUsage(IMG_VOID)
+{
+ PVRSRV_PROCESS_STATS* psProcessStats;
+ PVRSRV_PROCESS_STATS* psProcessStatsToBeFreed;
+ IMG_UINT32 ui32ItemsRemaining;
+
+ /*
+ * We hold the lock whilst checking the list, but we'll release it
+ * before freeing memory (as that will require the lock too)!
+ */
+ OSLockAcquire(psLinkedListLock);
+
+ /* Check that the dead list is not bigger than the max size... */
+ psProcessStats = psDeadList;
+ psProcessStatsToBeFreed = IMG_NULL;
+ ui32ItemsRemaining = MAX_DEAD_LIST_PROCESSES;
+
+ while (psProcessStats != IMG_NULL && ui32ItemsRemaining > 0)
+ {
+ ui32ItemsRemaining--;
+ if (ui32ItemsRemaining == 0)
+ {
+ /* This is the last allowed process, cut the linked list here! */
+ psProcessStatsToBeFreed = psProcessStats->psNext;
+ psProcessStats->psNext = IMG_NULL;
+ }
+ else
+ {
+ psProcessStats = psProcessStats->psNext;
+ }
+ }
+
+ OSLockRelease(psLinkedListLock);
+
+ /* Any processes stats remaining will need to be destroyed... */
+ while (psProcessStatsToBeFreed != IMG_NULL)
+ {
+ PVRSRV_PROCESS_STATS* psNextProcessStats = psProcessStatsToBeFreed->psNext;
+
+ psProcessStatsToBeFreed->psNext = IMG_NULL;
+ _DestoryProcessStat(psProcessStatsToBeFreed);
+
+ psProcessStatsToBeFreed = psNextProcessStats;
+ }
+} /* _CompressMemoryUsage */
+
+
+/* These functions move the process stats from the living to the dead list.
+ * _MoveProcessToDeadList moves the entry in the global lists and
+ * it needs to be protected by psLinkedListLock.
+ * _MoveProcessToDeadListDebugFS performs the OS calls and it
+ * shouldn't be used under psLinkedListLock because this could generate a
+ * lockdep warning. */
+static IMG_VOID
+_MoveProcessToDeadList(PVRSRV_PROCESS_STATS* psProcessStats)
+{
+ /* Take the element out of the live list and append to the dead list... */
+ _RemoveProcessStatsFromList(psProcessStats);
+ _AddProcessStatsToFrontOfDeadList(psProcessStats);
+} /* _MoveProcessToDeadList */
+
+static IMG_VOID
+_MoveProcessToDeadListDebugFS(PVRSRV_PROCESS_STATS* psProcessStats)
+{
+ /* Transfer the OS entries to the folder for dead processes... */
+ _RemoveOSStatisticEntries(psProcessStats);
+ _CreateOSStatisticEntries(psProcessStats, pvOSDeadPidFolder);
+} /* _MoveProcessToDeadListDebugFS */
+
+
+/*************************************************************************/ /*!
+@Function PVRSRVStatsInitialise
+@Description Entry point for initialising the statistics module.
+@Return Standard PVRSRV_ERROR error code.
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVStatsInitialise(IMG_VOID)
+{
+ PVRSRV_ERROR error;
+
+ PVR_ASSERT(psLiveList == IMG_NULL);
+ PVR_ASSERT(psDeadList == IMG_NULL);
+ PVR_ASSERT(psLinkedListLock == IMG_NULL);
+ PVR_ASSERT(gpsTrackingTable == IMG_NULL);
+ PVR_ASSERT(bProcessStatsInitialised == IMG_FALSE);
+
+ /* We need a lock to protect the linked lists... */
+ error = OSLockCreate(&psLinkedListLock, LOCK_TYPE_NONE);
+
+ /* Create a pid folders for putting the PID files in... */
+ pvOSLivePidFolder = OSCreateStatisticFolder(pszOSLivePidFolderName, IMG_NULL);
+ pvOSDeadPidFolder = OSCreateStatisticFolder(pszOSDeadPidFolderName, IMG_NULL);
+
+ /* for global memory stat */
+ pvOSGlobalMemEntryRef = OSCreateStatisticEntry(pszDriverStatFilename,
+ IMG_NULL,
+ _PVRSRVGetGlobalMemStat,
+ IMG_NULL);
+
+ OSMemSet(&gsGlobalStats, 0, sizeof(gsGlobalStats));
+
+ gpsTrackingTable = HASH_Create(HASH_INITIAL_SIZE);
+
+ /* Flag that we are ready to start monitoring memory allocations. */
+ bProcessStatsInitialised = IMG_TRUE;
+
+ return error;
+} /* PVRSRVStatsInitialise */
+
+
+/*************************************************************************/ /*!
+@Function PVRSRVStatsDestroy
+@Description Method for destroying the statistics module data.
+*/ /**************************************************************************/
+IMG_VOID
+PVRSRVStatsDestroy(IMG_VOID)
+{
+ PVR_ASSERT(bProcessStatsInitialised == IMG_TRUE);
+
+ if (pvOSPowerStatsEntryData!=NULL)
+ {
+ OSRemoveStatisticEntry(pvOSPowerStatsEntryData);
+ pvOSPowerStatsEntryData=NULL;
+ }
+
+ if (pvOSGlobalMemEntryRef != NULL)
+ {
+ OSRemoveStatisticEntry(pvOSGlobalMemEntryRef);
+ pvOSGlobalMemEntryRef = IMG_NULL;
+ }
+
+ /* Stop monitoring memory allocations... */
+ bProcessStatsInitialised = IMG_FALSE;
+
+ /* Destroy the lock... */
+ if (psLinkedListLock != IMG_NULL)
+ {
+ OSLockDestroy(psLinkedListLock);
+ psLinkedListLock = IMG_NULL;
+ }
+
+ /* Free the live and dead lists... */
+ while (psLiveList != IMG_NULL)
+ {
+ PVRSRV_PROCESS_STATS* psProcessStats = psLiveList;
+
+ _RemoveProcessStatsFromList(psProcessStats);
+ _DestoryProcessStat(psProcessStats);
+ }
+
+ while (psDeadList != IMG_NULL)
+ {
+ PVRSRV_PROCESS_STATS* psProcessStats = psDeadList;
+
+ _RemoveProcessStatsFromList(psProcessStats);
+ _DestoryProcessStat(psProcessStats);
+ }
+
+ /* Remove the OS folders used by the PID folders... */
+ OSRemoveStatisticFolder(pvOSLivePidFolder);
+ pvOSLivePidFolder = IMG_NULL;
+ OSRemoveStatisticFolder(pvOSDeadPidFolder);
+ pvOSDeadPidFolder = IMG_NULL;
+
+ if (gpsTrackingTable != IMG_NULL)
+ {
+ HASH_Delete(gpsTrackingTable);
+ }
+
+} /* PVRSRVStatsDestroy */
+
+
+
+static void _decrease_global_stat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_SIZE_T uiBytes)
+{
+ switch (eAllocType)
+ {
+ case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
+ if (gsGlobalStats.ui32MemoryUsageKMalloc > uiBytes)
+ {
+ gsGlobalStats.ui32MemoryUsageKMalloc -= uiBytes;
+ }
+ else
+ {
+ gsGlobalStats.ui32MemoryUsageKMalloc = 0;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
+ if (gsGlobalStats.ui32MemoryUsageVMalloc > uiBytes)
+ {
+ gsGlobalStats.ui32MemoryUsageVMalloc -= uiBytes;
+ }
+ else
+ {
+ gsGlobalStats.ui32MemoryUsageVMalloc = 0;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
+ if (gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA > uiBytes)
+ {
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA -= uiBytes;
+ }
+ else
+ {
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA = 0;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
+ if (gsGlobalStats.ui32MemoryUsageVMapPTUMA > uiBytes)
+ {
+ gsGlobalStats.ui32MemoryUsageVMapPTUMA -= uiBytes;
+ }
+ else
+ {
+ gsGlobalStats.ui32MemoryUsageVMapPTUMA = 0;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
+ if (gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA > uiBytes)
+ {
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA -= uiBytes;
+ }
+ else
+ {
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA = 0;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
+ if (gsGlobalStats.ui32MemoryUsageIORemapPTLMA > uiBytes)
+ {
+ gsGlobalStats.ui32MemoryUsageIORemapPTLMA -= uiBytes;
+ }
+ else
+ {
+ gsGlobalStats.ui32MemoryUsageIORemapPTLMA = 0;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
+ if (gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA > uiBytes)
+ {
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA -= uiBytes;
+ }
+ else
+ {
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA = 0;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
+ if (gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA > uiBytes)
+ {
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA -= uiBytes;
+ }
+ else
+ {
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA = 0;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
+ if (gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA > uiBytes)
+ {
+ gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA -= uiBytes;
+ }
+ else
+ {
+ gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA = 0;
+ }
+ break;
+
+ default:
+ PVR_ASSERT(0);
+ break;
+ }
+ //Count total data
+ gsGlobalStats.ui32MemoryUsageTotalAlloc = gsGlobalStats.ui32MemoryUsageKMalloc + gsGlobalStats.ui32MemoryUsageVMalloc +\
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA + gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA +\
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA + gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA;
+
+ gsGlobalStats.ui32MemoryUsageTotalMap = gsGlobalStats.ui32MemoryUsageVMapPTUMA + gsGlobalStats.ui32MemoryUsageIORemapPTLMA +\
+ gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA;
+}
+
+
+static void _increase_global_stat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_SIZE_T uiBytes)
+{
+ switch (eAllocType)
+ {
+ case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
+ gsGlobalStats.ui32MemoryUsageKMalloc += uiBytes;
+ if (gsGlobalStats.ui32MemoryUsageKMallocMax < gsGlobalStats.ui32MemoryUsageKMalloc)
+ {
+ gsGlobalStats.ui32MemoryUsageKMallocMax = gsGlobalStats.ui32MemoryUsageKMalloc;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
+ gsGlobalStats.ui32MemoryUsageVMalloc += uiBytes;
+ if (gsGlobalStats.ui32MemoryUsageVMallocMax < gsGlobalStats.ui32MemoryUsageVMalloc)
+ {
+ gsGlobalStats.ui32MemoryUsageVMallocMax = gsGlobalStats.ui32MemoryUsageVMalloc;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA += uiBytes;
+ if (gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMAMax < gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA)
+ {
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMAMax = gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
+ gsGlobalStats.ui32MemoryUsageVMapPTUMA += uiBytes;
+ if (gsGlobalStats.ui32MemoryUsageVMapPTUMAMax < gsGlobalStats.ui32MemoryUsageVMapPTUMA)
+ {
+ gsGlobalStats.ui32MemoryUsageVMapPTUMAMax = gsGlobalStats.ui32MemoryUsageVMapPTUMA;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA += uiBytes;
+ if (gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMAMax < gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA)
+ {
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMAMax = gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
+ gsGlobalStats.ui32MemoryUsageIORemapPTLMA += uiBytes;
+ if (gsGlobalStats.ui32MemoryUsageIORemapPTLMAMax < gsGlobalStats.ui32MemoryUsageIORemapPTLMA)
+ {
+ gsGlobalStats.ui32MemoryUsageIORemapPTLMAMax = gsGlobalStats.ui32MemoryUsageIORemapPTLMA;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA += uiBytes;
+ if (gsGlobalStats.ui32MemoryUsageAllocGPUMemLMAMax < gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA)
+ {
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemLMAMax = gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA += uiBytes;
+ if (gsGlobalStats.ui32MemoryUsageAllocGPUMemUMAMax < gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA)
+ {
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemUMAMax = gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA;
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
+ gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA += uiBytes;
+ if (gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMAMax < gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA)
+ {
+ gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMAMax = gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA;
+ }
+ break;
+
+ default:
+ PVR_ASSERT(0);
+ break;
+ }
+ //Count total data
+ gsGlobalStats.ui32MemoryUsageTotalAlloc = gsGlobalStats.ui32MemoryUsageKMalloc + gsGlobalStats.ui32MemoryUsageVMalloc +\
+ gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA + gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA +\
+ gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA + gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA;
+ UPDATE_MAX_VALUE(gsGlobalStats.ui32MemoryUsageTotalAllocMax,gsGlobalStats.ui32MemoryUsageTotalAlloc);
+
+ gsGlobalStats.ui32MemoryUsageTotalMap = gsGlobalStats.ui32MemoryUsageVMapPTUMA + gsGlobalStats.ui32MemoryUsageIORemapPTLMA +\
+ gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA;
+ UPDATE_MAX_VALUE(gsGlobalStats.ui32MemoryUsageTotalMapMax,gsGlobalStats.ui32MemoryUsageTotalMap);
+}
+
+
+/*************************************************************************/ /*!
+@Function PVRSRVStatsRegisterProcess
+@Description Register a process into the list statistics list.
+@Output phProcessStats Handle to the process to be used to deregister.
+@Return Standard PVRSRV_ERROR error code.
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVStatsRegisterProcess(IMG_HANDLE* phProcessStats)
+{
+ PVRSRV_PROCESS_STATS* psProcessStats;
+ IMG_PID currentPid = OSGetCurrentProcessIDKM();
+ IMG_BOOL bMoveProcess = IMG_FALSE;
+
+ PVR_ASSERT(phProcessStats != IMG_NULL);
+
+ /* Check the PID has not already moved to the dead list... */
+ OSLockAcquire(psLinkedListLock);
+ psProcessStats = _FindProcessStatsInDeadList(currentPid);
+ if (psProcessStats != IMG_NULL)
+ {
+ /* Move it back onto the live list! */
+ _RemoveProcessStatsFromList(psProcessStats);
+ _AddProcessStatsToFrontOfLiveList(psProcessStats);
+
+ /* we can perform the OS operation out of lock */
+ bMoveProcess = IMG_TRUE;
+ }
+ else
+ {
+ /* Check the PID is not already registered in the live list... */
+ psProcessStats = _FindProcessStatsInLiveList(currentPid);
+ }
+
+ /* If the PID is on the live list then just increment the ref count and return... */
+ if (psProcessStats != IMG_NULL)
+ {
+ psProcessStats->ui32RefCount++;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS] = psProcessStats->ui32RefCount;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_CONNECTIONS],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS]);
+ OSLockRelease(psLinkedListLock);
+
+ *phProcessStats = psProcessStats;
+
+ /* Check if we need to perform any OS operation */
+ if (bMoveProcess)
+ {
+ /* Transfer the OS entries back to the folder for live processes... */
+ _RemoveOSStatisticEntries(psProcessStats);
+ _CreateOSStatisticEntries(psProcessStats, pvOSLivePidFolder);
+ }
+
+ return PVRSRV_OK;
+ }
+ OSLockRelease(psLinkedListLock);
+
+ /* Allocate a new node structure and initialise it... */
+ psProcessStats = OSAllocMem(sizeof(PVRSRV_PROCESS_STATS));
+ if (psProcessStats == IMG_NULL)
+ {
+ *phProcessStats = 0;
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psProcessStats, 0, sizeof(PVRSRV_PROCESS_STATS));
+
+ psProcessStats->eStructureType = PVRSRV_STAT_STRUCTURE_PROCESS;
+ psProcessStats->pid = currentPid;
+ psProcessStats->ui32RefCount = 1;
+
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS] = 1;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_CONNECTIONS] = 1;
+
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+ psProcessStats->psMemoryStats = OSAllocMem(sizeof(PVRSRV_MEMORY_STATS));
+ if (psProcessStats->psMemoryStats == IMG_NULL)
+ {
+ OSFreeMem(psProcessStats);
+ *phProcessStats = 0;
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psProcessStats->psMemoryStats, 0, sizeof(PVRSRV_MEMORY_STATS));
+ psProcessStats->psMemoryStats->eStructureType = PVRSRV_STAT_STRUCTURE_MEMORY;
+#endif
+
+#if defined(PVR_RI_DEBUG)
+ psProcessStats->psRIMemoryStats = OSAllocMem(sizeof(PVRSRV_RI_MEMORY_STATS));
+ if (psProcessStats->psRIMemoryStats == IMG_NULL)
+ {
+ OSFreeMem(psProcessStats->psMemoryStats);
+ OSFreeMem(psProcessStats);
+ *phProcessStats = 0;
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psProcessStats->psRIMemoryStats, 0, sizeof(PVRSRV_RI_MEMORY_STATS));
+ psProcessStats->psRIMemoryStats->eStructureType = PVRSRV_STAT_STRUCTURE_RIMEMORY;
+ psProcessStats->psRIMemoryStats->pid = currentPid;
+#endif
+
+ /* Add it to the live list... */
+ OSLockAcquire(psLinkedListLock);
+ _AddProcessStatsToFrontOfLiveList(psProcessStats);
+ OSLockRelease(psLinkedListLock);
+
+ /* Create the process stat in the OS... */
+ OSSNPrintf(psProcessStats->szFolderName, sizeof(psProcessStats->szFolderName),
+ "%d", currentPid);
+ _CreateOSStatisticEntries(psProcessStats, pvOSLivePidFolder);
+
+ /* Done */
+ *phProcessStats = (IMG_HANDLE) psProcessStats;
+
+ return PVRSRV_OK;
+} /* PVRSRVStatsRegisterProcess */
+
+
+/*************************************************************************/ /*!
+@Function PVRSRVStatsDeregisterProcess
+@Input hProcessStats Handle to the process returned when registered.
+@Description Method for destroying the statistics module data.
+*/ /**************************************************************************/
+IMG_VOID
+PVRSRVStatsDeregisterProcess(IMG_HANDLE hProcessStats)
+{
+ IMG_BOOL bMoveProcess = IMG_FALSE;
+
+ if (hProcessStats != 0)
+ {
+ PVRSRV_PROCESS_STATS* psProcessStats = (PVRSRV_PROCESS_STATS*) hProcessStats;
+
+ /* Lower the reference count, if zero then move it to the dead list */
+ OSLockAcquire(psLinkedListLock);
+ if (psProcessStats->ui32RefCount > 0)
+ {
+ psProcessStats->ui32RefCount--;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS] = psProcessStats->ui32RefCount;
+
+ if (psProcessStats->ui32RefCount == 0)
+ {
+ _MoveProcessToDeadList(psProcessStats);
+ bMoveProcess = IMG_TRUE;
+ }
+ }
+ OSLockRelease(psLinkedListLock);
+
+ /* The OS calls need to be performed without psLinkedListLock */
+ if (bMoveProcess == IMG_TRUE)
+ {
+ _MoveProcessToDeadListDebugFS(psProcessStats);
+ }
+
+ /* Check if the dead list needs to be reduced */
+ _CompressMemoryUsage();
+ }
+} /* PVRSRVStatsDeregisterProcess */
+
+
+IMG_VOID
+PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_VOID *pvCpuVAddr,
+ IMG_CPU_PHYADDR sCpuPAddr,
+ IMG_SIZE_T uiBytes,
+ IMG_PVOID pvPrivateData)
+{
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+ IMG_PID currentPid = OSGetCurrentProcessIDKM();
+ PVRSRV_MEM_ALLOC_REC* psRecord = IMG_NULL;
+ PVRSRV_PROCESS_STATS* psProcessStats;
+ PVRSRV_MEMORY_STATS* psMemoryStats;
+
+ /* Don't do anything if we are not initialised or we are shutting down! */
+ if (!bProcessStatsInitialised)
+ {
+ return;
+ }
+
+ /*
+ * To prevent a recursive loop, we make the memory allocations
+ * for our memstat records via OSAllocMemstatMem(), which does not try to
+ * create a memstat record entry..
+ */
+
+ /* Allocate the memory record... */
+ psRecord = OSAllocMemstatMem(sizeof(PVRSRV_MEM_ALLOC_REC));
+ if (psRecord == IMG_NULL)
+ {
+ return;
+ }
+
+ OSMemSet(psRecord, 0, sizeof(PVRSRV_MEM_ALLOC_REC));
+ psRecord->eAllocType = eAllocType;
+ psRecord->pvCpuVAddr = pvCpuVAddr;
+ psRecord->sCpuPAddr.uiAddr = sCpuPAddr.uiAddr;
+ psRecord->uiBytes = uiBytes;
+ psRecord->pvPrivateData = pvPrivateData;
+
+ /* Lock while we find the correct process... */
+ OSLockAcquire(psLinkedListLock);
+
+ psProcessStats = _FindProcessStats(currentPid);
+ if (psProcessStats == IMG_NULL)
+ {
+ OSLockRelease(psLinkedListLock);
+ if (psRecord != IMG_NULL)
+ {
+ OSFreeMemstatMem(psRecord);
+ }
+ return;
+ }
+ psMemoryStats = psProcessStats->psMemoryStats;
+
+ _increase_global_stat(eAllocType, uiBytes);
+
+ /* Insert the memory record... */
+ if (psRecord != IMG_NULL)
+ {
+ psMemoryStats->ui32LastStatNumberRequested = 0;
+ psMemoryStats->psLastStatMemoryRecordFound = IMG_NULL;
+ List_PVRSRV_MEM_ALLOC_REC_Insert(&psMemoryStats->psMemoryRecords, psRecord);
+ }
+
+ /* Update the memory watermarks... */
+ switch (eAllocType)
+ {
+ case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
+ {
+ if (psRecord != IMG_NULL)
+ {
+ if (pvCpuVAddr == IMG_NULL)
+ {
+ return;
+ }
+ psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
+ }
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_KMALLOC],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
+ {
+ if (psRecord != IMG_NULL)
+ {
+ if (pvCpuVAddr == IMG_NULL)
+ {
+ return;
+ }
+ psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
+ }
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_VMALLOC],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC]);
+
+
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
+ {
+ if (psRecord != IMG_NULL)
+ {
+ if (pvCpuVAddr == IMG_NULL)
+ {
+ return;
+ }
+ psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
+ }
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_PAGES_PT_UMA],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
+ {
+ if (psRecord != IMG_NULL)
+ {
+ if (pvCpuVAddr == IMG_NULL)
+ {
+ return;
+ }
+ psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
+ }
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_VMAP_PT_UMA],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
+ {
+ if (psRecord != IMG_NULL)
+ {
+ psRecord->ui64Key = sCpuPAddr.uiAddr;
+ }
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_PAGES_PT_LMA],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
+ {
+ if (psRecord != IMG_NULL)
+ {
+ if (pvCpuVAddr == IMG_NULL)
+ {
+ return;
+ }
+ psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
+ }
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_IOREMAP_PT_LMA],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
+ {
+ if (psRecord != IMG_NULL)
+ {
+ psRecord->ui64Key = sCpuPAddr.uiAddr;
+ }
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_LMA_PAGES],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
+ {
+ if (psRecord != IMG_NULL)
+ {
+ psRecord->ui64Key = sCpuPAddr.uiAddr;
+ }
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_UMA_PAGES],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES]);
+ }
+ break;
+ case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
+ {
+ if (psRecord != IMG_NULL)
+ {
+ if (pvCpuVAddr == IMG_NULL)
+ {
+ return;
+ }
+ psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
+ }
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_MAP_UMA_LMA_PAGES],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES]);
+ }
+ break;
+ default:
+ {
+ PVR_ASSERT(0);
+ }
+ break;
+ }
+
+//Count total data
+psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC] += psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] + PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES];
+UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_ALLOC],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC]);
+
+psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP] += psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA];
+UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_MAP],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP]);
+
+ OSLockRelease(psLinkedListLock);
+#else
+PVR_UNREFERENCED_PARAMETER(eAllocType);
+PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+PVR_UNREFERENCED_PARAMETER(sCpuPAddr);
+PVR_UNREFERENCED_PARAMETER(uiBytes);
+PVR_UNREFERENCED_PARAMETER(pvPrivateData);
+#endif
+} /* PVRSRVStatsAddMemAllocRecord */
+
+
+IMG_VOID
+PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_UINT64 ui64Key)
+{
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+ IMG_PID currentPid = OSGetCurrentProcessIDKM();
+ PVRSRV_PROCESS_STATS* psProcessStats = IMG_NULL;
+ PVRSRV_MEMORY_STATS* psMemoryStats = IMG_NULL;
+ PVRSRV_MEM_ALLOC_REC* psRecord = IMG_NULL;
+ IMG_BOOL bFound = IMG_FALSE;
+
+ /* Don't do anything if we are not initialised or we are shutting down! */
+ if (!bProcessStatsInitialised)
+ {
+ return;
+ }
+
+ /* Lock while we find the correct process and remove this record... */
+ OSLockAcquire(psLinkedListLock);
+
+ /* First look for the record in the current PID... */
+ psProcessStats = _FindProcessStats(currentPid);
+ if (psProcessStats != IMG_NULL)
+ {
+ psMemoryStats = psProcessStats->psMemoryStats;
+ psRecord = psMemoryStats->psMemoryRecords;
+ while (psRecord != IMG_NULL)
+ {
+ if (psRecord->ui64Key == ui64Key && psRecord->eAllocType == eAllocType)
+ {
+ bFound = IMG_TRUE;
+ break;
+ }
+
+ psRecord = psRecord->psNext;
+ }
+ }
+
+ /* If not found, we need to do a full search in case it was allocated to a different PID... */
+ if (!bFound)
+ {
+ PVRSRV_PROCESS_STATS* psProcessStatsAlreadyChecked = psProcessStats;
+
+ /* Search all live lists first... */
+ psProcessStats = psLiveList;
+ while (psProcessStats != IMG_NULL)
+ {
+ if (psProcessStats != psProcessStatsAlreadyChecked)
+ {
+ psMemoryStats = psProcessStats->psMemoryStats;
+ psRecord = psMemoryStats->psMemoryRecords;
+ while (psRecord != IMG_NULL)
+ {
+ if (psRecord->ui64Key == ui64Key && psRecord->eAllocType == eAllocType)
+ {
+ bFound = IMG_TRUE;
+ break;
+ }
+
+ psRecord = psRecord->psNext;
+ }
+ }
+
+ if (bFound)
+ {
+ break;
+ }
+
+ psProcessStats = psProcessStats->psNext;
+ }
+
+ /* If not found, then search all dead lists next... */
+ if (!bFound)
+ {
+ psProcessStats = psDeadList;
+ while (psProcessStats != IMG_NULL)
+ {
+ if (psProcessStats != psProcessStatsAlreadyChecked)
+ {
+ psMemoryStats = psProcessStats->psMemoryStats;
+ psRecord = psMemoryStats->psMemoryRecords;
+ while (psRecord != IMG_NULL)
+ {
+ if (psRecord->ui64Key == ui64Key && psRecord->eAllocType == eAllocType)
+ {
+ bFound = IMG_TRUE;
+ break;
+ }
+
+ psRecord = psRecord->psNext;
+ }
+ }
+
+ if (bFound)
+ {
+ break;
+ }
+
+ psProcessStats = psProcessStats->psNext;
+ }
+ }
+ }
+
+ /* Update the watermark and remove this record...*/
+ if (bFound)
+ {
+ _decrease_global_stat(eAllocType, psRecord->uiBytes);
+
+ switch (eAllocType)
+ {
+ case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
+ {
+ if (psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] >= psRecord->uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] -= psRecord->uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
+ {
+ if (psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] >= psRecord->uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] -= psRecord->uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] = 0;
+ }
+
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
+ {
+ if (psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] >= psRecord->uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] -= psRecord->uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
+ {
+ if (psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] >= psRecord->uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] -= psRecord->uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
+ {
+ if (psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] >= psRecord->uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] -= psRecord->uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
+ {
+ if (psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] >= psRecord->uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] -= psRecord->uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
+ {
+ if (psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] >= psRecord->uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] -= psRecord->uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
+ {
+ if (psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] >= psRecord->uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] -= psRecord->uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
+ {
+ if (psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] >= psRecord->uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] -= psRecord->uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] = 0;
+ }
+ }
+ break;
+
+ default:
+ {
+ PVR_ASSERT(0);
+ }
+ break;
+ }
+
+ psMemoryStats->ui32LastStatNumberRequested = 0;
+ psMemoryStats->psLastStatMemoryRecordFound = IMG_NULL;
+ List_PVRSRV_MEM_ALLOC_REC_Remove(psRecord);
+ }
+//Count total data
+psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] + PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES];
+
+psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA];
+
+ OSLockRelease(psLinkedListLock);
+
+ /*
+ * Free the record outside the lock so we don't deadlock and so we
+ * reduce the time the lock is held.
+ */
+ if (psRecord != IMG_NULL)
+ {
+ OSFreeMemstatMem(psRecord);
+ }
+#else
+PVR_UNREFERENCED_PARAMETER(eAllocType);
+PVR_UNREFERENCED_PARAMETER(ui64Key);
+#endif
+} /* PVRSRVStatsRemoveMemAllocRecord */
+
+IMG_VOID
+PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_SIZE_T uiBytes,
+ IMG_UINT64 uiCpuVAddr)
+{
+
+ if (!bProcessStatsInitialised || (gpsTrackingTable == IMG_NULL) )
+ {
+ return;
+ }
+
+ HASH_Insert(gpsTrackingTable, uiCpuVAddr, uiBytes);
+
+ PVRSRVStatsIncrMemAllocStat(eAllocType, uiBytes);
+}
+
+IMG_VOID
+PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_SIZE_T uiBytes)
+{
+ IMG_PID currentPid = OSGetCurrentProcessIDKM();
+ PVRSRV_PROCESS_STATS* psProcessStats;
+
+ /* Don't do anything if we are not initialised or we are shutting down! */
+ if (!bProcessStatsInitialised)
+ {
+ return;
+ }
+
+ _increase_global_stat(eAllocType, uiBytes);
+
+ psProcessStats = _FindProcessStats(currentPid);
+ if (psProcessStats != IMG_NULL)
+ {
+ /* Update the memory watermarks... */
+ switch (eAllocType)
+ {
+ case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_KMALLOC],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_VMALLOC],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_PAGES_PT_UMA],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_VMAP_PT_UMA],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_PAGES_PT_LMA],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_IOREMAP_PT_LMA],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_LMA_PAGES],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_ALLOC_UMA_PAGES],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES]);
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] += uiBytes;
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_MAP_UMA_LMA_PAGES],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES]);
+ }
+ break;
+
+ default:
+ {
+ PVR_ASSERT(0);
+ }
+ break;
+ }
+ //Count total data
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] + PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES];
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_ALLOC],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC]);
+
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA];
+ UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_MAP],
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP]);
+ }
+}
+
+IMG_VOID
+PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_UINT64 uiCpuVAddr)
+{
+ IMG_SIZE_T uiBytes;
+
+ if (!bProcessStatsInitialised || (gpsTrackingTable == IMG_NULL) )
+ {
+ return;
+ }
+
+ uiBytes = HASH_Remove(gpsTrackingTable, uiCpuVAddr);
+
+ PVRSRVStatsDecrMemAllocStat(eAllocType, uiBytes);
+}
+
+IMG_VOID
+PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_SIZE_T uiBytes)
+{
+ IMG_PID currentPid = OSGetCurrentProcessIDKM();
+ PVRSRV_PROCESS_STATS* psProcessStats;
+
+ /* Don't do anything if we are not initialised or we are shutting down! */
+ if (!bProcessStatsInitialised)
+ {
+ return;
+ }
+
+ _decrease_global_stat(eAllocType, uiBytes);
+
+ psProcessStats = _FindProcessStats(currentPid);
+ if (psProcessStats != IMG_NULL)
+ {
+ /* Update the memory watermarks... */
+ switch (eAllocType)
+ {
+ case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
+ {
+ if ((IMG_SIZE_T)psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] >= uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] -= uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] = 0;
+ }
+
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
+ {
+ if ((IMG_SIZE_T)psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] >= uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] -= uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
+ {
+ if ((IMG_SIZE_T)psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] >= uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] -= uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
+ {
+ if ((IMG_SIZE_T)psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] >= uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] -= uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
+ {
+ if ((IMG_SIZE_T)psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] >= uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] -= uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
+ {
+ if ((IMG_SIZE_T)psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] >= uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] -= uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
+ {
+ if ((IMG_SIZE_T)psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] >= uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] -= uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
+ {
+ if ((IMG_SIZE_T)psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] >= uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] -= uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] = 0;
+ }
+ }
+ break;
+
+ case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
+ {
+ if ((IMG_SIZE_T)psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] >= uiBytes)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] -= uiBytes;
+ }
+ else
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES] = 0;
+ }
+ }
+ break;
+
+ default:
+ {
+ PVR_ASSERT(0);
+ }
+ break;
+ }
+ //Count total data
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] + PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES];
+
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] +\
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA];
+ }
+}
+
+
+IMG_VOID
+PVRSRVStatsUpdateRenderContextStats(IMG_UINT32 ui32TotalNumPartialRenders,
+ IMG_UINT32 ui32TotalNumOutOfMemory,
+ IMG_UINT32 ui32NumTAStores,
+ IMG_UINT32 ui32Num3DStores,
+ IMG_UINT32 ui32NumSHStores,
+ IMG_UINT32 ui32NumCDMStores,
+ IMG_PID pidOwner)
+{
+ //IMG_PID currentPid = OSGetCurrentProcessIDKM();
+ IMG_PID pidCurrent=pidOwner;
+
+ PVRSRV_PROCESS_STATS* psProcessStats;
+
+ /* Don't do anything if we are not initialised or we are shutting down! */
+ if (!bProcessStatsInitialised)
+ {
+ return;
+ }
+
+ /* Lock while we find the correct process and update the record... */
+ OSLockAcquire(psLinkedListLock);
+
+ psProcessStats = _FindProcessStats(pidCurrent);
+ if (psProcessStats != IMG_NULL)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_PRS] += ui32TotalNumPartialRenders;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_OOMS] += ui32TotalNumOutOfMemory;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_TA_STORES] += ui32NumTAStores;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_3D_STORES] += ui32Num3DStores;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_SH_STORES] += ui32NumSHStores;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_CDM_STORES]+= ui32NumCDMStores;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVStatsUpdateRenderContextStats: Null process. Pid=%d", pidCurrent));
+ }
+
+ OSLockRelease(psLinkedListLock);
+} /* PVRSRVStatsUpdateRenderContextStats */
+
+
+IMG_VOID
+PVRSRVStatsUpdateZSBufferStats(IMG_UINT32 ui32NumReqByApp,
+ IMG_UINT32 ui32NumReqByFW,
+ IMG_PID owner)
+{
+ IMG_PID currentPid = (owner==0)?OSGetCurrentProcessIDKM():owner;
+ PVRSRV_PROCESS_STATS* psProcessStats;
+
+
+ /* Don't do anything if we are not initialised or we are shutting down! */
+ if (!bProcessStatsInitialised)
+ {
+ return;
+ }
+
+ /* Lock while we find the correct process and update the record... */
+ OSLockAcquire(psLinkedListLock);
+
+ psProcessStats = _FindProcessStats(currentPid);
+ if (psProcessStats != IMG_NULL)
+ {
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_APP] += ui32NumReqByApp;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_FW] += ui32NumReqByFW;
+ }
+
+ OSLockRelease(psLinkedListLock);
+} /* PVRSRVStatsUpdateZSBufferStats */
+
+
+IMG_VOID
+PVRSRVStatsUpdateFreelistStats(IMG_UINT32 ui32NumGrowReqByApp,
+ IMG_UINT32 ui32NumGrowReqByFW,
+ IMG_UINT32 ui32InitFLPages,
+ IMG_UINT32 ui32NumHighPages,
+ IMG_PID ownerPid)
+{
+ IMG_PID currentPid = (ownerPid!=0)?ownerPid:OSGetCurrentProcessIDKM();
+ PVRSRV_PROCESS_STATS* psProcessStats;
+
+ /* Don't do anything if we are not initialised or we are shutting down! */
+ if (!bProcessStatsInitialised)
+ {
+ return;
+ }
+
+ /* Lock while we find the correct process and update the record... */
+ OSLockAcquire(psLinkedListLock);
+
+ psProcessStats = _FindProcessStats(currentPid);
+
+ if (psProcessStats != IMG_NULL)
+ {
+ /* Avoid signed / unsigned mismatch which is flagged by some compilers */
+ IMG_INT32 a, b;
+
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_APP] += ui32NumGrowReqByApp;
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_FW] += ui32NumGrowReqByFW;
+
+ a=psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT];
+ b=(IMG_INT32)(ui32InitFLPages);
+ UPDATE_MAX_VALUE(a, b);
+
+
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT]=a;
+ ui32InitFLPages=(IMG_UINT32)b;
+
+ a=psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_MAX_PAGES];
+ b=(IMG_INT32)ui32NumHighPages;
+
+ UPDATE_MAX_VALUE(a, b);
+ psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT]=a;
+ ui32InitFLPages=(IMG_UINT32)b;
+
+ }
+
+ OSLockRelease(psLinkedListLock);
+} /* PVRSRVStatsUpdateFreelistStats */
+
+
+/*************************************************************************/ /*!
+@Function _ObtainProcessStatistic
+@Description Returns a specific statistic number for a process.
+@Input psProcessStats Process statistics to examine.
+@Input ui32StatNumber Index of the statistic to return.
+@Output pi32StatData Statistic value.
+@Output peStatistic Statistic type being returned.
+@Output pszStatFmtText Pointer to formatting string for the stat.
+@Return IMG_TRUE if a statistic is returned, IMG_FALSE if no statistic
+ is available (and this also implies there are no more to get).
+*/ /**************************************************************************/
+static IMG_BOOL
+_ObtainProcessStatistic(PVRSRV_PROCESS_STATS* psProcessStats,
+ IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData,
+ IMG_CHAR** ppszStatFmtText)
+{
+ PVR_ASSERT(psProcessStats != IMG_NULL);
+ PVR_ASSERT(pi32StatData != IMG_NULL);
+
+ if (ui32StatNumber < PVRSRV_PROCESS_STAT_TYPE_COUNT)
+ {
+ *pi32StatData = psProcessStats->i32StatValue[ui32StatNumber];
+
+ if (ppszStatFmtText != IMG_NULL)
+ {
+ *ppszStatFmtText = pszProcessStatFmt[ui32StatNumber];
+ }
+
+ return IMG_TRUE;
+ }
+
+ return IMG_FALSE;
+} /* _ObtainProcessStatistic */
+
+
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+/*************************************************************************/ /*!
+@Function _ObtainMemoryStatistic
+@Description Returns a specific statistic number for a memory area.
+@Input psMemoryStats Memory statistics to examine.
+@Input ui32StatNumber Index of the statistic to return.
+@Output pi32StatData Statistic value.
+@Output pszStatFmtText Pointer to formatting string for the stat.
+@Return IMG_TRUE if a statistic is returned, IMG_FALSE if no statistic
+ is available (and this also implies there are no more to get).
+*/ /**************************************************************************/
+static IMG_BOOL
+_ObtainMemoryStatistic(PVRSRV_MEMORY_STATS* psMemoryStats,
+ IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData,
+ IMG_CHAR** ppszStatFmtText)
+{
+ PVRSRV_MEM_ALLOC_REC *psRecord;
+ IMG_BOOL found = IMG_FALSE;
+ IMG_UINT32 ui32ItemNumber, ui32VAddrFields, ui32PAddrFields;
+
+ PVR_ASSERT(psMemoryStats != IMG_NULL);
+ PVR_ASSERT(pi32StatData != IMG_NULL);
+
+ /*
+ * Displaying the record is achieved by passing back 32bit chunks of data and
+ * appropriate formatting for it. Therefore the ui32StatNumber is divided by the
+ * number of items to be displayed.
+ *
+ * sCpuPAddr.uiAddr is assumed to be a multiple of 32bits.
+ */
+ ui32VAddrFields = sizeof(IMG_VOID*)/sizeof(IMG_UINT32);
+ ui32PAddrFields = sizeof(IMG_CPU_PHYADDR)/sizeof(IMG_UINT32);
+ ui32ItemNumber = ui32StatNumber % (2 + ui32VAddrFields + ui32PAddrFields);
+ ui32StatNumber = ui32StatNumber / (2 + ui32VAddrFields + ui32PAddrFields);
+
+ /* Write the header... */
+ if (ui32StatNumber == 0)
+ {
+ if (ui32ItemNumber == 0)
+ {
+ *pi32StatData = 0;
+ *ppszStatFmtText = "Type ";
+ }
+ else if (ui32ItemNumber-1 < ui32VAddrFields)
+ {
+ *pi32StatData = 0;
+ *ppszStatFmtText = (ui32ItemNumber-1 == 0 ? "VAddress " : " ");
+ }
+ else if (ui32ItemNumber-1-ui32VAddrFields < ui32PAddrFields)
+ {
+ *pi32StatData = 0;
+ *ppszStatFmtText = (ui32ItemNumber-1-ui32VAddrFields == 0 ? "PAddress " : " ");
+ }
+ else if (ui32ItemNumber == ui32PAddrFields+2)
+ {
+ *pi32StatData = 0;
+ *ppszStatFmtText = "Size(bytes)\n";
+ }
+
+ return IMG_TRUE;
+ }
+
+ /* The lock has to be held whilst moving through the memory list... */
+ OSLockAcquire(psLinkedListLock);
+
+ /* Check if we have a cached position... */
+ if (psMemoryStats->ui32LastStatNumberRequested == ui32StatNumber &&
+ psMemoryStats->psLastStatMemoryRecordFound != IMG_NULL)
+ {
+ psRecord = psMemoryStats->psLastStatMemoryRecordFound;
+ }
+ else if (psMemoryStats->ui32LastStatNumberRequested == ui32StatNumber-1 &&
+ psMemoryStats->psLastStatMemoryRecordFound != IMG_NULL)
+ {
+ psRecord = psMemoryStats->psLastStatMemoryRecordFound->psNext;
+ }
+ else
+ {
+ psRecord = psMemoryStats->psMemoryRecords;
+ while (psRecord != IMG_NULL && ui32StatNumber > 1)
+ {
+ psRecord = psRecord->psNext;
+ ui32StatNumber--;
+ }
+ }
+
+ psMemoryStats->ui32LastStatNumberRequested = ui32StatNumber;
+ psMemoryStats->psLastStatMemoryRecordFound = psRecord;
+
+ /* Was a record found? */
+ if (psRecord != IMG_NULL)
+ {
+ if (ui32ItemNumber == 0)
+ {
+ *pi32StatData = 0;
+ switch (psRecord->eAllocType)
+ {
+ case PVRSRV_MEM_ALLOC_TYPE_KMALLOC: *ppszStatFmtText = "KMALLOC "; break;
+ case PVRSRV_MEM_ALLOC_TYPE_VMALLOC: *ppszStatFmtText = "VMALLOC "; break;
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA: *ppszStatFmtText = "ALLOC_PAGES_PT_LMA "; break;
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA: *ppszStatFmtText = "ALLOC_PAGES_PT_UMA "; break;
+ case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA: *ppszStatFmtText = "IOREMAP_PT_LMA "; break;
+ case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA: *ppszStatFmtText = "VMAP_PT_UMA "; break;
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES: *ppszStatFmtText = "ALLOC_LMA_PAGES "; break;
+ case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES: *ppszStatFmtText = "ALLOC_UMA_PAGES "; break;
+ case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES: *ppszStatFmtText = "MAP_UMA_LMA_PAGES "; break;
+ default: *ppszStatFmtText = "INVALID "; break;
+ }
+ }
+ else if (ui32ItemNumber-1 < ui32VAddrFields)
+ {
+ *pi32StatData = *(((IMG_UINT32*) &psRecord->pvCpuVAddr) + ui32VAddrFields - (ui32ItemNumber-1) - 1);
+ *ppszStatFmtText = (ui32ItemNumber-1 == ui32VAddrFields-1 ? "%08x " : "%08x");
+ }
+ else if (ui32ItemNumber-1-ui32VAddrFields < ui32PAddrFields)
+ {
+ *pi32StatData = *(((IMG_UINT32*) &psRecord->sCpuPAddr.uiAddr) + ui32PAddrFields - (ui32ItemNumber-1-ui32VAddrFields) - 1);
+ *ppszStatFmtText = (ui32ItemNumber-1-ui32VAddrFields == ui32PAddrFields-1 ? "%08x " : "%08x");
+ }
+ else if (ui32ItemNumber == ui32PAddrFields+2)
+ {
+ *pi32StatData = psRecord->uiBytes;
+ *ppszStatFmtText = "%u\n";
+ }
+
+ found = IMG_TRUE;
+ }
+
+ OSLockRelease(psLinkedListLock);
+
+ return found;
+} /* _ObtainMemoryStatistic */
+#endif
+
+
+#if defined(PVR_RI_DEBUG)
+/*************************************************************************/ /*!
+@Function _ObtainRIMemoryStatistic
+@Description Returns a specific RI MEMDESC entry.
+@Input psMemoryStats Memory statistics to examine.
+@Input ui32StatNumber Index of the statistic to return.
+@Output pi32StatData Statistic value.
+@Output pszStatFmtText Pointer to formatting string for the stat.
+@Return IMG_TRUE if a statistic is returned, IMG_FALSE if no statistic
+ is available (and this also implies there are no more to get).
+*/ /**************************************************************************/
+static IMG_BOOL
+_ObtainRIMemoryStatistic(PVRSRV_RI_MEMORY_STATS* psRIMemoryStats,
+ IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData,
+ IMG_CHAR** ppszStatFmtText)
+{
+ PVR_ASSERT(psRIMemoryStats != IMG_NULL);
+
+ PVR_UNREFERENCED_PARAMETER(pi32StatData);
+
+ /*
+ * If this request is for the first item then set the handle to null.
+ * If it is not the first request, then the handle should not be null
+ * unless this is the OS's way of double checking that the previous
+ * request, which returned IMG_FALSE was indeed the last request.
+ */
+ if (ui32StatNumber == 0)
+ {
+ psRIMemoryStats->pRIHandle = IMG_NULL;
+ }
+ else if (psRIMemoryStats->pRIHandle == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ return RIGetListEntryKM(psRIMemoryStats->pid,
+ &psRIMemoryStats->pRIHandle,
+ ppszStatFmtText);
+} /* _ObtainRIMemoryStatistic */
+#endif
+
+
+/*************************************************************************/ /*!
+@Function PVRSRVStatsObtainElement
+@Description Returns a specific statistic number for a process. Clients are
+ expected to iterate through the statistics by requesting stat
+ 0,1,2,3,4,etc. and stopping when FALSE is returned.
+@Input pvStatPtr Pointer to statistics structure.
+@Input ui32StatNumber Index of the statistic to return.
+@Output pi32StatData Statistic value.
+@Output pszStatFmtText Pointer to formatting string for the stat.
+@Return IMG_TRUE if a statistic is returned, IMG_FALSE if no statistic
+ is available (and this also implies there are no more to get).
+*/ /**************************************************************************/
+IMG_BOOL
+PVRSRVStatsObtainElement(IMG_PVOID pvStatPtr, IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData, IMG_CHAR** ppszStatFmtText)
+{
+ PVRSRV_STAT_STRUCTURE_TYPE* peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
+
+ if (peStructureType == IMG_NULL || pi32StatData == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ if (*peStructureType == PVRSRV_STAT_STRUCTURE_PROCESS)
+ {
+ PVRSRV_PROCESS_STATS* psProcessStats = (PVRSRV_PROCESS_STATS*) pvStatPtr;
+
+ return _ObtainProcessStatistic(psProcessStats, ui32StatNumber,
+ pi32StatData, ppszStatFmtText);
+ }
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+ else if (*peStructureType == PVRSRV_STAT_STRUCTURE_MEMORY)
+ {
+ PVRSRV_MEMORY_STATS* psMemoryStats = (PVRSRV_MEMORY_STATS*) pvStatPtr;
+
+ return _ObtainMemoryStatistic(psMemoryStats, ui32StatNumber,
+ pi32StatData, ppszStatFmtText);
+ }
+#endif
+#if defined(PVR_RI_DEBUG)
+ else if (*peStructureType == PVRSRV_STAT_STRUCTURE_RIMEMORY)
+ {
+ PVRSRV_RI_MEMORY_STATS* psRIMemoryStats = (PVRSRV_RI_MEMORY_STATS*) pvStatPtr;
+
+ return _ObtainRIMemoryStatistic(psRIMemoryStats, ui32StatNumber,
+ pi32StatData, ppszStatFmtText);
+ }
+#endif
+
+ /* Stat type not handled probably indicates bad pointers... */
+ PVR_ASSERT(IMG_FALSE);
+
+ return IMG_FALSE;
+} /* PVRSRVStatsObtainElement */
+
+static IMG_UINT32 ui32FirmwareStartTimestamp=0;
+static IMG_UINT64 ui64FirmwareIdleDuration=0;
+
+/* Averaging each new value with the previous accumulated knowledge. There are many coefficients for that
+ * (e.g.) 50 / 50 but i chose 75 / 25 meaning that previous knowledge affects the weighted average more
+ * than any new knowledge. As time goes by though eventually the number converges to the most commonly used
+ */
+
+IMG_VOID SetFirmwareStartTime(IMG_UINT32 ui32Time)
+{
+ if (ui32FirmwareStartTimestamp > 0)
+ {
+ ui32FirmwareStartTimestamp=MEAN_TIME(ui32FirmwareStartTimestamp, ui32Time);
+ }
+ else
+ {
+ ui32FirmwareStartTimestamp = ui32Time;
+ }
+}
+
+IMG_VOID SetFirmwareHandshakeIdleTime(IMG_UINT64 ui64Duration)
+{
+ if (ui64FirmwareIdleDuration > 0)
+ {
+ ui64FirmwareIdleDuration=MEAN_TIME(ui64FirmwareIdleDuration, ui64Duration);
+ }
+ else
+ {
+ ui64FirmwareIdleDuration = ui64Duration;
+ }
+}
+
+
+IMG_BOOL PVRSRVPowerStatsObtainElement(IMG_PVOID pvStatPtr, IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData, IMG_CHAR** ppszStatFmtText)
+{
+ PVRSRV_STAT_STRUCTURE_TYPE* peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
+
+ if (peStructureType == IMG_NULL || pi32StatData == IMG_NULL)
+ {
+ /* Stat type not handled probably indicates bad pointers... */
+ PVR_ASSERT(IMG_FALSE);
+ return IMG_FALSE;
+ }
+
+ switch(ui32StatNumber)
+ {
+ case PVRSRV_POWER_TIMING_STAT_FORCED_POWER_TRANSITION:
+ {
+ (*ppszStatFmtText)="Forced Power Transition (nanoseconds):\n\n";
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_PRE_DEVICE:
+ {
+ (*ppszStatFmtText)="Pre-Device: %u\n";
+ (*pi32StatData)= ((IMG_UINT32)(ui64ForcedPreDevice)/(IMG_UINT32) ui64TotalForcedEntries);
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_PRE_SYSTEM:
+ {
+ (*ppszStatFmtText)="Pre-System: %u\n";
+ (*pi32StatData)=((IMG_UINT32)(ui64ForcedPreSystem)/(IMG_UINT32) ui64TotalForcedEntries);
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_POST_DEVICE:
+ {
+ (*ppszStatFmtText)="Post-Device: %u\n";
+ (*pi32StatData)=((IMG_UINT32)(ui64ForcedPostDevice)/(IMG_UINT32) ui64TotalForcedEntries);
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_POST_SYSTEM:
+ {
+ (*ppszStatFmtText)="Post-System: %u\n";
+ (*pi32StatData)=((IMG_UINT32)(ui64ForcedPostSystem)/(IMG_UINT32) ui64TotalForcedEntries);
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_NEWLINE1:
+ case PVRSRV_POWER_TIMING_STAT_NEWLINE2:
+ {
+ (*ppszStatFmtText)="\n\n\n\n";
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_NOT_FORCED_POWER_TRANSITION:
+ {
+ (*ppszStatFmtText)="Not Forced Power Transition (nanoseconds):\n\n";
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_NON_PRE_DEVICE:
+ {
+ (*ppszStatFmtText)="Pre-Device: %u\n";
+ (*pi32StatData)=((IMG_UINT32)(ui64NotForcedPreDevice)/(IMG_UINT32) ui64TotalNotForcedEntries);
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_NON_PRE_SYSTEM:
+ {
+ (*ppszStatFmtText)="Pre-System: %u\n";
+ (*pi32StatData)=((IMG_UINT32)(ui64NotForcedPreSystem)/(IMG_UINT32) ui64TotalNotForcedEntries);
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_NON_POST_DEVICE:
+ {
+ (*ppszStatFmtText)="Post-Device: %u\n";
+ (*pi32StatData)= ((IMG_UINT32)(ui64NotForcedPostDevice)/(IMG_UINT32) ui64TotalNotForcedEntries);
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_NON_POST_SYSTEM:
+ {
+ (*ppszStatFmtText)="Post-System: %u\n";
+ (*pi32StatData)=((IMG_UINT32)(ui64NotForcedPostSystem)/(IMG_UINT32) ui64TotalNotForcedEntries);
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_FW_BOOTUP_TIME:
+ {
+ (*ppszStatFmtText)="FW bootup time (timer tics): %u\n";
+ (*pi32StatData)=ui32FirmwareStartTimestamp;
+ break;
+ }
+ case PVRSRV_POWER_TIMING_STAT_HOST_ACK:
+ {
+ (*ppszStatFmtText)="Host Acknowledge Time for FW Idle Signal (timer tics): %u\n";
+ (*pi32StatData)=(IMG_UINT32)(ui64FirmwareIdleDuration);
+ break;
+ }
+ default:
+ {
+ return IMG_FALSE;
+ }
+ }
+ return IMG_TRUE;
+}
+
+
+static IMG_BOOL
+_PVRSRVGetGlobalMemStat(IMG_PVOID pvStatPtr,
+ IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData,
+ IMG_CHAR** ppszStatFmtText)
+{
+ switch (ui32StatNumber)
+ {
+ case 0:
+ (*ppszStatFmtText) = "MemoryUsageKMalloc %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageKMalloc;
+ break;
+
+ case 1:
+ (*ppszStatFmtText) = "MemoryUsageKMallocMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageKMallocMax;
+ break;
+
+ case 2:
+ (*ppszStatFmtText) = "MemoryUsageVMalloc %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageVMalloc;
+ break;
+
+ case 3:
+ (*ppszStatFmtText) = "MemoryUsageVMallocMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageVMallocMax;
+ break;
+
+ case 4:
+ (*ppszStatFmtText) = "MemoryUsageAllocPTMemoryUMA %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA;
+ break;
+
+ case 5:
+ (*ppszStatFmtText) = "MemoryUsageAllocPTMemoryUMAMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMAMax;
+ break;
+
+ case 6:
+ (*ppszStatFmtText) = "MemoryUsageVMapPTUMA %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageVMapPTUMA;
+ break;
+
+ case 7:
+ (*ppszStatFmtText) = "MemoryUsageVMapPTUMAMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageVMapPTUMAMax;
+ break;
+
+ case 8:
+ (*ppszStatFmtText) = "MemoryUsageAllocPTMemoryLMA %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA;
+ break;
+
+ case 9:
+ (*ppszStatFmtText) = "MemoryUsageAllocPTMemoryLMAMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMAMax;
+ break;
+
+ case 10:
+ (*ppszStatFmtText) = "MemoryUsageIORemapPTLMA %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageIORemapPTLMA;
+ break;
+
+ case 11:
+ (*ppszStatFmtText) = "MemoryUsageIORemapPTLMAMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageIORemapPTLMAMax;
+ break;
+
+ case 12:
+ (*ppszStatFmtText) = "MemoryUsageAllocGPUMemLMA %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA;
+ break;
+
+ case 13:
+ (*ppszStatFmtText) = "MemoryUsageAllocGPUMemLMAMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageAllocGPUMemLMAMax;
+ break;
+
+ case 14:
+ (*ppszStatFmtText) = "MemoryUsageAllocGPUMemUMA %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA;
+ break;
+
+ case 15:
+ (*ppszStatFmtText) = "MemoryUsageAllocGPUMemUMAMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageAllocGPUMemUMAMax;
+ break;
+
+ case 16:
+ (*ppszStatFmtText) = "MemoryUsageMappedGPUMemUMA/LMA %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA;
+ break;
+
+ case 17:
+ (*ppszStatFmtText) = "MemoryUsageMappedGPUMemUMA/LMAMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMAMax;
+ break;
+
+ //zxl: count total data
+ case 18:
+ (*ppszStatFmtText) = "MemoryUsageTotalAlloc %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageTotalAlloc;
+ break;
+
+ case 19:
+ (*ppszStatFmtText) = "MemoryUsageTotalAllocMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageTotalAllocMax;
+ break;
+
+ case 20:
+ (*ppszStatFmtText) = "MemoryUsageTotalMap %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageTotalMap;
+ break;
+
+ case 21:
+ (*ppszStatFmtText) = "MemoryUsageTotalMapMax %10u\n";
+ (*pi32StatData) = (IMG_INT32) gsGlobalStats.ui32MemoryUsageTotalMapMax;
+ break;
+
+ default:
+ return IMG_FALSE;
+ }
+
+
+ return IMG_TRUE;
+}
diff --git a/drivers/gpu/rogue/services/server/common/pvrsrv.c b/drivers/gpu/rogue/services/server/common/pvrsrv.c
new file mode 100644
index 000000000000..c642bda8f87b
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/pvrsrv.c
@@ -0,0 +1,2468 @@
+/*************************************************************************/ /*!
+@File
+@Title core services functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for core services 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 "rgxdebug.h"
+#include "handle.h"
+#include "connection_server.h"
+#include "pdump_km.h"
+#include "ra.h"
+#include "allocmem.h"
+#include "pmr.h"
+#include "dc_server.h"
+#include "pvrsrv.h"
+#include "pvrsrv_device.h"
+#include "pvr_debug.h"
+#include "sync.h"
+#include "sync_server.h"
+#include "devicemem.h"
+
+#include "pvrversion.h"
+
+#include "lists.h"
+#include "dllist.h"
+#include "syscommon.h"
+
+#include "physmem_lma.h"
+#include "physmem_osmem.h"
+
+#include "tlintern.h"
+
+#if defined (SUPPORT_RGX)
+#include "rgxinit.h"
+#endif
+
+#include "debug_request_ids.h"
+#include "pvrsrv.h"
+
+#if defined(PVR_RI_DEBUG)
+#include "ri_server.h"
+#endif
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#include "process_stats.h"
+#endif
+/*! Wait 100ms before retrying deferred clean-up again */
+#define CLEANUP_THREAD_WAIT_RETRY_TIMEOUT 0x00000064
+
+/*! Wait 8hrs when no deferred clean-up required. Allows a poll several times
+ * a day to check for any missed clean-up. */
+#define CLEANUP_THREAD_WAIT_SLEEP_TIMEOUT 0x01B77400
+
+
+typedef struct DEBUG_REQUEST_ENTRY_TAG
+{
+ IMG_UINT32 ui32RequesterID;
+ DLLIST_NODE sListHead;
+} DEBUG_REQUEST_ENTRY;
+
+typedef struct DEBUG_REQUEST_TABLE_TAG
+{
+ IMG_UINT32 ui32RequestCount;
+ DEBUG_REQUEST_ENTRY asEntry[1];
+}DEBUG_REQUEST_TABLE;
+
+static PVRSRV_DATA *gpsPVRSRVData = IMG_NULL;
+static IMG_HANDLE g_hDbgSysNotify;
+
+static PVRSRV_SYSTEM_CONFIG *gpsSysConfig = IMG_NULL;
+
+typedef PVRSRV_ERROR (*PFN_REGISTER_DEVICE)(PVRSRV_DEVICE_NODE *psDeviceNode);
+typedef PVRSRV_ERROR (*PFN_UNREGISTER_DEVICE)(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+static PFN_REGISTER_DEVICE sRegisterDevice[PVRSRV_DEVICE_TYPE_LAST + 1];
+static PFN_UNREGISTER_DEVICE sUnregisterDevice[PVRSRV_DEVICE_TYPE_LAST + 1];
+
+static PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PVRSRV_DEVICE_CONFIG *psDevConfig);
+static PVRSRV_ERROR IMG_CALLCONV PVRSRVUnregisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+static PVRSRV_ERROR PVRSRVRegisterDbgTable(IMG_UINT32 *paui32Table, IMG_UINT32 ui32Length, IMG_PVOID *phTable);
+static IMG_VOID PVRSRVUnregisterDbgTable(IMG_PVOID hTable);
+
+static IMG_VOID _SysDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel);
+
+IMG_UINT32 g_ui32InitFlags;
+
+/* mark which parts of Services were initialised */
+#define INIT_DATA_ENABLE_PDUMPINIT 0x1U
+#define INIT_GLOBAL_RESMAN 0x2U
+
+/* Head of the list of callbacks called when Cmd complete happens */
+static DLLIST_NODE sCmdCompNotifyHead;
+static POSWR_LOCK hNotifyLock = IMG_NULL;
+
+/* Debug request table and lock */
+static POSWR_LOCK g_hDbgNotifyLock = IMG_NULL;
+static DEBUG_REQUEST_TABLE *g_psDebugTable;
+
+static IMG_PVOID g_hDebugTable = IMG_NULL;
+
+static IMG_UINT32 g_aui32DebugOrderTable[] = {
+ DEBUG_REQUEST_SYS,
+ DEBUG_REQUEST_RGX,
+ DEBUG_REQUEST_DC,
+ DEBUG_REQUEST_SERVERSYNC,
+ DEBUG_REQUEST_ANDROIDSYNC
+};
+
+DUMPDEBUG_PRINTF_FUNC *g_pfnDumpDebugPrintf = IMG_NULL;
+/*!
+******************************************************************************
+
+ @Function AllocateDeviceID
+
+ @Description
+
+ allocates a device id from the pool of valid ids
+
+ @input psPVRSRVData : Services private data
+
+ @input pui32DevID : device id to return
+
+ @Return device id
+
+******************************************************************************/
+static PVRSRV_ERROR AllocateDeviceID(PVRSRV_DATA *psPVRSRVData, IMG_UINT32 *pui32DevID)
+{
+ SYS_DEVICE_ID* psDeviceWalker;
+ SYS_DEVICE_ID* psDeviceEnd;
+
+ psDeviceWalker = &psPVRSRVData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + SYS_DEVICE_COUNT;
+
+ /* find a free ID */
+ while (psDeviceWalker < psDeviceEnd)
+ {
+ if (!psDeviceWalker->bInUse)
+ {
+ psDeviceWalker->bInUse = IMG_TRUE;
+ *pui32DevID = psDeviceWalker->uiID;
+
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
+
+ /* Should never get here: sDeviceID[] may have been setup too small */
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVAILABLE;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function FreeDeviceID
+
+ @Description
+
+ frees a device id from the pool of valid ids
+
+ @input psPVRSRVData : Services private data
+
+ @input ui32DevID : device id to free
+
+ @Return device id
+
+******************************************************************************/
+static PVRSRV_ERROR FreeDeviceID(PVRSRV_DATA *psPVRSRVData, IMG_UINT32 ui32DevID)
+{
+ SYS_DEVICE_ID* psDeviceWalker;
+ SYS_DEVICE_ID* psDeviceEnd;
+
+ psDeviceWalker = &psPVRSRVData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + SYS_DEVICE_COUNT;
+
+ /* find the ID to free */
+ while (psDeviceWalker < psDeviceEnd)
+ {
+ /* if matching id and in use, free */
+ if (
+ (psDeviceWalker->uiID == ui32DevID) &&
+ (psDeviceWalker->bInUse)
+ )
+ {
+ psDeviceWalker->bInUse = IMG_FALSE;
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
+
+ /* should never get here */
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_INVALID_DEVICEID;
+}
+
+
+/*!
+******************************************************************************
+ @Function PVRSRVEnumerateDevicesKM_ForEachVaCb
+
+ @Description
+
+ Enumerates the device node (if is of the same class as given).
+
+ @Input psDeviceNode - The device node to be enumerated
+ va - variable arguments list, with:
+ pui32DevCount - The device count pointer (to be increased)
+ ppeDeviceType - The pointer to the device type pointer (to be updated and increased)
+ ppeDeviceClass - The pointer to the device classes pointer (to be updated and increased)
+ ppui32DeviceIndex - The pointer to the device indexes pointer (to be updated and increased)
+******************************************************************************/
+static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT *pui32DevCount;
+ PVRSRV_DEVICE_TYPE **ppeDeviceType;
+ PVRSRV_DEVICE_CLASS **ppeDeviceClass;
+ IMG_UINT32 **ppui32DeviceIndex;
+
+ pui32DevCount = va_arg(va, IMG_UINT*);
+ ppeDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE**);
+ ppeDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS**);
+ ppui32DeviceIndex = va_arg(va, IMG_UINT32**);
+
+ if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
+ {
+ **ppeDeviceType = psDeviceNode->sDevId.eDeviceType;
+ **ppeDeviceClass = psDeviceNode->sDevId.eDeviceClass;
+ **ppui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ (*ppeDeviceType)++;
+ (*ppeDeviceClass)++;
+ (*ppui32DeviceIndex)++;
+
+ (*pui32DevCount)++;
+ }
+}
+
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumerateDevicesKM
+
+ @Description
+ This function will enumerate all the devices supported by the
+ PowerVR services within the target system.
+ The function returns a list of the device ID structures stored either in
+ the services or constructed in the user mode glue component in certain
+ environments. The number of devices in the list is also returned.
+
+ In a binary layered component which does not support dynamic runtime selection,
+ the glue code should compile to return the supported devices statically,
+ e.g. multiple instances of the same device if multiple devices are supported,
+ or the target combination of Rogue and display device.
+
+ In the case of an environment (for instance) where one Rogue may connect to two
+ display devices this code would enumerate all three devices and even
+ non-dynamic Rogue selection code should retain the facility to parse the list
+ to find the index of the Rogue device
+
+ @output pui32NumDevices : On success, contains the number of devices present
+ in the system
+
+ @output peDeviceType : Pointer to called supplied buffer to receive the
+ list of PVRSRV_DEVICE_TYPE
+
+ @output peDeviceClass : Pointer to called supplied buffer to receive the
+ list of PVRSRV_DEVICE_CLASS
+
+ @output pui32DeviceIndex: Pointer to called supplied buffer to receive the
+ list of device indexes
+
+ @return PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+ PVRSRV_DEVICE_TYPE *peDeviceType,
+ PVRSRV_DEVICE_CLASS *peDeviceClass,
+ IMG_UINT32 *pui32DeviceIndex)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ IMG_UINT32 i;
+
+ if (!pui32NumDevices || !peDeviceType || !peDeviceClass || !pui32DeviceIndex)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /*
+ setup input buffer to be `empty'
+ */
+ for (i=0; i<PVRSRV_MAX_DEVICES; i++)
+ {
+ peDeviceType[i] = PVRSRV_DEVICE_TYPE_UNKNOWN;
+ }
+
+ /* and zero device count */
+ *pui32NumDevices = 0;
+
+ /*
+ Search through the device list for services managed devices
+ return id info for each device and the number of devices
+ available
+ */
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psPVRSRVData->psDeviceNodeList,
+ &PVRSRVEnumerateDevicesKM_ForEachVaCb,
+ pui32NumDevices,
+ &peDeviceType,
+ &peDeviceClass,
+ &pui32DeviceIndex);
+
+ return PVRSRV_OK;
+}
+
+// #define CLEANUP_DPFL PVR_DBG_WARNING
+#define CLEANUP_DPFL PVR_DBG_MESSAGE
+
+static IMG_VOID CleanupThread(IMG_PVOID pvData)
+{
+ PVRSRV_DATA *psPVRSRVData = pvData;
+ IMG_BOOL bRetryCleanup = IMG_FALSE;
+ IMG_HANDLE hOSEvent;
+ PVRSRV_ERROR eRc;
+ IMG_UINT64 ui64TimesliceLimit;
+
+ PVR_DPF((CLEANUP_DPFL, "CleanupThread: thread starting... "));
+
+ /* Open an event on the clean up event object so we can listen on it,
+ * abort the clean up thread and driver if this fails.
+ */
+ eRc = OSEventObjectOpen(psPVRSRVData->hCleanupEventObject, &hOSEvent);
+ PVR_ASSERT(eRc == PVRSRV_OK);
+
+ /* While the driver is in a good state and is not being unloaded
+ * try to free any deferred items when RESMAN signals
+ */
+ while ((psPVRSRVData->eServicesState == PVRSRV_SERVICES_STATE_OK) &&
+ (!psPVRSRVData->bUnload))
+ {
+ /* Wait until RESMAN signals for deferred clean up OR wait for a
+ * short period if the previous deferred clean up was not able
+ * to release all the resources before trying again.
+ * Bridge lock re-acquired on our behalf before the wait call returns.
+ */
+ eRc = OSEventObjectWaitTimeout(hOSEvent, (bRetryCleanup) ?
+ CLEANUP_THREAD_WAIT_RETRY_TIMEOUT :
+ CLEANUP_THREAD_WAIT_SLEEP_TIMEOUT);
+ if (eRc == PVRSRV_ERROR_TIMEOUT)
+ {
+ PVR_DPF((CLEANUP_DPFL, "CleanupThread: wait timeout"));
+ }
+ else if (eRc == PVRSRV_OK)
+ {
+ PVR_DPF((CLEANUP_DPFL, "CleanupThread: wait OK, signal received"));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CleanupThread: wait error %d", eRc));
+ }
+
+ /* Acquire the bridge lock to protect the flush of the deferred contexts
+ * and to guarantee the consistency of the deferred contexts list.
+ * In order to avoid to block the system during the cleanup the lock is
+ * released periodically every time a specific time expires.
+ */
+ OSAcquireBridgeLock();
+
+ /* Estimate the time limit as soon as we acquire the global lock */
+ ui64TimesliceLimit = OSClockns64() + RESMAN_DEFERRED_CLEANUP_TIMESLICE_NS;
+
+ /* Attempt to clean up all deferred contexts that may exist. If
+ * resources still need cleanup on exit bRetryCleanup set to true.
+ */
+ bRetryCleanup = PVRSRVResManFlushDeferContext(
+ psPVRSRVData->hResManDeferContext,
+ ui64TimesliceLimit);
+
+ /* Release the bridge lock after the cleanup of the defer context */
+ OSReleaseBridgeLock();
+ }
+
+ eRc = OSEventObjectClose(hOSEvent);
+ PVR_LOG_IF_ERROR(eRc, "OSEventObjectClose");
+
+ PVR_DPF((CLEANUP_DPFL, "CleanupThread: thread ending... "));
+}
+
+
+static IMG_VOID DevicesWatchdogThread(IMG_PVOID pvData)
+{
+ PVRSRV_DATA *psPVRSRVData = pvData;
+ PVRSRV_DEVICE_HEALTH_STATUS ePreviousHealthStatus = PVRSRV_DEVICE_HEALTH_STATUS_OK;
+ IMG_HANDLE hOSEvent;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Timeout = DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT;
+ PVRSRV_DEV_POWER_STATE ePowerState;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "DevicesWatchdogThread: Power off sleep time: %d.",
+ DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT));
+
+ /* Open an event on the devices watchdog event object so we can listen on it
+ and abort the devices watchdog thread. */
+ eError = OSEventObjectOpen(psPVRSRVData->hDevicesWatchdogEvObj, &hOSEvent);
+ PVR_LOGRN_IF_ERROR(eError, "OSEventObjectOpen");
+
+ /* Loop continuously checking the device status every few seconds. */
+ while (!psPVRSRVData->bUnload)
+ {
+ IMG_UINT32 i;
+ IMG_BOOL bPwrIsOn = IMG_FALSE;
+
+ /* Wait time between polls (done at the start of the loop to allow devices
+ to initialise) or for the event signal (shutdown or power on). */
+ eError = OSEventObjectWaitTimeout(hOSEvent, ui32Timeout);
+
+#ifdef PVR_TESTING_UTILS
+ psPVRSRVData->ui32DevicesWdWakeupCounter++;
+#endif
+ if (eError == PVRSRV_OK)
+ {
+ if (psPVRSRVData->bUnload)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "DevicesWatchdogThread: Shutdown event received."));
+ break;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "DevicesWatchdogThread: Power state change event received."));
+ }
+ }
+ else if (eError != PVRSRV_ERROR_TIMEOUT)
+ {
+ /* If timeout do nothing otherwise print warning message. */
+ PVR_DPF((PVR_DBG_ERROR, "DevicesWatchdogThread: "
+ "Error (%d) when waiting for event!", eError));
+ }
+
+ eError = PVRSRVPowerLock();
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ /* power lock cannot be acquired at this time (sys power is off) */
+ ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ /* any other error is unexpected */
+ PVR_DPF((PVR_DBG_ERROR,"DevicesWatchdogThread: Failed to acquire power lock (%s)", PVRSRVGetErrorStringKM(eError)));
+ }
+ else
+ {
+ /* Check if at least one of the devices is on. */
+ for (i = 0; i < psPVRSRVData->ui32RegisteredDevices && !bPwrIsOn; i++)
+ {
+ if (PVRSRVGetDevicePowerState(i, &ePowerState) == PVRSRV_OK)
+ {
+ bPwrIsOn = ePowerState == PVRSRV_DEV_POWER_STATE_ON;
+ break;
+ }
+ }
+
+ if (bPwrIsOn || psPVRSRVData->ui32DevicesWatchdogPwrTrans)
+ {
+ psPVRSRVData->ui32DevicesWatchdogPwrTrans = 0;
+ ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT;
+ }
+ else
+ {
+ ui32Timeout = psPVRSRVData->ui32DevicesWatchdogTimeout = DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT;
+ }
+
+ PVRSRVPowerUnlock();
+ }
+
+ for (i = 0; i < psPVRSRVData->ui32RegisteredDevices; i++)
+ {
+ PVRSRV_DEVICE_NODE* psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[i];
+ PVRSRV_RGXDEV_INFO* psDevInfo = (PVRSRV_RGXDEV_INFO*) psDeviceNode->pvDevice;
+
+ if (psDeviceNode->pfnUpdateHealthStatus != IMG_NULL)
+ {
+ eError = psDeviceNode->pfnUpdateHealthStatus(psDeviceNode, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "DevicesWatchdogThread: "
+ "Could not check for fatal error (%d)!",
+ eError));
+ }
+ }
+
+ if (psDeviceNode->eHealthStatus != PVRSRV_DEVICE_HEALTH_STATUS_OK)
+ {
+ if (psDeviceNode->eHealthStatus != ePreviousHealthStatus)
+ {
+ if (!(psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevicesWatchdogThread: Device not responding!!!"));
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
+ }
+ }
+ }
+ ePreviousHealthStatus = psDeviceNode->eHealthStatus;
+
+ /* Attempt to service the HWPerf buffer to regularly transport
+ * idle / periodic packets to host buffer. */
+ if (psDeviceNode->pfnServiceHWPerf != IMG_NULL)
+ {
+ eError = psDeviceNode->pfnServiceHWPerf(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "DevicesWatchdogThread: "
+ "Error occurred when servicing HWPerf buffer (%d)",
+ eError));
+ }
+ }
+ }
+ }
+
+ eError = OSEventObjectClose(hOSEvent);
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectClose");
+}
+
+
+PVRSRV_DATA *PVRSRVGetPVRSRVData()
+{
+ return gpsPVRSRVData;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SYSTEM_CONFIG *psSysConfig;
+ IMG_UINT32 i;
+
+#if defined (SUPPORT_RGX)
+
+ sRegisterDevice[PVRSRV_DEVICE_TYPE_RGX] = RGXRegisterDevice;
+#endif
+
+ SET_LOG2_PAGESIZE(OSGetPageShift());
+
+ eError = PhysHeapInit();
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ /* Get the system config */
+ eError = SysCreateConfigData(&psSysConfig);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ /* Save to global pointer for later */
+ gpsSysConfig = psSysConfig;
+
+ /*
+ * Allocate the device-independent data
+ */
+ gpsPVRSRVData = OSAllocMem(sizeof(*gpsPVRSRVData));
+ if (gpsPVRSRVData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(gpsPVRSRVData, 0, sizeof(*gpsPVRSRVData));
+ gpsPVRSRVData->ui32NumDevices = psSysConfig->uiDeviceCount;
+
+ for (i=0;i<SYS_DEVICE_COUNT;i++)
+ {
+ gpsPVRSRVData->sDeviceID[i].uiID = i;
+ gpsPVRSRVData->sDeviceID[i].bInUse = IMG_FALSE;
+ }
+
+ /*
+ * Register the physical memory heaps
+ */
+ PVR_ASSERT(psSysConfig->ui32PhysHeapCount <= SYS_PHYS_HEAP_COUNT);
+ for (i=0;i<psSysConfig->ui32PhysHeapCount;i++)
+ {
+ eError = PhysHeapRegister(&psSysConfig->pasPhysHeaps[i],
+ &gpsPVRSRVData->apsRegisteredPhysHeaps[i]);
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+ gpsPVRSRVData->ui32RegisteredPhysHeaps++;
+ }
+
+ /* Init any OS specific's */
+ eError = OSInitEnvData();
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ /* Initialise Resource Manager */
+ eError = ResManInit();
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ eError = PVRSRVConnectionInit();
+ if(eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+#if defined(PVR_RI_DEBUG)
+ RIInitKM();
+#endif
+
+ eError = PMRInit();
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+#if !defined(UNDER_WDDM) && defined(SUPPORT_DISPLAY_CLASS)
+ eError = DCInit();
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+#endif
+
+ /* Initialise handles */
+ eError = PVRSRVHandleInit();
+ if(eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ /* Initialise Power Manager Lock */
+ eError = OSLockCreate(&gpsPVRSRVData->hPowerLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ /* Initialise system power state */
+ gpsPVRSRVData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_ON;
+ gpsPVRSRVData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+ /* Initialise overall system state */
+ gpsPVRSRVData->eServicesState = PVRSRV_SERVICES_STATE_OK;
+
+ /* Create an event object */
+ eError = OSEventObjectCreate("PVRSRV_GLOBAL_EVENTOBJECT", &gpsPVRSRVData->hGlobalEventObject);
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+ gpsPVRSRVData->ui32GEOConsecutiveTimeouts = 0;
+
+ /* initialise list of command complete notifiers */
+ dllist_init(&sCmdCompNotifyHead);
+
+ /* Create a lock of the list notifiers */
+ eError = OSWRLockCreate(&hNotifyLock);
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ /* Create a lock of the debug notifiers */
+ eError = OSWRLockCreate(&g_hDbgNotifyLock);
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ eError = PVRSRVRegisterDbgTable(g_aui32DebugOrderTable,
+ sizeof(g_aui32DebugOrderTable)/sizeof(g_aui32DebugOrderTable[0]),
+ &g_hDebugTable);
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ PVRSRVRegisterDbgRequestNotify(&g_hDbgSysNotify, &_SysDebugRequestNotify, DEBUG_REQUEST_SYS, gpsPVRSRVData);
+
+ eError = ServerSyncInit();
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ /* Initialise pdump */
+ eError = PDUMPINIT();
+ if(eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
+
+ /* Register all the system devices */
+ for (i=0;i<psSysConfig->uiDeviceCount;i++)
+ {
+ if (PVRSRVRegisterDevice(&psSysConfig->pasDevices[i]) != PVRSRV_OK)
+ {
+
+ return eError;
+ }
+
+ /* Initialise the Transport Layer.
+ * Need to remember the RGX device node for use in the Transport Layer
+ * when allocating stream buffers that are shared with clients.
+ * Note however when the device is an LMA device our buffers will not
+ * be in host memory but card memory.
+ */
+ if (gpsPVRSRVData->apsRegisteredDevNodes[gpsPVRSRVData->ui32RegisteredDevices-1]->psDevConfig->eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
+ {
+ eError = TLInit(gpsPVRSRVData->apsRegisteredDevNodes[gpsPVRSRVData->ui32RegisteredDevices-1]);
+ PVR_LOGG_IF_ERROR(eError, "TLInit", Error);
+ }
+ }
+
+ /* Create the clean up event object */
+ eError = OSEventObjectCreate("PVRSRV_CLEANUP_EVENTOBJECT", &gpsPVRSRVData->hCleanupEventObject);
+ PVR_LOGG_IF_ERROR(eError, "OSEventObjectCreate", Error);
+
+ eError = PVRSRVResManCreateDeferContext(gpsPVRSRVData->hCleanupEventObject,
+ &gpsPVRSRVData->hResManDeferContext);
+ PVR_LOGG_IF_ERROR(eError, "PVRSRVResManCreateDeferContext", Error);
+
+ g_ui32InitFlags |= INIT_GLOBAL_RESMAN;
+
+ /* Create a thread which is used to do the deferred cleanup running with the
+ * lowest priority */
+ eError = OSThreadCreatePriority(&gpsPVRSRVData->hCleanupThread,
+ "pvr_defer_free",
+ CleanupThread,
+ gpsPVRSRVData,
+ LOWEST_PRIORITY);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInit: Failed to create deferred cleanup thread"));
+ goto Error;
+ }
+
+ /* Create the devices watchdog event object */
+ eError = OSEventObjectCreate("PVRSRV_DEVICESWATCHDOG_EVENTOBJECT", &gpsPVRSRVData->hDevicesWatchdogEvObj);
+ PVR_LOGG_IF_ERROR(eError, "OSEventObjectCreate", Error);
+
+ /* Create a thread which is used to detect fatal errors */
+ eError = OSThreadCreate(&gpsPVRSRVData->hDevicesWatchdogThread,
+ "pvr_devices_wd_thread",
+ DevicesWatchdogThread,
+ gpsPVRSRVData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInit: Failed to create devices watchdog thread"));
+ goto Error;
+ }
+
+#if defined(PVR_TESTING_UTILS)
+ TUtilsInit();
+#endif
+
+ return eError;
+
+Error:
+ PVRSRVDeInit();
+ return eError;
+}
+
+
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(IMG_VOID)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+
+ if (gpsPVRSRVData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit failed - invalid gpsPVRSRVData"));
+ return;
+ }
+
+#if defined(PVR_TESTING_UTILS)
+ TUtilsDeinit();
+#endif
+
+#if defined (SUPPORT_RGX)
+ sUnregisterDevice[PVRSRV_DEVICE_TYPE_RGX] = DevDeInitRGX;
+#endif
+
+ psPVRSRVData->bUnload = IMG_TRUE;
+ if (psPVRSRVData->hGlobalEventObject)
+ {
+ OSEventObjectSignal(psPVRSRVData->hGlobalEventObject);
+ }
+
+ /* Stop and cleanup the devices watchdog thread */
+ if (psPVRSRVData->hDevicesWatchdogThread)
+ {
+ if (psPVRSRVData->hDevicesWatchdogEvObj)
+ {
+ eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj);
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+ }
+ eError = OSThreadDestroy(gpsPVRSRVData->hDevicesWatchdogThread);
+ gpsPVRSRVData->hDevicesWatchdogThread = IMG_NULL;
+ PVR_LOG_IF_ERROR(eError, "OSThreadDestroy");
+ }
+
+ if (gpsPVRSRVData->hDevicesWatchdogEvObj)
+ {
+ eError = OSEventObjectDestroy(gpsPVRSRVData->hDevicesWatchdogEvObj);
+ gpsPVRSRVData->hDevicesWatchdogEvObj = IMG_NULL;
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
+ }
+
+ /* Stop and cleanup the deferred clean up thread, event object and
+ * deferred context list.
+ */
+ if (psPVRSRVData->hCleanupThread)
+ {
+ if (psPVRSRVData->hCleanupEventObject)
+ {
+ eError = OSEventObjectSignal(psPVRSRVData->hCleanupEventObject);
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+ }
+ eError = OSThreadDestroy(gpsPVRSRVData->hCleanupThread);
+ gpsPVRSRVData->hCleanupThread = IMG_NULL;
+ PVR_LOG_IF_ERROR(eError, "OSThreadDestroy");
+ }
+
+ if (gpsPVRSRVData->hCleanupEventObject)
+ {
+ eError = OSEventObjectDestroy(gpsPVRSRVData->hCleanupEventObject);
+ gpsPVRSRVData->hCleanupEventObject = IMG_NULL;
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
+ }
+
+ if (g_ui32InitFlags & INIT_GLOBAL_RESMAN)
+ {
+ PVRSRVResManDestroyDeferContext(gpsPVRSRVData->hResManDeferContext);
+ }
+
+ /* Unregister all the system devices */
+ for (i=0;i<psPVRSRVData->ui32RegisteredDevices;i++)
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[i];
+
+ /* set device state */
+ psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_DEINIT;
+
+ /* Counter part to what gets done in PVRSRVFinaliseSystem */
+ if (psDeviceNode->hSyncPrimContext != IMG_NULL)
+ {
+ if (psDeviceNode->psSyncPrim != IMG_NULL)
+ {
+ /* Free general pupose sync primitive */
+ SyncPrimFree(psDeviceNode->psSyncPrim);
+ psDeviceNode->psSyncPrim = IMG_NULL;
+ }
+ if (psDeviceNode->psSyncPrimPreKick != IMG_NULL)
+ {
+ /* Free PreKick sync primitive */
+ SyncPrimFree(psDeviceNode->psSyncPrimPreKick);
+ psDeviceNode->psSyncPrimPreKick = IMG_NULL;
+ }
+
+ SyncPrimContextDestroy(psDeviceNode->hSyncPrimContext);
+ psDeviceNode->hSyncPrimContext = IMG_NULL;
+ }
+
+ PVRSRVUnregisterDevice(psDeviceNode);
+ psPVRSRVData->apsRegisteredDevNodes[i] = IMG_NULL;
+ }
+ SysDestroyConfigData(gpsSysConfig);
+
+ /* Clean up Transport Layer resources that remain.
+ * Done after RGX node clean up as HWPerf stream is destroyed during
+ * this
+ */
+ TLDeInit();
+
+ ServerSyncDeinit();
+
+ if (g_hDbgSysNotify)
+ {
+ PVRSRVUnregisterDbgRequestNotify(g_hDbgSysNotify);
+ }
+
+ if (g_hDebugTable)
+ {
+ PVRSRVUnregisterDbgTable(g_hDebugTable);
+ }
+
+ if (g_hDbgNotifyLock)
+ {
+ OSWRLockDestroy(g_hDbgNotifyLock);
+ }
+
+ if (hNotifyLock)
+ {
+ OSWRLockDestroy(hNotifyLock);
+ }
+
+ /* deinitialise pdump */
+ if ((g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
+ {
+ PDUMPDEINIT();
+ }
+
+ /* destroy event object */
+ if (gpsPVRSRVData->hGlobalEventObject)
+ {
+ OSEventObjectDestroy(gpsPVRSRVData->hGlobalEventObject);
+ gpsPVRSRVData->hGlobalEventObject = IMG_NULL;
+ }
+
+ /* Check there is no notify function */
+ if (!dllist_is_empty(&sCmdCompNotifyHead))
+ {
+ PDLLIST_NODE psNode = dllist_get_next_node(&sCmdCompNotifyHead);
+
+ /* some device did not unregistered properly */
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: Notify list for cmd complete is not empty!!"));
+
+ /* clean the nodes anyway */
+ while (psNode != IMG_NULL)
+ {
+ PVRSRV_CMDCOMP_NOTIFY *psNotify;
+
+ dllist_remove_node(psNode);
+
+ psNotify = IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
+ OSFreeMem(psNotify);
+
+ psNode = dllist_get_next_node(&sCmdCompNotifyHead);
+ }
+ }
+
+ OSLockDestroy(gpsPVRSRVData->hPowerLock);
+
+ eError = PVRSRVHandleDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
+ }
+
+#if !defined(UNDER_WDDM) && defined(SUPPORT_DISPLAY_CLASS)
+ eError = DCDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: DCInit() failed"));
+ }
+#endif
+
+
+ eError = PMRDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PMRDeInit() failed"));
+ }
+
+#if defined(PVR_RI_DEBUG)
+ RIDeInitKM();
+#endif
+
+ eError = PVRSRVConnectionDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVConnectionDataDeInit failed"));
+ }
+
+ ResManDeInit();
+
+ OSDeInitEnvData();
+
+ for (i=0;i<gpsPVRSRVData->ui32RegisteredPhysHeaps;i++)
+ {
+ PhysHeapUnregister(gpsPVRSRVData->apsRegisteredPhysHeaps[i]);
+ }
+ eError = PhysHeapDeinit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PhysHeapDeinit() failed"));
+ }
+
+ OSFreeMem(gpsPVRSRVData);
+ gpsPVRSRVData = IMG_NULL;
+}
+
+PVRSRV_ERROR LMA_MMUPxAlloc(PVRSRV_DEVICE_NODE *psDevNode, IMG_SIZE_T uiSize,
+ Px_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr)
+{
+ IMG_BOOL bSuccess;
+ RA_BASE_T uiCardAddr;
+ RA_LENGTH_T uiActualSize;
+
+ PVR_ASSERT((uiSize & OSGetPageMask()) == 0);
+
+ bSuccess = RA_Alloc(psDevNode->psLocalDevMemArena,
+ uiSize,
+ 0, /* No flags */
+ OSGetPageSize(),
+ &uiCardAddr,
+ &uiActualSize,
+ IMG_NULL); /* No private handle */
+
+ PVR_ASSERT(uiSize == uiActualSize);
+
+ psMemHandle->u.ui64Handle = uiCardAddr;
+ psDevPAddr->uiAddr = (IMG_UINT64) uiCardAddr;
+
+ if (bSuccess)
+ {
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Allocation is done a page at a time */
+ PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, OSGetPageSize());
+#else
+ IMG_CPU_PHYADDR sCpuPAddr;
+ sCpuPAddr.uiAddr = psDevPAddr->uiAddr;
+ PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
+ IMG_NULL,
+ sCpuPAddr,
+ OSGetPageSize(),
+ IMG_NULL);
+#endif
+#endif
+ return PVRSRV_OK;
+ }
+ else
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+IMG_VOID LMA_MMUPxFree(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle)
+{
+ RA_BASE_T uiCardAddr = (RA_BASE_T) psMemHandle->u.ui64Handle;
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Allocation is done a page at a time */
+ PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, OSGetPageSize());
+#else
+ PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, (IMG_UINT64)uiCardAddr);
+#endif
+#endif
+
+ RA_Free(psDevNode->psLocalDevMemArena, uiCardAddr);
+}
+
+PVRSRV_ERROR LMA_MMUPxMap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle,
+ IMG_SIZE_T uiSize, IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_VOID **pvPtr)
+{
+ IMG_CPU_PHYADDR sCpuPAddr;
+ PVR_UNREFERENCED_PARAMETER(psMemHandle);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
+
+ PhysHeapDevPAddrToCpuPAddr(psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &sCpuPAddr, psDevPAddr);
+ *pvPtr = OSMapPhysToLin(sCpuPAddr,
+ OSGetPageSize(),
+ 0);
+ if (*pvPtr == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Mapping is done a page at a time */
+ PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, OSGetPageSize());
+#else
+ {
+ PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
+ *pvPtr,
+ sCpuPAddr,
+ uiSize,
+ IMG_NULL);
+ }
+#endif
+#endif
+ return PVRSRV_OK;
+ }
+}
+
+IMG_VOID LMA_MMUPxUnmap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle,
+ IMG_VOID *pvPtr)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemHandle);
+ PVR_UNREFERENCED_PARAMETER(psDevNode);
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Mapping is done a page at a time */
+ PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, OSGetPageSize());
+#else
+ PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, (IMG_UINT64)(IMG_UINTPTR_T)pvPtr);
+#endif
+#endif
+
+ OSUnMapPhysToLin(pvPtr, OSGetPageSize(), 0);
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterDevice
+
+ @Description
+
+ registers a device with the system
+
+ @Input psDevConfig : Device configuration structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+static PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PVRSRV_DEVICE_CONFIG *psDevConfig)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_DEVICE_PHYS_HEAP physHeapIndex;
+
+ /* Allocate device node */
+ psDeviceNode = OSAllocMem(sizeof(PVRSRV_DEVICE_NODE));
+ if (psDeviceNode == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+ OSMemSet(psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ /* set device state */
+ psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_INIT;
+
+ eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL physical memory heap"));
+ goto e1;
+ }
+ eError = PhysHeapAcquire(psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL], &psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to acquire PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL physical memory heap"));
+ goto e1;
+ }
+
+ /* Do we have card memory? If so create an RA to manage it */
+ if (PhysHeapGetType(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]) == PHYS_HEAP_TYPE_LMA)
+ {
+ RA_BASE_T uBase;
+ RA_LENGTH_T uSize;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_UINT64 ui64Size;
+
+ eError = PhysHeapGetAddress(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &sCpuPAddr);
+ if (eError != PVRSRV_OK)
+ {
+ /* We can only get here if there is a bug in this module */
+ PVR_ASSERT(IMG_FALSE);
+ return eError;
+ }
+
+ eError = PhysHeapGetSize(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL], &ui64Size);
+ if (eError != PVRSRV_OK)
+ {
+ /* We can only get here if there is a bug in this module */
+ PVR_ASSERT(IMG_FALSE);
+ return eError;
+ }
+
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Creating RA for card memory 0x%016llx-0x%016llx",
+ (IMG_UINT64) sCpuPAddr.uiAddr, sCpuPAddr.uiAddr + ui64Size));
+
+ OSSNPrintf(psDeviceNode->szRAName, sizeof(psDeviceNode->szRAName),
+ "%s card mem",
+ psDevConfig->pszName);
+
+ uBase = 0;
+ if (psDevConfig->uiFlags & PVRSRV_DEVICE_CONFIG_LMA_USE_CPU_ADDR)
+ {
+ uBase = sCpuPAddr.uiAddr;
+ }
+
+ uSize = (RA_LENGTH_T) ui64Size;
+ PVR_ASSERT(uSize == ui64Size);
+
+ psDeviceNode->psLocalDevMemArena =
+ RA_Create(psDeviceNode->szRAName,
+ OSGetPageShift(), /* Use host page size, keeps things simple */
+ RA_LOCKCLASS_0, /* This arena doesn't use any other arenas. */
+ IMG_NULL, /* No Import */
+ IMG_NULL, /* No free import */
+ IMG_NULL); /* No import handle */
+
+ if (psDeviceNode->psLocalDevMemArena == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e2;
+ }
+
+ if (!RA_Add(psDeviceNode->psLocalDevMemArena, uBase, uSize, 0 /* No flags */, IMG_NULL /* No private data */))
+ {
+ RA_Delete(psDeviceNode->psLocalDevMemArena);
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e2;
+ }
+
+
+ psDeviceNode->pfnMMUPxAlloc = LMA_MMUPxAlloc;
+ psDeviceNode->pfnMMUPxFree = LMA_MMUPxFree;
+ psDeviceNode->pfnMMUPxMap = LMA_MMUPxMap;
+ psDeviceNode->pfnMMUPxUnmap = LMA_MMUPxUnmap;
+ psDeviceNode->uiMMUPxLog2AllocGran = OSGetPageShift();
+ psDeviceNode->ui32Flags = PRVSRV_DEVICE_FLAGS_LMA;
+ psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] = PhysmemNewLocalRamBackedPMR;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "===== OS System memory only, no local card memory"));
+
+ /* else we only have OS system memory */
+ psDeviceNode->pfnMMUPxAlloc = OSMMUPxAlloc;
+ psDeviceNode->pfnMMUPxFree = OSMMUPxFree;
+ psDeviceNode->pfnMMUPxMap = OSMMUPxMap;
+ psDeviceNode->pfnMMUPxUnmap = OSMMUPxUnmap;
+ psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] = PhysmemNewOSRamBackedPMR;
+ }
+
+ if (PhysHeapGetType(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL]) == PHYS_HEAP_TYPE_LMA)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "===== Local card memory only, no OS system memory"));
+ psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL] = PhysmemNewLocalRamBackedPMR;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "===== OS System memory, 2nd phys heap"));
+ psDeviceNode->pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL] = PhysmemNewOSRamBackedPMR;
+ }
+
+
+ psDeviceNode->pszMMUPxPDumpMemSpaceName = PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
+ psDeviceNode->uiMMUPxLog2AllocGran = OSGetPageShift();
+
+ /* Add the devnode to our list so we can unregister it later */
+ psPVRSRVData->apsRegisteredDevNodes[psPVRSRVData->ui32RegisteredDevices++] = psDeviceNode;
+
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->psDevConfig = psDevConfig;
+
+ /* all devices need a unique identifier */
+ AllocateDeviceID(psPVRSRVData, &psDeviceNode->sDevId.ui32DeviceIndex);
+
+ /* Device type and class will be setup during this callback */
+ eError = sRegisterDevice[psDevConfig->eDeviceType](psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ /*not nulling pointer, out of scope*/
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
+ eError = PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
+ goto e3;
+ }
+
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Registered device %d of type %d", psDeviceNode->sDevId.ui32DeviceIndex, psDeviceNode->sDevId.eDeviceType));
+ PVR_DPF((PVR_DBG_MESSAGE, "Register bank address = 0x%08lx", (unsigned long)psDevConfig->sRegsCpuPBase.uiAddr));
+ PVR_DPF((PVR_DBG_MESSAGE, "IRQ = %d", psDevConfig->ui32IRQ));
+
+ /* and finally insert the device into the dev-list */
+ List_PVRSRV_DEVICE_NODE_Insert(&psPVRSRVData->psDeviceNodeList, psDeviceNode);
+
+ /* set device state */
+ psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_ACTIVE;
+
+ return PVRSRV_OK;
+e3:
+ if (psDeviceNode->psLocalDevMemArena)
+ {
+ RA_Delete(psDeviceNode->psLocalDevMemArena);
+ }
+e2:
+e1:
+ for(physHeapIndex=0; physHeapIndex < PVRSRV_DEVICE_PHYS_HEAP_LAST; physHeapIndex++)
+ {
+ if (psDeviceNode->apsPhysHeap[physHeapIndex])
+ {
+ PhysHeapRelease(psDeviceNode->apsPhysHeap[physHeapIndex]);
+ }
+ }
+ OSFreeMem(psDeviceNode);
+e0:
+ return eError;
+}
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(bForced);
+
+ if (gpsSysConfig->pfnSysPrePowerState)
+ {
+ eError = gpsSysConfig->pfnSysPrePowerState(eNewPowerState);
+ }
+ return eError;
+}
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(bForced);
+
+ if (gpsSysConfig->pfnSysPostPowerState)
+ {
+ eError = gpsSysConfig->pfnSysPostPowerState(eNewPowerState);
+ }
+ return eError;
+}
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 *pui32DeviceIndex,
+ IMG_UINT32 ui32PhysHeapID)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PHYS_HEAP *psPhysHeapTmp;
+ PVRSRV_DEVICE_PHYS_HEAP eDevPhysHeap;
+ PVRSRV_ERROR eError;
+
+ psDeviceNode->ui32RefCount = 1;
+
+ eError = PhysHeapAcquire(ui32PhysHeapID, &psPhysHeapTmp);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterExtDevice: Failed to acquire physical memory heap"));
+ goto e0;
+ }
+ if (PhysHeapGetType(psPhysHeapTmp) == PHYS_HEAP_TYPE_LMA)
+ {
+ eDevPhysHeap = PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL;
+ }
+ else
+ {
+ eDevPhysHeap = PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL;
+ }
+ psDeviceNode->apsPhysHeap[eDevPhysHeap] = psPhysHeapTmp;
+
+ /* allocate a unique device id */
+ eError = AllocateDeviceID(psPVRSRVData, &psDeviceNode->sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterExtDevice: Failed to allocate Device ID"));
+ goto e1;
+ }
+
+ if (pui32DeviceIndex)
+ {
+ *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psPVRSRVData->psDeviceNodeList, psDeviceNode);
+
+ return PVRSRV_OK;
+e1:
+ PhysHeapRelease(psDeviceNode->apsPhysHeap[eDevPhysHeap]);
+e0:
+ return eError;
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVUnregisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_DEVICE_PHYS_HEAP eDevPhysHeap;
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+ (IMG_VOID)FreeDeviceID(psPVRSRVData, psDeviceNode->sDevId.ui32DeviceIndex);
+ for (eDevPhysHeap = 0; eDevPhysHeap < PVRSRV_DEVICE_PHYS_HEAP_LAST; eDevPhysHeap++)
+ {
+ if (psDeviceNode->apsPhysHeap[eDevPhysHeap])
+ {
+ PhysHeapRelease(psDeviceNode->apsPhysHeap[eDevPhysHeap]);
+ }
+ }
+}
+
+static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEV_POWER_STATE ePowState;
+
+ ePowState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ ePowState,
+ IMG_TRUE);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (%s, device index: %d)",
+ PVRSRVGetErrorStringKM(eError),
+ psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+
+ return eError;
+}
+
+/*wraps the PVRSRVDevInitCompatCheck call and prints a debugging message if failed*/
+static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_Any_va(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 *pui32ClientBuildOptions;
+
+ pui32ClientBuildOptions = va_arg(va, IMG_UINT32*);
+
+ eError = PVRSRVDevInitCompatCheck(psDeviceNode, *pui32ClientBuildOptions);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVFinaliseSystem
+
+ @Description
+
+ Final part of system initialisation.
+
+ @Input ui32DevIndex : Index to the required device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful, IMG_UINT32 ui32ClientBuildOptions)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
+
+ if (bInitSuccessful)
+ {
+ for (i=0;i<psPVRSRVData->ui32RegisteredDevices;i++)
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = psPVRSRVData->apsRegisteredDevNodes[i];
+
+ SyncPrimContextCreate(IMG_NULL,
+ psDeviceNode,
+ &psDeviceNode->hSyncPrimContext);
+
+ /* Allocate general purpose sync primitive */
+ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psDeviceNode->psSyncPrim, "pvrsrv dev general");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed to allocate sync primitive with error (%u)", eError));
+ return eError;
+ }
+ /* Allocate PreKick sync primitive */
+ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psDeviceNode->psSyncPrimPreKick, "pvrsrv pre kick");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed to allocate PreKick sync primitive with error (%u)", eError));
+ return eError;
+ }
+
+ }
+
+ eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem_SetPowerState_AnyCb: Failed to acquire power lock"));
+ return eError;
+ }
+
+ /* Always ensure a single power on command appears in the pdump.
+ * This should be the only power related call outside of PDUMPPOWCMDSTART/END.
+ * Place all devices into ON power state. */
+ eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
+ &PVRSRVFinaliseSystem_SetPowerState_AnyCb,
+ PVRSRV_DEV_POWER_STATE_ON);
+ if (eError != PVRSRV_OK)
+ {
+ PVRSRVPowerUnlock();
+ return eError;
+ }
+
+ /* Verify firmware compatibility for devices */
+ eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
+ &PVRSRVFinaliseSystem_CompatCheck_Any_va,
+ &ui32ClientBuildOptions);
+ if (eError != PVRSRV_OK)
+ {
+ PVRSRVPowerUnlock();
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
+ return eError;
+ }
+
+ PDUMPPOWCMDSTART();
+ /* Place all devices into their default power state. */
+ eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psPVRSRVData->psDeviceNodeList,
+ &PVRSRVFinaliseSystem_SetPowerState_AnyCb,
+ PVRSRV_DEV_POWER_STATE_DEFAULT);
+ PDUMPPOWCMDEND();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVRSRVPowerUnlock();
+ return eError;
+ }
+
+ PVRSRVPowerUnlock();
+
+ }
+
+ eError = PDumpStopInitPhaseKM(IMG_SRV_INIT);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Failed to stop PDump init phase"));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode,IMG_UINT32 ui32ClientBuildOptions)
+{
+ /* Only check devices which specify a compatibility check callback */
+ if (psDeviceNode->pfnInitDeviceCompatCheck)
+ return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode, ui32ClientBuildOptions);
+ else
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVAcquireDeviceDataKM
+
+ @Description
+
+ Matchs a device given a device type and a device index.
+
+ @input psDeviceNode :The device node to be matched.
+
+ @Input va : Variable argument list with:
+ eDeviceType : Required device type. If type is unknown use ui32DevIndex
+ to locate device data
+
+ ui32DevIndex : Index to the required device obtained from the
+ PVRSRVEnumerateDevice function
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ IMG_UINT32 ui32DevIndex;
+
+ eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
+ ui32DevIndex = va_arg(va, IMG_UINT32);
+
+ if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
+ (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
+ {
+ return psDeviceNode;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVAcquireDeviceDataKM
+
+ @Description
+
+ Returns device information
+
+ @Input ui32DevIndex : Index to the required device obtained from the
+ PVRSRVEnumerateDevice function
+
+ @Input eDeviceType : Required device type. If type is unknown use ui32DevIndex
+ to locate device data
+
+ @Output *phDevCookie : Dev Cookie
+
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
+ PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE *phDevCookie)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
+
+ /* Find device in the list */
+ psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ &PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
+ eDeviceType,
+ ui32DevIndex);
+
+
+ if (!psDeviceNode)
+ {
+ /* device can't be found in the list so it isn't in the system */
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+/*FoundDevice:*/
+
+ PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+ /* return the dev cookie? */
+ if (phDevCookie)
+ {
+ *phDevCookie = (IMG_HANDLE)psDeviceNode;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseDeviceDataKM (IMG_HANDLE hDevCookie)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ /*
+ Empty release body as the lifetime of this resource accessed by
+ PVRSRVAcquireDeviceDataKM is linked to driver lifetime, not API allocation.
+ This is one reason why this type crosses the bridge with a shared handle.
+ Thus no server release action is required, just bridge action to ensure
+ associated handle is freed.
+ */
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVUnregisterDevice
+
+ @Description
+
+ This De-inits device
+
+ @Input ui32DevIndex : Index to the required device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+static PVRSRV_ERROR IMG_CALLCONV PVRSRVUnregisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_DEVICE_PHYS_HEAP ePhysHeapIdx;
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVUnregisterDevice: Failed to acquire power lock"));
+ return eError;
+ }
+
+ /*
+ Power down the device if necessary.
+ */
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ IMG_TRUE);
+
+ PVRSRVPowerUnlock();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVUnregisterDevice: Failed PVRSRVSetDevicePowerStateKM call (%s). Dump debug.", PVRSRVGetErrorStringKM(eError)));
+
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
+
+ /* If the driver is okay then return the error, otherwise we can ignore this error. */
+ if (PVRSRVGetPVRSRVData()->eServicesState == PVRSRV_SERVICES_STATE_OK)
+ {
+ return eError;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVUnregisterDevice: Will continue to unregister as driver status is not OK"));
+ }
+ }
+
+ /*
+ De-init the device.
+ */
+ sUnregisterDevice[psDeviceNode->sDevId.eDeviceType](psDeviceNode);
+
+ /* Remove RA for local card memory */
+ if (psDeviceNode->psLocalDevMemArena)
+ {
+ RA_Delete(psDeviceNode->psLocalDevMemArena);
+ }
+
+ /* remove node from list */
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+ /* deallocate id and memory */
+ (IMG_VOID)FreeDeviceID(psPVRSRVData, psDeviceNode->sDevId.ui32DeviceIndex);
+
+ for (ePhysHeapIdx = 0; ePhysHeapIdx < PVRSRV_DEVICE_PHYS_HEAP_LAST; ePhysHeapIdx++)
+ {
+ if (psDeviceNode->apsPhysHeap[ePhysHeapIdx])
+ {
+ PhysHeapRelease(psDeviceNode->apsPhysHeap[ePhysHeapIdx]);
+ }
+ }
+
+ OSFreeMem(psDeviceNode);
+ /*not nulling pointer, out of scope*/
+
+ return (PVRSRV_OK);
+}
+
+
+/*
+ PollForValueKM
+*/
+static
+PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Timeoutus,
+ IMG_UINT32 ui32PollPeriodus,
+ IMG_BOOL bAllowPreemption)
+{
+#if defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(pui32LinMemAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ PVR_UNREFERENCED_PARAMETER(ui32Mask);
+ PVR_UNREFERENCED_PARAMETER(ui32Timeoutus);
+ PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus);
+ PVR_UNREFERENCED_PARAMETER(bAllowPreemption);
+ return PVRSRV_OK;
+#else
+ IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU; /* Initialiser only required to prevent incorrect warning */
+
+ if (bAllowPreemption)
+ {
+ PVR_ASSERT(ui32PollPeriodus >= 1000);
+ }
+
+ LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
+ {
+ ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
+ if(ui32ActualValue == ui32Value)
+ {
+ return PVRSRV_OK;
+ }
+
+ if (gpsPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+ {
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+
+ if (bAllowPreemption)
+ {
+ OSSleepms(ui32PollPeriodus / 1000);
+ }
+ else
+ {
+ OSWaitus(ui32PollPeriodus);
+ }
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
+ ui32Value, ui32ActualValue, ui32Mask));
+
+ return PVRSRV_ERROR_TIMEOUT;
+#endif /* NO_HARDWARE */
+}
+
+
+/*
+ PVRSRVPollForValueKM
+*/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPollForValueKM (volatile IMG_UINT32 *pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask)
+{
+ return PollForValueKM(pui32LinMemAddr, ui32Value, ui32Mask,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE);
+}
+
+/*
+ PVRSRVWaitForValueKM
+*/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWaitForValueKM (volatile IMG_UINT32 *pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask)
+{
+#if defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(pui32LinMemAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ PVR_UNREFERENCED_PARAMETER(ui32Mask);
+ return PVRSRV_OK;
+#else
+
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ IMG_HANDLE hOSEvent;
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eErrorWait;
+ IMG_UINT32 ui32ActualValue;
+
+ eError = OSEventObjectOpen(psPVRSRVData->hGlobalEventObject, &hOSEvent);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWaitForValueKM: Failed to setup EventObject with error (%d)", eError));
+ goto EventObjectOpenError;
+ }
+
+ eError = PVRSRV_ERROR_TIMEOUT;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
+
+ if (ui32ActualValue == ui32Value)
+ {
+ /* Expected value has been found */
+ eError = PVRSRV_OK;
+ break;
+ }
+ else if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+ {
+ /* Services in bad state, don't wait any more */
+ eError = PVRSRV_ERROR_NOT_READY;
+ break;
+ }
+ else
+ {
+ /* wait for event and retry */
+ eErrorWait = OSEventObjectWait(hOSEvent);
+ if (eErrorWait != PVRSRV_OK && eErrorWait != PVRSRV_ERROR_TIMEOUT)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"PVRSRVWaitForValueKM: Waiting for value failed with error %d. Expected 0x%x but found 0x%x (Mask 0x%08x). Retrying",
+ eErrorWait,
+ ui32Value,
+ ui32ActualValue,
+ ui32Mask));
+ }
+ }
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ OSEventObjectClose(hOSEvent);
+
+ /* One last check incase the object wait ended after the loop timeout... */
+ if (eError != PVRSRV_OK && (*pui32LinMemAddr & ui32Mask) == ui32Value)
+ {
+ eError = PVRSRV_OK;
+ }
+
+ /* Provide event timeout information to aid the Device Watchdog Thread... */
+ if (eError == PVRSRV_OK)
+ {
+ psPVRSRVData->ui32GEOConsecutiveTimeouts = 0;
+ }
+ else if (eError == PVRSRV_ERROR_TIMEOUT)
+ {
+ psPVRSRVData->ui32GEOConsecutiveTimeouts++;
+ }
+
+EventObjectOpenError:
+
+ return eError;
+
+#endif /* NO_HARDWARE */
+}
+
+#if !defined(NO_HARDWARE)
+static IMG_BOOL _CheckStatus(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle = (PVRSRV_CMDCOMP_HANDLE) pvCallbackData;
+ PVRSRV_CMDCOMP_NOTIFY *psNotify;
+
+ psNotify = IMG_CONTAINER_OF(psNode, PVRSRV_CMDCOMP_NOTIFY, sListNode);
+
+ /* A device has finished some processing, check if that unblocks other devices */
+ if (hCmdCompCallerHandle != psNotify->hCmdCompHandle)
+ {
+ psNotify->pfnCmdCompleteNotify(psNotify->hCmdCompHandle);
+ }
+
+ /* keep processing until the end of the list */
+ return IMG_TRUE;
+}
+#endif
+
+IMG_VOID IMG_CALLCONV PVRSRVCheckStatus(PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ /* notify any registered device to check if block work items can now proceed */
+#if !defined(NO_HARDWARE)
+ OSWRLockAcquireRead(hNotifyLock, GLOBAL_NOTIFY);
+ dllist_foreach_node(&sCmdCompNotifyHead, _CheckStatus, hCmdCompCallerHandle);
+ OSWRLockReleaseRead(hNotifyLock);
+#endif
+
+ /* signal global event object */
+ if (psPVRSRVData->hGlobalEventObject)
+ {
+ IMG_HANDLE hOSEventKM = psPVRSRVData->hGlobalEventObject;
+ if(hOSEventKM)
+ {
+ OSEventObjectSignal(hOSEventKM);
+ }
+ }
+}
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVKickDevicesKM(IMG_VOID)
+{
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVKickDevicesKM"));
+ PVRSRVCheckStatus(IMG_NULL);
+ return PVRSRV_OK;
+}
+
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVGetErrorStringKM
+
+ @Description Returns a text string relating to the PVRSRV_ERROR enum.
+
+ @Note case statement used rather than an indexed arrary to ensure text is
+ synchronised with the correct enum
+
+ @Input eError : PVRSRV_ERROR enum
+
+ @Return const IMG_CHAR * : Text string
+
+ @Note Must be kept in sync with servicesext.h
+
+******************************************************************************/
+
+IMG_EXPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
+{
+ switch(eError)
+ {
+ case PVRSRV_OK:
+ return "PVRSRV_OK";
+#define PVRE(x) \
+ case x: \
+ return #x;
+#include "pvrsrv_errors.h"
+#undef PVRE
+ default:
+ return "Unknown PVRSRV error number";
+ }
+}
+
+/*
+ PVRSRVSystemDebugInfo
+ */
+PVRSRV_ERROR PVRSRVSystemDebugInfo( DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ return SysDebugInfo(gpsSysConfig, pfnDumpDebugPrintf);
+}
+
+/*
+ PVRSRVGetSystemName
+*/
+const IMG_CHAR *PVRSRVGetSystemName(IMG_VOID)
+{
+ return gpsSysConfig->pszSystemName;
+}
+
+/*
+ PVRSRVSystemHasCacheSnooping
+*/
+IMG_BOOL PVRSRVSystemHasCacheSnooping(IMG_VOID)
+{
+ if (gpsSysConfig->eCacheSnoopingMode != PVRSRV_SYSTEM_SNOOP_NONE)
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+IMG_BOOL PVRSRVSystemSnoopingOfCPUCache(IMG_VOID)
+{
+ if ((gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_CPU_ONLY) ||
+ (gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_CROSS))
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+IMG_BOOL PVRSRVSystemSnoopingOfDeviceCache(IMG_VOID)
+{
+ if ((gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_DEVICE_ONLY) ||
+ (gpsSysConfig->eCacheSnoopingMode == PVRSRV_SYSTEM_SNOOP_CROSS))
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+/*
+ PVRSRVSystemWaitCycles
+*/
+IMG_VOID PVRSRVSystemWaitCycles(PVRSRV_DEVICE_CONFIG *psDevConfig, IMG_UINT32 ui32Cycles)
+{
+ /* Delay in us */
+ IMG_UINT32 ui32Delayus = 1;
+
+ /* obtain the device freq */
+ if (psDevConfig->pfnClockFreqGet != IMG_NULL)
+ {
+ IMG_UINT32 ui32DeviceFreq;
+
+ ui32DeviceFreq = psDevConfig->pfnClockFreqGet(psDevConfig->hSysData);
+
+ ui32Delayus = (ui32Cycles*1000000)/ui32DeviceFreq;
+
+ if (ui32Delayus == 0)
+ {
+ ui32Delayus = 1;
+ }
+ }
+
+ OSWaitus(ui32Delayus);
+}
+
+/*
+ PVRSRVRegisterCmdCompleteNotify
+*/
+PVRSRV_ERROR PVRSRVRegisterCmdCompleteNotify(IMG_HANDLE *phNotify, PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify, PVRSRV_CMDCOMP_HANDLE hCmdCompHandle)
+{
+ PVRSRV_CMDCOMP_NOTIFY *psNotify;
+
+ if ((phNotify == IMG_NULL) || (pfnCmdCompleteNotify == IMG_NULL) || (hCmdCompHandle == IMG_NULL))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p, %p, %p)", __FUNCTION__, phNotify, pfnCmdCompleteNotify, hCmdCompHandle));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psNotify = OSAllocMem(sizeof(*psNotify));
+ if (psNotify == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Not enough memory to allocate CmdCompleteNotify function", __FUNCTION__));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Set-up the notify data */
+ psNotify->hCmdCompHandle = hCmdCompHandle;
+ psNotify->pfnCmdCompleteNotify = pfnCmdCompleteNotify;
+
+ /* Add it to the list of Notify functions */
+ OSWRLockAcquireWrite(hNotifyLock, GLOBAL_NOTIFY);
+ dllist_add_to_tail(&sCmdCompNotifyHead, &psNotify->sListNode);
+ OSWRLockReleaseWrite(hNotifyLock);
+
+ *phNotify = psNotify;
+
+ return PVRSRV_OK;
+}
+
+/*
+ PVRSRVUnregisterCmdCompleteNotify
+*/
+PVRSRV_ERROR PVRSRVUnregisterCmdCompleteNotify(IMG_HANDLE hNotify)
+{
+ PVRSRV_CMDCOMP_NOTIFY *psNotify = (PVRSRV_CMDCOMP_NOTIFY*) hNotify;
+
+ if (psNotify == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p)", __FUNCTION__, hNotify));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* remove the node from the list */
+ OSWRLockAcquireWrite(hNotifyLock, GLOBAL_NOTIFY);
+ dllist_remove_node(&psNotify->sListNode);
+ OSWRLockReleaseWrite(hNotifyLock);
+
+ /* free the notify structure that holds the node */
+ OSFreeMem(psNotify);
+
+ return PVRSRV_OK;
+
+}
+
+static IMG_VOID _SysDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA*) hDebugRequestHandle;
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = IMG_NULL;
+
+ pfnDumpDebugPrintf = g_pfnDumpDebugPrintf;
+ /* only dump info on the lowest verbosity level */
+ if (ui32VerbLevel != DEBUG_REQUEST_VERBOSITY_LOW)
+ {
+ return;
+ }
+
+ PVR_DUMPDEBUG_LOG(("DDK info: %s (%s) %s", PVRVERSION_STRING, PVR_BUILD_TYPE, PVR_BUILD_DIR));
+
+ /* Services state */
+ switch (psPVRSRVData->eServicesState)
+ {
+ case PVRSRV_SERVICES_STATE_OK:
+ {
+ PVR_DUMPDEBUG_LOG(("Services State: OK"));
+ break;
+ }
+
+ case PVRSRV_SERVICES_STATE_BAD:
+ {
+ PVR_DUMPDEBUG_LOG(("Services State: BAD"));
+ break;
+ }
+
+ default:
+ {
+ PVR_DUMPDEBUG_LOG(("Services State: UNKNOWN (%d)", psPVRSRVData->eServicesState));
+ break;
+ }
+ }
+
+ /* Power state */
+ switch (psPVRSRVData->eCurrentPowerState)
+ {
+ case PVRSRV_SYS_POWER_STATE_OFF:
+ {
+ PVR_DUMPDEBUG_LOG(("System Power State: OFF"));
+ break;
+ }
+ case PVRSRV_SYS_POWER_STATE_ON:
+ {
+ PVR_DUMPDEBUG_LOG(("System Power State: ON"));
+ break;
+ }
+ default:
+ {
+ PVR_DUMPDEBUG_LOG(("System Power State: UNKNOWN (%d)", psPVRSRVData->eCurrentPowerState));
+ break;
+ }
+ }
+
+ /* Dump system specific debug info */
+ PVRSRVSystemDebugInfo(pfnDumpDebugPrintf);
+
+}
+
+static IMG_BOOL _DebugRequest(PDLLIST_NODE psNode, IMG_PVOID hVerbLevel)
+{
+ IMG_UINT32 *pui32VerbLevel = (IMG_UINT32 *) hVerbLevel;
+ PVRSRV_DBGREQ_NOTIFY *psNotify;
+
+ psNotify = IMG_CONTAINER_OF(psNode, PVRSRV_DBGREQ_NOTIFY, sListNode);
+
+ psNotify->pfnDbgRequestNotify(psNotify->hDbgRequestHandle, *pui32VerbLevel);
+
+ /* keep processing until the end of the list */
+ return IMG_TRUE;
+}
+
+/*
+ PVRSRVDebugRequest
+*/
+IMG_VOID IMG_CALLCONV PVRSRVDebugRequest(IMG_UINT32 ui32VerbLevel, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ IMG_UINT32 i,j;
+
+ g_pfnDumpDebugPrintf = pfnDumpDebugPrintf;
+ OSDumpStack();
+
+ /* notify any registered device to check if block work items can now proceed */
+ /* Lock the lists */
+ OSWRLockAcquireRead(g_hDbgNotifyLock, GLOBAL_DBGNOTIFY);
+
+ PVR_DUMPDEBUG_LOG(("------------[ PVR DBG: START ]------------"));
+
+ /* For each verbosity level */
+ for (j=0;j<(ui32VerbLevel+1);j++)
+ {
+ /* For each requester */
+ for (i=0;i<g_psDebugTable->ui32RequestCount;i++)
+ {
+ dllist_foreach_node(&g_psDebugTable->asEntry[i].sListHead, _DebugRequest, &j);
+ }
+ }
+ PVR_DUMPDEBUG_LOG(("------------[ PVR DBG: END ]------------"));
+
+ /* Unlock the lists */
+ OSWRLockReleaseRead(g_hDbgNotifyLock);
+}
+
+/*
+ PVRSRVRegisterDebugRequestNotify
+*/
+PVRSRV_ERROR PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify, PFN_DBGREQ_NOTIFY pfnDbgRequestNotify, IMG_UINT32 ui32RequesterID, PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
+{
+ PVRSRV_DBGREQ_NOTIFY *psNotify;
+ PDLLIST_NODE psHead = IMG_NULL;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+
+ if ((phNotify == IMG_NULL) || (pfnDbgRequestNotify == IMG_NULL))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p, %p,)", __FUNCTION__, phNotify, pfnDbgRequestNotify));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto fail_params;
+ }
+
+ psNotify = OSAllocMem(sizeof(*psNotify));
+ if (psNotify == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Not enough memory to allocate DbgRequestNotify structure", __FUNCTION__));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ /* Set-up the notify data */
+ psNotify->hDbgRequestHandle = hDbgRequestHandle;
+ psNotify->pfnDbgRequestNotify = pfnDbgRequestNotify;
+ psNotify->ui32RequesterID = ui32RequesterID;
+
+ /* Lock down all the lists */
+ OSWRLockAcquireWrite(g_hDbgNotifyLock, GLOBAL_DBGNOTIFY);
+
+ /* Find which list to add it to */
+ for (i=0;i<g_psDebugTable->ui32RequestCount;i++)
+ {
+ if (g_psDebugTable->asEntry[i].ui32RequesterID == ui32RequesterID)
+ {
+ psHead = &g_psDebugTable->asEntry[i].sListHead;
+ }
+ }
+
+ if (psHead == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Failed to find debug requester", __FUNCTION__));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto fail_add;
+ }
+
+ /* Add it to the list of Notify functions */
+ dllist_add_to_tail(psHead, &psNotify->sListNode);
+
+ /* Unlock the lists */
+ OSWRLockReleaseWrite(g_hDbgNotifyLock);
+
+ *phNotify = psNotify;
+
+ return PVRSRV_OK;
+
+fail_add:
+ OSWRLockReleaseWrite(g_hDbgNotifyLock);
+ OSFreeMem(psNotify);
+fail_alloc:
+fail_params:
+ return eError;
+}
+
+/*
+ PVRSRVUnregisterCmdCompleteNotify
+*/
+PVRSRV_ERROR PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify)
+{
+ PVRSRV_DBGREQ_NOTIFY *psNotify = (PVRSRV_DBGREQ_NOTIFY*) hNotify;
+
+ if (psNotify == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Bad arguments (%p)", __FUNCTION__, hNotify));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* remove the node from the list */
+ OSWRLockAcquireWrite(g_hDbgNotifyLock, GLOBAL_DBGNOTIFY);
+ dllist_remove_node(&psNotify->sListNode);
+ OSWRLockReleaseWrite(g_hDbgNotifyLock);
+
+ /* free the notify structure that holds the node */
+ OSFreeMem(psNotify);
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR PVRSRVRegisterDbgTable(IMG_UINT32 *paui32Table, IMG_UINT32 ui32Length, IMG_PVOID *phTable)
+{
+ IMG_UINT32 i;
+ if (g_psDebugTable != IMG_NULL)
+ {
+ return PVRSRV_ERROR_DBGTABLE_ALREADY_REGISTERED;
+ }
+
+ g_psDebugTable = OSAllocMem(sizeof(DEBUG_REQUEST_TABLE) + (sizeof(DEBUG_REQUEST_ENTRY) * (ui32Length-1)));
+ if (!g_psDebugTable)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ g_psDebugTable->ui32RequestCount = ui32Length;
+
+ /* Init the list heads */
+ for (i=0;i<ui32Length;i++)
+ {
+ g_psDebugTable->asEntry[i].ui32RequesterID = paui32Table[i];
+ dllist_init(&g_psDebugTable->asEntry[i].sListHead);
+ }
+
+ *phTable = g_psDebugTable;
+ return PVRSRV_OK;
+}
+
+static IMG_VOID PVRSRVUnregisterDbgTable(IMG_PVOID hTable)
+{
+ IMG_UINT32 i;
+
+ PVR_ASSERT(hTable == g_psDebugTable);
+
+ for (i=0;i<g_psDebugTable->ui32RequestCount;i++)
+ {
+ if (!dllist_is_empty(&g_psDebugTable->asEntry[i].sListHead))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVUnregisterDbgTable: Found registered callback(s) on %d", i));
+ }
+ }
+ OSFREEMEM(g_psDebugTable);
+ g_psDebugTable = IMG_NULL;
+}
+
+PVRSRV_ERROR AcquireGlobalEventObjectServer(IMG_HANDLE *phGlobalEventObject)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ *phGlobalEventObject = psPVRSRVData->hGlobalEventObject;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR ReleaseGlobalEventObjectServer(IMG_HANDLE hGlobalEventObject)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ PVR_ASSERT(psPVRSRVData->hGlobalEventObject == hGlobalEventObject);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR GetBIFTilingHeapXStride(IMG_UINT32 uiHeapNum, IMG_UINT32 *puiXStride)
+{
+ IMG_UINT32 uiMaxHeaps;
+
+ PVR_ASSERT(puiXStride != IMG_NULL);
+
+ GetNumBifTilingHeapConfigs(&uiMaxHeaps);
+
+ if(uiHeapNum < 1 || uiHeapNum > uiMaxHeaps) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *puiXStride = gpsSysConfig->pui32BIFTilingHeapConfigs[uiHeapNum - 1];
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR GetNumBifTilingHeapConfigs(IMG_UINT32 *puiNumHeaps)
+{
+ *puiNumHeaps = gpsSysConfig->ui32BIFTilingHeapCount;
+ return PVRSRV_OK;
+}
+
+/*
+ PVRSRVResetHWRLogsKM
+*/
+PVRSRV_ERROR PVRSRVResetHWRLogsKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_LOG(("User requested HWR logs reset"));
+
+ if(psDeviceNode && psDeviceNode->pfnResetHWRLogs)
+ {
+ return psDeviceNode->pfnResetHWRLogs(psDeviceNode);
+ }
+
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+}
+
+/*****************************************************************************
+ End of file (pvrsrv.c)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/common/resman.c b/drivers/gpu/rogue/services/server/common/resman.c
new file mode 100644
index 000000000000..c23db6135d18
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/resman.c
@@ -0,0 +1,1043 @@
+/*************************************************************************/ /*!
+@File
+@Title Resource Manager
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource management
+@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 "resman.h"
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "pvrsrv.h"
+#include "osfunc.h"
+
+/* use mutex here if required */
+#define ACQUIRE_SYNC_OBJ
+#define RELEASE_SYNC_OBJ
+
+
+#define RESMAN_SIGNATURE 0x12345678
+
+/******************************************************************************
+ * resman structures
+ *****************************************************************************/
+
+/* resman item structure */
+typedef struct _RESMAN_ITEM_
+{
+ IMG_UINT32 ui32Signature;
+
+ struct _RESMAN_ITEM_ **ppsThis; /*!< list navigation */
+ struct _RESMAN_ITEM_ *psNext; /*!< list navigation */
+
+ IMG_UINT32 ui32ResType;/*!< res type */
+ IMG_PVOID pvParam; /*!< param for callback */
+ RESMAN_FREE_FN pfnFreeResource;/*!< resman item free callback */
+} RESMAN_ITEM;
+
+
+/* resman context structure */
+typedef struct _RESMAN_CONTEXT_
+{
+
+ IMG_UINT32 ui32Signature;
+ PRESMAN_DEFER_CONTEXTS_LIST psDeferContext; /*!< Defer context to which the the DeferResManContext should be added */
+
+ struct _RESMAN_CONTEXT_ **ppsThis;/*!< list navigation */
+ struct _RESMAN_CONTEXT_ *psNext;/*!< list navigation */
+
+ RESMAN_ITEM *psResItemList;/*!< res item list for context */
+
+} RESMAN_CONTEXT;
+
+typedef struct _RESMAN_DEFER_CONTEXTS_LIST_
+{
+ IMG_UINT32 ui32Signature;
+ IMG_HANDLE hCleanupEventObject; /*!< used to trigger deferred clean-up when it is required */
+ IMG_UINT64 ui64TimesliceLimit;
+
+ RESMAN_CONTEXT *psDeferResManContextList; /*!< list of contexts for deferred clean-up */
+} RESMAN_DEFER_CONTEXTS_LIST;
+
+/* resman list structure */
+typedef struct
+{
+ RESMAN_CONTEXT *psContextList; /*!< resman context list */
+
+} RESMAN_LIST, *PRESMAN_LIST; /* PRQA S 3205 */
+
+
+#include "lists.h" /* PRQA S 5087 */ /* include lists.h required here */
+
+static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
+static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_INSERT(RESMAN_ITEM)
+static IMPLEMENT_LIST_REMOVE(RESMAN_ITEM)
+
+static IMPLEMENT_LIST_FOR_EACH_SAFE(RESMAN_CONTEXT)
+static IMPLEMENT_LIST_REMOVE(RESMAN_CONTEXT)
+static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
+
+/******************************************************** Forword references */
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem);
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam);
+
+static IMG_VOID ResManFreeResources(PRESMAN_CONTEXT psResManContext);
+static IMG_VOID ResManDeferResources(PRESMAN_CONTEXT psResManContext);
+
+/*!
+******************************************************************************
+
+ @Function ResManInit
+
+ @Description initialises the resman
+
+ @Return none
+
+******************************************************************************/
+PVRSRV_ERROR ResManInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function ResManDeInit
+
+ @Description de-initialises the resman
+
+ @Return none
+
+******************************************************************************/
+IMG_VOID ResManDeInit(IMG_VOID)
+{
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManConnect
+
+ @Description Opens a connection to the Resource Manager
+
+ @output phResManContext - Resman context
+
+ @Return error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVResManConnect(PRESMAN_DEFER_CONTEXTS_LIST psDeferContext,
+ PRESMAN_CONTEXT *phResManContext)
+{
+ PRESMAN_CONTEXT psResManContext;
+
+ /* Allocate memory for the new context. */
+ psResManContext = OSAllocMem(sizeof(*psResManContext));
+ if (psResManContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psResManContext->ui32Signature = RESMAN_SIGNATURE;
+ psResManContext->psResItemList = IMG_NULL;
+ psResManContext->psDeferContext = psDeferContext;
+
+ /*Acquire resource list sync object*/
+ ACQUIRE_SYNC_OBJ;
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ *phResManContext = psResManContext;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManDisconnect
+
+ @Description Closes a Resource Manager connection and frees all resources
+
+ @input hResManContext - Resman context
+ @input bKernelContext - IMG_TRUE for kernel contexts
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext)
+{
+
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ /* Free the ResMan context when it is empty */
+ if (psResManContext->psResItemList == IMG_NULL)
+ {
+ /* Free the context struct */
+ OSFreeMem(psResManContext);
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVResManDisconnect: ResManContext (%p) freed", psResManContext));
+ }
+ else
+ {
+ /* defer the freeing of this context */
+ ResManDeferResources(psResManContext);
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVResManDisconnect: Resman context (%p) disconnect deferred", psResManContext));
+ }
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManCreateDeferContext
+
+ @Description
+ Create a "defer context" which is used to store resman contexts
+ if they have resources that can't be freed at resman disconnect
+ time
+
+ @output phDeferContext - Created defer context
+
+ @Return IMG_VOID
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVResManCreateDeferContext(IMG_HANDLE hCleanupEventObject,
+ PRESMAN_DEFER_CONTEXTS_LIST *phDeferContext)
+{
+ PRESMAN_DEFER_CONTEXTS_LIST psDeferContext;
+
+ PVR_ASSERT(hCleanupEventObject);
+
+ psDeferContext = OSAllocMem(sizeof(RESMAN_DEFER_CONTEXTS_LIST));
+ if (psDeferContext == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Remember the handle of the clean up event object so that it may be
+ * signal when deferredclean is required. Stored as a global RESMAN
+ * member since the point where deferred clean up is detected involves
+ * a deep call stack.
+ */
+ psDeferContext->ui32Signature = RESMAN_SIGNATURE;
+ psDeferContext->hCleanupEventObject = hCleanupEventObject;
+ psDeferContext->psDeferResManContextList = IMG_NULL;
+
+ *phDeferContext = psDeferContext;
+ return PVRSRV_OK;
+}
+
+static IMG_VOID FlushDeferResManContext(PRESMAN_CONTEXT psResManContext)
+{
+ /* If there are no items on this list then it shouldn’t be here */
+ PVR_ASSERT(psResManContext->psResItemList);
+ if (psResManContext->psResItemList)
+ {
+ /* Free what we can */
+ ResManFreeResources(psResManContext);
+ }
+
+ /*
+ If we've freed everything then remove this context from
+ the defer context and destroy it
+ */
+ if (!psResManContext->psResItemList)
+ {
+ List_RESMAN_CONTEXT_Remove(psResManContext);
+ OSFreeMem(psResManContext);
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVResManDisconnect: ResManContext (%p) freed", psResManContext));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVResManDisconnect: Resman context (%p) still has pending resources", psResManContext));
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVResManDisconnect: psResManContext->psResItemList = %p", psResManContext->psResItemList));
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVResManDisconnect: type = %d, pvParam = %p",
+ psResManContext->psResItemList->ui32ResType,
+ psResManContext->psResItemList->pvParam));
+ }
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManFlushDeferContext
+
+ @Description
+ Try to free resources on resman contexts that have been moved to
+ this defer context
+
+ @input psResManDeferContext - Defer context
+ @input ui64TimesliceLimit - Limit for the time slice used to free the resman Items.
+ When this function is called by thread which is NOT holding
+ the bridge lock (e.g. deinit), this value HAS TO BE zero.
+
+ @Return IMG_BOOL - true when resources still need deferred cleanup
+ false otherwise, the deferred context list is empty
+
+******************************************************************************/
+IMG_BOOL PVRSRVResManFlushDeferContext(PRESMAN_DEFER_CONTEXTS_LIST psDeferContext, IMG_UINT64 ui64TimesliceLimit)
+{
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ /* Set the timeout to release the bridge lock */
+ psDeferContext->ui64TimesliceLimit = ui64TimesliceLimit;
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVResManFlushDeferContext: Flush time slice limit set to %llu",
+ psDeferContext->ui64TimesliceLimit));
+
+ /* Go through checking all resman contexts on this defer context */
+ List_RESMAN_CONTEXT_ForEachSafe(psDeferContext->psDeferResManContextList, FlushDeferResManContext);
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ PVR_DPF_RETURN_VAL((psDeferContext->psDeferResManContextList != IMG_NULL) ? IMG_TRUE : IMG_FALSE);
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManDestroyDeferContext
+
+ @Description Destroy the defer context
+
+ @input psResManDeferContext - Defer context
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID PVRSRVResManDestroyDeferContext(PRESMAN_DEFER_CONTEXTS_LIST psDeferContext)
+{
+ /*
+ If there are still items waiting on the defer list then we must try
+ and free them now.
+ */
+ if (psDeferContext->psDeferResManContextList != IMG_NULL)
+ {
+ /* Useful to know how many contexts are waiting at this point... */
+ IMG_UINT32 ui32DeferedCount = 0;
+ RESMAN_CONTEXT* psItem = psDeferContext->psDeferResManContextList;
+
+ while (psItem != IMG_NULL)
+ {
+ ui32DeferedCount++;
+ psItem = psItem->psNext;
+ }
+
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVResManDestroyDeferContext: %d resman context(s) waiting to be freed!", ui32DeferedCount));
+
+ /* Attempt to free more resources... */
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ /* Set timer to 0 because we don't need to release the global lock
+ * during the deinit phase. */
+ PVRSRVResManFlushDeferContext(psDeferContext, 0);
+
+ /* If the driver is not in a okay state then don't try again... */
+ if (PVRSRVGetPVRSRVData()->eServicesState != PVRSRV_SERVICES_STATE_OK)
+ {
+ break;
+ }
+
+ /* Break out if we have freed them all... */
+ if (psDeferContext->psDeferResManContextList == IMG_NULL)
+ {
+ break;
+ }
+
+ OSSleepms((MAX_HW_TIME_US / 1000) / 10);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ /* Once more for luck and then force the issue... */
+ PVRSRVResManFlushDeferContext(psDeferContext, 0);
+ if (psDeferContext->psDeferResManContextList != IMG_NULL)
+ {
+ ui32DeferedCount = 0;
+ psItem = psDeferContext->psDeferResManContextList;
+ while (psItem != IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManDestroyDeferContext: Resman context (%p) has not been freed!", psItem));
+ ui32DeferedCount++;
+ psItem = psItem->psNext;
+ }
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManDestroyDeferContext: %d resman context(s) still waiting!", ui32DeferedCount));
+
+ PVR_ASSERT(psDeferContext->psDeferResManContextList == IMG_NULL);
+ }
+ }
+
+ /* Free the defer context... */
+ OSFreeMem(psDeferContext);
+}
+
+/*!
+******************************************************************************
+ @Function ResManRegisterRes
+
+ @Description : Inform the resource manager that the given resource has
+ been alloacted and freeing of it will be the responsibility
+ of the resource manager
+
+ @input psResManContext - resman context
+ @input ui32ResType - identify what kind of resource it is
+ @input pvParam - address of resource
+ @input ui32Param - size of resource
+ @input pfnFreeResource - pointer to function that frees this resource
+
+ @Return On success a pointer to an opaque data structure that represents
+ the allocated resource, else NULL
+
+**************************************************************************/
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ RESMAN_FREE_FN pfnFreeResource)
+{
+ PRESMAN_ITEM psNewResItem;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(ui32ResType != 0);
+
+ if (psResManContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: invalid parameter - psResManContext"));
+ return (PRESMAN_ITEM) IMG_NULL;
+ }
+
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
+ "Context %p, ResType 0x%x, pvParam %p, "
+ "FreeFunc %p",
+ psResManContext, ui32ResType, pvParam, pfnFreeResource));
+
+ /* Allocate memory for the new resource structure */
+ psNewResItem = OSAllocMem(sizeof(RESMAN_ITEM));
+ if (psNewResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
+ "ERROR allocating new resource item"));
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ return((PRESMAN_ITEM)IMG_NULL);
+ }
+
+ /* Fill in details about this resource */
+ psNewResItem->ui32Signature = RESMAN_SIGNATURE;
+ psNewResItem->ui32ResType = ui32ResType;
+ psNewResItem->pvParam = pvParam;
+ psNewResItem->pfnFreeResource = pfnFreeResource;
+
+ /* Insert new structure after dummy first entry */
+ List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ return(psNewResItem);
+}
+
+/*!
+******************************************************************************
+ @Function ResManFreeResByPtr
+
+ @Description frees a resource by matching on pointer type
+
+ @inputs psResItem - pointer to resource item to free
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM *psResItem)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: NULL ptr - nothing to do"));
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %p",
+ psResItem));
+
+ /*Acquire resource list sync object*/
+ ACQUIRE_SYNC_OBJ;
+
+ /*Free resource*/
+ eError = FreeResourceByPtr(psResItem);
+
+ /*Release resource list sync object*/
+ RELEASE_SYNC_OBJ;
+
+ return(eError);
+}
+
+
+/*!
+******************************************************************************
+ @Function ResManFindPrivateDataByPtr
+
+ @Description finds the private date for a resource by matching on pointer type
+
+ @inputs psResItem - pointer to resource item
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+PVRSRV_ERROR
+ResManFindPrivateDataByPtr(
+ RESMAN_ITEM *psResItem,
+ IMG_PVOID *ppvParam1
+ )
+{
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFindPrivateDataByPtr: NULL ptr - nothing to do"));
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFindPrivateDataByPtr: looking up private data for resource at %p",
+ psResItem));
+
+ /*Acquire resource list sync object*/
+ ACQUIRE_SYNC_OBJ;
+
+ /* verify signature */
+ PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+
+ /* lookup params */
+ if (ppvParam1 != IMG_NULL)
+ {
+ *ppvParam1 = psResItem->pvParam;
+ }
+
+ /*Release resource list sync object*/
+ RELEASE_SYNC_OBJ;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+ @Function ResManDissociateRes
+
+ @Description Moves a resource from one context to another.
+
+ @inputs psResItem - pointer to resource item to dissociate
+ @inputs psNewResManContext - new resman context for the resource
+
+ @Return IMG_VOID
+**************************************************************************/
+PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
+ PRESMAN_CONTEXT psNewResManContext)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: invalid parameter - psResItem"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+
+ if (psNewResManContext != IMG_NULL)
+ {
+ /* Remove this item from its old resource list */
+ List_RESMAN_ITEM_Remove(psResItem);
+
+ /* Re-insert into new list */
+ List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
+
+ }
+ else
+ {
+ /* Remove this item from its old resource list */
+ List_RESMAN_ITEM_Remove(psResItem);
+
+ /* Free this item as no one refers to it now */
+ OSFreeMem(psResItem);
+ }
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+ @Function ResManFindResourceByPtr_AnyVaCb
+
+ @Description
+ Compares the resman item with a given pointer.
+
+ @inputs psCurItem - theThe item to check
+ @inputs va - Variable argument list with:
+ psItem - pointer to resource item to find
+
+ @Return IMG_BOOL
+**************************************************************************/
+static IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ RESMAN_ITEM *psItem;
+
+ psItem = va_arg(va, RESMAN_ITEM*);
+
+ return (IMG_BOOL)(psCurItem == psItem);
+}
+
+
+/*!
+******************************************************************************
+ @Function ResManFindResourceByPtr
+
+ @Description
+ Attempts to find a resource in the list for this context
+
+ @inputs hResManContext - handle for resman context
+ @inputs psItem - pointer to resource item to find
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContext,
+ RESMAN_ITEM *psItem)
+{
+/* RESMAN_ITEM *psCurItem;*/
+
+ PVRSRV_ERROR eResult;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if ((psItem == IMG_NULL) || (psResManContext == IMG_NULL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManFindResourceByPtr: invalid parameter"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: psItem=%p, psItem->psNext=%p",
+ psItem, psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: Resource Ctx %p, Type 0x%x, Addr %p, "
+ "FnCall %p",
+ psResManContext, psItem->ui32ResType, psItem->pvParam,
+ psItem->pfnFreeResource));
+
+ /* Search resource items starting at after the first dummy item */
+ if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
+ &ResManFindResourceByPtr_AnyVaCb,
+ psItem))
+ {
+ eResult = PVRSRV_OK;
+ }
+ else
+ {
+ eResult = PVRSRV_ERROR_NOT_OWNER;
+ }
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ return eResult;
+}
+
+/*!
+******************************************************************************
+ @Function FreeResourceByPtr
+
+ @Description
+ Frees a resource and move it from the list
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @inputs psItem - pointer to resource item to free
+ bExecuteCallback - execute callback?
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if (psItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: psItem=%p, psItem->psNext=%p",
+ psItem, psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: Type 0x%x, Addr %p, "
+ "FnCall %p",
+ psItem->ui32ResType, psItem->pvParam,
+ psItem->pfnFreeResource));
+
+ /* Release resource list sync object just in case the free routine calls the resource manager */
+ RELEASE_SYNC_OBJ;
+
+ /* Call the freeing routine */
+ eError = psItem->pfnFreeResource(psItem->pvParam);
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function for %p", psItem));
+ }
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "FreeResourceByPtr: Got retry while calling FreeResource function for %p", psItem));
+ }
+
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Remove this item from the resource list */
+ List_RESMAN_ITEM_Remove(psItem);
+
+ /* Free memory for the resource item */
+ OSFreeMem(psItem);
+ }
+
+ return(eError);
+}
+
+/*!
+******************************************************************************
+ @Function FreeResourceByCriteria_AnyVaCb
+
+ @Description
+ Matches a resource manager item with a given criteria.
+
+ @inputs psCuItem - the item to be matched
+ @inputs va - a variable argument list with:.
+ ui32SearchCriteria - indicates which parameters should be used
+ search for resources to free
+ ui32ResType - identify what kind of resource to free
+ pvParam - address of resource to be free
+ ui32Param - size of resource to be free
+
+
+ @Return psCurItem if matched, IMG_NULL otherwise.
+**************************************************************************/
+static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ IMG_UINT32 ui32SearchCriteria;
+ IMG_UINT32 ui32ResType;
+ IMG_PVOID pvParam;
+
+ ui32SearchCriteria = va_arg(va, IMG_UINT32);
+ ui32ResType = va_arg(va, IMG_UINT32);
+ pvParam = va_arg(va, IMG_PVOID);
+
+ /*check that for all conditions are either disabled or eval to true*/
+ if(
+ /* Check resource type */
+ (((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+ (psCurItem->ui32ResType == ui32ResType))
+ &&
+ /* Check address */
+ (((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+ (psCurItem->pvParam == pvParam))
+ )
+ {
+ return psCurItem;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+/*!
+******************************************************************************
+ @Function FreeResourceByCriteria
+
+ @Description
+ Frees all resources that match the given criteria for the
+ context.
+ If we've been asked to defer the free then if any resource
+ returns retry then we move the resman context onto the defer
+ context and immediately bail.
+ If we haven't been asked to defer the free then we will
+ try and free all resources that match the criteria, regardless
+ of any errors. If any resource returns a retry error then this
+ will be returned (after we've tried to free all the other
+ resources).
+
+ @inputs psResManContext - pointer to resman context
+ @inputs ui32SearchCriteria - indicates which parameters should be used
+ @inputs search for resources to free
+ @inputs ui32ResType - identify what kind of resource to free
+ @inputs pvParam - address of resource to be free
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam)
+{
+ PRESMAN_ITEM psCurItem;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 iu32ItemsCounter = 0;
+
+ /* Search resource items starting at after the first dummy item */
+ /*while we get a match and not an error*/
+ while((psCurItem = (PRESMAN_ITEM)
+ List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
+ &FreeResourceByCriteria_AnyVaCb,
+ ui32SearchCriteria,
+ ui32ResType,
+ pvParam)) != IMG_NULL
+ && eError == PVRSRV_OK)
+ {
+ /* Attempt the free of at least one resman Item */
+ eError = FreeResourceByPtr(psCurItem);
+
+ if (eError == PVRSRV_OK)
+ {
+ iu32ItemsCounter++;
+ }
+ else
+ {
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "FreeResourceByCriteria: Resource %p (type %d) returned retry.", psCurItem, ui32ResType));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByCriteria: Error freeing resource %p (%s)",
+ psCurItem, PVRSRVGetErrorStringKM(eError)));
+ }
+ return eError;
+ }
+
+ if (psResManContext->psDeferContext->ui64TimesliceLimit != 0
+ && OSClockns64() > psResManContext->psDeferContext->ui64TimesliceLimit)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "FreeResourceByCriteria: Lock timeout (timeout: %llu / delay: %llu). ResItems freed %d",
+ psResManContext->psDeferContext->ui64TimesliceLimit,
+ OSClockns64() - psResManContext->psDeferContext->ui64TimesliceLimit,
+ iu32ItemsCounter));
+ OSReleaseBridgeLock();
+ /* Invoke the scheduler to check if other processes are waiting for the lock */
+ OSReleaseThreadQuanta();
+ OSAcquireBridgeLock();
+ /* Set again lock timeout and reset itemcounts */
+ psResManContext->psDeferContext->ui64TimesliceLimit = OSClockns64() + RESMAN_DEFERRED_CLEANUP_TIMESLICE_NS;
+ iu32ItemsCounter = 0;
+ PVR_DPF((PVR_DBG_MESSAGE, "FreeResourceByCriteria: Lock acquired again. New timeout %llu",
+ psResManContext->psDeferContext->ui64TimesliceLimit));
+ }
+ }
+
+ return eError;
+}
+
+static IMG_UINT32 g_ui32OrderedFreeList [] = {
+ RESMAN_TYPE_EVENT_OBJECT,
+ RESMAN_TYPE_SHARED_EVENT_OBJECT,
+
+ /* RGX types */
+ RESMAN_TYPE_RGX_FWIF_HWRTDATA,
+ RESMAN_TYPE_RGX_FWIF_FREELIST,
+ RESMAN_TYPE_RGX_POPULATION,
+ RESMAN_TYPE_RGX_FWIF_ZSBUFFER,
+ RESMAN_TYPE_RGX_FWIF_RENDERTARGET,
+ RESMAN_TYPE_RGX_SERVER_RENDER_CONTEXT,
+ RESMAN_TYPE_RGX_SERVER_TQ_CONTEXT,
+ RESMAN_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
+ RESMAN_TYPE_RGX_SERVER_RAY_CONTEXT,
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+ RESMAN_TYPE_SHARED_PB_DESC,
+
+ /* Common */
+ RESMAN_TYPE_RI_HANDLE,
+ RESMAN_TYPE_DEVMEM_MEM_EXPORT,
+ RESMAN_TYPE_SYNC_RECORD_HANDLE,
+ RESMAN_TYPE_SERVER_OP_COOKIE,
+ RESMAN_TYPE_SYNC_PRIMITIVE,
+ RESMAN_TYPE_SERVER_SYNC_PRIMITIVE,
+ RESMAN_TYPE_SERVER_SYNC_EXPORT,
+ RESMAN_TYPE_SYNC_PRIMITIVE_BLOCK,
+ RESMAN_TYPE_SYNC_INFO,
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+ RESMAN_TYPE_DEVICEMEM_WRAP,
+ RESMAN_TYPE_DEVICEMEM_MAPPING,
+ RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ RESMAN_TYPE_DEVICEMEM_CONTEXT,
+ RESMAN_TYPE_SHARED_MEM_INFO,
+ RESMAN_TYPE_DEVICEMEM2_MAPPING,
+ RESMAN_TYPE_DEVICEMEM2_RESERVATION,
+ RESMAN_TYPE_DEVICEMEM2_HEAP,
+ RESMAN_TYPE_DEVICEMEM2_CONTEXT_EXPORT,
+ RESMAN_TYPE_DEVICEMEM2_CONTEXT,
+ RESMAN_TYPE_PMR_PAGELIST,
+ RESMAN_TYPE_PMR_EXPORT,
+ RESMAN_TYPE_PMR,
+
+ /* DISPLAY CLASS types: */
+ RESMAN_TYPE_DC_PIN_HANDLE,
+ RESMAN_TYPE_DC_DISPLAY_CONTEXT,
+ RESMAN_TYPE_DC_BUFFER,
+ RESMAN_TYPE_DC_DEVICE,
+
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+
+ /* BUFFER CLASS types: */
+ RESMAN_TYPE_BUFFERCLASS_DEVICE,
+
+ /* OS-specific user mode mappings: */
+ RESMAN_TYPE_OS_USERMODE_MAPPING,
+
+ /* TRANSPORT LAYER types: */
+ RESMAN_TYPE_TL_STREAM_DESC,
+};
+
+/*!
+******************************************************************************
+ @Function ResManDeferResources
+
+ @Description Defer the freeing of all resources on this context.
+ The resman context will be freed by the cleanup thread.
+
+ @inputs psResManContext - pointer to resman context.
+
+ @Return None
+**************************************************************************/
+static IMG_VOID ResManDeferResources(PRESMAN_CONTEXT psResManContext)
+{
+ PVRSRV_ERROR eError;
+
+ /* If the ResManContext doesn't contain any ResItem we can skip it */
+ if (psResManContext->psResItemList == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManDeferResources: ResManContext (%p) is empty", psResManContext));
+ return;
+ }
+
+ /* Defer the freeing of the ResManContext always when possible */
+ PVR_ASSERT(psResManContext->psDeferContext);
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManDeferResources: ResManContext (%p) freeing deferred", psResManContext));
+
+ /* Insert this resman context into the defer context so we can defer to free
+ * its items.
+ */
+ List_RESMAN_CONTEXT_Insert(&psResManContext->psDeferContext->psDeferResManContextList, psResManContext);
+
+ /* Now signal clean up thread */
+ eError = OSEventObjectSignal(psResManContext->psDeferContext->hCleanupEventObject);
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+}
+
+/*!
+******************************************************************************
+ @Function ResManFreeResources
+
+ @Description
+ Free or defer the freeing of all resources on this context.
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @inputs psResManContext - pointer to resman context
+
+ @Return None
+**************************************************************************/
+static IMG_VOID ResManFreeResources(PRESMAN_CONTEXT psResManContext)
+{
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+
+ /* If the ResManContext doesn't contain any ResItem we can skip it */
+ if (psResManContext->psResItemList == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "ResManFreeResources: ResManContext (%p) is empty", psResManContext));
+ return;
+ }
+
+ for (i = 0; i < (sizeof(g_ui32OrderedFreeList) / sizeof(g_ui32OrderedFreeList[0])); i++)
+ {
+ eError = FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, g_ui32OrderedFreeList[i], IMG_NULL);
+ if (eError != PVRSRV_OK)
+ {
+ /* Bail on error */
+ break;
+ }
+ }
+}
+
+/******************************************************************************
+ End of file (resman.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/common/ri_server.c b/drivers/gpu/rogue/services/server/common/ri_server.c
new file mode 100644
index 000000000000..7e6fe6b03ae0
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/ri_server.c
@@ -0,0 +1,1255 @@
+/*************************************************************************/ /*!
+@File ri_server.c
+@Title Resource Information (RI) server implementation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Resource Information (RI) server 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 <stdarg.h>
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "osfunc.h"
+
+#include "srvkm.h"
+#include "lock.h"
+/* services/server/include/ */
+#include "ri_server.h"
+
+/* services/include/shared/ */
+#include "hash.h"
+/* services/shared/include/ */
+#include "dllist.h"
+
+#include "pmr.h"
+
+#if defined(PVR_RI_DEBUG)
+
+#define USE_RI_LOCK 1
+
+/*
+ * Initial size use for Hash table.
+ * (Used to index the RI list entries).
+ */
+#define _RI_INITIAL_HASH_TABLE_SIZE 64
+
+/*
+ * Values written to the 'valid' field of
+ * RI structures when created and cleared
+ * prior to being destroyed.
+ * The code can then check this value
+ * before accessing the provided pointer
+ * contents as a valid RI structure.
+ */
+#define _VALID_RI_LIST_ENTRY 0x66bccb66
+#define _VALID_RI_SUBLIST_ENTRY 0x77cddc77
+#define _INVALID 0x00000000
+
+/*
+ * If this define is set to 1, details of
+ * the linked lists (addresses, prev/next
+ * ptrs, etc) are also output when function
+ * RIDumpList() is called
+ */
+#define _DUMP_LINKEDLIST_INFO 0
+
+
+typedef IMG_UINT64 _RI_BASE_T;
+
+/*
+ * Length of string used for process name
+ */
+#define TASK_COMM_LEN 16
+/*
+ * Length of string used for process ID
+ */
+#define TASK_PID_LEN 11
+/*
+ * Length of string used for "[{PID}:_{process_name}]"
+ */
+#define RI_PROC_TAG_CHAR_LEN (1+TASK_PID_LEN+2+TASK_COMM_LEN+1)
+
+/*
+ * Length of string used for address
+ */
+#define RI_ADDR_CHAR_LEN 12
+/*
+ * Length of string used for size
+ */
+#define RI_SIZE_CHAR_LEN 12
+/*
+ * Length of string used for "{Imported from PID nnnnnnnnnn}"
+ */
+#define RI_IMPORT_TAG_CHAR_LEN 32
+/*
+ * Total length of string returned to debugfs
+ * {0xaddr}_{annotation_text}_{0xsize}_{import_tag}
+ */
+#define RI_MAX_DEBUGFS_ENTRY_LEN (RI_ADDR_CHAR_LEN+1+RI_MAX_TEXT_LEN+1+RI_SIZE_CHAR_LEN+1+RI_IMPORT_TAG_CHAR_LEN+1)
+/*
+ * Total length of string output to _RIOutput()
+ * for MEMDESC RI sub-list entries
+ * {0xaddr}_{annotation_text}_[{PID}:_{process_name}]_{0xsize}_bytes_{import_tag}
+ */
+#define RI_MAX_MEMDESC_RI_ENTRY_LEN (RI_ADDR_CHAR_LEN+1+RI_MAX_TEXT_LEN+1+RI_PROC_TAG_CHAR_LEN+1+RI_SIZE_CHAR_LEN+7+RI_IMPORT_TAG_CHAR_LEN+1)
+/*
+ * Total length of string output to _RIOutput()
+ * for PMR RI list entries
+ * {annotation_text}_{pmr_handle}_suballocs:{num_suballocs}_{0xsize}
+ */
+#define RI_MAX_PMR_RI_ENTRY_LEN (RI_MAX_TEXT_LEN+1+RI_ADDR_CHAR_LEN+11+10+1+RI_SIZE_CHAR_LEN)
+
+
+/*
+ * Structure used to make linked sublist of
+ * memory allocations (MEMDESC)
+ */
+struct _RI_SUBLIST_ENTRY_
+{
+ DLLIST_NODE sListNode;
+ struct _RI_LIST_ENTRY_ *psRI;
+ IMG_UINT32 valid;
+ IMG_BOOL bIsImport;
+ IMG_BOOL bIsExportable;
+ IMG_PID pid;
+ IMG_CHAR ai8ProcName[TASK_COMM_LEN];
+ IMG_DEV_VIRTADDR sVAddr;
+ IMG_SIZE_T uiOffset;
+ IMG_SIZE_T uiSize;
+ IMG_CHAR ai8TextB[RI_MAX_TEXT_LEN+1];
+ DLLIST_NODE sProcListNode;
+};
+
+/*
+ * Structure used to make linked list of
+ * PMRs. Sublists of allocations (MEMDESCs) made
+ * from these PMRs are chained off these entries.
+ */
+struct _RI_LIST_ENTRY_
+{
+ DLLIST_NODE sListNode;
+ DLLIST_NODE sSubListFirst;
+ IMG_UINT32 valid;
+ PMR *hPMR;
+ IMG_SIZE_T uiLogicalSize;
+ IMG_PID pid;
+ IMG_CHAR ai8ProcName[TASK_COMM_LEN];
+ IMG_CHAR ai8TextA[RI_MAX_TEXT_LEN+1];
+ IMG_UINT16 ui16SubListCount;
+ IMG_UINT16 ui16MaxSubListCount;
+};
+
+typedef struct _RI_LIST_ENTRY_ RI_LIST_ENTRY;
+typedef struct _RI_SUBLIST_ENTRY_ RI_SUBLIST_ENTRY;
+
+static IMG_UINT16 g_ui16RICount = 0;
+static HASH_TABLE *g_pRIHashTable = IMG_NULL;
+static IMG_UINT16 g_ui16ProcCount = 0;
+static HASH_TABLE *g_pProcHashTable = IMG_NULL;
+
+static POS_LOCK g_hRILock;
+/*
+ * Flag used to indicate RILock if RILock should be destroyed when final PMR entry
+ * is deleted (if RIDeInitKM() has already been called before that point, but RESMAN
+ * has deferred deletion of RI entries.
+ */
+static IMG_BOOL bRIDeInitDeferred = IMG_FALSE;
+
+/*
+ * Used as head of linked-list of PMR RI entries -
+ * this is useful when we wish to iterate all PMR
+ * list entries (when we don't have a PMR ref)
+ */
+static DLLIST_NODE sListFirst;
+
+/* Function used to produce string containing info for MEMDESC RI entries (used for both debugfs and kernel log output) */
+static IMG_VOID _GenerateMEMDESCEntryString(RI_SUBLIST_ENTRY *psRISubEntry, IMG_BOOL bDebugFs, IMG_UINT16 ui16MaxStrLen, IMG_CHAR *pszEntryString);
+
+static PVRSRV_ERROR _DumpAllEntries (IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+static PVRSRV_ERROR _DeleteAllEntries (IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+static PVRSRV_ERROR _DumpList(PMR *hPMR, IMG_PID pid);
+#define _RIOutput(x) PVR_LOG(x)
+
+IMG_INTERNAL IMG_UINT32
+_ProcHashFunc (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+IMG_INTERNAL IMG_UINT32
+_ProcHashFunc (IMG_SIZE_T uKeySize, IMG_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;
+}
+IMG_INTERNAL IMG_BOOL
+_ProcHashComp (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+IMG_INTERNAL IMG_BOOL
+_ProcHashComp (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_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;
+}
+
+static IMG_VOID _RILock(IMG_VOID)
+{
+#if (USE_RI_LOCK == 1)
+ OSLockAcquire(g_hRILock);
+#endif
+}
+
+static IMG_VOID _RIUnlock(IMG_VOID)
+{
+#if (USE_RI_LOCK == 1)
+ OSLockRelease(g_hRILock);
+#endif
+}
+
+PVRSRV_ERROR RIInitKM(IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ bRIDeInitDeferred = IMG_FALSE;
+#if (USE_RI_LOCK == 1)
+ eError = OSLockCreate(&g_hRILock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSLockCreate failed (returned %d)",__func__,eError));
+ }
+#endif
+ return eError;
+}
+IMG_VOID RIDeInitKM(IMG_VOID)
+{
+#if (USE_RI_LOCK == 1)
+ if (g_ui16RICount > 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: called with %d entries remaining - deferring OSLockDestroy()",__func__,g_ui16RICount));
+ bRIDeInitDeferred = IMG_TRUE;
+ }
+ else
+ {
+ OSLockDestroy(g_hRILock);
+ }
+#endif
+}
+
+/*!
+******************************************************************************
+
+ @Function RIWritePMREntryKM
+
+ @Description
+ Writes a new Resource Information list entry.
+ The new entry will be inserted at the head of the list of
+ PMR RI entries and assigned the values provided.
+
+ @input hPMR - Reference (handle) to the PMR to which this reference relates
+ @input ai8TextA - String describing this PMR (may be null)
+ @input uiLogicalSize - Size of PMR
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIWritePMREntryKM(PMR *hPMR,
+ IMG_UINT32 ui32TextASize,
+ const IMG_CHAR *psz8TextA,
+ IMG_SIZE_T uiLogicalSize)
+{
+ IMG_UINTPTR_T hashData = 0;
+ PMR *pPMRHashKey = hPMR;
+ IMG_PCHAR pszText = (IMG_PCHAR)psz8TextA;
+ RI_LIST_ENTRY *psRIEntry = IMG_NULL;
+
+
+ /* if Hash table has not been created, create it now */
+ if (!g_pRIHashTable)
+ {
+ g_pRIHashTable = HASH_Create_Extended(_RI_INITIAL_HASH_TABLE_SIZE, sizeof(PMR*), HASH_Func_Default, HASH_Key_Comp_Default);
+ g_pProcHashTable = HASH_Create_Extended(_RI_INITIAL_HASH_TABLE_SIZE, sizeof(IMG_PID), _ProcHashFunc, _ProcHashComp);
+ }
+ if (!g_pRIHashTable || !g_pProcHashTable)
+ {
+ /* Error - no memory to allocate for Hash table(s) */
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ if (!hPMR)
+ {
+ /* NULL handle provided */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ else
+ {
+ /* Acquire RI Lock */
+ _RILock();
+
+ /* look-up hPMR in Hash Table */
+ hashData = HASH_Retrieve_Extended (g_pRIHashTable, (IMG_VOID *)&pPMRHashKey);
+ psRIEntry = (RI_LIST_ENTRY *)hashData;
+ if (!psRIEntry)
+ {
+ /*
+ * If failed to find a matching existing entry, create a new one
+ */
+ psRIEntry = (RI_LIST_ENTRY *)OSAllocZMem(sizeof(RI_LIST_ENTRY));
+ if (!psRIEntry)
+ {
+ /* Release RI Lock */
+ _RIUnlock();
+ /* Error - no memory to allocate for new RI entry */
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+ /*
+ * Add new RI Entry
+ */
+ if (g_ui16RICount == 0)
+ {
+ /* Initialise PMR entry linked-list head */
+ dllist_init(&sListFirst);
+ }
+ g_ui16RICount++;
+
+ dllist_init (&(psRIEntry->sSubListFirst));
+ psRIEntry->ui16SubListCount = 0;
+ psRIEntry->ui16MaxSubListCount = 0;
+ psRIEntry->valid = _VALID_RI_LIST_ENTRY;
+ psRIEntry->pid = OSGetCurrentProcessIDKM();
+ OSSNPrintf((IMG_CHAR *)psRIEntry->ai8ProcName, TASK_COMM_LEN, "%s", OSGetCurrentProcessNameKM());
+ /* Add PMR entry to linked-list of PMR entries */
+ dllist_init (&(psRIEntry->sListNode));
+ dllist_add_to_tail(&sListFirst,(PDLLIST_NODE)&(psRIEntry->sListNode));
+ }
+
+ if (pszText)
+ {
+ if (ui32TextASize > RI_MAX_TEXT_LEN)
+ ui32TextASize = RI_MAX_TEXT_LEN;
+
+ /* copy ai8TextA field data */
+ OSSNPrintf((IMG_CHAR *)psRIEntry->ai8TextA, ui32TextASize+1, "%s", pszText);
+
+ /* ensure string is NUL-terminated */
+ psRIEntry->ai8TextA[ui32TextASize] = '\0';
+ }
+ else
+ {
+ /* ensure string is NUL-terminated */
+ psRIEntry->ai8TextA[0] = '\0';
+ }
+ psRIEntry->hPMR = hPMR;
+ psRIEntry->uiLogicalSize = uiLogicalSize;
+
+ /* Create index entry in Hash Table */
+ HASH_Insert_Extended (g_pRIHashTable, (IMG_VOID *)&pPMRHashKey, (IMG_UINTPTR_T)psRIEntry);
+
+ /* Store phRIHandle in PMR structure, so it can delete the associated RI entry when it destroys the PMR */
+ PMRStoreRIHandle(hPMR, (IMG_PVOID)psRIEntry);
+ }
+ /* Release RI Lock */
+ _RIUnlock();
+ }
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function RIWriteMEMDESCEntryKM
+
+ @Description
+ Writes a new Resource Information sublist entry.
+ The new entry will be inserted at the head of the sublist of
+ the indicated PMR list entry, and assigned the values provided.
+
+ @input hPMR - Reference (handle) to the PMR to which this MEMDESC RI entry relates
+ @input ai8TextB - String describing this secondary reference (may be null)
+ @input uiOffset - Offset from the start of the PMR at which this allocation begins
+ @input uiSize - Size of this allocation
+ @input bIsImport - Flag indicating if this is an allocation or an import
+ @input bIsExportable - Flag indicating if this allocation is exportable
+ @output phRIHandle - Handle to the created RI entry
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIWriteMEMDESCEntryKM(PMR *hPMR,
+ IMG_UINT32 ui32TextBSize,
+ const IMG_CHAR *psz8TextB,
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ IMG_BOOL bIsImport,
+ IMG_BOOL bIsExportable,
+ RI_HANDLE *phRIHandle)
+{
+ IMG_UINTPTR_T hashData = 0;
+ PMR *pPMRHashKey = hPMR;
+ IMG_PID pid;
+ IMG_PCHAR pszText = (IMG_PCHAR)psz8TextB;
+ RI_LIST_ENTRY *psRIEntry = IMG_NULL;
+ RI_SUBLIST_ENTRY *psRISubEntry = IMG_NULL;
+
+
+ /* check Hash tables have been created (meaning at least one PMR has been defined) */
+ if (!g_pRIHashTable || !g_pProcHashTable)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ if (!hPMR || !phRIHandle)
+ {
+ /* NULL handle provided */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ else
+ {
+ /* Acquire RI Lock */
+ _RILock();
+
+ *phRIHandle = IMG_NULL;
+
+ /* look-up hPMR in Hash Table */
+ hashData = HASH_Retrieve_Extended (g_pRIHashTable, (IMG_VOID *)&pPMRHashKey);
+ psRIEntry = (RI_LIST_ENTRY *)hashData;
+ if (!psRIEntry)
+ {
+ /* Release RI Lock */
+ _RIUnlock();
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psRISubEntry = (RI_SUBLIST_ENTRY *)OSAllocZMem(sizeof(RI_SUBLIST_ENTRY));
+ if (!psRISubEntry)
+ {
+ /* Release RI Lock */
+ _RIUnlock();
+ /* Error - no memory to allocate for new RI sublist entry */
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+ /*
+ * Insert new entry in sublist
+ */
+ PDLLIST_NODE currentNode = dllist_get_next_node(&(psRIEntry->sSubListFirst));
+
+ /*
+ * Insert new entry before currentNode
+ */
+ if (!currentNode)
+ {
+ currentNode = &(psRIEntry->sSubListFirst);
+ }
+ dllist_add_to_tail(currentNode, (PDLLIST_NODE)&(psRISubEntry->sListNode));
+
+ psRISubEntry->psRI = psRIEntry;
+
+ /* Increment number of entries in sublist */
+ psRIEntry->ui16SubListCount++;
+ if (psRIEntry->ui16SubListCount > psRIEntry->ui16MaxSubListCount)
+ {
+ psRIEntry->ui16MaxSubListCount = psRIEntry->ui16SubListCount;
+ }
+ psRISubEntry->valid = _VALID_RI_SUBLIST_ENTRY;
+ }
+
+ psRISubEntry->pid = OSGetCurrentProcessIDKM();
+
+ if (ui32TextBSize > RI_MAX_TEXT_LEN)
+ ui32TextBSize = RI_MAX_TEXT_LEN;
+ /* copy ai8TextB field data */
+ OSSNPrintf((IMG_CHAR *)psRISubEntry->ai8TextB, ui32TextBSize+1, "%s", pszText);
+ /* ensure string is NUL-terminated */
+ psRISubEntry->ai8TextB[ui32TextBSize] = '\0';
+
+ psRISubEntry->uiOffset = uiOffset;
+ psRISubEntry->uiSize = uiSize;
+ psRISubEntry->bIsImport = bIsImport;
+ psRISubEntry->bIsExportable = bIsExportable;
+ OSSNPrintf((IMG_CHAR *)psRISubEntry->ai8ProcName, TASK_COMM_LEN, "%s", OSGetCurrentProcessNameKM());
+ dllist_init (&(psRISubEntry->sProcListNode));
+
+ /*
+ * Now insert this MEMDESC into the proc list
+ */
+ /* look-up pid in Hash Table */
+ pid = psRISubEntry->pid;
+ hashData = HASH_Retrieve_Extended (g_pProcHashTable, (IMG_VOID *)&pid);
+ if (!hashData)
+ {
+ /*
+ * No allocations for this pid yet
+ */
+ HASH_Insert_Extended (g_pProcHashTable, (IMG_VOID *)&pid, (IMG_UINTPTR_T)&(psRISubEntry->sProcListNode));
+ /* Increment number of entries in proc hash table */
+ g_ui16ProcCount++;
+ }
+ else
+ {
+ /*
+ * Insert allocation into pid allocations linked list
+ */
+ PDLLIST_NODE currentNode = (PDLLIST_NODE)hashData;
+
+ /*
+ * Insert new entry
+ */
+ dllist_add_to_tail(currentNode, (PDLLIST_NODE)&(psRISubEntry->sProcListNode));
+ }
+ *phRIHandle = (RI_HANDLE)psRISubEntry;
+ /* Release RI Lock */
+ _RIUnlock();
+ }
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function RIUpdateMEMDESCAddrKM
+
+ @Description
+ Update a Resource Information entry.
+
+ @input hRIHandle - Handle of object whose reference info is to be updated
+ @input uiAddr - New address for the RI entry
+ @input uiOffset - New offset for the RI entry
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIUpdateMEMDESCAddrKM(RI_HANDLE hRIHandle,
+ IMG_DEV_VIRTADDR sVAddr)
+{
+ RI_SUBLIST_ENTRY *psRISubEntry = IMG_NULL;
+
+ if (!hRIHandle)
+ {
+ /* NULL handle provided */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ psRISubEntry = (RI_SUBLIST_ENTRY *)hRIHandle;
+ if (psRISubEntry->valid != _VALID_RI_SUBLIST_ENTRY)
+ {
+ /* Pointer does not point to valid structure */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Acquire RI lock*/
+ _RILock();
+
+ psRISubEntry->sVAddr.uiAddr = sVAddr.uiAddr;
+
+ /* Release RI lock */
+ _RIUnlock();
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function RIDeletePMREntryKM
+
+ @Description
+ Delete a Resource Information entry.
+
+ @input hRIHandle - Handle of object whose reference info is to be deleted
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIDeletePMREntryKM(RI_HANDLE hRIHandle)
+{
+ RI_LIST_ENTRY *psRIEntry = IMG_NULL;
+ PMR *pPMRHashKey;
+ PVRSRV_ERROR eResult = PVRSRV_OK;
+
+
+ if (!hRIHandle)
+ {
+ /* NULL handle provided */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ else
+ {
+ psRIEntry = (RI_LIST_ENTRY *)hRIHandle;
+
+ if (psRIEntry->valid != _VALID_RI_LIST_ENTRY)
+ {
+ /* Pointer does not point to valid structure */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(psRIEntry->ui16SubListCount == 0)
+ {
+ /* Acquire RI lock*/
+ _RILock();
+
+ /* Remove the HASH table index entry */
+ pPMRHashKey = psRIEntry->hPMR;
+ HASH_Remove_Extended(g_pRIHashTable, (IMG_VOID *)&pPMRHashKey);
+
+ psRIEntry->valid = _INVALID;
+
+ /* Remove PMR entry from linked-list of PMR entries */
+ dllist_remove_node((PDLLIST_NODE)&(psRIEntry->sListNode));
+
+ /* Now, free the memory used to store the RI entry */
+ OSFreeMem(psRIEntry);
+ psRIEntry = IMG_NULL;
+
+ /* Release RI lock*/
+ _RIUnlock();
+
+ /*
+ * Decrement number of RI entries - if this is now zero,
+ * we can delete the RI hash table
+ */
+ if(--g_ui16RICount == 0)
+ {
+ HASH_Delete(g_pRIHashTable);
+ g_pRIHashTable = IMG_NULL;
+ /* If deInit has been deferred, we can now destroy the RI Lock */
+ if (bRIDeInitDeferred)
+ {
+ OSLockDestroy(g_hRILock);
+ }
+ }
+ /*
+ * Make the handle NULL once PMR RI entry is deleted
+ */
+ hRIHandle = IMG_NULL;
+ }
+ else
+ {
+ eResult = PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
+ }
+ }
+
+ return eResult;
+}
+
+/*!
+******************************************************************************
+
+ @Function RIDeleteMEMDESCEntryKM
+
+ @Description
+ Delete a Resource Information entry.
+
+ @input hRIHandle - Handle of object whose reference info is to be deleted
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIDeleteMEMDESCEntryKM(RI_HANDLE hRIHandle)
+{
+ RI_LIST_ENTRY *psRIEntry = IMG_NULL;
+ RI_SUBLIST_ENTRY *psRISubEntry = IMG_NULL;
+ IMG_UINTPTR_T hashData = 0;
+ IMG_PID pid;
+ PVRSRV_ERROR eResult = PVRSRV_OK;
+
+
+ if (!hRIHandle)
+ {
+ /* NULL handle provided */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psRISubEntry = (RI_SUBLIST_ENTRY *)hRIHandle;
+ if (psRISubEntry->valid != _VALID_RI_SUBLIST_ENTRY)
+ {
+ /* Pointer does not point to valid structure */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Acquire RI lock*/
+ _RILock();
+
+ psRIEntry = (RI_LIST_ENTRY *)psRISubEntry->psRI;
+
+ /* Now, remove entry from the sublist */
+ dllist_remove_node(&(psRISubEntry->sListNode));
+
+ psRISubEntry->valid = _INVALID;
+
+ /* Remove the entry from the proc allocations linked list */
+ pid = psRISubEntry->pid;
+ /* If this is the only allocation for this pid, just remove it from the hash table */
+ if (dllist_get_next_node(&(psRISubEntry->sProcListNode)) == IMG_NULL)
+ {
+ HASH_Remove_Extended(g_pProcHashTable, (IMG_VOID *)&pid);
+ /* Decrement number of entries in proc hash table, and delete the hash table if there are now none */
+ if(--g_ui16ProcCount == 0)
+ {
+ HASH_Delete(g_pProcHashTable);
+ g_pProcHashTable = IMG_NULL;
+ }
+ }
+ else
+ {
+ hashData = HASH_Retrieve_Extended (g_pProcHashTable, (IMG_VOID *)&pid);
+ if ((PDLLIST_NODE)hashData == &(psRISubEntry->sProcListNode))
+ {
+ HASH_Remove_Extended(g_pProcHashTable, (IMG_VOID *)&pid);
+ HASH_Insert_Extended (g_pProcHashTable, (IMG_VOID *)&pid, (IMG_UINTPTR_T)dllist_get_next_node(&(psRISubEntry->sProcListNode)));
+ }
+ }
+ dllist_remove_node(&(psRISubEntry->sProcListNode));
+
+ /* Now, free the memory used to store the sublist entry */
+ OSFreeMem(psRISubEntry);
+ psRISubEntry = IMG_NULL;
+
+ /*
+ * Decrement number of entries in sublist
+ */
+ psRIEntry->ui16SubListCount--;
+
+ /* Release RI lock*/
+ _RIUnlock();
+
+ /*
+ * Make the handle NULL once MEMDESC RI entry is deleted
+ */
+ hRIHandle = IMG_NULL;
+
+ return eResult;
+}
+
+/*!
+******************************************************************************
+
+ @Function RIDeleteListKM
+
+ @Description
+ Delete all Resource Information entries and free associated
+ memory.
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIDeleteListKM(IMG_VOID)
+{
+ PVRSRV_ERROR eResult = PVRSRV_OK;
+
+
+ if (g_pRIHashTable)
+ {
+ eResult = HASH_Iterate(g_pRIHashTable, (HASH_pfnCallback)_DeleteAllEntries);
+ if (eResult == PVRSRV_ERROR_RESOURCE_UNAVAILABLE)
+ {
+ /*
+ * PVRSRV_ERROR_RESOURCE_UNAVAILABLE is used to stop the Hash iterator when
+ * the hash table gets deleted as a result of deleting the final PMR entry,
+ * so this is not a real error condition...
+ */
+ eResult = PVRSRV_OK;
+ }
+ }
+ return eResult;
+}
+
+/*!
+******************************************************************************
+
+ @Function RIDumpListKM
+
+ @Description
+ Dumps out the contents of the RI List entry for the
+ specified PMR, and all MEMDESC allocation entries
+ in the associated sub linked list.
+ At present, output is directed to Kernel log
+ via PVR_DPF.
+
+ @input hPMR - PMR for which RI entry details are to be output
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIDumpListKM(PMR *hPMR)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ /* Acquire RI lock*/
+ _RILock();
+
+ eError = _DumpList(hPMR,0);
+
+ /* Release RI lock*/
+ _RIUnlock();
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function RIGetListEntryKM
+
+ @Description
+ Returns pointer to a formatted string with details of the specified
+ list entry. If no entry exists (e.g. it may have been deleted
+ since the previous call), IMG_NULL is returned.
+
+ @input pid - pid for which RI entry details are to be output
+ @input ppHandle - handle to the entry, if IMG_NULL, the first entry will be
+ returned.
+ @output pszEntryString - string to be output for the entry
+ @output hEntry - hEntry will be returned pointing to the next entry
+ (or IMG_NULL if there is no next entry)
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_BOOL RIGetListEntryKM(IMG_PID pid,
+ IMG_HANDLE **ppHandle,
+ IMG_CHAR **ppszEntryString)
+{
+ RI_SUBLIST_ENTRY *psRISubEntry = IMG_NULL;
+ IMG_UINTPTR_T hashData = 0;
+ IMG_PID hashKey = pid;
+ static IMG_BOOL bDisplaySummary = IMG_FALSE;
+ static IMG_CHAR ai8DebugfsSummaryString[RI_MAX_DEBUGFS_ENTRY_LEN+1];
+ static IMG_SIZE_T totalAlloc = 0;
+ static IMG_SIZE_T totalImport = 0;
+ static IMG_BOOL bTerminateNextCall = IMG_FALSE;
+
+ if (bDisplaySummary)
+ {
+ OSSNPrintf((IMG_CHAR *)&ai8DebugfsSummaryString[0],
+ RI_MAX_TEXT_LEN,
+ "Alloc:0x" IMG_SIZE_FMTSPECX " + Imports:0x" IMG_SIZE_FMTSPECX " = Total:0x" IMG_SIZE_FMTSPECX "\n",
+ totalAlloc,
+ totalImport,
+ (totalAlloc+totalImport));
+ *ppszEntryString = &ai8DebugfsSummaryString[0];
+ totalAlloc = 0;
+ totalImport = 0;
+ bTerminateNextCall = IMG_TRUE;
+ bDisplaySummary = IMG_FALSE;
+ return IMG_TRUE;
+ }
+
+ if (bTerminateNextCall)
+ {
+ bTerminateNextCall = IMG_FALSE;
+ *ppszEntryString = IMG_NULL;
+ *ppHandle = IMG_NULL;
+ return IMG_FALSE;
+ }
+
+ /* Acquire RI lock*/
+ _RILock();
+
+ /* look-up pid in Hash Table, to obtain first entry for pid */
+ hashData = HASH_Retrieve_Extended(g_pProcHashTable, (IMG_VOID *)&hashKey);
+ if (hashData)
+ {
+ if (*ppHandle)
+ {
+ psRISubEntry = (RI_SUBLIST_ENTRY *)*ppHandle;
+ if (psRISubEntry->valid != _VALID_RI_SUBLIST_ENTRY)
+ {
+ psRISubEntry = IMG_NULL;
+ }
+ }
+ else
+ {
+ psRISubEntry = IMG_CONTAINER_OF((PDLLIST_NODE)hashData, RI_SUBLIST_ENTRY, sProcListNode);
+ if (psRISubEntry->valid != _VALID_RI_SUBLIST_ENTRY)
+ {
+ psRISubEntry = IMG_NULL;
+ }
+ }
+ }
+
+ if (psRISubEntry)
+ {
+ PDLLIST_NODE psNextProcListNode = dllist_get_next_node(&psRISubEntry->sProcListNode);
+
+ if (psNextProcListNode == IMG_NULL ||
+ psNextProcListNode == (PDLLIST_NODE)hashData)
+ {
+ bDisplaySummary = IMG_TRUE;
+ }
+ if (psRISubEntry->bIsImport)
+ {
+ totalImport += psRISubEntry->uiSize;
+ }
+ else
+ {
+ totalAlloc += psRISubEntry->uiSize;
+ }
+
+ _GenerateMEMDESCEntryString(psRISubEntry, IMG_TRUE, RI_MAX_DEBUGFS_ENTRY_LEN, (IMG_CHAR *)&ai8DebugfsSummaryString);
+ ai8DebugfsSummaryString[RI_MAX_DEBUGFS_ENTRY_LEN] = '\0';
+
+ *ppszEntryString = (IMG_CHAR *)&ai8DebugfsSummaryString;
+ *ppHandle = (IMG_HANDLE)IMG_CONTAINER_OF(psNextProcListNode, RI_SUBLIST_ENTRY, sProcListNode);
+ }
+ else
+ {
+ bDisplaySummary = IMG_TRUE;
+ if (totalAlloc == 0)
+ {
+ ai8DebugfsSummaryString[0] = '\0';
+ *ppszEntryString = (IMG_CHAR *)&ai8DebugfsSummaryString;
+ }
+ }
+
+ /* Release RI lock*/
+ _RIUnlock();
+
+ return IMG_TRUE;
+}
+
+/* Function used to produce string containing info for MEMDESC RI entries (used for both debugfs and kernel log output) */
+static IMG_VOID _GenerateMEMDESCEntryString(RI_SUBLIST_ENTRY *psRISubEntry, IMG_BOOL bDebugFs, IMG_UINT16 ui16MaxStrLen, IMG_CHAR *pszEntryString)
+{
+ IMG_CHAR szProc[RI_PROC_TAG_CHAR_LEN];
+ IMG_CHAR szImport[RI_IMPORT_TAG_CHAR_LEN];
+ IMG_PCHAR pszAnnotationText = IMG_NULL;
+
+ if (!bDebugFs)
+ {
+ /* we don't include process ID info for debugfs output */
+ OSSNPrintf( (IMG_CHAR *)&szProc, RI_PROC_TAG_CHAR_LEN, "[%d: %s]",psRISubEntry->pid,(IMG_CHAR *)psRISubEntry->ai8ProcName);
+ }
+ if (psRISubEntry->bIsImport)
+ {
+ OSSNPrintf( (IMG_CHAR *)&szImport, RI_IMPORT_TAG_CHAR_LEN, "{Import from PID %d}",psRISubEntry->psRI->pid);
+ /* Set pszAnnotationText to that of the 'parent' PMR RI entry */
+ pszAnnotationText = (IMG_PCHAR)psRISubEntry->psRI->ai8TextA;
+ }
+ else
+ {
+ if (psRISubEntry->bIsExportable)
+ {
+ /* Set pszAnnotationText to that of the 'parent' PMR RI entry */
+ pszAnnotationText = (IMG_PCHAR)psRISubEntry->psRI->ai8TextA;
+ }
+ else
+ {
+ /* Set pszAnnotationText to that of the MEMDESC RI entry */
+ pszAnnotationText = (IMG_PCHAR)psRISubEntry->ai8TextB;
+ }
+ }
+ OSSNPrintf(pszEntryString, ui16MaxStrLen, "%s " IMG_DEV_VIRTADDR_FMTSPEC " %-80s %s 0x" IMG_SIZE_FMTSPECX " %s%c",(bDebugFs?"":" "),(psRISubEntry->sVAddr.uiAddr+psRISubEntry->uiOffset),pszAnnotationText,(bDebugFs?"":(IMG_CHAR *)szProc),psRISubEntry->uiSize,(psRISubEntry->bIsImport?(IMG_CHAR *)&szImport:""),(bDebugFs?'\n':' '));
+}
+
+
+/*!
+******************************************************************************
+
+ @Function _DumpList
+ @Description
+ Dumps out RI List entries according to parameters passed.
+
+ @input hPMR - If not NULL, function will output the RI entries for
+ the specified PMR only
+ @input pid - If non-zero, the function will only output MEMDESC RI
+ entries made by the process with ID pid.
+ If zero, all MEMDESC RI entries will be output.
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR _DumpList(PMR *hPMR, IMG_PID pid)
+{
+ RI_LIST_ENTRY *psRIEntry = IMG_NULL;
+ RI_SUBLIST_ENTRY *psRISubEntry = IMG_NULL;
+ IMG_UINT16 ui16SubEntriesParsed = 0;
+ IMG_UINTPTR_T hashData = 0;
+ IMG_PID hashKey;
+ PMR *pPMRHashKey = hPMR;
+ IMG_BOOL bDisplayedThisPMR = IMG_FALSE;
+
+
+ if (!hPMR)
+ {
+ /* NULL handle provided */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ if (g_pRIHashTable && g_pProcHashTable)
+ {
+ if (pid != 0)
+ {
+ /* look-up pid in Hash Table */
+ hashKey = pid;
+ hashData = HASH_Retrieve_Extended (g_pProcHashTable, (IMG_VOID *)&hashKey);
+ if (hashData)
+ {
+ psRISubEntry = IMG_CONTAINER_OF((PDLLIST_NODE)hashData, RI_SUBLIST_ENTRY, sProcListNode);
+ if (psRISubEntry)
+ {
+ psRIEntry = psRISubEntry->psRI;
+ }
+ }
+ }
+ else
+ {
+ /* look-up hPMR in Hash Table */
+ hashData = HASH_Retrieve_Extended (g_pRIHashTable, (IMG_VOID *)&pPMRHashKey);
+ psRIEntry = (RI_LIST_ENTRY *)hashData;
+ }
+ if (!psRIEntry)
+ {
+ /* No entry found in hash table */
+ return PVRSRV_ERROR_NOT_FOUND;
+ }
+ while (psRIEntry)
+ {
+ bDisplayedThisPMR = IMG_FALSE;
+ /* Output details for RI entry */
+ if (!pid)
+ {
+ _RIOutput (("%s (0x%p) suballocs:%d size:0x" IMG_SIZE_FMTSPECX, psRIEntry->ai8TextA,psRIEntry->hPMR,(IMG_UINT)psRIEntry->ui16SubListCount,psRIEntry->uiLogicalSize));
+ bDisplayedThisPMR = IMG_TRUE;
+ }
+ ui16SubEntriesParsed = 0;
+ if(psRIEntry->ui16SubListCount)
+ {
+#if _DUMP_LINKEDLIST_INFO
+ _RIOutput (("RI LIST: {sSubListFirst.psNextNode:0x%x}",(IMG_UINT)psRIEntry->sSubListFirst.psNextNode));
+#endif /* _DUMP_LINKEDLIST_INFO */
+ if (!pid)
+ {
+ psRISubEntry = IMG_CONTAINER_OF(dllist_get_next_node(&(psRIEntry->sSubListFirst)), RI_SUBLIST_ENTRY, sListNode);
+ }
+ /* Traverse RI sublist and output details for each entry */
+ while (psRISubEntry && (ui16SubEntriesParsed < psRIEntry->ui16SubListCount))
+ {
+ if (!bDisplayedThisPMR)
+ {
+ _RIOutput (("%s (0x%p) suballocs:%d size:0x" IMG_SIZE_FMTSPECX, psRIEntry->ai8TextA,psRIEntry->hPMR,(IMG_UINT)psRIEntry->ui16SubListCount,psRIEntry->uiLogicalSize));
+ bDisplayedThisPMR = IMG_TRUE;
+ }
+#if _DUMP_LINKEDLIST_INFO
+ _RIOutput (("RI LIST: [this subentry:0x%x]",(IMG_UINT)psRISubEntry));
+ _RIOutput (("RI LIST: psRI:0x%x",(IMG_UINT32)psRISubEntry->psRI));
+#endif /* _DUMP_LINKEDLIST_INFO */
+
+ {
+ IMG_CHAR szEntryString[RI_MAX_MEMDESC_RI_ENTRY_LEN];
+
+ _GenerateMEMDESCEntryString(psRISubEntry, IMG_FALSE, RI_MAX_MEMDESC_RI_ENTRY_LEN, (IMG_CHAR *)&szEntryString);
+ szEntryString[RI_MAX_MEMDESC_RI_ENTRY_LEN-1] = '\0';
+ _RIOutput (("%s",(IMG_CHAR *)&szEntryString));
+ }
+
+ if (pid)
+ {
+ if((dllist_get_next_node(&(psRISubEntry->sProcListNode)) == 0) ||
+ (dllist_get_next_node(&(psRISubEntry->sProcListNode)) == (PDLLIST_NODE)hashData))
+ {
+ psRISubEntry = IMG_NULL;
+ }
+ else
+ {
+ psRISubEntry = IMG_CONTAINER_OF(dllist_get_next_node(&(psRISubEntry->sProcListNode)), RI_SUBLIST_ENTRY, sProcListNode);
+ if (psRISubEntry)
+ {
+ if (psRIEntry != psRISubEntry->psRI)
+ {
+ /*
+ * The next MEMDESC in the process linked list is in a different PMR
+ */
+ psRIEntry = psRISubEntry->psRI;
+ bDisplayedThisPMR = IMG_FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ ui16SubEntriesParsed++;
+ psRISubEntry = IMG_CONTAINER_OF(dllist_get_next_node(&(psRISubEntry->sListNode)), RI_SUBLIST_ENTRY, sListNode);
+ }
+ }
+ }
+ if (!pid)
+ {
+ if (ui16SubEntriesParsed != psRIEntry->ui16SubListCount)
+ {
+ /*
+ * Output error message as sublist does not contain the
+ * number of entries indicated by sublist count
+ */
+ _RIOutput (("RI ERROR: RI sublist contains %d entries, not %d entries",ui16SubEntriesParsed,psRIEntry->ui16SubListCount));
+ }
+ else if (psRIEntry->ui16SubListCount && !dllist_get_next_node(&(psRIEntry->sSubListFirst)))
+ {
+ /*
+ * Output error message as sublist is empty but sublist count
+ * is not zero
+ */
+ _RIOutput (("RI ERROR: ui16SubListCount=%d for empty RI sublist",psRIEntry->ui16SubListCount));
+ }
+ }
+ psRIEntry = IMG_NULL;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function RIDumpAllKM
+
+ @Description
+ Dumps out the contents of all RI List entries (i.e. for all
+ MEMDESC allocations for each PMR).
+ At present, output is directed to Kernel log
+ via PVR_DPF.
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIDumpAllKM(IMG_VOID)
+{
+ if (g_pRIHashTable)
+ {
+ return HASH_Iterate(g_pRIHashTable, (HASH_pfnCallback)_DumpAllEntries);
+ }
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function RIDumpProcessKM
+
+ @Description
+ Dumps out the contents of all MEMDESC RI List entries (for every
+ PMR) which have been allocate by the specified process only.
+ At present, output is directed to Kernel log
+ via PVR_DPF.
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RIDumpProcessKM(IMG_PID pid)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 dummyPMR;
+
+ if (g_pProcHashTable)
+ {
+ /* Acquire RI lock*/
+ _RILock();
+
+ eError = _DumpList((PMR *)&dummyPMR,pid);
+
+ /* Release RI lock*/
+ _RIUnlock();
+ }
+ return eError;
+}
+
+static PVRSRV_ERROR _DumpAllEntries (IMG_UINTPTR_T k, IMG_UINTPTR_T v)
+{
+ RI_LIST_ENTRY *psRIEntry = (RI_LIST_ENTRY *)v;
+
+ PVR_UNREFERENCED_PARAMETER (k);
+
+ return RIDumpListKM(psRIEntry->hPMR);
+}
+
+static PVRSRV_ERROR _DeleteAllEntries (IMG_UINTPTR_T k, IMG_UINTPTR_T v)
+{
+ RI_LIST_ENTRY *psRIEntry = (RI_LIST_ENTRY *)v;
+ RI_SUBLIST_ENTRY *psRISubEntry;
+ PVRSRV_ERROR eResult = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER (k);
+
+ while ((eResult == PVRSRV_OK) && (psRIEntry->ui16SubListCount > 0))
+ {
+ psRISubEntry = IMG_CONTAINER_OF(dllist_get_next_node(&(psRIEntry->sSubListFirst)), RI_SUBLIST_ENTRY, sListNode);
+ eResult = RIDeleteMEMDESCEntryKM((RI_HANDLE)psRISubEntry);
+ }
+ if (eResult == PVRSRV_OK)
+ {
+ eResult = RIDeletePMREntryKM((RI_HANDLE)psRIEntry);
+ /*
+ * If we've deleted the Hash table, return
+ * an error to stop the iterator...
+ */
+ if (!g_pRIHashTable)
+ {
+ eResult = PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
+ }
+ }
+ return eResult;
+}
+
+#endif /* if defined(PVR_RI_DEBUG) */
diff --git a/drivers/gpu/rogue/services/server/common/scp.c b/drivers/gpu/rogue/services/server/common/scp.c
new file mode 100644
index 000000000000..5e098b580d22
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/scp.c
@@ -0,0 +1,923 @@
+/*************************************************************************/ /*!
+@File scp.c
+@Title Software Command Processor
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description The software command processor allows commands queued and
+ deferred until their synchronisation requirements have been meet.
+@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 "scp.h"
+#include "lists.h"
+#include "allocmem.h"
+#include "pvrsrv.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "lock.h"
+#include "sync_server.h"
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#include <linux/file.h>
+#include <linux/seq_file.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
+#include <linux/sw_sync.h>
+#else
+#include <../drivers/staging/android/sw_sync.h>
+#endif
+static PVRSRV_ERROR AllocReleaseFence(struct sw_sync_timeline *psTimeline, const char *szName, IMG_UINT32 ui32FenceVal, int *piFenceFd)
+{
+ struct sync_fence *psFence = IMG_NULL;
+ struct sync_pt *psPt;
+ int iFd = get_unused_fd();
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (iFd < 0)
+ {
+ return PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
+ }
+
+ psPt = sw_sync_pt_create(psTimeline, ui32FenceVal);
+ if(!psPt)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorPutFd;
+ }
+
+ psFence = sync_fence_create(szName, psPt);
+ if(!psFence)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorFreePoint;
+ }
+
+ sync_fence_install(psFence, iFd);
+
+ *piFenceFd = iFd;
+
+ErrorOut:
+ return eError;
+
+ErrorFreePoint:
+ sync_pt_free(psPt);
+
+ErrorPutFd:
+ put_unused_fd(iFd);
+
+ goto ErrorOut;
+}
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+struct _SCP_CONTEXT_
+{
+ IMG_VOID *pvCCB; /*!< Pointer to the command circler buffer*/
+ volatile IMG_UINT32 ui32DepOffset; /*!< Dependency offset */
+ volatile IMG_UINT32 ui32ReadOffset; /*!< Read offset */
+ volatile IMG_UINT32 ui32WriteOffset; /*!< Write offset */
+ IMG_UINT32 ui32CCBSize; /*!< CCB size */
+ IMG_UINT32 psSyncRequesterID; /*!< Sync requester ID, used when taking sync operations */
+ POS_LOCK hLock; /*!< Lock for this structure */
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ IMG_VOID *pvTimeline;
+ IMG_UINT32 ui32TimelineVal;
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+};
+
+typedef struct _SCP_SYNC_DATA_
+{
+ SERVER_SYNC_PRIMITIVE *psSync; /*!< Server sync */
+ IMG_UINT32 ui32Fence; /*!< Fence value to check for */
+ IMG_UINT32 ui32Update; /*!< Fence update value */
+ IMG_UINT32 ui32Flags; /*!< Flags for this sync data */
+#define SCP_SYNC_DATA_FENCE (1<<0) /*!< This sync has a fence */
+#define SCP_SYNC_DATA_UPDATE (1<<1) /*!< This sync has an update */
+} SCP_SYNC_DATA;
+
+
+#define SCP_COMMAND_INVALID 0 /*!< Invalid command */
+#define SCP_COMMAND_CALLBACK 1 /*!< Command with callbacks */
+#define SCP_COMMAND_PADDING 2 /*!< Padding */
+typedef struct _SCP_COMMAND_
+{
+ IMG_UINT32 ui32CmdType; /*!< Command type */
+ IMG_UINT32 ui32CmdSize; /*!< Total size of the command (i.e. includes header) */
+ IMG_UINT32 ui32SyncCount; /*!< Total number of syncs in pasSync */
+ SCP_SYNC_DATA *pasSCPSyncData; /*!< Pointer to the array of sync data (allocated in the CCB) */
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ struct sync_fence *psAcquireFence;
+ struct sync_fence *psReleaseFence;
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+ SCPReady pfnReady; /*!< Pointer to the funtion to check if the command is ready */
+ SCPDo pfnDo; /*!< Pointer to the funtion to call when the command is ready to go */
+ IMG_PVOID pvReadyData; /*!< Data to pass into pfnReady */
+ IMG_PVOID pvCompleteData; /*!< Data to pass into pfnComplete */
+} SCP_COMMAND;
+
+#define GET_CCB_SPACE(WOff, ROff, CCBSize) \
+ ((((ROff) - (WOff)) + ((CCBSize) - 1)) & ((CCBSize) - 1))
+
+#define UPDATE_CCB_OFFSET(Off, PacketSize, CCBSize) \
+ (Off) = (((Off) + (PacketSize)) & ((CCBSize) - 1))
+
+#define PADDING_COMMAND_SIZE (sizeof(SCP_COMMAND))
+
+#if defined(SCP_DEBUG)
+#define SCP_DEBUG_PRINT(fmt, ...) \
+ PVRSRVDebugPrintf(PVR_DBG_WARNING, \
+ __FILE__, __LINE__, \
+ fmt, \
+ __VA_ARGS__)
+#else
+#define SCP_DEBUG_PRINT(fmt, ...)
+#endif
+
+/*****************************************************************************
+ * Internal functions *
+ *****************************************************************************/
+
+/*************************************************************************/ /*!
+@Function __SCPAlloc
+
+@Description Allocate space in the software command processor.
+
+@Input psContext Context to allocate from
+
+@Input ui32Size Size to allocate
+
+@Output ppvBufferSpace Pointer to space allocated
+
+@Return PVRSRV_OK if the allocation was successful
+*/
+/*****************************************************************************/
+static
+PVRSRV_ERROR __SCPAlloc(SCP_CONTEXT *psContext,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID *ppvBufferSpace)
+{
+ IMG_UINT32 ui32FreeSpace;
+
+ ui32FreeSpace = GET_CCB_SPACE(psContext->ui32WriteOffset,
+ psContext->ui32ReadOffset,
+ psContext->ui32CCBSize);
+ if (ui32FreeSpace >= ui32Size)
+ {
+ *ppvBufferSpace = (IMG_PVOID)((IMG_UINT8 *)psContext->pvCCB +
+ psContext->ui32WriteOffset);
+ return PVRSRV_OK;
+ }
+ else
+ {
+ return PVRSRV_ERROR_RETRY;
+ }
+}
+
+/*************************************************************************/ /*!
+@Function _SCPAlloc
+
+@Description Allocate space in the software command processor, handling the
+ case where we wrap around the CCB.
+
+@Input psContext Context to allocate from
+
+@Input ui32Size Size to allocate
+
+@Output ppvBufferSpace Pointer to space allocated
+
+@Return PVRSRV_OK if the allocation was successful
+*/
+/*****************************************************************************/
+static
+PVRSRV_ERROR _SCPAlloc(SCP_CONTEXT *psContext,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID *ppvBufferSpace)
+{
+ if ((ui32Size + PADDING_COMMAND_SIZE) > psContext->ui32CCBSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Command size (%d) too big for CCB\n", ui32Size));
+ return PVRSRV_ERROR_CMD_TOO_BIG;
+ }
+
+ /*
+ Check we don't overflow the end of the buffer and make sure we have
+ enough for the padding command
+ */
+ if ((psContext->ui32WriteOffset + ui32Size + PADDING_COMMAND_SIZE) > psContext->ui32CCBSize)
+ {
+ SCP_COMMAND *psCommand;
+ IMG_PVOID pvCommand;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Remain = psContext->ui32CCBSize - psContext->ui32WriteOffset;
+
+ /* We're at the end of the buffer without enough contiguous space */
+ eError = __SCPAlloc(psContext, ui32Remain, &pvCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_ASSERT(eError == PVRSRV_ERROR_RETRY);
+ return eError;
+ }
+ psCommand = pvCommand;
+ psCommand->ui32CmdType = SCP_COMMAND_PADDING;
+ psCommand->ui32CmdSize = ui32Remain;
+
+ UPDATE_CCB_OFFSET(psContext->ui32WriteOffset, ui32Remain, psContext->ui32CCBSize);
+ }
+
+ return __SCPAlloc(psContext, ui32Size, ppvBufferSpace);
+}
+
+/*************************************************************************/ /*!
+@Function _SCPInsert
+
+@Description Insert the a finished command that was written into the CCB
+ space allocated in a previous call to _SCPAlloc.
+ This makes the command ready to be processed.
+
+@Input psContext Context to allocate from
+
+@Input ui32Size Size to allocate
+
+@Return None
+*/
+/*****************************************************************************/
+static
+IMG_VOID _SCPInsert(SCP_CONTEXT *psContext,
+ IMG_UINT32 ui32Size)
+{
+ /*
+ * Update the write offset.
+ */
+ UPDATE_CCB_OFFSET(psContext->ui32WriteOffset,
+ ui32Size,
+ psContext->ui32CCBSize);
+}
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+static void _SCPDumpFence(const char *psczName, struct sync_fence *psFence)
+{
+ struct list_head *psEntry;
+ char szTime[16] = { '\0' };
+ char szVal1[64] = { '\0' };
+ char szVal2[64] = { '\0' };
+ char szVal3[132] = { '\0' };
+
+ PVR_LOG(("\t %s: [%p] %s: %s", psczName, psFence, psFence->name,
+ (psFence->status > 0 ? "signaled" :
+ psFence->status == 0 ? "active" : "error")));
+ list_for_each(psEntry, &psFence->pt_list_head)
+ {
+ struct sync_pt *psPt = container_of(psEntry, struct sync_pt, pt_list);
+ struct timeval tv = ktime_to_timeval(psPt->timestamp);
+ snprintf(szTime, sizeof(szTime), "@%ld.%06ld", tv.tv_sec, tv.tv_usec);
+ if (psPt->parent->ops->pt_value_str &&
+ psPt->parent->ops->timeline_value_str)
+ {
+ psPt->parent->ops->pt_value_str(psPt, szVal1, sizeof(szVal1));
+ psPt->parent->ops->timeline_value_str(psPt->parent, szVal2, sizeof(szVal2));
+ snprintf(szVal3, sizeof(szVal3), ": %s / %s", szVal1, szVal2);
+ }
+ PVR_LOG(("\t %s %s%s%s", psPt->parent->name,
+ (psPt->status > 0 ? "signaled" :
+ psPt->status == 0 ? "active" : "error"),
+ (psPt->status > 0 ? szTime : ""),
+ szVal3));
+ }
+
+}
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+/*************************************************************************/ /*!
+@Function _SCPCommandReady
+
+@Description Check if a command is ready. Checks to see if the command
+ has had it's fences meet and is ready to go.
+
+@Input psCommand Command to check
+
+@Return PVRSRV_OK if the command is ready
+*/
+/*****************************************************************************/
+static
+PVRSRV_ERROR _SCPCommandReady(SCP_COMMAND *psCommand)
+{
+ IMG_UINT32 i;
+
+ PVR_ASSERT(psCommand->ui32CmdType != SCP_COMMAND_INVALID);
+
+ if (psCommand->ui32CmdType == SCP_COMMAND_PADDING)
+ {
+ return PVRSRV_OK;
+ }
+
+ for (i = 0; i < psCommand->ui32SyncCount; i++)
+ {
+ SCP_SYNC_DATA *psSCPSyncData = &psCommand->pasSCPSyncData[i];
+
+ /*
+ If the same sync is used in concurrent command we can skip the check
+ */
+ if (psSCPSyncData->ui32Flags & SCP_SYNC_DATA_FENCE)
+ {
+ if (!ServerSyncFenceIsMet(psSCPSyncData->psSync, psSCPSyncData->ui32Fence))
+ {
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ }
+ }
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ /* Check for the provided acquire fence */
+ if (psCommand->psAcquireFence != IMG_NULL)
+ {
+ int err = sync_fence_wait(psCommand->psAcquireFence, 0);
+ /* -ETIME means active. In this case we will retry later again. If the
+ * return value is an error or zero we will close this fence and
+ * proceed. This makes sure that we are not getting stuck here when a
+ * fence changes into an error state for whatever reason. */
+ if (err == -ETIME)
+ {
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ else
+ {
+ if (err)
+ {
+ PVR_LOG(("SCP: Fence wait failed with %d", err));
+ _SCPDumpFence("Acquire Fence", psCommand->psAcquireFence);
+ }
+ /* Put the fence. */
+ sync_fence_put(psCommand->psAcquireFence);
+ psCommand->psAcquireFence = IMG_NULL;
+ }
+ }
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+ /* Command is ready */
+ if (psCommand->pfnReady(psCommand->pvReadyData))
+ {
+ return PVRSRV_OK;
+ }
+
+ /*
+ If we got here it means the command is ready to go, but the SCP client
+ isn't ready for the command
+ */
+ return PVRSRV_ERROR_NOT_READY;
+}
+
+/*************************************************************************/ /*!
+@Function _SCPCommandDo
+
+@Description Run a command
+
+@Input psCommand Command to run
+
+@Return PVRSRV_OK if the command is ready
+*/
+/*****************************************************************************/
+static
+IMG_VOID _SCPCommandDo(SCP_COMMAND *psCommand)
+{
+ if (psCommand->ui32CmdType == SCP_COMMAND_CALLBACK)
+ {
+ psCommand->pfnDo(psCommand->pvReadyData, psCommand->pvCompleteData);
+ }
+}
+
+/*************************************************************************/ /*!
+@Function _SCPDumpCommand
+
+@Description Dump a SCP command
+
+@Input psCommand Command to dump
+
+@Return None
+*/
+/*****************************************************************************/
+static IMG_VOID _SCPDumpCommand(SCP_COMMAND *psCommand)
+{
+ IMG_UINT32 i;
+
+ PVR_LOG(("\tCommand type = %d (@%p)", psCommand->ui32CmdType, psCommand));
+
+ if (psCommand->ui32CmdType == SCP_COMMAND_CALLBACK)
+ {
+ for (i = 0; i < psCommand->ui32SyncCount; i++)
+ {
+ SCP_SYNC_DATA *psSCPSyncData = &psCommand->pasSCPSyncData[i];
+
+ /*
+ Only dump this sync if there is a fence operation on it
+ */
+ if (psSCPSyncData->ui32Flags & SCP_SYNC_DATA_FENCE)
+ {
+ PVR_LOG(("\t\tFenced on 0x%08x = 0x%08x (?= 0x%08x)",
+ ServerSyncGetFWAddr(psSCPSyncData->psSync),
+ psSCPSyncData->ui32Fence,
+ ServerSyncGetValue(psSCPSyncData->psSync)));
+ }
+ }
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ if (psCommand->psAcquireFence)
+ {
+ _SCPDumpFence("Acquire Fence", psCommand->psAcquireFence);
+ }
+ if (psCommand->psReleaseFence)
+ {
+ _SCPDumpFence("Release Fence", psCommand->psReleaseFence);
+ }
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+ }
+}
+
+/*****************************************************************************
+ * Public interface functions *
+ *****************************************************************************/
+
+/*
+ SCPCreate
+*/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV SCPCreate(IMG_UINT32 ui32CCBSizeLog2,
+ SCP_CONTEXT **ppsContext)
+{
+ SCP_CONTEXT *psContext;
+ IMG_UINT32 ui32Power2QueueSize = 1 << ui32CCBSizeLog2;
+ PVRSRV_ERROR eError;
+
+ /* allocate an internal queue info structure */
+ psContext = OSAllocMem(sizeof(SCP_CONTEXT));
+ if (psContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SCPCreate: Failed to alloc queue struct"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+ OSMemSet(psContext, 0, sizeof(SCP_CONTEXT));
+
+ /* allocate the command queue buffer - allow for overrun */
+ psContext->pvCCB = OSAllocMem(ui32Power2QueueSize);
+ if (psContext->pvCCB == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SCPCreate: Failed to alloc queue buffer"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+ /* Sanity check: Should be zeroed by OSMemSet */
+ PVR_ASSERT(psContext->ui32ReadOffset == 0);
+ PVR_ASSERT(psContext->ui32WriteOffset == 0);
+
+ psContext->ui32CCBSize = ui32Power2QueueSize;
+
+ eError = OSLockCreate(&psContext->hLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ eError = PVRSRVServerSyncRequesterRegisterKM(&psContext->psSyncRequesterID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ psContext->pvTimeline = sw_sync_timeline_create("pvr_scp");
+ if(psContext->pvTimeline == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SCPCreate: sw_sync_timeline_create() failed"));
+ goto ErrorExit;
+ }
+ psContext->ui32TimelineVal = 0;
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+ SCP_DEBUG_PRINT("%s: New SCP %p of size %d",
+ __FUNCTION__, psContext, ui32Power2QueueSize);
+
+ *ppsContext = psContext;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+ if(psContext)
+ {
+ if(psContext->pvCCB)
+ {
+ OSFreeMem(psContext->pvCCB);
+ psContext->pvCCB = IMG_NULL;
+ }
+
+ OSFreeMem(psContext);
+ }
+
+ return eError;
+}
+
+/*
+ SCPAllocCommand
+*/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV SCPAllocCommand(SCP_CONTEXT *psContext,
+ IMG_UINT32 ui32SyncPrimCount,
+ SERVER_SYNC_PRIMITIVE **papsSync,
+ IMG_BOOL *pabUpdate,
+ IMG_INT32 i32AcquireFenceFd,
+ SCPReady pfnCommandReady,
+ SCPDo pfnCommandDo,
+ IMG_SIZE_T ui32ReadyDataByteSize,
+ IMG_SIZE_T ui32CompleteDataByteSize,
+ IMG_PVOID *ppvReadyData,
+ IMG_PVOID *ppvCompleteData,
+ IMG_INT32 *pi32ReleaseFenceFd)
+{
+ PVRSRV_ERROR eError;
+ SCP_COMMAND *psCommand;
+ IMG_UINT32 ui32CommandSize;
+ IMG_UINT32 ui32SyncOpSize;
+ IMG_UINT32 i;
+
+ /* Round up the incoming data sizes to be pointer granular */
+ ui32ReadyDataByteSize = (ui32ReadyDataByteSize & (~(sizeof(IMG_PVOID)-1))) + sizeof(IMG_PVOID);
+ ui32CompleteDataByteSize = (ui32CompleteDataByteSize & (~(sizeof(IMG_PVOID)-1))) + sizeof(IMG_PVOID);
+
+ ui32SyncOpSize = (sizeof(PVRSRV_CLIENT_SYNC_PRIM_OP) * ui32SyncPrimCount);
+
+ /* Total command size */
+ ui32CommandSize = sizeof(SCP_COMMAND) +
+ ui32SyncOpSize +
+ ui32ReadyDataByteSize +
+ ui32CompleteDataByteSize;
+
+ eError = _SCPAlloc(psContext, ui32CommandSize, (IMG_VOID **) &psCommand);
+ if(eError != PVRSRV_OK)
+ {
+ SCP_DEBUG_PRINT("%s: Failed to allocate command of size %d for ctx %p (%d)", __FUNCTION__, ui32CommandSize, psContext, eError);
+ return eError;
+ }
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ if (pi32ReleaseFenceFd)
+ {
+ /* Create a release sync for the caller. */
+ eError = AllocReleaseFence(psContext->pvTimeline, "pvr_scp_retire",
+ ++psContext->ui32TimelineVal,
+ pi32ReleaseFenceFd);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+#else /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+ PVR_UNREFERENCED_PARAMETER(i32AcquireFenceFd);
+ PVR_UNREFERENCED_PARAMETER(pi32ReleaseFenceFd);
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+ SCP_DEBUG_PRINT("%s: New Command %p for ctx %p of size %d, syncCount: %d",
+ __FUNCTION__, psCommand, psContext, ui32CommandSize, ui32SyncPrimCount);
+
+ /* setup the command */
+ psCommand->ui32CmdSize = ui32CommandSize;
+ psCommand->ui32CmdType = SCP_COMMAND_CALLBACK;
+ psCommand->ui32SyncCount = ui32SyncPrimCount;
+
+ /* Set up command pointers */
+ psCommand->pasSCPSyncData = (SCP_SYNC_DATA *) (((IMG_CHAR *) psCommand) + sizeof(SCP_COMMAND));
+
+ psCommand->pfnReady = pfnCommandReady;
+ psCommand->pfnDo = pfnCommandDo;
+
+ psCommand->pvReadyData = ((IMG_CHAR *) psCommand) +
+ sizeof(SCP_COMMAND) + ui32SyncOpSize;
+ psCommand->pvCompleteData = ((IMG_CHAR *) psCommand) +
+ sizeof(SCP_COMMAND) + ui32SyncOpSize +
+ ui32ReadyDataByteSize;
+
+ /* Copy over the sync data */
+ for (i=0;i<ui32SyncPrimCount;i++)
+ {
+ SCP_SYNC_DATA *psSCPSyncData = &psCommand->pasSCPSyncData[i];
+ IMG_BOOL bFenceRequired;
+
+ psSCPSyncData->psSync = papsSync[i];
+
+ PVRSRVServerSyncQueueSWOpKM(papsSync[i],
+ &psSCPSyncData->ui32Fence,
+ &psSCPSyncData->ui32Update,
+ psContext->psSyncRequesterID,
+ pabUpdate[i],
+ &bFenceRequired);
+ if (bFenceRequired)
+ {
+ psSCPSyncData->ui32Flags = SCP_SYNC_DATA_FENCE;
+ }
+ else
+ {
+ psSCPSyncData->ui32Flags = 0;
+ }
+
+ /* Only update if requested */
+ if (pabUpdate[i])
+ {
+ psSCPSyncData->ui32Flags |= SCP_SYNC_DATA_UPDATE;
+ }
+ }
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ /* Copy over the fences */
+ if (i32AcquireFenceFd >= 0)
+ {
+ psCommand->psAcquireFence = sync_fence_fdget(i32AcquireFenceFd);
+ }
+ else
+ {
+ psCommand->psAcquireFence = IMG_NULL;
+ }
+
+ if (pi32ReleaseFenceFd)
+ {
+ psCommand->psReleaseFence = sync_fence_fdget(*pi32ReleaseFenceFd);
+ }
+ else
+ {
+ psCommand->psReleaseFence = IMG_NULL;
+ }
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+ *ppvReadyData = psCommand->pvReadyData;
+ *ppvCompleteData = psCommand->pvCompleteData;
+
+ return PVRSRV_OK;
+}
+
+/*
+ SCPSubmitCommand
+*/
+IMG_EXPORT
+PVRSRV_ERROR SCPSubmitCommand(SCP_CONTEXT *psContext)
+{
+ SCP_COMMAND *psCommand;
+
+ if (psContext == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psCommand = (SCP_COMMAND *) ((IMG_UINT8 *) psContext->pvCCB
+ + psContext->ui32WriteOffset);
+
+ SCP_DEBUG_PRINT("%s: Submit command %p for ctx %p",
+ __FUNCTION__, psCommand, psContext);
+
+ _SCPInsert(psContext, psCommand->ui32CmdSize);
+
+ return PVRSRV_OK;
+}
+
+/*
+ SCPRun
+*/
+IMG_EXPORT
+PVRSRV_ERROR SCPRun(SCP_CONTEXT *psContext)
+{
+ SCP_COMMAND *psCommand;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+
+ if (psContext == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ OSLockAcquire(psContext->hLock);
+ while (psContext->ui32DepOffset != psContext->ui32WriteOffset)
+ {
+ psCommand = (SCP_COMMAND *)((IMG_UINT8 *)psContext->pvCCB +
+ psContext->ui32DepOffset);
+
+ /* See if the command is ready to go */
+ eError = _SCPCommandReady(psCommand);
+
+ SCP_DEBUG_PRINT("%s: Processes command %p for ctx %p (%d)",
+ __FUNCTION__, psCommand, psContext, eError);
+
+ if (eError == PVRSRV_OK)
+ {
+ /* processed cmd so update queue */
+ UPDATE_CCB_OFFSET(psContext->ui32DepOffset,
+ psCommand->ui32CmdSize,
+ psContext->ui32CCBSize);
+ }
+ else
+ {
+ /* As soon as we hit a command that can't run break out */
+ break;
+ }
+
+ /* Run the command */
+ _SCPCommandDo(psCommand);
+ }
+ OSLockRelease(psContext->hLock);
+
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SCPFlush(SCP_CONTEXT *psContext)
+{
+ if (psContext->ui32ReadOffset != psContext->ui32WriteOffset)
+ {
+ return PVRSRV_ERROR_RETRY;
+ }
+
+ return PVRSRV_OK;
+}
+
+/*
+ SCPCommandComplete
+*/
+IMG_EXPORT
+IMG_VOID SCPCommandComplete(SCP_CONTEXT *psContext)
+{
+ SCP_COMMAND *psCommand;
+ IMG_UINT32 i;
+ IMG_BOOL bContinue = IMG_TRUE;
+
+ if (psContext == IMG_NULL)
+ {
+ return;
+ }
+
+ if (psContext->ui32ReadOffset == psContext->ui32DepOffset)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SCPCommandComplete: Called with no work to do!"));
+ return;
+ }
+
+ while(bContinue)
+ {
+ psCommand = (SCP_COMMAND *) ((IMG_UINT8 *) psContext->pvCCB +
+ psContext->ui32ReadOffset);
+
+ if (psCommand->ui32CmdType == SCP_COMMAND_CALLBACK)
+ {
+ /* Do any fence updates */
+ for (i=0;i<psCommand->ui32SyncCount;i++)
+ {
+ SCP_SYNC_DATA *psSCPSyncData = &psCommand->pasSCPSyncData[i];
+ IMG_BOOL bUpdate = (psSCPSyncData->ui32Flags & SCP_SYNC_DATA_UPDATE);
+
+ ServerSyncCompleteOp(psSCPSyncData->psSync, bUpdate, psSCPSyncData->ui32Update);
+
+ if (bUpdate)
+ {
+ psSCPSyncData->ui32Flags = 0; /* Stop future interaction with this sync prim. */
+ psSCPSyncData->psSync = NULL; /* Clear psSync as it is no longer referenced. */
+ }
+ }
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ if (psCommand->psReleaseFence)
+ {
+ sw_sync_timeline_inc(psContext->pvTimeline, 1);
+ /* Decrease the ref to this fence */
+ sync_fence_put(psCommand->psReleaseFence);
+ psCommand->psReleaseFence = IMG_NULL;
+ }
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+ bContinue = IMG_FALSE;
+ }
+
+ /* processed cmd so update queue */
+ UPDATE_CCB_OFFSET(psContext->ui32ReadOffset,
+ psCommand->ui32CmdSize,
+ psContext->ui32CCBSize);
+
+ SCP_DEBUG_PRINT("%s: Complete command %p for ctx %p (continue: %d)",
+ __FUNCTION__, psCommand, psContext, bContinue);
+
+ }
+}
+
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV SCPDumpStatus(SCP_CONTEXT *psContext)
+{
+ /*
+ Acquire the lock to ensure that the SCP isn't run while
+ while we're dumping info
+ */
+ OSLockAcquire(psContext->hLock);
+
+ PVR_LOG(("Pending command:"));
+ if (psContext->ui32DepOffset == psContext->ui32WriteOffset)
+ {
+ PVR_LOG(("\tNone"));
+ }
+ else
+ {
+ SCP_COMMAND *psCommand;
+ IMG_UINT32 ui32DepOffset = psContext->ui32DepOffset;
+
+ while (ui32DepOffset != psContext->ui32WriteOffset)
+ {
+ /* Dump the command we're pending on */
+ psCommand = (SCP_COMMAND *)((IMG_UINT8 *)psContext->pvCCB +
+ ui32DepOffset);
+
+ _SCPDumpCommand(psCommand);
+
+ /* processed cmd so update queue */
+ UPDATE_CCB_OFFSET(ui32DepOffset,
+ psCommand->ui32CmdSize,
+ psContext->ui32CCBSize);
+
+ }
+ }
+
+ PVR_LOG(("Active command(s):"));
+ if (psContext->ui32DepOffset == psContext->ui32ReadOffset)
+ {
+ PVR_LOG(("\tNone"));
+ }
+ else
+ {
+ SCP_COMMAND *psCommand;
+ IMG_UINT32 ui32ReadOffset = psContext->ui32ReadOffset;
+
+ while (ui32ReadOffset != psContext->ui32DepOffset)
+ {
+ psCommand = (SCP_COMMAND *)((IMG_UINT8 *)psContext->pvCCB +
+ ui32ReadOffset);
+
+ _SCPDumpCommand(psCommand);
+
+ /* processed cmd so update queue */
+ UPDATE_CCB_OFFSET(ui32ReadOffset,
+ psCommand->ui32CmdSize,
+ psContext->ui32CCBSize);
+ }
+ }
+
+ OSLockRelease(psContext->hLock);
+}
+
+
+/*
+ SCPDestroy
+*/
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV SCPDestroy(SCP_CONTEXT *psContext)
+{
+ /*
+ The caller must ensure that they completed all queued operations
+ before calling this function
+ */
+
+ PVR_ASSERT(psContext->ui32ReadOffset == psContext->ui32WriteOffset);
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ sync_timeline_destroy(psContext->pvTimeline);
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+ PVRSRVServerSyncRequesterUnregisterKM(psContext->psSyncRequesterID);
+ OSLockDestroy(psContext->hLock);
+ psContext->hLock = IMG_NULL;
+ OSFreeMem(psContext->pvCCB);
+ psContext->pvCCB = IMG_NULL;
+ OSFreeMem(psContext);
+}
diff --git a/drivers/gpu/rogue/services/server/common/srvcore.c b/drivers/gpu/rogue/services/server/common/srvcore.c
new file mode 100644
index 000000000000..094dbd676606
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/srvcore.c
@@ -0,0 +1,619 @@
+/*************************************************************************/ /*!
+@File
+@Title PVR Common Bridge Module (kernel side)
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements core PVRSRV API, server side
+@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 <stddef.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "ra.h"
+#include "pvr_bridge.h"
+#include "connection_server.h"
+#include "device.h"
+
+#include "pdump_km.h"
+
+#if defined LINUX
+#include "env_data.h"
+#endif
+
+#include "srvkm.h"
+#include "allocmem.h"
+#include "devicemem.h"
+
+#include "srvcore.h"
+#include "pvrsrv.h"
+#include "power.h"
+#include "lists.h"
+
+#include "rgx_options_km.h"
+#include "pvrversion.h"
+
+/* For the purpose of maintainability, it is intended that this file should not
+ * contain any OS specific #ifdefs. Please find a way to add e.g.
+ * an osfunc.c abstraction or override the entire function in question within
+ * env,*,pvr_bridge_k.c
+ */
+
+PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(CONNECTION_DATA *psConnection,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyFromUserTotalBytes+=ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+=ui32Size;
+ return OSCopyFromUser(psConnection, pvDest, pvSrc, ui32Size);
+}
+PVRSRV_ERROR
+CopyToUserWrapper(CONNECTION_DATA *psConnection,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyToUserTotalBytes+=ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes+=ui32Size;
+ return OSCopyToUser(psConnection, pvDest, pvSrc, ui32Size);
+}
+#endif
+
+PVRSRV_ERROR
+PVRSRVConnectKM(CONNECTION_DATA *psConnection,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32ClientBuildOptions,
+ IMG_UINT32 ui32ClientDDKVersion,
+ IMG_UINT32 ui32ClientDDKBuild,
+ IMG_UINT8 *pui8KernelArch,
+ IMG_UINT32 *ui32Log2PageSize)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 ui32BuildOptions, ui32BuildOptionsMismatch;
+ IMG_UINT32 ui32DDKVersion, ui32DDKBuild;
+
+ *ui32Log2PageSize = GET_LOG2_PAGESIZE();
+
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ if(ui32Flags & SRV_FLAGS_INIT_PROCESS)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Connecting as init process", __func__));
+ if ((OSProcHasPrivSrvInit() == IMG_FALSE) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Rejecting init process", __func__));
+ eError = PVRSRV_ERROR_SRV_CONNECT_FAILED;
+ goto chk_exit;
+ }
+#if defined (__linux__)
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
+#endif
+ }
+ else
+ {
+ if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+ {
+ if (!PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation failed. Driver unusable.",
+ __FUNCTION__));
+ eError = PVRSRV_ERROR_INIT_FAILURE;
+ goto chk_exit;
+ }
+ }
+ else
+ {
+ if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation is in progress",
+ __FUNCTION__));
+ eError = PVRSRV_ERROR_RETRY;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Driver initialisation not completed yet.",
+ __FUNCTION__));
+ eError = PVRSRV_ERROR_RETRY;
+ goto chk_exit;
+ }
+ }
+ }
+ ui32ClientBuildOptions &= RGX_BUILD_OPTIONS_MASK_KM;
+ /*
+ * Validate the build options
+ */
+ ui32BuildOptions = (RGX_BUILD_OPTIONS_KM);
+ if (ui32BuildOptions != ui32ClientBuildOptions)
+ {
+ ui32BuildOptionsMismatch = ui32BuildOptions ^ ui32ClientBuildOptions;
+ if ( (ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) %s: Mismatch in client-side and KM driver build options; "
+ "extra options present in client-side driver: (0x%x). Please check rgx_options.h",
+ __FUNCTION__,
+ ui32ClientBuildOptions & ui32BuildOptionsMismatch ));
+ }
+
+ if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) %s: Mismatch in client-side and KM driver build options; "
+ "extra options present in KM driver: (0x%x). Please check rgx_options.h",
+ __FUNCTION__,
+ ui32BuildOptions & ui32BuildOptionsMismatch ));
+ }
+ eError = PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: COMPAT_TEST: Client-side and KM driver build options match. [ OK ]", __FUNCTION__));
+ }
+
+ /*
+ * Validate DDK version
+ */
+ ui32DDKVersion = PVRVERSION_PACK(PVRVERSION_MAJ, PVRVERSION_MIN);
+ if (ui32ClientDDKVersion != ui32DDKVersion)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible driver DDK revision (%u.%u) / client DDK revision (%u.%u).",
+ __FUNCTION__,
+ PVRVERSION_MAJ, PVRVERSION_MIN,
+ PVRVERSION_UNPACK_MAJ(ui32ClientDDKVersion),
+ PVRVERSION_UNPACK_MIN(ui32ClientDDKVersion)));
+ eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+ PVR_DBG_BREAK;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: COMPAT_TEST: driver DDK revision (%u.%u) and client DDK revision (%u.%u) match. [ OK ]",
+ __FUNCTION__,
+ PVRVERSION_MAJ, PVRVERSION_MIN, PVRVERSION_MAJ, PVRVERSION_MIN));
+ }
+
+ /*
+ * Validate DDK build
+ */
+ ui32DDKBuild = PVRVERSION_BUILD;
+ if (ui32ClientDDKBuild != ui32DDKBuild)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible driver DDK build (%d) / client DDK build (%d).",
+ __FUNCTION__, ui32DDKBuild, ui32ClientDDKBuild));
+ eError = PVRSRV_ERROR_DDK_BUILD_MISMATCH;
+ PVR_DBG_BREAK;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: COMPAT_TEST: driver DDK build (%d) and client DDK build (%d) match. [ OK ]",
+ __FUNCTION__, ui32DDKBuild, ui32ClientDDKBuild));
+ }
+
+ /* Success so far so is it the PDump client that is connecting? */
+ if (ui32Flags & SRV_FLAGS_PDUMPCTRL)
+ {
+ PDumpConnectionNotify();
+ }
+
+ PVR_ASSERT(pui8KernelArch != NULL);
+ /* Can't use __SIZEOF_POINTER__ here as it is not defined on WDDM */
+ if (sizeof(IMG_PVOID) == 8)
+ {
+ *pui8KernelArch = 64;
+ }
+ else
+ {
+ *pui8KernelArch = 32;
+ }
+
+ if (ui32Flags & SRV_FLAGS_INIT_PROCESS)
+ {
+ psConnection->bInitProcess = IMG_TRUE;
+ }
+
+chk_exit:
+ return eError;
+}
+
+PVRSRV_ERROR
+PVRSRVDisconnectKM(IMG_VOID)
+{
+ /* just return OK, per-process data is cleaned up by resmgr */
+
+ return PVRSRV_OK;
+}
+
+/*
+ PVRSRVDumpDebugInfoKM
+*/
+PVRSRV_ERROR
+PVRSRVDumpDebugInfoKM(IMG_UINT32 ui32VerbLevel)
+{
+ if (ui32VerbLevel > DEBUG_REQUEST_VERBOSITY_MAX)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ PVR_LOG(("User requested PVR debug info"));
+
+ PVRSRVDebugRequest(ui32VerbLevel, IMG_NULL);
+
+ return PVRSRV_OK;
+}
+
+/*
+ PVRSRVGetDevClockSpeedKM
+*/
+PVRSRV_ERROR
+PVRSRVGetDevClockSpeedKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_PUINT32 pui32RGXClockSpeed)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVR_ASSERT(psDeviceNode->pfnDeviceClockSpeed != IMG_NULL);
+
+ eError = psDeviceNode->pfnDeviceClockSpeed(psDeviceNode, pui32RGXClockSpeed);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetDevClockSpeedKM: "
+ "Could not get device clock speed (%d)!",
+ eError));
+ }
+
+ return eError;
+}
+
+
+/*
+ PVRSRVHWOpTimeoutKM
+*/
+PVRSRV_ERROR
+PVRSRVHWOpTimeoutKM(IMG_VOID)
+{
+#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
+ PVR_LOG(("User requested OS reset"));
+ OSPanic();
+#endif
+ PVR_LOG(("HW operation timeout, dump server info"));
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_LOW,IMG_NULL);
+ return PVRSRV_OK;
+}
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ CONNECTION_DATA *psConnection)
+{
+#if !defined(DEBUG)
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+#endif
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u (%s) mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID, g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID));
+#endif
+ return -ENOTTY;
+}
+
+
+/*
+ PVRSRVSoftResetKM
+*/
+PVRSRV_ERROR
+PVRSRVSoftResetKM(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64ResetValue)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if ((psDeviceNode == IMG_NULL) || (psDeviceNode->pfnSoftReset == IMG_NULL))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = psDeviceNode->pfnSoftReset(psDeviceNode, ui64ResetValue);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVSoftResetKM: "
+ "Failed to soft reset (error %d)",
+ eError));
+ }
+
+ return eError;
+}
+
+
+/*!
+ * *****************************************************************************
+ * @brief A wrapper for filling in the g_BridgeDispatchTable array that does
+ * error checking.
+ *
+ * @param ui32Index
+ * @param pszIOCName
+ * @param pfFunction
+ * @param pszFunctionName
+ *
+ * @return
+ ********************************************************************************/
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+ const IMG_CHAR *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const IMG_CHAR *pszFunctionName)
+{
+ static IMG_UINT32 ui32PrevIndex = IMG_UINT32_MAX; /* -1 */
+#if !defined(DEBUG)
+ PVR_UNREFERENCED_PARAMETER(pszIOCName);
+#endif
+#if !defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE) && !defined(DEBUG_BRIDGE_KM)
+ PVR_UNREFERENCED_PARAMETER(pszFunctionName);
+#endif
+
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+ /* Enable this to dump out the dispatch table entries */
+ PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index, pszIOCName, pszFunctionName));
+#endif
+
+ /* Any gaps are sub-optimal in-terms of memory usage, but we are mainly
+ * interested in spotting any large gap of wasted memory that could be
+ * accidentally introduced.
+ *
+ * This will currently flag up any gaps > 5 entries.
+ *
+ * NOTE: This shouldn't be debug only since switching from debug->release
+ * etc is likely to modify the available ioctls and thus be a point where
+ * mistakes are exposed. This isn't run at at a performance critical time.
+ */
+ if((ui32PrevIndex != IMG_UINT32_MAX) &&
+ ((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
+ (ui32Index <= ui32PrevIndex)))
+ {
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: There is a gap in the dispatch table between indices %u (%s) and %u (%s)",
+ __FUNCTION__, ui32PrevIndex, g_BridgeDispatchTable[ui32PrevIndex].pszIOCName,
+ ui32Index, pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s: There is a gap in the dispatch table between indices %u and %u (%s)",
+ __FUNCTION__, (IMG_UINT)ui32PrevIndex, (IMG_UINT)ui32Index, pszIOCName));
+#endif
+#if !defined(PVRSRV_ALLOW_BRIDGE_DISPATCH_TABLE_GAPS)
+ /* In WDDM we do not register all the bridge modules and therefore
+ * it is natural to have gaps, hence do not panic.
+ */
+ PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+ OSPanic();
+#endif
+ }
+
+ if (ui32Index >= BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Index %u (%s) out of range",
+ __FUNCTION__, (IMG_UINT)ui32Index, pszIOCName));
+ OSPanic();
+ }
+
+ /* Panic if the previous entry has been overwritten as this is not allowed!
+ * NOTE: This shouldn't be debug only since switching from debug->release
+ * etc is likely to modify the available ioctls and thus be a point where
+ * mistakes are exposed. This isn't run at at a performance critical time.
+ */
+ if(g_BridgeDispatchTable[ui32Index].pfFunction)
+ {
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry for %s",
+ __FUNCTION__, pszIOCName, g_BridgeDispatchTable[ui32Index].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry (index=%u)",
+ __FUNCTION__, pszIOCName, ui32Index));
+#endif
+ PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+ OSPanic();
+ }
+
+ g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
+ g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
+ g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
+ g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+#endif
+
+ ui32PrevIndex = ui32Index;
+}
+
+PVRSRV_ERROR
+PVRSRVInitSrvDisconnectKM(CONNECTION_DATA *psConnection,
+ IMG_BOOL bInitSuccesful,
+ IMG_UINT32 ui32ClientBuildOptions)
+{
+ PVRSRV_ERROR eError;
+
+ if(!psConnection->bInitProcess)
+ {
+ return PVRSRV_ERROR_SRV_DISCONNECT_FAILED;
+ }
+
+ psConnection->bInitProcess = IMG_FALSE;
+
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
+
+ eError = PVRSRVFinaliseSystem(bInitSuccesful, ui32ClientBuildOptions);
+
+ PVRSRVSetInitServerState( PVRSRV_INIT_SERVER_SUCCESSFUL ,
+ (eError == PVRSRV_OK) && bInitSuccesful);
+
+ return eError;
+}
+
+IMG_INT BridgedDispatchKM(CONNECTION_DATA * psConnection,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM)
+{
+
+ IMG_VOID * psBridgeIn;
+ IMG_VOID * psBridgeOut;
+ BridgeWrapperFunction pfBridgeHandler;
+ IMG_UINT32 ui32BridgeID = psBridgePackageKM->ui32BridgeID;
+ IMG_INT err = -EFAULT;
+
+#if defined(DEBUG_BRIDGE_KM_STOP_AT_DISPATCH)
+ PVR_DBG_BREAK;
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: %s",
+ __FUNCTION__,
+ g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+ g_BridgeDispatchTable[ui32BridgeID].ui32CallCount++;
+ g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+
+#if defined(__linux__)
+ {
+
+ ENV_DATA *psEnvData = OSGetEnvData();
+
+ /* We have already set up some static buffers to store our ioctl data... */
+ psBridgeIn = psEnvData->pvBridgeData;
+ psBridgeOut = (IMG_PVOID)((IMG_PBYTE)psBridgeIn + PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+ /* check we are not using a bigger bridge than allocated */
+#if defined(DEBUG)
+ PVR_ASSERT(psBridgePackageKM->ui32InBufferSize < PVRSRV_MAX_BRIDGE_IN_SIZE);
+ PVR_ASSERT(psBridgePackageKM->ui32OutBufferSize < PVRSRV_MAX_BRIDGE_OUT_SIZE);
+#endif
+
+ if(psBridgePackageKM->ui32InBufferSize > 0)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->ui32InBufferSize))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid pvParamIn pointer", __FUNCTION__));
+ }
+
+ if(CopyFromUserWrapper(psConnection,
+ ui32BridgeID,
+ psBridgeIn,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->ui32InBufferSize)
+ != PVRSRV_OK)
+ {
+ goto return_fault;
+ }
+ }
+ }
+#else
+ psBridgeIn = psBridgePackageKM->pvParamIn;
+ psBridgeOut = psBridgePackageKM->pvParamOut;
+#endif
+
+ if(ui32BridgeID >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: ui32BridgeID = %d is out if range!",
+ __FUNCTION__, ui32BridgeID));
+ goto return_fault;
+ }
+ pfBridgeHandler =
+ (BridgeWrapperFunction)g_BridgeDispatchTable[ui32BridgeID].pfFunction;
+
+ if (pfBridgeHandler == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: ui32BridgeID = %d is not a registered function!",
+ __FUNCTION__, ui32BridgeID));
+ goto return_fault;
+ }
+
+ err = pfBridgeHandler(ui32BridgeID,
+ psBridgeIn,
+ psBridgeOut,
+ psConnection);
+ if(err < 0)
+ {
+ goto return_fault;
+ }
+
+
+#if defined(__linux__)
+ /*
+ This should always be true as a.t.m. all bridge calls have to
+ return an error message, but this could change so we do this
+ check to be safe.
+ */
+ if(psBridgePackageKM->ui32OutBufferSize > 0)
+ {
+
+ if(CopyToUserWrapper(psConnection,
+ ui32BridgeID,
+ psBridgePackageKM->pvParamOut,
+ psBridgeOut,
+ psBridgePackageKM->ui32OutBufferSize)
+ != PVRSRV_OK)
+ {
+ goto return_fault;
+ }
+ }
+#endif
+
+ err = 0;
+
+return_fault:
+ return err;
+}
diff --git a/drivers/gpu/rogue/services/server/common/sync_server.c b/drivers/gpu/rogue/services/server/common/sync_server.c
new file mode 100644
index 000000000000..c0d1a6d9bf1e
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/sync_server.c
@@ -0,0 +1,1707 @@
+/*************************************************************************/ /*!
+@File sync_server.c
+@Title Server side synchronisation functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements the server side functions that for 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.
+*/ /**************************************************************************/
+#include "img_types.h"
+#include "sync_server.h"
+#include "sync_server_internal.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "osfunc.h"
+#include "pdump.h"
+#include "pvr_debug.h"
+#include "pdump_km.h"
+#include "sync.h"
+#include "sync_internal.h"
+#include "pvrsrv.h"
+#include "debug_request_ids.h"
+#include "connection_server.h"
+
+#if defined(SUPPORT_SECURE_EXPORT)
+#include "ossecure_export.h"
+#endif
+
+struct _SYNC_PRIMITIVE_BLOCK_
+{
+ PVRSRV_DEVICE_NODE *psDevNode;
+ DEVMEM_MEMDESC *psMemDesc;
+ DEVMEM_EXPORTCOOKIE sExportCookie;
+ IMG_UINT32 *pui32LinAddr;
+ IMG_UINT32 ui32BlockSize; /*!< Size of the Sync Primitive Block */
+ IMG_UINT32 ui32RefCount;
+ POS_LOCK hLock;
+ DLLIST_NODE sConnectionNode;
+ SYNC_CONNECTION_DATA *psSyncConnectionData; /*!< Link back to the sync connection data if there is one */
+};
+
+struct _SERVER_SYNC_PRIMITIVE_
+{
+ PVRSRV_CLIENT_SYNC_PRIM *psSync;
+ IMG_UINT32 ui32NextOp;
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32UID;
+ IMG_UINT32 ui32LastSyncRequesterID;
+ DLLIST_NODE sNode;
+ /* PDump only data */
+ IMG_BOOL bSWOperation;
+ IMG_BOOL bSWOpStartedInCaptRange;
+ IMG_UINT32 ui32LastHWUpdate;
+ IMG_BOOL bPDumped;
+ POS_LOCK hLock;
+ IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN];
+};
+
+struct _SERVER_SYNC_EXPORT_
+{
+ SERVER_SYNC_PRIMITIVE *psSync;
+};
+
+struct _SERVER_OP_COOKIE_
+{
+ IMG_BOOL bActive;
+ /*
+ Client syncblock(s) info.
+ If this changes update the calculation of ui32BlockAllocSize
+ */
+ IMG_UINT32 ui32SyncBlockCount;
+ SYNC_PRIMITIVE_BLOCK **papsSyncPrimBlock;
+
+ /*
+ Client sync(s) info.
+ If this changes update the calculation of ui32ClientAllocSize
+ */
+ IMG_UINT32 ui32ClientSyncCount;
+ IMG_UINT32 *paui32SyncBlockIndex;
+ IMG_UINT32 *paui32Index;
+ IMG_UINT32 *paui32Flags;
+ IMG_UINT32 *paui32FenceValue;
+ IMG_UINT32 *paui32UpdateValue;
+
+ /*
+ Server sync(s) info
+ If this changes update the calculation of ui32ServerAllocSize
+ */
+ IMG_UINT32 ui32ServerSyncCount;
+ SERVER_SYNC_PRIMITIVE **papsServerSync;
+ IMG_UINT32 *paui32ServerFenceValue;
+ IMG_UINT32 *paui32ServerUpdateValue;
+
+};
+
+struct _SYNC_CONNECTION_DATA_
+{
+ DLLIST_NODE sListHead;
+ IMG_UINT32 ui32RefCount;
+ POS_LOCK hLock;
+};
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+enum SYNC_RECORD_TYPE
+{
+ SYNC_RECORD_TYPE_UNKNOWN = 0,
+ SYNC_RECORD_TYPE_CLIENT,
+ SYNC_RECORD_TYPE_SERVER,
+};
+
+struct SYNC_RECORD
+{
+ SYNC_PRIMITIVE_BLOCK *psServerSyncPrimBlock; /*!< handle to _SYNC_PRIMITIVE_BLOCK_ */
+ IMG_UINT32 ui32SyncOffset; /*!< offset to sync in block */
+ IMG_UINT32 ui32FwBlockAddr;
+ enum SYNC_RECORD_TYPE eRecordType;
+ DLLIST_NODE sNode;
+ IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN];
+};
+
+static POS_LOCK g_hSyncRecordListLock;
+static DLLIST_NODE g_sSyncRecordList;
+static IMG_HANDLE g_hSyncRecordNotify;
+#endif /* #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+
+static IMG_UINT32 g_ServerSyncUID = 0;
+
+POS_LOCK g_hListLock;
+static DLLIST_NODE g_sAllServerSyncs;
+IMG_HANDLE g_hNotify;
+
+#define SYNC_REQUESTOR_UNKNOWN 0
+static IMG_UINT32 g_ui32NextSyncRequestorID = 1;
+
+#if defined(SYNC_DEBUG) || defined(REFCOUNT_DEBUG)
+#define SYNC_REFCOUNT_PRINT(fmt, ...) PVRSRVDebugPrintf(PVR_DBG_WARNING, __FILE__, __LINE__, fmt, __VA_ARGS__)
+#else
+#define SYNC_REFCOUNT_PRINT(fmt, ...)
+#endif
+
+#if defined(SYNC_DEBUG)
+#define SYNC_UPDATES_PRINT(fmt, ...) PVRSRVDebugPrintf(PVR_DBG_WARNING, __FILE__, __LINE__, fmt, __VA_ARGS__)
+#else
+#define SYNC_UPDATES_PRINT(fmt, ...)
+#endif
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+PVRSRV_ERROR
+PVRSRVSyncRecordAddKM(
+ SYNC_RECORD_HANDLE * phRecord,
+ SYNC_PRIMITIVE_BLOCK * hServerSyncPrimBlock,
+ IMG_UINT32 ui32FwBlockAddr,
+ IMG_UINT32 ui32SyncOffset,
+ IMG_BOOL bServerSync,
+ IMG_UINT32 ui32ClassNameSize,
+ const IMG_CHAR *pszClassName)
+{
+ struct SYNC_RECORD * psSyncRec;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (!phRecord)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ *phRecord = IMG_NULL;
+
+ psSyncRec = OSAllocMem(sizeof(*psSyncRec));
+ if (!psSyncRec)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ psSyncRec->psServerSyncPrimBlock = hServerSyncPrimBlock;
+ psSyncRec->ui32SyncOffset = ui32SyncOffset;
+ psSyncRec->ui32FwBlockAddr = ui32FwBlockAddr;
+ psSyncRec->eRecordType = bServerSync? SYNC_RECORD_TYPE_SERVER: SYNC_RECORD_TYPE_CLIENT;
+
+ if(pszClassName)
+ {
+ if (ui32ClassNameSize >= SYNC_MAX_CLASS_NAME_LEN)
+ ui32ClassNameSize = SYNC_MAX_CLASS_NAME_LEN - 1;
+ /* Copy over the class name annotation */
+ OSStringNCopy(psSyncRec->szClassName, pszClassName, ui32ClassNameSize);
+ psSyncRec->szClassName[ui32ClassNameSize] = 0;
+ }
+ else
+ {
+ /* No class name annotation */
+ psSyncRec->szClassName[0] = 0;
+ }
+
+ OSLockAcquire(g_hSyncRecordListLock);
+ dllist_add_to_head(&g_sSyncRecordList, &psSyncRec->sNode);
+ OSLockRelease(g_hSyncRecordListLock);
+
+ *phRecord = (SYNC_RECORD_HANDLE)psSyncRec;
+
+fail_alloc:
+ return eError;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncRecordRemoveByHandleKM(
+ SYNC_RECORD_HANDLE hRecord)
+{
+ struct SYNC_RECORD *pSync = (struct SYNC_RECORD*)hRecord;
+
+ if ( !hRecord )
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ OSLockAcquire(g_hSyncRecordListLock);
+ dllist_remove_node(&pSync->sNode);
+ OSLockRelease(g_hSyncRecordListLock);
+
+ OSFreeMem(pSync);
+
+ return PVRSRV_OK;
+}
+#else
+PVRSRV_ERROR
+PVRSRVSyncRecordAddKM(
+ SYNC_RECORD_HANDLE * phRecord,
+ SYNC_PRIMITIVE_BLOCK * hServerSyncPrimBlock,
+ IMG_UINT32 ui32FwBlockAddr,
+ IMG_UINT32 ui32SyncOffset,
+ IMG_BOOL bServerSync,
+ IMG_UINT32 ui32ClassNameSize,
+ const IMG_CHAR *pszClassName)
+{
+ PVR_UNREFERENCED_PARAMETER(phRecord);
+ PVR_UNREFERENCED_PARAMETER(hServerSyncPrimBlock);
+ PVR_UNREFERENCED_PARAMETER(ui32FwBlockAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32SyncOffset);
+ PVR_UNREFERENCED_PARAMETER(bServerSync);
+ PVR_UNREFERENCED_PARAMETER(ui32ClassNameSize);
+ PVR_UNREFERENCED_PARAMETER(pszClassName);
+ return PVRSRV_OK;
+}
+PVRSRV_ERROR
+PVRSRVSyncRecordRemoveByHandleKM(
+ SYNC_RECORD_HANDLE hRecord)
+{
+ PVR_UNREFERENCED_PARAMETER(hRecord);
+ return PVRSRV_OK;
+}
+#endif /* #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+
+static
+IMG_VOID _SyncConnectionRef(SYNC_CONNECTION_DATA *psSyncConnectionData)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psSyncConnectionData->hLock);
+ ui32RefCount = ++psSyncConnectionData->ui32RefCount;
+ OSLockRelease(psSyncConnectionData->hLock);
+
+ SYNC_REFCOUNT_PRINT("%s: Sync connection %p, refcount = %d",
+ __FUNCTION__, psSyncConnectionData, ui32RefCount);
+}
+
+static
+IMG_VOID _SyncConnectionUnref(SYNC_CONNECTION_DATA *psSyncConnectionData)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psSyncConnectionData->hLock);
+ ui32RefCount = --psSyncConnectionData->ui32RefCount;
+ OSLockRelease(psSyncConnectionData->hLock);
+
+ if (ui32RefCount == 0)
+ {
+ SYNC_REFCOUNT_PRINT("%s: Sync connection %p, refcount = %d",
+ __FUNCTION__, psSyncConnectionData, ui32RefCount);
+
+ PVR_ASSERT(dllist_is_empty(&psSyncConnectionData->sListHead));
+ OSLockDestroy(psSyncConnectionData->hLock);
+ OSFreeMem(psSyncConnectionData);
+ }
+ else
+ {
+ SYNC_REFCOUNT_PRINT("%s: Sync connection %p, refcount = %d",
+ __FUNCTION__, psSyncConnectionData, ui32RefCount);
+ }
+}
+
+static
+IMG_VOID _SyncConnectionAddBlock(CONNECTION_DATA *psConnection, SYNC_PRIMITIVE_BLOCK *psBlock)
+{
+ if (psConnection)
+ {
+ SYNC_CONNECTION_DATA *psSyncConnectionData = psConnection->psSyncConnectionData;
+
+ /*
+ Make sure the connection doesn't go away. It doesn't matter that we will release
+ the lock between as the refcount and list don't have to be atomic w.r.t. to each other
+ */
+ _SyncConnectionRef(psSyncConnectionData);
+
+ OSLockAcquire(psSyncConnectionData->hLock);
+ if (psConnection != IMG_NULL)
+ {
+ dllist_add_to_head(&psSyncConnectionData->sListHead, &psBlock->sConnectionNode);
+ }
+ OSLockRelease(psSyncConnectionData->hLock);
+ psBlock->psSyncConnectionData = psSyncConnectionData;
+ }
+ else
+ {
+ psBlock->psSyncConnectionData = IMG_NULL;
+ }
+}
+
+static
+IMG_VOID _SyncConnectionRemoveBlock(SYNC_PRIMITIVE_BLOCK *psBlock)
+{
+ SYNC_CONNECTION_DATA *psSyncConnectionData = psBlock->psSyncConnectionData;
+
+ if (psBlock->psSyncConnectionData)
+ {
+ OSLockAcquire(psSyncConnectionData->hLock);
+ dllist_remove_node(&psBlock->sConnectionNode);
+ OSLockRelease(psSyncConnectionData->hLock);
+
+ _SyncConnectionUnref(psBlock->psSyncConnectionData);
+ }
+}
+
+static
+IMG_VOID _SyncPrimitiveBlockRef(SYNC_PRIMITIVE_BLOCK *psSyncBlk)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psSyncBlk->hLock);
+ ui32RefCount = ++psSyncBlk->ui32RefCount;
+ OSLockRelease(psSyncBlk->hLock);
+
+ SYNC_REFCOUNT_PRINT("%s: Sync block %p, refcount = %d",
+ __FUNCTION__, psSyncBlk, ui32RefCount);
+}
+
+static
+IMG_VOID _SyncPrimitiveBlockUnref(SYNC_PRIMITIVE_BLOCK *psSyncBlk)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psSyncBlk->hLock);
+ ui32RefCount = --psSyncBlk->ui32RefCount;
+ OSLockRelease(psSyncBlk->hLock);
+
+ if (ui32RefCount == 0)
+ {
+ PVRSRV_DEVICE_NODE *psDevNode = psSyncBlk->psDevNode;
+
+ SYNC_REFCOUNT_PRINT("%s: Sync block %p, refcount = %d (remove)",
+ __FUNCTION__, psSyncBlk, ui32RefCount);
+
+ _SyncConnectionRemoveBlock(psSyncBlk);
+ OSLockDestroy(psSyncBlk->hLock);
+ DevmemUnexport(psSyncBlk->psMemDesc, &psSyncBlk->sExportCookie);
+ DevmemReleaseCpuVirtAddr(psSyncBlk->psMemDesc);
+ psDevNode->pfnFreeUFOBlock(psDevNode, psSyncBlk->psMemDesc);
+ OSFreeMem(psSyncBlk);
+ }
+ else
+ {
+ SYNC_REFCOUNT_PRINT("%s: Sync block %p, refcount = %d",
+ __FUNCTION__, psSyncBlk, ui32RefCount);
+ }
+}
+
+PVRSRV_ERROR
+PVRSRVAllocSyncPrimitiveBlockKM(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDevNode,
+ SYNC_PRIMITIVE_BLOCK **ppsSyncBlk,
+ IMG_UINT32 *puiSyncPrimVAddr,
+ IMG_UINT32 *puiSyncPrimBlockSize,
+ DEVMEM_EXPORTCOOKIE **psExportCookie)
+{
+ SYNC_PRIMITIVE_BLOCK *psNewSyncBlk;
+ PVRSRV_ERROR eError;
+
+ psNewSyncBlk = OSAllocMem(sizeof(SYNC_PRIMITIVE_BLOCK));
+ if (psNewSyncBlk == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+ psNewSyncBlk->psDevNode = psDevNode;
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Allocate UFO block");
+
+ eError = psDevNode->pfnAllocUFOBlock(psDevNode,
+ &psNewSyncBlk->psMemDesc,
+ puiSyncPrimVAddr,
+ &psNewSyncBlk->ui32BlockSize);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psNewSyncBlk->psMemDesc,
+ (IMG_PVOID *) &psNewSyncBlk->pui32LinAddr);
+ if (eError != PVRSRV_OK)
+ {
+ goto e2;
+ }
+
+ eError = DevmemExport(psNewSyncBlk->psMemDesc, &psNewSyncBlk->sExportCookie);
+ if (eError != PVRSRV_OK)
+ {
+ goto e3;
+ }
+
+ eError = OSLockCreate(&psNewSyncBlk->hLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto e4;
+ }
+
+ psNewSyncBlk->ui32RefCount = 1;
+
+ /* If there is a connection pointer then add the new block onto it's list */
+ _SyncConnectionAddBlock(psConnection, psNewSyncBlk);
+
+ *psExportCookie = &psNewSyncBlk->sExportCookie;
+ *ppsSyncBlk = psNewSyncBlk;
+ *puiSyncPrimBlockSize = psNewSyncBlk->ui32BlockSize;
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Allocated UFO block (FirmwareVAddr = 0x%08x)",
+ *puiSyncPrimVAddr);
+
+ return PVRSRV_OK;
+e4:
+ DevmemUnexport(psNewSyncBlk->psMemDesc, &psNewSyncBlk->sExportCookie);
+
+e3:
+ DevmemReleaseCpuVirtAddr(psNewSyncBlk->psMemDesc);
+e2:
+ psDevNode->pfnFreeUFOBlock(psDevNode, psNewSyncBlk->psMemDesc);
+e1:
+ OSFreeMem(psNewSyncBlk);
+e0:
+ return eError;
+}
+
+PVRSRV_ERROR
+PVRSRVFreeSyncPrimitiveBlockKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk)
+{
+ _SyncPrimitiveBlockUnref(psSyncBlk);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimSetKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Index,
+ IMG_UINT32 ui32Value)
+{
+ psSyncBlk->pui32LinAddr[ui32Index] = ui32Value;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVServerSyncPrimSetKM(SERVER_SYNC_PRIMITIVE *psServerSync, IMG_UINT32 ui32Value)
+{
+ *psServerSync->psSync->pui32LinAddr = ui32Value;
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID
+ServerSyncRef(SERVER_SYNC_PRIMITIVE *psSync)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psSync->hLock);
+ ui32RefCount = ++psSync->ui32RefCount;
+ OSLockRelease(psSync->hLock);
+
+ SYNC_REFCOUNT_PRINT("%s: Server sync %p, refcount = %d",
+ __FUNCTION__, psSync, ui32RefCount);
+}
+
+IMG_VOID
+ServerSyncUnref(SERVER_SYNC_PRIMITIVE *psSync)
+{
+ IMG_UINT32 ui32RefCount;
+
+ OSLockAcquire(psSync->hLock);
+ ui32RefCount = --psSync->ui32RefCount;
+ OSLockRelease(psSync->hLock);
+
+ if (ui32RefCount == 0)
+ {
+ SYNC_REFCOUNT_PRINT("%s: Server sync %p, refcount = %d",
+ __FUNCTION__, psSync, ui32RefCount);
+
+ /* Remove the sync from the global list */
+ OSLockAcquire(g_hListLock);
+ dllist_remove_node(&psSync->sNode);
+ OSLockRelease(g_hListLock);
+
+ OSLockDestroy(psSync->hLock);
+ SyncPrimFree(psSync->psSync);
+ OSFreeMem(psSync);
+ }
+ else
+ {
+ SYNC_REFCOUNT_PRINT("%s: Server sync %p, refcount = %d",
+ __FUNCTION__, psSync, ui32RefCount);
+ }
+}
+
+PVRSRV_ERROR
+PVRSRVServerSyncAllocKM(PVRSRV_DEVICE_NODE *psDevNode,
+ SERVER_SYNC_PRIMITIVE **ppsSync,
+ IMG_UINT32 *pui32SyncPrimVAddr,
+ IMG_UINT32 ui32ClassNameSize,
+ const IMG_CHAR *pszClassName)
+{
+ SERVER_SYNC_PRIMITIVE *psNewSync;
+ PVRSRV_ERROR eError;
+
+ psNewSync = OSAllocMem(sizeof(SERVER_SYNC_PRIMITIVE));
+ if (psNewSync == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* szClassName must be setup now and used for the SyncPrimAlloc call because
+ * pszClassName is allocated in the bridge code is not NULL terminated
+ */
+ if(pszClassName)
+ {
+ if (ui32ClassNameSize >= SYNC_MAX_CLASS_NAME_LEN)
+ ui32ClassNameSize = SYNC_MAX_CLASS_NAME_LEN - 1;
+ /* Copy over the class name annotation */
+ OSStringNCopy(psNewSync->szClassName, pszClassName, ui32ClassNameSize);
+ psNewSync->szClassName[ui32ClassNameSize] = 0;
+ }
+ else
+ {
+ /* No class name annotation */
+ psNewSync->szClassName[0] = 0;
+ }
+
+ eError = SyncPrimAlloc(psDevNode->hSyncPrimContext,
+ &psNewSync->psSync,
+ psNewSync->szClassName);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_sync_alloc;
+ }
+
+ eError = OSLockCreate(&psNewSync->hLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_lock_create;
+ }
+
+ SyncPrimSet(psNewSync->psSync, 0);
+
+ psNewSync->ui32NextOp = 0;
+ psNewSync->ui32RefCount = 1;
+ psNewSync->ui32UID = g_ServerSyncUID++;
+ psNewSync->ui32LastSyncRequesterID = SYNC_REQUESTOR_UNKNOWN;
+ psNewSync->bSWOperation = IMG_FALSE;
+ psNewSync->ui32LastHWUpdate = 0x0bad592c;
+ psNewSync->bPDumped = IMG_FALSE;
+
+ /* Add the sync to the global list */
+ OSLockAcquire(g_hListLock);
+ dllist_add_to_head(&g_sAllServerSyncs, &psNewSync->sNode);
+ OSLockRelease(g_hListLock);
+
+ *pui32SyncPrimVAddr = SyncPrimGetFirmwareAddr(psNewSync->psSync);
+ SYNC_UPDATES_PRINT("%s: sync: %p, fwaddr: %8.8X", __FUNCTION__, psNewSync, *pui32SyncPrimVAddr);
+ *ppsSync = psNewSync;
+ return PVRSRV_OK;
+
+fail_lock_create:
+ SyncPrimFree(psNewSync->psSync);
+
+fail_sync_alloc:
+ OSFreeMem(psNewSync);
+ return eError;
+}
+
+PVRSRV_ERROR
+PVRSRVServerSyncFreeKM(SERVER_SYNC_PRIMITIVE *psSync)
+{
+ ServerSyncUnref(psSync);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVServerSyncGetStatusKM(IMG_UINT32 ui32SyncCount,
+ SERVER_SYNC_PRIMITIVE **papsSyncs,
+ IMG_UINT32 *pui32UID,
+ IMG_UINT32 *pui32FWAddr,
+ IMG_UINT32 *pui32CurrentOp,
+ IMG_UINT32 *pui32NextOp)
+{
+ IMG_UINT32 i;
+
+ for (i=0;i<ui32SyncCount;i++)
+ {
+ PVRSRV_CLIENT_SYNC_PRIM *psClientSync = papsSyncs[i]->psSync;
+
+ pui32UID[i] = papsSyncs[i]->ui32UID;
+ pui32FWAddr[i] = SyncPrimGetFirmwareAddr(psClientSync);
+ pui32CurrentOp[i] = *psClientSync->pui32LinAddr;
+ pui32NextOp[i] = papsSyncs[i]->ui32NextOp;
+ }
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_PVRSRVSyncPrimServerExportKM(SERVER_SYNC_PRIMITIVE *psSync,
+ SERVER_SYNC_EXPORT **ppsExport)
+{
+ SERVER_SYNC_EXPORT *psNewExport;
+ PVRSRV_ERROR eError;
+
+ psNewExport = OSAllocMem(sizeof(SERVER_SYNC_EXPORT));
+ if (!psNewExport)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+
+ ServerSyncRef(psSync);
+
+ psNewExport->psSync = psSync;
+ *ppsExport = psNewExport;
+
+ return PVRSRV_OK;
+e0:
+ return eError;
+}
+
+static PVRSRV_ERROR
+_PVRSRVSyncPrimServerUnexportKM(SERVER_SYNC_EXPORT *psExport)
+{
+ ServerSyncUnref(psExport->psSync);
+
+ OSFreeMem(psExport);
+
+ return PVRSRV_OK;
+}
+
+static IMG_VOID
+_PVRSRVSyncPrimServerImportKM(SERVER_SYNC_EXPORT *psExport,
+ SERVER_SYNC_PRIMITIVE **ppsSync,
+ IMG_UINT32 *pui32SyncPrimVAddr)
+{
+ ServerSyncRef(psExport->psSync);
+
+ *ppsSync = psExport->psSync;
+ *pui32SyncPrimVAddr = SyncPrimGetFirmwareAddr(psExport->psSync->psSync);
+}
+
+#if defined(SUPPORT_INSECURE_EXPORT)
+PVRSRV_ERROR
+PVRSRVSyncPrimServerExportKM(SERVER_SYNC_PRIMITIVE *psSync,
+ SERVER_SYNC_EXPORT **ppsExport)
+{
+ return _PVRSRVSyncPrimServerExportKM(psSync,
+ ppsExport);
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimServerUnexportKM(SERVER_SYNC_EXPORT *psExport)
+{
+ return _PVRSRVSyncPrimServerUnexportKM(psExport);
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimServerImportKM(SERVER_SYNC_EXPORT *psExport,
+ SERVER_SYNC_PRIMITIVE **ppsSync,
+ IMG_UINT32 *pui32SyncPrimVAddr)
+{
+ _PVRSRVSyncPrimServerImportKM(psExport,
+ ppsSync,
+ pui32SyncPrimVAddr);
+
+ return PVRSRV_OK;
+}
+#endif /* defined(SUPPORT_INSECURE_EXPORT) */
+
+#if defined(SUPPORT_SECURE_EXPORT)
+PVRSRV_ERROR
+PVRSRVSyncPrimServerSecureExportKM(CONNECTION_DATA *psConnection,
+ SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_SECURE_TYPE *phSecure,
+ SERVER_SYNC_EXPORT **ppsExport,
+ CONNECTION_DATA **ppsSecureConnection)
+{
+ SERVER_SYNC_EXPORT *psNewExport;
+ PVRSRV_ERROR eError;
+
+ /* Create an export server sync */
+ eError = _PVRSRVSyncPrimServerExportKM(psSync,
+ &psNewExport);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ /* Transform it into a secure export */
+ eError = OSSecureExport(psConnection,
+ (IMG_PVOID) psNewExport,
+ phSecure,
+ ppsSecureConnection);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ *ppsExport = psNewExport;
+ return PVRSRV_OK;
+e1:
+ _PVRSRVSyncPrimServerUnexportKM(psNewExport);
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PVRSRVSyncPrimServerSecureUnexportKM(SERVER_SYNC_EXPORT *psExport)
+{
+ _PVRSRVSyncPrimServerUnexportKM(psExport);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimServerSecureImportKM(IMG_SECURE_TYPE hSecure,
+ SERVER_SYNC_PRIMITIVE **ppsSync,
+ IMG_UINT32 *pui32SyncPrimVAddr)
+{
+ PVRSRV_ERROR eError;
+ SERVER_SYNC_EXPORT *psImport;
+
+ /* Retrieve the data from the secure import */
+ eError = OSSecureImport(hSecure, (IMG_PVOID *) &psImport);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ _PVRSRVSyncPrimServerImportKM(psImport,
+ ppsSync,
+ pui32SyncPrimVAddr);
+ return PVRSRV_OK;
+
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+#endif /* defined(SUPPORT_SECURE_EXPORT) */
+
+IMG_UINT32 PVRSRVServerSyncRequesterRegisterKM(IMG_UINT32 *pui32SyncRequesterID)
+{
+ *pui32SyncRequesterID = g_ui32NextSyncRequestorID++;
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID PVRSRVServerSyncRequesterUnregisterKM(IMG_UINT32 ui32SyncRequesterID)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32SyncRequesterID);
+}
+
+static IMG_VOID
+_ServerSyncTakeOperation(SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_BOOL bUpdate,
+ IMG_UINT32 *pui32FenceValue,
+ IMG_UINT32 *pui32UpdateValue)
+{
+ IMG_BOOL bInCaptureRange;
+
+ /* Only advance the pending if the an update is required */
+ if (bUpdate)
+ {
+ *pui32FenceValue = psSync->ui32NextOp++;
+ }
+ else
+ {
+ *pui32FenceValue = psSync->ui32NextOp;
+ }
+
+ *pui32UpdateValue = psSync->ui32NextOp;
+
+ PDumpIsCaptureFrameKM(&bInCaptureRange);
+ /*
+ If this is the 1st operation (in this capture range) then PDump
+ this sync
+ */
+ if (!psSync->bPDumped && bInCaptureRange)
+ {
+ IMG_CHAR azTmp[100];
+ OSSNPrintf(azTmp,
+ sizeof(azTmp),
+ "Dump initial sync state (0x%p, FW VAddr = 0x%08x) = 0x%08x\n",
+ psSync,
+ SyncPrimGetFirmwareAddr(psSync->psSync),
+ *psSync->psSync->pui32LinAddr);
+ PDumpCommentKM(azTmp, 0);
+
+ SyncPrimPDump(psSync->psSync);
+ psSync->bPDumped = IMG_TRUE;
+ }
+
+ /*
+ When exiting capture range clear down bPDumped as we might re-enter
+ capture range and thus need to PDump this sync again
+ */
+ if (!bInCaptureRange)
+ {
+ psSync->bPDumped = IMG_FALSE;
+ }
+}
+
+PVRSRV_ERROR
+PVRSRVServerSyncQueueSWOpKM(SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_UINT32 *pui32FenceValue,
+ IMG_UINT32 *pui32UpdateValue,
+ IMG_UINT32 ui32SyncRequesterID,
+ IMG_BOOL bUpdate,
+ IMG_BOOL *pbFenceRequired)
+{
+
+ ServerSyncRef(psSync);
+
+ /*
+ ServerSyncRef will acquire and release the lock but we need to
+ reacquire here to ensure the state that we're modifying below
+ will be consistent with itself. But it doesn't matter if another
+ thread acquires the lock in between as we've ensured the sync
+ wont go away
+ */
+ OSLockAcquire(psSync->hLock);
+ _ServerSyncTakeOperation(psSync,
+ bUpdate,
+ pui32FenceValue,
+ pui32UpdateValue);
+
+ /*
+ The caller want to know if a fence command is required
+ i.e. was the last operation done on this sync done by the
+ the same sync requestor
+ */
+ if (pbFenceRequired)
+ {
+ if (ui32SyncRequesterID == psSync->ui32LastSyncRequesterID)
+ {
+ *pbFenceRequired = IMG_FALSE;
+ }
+ else
+ {
+ *pbFenceRequired = IMG_TRUE;
+ }
+ }
+ /*
+ If we're transitioning from a HW operation to a SW operation we
+ need to save the last update the HW will do so that when we PDump
+ we can issue a POL for it before the next HW operation and then
+ LDB in the last SW fence update
+ */
+ if (psSync->bSWOperation == IMG_FALSE)
+ {
+ psSync->bSWOperation = IMG_TRUE;
+ psSync->ui32LastHWUpdate = *pui32FenceValue;
+ PDumpIsCaptureFrameKM(&psSync->bSWOpStartedInCaptRange);
+ }
+
+ if (pbFenceRequired)
+ {
+ if (*pbFenceRequired)
+ {
+ SYNC_UPDATES_PRINT("%s: sync: %p, fence: %d, value: %d", __FUNCTION__, psSync, *pui32FenceValue, *pui32UpdateValue);
+ }
+ }
+
+ /* Only update the last requester id if we are make changes to this sync
+ * object. */
+ if (bUpdate)
+ psSync->ui32LastSyncRequesterID = ui32SyncRequesterID;
+
+ OSLockRelease(psSync->hLock);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVServerSyncQueueHWOpKM(SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_BOOL bUpdate,
+ IMG_UINT32 *pui32FenceValue,
+ IMG_UINT32 *pui32UpdateValue)
+{
+ /*
+ For HW operations the client is required to ensure the
+ operation has completed before freeing the sync as we
+ no way of dropping the refcount if we where to acquire it
+ here.
+
+ Take the lock to ensure the state that we're modifying below
+ will be consistent with itself.
+ */
+ OSLockAcquire(psSync->hLock);
+ _ServerSyncTakeOperation(psSync,
+ bUpdate,
+ pui32FenceValue,
+ pui32UpdateValue);
+
+ /*
+ Note:
+
+ We might want to consider optimising the fences that we write for
+ HW operations but for now just clear it back to unknown
+ */
+ psSync->ui32LastSyncRequesterID = SYNC_REQUESTOR_UNKNOWN;
+
+ if (psSync->bSWOperation)
+ {
+ IMG_CHAR azTmp[256];
+ OSSNPrintf(azTmp,
+ sizeof(azTmp),
+ "Wait for HW ops and dummy update for SW ops (0x%p, FW VAddr = 0x%08x, value = 0x%08x)\n",
+ psSync,
+ SyncPrimGetFirmwareAddr(psSync->psSync),
+ *pui32FenceValue);
+ PDumpCommentKM(azTmp, 0);
+
+ if (psSync->bSWOpStartedInCaptRange)
+ {
+ /* Dump a POL for the previous HW operation */
+ SyncPrimPDumpPol(psSync->psSync,
+ psSync->ui32LastHWUpdate,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0);
+ }
+
+ /* Dump the expected value (i.e. the value after all the SW operations) */
+ SyncPrimPDumpValue(psSync->psSync, *pui32FenceValue);
+
+ /* Reset the state as we've just done a HW operation */
+ psSync->bSWOperation = IMG_FALSE;
+ }
+ OSLockRelease(psSync->hLock);
+
+ SYNC_UPDATES_PRINT("%s: sync: %p, fence: %d, value: %d", __FUNCTION__, psSync, *pui32FenceValue, *pui32UpdateValue);
+
+ return PVRSRV_OK;
+}
+
+IMG_BOOL ServerSyncFenceIsMet(SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_UINT32 ui32FenceValue)
+{
+ SYNC_UPDATES_PRINT("%s: sync: %p, value(%d) == fence(%d)?", __FUNCTION__, psSync, *psSync->psSync->pui32LinAddr, ui32FenceValue);
+ return (*psSync->psSync->pui32LinAddr == ui32FenceValue);
+}
+
+IMG_VOID
+ServerSyncCompleteOp(SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_BOOL bDoUpdate,
+ IMG_UINT32 ui32UpdateValue)
+{
+ if (bDoUpdate)
+ {
+ SYNC_UPDATES_PRINT("%s: sync: %p (%d) = %d", __FUNCTION__, psSync, *psSync->psSync->pui32LinAddr, ui32UpdateValue);
+
+ *psSync->psSync->pui32LinAddr = ui32UpdateValue;
+ }
+
+ ServerSyncUnref(psSync);
+}
+
+IMG_UINT32 ServerSyncGetId(SERVER_SYNC_PRIMITIVE *psSync)
+{
+ return psSync->ui32UID;
+}
+
+IMG_UINT32 ServerSyncGetFWAddr(SERVER_SYNC_PRIMITIVE *psSync)
+{
+ return SyncPrimGetFirmwareAddr(psSync->psSync);
+}
+
+IMG_UINT32 ServerSyncGetValue(SERVER_SYNC_PRIMITIVE *psSync)
+{
+ return *psSync->psSync->pui32LinAddr;
+}
+
+IMG_UINT32 ServerSyncGetNextValue(SERVER_SYNC_PRIMITIVE *psSync)
+{
+ return psSync->ui32NextOp;
+}
+
+static IMG_BOOL _ServerSyncState(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ SERVER_SYNC_PRIMITIVE *psSync = IMG_CONTAINER_OF(psNode, SERVER_SYNC_PRIMITIVE, sNode);
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = IMG_NULL;
+
+ pfnDumpDebugPrintf = g_pfnDumpDebugPrintf;
+
+ if (*psSync->psSync->pui32LinAddr != psSync->ui32NextOp)
+ {
+ PVR_DUMPDEBUG_LOG(("\tPending server sync (ID = %d, FWAddr = 0x%08x): Current = 0x%08x, NextOp = 0x%08x (%s)",
+ psSync->ui32UID,
+ ServerSyncGetFWAddr(psSync),
+ ServerSyncGetValue(psSync),
+ psSync->ui32NextOp,
+ psSync->szClassName));
+ }
+ return IMG_TRUE;
+}
+
+static IMG_VOID _ServerSyncDebugRequest(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel)
+{
+
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = IMG_NULL;
+
+ PVR_UNREFERENCED_PARAMETER(hDebugRequestHandle);
+
+ pfnDumpDebugPrintf = g_pfnDumpDebugPrintf;
+ if (ui32VerbLevel == DEBUG_REQUEST_VERBOSITY_HIGH)
+ {
+ PVR_DUMPDEBUG_LOG(("Dumping all pending server syncs"));
+ OSLockAcquire(g_hListLock);
+ dllist_foreach_node(&g_sAllServerSyncs, _ServerSyncState, IMG_NULL);
+ OSLockRelease(g_hListLock);
+ }
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpCreateKM(IMG_UINT32 ui32SyncBlockCount,
+ SYNC_PRIMITIVE_BLOCK **papsSyncPrimBlock,
+ IMG_UINT32 ui32ClientSyncCount,
+ IMG_UINT32 *paui32SyncBlockIndex,
+ IMG_UINT32 *paui32Index,
+ IMG_UINT32 ui32ServerSyncCount,
+ SERVER_SYNC_PRIMITIVE **papsServerSync,
+ SERVER_OP_COOKIE **ppsServerCookie)
+{
+ SERVER_OP_COOKIE *psNewCookie;
+ IMG_UINT32 ui32BlockAllocSize;
+ IMG_UINT32 ui32ServerAllocSize;
+ IMG_UINT32 ui32ClientAllocSize;
+ IMG_UINT32 ui32TotalAllocSize;
+ IMG_UINT32 i;
+ IMG_CHAR *pcPtr;
+ PVRSRV_ERROR eError;
+
+ /* Allocate space for all the sync block list */
+ ui32BlockAllocSize = ui32SyncBlockCount * (sizeof(SYNC_PRIMITIVE_BLOCK *));
+
+ /* Allocate space for all the client sync size elements */
+ ui32ClientAllocSize = ui32ClientSyncCount * (5 * sizeof(IMG_UINT32));
+
+ /* Allocate space for all the server sync size elements */
+ ui32ServerAllocSize = ui32ServerSyncCount * (sizeof(SERVER_SYNC_PRIMITIVE *)
+ + (2 * sizeof(IMG_UINT32)));
+
+ ui32TotalAllocSize = sizeof(SERVER_OP_COOKIE) +
+ ui32BlockAllocSize +
+ ui32ServerAllocSize +
+ ui32ClientAllocSize;
+
+ psNewCookie = OSAllocMem(ui32TotalAllocSize);
+ pcPtr = (IMG_CHAR *) psNewCookie;
+
+ if (!psNewCookie)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+ OSMemSet(psNewCookie, 0, ui32TotalAllocSize);
+
+ /* Setup the pointers */
+ pcPtr += sizeof(SERVER_OP_COOKIE);
+ psNewCookie->papsSyncPrimBlock = (SYNC_PRIMITIVE_BLOCK **) pcPtr;
+
+ pcPtr += sizeof(SYNC_PRIMITIVE_BLOCK *) * ui32SyncBlockCount;
+ psNewCookie->paui32SyncBlockIndex = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->paui32Index = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->paui32Flags = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->paui32FenceValue = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->paui32UpdateValue = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->papsServerSync =(SERVER_SYNC_PRIMITIVE **) pcPtr;
+
+ pcPtr += sizeof(SERVER_SYNC_PRIMITIVE *) * ui32ServerSyncCount;
+ psNewCookie->paui32ServerFenceValue = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ServerSyncCount;
+ psNewCookie->paui32ServerUpdateValue = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ServerSyncCount;
+
+ /* Check the pointer setup went ok */
+ PVR_ASSERT(pcPtr == (((IMG_CHAR *) psNewCookie) + ui32TotalAllocSize));
+
+ psNewCookie->ui32SyncBlockCount= ui32SyncBlockCount;
+ psNewCookie->ui32ServerSyncCount = ui32ServerSyncCount;
+ psNewCookie->ui32ClientSyncCount = ui32ClientSyncCount;
+ psNewCookie->bActive = IMG_FALSE;
+
+ /* Copy all the data into our server cookie */
+ OSMemCopy(psNewCookie->papsSyncPrimBlock,
+ papsSyncPrimBlock,
+ sizeof(SYNC_PRIMITIVE_BLOCK *) * ui32SyncBlockCount);
+
+ OSMemCopy(psNewCookie->paui32SyncBlockIndex,
+ paui32SyncBlockIndex,
+ sizeof(IMG_UINT32) * ui32ClientSyncCount);
+ OSMemCopy(psNewCookie->paui32Index,
+ paui32Index,
+ sizeof(IMG_UINT32) * ui32ClientSyncCount);
+
+ OSMemCopy(psNewCookie->papsServerSync,
+ papsServerSync,
+ sizeof(SERVER_SYNC_PRIMITIVE *) *ui32ServerSyncCount);
+
+ /*
+ Take a reference on all the sync blocks and server syncs so they can't
+ be freed while we're using them
+ */
+ for (i=0;i<ui32SyncBlockCount;i++)
+ {
+ _SyncPrimitiveBlockRef(psNewCookie->papsSyncPrimBlock[i]);
+ }
+
+ for (i=0;i<ui32ServerSyncCount;i++)
+ {
+ ServerSyncRef(psNewCookie->papsServerSync[i]);
+ }
+
+ *ppsServerCookie = psNewCookie;
+ return PVRSRV_OK;
+
+e0:
+ return eError;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpTakeKM(SERVER_OP_COOKIE *psServerCookie,
+ IMG_UINT32 ui32ClientSyncCount,
+ IMG_UINT32 *paui32Flags,
+ IMG_UINT32 *paui32FenceValue,
+ IMG_UINT32 *paui32UpdateValue,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_UINT32 *paui32ServerFlags)
+{
+ IMG_UINT32 i;
+
+ if ((ui32ClientSyncCount != psServerCookie->ui32ClientSyncCount) ||
+ (ui32ServerSyncCount != psServerCookie->ui32ServerSyncCount))
+ {
+ /* The bridge layer should have stopped us getting here but check incase */
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync counts", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ for (i=0;i<ui32ServerSyncCount;i++)
+ {
+ /* Server syncs must fence */
+ if ((paui32ServerFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK) == 0)
+ {
+ return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
+ }
+ }
+
+ /*
+ For client syncs all we need to do is save the values
+ that we've been passed
+ */
+ OSMemCopy(psServerCookie->paui32Flags,
+ paui32Flags,
+ sizeof(IMG_UINT32) * ui32ClientSyncCount);
+ OSMemCopy(psServerCookie->paui32FenceValue,
+ paui32FenceValue,
+ sizeof(IMG_UINT32) * ui32ClientSyncCount);
+ OSMemCopy(psServerCookie->paui32UpdateValue,
+ paui32UpdateValue,
+ sizeof(IMG_UINT32) * ui32ClientSyncCount);
+
+ /*
+ For server syncs we just take an operation
+ */
+ for (i=0;i<ui32ServerSyncCount;i++)
+ {
+ /*
+ Take op can only take one operation at a time so we can't
+ optimise away fences so just report the requestor as unknown
+ */
+ PVRSRVServerSyncQueueSWOpKM(psServerCookie->papsServerSync[i],
+ &psServerCookie->paui32ServerFenceValue[i],
+ &psServerCookie->paui32ServerUpdateValue[i],
+ SYNC_REQUESTOR_UNKNOWN,
+ (paui32ServerFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE) ? IMG_TRUE:IMG_FALSE,
+ IMG_NULL);
+ }
+
+ psServerCookie->bActive = IMG_TRUE;
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpReadyKM(SERVER_OP_COOKIE *psServerCookie,
+ IMG_BOOL *pbReady)
+{
+ IMG_UINT32 i;
+ IMG_BOOL bReady = IMG_TRUE;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (!psServerCookie->bActive)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Operation cookie not active (no take operation performed)", __FUNCTION__));
+
+ bReady = IMG_FALSE;
+ eError = PVRSRV_ERROR_BAD_SYNC_STATE;
+ goto e0;
+ }
+
+ /* Check the client syncs */
+ for (i=0;i<psServerCookie->ui32ClientSyncCount;i++)
+ {
+ if (psServerCookie->paui32Flags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)
+ {
+ IMG_UINT32 ui32BlockIndex = psServerCookie->paui32SyncBlockIndex[i];
+ IMG_UINT32 ui32Index = psServerCookie->paui32Index[i];
+ SYNC_PRIMITIVE_BLOCK *psSyncBlock = psServerCookie->papsSyncPrimBlock[ui32BlockIndex];
+
+ if (psSyncBlock->pui32LinAddr[ui32Index] !=
+ psServerCookie->paui32FenceValue[i])
+ {
+ bReady = IMG_FALSE;
+ goto e0;
+ }
+ }
+ }
+
+ for (i=0;i<psServerCookie->ui32ServerSyncCount;i++)
+ {
+ bReady = ServerSyncFenceIsMet(psServerCookie->papsServerSync[i],
+ psServerCookie->paui32ServerFenceValue[i]);
+ if (!bReady)
+ {
+ break;
+ }
+ }
+
+e0:
+ *pbReady = bReady;
+ return eError;
+}
+
+static
+PVRSRV_ERROR _SyncPrimOpComplete(SERVER_OP_COOKIE *psServerCookie)
+{
+ IMG_UINT32 i;
+
+ for (i=0;i<psServerCookie->ui32ClientSyncCount;i++)
+ {
+ if (psServerCookie->paui32Flags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)
+ {
+ IMG_UINT32 ui32BlockIndex = psServerCookie->paui32SyncBlockIndex[i];
+ IMG_UINT32 ui32Index = psServerCookie->paui32Index[i];
+ SYNC_PRIMITIVE_BLOCK *psSyncBlock = psServerCookie->papsSyncPrimBlock[ui32BlockIndex];
+
+ psSyncBlock->pui32LinAddr[ui32Index] = psServerCookie->paui32UpdateValue[i];
+ }
+ }
+
+ for (i=0;i<psServerCookie->ui32ServerSyncCount;i++)
+ {
+ ServerSyncCompleteOp(psServerCookie->papsServerSync[i],
+ (psServerCookie->paui32ServerFenceValue[i] != psServerCookie->paui32ServerUpdateValue[i]),
+ psServerCookie->paui32ServerUpdateValue[i]);
+ }
+
+ psServerCookie->bActive = IMG_FALSE;
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpCompleteKM(SERVER_OP_COOKIE *psServerCookie)
+{
+ IMG_BOOL bReady;
+
+ PVRSRVSyncPrimOpReadyKM(psServerCookie, &bReady);
+
+ /* Check the client is playing ball */
+ if (!bReady)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: sync op still not ready", __FUNCTION__));
+
+ return PVRSRV_ERROR_BAD_SYNC_STATE;
+ }
+
+ return _SyncPrimOpComplete(psServerCookie);
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpDestroyKM(SERVER_OP_COOKIE *psServerCookie)
+{
+ IMG_UINT32 i;
+
+ /* If the operation is still active then check if it's finished yet */
+ if (psServerCookie->bActive)
+ {
+ if (PVRSRVSyncPrimOpCompleteKM(psServerCookie) == PVRSRV_ERROR_BAD_SYNC_STATE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Not ready, ask for retry", __FUNCTION__));
+ return PVRSRV_ERROR_RETRY;
+ }
+ }
+
+ /* Drop our references on the sync blocks and server syncs*/
+ for (i = 0; i < psServerCookie->ui32SyncBlockCount; i++)
+ {
+ _SyncPrimitiveBlockUnref(psServerCookie->papsSyncPrimBlock[i]);
+ }
+
+ for (i = 0; i < psServerCookie->ui32ServerSyncCount; i++)
+ {
+ ServerSyncUnref(psServerCookie->papsServerSync[i]);
+ }
+
+ OSFreeMem(psServerCookie);
+ return PVRSRV_OK;
+}
+
+#if defined(PDUMP)
+PVRSRV_ERROR
+PVRSRVSyncPrimPDumpValueKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+ /*
+ We might be ask to PDump sync state outside of capture range
+ (e.g. texture uploads) so make this continuous.
+ */
+ DevmemPDumpLoadMemValue32(psSyncBlk->psMemDesc,
+ ui32Offset,
+ ui32Value,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimPDumpKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset)
+{
+ /*
+ We might be ask to PDump sync state outside of capture range
+ (e.g. texture uploads) so make this continuous.
+ */
+ DevmemPDumpLoadMem(psSyncBlk->psMemDesc,
+ ui32Offset,
+ sizeof(IMG_UINT32),
+ PDUMP_FLAGS_CONTINUOUS);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimPDumpPolKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value, IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T ui32PDumpFlags)
+{
+ DevmemPDumpDevmemPol32(psSyncBlk->psMemDesc,
+ ui32Offset,
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ ui32PDumpFlags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpPDumpPolKM(SERVER_OP_COOKIE *psServerCookie,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T ui32PDumpFlags)
+{
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (!psServerCookie->bActive)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Operation cookie not active (no take operation performed)", __FUNCTION__));
+
+ eError = PVRSRV_ERROR_BAD_SYNC_STATE;
+ goto e0;
+ }
+
+ /* PDump POL on the client syncs */
+ for (i = 0; i < psServerCookie->ui32ClientSyncCount; i++)
+ {
+ if (psServerCookie->paui32Flags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)
+ {
+ IMG_UINT32 ui32BlockIndex = psServerCookie->paui32SyncBlockIndex[i];
+ IMG_UINT32 ui32Index = psServerCookie->paui32Index[i];
+ SYNC_PRIMITIVE_BLOCK *psSyncBlock = psServerCookie->papsSyncPrimBlock[ui32BlockIndex];
+
+ PVRSRVSyncPrimPDumpPolKM(psSyncBlock,
+ ui32Index*sizeof(IMG_UINT32),
+ psServerCookie->paui32FenceValue[i],
+ 0xFFFFFFFFU,
+ eOperator,
+ ui32PDumpFlags);
+ }
+ }
+
+ /* PDump POL on the server syncs */
+ for (i = 0; i < psServerCookie->ui32ServerSyncCount; i++)
+ {
+ SERVER_SYNC_PRIMITIVE *psServerSync = psServerCookie->papsServerSync[i];
+ IMG_UINT32 ui32FenceValue = psServerCookie->paui32ServerFenceValue[i];
+
+ SyncPrimPDumpPol(psServerSync->psSync,
+ ui32FenceValue,
+ 0xFFFFFFFFU,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ ui32PDumpFlags);
+ }
+
+e0:
+ return eError;
+}
+
+PVRSRV_ERROR
+PVRSRVSyncPrimPDumpCBPKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT64 ui32Offset,
+ IMG_UINT64 uiWriteOffset, IMG_UINT64 uiPacketSize,
+ IMG_UINT64 uiBufferSize)
+{
+ DevmemPDumpCBP(psSyncBlk->psMemDesc,
+ ui32Offset,
+ uiWriteOffset,
+ uiPacketSize,
+ uiBufferSize);
+ return PVRSRV_OK;
+}
+#endif
+
+/* SyncRegisterConnection */
+PVRSRV_ERROR SyncRegisterConnection(SYNC_CONNECTION_DATA **ppsSyncConnectionData)
+{
+ SYNC_CONNECTION_DATA *psSyncConnectionData;
+ PVRSRV_ERROR eError;
+
+ psSyncConnectionData = OSAllocMem(sizeof(SYNC_CONNECTION_DATA));
+ if (psSyncConnectionData == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ eError = OSLockCreate(&psSyncConnectionData->hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_lockcreate;
+ }
+ dllist_init(&psSyncConnectionData->sListHead);
+ psSyncConnectionData->ui32RefCount = 1;
+
+ *ppsSyncConnectionData = psSyncConnectionData;
+ return PVRSRV_OK;
+
+fail_lockcreate:
+ OSFreeMem(psSyncConnectionData);
+fail_alloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/* SyncUnregisterConnection */
+IMG_VOID SyncUnregisterConnection(SYNC_CONNECTION_DATA *psSyncConnectionData)
+{
+ _SyncConnectionUnref(psSyncConnectionData);
+}
+
+static
+IMG_BOOL _PDumpSyncBlock(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ SYNC_PRIMITIVE_BLOCK *psSyncBlock = IMG_CONTAINER_OF(psNode, SYNC_PRIMITIVE_BLOCK, sConnectionNode);
+ PVR_UNREFERENCED_PARAMETER(pvCallbackData);
+
+ DevmemPDumpLoadMem(psSyncBlock->psMemDesc,
+ 0,
+ psSyncBlock->ui32BlockSize,
+ PDUMP_FLAGS_CONTINUOUS);
+ return IMG_TRUE;
+}
+
+IMG_VOID SyncConnectionPDumpSyncBlocks(SYNC_CONNECTION_DATA *psSyncConnectionData)
+{
+ OSLockAcquire(psSyncConnectionData->hLock);
+
+ PDUMPCOMMENT("Dump client Sync Prim state");
+ dllist_foreach_node(&psSyncConnectionData->sListHead,
+ _PDumpSyncBlock,
+ IMG_NULL);
+
+ OSLockRelease(psSyncConnectionData->hLock);
+}
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+static IMG_BOOL _SyncRecordPrint(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ struct SYNC_RECORD *psSyncRec;
+ SYNC_PRIMITIVE_BLOCK *psSyncBlock;
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = IMG_NULL;
+
+ pfnDumpDebugPrintf = g_pfnDumpDebugPrintf;
+
+ psSyncRec = IMG_CONTAINER_OF(psNode, struct SYNC_RECORD, sNode);
+ psSyncBlock = psSyncRec->psServerSyncPrimBlock;
+
+ if (SYNC_RECORD_TYPE_UNKNOWN != psSyncRec->eRecordType)
+ {
+ if (psSyncBlock->pui32LinAddr)
+ {
+ IMG_VOID *pSyncAddr;
+
+ pSyncAddr = psSyncBlock->pui32LinAddr + psSyncRec->ui32SyncOffset;
+ PVR_DUMPDEBUG_LOG(("\t%s sync FWAddr=0x%08x Val=0x%08x (%s)",
+ ((SYNC_RECORD_TYPE_SERVER==psSyncRec->eRecordType)?"Server":"Client"),
+ (psSyncRec->ui32FwBlockAddr+psSyncRec->ui32SyncOffset),
+ *(IMG_UINT32*)pSyncAddr,
+ psSyncRec->szClassName));
+ }
+ else
+ {
+ PVR_DUMPDEBUG_LOG(("\t%s sync FWAddr=0x%08x Val=<null ptr> (%s)",
+ ((SYNC_RECORD_TYPE_SERVER==psSyncRec->eRecordType)?"Server":"Client"),
+ (psSyncRec->ui32FwBlockAddr+psSyncRec->ui32SyncOffset),
+ psSyncRec->szClassName));
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID _SyncRecordRequest(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel)
+{
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = IMG_NULL;
+
+ PVR_UNREFERENCED_PARAMETER(hDebugRequestHandle);
+
+ pfnDumpDebugPrintf = g_pfnDumpDebugPrintf;
+
+ if (ui32VerbLevel == DEBUG_REQUEST_VERBOSITY_HIGH)
+ {
+ PVR_DUMPDEBUG_LOG(("Dumping all sync records"));
+ OSLockAcquire(g_hSyncRecordListLock);
+ dllist_foreach_node(&g_sSyncRecordList, _SyncRecordPrint, IMG_NULL);
+ OSLockRelease(g_hSyncRecordListLock);
+ }
+}
+
+static PVRSRV_ERROR SyncRecordListInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ eError = OSLockCreate(&g_hSyncRecordListLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_lock_create;
+ }
+ dllist_init(&g_sSyncRecordList);
+
+ eError = PVRSRVRegisterDbgRequestNotify(&g_hSyncRecordNotify,
+ _SyncRecordRequest,
+ DEBUG_REQUEST_SERVERSYNC,
+ IMG_NULL);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_dbg_register;
+ }
+
+ return PVRSRV_OK;
+
+fail_dbg_register:
+ OSLockDestroy(g_hSyncRecordListLock);;
+fail_lock_create:
+ return eError;
+}
+
+static IMG_BOOL _SyncRecordListDestroy(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ struct SYNC_RECORD *pSyncRec;
+
+ PVR_UNREFERENCED_PARAMETER(pvCallbackData);
+
+ pSyncRec = IMG_CONTAINER_OF(psNode, struct SYNC_RECORD, sNode);
+
+ dllist_remove_node(psNode);
+ OSFreeMem(pSyncRec);
+
+ return IMG_TRUE;
+}
+#endif /* #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+
+PVRSRV_ERROR ServerSyncInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ eError = OSLockCreate(&g_hListLock, LOCK_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_lock_create;
+ }
+ dllist_init(&g_sAllServerSyncs);
+
+ eError = PVRSRVRegisterDbgRequestNotify(&g_hNotify,
+ _ServerSyncDebugRequest,
+ DEBUG_REQUEST_SERVERSYNC,
+ IMG_NULL);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_dbg_register;
+ }
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+ eError = SyncRecordListInit();
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_record_list;
+ }
+#endif
+
+ return PVRSRV_OK;
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+fail_record_list:
+ PVRSRVUnregisterDbgRequestNotify(g_hNotify);
+#endif
+fail_dbg_register:
+ OSLockDestroy(g_hListLock);;
+fail_lock_create:
+ return eError;
+}
+
+IMG_VOID ServerSyncDeinit(IMG_VOID)
+{
+ PVRSRVUnregisterDbgRequestNotify(g_hNotify);
+ OSLockDestroy(g_hListLock);
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+ OSLockAcquire(g_hSyncRecordListLock);
+ dllist_foreach_node(&g_sSyncRecordList, _SyncRecordListDestroy, IMG_NULL);
+ OSLockRelease(g_hSyncRecordListLock);
+ PVRSRVUnregisterDbgRequestNotify(g_hSyncRecordNotify);
+ OSLockDestroy(g_hSyncRecordListLock);
+#endif
+}
diff --git a/drivers/gpu/rogue/services/server/common/tlintern.c b/drivers/gpu/rogue/services/server/common/tlintern.c
new file mode 100644
index 000000000000..2f5e55f7ddf9
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/tlintern.c
@@ -0,0 +1,301 @@
+/*************************************************************************/ /*!
+@File
+@Title Transport Layer kernel side API implementation.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Transport Layer functions available to driver components in
+ the driver.
+@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 "pvr_debug.h"
+
+#include "allocmem.h"
+#include "pvrsrv_error.h"
+#include "osfunc.h"
+
+#include "pvr_tlcommon.h"
+#include "tlintern.h"
+
+/*
+ * Make functions
+ */
+PTL_STREAM_DESC
+TLMakeStreamDesc(PTL_SNODE f1, IMG_UINT32 f2, IMG_HANDLE f3)
+{
+ PTL_STREAM_DESC ps = OSAllocZMem(sizeof(TL_STREAM_DESC));
+ if (ps == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+ ps->psNode = f1;
+ ps->ui32Flags = f2;
+ ps->hDataEvent = f3;
+ return ps;
+}
+
+PTL_SNODE
+TLMakeSNode(IMG_HANDLE f2, TL_STREAM *f3, TL_STREAM_DESC *f4)
+{
+ PTL_SNODE ps = OSAllocZMem(sizeof(TL_SNODE));
+ if (ps == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+ ps->hDataEventObj = f2;
+ ps->psStream = f3;
+ ps->psDesc = f4;
+ f3->psNode = ps;
+ return ps;
+}
+
+/*
+ * Transport Layer Global top variables and functions
+ */
+static TL_GLOBAL_DATA sTLGlobalData = { 0 };
+
+TL_GLOBAL_DATA *TLGGD(IMG_VOID) // TLGetGlobalData()
+{
+ return &sTLGlobalData;
+}
+
+/* TLInit must only be called once at driver initialisation for one device.
+ * An assert is provided to check this condition on debug builds.
+ */
+PVRSRV_ERROR
+TLInit(PVRSRV_DEVICE_NODE *psDevNode)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psDevNode);
+ PVR_ASSERT(sTLGlobalData.psRgxDevNode==0);
+
+ /* Store the RGX device node for later use in devmem buffer allocations */
+ sTLGlobalData.psRgxDevNode = (IMG_VOID*)psDevNode;
+
+ /* Allocate the event object used to signal global TL events such as
+ * - new stream created
+ * Don't allow the driver to start up on error */
+ PVR_DPF_RETURN_RC( OSEventObjectCreate("TLGlobalEventObj", &sTLGlobalData.hTLEventObj) );
+}
+
+static IMG_VOID RemoveAndFreeStreamNode(PTL_SNODE psRemove)
+{
+ TL_GLOBAL_DATA* psGD = TLGGD();
+ PTL_SNODE* last;
+ PTL_SNODE psn;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF_ENTERED;
+
+ // Unlink the stream node from the master list
+ PVR_ASSERT(psGD->psHead);
+ last = &psGD->psHead;
+ for (psn = psGD->psHead; psn; psn=psn->psNext)
+ {
+ if (psn == psRemove)
+ {
+ /* Other calling code may have freed and zero'd the pointers */
+ if (psn->psDesc)
+ {
+ OSFREEMEM(psn->psDesc);
+ }
+ if (psn->psStream)
+ {
+ OSFREEMEM(psn->psStream);
+ }
+ *last = psn->psNext;
+ break;
+ }
+ last = &psn->psNext;
+ }
+
+ // Release the event list object owned by the stream node
+ if (psRemove->hDataEventObj)
+ {
+ eError = OSEventObjectDestroy(psRemove->hDataEventObj);
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
+
+ psRemove->hDataEventObj = NULL;
+ }
+
+ // Release the memory of the stream node
+ OSFREEMEM(psRemove);
+
+ PVR_DPF_RETURN;
+}
+
+IMG_VOID
+TLDeInit(IMG_VOID)
+{
+ PVR_DPF_ENTERED;
+
+ if (sTLGlobalData.uiClientCnt)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "TLDeInit transport layer but %d client streams are still connected", sTLGlobalData.uiClientCnt));
+ sTLGlobalData.uiClientCnt = 0;
+ }
+
+ /* Clean up the SNODE list */
+ if (sTLGlobalData.psHead)
+ {
+ while (sTLGlobalData.psHead)
+ {
+ RemoveAndFreeStreamNode(sTLGlobalData.psHead);
+ }
+ /* Leave psHead NULL on loop exit */
+ }
+
+ /* Clean up the TL global event object */
+ if (sTLGlobalData.hTLEventObj)
+ {
+ OSEventObjectDestroy(sTLGlobalData.hTLEventObj);
+ sTLGlobalData.hTLEventObj = NULL;
+ }
+
+ sTLGlobalData.psRgxDevNode = NULL;
+
+ PVR_DPF_RETURN;
+}
+
+PVRSRV_DEVICE_NODE*
+TLGetGlobalRgxDevice(IMG_VOID)
+{
+ PVRSRV_DEVICE_NODE *p = (PVRSRV_DEVICE_NODE*)(TLGGD()->psRgxDevNode);
+ if (!p)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "TLGetGlobalRgxDevice() NULL node ptr, TL " \
+ "can not be used when no RGX device has been found"));
+ PVR_ASSERT(p);
+ }
+ return p;
+}
+
+IMG_VOID TLAddStreamNode(PTL_SNODE psAdd)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psAdd);
+ psAdd->psNext = TLGGD()->psHead;
+ TLGGD()->psHead = psAdd;
+
+ PVR_DPF_RETURN;
+}
+
+PTL_SNODE TLFindStreamNodeByName(IMG_PCHAR pszName)
+{
+ TL_GLOBAL_DATA* psGD = TLGGD();
+ PTL_SNODE psn;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(pszName);
+
+ for (psn = psGD->psHead; psn; psn=psn->psNext)
+ {
+ if (psn->psStream && OSStringCompare(psn->psStream->szName, pszName)==0)
+ {
+ PVR_DPF_RETURN_VAL(psn);
+ }
+ }
+
+ PVR_DPF_RETURN_VAL(IMG_NULL);
+}
+
+PTL_SNODE TLFindStreamNodeByDesc(PTL_STREAM_DESC psDesc)
+{
+ TL_GLOBAL_DATA* psGD = TLGGD();
+ PTL_SNODE psn;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psDesc);
+
+ for (psn = psGD->psHead; psn; psn=psn->psNext)
+ {
+ if (psn->psDesc == psDesc)
+ {
+ PVR_DPF_RETURN_VAL(psn);
+ }
+ }
+ PVR_DPF_RETURN_VAL(IMG_NULL);
+}
+
+IMG_VOID TLRemoveStreamAndTryFreeStreamNode(PTL_SNODE psRemove)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psRemove);
+ psRemove->psStream = IMG_NULL;
+
+ if (psRemove->psDesc != IMG_NULL)
+ {
+ PVRSRV_ERROR eError;
+
+ // Signal client if waiting...so they detect stream has been
+ // destroyed and can return an error.
+ eError = OSEventObjectSignal(psRemove->hDataEventObj);
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
+
+ PVR_DPF_RETURN;
+ }
+
+ RemoveAndFreeStreamNode(psRemove);
+
+ PVR_DPF_RETURN;
+}
+
+IMG_VOID TLRemoveDescAndTryFreeStreamNode(PTL_SNODE psRemove)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psRemove);
+
+ psRemove->psDesc = IMG_NULL;
+
+ // First check is node is really no longer needed
+ if (psRemove->psStream != IMG_NULL)
+ {
+ PVR_DPF_RETURN;
+ }
+
+ RemoveAndFreeStreamNode(psRemove);
+
+ PVR_DPF_RETURN;
+}
+
diff --git a/drivers/gpu/rogue/services/server/common/tlserver.c b/drivers/gpu/rogue/services/server/common/tlserver.c
new file mode 100644
index 000000000000..38e5afccbfe3
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/tlserver.c
@@ -0,0 +1,349 @@
+/*************************************************************************/ /*!
+@File
+@Title KM server Transport Layer implementation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main bridge APIs for Transport Layer client 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 <stddef.h>
+
+#include "img_defs.h"
+
+//#define PVR_DPF_FUNCTION_TRACE_ON 1
+#undef PVR_DPF_FUNCTION_TRACE_ON
+#include "pvr_debug.h"
+
+#include "connection_server.h"
+#include "allocmem.h"
+
+#include "tlintern.h"
+#include "tlserver.h"
+
+#include "tltestdefs.h"
+
+#define NO_STREAM_WAIT_PERIOD 2000
+#define NO_DATA_WAIT_PERIOD 1000
+#define NO_ACQUIRE 0xffffffffU
+
+/*
+ * Transport Layer Client API Kernel-Mode bridge implementation
+ */
+PVRSRV_ERROR
+TLServerConnectKM(CONNECTION_DATA *psConnection)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+ PVR_DPF_RETURN_OK;
+}
+
+PVRSRV_ERROR
+TLServerDisconnectKM(CONNECTION_DATA *psConnection)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+
+ PVR_DPF_RETURN_OK;
+}
+
+PVRSRV_ERROR
+TLServerOpenStreamKM(IMG_PCHAR pszName,
+ IMG_UINT32 ui32Mode,
+ PTL_STREAM_DESC* ppsSD,
+ DEVMEM_EXPORTCOOKIE** ppsBufCookie)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_ERROR eErrorEO = PVRSRV_OK;
+ PTL_SNODE psNode = 0;
+ TL_STREAM_DESC* psNewSD = 0;
+ IMG_HANDLE hEvent;
+ PTL_GLOBAL_DATA psGD = TLGGD();
+
+#if defined(PVR_DPF_FUNCTION_TRACE_ON)
+ PVR_DPF((PVR_DBG_CALLTRACE, "--> %s:%d entered (%s, %x)", __func__, __LINE__, pszName, ui32Mode));
+#endif
+
+ PVR_ASSERT(pszName);
+
+ psNode = TLFindStreamNodeByName(pszName);
+ if ((psNode == NULL) && (ui32Mode & PVRSRV_STREAM_FLAG_OPEN_WAIT))
+ { /* Blocking code to wait for stream to be created if it does not exist
+ */
+ eError = OSEventObjectOpen(psGD->hTLEventObj, &hEvent);
+ PVR_LOGR_IF_ERROR(eError, "OSEventObjectOpen");
+
+ do
+ {
+ if ((psNode = TLFindStreamNodeByName(pszName)) == NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "Stream %s does not exist, waiting...", pszName));
+ /* Will exit OK or with timeout, both cases safe to ignore */
+ eErrorEO = OSEventObjectWaitTimeout(hEvent, NO_STREAM_WAIT_PERIOD);
+ }
+ }
+ while ((psNode == NULL) && (eErrorEO == PVRSRV_OK));
+
+ eError = OSEventObjectClose(hEvent);
+ PVR_LOGR_IF_ERROR(eError, "OSEventObjectClose");
+ }
+
+ /* Make sure we have found a stream node after wait/search */
+ if (psNode == NULL)
+ {
+ /* Did we exit the wait with timeout, inform caller */
+ if (eErrorEO == PVRSRV_ERROR_TIMEOUT)
+ {
+ PVR_DPF_RETURN_RC(eErrorEO);
+ }
+ PVR_DPF((PVR_DBG_ERROR, "Stream does not exist"));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_FOUND);
+ }
+
+ // Only one client/descriptor per stream supported
+ if (psNode->psDesc != NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Can not open stream, stream already opened"));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_ALREADY_OPEN);
+ }
+
+ // Create an event handle for this client to wait on when no data in stream
+ // buffer.
+ eError = OSEventObjectOpen(psNode->hDataEventObj, &hEvent);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Not possible to open node's event object"));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT);
+ }
+
+ psNewSD = TLMakeStreamDesc(psNode, ui32Mode, hEvent);
+ if (!psNewSD)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Not possible to make a new stream descriptor"));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ TLGGD()->uiClientCnt++;
+
+ // Copy the export cookie back to the user mode API to enable access to
+ // the stream buffer from user-mode process.
+ *ppsBufCookie = TLStreamGetBufferCookie(psNode->psStream);
+
+ psNode->psDesc = psNewSD;
+ *ppsSD = psNewSD;
+
+ PVR_DPF((PVR_DBG_VERBOSE,
+ "TLServerOpenStreamKM evList=%p, evObj=%p",
+ psNode->hDataEventObj,
+ psNode->psDesc->hDataEvent));
+
+ PVR_DPF_RETURN_OK;
+}
+
+PVRSRV_ERROR
+TLServerCloseStreamKM(PTL_STREAM_DESC psSD)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PTL_GLOBAL_DATA psGD = TLGGD();
+ PTL_SNODE psNode = 0;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psSD);
+
+ // Sanity check, quick exit if there are no streams
+ if (psGD->psHead == NULL)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
+ }
+
+ // Check stream still valid
+ psNode = TLFindStreamNodeByDesc(psSD);
+ if ((psNode == NULL) || (psNode != psSD->psNode))
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
+ }
+
+ // Close and free the event handle resource used by this descriptor
+ eError = OSEventObjectClose(psSD->hDataEvent);
+ if (eError != PVRSRV_OK)
+ {
+ // Log error but continue as it seems best
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectClose() failed error %d", eError));
+ eError = PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+ }
+
+ // Remove descriptor from stream object/list
+ TLRemoveDescAndTryFreeStreamNode(psNode);
+
+ // Free the stream descriptor object
+ OSFREEMEM(psSD);
+
+ // Assert the counter is sane after input data validated.
+ PVR_ASSERT(TLGGD()->uiClientCnt > 0);
+ TLGGD()->uiClientCnt--;
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR
+TLServerAcquireDataKM(PTL_STREAM_DESC psSD,
+ IMG_UINT32* puiReadOffset,
+ IMG_UINT32* puiReadLen)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TL_GLOBAL_DATA* psGD = TLGGD();
+ IMG_UINT32 uiTmpOffset = NO_ACQUIRE;
+ IMG_UINT32 uiTmpLen = 0;
+ PTL_SNODE psNode = 0;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psSD);
+
+ // Sanity check, quick exit if there are no streams
+ if (psGD->psHead == NULL)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
+ }
+
+ // Check stream still valid
+ psNode = TLFindStreamNodeByDesc(psSD);
+ if ((psNode == NULL) || (psNode != psSD->psNode))
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
+ }
+
+ // Does stream still exist?
+ if (psNode->psStream == NULL)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_RESOURCE_UNAVAILABLE);
+ }
+
+ //PVR_DPF((PVR_DBG_VERBOSE, "TLServerAcquireDataKM evList=%p, evObj=%p", psSD->psNode->hDataEventObj, psSD->hDataEvent));
+
+ /* If stream still exists (has not be nulled in the mean time),
+ * check for data in the associated stream buffer, sleep/wait if none
+ */
+ while ((psNode->psStream != NULL) &&
+ ((uiTmpLen = TLStreamAcquireReadPos(psNode->psStream, &uiTmpOffset)) == 0) &&
+ (!(psSD->ui32Flags&PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING)) )
+ {
+ PVR_DPF((PVR_DBG_VERBOSE, "TLAcquireDataKM sleeping..."));
+
+ // Loop around if EndOfStream (nothing to read) and wait times out,
+ // exit loop if not time out but data is ready for client
+ while ((psNode->psStream != NULL) && TLStreamEOS(psNode->psStream))
+ {
+ eError = OSEventObjectWaitTimeout(psSD->hDataEvent, NO_DATA_WAIT_PERIOD);
+ if (eError != PVRSRV_OK)
+ {
+ /* Return timeout or other error condition to the caller who
+ * can choose to call again if desired. We don't block
+ * Indefinitely as we want the user mode application to have a
+ * chance to break out and end if it needs to, so we return the
+ * time out error code. */
+ PVR_DPF_RETURN_RC(eError);
+ }
+ }
+ }
+
+ /* Check we have been woken up because the stream has been destroyed? */
+ if (psNode->psStream == NULL)
+ {
+ PVR_DPF((PVR_DBG_VERBOSE, "TLAcquireDataKM awake, but stream now NULL"));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_RESOURCE_UNAVAILABLE);
+ }
+
+ /* Data available now if we reach here in blocking more or we take the
+ * values as is in non-blocking mode which might be all zeros. */
+ *puiReadOffset = uiTmpOffset;
+ *puiReadLen = uiTmpLen;
+
+ PVR_DPF((PVR_DBG_VERBOSE, "TLAcquireDataKM return offset=%d, len=%d bytes", *puiReadOffset, *puiReadLen));
+
+ PVR_DPF_RETURN_OK;
+}
+
+PVRSRV_ERROR
+TLServerReleaseDataKM(PTL_STREAM_DESC psSD,
+ IMG_UINT32 uiReadOffset,
+ IMG_UINT32 uiReadLen)
+{
+ TL_GLOBAL_DATA* psGD = TLGGD();
+ PTL_SNODE psNode = 0;
+
+ PVR_DPF_ENTERED;
+
+ /* Unreferenced in release builds */
+ PVR_UNREFERENCED_PARAMETER(uiReadOffset);
+
+ PVR_ASSERT(psSD);
+
+ // Sanity check, quick exit if there are no streams
+ if (psGD->psHead == NULL)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_ERROR);
+ }
+
+ // Check stream still valid
+ psNode = TLFindStreamNodeByDesc(psSD);
+ if ((psNode == NULL) || (psNode != psSD->psNode))
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
+ }
+
+ // Does stream still exist?
+ if (psNode->psStream == NULL)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_RESOURCE_UNAVAILABLE);
+ }
+
+ PVR_DPF((PVR_DBG_VERBOSE, "TLReleaseDataKM uiReadOffset=%d, uiReadLen=%d", uiReadOffset, uiReadLen));
+
+ // Move read position on to free up space in stream buffer
+ TLStreamAdvanceReadPos(psNode->psStream, uiReadLen);
+
+ PVR_DPF_RETURN_OK;
+}
+
+/*****************************************************************************
+ End of file (tlserver.c)
+*****************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/server/common/tlstream.c b/drivers/gpu/rogue/services/server/common/tlstream.c
new file mode 100644
index 000000000000..6af3dfc5c61f
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/tlstream.c
@@ -0,0 +1,842 @@
+/*************************************************************************/ /*!
+@File
+@Title Transport Layer kernel side API implementation.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Transport Layer API implementation.
+ These functions are provided to driver components.
+@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 "pvr_debug.h"
+
+#include "allocmem.h"
+#include "pvrsrv_error.h"
+#include "osfunc.h"
+
+#include "pvr_tlcommon.h"
+#include "tlintern.h"
+#include "tlstream.h"
+
+/* To debug buffer utilisation enable this macro here and
+ * define PVRSRV_NEED_PVR_TRACE in the server pvr_debug.c and in tutils.c
+ * before the inclusion of pvr_debug.h. Issue pvrtutils 6 on target to see
+ * stream buffer utilisation. */
+//#define TL_BUFFER_UTILIZATION 1
+
+#define EVENT_OBJECT_TIMEOUT_MS 1000
+
+/* Given the state of the buffer it returns a number of bytes that the client
+ * can use for a successful allocation. */
+static INLINE IMG_UINT32 suggestAllocSize(IMG_UINT32 ui32LRead,
+ IMG_UINT32 ui32LWrite,
+ IMG_UINT32 ui32CBSize,
+ IMG_UINT32 ui32ReqSizeMin)
+{
+ IMG_UINT32 ui32AvSpace = 0;
+
+ /* This could be written in fewer lines using the ? operator but it
+ would not be kind to potential readers of this source at all. */
+ if ( ui32LRead > ui32LWrite ) /* Buffer WRAPPED */
+ {
+ if ( (ui32LRead - ui32LWrite) > (sizeof(PVRSRVTL_PACKETHDR) + ui32ReqSizeMin + (IMG_INT) BUFFER_RESERVED_SPACE) )
+ {
+ ui32AvSpace = ui32LRead - ui32LWrite - sizeof(PVRSRVTL_PACKETHDR) - (IMG_INT) BUFFER_RESERVED_SPACE;
+ }
+ }
+ else /* Normal, no wrap */
+ {
+ if ( (ui32CBSize - ui32LWrite) > (sizeof(PVRSRVTL_PACKETHDR) + ui32ReqSizeMin + (IMG_INT) BUFFER_RESERVED_SPACE) )
+ {
+ ui32AvSpace = ui32CBSize - ui32LWrite - sizeof(PVRSRVTL_PACKETHDR) - (IMG_INT) BUFFER_RESERVED_SPACE;
+ }
+ else if ( (ui32LRead - 0) > (sizeof(PVRSRVTL_PACKETHDR) + ui32ReqSizeMin + (IMG_INT) BUFFER_RESERVED_SPACE) )
+ {
+ ui32AvSpace = ui32LRead - sizeof(PVRSRVTL_PACKETHDR) - (IMG_INT) BUFFER_RESERVED_SPACE;
+ }
+ }
+ /* The max size of a TL packet currently is UINT16. adjust accordingly */
+ return MIN(ui32AvSpace, IMG_UINT16_MAX);
+}
+
+/* Returns bytes left in the buffer. Negative if there is not any.
+ * two 4b aligned values are reserved, one for the write failed buffer flag
+ * and one to be able to distinguish the buffer full state to the buffer
+ * empty state.
+ * Always returns free space -8 even when the "write failed" packet may be
+ * already in the stream before this write. */
+static INLINE IMG_INT
+cbSpaceLeft(IMG_UINT32 ui32Read, IMG_UINT32 ui32Write, IMG_UINT32 ui32size)
+{
+ /* We need to reserve 4b (one packet) in the buffer to be able to tell empty
+ * buffers from full buffers and one more for packet write fail packet */
+ if ( ui32Read > ui32Write )
+ {
+ return (IMG_INT) ui32Read - (IMG_INT)ui32Write - (IMG_INT) BUFFER_RESERVED_SPACE;
+ }
+ else
+ {
+ return (IMG_INT)ui32size - ((IMG_INT)ui32Write - (IMG_INT)ui32Read) - (IMG_INT) BUFFER_RESERVED_SPACE;
+ }
+}
+
+/*******************************************************************************
+ * TL Server public API implementation.
+ ******************************************************************************/
+PVRSRV_ERROR
+TLStreamCreate(IMG_HANDLE *phStream,
+ IMG_CHAR *szStreamName,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32StreamFlags,
+ TL_STREAM_SOURCECB pfProducerCB,
+ IMG_PVOID pvProducerUD)
+{
+ PTL_STREAM psTmp;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hEventList;
+ PTL_SNODE psn = 0;
+ IMG_CHAR pszBufferLabel[PRVSRVTL_MAX_STREAM_NAME_SIZE+20];
+
+ DEVMEM_FLAGS_T uiMemFlags = PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED | /* GPU & CPU */
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+ PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE;
+
+ PVR_DPF_ENTERED;
+ /* Sanity checks: */
+ /* non NULL handler required */
+ if ( NULL == phStream )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+ if (OSStringLength(szStreamName) >= PRVSRVTL_MAX_STREAM_NAME_SIZE)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ /* Check if there already exists a stream with this name. */
+ psn = TLFindStreamNodeByName( szStreamName );
+ if ( IMG_NULL != psn )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_ALREADY_EXISTS);
+ }
+
+ /* Allocate stream structure container (stream struct) for the new stream */
+ psTmp = OSAllocZMem(sizeof(TL_STREAM)) ;
+ if ( NULL == psTmp )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ OSStringCopy(psTmp->szName, szStreamName);
+
+ if ( ui32StreamFlags & TL_FLAG_FORCE_FLUSH )
+ {
+ psTmp->bWaitForEmptyOnDestroy = IMG_TRUE;
+ }
+
+ psTmp->bNoSignalOnCommit = (ui32StreamFlags&TL_FLAG_NO_SIGNAL_ON_COMMIT) ? IMG_TRUE : IMG_FALSE;
+
+ if ( ui32StreamFlags & TL_FLAG_DROP_DATA )
+ {
+ if ( ui32StreamFlags & TL_FLAG_BLOCKING_RESERVE )
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+ psTmp->bDrop = IMG_TRUE;
+ }
+ else if ( ui32StreamFlags & TL_FLAG_BLOCKING_RESERVE )
+ { /* Additional synchronization object required for this kind of stream */
+ psTmp->bBlock = IMG_TRUE;
+
+ eError = OSEventObjectCreate(NULL, &psTmp->hProducerEventObj);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+ /* Create an event handle for this kind of stream */
+ eError = OSEventObjectOpen(psTmp->hProducerEventObj, &psTmp->hProducerEvent);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+ }
+
+ /* Remember producer supplied CB and data for later */
+ psTmp->pfProducerCallback = (IMG_VOID(*)(IMG_VOID))pfProducerCB;
+ psTmp->pvProducerUserData = pvProducerUD;
+
+ /* Round the requested bytes to a multiple of array elements' size, eg round 3 to 4 */
+ psTmp->ui32Size = PVRSRVTL_ALIGN(ui32Size);
+ psTmp->ui32Read = 0;
+ psTmp->ui32Write = 0;
+ psTmp->ui32Pending = NOTHING_PENDING;
+
+ OSSNPrintf(pszBufferLabel, sizeof(pszBufferLabel), "TLStreamBuf-%s", szStreamName);
+
+ /* Allocate memory for the circular buffer and export it to user space. */
+ eError = DevmemAllocateExportable( IMG_NULL,
+ (IMG_HANDLE) TLGetGlobalRgxDevice(),
+ (IMG_DEVMEM_SIZE_T)psTmp->ui32Size,
+ (IMG_DEVMEM_ALIGN_T) OSGetPageSize(),
+ uiMemFlags | PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
+ pszBufferLabel,
+ &psTmp->psStreamMemDesc);
+ PVR_LOGG_IF_ERROR(eError, "DevmemAllocateExportable", e2);
+
+ eError = DevmemAcquireCpuVirtAddr( psTmp->psStreamMemDesc, (IMG_VOID**) &psTmp->pbyBuffer );
+ PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", e3);
+
+ eError = DevmemExport(psTmp->psStreamMemDesc, &(psTmp->sExportCookie));
+ PVR_LOGG_IF_ERROR(eError, "DevmemExport", e4);
+
+ /* Synchronization object to synchronize with user side data transfers. */
+ eError = OSEventObjectCreate(psTmp->szName, &hEventList);
+ if (eError != PVRSRV_OK)
+ {
+ goto e5;
+ }
+
+ /* Stream created, now reset the reference count to 1 */
+ psTmp->uiRefCount = 1;
+
+//Thread Safety: Not yet implemented eError = OSLockCreate(&psTmp->hLock, LOCK_TYPE_PASSIVE);
+//Thread Safety: Not yet implemented if (eError != PVRSRV_OK)
+//Thread Safety: Not yet implemented {
+//Thread Safety: Not yet implemented goto e6;
+//Thread Safety: Not yet implemented }
+
+ /* Now remember the stream in the global TL structures */
+ psn = TLMakeSNode(hEventList, (TL_STREAM *)psTmp, 0);
+ if (psn == NULL)
+ {
+ eError=PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e7;
+ }
+ TLAddStreamNode(psn);
+
+ /* Best effort signal, client wait timeout will ultimately let it find the
+ * new stream if this fails, acceptable to avoid cleanup as it is tricky
+ * at this point */
+ (void) OSEventObjectSignal(TLGGD()->hTLEventObj);
+
+ /* Pass the newly created stream handle back to caller */
+ *phStream = (IMG_HANDLE)psTmp;
+ PVR_DPF_RETURN_OK;
+
+e7:
+//Thread Safety: Not yet implemented OSLockDestroy(psTmp->hLock);
+//Thread Safety: Not yet implemented e6:
+ OSEventObjectDestroy(hEventList);
+e5:
+ DevmemUnexport(psTmp->psStreamMemDesc, &(psTmp->sExportCookie));
+e4:
+ DevmemReleaseCpuVirtAddr( psTmp->psStreamMemDesc );
+e3:
+ DevmemFree(psTmp->psStreamMemDesc);
+e2:
+ OSEventObjectClose(psTmp->hProducerEvent);
+e1:
+ OSEventObjectDestroy(psTmp->hProducerEventObj);
+e0:
+ OSFREEMEM(psTmp);
+ PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR
+TLStreamOpen(IMG_HANDLE *phStream,
+ IMG_CHAR *szStreamName)
+{
+ PTL_SNODE psTmpSNode;
+
+ PVR_DPF_ENTERED;
+
+ if ( IMG_NULL == phStream || IMG_NULL == szStreamName )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ /* Search for a stream node with a matching stream name */
+ psTmpSNode = TLFindStreamNodeByName(szStreamName);
+
+ if ( IMG_NULL == psTmpSNode )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_FOUND);
+ }
+ else
+ { /* Found a stream to open. lock and increase reference count */
+
+//Thread Safety: Not yet implemented OSLockAcquire(psTmpStream->hLock);
+ psTmpSNode->psStream->uiRefCount++;
+ *phStream = (IMG_HANDLE)psTmpSNode->psStream;
+//Thread Safety: Not yet implemented OSLockRelease(psTmpStream->hLock);
+
+ PVR_DPF_RETURN_VAL(PVRSRV_OK);
+ }
+}
+
+IMG_VOID
+TLStreamClose(IMG_HANDLE hStream)
+{
+ PTL_STREAM psTmp;
+
+ PVR_DPF_ENTERED;
+
+ if ( IMG_NULL == hStream )
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "TLStreamClose failed as NULL stream handler passed, nothing done.\n"));
+ PVR_DPF_RETURN;
+ }
+
+ psTmp = (PTL_STREAM)hStream;
+
+ /* Decrement reference counter */
+//Thread Safety: Not yet implemented OSLockAcquire(psTmp->hLock);
+ psTmp->uiRefCount--;
+//Thread Safety: Not yet implemented OSLockRelease(psTmp->hLock);
+
+ /* The stream is still being used in other context(s) do not destroy anything */
+ if ( 0 != psTmp->uiRefCount )
+ {
+ PVR_DPF_RETURN;
+ }
+ else
+ {
+ if ( psTmp->bWaitForEmptyOnDestroy == IMG_TRUE )
+ {
+ while (psTmp->ui32Read != psTmp->ui32Write)
+ {
+ OSEventObjectWaitTimeout(psTmp->hProducerEvent,
+ EVENT_OBJECT_TIMEOUT_MS);
+ }
+ }
+ /* First remove it from the global structures to prevent access
+ * while it is being free'd. Lock it?
+ */
+ TLRemoveStreamAndTryFreeStreamNode(psTmp->psNode);
+
+//Thread Safety: Not yet implemented OSLockDestroy(psTmp->hLock);
+
+ // In block-while-reserve streams those not be NULL
+ if ( IMG_TRUE == psTmp->bBlock )
+ {
+ OSEventObjectClose(psTmp->hProducerEvent);
+ OSEventObjectDestroy(psTmp->hProducerEventObj);
+ }
+
+ DevmemUnexport(psTmp->psStreamMemDesc, &psTmp->sExportCookie);
+ DevmemReleaseCpuVirtAddr(psTmp->psStreamMemDesc);
+ DevmemFree(psTmp->psStreamMemDesc);
+
+ OSFREEMEM(psTmp);
+ PVR_DPF_RETURN;
+ }
+}
+
+static PVRSRV_ERROR
+DoTLStreamReserve(IMG_HANDLE hStream,
+ IMG_UINT8 **ppui8Data,
+ IMG_UINT32 ui32ReqSize,
+ IMG_UINT32 ui32ReqSizeMin,
+ PVRSRVTL_PACKETTYPE ePacketType,
+ IMG_UINT32* pui32AvSpace)
+{
+ PTL_STREAM psTmp;
+ IMG_UINT32 *ui32Buf, ui32LRead, ui32LWrite, ui32LPending, lReqSizeAligned, lReqSizeActual;
+ IMG_INT pad, iFreeSpace;
+
+ PVR_DPF_ENTERED;
+ if (pui32AvSpace) *pui32AvSpace = 0;
+
+ if (( IMG_NULL == hStream ))
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+ psTmp = (PTL_STREAM)hStream;
+
+ /* Assert used as the packet type parameter is currently only provided
+ * by the TL APIs, not the calling client */
+ PVR_ASSERT((PVRSRVTL_PACKETTYPE_UNDEF < ePacketType) && (PVRSRVTL_PACKETTYPE_LAST >= ePacketType));
+
+ /* The buffer is only used in "rounded" (aligned) chunks */
+ lReqSizeAligned = PVRSRVTL_ALIGN(ui32ReqSize);
+
+ /* Get a local copy of the stream buffer parameters */
+ ui32LRead = psTmp->ui32Read ;
+ ui32LWrite = psTmp->ui32Write ;
+ ui32LPending = psTmp->ui32Pending ;
+
+ /* Multiple pending reserves are not supported. */
+ if ( NOTHING_PENDING != ui32LPending )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_READY);
+ }
+
+ if ( IMG_UINT16_MAX < lReqSizeAligned )
+ {
+ psTmp->ui32Pending = NOTHING_PENDING;
+ if (pui32AvSpace)
+ {
+ *pui32AvSpace = suggestAllocSize(ui32LRead, ui32LWrite, psTmp->ui32Size, ui32ReqSizeMin);
+ }
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_FULL);
+ }
+
+ /* Prevent other threads from entering this region before we are done.
+ * Not exactly a lock... */
+ psTmp->ui32Pending = 0;
+
+ /* If there is enough contiguous space following the current Write
+ * position then no padding is required */
+ if ( psTmp->ui32Size
+ < ui32LWrite + lReqSizeAligned + sizeof(PVRSRVTL_PACKETHDR) )
+ {
+ pad = psTmp->ui32Size - ui32LWrite;
+ }
+ else
+ {
+ pad = 0 ;
+ }
+
+ lReqSizeActual = lReqSizeAligned + sizeof(PVRSRVTL_PACKETHDR) + pad ;
+ /* If this is a blocking reserve and there is not enough space then wait. */
+ if( psTmp->bBlock )
+ {
+ if( psTmp->ui32Size < lReqSizeActual )
+ {
+ psTmp->ui32Pending = NOTHING_PENDING;
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_MISUSE);
+ }
+ while ( ( cbSpaceLeft(ui32LRead, ui32LWrite, psTmp->ui32Size)
+ <(IMG_INT) lReqSizeActual ) )
+ {
+ OSEventObjectWait(psTmp->hProducerEvent);
+ // update local copies.
+ ui32LRead = psTmp->ui32Read ;
+ ui32LWrite = psTmp->ui32Write ;
+ }
+ }
+
+ /* The easy case: buffer has enough space to hold the requested packet (data + header)
+ */
+ iFreeSpace = cbSpaceLeft(ui32LRead, ui32LWrite, psTmp->ui32Size);
+ if ( iFreeSpace >=(IMG_INT) lReqSizeActual )
+ {
+ if ( pad )
+ {
+ /* Inserting padding packet. */
+ ui32Buf = (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite];
+ *ui32Buf = PVRSRVTL_SET_PACKET_PADDING(pad-sizeof(PVRSRVTL_PACKETHDR)) ;
+
+ /* CAUTION: the used pad value should always result in a properly
+ * aligned ui32LWrite pointer, which in this case is 0 */
+ ui32LWrite = (ui32LWrite + pad) % psTmp->ui32Size;
+ /* Detect unaligned pad value */
+ PVR_ASSERT( ui32LWrite == 0);
+ }
+ /* Insert size-stamped packet header */
+ ui32Buf = (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite];
+
+ *ui32Buf = PVRSRVTL_SET_PACKET_HDR(ui32ReqSize, ePacketType);
+
+ /* return the next position in the buffer to the user */
+ *ppui8Data = &psTmp->pbyBuffer[ ui32LWrite+sizeof(PVRSRVTL_PACKETHDR) ] ;
+
+ /* update pending offset: size stamp + data */
+ ui32LPending = lReqSizeAligned + sizeof(PVRSRVTL_PACKETHDR) ;
+ }
+ /* The not so easy case: not enough space, decide how to handle data */
+ else
+ {
+
+#if defined(DEBUG)
+ /* Sanity check that the user is not trying to add more data than the
+ * buffer size. Conditionally compile it out to ensure this check has
+ * no impact to release performance */
+ if ( lReqSizeAligned+sizeof(PVRSRVTL_PACKETHDR) > psTmp->ui32Size )
+ {
+ psTmp->ui32Pending = NOTHING_PENDING;
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_MISUSE);
+ }
+#endif
+
+ /* No data overwriting, insert write_failed flag and return */
+ if (psTmp->bDrop)
+ {
+ /* Caller should not try to use ppui8Data,
+ * NULLify to give user a chance of avoiding memory corruption */
+ ppui8Data = IMG_NULL;
+
+ /* This flag should not be inserted two consecutive times, so
+ * check the last ui32 in case it was a packet drop packet. */
+ ui32Buf = ui32LWrite
+ ?
+ (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite - sizeof(PVRSRVTL_PACKETHDR)]
+ : // Previous four bytes are not guaranteed to be a packet header...
+ (IMG_UINT32*)&psTmp->pbyBuffer[psTmp->ui32Size - PVRSRVTL_PACKET_ALIGNMENT];
+
+ if ( PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED
+ !=
+ GET_PACKET_TYPE( (PVRSRVTL_PACKETHDR*)ui32Buf ) )
+ {
+ /* Insert size-stamped packet header */
+ ui32Buf = (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite];
+ *ui32Buf = PVRSRVTL_SET_PACKET_WRITE_FAILED ;
+ ui32LWrite += sizeof(PVRSRVTL_PACKETHDR);
+ iFreeSpace -= sizeof(PVRSRVTL_PACKETHDR);
+ }
+
+ psTmp->ui32Write = ui32LWrite;
+ psTmp->ui32Pending = NOTHING_PENDING;
+ if (pui32AvSpace)
+ {
+ *pui32AvSpace = suggestAllocSize(ui32LRead, ui32LWrite, psTmp->ui32Size, ui32ReqSizeMin);
+ }
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_FULL);
+ }
+ }
+ /* Update stream. */
+ psTmp->ui32Write = ui32LWrite ;
+ psTmp->ui32Pending = ui32LPending ;
+
+ PVR_DPF_RETURN_OK;
+}
+
+PVRSRV_ERROR
+TLStreamReserve(IMG_HANDLE hStream,
+ IMG_UINT8 **ppui8Data,
+ IMG_UINT32 ui32Size)
+{
+ return DoTLStreamReserve(hStream, ppui8Data, ui32Size, ui32Size, PVRSRVTL_PACKETTYPE_DATA, NULL);
+}
+
+PVRSRV_ERROR
+TLStreamReserve2(IMG_HANDLE hStream,
+ IMG_UINT8 **ppui8Data,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32SizeMin,
+ IMG_UINT32* pui32Available)
+{
+ return DoTLStreamReserve(hStream, ppui8Data, ui32Size, ui32SizeMin, PVRSRVTL_PACKETTYPE_DATA, pui32Available);
+}
+
+PVRSRV_ERROR
+TLStreamCommit(IMG_HANDLE hStream, IMG_UINT32 ui32ReqSize)
+{
+ PTL_STREAM psTmp;
+ IMG_UINT32 ui32LRead, ui32OldWrite, ui32LWrite, ui32LPending;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF_ENTERED;
+
+ if ( IMG_NULL == hStream )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+ psTmp = (PTL_STREAM)hStream;
+
+ /* Get a local copy of the stream buffer parameters */
+ ui32LRead = psTmp->ui32Read ;
+ ui32LWrite = psTmp->ui32Write ;
+ ui32LPending = psTmp->ui32Pending ;
+
+ ui32OldWrite = ui32LWrite;
+
+ // Space in buffer is aligned
+ ui32ReqSize = PVRSRVTL_ALIGN(ui32ReqSize);
+
+ /* Sanity check. ReqSize + packet header size. */
+ if ( ui32LPending != ui32ReqSize + sizeof(PVRSRVTL_PACKETHDR) )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_MISUSE);
+ }
+
+ /* Update pointer to written data. */
+ ui32LWrite = (ui32LWrite + ui32LPending) % psTmp->ui32Size;
+
+ /* and reset LPending to 0 since data are now submitted */
+ ui32LPending = NOTHING_PENDING;
+
+ /* If we have transitioned from an empty buffer to a non-empty buffer,
+ * signal any consumers that may be waiting. */
+ if (ui32OldWrite == ui32LRead && !psTmp->bNoSignalOnCommit)
+ {
+ /* Signal consumers that may be waiting */
+ eError = OSEventObjectSignal(psTmp->psNode->hDataEventObj);
+ if ( eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(eError);
+ }
+ }
+
+ /* Calculate high water mark for debug purposes */
+#if defined(TL_BUFFER_UTILIZATION)
+ {
+ IMG_UINT32 tmp = 0;
+ if (ui32LWrite > ui32LRead)
+ {
+ tmp = (ui32LWrite-ui32LRead);
+ }
+ else if (ui32LWrite < ui32LRead)
+ {
+ tmp = (psTmp->ui32Size-ui32LRead+ui32LWrite);
+ } /* else equal, ignore */
+
+ if (tmp > psTmp->ui32BufferUt)
+ {
+ psTmp->ui32BufferUt = tmp;
+ }
+ }
+#endif
+
+ /* Update stream buffer parameters to match local copies */
+ psTmp->ui32Write = ui32LWrite ;
+ psTmp->ui32Pending = ui32LPending ;
+
+ PVR_DPF_RETURN_OK;
+}
+
+PVRSRV_ERROR
+TLStreamWrite(IMG_HANDLE hStream, IMG_UINT8 *pui8Src, IMG_UINT32 ui32Size)
+{
+ IMG_BYTE *pbyDest = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF_ENTERED;
+
+ if ( IMG_NULL == hStream )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ eError = TLStreamReserve(hStream, &pbyDest, ui32Size);
+ if ( PVRSRV_OK != eError )
+ {
+ PVR_DPF_RETURN_RC(eError);
+ }
+ else
+ {
+ PVR_ASSERT ( pbyDest != NULL );
+ OSMemCopy((IMG_VOID*)pbyDest, (IMG_VOID*)pui8Src, ui32Size);
+ eError = TLStreamCommit(hStream, ui32Size);
+ if ( PVRSRV_OK != eError )
+ {
+ PVR_DPF_RETURN_RC(eError);
+ }
+ }
+ PVR_DPF_RETURN_OK;
+}
+
+IMG_VOID TLStreamInfo(PTL_STREAM_INFO psInfo)
+{
+ IMG_DEVMEM_SIZE_T actual_req_size;
+ IMG_DEVMEM_ALIGN_T align = 4; /* Low dummy value so the real value can be obtained */
+
+ actual_req_size = 2;
+ DevmemExportalignAdjustSizeAndAlign(IMG_NULL, &actual_req_size, &align);
+
+ psInfo->headerSize = sizeof(PVRSRVTL_PACKETHDR);
+ psInfo->minReservationSize = sizeof(IMG_UINT32);
+ psInfo->pageSize = (IMG_UINT32)(actual_req_size);
+ psInfo->pageAlign = (IMG_UINT32)(align);
+}
+
+PVRSRV_ERROR
+TLStreamMarkEOS(IMG_HANDLE psStream)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT8* pData;
+
+ PVR_DPF_ENTERED;
+
+ if ( IMG_NULL == psStream )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ eError = DoTLStreamReserve(psStream, &pData, 0, 0, PVRSRVTL_PACKETTYPE_MARKER_EOS, NULL);
+ if ( PVRSRV_OK != eError )
+ {
+ PVR_DPF_RETURN_RC(eError);
+ }
+
+ PVR_DPF_RETURN_RC(TLStreamCommit(psStream, 0));
+}
+
+PVRSRV_ERROR
+TLStreamSync(IMG_HANDLE psStream)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PTL_STREAM psTmp;
+
+ PVR_DPF_ENTERED;
+
+ if ( IMG_NULL == psStream )
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+ psTmp = (PTL_STREAM)psStream;
+
+ /* Signal clients only when data is available to read */
+ if (psTmp->ui32Read != psTmp->ui32Write)
+ {
+ eError = OSEventObjectSignal(psTmp->psNode->hDataEventObj);
+ }
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+/*
+ * Internal stream APIs to server part of Transport Layer, declared in
+ * header tlintern.h. Direct pointers to stream objects are used here as
+ * these functions are internal.
+ */
+IMG_UINT32
+TLStreamAcquireReadPos(PTL_STREAM psStream, IMG_UINT32* puiReadOffset)
+{
+ IMG_UINT32 uiReadLen = 0;
+ IMG_UINT32 ui32LRead, ui32LWrite;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psStream);
+ PVR_ASSERT(puiReadOffset);
+
+ /* Grab a local copy */
+ ui32LRead = psStream->ui32Read;
+ ui32LWrite = psStream->ui32Write;
+
+ /* No data available and CB defined - try and get data */
+ if ((ui32LRead == ui32LWrite) && psStream->pfProducerCallback)
+ {
+ PVRSRV_ERROR eRc;
+ IMG_UINT32 ui32Resp = 0;
+
+ eRc = ((TL_STREAM_SOURCECB)psStream->pfProducerCallback)(psStream, TL_SOURCECB_OP_CLIENT_EOS,
+ &ui32Resp, psStream->pvProducerUserData);
+ PVR_LOG_IF_ERROR(eRc, "TLStream->pfProducerCallback");
+
+ ui32LWrite = psStream->ui32Write;
+ }
+
+ /* No data available... */
+ if (ui32LRead == ui32LWrite)
+ {
+ PVR_DPF_RETURN_VAL(0);
+ }
+
+ /* Data is available to read... */
+ *puiReadOffset = ui32LRead;
+
+ /*PVR_DPF((PVR_DBG_VERBOSE,
+ * "TLStreamAcquireReadPos Start before: Write:%d, Read:%d, size:%d",
+ * ui32LWrite, ui32LRead, psStream->ui32Size));
+ */
+
+ if ( ui32LRead > ui32LWrite )
+ { /* CB has wrapped around.
+ * Return the first contiguous piece of memory, ie [ReadLen,EndOfBuffer]
+ * and let a subsequent AcquireReadPos read the rest of the Buffer */
+ /*PVR_DPF((PVR_DBG_VERBOSE, "TLStreamAcquireReadPos buffer has wrapped"));*/
+ uiReadLen = psStream->ui32Size - ui32LRead;
+ }
+ else
+ { // CB has not wrapped
+ uiReadLen = ui32LWrite - ui32LRead;
+ }
+
+ PVR_DPF_RETURN_VAL(uiReadLen);
+}
+
+IMG_VOID
+TLStreamAdvanceReadPos(PTL_STREAM psStream, IMG_UINT32 uiReadLen)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psStream);
+
+ /* Get a local copy of the stream buffer parameters */
+ psStream->ui32Read = (psStream->ui32Read + uiReadLen) % psStream->ui32Size;
+
+ /* If this is a blocking reserve stream,
+ * notify reserves that may be pending */
+ if(psStream->bBlock)
+ {
+ PVRSRV_ERROR eError;
+ eError = OSEventObjectSignal(psStream->hProducerEventObj);
+ if ( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "Error in TLStreamAdvanceReadPos: OSEventObjectSignal returned:%u",
+ eError));
+ }
+ }
+
+ PVR_DPF((PVR_DBG_VERBOSE,
+ "TLStreamAdvanceReadPos Read now at: %d",
+ psStream->ui32Read));
+ PVR_DPF_RETURN;
+}
+
+DEVMEM_EXPORTCOOKIE*
+TLStreamGetBufferCookie(PTL_STREAM psStream)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psStream);
+
+ PVR_DPF_RETURN_VAL(&psStream->sExportCookie);
+}
+
+IMG_BOOL
+TLStreamEOS(PTL_STREAM psStream)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psStream);
+
+ /* If both pointers are equal then the buffer is empty */
+ PVR_DPF_RETURN_VAL( psStream->ui32Read == psStream->ui32Write );
+}
+
diff --git a/drivers/gpu/rogue/services/server/common/tutils.c b/drivers/gpu/rogue/services/server/common/tutils.c
new file mode 100644
index 000000000000..61d8a4468ee0
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/common/tutils.c
@@ -0,0 +1,1629 @@
+/*************************************************************************/ /*!
+@File
+@Title KM server Transport Layer implementation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main bridge APIs for Transport Layer client 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 <stddef.h>
+
+#if defined(LINUX)
+#include "linux/random.h"
+#include "linux/kthread.h"
+#elif defined(_WIN32)
+#if defined (UNDER_WDDM)
+#include <Ntifs.h>
+#endif
+#elif defined(__QNXNTO__)
+#include <stdlib.h>
+#else
+#error TLTEST.C needs random number API
+#endif
+
+#if defined(DEBUG) && !defined(PVRSRV_NEED_PVR_DPF)
+#define PVRSRV_NEED_PVR_DPF
+#endif
+
+#include "img_defs.h"
+
+#include "pvrsrv_error.h"
+
+//#define PVR_DPF_FUNCTION_TRACE_ON 1
+#undef PVR_DPF_FUNCTION_TRACE_ON
+
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "power.h"
+
+#include "allocmem.h"
+#include "osfunc.h"
+
+#include "pvrsrv.h"
+#include "rgxdevice.h"
+#include "lists.h"
+#include "rgxdefs_km.h"
+#include "rgxfwutils.h"
+
+#include "tlintern.h"
+#include "tlstream.h"
+#include "tltestdefs.h"
+
+/******************************************************************************
+ * Do not include tlserver.h, as this is testing the kernelAPI, some
+ * duplicate definitions
+ */
+PVRSRV_ERROR
+TLServerTestIoctlKM(IMG_UINT32 uiCmd,
+ IMG_PBYTE uiIn1,
+ IMG_UINT32 uiIn2,
+ IMG_UINT32 *puiOut1,
+ IMG_UINT32 *puiOut2);
+
+PVRSRV_ERROR
+PowMonTestIoctlKM(IMG_UINT32 uiCmd,
+ IMG_UINT32 uiIn1,
+ IMG_UINT32 uiIn2,
+ IMG_UINT32 *puiOut1,
+ IMG_UINT32 *puiOut2);
+
+/*****************************************************************************/
+
+#if defined(PVR_TESTING_UTILS)
+
+/******************************************************************************
+ *
+ * TL KM Test helper global variables, prototypes
+ */
+typedef struct _TLT_SRCNODE_
+{
+ struct _TLT_SRCNODE_* psNext;
+
+ IMG_HANDLE gTLStream;
+ IMG_HANDLE gStartTimer;
+ IMG_HANDLE gSourceTimer;
+
+ IMG_UINT32 gSourceCount;
+ IMG_UINT8* gpuiDataPacket;
+
+ union {
+ PVR_TL_TEST_CMD_SOURCE_START_IN gsStartIn;
+ PVR_TL_TEST_CMD_STREAM_CREATE_IN gsCreateIn;
+ } u;
+
+ IMG_VOID (*gSourceWriteCB)(IMG_VOID *, IMG_UINT16);
+} TLT_SRCNODE;
+
+TLT_SRCNODE* gpsSourceStack = 0;
+
+typedef enum
+{
+ TLT_OP_NONE,
+ TLT_OP_CLEANUP_START_TIMER,
+ TLT_OP_CLEANUP_SOURCE_STOP,
+ TLT_OP_END
+} TLT_OP;
+
+typedef struct _TLT_THREAD_
+{
+ IMG_HANDLE hThread;
+ IMG_HANDLE hEventList;
+ IMG_HANDLE hEvent;
+ TLT_OP eOperation;
+ IMG_VOID* pvOpParam1;
+} TLT_THREAD;
+
+TLT_THREAD* gpsCleanUp = 0;
+
+static PVRSRV_ERROR RegisterCleanupAction(TLT_OP eOp, IMG_VOID* pvParam1);
+
+#define RANDOM_MOD 256
+IMG_BOOL gRandomReady = IMG_FALSE;
+IMG_BYTE gRandomStore[RANDOM_MOD];
+
+#if defined(__QNXNTO__)
+#define RANDOM_STATE_SIZE 128
+static char gcRandomState[RANDOM_STATE_SIZE];
+#endif
+
+static IMG_VOID StartTimerFuncCB(IMG_VOID* p);
+static IMG_VOID SourceTimerFuncCB(IMG_VOID* p);
+static IMG_VOID SourceWriteFunc(IMG_VOID* p, IMG_UINT16 uiPacketSizeInBytes);
+static IMG_VOID SourceWriteFunc2(IMG_VOID* p, IMG_UINT16 uiPacketSizeInBytes);
+
+/******************************************************************************
+ *
+ * Power Monitoring variables
+ */
+
+static IMG_HANDLE g_hPowerMonitoringThread;
+static IMG_BOOL g_bPowMonEnable;
+static IMG_UINT32 g_ui32PowMonLatencyms;
+static IMG_UINT32 g_PowMonEstimate;
+static IMG_UINT32 g_PowMonState;
+
+/******************************************************************************
+ *
+ * TL KM Test helper routines
+ */
+
+/* Since this is done in multiple locations in this file, make it a local function. */
+static PVRSRV_ERROR createStream(PVR_TL_TEST_CMD_SOURCE_START_IN** ppsIn1,
+ TLT_SRCNODE** pSrcn)
+{
+ PVR_TL_TEST_CMD_SOURCE_START_IN* psIn1 = *ppsIn1;
+ TLT_SRCNODE* srcn = *pSrcn;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_DPF_ENTERED;
+
+ /* Do not ask the server to create two streams with the same name,
+ * reuse existing one to support multiple source single stream test cases.
+ */
+ if ( IMG_NULL == TLFindStreamNodeByName(psIn1->pszStreamName) )
+ {
+ eError = TLStreamCreate (&srcn->gTLStream,
+ psIn1->pszStreamName,
+ ((OSGetPageSize()*psIn1->uiStreamSizeInPages))
+ - PVR_TL_TEST_STREAM_BUFFER_REDUCTION,
+ psIn1->uiStreamCreateFlags, IMG_NULL, IMG_NULL);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_ALREADY_EXISTS);
+ }
+ PVR_ASSERT(srcn->gTLStream);
+ }
+ else
+ {
+ eError = TLStreamOpen (&srcn->gTLStream, psIn1->pszStreamName);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_ALREADY_EXISTS);
+ }
+ PVR_ASSERT(srcn->gTLStream);
+ }
+ PVR_DPF_RETURN_RC(PVRSRV_OK);
+}
+
+static PVRSRV_ERROR TLTestCMD_SourceStart (PVR_TL_TEST_CMD_SOURCE_START_IN *psIn1,
+ IMG_VOID (*pfCB)(IMG_VOID* , IMG_UINT16))
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 i;
+ IMG_UINT16 uiPacketBufferSize;
+ TLT_SRCNODE *srcn =0;
+
+ PVR_DPF_ENTERED;
+
+ srcn = OSAllocZMem(sizeof(TLT_SRCNODE));
+ if (!srcn)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ // Remember the start parameters, initialise buffers
+ srcn->u.gsStartIn = *psIn1;
+ PVR_DPF((PVR_DBG_MESSAGE, "--- SourceParameters (n:%s, p:%d, i:%d, k:%d, s:%d, f:%x sd:%d ds:%d cs:%d)",
+ psIn1->pszStreamName, psIn1->uiStreamSizeInPages,
+ psIn1->uiInterval, psIn1->uiCallbackKicks, psIn1->uiPacketSizeInBytes,
+ psIn1->uiStreamCreateFlags, psIn1->uiStartDelay,
+ psIn1->bDoNotDeleteStream, psIn1->bDelayStreamCreate));
+
+ uiPacketBufferSize = (psIn1->uiPacketSizeInBytes == 0) ? 256 : psIn1->uiPacketSizeInBytes;
+ srcn->gpuiDataPacket = OSAllocMem(uiPacketBufferSize);
+ if (!srcn->gpuiDataPacket)
+ {
+ OSFREEMEM(srcn);
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ for (i=0; i<uiPacketBufferSize; i++)
+ {
+ /* Only use LSB of i to populate the data array */
+ srcn->gpuiDataPacket[i] = (IMG_UINT8)i;
+ }
+
+ if (!gRandomReady)
+ {
+#if defined(LINUX)
+ get_random_bytes(gRandomStore, sizeof(gRandomStore));
+#elif defined(_WIN32)
+ // IMG_UINT32 seed = ( KeQueryInterruptTime() / 10 ) & 0xFFFFFFFF;
+ LARGE_INTEGER seed = KeQueryPerformanceCounter(0);
+
+ for (i=0; i< RANDOM_MOD/sizeof(ULONG); i+=sizeof(ULONG))
+ {
+ /* Use just the lower byte of the random 8-bit number */
+ gRandomStore[i] = (IMG_BYTE) RtlRandomEx(&seed.u.LowPart);
+ }
+#elif defined(__QNXNTO__)
+ initstate(time(NULL), gcRandomState, sizeof(gcRandomState));
+ setstate(gcRandomState);
+ for (i=0; i<RANDOM_MOD; ++i)
+ {
+ gRandomStore[i] = (IMG_BYTE) (random() & 0xFF);
+ }
+#endif
+ gRandomReady = IMG_TRUE;
+ }
+
+ // Create the stream to use with the source now if deferral not enabled.
+ if (!psIn1->bDelayStreamCreate)
+ {
+ eError = createStream(&psIn1, &srcn);
+ if (eError != PVRSRV_OK)
+ {
+ OSFREEMEM(srcn->gpuiDataPacket);
+ OSFREEMEM(srcn);
+ PVR_DPF_RETURN_RC(eError);
+ }
+ }
+
+ // Setup timer and start it
+ i = (psIn1->uiStartDelay==0) ? psIn1->uiInterval : psIn1->uiStartDelay;
+ srcn->gStartTimer = OSAddTimer(StartTimerFuncCB, (IMG_VOID *)srcn, i);
+ if (!srcn->gStartTimer)
+ {
+ OSFREEMEM(srcn->gpuiDataPacket);
+ OSFREEMEM(srcn);
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_UNABLE_TO_ADD_TIMER);
+ }
+
+ // Reset global count and enable timer
+ srcn->gSourceTimer = 0;
+ srcn->gSourceCount = 0;
+ srcn->gSourceWriteCB = pfCB;
+ eError = OSEnableTimer(srcn->gStartTimer);
+
+ srcn->psNext = gpsSourceStack;
+ gpsSourceStack = srcn;
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+static PVRSRV_ERROR TLTestCMD_SourceStop (PVR_TL_TEST_CMD_SOURCE_STOP_IN *psIn1)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TLT_SRCNODE *srcn = gpsSourceStack;
+ TLT_SRCNODE **srcn_prev = &gpsSourceStack;
+
+ PVR_DPF_ENTERED;
+
+ if (psIn1->pszStreamName[0] != '\0')
+ {
+ /* Find the data source in the stack of sources */
+ for (; srcn != 0; srcn = srcn->psNext)
+ {
+ if (OSStringCompare(srcn->u.gsStartIn.pszStreamName, psIn1->pszStreamName) == 0)
+ {
+ break;
+ }
+ srcn_prev = &srcn->psNext;
+ }
+ }
+ /* else
+ * Select the data source at the top of the stack.*/
+
+ if (!srcn)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_FOUND);
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "--- Stopping Data Source: %s", srcn->u.gsStartIn.pszStreamName));
+
+ /* See if we have been asked to stop before we have started */
+ if (srcn->gStartTimer)
+ {
+ /* Stop and clean up timer */
+ eError = OSDisableTimer(srcn->gStartTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER);
+ }
+
+ eError = OSRemoveTimer(srcn->gStartTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER);
+ }
+ srcn->gStartTimer = 0;
+ }
+
+ if (srcn->gSourceTimer)
+ {
+ /* Stop and clean up source timer */
+ eError = OSDisableTimer(srcn->gSourceTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER);
+ }
+
+ eError = OSRemoveTimer(srcn->gSourceTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER);
+ }
+ srcn->gSourceTimer = 0;
+ }
+
+ if (srcn->gpuiDataPacket)
+ {
+ OSFREEMEM(srcn->gpuiDataPacket);
+ }
+
+ /* Cleanup transport stream AND source node if we are not to keep the
+ * stream for later destruction */
+ if (psIn1->bDoNotDeleteStream)
+ {
+ srcn->gSourceWriteCB = 0;
+ }
+ else
+ {
+ TLStreamClose(srcn->gTLStream);
+ srcn->gTLStream = 0;
+
+ *srcn_prev = srcn->psNext;
+ OSFREEMEM(srcn);
+ }
+
+ PVR_DPF_RETURN_OK;
+}
+
+
+// Return TRUE if the source should generate a packet, FALSE if not.
+static IMG_BOOL SourceCBCommon(TLT_SRCNODE *srcn, IMG_UINT16 *puiPacketSizeInBytes)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ srcn->gSourceCount++;
+ PVR_DPF((PVR_DBG_MESSAGE, "--- Data Source CB: %s #%d", srcn->u.gsStartIn.pszStreamName, srcn->gSourceCount));
+
+ // Work out packet size to use...
+ if (srcn->u.gsStartIn.uiPacketSizeInBytes == 0)
+ {
+ // Random packet size
+ *puiPacketSizeInBytes = (IMG_UINT16)gRandomStore[srcn->gSourceCount%RANDOM_MOD];
+ }
+ else
+ {
+ // Fixed packet size
+ *puiPacketSizeInBytes = srcn->u.gsStartIn.uiPacketSizeInBytes;
+ }
+ if (*puiPacketSizeInBytes==0)
+ {
+ *puiPacketSizeInBytes=4;
+ }
+ PVR_ASSERT(srcn->gTLStream);
+
+ if (srcn->u.gsStartIn.uiCallbackKicks && (srcn->gSourceCount >= srcn->u.gsStartIn.uiCallbackKicks+2U))
+ { // If there is a kick limit and we have surpassed it, clean up
+
+ // Kick sequence should mean that this clean is only triggered
+ // on a periodic (not start) kick.
+ PVR_ASSERT((srcn->gStartTimer == 0) && (srcn->gSourceTimer != 0));
+
+ eError = RegisterCleanupAction(TLT_OP_CLEANUP_SOURCE_STOP, srcn);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RegisterCleanupAction() error %d", eError));
+ return IMG_TRUE;
+ }
+
+ return IMG_FALSE;
+ }
+ else if (srcn->u.gsStartIn.uiCallbackKicks &&
+ (srcn->gSourceCount > srcn->u.gsStartIn.uiCallbackKicks) &&
+ (srcn->gSourceCount <= srcn->u.gsStartIn.uiCallbackKicks+2U))
+ { // We have reached the callback limit, do not add data
+ // Delay the stream destructions for two kicks
+ return IMG_FALSE;
+ }
+ else
+ {
+ return IMG_TRUE;
+ }
+}
+
+
+static IMG_VOID StartTimerFuncCB(IMG_VOID *p)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT16 uiPacketSizeInBytes;
+ TLT_SRCNODE *srcn = (TLT_SRCNODE*)p;
+ PVR_TL_TEST_CMD_SOURCE_START_IN* psIn1;
+
+ PVR_ASSERT(srcn);
+
+ psIn1 = &(srcn->u.gsStartIn);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s() srcn->gSourceCount = '%d'", __func__, srcn->gSourceCount));
+
+ if (psIn1->bDelayStreamCreate)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s() Going to create stream '%s'", __func__, psIn1->pszStreamName));
+ eError = createStream(&psIn1, &srcn);
+ PVR_LOG_IF_ERROR(eError, "createStream");
+
+ PVR_ASSERT(srcn->gTLStream);
+ }
+ else
+ {
+ // We should only get CB once but if the period is short we might get
+ // invoked multiple times so silently return
+ if (srcn->gTLStream == 0)
+ {
+ return;
+ }
+ }
+ // Clean up start timer, we will use the source timer for our next invoke
+ eError = RegisterCleanupAction(TLT_OP_CLEANUP_START_TIMER, srcn);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RegisterCleanupAction() error %d", eError));
+ // No clean up not fatal so cont...
+ // return;
+ }
+
+ // Attempt to perform our first kick, submit 1st packet
+ // Has the kicks limit not been exceeded?
+ if (SourceCBCommon(srcn, &uiPacketSizeInBytes) == IMG_TRUE)
+ {
+ srcn->gSourceWriteCB(srcn, uiPacketSizeInBytes);
+ }
+
+ // Always start the periodic timer as clean up happens two kicks after
+ // the last data packet. This allows clients to drain the stream buffer.
+
+ // Setup timer and start it
+ srcn->gSourceTimer = OSAddTimer(SourceTimerFuncCB, (IMG_VOID *)srcn, srcn->u.gsStartIn.uiInterval);
+ if (!srcn->gSourceTimer)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer() unable to add timer"));
+ return;
+ }
+
+ eError = OSEnableTimer(srcn->gSourceTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEnableTimer() error %d", eError));
+ }
+
+ return;
+}
+
+
+static IMG_VOID SourceTimerFuncCB(IMG_VOID *p)
+{
+ IMG_UINT16 uiPacketSizeInBytes;
+ TLT_SRCNODE *srcn = (TLT_SRCNODE*)p;
+
+ PVR_ASSERT(srcn);
+
+ // Has the kicks limit not been exceeded?
+ if (SourceCBCommon(srcn, &uiPacketSizeInBytes) == IMG_TRUE)
+ {
+ srcn->gSourceWriteCB(srcn, uiPacketSizeInBytes);
+ }
+}
+
+static IMG_VOID InjectEOSPacket(TLT_SRCNODE *srcn)
+{
+ PVRSRV_ERROR eError;
+
+ if ( 0 != srcn->u.gsStartIn.uiEOSMarkerKicks )
+ {
+ if ( 0 == ( srcn->gSourceCount % srcn->u.gsStartIn.uiEOSMarkerKicks) )
+ {
+ eError = TLStreamMarkEOS(srcn->gTLStream);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "TLStreamMarkEOS() error %d", eError));
+ }
+ }
+ }
+}
+
+static IMG_VOID SourceWriteFunc(IMG_VOID *p, IMG_UINT16 uiPacketSizeInBytes)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TLT_SRCNODE *srcn = (TLT_SRCNODE*)p;
+
+ PVR_ASSERT(srcn);
+
+ // Inject EOS Markers every uiEOSMarkerKicks number of kicks.
+ InjectEOSPacket(srcn);
+
+ // Commit packet into transport layer
+ // Special case if it is one word in a packet, use global counter as data
+ if (uiPacketSizeInBytes <= 4)
+ {
+ eError = TLStreamWrite(srcn->gTLStream, (IMG_UINT8*)&srcn->gSourceCount, uiPacketSizeInBytes);
+ }
+ else
+ {
+ eError = TLStreamWrite(srcn->gTLStream, (IMG_UINT8*)srcn->gpuiDataPacket, uiPacketSizeInBytes);
+ }
+
+ if (eError == PVRSRV_ERROR_STREAM_FULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "TLStreamWrite() returned 'data dropped' error code"));
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ /* Consume errors as they may occur normally in test scenarios */
+ PVR_DPF((PVR_DBG_MESSAGE, "TLStreamWrite() error %d", eError));
+ }
+}
+
+static IMG_VOID SourceWriteFunc2(IMG_VOID *p, IMG_UINT16 uiPacketSizeInBytes)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TLT_SRCNODE *srcn = (TLT_SRCNODE*)p;
+ IMG_UINT32 *pBuffer;
+
+ PVR_ASSERT(srcn);
+
+ // Inject EOS Markers every uiEOSMarkerKicks number of kicks.
+ InjectEOSPacket(srcn);
+
+ // Commit packet into transport layer via 2-stage API...
+ eError = TLStreamReserve(srcn->gTLStream, (IMG_UINT8**) &pBuffer, uiPacketSizeInBytes);
+ if (eError == PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "TLStreamReserve() pBuffer %p, uiPacketSizeInBytes %d", pBuffer, uiPacketSizeInBytes));
+
+ OSMemCopy(pBuffer, srcn->gpuiDataPacket, uiPacketSizeInBytes);
+
+ TLStreamCommit(srcn->gTLStream, uiPacketSizeInBytes);
+ }
+ else if (eError == PVRSRV_ERROR_STREAM_FULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "TLStreamReserve() returned 'data dropped' error code"));
+ }
+ else
+ {
+ /* Consume errors as they may occur normally in test scenarios */
+ PVR_DPF((PVR_DBG_MESSAGE, "TLStreamReserve() error %d", eError));
+ }
+}
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+// From services/server/env/linux/pvr_debug.c
+// Externed here to allow us to update it to log "message" class trace
+extern IMG_UINT32 gPVRDebugLevel;
+#endif
+
+static PVRSRV_ERROR TLTestCMD_DebugLevel (IMG_UINT32 uiIn1, IMG_UINT32 *puiOut1)
+{
+ PVR_DPF_ENTERED;
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+// gPVRDebugLevel |= DBGPRIV_MESSAGE;
+
+ *puiOut1 = gPVRDebugLevel;
+
+ gPVRDebugLevel = uiIn1;
+
+#endif
+
+ PVR_DPF((PVR_DBG_WARNING, "TLTestCMD_DebugLevel: gPVRDebugLevel set to 0x%x", gPVRDebugLevel));
+
+ PVR_DPF_RETURN_OK;
+}
+
+
+static PVRSRV_ERROR TLTestCMD_DumpState (IMG_VOID)
+{
+ TL_GLOBAL_DATA *psd = TLGGD();
+ PTL_SNODE psn = 0;
+ IMG_UINT count = 0;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psd);
+
+ PVR_LOG(("--- TL_GLOBAL_DATA: %p - uiClientCnt(%d) psHead(%p) psRgxDevNode(%p)",
+ psd, psd->uiClientCnt, psd->psHead, psd->psRgxDevNode));
+
+ for (psn = psd->psHead; psn; psn = psn->psNext)
+ {
+ count++;
+ PVR_LOG(("----- TL_SNODE[%d]: %p - psNext(%p) hDataEventObj(%p) psStream(%p) psDesc(%p)",
+ count, psn, psn->psNext, psn->hDataEventObj, psn->psStream, psn->psDesc));
+
+ if (psn->psStream)
+ {
+ PVR_LOG(("------- TL_STREAM[%d]: %p - psNode(%p) szName(%s) bDrop(%d) ",
+ count, psn->psStream, psn->psStream->psNode, psn->psStream->szName, psn->psStream->bDrop));
+ PVR_LOG(("------- TL_STREAM[%d]: %p - ui32Read(%d) ui32Write(%d) ui32Pending(%d) ui32Size(%d) ui32BufferUt(%d.%d%%)",
+ count, psn->psStream, psn->psStream->ui32Read, psn->psStream->ui32Write, psn->psStream->ui32Pending, psn->psStream->ui32Size,
+ ((psn->psStream->ui32BufferUt*10000)/psn->psStream->ui32Size)/100,
+ ((psn->psStream->ui32BufferUt*10000)/psn->psStream->ui32Size)%100));
+ PVR_LOG(("------- TL_STREAM[%d]: %p - ui32Buffer(%p) psStreamMemDesc(%p) sExportCookie.hPMRExportHandle(%p)",
+ count, psn->psStream, psn->psStream->pbyBuffer, psn->psStream->psStreamMemDesc, psn->psStream->sExportCookie.hPMRExportHandle));
+ }
+
+ if (psn->psDesc)
+ {
+ PVR_LOG(("------ TL_STREAM_DESC[%d]: %p - psNode(%p) ui32Flags(%x) hDataEvent(%p)",
+ count, psn->psDesc, psn->psDesc->psNode, psn->psDesc->ui32Flags, psn->psDesc->hDataEvent));
+ }
+
+ }
+ PVR_DPF_RETURN_OK;
+}
+
+static PVRSRV_ERROR TLTestCMD_DumpHWPerfState (IMG_VOID)
+{
+ PVRSRV_DATA* psGD = PVRSRVGetPVRSRVData();
+ PVRSRV_RGXDEV_INFO* psRD;
+ RGXFWIF_TRACEBUF* psTB;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psGD);
+ if (psGD->ui32NumDevices != 1)
+ {
+ PVR_LOG(("--- PVRSRV_DATA: Unable to dump, 0 or multiple devices exist!"));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_READY);
+ }
+
+ PVR_LOG(("--- PVRSRV_DATA: %p - ui32NumDevices( %d ) apsRegisteredDevNodes[0]( %p ) apsRegisteredDevNodes[0]->pvDevice( %p )",
+ psGD, psGD->ui32NumDevices,
+ psGD->apsRegisteredDevNodes[0],
+ psGD->apsRegisteredDevNodes[0]->pvDevice));
+
+ psRD = psGD->apsRegisteredDevNodes[0]->pvDevice;
+ PVR_LOG(("----- PVRSRV_RGXDEV_INFO: %p - psRGXFWIfTraceBuf( %p ) psRGXFWIfHWPerfBuf( %p )",
+ psRD, psRD->psRGXFWIfTraceBuf,
+ psRD->psRGXFWIfHWPerfBuf));
+
+ psTB = psRD->psRGXFWIfTraceBuf;
+ PVR_LOG(("-------- RGXFWIF_TRACEBUF: %p", psTB));
+
+ PVR_LOG(("-------- RGXFWIF_TRACEBUF: HWPerSize( %d ) HWPerfFullWatermark%%( %d.%d %% )",
+ psRD->ui32RGXFWIfHWPerfBufSize,
+ ((psTB->ui32HWPerfUt*10000)/psRD->ui32RGXFWIfHWPerfBufSize)/100,
+ ((psTB->ui32HWPerfUt*10000)/psRD->ui32RGXFWIfHWPerfBufSize)%100));
+ PVR_LOG(("-------- RGXFWIF_TRACEBUF: HWPerfDropCount( %d ) FirstDropOrdinal( %d ) LastDropOrdinal( %d )",
+ psTB->ui32HWPerfDropCount, psTB->ui32FirstDropOrdinal, psTB->ui32LastDropOrdinal));
+ PVR_LOG(("-------- RGXFWIF_TRACEBUF: HWPerfRIdx( %d ) HWPerfWIdx( %d ) HWPerfWrapCount( %d )",
+ psTB->ui32HWPerfRIdx, psTB->ui32HWPerfWIdx,
+ psTB->ui32HWPerfWrapCount));
+
+ PVR_DPF_RETURN_OK;
+}
+
+static IMG_PVOID TLTestCMD_FindRGXDevNode(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
+ {
+ return psDeviceNode;
+ }
+ return NULL;
+}
+
+static PVRSRV_ERROR TLTestCMD_FlushHWPerfFWBuf (IMG_VOID)
+{
+ PVRSRV_ERROR rc = PVRSRV_OK;
+ PVRSRV_DEVICE_NODE* psDevNode = 0;
+ PVRSRV_DATA* psGlobalSrvData = PVRSRVGetPVRSRVData();
+
+ PVR_DPF_ENTERED;
+
+ PVR_DPF((PVR_DBG_WARNING, "TLTestCMD_FlushHWPerfFWBuf: ..."));
+
+ /* Search for the RGX device node */
+ psDevNode = List_PVRSRV_DEVICE_NODE_Any(psGlobalSrvData->psDeviceNodeList, TLTestCMD_FindRGXDevNode);
+ if (psDevNode == 0)
+ {
+ /* Device node was not found */
+ PVR_DPF((PVR_DBG_ERROR, "Failed to fin the RGX device node"));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_FOUND);
+ }
+
+ rc = psDevNode->pfnServiceHWPerf(psDevNode);
+
+#if defined(NO_HARDWARE)
+ PVR_DPF((PVR_DBG_WARNING, "TLTestCMD_FlushHWPerfFWBuf is a no-op on NO_HARDWARE!"));
+#endif
+
+ PVR_DPF_RETURN_RC(rc);
+}
+
+static PVRSRV_ERROR TLTestCMD_SignalPE (IMG_UINT32* psIn1)
+{
+ PVRSRV_DEVICE_NODE* psDevNode = 0;
+ PVRSRV_RGXDEV_INFO* psDevInfo = 0;
+ PVRSRV_DATA* psGlobalSrvData = PVRSRVGetPVRSRVData();
+ IMG_UINT32 ui32Tmp;
+
+ PVR_DPF_ENTERED;
+
+ PVR_DPF((PVR_DBG_WARNING, "TLTestCMD_SignalPE: ( %d ) ( %d )",
+ psIn1[1], psIn1[3]));
+
+ /* Search for the RGX device node */
+ psDevNode = List_PVRSRV_DEVICE_NODE_Any(psGlobalSrvData->psDeviceNodeList, TLTestCMD_FindRGXDevNode);
+ if (psDevNode == 0)
+ {
+ /* Device node was not found */
+ PVR_DPF((PVR_DBG_ERROR, "Failed to fin the RGX device node"));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_FOUND);
+ }
+ psDevInfo = psDevNode->pvDevice;
+
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, psIn1[0], psIn1[1]);
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, psIn1[2], psIn1[3]);
+
+ /* kick GPIO */
+ ui32Tmp = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_EVENT_STATUS);
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_EVENT_STATUS, ui32Tmp|RGX_CR_EVENT_STATUS_GPIO_REQ_EN);
+
+ /* ensure the registers goes through before continuing */
+ OSMemoryBarrier();
+
+ /* ack the output from the FW (using the event_status this way could lead to corrupted event_status,
+ as there is a race condition, but there is no other way to check the behaviour, so use this) */
+ ui32Tmp = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_EVENT_STATUS);
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_EVENT_STATUS, ui32Tmp|RGX_CR_EVENT_STATUS_GPIO_ACK_EN);
+ OSMemoryBarrier();
+
+#if defined(NO_HARDWARE)
+ PVR_DPF((PVR_DBG_WARNING, "TLTestCMD_SignalPwrEst is a no-op on NO_HARDWARE!"));
+#endif
+
+ PVR_DPF_RETURN_OK;
+}
+
+extern IMG_VOID PDumpCommonDumpState(IMG_VOID);
+
+static PVRSRV_ERROR TLTestCMD_DumpPDumpState (IMG_VOID)
+{
+ PVR_DPF_ENTERED;
+
+#if defined(PDUMP)
+ PDumpCommonDumpState();
+#endif
+
+ PVR_DPF_RETURN_OK;
+}
+
+
+
+static PVRSRV_ERROR RegisterCleanupAction(TLT_OP eOp, IMG_VOID *pvParam1)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_DPF_ENTERED;
+
+ if (gpsCleanUp == 0)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INIT_FAILURE);
+ }
+
+ if (gpsCleanUp->eOperation != TLT_OP_NONE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RegisterCleanupAction not ready, pending cleanup %d, requested cleanup %d", gpsCleanUp->eOperation, eOp));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_READY);
+ }
+
+ gpsCleanUp->eOperation = eOp;
+ gpsCleanUp->pvOpParam1 = pvParam1;
+
+ eError = OSEventObjectSignal(gpsCleanUp->hEventList);
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+/* Called at driver unloaded/shutdown.
+ */
+static PVRSRV_ERROR TLDeInitialiseCleanupTestThread (IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TLT_THREAD* psThreadData;
+
+ PVR_DPF_ENTERED;
+
+ /* Has the thread already died and cleaned up? */
+ if (gpsCleanUp == 0)
+ {
+ PVR_DPF_RETURN_OK;
+ }
+
+ psThreadData = gpsCleanUp;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "------- DeInit CleanUp: %p, %p, %p, %d, %p", psThreadData->hThread,
+ psThreadData->hEventList, psThreadData->hEvent, psThreadData->eOperation, psThreadData->pvOpParam1));
+
+ eError = RegisterCleanupAction(TLT_OP_END, 0);
+ PVR_LOG_IF_ERROR(eError, "RegisterCleanupAction");
+
+ /* Prevent any further registrations between now an when the thread exits */
+ gpsCleanUp = NULL;
+
+ eError = OSThreadDestroy(psThreadData->hThread);
+ PVR_LOG_IF_ERROR(eError, "OSThreadDestroy");
+
+ /* At this point we expect the clean up thread's event loop to break
+ * so that it can perform the clean up as needed and free the thread data.
+ */
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+#define TEN_SECOND_TIMEOUT 10000
+
+static IMG_VOID CleanupThread(IMG_PVOID pvData)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TLT_THREAD *psThreadData = pvData;
+ TLT_SRCNODE *psSrcNode;
+ PVR_TL_TEST_CMD_SOURCE_STOP_IN sStopParams;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psThreadData);
+ memset(&sStopParams, 0x00, sizeof(sStopParams));
+
+ while (psThreadData->eOperation != TLT_OP_END)
+ {
+ OSEventObjectWaitTimeout(psThreadData->hEvent, TEN_SECOND_TIMEOUT);
+
+#if defined(LINUX) && defined(__KERNEL__)
+ if (kthread_should_stop())
+ {
+ break;
+ }
+#endif
+
+ // On detecting bad state, exit thread as a safety measure
+ if (gpsCleanUp == 0)
+ {
+ break;
+ }
+
+ switch (psThreadData->eOperation)
+ {
+ case TLT_OP_CLEANUP_START_TIMER:
+ // Stop and clean up start timer
+ PVR_DPF((PVR_DBG_MESSAGE, "TLT CleanupThread: source start cleanup"));
+ psSrcNode = psThreadData->pvOpParam1;
+ eError = OSDisableTimer(psSrcNode->gStartTimer);
+ PVR_LOG_IF_ERROR(eError, "OSDisableTimer");
+ eError = OSRemoveTimer(psSrcNode->gStartTimer);
+ PVR_LOG_IF_ERROR(eError, "OSRemoveTimer");
+ psSrcNode->gStartTimer = 0;
+
+ /* Loop and wait again */
+ psThreadData->eOperation = TLT_OP_NONE;
+ psThreadData->pvOpParam1 = 0;
+ break;
+
+ case TLT_OP_CLEANUP_SOURCE_STOP:
+ // Stop and clean up data source
+ PVR_DPF((PVR_DBG_MESSAGE, "TLT CleanupThread: source stop cleanup"));
+ psSrcNode = psThreadData->pvOpParam1;
+ OSStringCopy(sStopParams.pszStreamName, psSrcNode->u.gsStartIn.pszStreamName);
+ sStopParams.bDoNotDeleteStream = psSrcNode->u.gsStartIn.bDoNotDeleteStream;
+ eError = TLTestCMD_SourceStop (&sStopParams);
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_SourceStop");
+ psSrcNode = 0;
+
+ /* Loop and wait again */
+ psThreadData->eOperation = TLT_OP_NONE;
+ psThreadData->pvOpParam1 = 0;
+ break;
+
+ case TLT_OP_END: /* Used on WDDM platform */
+ PVR_DPF((PVR_DBG_MESSAGE, "TLT CleanupThread: ending..."));
+ break;
+
+ case TLT_OP_NONE:
+ default: /* Do nothing... but wait again */
+ PVR_DPF((PVR_DBG_MESSAGE, "TLT CleanupThread: waiting..."));
+ break;
+ }
+
+ }
+
+ /* We exit event loop when the thread must end signalled either via our
+ * OP_END (WDDM) or a kill signal (Linux).
+ * We are responsible here for cleaning up of thread resources.
+ * gpsCleanUp==0 already from the TLDeInitialiseCleanupTestThread() call.
+ */
+ PVR_ASSERT(gpsCleanUp==0);
+
+ eError = OSEventObjectClose(psThreadData->hEvent);
+ psThreadData->hEvent = 0;
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectClose");
+
+ eError = OSEventObjectDestroy(psThreadData->hEventList);
+ psThreadData->hEventList = 0;
+ PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
+
+ OSFREEMEM(psThreadData);
+
+ PVR_DPF_RETURN;
+}
+
+static PVRSRV_ERROR InitialiseCleanupThread (IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_DPF_ENTERED;
+
+ /* If the TLTEST clean up thread is still running exit early
+ * as we don't want to reinitialise it.
+ */
+ if (gpsCleanUp)
+ {
+ return eError;
+ }
+
+ gpsCleanUp = OSAllocZMem(sizeof(TLT_THREAD));
+ if (!gpsCleanUp)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ eError = OSEventObjectCreate("TLT_CleanUpEL", &gpsCleanUp->hEventList);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(eError);
+ }
+
+ eError = OSEventObjectOpen(gpsCleanUp->hEventList, &gpsCleanUp->hEvent);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(eError);
+ }
+
+ eError = OSThreadCreate(&gpsCleanUp->hThread, "TLT_CleanUpT" , CleanupThread, gpsCleanUp);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(eError);
+ }
+
+ PVR_DPF_RETURN_OK;
+}
+
+
+static PVRSRV_ERROR TLTestCMD_StreamCreate(PVR_TL_TEST_CMD_STREAM_CREATE_IN *psIn1)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TLT_SRCNODE *srcn = 0;
+
+
+ PVR_DPF_ENTERED;
+
+ srcn = OSAllocZMem(sizeof(TLT_SRCNODE));
+ if (!srcn)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ srcn->u.gsCreateIn = *psIn1;
+
+ eError = TLStreamCreate (&srcn->gTLStream, psIn1->pszStreamName,
+ ((OSGetPageSize()*psIn1->uiStreamSizeInPages)) - PVR_TL_TEST_STREAM_BUFFER_REDUCTION,
+ psIn1->uiStreamCreateFlags, IMG_NULL, IMG_NULL);
+ if (eError != PVRSRV_OK)
+ {
+ OSFREEMEM(srcn);
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_ALREADY_EXISTS);
+ }
+ PVR_ASSERT(srcn->gTLStream);
+
+ srcn->psNext = gpsSourceStack;
+ gpsSourceStack = srcn;
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+
+static PVRSRV_ERROR TLTestCMD_StreamClose(PVR_TL_TEST_CMD_STREAM_NAME_IN* psIn1)
+{
+ TLT_SRCNODE *srcn = gpsSourceStack;
+ TLT_SRCNODE **srcn_prev = &gpsSourceStack;
+
+
+ PVR_DPF_ENTERED;
+
+ if (psIn1->pszStreamName[0] != '\0')
+ {
+ /* Find the data source in the stack of sources */
+ for (; srcn != 0; srcn = srcn->psNext)
+ {
+ if (OSStringCompare(srcn->u.gsCreateIn.pszStreamName, psIn1->pszStreamName) == 0)
+ {
+ break;
+ }
+ srcn_prev = &srcn->psNext;
+ }
+ }
+ /* else
+ * Select the data source at the top of the stack.*/
+
+ if (!srcn)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_FOUND);
+ }
+
+ {// If the stream is still referenced, we do not want to close it yet.
+ PTL_STREAM psTmp = (PTL_STREAM) srcn->gTLStream;
+ if ( psTmp->uiRefCount > 1 )
+ {
+ TLStreamClose(srcn->gTLStream);
+ PVR_DPF_RETURN_RC(PVRSRV_OK);
+ }
+ }
+ if (srcn->gStartTimer || srcn->gSourceTimer || srcn->gpuiDataPacket || srcn->gSourceWriteCB)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "TLUtils Warning Unable to close stream %p, %p, %p, %p", srcn->gStartTimer, srcn->gSourceTimer, srcn->gpuiDataPacket, srcn->gSourceWriteCB));
+
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_READY);
+ }
+
+ // Cleanup transport stream
+ TLStreamClose(srcn->gTLStream);
+ srcn->gTLStream = 0;
+
+ *srcn_prev = srcn->psNext;
+ OSFREEMEM(srcn);
+
+ PVR_DPF_RETURN_OK;
+}
+
+static PVRSRV_ERROR TLTestCMD_StreamOpen(PVR_TL_TEST_CMD_STREAM_NAME_IN *psIn1)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_HANDLE hSrcn;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT( psIn1 != IMG_NULL );
+
+ eError = TLStreamOpen (&hSrcn, psIn1->pszStreamName);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_HANDLE_NOT_FOUND);
+ }
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+static PVRSRV_ERROR TLTestCMD_SetPwrState(IMG_UINT32 *uiIn1)
+{
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"TLTestCMD_SetPwrState: Failed to acquire power lock"));
+ return eError;
+ }
+
+ if (*uiIn1 == PVR_TL_TEST_PWR_STATE_ON)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "TLTestCMD_SetPwrState: Turning GPU Power ON."));
+ eError = PVRSRVSetDevicePowerStateKM(0,
+ PVRSRV_DEV_POWER_STATE_ON,
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"TLTestCMD_SetPwrState: Failed to set power state."));
+ return eError;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "TLTestCMD_SetPwrState: Turning GPU Power OFF."));
+ eError = PVRSRVSetDevicePowerStateKM(0,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"TLTestCMD_SetPwrState: Failed to set power state."));
+ return eError;
+ }
+ }
+
+ PVRSRVPowerUnlock();
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR TLTestCMD_GetPwrState(IMG_UINT32 *puiOut1)
+{
+ PVRSRV_DEV_POWER_STATE ePwrState;
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"TLTestCMD_GetPwrState: Failed to acquire power lock"));
+ return eError;
+ }
+
+ PVRSRVGetDevicePowerState(0, &ePwrState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"TLTestCMD_GetPwrState: Could not obtain power state."));
+ return eError;
+ }
+
+ PVRSRVPowerUnlock();
+
+ *puiOut1 = ePwrState;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR TLTestCMD_SetDwtWakeupCounter(IMG_UINT32 *uiIn1)
+{
+ PVRSRVGetPVRSRVData()->ui32DevicesWdWakeupCounter = *uiIn1;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR TLTestCMD_GetDwtWakeupCounter(IMG_UINT32 *puiOut1)
+{
+ *puiOut1 = PVRSRVGetPVRSRVData()->ui32DevicesWdWakeupCounter;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+TLServerTestIoctlKM(IMG_UINT32 uiCmd,
+ IMG_PBYTE uiIn1,
+ IMG_UINT32 uiIn2,
+ IMG_UINT32 *puiOut1,
+ IMG_UINT32 *puiOut2)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVR_DPF_ENTERED;
+
+ PVR_UNREFERENCED_PARAMETER(puiOut2);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "--- Processing Test IOCTL command %d", uiCmd));
+ PVR_DPF((PVR_DBG_MESSAGE, "--- In Arguments: %p, %d", uiIn1, uiIn2));
+
+ switch (uiCmd)
+ {
+ case PVR_TL_TEST_CMD_SOURCE_START:
+ eError = TLTestCMD_SourceStart((PVR_TL_TEST_CMD_SOURCE_START_IN*)uiIn1, SourceWriteFunc);
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_SourceStart");
+ /* Initialise the test clean up thread */
+ if (eError == PVRSRV_OK) //&& (gpsCleanUp == 0))
+ {
+ eError = InitialiseCleanupThread();
+ PVR_LOGR_IF_ERROR(eError, "InitialiseCleanupThread");
+ }
+ break;
+
+ case PVR_TL_TEST_CMD_SOURCE_STOP:
+ eError = TLTestCMD_SourceStop((PVR_TL_TEST_CMD_SOURCE_STOP_IN*)uiIn1);
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_SourceStop");
+ break;
+
+ case PVR_TL_TEST_CMD_SOURCE_START2:
+ eError = TLTestCMD_SourceStart((PVR_TL_TEST_CMD_SOURCE_START_IN*)uiIn1, SourceWriteFunc2);
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_SourceStart");
+ /* Initialise the test clean up thread */
+ if (eError == PVRSRV_OK)//&& (gpsCleanUp == 0))
+ {
+ eError = InitialiseCleanupThread();
+ PVR_LOGR_IF_ERROR(eError, "InitialiseCleanupThread");
+ }
+ break;
+
+ case PVR_TL_TEST_CMD_DEBUG_LEVEL:
+ eError = TLTestCMD_DebugLevel(*(IMG_UINT32*)uiIn1, puiOut1);
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_DebugLevel");
+ break;
+
+ case PVR_TL_TEST_CMD_DUMP_TL_STATE:
+ eError = TLTestCMD_DumpState();
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_DumpState");
+ break;
+
+ case PVR_TL_TEST_CMD_STREAM_CREATE:
+ eError = TLTestCMD_StreamCreate((PVR_TL_TEST_CMD_STREAM_CREATE_IN*)uiIn1);
+ break;
+
+ case PVR_TL_TEST_CMD_STREAM_CLOSE:
+ eError = TLTestCMD_StreamClose((PVR_TL_TEST_CMD_STREAM_NAME_IN*)uiIn1);
+ break;
+
+ case PVR_TL_TEST_CMD_STREAM_OPEN:
+ eError = TLTestCMD_StreamOpen((PVR_TL_TEST_CMD_STREAM_NAME_IN*)uiIn1);
+ break;
+
+ case PVR_TL_TEST_CMD_DUMP_HWPERF_STATE:
+ eError = TLTestCMD_DumpHWPerfState();
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_DumpHWPerfState");
+ break;
+
+ case PVR_TL_TEST_CMD_FLUSH_HWPERF_FWBUF:
+ eError = TLTestCMD_FlushHWPerfFWBuf();
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_FlushHWPerfFWBuf");
+ break;
+
+ case PVR_TL_TEST_CMD_SIGNAL_PE:
+ eError = TLTestCMD_SignalPE((IMG_UINT32*)uiIn1);
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_SignalPE");
+ break;
+
+ case PVR_TL_TEST_CMD_DUMP_PDUMP_STATE:
+ eError = TLTestCMD_DumpPDumpState();
+ PVR_LOG_IF_ERROR(eError, "TLTestCMD_DumpPDumpState");
+ break;
+
+ case PVR_TL_TEST_CMD_SET_PWR_STATE:
+ eError = TLTestCMD_SetPwrState((IMG_UINT32*)uiIn1);
+ break;
+
+ case PVR_TL_TEST_CMD_GET_PWR_STATE:
+ eError = TLTestCMD_GetPwrState(puiOut1);
+ break;
+
+ case PVR_TL_TEST_CMD_SET_DWT_PWR_CHANGE_COUNTER:
+ eError = TLTestCMD_SetDwtWakeupCounter((IMG_UINT32*)uiIn1);
+ break;
+
+ case PVR_TL_TEST_CMD_GET_DWT_PWR_CHANGE_COUNTER:
+ eError = TLTestCMD_GetDwtWakeupCounter(puiOut1);
+ break;
+
+ default:
+ // Do nothing...
+ break;
+ }
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR
+PowMonTestIoctlKM(IMG_UINT32 uiCmd,
+ IMG_UINT32 uiIn1,
+ IMG_UINT32 uiIn2,
+ IMG_UINT32 *puiOut1,
+ IMG_UINT32 *puiOut2)
+{
+ PVR_DPF_ENTERED;
+ PVR_UNREFERENCED_PARAMETER(uiIn2);
+
+ switch (uiCmd)
+ {
+ case 1:
+ {
+ if ((puiOut1 == IMG_NULL) || (puiOut2 == IMG_NULL))
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ /* retrieve last measurement */
+ *puiOut1 = g_PowMonEstimate;
+ *puiOut2 = g_PowMonState;
+ break;
+ }
+ case 2:
+ {
+ if (uiIn1 == 0x0)
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ /* set new delay between measurement requests */
+ g_ui32PowMonLatencyms = uiIn1;
+ break;
+ }
+ default:
+ {
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS);
+ }
+ }
+
+ PVR_DPF_RETURN_RC(PVRSRV_OK);
+}
+
+static PVRSRV_ERROR PowMonEstimateRequest(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 *pui32PowEstValue, IMG_UINT32 *pui32PowEstState)
+{
+ IMG_UINT64 ui64Timer;
+ PVRSRV_ERROR eError;
+
+ /* read timer */
+ ui64Timer = RGXReadHWTimerReg(psDevInfo);
+
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, 0x6320U, 0x1);
+
+ /* send gpio_input req */
+#if !defined (SUPPORT_POWMON_WO_GPIO_PIN)
+ /* potentially dangerous to write directly to this reg */
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_EVENT_STATUS, 0x1000);
+#else
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, 0x140U, 0x00000080);
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MTS_SCHEDULE, 0x20);
+#endif
+
+ /* poll on input req to be cleared */
+
+ /* Poll on RGX_CR_GPIO_OUTPUT_REQ[0] = 1 */
+ eError =
+ PVRSRVPollForValueKM((IMG_UINT32*) (((IMG_UINT8*) psDevInfo->pvRegsBaseKM) + 0x148U), 0x1, 0x1);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PowMonEstimateRequest: Poll gpio output req failed (rc_timer 0x%llx) e:%d",
+ ui64Timer,
+ g_bPowMonEnable));
+ return eError;
+ }
+
+ /* read gpio_output_data */
+ *pui32PowEstState = OSReadHWReg32(psDevInfo->pvRegsBaseKM, 0x140U);
+
+ /* read power estimate result */
+ *pui32PowEstValue = OSReadHWReg32(psDevInfo->pvRegsBaseKM, 0x6328U);
+
+#if !defined (SUPPORT_POWMON_WO_GPIO_PIN)
+ /* Set RGX_CR_EVENT_STATUS[13] at MMADR offset 0x100130 to acknowledge the power estimation status and result have been absorbed. */
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_EVENT_STATUS, 0x2000);
+#else
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, 0x140U, 0x0);
+#endif
+
+ /* POLL on output ack to be cleared */
+ eError =
+#if !defined (SUPPORT_POWMON_WO_GPIO_PIN)
+ PVRSRVPollForValueKM((IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvRegsBaseKM) + RGX_CR_EVENT_STATUS), 0x0, 0x2000);
+#else
+ PVRSRVPollForValueKM((IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvRegsBaseKM) + 0x148U), 0x0, 0x1);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PowMonEstimateRequest: Poll on output ack failed (rgx_timer 0x%llx, value %x, state %d). e:%d",
+ ui64Timer,
+ *pui32PowEstValue,
+ *pui32PowEstState,
+ g_bPowMonEnable));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+static IMG_VOID PowMonTestThread(IMG_PVOID pvData)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = pvData;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32DeviceIndex = psDevInfo->psDeviceNode->sDevId.ui32DeviceIndex;
+
+#if defined(NO_HARDWARE)
+ PVR_LOG(("No Hardware driver has no Power Monitoring testing functionality"));
+ return;
+#endif
+
+#if defined(SUPPORT_POWMON_WO_GPIO_PIN)
+ PVR_LOG(("PowMon with SUPPORT_POWMON_WO_GPIO_PIN"));
+#endif
+
+ PVR_LOG(("PowMonTestThread Wait to start"));
+
+ /* Wait for FW to start */
+ for (;;)
+ {
+ if (psDevInfo->bFirmwareInitialised)
+ {
+ break;
+ }
+
+ if (!g_bPowMonEnable)
+ {
+ PVR_LOG(("PowMonTestThread exit"));
+ return;
+ }
+
+ OSSleepms(500);
+ }
+
+ PVR_LOG(("PowMonTestThread Running"));
+ while (g_bPowMonEnable)
+ {
+ PVRSRV_DEV_POWER_STATE ePowerState;
+
+ OSSleepms(g_ui32PowMonLatencyms);
+
+ eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOG_ERROR(eError, "PVRSRVPowerLock");
+ continue;
+ }
+
+ PVRSRVGetDevicePowerState(ui32DeviceIndex, &ePowerState);
+
+ if (ePowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ /* Request a power monitoring estimate */
+ eError = PowMonEstimateRequest(psDevInfo, &g_PowMonEstimate, &g_PowMonState);
+
+ /* reset on invalid */
+ if (g_PowMonState == 0x3)
+ {
+ g_PowMonEstimate = 0x0;
+ }
+ else if ((g_PowMonState != 0x1) && (g_PowMonState != 0x2))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PowMonEstimateRequest returned an invalid PowMonEstState: %d", g_PowMonState));
+ g_bPowMonEnable = IMG_FALSE;
+ }
+ }
+ else
+ {
+ g_PowMonEstimate = 0x0;
+ g_PowMonState = 0x0;
+
+ }
+
+ PVRSRVPowerUnlock();
+ }
+
+ PVR_LOG(("PowMonTestThread Stopped"));
+}
+
+static PVRSRV_ERROR
+PowMonInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ /* find RGX specific device data */
+ eError = PVRSRVAcquireDeviceDataKM(0, PVRSRV_DEVICE_TYPE_RGX, (IMG_HANDLE*) &psDeviceNode);
+ PVR_LOGR_IF_ERROR(eError, "PVRSRVAcquireDeviceDataKM");
+
+ /* initial state */
+ g_bPowMonEnable = IMG_TRUE;
+ g_ui32PowMonLatencyms = 1;
+ g_PowMonEstimate = 0;
+ g_PowMonState = 0x0;
+
+ /* Create a thread which is used to test power monitoring */
+ eError = OSThreadCreate(&g_hPowerMonitoringThread,
+ "pvr_powmon_test",
+ PowMonTestThread,
+ psDeviceNode->pvDevice);
+ PVR_LOGR_IF_ERROR(eError, "OSThreadCreate");
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PowMonDeinit(IMG_VOID)
+{
+ if (g_hPowerMonitoringThread)
+ {
+ g_bPowMonEnable = IMG_FALSE;
+ OSThreadDestroy(g_hPowerMonitoringThread);
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+TLSourceDeInit (IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVR_TL_TEST_CMD_SOURCE_STOP_IN sStopParams;
+
+ /*
+ * Stop and close all the streams that may have been started, but stopped
+ */
+
+ /* To call TLTestCMD_SourceStop with no stream-name so as to stop the streams in stackwise order of creation */
+ memset (&sStopParams, 0x00, sizeof (sStopParams));
+
+ do
+ {
+ PVR_LOG_IF_ERROR (eError, "TLTestCMD_SourceStop");
+ eError = TLTestCMD_SourceStop (&sStopParams);
+ } while (eError != PVRSRV_ERROR_NOT_FOUND); /* PVRSRV_ERROR_NOT_FOUND implies there are no more streams in sourceStack */
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+TUtilsInit(IMG_VOID)
+{
+
+ PowMonInit();
+
+ PVR_DPF_RETURN_OK;
+}
+
+PVRSRV_ERROR
+TUtilsDeinit(IMG_VOID)
+{
+ PowMonDeinit();
+
+ TLDeInitialiseCleanupTestThread();
+
+ TLSourceDeInit ();
+
+ PVR_DPF_RETURN_OK;
+}
+
+
+#else /* PVR_TESTING_UTILS */
+
+PVRSRV_ERROR
+TLServerTestIoctlKM(IMG_UINT32 uiCmd,
+ IMG_PBYTE uiIn1,
+ IMG_UINT32 uiIn2,
+ IMG_UINT32 *puiOut1,
+ IMG_UINT32 *puiOut2)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_UNREFERENCED_PARAMETER(uiCmd);
+ PVR_UNREFERENCED_PARAMETER(uiIn1);
+ PVR_UNREFERENCED_PARAMETER(uiIn2);
+ PVR_UNREFERENCED_PARAMETER(puiOut1);
+ PVR_UNREFERENCED_PARAMETER(puiOut2);
+
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_SUPPORTED);
+}
+
+PVRSRV_ERROR
+PowMonTestIoctlKM(IMG_UINT32 uiCmd,
+ IMG_UINT32 uiIn1,
+ IMG_UINT32 uiIn2,
+ IMG_UINT32 *puiOut1,
+ IMG_UINT32 *puiOut2)
+{
+ PVR_DPF_ENTERED;
+
+ PVR_UNREFERENCED_PARAMETER(uiCmd);
+ PVR_UNREFERENCED_PARAMETER(uiIn1);
+ PVR_UNREFERENCED_PARAMETER(uiIn2);
+ PVR_UNREFERENCED_PARAMETER(puiOut1);
+ PVR_UNREFERENCED_PARAMETER(puiOut2);
+
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_SUPPORTED);
+}
+#endif
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/debugmisc_server.c b/drivers/gpu/rogue/services/server/devices/rgx/debugmisc_server.c
new file mode 100644
index 000000000000..973b9bce4f6a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/debugmisc_server.c
@@ -0,0 +1,141 @@
+/*************************************************************************/ /*!
+@File
+@Title Debugging and miscellaneous functions server implementation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Kernel services functions for debugging and other
+ miscellaneous 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 "pvrsrv.h"
+#include "pvr_debug.h"
+#include "debugmisc_server.h"
+#include "rgxfwutils.h"
+#include "rgxta3d.h"
+#include "pdump_km.h"
+#include "mmu_common.h"
+#include "devicemem_server.h"
+#include "osfunc.h"
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVDebugMiscSLCSetBypassStateKM(
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 uiFlags,
+ IMG_BOOL bSetBypassed)
+{
+ RGXFWIF_KCCB_CMD sSLCBPCtlCmd;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ sSLCBPCtlCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCBPCTL;
+ sSLCBPCtlCmd.uCmdData.sSLCBPCtlData.bSetBypassed = bSetBypassed;
+ sSLCBPCtlCmd.uCmdData.sSLCBPCtlData.uiFlags = uiFlags;
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sSLCBPCtlCmd,
+ sizeof(sSLCBPCtlCmd),
+ IMG_TRUE);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscSLCSetEnableStateKM: RGXScheduleCommandfailed. Error:%u", eError));
+ }
+ else
+ {
+ /* Wait for the SLC flush to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDebugMiscSLCSetEnableStateKM: Waiting for value aborted with error (%u)", eError));
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscSetFWLogKM(
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32RGXFWLogType)
+{
+ PVRSRV_RGXDEV_INFO* psDevInfo = psDeviceNode->pvDevice;
+
+ /* check log type is valid */
+ if (ui32RGXFWLogType & ~RGXFWIF_LOG_TYPE_MASK)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* set the new log type */
+ psDevInfo->psRGXFWIfTraceBuf->ui32LogType = ui32RGXFWLogType;
+
+ return PVRSRV_OK;
+
+}
+
+static IMG_BOOL
+_RGXDumpFreeListPageList(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ RGX_FREELIST *psFreeList = IMG_CONTAINER_OF(psNode, RGX_FREELIST, sNode);
+
+ RGXDumpFreeListPageList(psFreeList);
+
+ return IMG_TRUE;
+}
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscDumpFreelistPageListKM(
+ PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_RGXDEV_INFO* psDevInfo = psDeviceNode->pvDevice;
+
+ if (dllist_is_empty(&psDevInfo->sFreeListHead))
+ {
+ return PVRSRV_OK;
+ }
+
+ PVR_LOG(("---------------[ Begin Freelist Page List Dump ]------------------"));
+
+ OSLockAcquire(psDevInfo->hLockFreeList);
+ dllist_foreach_node(&psDevInfo->sFreeListHead, _RGXDumpFreeListPageList, IMG_NULL);
+ OSLockRelease(psDevInfo->hLockFreeList);
+
+ PVR_LOG(("----------------[ End Freelist Page List Dump ]-------------------"));
+
+ return PVRSRV_OK;
+
+}
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/debugmisc_server.h b/drivers/gpu/rogue/services/server/devices/rgx/debugmisc_server.h
new file mode 100644
index 000000000000..f6c1cb488238
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/debugmisc_server.h
@@ -0,0 +1,81 @@
+/*************************************************************************/ /*!
+@File
+@Title Debugging and miscellaneous functions server interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Kernel services functions for debugging and other
+ miscellaneous 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(DEBUGMISC_SERVER_H)
+#define DEBUGMISC_SERVER_H
+
+#include <img_defs.h>
+#include <pvrsrv_error.h>
+#include <device.h>
+#include <pmr.h>
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVDebugMiscSLCSetBypassStateKM(
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 uiFlags,
+ IMG_BOOL bSetBypassed);
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVDebugMiscInitFWImageKM(
+ PMR *psFWImgDestPMR,
+ PMR *psFWImgSrcPMR,
+ IMG_UINT64 ui64FWImgLen,
+ PMR *psFWImgSigPMR,
+ IMG_UINT64 ui64FWSigLen);
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscSetFWLogKM(
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32RGXFWLogType);
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXDebugMiscDumpFreelistPageListKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_EXPORT PVRSRV_ERROR
+PowMonTestIoctlKM(IMG_UINT32 uiCmd,
+ IMG_UINT32 uiIn1,
+ IMG_UINT32 uiIn2,
+ IMG_UINT32 *puiOut1,
+ IMG_UINT32 *puiOut2);
+#endif
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxbreakpoint.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxbreakpoint.c
new file mode 100644
index 000000000000..b4e3d7a5482a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxbreakpoint.c
@@ -0,0 +1,269 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX Breakpoint routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX Breakpoint 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 "rgxbreakpoint.h"
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgxmem.h"
+#include "device.h"
+#include "sync_internal.h"
+#include "pdump_km.h"
+#include "pvrsrv.h"
+
+PVRSRV_ERROR PVRSRVRGXSetBreakpointKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hMemCtxPrivData,
+ RGXFWIF_DM eFWDataMaster,
+ IMG_UINT32 ui32BPAddr,
+ IMG_UINT32 ui32HandlerAddr,
+ IMG_UINT32 ui32DataMaster)
+{
+ DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sBPCmd;
+
+ if (psDeviceNode->psDevConfig->bBPSet == IMG_TRUE)
+ return PVRSRV_ERROR_BP_ALREADY_SET;
+
+ sBPCmd.eCmdType = RGXFWIF_KCCB_CMD_BP;
+ sBPCmd.uCmdData.sBPData.ui32BPAddr = ui32BPAddr;
+ sBPCmd.uCmdData.sBPData.ui32HandlerAddr = ui32HandlerAddr;
+ sBPCmd.uCmdData.sBPData.ui32BPDM = ui32DataMaster;
+ sBPCmd.uCmdData.sBPData.bEnable = IMG_TRUE;
+ sBPCmd.uCmdData.sBPData.ui32Flags = RGXFWIF_BPDATA_FLAGS_WRITE;
+
+ RGXSetFirmwareAddress(&sBPCmd.uCmdData.sBPData.psFWMemContext,
+ psFWMemContextMemDesc,
+ 0 ,
+ RFW_FWADDR_NOREF_FLAG);
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ eFWDataMaster,
+ &sBPCmd,
+ sizeof(sBPCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSetBreakpointKM: RGXScheduleCommand failed. Error:%u", eError));
+ return eError;
+ }
+
+ /* Wait for FW to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, eFWDataMaster, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXSetBreakpointKM: Wait for completion aborted with error (%u)", eError));
+ return eError;
+ }
+
+ psDeviceNode->psDevConfig->eBPDM = eFWDataMaster;
+ psDeviceNode->psDevConfig->bBPSet = IMG_TRUE;
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXClearBreakpointKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hMemCtxPrivData)
+{
+ DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sBPCmd;
+ RGXFWIF_DM eDataMaster = psDeviceNode->psDevConfig->eBPDM;
+
+ sBPCmd.eCmdType = RGXFWIF_KCCB_CMD_BP;
+ sBPCmd.uCmdData.sBPData.ui32BPAddr = 0;
+ sBPCmd.uCmdData.sBPData.ui32HandlerAddr = 0;
+ sBPCmd.uCmdData.sBPData.bEnable = IMG_FALSE;
+ sBPCmd.uCmdData.sBPData.ui32Flags = RGXFWIF_BPDATA_FLAGS_WRITE | RGXFWIF_BPDATA_FLAGS_CTL;
+
+ RGXSetFirmwareAddress(&sBPCmd.uCmdData.sBPData.psFWMemContext,
+ psFWMemContextMemDesc,
+ 0 ,
+ RFW_FWADDR_NOREF_FLAG);
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ eDataMaster,
+ &sBPCmd,
+ sizeof(sBPCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXClearBreakpointKM: RGXScheduleCommand failed. Error:%u", eError));
+ return eError;
+ }
+
+ /* Wait for FW to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, eDataMaster, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXClearBreakpointKM: Wait for completion aborted with error (%u)", eError));
+ return eError;
+ }
+
+ psDeviceNode->psDevConfig->bBPSet = IMG_FALSE;
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXEnableBreakpointKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hMemCtxPrivData)
+{
+ DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sBPCmd;
+ RGXFWIF_DM eDataMaster = psDeviceNode->psDevConfig->eBPDM;
+
+ if (psDeviceNode->psDevConfig->bBPSet == IMG_FALSE)
+ return PVRSRV_ERROR_BP_NOT_SET;
+
+ sBPCmd.eCmdType = RGXFWIF_KCCB_CMD_BP;
+ sBPCmd.uCmdData.sBPData.bEnable = IMG_TRUE;
+ sBPCmd.uCmdData.sBPData.ui32Flags = RGXFWIF_BPDATA_FLAGS_CTL;
+
+ RGXSetFirmwareAddress(&sBPCmd.uCmdData.sBPData.psFWMemContext,
+ psFWMemContextMemDesc,
+ 0 ,
+ RFW_FWADDR_NOREF_FLAG);
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ eDataMaster,
+ &sBPCmd,
+ sizeof(sBPCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXEnableBreakpointKM: RGXScheduleCommand failed. Error:%u", eError));
+ return eError;
+ }
+
+ /* Wait for FW to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, eDataMaster, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXEnableBreakpointKM: Wait for completion aborted with error (%u)", eError));
+ return eError;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXDisableBreakpointKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hMemCtxPrivData)
+{
+ DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sBPCmd;
+ RGXFWIF_DM eDataMaster = psDeviceNode->psDevConfig->eBPDM;
+
+ if (psDeviceNode->psDevConfig->bBPSet == IMG_FALSE)
+ return PVRSRV_ERROR_BP_NOT_SET;
+
+ sBPCmd.eCmdType = RGXFWIF_KCCB_CMD_BP;
+ sBPCmd.uCmdData.sBPData.bEnable = IMG_FALSE;
+ sBPCmd.uCmdData.sBPData.ui32Flags = RGXFWIF_BPDATA_FLAGS_CTL;
+
+ RGXSetFirmwareAddress(&sBPCmd.uCmdData.sBPData.psFWMemContext,
+ psFWMemContextMemDesc,
+ 0 ,
+ RFW_FWADDR_NOREF_FLAG);
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ eDataMaster,
+ &sBPCmd,
+ sizeof(sBPCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXDisableBreakpointKM: RGXScheduleCommand failed. Error:%u", eError));
+ return eError;
+ }
+
+ /* Wait for FW to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, eDataMaster, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXDisableBreakpointKM: Wait for completion aborted with error (%u)", eError));
+ return eError;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXOverallocateBPRegistersKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32TempRegs,
+ IMG_UINT32 ui32SharedRegs)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sBPCmd;
+
+ sBPCmd.eCmdType = RGXFWIF_KCCB_CMD_BP;
+ sBPCmd.uCmdData.sBPData.ui32Flags = RGXFWIF_BPDATA_FLAGS_REGS;
+ sBPCmd.uCmdData.sBPData.ui32TempRegs = ui32TempRegs;
+ sBPCmd.uCmdData.sBPData.ui32SharedRegs = ui32SharedRegs;
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sBPCmd,
+ sizeof(sBPCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXOverallocateBPRegistersKM: RGXScheduleCommand failed. Error:%u", eError));
+ return eError;
+ }
+
+ /* Wait for FW to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXOverallocateBPRegistersKM: Wait for completion aborted with error (%u)", eError));
+ return eError;
+ }
+
+ return eError;
+}
+
+
+/******************************************************************************
+ End of file (rgxbreakpoint.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxbreakpoint.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxbreakpoint.h
new file mode 100644
index 000000000000..44792d66fcc3
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxbreakpoint.h
@@ -0,0 +1,136 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX breakpoint functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the RGX breakpoint 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(__RGXBREAKPOINT_H__)
+#define __RGXBREAKPOINT_H__
+
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgx_fwif_km.h"
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXSetBreakpointKM
+
+ @Description
+ Server-side implementation of RGXSetBreakpoint
+
+ @Input psDeviceNode - RGX Device node
+ @Input eDataMaster - Data Master to schedule command for
+ @Input hMemCtxPrivData - memory context private data
+ @Input ui32BPAddr - Address of breakpoint
+ @Input ui32HandlerAddr - Address of breakpoint handler
+ @Input ui32BPCtl - Breakpoint controls
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXSetBreakpointKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hMemCtxPrivData,
+ RGXFWIF_DM eFWDataMaster,
+ IMG_UINT32 ui32BPAddr,
+ IMG_UINT32 ui32HandlerAddr,
+ IMG_UINT32 ui32DataMaster);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXClearBreakpointKM
+
+ @Description
+ Server-side implementation of RGXClearBreakpoint
+
+ @Input psDeviceNode - RGX Device node
+ @Input hMemCtxPrivData - memory context private data
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXClearBreakpointKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hMemCtxPrivData);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXEnableBreakpointKM
+
+ @Description
+ Server-side implementation of RGXEnableBreakpoint
+
+ @Input psDeviceNode - RGX Device node
+ @Input hMemCtxPrivData - memory context private data
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXEnableBreakpointKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hMemCtxPrivData);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXDisableBreakpointKM
+
+ @Description
+ Server-side implementation of RGXDisableBreakpoint
+
+ @Input psDeviceNode - RGX Device node
+ @Input hMemCtxPrivData - memory context private data
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXDisableBreakpointKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hMemCtxPrivData);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXOverallocateBPRegistersKM
+
+ @Description
+ Server-side implementation of RGXOverallocateBPRegisters
+
+ @Input psDeviceNode - RGX Device node
+ @Input ui32TempRegs - Number of temporary registers to overallocate
+ @Input ui32SharedRegs - Number of shared registers to overallocate
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXOverallocateBPRegistersKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32TempRegs,
+ IMG_UINT32 ui32SharedRegs);
+#endif /* __RGXBREAKPOINT_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxccb.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxccb.c
new file mode 100644
index 000000000000..f5dca402000c
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxccb.c
@@ -0,0 +1,1463 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX CCb routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX CCB 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 "pvr_debug.h"
+#include "rgxdevice.h"
+#include "pdump_km.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "rgxfwutils.h"
+#include "osfunc.h"
+#include "rgxccb.h"
+#include "rgx_memallocflags.h"
+#include "devicemem_pdump.h"
+#include "pvr_debug.h"
+#include "dllist.h"
+#include "rgx_fwif_shared.h"
+#include "rgxtimerquery.h"
+#if defined(LINUX)
+#include "trace_events.h"
+#endif
+
+/*
+ * Defines the number of fence updates to record so that future fences in the CCB
+ * can be checked to see if they are already known to be satisfied. The value has
+ * implications for memory and host CPU usage and so should be tuned by using
+ * firmware performance measurements to trade these off against performance gains.
+ *
+ * Must be a power of 2!
+ */
+#define RGX_CCCB_FENCE_UPDATE_LIST_SIZE (64)
+
+
+struct _RGX_CLIENT_CCB_ {
+ volatile RGXFWIF_CCCB_CTL *psClientCCBCtrl; /*!< CPU mapping of the CCB control structure used by the fw */
+ IMG_UINT8 *pui8ClientCCB; /*!< CPU mapping of the CCB */
+ DEVMEM_MEMDESC *psClientCCBMemDesc; /*!< MemDesc for the CCB */
+ DEVMEM_MEMDESC *psClientCCBCtrlMemDesc; /*!< MemDesc for the CCB control */
+ IMG_UINT32 ui32HostWriteOffset; /*!< CCB write offset from the driver side */
+ IMG_UINT32 ui32LastPDumpWriteOffset; /*!< CCB write offset from the last time we submitted a command in capture range */
+ IMG_UINT32 ui32LastROff; /*!< Last CCB Read offset to help detect any CCB wedge */
+ IMG_UINT32 ui32LastWOff; /*!< Last CCB Write offset to help detect any CCB wedge */
+ IMG_UINT32 ui32ByteCount; /*!< Count of the number of bytes written to CCCB */
+ IMG_UINT32 ui32LastByteCount; /*!< Last value of ui32ByteCount to help detect any CCB wedge */
+ IMG_UINT32 ui32Size; /*!< Size of the CCB */
+ DLLIST_NODE sNode; /*!< Node used to store this CCB on the per connection list */
+ PDUMP_CONNECTION_DATA *psPDumpConnectionData; /*!< Pointer to the per connection data in which we reside */
+ IMG_PVOID hTransition; /*!< Handle for Transition callback */
+ IMG_CHAR szName[MAX_CLIENT_CCB_NAME];/*!< Name of this client CCB */
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext; /*!< Parent server common context that this CCB belongs to */
+#if defined REDUNDANT_SYNCS_DEBUG
+ IMG_UINT32 ui32UpdateWriteIndex; /*!< Next position to overwrite in Fence Update List */
+ RGXFWIF_UFO asFenceUpdateList[RGX_CCCB_FENCE_UPDATE_LIST_SIZE]; /*!< Cache of recent updates written in this CCB */
+#endif
+};
+
+static PVRSRV_ERROR _RGXCCBPDumpTransition(IMG_PVOID *pvData, IMG_BOOL bInto, IMG_BOOL bContinuous)
+{
+ RGX_CLIENT_CCB *psClientCCB = (RGX_CLIENT_CCB *) pvData;
+
+ IMG_UINT32 ui32PDumpFlags = bContinuous ? PDUMP_FLAGS_CONTINUOUS:0;
+
+ /*
+ We're about to Transition into capture range and we've submitted
+ new commands since the last time we entered capture range so drain
+ the CCB as required
+ */
+ if (bInto)
+ {
+ volatile RGXFWIF_CCCB_CTL *psCCBCtl = psClientCCB->psClientCCBCtrl;
+ PVRSRV_ERROR eError;
+
+ /*
+ Wait for the FW to catch up (retry will get pushed back out services
+ client where we wait on the event object and try again later)
+ */
+ if (psClientCCB->psClientCCBCtrl->ui32ReadOffset != psClientCCB->ui32HostWriteOffset)
+ {
+ return PVRSRV_ERROR_RETRY;
+ }
+
+ /*
+ We drain whenever capture range is entered. Even if no commands
+ have been issued while where out of capture range we have to wait for
+ operations that we might have issued in the last capture range
+ to finish so the sync prim update that will happen after all the
+ PDumpTransition callbacks have been called doesn't clobber syncs
+ which the FW is currently working on.
+ Although this is suboptimal, while out of capture range for every
+ persistent operation we serialise the PDump script processing and
+ the FW, there is no easy solution.
+ Not all modules that work on syncs register a PDumpTransition and
+ thus we have no way of knowing if we can skip drain and the sync
+ prim dump or not.
+ */
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+ "cCCB(%s@%p): Draining rgxfw_roff == woff (%d)",
+ psClientCCB->szName,
+ psClientCCB,
+ psClientCCB->ui32LastPDumpWriteOffset);
+
+ eError = DevmemPDumpDevmemPol32(psClientCCB->psClientCCBCtrlMemDesc,
+ offsetof(RGXFWIF_CCCB_CTL, ui32ReadOffset),
+ psClientCCB->ui32LastPDumpWriteOffset,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ ui32PDumpFlags);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "_RGXCCBPDumpTransition: problem pdumping POL for cCCBCtl (%d)", eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /*
+ If new command(s) have been written out of capture range then we
+ need to fast forward past uncaptured operations.
+ */
+ if (psClientCCB->ui32LastPDumpWriteOffset != psClientCCB->ui32HostWriteOffset)
+ {
+ /*
+ There are commands that where not captured so after the
+ simulation drain (above) we also need to fast-forward pass
+ those commands so the FW can start with the 1st command
+ which is in the new capture range
+ */
+ psCCBCtl->ui32ReadOffset = psClientCCB->ui32HostWriteOffset;
+ psCCBCtl->ui32DepOffset = psClientCCB->ui32HostWriteOffset;
+ psCCBCtl->ui32WriteOffset = psClientCCB->ui32HostWriteOffset;
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+ "cCCB(%s@%p): Fast-forward from %d to %d",
+ psClientCCB->szName,
+ psClientCCB,
+ psClientCCB->ui32LastPDumpWriteOffset,
+ psClientCCB->ui32HostWriteOffset);
+
+ DevmemPDumpLoadMem(psClientCCB->psClientCCBCtrlMemDesc,
+ 0,
+ sizeof(RGXFWIF_CCCB_CTL),
+ ui32PDumpFlags);
+
+ /*
+ Although we've entered capture range we might not do any work
+ on this CCB so update the ui32LastPDumpWriteOffset to reflect
+ where we got to for next so we start the drain from where we
+ got to last time
+ */
+ psClientCCB->ui32LastPDumpWriteOffset = psClientCCB->ui32HostWriteOffset;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXCreateCCB(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32CCBSizeLog2,
+ CONNECTION_DATA *psConnectionData,
+ const IMG_CHAR *pszName,
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+ RGX_CLIENT_CCB **ppsClientCCB,
+ DEVMEM_MEMDESC **ppsClientCCBMemDesc,
+ DEVMEM_MEMDESC **ppsClientCCBCtrlMemDesc)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_FLAGS_T uiClientCCBMemAllocFlags, uiClientCCBCtlMemAllocFlags;
+ IMG_UINT32 ui32AllocSize = (1U << ui32CCBSizeLog2);
+ RGX_CLIENT_CCB *psClientCCB;
+
+ psClientCCB = OSAllocMem(sizeof(*psClientCCB));
+ if (psClientCCB == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+ psClientCCB->psServerCommonContext = psServerCommonContext;
+
+ uiClientCCBMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;
+
+ uiClientCCBCtlMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;
+
+ PDUMPCOMMENT("Allocate RGXFW cCCB");
+ eError = DevmemFwAllocateExportable(psDeviceNode,
+ ui32AllocSize,
+ uiClientCCBMemAllocFlags,
+ "FirmwareClientCCB",
+ &psClientCCB->psClientCCBMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to allocate RGX client CCB (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto fail_alloc_ccb;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psClientCCB->psClientCCBMemDesc,
+ (IMG_VOID **) &psClientCCB->pui8ClientCCB);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to map RGX client CCB (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto fail_map_ccb;
+ }
+
+ PDUMPCOMMENT("Allocate RGXFW cCCB control");
+ eError = DevmemFwAllocateExportable(psDeviceNode,
+ sizeof(RGXFWIF_CCCB_CTL),
+ uiClientCCBCtlMemAllocFlags,
+ "FirmwareClientCCBControl",
+ &psClientCCB->psClientCCBCtrlMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to allocate RGX client CCB control (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto fail_alloc_ccbctrl;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc,
+ (IMG_VOID **) &psClientCCB->psClientCCBCtrl);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to map RGX client CCB (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto fail_map_ccbctrl;
+ }
+
+ psClientCCB->psClientCCBCtrl->ui32WriteOffset = 0;
+ psClientCCB->psClientCCBCtrl->ui32ReadOffset = 0;
+ psClientCCB->psClientCCBCtrl->ui32DepOffset = 0;
+ psClientCCB->psClientCCBCtrl->ui32WrapMask = ui32AllocSize - 1;
+ OSSNPrintf(psClientCCB->szName, MAX_CLIENT_CCB_NAME, "%s-P%lu-T%lu-%s",
+ pszName,
+ (unsigned long) OSGetCurrentProcessIDKM(),
+ (unsigned long) OSGetCurrentThreadIDKM(),
+ OSGetCurrentProcessNameKM());
+
+ PDUMPCOMMENT("cCCB control");
+ DevmemPDumpLoadMem(psClientCCB->psClientCCBCtrlMemDesc,
+ 0,
+ sizeof(RGXFWIF_CCCB_CTL),
+ PDUMP_FLAGS_CONTINUOUS);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ psClientCCB->ui32HostWriteOffset = 0;
+ psClientCCB->ui32LastPDumpWriteOffset = 0;
+ psClientCCB->ui32Size = ui32AllocSize;
+ psClientCCB->ui32LastROff = ui32AllocSize - 1;
+ psClientCCB->ui32ByteCount = 0;
+ psClientCCB->ui32LastByteCount = 0;
+
+#if defined REDUNDANT_SYNCS_DEBUG
+ psClientCCB->ui32UpdateWriteIndex = 0;
+ OSMemSet(psClientCCB->asFenceUpdateList, 0, sizeof(psClientCCB->asFenceUpdateList));
+#endif
+
+ eError = PDumpRegisterTransitionCallback(psConnectionData->psPDumpConnectionData,
+ _RGXCCBPDumpTransition,
+ psClientCCB,
+ &psClientCCB->hTransition);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_pdumpreg;
+ }
+ /*
+ Note:
+ Due to resman the connection structure could be freed before the client
+ CCB so rather then saving off the connection structure save the PDump
+ specific memory which is refcounted to ensure it's not freed too early
+ */
+ psClientCCB->psPDumpConnectionData = psConnectionData->psPDumpConnectionData;
+ PDUMPCOMMENT("New RGXFW cCCB(%s@%p) created",
+ psClientCCB->szName,
+ psClientCCB);
+
+ *ppsClientCCB = psClientCCB;
+ *ppsClientCCBMemDesc = psClientCCB->psClientCCBMemDesc;
+ *ppsClientCCBCtrlMemDesc = psClientCCB->psClientCCBCtrlMemDesc;
+ return PVRSRV_OK;
+
+fail_pdumpreg:
+ DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc);
+fail_map_ccbctrl:
+ DevmemFwFree(psClientCCB->psClientCCBCtrlMemDesc);
+fail_alloc_ccbctrl:
+ DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBMemDesc);
+fail_map_ccb:
+ DevmemFwFree(psClientCCB->psClientCCBMemDesc);
+fail_alloc_ccb:
+ OSFreeMem(psClientCCB);
+fail_alloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_VOID RGXDestroyCCB(RGX_CLIENT_CCB *psClientCCB)
+{
+ PDumpUnregisterTransitionCallback(psClientCCB->hTransition);
+ DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc);
+ DevmemFwFree(psClientCCB->psClientCCBCtrlMemDesc);
+ DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBMemDesc);
+ DevmemFwFree(psClientCCB->psClientCCBMemDesc);
+ OSFreeMem(psClientCCB);
+}
+
+
+static PVRSRV_ERROR _RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
+ IMG_UINT32 ui32CmdSize,
+ IMG_PVOID *ppvBufferSpace)
+{
+ IMG_UINT32 ui32FreeSpace;
+
+#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);
+ DevmemPDumpCBP(psClientCCB->psClientCCBCtrlMemDesc,
+ offsetof(RGXFWIF_CCCB_CTL, ui32ReadOffset),
+ psClientCCB->ui32HostWriteOffset,
+ ui32CmdSize,
+ psClientCCB->ui32Size);
+#endif
+
+ ui32FreeSpace = GET_CCB_SPACE(psClientCCB->ui32HostWriteOffset,
+ psClientCCB->psClientCCBCtrl->ui32ReadOffset,
+ psClientCCB->ui32Size);
+
+ /* Don't allow all the space to be used */
+ if (ui32FreeSpace > ui32CmdSize)
+ {
+ *ppvBufferSpace = (IMG_PVOID) (psClientCCB->pui8ClientCCB +
+ psClientCCB->ui32HostWriteOffset);
+ return PVRSRV_OK;
+ }
+
+ return PVRSRV_ERROR_RETRY;
+}
+
+/******************************************************************************
+ FUNCTION : RGXAcquireCCB
+
+ PURPOSE : Obtains access to write some commands to a CCB
+
+ PARAMETERS : psClientCCB - The client CCB
+ ui32CmdSize - How much space is required
+ ppvBufferSpace - Pointer to space in the buffer
+ bPDumpContinuous - Should this be PDump continuous?
+
+ RETURNS : PVRSRV_ERROR
+******************************************************************************/
+IMG_INTERNAL PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
+ IMG_UINT32 ui32CmdSize,
+ IMG_PVOID *ppvBufferSpace,
+ IMG_BOOL bPDumpContinuous)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32PDumpFlags = bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS : 0;
+ IMG_BOOL bInCaptureRange;
+ IMG_BOOL bPdumpEnabled;
+
+ PDumpIsCaptureFrameKM(&bInCaptureRange);
+ bPdumpEnabled = (bInCaptureRange || bPDumpContinuous);
+
+ /*
+ 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
+ */
+ if (bPDumpContinuous && !bInCaptureRange)
+ {
+ eError = PDumpTransition(psClientCCB->psPDumpConnectionData, IMG_TRUE, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ /* Check that the CCB can hold this command + padding */
+ if ((ui32CmdSize + PADDING_COMMAND_SIZE + 1) > psClientCCB->ui32Size)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Command size (%d bytes) too big for CCB (%d bytes)\n",
+ ui32CmdSize, psClientCCB->ui32Size));
+ return PVRSRV_ERROR_CMD_TOO_BIG;
+ }
+
+ /*
+ Check we don't overflow the end of the buffer and make sure we have
+ enough for the padding command.
+ */
+ if ((psClientCCB->ui32HostWriteOffset + ui32CmdSize + PADDING_COMMAND_SIZE) >
+ psClientCCB->ui32Size)
+ {
+ RGXFWIF_CCB_CMD_HEADER *psHeader;
+ IMG_VOID *pvHeader;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Remain = psClientCCB->ui32Size - psClientCCB->ui32HostWriteOffset;
+
+ /* We're at the end of the buffer without enough contiguous space */
+ eError = _RGXAcquireCCB(psClientCCB,
+ ui32Remain,
+ &pvHeader);
+ if (eError != PVRSRV_OK)
+ {
+ /*
+ It's possible no commands have been processed in which case as we
+ can fail the padding allocation due to that fact we never allow
+ the client CCB to be full
+ */
+ return eError;
+ }
+ psHeader = pvHeader;
+ psHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_PADDING;
+ psHeader->ui32CmdSize = ui32Remain - sizeof(RGXFWIF_CCB_CMD_HEADER);
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "cCCB(%p): Padding cmd %d", psClientCCB, psHeader->ui32CmdSize);
+ if (bPdumpEnabled)
+ {
+ DevmemPDumpLoadMem(psClientCCB->psClientCCBMemDesc,
+ psClientCCB->ui32HostWriteOffset,
+ ui32Remain,
+ ui32PDumpFlags);
+ }
+
+ UPDATE_CCB_OFFSET(psClientCCB->ui32HostWriteOffset,
+ ui32Remain,
+ psClientCCB->ui32Size);
+ psClientCCB->ui32ByteCount += ui32Remain;
+ }
+
+ return _RGXAcquireCCB(psClientCCB,
+ ui32CmdSize,
+ ppvBufferSpace);
+}
+
+/******************************************************************************
+ FUNCTION : RGXReleaseCCB
+
+ PURPOSE : Release a CCB that we have been writing to.
+
+ PARAMETERS : psDevData - device data
+ psCCB - the CCB
+
+ RETURNS : None
+******************************************************************************/
+IMG_INTERNAL IMG_VOID RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB,
+ IMG_UINT32 ui32CmdSize,
+ IMG_BOOL bPDumpContinuous)
+{
+ IMG_UINT32 ui32PDumpFlags = bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS : 0;
+ IMG_BOOL bInCaptureRange;
+ IMG_BOOL bPdumpEnabled;
+
+ PDumpIsCaptureFrameKM(&bInCaptureRange);
+ bPdumpEnabled = (bInCaptureRange || bPDumpContinuous);
+
+ /* Dump the CCB data */
+ if (bPdumpEnabled)
+ {
+ DevmemPDumpLoadMem(psClientCCB->psClientCCBMemDesc,
+ psClientCCB->ui32HostWriteOffset,
+ ui32CmdSize,
+ ui32PDumpFlags);
+ }
+
+ /*
+ * Check if there have been any fences written that will already be
+ * satistified by a previously written update in this CCB.
+ */
+#if defined REDUNDANT_SYNCS_DEBUG
+ {
+ IMG_UINT8 *pui8BufferStart = (IMG_PVOID)((IMG_UINTPTR_T)psClientCCB->pui8ClientCCB + psClientCCB->ui32HostWriteOffset);
+ IMG_UINT8 *pui8BufferEnd = (IMG_PVOID)((IMG_UINTPTR_T)psClientCCB->pui8ClientCCB + psClientCCB->ui32HostWriteOffset + ui32CmdSize);
+
+ /* Walk through the commands in this section of CCB being released... */
+ while (pui8BufferStart < pui8BufferEnd)
+ {
+ RGXFWIF_CCB_CMD_HEADER *psCmdHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8BufferStart;
+
+ if (psCmdHeader->eCmdType == RGXFWIF_CCB_CMD_TYPE_UPDATE)
+ {
+ /* If an UPDATE then record the value incase a later fence depends on it. */
+ IMG_UINT32 ui32NumUpdates = psCmdHeader->ui32CmdSize / sizeof(RGXFWIF_UFO);
+ IMG_UINT32 i;
+
+ for (i = 0; i < ui32NumUpdates; i++)
+ {
+ RGXFWIF_UFO *psUFOPtr = ((RGXFWIF_UFO*)(pui8BufferStart + sizeof(RGXFWIF_CCB_CMD_HEADER))) + i;
+
+ psClientCCB->asFenceUpdateList[psClientCCB->ui32UpdateWriteIndex++] = *psUFOPtr;
+ psClientCCB->ui32UpdateWriteIndex &= (RGX_CCCB_FENCE_UPDATE_LIST_SIZE-1);
+ }
+ }
+ else if (psCmdHeader->eCmdType == RGXFWIF_CCB_CMD_TYPE_FENCE)
+ {
+ IMG_UINT32 ui32NumFences = psCmdHeader->ui32CmdSize / sizeof(RGXFWIF_UFO);
+ IMG_UINT32 i;
+
+ for (i = 0; i < ui32NumFences; i++)
+ {
+ RGXFWIF_UFO *psUFOPtr = ((RGXFWIF_UFO*)(pui8BufferStart + sizeof(RGXFWIF_CCB_CMD_HEADER))) + i;
+ IMG_UINT32 ui32UpdateIndex;
+
+ /* Check recently queued updates to see if this fence will be satisfied by the time it is checked. */
+ for (ui32UpdateIndex = 0; ui32UpdateIndex < RGX_CCCB_FENCE_UPDATE_LIST_SIZE; ui32UpdateIndex++)
+ {
+ RGXFWIF_UFO *psUpdatePtr = &psClientCCB->asFenceUpdateList[ui32UpdateIndex];
+
+ if (psUFOPtr->puiAddrUFO.ui32Addr == psUpdatePtr->puiAddrUFO.ui32Addr &&
+ psUFOPtr->ui32Value == psUpdatePtr->ui32Value)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Redundant fence found in cCCB(%p) - 0x%x -> 0x%x",
+ psClientCCB, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value));
+ //psUFOPtr->puiAddrUFO.ui32Addr = 0;
+ break;
+ }
+ }
+ }
+ }
+ else if (psCmdHeader->eCmdType == RGXFWIF_CCB_CMD_TYPE_FENCE_PR)
+ {
+ IMG_UINT32 ui32NumFences = psCmdHeader->ui32CmdSize / sizeof(RGXFWIF_UFO);
+ IMG_UINT32 i;
+
+ for (i = 0; i < ui32NumFences; i++)
+ {
+ RGXFWIF_UFO *psUFOPtr = ((RGXFWIF_UFO*)(pui8BufferStart + sizeof(RGXFWIF_CCB_CMD_HEADER))) + i;
+ IMG_UINT32 ui32UpdateIndex;
+
+ /* Check recently queued updates to see if this fence will be satisfied by the time it is checked. */
+ for (ui32UpdateIndex = 0; ui32UpdateIndex < RGX_CCCB_FENCE_UPDATE_LIST_SIZE; ui32UpdateIndex++)
+ {
+ RGXFWIF_UFO *psUpdatePtr = &psClientCCB->asFenceUpdateList[ui32UpdateIndex];
+
+ /*
+ * The PR-fence will be met if the update value is >= the required fence value. E.g.
+ * the difference between the update value and fence value is positive.
+ */
+ if (psUFOPtr->puiAddrUFO.ui32Addr == psUpdatePtr->puiAddrUFO.ui32Addr &&
+ ((psUpdatePtr->ui32Value - psUFOPtr->ui32Value) & (1U << 31)) == 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Redundant PR fence found in cCCB(%p) - 0x%x -> 0x%x",
+ psClientCCB, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value));
+ //psUFOPtr->puiAddrUFO.ui32Addr = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Move to the next command in this section of CCB being released... */
+ pui8BufferStart += sizeof(RGXFWIF_CCB_CMD_HEADER) + psCmdHeader->ui32CmdSize;
+ }
+ }
+#endif /* REDUNDANT_SYNCS_DEBUG */
+
+ /*
+ * Update the CCB write offset.
+ */
+ UPDATE_CCB_OFFSET(psClientCCB->ui32HostWriteOffset,
+ ui32CmdSize,
+ psClientCCB->ui32Size);
+ psClientCCB->ui32ByteCount += ui32CmdSize;
+
+ /*
+ 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
+ */
+ if (bPDumpContinuous && !bInCaptureRange)
+ {
+ PVRSRV_ERROR eError;
+
+ /* Only Transitioning into capture range can cause an error */
+ eError = PDumpTransition(psClientCCB->psPDumpConnectionData, IMG_FALSE, IMG_TRUE);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+
+ if (bPdumpEnabled)
+ {
+ /* Update the PDump write offset to show we PDumped this command */
+ psClientCCB->ui32LastPDumpWriteOffset = psClientCCB->ui32HostWriteOffset;
+ }
+
+#if defined(NO_HARDWARE)
+ /*
+ The firmware is not running, it cannot update these; we do here instead.
+ */
+ psClientCCB->psClientCCBCtrl->ui32ReadOffset = psClientCCB->ui32HostWriteOffset;
+ psClientCCB->psClientCCBCtrl->ui32DepOffset = psClientCCB->ui32HostWriteOffset;
+#endif
+}
+
+IMG_UINT32 RGXGetHostWriteOffsetCCB(RGX_CLIENT_CCB *psClientCCB)
+{
+ return psClientCCB->ui32HostWriteOffset;
+}
+
+#define SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL PVR_DBG_ERROR
+#define CHECK_COMMAND(cmd, fenceupdate) \
+ case RGXFWIF_CCB_CMD_TYPE_##cmd: \
+ PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, #cmd " command (%d bytes)", psHeader->ui32CmdSize)); \
+ bFenceUpdate = fenceupdate; \
+ break
+
+static IMG_VOID _RGXClientCCBDumpCommands(RGX_CLIENT_CCB *psClientCCB,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32ByteCount)
+{
+#if defined(SUPPORT_DUMP_CLIENT_CCB_COMMANDS)
+ IMG_UINT8 *pui8Ptr = psClientCCB->pui8ClientCCB + ui32Offset;
+ IMG_UINT32 ui32ConsumeSize = ui32ByteCount;
+
+ while (ui32ConsumeSize)
+ {
+ RGXFWIF_CCB_CMD_HEADER *psHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8Ptr;
+ IMG_BOOL bFenceUpdate = IMG_FALSE;
+
+ PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "@offset 0x%08x", pui8Ptr - psClientCCB->pui8ClientCCB));
+ switch(psHeader->eCmdType)
+ {
+ CHECK_COMMAND(TA, IMG_FALSE);
+ CHECK_COMMAND(3D, IMG_FALSE);
+ CHECK_COMMAND(CDM, IMG_FALSE);
+ CHECK_COMMAND(TQ_3D, IMG_FALSE);
+ CHECK_COMMAND(TQ_2D, IMG_FALSE);
+ CHECK_COMMAND(3D_PR, IMG_FALSE);
+ CHECK_COMMAND(NULL, IMG_FALSE);
+ CHECK_COMMAND(SHG, IMG_FALSE);
+ CHECK_COMMAND(RTU, IMG_FALSE);
+ CHECK_COMMAND(RTU_FC, IMG_FALSE);
+ CHECK_COMMAND(PRE_TIMESTAMP, IMG_FALSE);
+ CHECK_COMMAND(POST_TIMESTAMP, IMG_FALSE);
+ CHECK_COMMAND(FENCE, IMG_TRUE);
+ CHECK_COMMAND(UPDATE, IMG_TRUE);
+ CHECK_COMMAND(RMW_UPDATE, IMG_TRUE);
+ CHECK_COMMAND(FENCE_PR, IMG_TRUE);
+ CHECK_COMMAND(PADDING, IMG_FALSE);
+ default:
+ PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "Unknown command!"));
+ break;
+ }
+ pui8Ptr += sizeof(*psHeader);
+ if (bFenceUpdate)
+ {
+ IMG_UINT32 j;
+ RGXFWIF_UFO *psUFOPtr = (RGXFWIF_UFO *) pui8Ptr;
+ for (j=0;j<psHeader->ui32CmdSize/sizeof(RGXFWIF_UFO);j++)
+ {
+ PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "Addr = 0x%08x, value = 0x%08x",
+ psUFOPtr[j].puiAddrUFO.ui32Addr, psUFOPtr[j].ui32Value));
+ }
+ }
+ else
+ {
+ IMG_UINT32 *pui32Ptr = (IMG_UINT32 *) pui8Ptr;
+ IMG_UINT32 ui32Remain = psHeader->ui32CmdSize/sizeof(IMG_UINT32);
+ while(ui32Remain)
+ {
+ if (ui32Remain >= 4)
+ {
+ PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "0x%08x 0x%08x 0x%08x 0x%08x",
+ pui32Ptr[0], pui32Ptr[1], pui32Ptr[2], pui32Ptr[3]));
+ pui32Ptr += 4;
+ ui32Remain -= 4;
+ }
+ if (ui32Remain == 3)
+ {
+ PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "0x%08x 0x%08x 0x%08x",
+ pui32Ptr[0], pui32Ptr[1], pui32Ptr[2]));
+ pui32Ptr += 3;
+ ui32Remain -= 3;
+ }
+ if (ui32Remain == 2)
+ {
+ PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "0x%08x 0x%08x",
+ pui32Ptr[0], pui32Ptr[1]));
+ pui32Ptr += 2;
+ ui32Remain -= 2;
+ }
+ if (ui32Remain == 1)
+ {
+ PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "0x%08x",
+ pui32Ptr[0]));
+ pui32Ptr += 1;
+ ui32Remain -= 1;
+ }
+ }
+ }
+ pui8Ptr += psHeader->ui32CmdSize;
+ ui32ConsumeSize -= sizeof(*psHeader) + psHeader->ui32CmdSize;
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(psClientCCB);
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteCount);
+#endif
+}
+
+/*
+ Workout how much space this command will require
+*/
+PVRSRV_ERROR RGXCmdHelperInitCmdCCB(RGX_CLIENT_CCB *psClientCCB,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiFenceUFOAddress,
+ IMG_UINT32 *paui32FenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiUpdateUFOAddress,
+ IMG_UINT32 *paui32UpdateValue,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_UINT32 *paui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **papsServerSyncs,
+ IMG_UINT32 ui32CmdSize,
+ IMG_PBYTE pui8DMCmd,
+ PRGXFWIF_TIMESTAMP_ADDR * ppPreAddr,
+ PRGXFWIF_TIMESTAMP_ADDR * ppPostAddr,
+ PRGXFWIF_UFO_ADDR * ppRMWUFOAddr,
+ RGXFWIF_CCB_CMD_TYPE eType,
+ IMG_BOOL bPDumpContinuous,
+ IMG_CHAR *pszCommandName,
+ RGX_CCB_CMD_HELPER_DATA *psCmdHelperData)
+{
+ IMG_UINT32 ui32FenceCount;
+ IMG_UINT32 ui32UpdateCount;
+ IMG_UINT32 i;
+
+ /* Save the data we require in the submit call */
+ psCmdHelperData->psClientCCB = psClientCCB;
+ psCmdHelperData->bPDumpContinuous = bPDumpContinuous;
+ psCmdHelperData->pszCommandName = pszCommandName;
+
+ /* Client sync data */
+ psCmdHelperData->ui32ClientFenceCount = ui32ClientFenceCount;
+ psCmdHelperData->pauiFenceUFOAddress = pauiFenceUFOAddress;
+ psCmdHelperData->paui32FenceValue = paui32FenceValue;
+ psCmdHelperData->ui32ClientUpdateCount = ui32ClientUpdateCount;
+ psCmdHelperData->pauiUpdateUFOAddress = pauiUpdateUFOAddress;
+ psCmdHelperData->paui32UpdateValue = paui32UpdateValue;
+
+ /* Server sync data */
+ psCmdHelperData->ui32ServerSyncCount = ui32ServerSyncCount;
+ psCmdHelperData->paui32ServerSyncFlags = paui32ServerSyncFlags;
+ psCmdHelperData->papsServerSyncs = papsServerSyncs;
+
+ /* Command data */
+ psCmdHelperData->ui32CmdSize = ui32CmdSize;
+ psCmdHelperData->pui8DMCmd = pui8DMCmd;
+ psCmdHelperData->eType = eType;
+
+ PDUMPCOMMENTWITHFLAGS((bPDumpContinuous) ? PDUMP_FLAGS_CONTINUOUS : 0,
+ "%s Command Server Init on FWCtx %08x", pszCommandName,
+ FWCommonContextGetFWAddress(psClientCCB->psServerCommonContext).ui32Addr);
+
+ /* Init the generated data members */
+ psCmdHelperData->ui32ServerFenceCount = 0;
+ psCmdHelperData->ui32ServerUpdateCount = 0;
+ psCmdHelperData->ui32PreTimeStampCmdSize = 0;
+ psCmdHelperData->ui32PostTimeStampCmdSize = 0;
+ psCmdHelperData->ui32RMWUFOCmdSize = 0;
+
+
+ if (ppPreAddr && (ppPreAddr->ui32Addr != 0))
+ {
+
+ psCmdHelperData->pPreTimestampAddr = * ppPreAddr;
+ psCmdHelperData->ui32PreTimeStampCmdSize = sizeof(RGXFWIF_CCB_CMD_HEADER)
+ + ((sizeof(RGXFWIF_DEV_VIRTADDR) + RGXFWIF_FWALLOC_ALIGN - 1) & ~(RGXFWIF_FWALLOC_ALIGN - 1));
+ }
+
+ if (ppPostAddr && (ppPostAddr->ui32Addr != 0))
+ {
+ psCmdHelperData->pPostTimestampAddr = * ppPostAddr;
+ psCmdHelperData->ui32PostTimeStampCmdSize = sizeof(RGXFWIF_CCB_CMD_HEADER)
+ + ((sizeof(RGXFWIF_DEV_VIRTADDR) + RGXFWIF_FWALLOC_ALIGN - 1) & ~(RGXFWIF_FWALLOC_ALIGN - 1));
+ }
+
+ if (ppRMWUFOAddr && (ppRMWUFOAddr->ui32Addr != 0))
+ {
+ psCmdHelperData->pRMWUFOAddr = * ppRMWUFOAddr;
+ psCmdHelperData->ui32RMWUFOCmdSize = sizeof(RGXFWIF_CCB_CMD_HEADER) + sizeof(RGXFWIF_UFO);
+ }
+
+
+ /* Workout how many fence and update's this command will have */
+ for (i = 0; i < ui32ServerSyncCount; i++)
+ {
+ if (paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)
+ {
+ /* Server syncs must fence */
+ psCmdHelperData->ui32ServerFenceCount++;
+ }
+ if (paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)
+ {
+ psCmdHelperData->ui32ServerUpdateCount++;
+ }
+ }
+
+ /* Total fence command size (header plus command data) */
+ ui32FenceCount = ui32ClientFenceCount + psCmdHelperData->ui32ServerFenceCount;
+ if (ui32FenceCount)
+ {
+ psCmdHelperData->ui32FenceCmdSize = RGX_CCB_FWALLOC_ALIGN((ui32FenceCount * sizeof(RGXFWIF_UFO)) +
+ sizeof(RGXFWIF_CCB_CMD_HEADER));
+ }
+ else
+ {
+ psCmdHelperData->ui32FenceCmdSize = 0;
+ }
+
+ /* Total DM command size (header plus command data) */
+ psCmdHelperData->ui32DMCmdSize = RGX_CCB_FWALLOC_ALIGN(ui32CmdSize +
+ sizeof(RGXFWIF_CCB_CMD_HEADER));
+
+ /* Total update command size (header plus command data) */
+ ui32UpdateCount = ui32ClientUpdateCount + psCmdHelperData->ui32ServerUpdateCount;
+ if (ui32UpdateCount)
+ {
+ psCmdHelperData->ui32UpdateCmdSize = RGX_CCB_FWALLOC_ALIGN((ui32UpdateCount * sizeof(RGXFWIF_UFO)) +
+ sizeof(RGXFWIF_CCB_CMD_HEADER));
+ }
+ else
+ {
+ psCmdHelperData->ui32UpdateCmdSize = 0;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+/*
+ Reserve space in the CCB and fill in the command and client sync data
+*/
+PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
+ RGX_CCB_CMD_HELPER_DATA *asCmdHelperData,
+ IMG_BOOL *pbKickRequired)
+{
+ IMG_UINT32 ui32BeforeWOff = asCmdHelperData[0].psClientCCB->ui32HostWriteOffset;
+ IMG_UINT32 ui32AllocSize = 0;
+ IMG_UINT32 i;
+ IMG_UINT8 *pui8StartPtr;
+ PVRSRV_ERROR eError;
+
+ *pbKickRequired = IMG_FALSE;
+
+ /*
+ Workout how much space we need for all the command(s)
+ */
+ ui32AllocSize = RGXCmdHelperGetCommandSize(ui32CmdCount, asCmdHelperData);
+
+
+ for (i = 0; i < ui32CmdCount; i++)
+ {
+ if (asCmdHelperData[0].bPDumpContinuous != asCmdHelperData[i].bPDumpContinuous)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PDump continuous is not consistent (%s != %s) for command %d",
+ __FUNCTION__,
+ asCmdHelperData[0].bPDumpContinuous?"IMG_TRUE":"IMG_FALSE",
+ asCmdHelperData[i].bPDumpContinuous?"IMG_TRUE":"IMG_FALSE",
+ ui32CmdCount));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ /*
+ Acquire space in the CCB for all the command(s).
+ */
+ eError = RGXAcquireCCB(asCmdHelperData[0].psClientCCB,
+ ui32AllocSize,
+ (IMG_PVOID *)&pui8StartPtr,
+ asCmdHelperData[0].bPDumpContinuous);
+ if (eError != PVRSRV_OK)
+ {
+ /* Failed so bail out and allow the client side to retry */
+ if (asCmdHelperData[0].psClientCCB->ui32HostWriteOffset != ui32BeforeWOff)
+ {
+ *pbKickRequired = IMG_TRUE;
+ }
+ return eError;
+ }
+
+
+
+ /*
+ For each command fill in the fence, DM, and update command
+
+ Note:
+ We only fill in the client fences here, the server fences (and updates)
+ will be filled in together at the end. This is because we might fail the
+ kernel CCB alloc and would then have to rollback the server syncs if
+ we took the operation here
+ */
+ for (i = 0; i < ui32CmdCount; i++)
+ {
+ RGX_CCB_CMD_HELPER_DATA *psCmdHelperData = & asCmdHelperData[i];
+ IMG_UINT8 *pui8CmdPtr;
+ IMG_UINT8 *pui8ServerFenceStart = 0;
+ IMG_UINT8 *pui8ServerUpdateStart = 0;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CtxAddr = FWCommonContextGetFWAddress(asCmdHelperData->psClientCCB->psServerCommonContext).ui32Addr;
+ IMG_UINT32 ui32CcbWoff = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(asCmdHelperData->psClientCCB->psServerCommonContext));
+#endif
+
+ 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);
+ }
+
+
+
+ /*
+ Create the fence command.
+ */
+ if (psCmdHelperData->ui32FenceCmdSize)
+ {
+ RGXFWIF_CCB_CMD_HEADER *psHeader;
+ IMG_UINT k;
+
+ /* Fences are at the start of the command */
+ pui8CmdPtr = pui8StartPtr;
+
+ psHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8CmdPtr;
+ psHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_FENCE;
+ psHeader->ui32CmdSize = psCmdHelperData->ui32FenceCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER);
+ pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER);
+
+ /* Fill in the client fences */
+ for (k = 0; k < psCmdHelperData->ui32ClientFenceCount; k++)
+ {
+ RGXFWIF_UFO *psUFOPtr = (RGXFWIF_UFO *) pui8CmdPtr;
+
+ psUFOPtr->puiAddrUFO = psCmdHelperData->pauiFenceUFOAddress[k];
+ psUFOPtr->ui32Value = psCmdHelperData->paui32FenceValue[k];
+ pui8CmdPtr += sizeof(RGXFWIF_UFO);
+
+#if defined SYNC_COMMAND_DEBUG
+ 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);
+
+
+ }
+ pui8ServerFenceStart = pui8CmdPtr;
+ }
+
+ /* jump over the Server fences */
+ pui8CmdPtr = pui8StartPtr + psCmdHelperData->ui32FenceCmdSize;
+
+
+ /*
+ Create the pre DM timestamp commands. Pre and Post timestamp commands are supposed to
+ sandwich the DM cmd. The padding code with the CCB wrap upsets the FW if we don't have
+ the task type bit cleared for POST_TIMESTAMPs. That's why we have 2 different cmd types.
+ */
+ if (psCmdHelperData->ui32PreTimeStampCmdSize != 0)
+ {
+ RGXWriteTimestampCommand(& pui8CmdPtr,
+ RGXFWIF_CCB_CMD_TYPE_PRE_TIMESTAMP,
+ psCmdHelperData->pPreTimestampAddr);
+ }
+
+ /*
+ Create the DM command
+ */
+ if (psCmdHelperData->ui32DMCmdSize)
+ {
+ RGXFWIF_CCB_CMD_HEADER *psHeader;
+
+ psHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8CmdPtr;
+ psHeader->eCmdType = psCmdHelperData->eType;
+ psHeader->ui32CmdSize = psCmdHelperData->ui32DMCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER);
+
+
+
+ pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER);
+
+
+ OSMemCopy(pui8CmdPtr, psCmdHelperData->pui8DMCmd, psCmdHelperData->ui32CmdSize);
+ pui8CmdPtr += psCmdHelperData->ui32CmdSize;
+ }
+
+
+
+ if (psCmdHelperData->ui32PostTimeStampCmdSize != 0)
+ {
+ RGXWriteTimestampCommand(& pui8CmdPtr,
+ RGXFWIF_CCB_CMD_TYPE_POST_TIMESTAMP,
+ psCmdHelperData->pPostTimestampAddr);
+ }
+
+
+ if (psCmdHelperData->ui32RMWUFOCmdSize != 0)
+ {
+ RGXFWIF_CCB_CMD_HEADER * psHeader;
+ RGXFWIF_UFO * psUFO;
+
+ psHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8CmdPtr;
+ psHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_RMW_UPDATE;
+ psHeader->ui32CmdSize = psCmdHelperData->ui32RMWUFOCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER);
+ pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER);
+
+ psUFO = (RGXFWIF_UFO *) pui8CmdPtr;
+ psUFO->puiAddrUFO = psCmdHelperData->pRMWUFOAddr;
+
+ pui8CmdPtr += sizeof(RGXFWIF_UFO);
+ }
+
+
+ /*
+ Create the update command.
+
+ Note:
+ We only fill in the client updates here, the server updates (and fences)
+ will be filled in together at the end
+ */
+ if (psCmdHelperData->ui32UpdateCmdSize)
+ {
+ RGXFWIF_CCB_CMD_HEADER *psHeader;
+ IMG_UINT k;
+
+ psHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8CmdPtr;
+ psHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_UPDATE;
+ psHeader->ui32CmdSize = psCmdHelperData->ui32UpdateCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER);
+ pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER);
+
+ /* Fill in the client updates */
+ for (k = 0; k < psCmdHelperData->ui32ClientUpdateCount; k++)
+ {
+ RGXFWIF_UFO *psUFOPtr = (RGXFWIF_UFO *) pui8CmdPtr;
+
+ psUFOPtr->puiAddrUFO = psCmdHelperData->pauiUpdateUFOAddress[k];
+ psUFOPtr->ui32Value = psCmdHelperData->paui32UpdateValue[k];
+ pui8CmdPtr += sizeof(RGXFWIF_UFO);
+
+#if defined SYNC_COMMAND_DEBUG
+ 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);
+
+ }
+ pui8ServerUpdateStart = pui8CmdPtr;
+ }
+
+ /* Save the server sync fence & update offsets for submit time */
+ psCmdHelperData->pui8ServerFenceStart = pui8ServerFenceStart;
+ psCmdHelperData->pui8ServerUpdateStart = pui8ServerUpdateStart;
+
+ /* Save start for sanity checking at submit time */
+ psCmdHelperData->pui8StartPtr = pui8StartPtr;
+
+ /* Set the start pointer for the next iteration around the loop */
+ pui8StartPtr +=
+ psCmdHelperData->ui32FenceCmdSize +
+ psCmdHelperData->ui32PreTimeStampCmdSize +
+ psCmdHelperData->ui32DMCmdSize +
+ psCmdHelperData->ui32PostTimeStampCmdSize +
+ psCmdHelperData->ui32RMWUFOCmdSize +
+ psCmdHelperData->ui32UpdateCmdSize;
+
+ 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);
+ }
+ else
+ {
+ PDUMPCOMMENT("No %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes",
+ psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff);
+ }
+ }
+
+ *pbKickRequired = IMG_TRUE;
+ return PVRSRV_OK;
+}
+
+/*
+ Fill in the server syncs data and release the CCB space
+*/
+IMG_VOID RGXCmdHelperReleaseCmdCCB(IMG_UINT32 ui32CmdCount,
+ RGX_CCB_CMD_HELPER_DATA *asCmdHelperData,
+ const IMG_CHAR *pcszDMName,
+ IMG_UINT32 ui32CtxAddr)
+{
+ IMG_UINT32 ui32AllocSize = 0;
+ IMG_UINT32 i;
+
+ /*
+ Workout how much space we need for all the command(s)
+ */
+ ui32AllocSize = RGXCmdHelperGetCommandSize(ui32CmdCount, asCmdHelperData);
+
+ /*
+ For each command fill in the server sync info
+ */
+ for (i=0;i<ui32CmdCount;i++)
+ {
+ RGX_CCB_CMD_HELPER_DATA *psCmdHelperData = &asCmdHelperData[i];
+ IMG_UINT8 *pui8ServerFenceStart = psCmdHelperData->pui8ServerFenceStart;
+ IMG_UINT8 *pui8ServerUpdateStart = psCmdHelperData->pui8ServerUpdateStart;
+ IMG_UINT32 j;
+
+ /* Now fill in the server fence and updates together */
+ for (j = 0; j < psCmdHelperData->ui32ServerSyncCount; j++)
+ {
+ RGXFWIF_UFO *psUFOPtr;
+ IMG_UINT32 ui32UpdateValue;
+ IMG_UINT32 ui32FenceValue;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bFence = ((psCmdHelperData->paui32ServerSyncFlags[j] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)!=0)?IMG_TRUE:IMG_FALSE;
+ IMG_BOOL bUpdate = ((psCmdHelperData->paui32ServerSyncFlags[j] & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)!=0)?IMG_TRUE:IMG_FALSE;
+
+ eError = PVRSRVServerSyncQueueHWOpKM(psCmdHelperData->papsServerSyncs[j],
+ bUpdate,
+ &ui32FenceValue,
+ &ui32UpdateValue);
+ /* This function can't fail */
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /*
+ As server syncs always fence (we have a check in RGXCmcdHelperInitCmdCCB
+ which ensures the client is playing ball) the filling in of the fence
+ is unconditional.
+ */
+ if (bFence)
+ {
+ PVR_ASSERT(pui8ServerFenceStart != 0);
+
+ psUFOPtr = (RGXFWIF_UFO *) pui8ServerFenceStart;
+ psUFOPtr->puiAddrUFO.ui32Addr = ServerSyncGetFWAddr(psCmdHelperData->papsServerSyncs[j]);
+ psUFOPtr->ui32Value = ui32FenceValue;
+ pui8ServerFenceStart += sizeof(RGXFWIF_UFO);
+
+#if defined(LINUX)
+ trace_rogue_fence_checks(pcszDMName,
+ ui32CtxAddr,
+ psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
+ 1,
+ &psUFOPtr->puiAddrUFO,
+ &psUFOPtr->ui32Value);
+#endif
+ }
+
+ /* If there is an update then fill that in as well */
+ if (bUpdate)
+ {
+ PVR_ASSERT(pui8ServerUpdateStart != 0);
+
+ psUFOPtr = (RGXFWIF_UFO *) pui8ServerUpdateStart;
+ psUFOPtr->puiAddrUFO.ui32Addr = ServerSyncGetFWAddr(psCmdHelperData->papsServerSyncs[j]);
+ psUFOPtr->ui32Value = ui32UpdateValue;
+ pui8ServerUpdateStart += sizeof(RGXFWIF_UFO);
+
+#if defined(LINUX)
+ trace_rogue_fence_updates(pcszDMName,
+ ui32CtxAddr,
+ psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
+ 1,
+ &psUFOPtr->puiAddrUFO,
+ &psUFOPtr->ui32Value);
+#endif
+
+#if defined(NO_HARDWARE)
+ /*
+ There is no FW so the host has to do any Sync updates
+ (client sync updates are done in the client
+ */
+ PVRSRVServerSyncPrimSetKM(psCmdHelperData->papsServerSyncs[j], ui32UpdateValue);
+#endif
+ }
+ }
+
+#if defined(LINUX)
+ trace_rogue_fence_checks(pcszDMName,
+ ui32CtxAddr,
+ psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
+ psCmdHelperData->ui32ClientFenceCount,
+ psCmdHelperData->pauiFenceUFOAddress,
+ psCmdHelperData->paui32FenceValue);
+ trace_rogue_fence_updates(pcszDMName,
+ ui32CtxAddr,
+ psCmdHelperData->psClientCCB->ui32HostWriteOffset + ui32AllocSize,
+ psCmdHelperData->ui32ClientUpdateCount,
+ psCmdHelperData->pauiUpdateUFOAddress,
+ psCmdHelperData->paui32UpdateValue);
+#endif
+
+ if (psCmdHelperData->ui32ServerSyncCount)
+ {
+ /*
+ Do some sanity checks to ensure we did the point math right
+ */
+ if (pui8ServerFenceStart != 0)
+ {
+ PVR_ASSERT(pui8ServerFenceStart ==
+ (psCmdHelperData->pui8StartPtr +
+ psCmdHelperData->ui32FenceCmdSize));
+ }
+
+ if (pui8ServerUpdateStart != 0)
+ {
+ PVR_ASSERT(pui8ServerUpdateStart ==
+ psCmdHelperData->pui8StartPtr +
+ psCmdHelperData->ui32FenceCmdSize +
+ psCmdHelperData->ui32PreTimeStampCmdSize +
+ psCmdHelperData->ui32DMCmdSize +
+ psCmdHelperData->ui32RMWUFOCmdSize +
+ psCmdHelperData->ui32PostTimeStampCmdSize +
+ psCmdHelperData->ui32UpdateCmdSize);
+ }
+ }
+
+ /*
+ 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->bPDumpContinuous) ? PDUMP_FLAGS_CONTINUOUS : 0,
+ "%s Command Server Release on FWCtx %08x",
+ psCmdHelperData->pszCommandName, ui32CtxAddr);
+ }
+
+ _RGXClientCCBDumpCommands(asCmdHelperData[0].psClientCCB,
+ asCmdHelperData[0].psClientCCB->ui32HostWriteOffset,
+ ui32AllocSize);
+
+ RGXReleaseCCB(asCmdHelperData[0].psClientCCB,
+ ui32AllocSize,
+ asCmdHelperData[0].bPDumpContinuous);
+}
+
+
+IMG_UINT32 RGXCmdHelperGetCommandSize(IMG_UINT32 ui32CmdCount,
+ RGX_CCB_CMD_HELPER_DATA *asCmdHelperData)
+{
+ IMG_UINT32 ui32AllocSize = 0;
+ IMG_UINT32 i;
+
+ /*
+ Workout how much space we need for all the command(s)
+ */
+ for (i = 0; i < ui32CmdCount; i++)
+ {
+ ui32AllocSize +=
+ asCmdHelperData[i].ui32FenceCmdSize +
+ asCmdHelperData[i].ui32DMCmdSize +
+ asCmdHelperData[i].ui32UpdateCmdSize +
+ asCmdHelperData[i].ui32PreTimeStampCmdSize +
+ asCmdHelperData[i].ui32PostTimeStampCmdSize +
+ asCmdHelperData[i].ui32RMWUFOCmdSize;
+ }
+
+ return ui32AllocSize;
+}
+
+
+static IMG_PCCHAR _CCBCmdTypename(RGXFWIF_CCB_CMD_TYPE cmdType)
+{
+ static const IMG_CHAR* aCCBCmdName[18] = { "TA", "3D", "CDM", "TQ_3D", "TQ_2D",
+ "3D_PR", "NULL", "SHG", "RTU", "RTU_FC",
+ "PRE_TIMESTAMP",
+ "FENCE", "UPDATE", "RMW_UPDATE",
+ "FENCE_PR", "PRIORITY",
+ "POST_TIMESTAMP", "PADDING"};
+ IMG_UINT32 cmdStrIdx = 17;
+
+ PVR_ASSERT( (cmdType == RGXFWIF_CCB_CMD_TYPE_TA)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_3D)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_CDM)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_TQ_3D)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_TQ_2D)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_3D_PR)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_NULL)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_SHG)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_RTU)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_RTU_FC)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_PRE_TIMESTAMP)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_POST_TIMESTAMP)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_FENCE)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_UPDATE)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_RMW_UPDATE)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_FENCE_PR)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_PRIORITY)
+ || (cmdType == RGXFWIF_CCB_CMD_TYPE_PADDING));
+
+ if( cmdType != RGXFWIF_CCB_CMD_TYPE_PADDING)
+ {
+ cmdStrIdx = ((IMG_UINT32)cmdType & ~RGX_CCB_TYPE_TASK) - (RGXFWIF_CCB_CMD_TYPE_TA & ~RGX_CCB_TYPE_TASK);
+ }
+
+ return aCCBCmdName[cmdStrIdx];
+}
+
+PVRSRV_ERROR CheckForStalledCCB(RGX_CLIENT_CCB *psCurrentClientCCB)
+{
+ volatile RGXFWIF_CCCB_CTL *psClientCCBCtrl = psCurrentClientCCB->psClientCCBCtrl;
+ IMG_UINT32 ui32SampledRdOff = psClientCCBCtrl->ui32ReadOffset;
+ IMG_UINT32 ui32SampledWrOff = psCurrentClientCCB->ui32HostWriteOffset;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (ui32SampledRdOff > psClientCCBCtrl->ui32WrapMask ||
+ ui32SampledWrOff > psClientCCBCtrl->ui32WrapMask)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "CheckForStalledCCB: CCCB has invalid offset (ROFF=%d WOFF=%d)",
+ ui32SampledRdOff, ui32SampledWrOff));
+ return PVRSRV_ERROR_INVALID_OFFSET;
+ }
+
+ if (ui32SampledRdOff != ui32SampledWrOff &&
+ psCurrentClientCCB->ui32LastROff != psCurrentClientCCB->ui32LastWOff &&
+ ui32SampledRdOff == psCurrentClientCCB->ui32LastROff &&
+ (psCurrentClientCCB->ui32ByteCount - psCurrentClientCCB->ui32LastByteCount) < psCurrentClientCCB->ui32Size)
+ {
+ //RGXFWIF_DEV_VIRTADDR v = {0};
+ //DumpStalledCCBCommand(v,psCurrentClientCCB,IMG_NULL);
+
+ /* Don't log this by default unless debugging since a higher up
+ * function will log the stalled condition. Helps avoid double
+ * messages in the log.
+ */
+ PVR_DPF((PVR_DBG_MESSAGE, "CheckForStalledCCB: CCCB has not progressed (ROFF=%d WOFF=%d)",
+ ui32SampledRdOff, ui32SampledWrOff));
+ eError = PVRSRV_ERROR_CCCB_STALLED;
+ }
+
+ psCurrentClientCCB->ui32LastROff = ui32SampledRdOff;
+ psCurrentClientCCB->ui32LastWOff = ui32SampledWrOff;
+ psCurrentClientCCB->ui32LastByteCount = psCurrentClientCCB->ui32ByteCount;
+
+ return eError;
+}
+
+IMG_VOID DumpStalledCCBCommand(PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext,
+ RGX_CLIENT_CCB *psCurrentClientCCB,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ volatile RGXFWIF_CCCB_CTL *psClientCCBCtrl = psCurrentClientCCB->psClientCCBCtrl;
+ IMG_UINT8 *pui8ClientCCBBuff = psCurrentClientCCB->pui8ClientCCB;
+ volatile IMG_UINT8 *pui8Ptr;
+ IMG_UINT32 ui32SampledRdOff = psClientCCBCtrl->ui32ReadOffset;
+ IMG_UINT32 ui32SampledDepOff = psClientCCBCtrl->ui32DepOffset;
+ IMG_UINT32 ui32SampledWrOff = psCurrentClientCCB->ui32HostWriteOffset;
+
+ pui8Ptr = pui8ClientCCBBuff + ui32SampledRdOff;
+
+ if ((ui32SampledRdOff == ui32SampledDepOff) &&
+ (ui32SampledRdOff != ui32SampledWrOff))
+ {
+ volatile RGXFWIF_CCB_CMD_HEADER *psCommandHeader = (RGXFWIF_CCB_CMD_HEADER *)(pui8ClientCCBBuff + ui32SampledRdOff);
+ RGXFWIF_CCB_CMD_TYPE eCommandType = psCommandHeader->eCmdType;
+ volatile IMG_UINT8 *pui8Ptr = (IMG_UINT8 *)psCommandHeader;
+
+ /* CCB is stalled on a fence... */
+ if ((eCommandType == RGXFWIF_CCB_CMD_TYPE_FENCE) || (eCommandType == RGXFWIF_CCB_CMD_TYPE_FENCE_PR))
+ {
+ RGXFWIF_UFO *psUFOPtr = (RGXFWIF_UFO *)(pui8Ptr + sizeof(*psCommandHeader));
+ IMG_UINT32 jj;
+
+ /* Display details of the fence object on which the context is pending */
+ PVR_DUMPDEBUG_LOG(("FWCtx 0x%08X @ %d (%s) pending on %s:",
+ sFWCommonContext.ui32Addr,
+ ui32SampledRdOff,
+ (IMG_PCHAR)&psCurrentClientCCB->szName,
+ _CCBCmdTypename(eCommandType)));
+ for (jj=0; jj<psCommandHeader->ui32CmdSize/sizeof(RGXFWIF_UFO); jj++)
+ {
+ PVR_DUMPDEBUG_LOG((" Addr:0x%08x Value=0x%08x",psUFOPtr[jj].puiAddrUFO.ui32Addr, psUFOPtr[jj].ui32Value));
+ }
+
+ /* Advance psCommandHeader past the FENCE to the next command header (this will be the TA/3D command that is fenced) */
+ pui8Ptr = (IMG_UINT8 *)psUFOPtr + psCommandHeader->ui32CmdSize;
+ psCommandHeader = (RGXFWIF_CCB_CMD_HEADER *)pui8Ptr;
+ if( (IMG_UINTPTR_T)psCommandHeader != ((IMG_UINTPTR_T)pui8ClientCCBBuff + ui32SampledWrOff))
+ {
+ PVR_DUMPDEBUG_LOG((" FWCtx 0x%08X fenced command is of type %s",sFWCommonContext.ui32Addr, _CCBCmdTypename(psCommandHeader->eCmdType)));
+ /* Advance psCommandHeader past the TA/3D to the next command header (this will possibly be an UPDATE) */
+ pui8Ptr += sizeof(*psCommandHeader) + psCommandHeader->ui32CmdSize;
+ psCommandHeader = (RGXFWIF_CCB_CMD_HEADER *)pui8Ptr;
+ /* If the next command is an update, display details of that so we can see what would then become unblocked */
+ if( (IMG_UINTPTR_T)psCommandHeader != ((IMG_UINTPTR_T)pui8ClientCCBBuff + ui32SampledWrOff))
+ {
+ eCommandType = psCommandHeader->eCmdType;
+
+ if (eCommandType == RGXFWIF_CCB_CMD_TYPE_UPDATE)
+ {
+ psUFOPtr = (RGXFWIF_UFO *)((IMG_UINT8 *)psCommandHeader + sizeof(*psCommandHeader));
+ PVR_DUMPDEBUG_LOG((" preventing %s:",_CCBCmdTypename(eCommandType)));
+ for (jj=0; jj<psCommandHeader->ui32CmdSize/sizeof(RGXFWIF_UFO); jj++)
+ {
+ PVR_DUMPDEBUG_LOG((" Addr:0x%08x Value=0x%08x",psUFOPtr[jj].puiAddrUFO.ui32Addr, psUFOPtr[jj].ui32Value));
+ }
+ }
+ }
+ else
+ {
+ PVR_DUMPDEBUG_LOG((" FWCtx 0x%08X has no further commands",sFWCommonContext.ui32Addr));
+ }
+ }
+ else
+ {
+ PVR_DUMPDEBUG_LOG((" FWCtx 0x%08X has no further commands",sFWCommonContext.ui32Addr));
+ }
+ }
+ }
+}
+
+/******************************************************************************
+ End of file (rgxccb.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxccb.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxccb.h
new file mode 100644
index 000000000000..3426a16062e1
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxccb.h
@@ -0,0 +1,164 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX Circular Command Buffer functionality.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the RGX Circular Command Buffer 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(__RGXCCB_H__)
+#define __RGXCCB_H__
+
+#include "devicemem.h"
+#include "device.h"
+#include "rgxdevice.h"
+#include "sync_server.h"
+#include "connection_server.h"
+#include "rgx_fwif_shared.h"
+#include "rgxdebug.h"
+
+#define MAX_CLIENT_CCB_NAME 30
+
+typedef struct _RGX_CLIENT_CCB_ RGX_CLIENT_CCB;
+
+/*
+ This structure is declared here as it's allocated on the heap by
+ the callers
+*/
+
+typedef struct _RGX_CCB_CMD_HELPER_DATA_ {
+ /* Data setup at command init time */
+ RGX_CLIENT_CCB *psClientCCB;
+ IMG_CHAR *pszCommandName;
+ IMG_BOOL bPDumpContinuous;
+
+ IMG_UINT32 ui32ClientFenceCount;
+ PRGXFWIF_UFO_ADDR *pauiFenceUFOAddress;
+ IMG_UINT32 *paui32FenceValue;
+ IMG_UINT32 ui32ClientUpdateCount;
+ PRGXFWIF_UFO_ADDR *pauiUpdateUFOAddress;
+ IMG_UINT32 *paui32UpdateValue;
+
+ IMG_UINT32 ui32ServerSyncCount;
+ IMG_UINT32 *paui32ServerSyncFlags;
+ SERVER_SYNC_PRIMITIVE **papsServerSyncs;
+
+ RGXFWIF_KCCB_CMD_TYPE eType;
+ IMG_UINT32 ui32CmdSize;
+ IMG_UINT8 *pui8DMCmd;
+ IMG_UINT32 ui32FenceCmdSize;
+ IMG_UINT32 ui32DMCmdSize;
+ IMG_UINT32 ui32UpdateCmdSize;
+
+ /* timestamp commands */
+ PRGXFWIF_TIMESTAMP_ADDR pPreTimestampAddr;
+ IMG_UINT32 ui32PreTimeStampCmdSize;
+ PRGXFWIF_TIMESTAMP_ADDR pPostTimestampAddr;
+ IMG_UINT32 ui32PostTimeStampCmdSize;
+ PRGXFWIF_UFO_ADDR pRMWUFOAddr;
+ IMG_UINT32 ui32RMWUFOCmdSize;
+
+ /* Data setup at command acquire time */
+ IMG_UINT8 *pui8StartPtr;
+ IMG_UINT8 *pui8ServerUpdateStart;
+ IMG_UINT8 *pui8ServerFenceStart;
+ IMG_UINT32 ui32ServerFenceCount;
+ IMG_UINT32 ui32ServerUpdateCount;
+
+} RGX_CCB_CMD_HELPER_DATA;
+
+#define PADDING_COMMAND_SIZE (sizeof(RGXFWIF_CCB_CMD_HEADER))
+
+PVRSRV_ERROR RGXCreateCCB(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32CCBSizeLog2,
+ CONNECTION_DATA *psConnectionData,
+ const IMG_CHAR *pszName,
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+ RGX_CLIENT_CCB **ppsClientCCB,
+ DEVMEM_MEMDESC **ppsClientCCBMemDesc,
+ DEVMEM_MEMDESC **ppsClientCCBCtlMemDesc);
+
+IMG_VOID RGXDestroyCCB(RGX_CLIENT_CCB *psClientCCB);
+
+PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
+ IMG_UINT32 ui32CmdSize,
+ IMG_PVOID *ppvBufferSpace,
+ IMG_BOOL bPDumpContinuous);
+
+IMG_INTERNAL IMG_VOID RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB,
+ IMG_UINT32 ui32CmdSize,
+ IMG_BOOL bPDumpContinuous);
+
+IMG_UINT32 RGXGetHostWriteOffsetCCB(RGX_CLIENT_CCB *psClientCCB);
+
+PVRSRV_ERROR RGXCmdHelperInitCmdCCB(RGX_CLIENT_CCB *psClientCCB,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiFenceUFOAddress,
+ IMG_UINT32 *paui32FenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiUpdateUFOAddress,
+ IMG_UINT32 *paui32UpdateValue,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_UINT32 *paui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerSyncs,
+ IMG_UINT32 ui32CmdSize,
+ IMG_UINT8 *pui8DMCmd,
+ PRGXFWIF_TIMESTAMP_ADDR * ppPreAddr,
+ PRGXFWIF_TIMESTAMP_ADDR * ppPostAddr,
+ RGXFWIF_DEV_VIRTADDR * ppRMWUFOAddr,
+ RGXFWIF_CCB_CMD_TYPE eType,
+ IMG_BOOL bPDumpContinuous,
+ IMG_CHAR *pszCommandName,
+ RGX_CCB_CMD_HELPER_DATA *psCmdHelperData);
+
+PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
+ RGX_CCB_CMD_HELPER_DATA *asCmdHelperData,
+ IMG_BOOL *pbKickRequired);
+
+IMG_VOID RGXCmdHelperReleaseCmdCCB(IMG_UINT32 ui32CmdCount,
+ RGX_CCB_CMD_HELPER_DATA *asCmdHelperData,
+ const IMG_CHAR *pcszDMName,
+ IMG_UINT32 ui32CtxAddr);
+
+IMG_UINT32 RGXCmdHelperGetCommandSize(IMG_UINT32 ui32CmdCount,
+ RGX_CCB_CMD_HELPER_DATA *asCmdHelperData);
+
+IMG_VOID DumpStalledCCBCommand(PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext, RGX_CLIENT_CCB *psCurrentClientCCB, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf);
+
+PVRSRV_ERROR CheckForStalledCCB(RGX_CLIENT_CCB *psCurrentClientCCB);
+#endif /* __RGXCCB_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxcompute.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxcompute.c
new file mode 100644
index 000000000000..e7fe7e5b607a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxcompute.c
@@ -0,0 +1,531 @@
+/*************************************************************************/ /*!
+@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 "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 "rgxtimerquery.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "rgx_memallocflags.h"
+#include "rgxsync.h"
+
+struct _RGX_SERVER_COMPUTE_CONTEXT_ {
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
+ DEVMEM_MEMDESC *psFWFrameworkMemDesc;
+ DEVMEM_MEMDESC *psFWComputeContextStateMemDesc;
+ PVRSRV_CLIENT_SYNC_PRIM *psSync;
+ DLLIST_NODE sListNode;
+};
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32Priority,
+ IMG_DEV_VIRTADDR sMCUFenceAddr,
+ IMG_UINT32 ui32FrameworkCommandSize,
+ IMG_PBYTE pbyFrameworkCommand,
+ IMG_HANDLE hMemCtxPrivData,
+ RGX_SERVER_COMPUTE_CONTEXT **ppsComputeContext)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+ RGX_SERVER_COMPUTE_CONTEXT *psComputeContext;
+ RGX_COMMON_CONTEXT_INFO sInfo;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ /* Prepare cleanup struct */
+ *ppsComputeContext = IMG_NULL;
+ psComputeContext = OSAllocMem(sizeof(*psComputeContext));
+ if (psComputeContext == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psComputeContext, 0, sizeof(*psComputeContext));
+
+ psComputeContext->psDeviceNode = psDeviceNode;
+
+ /* Allocate cleanup sync */
+ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+ &psComputeContext->psSync,
+ "compute cleanup");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate cleanup sync (0x%x)",
+ eError));
+ goto fail_syncalloc;
+ }
+
+ /*
+ 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");
+
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_COMPUTECTX_STATE),
+ RGX_FWCOMCTX_ALLOCFLAGS,
+ "ComputeContextState",
+ &psComputeContext->psFWComputeContextStateMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate firmware GPU context suspend state (%u)",
+ eError));
+ goto fail_contextsuspendalloc;
+ }
+
+ /*
+ * Create the FW framework buffer
+ */
+ eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode,
+ &psComputeContext->psFWFrameworkMemDesc,
+ ui32FrameworkCommandSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate firmware GPU framework state (%u)",
+ eError));
+ goto fail_frameworkcreate;
+ }
+
+ /* Copy the Framework client data into the framework buffer */
+ eError = PVRSRVRGXFrameworkCopyCommand(psComputeContext->psFWFrameworkMemDesc,
+ pbyFrameworkCommand,
+ ui32FrameworkCommandSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to populate the framework buffer (%u)",
+ eError));
+ goto fail_frameworkcopy;
+ }
+
+ sInfo.psFWFrameworkMemDesc = psComputeContext->psFWFrameworkMemDesc;
+ sInfo.psMCUFenceAddr = &sMCUFenceAddr;
+
+ eError = FWCommonContextAllocate(psConnection,
+ psDeviceNode,
+ "CDM",
+ IMG_NULL,
+ 0,
+ psFWMemContextMemDesc,
+ psComputeContext->psFWComputeContextStateMemDesc,
+ RGX_CCB_SIZE_LOG2,
+ ui32Priority,
+ &sInfo,
+ &psComputeContext->psServerCommonContext);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_contextalloc;
+ }
+
+ {
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ OSWRLockAcquireWrite(psDevInfo->hComputeCtxListLock, DEVINFO_COMPUTELIST);
+ dllist_add_to_tail(&(psDevInfo->sComputeCtxtListHead), &(psComputeContext->sListNode));
+ OSWRLockReleaseWrite(psDevInfo->hComputeCtxListLock);
+ }
+
+ *ppsComputeContext = psComputeContext;
+ return PVRSRV_OK;
+
+fail_contextalloc:
+fail_frameworkcopy:
+ DevmemFwFree(psComputeContext->psFWFrameworkMemDesc);
+fail_frameworkcreate:
+ DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc);
+fail_contextsuspendalloc:
+ SyncPrimFree(psComputeContext->psSync);
+fail_syncalloc:
+ OSFreeMem(psComputeContext);
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psComputeContext->psDeviceNode->pvDevice;
+
+ /* Check if the FW has finished with this resource ... */
+ eError = RGXFWRequestCommonContextCleanUp(psComputeContext->psDeviceNode,
+ FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext),
+ psComputeContext->psSync,
+ RGXFWIF_DM_CDM);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ return eError;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+ __FUNCTION__,
+ PVRSRVGetErrorStringKM(eError)));
+ return eError;
+ }
+
+ /* ... it has so we can free its resources */
+
+ OSWRLockAcquireWrite(psDevInfo->hComputeCtxListLock, DEVINFO_COMPUTELIST);
+ dllist_remove_node(&(psComputeContext->sListNode));
+ OSWRLockReleaseWrite(psDevInfo->hComputeCtxListLock);
+
+ FWCommonContextFree(psComputeContext->psServerCommonContext);
+ DevmemFwFree(psComputeContext->psFWFrameworkMemDesc);
+ DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc);
+ SyncPrimFree(psComputeContext->psSync);
+ OSFreeMem(psComputeContext);
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress,
+ IMG_UINT32 *paui32ClientFenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress,
+ IMG_UINT32 *paui32ClientUpdateValue,
+ IMG_UINT32 ui32ServerSyncPrims,
+ IMG_UINT32 *paui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerSyncs,
+ IMG_UINT32 ui32CmdSize,
+ IMG_PBYTE pui8DMCmd,
+ IMG_BOOL bPDumpContinuous,
+ IMG_UINT32 ui32ExtJobRef,
+ IMG_UINT32 ui32IntJobRef)
+{
+ RGXFWIF_KCCB_CMD sCmpKCCBCmd;
+ RGX_CCB_CMD_HELPER_DATA sCmdHelperData;
+ IMG_BOOL bKickRequired;
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError2;
+ IMG_UINT32 i;
+
+ PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+ PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+ PRGXFWIF_UFO_ADDR pRMWUFOAddr;
+
+
+ /* Sanity check the server fences */
+ for (i=0;i<ui32ServerSyncPrims;i++)
+ {
+ if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on CDM) must fence", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
+ }
+ }
+
+ RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psComputeContext->psDeviceNode->pvDevice,
+ & pPreAddr,
+ & pPostAddr,
+ & pRMWUFOAddr);
+
+ eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psComputeContext->psServerCommonContext),
+ ui32ClientFenceCount,
+ pauiClientFenceUFOAddress,
+ paui32ClientFenceValue,
+ ui32ClientUpdateCount,
+ pauiClientUpdateUFOAddress,
+ paui32ClientUpdateValue,
+ ui32ServerSyncPrims,
+ paui32ServerSyncFlags,
+ pasServerSyncs,
+ ui32CmdSize,
+ pui8DMCmd,
+ & pPreAddr,
+ & pPostAddr,
+ & pRMWUFOAddr,
+ RGXFWIF_CCB_CMD_TYPE_CDM,
+ bPDumpContinuous,
+ "Compute",
+ &sCmdHelperData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_cmdinit;
+ }
+
+ eError = RGXCmdHelperAcquireCmdCCB(1, &sCmdHelperData, &bKickRequired);
+ if ((eError != PVRSRV_OK) && (!bKickRequired))
+ {
+ /*
+ Only bail if no new data was submitted into the client CCB, we might
+ have already submitted a padding packet which we should flush through
+ the FW.
+ */
+ PVR_DPF((PVR_DBG_ERROR, "RGXKickCDM: Failed to create client CCB command"));
+ goto fail_cmdaquire;
+ }
+
+
+ /*
+ We should reserved 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
+ */
+ RGXCmdHelperReleaseCmdCCB(1, &sCmdHelperData, "CDM", FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext).ui32Addr);
+ }
+
+ /* Construct the kernel compute CCB command. */
+ sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+ sCmpKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext);
+ sCmpKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psComputeContext->psServerCommonContext));
+ sCmpKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+ /*
+ * Submit the compute command to the firmware.
+ */
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError2 = RGXScheduleCommand(psComputeContext->psDeviceNode->pvDevice,
+ RGXFWIF_DM_CDM,
+ &sCmpKCCBCmd,
+ sizeof(sCmpKCCBCmd),
+ bPDumpContinuous);
+ 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, "PVRSRVRGXKickCDMKM failed to schedule kernel CCB command. (0x%x)", eError));
+ }
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+ else
+ {
+ RGXHWPerfFTraceGPUEnqueueEvent(psComputeContext->psDeviceNode->pvDevice,
+ ui32ExtJobRef, ui32IntJobRef, "CDM");
+ }
+#endif
+ /*
+ * 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;
+ }
+
+ return PVRSRV_OK;
+
+fail_cmdaquire:
+fail_cmdinit:
+ return eError;
+}
+
+IMG_EXPORT PVRSRV_ERROR PVRSRVRGXFlushComputeDataKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext)
+{
+ RGXFWIF_KCCB_CMD sFlushCmd;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit Compute flush");
+#endif
+ sFlushCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
+ sFlushCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_FALSE;
+ sFlushCmd.uCmdData.sSLCFlushInvalData.eDM = RGXFWIF_DM_CDM;
+ sFlushCmd.uCmdData.sSLCFlushInvalData.psContext = FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext);
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError = RGXScheduleCommand(psComputeContext->psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sFlushCmd,
+ sizeof(sFlushCmd),
+ IMG_TRUE);
+ 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,"PVRSRVRGXFlushComputeDataKM: Failed to schedule SLC flush command with error (%u)", eError));
+ }
+ else
+ {
+ /* Wait for the SLC flush to complete */
+ eError = RGXWaitForFWOp(psComputeContext->psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ psComputeContext->psSync,
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXFlushComputeDataKM: Compute flush aborted with error (%u)", eError));
+ }
+ }
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXSetComputeContextPriorityKM(CONNECTION_DATA *psConnection,
+ RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+ IMG_UINT32 ui32Priority)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ContextSetPriority(psComputeContext->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)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+ }
+ return eError;
+}
+
+static IMG_BOOL CheckForStalledComputeCtxtCommand(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ RGX_SERVER_COMPUTE_CONTEXT *psCurrentServerComputeCtx = IMG_CONTAINER_OF(psNode, RGX_SERVER_COMPUTE_CONTEXT, sListNode);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServerComputeCommonCtx = psCurrentServerComputeCtx->psServerCommonContext;
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = pvCallbackData;
+
+ DumpStalledFWCommonContext(psCurrentServerComputeCommonCtx, pfnDumpDebugPrintf);
+ return IMG_TRUE;
+}
+IMG_VOID CheckForStalledComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ OSWRLockAcquireRead(psDevInfo->hComputeCtxListLock, DEVINFO_COMPUTELIST);
+ dllist_foreach_node(&(psDevInfo->sComputeCtxtListHead),
+ CheckForStalledComputeCtxtCommand, pfnDumpDebugPrintf);
+ OSWRLockReleaseRead(psDevInfo->hComputeCtxListLock);
+}
+
+static IMG_BOOL CheckForStalledClientComputeCtxtCommand(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ PVRSRV_ERROR *peError = (PVRSRV_ERROR*)pvCallbackData;
+ RGX_SERVER_COMPUTE_CONTEXT *psCurrentServerComputeCtx = IMG_CONTAINER_OF(psNode, RGX_SERVER_COMPUTE_CONTEXT, sListNode);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServerComputeCommonCtx = psCurrentServerComputeCtx->psServerCommonContext;
+
+ if (PVRSRV_ERROR_CCCB_STALLED == CheckStalledClientCommonContext(psCurrentServerComputeCommonCtx))
+ {
+ *peError = PVRSRV_ERROR_CCCB_STALLED;
+ }
+
+ return IMG_TRUE;
+}
+IMG_BOOL CheckForStalledClientComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ OSWRLockAcquireRead(psDevInfo->hComputeCtxListLock, DEVINFO_COMPUTELIST);
+ dllist_foreach_node(&(psDevInfo->sComputeCtxtListHead),
+ CheckForStalledClientComputeCtxtCommand, &eError);
+ OSWRLockReleaseRead(psDevInfo->hComputeCtxListLock);
+ return (PVRSRV_ERROR_CCCB_STALLED == eError)? IMG_TRUE: IMG_FALSE;
+}
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXKickSyncCDMKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress,
+ IMG_UINT32 *paui32ClientFenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress,
+ IMG_UINT32 *paui32ClientUpdateValue,
+ IMG_UINT32 ui32ServerSyncPrims,
+ IMG_UINT32 *paui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerSyncs,
+ IMG_UINT32 ui32NumFenceFDs,
+ IMG_INT32 *paui32FenceFDs,
+ IMG_BOOL bPDumpContinuous)
+{
+ if (ui32NumFenceFDs > 0)
+ {
+ return PVRSRV_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return RGXKickSyncKM(psComputeContext->psDeviceNode,
+ psComputeContext->psServerCommonContext,
+ RGXFWIF_DM_CDM,
+ "SyncCDM",
+ ui32ClientFenceCount,
+ pauiClientFenceUFOAddress,
+ paui32ClientFenceValue,
+ ui32ClientUpdateCount,
+ pauiClientUpdateUFOAddress,
+ paui32ClientUpdateValue,
+ ui32ServerSyncPrims,
+ paui32ServerSyncFlags,
+ pasServerSyncs,
+ bPDumpContinuous);
+}
+/******************************************************************************
+ End of file (rgxcompute.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxcompute.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxcompute.h
new file mode 100644
index 000000000000..6d0ad77c8860
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxcompute.h
@@ -0,0 +1,177 @@
+/*************************************************************************/ /*!
+@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 "sync_server.h"
+#include "sync_internal.h"
+#include "connection_server.h"
+
+typedef struct _RGX_SERVER_COMPUTE_CONTEXT_ RGX_SERVER_COMPUTE_CONTEXT;
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXCreateComputeContextKM
+
+ @Description
+
+
+ @Input pvDeviceNode
+ @Input psCmpCCBMemDesc -
+ @Input psCmpCCBCtlMemDesc -
+ @Output ppsFWComputeContextMemDesc -
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32Priority,
+ IMG_DEV_VIRTADDR sMCUFenceAddr,
+ IMG_UINT32 ui32FrameworkRegisterSize,
+ IMG_PBYTE pbyFrameworkRegisters,
+ IMG_HANDLE hMemCtxPrivData,
+ RGX_SERVER_COMPUTE_CONTEXT **ppsComputeContext);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXDestroyComputeContextKM
+
+ @Description
+ Server-side implementation of RGXDestroyComputeContext
+
+ @Input psCleanupData -
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext);
+
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXKickCDMKM
+
+ @Description
+ Server-side implementation of RGXKickCDM
+
+ @Input psDeviceNode - RGX Device node
+ @Input psFWComputeContextMemDesc - Mem desc for firmware compute context
+ @Input ui32cCCBWoffUpdate - New fw Woff for the client CDM CCB
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress,
+ IMG_UINT32 *paui32ClientFenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress,
+ IMG_UINT32 *paui32ClientUpdateValue,
+ IMG_UINT32 ui32ServerSyncPrims,
+ IMG_UINT32 *paui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerSyncs,
+ IMG_UINT32 ui32CmdSize,
+ IMG_PBYTE pui8DMCmd,
+ IMG_BOOL bPDumpContinuous,
+ IMG_UINT32 ui32ExtJobRef,
+ IMG_UINT32 ui32IntJobRef);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXFlushComputeDataKM
+
+ @Description
+ Server-side implementation of RGXFlushComputeData
+
+ @Input psComputeContext - Compute context to flush
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXFlushComputeDataKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext);
+
+PVRSRV_ERROR PVRSRVRGXSetComputeContextPriorityKM(CONNECTION_DATA *psConnection,
+ RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+ IMG_UINT32 ui32Priority);
+
+/* Debug - check if compute context is waiting on a fence */
+IMG_VOID CheckForStalledComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf);
+
+/* Debug/Watchdog - check if client compute contexts are stalled */
+IMG_BOOL CheckForStalledClientComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXKickSyncCDMKM
+
+ @Description
+ Sending a sync kick command though this CDM context
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXKickSyncCDMKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress,
+ IMG_UINT32 *paui32ClientFenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress,
+ IMG_UINT32 *paui32ClientUpdateValue,
+ IMG_UINT32 ui32ServerSyncPrims,
+ IMG_UINT32 *paui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerSyncs,
+ IMG_UINT32 ui32NumFenceFDs,
+ IMG_INT32 *paui32FenceFDs,
+ IMG_BOOL bPDumpContinuous);
+
+#endif /* __RGXCOMPUTE_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.c
new file mode 100644
index 000000000000..b7029fd33c74
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.c
@@ -0,0 +1,2141 @@
+/*************************************************************************/ /*!
+@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 "rgxdefs_km.h"
+#include "rgxdevice.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "osfunc.h"
+
+#include "lists.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 "devicemem_pdump.h"
+
+#include "rgx_fwif.h"
+#include "pvrsrv.h"
+
+#if defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS)
+#include "rgx_fwif_sf.h"
+#include "rgxfw_log_helper.h"
+#endif
+
+#include "rgxta3d.h"
+#include "rgxcompute.h"
+#include "rgxtransfer.h"
+#if defined(RGX_FEATURE_RAY_TRACING)
+#include "rgxray.h"
+#endif
+
+
+#define RGX_DEBUG_STR_SIZE (150)
+
+#define RGX_CR_BIF_CAT_BASE0 (0x1200U)
+#define RGX_CR_BIF_CAT_BASE1 (0x1208U)
+
+#define RGX_CR_BIF_CAT_BASEN(n) \
+ RGX_CR_BIF_CAT_BASE0 + \
+ ((RGX_CR_BIF_CAT_BASE1 - RGX_CR_BIF_CAT_BASE0) * n)
+
+
+#define RGXDBG_BIF_IDS \
+ X(BIF0)\
+ X(BIF1)\
+ X(TEXAS_BIF)
+
+#define RGXDBG_SIDEBAND_TYPES \
+ X(META)\
+ X(TLA)\
+ X(VDMM)\
+ X(CDM)\
+ X(IPP)\
+ X(PM)\
+ X(TILING)\
+ X(MCU)\
+ X(PDS)\
+ X(PBE)\
+ X(VDMS)\
+ X(IPF)\
+ X(ISP)\
+ X(TPF)\
+ X(USCS)\
+ X(PPP)\
+ X(VCE)\
+ X(FBCDC)
+
+typedef enum
+{
+#define X(NAME) RGXDBG_##NAME,
+ RGXDBG_BIF_IDS
+#undef X
+} RGXDBG_BIF_ID;
+
+typedef enum
+{
+#define X(NAME) RGXDBG_##NAME,
+ RGXDBG_SIDEBAND_TYPES
+#undef X
+} RGXDBG_SIDEBAND_TYPE;
+
+
+IMG_CHAR* pszPowStateName [] = {
+#define X(NAME) #NAME,
+ RGXFWIF_POW_STATES
+#undef X
+};
+
+IMG_CHAR* pszBIFNames [] = {
+#define X(NAME) #NAME,
+ RGXDBG_BIF_IDS
+#undef X
+};
+
+extern IMG_UINT32 g_ui32HostSampleIRQCount;
+
+
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*!
+*******************************************************************************
+
+ @Function _RGXDecodePMPC
+
+ @Description
+
+ Return the name for the PM managed Page Catalogues
+
+ @Input ui32PC - Page Catalogue number
+
+ @Return IMG_VOID
+
+******************************************************************************/
+static IMG_CHAR* _RGXDecodePMPC(IMG_UINT32 ui32PC)
+{
+ IMG_CHAR* pszPMPC = " (-)";
+
+ switch (ui32PC)
+ {
+ case 0x8: pszPMPC = " (PM-VCE0)"; break;
+ case 0x9: pszPMPC = " (PM-TE0)"; break;
+ case 0xA: pszPMPC = " (PM-ZLS0)"; break;
+ case 0xB: pszPMPC = " (PM-ALIST0)"; break;
+ case 0xC: pszPMPC = " (PM-VCE1)"; break;
+ case 0xD: pszPMPC = " (PM-TE1)"; break;
+ case 0xE: pszPMPC = " (PM-ZLS1)"; break;
+ case 0xF: pszPMPC = " (PM-ALIST1)"; break;
+ }
+
+ return pszPMPC;
+}
+
+/*!
+*******************************************************************************
+
+ @Function _RGXDecodeBIFReqTags
+
+ @Description
+
+ Decode the BIF Tag ID and sideband data fields from BIF_FAULT_BANK_REQ_STATUS regs
+
+ @Input eBankID - BIF identifier
+ @Input ui32TagID - Tag ID value
+ @Input ui32TagSB - Tag Sideband data
+ @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 IMG_VOID
+
+******************************************************************************/
+static IMG_VOID _RGXDecodeBIFReqTags(RGXDBG_BIF_ID eBankID,
+ IMG_UINT32 ui32TagID,
+ IMG_UINT32 ui32TagSB,
+ IMG_CHAR **ppszTagID,
+ IMG_CHAR **ppszTagSB,
+ IMG_CHAR *pszScratchBuf,
+ IMG_UINT32 ui32ScratchBufSize)
+{
+ /* default to unknown */
+ IMG_CHAR *pszTagID = "-";
+ IMG_CHAR *pszTagSB = "-";
+
+ PVR_ASSERT(ppszTagID != IMG_NULL);
+ PVR_ASSERT(ppszTagSB != IMG_NULL);
+
+ switch (ui32TagID)
+ {
+ case 0x0:
+ {
+ pszTagID = "MMU";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Table"; break;
+ case 0x1: pszTagSB = "Directory"; break;
+ case 0x2: pszTagSB = "Catalogue"; break;
+ }
+ break;
+ }
+ case 0x1:
+ {
+ pszTagID = "TLA";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Pixel data"; break;
+ case 0x1: pszTagSB = "Command stream data"; break;
+ case 0x2: pszTagSB = "Fence or flush"; break;
+ }
+ break;
+ }
+ case 0x2:
+ {
+ pszTagID = "HOST";
+ break;
+ }
+ case 0x3:
+ {
+ pszTagID = "META";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "DCache - Thread 0"; break;
+ case 0x1: pszTagSB = "ICache - Thread 0"; break;
+ case 0x2: pszTagSB = "JTag - Thread 0"; break;
+ case 0x3: pszTagSB = "Slave bus - Thread 0"; break;
+ case 0x4: pszTagSB = "DCache - Thread "; break;
+ case 0x5: pszTagSB = "ICache - Thread 1"; break;
+ case 0x6: pszTagSB = "JTag - Thread 1"; break;
+ case 0x7: pszTagSB = "Slave bus - Thread 1"; break;
+ }
+ break;
+ }
+ case 0x4:
+ {
+ pszTagID = "USC";
+ OSSNPrintf(pszScratchBuf, ui32ScratchBufSize,
+ "Cache line %d", (ui32TagSB & 0x3f));
+ pszTagSB = pszScratchBuf;
+ break;
+ }
+ case 0x5:
+ {
+ pszTagID = "PBE";
+ break;
+ }
+ case 0x6:
+ {
+ pszTagID = "ISP";
+ switch (ui32TagSB)
+ {
+ case 0x00: pszTagSB = "ZLS"; break;
+ case 0x20: pszTagSB = "Occlusion Query"; break;
+ }
+ break;
+ }
+ case 0x7:
+ {
+#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
+ if (eBankID == RGXDBG_TEXAS_BIF)
+ {
+ pszTagID = "IPF";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "CPF"; break;
+ case 0x1: pszTagSB = "DBSC"; break;
+ case 0x2:
+ case 0x4:
+ case 0x6:
+ case 0x8: pszTagSB = "Control Stream"; break;
+ case 0x3:
+ case 0x5:
+ case 0x7:
+ case 0x9: pszTagSB = "Primitive Block"; break;
+ }
+ }
+ else
+ {
+ pszTagID = "IPP";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Macrotile Header"; break;
+ case 0x1: pszTagSB = "Region Header"; break;
+ }
+ }
+#else
+ pszTagID = "IPF";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Macrotile Header"; break;
+ case 0x1: pszTagSB = "Region Header"; break;
+ case 0x2: pszTagSB = "DBSC"; break;
+ case 0x3: pszTagSB = "CPF"; break;
+ case 0x4:
+ case 0x6:
+ case 0x8: pszTagSB = "Control Stream"; break;
+ case 0x5:
+ case 0x7:
+ case 0x9: pszTagSB = "Primitive Block"; break;
+ }
+#endif
+ break;
+ }
+ case 0x8:
+ {
+ pszTagID = "CDM";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Control Stream"; break;
+ case 0x1: pszTagSB = "Indirect Data"; break;
+ case 0x2: pszTagSB = "Event Write"; break;
+ case 0x3: pszTagSB = "Context State"; break;
+ }
+ break;
+ }
+ case 0x9:
+ {
+ pszTagID = "VDM";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Control Stream"; break;
+ case 0x1: pszTagSB = "PPP State"; break;
+ case 0x2: pszTagSB = "Index Data"; break;
+ case 0x4: pszTagSB = "Call Stack"; break;
+ case 0x8: pszTagSB = "Context State"; break;
+ }
+ break;
+ }
+ case 0xA:
+ {
+ pszTagID = "PM";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "PMA_TAFSTACK"; break;
+ case 0x1: pszTagSB = "PMA_TAMLIST"; break;
+ case 0x2: pszTagSB = "PMA_3DFSTACK"; break;
+ case 0x3: pszTagSB = "PMA_3DMLIST"; break;
+ case 0x4: pszTagSB = "PMA_PMCTX0"; break;
+ case 0x5: pszTagSB = "PMA_PMCTX1"; break;
+ case 0x6: pszTagSB = "PMA_MAVP"; break;
+ case 0x7: pszTagSB = "PMA_UFSTACK"; break;
+ case 0x8: pszTagSB = "PMD_TAFSTACK"; break;
+ case 0x9: pszTagSB = "PMD_TAMLIST"; break;
+ case 0xA: pszTagSB = "PMD_3DFSTACK"; break;
+ case 0xB: pszTagSB = "PMD_3DMLIST"; break;
+ case 0xC: pszTagSB = "PMD_PMCTX0"; break;
+ case 0xD: pszTagSB = "PMD_PMCTX1"; break;
+ case 0xF: pszTagSB = "PMD_UFSTACK"; break;
+ case 0x10: pszTagSB = "PMA_TAMMUSTACK"; break;
+ case 0x11: pszTagSB = "PMA_3DMMUSTACK"; break;
+ case 0x12: pszTagSB = "PMD_TAMMUSTACK"; break;
+ case 0x13: pszTagSB = "PMD_3DMMUSTACK"; break;
+ case 0x14: pszTagSB = "PMA_TAUFSTACK"; break;
+ case 0x15: pszTagSB = "PMA_3DUFSTACK"; break;
+ case 0x16: pszTagSB = "PMD_TAUFSTACK"; break;
+ case 0x17: pszTagSB = "PMD_3DUFSTACK"; break;
+ case 0x18: pszTagSB = "PMA_TAVFP"; break;
+ case 0x19: pszTagSB = "PMD_3DVFP"; break;
+ case 0x1A: pszTagSB = "PMD_TAVFP"; break;
+ }
+ break;
+ }
+ case 0xB:
+ {
+ pszTagID = "TA";
+ switch (ui32TagSB)
+ {
+ case 0x1: pszTagSB = "VCE"; break;
+ case 0x2: pszTagSB = "TPC"; break;
+ case 0x3: pszTagSB = "TE Control Stream"; break;
+ case 0x4: pszTagSB = "TE Region Header"; break;
+ case 0x5: pszTagSB = "TE Render Target Cache"; break;
+ case 0x6: pszTagSB = "TEAC Render Target Cache"; break;
+ case 0x7: pszTagSB = "VCE Render Target Cache"; break;
+ case 0x8: pszTagSB = "PPP Context State"; break;
+ }
+ break;
+ }
+ case 0xC:
+ {
+ pszTagID = "TPF";
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "TPF0: Primitive Block"; break;
+ case 0x1: pszTagSB = "TPF0: Depth Bias"; break;
+ case 0x2: pszTagSB = "TPF0: Per Primitive IDs"; break;
+ case 0x3: pszTagSB = "CPF - Tables"; break;
+ case 0x4: pszTagSB = "TPF1: Primitive Block"; break;
+ case 0x5: pszTagSB = "TPF1: Depth Bias"; break;
+ case 0x6: pszTagSB = "TPF1: Per Primitive IDs"; break;
+ case 0x7: pszTagSB = "CPF - Data: Pipe 0"; break;
+ case 0x8: pszTagSB = "TPF2: Primitive Block"; break;
+ case 0x9: pszTagSB = "TPF2: Depth Bias"; break;
+ case 0xA: pszTagSB = "TPF2: Per Primitive IDs"; break;
+ case 0xB: pszTagSB = "CPF - Data: Pipe 1"; break;
+ case 0xC: pszTagSB = "TPF3: Primitive Block"; break;
+ case 0xD: pszTagSB = "TPF3: Depth Bias"; break;
+ case 0xE: pszTagSB = "TPF3: Per Primitive IDs"; break;
+ case 0xF: pszTagSB = "CPF - Data: Pipe 2"; break;
+ }
+ break;
+ }
+ case 0xD:
+ {
+ pszTagID = "PDS";
+ break;
+ }
+ case 0xE:
+ {
+ pszTagID = "MCU";
+ {
+ IMG_UINT32 ui32Burst = (ui32TagSB >> 5) & 0x7;
+ IMG_UINT32 ui32GroupEnc = (ui32TagSB >> 2) & 0x7;
+ IMG_UINT32 ui32Group = ui32TagSB & 0x3;
+
+ IMG_CHAR* pszBurst = "";
+ IMG_CHAR* pszGroupEnc = "";
+ IMG_CHAR* pszGroup = "";
+
+ switch (ui32Burst)
+ {
+ case 0x0:
+ case 0x1: pszBurst = "128bit word within the Lower 256bits"; break;
+ case 0x2:
+ case 0x3: pszBurst = "128bit word within the Upper 256bits"; break;
+ case 0x4: pszBurst = "Lower 256bits"; break;
+ case 0x5: pszBurst = "Upper 256bits"; break;
+ case 0x6: pszBurst = "512 bits"; break;
+ }
+ switch (ui32GroupEnc)
+ {
+#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE)
+ case 0x0: pszGroupEnc = "PDS_REQ"; break;
+ case 0x1: pszGroupEnc = "USC_REQ"; break;
+ case 0x2: pszGroupEnc = "MADD_REQ"; break;
+ case 0x3: pszGroupEnc = "USCB_USC"; break;
+#else
+ case 0x0: pszGroupEnc = "TPUA_USC"; break;
+ case 0x1: pszGroupEnc = "TPUB_USC"; break;
+ case 0x2: pszGroupEnc = "USCA_USC"; break;
+ case 0x3: pszGroupEnc = "USCB_USC"; break;
+ case 0x4: pszGroupEnc = "PDS_USC"; break;
+#if (RGX_FEATURE_NUM_CLUSTERS < 6)
+ case 0x5: pszGroupEnc = "PDSRW"; break;
+#elif (RGX_FEATURE_NUM_CLUSTERS == 6)
+ case 0x5: pszGroupEnc = "UPUC_USC"; break;
+ case 0x6: pszGroupEnc = "TPUC_USC"; break;
+ case 0x7: pszGroupEnc = "PDSRW"; break;
+#endif
+#endif
+ }
+ switch (ui32Group)
+ {
+ case 0x0: pszGroup = "Banks 0-3"; break;
+ case 0x1: pszGroup = "Banks 4-7"; break;
+ case 0x2: pszGroup = "Banks 8-11"; break;
+ case 0x3: pszGroup = "Banks 12-15"; break;
+ }
+
+ OSSNPrintf(pszScratchBuf, ui32ScratchBufSize,
+ "%s, %s, %s", pszBurst, pszGroupEnc, pszGroup);
+ pszTagSB = pszScratchBuf;
+ }
+ break;
+ }
+ case 0xF:
+ {
+ pszTagID = "FB_CDC";
+ {
+ IMG_UINT32 ui32Req = (ui32TagSB >> 2) & 0x3;
+ IMG_UINT32 ui32MCUSB = ui32TagSB & 0x3;
+
+ IMG_CHAR* pszReqId = (ui32TagSB & 0x10)?"FBDC":"FBC";
+ IMG_CHAR* pszOrig = "";
+
+ switch (ui32Req)
+ {
+ case 0x0: pszOrig = "ZLS"; break;
+ case 0x1: pszOrig = (ui32TagSB & 0x10)?"MCU":"PBE"; break;
+ case 0x2: pszOrig = "Host"; break;
+ case 0x3: pszOrig = "TLA"; break;
+ }
+ OSSNPrintf(pszScratchBuf, ui32ScratchBufSize,
+ "%s Request, originator %s, MCU sideband 0x%X",
+ pszReqId, pszOrig, ui32MCUSB);
+ pszTagSB = pszScratchBuf;
+ }
+ break;
+ }
+ } /* switch(TagID) */
+
+ *ppszTagID = pszTagID;
+ *ppszTagSB = pszTagSB;
+}
+#endif
+
+
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*!
+*******************************************************************************
+
+ @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 IMG_CHAR* _RGXDecodeMMULevel(IMG_UINT32 ui32MMULevel)
+{
+ 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)"; 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 ui32TagSB - Tag Sideband data
+ @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 IMG_VOID
+
+******************************************************************************/
+static IMG_VOID _RGXDecodeMMUReqTags(IMG_UINT32 ui32TagID,
+ IMG_UINT32 ui32TagSB,
+ IMG_CHAR **ppszTagID,
+ IMG_CHAR **ppszTagSB,
+ IMG_CHAR *pszScratchBuf,
+ IMG_UINT32 ui32ScratchBufSize)
+{
+ IMG_INT32 i32SideBandType = -1;
+ IMG_CHAR *pszTagID = "-";
+ IMG_CHAR *pszTagSB = "-";
+
+ PVR_ASSERT(ppszTagID != IMG_NULL);
+ PVR_ASSERT(ppszTagSB != IMG_NULL);
+
+ switch (ui32TagID)
+ {
+ case 0: pszTagID = "META (Jones)"; i32SideBandType = RGXDBG_META; break;
+ case 1: pszTagID = "TLA (Jones)"; i32SideBandType = RGXDBG_TLA; break;
+ case 3: pszTagID = "VDMM (Jones)"; i32SideBandType = RGXDBG_VDMM; break;
+ case 4: pszTagID = "CDM (Jones)"; i32SideBandType = RGXDBG_CDM; break;
+ case 5: pszTagID = "IPP (Jones)"; i32SideBandType = RGXDBG_IPP; break;
+ case 6: pszTagID = "PM (Jones)"; i32SideBandType = RGXDBG_PM; break;
+ case 7: pszTagID = "Tiling (Jones)"; i32SideBandType = RGXDBG_TILING; break;
+ case 8: pszTagID = "MCU (Texas 0)"; i32SideBandType = RGXDBG_MCU; break;
+ case 9: pszTagID = "PDS (Texas 0)"; i32SideBandType = RGXDBG_PDS; break;
+ case 10: pszTagID = "PBE0 (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
+ case 11: pszTagID = "PBE1 (Texas 0)"; i32SideBandType = RGXDBG_PBE; break;
+ case 12: pszTagID = "VDMS (Black Pearl 0)"; i32SideBandType = RGXDBG_VDMS; break;
+ case 13: pszTagID = "IPF (Black Pearl 0)"; i32SideBandType = RGXDBG_IPF; break;
+ case 14: pszTagID = "ISP (Black Pearl 0)"; i32SideBandType = RGXDBG_ISP; break;
+ case 15: pszTagID = "TPF (Black Pearl 0)"; i32SideBandType = RGXDBG_TPF; break;
+ case 16: pszTagID = "USCS (Black Pearl 0)"; i32SideBandType = RGXDBG_USCS; break;
+ case 17: pszTagID = "PPP (Black Pearl 0)"; i32SideBandType = RGXDBG_PPP; break;
+ case 18: pszTagID = "VCE (Black Pearl 0)"; i32SideBandType = RGXDBG_VCE; break;
+ case 19: pszTagID = "FBCDC (Black Pearl 0)"; i32SideBandType = RGXDBG_FBCDC; break;
+ case 20: pszTagID = "MCU (Texas 1)"; i32SideBandType = RGXDBG_MCU; break;
+ case 21: pszTagID = "PDS (Texas 1)"; i32SideBandType = RGXDBG_PDS; break;
+ case 22: pszTagID = "PBE0 (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
+ case 23: pszTagID = "PBE1 (Texas 1)"; i32SideBandType = RGXDBG_PBE; break;
+ case 24: pszTagID = "MCU (Texas 2)"; i32SideBandType = RGXDBG_MCU; break;
+ case 25: pszTagID = "PDS (Texas 2)"; i32SideBandType = RGXDBG_PDS; break;
+ case 26: pszTagID = "PBE0 (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
+ case 27: pszTagID = "PBE1 (Texas 2)"; i32SideBandType = RGXDBG_PBE; break;
+ case 28: pszTagID = "VDMS (Black Pearl 1)"; i32SideBandType = RGXDBG_VDMS; break;
+ case 29: pszTagID = "IPF (Black Pearl 1)"; i32SideBandType = RGXDBG_IPF; break;
+ case 30: pszTagID = "ISP (Black Pearl 1)"; i32SideBandType = RGXDBG_ISP; break;
+ case 31: pszTagID = "TPF (Black Pearl 1)"; i32SideBandType = RGXDBG_TPF; break;
+ case 32: pszTagID = "USCS (Black Pearl 1)"; i32SideBandType = RGXDBG_USCS; break;
+ case 33: pszTagID = "PPP (Black Pearl 1)"; i32SideBandType = RGXDBG_PPP; break;
+ case 34: pszTagID = "VCE (Black Pearl 1)"; i32SideBandType = RGXDBG_VCE; break;
+ case 35: pszTagID = "FBCDC (Black Pearl 1)"; i32SideBandType = RGXDBG_FBCDC; break;
+ case 36: pszTagID = "MCU (Texas 3)"; i32SideBandType = RGXDBG_MCU; break;
+ case 37: pszTagID = "PDS (Texas 3)"; i32SideBandType = RGXDBG_PDS; break;
+ case 38: pszTagID = "PBE0 (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
+ case 39: pszTagID = "PBE1 (Texas 3)"; i32SideBandType = RGXDBG_PBE; break;
+ }
+
+ switch (i32SideBandType)
+ {
+ case RGXDBG_META:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "DCache - Thread 0"; break;
+ case 0x1: pszTagSB = "ICache - Thread 0"; break;
+ case 0x2: pszTagSB = "JTag - Thread 0"; break;
+ case 0x3: pszTagSB = "Slave bus - Thread 0"; break;
+ case 0x4: pszTagSB = "DCache - Thread 1"; break;
+ case 0x5: pszTagSB = "ICache - Thread 1"; break;
+ case 0x6: pszTagSB = "JTag - Thread 1"; break;
+ case 0x7: pszTagSB = "Slave bus - Thread 1"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_TLA:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Pixel data"; break;
+ case 0x1: pszTagSB = "Command stream data"; break;
+ case 0x2: pszTagSB = "Fence or flush"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_VDMM:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Control Stream - Read Only"; break;
+ case 0x1: pszTagSB = "PPP State - Read Only"; break;
+ case 0x2: pszTagSB = "Indices - Read Only"; break;
+ case 0x4: pszTagSB = "Call Stack - Read/Write"; break;
+ case 0x6: pszTagSB = "DrawIndirect - Read Only"; break;
+ case 0xA: pszTagSB = "Context State - Write Only"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_CDM:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Control Stream"; break;
+ case 0x1: pszTagSB = "Indirect Data"; break;
+ case 0x2: pszTagSB = "Event Write"; break;
+ case 0x3: pszTagSB = "Context State"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_IPP:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Macrotile Header"; break;
+ case 0x1: pszTagSB = "Region Header"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_PM:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "PMA_TAFSTACK"; break;
+ case 0x1: pszTagSB = "PMA_TAMLIST"; break;
+ case 0x2: pszTagSB = "PMA_3DFSTACK"; break;
+ case 0x3: pszTagSB = "PMA_3DMLIST"; break;
+ case 0x4: pszTagSB = "PMA_PMCTX0"; break;
+ case 0x5: pszTagSB = "PMA_PMCTX1"; break;
+ case 0x6: pszTagSB = "PMA_MAVP"; break;
+ case 0x7: pszTagSB = "PMA_UFSTACK"; break;
+ case 0x8: pszTagSB = "PMD_TAFSTACK"; break;
+ case 0x9: pszTagSB = "PMD_TAMLIST"; break;
+ case 0xA: pszTagSB = "PMD_3DFSTACK"; break;
+ case 0xB: pszTagSB = "PMD_3DMLIST"; break;
+ case 0xC: pszTagSB = "PMD_PMCTX0"; break;
+ case 0xD: pszTagSB = "PMD_PMCTX1"; break;
+ case 0xF: pszTagSB = "PMD_UFSTACK"; break;
+ case 0x10: pszTagSB = "PMA_TAMMUSTACK"; break;
+ case 0x11: pszTagSB = "PMA_3DMMUSTACK"; break;
+ case 0x12: pszTagSB = "PMD_TAMMUSTACK"; break;
+ case 0x13: pszTagSB = "PMD_3DMMUSTACK"; break;
+ case 0x14: pszTagSB = "PMA_TAUFSTACK"; break;
+ case 0x15: pszTagSB = "PMA_3DUFSTACK"; break;
+ case 0x16: pszTagSB = "PMD_TAUFSTACK"; break;
+ case 0x17: pszTagSB = "PMD_3DUFSTACK"; break;
+ case 0x18: pszTagSB = "PMA_TAVFP"; break;
+ case 0x19: pszTagSB = "PMD_3DVFP"; break;
+ case 0x1A: pszTagSB = "PMD_TAVFP"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_TILING:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "PSG Control Stream TP0"; break;
+ case 0x1: pszTagSB = "TPC TP0"; break;
+ case 0x2: pszTagSB = "VCE0"; break;
+ case 0x3: pszTagSB = "VCE1"; break;
+ case 0x4: pszTagSB = "PSG Control Stream TP1"; break;
+ case 0x5: pszTagSB = "TPC TP1"; break;
+ case 0x8: pszTagSB = "PSG Region Header TP0"; break;
+ case 0xC: pszTagSB = "PSG Region Header TP1"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_VDMS:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "Context State - Write Only"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_IPF:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x00:
+ case 0x20: pszTagSB = "CPF"; break;
+ case 0x01: pszTagSB = "DBSC"; break;
+ case 0x02:
+ case 0x04:
+ case 0x06:
+ case 0x08:
+ case 0x0A:
+ case 0x0C:
+ case 0x0E:
+ case 0x10: pszTagSB = "Control Stream"; break;
+ case 0x03:
+ case 0x05:
+ case 0x07:
+ case 0x09:
+ case 0x0B:
+ case 0x0D:
+ case 0x0F:
+ case 0x11: pszTagSB = "Primitive Block"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_ISP:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x00: pszTagSB = "ZLS read/write"; break;
+ case 0x20: pszTagSB = "Occlusion query read/write"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_TPF:
+ {
+ switch (ui32TagSB)
+ {
+ case 0x0: pszTagSB = "TPF0: Primitive Block"; break;
+ case 0x1: pszTagSB = "TPF0: Depth Bias"; break;
+ case 0x2: pszTagSB = "TPF0: Per Primitive IDs"; break;
+ case 0x3: pszTagSB = "CPF - Tables"; break;
+ case 0x4: pszTagSB = "TPF1: Primitive Block"; break;
+ case 0x5: pszTagSB = "TPF1: Depth Bias"; break;
+ case 0x6: pszTagSB = "TPF1: Per Primitive IDs"; break;
+ case 0x7: pszTagSB = "CPF - Data: Pipe 0"; break;
+ case 0x8: pszTagSB = "TPF2: Primitive Block"; break;
+ case 0x9: pszTagSB = "TPF2: Depth Bias"; break;
+ case 0xA: pszTagSB = "TPF2: Per Primitive IDs"; break;
+ case 0xB: pszTagSB = "CPF - Data: Pipe 1"; break;
+ case 0xC: pszTagSB = "TPF3: Primitive Block"; break;
+ case 0xD: pszTagSB = "TPF3: Depth Bias"; break;
+ case 0xE: pszTagSB = "TPF3: Per Primitive IDs"; break;
+ case 0xF: pszTagSB = "CPF - Data: Pipe 2"; break;
+ }
+ break;
+ }
+
+ case RGXDBG_FBCDC:
+ {
+ IMG_UINT32 ui32Req = (ui32TagSB >> 2) & 0x3;
+ IMG_UINT32 ui32MCUSB = ui32TagSB & 0x3;
+
+ IMG_CHAR* pszReqId = (ui32TagSB & 0x10)?"FBDC":"FBC";
+ IMG_CHAR* pszOrig = "";
+
+ switch (ui32Req)
+ {
+ case 0x0: pszOrig = "ZLS"; break;
+ case 0x1: pszOrig = (ui32TagSB & 0x10)?"MCU":"PBE"; break;
+ case 0x2: pszOrig = "Host"; break;
+ case 0x3: pszOrig = "TLA"; break;
+ }
+ OSSNPrintf(pszScratchBuf, ui32ScratchBufSize,
+ "%s Request, originator %s, MCU sideband 0x%X",
+ pszReqId, pszOrig, ui32MCUSB);
+ pszTagSB = pszScratchBuf;
+ break;
+ }
+
+ case RGXDBG_MCU:
+ {
+ IMG_UINT32 ui32SetNumber = (ui32TagSB >> 5) & 0x7;
+ IMG_UINT32 ui32WayNumber = (ui32TagSB >> 2) & 0x7;
+ IMG_UINT32 ui32Group = ui32TagSB & 0x3;
+
+ IMG_CHAR* pszGroup = "";
+
+ switch (ui32Group)
+ {
+ case 0x0: pszGroup = "Banks 0-1"; break;
+ case 0x1: pszGroup = "Banks 2-3"; break;
+ case 0x2: pszGroup = "Banks 4-5"; break;
+ case 0x3: pszGroup = "Banks 6-7"; break;
+ }
+
+ OSSNPrintf(pszScratchBuf, ui32ScratchBufSize,
+ "Set=%d, Way=%d, %s", ui32SetNumber, ui32WayNumber, pszGroup);
+ pszTagSB = pszScratchBuf;
+ break;
+ }
+
+ default:
+ {
+ OSSNPrintf(pszScratchBuf, ui32ScratchBufSize, "SB=0x%02x", ui32TagSB);
+ pszTagSB = pszScratchBuf;
+ break;
+ }
+ }
+
+ *ppszTagID = pszTagID;
+ *ppszTagSB = pszTagSB;
+}
+#endif
+
+
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*!
+*******************************************************************************
+
+ @Function _RGXDumpRGXBIFBank
+
+ @Description
+
+ Dump BIF Bank state in human readable form.
+
+ @Input psDevInfo - RGX device info
+ @Input eBankID - BIF identifier
+ @Input ui64MMUStatus - MMU Status register value
+ @Input ui64ReqStatus - BIF request Status register value
+ @Input bBIFSummary - Flag to check whether the function is called
+ as a part of the debug dump summary or
+ as a part of a HWR log
+ @Return IMG_VOID
+
+******************************************************************************/
+static IMG_VOID _RGXDumpRGXBIFBank(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXDBG_BIF_ID eBankID,
+ IMG_UINT64 ui64MMUStatus,
+ IMG_UINT64 ui64ReqStatus,
+ IMG_BOOL bBIFSummary)
+{
+
+ if (ui64MMUStatus == 0x0)
+ {
+ PVR_DUMPDEBUG_LOG(("%s - OK", pszBIFNames[eBankID]));
+ }
+ else
+ {
+ /* Bank 0 & 1 share the same fields */
+ PVR_DUMPDEBUG_LOG(("%s%s - FAULT:",
+ (bBIFSummary)?"":" ",
+ pszBIFNames[eBankID]));
+
+ /* MMU Status */
+ {
+ IMG_UINT32 ui32PC =
+ (ui64MMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_CLRMSK) >>
+ RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_SHIFT;
+
+ IMG_UINT32 ui32PageSize =
+ (ui64MMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_PAGE_SIZE_CLRMSK) >>
+ RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_PAGE_SIZE_SHIFT;
+
+ IMG_UINT32 ui32MMUDataType =
+ (ui64MMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_DATA_TYPE_CLRMSK) >>
+ RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_DATA_TYPE_SHIFT;
+
+ IMG_BOOL bROFault = (ui64MMUStatus & RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_RO_EN) != 0;
+ IMG_BOOL bProtFault = (ui64MMUStatus & RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_FAULT_PM_META_RO_EN) != 0;
+
+ PVR_DUMPDEBUG_LOG(("%s * MMU status (0x%016llX): PC = %d%s, Page Size = %d, MMU data type = %d%s%s.",
+ (bBIFSummary)?"":" ",
+ ui64MMUStatus,
+ ui32PC,
+ (ui32PC < 0x8)?"":_RGXDecodePMPC(ui32PC),
+ ui32PageSize,
+ ui32MMUDataType,
+ (bROFault)?", Read Only fault":"",
+ (bProtFault)?", PM/META protection fault":""));
+ }
+
+ /* Req Status */
+ {
+ IMG_CHAR *pszTagID;
+ IMG_CHAR *pszTagSB;
+ IMG_CHAR aszScratch[RGX_DEBUG_STR_SIZE];
+
+ IMG_BOOL bRead = (ui64ReqStatus & RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_RNW_EN) != 0;
+ IMG_UINT32 ui32TagSB =
+ (ui64ReqStatus & ~RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_SB_CLRMSK) >>
+ RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_SB_SHIFT;
+ IMG_UINT32 ui32TagID =
+ (ui64ReqStatus & ~RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_ID_CLRMSK) >>
+ RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_TAG_ID_SHIFT;
+ IMG_UINT64 ui64Addr = (ui64ReqStatus & ~RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_CLRMSK);
+
+ _RGXDecodeBIFReqTags(eBankID, ui32TagID, ui32TagSB, &pszTagID, &pszTagSB, &aszScratch[0], RGX_DEBUG_STR_SIZE);
+
+ PVR_DUMPDEBUG_LOG(("%s * Request (0x%016llX): %s (%s), %s 0x%010llX.",
+ (bBIFSummary)?"":" ",
+ ui64ReqStatus,
+ pszTagID,
+ pszTagSB,
+ (bRead)?"Reading from":"Writing to",
+ ui64Addr));
+ }
+
+ /* Check if the host thinks this fault is valid */
+ if(bBIFSummary)
+ {
+ IMG_UINT32 ui32PC =
+ (ui64MMUStatus & ~RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_CLRMSK) >>
+ RGX_CR_BIF_FAULT_BANK0_MMU_STATUS_CAT_BASE_SHIFT;
+ IMG_DEV_VIRTADDR sFaultDevVAddr;
+ IMG_DEV_PHYADDR sPCDevPAddr;
+
+ sPCDevPAddr.uiAddr = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_CAT_BASEN(ui32PC));
+ sFaultDevVAddr.uiAddr = (ui64ReqStatus & ~RGX_CR_BIF_FAULT_BANK0_REQ_STATUS_ADDRESS_CLRMSK);
+ RGXCheckFaultAddress(psDevInfo, &sFaultDevVAddr, &sPCDevPAddr);
+ }
+
+ }
+
+}
+#endif
+
+
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+/*!
+*******************************************************************************
+
+ @Function _RGXDumpRGXMMUFaultStatus
+
+ @Description
+
+ Dump MMU Fault status in human readable form.
+
+ @Input psDevInfo - RGX device info
+ @Input ui64MMUStatus - MMU Status register value
+ @Input bSummary - Flag to check whether the function is called
+ as a part of the debug dump summary or
+ as a part of a HWR log
+ @Return IMG_VOID
+
+******************************************************************************/
+static IMG_VOID _RGXDumpRGXMMUFaultStatus(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT64 ui64MMUStatus,
+ IMG_BOOL bSummary)
+{
+ if (ui64MMUStatus == 0x0)
+ {
+ PVR_DUMPDEBUG_LOG(("MMU (Core) - OK"));
+ }
+ else
+ {
+ IMG_UINT32 ui32PC = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_CONTEXT_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_CONTEXT_SHIFT;
+ IMG_UINT64 ui64Addr = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_ADDRESS_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_ADDRESS_SHIFT;
+ IMG_UINT32 ui32Requester = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_REQ_ID_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_REQ_ID_SHIFT;
+ IMG_UINT32 ui32SideBand = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_TAG_SB_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_TAG_SB_SHIFT;
+ IMG_UINT32 ui32MMULevel = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_LEVEL_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_LEVEL_SHIFT;
+ IMG_BOOL bRead = (ui64MMUStatus & RGX_CR_MMU_FAULT_STATUS_RNW_EN) != 0;
+ IMG_BOOL bFault = (ui64MMUStatus & RGX_CR_MMU_FAULT_STATUS_FAULT_EN) != 0;
+ IMG_BOOL bROFault = ((ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_TYPE_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_TYPE_SHIFT) == 0x2;
+ IMG_BOOL bProtFault = ((ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_TYPE_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_TYPE_SHIFT) == 0x3;
+ IMG_CHAR aszScratch[RGX_DEBUG_STR_SIZE];
+ IMG_CHAR *pszTagID;
+ IMG_CHAR *pszTagSB;
+
+ _RGXDecodeMMUReqTags(ui32Requester, ui32SideBand, &pszTagID, &pszTagSB, aszScratch, RGX_DEBUG_STR_SIZE);
+
+ PVR_DUMPDEBUG_LOG(("%sMMU (Core) - FAULT:", (bSummary)?"":" "));
+ PVR_DUMPDEBUG_LOG(("%s * MMU status (0x%016llX): PC = %d, %s 0x%010llX, %s (%s)%s%s%s%s.",
+ (bSummary)?"":" ",
+ ui64MMUStatus,
+ ui32PC,
+ (bRead)?"Reading from":"Writing to",
+ ui64Addr,
+ pszTagID,
+ pszTagSB,
+ (bFault)?", Fault":"",
+ (bROFault)?", Read Only fault":"",
+ (bProtFault)?", PM/META protection fault":"",
+ _RGXDecodeMMULevel(ui32MMULevel)));
+ }
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function _RGXDumpRGXMMUMetaFaultStatus
+
+ @Description
+
+ Dump MMU Meta Fault state in human readable form.
+
+ @Input psDevInfo - RGX device info
+ @Input ui64MMUStatus - MMU Status register value
+ @Input bSummary - Flag to check whether the function is called
+ as a part of the debug dump summary or
+ as a part of a HWR log
+ @Return IMG_VOID
+
+******************************************************************************/
+static IMG_VOID _RGXDumpRGXMMUMetaFaultStatus(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT64 ui64MMUStatus,
+ IMG_BOOL bSummary)
+{
+ if (ui64MMUStatus == 0x0)
+ {
+ PVR_DUMPDEBUG_LOG(("MMU (Meta) - OK"));
+ }
+ else
+ {
+ IMG_UINT32 ui32PC = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_META_CONTEXT_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_META_CONTEXT_SHIFT;
+ IMG_UINT64 ui64Addr = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_META_ADDRESS_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_META_ADDRESS_SHIFT;
+ IMG_UINT32 ui32SideBand = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_META_TAG_SB_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_META_TAG_SB_SHIFT;
+ IMG_UINT32 ui32Requester = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_META_REQ_ID_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_META_REQ_ID_SHIFT;
+ IMG_UINT32 ui32MMULevel = (ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_META_LEVEL_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_META_LEVEL_SHIFT;
+ IMG_BOOL bRead = (ui64MMUStatus & RGX_CR_MMU_FAULT_STATUS_META_RNW_EN) != 0;
+ IMG_BOOL bFault = (ui64MMUStatus & RGX_CR_MMU_FAULT_STATUS_META_FAULT_EN) != 0;
+ IMG_BOOL bROFault = ((ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_META_TYPE_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_META_TYPE_SHIFT) == 0x2;
+ IMG_BOOL bProtFault = ((ui64MMUStatus & ~RGX_CR_MMU_FAULT_STATUS_META_TYPE_CLRMSK) >>
+ RGX_CR_MMU_FAULT_STATUS_META_TYPE_SHIFT) == 0x3;
+ IMG_CHAR aszScratch[RGX_DEBUG_STR_SIZE];
+ IMG_CHAR *pszTagID;
+ IMG_CHAR *pszTagSB;
+
+ _RGXDecodeMMUReqTags(ui32Requester, ui32SideBand, &pszTagID, &pszTagSB, aszScratch, RGX_DEBUG_STR_SIZE);
+
+ PVR_DUMPDEBUG_LOG(("%sMMU (Meta) - FAULT:", (bSummary)?"":" "));
+ PVR_DUMPDEBUG_LOG(("%s * MMU status (0x%016llX): PC = %d, %s 0x%010llX, %s (%s)%s%s%s%s.",
+ (bSummary)?"":" ",
+ ui64MMUStatus,
+ ui32PC,
+ (bRead)?"Reading from":"Writing to",
+ ui64Addr,
+ pszTagID,
+ pszTagSB,
+ (bFault)?", Fault":"",
+ (bROFault)?", Read Only fault":"",
+ (bProtFault)?", PM/META protection fault":"",
+ _RGXDecodeMMULevel(ui32MMULevel)));
+ }
+}
+#endif
+
+
+/*!
+*******************************************************************************
+
+ @Function _RGXDumpFWAssert
+
+ @Description
+
+ Dump FW assert strings when a thread asserts.
+
+ @Input psRGXFWIfTraceBufCtl - RGX FW trace buffer
+
+ @Return IMG_VOID
+
+******************************************************************************/
+static IMG_VOID _RGXDumpFWAssert(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl)
+{
+ IMG_CHAR *pszTraceAssertPath;
+ 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));
+ }
+ }
+}
+
+static IMG_VOID _RGXDumpFWPoll(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl)
+{
+ IMG_UINT32 i;
+ for (i = 0; i < RGXFW_THREAD_NUM; i++)
+ {
+ if (psRGXFWIfTraceBufCtl->aui32CrPollAddr[i])
+ {
+ PVR_DUMPDEBUG_LOG(("T%u polling %s (reg:0x%08X mask:0x%08X)",
+ i,
+ ((psRGXFWIfTraceBufCtl->aui32CrPollAddr[i] & RGXFW_POLL_TYPE_SET)?("set"):("unset")),
+ psRGXFWIfTraceBufCtl->aui32CrPollAddr[i] & ~RGXFW_POLL_TYPE_SET,
+ psRGXFWIfTraceBufCtl->aui32CrPollMask[i]));
+ }
+ }
+
+}
+
+static IMG_VOID _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl, 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 + 1] = { "GP(", "2D(", "TA(", "3D(", "CDM(",
+#if defined(RGX_FEATURE_RAY_TRACING)
+ "RTU(", "SHG(",
+#endif /* RGX_FEATURE_RAY_TRACING */
+ NULL };
+
+ const IMG_CHAR *pszMsgHeader = "Number of HWR: ";
+ IMG_CHAR *pszLockupType = "";
+ RGXFWIF_HWRINFOBUF *psHWInfoBuf = psDevInfo->psRGXFWIfHWRInfoBuf;
+ RGX_HWRINFO *psHWRInfo;
+ IMG_UINT32 ui32MsgHeaderSize = OSStringLength(pszMsgHeader);
+ IMG_UINT32 ui32HWRRecoveryFlags;
+ IMG_UINT32 ui32ReadIndex;
+
+ for (dm = 0; dm < RGXFWIF_DM_MAX; dm++)
+ {
+ if (psRGXFWIfTraceBufCtl->aui16HwrDmLockedUpCount[dm] ||
+ psRGXFWIfTraceBufCtl->aui16HwrDmOverranCount[dm])
+ {
+ bAnyLocked = IMG_TRUE;
+ break;
+ }
+ }
+
+ if (!bAnyLocked && (psRGXFWIfTraceBufCtl->ui32HWRStateFlags & RGXFWIF_HWR_HARDWARE_OK))
+ {
+ /* No HWR situation, print nothing */
+ return;
+ }
+
+ ui32LineSize = sizeof(IMG_CHAR) * ( ui32MsgHeaderSize +
+ (RGXFWIF_DM_MAX*( 4/*DM name + left parenthesis*/ +
+ 5/*UINT16 max num of digits*/ +
+ 1/*slash*/ +
+ 5/*UINT16 max num of digits*/ +
+ 3/*right parenthesis + comma + space*/)) +
+ 7 + (RGXFWIF_DM_MAX*6)/* FALSE() + (UINT16 max num + comma) per DM */ +
+ 1/* \0 */);
+
+ pszLine = OSAllocMem(ui32LineSize);
+ if (pszLine == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"_RGXDumpRGXDebugSummary: Out of mem allocating line string (size: %d)", ui32LineSize));
+ return;
+ }
+
+ OSStringCopy(pszLine,pszMsgHeader);
+ pszTemp = pszLine + ui32MsgHeaderSize;
+
+ for (dm = 0; (dm < RGXFWIF_DM_MAX) && (apszDmNames[dm] != IMG_NULL); dm++)
+ {
+ OSStringCopy(pszTemp,apszDmNames[dm]);
+ pszTemp += OSStringLength(apszDmNames[dm]);
+ pszTemp += OSSNPrintf(pszTemp,
+ 5 + 1 + 5 + 1 + 5 + 1 + 1 + 1 + 1 /* UINT16 + slash + UINT16 + plus + UINT16 + right parenthesis + comma + space + \0 */,
+ "%u/%u+%u), ",
+ psRGXFWIfTraceBufCtl->aui16HwrDmRecoveredCount[dm],
+ psRGXFWIfTraceBufCtl->aui16HwrDmLockedUpCount[dm],
+ psRGXFWIfTraceBufCtl->aui16HwrDmOverranCount[dm]);
+ }
+
+ OSStringCopy(pszTemp, "FALSE(");
+ pszTemp += 6;
+
+ for (dm = 0; (dm < RGXFWIF_DM_MAX) && (apszDmNames[dm] != IMG_NULL); dm++)
+ {
+ pszTemp += OSSNPrintf(pszTemp,
+ 5 + 1 + 1 /* UINT16 max num + comma + \0 */,
+ (dm < RGXFWIF_DM_MAX-1 ? "%u," : "%u)"),
+ psRGXFWIfTraceBufCtl->aui16HwrDmFalseDetectCount[dm]);
+ }
+
+ PVR_DUMPDEBUG_LOG((pszLine));
+
+ OSFreeMem(pszLine);
+
+ /* Print out per HWR info */
+ for (dm = 0; (dm < RGXFWIF_DM_MAX) && (apszDmNames[dm] != IMG_NULL); dm++)
+ {
+ if (dm == RGXFWIF_DM_GP)
+ {
+ PVR_DUMPDEBUG_LOG(("DM %d (GP)", dm));
+ }
+ else
+ {
+ PVR_DUMPDEBUG_LOG(("DM %d (HWRflags 0x%08x)", dm, psRGXFWIfTraceBufCtl->aui32HWRRecoveryFlags[dm]));
+ }
+
+ ui32ReadIndex = 0;
+ for(i = 0 ; i < RGXFWIF_HWINFO_MAX ; i++)
+ {
+ psHWRInfo = &psHWInfoBuf->sHWRInfo[ui32ReadIndex];
+
+ if((psHWRInfo->eDM == dm) && (psHWRInfo->ui32HWRNumber != 0))
+ {
+ 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_GUILTY_LOCKUP) { pszLockupType = ", Innocent Overrun"; }
+
+ PVR_DUMPDEBUG_LOG((" Recovery %d: PID = %d, frame = %d, HWRTData = 0x%08X, EventStatus = 0x%08X, CRTimer = 0x%012llX%s",
+ psHWRInfo->ui32HWRNumber,
+ psHWRInfo->ui32PID,
+ psHWRInfo->ui32FrameNum,
+ psHWRInfo->ui32ActiveHWRTData,
+ psHWRInfo->ui32EventStatus,
+ psHWRInfo->ui64CRTimer,
+ pszLockupType));
+
+ switch(psHWRInfo->eHWRType)
+ {
+#if !defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+ case RGX_HWRTYPE_BIF0FAULT:
+ case RGX_HWRTYPE_BIF1FAULT:
+ {
+ _RGXDumpRGXBIFBank(pfnDumpDebugPrintf, psDevInfo, RGXFWIF_HWRTYPE_BIF_BANK_GET(psHWRInfo->eHWRType),
+ psHWRInfo->uHWRData.sBIFInfo.ui64BIFMMUStatus,
+ psHWRInfo->uHWRData.sBIFInfo.ui64BIFReqStatus,
+ IMG_FALSE);
+ }
+ break;
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+ case RGX_HWRTYPE_TEXASBIF0FAULT:
+ {
+ _RGXDumpRGXBIFBank(pfnDumpDebugPrintf, psDevInfo, RGXDBG_TEXAS_BIF,
+ psHWRInfo->uHWRData.sBIFInfo.ui64BIFMMUStatus,
+ psHWRInfo->uHWRData.sBIFInfo.ui64BIFReqStatus,
+ IMG_FALSE);
+ }
+ break;
+#endif
+#else
+ case RGX_HWRTYPE_MMUFAULT:
+ {
+ _RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, psDevInfo,
+ psHWRInfo->uHWRData.sMMUInfo.ui64MMUStatus,
+ IMG_FALSE);
+ }
+ break;
+
+ case RGX_HWRTYPE_MMUMETAFAULT:
+ {
+ _RGXDumpRGXMMUMetaFaultStatus(pfnDumpDebugPrintf, psDevInfo,
+ psHWRInfo->uHWRData.sMMUInfo.ui64MMUStatus,
+ IMG_FALSE);
+ }
+ break;
+#endif
+
+ case RGX_HWRTYPE_POLLFAILURE:
+ {
+ PVR_DUMPDEBUG_LOG((" T%u polling %s (reg:0x%08X mask: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));
+ }
+ break;
+
+ case RGX_HWRTYPE_OVERRUN:
+ case RGX_HWRTYPE_UNKNOWNFAILURE:
+ {
+ /* Nothing to dump */
+ }
+ break;
+
+ default:
+ {
+ PVR_ASSERT(IMG_FALSE);
+ }
+ break;
+ }
+ }
+
+ if(ui32ReadIndex == RGXFWIF_HWINFO_MAX_FIRST - 1)
+ ui32ReadIndex = psHWInfoBuf->ui32WriteIndex;
+ else
+ ui32ReadIndex = (ui32ReadIndex + 1) - (ui32ReadIndex / RGXFWIF_HWINFO_LAST_INDEX) * RGXFWIF_HWINFO_MAX_LAST;
+ }
+ }
+}
+
+/*!
+*******************************************************************************
+
+ @Function _RGXDumpRGXDebugSummary
+
+ @Description
+
+ Dump a summary in human readable form with the RGX state
+
+ @Input psDevInfo - RGX device info
+
+ @Return IMG_VOID
+
+******************************************************************************/
+static IMG_VOID _RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo, IMG_BOOL bRGXPoweredON)
+{
+ IMG_CHAR *pszState;
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+
+ if (bRGXPoweredON)
+ {
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE)
+ IMG_UINT64 ui64RegValMMUStatus;
+
+ ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_FAULT_STATUS);
+ _RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, psDevInfo, ui64RegValMMUStatus, IMG_TRUE);
+
+ ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_FAULT_STATUS_META);
+ _RGXDumpRGXMMUMetaFaultStatus(pfnDumpDebugPrintf, psDevInfo, ui64RegValMMUStatus, IMG_TRUE);
+#else
+ IMG_UINT64 ui64RegValMMUStatus, ui64RegValREQStatus;
+
+ ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK0_MMU_STATUS);
+ ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK0_REQ_STATUS);
+
+ _RGXDumpRGXBIFBank(pfnDumpDebugPrintf, psDevInfo, RGXDBG_BIF0, ui64RegValMMUStatus, ui64RegValREQStatus, IMG_TRUE);
+
+ ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK1_MMU_STATUS);
+ ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_FAULT_BANK1_REQ_STATUS);
+
+ _RGXDumpRGXBIFBank(pfnDumpDebugPrintf, psDevInfo, RGXDBG_BIF1, ui64RegValMMUStatus, ui64RegValREQStatus, IMG_TRUE);
+
+#if defined(RGX_FEATURE_CLUSTER_GROUPING)
+#if defined(RGX_NUM_PHANTOMS)
+ {
+ IMG_UINT32 ui32Phantom;
+
+ for (ui32Phantom = 0; ui32Phantom < RGX_NUM_PHANTOMS; ui32Phantom++)
+ {
+ /* This can't be done as it may interfere with the FW... */
+ /*OSWriteHWReg64(RGX_CR_TEXAS_INDIRECT, ui32Phantom);*/
+
+ ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS);
+ ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS);
+
+ _RGXDumpRGXBIFBank(pfnDumpDebugPrintf, psDevInfo, RGXDBG_TEXAS, ui64RegValMMUStatus, ui64RegValREQStatus, IMG_TRUE);
+ }
+ }
+#else
+ ui64RegValMMUStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_MMU_STATUS);
+ ui64RegValREQStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TEXAS_BIF_FAULT_BANK0_REQ_STATUS);
+
+ _RGXDumpRGXBIFBank(pfnDumpDebugPrintf, psDevInfo, RGXDBG_TEXAS_BIF, ui64RegValMMUStatus, ui64RegValREQStatus, IMG_TRUE);
+#endif
+#endif
+#endif
+ }
+
+ /* Firmware state */
+ switch (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;
+ }
+
+ default:
+ {
+ pszState = "UNKNOWN";
+ break;
+ }
+ }
+
+ if (psRGXFWIfTraceBuf == IMG_NULL)
+ {
+ PVR_DUMPDEBUG_LOG(("RGX FW State: %s", pszState));
+
+ /* can't dump any more information */
+ return;
+ }
+
+ PVR_DUMPDEBUG_LOG(("RGX FW State: %s (HWRState 0x%08x)", pszState, psRGXFWIfTraceBuf->ui32HWRStateFlags));
+ PVR_DUMPDEBUG_LOG(("RGX FW Power State: %s (APM %s: %d ok, %d denied, %d other, %d total)",
+ pszPowStateName[psRGXFWIfTraceBuf->ePowState],
+ (psDevInfo->pvAPMISRData)?"enabled":"disabled",
+ psDevInfo->ui32ActivePMReqOk,
+ psDevInfo->ui32ActivePMReqDenied,
+ psDevInfo->ui32ActivePMReqTotal - psDevInfo->ui32ActivePMReqOk - psDevInfo->ui32ActivePMReqDenied,
+ psDevInfo->ui32ActivePMReqTotal));
+
+
+ _RGXDumpFWAssert(pfnDumpDebugPrintf, psRGXFWIfTraceBuf);
+
+ _RGXDumpFWPoll(pfnDumpDebugPrintf, psRGXFWIfTraceBuf);
+
+ _RGXDumpFWHWRInfo(pfnDumpDebugPrintf, psRGXFWIfTraceBuf, psDevInfo);
+
+}
+
+static IMG_VOID _RGXDumpMetaSPExtraDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+/* List of extra META Slave Port debug registers */
+#define RGX_META_SP_EXTRA_DEBUG \
+ X(RGX_CR_META_SP_MSLVCTRL0) \
+ X(RGX_CR_META_SP_MSLVCTRL1) \
+ X(RGX_CR_META_SP_MSLVIRQSTATUS) \
+ X(RGX_CR_META_SP_MSLVIRQENABLE) \
+ X(RGX_CR_META_SP_MSLVIRQLEVEL)
+
+ IMG_UINT32 ui32Idx, ui32RegIdx;
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32RegAddr;
+
+ const IMG_UINT32 aui32DebugRegAddr [] = {
+#define X(A) A,
+ RGX_META_SP_EXTRA_DEBUG
+#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:"));
+
+ /* 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 = aui32DebugRegAddr[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));
+ }
+ }
+
+}
+
+/*
+ RGXDumpDebugInfo
+*/
+IMG_VOID RGXDumpDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ IMG_UINT32 i;
+
+ for(i=0;i<=DEBUG_REQUEST_VERBOSITY_MAX;i++)
+ {
+ RGXDebugRequestProcess(pfnDumpDebugPrintf, psDevInfo, i);
+ }
+}
+
+
+#if defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS)
+/*
+ * Array of all the Firmware Trace log IDs used to convert the trace data.
+ */
+typedef struct _TRACEBUF_LOG_ {
+ RGXFW_LOG_SFids eSFId;
+ IMG_CHAR *pszName;
+ IMG_CHAR *pszFmt;
+ IMG_UINT32 ui32ArgNum;
+} TRACEBUF_LOG;
+
+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)
+{
+ 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)
+ {
+ IMG_UINT32 ui32Count;
+ IMG_CHAR *pszString;
+ TRACEBUF_LOG *psLogDef2;
+
+ /*
+ * 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;
+}
+
+IMG_VOID RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
+ static IMG_BOOL bIntegrityCheckPassed = IMG_FALSE;
+
+ /* Check that the firmware trace is correctly defined... */
+ if (!bIntegrityCheckPassed)
+ {
+ bIntegrityCheckPassed = _FirmwareTraceIntegrityCheck(pfnDumpDebugPrintf);
+ if (!bIntegrityCheckPassed)
+ {
+ return;
+ }
+ }
+
+ /* Dump FW trace information... */
+ if (psRGXFWIfTraceBufCtl != IMG_NULL)
+ {
+ IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
+ IMG_UINT32 tid;
+
+ /* 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++)
+ {
+ IMG_UINT32 *ui32TraceBuf = psRGXFWIfTraceBufCtl->sTraceBuf[tid].aui32TraceBuffer;
+ IMG_UINT32 ui32TracePtr = psRGXFWIfTraceBufCtl->sTraceBuf[tid].ui32TracePointer;
+ IMG_UINT32 ui32Count = 0;
+
+ while (ui32Count < RGXFW_TRACE_BUFFER_SIZE)
+ {
+ IMG_UINT32 ui32Data, ui32DataToId;
+
+ /* Find the first valid log ID, skipping whitespace... */
+ do
+ {
+ ui32Data = ui32TraceBuf[ui32TracePtr];
+ ui32DataToId = idToStringID(ui32Data);
+
+ /* If an unrecognized id is found check if it is valid, if it is tracebuf needs updating. */
+ if (ui32DataToId == RGXFW_SF_LAST && RGXFW_LOG_VALIDID(ui32Data))
+ {
+ PVR_DUMPDEBUG_LOG(("ERROR: Unrecognized id (%x). From here on the trace might be wrong!", ui32Data));
+ return;
+ }
+
+ /* Update the trace pointer... */
+ ui32TracePtr = (ui32TracePtr + 1) % RGXFW_TRACE_BUFFER_SIZE;
+ ui32Count++;
+ } while ((RGXFW_SF_LAST == ui32DataToId || ui32DataToId >= RGXFW_SF_FIRST) &&
+ ui32Count < RGXFW_TRACE_BUFFER_SIZE);
+
+ if (ui32Count < RGXFW_TRACE_BUFFER_SIZE)
+ {
+ IMG_UINT64 ui64RGXTimer;
+
+ /* 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;
+ }
+
+ /*
+ * 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.
+ */
+ OSStringCopy(szBuffer, "%llu:T%u-%s> ");
+ OSStringCopy(&szBuffer[OSStringLength(szBuffer)], SFs[ui32DataToId].name);
+ szBuffer[OSStringLength(szBuffer)-1] = '\0';
+ ui64RGXTimer = (IMG_UINT64)(ui32TraceBuf[(ui32TracePtr + 0) % RGXFW_TRACE_BUFFER_SIZE]) << 32 |
+ (IMG_UINT64)(ui32TraceBuf[(ui32TracePtr + 1) % RGXFW_TRACE_BUFFER_SIZE]);
+ PVR_DUMPDEBUG_LOG((szBuffer, ui64RGXTimer, tid, groups[RGXFW_SF_GID(ui32Data)],
+ ui32TraceBuf[(ui32TracePtr + 2) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 3) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 4) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 5) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 6) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 7) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 8) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 9) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 10) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 11) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 12) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 13) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 14) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 15) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 16) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 17) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 18) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 19) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 20) % RGXFW_TRACE_BUFFER_SIZE],
+ ui32TraceBuf[(ui32TracePtr + 21) % RGXFW_TRACE_BUFFER_SIZE]));
+
+ /* Update the trace pointer... */
+ ui32TracePtr = (ui32TracePtr + 2 + RGXFW_SF_PARAMNUM(ui32Data)) % RGXFW_TRACE_BUFFER_SIZE;
+ ui32Count = (ui32Count + 2 + RGXFW_SF_PARAMNUM(ui32Data));
+ }
+ }
+ }
+ }
+}
+#endif
+
+
+static 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";
+ }
+}
+
+IMG_VOID RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32VerbLevel)
+{
+ PVRSRV_ERROR eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDebugRequestProcess : failed to acquire lock, error:0x%x", eError));
+ return;
+ }
+
+ switch (ui32VerbLevel)
+ {
+ case DEBUG_REQUEST_VERBOSITY_LOW :
+ {
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE ePowerState;
+ IMG_BOOL bRGXPoweredON;
+
+ ui32DeviceIndex = psDevInfo->psDeviceNode->sDevId.ui32DeviceIndex;
+
+ eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &ePowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDebugRequestProcess: Error retrieving RGX power state. No debug info dumped."));
+ goto Exit;
+ }
+
+ bRGXPoweredON = (ePowerState == PVRSRV_DEV_POWER_STATE_ON);
+
+ PVR_DUMPDEBUG_LOG(("------[ RGX summary ]------"));
+ PVR_DUMPDEBUG_LOG(("RGX BVNC: %s", RGX_BVNC_KM));
+ PVR_DUMPDEBUG_LOG(("RGX Power State: %s", _RGXGetDebugDevPowerStateString(ePowerState)));
+
+ _RGXDumpRGXDebugSummary(pfnDumpDebugPrintf, psDevInfo, bRGXPoweredON);
+
+ if (bRGXPoweredON)
+ {
+
+ 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));
+
+ /* Forcing bit 6 of MslvCtrl1 to 0 to avoid internal reg read going though the core */
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL1, 0x0);
+
+ eError = RGXRunScript(psDevInfo, psDevInfo->psScripts->asDbgCommands, RGX_MAX_INIT_COMMANDS, PDUMP_FLAGS_CONTINUOUS, pfnDumpDebugPrintf);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"RGXDebugRequestProcess: RGXRunScript failed (%d) - Retry", eError));
+
+ /* use thread1 for slave port accesses */
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL1, 0x1 << RGX_CR_META_SP_MSLVCTRL1_THREAD_SHIFT);
+
+ eError = RGXRunScript(psDevInfo, psDevInfo->psScripts->asDbgCommands, RGX_MAX_INIT_COMMANDS, PDUMP_FLAGS_CONTINUOUS, pfnDumpDebugPrintf);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXDebugRequestProcess: RGXRunScript retry failed (%d) - Dump Slave Port debug information", eError));
+ _RGXDumpMetaSPExtraDebugInfo(pfnDumpDebugPrintf, psDevInfo);
+ }
+
+ /* use thread0 again */
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL1, 0x0 << RGX_CR_META_SP_MSLVCTRL1_THREAD_SHIFT);
+ }
+ }
+ else
+ {
+ PVR_DUMPDEBUG_LOG((" (!) RGX power is down. No registers dumped"));
+ }
+
+ {
+ RGXFWIF_DM eKCCBType;
+
+ /*
+ Dump out the kernel CCBs.
+ */
+ for (eKCCBType = 0; eKCCBType < RGXFWIF_DM_MAX; eKCCBType++)
+ {
+ RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->apsKernelCCBCtl[eKCCBType];
+
+ if (psKCCBCtl != IMG_NULL)
+ {
+ PVR_DUMPDEBUG_LOG(("RGX Kernel CCB %u WO:0x%X RO:0x%X",
+ eKCCBType, psKCCBCtl->ui32WriteOffset, psKCCBCtl->ui32ReadOffset));
+ }
+ }
+ }
+
+ /* Dump the KCCB commands executed */
+ {
+ PVR_DUMPDEBUG_LOG(("RGX Kernel CCB commands executed = %d",
+ psDevInfo->psRGXFWIfTraceBuf->ui32KCCBCmdsExecuted));
+ }
+
+ /* Dump the IRQ info */
+ {
+ PVR_DUMPDEBUG_LOG(("RGX FW IRQ count = %d, last sampled in MISR = %d",
+ psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount,
+ g_ui32HostSampleIRQCount));
+ }
+
+ /* Dump the FW config flags */
+ {
+ RGXFWIF_INIT *psRGXFWInit;
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc,
+ (IMG_VOID **)&psRGXFWInit);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXDebugRequestProcess: Failed to acquire kernel fw if ctl (%u)",
+ eError));
+ goto Exit;
+ }
+
+ PVR_DUMPDEBUG_LOG(("RGX FW config flags = 0x%X", psRGXFWInit->ui32ConfigFlags));
+
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
+ }
+
+ break;
+
+ }
+ case DEBUG_REQUEST_VERBOSITY_MEDIUM :
+ {
+ IMG_INT tid;
+ /* Dump FW trace information */
+ if (psDevInfo->psRGXFWIfTraceBuf != IMG_NULL)
+ {
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
+
+ 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;
+
+ pui32TraceBuffer = &psRGXFWIfTraceBufCtl->sTraceBuf[tid].aui32TraceBuffer[0];
+
+ /* each element in the line is 8 characters plus a space. The '+1' is because of the final trailing '\0'. */
+ pszLine = OSAllocMem(9*RGXFW_TRACE_BUFFER_LINESIZE+1);
+ if (pszLine == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXDebugRequestProcess: Out of mem allocating line string (size: %d)", 9*RGXFW_TRACE_BUFFER_LINESIZE));
+ goto Exit;
+ }
+
+ /* Print the tracepointer */
+ 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"));
+ }
+
+ 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", RGXFW_TRACE_BUFFER_SIZE));
+
+ for (i = 0; i < RGXFW_TRACE_BUFFER_SIZE; i += RGXFW_TRACE_BUFFER_LINESIZE)
+ {
+ IMG_UINT32 k = 0;
+ IMG_UINT32 ui32Line = 0x0;
+ IMG_UINT32 ui32LineOffset = i*sizeof(IMG_UINT32);
+ IMG_CHAR *pszBuf = pszLine;
+
+ for (k = 0; k < RGXFW_TRACE_BUFFER_LINESIZE; k++)
+ {
+ 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 && bPrevLineWasZero)
+ {
+ ui32CountLines++;
+ }
+ else if (bLineIsAllZeros && !bPrevLineWasZero)
+ {
+ bPrevLineWasZero = IMG_TRUE;
+ ui32CountLines = 0;
+ PVR_DUMPDEBUG_LOG(("FWT[%08x]: 00000000 ... 00000000", ui32LineOffset));
+ }
+ else
+ {
+ if (bPrevLineWasZero)
+ {
+ PVR_DUMPDEBUG_LOG(("FWT[%08x]: %d lines were all zero", ui32LineOffset, ui32CountLines));
+ }
+ else
+ {
+
+ PVR_DUMPDEBUG_LOG(("FWT[%08x]:%s", ui32LineOffset, pszLine));
+ }
+ bPrevLineWasZero = IMG_FALSE;
+ }
+
+ }
+ 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);
+ }
+ }
+
+ {
+ PVR_DUMPDEBUG_LOG(("------[ Stalled FWCtxs ]------"));
+
+ CheckForStalledTransferCtxt(psDevInfo, pfnDumpDebugPrintf);
+ CheckForStalledRenderCtxt(psDevInfo, pfnDumpDebugPrintf);
+#if !defined(UNDER_WDDM)
+ CheckForStalledComputeCtxt(psDevInfo, pfnDumpDebugPrintf);
+#endif
+#if defined(RGX_FEATURE_RAY_TRACING)
+ CheckForStalledRayCtxt(psDevInfo, pfnDumpDebugPrintf);
+#endif
+ }
+ break;
+ }
+ case DEBUG_REQUEST_VERBOSITY_HIGH:
+ {
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE ePowerState;
+ IMG_BOOL bRGXPoweredON;
+
+ ui32DeviceIndex = psDevInfo->psDeviceNode->sDevId.ui32DeviceIndex;
+
+ eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &ePowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDebugRequestProcess: Error retrieving RGX power state. No debug info dumped."));
+ return;
+ }
+
+ bRGXPoweredON = (ePowerState == PVRSRV_DEV_POWER_STATE_ON);
+
+ PVR_DUMPDEBUG_LOG(("------[ Debug bus ]------"));
+
+ _RGXDumpRGXDebugSummary(pfnDumpDebugPrintf, psDevInfo, bRGXPoweredON);
+
+ if (bRGXPoweredON)
+ {
+ eError = RGXRunScript(psDevInfo, psDevInfo->psScripts->asDbgBusCommands, RGX_MAX_DBGBUS_COMMANDS, PDUMP_FLAGS_CONTINUOUS, pfnDumpDebugPrintf);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"RGXDebugRequestProcess: RGXRunScript failed (%s)", PVRSRVGetErrorStringKM(eError)));
+ }
+ break;
+ }
+ }
+ default:
+ break;
+ }
+
+Exit:
+ PVRSRVPowerUnlock();
+}
+
+/*
+ RGXPanic
+*/
+IMG_VOID RGXPanic(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVR_LOG(("RGX panic"));
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
+ OSPanic();
+}
+
+/*
+ RGXQueryDMState
+*/
+PVRSRV_ERROR RGXQueryDMState(PVRSRV_RGXDEV_INFO *psDevInfo, RGXFWIF_DM eDM, RGXFWIF_DM_STATE *peState, RGXFWIF_DEV_VIRTADDR *psCommonContextDevVAddr)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
+
+ if (eDM >= RGXFWIF_DM_MAX)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ PVR_DPF((PVR_DBG_ERROR,"RGXQueryDMState: eDM parameter is out of range (%u)",eError));
+ return eError;
+ }
+
+ if (peState == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ PVR_DPF((PVR_DBG_ERROR,"RGXQueryDMState: peState is NULL (%u)",eError));
+ return eError;
+ }
+
+ if (psCommonContextDevVAddr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ PVR_DPF((PVR_DBG_ERROR,"RGXQueryDMState: psCommonContextDevVAddr is NULL (%u)",eError));
+ return eError;
+ }
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXQueryDMState: Failed (%d) to acquire address for trace buffer", eError));
+ return eError;
+ }
+
+ if (psRGXFWIfTraceBufCtl->apsHwrDmFWCommonContext[eDM].ui32Addr)
+ {
+ *peState = RGXFWIF_DM_STATE_LOCKEDUP;
+ }
+ else
+ {
+ *peState = RGXFWIF_DM_STATE_NORMAL;
+ }
+
+ *psCommonContextDevVAddr = psRGXFWIfTraceBufCtl->apsHwrDmFWCommonContext[eDM];
+
+ return eError;
+}
+
+
+/******************************************************************************
+ End of file (rgxdebug.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.h
new file mode 100644
index 000000000000..a02c41e7f572
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxdebug.h
@@ -0,0 +1,152 @@
+/*************************************************************************/ /*!
+@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 "pvrsrv.h"
+#include "rgxdevice.h"
+
+
+/*!
+*******************************************************************************
+
+ @Function RGXPanic
+
+ @Description
+
+ Called when an unrecoverable situation is detected. Dumps RGX debug
+ information and tells the OS to panic.
+
+ @Input psDevInfo - RGX device info
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID RGXPanic(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+
+ @Function RGXDumpDebugInfo
+
+ @Description
+
+ Dump useful debugging info. Dumps lesser information than PVRSRVDebugRequest.
+ Does not dump debugging information for all requester types.(SysDebug, ServerSync info)
+
+ @Input pfnDumpDebugPrintf - Optional replacement print function
+ @Input psDevInfo - RGX device info
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID RGXDumpDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+
+ @Function RGXDebugRequestProcess
+
+ @Description
+
+ This function will print out the debug for the specificed level of
+ verbosity
+
+ @Input pfnDumpDebugPrintf - Optional replacement print function
+ @Input psDevInfo - RGX device info
+ @Input ui32VerbLevel - Verbosity level
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32VerbLevel);
+
+
+#if defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS)
+/*!
+*******************************************************************************
+
+ @Function RGXDumpFirmwareTrace
+
+ @Description Dumps the decoded version of the firmware trace buffer.
+
+ Dump useful debugging info
+
+ @Input pfnDumpDebugPrintf - Optional replacement print function
+ @Input psDevInfo - RGX device info
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+ PVRSRV_RGXDEV_INFO *psDevInfo);
+#endif
+
+
+/*!
+*******************************************************************************
+
+ @Function RGXQueryDMState
+
+ @Description
+
+ Query DM state
+
+ @Input psDevInfo - RGX device info
+ @Input eDM - DM number for which to return status
+ @Output peState - RGXFWIF_DM_STATE
+ @Output psComCtxDevVAddr - If DM is locked-up, Firmware address of Firmware Common Context, otherwise IMG_NULL
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXQueryDMState(PVRSRV_RGXDEV_INFO *psDevInfo, RGXFWIF_DM eDM, RGXFWIF_DM_STATE *peState, RGXFWIF_DEV_VIRTADDR *psComCtxDevVAddr);
+
+
+#endif /* __RGXDEBUG_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxdevice.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxdevice.h
new file mode 100644
index 000000000000..b342a52113e9
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxdevice.h
@@ -0,0 +1,371 @@
+/*************************************************************************/ /*!
+@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 "pvrsrv_device_types.h"
+#include "mmu_common.h"
+#include "rgx_fwif_km.h"
+#include "rgx_fwif.h"
+#include "rgxscript.h"
+#include "cache_external.h"
+#include "device.h"
+#include "osfunc.h"
+
+typedef struct _RGX_SERVER_COMMON_CONTEXT_ RGX_SERVER_COMMON_CONTEXT;
+
+typedef struct {
+ DEVMEM_MEMDESC *psFWFrameworkMemDesc;
+ IMG_DEV_VIRTADDR *psMCUFenceAddr;
+} RGX_COMMON_CONTEXT_INFO;
+
+
+/*!
+ ******************************************************************************
+ * Device state flags
+ *****************************************************************************/
+#define RGXKM_DEVICE_STATE_ZERO_FREELIST (0x1 << 0) /*!< Zeroing the physical pages of reconstructed free lists */
+#define RGXKM_DEVICE_STATE_FTRACE_EN (0x1 << 1) /*!< Used to enable device FTrace thread to consume HWPerf data */
+#define RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN (0x1 << 2) /*!< Used to disable the Devices Watchdog logging */
+
+/*!
+ ******************************************************************************
+ * GPU DVFS History CB
+ *****************************************************************************/
+
+#define RGX_GPU_DVFS_HIST_SIZE 200 /* History size must NOT be greater than 4096 (2^12) */
+
+typedef struct _RGX_GPU_DVFS_HIST_
+{
+ IMG_UINT32 ui32CurrentDVFSId; /*!< Current history entry index */
+ IMG_UINT32 aui32DVFSClockCB[RGX_GPU_DVFS_HIST_SIZE]; /*!< Circular buffer of DVFS clock history in Hz */
+} RGX_GPU_DVFS_HIST;
+
+typedef struct _RGXFWIF_GPU_UTIL_STATS_
+{
+ IMG_BOOL bValid; /* If TRUE, statistics are valid.
+ It might be FALSE if DVFS frequency is not provided by system layer (see RGX_TIMING_INFORMATION::ui32CoreClockSpeed)
+ or if the driver couldn't acquire the PowerLock */
+ IMG_BOOL bIncompleteData; /* TRUE when the host couldn't find enough data to cover the whole time window, so the returned values could be wrong */
+ IMG_UINT32 ui32GpuStatActiveHigh; /* GPU active high ratio expressed in 0,01% units */
+ IMG_UINT32 ui32GpuStatActiveLow; /* GPU active low (i.e. TLA active only) ratio expressed in 0,01% units */
+ IMG_UINT32 ui32GpuStatBlocked; /* GPU blocked ratio expressed in 0,01% units */
+ IMG_UINT32 ui32GpuStatIdle; /* GPU idle ratio expressed in 0,01% units */
+} RGXFWIF_GPU_UTIL_STATS;
+
+typedef struct _RGX_REG_CONFIG_
+{
+ IMG_BOOL bEnabled;
+ RGXFWIF_PWR_EVT ePowerIslandToPush;
+ IMG_UINT32 ui32NumRegRecords;
+} RGX_REG_CONFIG;
+
+typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
+
+/* there is a corresponding define in rgxapi.h */
+#define RGX_MAX_TIMER_QUERIES 16
+
+/*!
+ ******************************************************************************
+ * RGX Device info
+ *****************************************************************************/
+
+typedef struct _PVRSRV_RGXDEV_INFO_
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ PVRSRV_DEVICE_CLASS eDeviceClass;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ IMG_UINT8 ui8VersionMajor;
+ IMG_UINT8 ui8VersionMinor;
+ IMG_UINT32 ui32CoreConfig;
+ IMG_UINT32 ui32CoreFlags;
+
+ IMG_BOOL bFirmwareInitialised;
+ IMG_BOOL bPDPEnabled;
+
+ /* Kernel mode linear address of device registers */
+ IMG_PVOID 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;
+
+ IMG_BOOL bEnableProcessStats;
+
+ /* Firmware memory context info */
+ DEVMEM_CONTEXT *psKernelDevmemCtx;
+ DEVMEM_HEAP *psFirmwareHeap;
+ MMU_CONTEXT *psKernelMMUCtx;
+ IMG_UINT32 ui32KernelCatBaseIdReg;
+ IMG_UINT32 ui32KernelCatBaseId;
+ IMG_UINT32 ui32KernelCatBaseReg;
+ IMG_UINT32 ui32KernelCatBaseWordSize;
+ IMG_UINT32 ui32KernelCatBaseAlignShift;
+ IMG_UINT32 ui32KernelCatBaseShift;
+ IMG_UINT64 ui64KernelCatBaseMask;
+
+ IMG_VOID *pvDeviceMemoryHeap;
+
+ /* Kernel CCBs */
+ DEVMEM_MEMDESC *apsKernelCCBCtlMemDesc[RGXFWIF_DM_MAX]; /*!< memdesc for kernel CCB control */
+ RGXFWIF_CCB_CTL *apsKernelCCBCtl[RGXFWIF_DM_MAX]; /*!< kernel CCB control kernel mapping */
+ DEVMEM_MEMDESC *apsKernelCCBMemDesc[RGXFWIF_DM_MAX]; /*!< memdesc for kernel CCB */
+ IMG_UINT8 *apsKernelCCB[RGXFWIF_DM_MAX]; /*!< kernel CCB kernel mapping */
+
+ /* Firmware CCBs */
+ DEVMEM_MEMDESC *apsFirmwareCCBCtlMemDesc[RGXFWIF_DM_MAX]; /*!< memdesc for Firmware CCB control */
+ RGXFWIF_CCB_CTL *apsFirmwareCCBCtl[RGXFWIF_DM_MAX]; /*!< kernel CCB control Firmware mapping */
+ DEVMEM_MEMDESC *apsFirmwareCCBMemDesc[RGXFWIF_DM_MAX]; /*!< memdesc for Firmware CCB */
+ IMG_UINT8 *apsFirmwareCCB[RGXFWIF_DM_MAX]; /*!< kernel CCB Firmware mapping */
+
+ /*
+ if we don't preallocate the pagetables we must
+ insert newly allocated page tables dynamically
+ */
+ IMG_VOID *pvMMUContextList;
+
+ IMG_UINT32 ui32ClkGateStatusReg;
+ IMG_UINT32 ui32ClkGateStatusMask;
+ RGX_SCRIPTS *psScripts;
+
+ DEVMEM_MEMDESC *psRGXFWCodeMemDesc;
+ DEVMEM_EXPORTCOOKIE sRGXFWCodeExportCookie;
+
+ DEVMEM_MEMDESC *psRGXFWDataMemDesc;
+ DEVMEM_EXPORTCOOKIE sRGXFWDataExportCookie;
+
+ DEVMEM_MEMDESC *psRGXFWCorememMemDesc;
+ DEVMEM_EXPORTCOOKIE sRGXFWCorememExportCookie;
+
+ DEVMEM_MEMDESC *psRGXFWIfTraceBufCtlMemDesc;
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBuf;
+
+ DEVMEM_MEMDESC *psRGXFWIfHWRInfoBufCtlMemDesc;
+ RGXFWIF_HWRINFOBUF *psRGXFWIfHWRInfoBuf;
+
+ DEVMEM_MEMDESC *psRGXFWIfGpuUtilFWCbCtlMemDesc;
+ RGXFWIF_GPU_UTIL_FWCB *psRGXFWIfGpuUtilFWCb;
+
+ DEVMEM_MEMDESC *psRGXFWIfHWPerfBufMemDesc;
+ IMG_BYTE *psRGXFWIfHWPerfBuf;
+ IMG_UINT32 ui32RGXFWIfHWPerfBufSize; /* in bytes */
+
+ DEVMEM_MEMDESC *psRGXFWIfCorememDataStoreMemDesc;
+
+ DEVMEM_MEMDESC *psRGXFWIfRegCfgMemDesc;
+
+ DEVMEM_MEMDESC *psRGXFWIfInitMemDesc;
+
+ DEVMEM_MEMDESC *psRGXFWIfRuntimeCfgMemDesc;
+ RGXFWIF_RUNTIME_CFG *psRGXFWIfRuntimeCfg;
+
+#if defined(RGXFW_ALIGNCHECKS)
+ DEVMEM_MEMDESC *psRGXFWAlignChecksMemDesc;
+#endif
+
+ DEVMEM_MEMDESC *psRGXFWSigTAChecksMemDesc;
+ IMG_UINT32 ui32SigTAChecksSize;
+
+ DEVMEM_MEMDESC *psRGXFWSig3DChecksMemDesc;
+ IMG_UINT32 ui32Sig3DChecksSize;
+
+#if defined(RGX_FEATURE_RAY_TRACING)
+ DEVMEM_MEMDESC *psRGXFWSigRTChecksMemDesc;
+ IMG_UINT32 ui32SigRTChecksSize;
+
+ DEVMEM_MEMDESC *psRGXFWSigSHChecksMemDesc;
+ IMG_UINT32 ui32SigSHChecksSize;
+#endif
+
+ IMG_VOID *pvLISRData;
+ IMG_VOID *pvMISRData;
+ IMG_VOID *pvAPMISRData;
+
+ DEVMEM_MEMDESC *psRGXFaultAddressMemDesc;
+
+#if defined(FIX_HW_BRN_37200)
+ DEVMEM_MEMDESC *psRGXFWHWBRN37200MemDesc;
+#endif
+
+#if defined(RGX_FEATURE_SLC_VIVT)
+ DEVMEM_MEMDESC *psSLC3FenceMemDesc;
+#endif
+
+#if defined (PDUMP)
+ IMG_BOOL abDumpedKCCBCtlAlready[RGXFWIF_DM_MAX];
+
+#endif
+
+ /*! Handles to the lock and stream objects used to transport
+ * HWPerf data to user side clients. See RGXHWPerfInit() RGXHWPerfDeinit().
+ * Set during initialisation if the application hint turns bit 7
+ * 'Enable HWPerf' on in the ConfigFlags sent to the FW. FW stores this
+ * bit in the RGXFW_CTL.ui32StateFlags member. They may also get
+ * set by the API RGXCtrlHWPerf(). Thus these members may be 0 if HWPerf is
+ * not enabled as these members are created on demand and destroyed at
+ * driver unload.
+ */
+ POS_LOCK hLockHWPerfStream;
+ IMG_HANDLE hHWPerfStream;
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+ IMG_HANDLE hGPUTraceCmdCompleteHandle;
+ IMG_BOOL bFTraceGPUEventsEnabled;
+ IMG_HANDLE hGPUTraceTLConnection;
+ IMG_HANDLE hGPUTraceTLStream;
+ IMG_UINT64 ui64LastSampledTimeCorrOSTimeStamp;
+#endif
+
+ /* If we do 10 deferred memory allocations per second, then the ID would warp 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 ui32ActivePMReqTotal;
+
+ IMG_HANDLE hProcessQueuesMISR;
+
+ IMG_UINT32 ui32DeviceFlags; /*!< Flags to track general device state */
+
+ /* Poll data for detecting firmware fatal errors */
+ IMG_UINT32 aui32CrLastPollAddr[RGXFW_THREAD_NUM];
+ IMG_UINT32 ui32KCCBCmdsExecutedLastTime;
+ IMG_BOOL bKCCBCmdsWaitingLastTime;
+ IMG_UINT32 ui32GEOTimeoutsLastTime;
+
+ /* Client stall detection */
+ IMG_BOOL bStalledClient;
+
+ /* 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 */
+
+
+ /* GPU DVFS History and GPU Utilization stats */
+ RGX_GPU_DVFS_HIST* psGpuDVFSHistory;
+ RGXFWIF_GPU_UTIL_STATS (*pfnGetGpuUtilStats) (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+ /* Register configuration */
+ RGX_REG_CONFIG sRegCongfig;
+
+ IMG_BOOL bIgnoreFurtherIRQs;
+ DLLIST_NODE sMemoryContextList;
+
+ POSWR_LOCK hRenderCtxListLock;
+ POSWR_LOCK hComputeCtxListLock;
+ POSWR_LOCK hTransferCtxListLock;
+ POSWR_LOCK hRaytraceCtxListLock;
+ POSWR_LOCK hMemoryCtxListLock;
+
+ /* Linked lists of contexts on this device */
+ DLLIST_NODE sRenderCtxtListHead;
+ DLLIST_NODE sComputeCtxtListHead;
+ DLLIST_NODE sTransferCtxtListHead;
+ DLLIST_NODE sRaytraceCtxtListHead;
+
+ DLLIST_NODE sCommonCtxtListHead;
+ IMG_UINT32 ui32CommonCtxtCurrentID; /*!< ID assigned to the next common context */
+} 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;
+ IMG_BOOL bHasTDMetaCodePhysHeap;
+ IMG_UINT32 uiTDMetaCodePhysHeapID;
+ IMG_BOOL bHasTDSecureBufPhysHeap;
+ IMG_UINT32 uiTDSecureBufPhysHeapID;
+} RGX_DATA;
+
+
+/*
+ RGX PDUMP register bank name (prefix)
+*/
+#define RGX_PDUMPREG_NAME "RGXREG"
+
+#endif /* __RGXDEVICE_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxfwutils.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxfwutils.c
new file mode 100644
index 000000000000..d8510eaac2b5
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxfwutils.c
@@ -0,0 +1,3967 @@
+ /*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+
+#include "lists.h"
+
+#include "rgxdefs_km.h"
+#include "rgx_fwif_km.h"
+#include "pdump_km.h"
+#include "osfunc.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "devicemem_server.h"
+#include "pvr_debug.h"
+#include "rgxfwutils.h"
+#include "rgx_fwif.h"
+#include "rgx_fwif_alignchecks_km.h"
+#include "rgx_fwif_resetframework.h"
+#include "rgx_pdump_panics.h"
+#include "rgxheapconfig.h"
+#include "pvrsrv.h"
+#include "rgxdebug.h"
+#include "rgxhwperf.h"
+#include "rgxccb.h"
+#include "rgxcompute.h"
+#include "rgxtransfer.h"
+#if defined(RGX_FEATURE_RAY_TRACING)
+#include "rgxray.h"
+#endif
+#include "dc_server.h"
+#include "rgxmem.h"
+#include "rgxta3d.h"
+#include "rgxutils.h"
+#include "sync_internal.h"
+#include "tlstream.h"
+
+#if defined(TDMETACODE)
+#include "physmem_osmem.h"
+#endif
+
+#ifdef __linux__
+#include <linux/kernel.h> // sprintf
+#include <linux/string.h> // strncpy, strlen
+#include "trace_events.h"
+#else
+#include <stdio.h>
+#endif
+
+#include "process_stats.h"
+
+/* Kernel CCB length */
+#define RGXFWIF_KCCB_TA_NUMCMDS_LOG2 (6)
+#define RGXFWIF_KCCB_3D_NUMCMDS_LOG2 (6)
+#define RGXFWIF_KCCB_2D_NUMCMDS_LOG2 (6)
+#define RGXFWIF_KCCB_CDM_NUMCMDS_LOG2 (6)
+#define RGXFWIF_KCCB_GP_NUMCMDS_LOG2 (6)
+#define RGXFWIF_KCCB_RTU_NUMCMDS_LOG2 (6)
+#define RGXFWIF_KCCB_SHG_NUMCMDS_LOG2 (6)
+
+/* Firmware CCB length */
+#define RGXFWIF_FWCCB_TA_NUMCMDS_LOG2 (4)
+#define RGXFWIF_FWCCB_3D_NUMCMDS_LOG2 (4)
+#define RGXFWIF_FWCCB_2D_NUMCMDS_LOG2 (4)
+#define RGXFWIF_FWCCB_CDM_NUMCMDS_LOG2 (4)
+#define RGXFWIF_FWCCB_GP_NUMCMDS_LOG2 (4)
+#define RGXFWIF_FWCCB_RTU_NUMCMDS_LOG2 (4)
+#define RGXFWIF_FWCCB_SHG_NUMCMDS_LOG2 (4)
+
+#if defined(RGX_FEATURE_SLC_VIVT)
+static PVRSRV_ERROR _AllocateSLC3Fence(PVRSRV_RGXDEV_INFO* psDevInfo, RGXFWIF_INIT* psRGXFWInit)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_MEMDESC** ppsSLC3FenceMemDesc = &psDevInfo->psSLC3FenceMemDesc;
+
+ PVR_DPF_ENTERED;
+
+ eError = DevmemAllocate(psDevInfo->psFirmwareHeap,
+ 1,
+ ROGUE_CACHE_LINE_SIZE,
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED,
+ "SLC3 Fence WA",
+ 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->psFirmwareHeap,
+ &psRGXFWInit->sSLC3FenceDevVAddr);
+ if (eError != PVRSRV_OK)
+ {
+ DevmemFwFree(*ppsSLC3FenceMemDesc);
+ }
+
+ PVR_DPF_RETURN_RC1(eError, *ppsSLC3FenceMemDesc);
+}
+
+static IMG_VOID _FreeSLC3Fence(PVRSRV_RGXDEV_INFO* psDevInfo)
+{
+ DEVMEM_MEMDESC* psSLC3FenceMemDesc = psDevInfo->psSLC3FenceMemDesc;
+
+ if (psSLC3FenceMemDesc)
+ {
+ DevmemReleaseDevVirtAddr(psSLC3FenceMemDesc);
+ DevmemFree(psSLC3FenceMemDesc);
+ }
+}
+#endif
+
+static IMG_VOID __MTSScheduleWrite(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Value)
+{
+ /* ensure memory is flushed before kicking MTS */
+ OSWriteMemoryBarrier();
+
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MTS_SCHEDULE, ui32Value);
+
+ /* ensure the MTS kick goes through before continuing */
+ OSMemoryBarrier();
+}
+
+
+/*!
+*******************************************************************************
+ @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,
+ const IMG_CHAR* pszBufferName)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_FLAGS_T uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ /* Allocate memory for the checks */
+ PDUMPCOMMENT("Allocate memory for %s signature checks", pszBufferName);
+ eError = DevmemFwAllocate(psDevInfo,
+ ui32SigChecksBufSize,
+ uiMemAllocFlags,
+ "SignatureChecks",
+ ppsSigChecksMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate %d bytes for signature checks (%u)",
+ ui32SigChecksBufSize,
+ eError));
+ return eError;
+ }
+
+ /* Prepare the pointer for the fw to access that memory */
+ RGXSetFirmwareAddress(&psSigBufCtl->psBuffer,
+ *ppsSigChecksMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ DevmemPDumpLoadMem( *ppsSigChecksMemDesc,
+ 0,
+ ui32SigChecksBufSize,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ psSigBufCtl->ui32LeftSizeInRegs = ui32SigChecksBufSize / sizeof(IMG_UINT32);
+
+ return PVRSRV_OK;
+}
+
+#if defined(RGXFW_ALIGNCHECKS)
+/*!
+*******************************************************************************
+ @Function RGXFWSetupAlignChecks
+ @Description
+ @Input psDevInfo
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXFWSetupAlignChecks(PVRSRV_RGXDEV_INFO* psDevInfo,
+ RGXFWIF_DEV_VIRTADDR *psAlignChecksDevFW,
+ IMG_UINT32 *pui32RGXFWAlignChecks,
+ IMG_UINT32 ui32RGXFWAlignChecksSize)
+{
+ IMG_UINT32 aui32RGXFWAlignChecksKM[] = { RGXFW_ALIGN_CHECKS_INIT_KM };
+ IMG_UINT32 ui32RGXFWAlingChecksTotal = sizeof(aui32RGXFWAlignChecksKM) + ui32RGXFWAlignChecksSize;
+ IMG_UINT32* paui32AlignChecks;
+ PVRSRV_ERROR eError;
+
+ /* Allocate memory for the checks */
+ PDUMPCOMMENT("Allocate memory for alignment checks");
+ eError = DevmemFwAllocate(psDevInfo,
+ ui32RGXFWAlingChecksTotal,
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | PVRSRV_MEMALLOCFLAG_UNCACHED,
+ "AlignmentChecks",
+ &psDevInfo->psRGXFWAlignChecksMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate %d bytes for alignment checks (%u)",
+ ui32RGXFWAlingChecksTotal,
+ eError));
+ goto failAlloc;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWAlignChecksMemDesc,
+ (IMG_VOID **)&paui32AlignChecks);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire kernel addr for alignment checks (%u)",
+ eError));
+ goto failAqCpuAddr;
+ }
+
+ /* Copy the values */
+ OSMemCopy(paui32AlignChecks, &aui32RGXFWAlignChecksKM[0], sizeof(aui32RGXFWAlignChecksKM));
+ paui32AlignChecks += sizeof(aui32RGXFWAlignChecksKM)/sizeof(IMG_UINT32);
+
+ OSMemCopy(paui32AlignChecks, pui32RGXFWAlignChecks, ui32RGXFWAlignChecksSize);
+
+ DevmemPDumpLoadMem( psDevInfo->psRGXFWAlignChecksMemDesc,
+ 0,
+ ui32RGXFWAlingChecksTotal,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ /* Prepare the pointer for the fw to access that memory */
+ RGXSetFirmwareAddress(psAlignChecksDevFW,
+ psDevInfo->psRGXFWAlignChecksMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ return PVRSRV_OK;
+
+
+
+
+failAqCpuAddr:
+ DevmemFwFree(psDevInfo->psRGXFWAlignChecksMemDesc);
+failAlloc:
+
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+static IMG_VOID RGXFWFreeAlignChecks(PVRSRV_RGXDEV_INFO* psDevInfo)
+{
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWAlignChecksMemDesc);
+ DevmemFwFree(psDevInfo->psRGXFWAlignChecksMemDesc);
+}
+#endif
+
+
+IMG_VOID RGXSetFirmwareAddress(RGXFWIF_DEV_VIRTADDR *ppDest,
+ DEVMEM_MEMDESC *psSrc,
+ IMG_UINT32 uiExtraOffset,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eError;
+ IMG_DEV_VIRTADDR psDevVirtAddr;
+ IMG_UINT64 ui64Offset;
+#if !defined(HW_ERN_45914)
+ DEVMEM_FLAGS_T uiDevFlags;
+#endif
+
+ eError = DevmemAcquireDevVirtAddr(psSrc, &psDevVirtAddr);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /* Convert to an address in META memmap */
+ ui64Offset = psDevVirtAddr.uiAddr + uiExtraOffset - RGX_FIRMWARE_HEAP_BASE;
+
+ /* The biggest offset for the Shared region that can be addressed */
+ PVR_ASSERT(ui64Offset < 3*RGXFW_SEGMMU_DMAP_SIZE);
+
+#if !defined(HW_ERN_45914)
+ /* when ERN45914, temporarily disable META cached addresses sent from the
+ host because they are undistinguishable from SLC cached and some of them
+ need to be SLC uncached. */
+ /* The address offset fixes whether the mem is cached or uncached */
+ DevmemGetFlags(psSrc, &uiDevFlags);
+ if (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) & uiDevFlags)
+ {
+ ppDest->ui32Addr = ((IMG_UINT32) ui64Offset) | RGXFW_BOOTLDR_META_ADDR;
+ }
+ else
+#endif
+ {
+ ppDest->ui32Addr = ((IMG_UINT32) ui64Offset) | RGXFW_SEGMMU_DMAP_ADDR_START;
+ }
+
+ if (ui32Flags & RFW_FWADDR_NOREF_FLAG)
+ {
+ DevmemReleaseDevVirtAddr(psSrc);
+ }
+}
+
+#if defined(RGX_FEATURE_DMA)
+IMG_VOID RGXSetDMAAddress(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);
+}
+#endif
+
+IMG_VOID RGXUnsetFirmwareAddress(DEVMEM_MEMDESC *psSrc)
+{
+ DevmemReleaseDevVirtAddr(psSrc);
+}
+
+struct _RGX_SERVER_COMMON_CONTEXT_ {
+ DEVMEM_MEMDESC *psFWCommonContextMemDesc;
+ PRGXFWIF_FWCOMMONCONTEXT sFWCommonContextFWAddr;
+ 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;
+ RGXFWIF_CONTEXT_RESET_REASON eLastResetReason;
+};
+
+PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ const IMG_CHAR *pszContextName,
+ DEVMEM_MEMDESC *psAllocatedMemDesc,
+ IMG_UINT32 ui32AllocatedOffset,
+ DEVMEM_MEMDESC *psFWMemContextMemDesc,
+ DEVMEM_MEMDESC *psContextStateMemDesc,
+ IMG_UINT32 ui32CCBAllocSize,
+ IMG_UINT32 ui32Priority,
+ 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;
+ PVRSRV_ERROR eError;
+
+ /*
+ Allocate all the resources that are required
+ */
+ psServerCommonContext = OSAllocMem(sizeof(*psServerCommonContext));
+ if (psServerCommonContext == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ if (psAllocatedMemDesc)
+ {
+ PDUMPCOMMENT("Using existing MemDesc for Rogue firmware %s context (offset = %d)",
+ pszContextName,
+ ui32AllocatedOffset);
+ ui32FWCommonContextOffset = ui32AllocatedOffset;
+ psServerCommonContext->psFWCommonContextMemDesc = psAllocatedMemDesc;
+ psServerCommonContext->bCommonContextMemProvided = IMG_TRUE;
+ }
+ else
+ {
+ /* Allocate device memory for the firmware context */
+ PDUMPCOMMENT("Allocate Rogue firmware %s context", pszContextName);
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(*psFWCommonContext),
+ RGX_FWCOMCTX_ALLOCFLAGS,
+ "FirmwareContext",
+ &psServerCommonContext->psFWCommonContextMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s : Failed to allocate firmware %s context (%s)",
+ __FUNCTION__,
+ pszContextName,
+ PVRSRVGetErrorStringKM(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 = RGXFWIF_CONTEXT_RESET_REASON_NONE;
+ psServerCommonContext->ui32ContextID = psDevInfo->ui32CommonCtxtCurrentID++;
+ dllist_add_to_tail(&(psDevInfo->sCommonCtxtListHead), &(psServerCommonContext->sListNode));
+
+ /* Allocate the client CCB */
+ eError = RGXCreateCCB(psDeviceNode,
+ ui32CCBAllocSize,
+ psConnection,
+ pszContextName,
+ 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)",
+ __FUNCTION__,
+ pszContextName,
+ PVRSRVGetErrorStringKM(eError)));
+ goto fail_allocateccb;
+ }
+
+ /*
+ Temporarily map the firmware context to the kernel and init it
+ */
+ eError = DevmemAcquireCpuVirtAddr(psServerCommonContext->psFWCommonContextMemDesc,
+ (IMG_VOID **)&pui8Ptr);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Failed to map firmware %s context (%s)to CPU",
+ __FUNCTION__,
+ pszContextName,
+ PVRSRVGetErrorStringKM(eError)));
+ goto fail_cpuvirtacquire;
+ }
+
+ psFWCommonContext = (RGXFWIF_FWCOMMONCONTEXT *) (pui8Ptr + ui32FWCommonContextOffset);
+
+ /* Set the firmware CCB device addresses in the firmware common context */
+ RGXSetFirmwareAddress(&psFWCommonContext->psCCB,
+ psServerCommonContext->psClientCCBMemDesc,
+ 0, RFW_FWADDR_FLAG_NONE);
+ RGXSetFirmwareAddress(&psFWCommonContext->psCCBCtl,
+ psServerCommonContext->psClientCCBCtrlMemDesc,
+ 0, RFW_FWADDR_FLAG_NONE);
+
+ /* Set the memory context device address */
+ psServerCommonContext->psFWMemContextMemDesc = psFWMemContextMemDesc;
+ RGXSetFirmwareAddress(&psFWCommonContext->psFWMemContext,
+ psFWMemContextMemDesc,
+ 0, RFW_FWADDR_FLAG_NONE);
+
+ /* Set the framework register updates address */
+ psServerCommonContext->psFWFrameworkMemDesc = psInfo->psFWFrameworkMemDesc;
+ RGXSetFirmwareAddress(&psFWCommonContext->psRFCmd,
+ psInfo->psFWFrameworkMemDesc,
+ 0, RFW_FWADDR_FLAG_NONE);
+
+ psFWCommonContext->ui32Priority = ui32Priority;
+
+ if(psInfo->psMCUFenceAddr != IMG_NULL)
+ {
+ psFWCommonContext->ui64MCUFenceAddr = psInfo->psMCUFenceAddr->uiAddr;
+ }
+
+ /* Store a reference to Server Common Context for notifications back from the FW. */
+ psFWCommonContext->ui32ServerCommonContextID = psServerCommonContext->ui32ContextID;
+
+ /* Set the firmware GPU context state buffer */
+ psServerCommonContext->psContextStateMemDesc = psContextStateMemDesc;
+ if (psContextStateMemDesc)
+ {
+ RGXSetFirmwareAddress(&psFWCommonContext->psContextState,
+ psContextStateMemDesc,
+ 0,
+ RFW_FWADDR_FLAG_NONE);
+ }
+
+ /*
+ * Dump the created context
+ */
+ PDUMPCOMMENT("Dump %s context", pszContextName);
+ 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 */
+ RGXSetFirmwareAddress(&psServerCommonContext->sFWCommonContextFWAddr,
+ psServerCommonContext->psFWCommonContextMemDesc,
+ ui32FWCommonContextOffset,
+ RFW_FWADDR_FLAG_NONE);
+
+#if defined(LINUX)
+ trace_rogue_create_fw_context(OSGetCurrentProcessNameKM(),
+ pszContextName,
+ psServerCommonContext->sFWCommonContextFWAddr.ui32Addr);
+#endif
+
+ *ppsServerCommonContext = psServerCommonContext;
+ return PVRSRV_OK;
+
+fail_allocateccb:
+ DevmemReleaseCpuVirtAddr(psServerCommonContext->psFWCommonContextMemDesc);
+fail_cpuvirtacquire:
+ RGXUnsetFirmwareAddress(psServerCommonContext->psFWCommonContextMemDesc);
+ if (!psServerCommonContext->bCommonContextMemProvided)
+ {
+ DevmemFwFree(psServerCommonContext->psFWCommonContextMemDesc);
+ }
+fail_contextalloc:
+ OSFreeMem(psServerCommonContext);
+fail_alloc:
+ return eError;
+}
+
+IMG_VOID FWCommonContextFree(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext)
+{
+ /*
+ Unmap the context itself and then all it's 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 */
+ 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->psClientCCB);
+
+ /* Remove the context from the list of all contexts. */
+ dllist_remove_node(&psServerCommonContext->sListNode);
+
+ /* Free the FW common context (if there was one) */
+ if (!psServerCommonContext->bCommonContextMemProvided)
+ {
+ DevmemFwFree(psServerCommonContext->psFWCommonContextMemDesc);
+ }
+ /* 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;
+}
+
+RGXFWIF_CONTEXT_RESET_REASON FWCommonContextGetLastResetReason(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext)
+{
+ RGXFWIF_CONTEXT_RESET_REASON eLastResetReason;
+
+ PVR_ASSERT(psServerCommonContext != IMG_NULL);
+
+ /* Take the most recent reason and reset for next time... */
+ eLastResetReason = psServerCommonContext->eLastResetReason;
+ psServerCommonContext->eLastResetReason = RGXFWIF_CONTEXT_RESET_REASON_NONE;
+
+ return eLastResetReason;
+}
+
+
+/*!
+*******************************************************************************
+ @Function RGXSetupKernelCCB
+ @Description Allocate and initialise a kernel CCB
+ @Input psDevInfo
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXSetupKernelCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_INIT *psRGXFWInit,
+ RGXFWIF_DM eKCCBType,
+ IMG_UINT32 ui32NumCmdsLog2,
+ IMG_UINT32 ui32CmdSize)
+{
+ PVRSRV_ERROR eError;
+ RGXFWIF_CCB_CTL *psKCCBCtl;
+ DEVMEM_FLAGS_T uiCCBCtlMemAllocFlags, uiCCBMemAllocFlags;
+ IMG_UINT32 ui32kCCBSize = (1U << ui32NumCmdsLog2);
+
+
+ /*
+ *
+*/
+ uiCCBCtlMemAllocFlags = 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;
+
+ /* Allocation flags for Kernel CCB */
+ uiCCBMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ /*
+ Allocate memory for the kernel CCB control.
+ */
+ PDUMPCOMMENT("Allocate memory for kernel CCB control %u", eKCCBType);
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_CCB_CTL),
+ uiCCBCtlMemAllocFlags,
+ "KernelCCBControl",
+ &psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType]);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupKernelCCB: Failed to allocate kernel CCB ctl %u (%u)",
+ eKCCBType, eError));
+ goto failCCBCtlMemDescAlloc;
+ }
+
+ /*
+ Allocate memory for the kernel CCB.
+ (this will reference further command data in non-shared CCBs)
+ */
+ PDUMPCOMMENT("Allocate memory for kernel CCB %u", eKCCBType);
+ eError = DevmemFwAllocate(psDevInfo,
+ ui32kCCBSize * ui32CmdSize,
+ uiCCBMemAllocFlags,
+ "KernelCCB",
+ &psDevInfo->apsKernelCCBMemDesc[eKCCBType]);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupKernelCCB: Failed to allocate kernel CCB %u (%u)",
+ eKCCBType, eError));
+ goto failCCBMemDescAlloc;
+ }
+
+ /*
+ Map the kernel CCB control to the kernel.
+ */
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType],
+ (IMG_VOID **)&psDevInfo->apsKernelCCBCtl[eKCCBType]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupKernelCCB: Failed to acquire cpu kernel CCB Ctl %u (%u)",
+ eKCCBType, eError));
+ goto failCCBCtlMemDescAqCpuVirt;
+ }
+
+ /*
+ Map the kernel CCB to the kernel.
+ */
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->apsKernelCCBMemDesc[eKCCBType],
+ (IMG_VOID **)&psDevInfo->apsKernelCCB[eKCCBType]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupKernelCCB: Failed to acquire cpu kernel CCB %u (%u)",
+ eKCCBType, eError));
+ goto failCCBMemDescAqCpuVirt;
+ }
+
+ /*
+ * Initialise the kernel CCB control.
+ */
+ psKCCBCtl = psDevInfo->apsKernelCCBCtl[eKCCBType];
+ psKCCBCtl->ui32WriteOffset = 0;
+ psKCCBCtl->ui32ReadOffset = 0;
+ psKCCBCtl->ui32WrapMask = ui32kCCBSize - 1;
+ psKCCBCtl->ui32CmdSize = ui32CmdSize;
+
+ /*
+ * Set-up RGXFWIfCtl pointers to access the kCCBs
+ */
+ RGXSetFirmwareAddress(&psRGXFWInit->psKernelCCBCtl[eKCCBType],
+ psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType],
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ RGXSetFirmwareAddress(&psRGXFWInit->psKernelCCB[eKCCBType],
+ psDevInfo->apsKernelCCBMemDesc[eKCCBType],
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ psRGXFWInit->eDM[eKCCBType] = eKCCBType;
+
+ /*
+ * Pdump the kernel CCB control.
+ */
+ PDUMPCOMMENT("Initialise kernel CCB ctl %d", eKCCBType);
+ DevmemPDumpLoadMem(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType],
+ 0,
+ sizeof(RGXFWIF_CCB_CTL),
+ 0);
+
+ return PVRSRV_OK;
+
+
+failCCBMemDescAqCpuVirt:
+ DevmemReleaseCpuVirtAddr(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType]);
+failCCBCtlMemDescAqCpuVirt:
+ DevmemFwFree(psDevInfo->apsKernelCCBMemDesc[eKCCBType]);
+failCCBMemDescAlloc:
+ DevmemFwFree(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType]);
+failCCBCtlMemDescAlloc:
+
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*!
+*******************************************************************************
+ @Function RGXSetupFirmwareCCB
+ @Description Allocate and initialise a Firmware CCB
+ @Input psDevInfo
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXSetupFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_INIT *psRGXFWInit,
+ RGXFWIF_DM eFWCCBType,
+ IMG_UINT32 ui32NumCmdsLog2,
+ IMG_UINT32 ui32CmdSize)
+{
+ PVRSRV_ERROR eError;
+ RGXFWIF_CCB_CTL *psFWCCBCtl;
+ DEVMEM_FLAGS_T uiCCBCtlMemAllocFlags, uiCCBMemAllocFlags;
+ IMG_UINT32 ui32FWCCBSize = (1U << ui32NumCmdsLog2);
+
+ /*
+ *
+*/
+ uiCCBCtlMemAllocFlags = 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;
+
+ /* Allocation flags for Firmware CCB */
+ uiCCBMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ /*
+ Allocate memory for the Firmware CCB control.
+ */
+ PDUMPCOMMENT("Allocate memory for firmware CCB control %u", eFWCCBType);
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_CCB_CTL),
+ uiCCBCtlMemAllocFlags,
+ "FirmwareCCBControl",
+ &psDevInfo->apsFirmwareCCBCtlMemDesc[eFWCCBType]);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to allocate Firmware CCB ctl %u (%u)",
+ eFWCCBType, eError));
+ goto failCCBCtlMemDescAlloc;
+ }
+
+ /*
+ Allocate memory for the Firmware CCB.
+ (this will reference further command data in non-shared CCBs)
+ */
+ PDUMPCOMMENT("Allocate memory for firmware CCB %u", eFWCCBType);
+ eError = DevmemFwAllocate(psDevInfo,
+ ui32FWCCBSize * ui32CmdSize,
+ uiCCBMemAllocFlags,
+ "FirmwareCCB",
+ &psDevInfo->apsFirmwareCCBMemDesc[eFWCCBType]);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to allocate Firmware CCB %u (%u)",
+ eFWCCBType, eError));
+ goto failCCBMemDescAlloc;
+ }
+
+ /*
+ Map the Firmware CCB control to the kernel.
+ */
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->apsFirmwareCCBCtlMemDesc[eFWCCBType],
+ (IMG_VOID **)&psDevInfo->apsFirmwareCCBCtl[eFWCCBType]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to acquire cpu firmware CCB Ctl %u (%u)",
+ eFWCCBType, eError));
+ goto failCCBCtlMemDescAqCpuVirt;
+ }
+
+ /*
+ Map the firmware CCB to the kernel.
+ */
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->apsFirmwareCCBMemDesc[eFWCCBType],
+ (IMG_VOID **)&psDevInfo->apsFirmwareCCB[eFWCCBType]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmwareCCB: Failed to acquire cpu firmware CCB %u (%u)",
+ eFWCCBType, eError));
+ goto failCCBMemDescAqCpuVirt;
+ }
+
+ /*
+ * Initialise the firmware CCB control.
+ */
+ psFWCCBCtl = psDevInfo->apsFirmwareCCBCtl[eFWCCBType];
+ psFWCCBCtl->ui32WriteOffset = 0;
+ psFWCCBCtl->ui32ReadOffset = 0;
+ psFWCCBCtl->ui32WrapMask = ui32FWCCBSize - 1;
+ psFWCCBCtl->ui32CmdSize = ui32CmdSize;
+
+ /*
+ * Set-up RGXFWIfCtl pointers to access the kCCBs
+ */
+ RGXSetFirmwareAddress(&psRGXFWInit->psFirmwareCCBCtl[eFWCCBType],
+ psDevInfo->apsFirmwareCCBCtlMemDesc[eFWCCBType],
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ RGXSetFirmwareAddress(&psRGXFWInit->psFirmwareCCB[eFWCCBType],
+ psDevInfo->apsFirmwareCCBMemDesc[eFWCCBType],
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ psRGXFWInit->eDM[eFWCCBType] = eFWCCBType;
+
+ /*
+ * Pdump the kernel CCB control.
+ */
+ PDUMPCOMMENT("Initialise firmware CCB ctl %d", eFWCCBType);
+ DevmemPDumpLoadMem(psDevInfo->apsFirmwareCCBCtlMemDesc[eFWCCBType],
+ 0,
+ sizeof(RGXFWIF_CCB_CTL),
+ 0);
+
+ return PVRSRV_OK;
+
+
+failCCBMemDescAqCpuVirt:
+ DevmemReleaseCpuVirtAddr(psDevInfo->apsFirmwareCCBCtlMemDesc[eFWCCBType]);
+failCCBCtlMemDescAqCpuVirt:
+ DevmemFwFree(psDevInfo->apsFirmwareCCBMemDesc[eFWCCBType]);
+failCCBMemDescAlloc:
+ DevmemFwFree(psDevInfo->apsFirmwareCCBCtlMemDesc[eFWCCBType]);
+failCCBCtlMemDescAlloc:
+
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*!
+*******************************************************************************
+ @Function RGXFreeKernelCCB
+ @Description Free a kernel CCB
+ @Input psDevInfo
+ @Input eKCCBType
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+static IMG_VOID RGXFreeKernelCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eKCCBType)
+{
+ DevmemReleaseCpuVirtAddr(psDevInfo->apsKernelCCBMemDesc[eKCCBType]);
+ DevmemReleaseCpuVirtAddr(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType]);
+ DevmemFwFree(psDevInfo->apsKernelCCBMemDesc[eKCCBType]);
+ DevmemFwFree(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType]);
+}
+
+/*!
+*******************************************************************************
+ @Function RGXFreeFirmwareCCB
+ @Description Free a firmware CCB
+ @Input psDevInfo
+ @Input eFWCCBType
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+static IMG_VOID RGXFreeFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eFWCCBType)
+{
+ DevmemReleaseCpuVirtAddr(psDevInfo->apsFirmwareCCBMemDesc[eFWCCBType]);
+ DevmemReleaseCpuVirtAddr(psDevInfo->apsFirmwareCCBCtlMemDesc[eFWCCBType]);
+ DevmemFwFree(psDevInfo->apsFirmwareCCBMemDesc[eFWCCBType]);
+ DevmemFwFree(psDevInfo->apsFirmwareCCBCtlMemDesc[eFWCCBType]);
+}
+
+static IMG_VOID RGXSetupFaultReadRegisterRollback(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PMR *psPMR;
+
+ if (psDevInfo->psRGXFaultAddressMemDesc)
+ {
+ if (DevmemServerGetImportHandle(psDevInfo->psRGXFaultAddressMemDesc,(IMG_VOID **)&psPMR) == PVRSRV_OK)
+ {
+ PMRUnlockSysPhysAddresses(psPMR);
+ }
+ DevmemFwFree(psDevInfo->psRGXFaultAddressMemDesc);
+ }
+}
+
+static PVRSRV_ERROR RGXSetupFaultReadRegister(PVRSRV_DEVICE_NODE *psDeviceNode, RGXFWIF_INIT *psRGXFWInit)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 *pui32MemoryVirtAddr;
+ IMG_UINT32 i;
+ IMG_SIZE_T ui32PageSize;
+ DEVMEM_FLAGS_T uiMemAllocFlags;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ PMR *psPMR;
+
+ ui32PageSize = OSGetPageSize();
+
+ /* Allocate page of memory to use for page faults on non-blocking memory transactions */
+ 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_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED;
+
+ psDevInfo->psRGXFaultAddressMemDesc = IMG_NULL;
+ eError = DevmemFwAllocateExportable(psDeviceNode,
+ ui32PageSize,
+ uiMemAllocFlags,
+ "FaultAddress",
+ &psDevInfo->psRGXFaultAddressMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to allocate mem for fault address (%u)",
+ eError));
+ goto failFaultAddressDescAlloc;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFaultAddressMemDesc,
+ (IMG_VOID **)&pui32MemoryVirtAddr);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire mem for fault adress (%u)",
+ eError));
+ goto failFaultAddressDescAqCpuVirt;
+ }
+
+ for (i = 0; i < ui32PageSize/sizeof(IMG_UINT32); i++)
+ {
+ *(pui32MemoryVirtAddr + i) = 0xDEADBEEF;
+ }
+
+ eError = DevmemServerGetImportHandle(psDevInfo->psRGXFaultAddressMemDesc,(IMG_VOID **)&psPMR);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Error getting PMR for fault adress (%u)",
+ eError));
+
+ goto failFaultAddressDescGetPMR;
+ }
+ else
+ {
+ IMG_BOOL bValid;
+
+ eError = PMRLockSysPhysAddresses(psPMR,OSGetPageShift());
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Error locking physical address for fault address MemDesc (%u)",
+ eError));
+
+ goto failFaultAddressDescLockPhys;
+ }
+
+ eError = PMR_DevPhysAddr(psPMR,0,&(psRGXFWInit->sFaultPhysAddr),&bValid);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Error getting physical address for fault address MemDesc (%u)",
+ eError));
+
+ goto failFaultAddressDescGetPhys;
+ }
+
+ if (!bValid)
+ {
+ psRGXFWInit->sFaultPhysAddr.uiAddr = 0;
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed getting physical address for fault address MemDesc - invalid page (0x%llX)",
+ psRGXFWInit->sFaultPhysAddr.uiAddr));
+
+ goto failFaultAddressDescGetPhys;
+ }
+ }
+
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFaultAddressMemDesc);
+
+ return PVRSRV_OK;
+
+failFaultAddressDescGetPhys:
+ PMRUnlockSysPhysAddresses(psPMR);
+
+failFaultAddressDescLockPhys:
+
+failFaultAddressDescGetPMR:
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFaultAddressMemDesc);
+
+failFaultAddressDescAqCpuVirt:
+ DevmemFwFree(psDevInfo->psRGXFaultAddressMemDesc);
+
+failFaultAddressDescAlloc:
+
+ return eError;
+}
+
+static IMG_VOID RGXHwBrn37200Rollback(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if defined(FIX_HW_BRN_37200)
+ DevmemFwFree(psDevInfo->psRGXFWHWBRN37200MemDesc);
+#endif
+}
+
+static PVRSRV_ERROR RGXHwBrn37200(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+#if defined(FIX_HW_BRN_37200)
+ struct _DEVMEM_HEAP_ *psBRNHeap;
+ DEVMEM_FLAGS_T uiFlags;
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_SIZE_T uiPageSize;
+
+ uiPageSize = OSGetPageSize();
+
+ uiFlags = 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_GPU_CACHE_INCOHERENT |
+ PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx,
+ "HWBRN37200",
+ &psBRNHeap);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXHwBrn37200: HWBRN37200 Failed DevmemFindHeapByName (%u)", eError));
+ goto failFWHWBRN37200FindHeapByName;
+ }
+
+ psDevInfo->psRGXFWHWBRN37200MemDesc = IMG_NULL;
+ eError = DevmemAllocate(psBRNHeap,
+ uiPageSize,
+ ROGUE_CACHE_LINE_SIZE,
+ uiFlags,
+ "HWBRN37200",
+ &psDevInfo->psRGXFWHWBRN37200MemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXHwBrn37200: Failed to allocate %u bytes for HWBRN37200 (%u)",
+ (IMG_UINT32)uiPageSize,
+ eError));
+ goto failFWHWBRN37200MemDescAlloc;
+ }
+
+ /*
+ We need to map it so the heap for this allocation
+ is set
+ */
+ eError = DevmemMapToDevice(psDevInfo->psRGXFWHWBRN37200MemDesc,
+ psBRNHeap,
+ &sTmpDevVAddr);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXHwBrn37200: Failed to allocate %u bytes for HWBRN37200 (%u)",
+ (IMG_UINT32)uiPageSize,
+ eError));
+ goto failFWHWBRN37200DevmemMapToDevice;
+ }
+
+ return PVRSRV_OK;
+
+failFWHWBRN37200DevmemMapToDevice:
+
+failFWHWBRN37200MemDescAlloc:
+ RGXHwBrn37200Rollback(psDevInfo);
+
+failFWHWBRN37200FindHeapByName:
+#endif
+
+ return eError;
+}
+
+/*!
+*******************************************************************************
+
+ @Function RGXSetupFirmware
+
+ @Description
+
+ Setups all the 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 ui32RGXFWAlignChecksSize,
+ IMG_UINT32 *pui32RGXFWAlignChecks,
+ IMG_UINT32 ui32ConfigFlags,
+ IMG_UINT32 ui32LogType,
+ IMG_UINT32 ui32NumTilingCfgs,
+ IMG_UINT32 *pui32BIFTilingXStrides,
+ IMG_UINT32 ui32FilterFlags,
+ RGXFWIF_DEV_VIRTADDR *psRGXFWInitFWAddr)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_FLAGS_T uiMemAllocFlags;
+ RGXFWIF_INIT *psRGXFWInit;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 dm;
+#if defined(RGX_FEATURE_DMA)
+ RGXFWIF_DEV_VIRTADDR sRGXTmpCorememDataStoreFWAddr;
+#endif
+
+ /* Fw init data */
+ uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
+ 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;
+
+
+ PDUMPCOMMENT("Allocate RGXFWIF_INIT structure");
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_INIT),
+ uiMemAllocFlags,
+ "FirmwareInitStructure",
+ &psDevInfo->psRGXFWIfInitMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate %u bytes for fw if ctl (%u)",
+ (IMG_UINT32)sizeof(RGXFWIF_INIT),
+ eError));
+ goto failFWIfInitMemDescAlloc;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc,
+ (IMG_VOID **)&psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire kernel fw if ctl (%u)",
+ eError));
+ goto failFWIfInitMemDescAqCpuVirt;
+ }
+
+ RGXSetFirmwareAddress(psRGXFWInitFWAddr,
+ psDevInfo->psRGXFWIfInitMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ /* FW Trace buffer */
+ uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ PDUMPCOMMENT("Allocate rgxfw trace structure");
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_TRACEBUF),
+ uiMemAllocFlags,
+ "FirmwareTraceStructure",
+ &psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate %u bytes for fw trace (%u)",
+ (IMG_UINT32)sizeof(RGXFWIF_TRACEBUF),
+ eError));
+ goto failFWIfTraceBufCtlMemDescAlloc;
+ }
+
+ RGXSetFirmwareAddress(&psRGXFWInit->psTraceBufCtl,
+ psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+ (IMG_VOID **)&psDevInfo->psRGXFWIfTraceBuf);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire kernel tracebuf ctl (%u)",
+ eError));
+ goto failFWIfTraceBufCtlMemDescAqCpuVirt;
+ }
+
+ /* Determine the size of the HWPerf FW buffer */
+ if (ui32HWPerfFWBufSizeKB > (RGXFW_HWPERF_L1_SIZE_MAX>>10))
+ {
+ /* Size specified as a AppHint but it is too big */
+ PVR_DPF((PVR_DBG_WARNING,"RGXSetupFirmware: HWPerfFWBufSizeInKB value (%u) too big, using maximum (%u)",
+ ui32HWPerfFWBufSizeKB, RGXFW_HWPERF_L1_SIZE_MAX>>10));
+ psDevInfo->ui32RGXFWIfHWPerfBufSize = RGXFW_HWPERF_L1_SIZE_MAX;
+
+ }
+ else if (ui32HWPerfFWBufSizeKB > (RGXFW_HWPERF_L1_SIZE_MIN>>10))
+ {
+ /* Size specified as in AppHint HWPerfFWBufSizeInKB */
+ PVR_DPF((PVR_DBG_WARNING,"RGXSetupFirmware: Using HWPerf FW buffer size of %u KB",
+ ui32HWPerfFWBufSizeKB));
+ psDevInfo->ui32RGXFWIfHWPerfBufSize = ui32HWPerfFWBufSizeKB<<10;
+ }
+ else if (ui32HWPerfFWBufSizeKB > 0)
+ {
+ /* Size specified as a AppHint but it is too small */
+ PVR_DPF((PVR_DBG_WARNING,"RGXSetupFirmware: HWPerfFWBufSizeInKB value (%u) too small, using minimum (%u)",
+ ui32HWPerfFWBufSizeKB, RGXFW_HWPERF_L1_SIZE_MIN>>10));
+ psDevInfo->ui32RGXFWIfHWPerfBufSize = RGXFW_HWPERF_L1_SIZE_MIN;
+ }
+ else
+ {
+ /* 0 size implies AppHint not set or is set to zero,
+ * use default size from driver constant. */
+ psDevInfo->ui32RGXFWIfHWPerfBufSize = RGXFW_HWPERF_L1_SIZE_DEFAULT;
+ }
+
+ /* Allocate HWPerf FW L1 buffer */
+ eError = DevmemFwAllocate(psDevInfo,
+ psDevInfo->ui32RGXFWIfHWPerfBufSize+RGXFW_HWPERF_L1_PADDING_DEFAULT,
+ uiMemAllocFlags,
+ "FirmwareHWPerfBuffer",
+ &psDevInfo->psRGXFWIfHWPerfBufMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXSetupFirmware: Failed to allocate kernel fw hwperf buffer (%u)",
+ eError));
+ goto failFWIfInitHWPerfInfoMemDescAlloc;
+ }
+
+ /* Meta cached flag removed from this allocation as it was found
+ * FW performance was better without it. */
+ RGXSetFirmwareAddress(&psRGXFWInit->psHWPerfInfoCtl,
+ psDevInfo->psRGXFWIfHWPerfBufMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfHWPerfBufMemDesc,
+ (IMG_VOID**)&psDevInfo->psRGXFWIfHWPerfBuf);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXSetupFirmware: Failed to acquire kernel hwperf buffer (%u)",
+ eError));
+ goto failFWIfInitHWPerfInfoMemDescAqCpuVirt;
+ }
+
+
+ uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ /* Allocate buffer to store FW data */
+ eError = DevmemFwAllocate(psDevInfo,
+ RGX_META_COREMEM_DATA_SIZE,
+ uiMemAllocFlags,
+ "FirmwareCorememDataStore",
+ &psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXSetupFirmware: Failed to allocate coremem data store (%u)",
+ eError));
+ goto failFWIfCorememDataStoreMemDescAlloc;
+ }
+
+#if defined(RGX_FEATURE_DMA)
+ RGXSetFirmwareAddress(&sRGXTmpCorememDataStoreFWAddr,
+ psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ RGXSetDMAAddress(&psRGXFWInit->sCorememDataStore,
+ psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+ &sRGXTmpCorememDataStoreFWAddr,
+ 0);
+#else
+ RGXSetFirmwareAddress(&psRGXFWInit->sCorememDataStore.pbyFWAddr,
+ psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+#endif
+
+ /* init HW frame info */
+ PDUMPCOMMENT("Allocate rgxfw HW info buffer");
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_HWRINFOBUF),
+ uiMemAllocFlags,
+ "FirmwareHWInfoBuffer",
+ &psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate %d bytes for HW info (%u)",
+ (IMG_UINT32)sizeof(RGXFWIF_HWRINFOBUF),
+ eError));
+ goto failFWIfHWRInfoBufCtlMemDescAlloc;
+ }
+
+ RGXSetFirmwareAddress(&psRGXFWInit->psRGXFWIfHWRInfoBufCtl,
+ psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc,
+ (IMG_VOID **)&psDevInfo->psRGXFWIfHWRInfoBuf);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire kernel tracebuf ctl (%u)",
+ eError));
+ goto failFWIfHWRInfoBufCtlMemDescAqCpuVirt;
+ }
+ OSMemSet(psDevInfo->psRGXFWIfHWRInfoBuf, 0, sizeof(RGXFWIF_HWRINFOBUF));
+
+ /* init HWPERF data */
+ psDevInfo->psRGXFWIfTraceBuf->ui32HWPerfRIdx = 0;
+ psDevInfo->psRGXFWIfTraceBuf->ui32HWPerfWIdx = 0;
+ psDevInfo->psRGXFWIfTraceBuf->ui32HWPerfWrapCount = 0;
+ psDevInfo->psRGXFWIfTraceBuf->ui32HWPerfSize = psDevInfo->ui32RGXFWIfHWPerfBufSize;
+ psRGXFWInit->ui64HWPerfFilter = ui64HWPerfFilter;
+ psRGXFWInit->bDisableFilterHWPerfCustomCounter = (ui32ConfigFlags & RGXFWIF_INICFG_HWP_DISABLE_FILTER) ? IMG_TRUE : IMG_FALSE;
+ psDevInfo->psRGXFWIfTraceBuf->ui32HWPerfUt = 0;
+ psDevInfo->psRGXFWIfTraceBuf->ui32HWPerfDropCount = 0;
+ psDevInfo->psRGXFWIfTraceBuf->ui32FirstDropOrdinal = 0;
+ psDevInfo->psRGXFWIfTraceBuf->ui32LastDropOrdinal = 0;
+
+
+ /* Initialise the HWPerf module in the Rogue device driver.
+ * May allocate host buffer if HWPerf enabled at driver load time.
+ */
+ eError = RGXHWPerfInit(psDeviceNode, (ui32ConfigFlags & RGXFWIF_INICFG_HWPERF_EN));
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGG_IF_ERROR(eError, "RGXHWPerfInit", failHWPerfInit);
+ goto failHWPerfInit;
+ }
+
+ /* Set initial log type */
+ if (ui32LogType & ~RGXFWIF_LOG_TYPE_MASK)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Invalid initial log type (0x%X)",ui32LogType));
+ goto failInvalidLogType;
+ }
+ psDevInfo->psRGXFWIfTraceBuf->ui32LogType = ui32LogType;
+
+ /* Allocate FW CB for GPU utilization */
+ uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ PDUMPCOMMENT("Allocate rgxfw GPU utilization CB (FW)");
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_GPU_UTIL_FWCB),
+ uiMemAllocFlags,
+ "FirmwareGPUUtilizationCB",
+ &psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate %u bytes for GPU utilization FW CB ctl (%u)",
+ (IMG_UINT32)sizeof(RGXFWIF_GPU_UTIL_FWCB),
+ eError));
+ goto failFWIfGpuUtilFWCbCtlMemDescAlloc;
+ }
+
+ RGXSetFirmwareAddress(&psRGXFWInit->psGpuUtilFWCbCtl,
+ psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc,
+ (IMG_VOID **)&psDevInfo->psRGXFWIfGpuUtilFWCb);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire kernel GPU utilization FW CB ctl (%u)",
+ eError));
+ goto failFWIfGpuUtilFWCbCtlMemDescAqCpuVirt;
+ }
+
+ /* Reset FW CB of GPU state transitions history */
+ /* Setting ui32LastGpuUtilState to idle lets the very first host power-on
+ * entry in the FW CB to be recorded as an idle state rather than a reserved one
+ * (which would be discarded by RGXGetGpuUtilStats() but we might need it) */
+ psDevInfo->psRGXFWIfGpuUtilFWCb->ui32LastGpuUtilState = RGXFWIF_GPU_UTIL_FWCB_STATE_IDLE;
+ psDevInfo->psRGXFWIfGpuUtilFWCb->ui32WriteOffset = 0;
+ psDevInfo->psRGXFWIfGpuUtilFWCb->ui32CurrentDVFSId = 0;
+ psDevInfo->psRGXFWIfGpuUtilFWCb->aui64CB[0] = RGXFWIF_GPU_UTIL_FWCB_RESERVED;
+ psDevInfo->psRGXFWIfGpuUtilFWCb->aui64CB[RGXFWIF_GPU_UTIL_FWCB_SIZE-1] = RGXFWIF_GPU_UTIL_FWCB_RESERVED;
+
+ uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ PDUMPCOMMENT("Allocate rgxfw FW runtime configuration (FW)");
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_RUNTIME_CFG),
+ uiMemAllocFlags,
+ "FirmwareFWRuntimeCfg",
+ &psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate %u bytes for FW runtime configuration (%u)",
+ (IMG_UINT32)sizeof(RGXFWIF_RUNTIME_CFG),
+ eError));
+ goto failFWIfRuntimeCfgMemDescAlloc;
+ }
+
+ RGXSetFirmwareAddress(&psRGXFWInit->psRuntimeCfg,
+ psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+ (IMG_VOID **)&psDevInfo->psRGXFWIfRuntimeCfg);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to acquire kernel FW runtime configuration (%u)",
+ eError));
+ goto failFWIfRuntimeCfgMemDescAqCpuVirt;
+ }
+
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ PDUMPCOMMENT("Allocate rgxfw register configuration structure");
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_REG_CFG),
+ uiMemAllocFlags,
+ "Firmware register configuration structure",
+ &psDevInfo->psRGXFWIfRegCfgMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate %ld bytes for fw register configurations (%u)",
+ sizeof(RGXFWIF_REG_CFG),
+ eError));
+ goto failFWIfRegconfigMemDescAlloc;
+ }
+
+ RGXSetFirmwareAddress(&psRGXFWInit->psRegCfg,
+ psDevInfo->psRGXFWIfRegCfgMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+#endif
+ /* Allocate a sync for power management */
+ eError = SyncPrimContextCreate(IMG_NULL,
+ psDevInfo->psDeviceNode,
+ &psDevInfo->hSyncPrimContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate sync primitive context with error (%u)", eError));
+ goto failed_sync_ctx_alloc;
+ }
+
+ eError = SyncPrimAlloc(psDevInfo->hSyncPrimContext, &psDevInfo->psPowSyncPrim, "fw power ack");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate sync primitive with error (%u)", eError));
+ goto failed_sync_alloc;
+ }
+
+ psRGXFWInit->uiPowerSync = SyncPrimGetFirmwareAddr(psDevInfo->psPowSyncPrim);
+
+ /* Required info by FW to calculate the ActivePM idle timer latency */
+ {
+ RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
+ RGXFWIF_RUNTIME_CFG *psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
+
+ psRGXFWInit->ui32InitialCoreClockSpeed = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
+ psRGXFWInit->ui32ActivePMLatencyms = psRGXData->psRGXTimingInfo->ui32ActivePMLatencyms;
+
+ /* Initialise variable runtime configuration to the system defaults */
+ psRuntimeCfg->ui32CoreClockSpeed = psRGXFWInit->ui32InitialCoreClockSpeed;
+ psRuntimeCfg->ui32ActivePMLatencyms = psRGXFWInit->ui32ActivePMLatencyms;
+ psRuntimeCfg->bActivePMLatencyPersistant = IMG_TRUE;
+ }
+
+ /* Setup Fault read register */
+ eError = RGXSetupFaultReadRegister(psDeviceNode, psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup fault read register"));
+ goto failFWSetupFaultReadRegister;
+ }
+
+ /* Apply FIX_HW_BRN_37200 */
+ eError = RGXHwBrn37200(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to apply HWBRN37200"));
+ goto failFWHWBRN37200;
+ }
+
+ /*
+ * Set up kernel TA CCB.
+ */
+ eError = RGXSetupKernelCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_TA, RGXFWIF_KCCB_TA_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_KCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate kernel TA CCB"));
+ goto failTAKCCB;
+ }
+
+ /*
+ * Set up firmware TA CCB.
+ */
+ eError = RGXSetupFirmwareCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_TA, RGXFWIF_FWCCB_TA_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_FWCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate Firmware TA CCB"));
+ goto failTAFWCCB;
+ }
+
+ /*
+ * Set up kernel 3D CCB.
+ */
+ eError = RGXSetupKernelCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_3D, RGXFWIF_KCCB_3D_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_KCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate kernel 3D CCB"));
+ goto fail3DKCCB;
+ }
+
+ /*
+ * Set up Firmware 3D CCB.
+ */
+ eError = RGXSetupFirmwareCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_3D, RGXFWIF_FWCCB_3D_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_FWCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate Firmware 3D CCB"));
+ goto fail3DFWCCB;
+ }
+
+ /*
+ * Set up kernel 2D CCB.
+ */
+ eError = RGXSetupKernelCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_2D, RGXFWIF_KCCB_2D_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_KCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate kernel 2D CCB"));
+ goto fail2DKCCB;
+ }
+ /*
+ * Set up Firmware 2D CCB.
+ */
+ eError = RGXSetupFirmwareCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_2D, RGXFWIF_FWCCB_2D_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_FWCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate Firmware 2D CCB"));
+ goto fail2DFWCCB;
+ }
+
+ /*
+ * Set up kernel compute CCB.
+ */
+ eError = RGXSetupKernelCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_CDM, RGXFWIF_KCCB_CDM_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_KCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate kernel Compute CCB"));
+ goto failCompKCCB;
+ }
+
+ /*
+ * Set up Firmware Compute CCB.
+ */
+ eError = RGXSetupFirmwareCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_CDM, RGXFWIF_FWCCB_CDM_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_FWCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate Firmware Compute CCB"));
+ goto failCompFWCCB;
+ }
+
+ /*
+ * Set up kernel general purpose CCB.
+ */
+ eError = RGXSetupKernelCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_GP, RGXFWIF_KCCB_GP_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_KCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate kernel General Purpose CCB"));
+ goto failGPKCCB;
+ }
+
+ /*
+ * Set up Firmware general purpose CCB.
+ */
+ eError = RGXSetupFirmwareCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_GP, RGXFWIF_FWCCB_GP_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_FWCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate Firmware General Purpose CCB"));
+ goto failGPFWCCB;
+ }
+#if defined(RGX_FEATURE_RAY_TRACING)
+ /*
+ * Set up kernel SHG CCB.
+ */
+ eError = RGXSetupKernelCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_SHG, RGXFWIF_KCCB_SHG_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_KCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate kernel SHG CCB"));
+ goto failSHGCCB;
+ }
+
+ /*
+ * Set up Firmware SHG CCB.
+ */
+ eError = RGXSetupFirmwareCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_SHG, RGXFWIF_FWCCB_SHG_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_FWCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate Firmware SHG CCB"));
+ goto failSHGFWCCB;
+ }
+
+ /*
+ * Set up kernel RTU CCB.
+ */
+ eError = RGXSetupKernelCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_RTU, RGXFWIF_KCCB_RTU_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_KCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate kernel RTU CCB"));
+ goto failRTUCCB;
+ }
+
+ /*
+ * Set up Firmware RTU CCB.
+ */
+ eError = RGXSetupFirmwareCCB(psDevInfo,
+ psRGXFWInit,
+ RGXFWIF_DM_RTU, RGXFWIF_FWCCB_RTU_NUMCMDS_LOG2,
+ sizeof(RGXFWIF_FWCCB_CMD));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate Firmware SHG CCB"));
+ goto failRTUFWCCB;
+ }
+#endif
+
+ /* Setup Signature and Checksum Buffers for TA and 3D */
+ eError = RGXFWSetupSignatureChecks(psDevInfo,
+ &psDevInfo->psRGXFWSigTAChecksMemDesc,
+ ui32SignatureChecksBufSize,
+ &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_TA],
+ "TA");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup TA signature checks"));
+ goto failTASigCheck;
+ }
+ psDevInfo->ui32SigTAChecksSize = ui32SignatureChecksBufSize;
+
+ eError = RGXFWSetupSignatureChecks(psDevInfo,
+ &psDevInfo->psRGXFWSig3DChecksMemDesc,
+ ui32SignatureChecksBufSize,
+ &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_3D],
+ "3D");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup 3D signature checks"));
+ goto fail3DSigCheck;
+ }
+ psDevInfo->ui32Sig3DChecksSize = ui32SignatureChecksBufSize;
+
+#if defined(RGX_FEATURE_RAY_TRACING)
+ eError = RGXFWSetupSignatureChecks(psDevInfo,
+ &psDevInfo->psRGXFWSigRTChecksMemDesc,
+ ui32SignatureChecksBufSize,
+ &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_RTU],
+ "RTU");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup RTU signature checks"));
+ goto failSHGSigCheck;
+ }
+ psDevInfo->ui32SigRTChecksSize = ui32SignatureChecksBufSize;
+
+ eError = RGXFWSetupSignatureChecks(psDevInfo,
+ &psDevInfo->psRGXFWSigSHChecksMemDesc,
+ ui32SignatureChecksBufSize,
+ &psRGXFWInit->asSigBufCtl[RGXFWIF_DM_SHG],
+ "SHG");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup SHG signature checks"));
+ goto failSHGSigCheck;
+ }
+ psDevInfo->ui32SigSHChecksSize = ui32SignatureChecksBufSize;
+#endif
+
+#if defined(RGXFW_ALIGNCHECKS)
+ eError = RGXFWSetupAlignChecks(psDevInfo,
+ &psRGXFWInit->paui32AlignChecks,
+ pui32RGXFWAlignChecks,
+ ui32RGXFWAlignChecksSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to setup alignment checks"));
+ goto failAlignCheck;
+ }
+#endif
+
+ /* Fill the remaining bits of fw the init data */
+ psRGXFWInit->sPDSExecBase.uiAddr = RGX_PDSCODEDATA_HEAP_BASE;
+ psRGXFWInit->sUSCExecBase.uiAddr = RGX_USCCODE_HEAP_BASE;
+ psRGXFWInit->sDPXControlStreamBase.uiAddr = RGX_DOPPLER_HEAP_BASE;
+ psRGXFWInit->sResultDumpBase.uiAddr = RGX_DOPPLER_OVERFLOW_HEAP_BASE;
+ psRGXFWInit->sRTUHeapBase.uiAddr = RGX_DOPPLER_HEAP_BASE;
+
+ /* RD Power Island */
+ {
+ RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
+ IMG_BOOL bEnableRDPowIsland = psRGXData->psRGXTimingInfo->bEnableRDPowIsland;
+
+ ui32ConfigFlags |= bEnableRDPowIsland? RGXFWIF_INICFG_POW_RASCALDUST : 0;
+
+ }
+
+ psRGXFWInit->ui32ConfigFlags = ui32ConfigFlags & RGXFWIF_INICFG_ALL;
+ psRGXFWInit->ui32FilterFlags = ui32FilterFlags;
+
+ psDevInfo->bPDPEnabled = (ui32ConfigFlags & RGXFWIF_SRVCFG_DISABLE_PDP_EN)
+ ? IMG_FALSE : IMG_TRUE;
+
+#if defined(RGX_FEATURE_SLC_VIVT)
+ eError = _AllocateSLC3Fence(psDevInfo, psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to allocate memory for SLC3Fence"));
+ goto failSLC3Fence;
+ }
+#endif
+
+ /* Timestamps */
+ uiMemAllocFlags =
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE | /* XXX ?? */
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ /*
+ the timer query arrays
+ */
+ PDUMPCOMMENT("Allocate timer query arrays (FW)");
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(IMG_UINT64) * RGX_MAX_TIMER_QUERIES,
+ uiMemAllocFlags,
+ "Start times array",
+ & psDevInfo->psStartTimeMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to map start times array"));
+ goto failAllocStartTimes;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psStartTimeMemDesc,
+ (IMG_VOID **)& psDevInfo->pui64StartTimeById);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to map start times array"));
+ goto failMapStartTimes;
+ }
+
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(IMG_UINT64) * RGX_MAX_TIMER_QUERIES,
+ uiMemAllocFlags,
+ "End times array",
+ & psDevInfo->psEndTimeMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to map end times array"));
+ goto failAllocEndTimes;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psEndTimeMemDesc,
+ (IMG_VOID **)& psDevInfo->pui64EndTimeById);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to map end times array"));
+ goto failMapEndTimes;
+ }
+
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(IMG_UINT32) * RGX_MAX_TIMER_QUERIES,
+ uiMemAllocFlags,
+ "Completed ops array",
+ & psDevInfo->psCompletedMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to completed ops array"));
+ goto failAllocCompleted;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psCompletedMemDesc,
+ (IMG_VOID **)& psDevInfo->pui32CompletedById);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSetupFirmware: Failed to map completed ops array"));
+ goto failMapCompleted;
+ }
+
+ /* Initialize FW started flag */
+ psRGXFWInit->bFirmwareStarted = IMG_FALSE;
+
+ /* Initialise the compatibility check data */
+ RGXFWIF_COMPCHECKS_BVNC_INIT(psRGXFWInit->sRGXCompChecks.sFWBVNC);
+ RGXFWIF_COMPCHECKS_BVNC_INIT(psRGXFWInit->sRGXCompChecks.sHWBVNC);
+
+ {
+ /* Below line is to make sure (compilation time check) that
+ RGX_BVNC_KM_V_ST fits into RGXFWIF_COMPCHECKS_BVNC structure */
+ IMG_CHAR _tmp_[RGXFWIF_COMPCHECKS_BVNC_V_LEN_MAX] = RGX_BVNC_KM_V_ST;
+ _tmp_[0] = '\0';
+ }
+
+ PDUMPCOMMENT("Dump RGXFW Init data");
+ if (!bEnableSignatureChecks)
+ {
+#if defined(PDUMP)
+ PDUMPCOMMENT("(to enable rgxfw signatures place the following line after the RTCONF line)");
+ DevmemPDumpLoadMem( psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, asSigBufCtl),
+ sizeof(RGXFWIF_SIGBUF_CTL)*RGXFWIF_DM_MAX,
+ PDUMP_FLAGS_CONTINUOUS);
+#endif
+ psRGXFWInit->asSigBufCtl[RGXFWIF_DM_3D].psBuffer.ui32Addr = 0x0;
+ psRGXFWInit->asSigBufCtl[RGXFWIF_DM_TA].psBuffer.ui32Addr = 0x0;
+ }
+
+ for (dm = 0; dm < RGXFWIF_DM_MAX; dm++)
+ {
+ psDevInfo->psRGXFWIfTraceBuf->aui16HwrDmLockedUpCount[dm] = 0;
+ psDevInfo->psRGXFWIfTraceBuf->aui16HwrDmOverranCount[dm] = 0;
+ psDevInfo->psRGXFWIfTraceBuf->aui16HwrDmRecoveredCount[dm] = 0;
+ psDevInfo->psRGXFWIfTraceBuf->aui16HwrDmFalseDetectCount[dm] = 0;
+ psDevInfo->psRGXFWIfTraceBuf->apsHwrDmFWCommonContext[dm].ui32Addr = 0;
+ }
+
+ /*
+ * BIF Tiling configuration
+ */
+
+ psRGXFWInit->sBifTilingCfg[0].uiBase = RGX_BIF_TILING_HEAP_1_BASE;
+ psRGXFWInit->sBifTilingCfg[0].uiLen = RGX_BIF_TILING_HEAP_SIZE;
+ psRGXFWInit->sBifTilingCfg[0].uiXStride = pui32BIFTilingXStrides[0];
+ psRGXFWInit->sBifTilingCfg[1].uiBase = RGX_BIF_TILING_HEAP_2_BASE;
+ psRGXFWInit->sBifTilingCfg[1].uiLen = RGX_BIF_TILING_HEAP_SIZE;
+ psRGXFWInit->sBifTilingCfg[1].uiXStride = pui32BIFTilingXStrides[1];
+ psRGXFWInit->sBifTilingCfg[2].uiBase = RGX_BIF_TILING_HEAP_3_BASE;
+ psRGXFWInit->sBifTilingCfg[2].uiLen = RGX_BIF_TILING_HEAP_SIZE;
+ psRGXFWInit->sBifTilingCfg[2].uiXStride = pui32BIFTilingXStrides[2];
+ psRGXFWInit->sBifTilingCfg[3].uiBase = RGX_BIF_TILING_HEAP_4_BASE;
+ psRGXFWInit->sBifTilingCfg[3].uiLen = RGX_BIF_TILING_HEAP_SIZE;
+ psRGXFWInit->sBifTilingCfg[3].uiXStride = pui32BIFTilingXStrides[3];
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Dump rgxfw HW Perf Info structure");
+ DevmemPDumpLoadMem (psDevInfo->psRGXFWIfHWPerfBufMemDesc,
+ 0,
+ psDevInfo->ui32RGXFWIfHWPerfBufSize,
+ PDUMP_FLAGS_CONTINUOUS);
+ PDUMPCOMMENT("Dump rgxfw trace structure");
+ DevmemPDumpLoadMem( psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+ 0,
+ sizeof(RGXFWIF_TRACEBUF),
+ PDUMP_FLAGS_CONTINUOUS);
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ PDUMPCOMMENT("Dump rgxfw register configuration buffer");
+ DevmemPDumpLoadMem( psDevInfo->psRGXFWIfRegCfgMemDesc,
+ 0,
+ sizeof(RGXFWIF_REG_CFG),
+ PDUMP_FLAGS_CONTINUOUS);
+#endif
+ PDUMPCOMMENT("Dump rgxfw init structure");
+ DevmemPDumpLoadMem( psDevInfo->psRGXFWIfInitMemDesc,
+ 0,
+ sizeof(RGXFWIF_INIT),
+ PDUMP_FLAGS_CONTINUOUS);
+
+ PDUMPCOMMENT("Dump rgxfw coremem data store");
+ DevmemPDumpLoadMem( psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+ 0,
+ RGX_META_COREMEM_DATA_SIZE,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ PDUMPCOMMENT("RTCONF: run-time configuration");
+
+
+ /* Dump the config options so they can be edited.
+ *
+ *
+*/
+ PDUMPCOMMENT("(Set the FW config options here)");
+ PDUMPCOMMENT("( Ctx Switch TA Enable: 0x%08x)", RGXFWIF_INICFG_CTXSWITCH_TA_EN);
+ PDUMPCOMMENT("( Ctx Switch 3D Enable: 0x%08x)", RGXFWIF_INICFG_CTXSWITCH_3D_EN);
+ PDUMPCOMMENT("( Ctx Switch CDM Enable: 0x%08x)", RGXFWIF_INICFG_CTXSWITCH_CDM_EN);
+ 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("( Reserved (do not set): 0x%08x)", RGXFWIF_INICFG_RSVD);
+ PDUMPCOMMENT("( Rascal+Dust Power Island: 0x%08x)", RGXFWIF_INICFG_POW_RASCALDUST);
+ PDUMPCOMMENT("( Enable HWPerf: 0x%08x)", RGXFWIF_INICFG_HWPERF_EN);
+ PDUMPCOMMENT("( Enable HWR: 0x%08x)", RGXFWIF_INICFG_HWR_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 defined(RGX_FEATURE_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)", RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_INSTANCE);
+ PDUMPCOMMENT("( Ctx Switch Object mode List: 0x%08x)", RGXFWIF_INICFG_VDM_CTX_STORE_MODE_LIST);
+#endif
+ PDUMPCOMMENT("( Enable SHG Bypass mode: 0x%08x)", RGXFWIF_INICFG_SHG_BYPASS_EN);
+ PDUMPCOMMENT("( Enable RTU Bypass mode: 0x%08x)", RGXFWIF_INICFG_RTU_BYPASS_EN);
+ PDUMPCOMMENT("( Enable register configuration: 0x%08x)", RGXFWIF_INICFG_REGCONFIG_EN);
+
+ DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, ui32ConfigFlags),
+ psRGXFWInit->ui32ConfigFlags,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ /*
+ * 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("( DEBUG Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DEBUG);
+ DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+ offsetof(RGXFWIF_TRACEBUF, ui32LogType),
+ psDevInfo->psRGXFWIfTraceBuf->ui32LogType,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ PDUMPCOMMENT("Set the HWPerf Filter config here");
+ DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, ui64HWPerfFilter),
+ psRGXFWInit->ui64HWPerfFilter,
+ PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ PDUMPCOMMENT("(Number of registers configurations in sidekick)");
+ DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRegCfgMemDesc,
+ offsetof(RGXFWIF_REG_CFG, ui32NumRegsSidekick),
+ 0,
+ PDUMP_FLAGS_CONTINUOUS);
+ PDUMPCOMMENT("(Number of registers configurations in rascal/dust)");
+ DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRegCfgMemDesc,
+ offsetof(RGXFWIF_REG_CFG, ui32NumRegsRascalDust),
+ 0,
+ PDUMP_FLAGS_CONTINUOUS);
+ PDUMPCOMMENT("(Set registers here, address, value)");
+ DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfRegCfgMemDesc,
+ offsetof(RGXFWIF_REG_CFG, asRegConfigs[0].ui64Addr),
+ 0,
+ PDUMP_FLAGS_CONTINUOUS);
+ DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfRegCfgMemDesc,
+ offsetof(RGXFWIF_REG_CFG, asRegConfigs[0].ui64Value),
+ 0,
+ PDUMP_FLAGS_CONTINUOUS);
+#endif /* SUPPORT_USER_REGISTER_CONFIGURATION */
+#endif
+
+ /* We don't need access to the fw init data structure anymore */
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
+ psRGXFWInit = IMG_NULL;
+
+ psDevInfo->bFirmwareInitialised = IMG_TRUE;
+
+ return PVRSRV_OK;
+
+failMapCompleted:
+ DevmemFwFree(psDevInfo->psCompletedMemDesc);
+failAllocCompleted:
+ DevmemReleaseCpuVirtAddr(psDevInfo->psEndTimeMemDesc);
+failMapEndTimes:
+ DevmemFwFree(psDevInfo->psEndTimeMemDesc);
+failAllocEndTimes:
+ DevmemReleaseCpuVirtAddr(psDevInfo->psStartTimeMemDesc);
+failMapStartTimes:
+ DevmemFwFree(psDevInfo->psStartTimeMemDesc);
+failAllocStartTimes:
+
+#if defined(RGX_FEATURE_SLC_VIVT)
+failSLC3Fence:
+#endif
+
+#if defined(RGXFW_ALIGNCHECKS)
+failAlignCheck:
+ DevmemFwFree(psDevInfo->psRGXFWSig3DChecksMemDesc);
+#endif
+
+
+#if defined(RGX_FEATURE_RAY_TRACING)
+failSHGSigCheck:
+ DevmemFwFree(psDevInfo->psRGXFWSigSHChecksMemDesc);
+#endif
+fail3DSigCheck:
+ DevmemFwFree(psDevInfo->psRGXFWSigTAChecksMemDesc);
+failTASigCheck:
+#if defined(RGX_FEATURE_RAY_TRACING)
+ RGXFreeFirmwareCCB(psDevInfo, RGXFWIF_DM_RTU);
+failRTUFWCCB:
+ RGXFreeKernelCCB(psDevInfo, RGXFWIF_DM_RTU);
+failRTUCCB:
+ RGXFreeFirmwareCCB(psDevInfo, RGXFWIF_DM_SHG);
+failSHGFWCCB:
+ RGXFreeKernelCCB(psDevInfo, RGXFWIF_DM_SHG);
+failSHGCCB:
+#endif /* RGX_FEATURE_RAY_TRACING */
+ RGXFreeFirmwareCCB(psDevInfo, RGXFWIF_DM_GP);
+failGPFWCCB:
+ RGXFreeKernelCCB(psDevInfo, RGXFWIF_DM_GP);
+failGPKCCB:
+ RGXFreeFirmwareCCB(psDevInfo, RGXFWIF_DM_CDM);
+failCompFWCCB:
+ RGXFreeKernelCCB(psDevInfo, RGXFWIF_DM_CDM);
+failCompKCCB:
+ RGXFreeFirmwareCCB(psDevInfo, RGXFWIF_DM_2D);
+fail2DFWCCB:
+ RGXFreeKernelCCB(psDevInfo, RGXFWIF_DM_2D);
+fail2DKCCB:
+ RGXFreeFirmwareCCB(psDevInfo, RGXFWIF_DM_3D);
+fail3DFWCCB:
+ RGXFreeKernelCCB(psDevInfo, RGXFWIF_DM_3D);
+fail3DKCCB:
+ RGXFreeFirmwareCCB(psDevInfo, RGXFWIF_DM_TA);
+failTAFWCCB:
+ RGXFreeKernelCCB(psDevInfo, RGXFWIF_DM_TA);
+
+failTAKCCB:
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
+
+ RGXHwBrn37200Rollback(psDevInfo);
+failFWHWBRN37200:
+
+ RGXSetupFaultReadRegisterRollback(psDevInfo);
+failFWSetupFaultReadRegister:
+ SyncPrimFree(psDevInfo->psPowSyncPrim);
+
+failed_sync_alloc:
+ SyncPrimContextDestroy(psDevInfo->hSyncPrimContext);
+
+failed_sync_ctx_alloc:
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ DevmemFwFree(psDevInfo->psRGXFWIfRegCfgMemDesc);
+
+failFWIfRegconfigMemDescAlloc:
+#endif
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
+
+failFWIfRuntimeCfgMemDescAqCpuVirt:
+ DevmemFwFree(psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
+
+failFWIfRuntimeCfgMemDescAlloc:
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
+
+failFWIfGpuUtilFWCbCtlMemDescAqCpuVirt:
+ DevmemFwFree(psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
+
+failFWIfGpuUtilFWCbCtlMemDescAlloc:
+ /* Nothing to do for invalid log type check */
+
+failInvalidLogType:
+ RGXHWPerfDeinit();
+
+failHWPerfInit:
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
+
+failFWIfHWRInfoBufCtlMemDescAqCpuVirt:
+ DevmemFwFree(psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
+
+failFWIfHWRInfoBufCtlMemDescAlloc:
+ DevmemFwFree(psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+
+failFWIfCorememDataStoreMemDescAlloc:
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfHWPerfBufMemDesc);
+failFWIfInitHWPerfInfoMemDescAqCpuVirt:
+ PVR_DPF((PVR_DBG_WARNING, "failFWIfInitHWRPerfInfoMemDescAqCpuVirt"));
+ DevmemFwFree(psDevInfo->psRGXFWIfHWPerfBufMemDesc);
+
+failFWIfInitHWPerfInfoMemDescAlloc:
+ PVR_DPF((PVR_DBG_WARNING, "failFWIfInitHWPerfInfoMemDescAlloc"));
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
+failFWIfTraceBufCtlMemDescAqCpuVirt:
+ DevmemFwFree(psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
+
+failFWIfTraceBufCtlMemDescAlloc:
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
+failFWIfInitMemDescAqCpuVirt:
+ DevmemFwFree(psDevInfo->psRGXFWIfInitMemDesc);
+
+failFWIfInitMemDescAlloc:
+
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*!
+*******************************************************************************
+
+ @Function RGXFreeFirmware
+
+ @Description
+
+ Frees all the firmware-related allocations
+
+ @Input psDevInfo
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_VOID RGXFreeFirmware(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ RGXFWIF_DM eCCBType;
+
+ psDevInfo->bFirmwareInitialised = IMG_FALSE;
+
+ for (eCCBType = 0; eCCBType < RGXFWIF_DM_MAX; eCCBType++)
+ {
+ if (psDevInfo->apsKernelCCBMemDesc[eCCBType])
+ {
+ RGXFreeKernelCCB(psDevInfo, eCCBType);
+ }
+ if (psDevInfo->apsFirmwareCCBMemDesc[eCCBType])
+ {
+ RGXFreeFirmwareCCB(psDevInfo, eCCBType);
+ }
+ }
+
+ if (psDevInfo->psRGXFWCodeMemDesc)
+ {
+ /* Free fw code */
+ PDUMPCOMMENT("Freeing FW code memory");
+ DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
+ DevmemFwFree(psDevInfo->psRGXFWCodeMemDesc);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"No firmware code memory to free!"));
+ }
+
+ if (psDevInfo->psRGXFWDataMemDesc)
+ {
+ /* Free fw data */
+ PDUMPCOMMENT("Freeing FW data memory");
+ DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
+ DevmemFwFree(psDevInfo->psRGXFWDataMemDesc);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"No firmware data memory to free!"));
+ }
+
+ if (psDevInfo->psRGXFWCorememMemDesc)
+ {
+ /* Free fw data */
+ PDUMPCOMMENT("Freeing FW coremem memory");
+ DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCorememMemDesc);
+ DevmemFwFree(psDevInfo->psRGXFWCorememMemDesc);
+ }
+
+#if defined(RGXFW_ALIGNCHECKS)
+ if (psDevInfo->psRGXFWAlignChecksMemDesc)
+ {
+ RGXFWFreeAlignChecks(psDevInfo);
+ }
+#endif
+
+ if (psDevInfo->psRGXFWSigTAChecksMemDesc)
+ {
+ DevmemFwFree(psDevInfo->psRGXFWSigTAChecksMemDesc);
+ }
+
+ if (psDevInfo->psRGXFWSig3DChecksMemDesc)
+ {
+ DevmemFwFree(psDevInfo->psRGXFWSig3DChecksMemDesc);
+ }
+
+#if defined(RGX_FEATURE_RAY_TRACING)
+ if (psDevInfo->psRGXFWSigRTChecksMemDesc)
+ {
+ DevmemFwFree(psDevInfo->psRGXFWSigRTChecksMemDesc);
+ }
+
+ if (psDevInfo->psRGXFWSigSHChecksMemDesc)
+ {
+ DevmemFwFree(psDevInfo->psRGXFWSigSHChecksMemDesc);
+ }
+#endif
+
+#if defined(FIX_HW_BRN_37200)
+ if (psDevInfo->psRGXFWHWBRN37200MemDesc)
+ {
+ DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWHWBRN37200MemDesc);
+ DevmemFree(psDevInfo->psRGXFWHWBRN37200MemDesc);
+ }
+#endif
+
+ RGXSetupFaultReadRegisterRollback(psDevInfo);
+
+ if (psDevInfo->psPowSyncPrim != IMG_NULL)
+ {
+ SyncPrimFree(psDevInfo->psPowSyncPrim);
+ psDevInfo->psPowSyncPrim = IMG_NULL;
+ }
+
+ if (psDevInfo->hSyncPrimContext != 0)
+ {
+ SyncPrimContextDestroy(psDevInfo->hSyncPrimContext);
+ psDevInfo->hSyncPrimContext = 0;
+ }
+
+ if (psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc)
+ {
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
+ DevmemFwFree(psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
+ }
+
+ if (psDevInfo->psRGXFWIfRuntimeCfgMemDesc)
+ {
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
+ DevmemFwFree(psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
+ }
+
+ if (psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc)
+ {
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
+ DevmemFwFree(psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
+ }
+
+ RGXHWPerfDeinit();
+
+ if (psDevInfo->psRGXFWIfHWPerfBufMemDesc)
+ {
+ psDevInfo->psRGXFWIfHWPerfBuf = IMG_NULL;
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfHWPerfBufMemDesc);
+ DevmemFwFree(psDevInfo->psRGXFWIfHWPerfBufMemDesc);
+ psDevInfo->psRGXFWIfHWPerfBufMemDesc = IMG_NULL;
+ }
+
+ if (psDevInfo->psRGXFWIfCorememDataStoreMemDesc)
+ {
+ DevmemFwFree(psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+ psDevInfo->psRGXFWIfCorememDataStoreMemDesc = IMG_NULL;
+ }
+
+ if (psDevInfo->psRGXFWIfTraceBufCtlMemDesc)
+ {
+ psDevInfo->psRGXFWIfTraceBuf = IMG_NULL;
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
+ DevmemFwFree(psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
+ psDevInfo->psRGXFWIfTraceBufCtlMemDesc = IMG_NULL;
+ }
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ if (psDevInfo->psRGXFWIfRegCfgMemDesc)
+ {
+ DevmemFwFree(psDevInfo->psRGXFWIfRegCfgMemDesc);
+ }
+#endif
+
+#if defined(RGX_FEATURE_SLC_VIVT)
+ _FreeSLC3Fence(psDevInfo);
+#endif
+
+ if (psDevInfo->psRGXFWIfInitMemDesc)
+ {
+ DevmemFwFree(psDevInfo->psRGXFWIfInitMemDesc);
+ psDevInfo->psRGXFWIfInitMemDesc = IMG_NULL;
+ }
+
+ if (psDevInfo->psCompletedMemDesc)
+ {
+ if (psDevInfo->pui32CompletedById)
+ {
+ DevmemReleaseCpuVirtAddr(psDevInfo->psCompletedMemDesc);
+ psDevInfo->pui32CompletedById = IMG_NULL;
+ }
+ DevmemFwFree(psDevInfo->psCompletedMemDesc);
+ psDevInfo->psCompletedMemDesc = IMG_NULL;
+ }
+ if (psDevInfo->psEndTimeMemDesc)
+ {
+ if (psDevInfo->pui64EndTimeById)
+ {
+ DevmemReleaseCpuVirtAddr(psDevInfo->psEndTimeMemDesc);
+ psDevInfo->pui64EndTimeById = IMG_NULL;
+ }
+
+ DevmemFwFree(psDevInfo->psEndTimeMemDesc);
+ psDevInfo->psEndTimeMemDesc = IMG_NULL;
+ }
+ if (psDevInfo->psStartTimeMemDesc)
+ {
+ if (psDevInfo->pui64StartTimeById)
+ {
+ DevmemReleaseCpuVirtAddr(psDevInfo->psStartTimeMemDesc);
+ psDevInfo->pui64StartTimeById = IMG_NULL;
+ }
+
+ DevmemFwFree(psDevInfo->psStartTimeMemDesc);
+ psDevInfo->psStartTimeMemDesc = IMG_NULL;
+ }
+}
+
+
+/******************************************************************************
+ FUNCTION : RGXStartFirmware
+
+ PURPOSE : Attempts to obtain a slot in the Kernel CCB
+
+ PARAMETERS : psDevInfo
+
+ RETURNS : PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXStartFirmware(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: Rogue Firmware Slave boot Start");
+ /*
+ * Run init script.
+ */
+ eError = RGXRunScript(psDevInfo, psDevInfo->psScripts->asInitCommands, RGX_MAX_INIT_COMMANDS, PDUMP_FLAGS_CONTINUOUS, IMG_NULL);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXStart: RGXRunScript failed (%d)", eError));
+ return eError;
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: Rogue Firmware startup complete\n");
+
+ return eError;
+}
+
+
+/******************************************************************************
+ FUNCTION : RGXAcquireKernelCCBSlot
+
+ PURPOSE : Attempts to obtain a slot in the Kernel CCB
+
+ PARAMETERS : psCCB - the CCB
+ : Address of space if available, IMG_NULL otherwise
+
+ RETURNS : PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXAcquireKernelCCBSlot(DEVMEM_MEMDESC *psKCCBCtrlMemDesc,
+ RGXFWIF_CCB_CTL *psKCCBCtl,
+ IMG_UINT32 *pui32Offset)
+{
+ IMG_UINT32 ui32OldWriteOffset, ui32NextWriteOffset;
+
+ ui32OldWriteOffset = psKCCBCtl->ui32WriteOffset;
+ ui32NextWriteOffset = (ui32OldWriteOffset + 1) & psKCCBCtl->ui32WrapMask;
+
+ /* Note: The MTS can queue up to 255 kicks (254 pending kicks and 1 executing kick)
+ * Hence the kernel CCB should not queue more 254 commands
+ */
+ PVR_ASSERT(psKCCBCtl->ui32WrapMask < 255);
+
+#if defined(PDUMP)
+ /* Wait for sufficient CCB space to become available */
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for kCCB woff=%u", ui32NextWriteOffset);
+ DevmemPDumpCBP(psKCCBCtrlMemDesc,
+ offsetof(RGXFWIF_CCB_CTL, ui32ReadOffset),
+ ui32NextWriteOffset,
+ 1,
+ (psKCCBCtl->ui32WrapMask + 1));
+#endif
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+
+ if (ui32NextWriteOffset != psKCCBCtl->ui32ReadOffset)
+ {
+ *pui32Offset = ui32NextWriteOffset;
+ return PVRSRV_OK;
+ }
+ {
+ /*
+ * The following sanity 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();
+
+ /* Time out on waiting for CCB space */
+ return PVRSRV_ERROR_KERNEL_CCB_FULL;
+}
+
+
+PVRSRV_ERROR RGXSendCommandWithPowLock(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eKCCBType,
+ RGXFWIF_KCCB_CMD *psKCCBCmd,
+ IMG_UINT32 ui32CmdSize,
+ IMG_BOOL bPDumpContinuous)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+
+ /* Ensure Rogue is powered up before kicking MTS */
+ eError = PVRSRVPowerLock();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXSendCommandWithPowLock: failed to acquire powerlock (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+
+ goto _PVRSRVPowerLock_Exit;
+ }
+
+ PDUMPPOWCMDSTART();
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_ON,
+ IMG_FALSE);
+ PDUMPPOWCMDEND();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXSendCommandWithPowLock: failed to transition Rogue to ON (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+
+ goto _PVRSRVSetDevicePowerStateKM_Exit;
+ }
+
+ eError = RGXSendCommandRaw(psDevInfo, eKCCBType, psKCCBCmd, ui32CmdSize, bPDumpContinuous?PDUMP_FLAGS_CONTINUOUS:0);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXSendCommandWithPowLock: failed to schedule command (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+#if defined(DEBUG)
+ /* PVRSRVDebugRequest must be called without powerlock */
+ PVRSRVPowerUnlock();
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
+ goto _PVRSRVPowerLock_Exit;
+#endif
+ }
+
+_PVRSRVSetDevicePowerStateKM_Exit:
+ PVRSRVPowerUnlock();
+
+_PVRSRVPowerLock_Exit:
+ return eError;
+}
+
+PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eKCCBType,
+ RGXFWIF_KCCB_CMD *psKCCBCmd,
+ IMG_UINT32 ui32CmdSize,
+ PDUMP_FLAGS_T uiPdumpFlags)
+{
+ PVRSRV_ERROR eError;
+ RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->apsKernelCCBCtl[eKCCBType];
+ IMG_UINT8 *pui8KCCB = psDevInfo->apsKernelCCB[eKCCBType];
+ IMG_UINT32 ui32NewWriteOffset;
+ IMG_UINT32 ui32OldWriteOffset = psKCCBCtl->ui32WriteOffset;
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(uiPdumpFlags);
+#endif
+#if defined(PDUMP)
+ IMG_BOOL bIsInCaptureRange;
+ IMG_BOOL bPdumpEnabled;
+ IMG_BOOL bPDumpContinuous = (uiPdumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0;
+ IMG_BOOL bPDumpPowTrans = PDUMPPOWCMDINTRANS();
+
+ PDumpIsCaptureFrameKM(&bIsInCaptureRange);
+ bPdumpEnabled = (bIsInCaptureRange || bPDumpContinuous) && !bPDumpPowTrans;
+
+ /* in capture range */
+ if (bPdumpEnabled)
+ {
+ if (!psDevInfo->abDumpedKCCBCtlAlready[eKCCBType])
+ {
+ /* entering capture range */
+ psDevInfo->abDumpedKCCBCtlAlready[eKCCBType] = IMG_TRUE;
+
+ /* wait for firmware to catch up */
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXSendCommandRaw: waiting on fw to catch-up. DM: %d, roff: %d, woff: %d",
+ eKCCBType, psKCCBCtl->ui32ReadOffset, ui32OldWriteOffset));
+ PVRSRVPollForValueKM(&psKCCBCtl->ui32ReadOffset, ui32OldWriteOffset, 0xFFFFFFFF);
+
+ /* Dump Init state of Kernel CCB control (read and write offset) */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Initial state of kernel CCB Control(%d), roff: %d, woff: %d", eKCCBType, psKCCBCtl->ui32ReadOffset, psKCCBCtl->ui32WriteOffset);
+ DevmemPDumpLoadMem(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType],
+ 0,
+ sizeof(RGXFWIF_CCB_CTL),
+ PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+#endif
+
+ PVR_ASSERT(ui32CmdSize == psKCCBCtl->ui32CmdSize);
+ if (!OSLockIsLocked(PVRSRVGetPVRSRVData()->hPowerLock))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXSendCommandRaw called without power lock held!"));
+ PVR_ASSERT(OSLockIsLocked(PVRSRVGetPVRSRVData()->hPowerLock));
+ }
+
+ /*
+ * Acquire a slot in the CCB.
+ */
+ eError = RGXAcquireKernelCCBSlot(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType], psKCCBCtl, &ui32NewWriteOffset);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXSendCommandRaw failed to acquire CCB slot. Type:%u Error:%u",
+ eKCCBType, eError));
+ goto _RGXSendCommandRaw_Exit;
+ }
+
+ /*
+ * Copy the command into the CCB.
+ */
+ OSMemCopy(&pui8KCCB[ui32OldWriteOffset * psKCCBCtl->ui32CmdSize],
+ psKCCBCmd, psKCCBCtl->ui32CmdSize);
+
+ /* ensure kCCB data is written before the offsets */
+ OSWriteMemoryBarrier();
+
+ /* Move past the current command */
+ psKCCBCtl->ui32WriteOffset = ui32NewWriteOffset;
+
+
+#if defined(PDUMP)
+ /* in capture range */
+ if (bPdumpEnabled)
+ {
+ /* Dump new Kernel CCB content */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Dump kCCB(%d) cmd, woff = %d", eKCCBType, ui32OldWriteOffset);
+ DevmemPDumpLoadMem(psDevInfo->apsKernelCCBMemDesc[eKCCBType],
+ ui32OldWriteOffset * psKCCBCtl->ui32CmdSize,
+ psKCCBCtl->ui32CmdSize,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ /* Dump new kernel CCB write offset */
+ PDUMPCOMMENTWITHFLAGS(uiPdumpFlags, "Dump kCCBCtl(%d) woff: %d", eKCCBType, ui32NewWriteOffset);
+ DevmemPDumpLoadMem(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType],
+ offsetof(RGXFWIF_CCB_CTL, ui32WriteOffset),
+ sizeof(IMG_UINT32),
+ uiPdumpFlags);
+ }
+
+ /* out of capture range */
+ if (!bPdumpEnabled)
+ {
+ if (psDevInfo->abDumpedKCCBCtlAlready[eKCCBType])
+ {
+ /* exiting capture range */
+ psDevInfo->abDumpedKCCBCtlAlready[eKCCBType] = IMG_FALSE;
+
+ /* make sure previous cmds are drained in pdump in case we will 'jump' over some future cmds */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_POWER,
+ "kCCB(%p): Draining rgxfw_roff (0x%x) == woff (0x%x)",
+ psKCCBCtl,
+ ui32OldWriteOffset,
+ ui32OldWriteOffset);
+ eError = DevmemPDumpDevmemPol32(psDevInfo->apsKernelCCBCtlMemDesc[eKCCBType],
+ offsetof(RGXFWIF_CCB_CTL, ui32ReadOffset),
+ ui32OldWriteOffset,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_POWER);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXSendCommandRaw: problem pdumping POL for cCCBCtl (%d)", eError));
+ goto _RGXSendCommandRaw_Exit;
+ }
+ }
+ }
+#endif
+
+
+ PDUMPCOMMENTWITHFLAGS(uiPdumpFlags, "MTS kick for kernel CCB %d", eKCCBType);
+ /*
+ * Kick the MTS to schedule the firmware.
+ */
+ {
+ IMG_UINT32 ui32MTSRegVal = (eKCCBType & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK) | RGX_CR_MTS_SCHEDULE_TASK_COUNTED;
+
+ __MTSScheduleWrite(psDevInfo, ui32MTSRegVal);
+
+ PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_MTS_SCHEDULE, ui32MTSRegVal, uiPdumpFlags);
+ }
+
+#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;
+}
+
+IMG_VOID RGXScheduleProcessQueuesKM(PVRSRV_CMDCOMP_HANDLE hCmdCompHandle)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE*) hCmdCompHandle;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ OSScheduleMISR(psDevInfo->hProcessQueuesMISR);
+}
+
+/*!
+******************************************************************************
+
+ @Function _RGXScheduleProcessQueuesMISR
+
+ @Description - Sends uncounted kick to all the DMs (the FW will process all
+ the queue for all the DMs)
+******************************************************************************/
+static IMG_VOID _RGXScheduleProcessQueuesMISR(IMG_VOID *pvData)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_DM eDM;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEV_POWER_STATE ePowerState;
+
+ /* We don't need to acquire the BridgeLock as this power transition won't
+ send a command to the FW */
+ eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXScheduleProcessQueuesKM: failed to acquire powerlock (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+
+ return;
+ }
+
+ /* Check whether it's worth waking up the GPU */
+ eError = PVRSRVGetDevicePowerState(psDeviceNode->sDevId.ui32DeviceIndex, &ePowerState);
+
+ if ((eError == PVRSRV_OK) && (ePowerState == PVRSRV_DEV_POWER_STATE_OFF))
+ {
+ RGXFWIF_GPU_UTIL_FWCB *psUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
+ IMG_UINT64 ui64FWCbEntryCurrent;
+ IMG_BOOL bGPUHasWorkWaiting;
+ IMG_UINT32 ui32WriteOffset;
+
+ ui32WriteOffset = (psUtilFWCb->ui32WriteOffset == 0)? (RGXFWIF_GPU_UTIL_FWCB_SIZE-1):(psUtilFWCb->ui32WriteOffset-1);
+ ui64FWCbEntryCurrent = psUtilFWCb->aui64CB[ui32WriteOffset];
+ bGPUHasWorkWaiting = (RGXFWIF_GPU_UTIL_FWCB_ENTRY_STATE(ui64FWCbEntryCurrent) == RGXFWIF_GPU_UTIL_FWCB_STATE_BLOCKED);
+
+ if (!bGPUHasWorkWaiting)
+ {
+ /* all queues are empty, don't wake up the GPU */
+ PVRSRVPowerUnlock();
+ return;
+ }
+ }
+
+ PDUMPPOWCMDSTART();
+ /* wake up the GPU */
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_ON,
+ IMG_FALSE);
+ PDUMPPOWCMDEND();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXScheduleProcessQueuesKM: failed to transition Rogue to ON (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+
+ PVRSRVPowerUnlock();
+ return;
+ }
+
+ /* uncounted kick for all DMs */
+ for (eDM = RGXFWIF_HWDM_MIN; eDM < RGXFWIF_HWDM_MAX; eDM++)
+ {
+ IMG_UINT32 ui32MTSRegVal = (eDM & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK) | RGX_CR_MTS_SCHEDULE_TASK_NON_COUNTED;
+
+ __MTSScheduleWrite(psDevInfo, ui32MTSRegVal);
+ }
+
+ PVRSRVPowerUnlock();
+}
+
+PVRSRV_ERROR RGXInstallProcessQueuesMISR(IMG_HANDLE *phMISR, PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ return OSInstallMISR(phMISR,
+ _RGXScheduleProcessQueuesMISR,
+ psDeviceNode);
+}
+
+typedef struct _DEVMEM_COMMON_CONTEXT_LOOKUP_
+{
+ IMG_UINT32 ui32ContextID;
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
+} DEVMEM_COMMON_CONTEXT_LOOKUP;
+
+
+static IMG_BOOL _FindServerCommonContext(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ DEVMEM_COMMON_CONTEXT_LOOKUP *psRefLookUp = (DEVMEM_COMMON_CONTEXT_LOOKUP *)pvCallbackData;
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
+
+ psServerCommonContext = IMG_CONTAINER_OF(psNode, RGX_SERVER_COMMON_CONTEXT, sListNode);
+
+ if (psServerCommonContext->ui32ContextID == psRefLookUp->ui32ContextID)
+ {
+ psRefLookUp->psServerCommonContext = psServerCommonContext;
+ return IMG_FALSE;
+ }
+ else
+ {
+ return IMG_TRUE;
+ }
+}
+
+
+/*!
+******************************************************************************
+
+ @Function RGXScheduleCommand
+
+ @Description - Submits a CCB command and kicks the firmware but first schedules
+ any commands which have to happen before handle
+
+ @Input psDevInfo - pointer to device info
+ @Input eKCCBType - see RGXFWIF_CMD_*
+ @Input pvKCCBCmd - kernel CCB command
+ @Input ui32CmdSize -
+ @Input bPDumpContinuous - TRUE if the pdump flags should be continuous
+
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
+PVRSRV_ERROR RGXScheduleCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eKCCBType,
+ RGXFWIF_KCCB_CMD *psKCCBCmd,
+ IMG_UINT32 ui32CmdSize,
+ IMG_BOOL bPDumpContinuous)
+{
+ PVRSRV_DATA *psData = PVRSRVGetPVRSRVData();
+ PVRSRV_ERROR eError;
+
+ if ((eKCCBType == RGXFWIF_DM_3D) || (eKCCBType == RGXFWIF_DM_2D) || (eKCCBType == RGXFWIF_DM_CDM))
+ {
+ /* This handles the no operation case */
+ OSCPUOperation(psData->uiCacheOp);
+ psData->uiCacheOp = PVRSRV_CACHE_OP_NONE;
+ }
+
+ eError = RGXPreKickCacheCommand(psDevInfo);
+ if (eError != PVRSRV_OK) goto RGXScheduleCommand_exit;
+
+ eError = RGXSendCommandWithPowLock(psDevInfo, eKCCBType, psKCCBCmd, ui32CmdSize, bPDumpContinuous);
+ if (eError != PVRSRV_OK) goto RGXScheduleCommand_exit;
+
+
+RGXScheduleCommand_exit:
+ return eError;
+}
+
+/*
+ * RGXCheckFirmwareCCBs
+ */
+IMG_VOID RGXCheckFirmwareCCBs(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ RGXFWIF_FWCCB_CMD *psFwCCBCmd;
+ IMG_UINT32 ui32DMCount;
+
+ for (ui32DMCount = 0; ui32DMCount < RGXFWIF_DM_MAX; ui32DMCount++)
+ {
+ RGXFWIF_CCB_CTL *psFWCCBCtl = psDevInfo->apsFirmwareCCBCtl[ui32DMCount];
+ IMG_UINT8 *psFWCCB = psDevInfo->apsFirmwareCCB[ui32DMCount];
+
+ while (psFWCCBCtl->ui32ReadOffset != psFWCCBCtl->ui32WriteOffset)
+ {
+ /* Point to the next command */
+ psFwCCBCmd = ((RGXFWIF_FWCCB_CMD *)psFWCCB) + psFWCCBCtl->ui32ReadOffset;
+
+ switch(psFwCCBCmd->eCmdType)
+ {
+ case RGXFWIF_FWCCB_CMD_ZSBUFFER_BACKING:
+ {
+ if (psDevInfo->bPDPEnabled)
+ {
+ PDUMP_PANIC(RGX, 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(RGX, 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(RGX, 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(RGX, FREELISTS_RECONSTRUCTION, "Request to reconstruct free lists");
+ }
+ RGXProcessRequestFreelistsReconstruction(psDevInfo, ui32DMCount,
+ psFwCCBCmd->uCmdData.sCmdFreeListsReconstruction.ui32FreelistsCount,
+ psFwCCBCmd->uCmdData.sCmdFreeListsReconstruction.aui32FreelistIDs);
+ break;
+ }
+
+ case RGXFWIF_FWCCB_CMD_CONTEXT_RESET_NOTIFICATION:
+ {
+ DEVMEM_COMMON_CONTEXT_LOOKUP sLookUp;
+
+ sLookUp.ui32ContextID = psFwCCBCmd->uCmdData.sCmdContextResetNotification.ui32ServerCommonContextID;
+ sLookUp.psServerCommonContext = IMG_NULL;
+
+ dllist_foreach_node(&psDevInfo->sCommonCtxtListHead, _FindServerCommonContext, (IMG_PVOID)&sLookUp);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXCheckFirmwareCCBs: Context 0x%p reset (ID=0x%08x, Reason=%d)",
+ sLookUp.psServerCommonContext,
+ (IMG_UINT32)(psFwCCBCmd->uCmdData.sCmdContextResetNotification.ui32ServerCommonContextID),
+ (IMG_UINT32)(psFwCCBCmd->uCmdData.sCmdContextResetNotification.eResetReason)));
+
+ if (sLookUp.psServerCommonContext != IMG_NULL)
+ {
+ sLookUp.psServerCommonContext->eLastResetReason = psFwCCBCmd->uCmdData.sCmdContextResetNotification.eResetReason;
+ }
+ break;
+ }
+
+ case RGXFWIF_FWCCB_CMD_DEBUG_DUMP:
+ {
+ RGXDumpDebugInfo(IMG_NULL,psDevInfo);
+ break;
+ }
+
+ case RGXFWIF_FWCCB_CMD_UPDATE_STATS:
+ {
+ IMG_PID pidTmp=psFwCCBCmd->uCmdData.sCmdUpdateStatsData.pidOwner;
+
+ switch (psFwCCBCmd->uCmdData.sCmdUpdateStatsData.ui32ElementToUpdate)
+ {
+ case RGXFWIF_INCREASE_TOTAL_NUM_PARTIAL_RENDERS:
+ {
+ PVRSRVStatsUpdateRenderContextStats(1,0,0,0,0,0,pidTmp);
+ break;
+ }
+ case RGXFWIF_INCREASE_TOTAL_NUM_OUT_OF_MEMORY:
+ {
+ PVRSRVStatsUpdateRenderContextStats(0,1,0,0,0,0,pidTmp);
+ break;
+ }
+ case RGXFWIF_INCREASE_NUM_TA_STORES:
+ {
+ PVRSRVStatsUpdateRenderContextStats(0,0,1,0,0,0,pidTmp);
+ break;
+ }
+ case RGXFWIF_INCREASE_NUM_3D_STORES:
+ {
+ PVRSRVStatsUpdateRenderContextStats(0,0,0,1,0,0,pidTmp);
+ break;
+ }
+ case RGXFWIF_INCREASE_NUM_SH_STORES:
+ {
+ PVRSRVStatsUpdateRenderContextStats(0,0,0,0,1,0,pidTmp);
+ break;
+ }
+ case RGXFWIF_INCREASE_NUM_CDM_STORES:
+ {
+ PVRSRVStatsUpdateRenderContextStats(0,0,0,0,0,1,pidTmp);
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ PVR_ASSERT(IMG_FALSE);
+ }
+
+ /* Update read offset */
+ psFWCCBCtl->ui32ReadOffset = (psFWCCBCtl->ui32ReadOffset + 1) & psFWCCBCtl->ui32WrapMask;
+ }
+ }
+}
+
+/*
+ * PVRSRVRGXFrameworkCopyCommand
+ */
+PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(DEVMEM_MEMDESC *psFWFrameworkMemDesc,
+ IMG_PBYTE pbyGPUFRegisterList,
+ IMG_UINT32 ui32FrameworkRegisterSize)
+{
+ PVRSRV_ERROR eError;
+ RGXFWIF_RF_REGISTERS *psRFReg;
+
+ eError = DevmemAcquireCpuVirtAddr(psFWFrameworkMemDesc,
+ (IMG_VOID **)&psRFReg);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXFrameworkCopyCommand: Failed to map firmware render context state (%u)",
+ eError));
+ return eError;
+ }
+
+ OSMemCopy(psRFReg, pbyGPUFRegisterList, ui32FrameworkRegisterSize);
+
+ /* Release the CPU mapping */
+ DevmemReleaseCpuVirtAddr(psFWFrameworkMemDesc);
+
+ /*
+ * Dump the FW framework buffer
+ */
+ PDUMPCOMMENT("Dump FWFramework buffer");
+ DevmemPDumpLoadMem(psFWFrameworkMemDesc, 0, ui32FrameworkRegisterSize, PDUMP_FLAGS_CONTINUOUS);
+
+ 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("Allocate Rogue firmware framework state");
+
+ eError = DevmemFwAllocate(psDevInfo,
+ ui32FrameworkCommandSize,
+ RGX_FWCOMCTX_ALLOCFLAGS,
+ "FirmwareGPUFrameworkState",
+ ppsFWFrameworkMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXFrameworkContextKM: Failed to allocate firmware framework state (%u)",
+ eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXWaitForFWOp(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eDM,
+ PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
+ IMG_BOOL bPDumpContinuous)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+ RGXFWIF_KCCB_CMD sCmdSyncPrim;
+
+ /* Ensure Rogue is powered up before kicking MTS */
+ eError = PVRSRVPowerLock();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXWaitForFWOp: failed to acquire powerlock (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+
+ goto _PVRSRVPowerLock_Exit;
+ }
+
+ PDUMPPOWCMDSTART();
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_ON,
+ IMG_FALSE);
+ PDUMPPOWCMDEND();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXWaitForFWOp: failed to transition Rogue to ON (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+
+ goto _PVRSRVSetDevicePowerStateKM_Exit;
+ }
+
+
+
+
+ /* Setup sync primitive */
+ SyncPrimSet(psSyncPrim, 0);
+
+ /* prepare a sync command */
+ sCmdSyncPrim.eCmdType = RGXFWIF_KCCB_CMD_SYNC;
+ sCmdSyncPrim.uCmdData.sSyncData.uiSyncObjDevVAddr = SyncPrimGetFirmwareAddr(psSyncPrim);
+ sCmdSyncPrim.uCmdData.sSyncData.uiUpdateVal = 1;
+
+ PDUMPCOMMENT("RGXWaitForFWOp: Submit Kernel SyncPrim [0x%08x] to DM %d ", sCmdSyncPrim.uCmdData.sSyncData.uiSyncObjDevVAddr, eDM);
+
+ /* submit the sync primitive to the kernel CCB */
+ eError = RGXSendCommandRaw(psDevInfo,
+ eDM,
+ &sCmdSyncPrim,
+ sizeof(RGXFWIF_KCCB_CMD),
+ bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS:0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXScheduleCommandAndWait: Failed to schedule Kernel SyncPrim with error (%u)", eError));
+ goto _RGXSendCommandRaw_Exit;
+ }
+
+ /* Wait for sync primitive to be updated */
+#if defined(PDUMP)
+ PDUMPCOMMENT("RGXScheduleCommandAndWait: Poll for Kernel SyncPrim [0x%08x] on DM %d ", sCmdSyncPrim.uCmdData.sSyncData.uiSyncObjDevVAddr, eDM);
+
+ SyncPrimPDumpPol(psSyncPrim,
+ 1,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS:0);
+#endif
+
+ {
+ RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->apsKernelCCBCtl[eDM];
+ IMG_UINT32 ui32CurrentQueueLength = (psKCCBCtl->ui32WrapMask+1 +
+ psKCCBCtl->ui32WriteOffset -
+ psKCCBCtl->ui32ReadOffset) & psKCCBCtl->ui32WrapMask;
+ IMG_UINT32 ui32MaxRetries;
+
+ for (ui32MaxRetries = (ui32CurrentQueueLength + 1) * 3;
+ ui32MaxRetries > 0;
+ ui32MaxRetries--)
+ {
+
+ OSSetKeepPVRLock();
+ eError = PVRSRVWaitForValueKM(psSyncPrim->pui32LinAddr, 1, 0xffffffff);
+ OSSetReleasePVRLock();
+
+ if (eError != PVRSRV_ERROR_TIMEOUT)
+ {
+ break;
+ }
+ }
+
+ if (eError == PVRSRV_ERROR_TIMEOUT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXScheduleCommandAndWait: PVRSRVWaitForValueKM timed out. Dump debug information."));
+ PVRSRVPowerUnlock();
+
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX,IMG_NULL);
+ PVR_ASSERT(eError != PVRSRV_ERROR_TIMEOUT);
+ goto _PVRSRVDebugRequest_Exit;
+ }
+ }
+
+_RGXSendCommandRaw_Exit:
+_PVRSRVSetDevicePowerStateKM_Exit:
+
+ PVRSRVPowerUnlock();
+
+_PVRSRVDebugRequest_Exit:
+_PVRSRVPowerLock_Exit:
+ return eError;
+}
+
+static
+PVRSRV_ERROR RGXScheduleCleanupCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eDM,
+ RGXFWIF_KCCB_CMD *psKCCBCmd,
+ IMG_UINT32 ui32CmdSize,
+ RGXFWIF_CLEANUP_TYPE eCleanupType,
+ PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
+ IMG_BOOL bPDumpContinuous)
+{
+ PVRSRV_ERROR eError;
+
+ psKCCBCmd->eCmdType = RGXFWIF_KCCB_CMD_CLEANUP;
+
+ psKCCBCmd->uCmdData.sCleanupData.eCleanupType = eCleanupType;
+ psKCCBCmd->uCmdData.sCleanupData.uiSyncObjDevVAddr = SyncPrimGetFirmwareAddr(psSyncPrim);
+
+ SyncPrimSet(psSyncPrim, 0);
+
+ /*
+ 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 = RGXScheduleCommand(psDevInfo,
+ eDM,
+ psKCCBCmd,
+ ui32CmdSize,
+ bPDumpContinuous);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_command;
+ }
+
+ /* Wait for sync primitive to be updated */
+#if defined(PDUMP)
+ PDUMPCOMMENT("Wait for the firmware to reply to the cleanup command");
+ SyncPrimPDumpPol(psSyncPrim,
+ RGXFWIF_CLEANUP_RUN,
+ RGXFWIF_CLEANUP_RUN,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS:0);
+
+ /*
+ * The cleanup request to the firmware will tell us if a given resource is busy or not.
+ * If the RGXFWIF_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.
+ */
+ PDUMPCOMMENT("Cleanup: If this poll fails, the following resource is still in use (DM=%u, type=%u, address=0x%08x)",
+ eDM,
+ psKCCBCmd->uCmdData.sCleanupData.eCleanupType,
+ psKCCBCmd->uCmdData.sCleanupData.uCleanupData.psContext.ui32Addr);
+ SyncPrimPDumpPol(psSyncPrim,
+ 0,
+ RGXFWIF_CLEANUP_BUSY,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS:0);
+#endif
+
+ {
+ RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->apsKernelCCBCtl[eDM];
+ IMG_UINT32 ui32CurrentQueueLength = (psKCCBCtl->ui32WrapMask+1 +
+ psKCCBCtl->ui32WriteOffset -
+ psKCCBCtl->ui32ReadOffset) & psKCCBCtl->ui32WrapMask;
+ IMG_UINT32 ui32MaxRetries;
+
+ for (ui32MaxRetries = ui32CurrentQueueLength + 1;
+ ui32MaxRetries > 0;
+ ui32MaxRetries--)
+ {
+
+ OSSetKeepPVRLock();
+ eError = PVRSRVWaitForValueKM(psSyncPrim->pui32LinAddr, RGXFWIF_CLEANUP_RUN, RGXFWIF_CLEANUP_RUN);
+ OSSetReleasePVRLock();
+
+ if (eError != PVRSRV_ERROR_TIMEOUT)
+ {
+ break;
+ }
+ }
+
+ /*
+ 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,"RGXScheduleCleanupCommand: PVRSRVWaitForValueKM timed out. Dump debug information."));
+
+ eError = PVRSRV_ERROR_RETRY;
+#if defined(DEBUG)
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX,IMG_NULL);
+#endif
+ goto fail_poll;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ goto fail_poll;
+ }
+ }
+
+ /*
+ If the command has was run but a resource was busy, then the request
+ will need to be retried.
+ */
+ if (*psSyncPrim->pui32LinAddr & RGXFWIF_CLEANUP_BUSY)
+ {
+ 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,
+ PRGXFWIF_FWCOMMONCONTEXT psFWCommonContextFWAddr,
+ PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
+ RGXFWIF_DM eDM)
+{
+ RGXFWIF_KCCB_CMD sRCCleanUpCmd = {0};
+ PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("Common ctx cleanup Request DM%d [context = 0x%08x]", eDM, psFWCommonContextFWAddr.ui32Addr);
+
+ /* 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,
+ sizeof(RGXFWIF_KCCB_CMD),
+ RGXFWIF_CLEANUP_FWCOMMONCONTEXT,
+ psSyncPrim,
+ IMG_FALSE);
+
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRequestCommonContextCleanUp: Failed to schedule a memory context cleanup with error (%u)", eError));
+ }
+
+ return eError;
+}
+
+/*
+ * RGXRequestHWRTDataCleanUp
+ */
+
+PVRSRV_ERROR RGXFWRequestHWRTDataCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
+ PRGXFWIF_HWRTDATA psHWRTData,
+ PVRSRV_CLIENT_SYNC_PRIM *psSync,
+ RGXFWIF_DM eDM)
+{
+ RGXFWIF_KCCB_CMD sHWRTDataCleanUpCmd = {0};
+ PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("HW RTData cleanup Request DM%d [HWRTData = 0x%08x]", eDM, psHWRTData.ui32Addr);
+
+ sHWRTDataCleanUpCmd.uCmdData.sCleanupData.uCleanupData.psHWRTData = psHWRTData;
+
+ eError = RGXScheduleCleanupCommand(psDeviceNode->pvDevice,
+ eDM,
+ &sHWRTDataCleanUpCmd,
+ sizeof(sHWRTDataCleanUpCmd),
+ RGXFWIF_CLEANUP_HWRTDATA,
+ psSync,
+ IMG_FALSE);
+
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRequestHWRTDataCleanUp: Failed to schedule a HWRTData cleanup with error (%u)", eError));
+ }
+
+ return eError;
+}
+
+/*
+ RGXFWRequestFreeListCleanUp
+*/
+PVRSRV_ERROR RGXFWRequestFreeListCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
+ PRGXFWIF_FREELIST psFWFreeList,
+ PVRSRV_CLIENT_SYNC_PRIM *psSync)
+{
+ RGXFWIF_KCCB_CMD sFLCleanUpCmd = {0};
+ PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("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,
+ sizeof(RGXFWIF_KCCB_CMD),
+ RGXFWIF_CLEANUP_FREELIST,
+ psSync,
+ IMG_FALSE);
+
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXFWRequestFreeListCleanUp: Failed to schedule a memory context cleanup with error (%u)", eError));
+ }
+
+ return eError;
+}
+
+/*
+ RGXFWRequestZSBufferCleanUp
+*/
+PVRSRV_ERROR RGXFWRequestZSBufferCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
+ PRGXFWIF_ZSBUFFER psFWZSBuffer,
+ PVRSRV_CLIENT_SYNC_PRIM *psSync)
+{
+ RGXFWIF_KCCB_CMD sZSBufferCleanUpCmd = {0};
+ PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("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,
+ sizeof(RGXFWIF_KCCB_CMD),
+ RGXFWIF_CLEANUP_ZSBUFFER,
+ psSync,
+ IMG_FALSE);
+
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXFWRequestZSBufferCleanUp: Failed to schedule a memory context cleanup with error (%u)", eError));
+ }
+
+ 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;
+ RGXFWIF_CCB_CMD_HEADER *psCmdHeader;
+ RGXFWIF_CMD_PRIORITY *psCmd;
+ IMG_UINT32 ui32BeforeWOff = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psContext));
+ IMG_BOOL bKickCMD = IMG_TRUE;
+ PVRSRV_ERROR eError;
+
+ /*
+ Get space for command
+ */
+ ui32CmdSize = RGX_CCB_FWALLOC_ALIGN(sizeof(RGXFWIF_CCB_CMD_HEADER) + sizeof(RGXFWIF_CMD_PRIORITY));
+
+ eError = RGXAcquireCCB(FWCommonContextGetClientCCB(psContext),
+ ui32CmdSize,
+ (IMG_PVOID *) &pui8CmdPtr,
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ if (ui32BeforeWOff != RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psContext)))
+ {
+ bKickCMD = IMG_FALSE;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire client CCB", __FUNCTION__));
+ goto fail_ccbacquire;
+ }
+ }
+
+ if (bKickCMD)
+ {
+ /*
+ 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->ui32Priority = ui32Priority;
+ pui8CmdPtr += sizeof(*psCmd);
+ }
+
+ /*
+ We should reserved 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
+ */
+
+ if (bKickCMD)
+ {
+ /*
+ Submit the command
+ */
+ RGXReleaseCCB(FWCommonContextGetClientCCB(psContext),
+ ui32CmdSize,
+ IMG_TRUE);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to release space in client CCB", __FUNCTION__));
+ return eError;
+ }
+ }
+
+ /* Construct the priority command. */
+ sPriorityCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+ sPriorityCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psContext);
+ sPriorityCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psContext));
+ sPriorityCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError = RGXScheduleCommand(psDevInfo,
+ eDM,
+ &sPriorityCmd,
+ sizeof(sPriorityCmd),
+ IMG_TRUE);
+ 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,"PVRSRVRGXFlushComputeDataKM: Failed to schedule SLC flush command with error (%u)", eError));
+ }
+
+ return PVRSRV_OK;
+
+fail_ccbacquire:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*
+ RGXReadMETAReg
+*/
+PVRSRV_ERROR RGXReadMETAReg(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32RegAddr, IMG_UINT32 *pui32RegValue)
+{
+
+ IMG_UINT8 *pui8RegBase = (IMG_UINT8*)psDevInfo->pvRegsBaseKM;
+ IMG_UINT32 ui32RegValue;
+
+ /* Wait for Slave Port to be Ready */
+ if (PVRSRVPollForValueKM(
+ (IMG_UINT32*) (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) != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+
+ /* Issue the Read */
+ OSWriteHWReg32(
+ psDevInfo->pvRegsBaseKM,
+ RGX_CR_META_SP_MSLVCTRL0,
+ ui32RegAddr | RGX_CR_META_SP_MSLVCTRL0_RD_EN);
+
+ /* Wait for Slave Port to be Ready: read complete */
+ if (PVRSRVPollForValueKM(
+ (IMG_UINT32*) (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) != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+
+ /* Read the value */
+ ui32RegValue = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVDATAX);
+
+ *pui32RegValue = ui32RegValue;
+
+ return PVRSRV_OK;
+}
+
+
+/*
+ RGXUpdateHealthStatus
+*/
+PVRSRV_ERROR RGXUpdateHealthStatus(PVRSRV_DEVICE_NODE* psDevNode,
+ IMG_BOOL bCheckAfterTimePassed)
+{
+ PVRSRV_DATA* psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_DEVICE_HEALTH_STATUS eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_OK;
+ PVRSRV_RGXDEV_INFO* psDevInfo;
+ RGXFWIF_TRACEBUF* psRGXFWIfTraceBufCtl;
+ IMG_UINT32 ui32DMCount, ui32ThreadCount;
+ IMG_BOOL bKCCBCmdsWaiting;
+
+ PVR_ASSERT(psDevNode != NULL);
+ psDevInfo = psDevNode->pvDevice;
+ psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
+
+ /* If the firmware is not initialised, there is not much point continuing! */
+ if (!psDevInfo->bFirmwareInitialised || psDevInfo->pvRegsBaseKM == IMG_NULL ||
+ psDevInfo->psDeviceNode == IMG_NULL ||
+ psDevInfo->psDeviceNode->psSyncPrimPreKick == IMG_NULL)
+ {
+ return PVRSRV_OK;
+ }
+
+ /* If Rogue is not powered on, don't continue
+ (there is a race condition where PVRSRVIsDevicePowered returns TRUE when the GPU is actually powering down.
+ That's not a problem as this function does not touch the HW except for the RGXScheduleCommand function,
+ which is already powerlock safe. The worst thing that could happen is that Rogue might power back up
+ but the chances of that are very low */
+ if (!PVRSRVIsDevicePowered(psDevNode->sDevId.ui32DeviceIndex))
+ {
+ return PVRSRV_OK;
+ }
+
+ /* If this is a quick update, then include the last current value... */
+ if (!bCheckAfterTimePassed)
+ {
+ eNewStatus = psDevNode->eHealthStatus;
+ }
+
+ /*
+ Firmware thread checks...
+ */
+ for (ui32ThreadCount = 0; ui32ThreadCount < RGXFW_THREAD_NUM; ui32ThreadCount++)
+ {
+ if (psRGXFWIfTraceBufCtl != IMG_NULL)
+ {
+ IMG_CHAR* pszTraceAssertInfo = psRGXFWIfTraceBufCtl->sTraceBuf[ui32ThreadCount].sAssertBuf.szInfo;
+
+ /*
+ Check if the FW has hit an assert...
+ */
+ if (*pszTraceAssertInfo != '\0')
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Firmware thread %d has asserted: %s (%s:%d)",
+ ui32ThreadCount, pszTraceAssertInfo,
+ psRGXFWIfTraceBufCtl->sTraceBuf[ui32ThreadCount].sAssertBuf.szPath,
+ psRGXFWIfTraceBufCtl->sTraceBuf[ui32ThreadCount].sAssertBuf.ui32LineNum));
+ eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_DEAD;
+ goto _RGXUpdateHealthStatus_Exit;
+ }
+
+ /*
+ Check the threads to see if they are in the same poll locations as last time...
+ */
+ if (bCheckAfterTimePassed)
+ {
+ if (psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] != 0 &&
+ psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] == psDevInfo->aui32CrLastPollAddr[ui32ThreadCount])
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Firmware stuck on CR poll: T%u polling %s (reg:0x%08X mask:0x%08X)",
+ ui32ThreadCount,
+ ((psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] & RGXFW_POLL_TYPE_SET)?("set"):("unset")),
+ psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount] & ~RGXFW_POLL_TYPE_SET,
+ psRGXFWIfTraceBufCtl->aui32CrPollMask[ui32ThreadCount]));
+ eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_DEAD;
+ goto _RGXUpdateHealthStatus_Exit;
+ }
+ psDevInfo->aui32CrLastPollAddr[ui32ThreadCount] = psRGXFWIfTraceBufCtl->aui32CrPollAddr[ui32ThreadCount];
+ }
+ }
+ }
+
+ /*
+ Event Object Timeouts check...
+ */
+ if (psDevInfo->ui32GEOTimeoutsLastTime > 1 && psPVRSRVData->ui32GEOConsecutiveTimeouts > psDevInfo->ui32GEOTimeoutsLastTime)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Global Event Object Timeouts have risen (from %d to %d)",
+ psDevInfo->ui32GEOTimeoutsLastTime, psPVRSRVData->ui32GEOConsecutiveTimeouts));
+ eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
+ }
+ psDevInfo->ui32GEOTimeoutsLastTime = psPVRSRVData->ui32GEOConsecutiveTimeouts;
+
+ /*
+ Check the Kernel CCB pointers are valid. If any commands were waiting last time, then check
+ that some have executed since then.
+ */
+ bKCCBCmdsWaiting = IMG_FALSE;
+
+ for (ui32DMCount = 0; ui32DMCount < RGXFWIF_DM_MAX; ui32DMCount++)
+ {
+ RGXFWIF_CCB_CTL *psKCCBCtl = ((PVRSRV_RGXDEV_INFO*)psDevNode->pvDevice)->apsKernelCCBCtl[ui32DMCount];
+
+ if (psKCCBCtl != IMG_NULL)
+ {
+ if (psKCCBCtl->ui32ReadOffset > psKCCBCtl->ui32WrapMask ||
+ psKCCBCtl->ui32WriteOffset > psKCCBCtl->ui32WrapMask)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: KCCB for DM%d has invalid offset (ROFF=%d WOFF=%d)",
+ ui32DMCount, psKCCBCtl->ui32ReadOffset, psKCCBCtl->ui32WriteOffset));
+ eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
+ }
+
+ if (psKCCBCtl->ui32ReadOffset != psKCCBCtl->ui32WriteOffset)
+ {
+ bKCCBCmdsWaiting = IMG_TRUE;
+ }
+ }
+ }
+
+ if (bCheckAfterTimePassed)
+ {
+ IMG_UINT32 ui32KCCBCmdsExecuted = psDevInfo->psRGXFWIfTraceBuf->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, "RGXGetDeviceHealthStatus: No KCCB commands executed since check!"));
+ eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
+ }
+
+ /*
+ 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)
+ {
+ RGXFWIF_KCCB_CMD sCmpKCCBCmd;
+ PVRSRV_ERROR eError;
+
+ sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_HEALTH_CHECK;
+
+ eError = RGXScheduleCommand(psDevNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sCmpKCCBCmd,
+ sizeof(sCmpKCCBCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Cannot schedule Health Check command! (0x%x)", eError));
+ }
+ else
+ {
+ bKCCBCmdsWaiting = IMG_TRUE;
+ }
+ }
+ }
+
+ psDevInfo->bKCCBCmdsWaitingLastTime = bKCCBCmdsWaiting;
+ psDevInfo->ui32KCCBCmdsExecutedLastTime = ui32KCCBCmdsExecuted;
+ }
+
+ if (bCheckAfterTimePassed && (PVRSRV_DEVICE_HEALTH_STATUS_OK==eNewStatus))
+ {
+ /* Attempt to detect and deal with any stalled client contexts */
+ IMG_BOOL bStalledClient = IMG_FALSE;
+ if (CheckForStalledClientTransferCtxt(psDevInfo))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Detected stalled client transfer context"));
+ bStalledClient = IMG_TRUE;
+ }
+ if (CheckForStalledClientRenderCtxt(psDevInfo))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Detected stalled client render context"));
+ bStalledClient = IMG_TRUE;
+ }
+#if !defined(UNDER_WDDM)
+ if (CheckForStalledClientComputeCtxt(psDevInfo))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Detected stalled client compute context"));
+ bStalledClient = IMG_TRUE;
+ }
+#endif
+#if defined(RGX_FEATURE_RAY_TRACING)
+ if (CheckForStalledClientRayCtxt(psDevInfo))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXGetDeviceHealthStatus: Detected stalled client raytrace context"));
+ bStalledClient = IMG_TRUE;
+ }
+#endif
+ /* try the unblock routines only on the transition from OK to stalled */
+ if (!psDevInfo->bStalledClient && bStalledClient)
+ {
+#if defined(SUPPORT_DISPLAY_CLASS)
+ DCDisplayContextFlush();
+#endif
+ }
+ psDevInfo->bStalledClient = bStalledClient;
+ }
+
+ /*
+ Finished, save the new status...
+ */
+_RGXUpdateHealthStatus_Exit:
+ psDevNode->eHealthStatus = eNewStatus;
+
+ return PVRSRV_OK;
+} /* RGXUpdateHealthStatus */
+
+PVRSRV_ERROR CheckStalledClientCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext)
+{
+ RGX_CLIENT_CCB *psCurrentClientCCB = psCurrentServerCommonContext->psClientCCB;
+
+ return CheckForStalledCCB(psCurrentClientCCB);
+}
+
+IMG_VOID DumpStalledFWCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ RGX_CLIENT_CCB *psCurrentClientCCB = psCurrentServerCommonContext->psClientCCB;
+ PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext = psCurrentServerCommonContext->sFWCommonContextFWAddr;
+
+ DumpStalledCCBCommand(sFWCommonContext, psCurrentClientCCB, pfnDumpDebugPrintf);
+}
+
+IMG_VOID AttachKickResourcesCleanupCtls(PRGXFWIF_CLEANUP_CTL *apsCleanupCtl,
+ IMG_UINT32 *pui32NumCleanupCtl,
+ RGXFWIF_DM eDM,
+ IMG_BOOL bKick,
+ RGX_RTDATA_CLEANUP_DATA *psRTDataCleanup,
+ RGX_ZSBUFFER_DATA *psZBuffer,
+ RGX_ZSBUFFER_DATA *psSBuffer)
+{
+ PRGXFWIF_CLEANUP_CTL *psCleanupCtlWrite = apsCleanupCtl;
+
+ PVR_ASSERT((eDM == RGXFWIF_DM_TA) || (eDM == RGXFWIF_DM_3D));
+
+ if(bKick)
+ {
+ if(eDM == RGXFWIF_DM_TA)
+ {
+ if(psRTDataCleanup)
+ {
+ PRGXFWIF_CLEANUP_CTL psCleanupCtl;
+
+ RGXSetFirmwareAddress(&psCleanupCtl, psRTDataCleanup->psFWHWRTDataMemDesc,
+ offsetof(RGXFWIF_HWRTDATA, sTACleanupState),
+ RFW_FWADDR_NOREF_FLAG);
+
+ *(psCleanupCtlWrite++) = psCleanupCtl;
+ }
+ }
+ else
+ {
+ if(psRTDataCleanup)
+ {
+ PRGXFWIF_CLEANUP_CTL psCleanupCtl;
+
+ RGXSetFirmwareAddress(&psCleanupCtl, psRTDataCleanup->psFWHWRTDataMemDesc,
+ offsetof(RGXFWIF_HWRTDATA, s3DCleanupState),
+ RFW_FWADDR_NOREF_FLAG);
+
+ *(psCleanupCtlWrite++) = psCleanupCtl;
+ }
+
+ if(psZBuffer)
+ {
+ (psCleanupCtlWrite++)->ui32Addr = psZBuffer->sZSBufferFWDevVAddr.ui32Addr +
+ offsetof(RGXFWIF_FWZSBUFFER, sCleanupState);
+ }
+
+ if(psSBuffer)
+ {
+ (psCleanupCtlWrite++)->ui32Addr = psSBuffer->sZSBufferFWDevVAddr.ui32Addr +
+ offsetof(RGXFWIF_FWZSBUFFER, sCleanupState);
+ }
+ }
+ }
+
+ *pui32NumCleanupCtl = psCleanupCtlWrite - apsCleanupCtl;
+
+ PVR_ASSERT(*pui32NumCleanupCtl <= RGXFWIF_KCCB_CMD_KICK_DATA_MAX_NUM_CLEANUP_CTLS);
+}
+
+PVRSRV_ERROR RGXResetHWRLogs(PVRSRV_DEVICE_NODE *psDevNode)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+ RGXFWIF_HWRINFOBUF *psHWRInfoBuf;
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl;
+ IMG_UINT32 i;
+
+ if(psDevNode->pvDevice == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_DEVINFO;
+ }
+ psDevInfo = psDevNode->pvDevice;
+
+ psHWRInfoBuf = psDevInfo->psRGXFWIfHWRInfoBuf;
+ psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
+
+ for(i = 0 ; i < RGXFWIF_DM_MAX ; i++)
+ {
+ /* Reset the HWR numbers */
+ psRGXFWIfTraceBufCtl->aui16HwrDmLockedUpCount[i] = 0;
+ psRGXFWIfTraceBufCtl->aui16HwrDmFalseDetectCount[i] = 0;
+ psRGXFWIfTraceBufCtl->aui16HwrDmRecoveredCount[i] = 0;
+ psRGXFWIfTraceBufCtl->aui16HwrDmOverranCount[i] = 0;
+ }
+
+ for(i = 0 ; i < RGXFWIF_HWINFO_MAX ; i++)
+ {
+ psHWRInfoBuf->sHWRInfo[i].ui32HWRNumber = 0;
+ }
+
+ for(i = 0 ; i < RGXFW_THREAD_NUM ; i++)
+ {
+ psHWRInfoBuf->ui32FirstCrPollAddr[i] = 0;
+ psHWRInfoBuf->ui32FirstCrPollMask[i] = 0;
+ }
+
+ psHWRInfoBuf->ui32WriteIndex = 0;
+ psHWRInfoBuf->bDDReqIssued = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+/******************************************************************************
+ End of file (rgxfwutils.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxfwutils.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxfwutils.h
new file mode 100644
index 000000000000..185d1344101e
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxfwutils.h
@@ -0,0 +1,662 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+
+#if !defined(__RGXFWUTILS_H__)
+#define __RGXFWUTILS_H__
+
+#include "rgxdevice.h"
+#include "rgxccb.h"
+#include "devicemem.h"
+#include "device.h"
+#include "pvrsrv.h"
+#include "connection_server.h"
+#include "rgxta3d.h"
+
+
+
+/*
+ * 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,
+ DEVMEM_FLAGS_T uiFlags,
+ IMG_PCHAR pszText,
+ DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF_ENTERED;
+
+ eError = DevmemAllocate(psDevInfo->psFirmwareHeap,
+ uiSize,
+ ROGUE_CACHE_LINE_SIZE,
+ uiFlags,
+ 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,
+ psDevInfo->psFirmwareHeap,
+ &sTmpDevVAddr);
+ PVR_DPF_RETURN_RC1(eError, *ppsMemDescPtr);
+}
+
+static INLINE PVRSRV_ERROR DevmemFwAllocateExportable(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ DEVMEM_FLAGS_T uiFlags,
+ IMG_PCHAR pszText,
+ DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF_ENTERED;
+
+ eError = DevmemAllocateExportable(IMG_NULL,
+ (IMG_HANDLE) psDeviceNode,
+ uiSize,
+ 64,
+ 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->psFirmwareHeap,
+ &sTmpDevVAddr);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"FW DevmemMapToDevice failed (%u)", eError));
+ }
+ PVR_DPF_RETURN_RC1(eError, *ppsMemDescPtr);
+}
+
+static INLINE IMG_VOID DevmemFwFree(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 is 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(META_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_WRITE_COMBINE | \
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+
+/******************************************************************************
+ * 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. */
+
+
+PVRSRV_ERROR RGXSetupFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_BOOL bEnableSignatureChecks,
+ IMG_UINT32 ui32SignatureChecksBufSize,
+ IMG_UINT32 ui32HWPerfFWBufSizeKB,
+ IMG_UINT64 ui64HWPerfFilter,
+ IMG_UINT32 ui32RGXFWAlignChecksSize,
+ IMG_UINT32 *pui32RGXFWAlignChecks,
+ IMG_UINT32 ui32ConfigFlags,
+ IMG_UINT32 ui32LogType,
+ IMG_UINT32 ui32NumTilingCfgs,
+ IMG_UINT32 *pui32BIFTilingXStrides,
+ IMG_UINT32 ui32FilterMode,
+ RGXFWIF_DEV_VIRTADDR *psRGXFWInitFWAddr);
+
+
+IMG_VOID RGXFreeFirmware(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*************************************************************************/ /*!
+@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 IMG_VOID
+*/ /**************************************************************************/
+IMG_VOID RGXSetFirmwareAddress(RGXFWIF_DEV_VIRTADDR *ppDest,
+ DEVMEM_MEMDESC *psSrc,
+ IMG_UINT32 uiOffset,
+ IMG_UINT32 ui32Flags);
+
+#if defined(RGX_FEATURE_DMA)
+/*************************************************************************/ /*!
+@Function RGXSetDMAAddress
+
+@Description Fills a firmware data structure used for 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 IMG_VOID
+*/ /**************************************************************************/
+IMG_VOID RGXSetDMAAddress(RGXFWIF_DMA_ADDR *psDest,
+ DEVMEM_MEMDESC *psSrcMemDesc,
+ RGXFWIF_DEV_VIRTADDR *psSrcFWDevVAddr,
+ IMG_UINT32 uiOffset);
+#endif
+
+/*************************************************************************/ /*!
+@Function RGXUnsetFirmwareAddress
+
+@Description Unsets a pointer in a firmware data structure
+
+@Input psSrc MemDesc describing the pointer
+
+@Return IMG_VOID
+*/ /**************************************************************************/
+IMG_VOID RGXUnsetFirmwareAddress(DEVMEM_MEMDESC *psSrc);
+
+/*************************************************************************/ /*!
+@Function FWCommonContextAllocate
+
+@Description Allocate a FW common coontext. 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 pszContextName Name of the 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 ui32CCBAllocSize Size of the CCB for this context
+@Input ui32Priority Priority of the context
+@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,
+ const IMG_CHAR *pszContextName,
+ DEVMEM_MEMDESC *psAllocatedMemDesc,
+ IMG_UINT32 ui32AllocatedOffset,
+ DEVMEM_MEMDESC *psFWMemContextMemDesc,
+ DEVMEM_MEMDESC *psContextStateMemDesc,
+ IMG_UINT32 ui32CCBAllocSize,
+ IMG_UINT32 ui32Priority,
+ RGX_COMMON_CONTEXT_INFO *psInfo,
+ RGX_SERVER_COMMON_CONTEXT **ppsServerCommonContext);
+
+
+
+IMG_VOID FWCommonContextFree(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext);
+
+PRGXFWIF_FWCOMMONCONTEXT FWCommonContextGetFWAddress(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext);
+
+RGX_CLIENT_CCB *FWCommonContextGetClientCCB(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext);
+
+RGXFWIF_CONTEXT_RESET_REASON FWCommonContextGetLastResetReason(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext);
+
+PVRSRV_ERROR RGXStartFirmware(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+******************************************************************************
+
+ @Function RGXScheduleProcessQueuesKM
+
+ @Description - Software command complete handler
+ (sends uncounted kicks for all the DMs through the MISR)
+
+ @Input hCmdCompHandle - RGX device node
+
+******************************************************************************/
+IMG_IMPORT
+IMG_VOID RGXScheduleProcessQueuesKM(PVRSRV_CMDCOMP_HANDLE hCmdCompHandle);
+
+/*!
+******************************************************************************
+
+ @Function RGXInstallProcessQueuesMISR
+
+ @Description - Installs the MISR to handle Process Queues operations
+
+ @Input phMISR - Pointer to the MISR handler
+
+ @Input psDeviceNode - RGX Device node
+
+******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR RGXInstallProcessQueuesMISR(IMG_HANDLE *phMISR, PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/*************************************************************************/ /*!
+@Function RGXSendCommandWithPowLock
+
+@Description Sends a command to a particular DM without honouring
+ pending cache operations but taking the power lock.
+
+@Input psDevInfo Device Info
+@Input eDM To which DM the cmd is sent.
+@Input psKCCBCmd The cmd to send.
+@Input ui32CmdSize The cmd size.
+@Input bPDumpContinuous
+
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXSendCommandWithPowLock(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eKCCBType,
+ RGXFWIF_KCCB_CMD *psKCCBCmd,
+ IMG_UINT32 ui32CmdSize,
+ IMG_BOOL bPDumpContinuous);
+
+/*************************************************************************/ /*!
+@Function RGXSendCommandRaw
+
+@Description Sends a command to a particular DM without honouring
+ pending cache operations or the power lock.
+
+@Input psDevInfo Device Info
+@Input eDM To which DM the cmd is sent.
+@Input psKCCBCmd The cmd to send.
+@Input ui32CmdSize The cmd size.
+@Input bPDumpContinuous
+
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eKCCBType,
+ RGXFWIF_KCCB_CMD *psKCCBCmd,
+ IMG_UINT32 ui32CmdSize,
+ PDUMP_FLAGS_T uiPdumpFlags);
+
+
+/*************************************************************************/ /*!
+@Function RGXScheduleCommand
+
+@Description Sends a command to a particular DM
+
+@Input psDevInfo Device Info
+@Input eDM To which DM the cmd is sent.
+@Input psKCCBCmd The cmd to send.
+@Input ui32CmdSize The cmd size.
+@Input bPDumpContinuous
+
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXScheduleCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eKCCBType,
+ RGXFWIF_KCCB_CMD *psKCCBCmd,
+ IMG_UINT32 ui32CmdSize,
+ IMG_BOOL bPDumpContinuous);
+
+/*************************************************************************/ /*!
+@Function RGXScheduleCommandAndWait
+
+@Description Schedules the command with RGXScheduleCommand and then waits
+ for the FW to update a sync. The sync must be piggy backed on
+ the cmd, either by passing a sync cmd or a cmd that contains the
+ sync which the FW will eventually update. The sync is created in
+ the function, therefore the function provides a FWAddr and
+ UpdateValue for that cmd.
+
+@Input psDevInfo Device Info
+@Input eDM To which DM the cmd is sent.
+@Input psKCCBCmd The cmd to send.
+@Input ui32CmdSize The cmd size.
+@Input puiSyncObjFWAddr Pointer to the location with the FWAddr of
+ the sync.
+@Input puiUpdateValue Pointer to the location with the update
+ value of the sync.
+@Input bPDumpContinuous
+
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXScheduleCommandAndWait(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eDM,
+ RGXFWIF_KCCB_CMD *psKCCBCmd,
+ IMG_UINT32 ui32CmdSize,
+ IMG_UINT32 *puiSyncObjDevVAddr,
+ IMG_UINT32 *puiUpdateValue,
+ PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
+ IMG_BOOL bPDumpContinuous);
+
+PVRSRV_ERROR RGXFirmwareUnittests(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+
+/*! ***********************************************************************//**
+@brief Copy framework command into FW addressable buffer
+
+@param psFWFrameworkMemDesc
+@param pbyGPUFRegisterList
+@param ui32FrameworkRegisterSize
+
+@returns PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(DEVMEM_MEMDESC *psFWFrameworkMemDesc,
+ IMG_PBYTE pbyGPUFRegisterList,
+ IMG_UINT32 ui32FrameworkRegisterSize);
+
+
+/*! ***********************************************************************//**
+@brief Create FW addressable buffer for framework
+
+@param psDeviceNode
+@param ppsFWFrameworkMemDesc
+@param ui32FrameworkRegisterSize
+
+@returns PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR PVRSRVRGXFrameworkCreateKM(PVRSRV_DEVICE_NODE * psDeviceNode,
+ DEVMEM_MEMDESC ** ppsFWFrameworkMemDesc,
+ IMG_UINT32 ui32FrameworkRegisterSize);
+
+/*************************************************************************/ /*!
+@Function RGXWaitForFWOp
+
+@Description Send a sync command and wait to be signaled.
+
+@Input psDevInfo Device Info
+@Input eDM To which DM the cmd is sent.
+@Input bPDumpContinuous
+
+@Return IMG_VOID
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXWaitForFWOp(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eDM,
+ PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
+ IMG_BOOL bPDumpContinuous);
+
+/*!
+******************************************************************************
+
+ @Function RGXFWRequestCommonContextCleanUp
+
+ @Description Schedules a FW common context cleanup. The firmware will 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 psFWContext - firmware address of the context to be cleaned up
+
+ @Input eDM - Data master, to which the cleanup command should be send
+
+******************************************************************************/
+PVRSRV_ERROR RGXFWRequestCommonContextCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
+ PRGXFWIF_FWCOMMONCONTEXT psFWContext,
+ PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim,
+ RGXFWIF_DM eDM);
+
+/*!
+******************************************************************************
+
+ @Function RGXFWRequestHWRTDataCleanUp
+
+ @Description Schedules a FW HWRTData memory cleanup. The firmware will 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 to be cleaned up
+
+ @Input eDM - Data master, to which the cleanup command should be send
+
+ ******************************************************************************/
+PVRSRV_ERROR RGXFWRequestHWRTDataCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
+ PRGXFWIF_HWRTDATA psHWRTData,
+ PVRSRV_CLIENT_SYNC_PRIM *psSync,
+ RGXFWIF_DM eDM);
+
+/*!
+******************************************************************************
+
+ @Function RGXFWRequestFreeListCleanUp
+
+ @Description Schedules a FW FreeList cleanup. The firmware will 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 to be cleaned up
+
+ @Input eDM - Data master, to which the cleanup command should be send
+
+ ******************************************************************************/
+PVRSRV_ERROR RGXFWRequestFreeListCleanUp(PVRSRV_RGXDEV_INFO *psDeviceNode,
+ PRGXFWIF_FREELIST psFWFreeList,
+ PVRSRV_CLIENT_SYNC_PRIM *psSync);
+
+/*!
+******************************************************************************
+
+ @Function RGXFWRequestZSBufferCleanUp
+
+ @Description Schedules a FW ZS Buffer cleanup. The firmware will 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 psFWZSBuffer - firmware address of the ZS Buffer to be cleaned up
+
+ @Input eDM - Data master, to which the cleanup command should be send
+
+ ******************************************************************************/
+
+PVRSRV_ERROR RGXFWRequestZSBufferCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
+ PRGXFWIF_ZSBUFFER psFWZSBuffer,
+ PVRSRV_CLIENT_SYNC_PRIM *psSync);
+
+PVRSRV_ERROR ContextSetPriority(RGX_SERVER_COMMON_CONTEXT *psContext,
+ CONNECTION_DATA *psConnection,
+ PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32Priority,
+ RGXFWIF_DM eDM);
+
+/*!
+******************************************************************************
+
+ @Function RGXReadMETAReg
+
+ @Description Reads META register at given address and returns its value
+
+ @Input psDevInfo - pointer to device info
+
+ @Input ui32RegAddr - register address
+
+ @Output pui32RegValue - register value
+
+ ******************************************************************************/
+
+PVRSRV_ERROR RGXReadMETAReg(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 *pui32RegValue);
+
+/*!
+******************************************************************************
+
+ @Function RGXCheckFirmwareCCBs
+
+ @Description Processes all commands that are found in any firmware CCB.
+
+ @Input psDevInfo - pointer to device
+
+ ******************************************************************************/
+IMG_VOID RGXCheckFirmwareCCBs(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+******************************************************************************
+
+ @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
+ eheathStatus.
+
+ @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.
+
+ @returns PVRSRV_ERROR
+ ******************************************************************************/
+PVRSRV_ERROR RGXUpdateHealthStatus(PVRSRV_DEVICE_NODE* psDevNode,
+ IMG_BOOL bCheckAfterTimePassed);
+
+
+PVRSRV_ERROR CheckStalledClientCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext);
+
+IMG_VOID DumpStalledFWCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf);
+
+/*!
+******************************************************************************
+
+ @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 ZBuffer associated with the command.
+ @Input psSBuffer Optional SBuffer associated with the command.
+ ******************************************************************************/
+IMG_VOID AttachKickResourcesCleanupCtls(PRGXFWIF_CLEANUP_CTL *apsCleanupCtl,
+ IMG_UINT32 *pui32NumCleanupCtl,
+ RGXFWIF_DM eDM,
+ IMG_BOOL bKick,
+ RGX_RTDATA_CLEANUP_DATA *psRTDataCleanup,
+ RGX_ZSBUFFER_DATA *psZBuffer,
+ RGX_ZSBUFFER_DATA *psSBuffer);
+
+/*!
+******************************************************************************
+
+ @Function RGXResetHWRLogs
+
+ @Description Resets the HWR Logs buffer (the hardware recovery count is not reset)
+
+ @Input psDevInfo Pointer to the device
+
+ @Return PVRSRV_ERROR PVRSRV_OK on success. Otherwise, a PVRSRV_
+ error code
+ ******************************************************************************/
+PVRSRV_ERROR RGXResetHWRLogs(PVRSRV_DEVICE_NODE *psDevNode);
+
+#endif /* __RGXFWUTILS_H__ */
+/******************************************************************************
+ End of file (rgxfwutils.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxheapconfig.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxheapconfig.h
new file mode 100644
index 000000000000..3e0eea45fcdf
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxheapconfig.h
@@ -0,0 +1,181 @@
+/*************************************************************************/ /*!
+@File
+@Title device configuration
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Memory heaps device specific configuration
+@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.
+*/ /**************************************************************************/
+
+//#warning
+
+#ifndef __RGXHEAPCONFIG_H__
+#define __RGXHEAPCONFIG_H__
+
+#include "rgxdefs_km.h"
+
+#define DEV_DEVICE_TYPE PVRSRV_DEVICE_TYPE_RGX
+#define DEV_DEVICE_CLASS PVRSRV_DEVICE_CLASS_3D
+
+#define DEV_MAJOR_VERSION 1
+#define DEV_MINOR_VERSION 0
+
+/*
+ RGX Device Virtual Address Space Definitions:
+
+ Notes:
+ Base addresses have to be a multiple of 4MiB
+
+ RGX_PDSCODEDATA_HEAP_BASE and RGX_USCCODE_HEAP_BASE will be programmed, on a
+ global basis, into RGX_CR_PDS_EXEC_BASE and RGX_CR_USC_CODE_BASE_*
+ respectively.
+ Therefore if clients use multiple configs they must still be consistent with
+ their definitions for these heaps.
+*/
+
+#if RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS == 40
+
+ /* Start at 128 Kb. Size of 256 Mb */
+// #define RGX_3DPARAMETERS_HEAP_BASE IMG_UINT64_C(0x0000020000)
+// #define RGX_3DPARAMETERS_HEAP_SIZE IMG_UINT64_C(0x0010000000)
+
+ /* Start at 4GiB. Size of 512 GiB */
+ #define RGX_GENERAL_HEAP_BASE IMG_UINT64_C(0x0100000000)
+ #define RGX_GENERAL_HEAP_SIZE IMG_UINT64_C(0x8000000000)
+
+ /* start at 516 GiB. Size of 32 GiB */
+ #define RGX_BIF_TILING_NUM_HEAPS 4
+ #define RGX_BIF_TILING_HEAP_SIZE IMG_UINT64_C(0x0200000000)
+ #define RGX_BIF_TILING_HEAP_1_BASE IMG_UINT64_C(0x8100000000)
+ #define RGX_BIF_TILING_HEAP_2_BASE (RGX_BIF_TILING_HEAP_1_BASE + RGX_BIF_TILING_HEAP_SIZE)
+ #define RGX_BIF_TILING_HEAP_3_BASE (RGX_BIF_TILING_HEAP_2_BASE + RGX_BIF_TILING_HEAP_SIZE)
+ #define RGX_BIF_TILING_HEAP_4_BASE (RGX_BIF_TILING_HEAP_3_BASE + RGX_BIF_TILING_HEAP_SIZE)
+
+ /* Start at 600GiB. Size of 4 GiB */
+ #define RGX_PDSCODEDATA_HEAP_BASE IMG_UINT64_C(0x9600000000)
+ #define RGX_PDSCODEDATA_HEAP_SIZE IMG_UINT64_C(0x0100000000)
+
+ /* Start at 800GiB. Size of 4 GiB */
+ #define RGX_USCCODE_HEAP_BASE IMG_UINT64_C(0xC800000000)
+ #define RGX_USCCODE_HEAP_SIZE IMG_UINT64_C(0x0100000000)
+
+ /* Start at 903GiB. Size of 4 GiB */
+ #define RGX_FIRMWARE_HEAP_BASE IMG_UINT64_C(0xE1C0000000)
+ #define RGX_FIRMWARE_HEAP_SIZE IMG_UINT64_C(0x0100000000)
+
+ /* Start at 912GiB. Size of 16 GiB. 16GB aligned to match RGX_CR_ISP_PIXEL_BASE */
+ #define RGX_TQ3DPARAMETERS_HEAP_BASE IMG_UINT64_C(0xE400000000)
+ #define RGX_TQ3DPARAMETERS_HEAP_SIZE IMG_UINT64_C(0x0400000000)
+
+ /* Size of 16 * 4 KB (think about large page systems .. */
+#if defined(FIX_HW_BRN_37200)
+ #define RGX_HWBRN37200_HEAP_BASE IMG_UINT64_C(0xFFFFF00000)
+ #define RGX_HWBRN37200_HEAP_SIZE IMG_UINT64_C(0x0000100000)
+#endif
+
+ /* Start at 928GiB. Size of 4 GiB */
+ #define RGX_DOPPLER_HEAP_BASE IMG_UINT64_C(0xE800000000)
+ #define RGX_DOPPLER_HEAP_SIZE IMG_UINT64_C(0x0100000000)
+
+ /* Start at 932GiB. Size of 4 GiB */
+ #define RGX_DOPPLER_OVERFLOW_HEAP_BASE IMG_UINT64_C(0xE900000000)
+ #define RGX_DOPPLER_OVERFLOW_HEAP_SIZE IMG_UINT64_C(0x0100000000)
+
+ /* signal we've identified the core by the build */
+ #define RGX_CORE_IDENTIFIED
+#endif /* RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS == 40 */
+
+#if !defined(RGX_CORE_IDENTIFIED)
+ #error "rgxheapconfig.h: ERROR: unspecified RGX Core version"
+#endif
+
+/* /\********************************************************************************* */
+/* * */
+/* * Heap overlap check */
+/* * */
+/* ********************************************************************************\/ */
+/* #if defined(SUPPORT_RGX_GENERAL_MAPPING_HEAP) */
+/* #if ((RGX_GENERAL_MAPPING_HEAP_BASE + RGX_GENERAL_MAPPING_HEAP_SIZE) >= RGX_GENERAL_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_GENERAL_MAPPING_HEAP overlaps RGX_GENERAL_HEAP" */
+/* #endif */
+/* #endif */
+
+/* #if ((RGX_GENERAL_HEAP_BASE + RGX_GENERAL_HEAP_SIZE) >= RGX_3DPARAMETERS_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_GENERAL_HEAP overlaps RGX_3DPARAMETERS_HEAP" */
+/* #endif */
+
+/* #if ((RGX_3DPARAMETERS_HEAP_BASE + RGX_3DPARAMETERS_HEAP_SIZE) >= RGX_TADATA_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_3DPARAMETERS_HEAP overlaps RGX_TADATA_HEAP" */
+/* #endif */
+
+/* #if ((RGX_TADATA_HEAP_BASE + RGX_TADATA_HEAP_SIZE) >= RGX_SYNCINFO_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_TADATA_HEAP overlaps RGX_SYNCINFO_HEAP" */
+/* #endif */
+
+/* #if ((RGX_SYNCINFO_HEAP_BASE + RGX_SYNCINFO_HEAP_SIZE) >= RGX_PDSPIXEL_CODEDATA_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_SYNCINFO_HEAP overlaps RGX_PDSPIXEL_CODEDATA_HEAP" */
+/* #endif */
+
+/* #if ((RGX_PDSPIXEL_CODEDATA_HEAP_BASE + RGX_PDSPIXEL_CODEDATA_HEAP_SIZE) >= RGX_KERNEL_CODE_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_PDSPIXEL_CODEDATA_HEAP overlaps RGX_KERNEL_CODE_HEAP" */
+/* #endif */
+
+/* #if ((RGX_KERNEL_CODE_HEAP_BASE + RGX_KERNEL_CODE_HEAP_SIZE) >= RGX_PDSVERTEX_CODEDATA_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_KERNEL_CODE_HEAP overlaps RGX_PDSVERTEX_CODEDATA_HEAP" */
+/* #endif */
+
+/* #if ((RGX_PDSVERTEX_CODEDATA_HEAP_BASE + RGX_PDSVERTEX_CODEDATA_HEAP_SIZE) >= RGX_KERNEL_DATA_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_PDSVERTEX_CODEDATA_HEAP overlaps RGX_KERNEL_DATA_HEAP" */
+/* #endif */
+
+/* #if ((RGX_KERNEL_DATA_HEAP_BASE + RGX_KERNEL_DATA_HEAP_SIZE) >= RGX_PIXELSHADER_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_KERNEL_DATA_HEAP overlaps RGX_PIXELSHADER_HEAP" */
+/* #endif */
+
+/* #if ((RGX_PIXELSHADER_HEAP_BASE + RGX_PIXELSHADER_HEAP_SIZE) >= RGX_VERTEXSHADER_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_PIXELSHADER_HEAP overlaps RGX_VERTEXSHADER_HEAP" */
+/* #endif */
+
+/* #if ((RGX_VERTEXSHADER_HEAP_BASE + RGX_VERTEXSHADER_HEAP_SIZE) < RGX_VERTEXSHADER_HEAP_BASE) */
+/* #error "rgxheapconfig.h: ERROR: RGX_VERTEXSHADER_HEAP_BASE size cause wraparound" */
+/* #endif */
+
+#endif /* __RGXHEAPCONFIG_H__ */
+
+/*****************************************************************************
+ End of file (rgxheapconfig.h)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.c
new file mode 100644
index 000000000000..d8a3f2c8c4f7
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.c
@@ -0,0 +1,1727 @@
+/*************************************************************************/ /*!
+@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 "pvr_debug.h"
+#include "osfunc.h"
+#include "allocmem.h"
+
+#include "pvrsrv.h"
+#include "tlclient.h"
+#include "tlstream.h"
+
+#include "rgx_hwperf_km.h"
+#include "rgxhwperf.h"
+#include "rgxapi_km.h"
+#include "rgxfwutils.h"
+#include "devicemem_pdump.h"
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+#include "pvr_gputrace.h"
+#endif
+
+#define HWPERF_TL_STREAM_NAME "hwperf"
+
+/* Defined to ensure HWPerf packets are not delayed */
+#define SUPPORT_TL_PROODUCER_CALLBACK 1
+
+
+/******************************************************************************
+ *
+ *****************************************************************************/
+
+
+/*
+ RGXHWPerfCopyDataL1toL2
+*/
+static IMG_UINT32 RGXHWPerfCopyDataL1toL2(IMG_HANDLE hHWPerfStream,
+ IMG_BYTE *pbFwBuffer,
+ IMG_UINT32 ui32BytesExp)
+{
+ IMG_BYTE *pbL2Buffer;
+ IMG_UINT32 ui32L2BufFree;
+ IMG_UINT32 ui32BytesCopied = 0;
+ IMG_UINT32 ui32BytesExpMin = RGX_HWPERF_GET_SIZE(RGX_HWPERF_GET_PACKET(pbFwBuffer));
+ PVRSRV_ERROR eError;
+
+/* HWPERF_MISR_FUNC_DEBUG enables debug code for investigating HWPerf issues */
+#ifdef HWPERF_MISR_FUNC_DEBUG
+ static IMG_UINT32 gui32Ordinal = IMG_UINT32_MAX;
+#endif
+
+ PVR_DPF_ENTERED;
+
+#ifdef HWPERF_MISR_FUNC_DEBUG
+ PVR_DPF((PVR_DBG_VERBOSE, "EVENTS to copy from 0x%p length:%05d",
+ pbFwBuffer, ui32BytesExp));
+#endif
+
+#ifdef HWPERF_MISR_FUNC_DEBUG
+ {
+ /* Check the incoming buffer of data has not lost any packets */
+ IMG_BYTE *pbFwBufferIter = pbFwBuffer;
+ IMG_BYTE *pbFwBufferEnd = pbFwBuffer+ui32BytesExp;
+ do
+ {
+ RGX_HWPERF_V2_PACKET_HDR *asCurPos = RGX_HWPERF_GET_PACKET(pbFwBufferIter);
+ IMG_UINT32 ui32CurOrdinal = asCurPos->ui32Ordinal;
+ if (gui32Ordinal != IMG_UINT32_MAX)
+ {
+ if ((gui32Ordinal+1) != ui32CurOrdinal)
+ {
+ if (gui32Ordinal < ui32CurOrdinal)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "HWPerf [%p] packets lost (%u packets) between ordinal %u...%u",
+ pbFwBufferIter,
+ ui32CurOrdinal - gui32Ordinal - 1,
+ gui32Ordinal,
+ ui32CurOrdinal));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "HWPerf [%p] packet ordinal out of sequence last: %u, current: %u",
+ pbFwBufferIter,
+ gui32Ordinal,
+ ui32CurOrdinal));
+ }
+ }
+ }
+ gui32Ordinal = asCurPos->ui32Ordinal;
+ pbFwBufferIter += RGX_HWPERF_GET_SIZE(asCurPos);
+ } while( pbFwBufferIter < pbFwBufferEnd );
+ }
+#endif
+
+ /* Try submitting all data in one TL packet. */
+ eError = TLStreamReserve2( hHWPerfStream,
+ &pbL2Buffer,
+ (IMG_SIZE_T)ui32BytesExp, ui32BytesExpMin,
+ &ui32L2BufFree);
+ if ( eError == PVRSRV_OK )
+ {
+ OSMemCopy( pbL2Buffer, pbFwBuffer, (IMG_SIZE_T)ui32BytesExp );
+ eError = TLStreamCommit(hHWPerfStream, (IMG_SIZE_T)ui32BytesExp);
+ if ( eError != PVRSRV_OK )
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "TLStreamCommit() failed (%d) in %s(), unable to copy packet from L1 to L2 buffer",
+ eError, __func__));
+ goto e0;
+ }
+ /* Data were successfully written */
+ ui32BytesCopied = ui32BytesExp;
+ }
+ else if (eError == PVRSRV_ERROR_STREAM_FULL)
+ {
+ /* There was not enough space for all data, copy as much as possible */
+ IMG_UINT32 sizeSum = 0;
+ RGX_PHWPERF_V2_PACKET_HDR psCurPkt = RGX_HWPERF_GET_PACKET(pbFwBuffer);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Unable to reserve space (%d) in host buffer on first attempt, remaining free space: %d", ui32BytesExp, ui32L2BufFree));
+
+ /* Traverse the array to find how many packets will fit in the available space. */
+ while ( sizeSum < ui32BytesExp &&
+ sizeSum + RGX_HWPERF_GET_SIZE(psCurPkt) < ui32L2BufFree )
+ {
+ sizeSum += RGX_HWPERF_GET_SIZE(psCurPkt);
+ psCurPkt = RGX_HWPERF_GET_NEXT_PACKET(psCurPkt);
+ }
+
+ if ( 0 != sizeSum )
+ {
+ eError = TLStreamReserve( hHWPerfStream, &pbL2Buffer, (IMG_SIZE_T)sizeSum);
+
+ if ( eError == PVRSRV_OK )
+ {
+ OSMemCopy( pbL2Buffer, pbFwBuffer, (IMG_SIZE_T)sizeSum );
+ eError = TLStreamCommit(hHWPerfStream, (IMG_SIZE_T)sizeSum);
+ if ( eError != PVRSRV_OK )
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "TLStreamCommit() failed (%d) in %s(), unable to copy packet from L1 to L2 buffer",
+ eError, __func__));
+ goto e0;
+ }
+ /* sizeSum bytes of hwperf packets have been successfully written */
+ ui32BytesCopied = sizeSum;
+ }
+ else if ( PVRSRV_ERROR_STREAM_FULL == eError )
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Can not write HWPerf packet into host buffer, check data in case of packet loss, remaining free space: %d", ui32L2BufFree));
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "Can not find space in host buffer, check data in case of packet loss, remaining free space: %d", ui32L2BufFree));
+ }
+ }
+ if ( PVRSRV_OK != eError && /* Some other error occurred */
+ PVRSRV_ERROR_STREAM_FULL != eError ) /* Full error handled by caller, we returning the copied bytes count to caller*/
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "HWPerf enabled: Unexpected Error ( %d ) while copying FW buffer to TL buffer.",
+ eError));
+ }
+
+e0:
+ /* Return the remaining packets left to be transported. */
+ PVR_DPF_RETURN_VAL(ui32BytesCopied);
+}
+
+
+static INLINE IMG_UINT32 RGXHWPerfAdvanceRIdx(
+ const IMG_UINT32 ui32BufSize,
+ const IMG_UINT32 ui32Pos,
+ const IMG_UINT32 ui32Size)
+{
+ return ( ui32Pos + ui32Size < ui32BufSize ? ui32Pos + ui32Size : 0 );
+}
+
+
+/*
+ RGXHWPerfDataStore
+*/
+static IMG_UINT32 RGXHWPerfDataStore(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
+ IMG_BYTE* psHwPerfInfo = psDevInfo->psRGXFWIfHWPerfBuf;
+ IMG_UINT32 ui32SrcRIdx, ui32SrcWIdx, ui32SrcWrapCount;
+ IMG_UINT32 ui32BytesExp = 0, ui32BytesCopied = 0, ui32BytesCopiedSum = 0;
+#ifdef HWPERF_MISR_FUNC_DEBUG
+ IMG_UINT32 ui32BytesExpSum = 0;
+#endif
+
+ PVR_DPF_ENTERED;
+
+ /* Caller should check this member is valid before calling */
+ PVR_ASSERT(psDevInfo->hHWPerfStream);
+
+ /* Get a copy of the current
+ * read (first packet to read)
+ * write (empty location for the next write to be inserted)
+ * WrapCount (size in bytes of the buffer at or past end)
+ * indexes of the FW buffer */
+ ui32SrcRIdx = psRGXFWIfTraceBufCtl->ui32HWPerfRIdx;
+ ui32SrcWIdx = psRGXFWIfTraceBufCtl->ui32HWPerfWIdx;
+ OSMemoryBarrier();
+ ui32SrcWrapCount = psRGXFWIfTraceBufCtl->ui32HWPerfWrapCount;
+
+ /* Is there any data in the buffer not yet retrieved? */
+ if ( ui32SrcRIdx != ui32SrcWIdx )
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfDataStore EVENTS found srcRIdx:%d srcWIdx: %d ", ui32SrcRIdx, ui32SrcWIdx));
+
+ /* Is the write position higher than the read position? */
+ if ( ui32SrcWIdx > ui32SrcRIdx )
+ {
+ /* Yes, buffer has not wrapped */
+ ui32BytesExp = ui32SrcWIdx - ui32SrcRIdx;
+#ifdef HWPERF_MISR_FUNC_DEBUG
+ ui32BytesExpSum += ui32BytesExp;
+#endif
+ ui32BytesCopied = RGXHWPerfCopyDataL1toL2(psDevInfo->hHWPerfStream,
+ psHwPerfInfo + ui32SrcRIdx,
+ ui32BytesExp);
+ ui32BytesCopiedSum += ui32BytesCopied;
+
+ /* 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. */
+ psRGXFWIfTraceBufCtl->ui32HWPerfRIdx = RGXHWPerfAdvanceRIdx(
+ psDevInfo->ui32RGXFWIfHWPerfBufSize, ui32SrcRIdx,
+ ui32BytesCopied);
+ }
+ /* No, buffer has wrapped and write position is behind read position */
+ else
+ {
+ /* Byte count equal to
+ * number of bytes from read position to the end of the buffer,
+ * + data in the extra space in the end of the buffer. */
+ ui32BytesExp = ui32SrcWrapCount - ui32SrcRIdx;
+
+#ifdef HWPERF_MISR_FUNC_DEBUG
+ ui32BytesExpSum += ui32BytesExp;
+#endif
+ /* Attempt to transfer the packets to the TL stream buffer */
+ ui32BytesCopied = RGXHWPerfCopyDataL1toL2(psDevInfo->hHWPerfStream,
+ psHwPerfInfo + ui32SrcRIdx,
+ ui32BytesExp);
+ ui32BytesCopiedSum += ui32BytesCopied;
+
+ /* Advance read index as before and Update the local copy of the
+ * read index as it might be used in the last if branch*/
+ ui32SrcRIdx = RGXHWPerfAdvanceRIdx(
+ psDevInfo->ui32RGXFWIfHWPerfBufSize, ui32SrcRIdx,
+ ui32BytesCopied);
+
+ /* Update Wrap Count */
+ if ( ui32SrcRIdx == 0)
+ {
+ psRGXFWIfTraceBufCtl->ui32HWPerfWrapCount = psDevInfo->ui32RGXFWIfHWPerfBufSize;
+ }
+ psRGXFWIfTraceBufCtl->ui32HWPerfRIdx = ui32SrcRIdx;
+
+ /* If all the data in the end of the array was copied, try copying
+ * wrapped data in the beginning of the array, assuming there is
+ * any and the RIdx was wrapped. */
+ if ( (ui32BytesCopied == ui32BytesExp)
+ && (ui32SrcWIdx > 0)
+ && (ui32SrcRIdx == 0) )
+ {
+ ui32BytesExp = ui32SrcWIdx;
+#ifdef HWPERF_MISR_FUNC_DEBUG
+ ui32BytesExpSum += ui32BytesExp;
+#endif
+ ui32BytesCopied = RGXHWPerfCopyDataL1toL2(psDevInfo->hHWPerfStream,
+ psHwPerfInfo,
+ ui32BytesExp);
+ ui32BytesCopiedSum += ui32BytesCopied;
+ /* Advance the FW buffer read position. */
+ psRGXFWIfTraceBufCtl->ui32HWPerfRIdx = RGXHWPerfAdvanceRIdx(
+ psDevInfo->ui32RGXFWIfHWPerfBufSize, ui32SrcRIdx,
+ ui32BytesCopied);
+ }
+ }
+#ifdef HWPERF_MISR_FUNC_DEBUG
+ if (ui32BytesCopiedSum != ui32BytesExpSum)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXHWPerfDataStore: FW L1 RIdx:%u. Not all bytes copied to L2: %u bytes out of %u expected", psRGXFWIfTraceBufCtl->ui32HWPerfRIdx, ui32BytesCopiedSum, ui32BytesExpSum));
+ }
+#endif
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfDataStore NO EVENTS to transport"));
+ }
+
+ PVR_DPF_RETURN_VAL(ui32BytesCopiedSum);
+}
+
+
+PVRSRV_ERROR RGXHWPerfDataStoreCB(PVRSRV_DEVICE_NODE *psDevInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_RGXDEV_INFO* psRgxDevInfo;
+ IMG_UINT32 ui32BytesCopied;
+
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psDevInfo);
+ psRgxDevInfo = psDevInfo->pvDevice;
+
+ if (psRgxDevInfo->hHWPerfStream != 0)
+ {
+ OSLockAcquire(psRgxDevInfo->hLockHWPerfStream);
+ ui32BytesCopied = RGXHWPerfDataStore(psRgxDevInfo);
+ OSLockRelease(psRgxDevInfo->hLockHWPerfStream);
+
+ if ( ui32BytesCopied )
+ { /* Signal consumers that packets may be available to read when
+ * running from a HW kick, not when called by client APP thread
+ * via the transport layer CB as this can lead to stream
+ * corruption.*/
+ eError = TLStreamSync(psRgxDevInfo->hHWPerfStream);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfDataStoreCB: Zero bytes copied from FW L1 to L2."));
+ }
+ }
+
+ PVR_DPF_RETURN_OK;
+}
+
+
+/* Not currently supported by default */
+#if defined(SUPPORT_TL_PROODUCER_CALLBACK)
+static PVRSRV_ERROR RGXHWPerfTLCB(IMG_HANDLE hStream,
+ IMG_UINT32 ui32ReqOp, IMG_UINT32* ui32Resp, IMG_VOID* pvUser)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_RGXDEV_INFO* psRgxDevInfo = (PVRSRV_RGXDEV_INFO*)pvUser;
+
+ PVR_UNREFERENCED_PARAMETER(hStream);
+ PVR_UNREFERENCED_PARAMETER(ui32Resp);
+
+ PVR_ASSERT(psRgxDevInfo);
+
+ switch (ui32ReqOp)
+ {
+ case TL_SOURCECB_OP_CLIENT_EOS:
+ if (psRgxDevInfo->hHWPerfStream != 0)
+ {
+ OSLockAcquire(psRgxDevInfo->hLockHWPerfStream);
+ (void) RGXHWPerfDataStore(psRgxDevInfo);
+ OSLockRelease(psRgxDevInfo->hLockHWPerfStream);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return eError;
+}
+#endif
+
+
+/* References to key objects to allow kernel-side behaviour to function
+ * e.g. FTrace and KM interface to HWPerf.
+ */
+static PVRSRV_DEVICE_NODE* gpsRgxDevNode = IMG_NULL;
+static PVRSRV_RGXDEV_INFO* gpsRgxDevInfo = IMG_NULL;
+
+
+PVRSRV_ERROR RGXHWPerfInit(PVRSRV_DEVICE_NODE *psRgxDevNode, IMG_BOOL bEnable)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32L2BufferSize;
+
+ PVR_DPF_ENTERED;
+
+ /* On first call at driver initialisation we get the RGX device,
+ * in later on-demand calls this parameter is optional. */
+ if (psRgxDevNode)
+ {
+ gpsRgxDevNode = psRgxDevNode;
+ gpsRgxDevInfo = psRgxDevNode->pvDevice;
+ }
+
+ /* Before proper initialisation make sure we have a valid RGX device. */
+ if (!gpsRgxDevInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HWPerf module not initialised"));
+ PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_DEVICE);
+ }
+
+ /* Initialise first in case of an error condition or if it is not enabled
+ */
+ gpsRgxDevInfo->hLockHWPerfStream = IMG_NULL;
+ gpsRgxDevInfo->hHWPerfStream = IMG_NULL;
+
+ /* Does the caller want to enable data collection resources? */
+ if (!bEnable)
+ {
+ PVR_DPF_RETURN_OK;
+ }
+
+ /* Create the HWPerf stream lock used for multiple stream writers when
+ * configured e.g. TL producer callback
+ */
+ eError = OSLockCreate(&gpsRgxDevInfo->hLockHWPerfStream, LOCK_TYPE_PASSIVE);
+ PVR_LOGR_IF_ERROR(eError, "OSLockCreate");
+
+ /* Host L2 HWPERF buffer size in bytes must be bigger than the L1 buffer
+ * accessed by the FW. The MISR may try to write one packet the size of the L1
+ * buffer in some scenarios. When logging is enabled in the MISR, it can be seen
+ * if the L2 buffer hits a full condition. The closer in size the L2 and L1 buffers
+ * are the more chance of this happening.
+ * Size chosen to allow MISR to write an L1 sized packet and for the client
+ * application/daemon to drain a L1 sized packet e.g. ~ 2xL1+64 working space.
+ *
+ * However in the case of NO_HARDWARE the L2 buffer will not be used.
+ * By reducing the size of the L2 buffer we can support a larger L1 buffer size
+ * since on a 32-bit system, vmalloc memory is limited.
+ */
+#if defined(NO_HARDWARE)
+ ui32L2BufferSize = 0;
+#else
+ ui32L2BufferSize = gpsRgxDevInfo->ui32RGXFWIfHWPerfBufSize<<1;
+#endif
+ eError = TLStreamCreate(&gpsRgxDevInfo->hHWPerfStream, HWPERF_TL_STREAM_NAME,
+ ui32L2BufferSize+RGXFW_HWPERF_L1_PADDING_DEFAULT,
+ TL_FLAG_DROP_DATA | TL_FLAG_NO_SIGNAL_ON_COMMIT,
+#if !defined(SUPPORT_TL_PROODUCER_CALLBACK)
+ IMG_NULL, IMG_NULL
+#else
+ /* Not enabled by default */
+ RGXHWPerfTLCB, gpsRgxDevInfo
+#endif
+ );
+
+ PVR_LOGG_IF_ERROR(eError, "TLStreamCreate", e1);
+
+ PVR_DPF_RETURN_OK;
+
+e1:
+ OSLockDestroy(gpsRgxDevInfo->hLockHWPerfStream);
+ gpsRgxDevInfo->hLockHWPerfStream = IMG_NULL;
+ gpsRgxDevInfo->hHWPerfStream = IMG_NULL;
+/* e0: */
+ PVR_DPF_RETURN_RC(eError);
+}
+
+
+IMG_VOID RGXHWPerfDeinit(void)
+{
+ PVR_DPF_ENTERED;
+
+ /* Clean up the stream and lock objects if allocated
+ */
+ if (gpsRgxDevInfo && gpsRgxDevInfo->hHWPerfStream)
+ {
+ TLStreamClose(gpsRgxDevInfo->hHWPerfStream);
+ gpsRgxDevInfo->hHWPerfStream = IMG_NULL;
+ }
+ if (gpsRgxDevInfo && gpsRgxDevInfo->hLockHWPerfStream)
+ {
+ OSLockDestroy(gpsRgxDevInfo->hLockHWPerfStream);
+ gpsRgxDevInfo->hLockHWPerfStream = IMG_NULL;
+ }
+
+ /* Clear global RGX device reference
+ */
+ gpsRgxDevInfo = IMG_NULL;
+ gpsRgxDevNode = IMG_NULL;
+
+ PVR_DPF_RETURN;
+}
+
+
+/******************************************************************************
+ * RGX HW Performance Profiling Server API(s)
+ *****************************************************************************/
+/*
+ PVRSRVRGXCtrlHWPerfKM
+*/
+PVRSRV_ERROR PVRSRVRGXCtrlHWPerfKM(
+ PVRSRV_DEVICE_NODE* psDeviceNode,
+ IMG_BOOL bToggle,
+ IMG_UINT64 ui64Mask)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_RGXDEV_INFO* psDevice;
+ RGXFWIF_KCCB_CMD sKccbCmd;
+
+ PVR_DPF_ENTERED;
+ PVR_ASSERT(psDeviceNode);
+ psDevice = psDeviceNode->pvDevice;
+
+ /* If this method is being used whether to enable or disable
+ * then the hwperf stream is likely to be needed eventually so create it,
+ * also helps unit testing.
+ * Stream allocated on demand to reduce RAM foot print on systems not
+ * needing HWPerf resources.
+ */
+ if (psDevice->hHWPerfStream == IMG_NULL)
+ {
+ eError = RGXHWPerfInit(psDeviceNode, IMG_TRUE);
+ PVR_LOGR_IF_ERROR(eError, "RGXHWPerfInit");
+ }
+
+ /* Prepare command parameters ...
+ */
+ sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_CTRL_EVENTS;
+ sKccbCmd.uCmdData.sHWPerfCtrl.bToggle = bToggle;
+ sKccbCmd.uCmdData.sHWPerfCtrl.ui64Mask = ui64Mask;
+
+ /* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXCtrlHWPerfKM parameters set, calling FW")); */
+
+ /* Ask the FW to carry out the HWPerf configuration command
+ */
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice, RGXFWIF_DM_GP,
+ &sKccbCmd, sizeof(sKccbCmd), IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGR_IF_ERROR(eError, "RGXScheduleCommand");
+ }
+
+ /* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXCtrlHWPerfKM command scheduled for FW")); */
+
+ /* Wait for FW to complete
+ */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGR_IF_ERROR(eError, "RGXWaitForFWOp");
+ }
+
+ /* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXCtrlHWPerfKM firmware completed")); */
+
+ /* If it was being asked to disable then don't delete the stream as the FW
+ * will continue to generate events during the disabling phase. Clean up
+ * will be done when the driver is unloaded.
+ * The increase in extra memory used by the stream would only occur on a
+ * developer system and not a production device as a user would never
+ * enable HWPerf. If this is not the case then a deferred clean system will
+ * need to be implemented.
+ */
+ /*if ((!bEnable) && (psDevice->hHWPerfStream))
+ {
+ TLStreamDestroy(psDevice->hHWPerfStream);
+ psDevice->hHWPerfStream = 0;
+ }*/
+
+#if defined(DEBUG)
+ if (bToggle)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "HWPerf events (%llx) have been TOGGLED", ui64Mask));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "HWPerf mask has been SET to (%llx)", ui64Mask));
+ }
+#endif
+
+ PVR_DPF_RETURN_OK;
+}
+
+
+/*
+ PVRSRVRGXEnableHWPerfCountersKM
+*/
+PVRSRV_ERROR PVRSRVRGXConfigEnableHWPerfCountersKM(
+ PVRSRV_DEVICE_NODE* psDeviceNode,
+ 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;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psDeviceNode);
+ PVR_ASSERT(ui32ArrayLen>0);
+ PVR_ASSERT(psBlockConfigs);
+
+ /* Fill in the command structure with the parameters needed
+ */
+ sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_CONFIG_ENABLE_BLKS;
+ sKccbCmd.uCmdData.sHWPerfCfgEnableBlks.ui32NumBlocks = ui32ArrayLen;
+
+ eError = DevmemFwAllocate(psDeviceNode->pvDevice,
+ sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen,
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
+ "HWPerfCountersConfigBlock",
+ &psFwBlkConfigsMemDesc);
+ if (eError != PVRSRV_OK)
+ PVR_LOGR_IF_ERROR(eError, "DevmemFwAllocate");
+
+ RGXSetFirmwareAddress(&sKccbCmd.uCmdData.sHWPerfCfgEnableBlks.pasBlockConfigs,
+ psFwBlkConfigsMemDesc, 0, 0);
+
+ eError = DevmemAcquireCpuVirtAddr(psFwBlkConfigsMemDesc, (IMG_VOID **)&psFwArray);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", fail1);
+ }
+
+ OSMemCopy(psFwArray, psBlockConfigs, sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen);
+ DevmemPDumpLoadMem(psFwBlkConfigsMemDesc,
+ 0,
+ sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen,
+ 0);
+
+ /* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigEnableHWPerfCountersKM parameters set, calling FW")); */
+
+ /* Ask the FW to carry out the HWPerf configuration command
+ */
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP, &sKccbCmd, sizeof(sKccbCmd), IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGG_IF_ERROR(eError, "RGXScheduleCommand", fail2);
+ }
+
+ /* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigEnableHWPerfCountersKM command scheduled for FW")); */
+
+ /* Wait for FW to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGG_IF_ERROR(eError, "RGXWaitForFWOp", fail2);
+ }
+
+ /* Release temporary memory used for block configuration
+ */
+ RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
+ DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
+ DevmemFwFree(psFwBlkConfigsMemDesc);
+
+ /* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigEnableHWPerfCountersKM firmware completed")); */
+
+ PVR_DPF((PVR_DBG_WARNING, "HWPerf %d counter blocks configured and ENABLED", ui32ArrayLen));
+
+ PVR_DPF_RETURN_OK;
+
+fail2:
+ DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
+fail1:
+ RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
+ DevmemFwFree(psFwBlkConfigsMemDesc);
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+
+/*
+ PVRSRVRGXConfigCustomCountersReadingHWPerfKM
+ */
+PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
+ PVRSRV_DEVICE_NODE* psDeviceNode,
+ IMG_UINT16 ui16CustomBlockID,
+ IMG_UINT16 ui16NumCustomCounters,
+ IMG_UINT32* pui32CustomCounterIDs)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sKccbCmd;
+ DEVMEM_MEMDESC* psFwSelectCntrsMemDesc = IMG_NULL;
+ IMG_UINT32* psFwArray;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psDeviceNode);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVRGXSelectCustomCountersKM: configure block %u to read %u counters", ui16CustomBlockID, ui16NumCustomCounters));
+
+ /* Fill in the command structure with the parameters needed */
+ sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_SELECT_CUSTOM_CNTRS;
+ sKccbCmd.uCmdData.sHWPerfSelectCstmCntrs.ui16NumCounters = ui16NumCustomCounters;
+ sKccbCmd.uCmdData.sHWPerfSelectCstmCntrs.ui16CustomBlock = ui16CustomBlockID;
+
+ if (ui16NumCustomCounters > 0)
+ {
+ PVR_ASSERT(pui32CustomCounterIDs);
+
+ eError = DevmemFwAllocate(psDeviceNode->pvDevice,
+ sizeof(IMG_UINT32) * ui16NumCustomCounters,
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
+ "HWPerfConfigCustomCounters",
+ &psFwSelectCntrsMemDesc);
+ if (eError != PVRSRV_OK)
+ PVR_LOGR_IF_ERROR(eError, "DevmemFwAllocate");
+
+ RGXSetFirmwareAddress(&sKccbCmd.uCmdData.sHWPerfSelectCstmCntrs.pui32CustomCounterIDs,
+ psFwSelectCntrsMemDesc, 0, 0);
+
+ eError = DevmemAcquireCpuVirtAddr(psFwSelectCntrsMemDesc, (IMG_VOID **)&psFwArray);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", fail1);
+ }
+
+ OSMemCopy(psFwArray, pui32CustomCounterIDs, sizeof(IMG_UINT32) * ui16NumCustomCounters);
+ DevmemPDumpLoadMem(psFwSelectCntrsMemDesc,
+ 0,
+ sizeof(IMG_UINT32) * ui16NumCustomCounters,
+ 0);
+ }
+
+ /* Push in the KCCB the command to configure the custom counters block */
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP, &sKccbCmd, sizeof(sKccbCmd), IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGG_IF_ERROR(eError, "RGXScheduleCommand", fail2);
+ }
+ PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXSelectCustomCountersKM: Command scheduled"));
+
+ /* Wait for FW to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGG_IF_ERROR(eError, "RGXWaitForFWOp", fail2);
+ }
+ PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXSelectCustomCountersKM: FW operation completed"));
+
+ if (ui16NumCustomCounters > 0)
+ {
+ /* Release temporary memory used for block configuration */
+ RGXUnsetFirmwareAddress(psFwSelectCntrsMemDesc);
+ DevmemReleaseCpuVirtAddr(psFwSelectCntrsMemDesc);
+ DevmemFwFree(psFwSelectCntrsMemDesc);
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "HWPerf custom counters %u reading will be sent with the next HW events", ui16NumCustomCounters));
+
+ PVR_DPF_RETURN_OK;
+
+ fail2:
+ if (psFwSelectCntrsMemDesc) DevmemReleaseCpuVirtAddr(psFwSelectCntrsMemDesc);
+
+ fail1:
+ if (psFwSelectCntrsMemDesc)
+ {
+ RGXUnsetFirmwareAddress(psFwSelectCntrsMemDesc);
+ DevmemFwFree(psFwSelectCntrsMemDesc);
+ }
+
+ PVR_DPF_RETURN_RC(eError);
+}
+/*
+ PVRSRVRGXDisableHWPerfcountersKM
+*/
+PVRSRV_ERROR PVRSRVRGXCtrlHWPerfCountersKM(
+ PVRSRV_DEVICE_NODE* psDeviceNode,
+ IMG_BOOL bEnable,
+ IMG_UINT32 ui32ArrayLen,
+ IMG_UINT8* psBlockIDs)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sKccbCmd;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psDeviceNode);
+ PVR_ASSERT(ui32ArrayLen>0);
+ PVR_ASSERT(ui32ArrayLen<32);
+ PVR_ASSERT(psBlockIDs);
+
+ /* Fill in the command structure with the parameters needed
+ */
+ sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_CTRL_BLKS;
+ sKccbCmd.uCmdData.sHWPerfCtrlBlks.bEnable = bEnable;
+ sKccbCmd.uCmdData.sHWPerfCtrlBlks.ui32NumBlocks = ui32ArrayLen;
+ OSMemCopy(sKccbCmd.uCmdData.sHWPerfCtrlBlks.aeBlockIDs, psBlockIDs, sizeof(IMG_UINT8)*ui32ArrayLen);
+
+ /* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXCtrlHWPerfCountersKM parameters set, calling FW")); */
+
+ /* Ask the FW to carry out the HWPerf configuration command
+ */
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP, &sKccbCmd, sizeof(sKccbCmd), IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ PVR_LOGR_IF_ERROR(eError, "RGXScheduleCommand");
+
+ /* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXCtrlHWPerfCountersKM command scheduled for FW")); */
+
+ /* Wait for FW to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ PVR_LOGR_IF_ERROR(eError, "RGXWaitForFWOp");
+
+ /* PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXCtrlHWPerfCountersKM firmware completed")); */
+
+#if defined(DEBUG)
+ if (bEnable)
+ PVR_DPF((PVR_DBG_WARNING, "HWPerf %d counter blocks have been ENABLED", ui32ArrayLen));
+ else
+ PVR_DPF((PVR_DBG_WARNING, "HWPerf %d counter blocks have been DISABLED", ui32ArrayLen));
+#endif
+
+ PVR_DPF_RETURN_OK;
+}
+
+
+/******************************************************************************
+ * SUPPORT_GPUTRACE_EVENTS
+ *
+ * Currently only implemented on Linux and Android. Feature can be enabled on
+ * Android builds but can also be enabled on Linux builds for testing
+ * but requires the gpu.h FTrace event header file to be present.
+ *****************************************************************************/
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+
+
+static POS_LOCK hFTraceLock;
+static IMG_VOID RGXHWPerfFTraceCmdCompleteNotify(PVRSRV_CMDCOMP_HANDLE);
+
+static IMG_VOID RGXHWPerfFTraceGPUEnable(void)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(gpsRgxDevNode && gpsRgxDevInfo);
+
+ /* In the case where the AppHint has not been set we need to
+ * initialise the host driver HWPerf resources here. Allocated on
+ * demand to reduce RAM foot print on systems not needing HWPerf.
+ * Signal FW to enable event generation.
+ */
+ if (gpsRgxDevNode->psSyncPrim)
+ {
+ eError = PVRSRVRGXCtrlHWPerfKM(gpsRgxDevNode, IMG_FALSE, RGX_HWPERF_EVENT_MASK_HW_KICKFINISH);
+ PVR_LOGG_IF_ERROR(eError, "PVRSRVRGXCtrlHWPerfKM", err_out);
+ }
+
+ /* Connect to the TL Stream for HWPerf data consumption */
+ eError = TLClientConnect(&gpsRgxDevInfo->hGPUTraceTLConnection);
+ PVR_LOGG_IF_ERROR(eError, "TLClientConnect", err_out);
+
+ eError = TLClientOpenStream(gpsRgxDevInfo->hGPUTraceTLConnection,
+ HWPERF_TL_STREAM_NAME,
+ PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING,
+ &gpsRgxDevInfo->hGPUTraceTLStream);
+ PVR_LOGG_IF_ERROR(eError, "TLClientOpenStream", err_disconnect);
+
+ /* Register a notifier to collect HWPerf data whenever the HW completes
+ * an operation.
+ */
+ eError = PVRSRVRegisterCmdCompleteNotify(
+ &gpsRgxDevInfo->hGPUTraceCmdCompleteHandle,
+ &RGXHWPerfFTraceCmdCompleteNotify,
+ gpsRgxDevInfo);
+ PVR_LOGG_IF_ERROR(eError, "PVRSRVRegisterCmdCompleteNotify", err_close_stream);
+
+ /* Reset the OS timestamp coming from the timer correlation data
+ * associated with the latest HWPerf event we processed.
+ */
+ gpsRgxDevInfo->ui64LastSampledTimeCorrOSTimeStamp = 0;
+
+ gpsRgxDevInfo->bFTraceGPUEventsEnabled = IMG_TRUE;
+
+err_out:
+ PVR_DPF_RETURN;
+
+err_close_stream:
+ TLClientCloseStream(gpsRgxDevInfo->hGPUTraceTLConnection,
+ gpsRgxDevInfo->hGPUTraceTLStream);
+err_disconnect:
+ TLClientDisconnect(gpsRgxDevInfo->hGPUTraceTLConnection);
+ goto err_out;
+}
+
+static IMG_VOID RGXHWPerfFTraceGPUDisable(IMG_BOOL bDeInit)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(gpsRgxDevNode && gpsRgxDevInfo);
+
+ OSLockAcquire(hFTraceLock);
+
+ if (!bDeInit)
+ {
+ eError = PVRSRVRGXCtrlHWPerfKM(gpsRgxDevNode, IMG_FALSE, (RGX_HWPERF_EVENT_MASK_NONE));
+ PVR_LOG_IF_ERROR(eError, "PVRSRVRGXCtrlHWPerfKM");
+ }
+
+
+ if (gpsRgxDevInfo->hGPUTraceCmdCompleteHandle)
+ {
+ /* Tracing is being turned off. Unregister the notifier. */
+ eError = PVRSRVUnregisterCmdCompleteNotify(
+ gpsRgxDevInfo->hGPUTraceCmdCompleteHandle);
+ PVR_LOG_IF_ERROR(eError, "PVRSRVUnregisterCmdCompleteNotify");
+ gpsRgxDevInfo->hGPUTraceCmdCompleteHandle = IMG_NULL;
+ }
+
+ if (gpsRgxDevInfo->hGPUTraceTLStream)
+ {
+ eError = TLClientCloseStream(gpsRgxDevInfo->hGPUTraceTLConnection,
+ gpsRgxDevInfo->hGPUTraceTLStream);
+ PVR_LOG_IF_ERROR(eError, "TLClientCloseStream");
+ gpsRgxDevInfo->hGPUTraceTLStream = IMG_NULL;
+ }
+
+ if (gpsRgxDevInfo->hGPUTraceTLConnection)
+ {
+ eError = TLClientDisconnect(gpsRgxDevInfo->hGPUTraceTLConnection);
+ PVR_LOG_IF_ERROR(eError, "TLClientDisconnect");
+ gpsRgxDevInfo->hGPUTraceTLConnection = IMG_NULL;
+ }
+
+ gpsRgxDevInfo->bFTraceGPUEventsEnabled = IMG_FALSE;
+
+ OSLockRelease(hFTraceLock);
+
+ PVR_DPF_RETURN;
+}
+
+IMG_VOID RGXHWPerfFTraceGPUEventsEnabledSet(IMG_BOOL bNewValue)
+{
+ IMG_BOOL bOldValue;
+
+ PVR_DPF_ENTERED;
+
+ if (!gpsRgxDevInfo)
+ {
+ /* RGXHWPerfFTraceGPUInit hasn't been called yet -- it's too early
+ * to enable tracing.
+ */
+ PVR_DPF_RETURN;
+ }
+
+ bOldValue = gpsRgxDevInfo->bFTraceGPUEventsEnabled;
+
+ if (bOldValue != bNewValue)
+ {
+ if (bNewValue)
+ {
+ RGXHWPerfFTraceGPUEnable();
+ }
+ else
+ {
+ RGXHWPerfFTraceGPUDisable(IMG_FALSE);
+ }
+ }
+
+ PVR_DPF_RETURN;
+}
+
+IMG_VOID PVRGpuTraceEnabledSet(IMG_BOOL bNewValue)
+{
+ /* Lock down because we need to protect
+ * RGXHWPerfFTraceGPUDisable()/RGXHWPerfFTraceGPUEnable()
+ */
+ OSAcquireBridgeLock();
+ RGXHWPerfFTraceGPUEventsEnabledSet(bNewValue);
+ OSReleaseBridgeLock();
+}
+
+IMG_BOOL RGXHWPerfFTraceGPUEventsEnabled(IMG_VOID)
+{
+ return(gpsRgxDevInfo->bFTraceGPUEventsEnabled);
+}
+
+IMG_BOOL PVRGpuTraceEnabled(IMG_VOID)
+{
+ return (RGXHWPerfFTraceGPUEventsEnabled());
+}
+
+IMG_VOID RGXHWPerfFTraceGPUEnqueueEvent(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32ExternalJobRef, IMG_UINT32 ui32InternalJobRef,
+ const IMG_CHAR* pszJobType)
+{
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(pszJobType);
+
+ PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUEnqueueEvent: PID %u, external jobRef %u, internal jobRef %u", ui32PID, ui32ExternalJobRef, ui32InternalJobRef));
+
+ PVRGpuTraceClientWork(ui32PID, ui32ExternalJobRef, ui32InternalJobRef, pszJobType);
+
+ PVR_DPF_RETURN;
+}
+
+
+static IMG_VOID RGXHWPerfFTraceGPUSwitchEvent(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGX_HWPERF_V2_PACKET_HDR* psHWPerfPkt, const IMG_CHAR* pszWorkName,
+ PVR_GPUTRACE_SWITCH_TYPE eSwType)
+{
+ IMG_UINT64 ui64Timestamp;
+ RGX_HWPERF_HW_DATA_FIELDS* psHWPerfPktData;
+ RGXFWIF_GPU_UTIL_FWCB *psGpuUtilFWCB = psDevInfo->psRGXFWIfGpuUtilFWCb;
+ RGXFWIF_TIME_CORR *psTimeCorr;
+ IMG_UINT32 ui32DVFSClock;
+ IMG_UINT64 ui64CRTimeStamp;
+ IMG_UINT64 ui64OSTimeStamp;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psHWPerfPkt);
+ PVR_ASSERT(pszWorkName);
+
+ psHWPerfPktData = (RGX_HWPERF_HW_DATA_FIELDS*) RGX_HWPERF_GET_PACKET_DATA_BYTES(psHWPerfPkt);
+
+ /* Filter out 3DFINISH events for 3DTQKICKs which have already been
+ * filtered by ValidFTraceEvent() */
+
+ /* Calculate the OS timestamp given an RGX timestamp in the HWPerf event */
+ psTimeCorr = &psGpuUtilFWCB->sTimeCorr[psHWPerfPktData->ui32TimeCorrIndex];
+ ui64CRTimeStamp = psTimeCorr->ui64CRTimeStamp;
+ ui64OSTimeStamp = psTimeCorr->ui64OSTimeStamp;
+ ui32DVFSClock = psTimeCorr->ui32DVFSClock;
+ PVR_ASSERT(ui32DVFSClock>=1000000);
+
+ if(psDevInfo->ui64LastSampledTimeCorrOSTimeStamp > ui64OSTimeStamp)
+ {
+ /* The previous packet had a time reference (time correlation data) more recent
+ * than the one in the current packet, it means the timer correlation array wrapped
+ * too quickly (buffer too small) and in the previous call to RGXHWPerfFTraceGPUSwitchEvent
+ * we read one of the newest timer correlations rather than one of the oldest ones.
+ */
+ PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfFTraceGPUSwitchEvent: The timestamps computed so far could be wrong! The time correlation array size should be increased to avoid this."));
+ }
+ psDevInfo->ui64LastSampledTimeCorrOSTimeStamp = ui64OSTimeStamp;
+
+ {
+ IMG_UINT32 rgxCyclesPer_uS = ui32DVFSClock/1000000; /* RGX Speed Hz->uHz */
+
+ IMG_UINT64 deltaRgxCycles = (psHWPerfPkt->ui64RGXTimer - ui64CRTimeStamp) /* RGX CR timer ticks delta */
+ << 8ULL ; /* x256 to convert to cycles delta */
+ IMG_UINT32 deltaRgxCycles_remainder; /* Unable to use as not in a time unit */
+ IMG_UINT64 delta_uS = OSDivide64r64(deltaRgxCycles, rgxCyclesPer_uS, &deltaRgxCycles_remainder);/* RGX time delta in uS */
+ ui64Timestamp = ui64OSTimeStamp + (delta_uS * 1000ULL); /* Calculate OS time of HWPerf event */
+
+ PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUSwitchEvent: psCurrentDvfs RGX %llu, OS %llu, DVFSCLK %u",
+ ui64CRTimeStamp, ui64OSTimeStamp, ui32DVFSClock ));
+
+ PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUSwitchEvent: event RGX %llu, rgxCyclesPer_uS %u, deltaRgxCycles %llu, deltaRgxCycles_remainder %u, delta_uS %llu, TS %llu, ",
+ psHWPerfPkt->ui64RGXTimer, rgxCyclesPer_uS, deltaRgxCycles, deltaRgxCycles_remainder, delta_uS, ui64Timestamp ));
+ }
+
+ PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUSwitchEvent: %s ui32ExtJobRef=%d, ui32IntJobRef=%d, eSwType=%d",
+ pszWorkName, psHWPerfPktData->ui32ExtJobRef, psHWPerfPktData->ui32IntJobRef, eSwType));
+
+ PVRGpuTraceWorkSwitch(ui64Timestamp, psHWPerfPktData->ui32PID,
+ psHWPerfPktData->ui32ExtJobRef, psHWPerfPktData->ui32IntJobRef,
+ pszWorkName, eSwType);
+
+ PVR_DPF_RETURN;
+}
+
+
+static IMG_BOOL ValidFTraceEvent(RGX_HWPERF_V2_PACKET_HDR* psHWPerfPkt,
+ IMG_PCHAR* ppszWorkName, PVR_GPUTRACE_SWITCH_TYPE* peSwType)
+{
+ RGX_HWPERF_EVENT_TYPE eType;
+ static const struct {
+ IMG_CHAR* pszName;
+ PVR_GPUTRACE_SWITCH_TYPE eSwType;
+ } aszEventTypeMap[] = {
+ { /* RGX_HWPERF_HW_TAKICK */ "TA", PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+ { /* RGX_HWPERF_HW_TAFINISHED */ "TA", PVR_GPUTRACE_SWITCH_TYPE_END },
+ { /* RGX_HWPERF_HW_3DTQKICK */ "TQ3D", PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+ { /* RGX_HWPERF_HW_3DKICK */ "3D", PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+ { /* RGX_HWPERF_HW_3DFINISHED */ "3D", PVR_GPUTRACE_SWITCH_TYPE_END },
+ { /* RGX_HWPERF_HW_CDMKICK */ "CDM", PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+ { /* RGX_HWPERF_HW_CDMFINISHED */ "CDM", PVR_GPUTRACE_SWITCH_TYPE_END },
+ { /* RGX_HWPERF_HW_TLAKICK */ "TQ2D", PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+ { /* RGX_HWPERF_HW_TLAFINISHED */ "TQ2D", PVR_GPUTRACE_SWITCH_TYPE_END },
+ { /* RGX_HWPERF_HW_3DSPMKICK */ "3DSPM", PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+ { /* RGX_HWPERF_HW_PERIODIC */ IMG_NULL, 0 }, /* PERIODIC not supported */
+ { /* RGX_HWPERF_HW_RTUKICK */ "RTU", PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+ { /* RGX_HWPERF_HW_RTUFINISHED */ "RTU", PVR_GPUTRACE_SWITCH_TYPE_END },
+ { /* RGX_HWPERF_HW_SHGKICK */ "SHG", PVR_GPUTRACE_SWITCH_TYPE_BEGIN },
+ { /* RGX_HWPERF_HW_SHGFINISHED */ "SHG", PVR_GPUTRACE_SWITCH_TYPE_END },
+ { /* RGX_HWPERF_HW_3DTQFINISHED */ "TQ3D", PVR_GPUTRACE_SWITCH_TYPE_END },
+ { /* RGX_HWPERF_HW_3DSPMFINISHED */ "3DSPM", PVR_GPUTRACE_SWITCH_TYPE_END },
+ };
+
+ PVR_ASSERT(psHWPerfPkt);
+
+ eType = RGX_HWPERF_GET_TYPE(psHWPerfPkt);
+ if ((eType < RGX_HWPERF_HW_TAKICK) || (eType > RGX_HWPERF_HW_3DSPMFINISHED))
+ {
+ /* No map entry, ignore event */
+ PVR_DPF((PVR_DBG_VERBOSE, "ValidFTraceEvent: Unsupported event type %d %02d",
+ eType, eType+RGX_HWPERF_HW_TAKICK));
+ return IMG_FALSE;
+ }
+ eType-=RGX_HWPERF_HW_TAKICK;
+
+ if (aszEventTypeMap[eType].pszName == IMG_NULL)
+ {
+ /* Not supported map entry, ignore event */
+ PVR_DPF((PVR_DBG_VERBOSE, "ValidFTraceEventl: Unsupported event type %d %02d",
+ eType, eType+RGX_HWPERF_HW_TAKICK));
+ return IMG_FALSE;
+ }
+
+ *ppszWorkName = aszEventTypeMap[eType].pszName;
+ *peSwType = aszEventTypeMap[eType].eSwType;
+
+ return IMG_TRUE;
+}
+
+
+static IMG_VOID RGXHWPerfFTraceGPUThreadProcessPackets(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_PBYTE pBuffer, IMG_UINT32 ui32ReadLen)
+{
+ IMG_UINT32 ui32TlPackets = 0;
+ IMG_UINT32 ui32HWPerfPackets = 0;
+ IMG_UINT32 ui32HWPerfPacketsSent = 0;
+ IMG_PBYTE pBufferEnd;
+ PVRSRVTL_PPACKETHDR psHDRptr;
+ PVRSRVTL_PACKETTYPE ui16TlType;
+
+ PVR_DPF_ENTERED;
+
+ PVR_ASSERT(psDevInfo);
+ PVR_ASSERT(pBuffer);
+ PVR_ASSERT(ui32ReadLen);
+
+ /* Process the TL Packets
+ */
+ pBufferEnd = pBuffer+ui32ReadLen;
+ psHDRptr = GET_PACKET_HDR(pBuffer);
+ while ( psHDRptr < (PVRSRVTL_PPACKETHDR)pBufferEnd )
+ {
+ ui16TlType = GET_PACKET_TYPE(psHDRptr);
+ if (ui16TlType == PVRSRVTL_PACKETTYPE_DATA)
+ {
+ IMG_UINT16 ui16DataLen = GET_PACKET_DATA_LEN(psHDRptr);
+ if (0 == ui16DataLen)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfFTraceGPUThreadProcessPackets: ZERO Data in TL data packet: %p", psHDRptr));
+ }
+ else
+ {
+ RGX_HWPERF_V2_PACKET_HDR* psHWPerfPkt;
+ RGX_HWPERF_V2_PACKET_HDR* psHWPerfEnd;
+ IMG_CHAR* pszWorkName;
+ PVR_GPUTRACE_SWITCH_TYPE eSwType;
+
+ /* Check for lost hwperf data packets */
+ psHWPerfEnd = RGX_HWPERF_GET_PACKET(GET_PACKET_DATA_PTR(psHDRptr)+ui16DataLen);
+ psHWPerfPkt = RGX_HWPERF_GET_PACKET(GET_PACKET_DATA_PTR(psHDRptr));
+ do
+ {
+ if (ValidFTraceEvent(psHWPerfPkt, &pszWorkName, &eSwType))
+ {
+ RGXHWPerfFTraceGPUSwitchEvent(psDevInfo, psHWPerfPkt, pszWorkName, eSwType);
+ ui32HWPerfPacketsSent++;
+ }
+ ui32HWPerfPackets++;
+ psHWPerfPkt = RGX_HWPERF_GET_NEXT_PACKET(psHWPerfPkt);
+ }
+ while (psHWPerfPkt < psHWPerfEnd);
+ }
+ }
+ else if (ui16TlType == PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfFTraceGPUThreadProcessPackets: Indication that the transport buffer was full"));
+ }
+ else
+ {
+ /* else Ignore padding packet type and others */
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfFTraceGPUThreadProcessPackets: Ignoring TL packet, type %d", ui16TlType ));
+ }
+
+ psHDRptr = GET_NEXT_PACKET_ADDR(psHDRptr);
+ ui32TlPackets++;
+ }
+
+ PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUThreadProcessPackets: TL "
+ "Packets processed %03d, HWPerf packets %03d, sent %03d",
+ ui32TlPackets, ui32HWPerfPackets, ui32HWPerfPacketsSent));
+
+ PVR_DPF_RETURN;
+}
+
+
+static
+IMG_VOID RGXHWPerfFTraceCmdCompleteNotify(PVRSRV_CMDCOMP_HANDLE hCmdCompHandle)
+{
+ PVRSRV_DATA* psPVRSRVData = PVRSRVGetPVRSRVData();
+ PVRSRV_RGXDEV_INFO* psDeviceInfo = hCmdCompHandle;
+ IMG_HANDLE hUnusedByTL;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hStream;
+ IMG_PBYTE pBuffer;
+ IMG_UINT32 ui32ReadLen;
+
+ PVR_DPF_ENTERED;
+
+ /* Command-complete notifiers can run concurrently. If this is
+ * happening, just bail out and let the previous call finish.
+ * This is ok because we can process the queued packets on the next call.
+ */
+ if (!(OSTryLockAcquire(hFTraceLock)))
+ {
+ PVR_DPF_RETURN;
+ }
+
+ /* Exit if no HWPerf enabled device exits */
+ PVR_ASSERT(psDeviceInfo != IMG_NULL &&
+ psPVRSRVData != IMG_NULL &&
+ gpsRgxDevInfo != NULL);
+
+
+ hUnusedByTL = psDeviceInfo->hGPUTraceTLConnection;
+ hStream = psDeviceInfo->hGPUTraceTLStream;
+
+ if (hStream)
+ {
+ /* If we have a valid stream attempt to acquire some data */
+ eError = TLClientAcquireData(hUnusedByTL, hStream, &pBuffer, &ui32ReadLen);
+ if (eError == PVRSRV_OK)
+ {
+ /* Process the HWPerf packets and release the data */
+ if (ui32ReadLen > 0)
+ {
+ PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfFTraceGPUThread: DATA AVAILABLE offset=%p, length=%d", pBuffer, ui32ReadLen));
+
+ /* Process the transport layer data for HWPerf packets... */
+ RGXHWPerfFTraceGPUThreadProcessPackets (psDeviceInfo, pBuffer, ui32ReadLen);
+
+ eError = TLClientReleaseData(hUnusedByTL, hStream);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOG_ERROR(eError, "TLClientReleaseData");
+
+ /* Serious error, disable FTrace GPU events */
+
+ /* Release TraceLock so we always have the locking
+ * order BridgeLock->TraceLock to prevent AB-BA deadlocks*/
+ OSLockRelease(hFTraceLock);
+ OSAcquireBridgeLock();
+ RGXHWPerfFTraceGPUDisable(IMG_FALSE);
+ OSReleaseBridgeLock();
+ goto out;
+
+ }
+ } /* else no data, ignore */
+ }
+ else if (eError != PVRSRV_ERROR_TIMEOUT)
+ {
+ PVR_LOG_ERROR(eError, "TLClientAcquireData");
+ }
+ }
+
+ OSLockRelease(hFTraceLock);
+out:
+ PVR_DPF_RETURN;
+}
+
+
+PVRSRV_ERROR RGXHWPerfFTraceGPUInit(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_DPF_ENTERED;
+
+ /* Must be setup already by the general HWPerf module initialisation.
+ * DevInfo object needed by FTrace event generation code */
+ PVR_ASSERT(gpsRgxDevInfo);
+ gpsRgxDevInfo->bFTraceGPUEventsEnabled = IMG_FALSE;
+
+ eError = OSLockCreate(&hFTraceLock, LOCK_TYPE_DISPATCH);
+
+ PVR_DPF_RETURN_RC(eError);
+}
+
+
+IMG_VOID RGXHWPerfFTraceGPUDeInit(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVR_DPF_ENTERED;
+
+ RGXHWPerfFTraceGPUDisable(IMG_TRUE);
+
+ OSLockDestroy(hFTraceLock);
+
+ PVR_DPF_RETURN;
+}
+
+
+#endif /* SUPPORT_GPUTRACE_EVENTS */
+
+
+/******************************************************************************
+ * SUPPORT_KERNEL_HWPERF
+ *
+ * Currently only implemented on Linux. Feature can be enabled on Linux builds
+ * 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.
+ *****************************************************************************/
+#if defined(SUPPORT_KERNEL_HWPERF)
+
+/* Internal HWPerf kernel connection/device data object to track the state
+ * of a client session.
+ */
+typedef struct
+{
+ PVRSRV_DEVICE_NODE* psRgxDevNode;
+
+ /* TL Connect/disconnect state */
+ IMG_HANDLE hTLConnection;
+
+ /* TL Open/close state */
+ IMG_HANDLE hSD;
+
+ /* TL Acquire/release state */
+ IMG_PBYTE pHwpBuf;
+ IMG_UINT32 ui32HwpBufLen;
+
+} RGX_KM_HWPERF_DEVDATA;
+
+
+PVRSRV_ERROR RGXHWPerfConnect(
+ IMG_HANDLE* phDevData)
+{
+ PVRSRV_ERROR eError;
+ RGX_KM_HWPERF_DEVDATA* psDevData;
+
+ /* Valid input argument values supplied by the caller */
+ if (!phDevData)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Clear the handle to aid error checking by caller */
+ *phDevData = IMG_NULL;
+
+ /* Check the HWPerf module is initialised before we allow a connection */
+ if (!gpsRgxDevNode || !gpsRgxDevInfo)
+ {
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ /* In the case where the AppHint has not been set we need to
+ * initialise the host driver HWPerf resources here. Allocated on
+ * demand to reduce RAM foot print on systems not needing HWPerf.
+ */
+ if (gpsRgxDevInfo->hHWPerfStream == IMG_NULL)
+ {
+ eError = RGXHWPerfInit(IMG_NULL, IMG_TRUE);
+ PVR_LOGR_IF_ERROR(eError, "RGXHWPerfInit");
+ }
+
+ /* Allocation the session object for this connection */
+ psDevData = OSAllocZMem(sizeof(*psDevData));
+ if (psDevData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ psDevData->psRgxDevNode = gpsRgxDevNode;
+
+
+ /* Open a TL connection and store it in the session object */
+ eError = TLClientConnect(&psDevData->hTLConnection);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ /* Open the 'hwperf' TL stream for reading in this session */
+ eError = TLClientOpenStream(psDevData->hTLConnection,
+ HWPERF_TL_STREAM_NAME,
+ PVRSRV_STREAM_FLAG_ACQUIRE_NONBLOCKING,
+ &psDevData->hSD);
+ if (eError != PVRSRV_OK)
+ {
+ goto e2;
+ }
+
+ *phDevData = psDevData;
+ return PVRSRV_OK;
+
+ /* Error path... */
+e2:
+ TLClientDisconnect(psDevData->hTLConnection);
+e1:
+ OSFREEMEM(psDevData);
+// e0:
+ return eError;
+}
+
+
+
+PVRSRV_ERROR RGXHWPerfControl(
+ IMG_HANDLE hDevData,
+ IMG_BOOL bToggle,
+ IMG_UINT64 ui64Mask)
+{
+ PVRSRV_ERROR eError;
+ RGX_KM_HWPERF_DEVDATA* psDevData = (RGX_KM_HWPERF_DEVDATA*)hDevData;
+
+ /* Valid input argument values supplied by the caller */
+ if (!psDevData)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Ensure we are initialised and have a valid device node */
+ if (!psDevData->psRgxDevNode)
+ {
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ /* Call the internal server API */
+ eError = PVRSRVRGXCtrlHWPerfKM(psDevData->psRgxDevNode, bToggle, ui64Mask);
+ return eError;
+}
+
+
+PVRSRV_ERROR RGXHWPerfConfigureAndEnableCounters(
+ IMG_HANDLE hDevData,
+ IMG_UINT32 ui32NumBlocks,
+ RGX_HWPERF_CONFIG_CNTBLK* asBlockConfigs)
+{
+ PVRSRV_ERROR eError;
+ RGX_KM_HWPERF_DEVDATA* psDevData = (RGX_KM_HWPERF_DEVDATA*)hDevData;
+
+ /* Valid input argument values supplied by the caller */
+ if (!psDevData || ui32NumBlocks==0 || !asBlockConfigs)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Ensure we are initialised and have a valid device node */
+ if (!psDevData->psRgxDevNode)
+ {
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ /* Call the internal server API */
+ eError = PVRSRVRGXConfigEnableHWPerfCountersKM(
+ psDevData->psRgxDevNode, ui32NumBlocks, asBlockConfigs);
+ return eError;
+}
+
+
+PVRSRV_ERROR RGXHWPerfDisableCounters(
+ IMG_HANDLE hDevData,
+ IMG_UINT32 ui32NumBlocks,
+ IMG_UINT8* aeBlockIDs)
+{
+ PVRSRV_ERROR eError;
+ RGX_KM_HWPERF_DEVDATA* psDevData = (RGX_KM_HWPERF_DEVDATA*)hDevData;
+
+ /* Valid input argument values supplied by the caller */
+ if (!psDevData || ui32NumBlocks==0 || !aeBlockIDs)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Ensure we are initialised and have a valid device node */
+ if (!psDevData->psRgxDevNode)
+ {
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ /* Call the internal server API */
+ eError = PVRSRVRGXCtrlHWPerfCountersKM(
+ psDevData->psRgxDevNode, IMG_FALSE, ui32NumBlocks, aeBlockIDs);
+ return eError;
+}
+
+
+PVRSRV_ERROR RGXHWPerfAcquireData(
+ IMG_HANDLE hDevData,
+ IMG_PBYTE* ppBuf,
+ IMG_UINT32* pui32BufLen)
+{
+ PVRSRV_ERROR eError;
+ RGX_KM_HWPERF_DEVDATA* psDevData = (RGX_KM_HWPERF_DEVDATA*)hDevData;
+ IMG_PBYTE pTlBuf = IMG_NULL;
+ IMG_UINT32 ui32TlBufLen = 0;
+ IMG_PBYTE pDataDest;
+ IMG_UINT32 ui32TlPackets = 0;
+ IMG_PBYTE pBufferEnd;
+ PVRSRVTL_PPACKETHDR psHDRptr;
+ PVRSRVTL_PACKETTYPE ui16TlType;
+
+ /* Reset the output arguments in case we discover an error */
+ *ppBuf = IMG_NULL;
+ *pui32BufLen = 0;
+
+ /* Valid input argument values supplied by the caller */
+ if (!psDevData)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Acquire some data to read from the HWPerf TL stream */
+ eError = TLClientAcquireData(psDevData->hTLConnection,
+ psDevData->hSD,
+ &pTlBuf,
+ &ui32TlBufLen);
+ PVR_LOGR_IF_ERROR(eError, "TLClientAcquireData");
+
+ /* TL indicates no data exists so return OK and zero. */
+ if ((pTlBuf == IMG_NULL) || (ui32TlBufLen == 0))
+ {
+ return PVRSRV_OK;
+ }
+
+ /* Is the client buffer allocated and too small? */
+ if (psDevData->pHwpBuf && (psDevData->ui32HwpBufLen < ui32TlBufLen))
+ {
+ OSFREEMEM(psDevData->pHwpBuf);
+ }
+
+ /* Do we need to allocate a new client buffer? */
+ if (!psDevData->pHwpBuf)
+ {
+ psDevData->pHwpBuf = OSAllocMem(ui32TlBufLen);
+ if (psDevData->pHwpBuf == IMG_NULL)
+ {
+ (void) TLClientReleaseData(psDevData->hTLConnection, psDevData->hSD);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ psDevData->ui32HwpBufLen = ui32TlBufLen;
+ }
+
+ /* Process each TL packet in the data buffer we have acquired */
+ pBufferEnd = pTlBuf+ui32TlBufLen;
+ pDataDest = psDevData->pHwpBuf;
+ psHDRptr = GET_PACKET_HDR(pTlBuf);
+ while ( psHDRptr < (PVRSRVTL_PPACKETHDR)pBufferEnd )
+ {
+ ui16TlType = GET_PACKET_TYPE(psHDRptr);
+ if (ui16TlType == PVRSRVTL_PACKETTYPE_DATA)
+ {
+ IMG_UINT16 ui16DataLen = GET_PACKET_DATA_LEN(psHDRptr);
+ if (0 == ui16DataLen)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfAcquireData: ZERO Data in TL data packet: %p", psHDRptr));
+ }
+ else
+ {
+ /* For valid data copy it into the client buffer and move
+ * the write position on */
+ OSMemCopy(pDataDest, GET_PACKET_DATA_PTR(psHDRptr), ui16DataLen);
+ pDataDest += ui16DataLen;
+ }
+ }
+ else if (ui16TlType == PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfAcquireData: Indication that the transport buffer was full"));
+ }
+ else
+ {
+ /* else Ignore padding packet type and others */
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXHWPerfAcquireData: Ignoring TL packet, type %d", ui16TlType ));
+ }
+
+ /* Update loop variable to the next packet and increment counts */
+ psHDRptr = GET_NEXT_PACKET_ADDR(psHDRptr);
+ ui32TlPackets++;
+ }
+
+ PVR_DPF((PVR_DBG_VERBOSE, "RGXHWPerfAcquireData: TL Packets processed %03d", ui32TlPackets));
+
+ /* Update output arguments with client buffer details and true length */
+ *ppBuf = psDevData->pHwpBuf;
+ *pui32BufLen = pDataDest - psDevData->pHwpBuf;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR RGXHWPerfReleaseData(
+ IMG_HANDLE hDevData)
+{
+ PVRSRV_ERROR eError;
+ RGX_KM_HWPERF_DEVDATA* psDevData = (RGX_KM_HWPERF_DEVDATA*)hDevData;
+
+ /* Valid input argument values supplied by the caller */
+ if (!psDevData)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Free the client buffer if allocated and reset length */
+ if (psDevData->pHwpBuf)
+ {
+ OSFREEMEM(psDevData->pHwpBuf);
+ }
+ psDevData->ui32HwpBufLen = 0;
+
+ /* Inform the TL that we are done with reading the data. Could perform this
+ * in the acquire call but felt it worth keeping it symmetrical */
+ eError = TLClientReleaseData(psDevData->hTLConnection, psDevData->hSD);
+ return eError;
+}
+
+
+PVRSRV_ERROR RGXHWPerfDisconnect(
+ IMG_HANDLE hDevData)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGX_KM_HWPERF_DEVDATA* psDevData = (RGX_KM_HWPERF_DEVDATA*)hDevData;
+
+ /* Check session handle is not zero */
+ if (!psDevData)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* If the client buffer exists they have not called ReleaseData
+ * before disconnecting so clean it up */
+ if (psDevData->pHwpBuf)
+ {
+ eError = RGXHWPerfReleaseData(hDevData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfDisconnect: Failed to release data (%d)", eError));
+ }
+ /* RGXHWPerfReleaseData call above will null out the buffer
+ * fields and length */
+ }
+
+ /* Close the TL stream, ignore the error if it occurs as we
+ * are disconnecting */
+ if (psDevData->hSD)
+ {
+ eError = TLClientCloseStream(psDevData->hTLConnection,
+ psDevData->hSD);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfDisconnect: Failed to close handle on HWPerf stream (%d)", eError));
+ }
+ psDevData->hSD = IMG_NULL;
+ }
+
+ /* End the TL connection as we don't require it anymore */
+ if (psDevData->hTLConnection)
+ {
+ eError = TLClientDisconnect(psDevData->hTLConnection);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXHWPerfDisconnect: Failed to disconnect from the Transport (%d)", eError));
+ }
+ psDevData->hTLConnection = IMG_NULL;
+ }
+
+ /* Free the session memory */
+ psDevData->psRgxDevNode = IMG_NULL;
+ OSFREEMEM(psDevData);
+ return eError;
+}
+
+
+#endif /* SUPPORT_KERNEL_HWPERF */
+
+
+/******************************************************************************
+ End of file (rgxdebug.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.h
new file mode 100644
index 000000000000..1e5bd03ab216
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxhwperf.h
@@ -0,0 +1,114 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX HW Performance header file
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@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.
+
+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 RGXHWPERF_H_
+#define RGXHWPERF_H_
+
+#include "img_types.h"
+#include "img_defs.h"
+#include "pvrsrv_error.h"
+
+#include "device.h"
+#include "rgxdevice.h"
+#include "rgx_hwperf_km.h"
+
+
+/******************************************************************************
+ * RGX HW Performance Data Transport Routines
+ *****************************************************************************/
+
+PVRSRV_ERROR RGXHWPerfDataStoreCB(PVRSRV_DEVICE_NODE* psDevInfo);
+
+PVRSRV_ERROR RGXHWPerfInit(PVRSRV_DEVICE_NODE *psRgxDevInfo, IMG_BOOL bEnable);
+IMG_VOID RGXHWPerfDeinit(void);
+
+
+/******************************************************************************
+ * RGX HW Performance Profiling API(s)
+ *****************************************************************************/
+
+PVRSRV_ERROR PVRSRVRGXCtrlHWPerfKM(
+ PVRSRV_DEVICE_NODE* psDeviceNode,
+ IMG_BOOL bToggle,
+ IMG_UINT64 ui64Mask);
+
+
+PVRSRV_ERROR PVRSRVRGXConfigEnableHWPerfCountersKM(
+ PVRSRV_DEVICE_NODE* psDeviceNode,
+ IMG_UINT32 ui32ArrayLen,
+ RGX_HWPERF_CONFIG_CNTBLK* psBlockConfigs);
+
+PVRSRV_ERROR PVRSRVRGXCtrlHWPerfCountersKM(
+ PVRSRV_DEVICE_NODE* psDeviceNode,
+ IMG_BOOL bEnable,
+ IMG_UINT32 ui32ArrayLen,
+ IMG_UINT8* psBlockIDs);
+
+PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
+ PVRSRV_DEVICE_NODE* psDeviceNode,
+ IMG_UINT16 ui16CustomBlockID,
+ IMG_UINT16 ui16NumCustomCounters,
+ IMG_UINT32* pui32CustomCounterIDs);
+
+/******************************************************************************
+ * RGX HW Performance To FTrace Profiling API(s)
+ *****************************************************************************/
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+
+PVRSRV_ERROR RGXHWPerfFTraceGPUInit(PVRSRV_RGXDEV_INFO *psDevInfo);
+IMG_VOID RGXHWPerfFTraceGPUDeInit(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+IMG_VOID RGXHWPerfFTraceGPUEnqueueEvent(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32ExternalJobRef, IMG_UINT32 ui32InternalJobRef,
+ const IMG_CHAR* pszJobType);
+
+IMG_VOID RGXHWPerfFTraceGPUEventsEnabledSet(IMG_BOOL bNewValue);
+IMG_BOOL RGXHWPerfFTraceGPUEventsEnabled(IMG_VOID);
+
+IMG_VOID RGXHWPerfFTraceGPUThread(IMG_PVOID pvData);
+
+#endif
+
+
+#endif /* RGXHWPERF_H_ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxinit.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxinit.c
new file mode 100755
index 000000000000..7e8ffb19bc0a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxinit.c
@@ -0,0 +1,2972 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+
+#include "pvrsrv.h"
+#include "rgxheapconfig.h"
+#include "rgxpower.h"
+
+#include "rgxinit.h"
+
+#include "pdump_km.h"
+#include "handle.h"
+#include "allocmem.h"
+#include "devicemem_pdump.h"
+#include "rgxmem.h"
+#include "sync_internal.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 "rgxdebug.h"
+#include "rgxhwperf.h"
+
+#include "rgx_options_km.h"
+#include "pvrversion.h"
+
+#include "rgx_compat_bvnc.h"
+
+#include "rgx_heaps.h"
+
+#include "rgxta3d.h"
+#include "debug_request_ids.h"
+
+static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32ClientBuildOptions);
+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);
+
+#define RGX_MMU_LOG2_PAGE_SIZE_4KB (12)
+#define RGX_MMU_LOG2_PAGE_SIZE_16KB (14)
+#define RGX_MMU_LOG2_PAGE_SIZE_64KB (16)
+#define RGX_MMU_LOG2_PAGE_SIZE_256KB (18)
+#define RGX_MMU_LOG2_PAGE_SIZE_1MB (20)
+#define RGX_MMU_LOG2_PAGE_SIZE_2MB (21)
+
+#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
+
+
+static IMG_BOOL g_bDevInit2Done = IMG_FALSE;
+
+
+static IMG_VOID RGX_DeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo);
+
+IMG_UINT32 g_ui32HostSampleIRQCount = 0;
+
+#if !defined(NO_HARDWARE)
+
+/*
+ RGX LISR Handler
+*/
+static IMG_BOOL RGX_LISRHandler (IMG_VOID *pvData)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_DEVICE_CONFIG *psDevConfig;
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32IRQStatus;
+ IMG_BOOL bInterruptProcessed = IMG_FALSE;
+
+ psDeviceNode = pvData;
+ psDevConfig = psDeviceNode->psDevConfig;
+ psDevInfo = psDeviceNode->pvDevice;
+
+ if (psDevInfo->bIgnoreFurtherIRQs)
+ {
+ return IMG_FALSE;
+ }
+
+ ui32IRQStatus = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVIRQSTATUS);
+
+ if (ui32IRQStatus & RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_EN)
+ {
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVIRQSTATUS, RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK);
+
+#if defined(RGX_FEATURE_OCPBUS)
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OCP_IRQSTATUS_2, RGX_CR_OCP_IRQSTATUS_2_RGX_IRQ_STATUS_EN);
+#endif
+
+ if (psDevConfig->pfnInterruptHandled)
+ {
+ psDevConfig->pfnInterruptHandled(psDevConfig);
+ }
+
+ bInterruptProcessed = IMG_TRUE;
+
+ /* Sample the current count from the FW _after_ we've cleared the interrupt. */
+ g_ui32HostSampleIRQCount = psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount;
+
+ OSScheduleMISR(psDevInfo->pvMISRData);
+
+ if (psDevInfo->pvAPMISRData != IMG_NULL)
+ {
+ OSScheduleMISR(psDevInfo->pvAPMISRData);
+ }
+ }
+ return bInterruptProcessed;
+}
+
+static IMG_VOID RGXCheckFWActivePowerState(IMG_VOID *psDevice)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = psDevice;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_TRACEBUF *psFWTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psFWTraceBuf->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))
+ {
+ PVR_DPF((PVR_DBG_WARNING,"RGXCheckFWActivePowerState: Failed RGXActivePowerRequest call (device index: %d) with %s",
+ psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRVGetErrorStringKM(eError)));
+
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, IMG_NULL);
+ }
+ }
+
+}
+
+static RGXFWIF_GPU_UTIL_STATS RGXGetGpuUtilStats(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_GPU_UTIL_FWCB *psUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
+ IMG_UINT32 ui32StatActiveLow = 0, ui32StatActiveHigh = 0, ui32StatBlocked = 0, ui32StatIdle = 0;
+ IMG_UINT32 ui32StatCumulative = 0;
+ IMG_UINT32 ui32WOffSample, ui32PrevWOffSample, ui32PriorWOffSample;
+ IMG_UINT32 ui32WOffSampleSaved;
+ IMG_UINT64 ui64CurrentTimer;
+ IMG_UINT32 ui32Remainder;
+ RGXFWIF_GPU_UTIL_STATS sRet;
+ PVRSRV_DEV_POWER_STATE ePowerState;
+// PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 ui32NextType;
+
+ static RGXFWIF_GPU_UTIL_STATS sPreviousStats;
+ static IMG_UINT32 ui32WarningTicks = 0;
+
+ /* init response */
+ sRet.ui32GpuStatActiveHigh = 0;
+ sRet.ui32GpuStatActiveLow = 0;
+ sRet.ui32GpuStatBlocked = 0;
+ sRet.ui32GpuStatIdle = 0;
+ sRet.bValid = IMG_FALSE;
+ sRet.bIncompleteData = IMG_FALSE;
+
+ /* take the power lock as we might issue an OSReadHWReg64 below */
+/* eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ return sRet;
+ }*/
+
+ /* write offset is incremented after writing to FWCB, so subtract 1 */
+ ui32WOffSample = psUtilFWCb->ui32WriteOffset;
+ if(ui32WOffSample == 0)
+ {
+ ui32WOffSample = RGXFWIF_GPU_UTIL_FWCB_SIZE;
+ }
+ ui32WOffSample--;
+ ui32WOffSampleSaved = ui32PrevWOffSample = ui32PriorWOffSample = ui32WOffSample;
+
+ PVRSRVGetDevicePowerState(psDeviceNode->sDevId.ui32DeviceIndex, &ePowerState);
+ if (ePowerState != PVRSRV_DEV_POWER_STATE_ON) /* GPU powered off */
+ {
+ ui64CurrentTimer = OSClockus64() & RGXFWIF_GPU_UTIL_FWCB_OS_TIMER_MASK;
+ ui32NextType = RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON;
+ }
+ else /* GPU powered on */
+ {
+ ui64CurrentTimer = RGXReadHWTimerReg(psDevInfo);
+ ui32NextType = RGXFWIF_GPU_UTIL_FWCB_TYPE_CRTIME;
+ }
+ //PVRSRVPowerUnlock();
+
+ do
+ {
+ IMG_UINT64 ui64FWCbEntryCurrent = psUtilFWCb->aui64CB[ui32WOffSample];
+
+ if (ui64FWCbEntryCurrent != RGXFWIF_GPU_UTIL_FWCB_RESERVED)
+ {
+ IMG_UINT64 ui64Period = 0;
+
+ ui32Type = RGXFWIF_GPU_UTIL_FWCB_ENTRY_TYPE(ui64FWCbEntryCurrent);
+
+ switch(ui32Type)
+ {
+ case RGXFWIF_GPU_UTIL_FWCB_TYPE_CRTIME:
+ {
+ IMG_UINT32 ui32DVFSHistClock =
+ psDevInfo->psGpuDVFSHistory->aui32DVFSClockCB[RGXFWIF_GPU_UTIL_FWCB_ENTRY_ID(ui64FWCbEntryCurrent)];
+
+ if (ui32DVFSHistClock < 256)
+ {
+ /* DVFS frequency is 0 in DVFS history entry, which means that
+ system layer doesn't define core clock frequency */
+ ui32StatCumulative = 0;
+
+ goto gpuutilstats_endloop;
+ }
+
+ /* Calculate the difference between current CR timer and CR timer at DVFS transition */
+ ui64Period = ui64CurrentTimer - RGXFWIF_GPU_UTIL_FWCB_ENTRY_CR_TIMER(ui64FWCbEntryCurrent);
+
+ /* Scale the difference to microseconds */
+ ui64Period = OSDivide64((ui64Period * 1000000), (ui32DVFSHistClock / 256), &ui32Remainder);
+
+ /* Update "now" to CR Timer of current entry */
+ ui64CurrentTimer = RGXFWIF_GPU_UTIL_FWCB_ENTRY_CR_TIMER(ui64FWCbEntryCurrent);
+
+ break;
+ }
+
+ case RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_OFF:
+
+ /* Calculate the difference between OS timers at power-on/power-off transitions */
+ ui64Period = ui64CurrentTimer - RGXFWIF_GPU_UTIL_FWCB_ENTRY_OS_TIMER(ui64FWCbEntryCurrent);
+
+ break;
+
+ case RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON:
+ case RGXFWIF_GPU_UTIL_FWCB_TYPE_END_CRTIME:
+
+ /* Update "now" to the Timer of current entry */
+ if(ui32Type == RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON)
+ {
+ ui64CurrentTimer = RGXFWIF_GPU_UTIL_FWCB_ENTRY_OS_TIMER(ui64FWCbEntryCurrent);
+ }
+ else
+ {
+ ui64CurrentTimer = RGXFWIF_GPU_UTIL_FWCB_ENTRY_CR_TIMER(ui64FWCbEntryCurrent);
+ }
+
+ /* Move to next-previous state transition */
+ if(ui32WOffSample == 0)
+ {
+ ui32WOffSample = RGXFWIF_GPU_UTIL_FWCB_SIZE;
+ }
+ ui32WOffSample--;
+
+ /* Remember the next-previous entry type */
+ ui32NextType = ui32Type;
+
+ continue;
+
+ default:
+ PVR_DPF((PVR_DBG_WARNING,"RGXGetGpuUtilStats: Wrong type: %8.8X\n", ui32Type));
+ break;
+ }
+
+ /* If calculated period goes beyond the time window that we want to look at to calculate stats,
+ cut it down to this window */
+ if (((IMG_UINT64)ui32StatCumulative + ui64Period) > (IMG_UINT64)RGXFWIF_GPU_STATS_WINDOW_SIZE_US)
+ {
+ ui64Period = RGXFWIF_GPU_STATS_WINDOW_SIZE_US - ui32StatCumulative;
+ }
+
+ /* Update cumulative time of state transition */
+ ui32StatCumulative += (IMG_UINT32)ui64Period;
+
+ /* Update per-state cumulative times */
+ switch (RGXFWIF_GPU_UTIL_FWCB_ENTRY_STATE(ui64FWCbEntryCurrent))
+ {
+ case RGXFWIF_GPU_UTIL_FWCB_STATE_ACTIVE_LOW:
+ ui32StatActiveLow += (IMG_UINT32)ui64Period;
+ break;
+ case RGXFWIF_GPU_UTIL_FWCB_STATE_IDLE:
+ ui32StatIdle += (IMG_UINT32)ui64Period;
+ break;
+ case RGXFWIF_GPU_UTIL_FWCB_STATE_ACTIVE_HIGH:
+ ui32StatActiveHigh += (IMG_UINT32)ui64Period;
+ break;
+ case RGXFWIF_GPU_UTIL_FWCB_STATE_BLOCKED:
+ ui32StatBlocked += (IMG_UINT32)ui64Period;
+ break;
+ }
+ }
+ else
+ {
+ /* current sample is reserved */
+ break;
+ }
+
+ /* Move to next-previous state transition */
+ ui32PriorWOffSample = ui32PrevWOffSample;
+ ui32PrevWOffSample = ui32WOffSample;
+ if(ui32WOffSample == 0)
+ {
+ ui32WOffSample = RGXFWIF_GPU_UTIL_FWCB_SIZE;
+ }
+ ui32WOffSample--;
+
+ /* Remember the next-previous entry type */
+ ui32NextType = ui32Type;
+
+ ui32WOffSampleSaved = psUtilFWCb->ui32WriteOffset;
+ }
+ /* break if the FW or the Host wrote something to the CB while we were reading it
+ * or if we have already calculated the whole window */
+ while ((ui32WOffSample != ui32WOffSampleSaved) &&
+ (ui32PrevWOffSample != ui32WOffSampleSaved) &&
+ (ui32PriorWOffSample != ui32WOffSampleSaved) &&
+ (ui32StatCumulative < RGXFWIF_GPU_STATS_WINDOW_SIZE_US));
+
+gpuutilstats_endloop:
+
+ if (ui32StatCumulative)
+ {
+ /* Update stats */
+ sRet.ui32GpuStatActiveLow = OSDivide64(((IMG_UINT64)ui32StatActiveLow * RGXFWIF_GPU_STATS_MAX_VALUE_OF_STATE), ui32StatCumulative, &ui32Remainder);
+ sRet.ui32GpuStatActiveHigh = OSDivide64(((IMG_UINT64)ui32StatActiveHigh * RGXFWIF_GPU_STATS_MAX_VALUE_OF_STATE), ui32StatCumulative, &ui32Remainder);
+ sRet.ui32GpuStatBlocked = OSDivide64(((IMG_UINT64)ui32StatBlocked * RGXFWIF_GPU_STATS_MAX_VALUE_OF_STATE), ui32StatCumulative, &ui32Remainder);
+ sRet.ui32GpuStatIdle = OSDivide64(((IMG_UINT64)ui32StatIdle * RGXFWIF_GPU_STATS_MAX_VALUE_OF_STATE), ui32StatCumulative, &ui32Remainder);
+ sRet.bValid = IMG_TRUE;
+
+ if(ui32StatCumulative < RGXFWIF_GPU_STATS_WINDOW_SIZE_US)
+ {
+#define RGX_GPU_UTIL_STAT_MULTIPLIER 1000 /* Multiply everything to get some better accuracy when weighting last and previous values */
+#define RGX_GPU_UTIL_STAT_SCALE 4 /* Give less importance to the values just computed */
+#define RGX_GPU_UTIL_STAT_WARNING_PERIOD 8
+ IMG_UINT32 ui32LastStatWeight = (RGX_GPU_UTIL_STAT_MULTIPLIER * ui32StatCumulative)/(RGX_GPU_UTIL_STAT_SCALE * RGXFWIF_GPU_STATS_WINDOW_SIZE_US);
+ IMG_UINT32 ui32PrevStatWeight = (RGX_GPU_UTIL_STAT_MULTIPLIER - ui32LastStatWeight);
+
+ sRet.ui32GpuStatActiveHigh = ( (sRet.ui32GpuStatActiveHigh * ui32LastStatWeight) + (sPreviousStats.ui32GpuStatActiveHigh * ui32PrevStatWeight) ) / RGX_GPU_UTIL_STAT_MULTIPLIER;
+ sRet.ui32GpuStatActiveLow = ( (sRet.ui32GpuStatActiveLow * ui32LastStatWeight) + (sPreviousStats.ui32GpuStatActiveLow * ui32PrevStatWeight) ) / RGX_GPU_UTIL_STAT_MULTIPLIER;
+ sRet.ui32GpuStatBlocked = ( (sRet.ui32GpuStatBlocked * ui32LastStatWeight) + (sPreviousStats.ui32GpuStatBlocked * ui32PrevStatWeight) ) / RGX_GPU_UTIL_STAT_MULTIPLIER;
+ sRet.ui32GpuStatIdle = ( (sRet.ui32GpuStatIdle * ui32LastStatWeight) + (sPreviousStats.ui32GpuStatIdle * ui32PrevStatWeight) ) / RGX_GPU_UTIL_STAT_MULTIPLIER;
+ sRet.bIncompleteData = IMG_TRUE;
+
+ if((ui32WarningTicks % RGX_GPU_UTIL_STAT_WARNING_PERIOD) == 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"RGXGetGpuUtilStats: Time window shorter than expected, returned data may be inaccurate\n"));
+ }
+ ui32WarningTicks++;
+ }
+
+ sPreviousStats.ui32GpuStatActiveLow = sRet.ui32GpuStatActiveLow;
+ sPreviousStats.ui32GpuStatActiveHigh = sRet.ui32GpuStatActiveHigh;
+ sPreviousStats.ui32GpuStatBlocked = sRet.ui32GpuStatBlocked;
+ sPreviousStats.ui32GpuStatIdle = sRet.ui32GpuStatIdle;
+ }
+
+ return sRet;
+}
+
+/*
+ RGX MISR Handler
+*/
+static IMG_VOID RGX_MISRHandler (IMG_VOID *pvData)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+
+ /* Inform other services devices that we have finished an operation */
+ PVRSRVCheckStatus(psDeviceNode);
+
+ /* Give the HWPerf service a chance to transfer some data from the FW
+ * buffer to the host driver transport layer buffer.
+ */
+ RGXHWPerfDataStoreCB(psDeviceNode);
+
+ /* Process all firmware CCBs for pending commands */
+ RGXCheckFirmwareCCBs(psDeviceNode->pvDevice);
+}
+#endif
+
+
+/*
+ * PVRSRVRGXInitDevPart2KM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXInitDevPart2KM (PVRSRV_DEVICE_NODE *psDeviceNode,
+ RGX_INIT_COMMAND *psInitScript,
+ RGX_INIT_COMMAND *psDbgScript,
+ RGX_INIT_COMMAND *psDbgBusScript,
+ RGX_INIT_COMMAND *psDeinitScript,
+ IMG_UINT32 ui32KernelCatBaseIdReg,
+ IMG_UINT32 ui32KernelCatBaseId,
+ IMG_UINT32 ui32KernelCatBaseReg,
+ IMG_UINT32 ui32KernelCatBaseWordSize,
+ IMG_UINT32 ui32KernelCatBaseAlignShift,
+ IMG_UINT32 ui32KernelCatBaseShift,
+ IMG_UINT64 ui64KernelCatBaseMask,
+ IMG_UINT32 ui32DeviceFlags,
+ RGX_ACTIVEPM_CONF eActivePMConf,
+ DEVMEM_EXPORTCOOKIE *psFWCodeAllocServerExportCookie,
+ DEVMEM_EXPORTCOOKIE *psFWDataAllocServerExportCookie,
+ DEVMEM_EXPORTCOOKIE *psFWCorememAllocServerExportCookie)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+ PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
+
+ PDUMPCOMMENT("RGX Initialisation Part 2");
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ psDevInfo->bEnableProcessStats=IMG_TRUE;
+#else
+ psDevInfo->bEnableProcessStats=IMG_FALSE;
+#endif
+
+ psDevInfo->ui32KernelCatBaseIdReg = ui32KernelCatBaseIdReg;
+ psDevInfo->ui32KernelCatBaseId = ui32KernelCatBaseId;
+ psDevInfo->ui32KernelCatBaseReg = ui32KernelCatBaseReg;
+ psDevInfo->ui32KernelCatBaseAlignShift = ui32KernelCatBaseAlignShift;
+ psDevInfo->ui32KernelCatBaseShift = ui32KernelCatBaseShift;
+ psDevInfo->ui32KernelCatBaseWordSize = ui32KernelCatBaseWordSize;
+ psDevInfo->ui64KernelCatBaseMask = ui64KernelCatBaseMask;
+
+ /*
+ * Map RGX Registers
+ */
+#if !defined(NO_HARDWARE)
+ psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psDevConfig->sRegsCpuPBase,
+ psDevConfig->ui32RegsSize,
+ 0);
+
+ if (psDevInfo->pvRegsBaseKM == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: Failed to create RGX register mapping\n"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+#else
+ psDevInfo->pvRegsBaseKM = IMG_NULL;
+#endif /* !NO_HARDWARE */
+
+ /* free the export cookies provided to srvinit */
+ DevmemUnexport(psDevInfo->psRGXFWCodeMemDesc, psFWCodeAllocServerExportCookie);
+ DevmemUnexport(psDevInfo->psRGXFWDataMemDesc, psFWDataAllocServerExportCookie);
+ if (DevmemIsValidExportCookie(psFWCorememAllocServerExportCookie))
+ {
+ DevmemUnexport(psDevInfo->psRGXFWCorememMemDesc, psFWCorememAllocServerExportCookie);
+ }
+
+ /*
+ * Copy scripts
+ */
+ OSMemCopy(psDevInfo->psScripts->asInitCommands, psInitScript,
+ RGX_MAX_INIT_COMMANDS * sizeof(*psInitScript));
+
+ OSMemCopy(psDevInfo->psScripts->asDbgCommands, psDbgScript,
+ RGX_MAX_INIT_COMMANDS * sizeof(*psDbgScript));
+
+ OSMemCopy(psDevInfo->psScripts->asDbgBusCommands, psDbgBusScript,
+ RGX_MAX_DBGBUS_COMMANDS * sizeof(*psDbgBusScript));
+
+ OSMemCopy(psDevInfo->psScripts->asDeinitCommands, psDeinitScript,
+ RGX_MAX_DEINIT_COMMANDS * sizeof(*psDeinitScript));
+
+#if defined(PDUMP)
+ /* Run the deinit script to feed the last-frame deinit buffer */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_DEINIT, "RGX deinitialisation script");
+ RGXRunScript(psDevInfo, psDevInfo->psScripts->asDeinitCommands, RGX_MAX_DEINIT_COMMANDS, PDUMP_FLAGS_DEINIT | PDUMP_FLAGS_NOHW, IMG_NULL);
+#endif
+
+
+ psDevInfo->ui32RegSize = psDevConfig->ui32RegsSize;
+ psDevInfo->sRegsPhysBase = psDevConfig->sRegsCpuPBase;
+
+ /* Initialise Device Flags */
+ psDevInfo->ui32DeviceFlags = 0;
+ if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_ZERO_FREELIST)
+ {
+ psDevInfo->ui32DeviceFlags |= RGXKM_DEVICE_STATE_ZERO_FREELIST;
+ }
+
+ if (ui32DeviceFlags & RGXKMIF_DEVICE_STATE_DISABLE_DW_LOGGING_EN)
+ {
+ psDevInfo->ui32DeviceFlags |= RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN;
+ }
+
+ #if defined(SUPPORT_GPUTRACE_EVENTS)
+ /* If built, always setup FTrace consumer thread. */
+ RGXHWPerfFTraceGPUInit(psDeviceNode->pvDevice);
+
+ RGXHWPerfFTraceGPUEventsEnabledSet((ui32DeviceFlags & RGXKMIF_DEVICE_STATE_FTRACE_EN) ? IMG_TRUE: IMG_FALSE);
+#endif
+
+ /* Initialise lists of ZSBuffers */
+ eError = OSLockCreate(&psDevInfo->hLockZSBuffer,LOCK_TYPE_PASSIVE);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ dllist_init(&psDevInfo->sZSBufferHead);
+ psDevInfo->ui32ZSBufferCurrID = 1;
+
+ /* Initialise lists of growable Freelists */
+ eError = OSLockCreate(&psDevInfo->hLockFreeList,LOCK_TYPE_PASSIVE);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ dllist_init(&psDevInfo->sFreeListHead);
+ psDevInfo->ui32FreelistCurrID = 1;
+
+ /* Allocate DVFS History */
+ psDevInfo->psGpuDVFSHistory = OSAllocZMem(sizeof(*(psDevInfo->psGpuDVFSHistory)));
+ if (psDevInfo->psGpuDVFSHistory == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: failed to allocate gpu dvfs history storage"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Reset DVFS history */
+ psDevInfo->psGpuDVFSHistory->ui32CurrentDVFSId = 0;
+ psDevInfo->psGpuDVFSHistory->aui32DVFSClockCB[0] = 0;
+
+ /* Setup GPU Utilization stat update callback */
+#if !defined(NO_HARDWARE)
+ psDevInfo->pfnGetGpuUtilStats = RGXGetGpuUtilStats;
+#endif
+
+ eDefaultPowerState = PVRSRV_DEV_POWER_STATE_ON;
+
+ /* set-up the Active Power Mgmt callback */
+#if !defined(NO_HARDWARE)
+ {
+ 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)
+ {
+ eError = OSInstallMISR(&psDevInfo->pvAPMISRData, RGXCheckFWActivePowerState, psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ /* Prevent the device being woken up before there is something to do. */
+ eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ }
+ }
+#endif
+
+ /* Register the device with the power manager. */
+ eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
+ &RGXPrePowerState, &RGXPostPowerState,
+ psDevConfig->pfnPrePowerState, psDevConfig->pfnPostPowerState,
+ &RGXPreClockSpeedChange, &RGXPostClockSpeedChange,
+ (IMG_HANDLE)psDeviceNode,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ eDefaultPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitDevPart2KM: failed to register device with power manager"));
+ return eError;
+ }
+
+#if !defined(NO_HARDWARE)
+ eError = RGXInstallProcessQueuesMISR(&psDevInfo->hProcessQueuesMISR, psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ if (psDevInfo->pvAPMISRData != IMG_NULL)
+ {
+ (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
+ }
+ return eError;
+ }
+
+ /* Register the interrupt handlers */
+ eError = OSInstallMISR(&psDevInfo->pvMISRData,
+ RGX_MISRHandler, psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ if (psDevInfo->pvAPMISRData != IMG_NULL)
+ {
+ (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
+ }
+ (IMG_VOID) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
+ return eError;
+ }
+
+ eError = OSInstallDeviceLISR(psDevConfig, &psDevInfo->pvLISRData,
+ RGX_LISRHandler, psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ if (psDevInfo->pvAPMISRData != IMG_NULL)
+ {
+ (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
+ }
+ (IMG_VOID) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
+ (IMG_VOID) OSUninstallMISR(psDevInfo->pvMISRData);
+ return eError;
+ }
+
+#endif
+ g_bDevInit2Done = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR RGXAllocateFWCodeRegion(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEVMEM_SIZE_T ui32FWCodeAllocSize,
+ IMG_UINT32 uiMemAllocFlags)
+{
+ PVRSRV_ERROR eError;
+
+#if ! defined(TDMETACODE)
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ uiMemAllocFlags |= PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ PDUMPCOMMENT("Allocate and export code memory for fw");
+
+ eError = DevmemFwAllocateExportable(psDeviceNode,
+ ui32FWCodeAllocSize,
+ uiMemAllocFlags,
+ "FirmwareCodeRegion",
+ &psDevInfo->psRGXFWCodeMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevmemFwAllocateExportable failed (%u)",
+ eError));
+ }
+
+ return eError;
+
+#else
+ PMR *psTDMetaCodePMR;
+ IMG_DEVMEM_SIZE_T uiMemDescSize;
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+
+ PDUMPCOMMENT("Allocate TD META code memory for fw");
+
+ eError = PhysmemNewTDMetaCodePMR(psDeviceNode,
+ ui32FWCodeAllocSize,
+ 12,
+ uiMemAllocFlags,
+ &psTDMetaCodePMR);
+ if(eError != PVRSRV_OK)
+ {
+ goto PMRCreateError;
+ }
+
+ PDUMPCOMMENT("Import TD META code memory for fw");
+
+ /* NB: psTDMetaCodePMR refcount: 1 -> 2 */
+ eError = DevmemLocalImport(IMG_NULL, /* bridge handle not applicable here */
+ psTDMetaCodePMR,
+ uiMemAllocFlags,
+ &psDevInfo->psRGXFWCodeMemDesc,
+ &uiMemDescSize);
+ if(eError != PVRSRV_OK)
+ {
+ goto ImportError;
+ }
+
+ eError = DevmemMapToDevice(psDevInfo->psRGXFWCodeMemDesc,
+ psDevInfo->psFirmwareHeap,
+ &sTmpDevVAddr);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to map TD META code PMR (%u)", eError));
+ goto MapError;
+ }
+
+ /* Caution, oddball code follows:
+ When doing the DevmemLocalImport above, we wrap the PMR in a memdesc and increment
+ the PMR's refcount. We would like to implicitly say now, that memdesc is our
+ tracking mechanism for the PMR, and no longer the original pointer to it. The call
+ to PMRUnimportPMR below does that. For reasons explained below, this is only done
+ if this function will return successfully.
+
+ NB: i.e., psTDMetaCodePMR refcount: 2 -> 1
+ */
+ PMRUnimportPMR(psTDMetaCodePMR);
+
+ return eError;
+
+MapError:
+ DevmemFree(psDevInfo->psRGXFWCodeMemDesc);
+
+ImportError:
+ /* This is done even after the DevmemFree above because as a result of the PMRUnimportPMR
+ at the end of the function never getting hit on an error condition, the PMR must be
+ unreferenced "again" as part of the cleanup */
+ PMRUnimportPMR(psTDMetaCodePMR);
+
+PMRCreateError:
+
+ return eError;
+#endif
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXInitAllocFWImgMemKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEVMEM_SIZE_T uiFWCodeLen,
+ IMG_DEVMEM_SIZE_T uiFWDataLen,
+ IMG_DEVMEM_SIZE_T uiFWCorememLen,
+ DEVMEM_EXPORTCOOKIE **ppsFWCodeAllocServerExportCookie,
+ IMG_DEV_VIRTADDR *psFWCodeDevVAddrBase,
+ DEVMEM_EXPORTCOOKIE **ppsFWDataAllocServerExportCookie,
+ IMG_DEV_VIRTADDR *psFWDataDevVAddrBase,
+ DEVMEM_EXPORTCOOKIE **ppsFWCorememAllocServerExportCookie,
+ IMG_DEV_VIRTADDR *psFWCorememDevVAddrBase,
+ RGXFWIF_DEV_VIRTADDR *psFWCorememMetaVAddrBase)
+{
+ DEVMEM_FLAGS_T uiMemAllocFlags;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+
+ /* set up memory contexts */
+
+ /* Register callbacks for creation of device memory contexts */
+ psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
+ psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
+
+ /* Create the memory context for the firmware. */
+ eError = DevmemCreateContext(IMG_NULL, psDeviceNode,
+ DEVMEM_HEAPCFG_META,
+ &psDevInfo->psKernelDevmemCtx);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitAllocFWImgMemKM: Failed DevmemCreateContext (%u)", eError));
+ goto failed_to_create_ctx;
+ }
+
+ eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx,
+ "Firmware",
+ &psDevInfo->psFirmwareHeap);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitAllocFWImgMemKM: Failed DevmemFindHeapByName (%u)", eError));
+ goto failed_to_find_heap;
+ }
+
+ /*
+ * 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_KERNEL_CPU_MAPPABLE;
+
+
+ eError = RGXAllocateFWCodeRegion(psDeviceNode,
+ uiFWCodeLen,
+ uiMemAllocFlags);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw code mem (%u)",
+ eError));
+ goto failFWCodeMemDescAlloc;
+ }
+
+ eError = DevmemExport(psDevInfo->psRGXFWCodeMemDesc,
+ &psDevInfo->sRGXFWCodeExportCookie);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to export fw code mem (%u)",
+ eError));
+ goto failFWCodeMemDescExport;
+ }
+
+ eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc,
+ psFWCodeDevVAddrBase);
+ 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 (META will not be able to find the bootloader).
+ */
+ PVR_ASSERT(psFWCodeDevVAddrBase->uiAddr == RGX_FIRMWARE_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_GPU_CACHE_INCOHERENT |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ PDUMPCOMMENT("Allocate and export data memory for fw");
+
+ eError = DevmemFwAllocateExportable(psDeviceNode,
+ uiFWDataLen,
+ uiMemAllocFlags,
+ "FirmwareDataRegion",
+ &psDevInfo->psRGXFWDataMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw data mem (%u)",
+ eError));
+ goto failFWDataMemDescAlloc;
+ }
+
+ eError = DevmemExport(psDevInfo->psRGXFWDataMemDesc,
+ &psDevInfo->sRGXFWDataExportCookie);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to export fw data mem (%u)",
+ eError));
+ goto failFWDataMemDescExport;
+ }
+
+ eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWDataMemDesc,
+ psFWDataDevVAddrBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw data mem (%u)",
+ eError));
+ goto failFWDataMemDescAqDevVirt;
+ }
+
+ if (uiFWCorememLen != 0)
+ {
+ /*
+ * Set up Allocation for FW coremem section
+ */
+ uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_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_WRITE_COMBINE |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ PDUMPCOMMENT("Allocate and export coremem memory for fw");
+
+ eError = DevmemFwAllocateExportable(psDeviceNode,
+ uiFWCorememLen,
+ uiMemAllocFlags,
+ "FirmwareCorememRegion",
+ &psDevInfo->psRGXFWCorememMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to allocate fw coremem mem, size: %lld, flags: %x (%u)",
+ uiFWCorememLen, uiMemAllocFlags, eError));
+ goto failFWCorememMemDescAlloc;
+ }
+
+ eError = DevmemExport(psDevInfo->psRGXFWCorememMemDesc,
+ &psDevInfo->sRGXFWCorememExportCookie);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to export fw coremem mem (%u)",
+ eError));
+ goto failFWCorememMemDescExport;
+ }
+
+ eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCorememMemDesc,
+ psFWCorememDevVAddrBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to acquire devVAddr for fw coremem mem (%u)",
+ eError));
+ goto failFWCorememMemDescAqDevVirt;
+ }
+
+ RGXSetFirmwareAddress(psFWCorememMetaVAddrBase,
+ psDevInfo->psRGXFWCorememMemDesc,
+ 0, RFW_FWADDR_NOREF_FLAG);
+
+#if defined(HW_ERN_45914)
+ /* temporarily make sure the coremem is init using the SLC */
+ psFWCorememMetaVAddrBase->ui32Addr &= ~RGXFW_SEGMMU_DMAP_ADDR_START;
+ psFWCorememMetaVAddrBase->ui32Addr |= RGXFW_BOOTLDR_META_ADDR;
+#endif
+
+ }
+
+ *ppsFWCodeAllocServerExportCookie = &psDevInfo->sRGXFWCodeExportCookie;
+ *ppsFWDataAllocServerExportCookie = &psDevInfo->sRGXFWDataExportCookie;
+ /* Set all output arguments to ensure safe use in Part2 initialisation */
+ *ppsFWCorememAllocServerExportCookie = &psDevInfo->sRGXFWCorememExportCookie;
+
+ return PVRSRV_OK;
+
+
+failFWCorememMemDescAqDevVirt:
+
+ if (uiFWCorememLen != 0)
+ {
+ DevmemUnexport(psDevInfo->psRGXFWCorememMemDesc, &psDevInfo->sRGXFWCorememExportCookie);
+ }
+failFWCorememMemDescExport:
+
+ if (uiFWCorememLen != 0)
+ {
+ DevmemFwFree(psDevInfo->psRGXFWCorememMemDesc);
+ }
+failFWCorememMemDescAlloc:
+
+ DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
+failFWDataMemDescAqDevVirt:
+
+ DevmemUnexport(psDevInfo->psRGXFWDataMemDesc, &psDevInfo->sRGXFWDataExportCookie);
+failFWDataMemDescExport:
+
+ DevmemFwFree(psDevInfo->psRGXFWDataMemDesc);
+failFWDataMemDescAlloc:
+
+ DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
+failFWCodeMemDescAqDevVirt:
+
+ DevmemUnexport(psDevInfo->psRGXFWCodeMemDesc, &psDevInfo->sRGXFWCodeExportCookie);
+failFWCodeMemDescExport:
+
+ DevmemFwFree(psDevInfo->psRGXFWCodeMemDesc);
+failFWCodeMemDescAlloc:
+
+failed_to_find_heap:
+ /*
+ * Clear the mem context create callbacks before destroying the RGX firmware
+ * context to avoid a spurious callback.
+ */
+ psDeviceNode->pfnRegisterMemoryContext = IMG_NULL;
+ psDeviceNode->pfnUnregisterMemoryContext = IMG_NULL;
+ DevmemDestroyContext(psDevInfo->psKernelDevmemCtx);
+failed_to_create_ctx:
+
+ return eError;
+}
+
+/*
+ * PVRSRVRGXInitFirmwareKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXInitFirmwareKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ RGXFWIF_DEV_VIRTADDR *psRGXFwInit,
+ IMG_BOOL bEnableSignatureChecks,
+ IMG_UINT32 ui32SignatureChecksBufSize,
+ IMG_UINT32 ui32HWPerfFWBufSizeKB,
+ IMG_UINT64 ui64HWPerfFilter,
+ IMG_UINT32 ui32RGXFWAlignChecksSize,
+ IMG_UINT32 *pui32RGXFWAlignChecks,
+ IMG_UINT32 ui32ConfigFlags,
+ IMG_UINT32 ui32LogType,
+ IMG_UINT32 ui32FilterFlags,
+ RGXFWIF_COMPCHECKS_BVNC *psClientBVNC)
+{
+ PVRSRV_ERROR eError;
+ RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
+ IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
+ IMG_UINT32 ui32NumBIFTilingConfigs, *pui32BIFTilingXStrides, i;
+
+
+ /* Check if BVNC numbers of client and driver are compatible */
+ rgx_bvnc_packed(&sBVNC.ui32BNC, sBVNC.aszV, sBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C);
+
+ RGX_BVNC_EQUAL(sBVNC, *psClientBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
+
+ if (!bCompatibleAll)
+ {
+ if (!bCompatibleVersion)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%d) and client (%d).",
+ __FUNCTION__,
+ sBVNC.ui32LayoutVersion,
+ psClientBVNC->ui32LayoutVersion));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ PVR_DBG_BREAK;
+ goto failed_to_pass_compatibility_check;
+ }
+
+ if (!bCompatibleLenMax)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible V maxlen of driver (%d) and client (%d).",
+ __FUNCTION__,
+ sBVNC.ui32VLenMax,
+ psClientBVNC->ui32VLenMax));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ PVR_DBG_BREAK;
+ goto failed_to_pass_compatibility_check;
+ }
+
+ if (!bCompatibleBNC)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible driver BNC (%d._.%d.%d) / client BNC (%d._.%d.%d).",
+ __FUNCTION__,
+ RGX_BVNC_PACKED_EXTR_B(sBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sBVNC),
+ RGX_BVNC_PACKED_EXTR_B(*psClientBVNC),
+ RGX_BVNC_PACKED_EXTR_N(*psClientBVNC),
+ RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ PVR_DBG_BREAK;
+ goto failed_to_pass_compatibility_check;
+ }
+
+ if (!bCompatibleV)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible driver BVNC (%d.%s.%d.%d) / client BVNC (%d.%s.%d.%d).",
+ __FUNCTION__,
+ RGX_BVNC_PACKED_EXTR_B(sBVNC),
+ RGX_BVNC_PACKED_EXTR_V(sBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sBVNC),
+ RGX_BVNC_PACKED_EXTR_B(*psClientBVNC),
+ RGX_BVNC_PACKED_EXTR_V(*psClientBVNC),
+ RGX_BVNC_PACKED_EXTR_N(*psClientBVNC),
+ RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ PVR_DBG_BREAK;
+ goto failed_to_pass_compatibility_check;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: COMPAT_TEST: driver BVNC (%d.%s.%d.%d) and client BVNC (%d.%s.%d.%d) match. [ OK ]",
+ __FUNCTION__,
+ RGX_BVNC_PACKED_EXTR_B(sBVNC),
+ RGX_BVNC_PACKED_EXTR_V(sBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sBVNC),
+ RGX_BVNC_PACKED_EXTR_B(*psClientBVNC),
+ RGX_BVNC_PACKED_EXTR_V(*psClientBVNC),
+ RGX_BVNC_PACKED_EXTR_N(*psClientBVNC),
+ RGX_BVNC_PACKED_EXTR_C(*psClientBVNC)));
+ }
+
+ GetNumBifTilingHeapConfigs(&ui32NumBIFTilingConfigs);
+ pui32BIFTilingXStrides = OSAllocMem(sizeof(IMG_UINT32) * ui32NumBIFTilingConfigs);
+ if(pui32BIFTilingXStrides == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: OSAllocMem failed (%u)", eError));
+ goto failed_BIF_tiling_alloc;
+ }
+ for(i = 0; i < ui32NumBIFTilingConfigs; i++)
+ {
+ eError = GetBIFTilingHeapXStride(i+1, &pui32BIFTilingXStrides[i]);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: GetBIFTilingHeapXStride for heap %u failed (%u)",
+ i + 1, eError));
+ goto failed_BIF_heap_init;
+ }
+ }
+
+ eError = RGXSetupFirmware(psDeviceNode,
+ bEnableSignatureChecks,
+ ui32SignatureChecksBufSize,
+ ui32HWPerfFWBufSizeKB,
+ ui64HWPerfFilter,
+ ui32RGXFWAlignChecksSize,
+ pui32RGXFWAlignChecks,
+ ui32ConfigFlags,
+ ui32LogType,
+ ui32NumBIFTilingConfigs,
+ pui32BIFTilingXStrides,
+ ui32FilterFlags,
+ psRGXFwInit);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXInitFirmwareKM: RGXSetupFirmware failed (%u)", eError));
+ goto failed_init_firmware;
+ }
+
+ OSFreeMem(pui32BIFTilingXStrides);
+ return PVRSRV_OK;
+
+failed_init_firmware:
+failed_BIF_heap_init:
+ OSFreeMem(pui32BIFTilingXStrides);
+failed_BIF_tiling_alloc:
+failed_to_pass_compatibility_check:
+ 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);
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+ /* Size and align are 'expanded' because we request an Exportalign allocation */
+ DevmemExportalignAdjustSizeAndAlign(psDevInfo->psFirmwareHeap,
+ &uiUFOBlockSize,
+ &ui32UFOBlockAlign);
+
+ eError = DevmemFwAllocateExportable(psDeviceNode,
+ uiUFOBlockSize,
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+ PVRSRV_MEMALLOCFLAG_CACHE_COHERENT |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
+ "UFOBlock",
+ psMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ DevmemPDumpLoadMem(*psMemDesc,
+ 0,
+ uiUFOBlockSize,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ RGXSetFirmwareAddress(&pFirmwareAddr, *psMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+ *puiSyncPrimVAddr = pFirmwareAddr.ui32Addr;
+ *puiSyncPrimBlockSize = TRUNCATE_64BITS_TO_32BITS(uiUFOBlockSize);
+
+ return PVRSRV_OK;
+
+ DevmemFwFree(*psMemDesc);
+e0:
+ return eError;
+}
+
+/* See device.h for function declaration */
+static IMG_VOID RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
+ DEVMEM_MEMDESC *psMemDesc)
+{
+ /*
+ 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
+ */
+ if (PVRSRVSystemSnoopingOfDeviceCache())
+ {
+ RGXFWIF_KCCB_CMD sFlushInvalCmd;
+ PVRSRV_ERROR eError;
+
+ /* Schedule the SLC flush command ... */
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
+#endif
+ sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
+ sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
+ sFlushInvalCmd.uCmdData.sSLCFlushInvalData.eDM = RGXFWIF_DM_2D; //Covers all of Sidekick
+ sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
+
+ eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sFlushInvalCmd,
+ sizeof(sFlushInvalCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: Failed to schedule SLC flush command with error (%u)", eError));
+ }
+ else
+ {
+ /* Wait for the SLC flush to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXFreeUFOBlock: SLC flush and invalidate aborted with error (%u)", eError));
+ }
+ }
+ }
+
+ RGXUnsetFirmwareAddress(psMemDesc);
+ DevmemFwFree(psMemDesc);
+}
+
+/*
+ DevDeInitRGX
+*/
+PVRSRV_ERROR DevDeInitRGX (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO*)psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+
+ if (!psDevInfo)
+ {
+ /* Can happen if DevInitRGX failed */
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: Null DevInfo"));
+ return PVRSRV_OK;
+ }
+
+ /* Unregister debug request notifiers first as they could depend on anything. */
+ PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hDbgReqNotify);
+
+ /* Cancel notifications to this device */
+ PVRSRVUnregisterCmdCompleteNotify(psDeviceNode->hCmdCompNotify);
+ psDeviceNode->hCmdCompNotify = IMG_NULL;
+
+ /*
+ * De-initialise in reverse order, so stage 2 init is undone first.
+ */
+ if (g_bDevInit2Done)
+ {
+ g_bDevInit2Done = IMG_FALSE;
+
+#if !defined(NO_HARDWARE)
+ (IMG_VOID) OSUninstallDeviceLISR(psDevInfo->pvLISRData);
+ (IMG_VOID) OSUninstallMISR(psDevInfo->pvMISRData);
+ (IMG_VOID) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
+ if (psDevInfo->pvAPMISRData != IMG_NULL)
+ {
+ (IMG_VOID) OSUninstallMISR(psDevInfo->pvAPMISRData);
+ }
+#endif /* !NO_HARDWARE */
+
+ /* Remove the device from the power manager */
+ eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ /* Free DVFS History */
+ if (psDevInfo->psGpuDVFSHistory != IMG_NULL)
+ {
+ OSFreeMem(psDevInfo->psGpuDVFSHistory);
+ psDevInfo->psGpuDVFSHistory = IMG_NULL;
+ }
+
+ /* De-init Freelists/ZBuffers... */
+ OSLockDestroy(psDevInfo->hLockFreeList);
+ OSLockDestroy(psDevInfo->hLockZSBuffer);
+
+ /* De-init HWPerf Ftrace thread resources for the RGX device */
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+ RGXHWPerfFTraceGPUDeInit(psDevInfo);
+#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));
+ return eError;
+ }
+
+ /* UnMap Regs */
+ if (psDevInfo->pvRegsBaseKM != IMG_NULL)
+ {
+#if !defined(NO_HARDWARE)
+ OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32RegSize,
+ 0);
+#endif /* !NO_HARDWARE */
+ psDevInfo->pvRegsBaseKM = IMG_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 = IMG_NULL;
+ }
+#endif
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ RGX_DeInitHeaps(psDevMemoryInfo);
+
+ if (DevmemIsValidExportCookie(&psDevInfo->sRGXFWCodeExportCookie))
+ {
+ /* if the export cookie is valid, the init sequence failed */
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: FW Code Export cookie still valid (should have been unexported at init time)"));
+ DevmemUnexport(psDevInfo->psRGXFWCodeMemDesc, &psDevInfo->sRGXFWCodeExportCookie);
+ }
+
+ if (DevmemIsValidExportCookie(&psDevInfo->sRGXFWDataExportCookie))
+ {
+ /* if the export cookie is valid, the init sequence failed */
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: FW Data Export cookie still valid (should have been unexported at init time)"));
+ DevmemUnexport(psDevInfo->psRGXFWDataMemDesc, &psDevInfo->sRGXFWDataExportCookie);
+ }
+
+ if (DevmemIsValidExportCookie(&psDevInfo->sRGXFWCorememExportCookie))
+ {
+ /* if the export cookie is valid, the init sequence failed */
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitRGX: FW Coremem Export cookie still valid (should have been unexported at init time)"));
+ DevmemUnexport(psDevInfo->psRGXFWCorememMemDesc, &psDevInfo->sRGXFWCorememExportCookie);
+ }
+
+ /*
+ Free the firmware allocations.
+ */
+ RGXFreeFirmware(psDevInfo);
+
+ /*
+ * Clear the mem context create callbacks before destroying the RGX firmware
+ * context to avoid a spurious callback.
+ */
+ psDeviceNode->pfnRegisterMemoryContext = IMG_NULL;
+ psDeviceNode->pfnUnregisterMemoryContext = IMG_NULL;
+
+ if (psDevInfo->psKernelDevmemCtx)
+ {
+ eError = DevmemDestroyContext(psDevInfo->psKernelDevmemCtx);
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+
+ /* destroy the context list locks */
+ OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
+ OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
+ OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
+ OSWRLockDestroy(psDevInfo->hRaytraceCtxListLock);
+ OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
+
+ /* Free the init scripts. */
+ OSFreeMem(psDevInfo->psScripts);
+
+ /* DeAllocate devinfo */
+ OSFreeMem(psDevInfo);
+
+ psDeviceNode->pvDevice = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function RGXDebugRequestNotify
+
+ @Description Dump the debug data for RGX
+
+******************************************************************************/
+static IMG_VOID RGXDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgReqestHandle, IMG_UINT32 ui32VerbLevel)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDbgReqestHandle;
+
+ /* Only action the request if we've fully init'ed */
+ if (g_bDevInit2Done)
+ {
+ RGXDebugRequestProcess(g_pfnDumpDebugPrintf, psDeviceNode->pvDevice, ui32VerbLevel);
+ }
+}
+
+#if defined(PDUMP)
+static
+PVRSRV_ERROR RGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)(psDeviceNode->pvDevice);
+ IMG_UINT32 ui32Idx;
+
+ for (ui32Idx = 0; ui32Idx < RGXFWIF_DM_MAX; ui32Idx++)
+ {
+ psDevInfo->abDumpedKCCBCtlAlready[ui32Idx] = IMG_FALSE;
+ }
+
+
+ return PVRSRV_OK;
+}
+#endif /* PDUMP */
+
+
+static PVRSRV_ERROR RGX_InitHeaps(DEVICE_MEMORY_INFO *psNewMemoryInfo)
+{
+ DEVMEM_HEAP_BLUEPRINT *psDeviceMemoryHeapCursor;
+
+
+ psNewMemoryInfo->psDeviceMemoryHeap = OSAllocMem(sizeof(DEVMEM_HEAP_BLUEPRINT) * RGX_MAX_HEAP_ID);
+ if(psNewMemoryInfo->psDeviceMemoryHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_BLUEPRINT"));
+ goto e0;
+ }
+
+ psDeviceMemoryHeapCursor = psNewMemoryInfo->psDeviceMemoryHeap;
+
+ /************* general ***************/
+ psDeviceMemoryHeapCursor->pszName = RGX_GENERAL_HEAP_IDENT;
+ psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_GENERAL_HEAP_BASE;
+ psDeviceMemoryHeapCursor->uiHeapLength = RGX_GENERAL_HEAP_SIZE;
+ psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
+
+ psDeviceMemoryHeapCursor++;/* advance to the next heap */
+
+ /************* PDS code and data ***************/
+ psDeviceMemoryHeapCursor->pszName = RGX_PDSCODEDATA_HEAP_IDENT;
+ psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_PDSCODEDATA_HEAP_BASE;
+ psDeviceMemoryHeapCursor->uiHeapLength = RGX_PDSCODEDATA_HEAP_SIZE;
+ psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
+
+ psDeviceMemoryHeapCursor++;/* advance to the next heap */
+
+ /************* USC code ***************/
+ psDeviceMemoryHeapCursor->pszName = RGX_USCCODE_HEAP_IDENT;
+ psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_USCCODE_HEAP_BASE;
+ psDeviceMemoryHeapCursor->uiHeapLength = RGX_USCCODE_HEAP_SIZE;
+ psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
+
+ psDeviceMemoryHeapCursor++;/* advance to the next heap */
+
+ /************* TQ 3D Parameters ***************/
+ psDeviceMemoryHeapCursor->pszName = RGX_TQ3DPARAMETERS_HEAP_IDENT;
+ psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_TQ3DPARAMETERS_HEAP_BASE;
+ psDeviceMemoryHeapCursor->uiHeapLength = RGX_TQ3DPARAMETERS_HEAP_SIZE;
+ psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
+
+ psDeviceMemoryHeapCursor++;/* advance to the next heap */
+
+ /************ Tiling Heaps ************/
+ #define INIT_TILING_HEAP(N) \
+ do { \
+ psDeviceMemoryHeapCursor->pszName = RGX_BIF_TILING_HEAP_ ## N ## _IDENT; \
+ psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_BIF_TILING_HEAP_ ## N ## _BASE; \
+ psDeviceMemoryHeapCursor->uiHeapLength = RGX_BIF_TILING_HEAP_SIZE; \
+ psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE(); \
+ psDeviceMemoryHeapCursor++; \
+ } while (0)
+ INIT_TILING_HEAP(1);
+ INIT_TILING_HEAP(2);
+ INIT_TILING_HEAP(3);
+ INIT_TILING_HEAP(4);
+ #undef INIT_TILING_HEAP
+
+ /************* Doppler ***************/
+ psDeviceMemoryHeapCursor->pszName = RGX_DOPPLER_HEAP_IDENT;
+ psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_DOPPLER_HEAP_BASE;
+ psDeviceMemoryHeapCursor->uiHeapLength = RGX_DOPPLER_HEAP_SIZE;
+ psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
+
+ psDeviceMemoryHeapCursor++;/* advance to the next heap */
+
+ /************* Doppler Overflow ***************/
+ psDeviceMemoryHeapCursor->pszName = RGX_DOPPLER_OVERFLOW_HEAP_IDENT;
+ psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_DOPPLER_OVERFLOW_HEAP_BASE;
+ psDeviceMemoryHeapCursor->uiHeapLength = RGX_DOPPLER_OVERFLOW_HEAP_SIZE;
+ psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
+
+ psDeviceMemoryHeapCursor++;/* advance to the next heap */
+
+ /************* HWBRN37200 ***************/
+#if defined(FIX_HW_BRN_37200)
+ psDeviceMemoryHeapCursor->pszName = "HWBRN37200";
+ psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_HWBRN37200_HEAP_BASE;
+ psDeviceMemoryHeapCursor->uiHeapLength = RGX_HWBRN37200_HEAP_SIZE;
+ psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
+
+ psDeviceMemoryHeapCursor++;/* advance to the next heap */
+#endif
+
+ /************* Firmware ***************/
+ psDeviceMemoryHeapCursor->pszName = "Firmware";
+ psDeviceMemoryHeapCursor->sHeapBaseAddr.uiAddr = RGX_FIRMWARE_HEAP_BASE;
+ psDeviceMemoryHeapCursor->uiHeapLength = RGX_FIRMWARE_HEAP_SIZE;
+ psDeviceMemoryHeapCursor->uiLog2DataPageSize = GET_LOG2_PAGESIZE();
+
+ psDeviceMemoryHeapCursor++;/* advance to the next heap */
+
+ /* set the heap count */
+ psNewMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeapCursor - psNewMemoryInfo->psDeviceMemoryHeap);
+
+ PVR_ASSERT(psNewMemoryInfo->ui32HeapCount <= RGX_MAX_HEAP_ID);
+
+ /* the new way: we'll set up 2 heap configs: one will be for Meta
+ only, and has only the firmware heap in it.
+ The remaining one shall be for clients only, and shall have all
+ the other heaps in it */
+
+ psNewMemoryInfo->uiNumHeapConfigs = 2;
+ psNewMemoryInfo->psDeviceMemoryHeapConfigArray = OSAllocMem(sizeof(DEVMEM_HEAP_CONFIG) * psNewMemoryInfo->uiNumHeapConfigs);
+ if (psNewMemoryInfo->psDeviceMemoryHeapConfigArray == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRegisterDevice : Failed to alloc memory for DEVMEM_HEAP_CONFIG"));
+ goto e1;
+ }
+
+ psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].pszName = "Default Heap Configuration";
+ psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].uiNumHeaps = psNewMemoryInfo->ui32HeapCount-1;
+ psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].psHeapBlueprintArray = psNewMemoryInfo->psDeviceMemoryHeap;
+
+ psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].pszName = "Firmware Heap Configuration";
+#if defined(FIX_HW_BRN_37200)
+ psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = 2;
+ psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor-2;
+#else
+ psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = 1;
+ psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor-1;
+#endif
+
+ return PVRSRV_OK;
+e1:
+ OSFreeMem(psNewMemoryInfo->psDeviceMemoryHeap);
+e0:
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+static IMG_VOID RGX_DeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo)
+{
+ OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeapConfigArray);
+ OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeap);
+}
+
+
+/*
+ RGXRegisterDevice
+*/
+PVRSRV_ERROR RGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+
+ /* pdump info about the core */
+ PDUMPCOMMENT("RGX Version Information (KM): %s", RGX_BVNC_KM);
+
+ #if defined(RGX_FEATURE_SYSTEM_CACHE)
+ PDUMPCOMMENT("RGX System Level Cache is present");
+ #endif /* RGX_FEATURE_SYSTEM_CACHE */
+
+ PDUMPCOMMENT("RGX Initialisation (Part 1)");
+
+ /*********************
+ * Device node setup *
+ *********************/
+ /* Setup static data and callbacks on the device agnostic device node */
+ psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
+ psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
+#if defined(PDUMP)
+ psDeviceNode->sDevId.pszPDumpRegName = RGX_PDUMPREG_NAME;
+
+ psDeviceNode->sDevId.pszPDumpDevName = PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]);
+ psDeviceNode->pfnPDumpInitDevice = &RGXResetPDump;
+#endif /* PDUMP */
+
+ psDeviceNode->eHealthStatus = PVRSRV_DEVICE_HEALTH_STATUS_OK;
+
+#if defined(SUPPORT_MEMORY_TILING)
+ psDeviceNode->pfnAllocMemTilingRange = RGX_AllocMemTilingRange;
+ psDeviceNode->pfnFreeMemTilingRange = RGX_FreeMemTilingRange;
+#endif
+
+ /* Configure MMU specific stuff */
+ RGXMMUInit_Register(psDeviceNode);
+
+ psDeviceNode->pfnMMUCacheInvalidate = RGXMMUCacheInvalidate;
+
+ psDeviceNode->pfnSLCCacheInvalidateRequest = RGXSLCCacheInvalidateRequest;
+
+ /* 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 */
+ psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
+ psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
+
+ /* Register callbacks for Unified Fence Objects */
+ psDeviceNode->pfnAllocUFOBlock = RGXAllocUFOBlock;
+ psDeviceNode->pfnFreeUFOBlock = RGXFreeUFOBlock;
+
+ /* Register callback for dumping debug info */
+ PVRSRVRegisterDbgRequestNotify(&psDeviceNode->hDbgReqNotify, &RGXDebugRequestNotify, DEBUG_REQUEST_RGX, psDeviceNode);
+
+ /* Register callback for checking the device's health */
+ psDeviceNode->pfnUpdateHealthStatus = RGXUpdateHealthStatus;
+
+ /* 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;
+
+
+ /*********************
+ * Device info setup *
+ *********************/
+ /* Allocate device control block */
+ psDevInfo = OSAllocMem(sizeof(*psDevInfo));
+ if (psDevInfo == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitRGXPart1 : Failed to alloc memory for DevInfo"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet (psDevInfo, 0, sizeof(*psDevInfo));
+
+ /* 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->hRaytraceCtxListLock));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create raytrace context list lock", __func__));
+ goto e3;
+ }
+
+ eError = OSWRLockCreate(&(psDevInfo->hMemoryCtxListLock));
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create memory context list lock", __func__));
+ goto e4;
+ }
+
+ dllist_init(&(psDevInfo->sRenderCtxtListHead));
+ dllist_init(&(psDevInfo->sComputeCtxtListHead));
+ dllist_init(&(psDevInfo->sTransferCtxtListHead));
+ dllist_init(&(psDevInfo->sRaytraceCtxtListHead));
+
+ dllist_init(&(psDevInfo->sCommonCtxtListHead));
+ psDevInfo->ui32CommonCtxtCurrentID = 1;
+
+ psDeviceNode->pvDevice = psDevInfo;
+ dllist_init(&psDevInfo->sMemoryContextList);
+
+ /* Allocate space for scripts. */
+ psDevInfo->psScripts = OSAllocMem(sizeof(*psDevInfo->psScripts));
+ if (!psDevInfo->psScripts)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ PVR_LOGG_IF_ERROR(PVRSRV_ERROR_OUT_OF_MEMORY, "OSAllocMem", e5);
+ }
+
+ /* Setup static data and callbacks on the device specific device info */
+ psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
+ psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
+ psDevInfo->psDeviceNode = psDeviceNode;
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDevMemoryInfo->ui32AddressSpaceSizeLog2 = RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS;
+ psDevInfo->pvDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+ /* flags, backing store details to be specified by system */
+ psDevMemoryInfo->ui32Flags = 0;
+
+ eError = RGX_InitHeaps(psDevMemoryInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_LOGG_IF_ERROR(eError, "RGX_InitHeaps", e6);
+ }
+
+ return PVRSRV_OK;
+
+e6:
+ OSFreeMem(psDevInfo->psScripts);
+ psDevInfo->psScripts = NULL;
+e5:
+ OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
+e4:
+ OSWRLockDestroy(psDevInfo->hRaytraceCtxListLock);
+e3:
+ OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
+e2:
+ OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
+e1:
+ OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
+e0:
+ psDeviceNode->pvDevice = NULL;
+ OSFreeMem(psDevInfo);
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*!
+*******************************************************************************
+
+ @Function RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver
+
+ @Description
+
+ Validate the FW build options against KM driver build options (KM build options only)
+
+ Following check is reduntant, 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 psRGXFWInit - FW init data
+
+ @Return PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver(RGXFWIF_INIT *psRGXFWInit)
+{
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32BuildOptions, ui32BuildOptionsFWKMPart, ui32BuildOptionsMismatch;
+
+ if (psRGXFWInit == IMG_NULL)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ ui32BuildOptions = (RGX_BUILD_OPTIONS_KM);
+
+ ui32BuildOptionsFWKMPart = psRGXFWInit->sRGXCompChecks.ui32BuildOptions & RGX_BUILD_OPTIONS_MASK_KM;
+
+ if (ui32BuildOptions != ui32BuildOptionsFWKMPart)
+ {
+ ui32BuildOptionsMismatch = ui32BuildOptions ^ ui32BuildOptionsFWKMPart;
+ 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_km.h",
+ ui32BuildOptions & ui32BuildOptionsMismatch ));
+ }
+
+ 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_km.h",
+ ui32BuildOptionsFWKMPart & ui32BuildOptionsMismatch ));
+ }
+ return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware and KM driver build options match. [ OK ]"));
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+
+ @Function RGXDevInitCompatCheck_BuildOptions_FWAgainstClient
+
+ @Description
+
+ Validate the FW build options against client build options (KM and non-KM)
+
+ @Input psDevInfo - device info
+ @Input psRGXFWInit - FW init data
+ @Input ui32ClientBuildOptions - client build options flags
+
+ @Return PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_BuildOptions_FWAgainstClient(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_INIT *psRGXFWInit,
+ IMG_UINT32 ui32ClientBuildOptions)
+{
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32BuildOptionsMismatch;
+ IMG_UINT32 ui32BuildOptionsFW;
+#endif
+#if defined(PDUMP)
+ PVRSRV_ERROR eError;
+#endif
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Compatibility check: client and FW build options");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+ offsetof(RGXFWIF_COMPCHECKS, ui32BuildOptions),
+ ui32ClientBuildOptions,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ return eError;
+ }
+#endif
+
+#if !defined(NO_HARDWARE)
+ if (psRGXFWInit == IMG_NULL)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ ui32BuildOptionsFW = psRGXFWInit->sRGXCompChecks.ui32BuildOptions;
+
+ if (ui32ClientBuildOptions != ui32BuildOptionsFW)
+ {
+ ui32BuildOptionsMismatch = ui32ClientBuildOptions ^ ui32BuildOptionsFW;
+ 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, "RGXDevInitCompatCheck: Firmware and client 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 psRGXFWInit - FW init data
+
+ @Return PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_INIT *psRGXFWInit)
+{
+#if defined(PDUMP)||(!defined(NO_HARDWARE))
+ IMG_UINT32 ui32DDKVersion;
+ PVRSRV_ERROR eError;
+
+ ui32DDKVersion = PVRVERSION_PACK(PVRVERSION_MAJ, PVRVERSION_MIN);
+#endif
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Compatibility check: KM driver and FW DDK version");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, 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 psRGXFWIfInitMemDesc (%d)", eError));
+ return eError;
+ }
+#endif
+
+#if !defined(NO_HARDWARE)
+ if (psRGXFWInit == IMG_NULL)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ if (psRGXFWInit->sRGXCompChecks.ui32DDKVersion != ui32DDKVersion)
+ {
+ PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible driver DDK revision (%u.%u) / Firmware DDK revision (%u.%u).",
+ PVRVERSION_MAJ, PVRVERSION_MIN,
+ PVRVERSION_UNPACK_MAJ(psRGXFWInit->sRGXCompChecks.ui32DDKVersion),
+ PVRVERSION_UNPACK_MIN(psRGXFWInit->sRGXCompChecks.ui32DDKVersion)));
+ eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+ PVR_DBG_BREAK;
+ return eError;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: driver DDK revision (%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 psRGXFWInit - FW init data
+
+ @Return PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_INIT *psRGXFWInit)
+{
+#if defined(PDUMP)||(!defined(NO_HARDWARE))
+ IMG_UINT32 ui32DDKBuild;
+ PVRSRV_ERROR eError;
+
+ ui32DDKBuild = PVRVERSION_BUILD;
+#endif
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Compatibility check: KM driver and FW DDK build");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, 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 psRGXFWIfInitMemDesc (%d)", eError));
+ return eError;
+ }
+#endif
+
+#if !defined(NO_HARDWARE)
+ if (psRGXFWInit == IMG_NULL)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ if (psRGXFWInit->sRGXCompChecks.ui32DDKBuild != ui32DDKBuild)
+ {
+ PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible driver DDK build (%d) / Firmware DDK build (%d).",
+ ui32DDKBuild, psRGXFWInit->sRGXCompChecks.ui32DDKBuild));
+ eError = PVRSRV_ERROR_DDK_BUILD_MISMATCH;
+ PVR_DBG_BREAK;
+ return eError;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: driver DDK build (%d) and Firmware DDK build (%d) match. [ OK ]",
+ ui32DDKBuild, psRGXFWInit->sRGXCompChecks.ui32DDKBuild));
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+
+ @Function RGXDevInitCompatCheck_BVNC_FWAgainstDriver
+
+ @Description
+
+ Validate FW BVNC against driver BVNC
+
+ @Input psDevInfo - device info
+ @Input psRGXFWInit - FW init data
+
+ @Return PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_INIT *psRGXFWInit)
+{
+#if defined(PDUMP)
+ IMG_UINT32 i;
+#endif
+#if !defined(NO_HARDWARE)
+ IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
+#endif
+#if defined(PDUMP)||(!defined(NO_HARDWARE))
+ RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
+ PVRSRV_ERROR eError;
+
+ rgx_bvnc_packed(&sBVNC.ui32BNC, sBVNC.aszV, sBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C);
+#endif
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (struct version)");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, 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 psRGXFWIfInitMemDesc (%d)", eError));
+ }
+
+ PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (maxlen)");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+ offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
+ offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32VLenMax),
+ sBVNC.ui32VLenMax,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ }
+
+ PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (BNC part)");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+ offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
+ offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32BNC),
+ sBVNC.ui32BNC,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ }
+
+ for (i = 0; i < sBVNC.ui32VLenMax; i += sizeof(IMG_UINT32))
+ {
+ PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (V part)");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+ offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
+ offsetof(RGXFWIF_COMPCHECKS_BVNC, aszV) +
+ i,
+ *((IMG_UINT32 *)(sBVNC.aszV + i)),
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ }
+ }
+#endif
+
+#if !defined(NO_HARDWARE)
+ if (psRGXFWInit == IMG_NULL)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ RGX_BVNC_EQUAL(sBVNC, psRGXFWInit->sRGXCompChecks.sFWBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
+
+ if (!bCompatibleAll)
+ {
+ if (!bCompatibleVersion)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%d) and firmware (%d).",
+ __FUNCTION__,
+ sBVNC.ui32LayoutVersion,
+ psRGXFWInit->sRGXCompChecks.sFWBVNC.ui32LayoutVersion));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ return eError;
+ }
+
+ if (!bCompatibleLenMax)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible V maxlen of driver (%d) and firmware (%d).",
+ __FUNCTION__,
+ sBVNC.ui32VLenMax,
+ psRGXFWInit->sRGXCompChecks.sFWBVNC.ui32VLenMax));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ return eError;
+ }
+
+ if (!bCompatibleBNC)
+ {
+ PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in KM driver BNC (%d._.%d.%d) and Firmware BNC (%d._.%d.%d)",
+ RGX_BVNC_PACKED_EXTR_B(sBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sBVNC),
+ RGX_BVNC_PACKED_EXTR_B(psRGXFWInit->sRGXCompChecks.sFWBVNC),
+ RGX_BVNC_PACKED_EXTR_N(psRGXFWInit->sRGXCompChecks.sFWBVNC),
+ RGX_BVNC_PACKED_EXTR_C(psRGXFWInit->sRGXCompChecks.sFWBVNC)));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ return eError;
+ }
+
+ if (!bCompatibleV)
+ {
+ PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in KM driver BVNC (%d.%s.%d.%d) and Firmware BVNC (%d.%s.%d.%d)",
+ RGX_BVNC_PACKED_EXTR_B(sBVNC),
+ RGX_BVNC_PACKED_EXTR_V(sBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sBVNC),
+ RGX_BVNC_PACKED_EXTR_B(psRGXFWInit->sRGXCompChecks.sFWBVNC),
+ RGX_BVNC_PACKED_EXTR_V(psRGXFWInit->sRGXCompChecks.sFWBVNC),
+ RGX_BVNC_PACKED_EXTR_N(psRGXFWInit->sRGXCompChecks.sFWBVNC),
+ RGX_BVNC_PACKED_EXTR_C(psRGXFWInit->sRGXCompChecks.sFWBVNC)));
+ 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 psRGXFWInit - FW init data
+
+ @Return PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+#if ((!defined(NO_HARDWARE))&&(!defined(EMULATOR)))
+#define TARGET_SILICON /* definition for everything that is not emu and not nohw configuration */
+#endif
+
+#if defined(FIX_HW_BRN_38835)
+#define COMPAT_BVNC_MASK_B
+#define COMPAT_BVNC_MASK_V
+#endif
+
+static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_INIT *psRGXFWInit)
+{
+#if defined(PDUMP) || defined(TARGET_SILICON)
+ IMG_UINT32 ui32MaskBNC = RGX_BVNC_PACK_MASK_B |
+ RGX_BVNC_PACK_MASK_N |
+ RGX_BVNC_PACK_MASK_C;
+
+ IMG_UINT32 bMaskV = IMG_FALSE;
+
+ PVRSRV_ERROR eError;
+ RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sSWBVNC);
+#endif
+
+#if defined(TARGET_SILICON)
+ RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sHWBVNC);
+ IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV;
+#endif
+
+#if defined(PDUMP) || defined(TARGET_SILICON)
+
+#if defined(COMPAT_BVNC_MASK_B)
+ ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_B;
+#endif
+#if defined(COMPAT_BVNC_MASK_V)
+ bMaskV = IMG_TRUE;
+#endif
+#if defined(COMPAT_BVNC_MASK_N)
+ ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_N;
+#endif
+#if defined(COMPAT_BVNC_MASK_C)
+ ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
+#endif
+
+ rgx_bvnc_packed(&sSWBVNC.ui32BNC, sSWBVNC.aszV, sSWBVNC.ui32VLenMax, RGX_BVNC_KM_B, RGX_BVNC_KM_V_ST, RGX_BVNC_KM_N, RGX_BVNC_KM_C);
+
+#if defined(FIX_HW_BRN_38344)
+ if (RGX_BVNC_KM_C >= 10)
+ {
+ ui32MaskBNC &= ~RGX_BVNC_PACK_MASK_C;
+ }
+#endif
+
+ if ((ui32MaskBNC != (RGX_BVNC_PACK_MASK_B | RGX_BVNC_PACK_MASK_N | RGX_BVNC_PACK_MASK_C)) || bMaskV)
+ {
+ PVR_LOG(("Compatibility checks: Ignoring fields: '%s%s%s%s' of HW BVNC.",
+ ((!(ui32MaskBNC & RGX_BVNC_PACK_MASK_B))?("B"):("")),
+ ((bMaskV)?("V"):("")),
+ ((!(ui32MaskBNC & RGX_BVNC_PACK_MASK_N))?("N"):("")),
+ ((!(ui32MaskBNC & RGX_BVNC_PACK_MASK_C))?("C"):(""))));
+ }
+#endif
+
+#if defined(EMULATOR)
+ PVR_LOG(("Compatibility checks for emu target: Ignoring HW BVNC checks."));
+#endif
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Compatibility check: Layout version of compchecks struct");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+ offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
+ offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32LayoutVersion),
+ sSWBVNC.ui32LayoutVersion,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ return eError;
+ }
+
+ PDUMPCOMMENT("Compatibility check: HW V max len and FW V max len");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+ offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
+ offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32VLenMax),
+ sSWBVNC.ui32VLenMax,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ return eError;
+ }
+
+ if (ui32MaskBNC != 0)
+ {
+ PDUMPIF("DISABLE_HWBNC_CHECK");
+ PDUMPELSE("DISABLE_HWBNC_CHECK");
+ PDUMPCOMMENT("Compatibility check: HW BNC and FW BNC");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+ offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
+ offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32BNC),
+ sSWBVNC.ui32BNC,
+ ui32MaskBNC,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ return eError;
+ }
+ PDUMPFI("DISABLE_HWBNC_CHECK");
+ }
+ if (!bMaskV)
+ {
+ IMG_UINT32 i;
+ PDUMPIF("DISABLE_HWV_CHECK");
+ PDUMPELSE("DISABLE_HWV_CHECK");
+ for (i = 0; i < sSWBVNC.ui32VLenMax; i += sizeof(IMG_UINT32))
+ {
+ PDUMPCOMMENT("Compatibility check: HW V and FW V");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+ offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
+ offsetof(RGXFWIF_COMPCHECKS_BVNC, aszV) +
+ i,
+ *((IMG_UINT32 *)(sSWBVNC.aszV + i)),
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ return eError;
+ }
+ }
+ PDUMPFI("DISABLE_HWV_CHECK");
+ }
+#endif
+
+#if defined(TARGET_SILICON)
+ if (psRGXFWInit == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ sHWBVNC = psRGXFWInit->sRGXCompChecks.sHWBVNC;
+
+ sHWBVNC.ui32BNC &= ui32MaskBNC;
+ sSWBVNC.ui32BNC &= ui32MaskBNC;
+
+ if (bMaskV)
+ {
+ sHWBVNC.aszV[0] = '\0';
+ sSWBVNC.aszV[0] = '\0';
+ }
+
+ RGX_BVNC_EQUAL(sSWBVNC, sHWBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleLenMax, bCompatibleBNC, bCompatibleV);
+
+#if defined(FIX_HW_BRN_42480)
+ if (!bCompatibleAll && bCompatibleVersion)
+ {
+ if ((RGX_BVNC_PACKED_EXTR_B(sSWBVNC) == 1) &&
+ !(OSStringCompare(RGX_BVNC_PACKED_EXTR_V(sSWBVNC),"76")) &&
+ (RGX_BVNC_PACKED_EXTR_N(sSWBVNC) == 4) &&
+ (RGX_BVNC_PACKED_EXTR_C(sSWBVNC) == 6))
+ {
+ if ((RGX_BVNC_PACKED_EXTR_B(sHWBVNC) == 1) &&
+ !(OSStringCompare(RGX_BVNC_PACKED_EXTR_V(sHWBVNC),"69")) &&
+ (RGX_BVNC_PACKED_EXTR_N(sHWBVNC) == 4) &&
+ (RGX_BVNC_PACKED_EXTR_C(sHWBVNC) == 4))
+ {
+ bCompatibleBNC = IMG_TRUE;
+ bCompatibleLenMax = IMG_TRUE;
+ bCompatibleV = IMG_TRUE;
+ bCompatibleAll = IMG_TRUE;
+ }
+ }
+ }
+#endif
+
+ if (!bCompatibleAll)
+ {
+ if (!bCompatibleVersion)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of HW (%d) and FW (%d).",
+ __FUNCTION__,
+ sHWBVNC.ui32LayoutVersion,
+ sSWBVNC.ui32LayoutVersion));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ return eError;
+ }
+
+ if (!bCompatibleLenMax)
+ {
+ PVR_LOG(("(FAIL) %s: Incompatible V maxlen of HW (%d) and FW (%d).",
+ __FUNCTION__,
+ sHWBVNC.ui32VLenMax,
+ sSWBVNC.ui32VLenMax));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ return eError;
+ }
+
+ if (!bCompatibleBNC)
+ {
+ PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible HW BNC (%d._.%d.%d) and FW BNC (%d._.%d.%d).",
+ RGX_BVNC_PACKED_EXTR_B(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_B(sSWBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sSWBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sSWBVNC)));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ return eError;
+ }
+
+ if (!bCompatibleV)
+ {
+ PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible HW BVNC (%d.%s.%d.%d) and FW BVNC (%d.%s.%d.%d).",
+ RGX_BVNC_PACKED_EXTR_B(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_V(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_B(sSWBVNC),
+ RGX_BVNC_PACKED_EXTR_V(sSWBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sSWBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sSWBVNC)));
+ eError = PVRSRV_ERROR_BVNC_MISMATCH;
+ return eError;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: HW BVNC (%d.%s.%d.%d) and FW BVNC (%d.%s.%d.%d) match. [ OK ]",
+ RGX_BVNC_PACKED_EXTR_B(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_V(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sHWBVNC),
+ RGX_BVNC_PACKED_EXTR_B(sSWBVNC),
+ RGX_BVNC_PACKED_EXTR_V(sSWBVNC),
+ RGX_BVNC_PACKED_EXTR_N(sSWBVNC),
+ RGX_BVNC_PACKED_EXTR_C(sSWBVNC)));
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+
+ @Function RGXDevInitCompatCheck_METACoreVersion_AgainstDriver
+
+ @Description
+
+ Validate HW META version against driver META version
+
+ @Input psDevInfo - device info
+ @Input psRGXFWInit - FW init data
+
+ @Return PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+
+static PVRSRV_ERROR RGXDevInitCompatCheck_METACoreVersion_AgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_INIT *psRGXFWInit)
+{
+#if defined(PDUMP)||(!defined(NO_HARDWARE))
+ PVRSRV_ERROR eError;
+#endif
+
+#if defined(PDUMP)
+ PDUMPIF("DISABLE_HWMETA_CHECK");
+ PDUMPELSE("DISABLE_HWMETA_CHECK");
+ PDUMPCOMMENT("Compatibility check: KM driver and HW META version");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, sRGXCompChecks) +
+ offsetof(RGXFWIF_COMPCHECKS, ui32METAVersion),
+ RGX_CR_META_CORE_ID_VALUE,
+ 0xffffffff,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ return eError;
+ }
+ PDUMPFI("DISABLE_HWMETA_CHECK");
+#endif
+
+#if !defined(NO_HARDWARE)
+ if (psRGXFWInit == IMG_NULL)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ if (psRGXFWInit->sRGXCompChecks.ui32METAVersion != RGX_CR_META_CORE_ID_VALUE)
+ {
+ PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible driver META version (%d) / HW META version (%d).",
+ RGX_CR_META_CORE_ID_VALUE, psRGXFWInit->sRGXCompChecks.ui32METAVersion));
+ eError = PVRSRV_ERROR_META_MISMATCH;
+ PVR_DBG_BREAK;
+ return eError;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: driver META version (%d) and HW META version (%d) match. [ OK ]",
+ RGX_CR_META_CORE_ID_VALUE, psRGXFWInit->sRGXCompChecks.ui32METAVersion));
+ }
+#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, IMG_UINT32 ui32ClientBuildOptions)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_INIT *psRGXFWInit = IMG_NULL;
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32RegValue;
+#endif
+
+ /* Ensure it's a RGX device */
+ if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_RGX)
+ {
+ PVR_LOG(("(FAIL) %s: Device not of type RGX", __FUNCTION__));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto chk_exit;
+ }
+
+ /*
+ * Retrieve the FW information
+ */
+
+#if !defined(NO_HARDWARE)
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc,
+ (IMG_VOID **)&psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Failed to acquire kernel fw compatibility check info (%u)",
+ __FUNCTION__, eError));
+ return eError;
+ }
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(*((volatile IMG_BOOL *)&psRGXFWInit->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();
+
+ ui32RegValue = 0;
+ eError = RGXReadMETAReg(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)",
+ __FUNCTION__, 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)",
+ __FUNCTION__, psRGXFWInit->sRGXCompChecks.bUpdated, eError));
+ goto chk_exit;
+ }
+
+ if (!*((volatile IMG_BOOL *)&psRGXFWInit->sRGXCompChecks.bUpdated))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT;
+ PVR_DPF((PVR_DBG_ERROR,"%s: Missing compatibility info from FW (%u)",
+ __FUNCTION__, eError));
+ goto chk_exit;
+ }
+#endif
+
+ eError = RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver(psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ goto chk_exit;
+ }
+
+ eError = RGXDevInitCompatCheck_BuildOptions_FWAgainstClient(psDevInfo, psRGXFWInit, ui32ClientBuildOptions);
+ if (eError != PVRSRV_OK)
+ {
+ goto chk_exit;
+ }
+
+ eError = RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(psDevInfo, psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ goto chk_exit;
+ }
+
+ eError = RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver(psDevInfo, psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ goto chk_exit;
+ }
+
+ eError = RGXDevInitCompatCheck_BVNC_FWAgainstDriver(psDevInfo, psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ goto chk_exit;
+ }
+
+ eError = RGXDevInitCompatCheck_BVNC_HWAgainstDriver(psDevInfo, psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ goto chk_exit;
+ }
+
+ eError = RGXDevInitCompatCheck_METACoreVersion_AgainstDriver(psDevInfo, psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ goto chk_exit;
+ }
+
+ eError = PVRSRV_OK;
+chk_exit:
+#if !defined(NO_HARDWARE)
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
+#endif
+ return eError;
+}
+
+#define MAKESTRING(x) #x
+#define TOSTRING(x) MAKESTRING(x)
+
+
+
+
+
+static PVRSRV_ERROR
+ValidateFWImage(
+ IMG_CHAR *pcFWImgDestAddr,
+ IMG_CHAR *pcFWImgSrcAddr,
+ IMG_SIZE_T uiFWImgLen,
+ IMG_CHAR *pcFWImgSigAddr,
+ IMG_UINT64 ui64FWSigLen)
+{
+#if defined(DEBUG)
+ if(OSMemCmp(pcFWImgDestAddr, pcFWImgSrcAddr, uiFWImgLen) != 0)
+ {
+ return PVRSRV_ERROR_INIT_TDMETACODE_PAGES_FAIL;
+ }
+
+ PVR_UNREFERENCED_PARAMETER(pcFWImgSigAddr);
+ PVR_UNREFERENCED_PARAMETER(ui64FWSigLen);
+#else
+ PVR_UNREFERENCED_PARAMETER(pcFWImgDestAddr);
+ PVR_UNREFERENCED_PARAMETER(uiFWImgLen);
+ PVR_UNREFERENCED_PARAMETER(pcFWImgSigAddr);
+ PVR_UNREFERENCED_PARAMETER(ui64FWSigLen);
+#endif
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PMRCopy(PMR *psDstPMR, PMR *psSrcPMR, IMG_SIZE_T uiMaxCopyLen)
+{
+ IMG_CHAR acBuf[512];
+ IMG_UINT64 uiBytesCopied;
+ PVRSRV_ERROR eStatus;
+
+ uiBytesCopied = 0;
+ while(uiBytesCopied < uiMaxCopyLen)
+ {
+ IMG_SIZE_T uiRead, uiWritten;
+ IMG_SIZE_T uiCopyAmt;
+ uiCopyAmt = sizeof(acBuf) > uiMaxCopyLen ? uiMaxCopyLen : sizeof(acBuf);
+ eStatus = PMR_ReadBytes(psSrcPMR,
+ uiBytesCopied,
+ acBuf,
+ uiCopyAmt,
+ &uiRead);
+ if(eStatus != PVRSRV_OK)
+ {
+ return eStatus;
+ }
+ eStatus = PMR_WriteBytes(psDstPMR,
+ uiBytesCopied,
+ acBuf,
+ uiCopyAmt,
+ &uiWritten);
+ if(eStatus != PVRSRV_OK)
+ {
+ return eStatus;
+ }
+ PVR_ASSERT(uiRead == uiWritten);
+ PVR_ASSERT(uiRead == uiCopyAmt);
+ uiBytesCopied += uiCopyAmt;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXInitLoadFWImageKM(
+ PMR *psFWImgDestPMR,
+ PMR *psFWImgSrcPMR,
+ IMG_UINT64 ui64FWImgLen,
+ PMR *psFWImgSigPMR,
+ IMG_UINT64 ui64FWSigLen)
+{
+ IMG_CHAR *pcFWImgSigAddr, *pcFWImgDestAddr, *pcFWImgSrcAddr;
+ IMG_HANDLE hFWImgSigHdl, hFWImgDestHdl, hFWImgSrcHdl;
+ IMG_SIZE_T uiLen;
+ PVRSRV_ERROR eStatus;
+
+ /* The purpose of this function is to do the following:
+ - copy the data contained in psFWImgSrcPMR into psFWImgDestPMR
+ - use the data contained in psFWImgSigPMR to validate the contents of psFWImgDestPMR
+
+ This is a functional placeholder that is meant to be overridden when actually using
+ the protected META code feature. As a result, normally, the memory backed by
+ psFWImgDestPMR will not be read/writeable from this layer. Thus the operation of
+ actually doing the copy and verify must be handled in a mode with more privilege,
+ typically a hypervisor.
+
+ Because psFWImgSrcPMR and psFWImgSigPMR are normal OS-memory controlled PMR's, it
+ should be sufficient to acquire their kernel mappings and pass the pointers to
+ their mapped addressed into the hypervisor. However, since psFWImgDestPMR references
+ a region of memory that would typically be allocated (and writeable) by a hypervisor,
+ it will be necessary to pass the psFWImgDestPMR->pvFlavourData (or a field contained
+ within it) to the hypervisor to identify the region of memory to copy to and validate.
+
+ In the example function provided below, the following things happen:
+ - kernel mappings are acquired for the destination and signature PMRs
+ - a copy is done using the PMR_ReadBytes / PMR_WriteBytes callback functionality in
+ the PMR layer
+ - a validation is done by reading back the destination buffer and comparing it against
+ the source buffer.
+
+ c.f. a real implementation, where the following things would likely happen:
+ - kernel mappings are acquired for the source and signature PMRs
+ - the source/signature mapped addresses and lengths, and psFWImgDestPMR->pvFlavourData
+ are passed into the hypervisor to do the copy/validate.
+ */
+
+ eStatus = PMRAcquireKernelMappingData(psFWImgDestPMR,
+ 0,
+ 0,
+ (IMG_VOID **) &pcFWImgDestAddr,
+ &uiLen,
+ &hFWImgDestHdl);
+ if(eStatus != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Acquire mapping for dest failed (%u)", eStatus));
+ goto error;
+ }
+ if(ui64FWImgLen > uiLen)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: PMR dst len (%llu) > mapped len (%llu)",
+ ui64FWImgLen, (unsigned long long)uiLen));
+ goto error;
+ }
+
+ eStatus = PMRAcquireKernelMappingData(psFWImgSrcPMR,
+ 0,
+ 0,
+ (IMG_VOID **) &pcFWImgSrcAddr,
+ &uiLen,
+ &hFWImgSrcHdl);
+ if(eStatus != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Acquire mapping for src failed (%u)", eStatus));
+ goto error;
+ }
+ if(ui64FWImgLen > uiLen)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: PMR dst len (%llu) > mapped len (%llu)",
+ ui64FWImgLen, (unsigned long long)uiLen));
+ goto error;
+ }
+
+ eStatus = PMRAcquireKernelMappingData(psFWImgSigPMR,
+ 0,
+ 0,
+ (IMG_VOID **) &pcFWImgSigAddr,
+ &uiLen,
+ &hFWImgSigHdl);
+ if(eStatus != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Acquire mapping for sig failed (%u)", eStatus));
+ goto error;
+ }
+ if(ui64FWSigLen > uiLen)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: sig len (%llu) > mapped len (%llu)",
+ ui64FWSigLen, (unsigned long long)uiLen));
+ goto error;
+ }
+
+ /* Copy the firmware image from the intermediate buffer to the real firmware memory allocation. */
+ PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVDebugMiscInitFWImageKM: copying %llu bytes from PMR %p to PMR %p",
+ ui64FWImgLen, psFWImgSrcPMR, psFWImgDestPMR));
+ PMRCopy(psFWImgDestPMR, psFWImgSrcPMR, TRUNCATE_64BITS_TO_SIZE_T(ui64FWImgLen));
+
+ /* validate the firmware image after it has been copied into place */
+ eStatus = ValidateFWImage(pcFWImgDestAddr, pcFWImgSrcAddr, TRUNCATE_64BITS_TO_SIZE_T(ui64FWImgLen), pcFWImgSigAddr, ui64FWSigLen);
+ if(eStatus != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Signature check failed"));
+ goto error;
+ }
+
+ eStatus = PMRReleaseKernelMappingData(psFWImgDestPMR,
+ hFWImgDestHdl);
+ if(eStatus != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Release mapping for dest failed (%u)", eStatus));
+ goto error;
+ }
+
+ eStatus = PMRReleaseKernelMappingData(psFWImgSrcPMR,
+ hFWImgSrcHdl);
+ if(eStatus != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Release mapping for src failed (%u)", eStatus));
+ goto error;
+ }
+
+ eStatus = PMRReleaseKernelMappingData(psFWImgSigPMR,
+ hFWImgSigHdl);
+ if(eStatus != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDebugMiscInitFWImageKM: Release mapping for sig failed (%u)", eStatus));
+ goto error;
+ }
+
+ return PVRSRV_OK;
+
+error:
+ return PVRSRV_ERROR_INIT_TDMETACODE_PAGES_FAIL;
+}
+
+
+
+/*************************************************************************/ /*!
+@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)
+ IMG_CHAR pszFormatString[] = "Rogue Version: %d.%s.%d.%d (SW)";
+#else
+ IMG_CHAR pszFormatString[] = "Rogue Version: %d.%s.%d.%d (HW)";
+#endif
+ IMG_SIZE_T uiStringLength;
+
+ if (psDeviceNode == NULL || ppszVersionString == NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uiStringLength = OSStringLength(pszFormatString);
+ uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_B));
+ uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_V));
+ uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_N));
+ uiStringLength += OSStringLength(TOSTRING(RGX_BVNC_KM_C));
+
+ *ppszVersionString = OSAllocZMem(uiStringLength * sizeof(IMG_CHAR));
+ if (*ppszVersionString == NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSSNPrintf(*ppszVersionString, uiStringLength, pszFormatString,
+ RGX_BVNC_KM_B, TOSTRING(RGX_BVNC_KM_V), RGX_BVNC_KM_N, RGX_BVNC_KM_C);
+
+ 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;
+}
+
+
+/**************************************************************************/ /*!
+@Function RGXSoftReset
+@Description Resets some modules of the RGX device
+@Input psDeviceNode Device node
+@Output ui64ResetValue a mask for which each bit set correspond
+ to a module to reset.
+@Return PVRSRV_ERROR
+*/ /***************************************************************************/
+static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT64 ui64ResetValue)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+
+ PVR_ASSERT(psDeviceNode != NULL);
+ PVR_ASSERT(psDeviceNode->pvDevice != NULL);
+
+ if ((ui64ResetValue & RGX_CR_SOFT_RESET_MASKFULL) != ui64ResetValue)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* the device info */
+ psDevInfo = psDeviceNode->pvDevice;
+
+ /* Set in soft-reset */
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, ui64ResetValue);
+
+ /* Read soft-reset to fence previos write in order to clear the SOCIF pipeline */
+ (IMG_VOID) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
+
+ return PVRSRV_OK;
+}
+
+
+/******************************************************************************
+ End of file (rgxinit.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxinit.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxinit.h
new file mode 100644
index 000000000000..4e63c9849953
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxinit.h
@@ -0,0 +1,196 @@
+/*************************************************************************/ /*!
+@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 "pvrsrv_error.h"
+#include "img_types.h"
+#include "rgxscript.h"
+#include "device.h"
+#include "rgxdevice.h"
+
+
+/*!
+*******************************************************************************
+
+ @Function PVRSRVRGXInitDevPart2KM
+
+ @Description
+
+ Second part of server-side RGX initialisation
+
+ @Input pvDeviceNode - device node
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRGXInitDevPart2KM (PVRSRV_DEVICE_NODE *psDeviceNode,
+ RGX_INIT_COMMAND *psInitScript,
+ RGX_INIT_COMMAND *psDbgScript,
+ RGX_INIT_COMMAND *psDbgBusScript,
+ RGX_INIT_COMMAND *psDeinitScript,
+ IMG_UINT32 ui32KernelCatBaseIdReg,
+ IMG_UINT32 ui32KernelCatBaseId,
+ IMG_UINT32 ui32KernelCatBaseReg,
+ IMG_UINT32 ui32KernelCatBaseWordSize,
+ IMG_UINT32 ui32KernelCatBaseAlignShift,
+ IMG_UINT32 ui32KernelCatBaseShift,
+ IMG_UINT64 ui64KernelCatBaseMask,
+ IMG_UINT32 ui32DeviceFlags,
+ RGX_ACTIVEPM_CONF eActivePMConf,
+ DEVMEM_EXPORTCOOKIE *psFWCodeAllocServerExportCookie,
+ DEVMEM_EXPORTCOOKIE *psFWDataAllocServerExportCookie,
+ DEVMEM_EXPORTCOOKIE *psFWCorememAllocServerExportCookie);
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXInitAllocFWImgMemKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEVMEM_SIZE_T ui32FWCodeLen,
+ IMG_DEVMEM_SIZE_T ui32FWDataLen,
+ IMG_DEVMEM_SIZE_T uiFWCorememLen,
+ DEVMEM_EXPORTCOOKIE **ppsFWCodeAllocServerExportCookie,
+ IMG_DEV_VIRTADDR *psFWCodeDevVAddrBase,
+ DEVMEM_EXPORTCOOKIE **ppsFWDataAllocServerExportCookie,
+ IMG_DEV_VIRTADDR *psFWDataDevVAddrBase,
+ DEVMEM_EXPORTCOOKIE **ppsFWCorememAllocServerExportCookie,
+ IMG_DEV_VIRTADDR *psFWCorememDevVAddrBase,
+ RGXFWIF_DEV_VIRTADDR *psFWCorememMetaVAddrBase);
+
+
+
+/*!
+*******************************************************************************
+
+ @Function PVRSRVRGXInitFirmwareKM
+
+ @Description
+
+ Server-side RGX firmware initialisation
+
+ @Input pvDeviceNode - device node
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRGXInitFirmwareKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ RGXFWIF_DEV_VIRTADDR *psRGXFwInit,
+ IMG_BOOL bEnableSignatureChecks,
+ IMG_UINT32 ui32SignatureChecksBufSize,
+ IMG_UINT32 ui32HWPerfFWBufSizeKB,
+ IMG_UINT64 ui64HWPerfFilter,
+ IMG_UINT32 ui32RGXFWAlignChecksSize,
+ IMG_UINT32 *pui32RGXFWAlignChecks,
+ IMG_UINT32 ui32ConfigFlags,
+ IMG_UINT32 ui32LogType,
+ IMG_UINT32 ui32FilterMode,
+ RGXFWIF_COMPCHECKS_BVNC *psClientBVNC);
+
+
+/*!
+*******************************************************************************
+
+ @Function PVRSRVRGXInitLoadFWImageKM
+
+ @Description
+
+ Load the firmware image into place.
+
+ @Input psFWImgDestPMR - PMR holding destination memory buffer for firmware
+
+ @input psFWImgSrcPMR - PMR holding firmware image data to load
+
+ @input ui64FWImgLen - number of bytes in Src/Dst memory buffers
+
+ @input psFWImgSigPMR - a buffer holding a signature for Src, which is used for validation
+
+ @input ui64FWSigLen - number of bytes contained in the signature buffer.
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXInitLoadFWImageKM(PMR *psFWImgDestPMR,
+ PMR *psFWImgSrcPMR,
+ IMG_UINT64 ui64FWImgLen,
+ PMR *psFWImgSigPMR,
+ IMG_UINT64 ui64FWSigLen);
+
+
+/*!
+*******************************************************************************
+
+ @Function RGXRegisterDevice
+
+ @Description
+
+ Registers the device with the system
+
+ @Input: psDeviceNode - device node
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+
+/*!
+*******************************************************************************
+
+ @Function DevDeInitRGX
+
+ @Description
+
+ Reset and deinitialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+
+#endif /* __RGXINIT_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxmem.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxmem.c
new file mode 100644
index 000000000000..dc97b8f03240
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxmem.c
@@ -0,0 +1,508 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX memory context management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX memory context management
+@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_debug.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_server_utils.h"
+#include "devicemem_pdump.h"
+#include "rgxdevice.h"
+#include "rgx_fwif_km.h"
+#include "rgxfwutils.h"
+#include "pdump_km.h"
+#include "pvrsrv.h"
+#include "sync_internal.h"
+#include "rgx_memallocflags.h"
+
+
+static IMG_UINT32 ui32CacheOpps = 0;
+static IMG_UINT32 ui32CacheOpSequence = 0;
+
+
+#define SERVER_MMU_CONTEXT_MAX_NAME 40
+typedef struct _SERVER_MMU_CONTEXT_ {
+ DEVMEM_MEMDESC *psFWMemContextMemDesc;
+ MMU_CONTEXT *psMMUContext;
+ IMG_PID uiPID;
+ IMG_CHAR szProcessName[SERVER_MMU_CONTEXT_MAX_NAME];
+ DLLIST_NODE sNode;
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+} SERVER_MMU_CONTEXT;
+
+IMG_VOID RGXMMUCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDeviceData,
+ MMU_LEVEL eMMULevel,
+ IMG_BOOL bUnmap)
+{
+ PVR_UNREFERENCED_PARAMETER(bUnmap);
+
+ switch (eMMULevel)
+ {
+ case MMU_LEVEL_3: ui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_PC;
+ break;
+ case MMU_LEVEL_2: ui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_PD;
+ break;
+ case MMU_LEVEL_1: ui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_PT;
+ ui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_TLB;
+ break;
+ default:
+ PVR_ASSERT(0);
+ break;
+ }
+}
+
+PVRSRV_ERROR RGXSLCCacheInvalidateRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+ PMR *psPmr)
+{
+ RGXFWIF_KCCB_CMD sFlushInvalCmd;
+ IMG_UINT32 ulPMRFlags;
+ IMG_UINT32 ui32DeviceCacheFlags;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psDeviceNode);
+
+ /* In DEINIT state, we stop scheduling SLC flush commands, because we don't know in what state the firmware is.
+ * Anyway, if we are in DEINIT state, we don't care anymore about FW memory consistency
+ */
+ if (psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_DEINIT)
+ {
+
+ /* get the PMR's caching flags */
+ eError = PMR_Flags(psPmr, &ulPMRFlags);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXSLCCacheInvalidateRequest: Unable to get the caching attributes of PMR %p",psPmr));
+ }
+
+ ui32DeviceCacheFlags = DevmemDeviceCacheMode(ulPMRFlags);
+
+ /* Schedule a SLC flush and invalidate if
+ * - the memory is cached.
+ * - we can't get the caching attributes (by precaution).
+ */
+ if ((ui32DeviceCacheFlags == PVRSRV_MEMALLOCFLAG_GPU_CACHED) || (eError != PVRSRV_OK))
+ {
+ /* Schedule the SLC flush command ... */
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
+#endif
+ sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
+ sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
+ sFlushInvalCmd.uCmdData.sSLCFlushInvalData.eDM = RGXFWIF_DM_2D; //Covers all of Sidekick
+ sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
+
+ eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sFlushInvalCmd,
+ sizeof(sFlushInvalCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSLCCacheInvalidateRequest: Failed to schedule SLC flush command with error (%u)", eError));
+ }
+ else
+ {
+ /* Wait for the SLC flush to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXSLCCacheInvalidateRequest: SLC flush and invalidate aborted with error (%u)", eError));
+ }
+ }
+ }
+ }
+
+ return eError;
+}
+
+
+PVRSRV_ERROR RGXPreKickCacheCommand(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+ RGXFWIF_KCCB_CMD sFlushCmd;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_DM eDMcount = RGXFWIF_DM_MAX;
+
+ if (!ui32CacheOpps)
+ {
+ goto _PVRSRVPowerLock_Exit;
+ }
+
+ sFlushCmd.eCmdType = RGXFWIF_KCCB_CMD_MMUCACHE;
+ /* Set which memory context this command is for (all ctxs for now) */
+ ui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL;
+#if 0
+ sFlushCmd.uCmdData.sMMUCacheData.psMemoryContext = ???
+#endif
+
+ /* PVRSRVPowerLock guarantees atomicity between commands and global variables consistency.
+ * This is helpful in a scenario with several applications allocating resources. */
+ eError = PVRSRVPowerLock();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXPreKickCacheCommand: failed to acquire powerlock (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+ goto _PVRSRVPowerLock_Exit;
+ }
+
+ PDUMPPOWCMDSTART();
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_ON,
+ IMG_FALSE);
+ PDUMPPOWCMDEND();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "RGXPreKickCacheCommand: failed to transition RGX to ON (%s)",
+ PVRSRVGetErrorStringKM(eError)));
+
+ goto _PVRSRVSetDevicePowerStateKM_Exit;
+ }
+
+ sFlushCmd.uCmdData.sMMUCacheData.ui32Flags = ui32CacheOpps;
+ sFlushCmd.uCmdData.sMMUCacheData.ui32CacheSequenceNum = ++ui32CacheOpSequence;
+
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Submit MMU flush and invalidate (flags = 0x%08x, cache operation sequence = %u)",
+ ui32CacheOpps, ui32CacheOpSequence);
+#endif
+
+ ui32CacheOpps = 0;
+
+ /* Schedule MMU cache command */
+ do
+ {
+ eDMcount--;
+ eError = RGXSendCommandRaw(psDevInfo, eDMcount, &sFlushCmd, sizeof(RGXFWIF_KCCB_CMD), PDUMP_FLAGS_CONTINUOUS);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPreKickCacheCommand: Failed to schedule MMU cache command \
+ to DM=%d with error (%u)", eDMcount, eError));
+ break;
+ }
+ }
+ while(eDMcount > 0);
+
+_PVRSRVSetDevicePowerStateKM_Exit:
+ PVRSRVPowerUnlock();
+
+_PVRSRVPowerLock_Exit:
+ return eError;
+}
+
+IMG_VOID RGXUnregisterMemoryContext(IMG_HANDLE hPrivData)
+{
+ SERVER_MMU_CONTEXT *psServerMMUContext = hPrivData;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psServerMMUContext->psDevInfo;
+
+ OSWRLockAcquireWrite(psDevInfo->hMemoryCtxListLock, DEVINFO_MEMORYLIST);
+ dllist_remove_node(&psServerMMUContext->sNode);
+ OSWRLockReleaseWrite(psDevInfo->hMemoryCtxListLock);
+
+ /*
+ * Release the page catalogue address acquired in RGXRegisterMemoryContext().
+ */
+ MMU_ReleaseBaseAddr(IMG_NULL );
+
+ /*
+ * Free the firmware memory context.
+ */
+ DevmemFwFree(psServerMMUContext->psFWMemContextMemDesc);
+
+ OSFreeMem(psServerMMUContext);
+}
+
+
+/*
+ * RGXRegisterMemoryContext
+ */
+PVRSRV_ERROR RGXRegisterMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+ MMU_CONTEXT *psMMUContext,
+ IMG_HANDLE *hPrivData)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ DEVMEM_FLAGS_T uiFWMemContextMemAllocFlags;
+ RGXFWIF_FWMEMCONTEXT *psFWMemContext;
+ DEVMEM_MEMDESC *psFWMemContextMemDesc;
+ SERVER_MMU_CONTEXT *psServerMMUContext;
+
+ if (psDevInfo->psKernelMMUCtx == IMG_NULL)
+ {
+ /*
+ * This must be the creation of the Kernel memory context. Take a copy
+ * of the MMU context for use when programming the BIF.
+ */
+ psDevInfo->psKernelMMUCtx = psMMUContext;
+ }
+ else
+ {
+ psServerMMUContext = OSAllocMem(sizeof(*psServerMMUContext));
+ if (psServerMMUContext == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc_server_ctx;
+ }
+
+ psServerMMUContext->psDevInfo = psDevInfo;
+
+ /*
+ * This FW MemContext is only mapped into kernel for initialisation purposes.
+ * Otherwise this allocation is only used by the FW.
+ * Therefore the GPU cache doesn't need coherency,
+ * and write-combine is suffice on the CPU side (WC buffer will be flushed at any kick)
+ */
+ uiFWMemContextMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_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_WRITE_COMBINE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;
+
+ /*
+ Allocate device memory for the firmware memory context for the new
+ application.
+ */
+ PDUMPCOMMENT("Allocate RGX firmware memory context");
+
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(*psFWMemContext),
+ uiFWMemContextMemAllocFlags,
+ "FirmwareMemoryContext",
+ &psFWMemContextMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to allocate firmware memory context (%u)",
+ eError));
+ goto fail_alloc_fw_ctx;
+ }
+
+ /*
+ Temporarily map the firmware memory context to the kernel.
+ */
+ eError = DevmemAcquireCpuVirtAddr(psFWMemContextMemDesc,
+ (IMG_VOID **)&psFWMemContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to map firmware memory context (%u)",
+ eError));
+ goto fail_acquire_cpu_addr;
+ }
+
+ /*
+ * Write the new memory context's page catalogue into the firmware memory
+ * context for the client.
+ */
+ eError = MMU_AcquireBaseAddr(psMMUContext, &psFWMemContext->sPCDevPAddr);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to acquire Page Catalogue address (%u)",
+ eError));
+ DevmemReleaseCpuVirtAddr(psFWMemContextMemDesc);
+ goto fail_acquire_base_addr;
+ }
+
+ /*
+ * Set default values for the rest of the structure.
+ */
+ psFWMemContext->uiPageCatBaseRegID = -1;
+ psFWMemContext->uiBreakpointAddr = 0;
+ psFWMemContext->uiBPHandlerAddr = 0;
+ psFWMemContext->uiBreakpointCtl = 0;
+
+#if defined(PDUMP)
+ {
+ IMG_CHAR aszName[PMR_MAX_MEMSPNAME_SYMB_ADDR_LENGTH_DEFAULT];
+ IMG_DEVMEM_OFFSET_T uiOffset = 0;
+
+ /*
+ * Dump the Mem context allocation
+ */
+ DevmemPDumpLoadMem(psFWMemContextMemDesc, 0, sizeof(*psFWMemContext), PDUMP_FLAGS_CONTINUOUS);
+
+
+ /*
+ * Obtain a symbolic addr of the mem context structure
+ */
+ eError = DevmemPDumpPageCatBaseToSAddr(psFWMemContextMemDesc,
+ &uiOffset,
+ aszName,
+ PMR_MAX_MEMSPNAME_SYMB_ADDR_LENGTH_DEFAULT);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to generate a Dump Page Catalogue address (%u)",
+ eError));
+ DevmemReleaseCpuVirtAddr(psFWMemContextMemDesc);
+ goto fail_pdump_cat_base_addr;
+ }
+
+ /*
+ * Dump the Page Cat tag in the mem context (symbolic address)
+ */
+ eError = MMU_PDumpWritePageCatBase(psMMUContext,
+ aszName,
+ uiOffset,
+ 8, /* 64-bit register write */
+ 0,
+ 0,
+ 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to acquire Page Catalogue address (%u)",
+ eError));
+ DevmemReleaseCpuVirtAddr(psFWMemContextMemDesc);
+ goto fail_pdump_cat_base;
+ }
+ }
+#endif
+
+ /*
+ * Release kernel address acquired above.
+ */
+ DevmemReleaseCpuVirtAddr(psFWMemContextMemDesc);
+
+ /*
+ * Store the process information for this device memory context
+ * for use with the host page-fault analysis.
+ */
+ psServerMMUContext->uiPID = OSGetCurrentProcessIDKM();
+ psServerMMUContext->psMMUContext = psMMUContext;
+ psServerMMUContext->psFWMemContextMemDesc = psFWMemContextMemDesc;
+ if (OSSNPrintf(psServerMMUContext->szProcessName,
+ SERVER_MMU_CONTEXT_MAX_NAME,
+ "%s",
+ OSGetCurrentProcessNameKM()) == SERVER_MMU_CONTEXT_MAX_NAME)
+ {
+ psServerMMUContext->szProcessName[SERVER_MMU_CONTEXT_MAX_NAME-1] = '\0';
+ }
+
+ OSWRLockAcquireWrite(psDevInfo->hMemoryCtxListLock, DEVINFO_MEMORYLIST);
+ dllist_add_to_tail(&psDevInfo->sMemoryContextList, &psServerMMUContext->sNode);
+ OSWRLockReleaseWrite(psDevInfo->hMemoryCtxListLock);
+
+ MMU_SetDeviceData(psMMUContext, psFWMemContextMemDesc);
+ *hPrivData = psServerMMUContext;
+ }
+
+ return PVRSRV_OK;
+
+#if defined(PDUMP)
+fail_pdump_cat_base:
+fail_pdump_cat_base_addr:
+ MMU_ReleaseBaseAddr(IMG_NULL);
+#endif
+fail_acquire_base_addr:
+ /* Done before jumping to the fail point as the release is done before exit */
+fail_acquire_cpu_addr:
+ DevmemFwFree(psServerMMUContext->psFWMemContextMemDesc);
+fail_alloc_fw_ctx:
+ OSFreeMem(psServerMMUContext);
+fail_alloc_server_ctx:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+DEVMEM_MEMDESC *RGXGetFWMemDescFromMemoryContextHandle(IMG_HANDLE hPriv)
+{
+ SERVER_MMU_CONTEXT *psMMUContext = (SERVER_MMU_CONTEXT *) hPriv;
+
+ return psMMUContext->psFWMemContextMemDesc;
+}
+
+typedef struct _RGX_FAULT_DATA_ {
+ IMG_DEV_VIRTADDR *psDevVAddr;
+ IMG_DEV_PHYADDR *psDevPAddr;
+} RGX_FAULT_DATA;
+
+static IMG_BOOL _RGXCheckFaultAddress(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ SERVER_MMU_CONTEXT *psServerMMUContext = IMG_CONTAINER_OF(psNode, SERVER_MMU_CONTEXT, sNode);
+ RGX_FAULT_DATA *psFaultData = (RGX_FAULT_DATA *) pvCallbackData;
+ IMG_DEV_PHYADDR sPCDevPAddr;
+
+ if (MMU_AcquireBaseAddr(psServerMMUContext->psMMUContext, &sPCDevPAddr) != PVRSRV_OK)
+ {
+ PVR_LOG(("Failed to get PC address for memory context"));
+ return IMG_TRUE;
+ }
+
+ if (psFaultData->psDevPAddr->uiAddr == sPCDevPAddr.uiAddr)
+ {
+ PVR_LOG(("Found memory context (PID = %d, %s)",
+ psServerMMUContext->uiPID,
+ psServerMMUContext->szProcessName));
+
+ MMU_CheckFaultAddress(psServerMMUContext->psMMUContext, psFaultData->psDevVAddr);
+ return IMG_FALSE;
+ }
+ return IMG_TRUE;
+}
+
+IMG_VOID RGXCheckFaultAddress(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_DEV_VIRTADDR *psDevVAddr, IMG_DEV_PHYADDR *psDevPAddr)
+{
+ RGX_FAULT_DATA sFaultData;
+
+ sFaultData.psDevVAddr = psDevVAddr;
+ sFaultData.psDevPAddr = psDevPAddr;
+
+ OSWRLockAcquireRead(psDevInfo->hMemoryCtxListLock, DEVINFO_MEMORYLIST);
+
+ dllist_foreach_node(&psDevInfo->sMemoryContextList,
+ _RGXCheckFaultAddress,
+ &sFaultData);
+
+ OSWRLockReleaseRead(psDevInfo->hMemoryCtxListLock);
+}
+
+/******************************************************************************
+ End of file (rgxmem.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxmem.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxmem.h
new file mode 100644
index 000000000000..1b7d8c3ee7a5
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxmem.h
@@ -0,0 +1,76 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX memory context management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for RGX memory context management
+@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(__RGXMEM_H__)
+#define __RGXMEM_H__
+
+#include "pvrsrv_error.h"
+#include "device.h"
+#include "mmu_common.h"
+#include "rgxdevice.h"
+
+
+IMG_VOID RGXMMUSyncPrimAlloc(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_VOID RGXMMUSyncPrimFree(IMG_VOID);
+
+IMG_VOID RGXMMUCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDeviceData,
+ MMU_LEVEL eMMULevel,
+ IMG_BOOL bUnmap);
+
+PVRSRV_ERROR RGXSLCCacheInvalidateRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+ PMR *psPmr);
+
+PVRSRV_ERROR RGXPreKickCacheCommand(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+IMG_VOID RGXUnregisterMemoryContext(IMG_HANDLE hPrivData);
+PVRSRV_ERROR RGXRegisterMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+ MMU_CONTEXT *psMMUContext,
+ IMG_HANDLE *hPrivData);
+
+DEVMEM_MEMDESC *RGXGetFWMemDescFromMemoryContextHandle(IMG_HANDLE hPriv);
+
+IMG_VOID RGXCheckFaultAddress(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+#endif /* __RGXMEM_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxmmuinit.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxmmuinit.c
new file mode 100644
index 000000000000..1a78ec917936
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxmmuinit.c
@@ -0,0 +1,943 @@
+/*************************************************************************/ /*!
+@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 "device.h"
+#include "img_types.h"
+#include "mmu_common.h"
+#include "pdump_mmu.h"
+
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "rgx_memallocflags.h"
+#include "pdump_km.h"
+
+/*
+ * Bits of PT, PD and PC not involving addresses
+ */
+
+#define RGX_MMUCTRL_PTE_PROTMASK (RGX_MMUCTRL_PT_DATA_PM_META_PROTECT_EN | \
+ RGX_MMUCTRL_PT_DATA_ENTRY_PENDING_EN | \
+ RGX_MMUCTRL_PT_DATA_PM_SRC_EN | \
+ RGX_MMUCTRL_PT_DATA_SLC_BYPASS_CTRL_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)
+
+
+
+
+
+static MMU_PxE_CONFIG sRGXMMUPCEConfig;
+static MMU_DEVVADDR_CONFIG sRGXMMUTopLevelDevVAddrConfig;
+
+
+typedef struct _RGX_PAGESIZECONFIG_
+{
+ const MMU_PxE_CONFIG *psPDEConfig;
+ const MMU_PxE_CONFIG *psPTEConfig;
+ const MMU_DEVVADDR_CONFIG *psDevVAddrConfig;
+ IMG_UINT32 uiRefCount;
+ IMG_UINT32 uiMaxRefCount;
+} RGX_PAGESIZECONFIG;
+
+/*
+ *
+ * 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 RGX_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 RGX_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 RGX_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 RGX_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 RGX_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 RGX_PAGESIZECONFIG gsPageSizeConfig2MB;
+
+
+/* Forward declaration of protection bits derivation functions, for
+ the following structure */
+static IMG_UINT64 RGXDerivePCEProt8(IMG_UINT32 uiProtFlags, IMG_UINT8 ui8Log2PageSize);
+static IMG_UINT32 RGXDerivePCEProt4(IMG_UINT32 uiProtFlags);
+static IMG_UINT64 RGXDerivePDEProt8(IMG_UINT32 uiProtFlags, IMG_UINT8 ui8Log2PageSize);
+static IMG_UINT32 RGXDerivePDEProt4(IMG_UINT32 uiProtFlags);
+static IMG_UINT64 RGXDerivePTEProt8(IMG_UINT32 uiProtFlags, IMG_UINT8 ui8Log2PageSize);
+static IMG_UINT32 RGXDerivePTEProt4(IMG_UINT32 uiProtFlags);
+
+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)
+{
+ /*
+ * 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;
+
+ /*
+ * Setup sRGXMMUPCEConfig
+ */
+ sRGXMMUPCEConfig.uiBytesPerEntry = 4; /* 32 bit entries */
+ sRGXMMUPCEConfig.uiAddrMask = 0xfffffff0; /* Mask to get significant address bits of PC entry */
+
+ sRGXMMUPCEConfig.uiAddrShift = 4; /* Shift this many bits to get PD address in PC entry */
+ sRGXMMUPCEConfig.uiLog2Align = 12; /* Alignment of PD AND PC */
+
+ sRGXMMUPCEConfig.uiProtMask = RGX_MMUCTRL_PCE_PROTMASK; //Mask to get the status bits of the PC */
+ sRGXMMUPCEConfig.uiProtShift = 0; /* Shift this many bits to have status bits starting with bit 0 */
+
+ /*
+ * Setup sRGXMMUTopLevelDevVAddrConfig
+ */
+ sRGXMMUTopLevelDevVAddrConfig.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK; /* Get the PC address bits from a 40 bit virt. address (in a 64bit UINT) */
+ sRGXMMUTopLevelDevVAddrConfig.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+
+ sRGXMMUTopLevelDevVAddrConfig.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK; /* Get the PD address bits from a 40 bit virt. address (in a 64bit UINT) */
+ sRGXMMUTopLevelDevVAddrConfig.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+
+/*
+ *
+ * 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.uiLog2Align = 12;
+
+ sRGXMMUPDEConfig_4KBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+ sRGXMMUPDEConfig_4KBDP.uiVarCtrlShift = 1;
+
+ sRGXMMUPDEConfig_4KBDP.uiProtMask = RGX_MMUCTRL_PDE_PROTMASK;
+ sRGXMMUPDEConfig_4KBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUPTEConfig_4KBDP
+ */
+ sRGXMMUPTEConfig_4KBDP.uiBytesPerEntry = 8;
+
+ sRGXMMUPTEConfig_4KBDP.uiAddrMask = IMG_UINT64_C(0xfffffff000);
+ sRGXMMUPTEConfig_4KBDP.uiAddrShift = 12;
+ sRGXMMUPTEConfig_4KBDP.uiLog2Align = 12;
+
+ sRGXMMUPTEConfig_4KBDP.uiProtMask = RGX_MMUCTRL_PTE_PROTMASK;
+ sRGXMMUPTEConfig_4KBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUDevVAddrConfig_4KBDP
+ */
+ sRGXMMUDevVAddrConfig_4KBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_4KBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_4KBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_4KBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_4KBDP.uiPTIndexMask = ~RGX_MMUCTRL_VADDR_PT_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_4KBDP.uiPTIndexShift = RGX_MMUCTRL_VADDR_PT_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_4KBDP.uiPageOffsetMask = IMG_UINT64_C(0x0000000fff);
+ sRGXMMUDevVAddrConfig_4KBDP.uiPageOffsetShift = 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; /* These are for a page directory ENTRY, meaning the address of a PT cropped to suit the PD */
+ sRGXMMUPDEConfig_16KBDP.uiLog2Align = 10; /* Alignment of the page tables NOT directories */
+
+ sRGXMMUPDEConfig_16KBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+ sRGXMMUPDEConfig_16KBDP.uiVarCtrlShift = 1;
+
+ sRGXMMUPDEConfig_16KBDP.uiProtMask = RGX_MMUCTRL_PDE_PROTMASK;
+ sRGXMMUPDEConfig_16KBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUPTEConfig_16KBDP
+ */
+ sRGXMMUPTEConfig_16KBDP.uiBytesPerEntry = 8;
+
+ sRGXMMUPTEConfig_16KBDP.uiAddrMask = IMG_UINT64_C(0xffffffc000);
+ sRGXMMUPTEConfig_16KBDP.uiAddrShift = 14; /* These are for a page table ENTRY, meaning the address of a PAGE cropped to suit the PD */
+ sRGXMMUPTEConfig_16KBDP.uiLog2Align = 14; /* Alignment of the pages NOT tables */
+
+ sRGXMMUPTEConfig_16KBDP.uiProtMask = RGX_MMUCTRL_PTE_PROTMASK;
+ sRGXMMUPTEConfig_16KBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUDevVAddrConfig_16KBDP
+ */
+ sRGXMMUDevVAddrConfig_16KBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_16KBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_16KBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_16KBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_16KBDP.uiPTIndexMask = IMG_UINT64_C(0x00001fc000);
+ sRGXMMUDevVAddrConfig_16KBDP.uiPTIndexShift = 14;
+
+ sRGXMMUDevVAddrConfig_16KBDP.uiPageOffsetMask = IMG_UINT64_C(0x0000003fff);
+ sRGXMMUDevVAddrConfig_16KBDP.uiPageOffsetShift = 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.uiLog2Align = 8;
+
+ sRGXMMUPDEConfig_64KBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+ sRGXMMUPDEConfig_64KBDP.uiVarCtrlShift = 1;
+
+ sRGXMMUPDEConfig_64KBDP.uiProtMask = RGX_MMUCTRL_PDE_PROTMASK;
+ sRGXMMUPDEConfig_64KBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUPTEConfig_64KBDP
+ */
+ sRGXMMUPTEConfig_64KBDP.uiBytesPerEntry = 8;
+
+ sRGXMMUPTEConfig_64KBDP.uiAddrMask = IMG_UINT64_C(0xffffff0000);
+ sRGXMMUPTEConfig_64KBDP.uiAddrShift =16;
+ sRGXMMUPTEConfig_64KBDP.uiLog2Align = 16;
+
+ sRGXMMUPTEConfig_64KBDP.uiProtMask = RGX_MMUCTRL_PTE_PROTMASK;
+ sRGXMMUPTEConfig_64KBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUDevVAddrConfig_64KBDP
+ */
+ sRGXMMUDevVAddrConfig_64KBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_64KBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_64KBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_64KBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_64KBDP.uiPTIndexMask = IMG_UINT64_C(0x00001f0000);
+ sRGXMMUDevVAddrConfig_64KBDP.uiPTIndexShift = 16;
+
+ sRGXMMUDevVAddrConfig_64KBDP.uiPageOffsetMask = IMG_UINT64_C(0x000000ffff);
+ sRGXMMUDevVAddrConfig_64KBDP.uiPageOffsetShift = 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.uiLog2Align = 6;
+
+ sRGXMMUPDEConfig_256KBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+ sRGXMMUPDEConfig_256KBDP.uiVarCtrlShift = 1;
+
+ sRGXMMUPDEConfig_256KBDP.uiProtMask = RGX_MMUCTRL_PDE_PROTMASK;
+ sRGXMMUPDEConfig_256KBDP.uiProtShift = 0;
+
+ /*
+ * Setup MMU_PxE_CONFIG sRGXMMUPTEConfig_256KBDP
+ */
+ sRGXMMUPTEConfig_256KBDP.uiBytesPerEntry = 8;
+
+ sRGXMMUPTEConfig_256KBDP.uiAddrMask = IMG_UINT64_C(0xfffffc0000);
+ sRGXMMUPTEConfig_256KBDP.uiAddrShift = 18;
+ sRGXMMUPTEConfig_256KBDP.uiLog2Align = 18;
+
+ sRGXMMUPTEConfig_256KBDP.uiProtMask = RGX_MMUCTRL_PTE_PROTMASK;
+ sRGXMMUPTEConfig_256KBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUDevVAddrConfig_256KBDP
+ */
+ sRGXMMUDevVAddrConfig_256KBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_256KBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_256KBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_256KBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_256KBDP.uiPTIndexMask = IMG_UINT64_C(0x00001c0000);
+ sRGXMMUDevVAddrConfig_256KBDP.uiPTIndexShift = 18;
+
+ sRGXMMUDevVAddrConfig_256KBDP.uiPageOffsetMask = IMG_UINT64_C(0x000003ffff);
+ sRGXMMUDevVAddrConfig_256KBDP.uiPageOffsetShift = 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);
+ sRGXMMUPDEConfig_1MBDP.uiAddrShift = 4;
+ sRGXMMUPDEConfig_1MBDP.uiLog2Align = 4;
+
+ sRGXMMUPDEConfig_1MBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+ sRGXMMUPDEConfig_1MBDP.uiVarCtrlShift = 1;
+
+ sRGXMMUPDEConfig_1MBDP.uiProtMask = RGX_MMUCTRL_PDE_PROTMASK;
+ sRGXMMUPDEConfig_1MBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUPTEConfig_1MBDP
+ */
+ sRGXMMUPTEConfig_1MBDP.uiBytesPerEntry = 8;
+
+ sRGXMMUPTEConfig_1MBDP.uiAddrMask = IMG_UINT64_C(0xfffff00000);
+ sRGXMMUPTEConfig_1MBDP.uiAddrShift = 20;
+ sRGXMMUPTEConfig_1MBDP.uiLog2Align = 20;
+
+ sRGXMMUPTEConfig_1MBDP.uiProtMask = RGX_MMUCTRL_PTE_PROTMASK;
+ sRGXMMUPTEConfig_1MBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUDevVAddrConfig_1MBDP
+ */
+ sRGXMMUDevVAddrConfig_1MBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_1MBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_1MBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_1MBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_1MBDP.uiPTIndexMask = IMG_UINT64_C(0x0000100000);
+ sRGXMMUDevVAddrConfig_1MBDP.uiPTIndexShift = 20;
+
+ sRGXMMUDevVAddrConfig_1MBDP.uiPageOffsetMask = IMG_UINT64_C(0x00000fffff);
+ sRGXMMUDevVAddrConfig_1MBDP.uiPageOffsetShift = 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);
+ sRGXMMUPDEConfig_2MBDP.uiAddrShift = 4;
+ sRGXMMUPDEConfig_2MBDP.uiLog2Align = 4;
+
+ sRGXMMUPDEConfig_2MBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+ sRGXMMUPDEConfig_2MBDP.uiVarCtrlShift = 1;
+
+ sRGXMMUPDEConfig_2MBDP.uiProtMask = RGX_MMUCTRL_PDE_PROTMASK;
+ sRGXMMUPDEConfig_2MBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUPTEConfig_2MBDP
+ */
+ sRGXMMUPTEConfig_2MBDP.uiBytesPerEntry = 8;
+
+ sRGXMMUPTEConfig_2MBDP.uiAddrMask = IMG_UINT64_C(0xffffe00000);
+ sRGXMMUPTEConfig_2MBDP.uiAddrShift = 21;
+ sRGXMMUPTEConfig_2MBDP.uiLog2Align = 21;
+
+ sRGXMMUPTEConfig_2MBDP.uiProtMask = RGX_MMUCTRL_PTE_PROTMASK;
+ sRGXMMUPTEConfig_2MBDP.uiProtShift = 0;
+
+ /*
+ * Setup sRGXMMUDevVAddrConfig_2MBDP
+ */
+ sRGXMMUDevVAddrConfig_2MBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_2MBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_2MBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+ sRGXMMUDevVAddrConfig_2MBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+
+ sRGXMMUDevVAddrConfig_2MBDP.uiPTIndexMask = IMG_UINT64_C(0x0000000000);
+ sRGXMMUDevVAddrConfig_2MBDP.uiPTIndexShift = 21;
+
+ sRGXMMUDevVAddrConfig_2MBDP.uiPageOffsetMask = IMG_UINT64_C(0x00001fffff);
+ sRGXMMUDevVAddrConfig_2MBDP.uiPageOffsetShift = 0;
+
+ /*
+ * Setup gsPageSizeConfig2MB
+ */
+ gsPageSizeConfig2MB.psPDEConfig = &sRGXMMUPDEConfig_2MBDP;
+ gsPageSizeConfig2MB.psPTEConfig = &sRGXMMUPTEConfig_2MBDP;
+ gsPageSizeConfig2MB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_2MBDP;
+ gsPageSizeConfig2MB.uiRefCount = 0;
+ gsPageSizeConfig2MB.uiMaxRefCount = 0;
+
+ /*
+ * Setup sRGXMMUDeviceAttributes
+ */
+ 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;
+
+ 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 = IMG_NULL;
+#endif
+
+ psDeviceNode->psMMUDevAttrs = IMG_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 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_UINT8 ui8Log2PageSize)
+{
+ PVR_UNREFERENCED_PARAMETER(uiProtFlags);
+ PVR_UNREFERENCED_PARAMETER(ui8Log2PageSize);
+
+ 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 ui8Log2PageSize 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_UINT8 ui8Log2PageSize)
+{
+ IMG_UINT64 ret_value = 0; // 0 means invalid
+
+ if (! (uiProtFlags & MMU_PROTFLAGS_INVALID)) // if not invalid
+ {
+ switch (ui8Log2PageSize)
+ {
+ case 12:
+ ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_4KB;
+ break;
+ case 14:
+ ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_16KB;
+ break;
+ case 16:
+ ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_64KB;
+ break;
+ case 18:
+ ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_256KB;
+ break;
+ case 20:
+ ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_1MB;
+ break;
+ case 21:
+ 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__, __FUNCTION__, ui8Log2PageSize));
+ }
+ }
+ 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_UINT8 ui8Log2PageSize)
+{
+ IMG_UINT64 ui64MMUFlags=0;
+
+ PVR_UNREFERENCED_PARAMETER(ui8Log2PageSize);
+
+ 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_ERROR, "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;
+ }
+
+ /* cache setup */
+ if ((MMU_PROTFLAGS_CACHED & uiProtFlags) == 0)
+ {
+ ui64MMUFlags |= RGX_MMUCTRL_PT_DATA_SLC_BYPASS_CTRL_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;
+ }
+
+ return ui64MMUFlags;
+}
+
+
+/*************************************************************************/ /*!
+@Function RGXGetPageSizeConfig
+@Description Set up configuration for variable sized data pages
+@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)
+{
+ RGX_PAGESIZECONFIG *psPageSizeConfig;
+
+ switch (uiLog2DataPageSize)
+ {
+ case 12:
+ psPageSizeConfig = &gsPageSizeConfig4KB;
+ break;
+ case 14:
+ psPageSizeConfig = &gsPageSizeConfig16KB;
+ break;
+ case 16:
+ psPageSizeConfig = &gsPageSizeConfig64KB;
+ break;
+ case 18:
+ psPageSizeConfig = &gsPageSizeConfig256KB;
+ break;
+ case 20:
+ psPageSizeConfig = &gsPageSizeConfig1MB;
+ break;
+ case 21:
+ psPageSizeConfig = &gsPageSizeConfig2MB;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "RGXGetPageSizeConfigCB: Invalid Data Page Size 1<<0x%x",
+ uiLog2DataPageSize));
+ 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;
+
+ /* 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);
+
+ *phPriv = (IMG_HANDLE)(IMG_UINTPTR_T)uiLog2DataPageSize;
+ PVR_ASSERT (uiLog2DataPageSize == (IMG_UINT32)(IMG_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.
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+static PVRSRV_ERROR RGXPutPageSizeConfigCB(IMG_HANDLE hPriv)
+{
+ RGX_PAGESIZECONFIG *psPageSizeConfig;
+ IMG_UINT32 uiLog2DataPageSize;
+
+ uiLog2DataPageSize = (IMG_UINT32)(IMG_UINTPTR_T) hPriv;
+
+ switch (uiLog2DataPageSize)
+ {
+ case 12:
+ psPageSizeConfig = &gsPageSizeConfig4KB;
+ break;
+ case 14:
+ psPageSizeConfig = &gsPageSizeConfig16KB;
+ break;
+ case 16:
+ psPageSizeConfig = &gsPageSizeConfig64KB;
+ break;
+ case 18:
+ psPageSizeConfig = &gsPageSizeConfig256KB;
+ break;
+ case 20:
+ psPageSizeConfig = &gsPageSizeConfig1MB;
+ break;
+ case 21:
+ 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 --;
+
+ 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)
+{
+ switch (ui64PDE & (~RGX_MMUCTRL_PD_DATA_PAGE_SIZE_CLRMSK))
+ {
+ case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_4KB:
+ *pui32Log2PageSize = 12;
+ break;
+ case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_16KB:
+ *pui32Log2PageSize = 14;
+ break;
+ case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_64KB:
+ *pui32Log2PageSize = 16;
+ break;
+ case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_256KB:
+ *pui32Log2PageSize = 18;
+ break;
+ case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_1MB:
+ *pui32Log2PageSize = 20;
+ break;
+ case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_2MB:
+ *pui32Log2PageSize = 21;
+ break;
+ default:
+ return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+ break;
+ }
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxmmuinit.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxmmuinit.h
new file mode 100644
index 000000000000..c79a72e42843
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxmmuinit.h
@@ -0,0 +1,60 @@
+/*************************************************************************/ /*!
+@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"
+
+IMG_EXPORT PVRSRV_ERROR RGXMMUInit_Register(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_EXPORT PVRSRV_ERROR RGXMMUInit_Unregister(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+
+#endif /* #ifndef _SRVKM_RGXMMUINIT_H_ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxpdump.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxpdump.c
new file mode 100644
index 000000000000..0f245c015474
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxpdump.c
@@ -0,0 +1,133 @@
+/*************************************************************************/ /*!
+@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 "devicemem_pdump.h"
+#include "rgxpdump.h"
+
+/*
+ * PVRSRVPDumpSignatureBufferKM
+ */
+PVRSRV_ERROR PVRSRVPDumpSignatureBufferKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ /* TA signatures */
+ PDumpCommentWithFlags(ui32PDumpFlags, "** Dump TA signatures and checksums Buffer");
+
+ DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigTAChecksMemDesc,
+ 0,
+ psDevInfo->ui32SigTAChecksSize,
+ "out.tasig",
+ 0,
+ ui32PDumpFlags);
+
+ /* 3D signatures */
+ PDumpCommentWithFlags(ui32PDumpFlags, "** Dump 3D signatures and checksums Buffer");
+ DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSig3DChecksMemDesc,
+ 0,
+ psDevInfo->ui32Sig3DChecksSize,
+ "out.3dsig",
+ 0,
+ ui32PDumpFlags);
+
+#if defined(RGX_FEATURE_RAY_TRACING)
+ /* RT signatures */
+ PDumpCommentWithFlags(ui32PDumpFlags, "** Dump RTU signatures and checksums Buffer");
+ DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigRTChecksMemDesc,
+ 0,
+ psDevInfo->ui32SigRTChecksSize,
+ "out.rtsig",
+ 0,
+ ui32PDumpFlags);
+
+ /* SH signatures */
+ PDumpCommentWithFlags(ui32PDumpFlags, "** Dump SHG signatures and checksums Buffer");
+ DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigSHChecksMemDesc,
+ 0,
+ psDevInfo->ui32SigSHChecksSize,
+ "out.shsig",
+ 0,
+ ui32PDumpFlags);
+#endif
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPDumpTraceBufferKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ /* Dump trace buffers */
+ PDumpCommentWithFlags(ui32PDumpFlags, "** Dump trace buffers");
+ DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+ offsetof(RGXFWIF_TRACEBUF, sTraceBuf),
+ RGXFW_THREAD_NUM *
+ ( 1 * sizeof(IMG_UINT32)
+ +RGXFW_TRACE_BUFFER_SIZE * sizeof(IMG_UINT32)
+ +RGXFW_TRACE_BUFFER_ASSERT_SIZE * sizeof(IMG_CHAR)),
+ "out.trace",
+ 0,
+ ui32PDumpFlags);
+
+ /* Dump hwperf buffer */
+ PDumpCommentWithFlags(ui32PDumpFlags, "** Dump HWPerf Buffer");
+ DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfHWPerfBufMemDesc,
+ 0,
+ psDevInfo->ui32RGXFWIfHWPerfBufSize,
+ "out.hwperf",
+ 0,
+ ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+#endif /* PDUMP */
+
+/******************************************************************************
+ End of file (rgxpdump.c)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxpdump.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxpdump.h
new file mode 100644
index 000000000000..4cdf9cb8cbf2
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxpdump.h
@@ -0,0 +1,112 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX pdump Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX pdump 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 "img_defs.h"
+#include "pvrsrv_error.h"
+#include "rgxdevice.h"
+#include "device.h"
+#include "devicemem.h"
+#include "pdump_km.h"
+#include "pvr_debug.h"
+
+#if defined(PDUMP)
+/*!
+******************************************************************************
+
+ @Function PVRSRVPDumpSignatureBufferKM
+
+ @Description
+
+ Dumps TA and 3D signature and checksum buffers
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPDumpSignatureBufferKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32PDumpFlags);
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVPDumpTraceBufferKM
+
+ @Description
+
+ Dumps TA and 3D signature and checksum buffers
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPDumpTraceBufferKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32PDumpFlags);
+#else /* PDUMP */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpSignatureBufferKM)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpSignatureBufferKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPDumpTraceBufferKM)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVPDumpTraceBufferKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+#endif /* PDUMP */
+/******************************************************************************
+ End of file (rgxpdump.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxpower.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxpower.c
new file mode 100644
index 000000000000..2697dd86cc2c
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxpower.c
@@ -0,0 +1,1268 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+
+#include "rgxpower.h"
+#include "rgx_fwif_km.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "pdump_km.h"
+#include "rgxdefs_km.h"
+#include "pvrsrv.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "rgxdebug.h"
+#include "rgx_meta.h"
+#include "devicemem_pdump.h"
+#include "rgxapi_km.h"
+
+#include "process_stats.h"
+
+extern IMG_UINT32 g_ui32HostSampleIRQCount;
+
+#if ! defined(FIX_HW_BRN_37453)
+/*!
+*******************************************************************************
+
+ @Function RGXEnableClocks
+
+ @Description Enable RGX Clocks
+
+ @Input psDevInfo - device info structure
+
+ @Return IMG_VOID
+
+******************************************************************************/
+static IMG_VOID RGXEnableClocks(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGX clock: use default (automatic clock gating)");
+}
+#endif
+
+
+/*!
+*******************************************************************************
+
+ @Function _RGXInitSLC
+
+ @Description Initialise RGX SLC
+
+ @Input psDevInfo - device info structure
+
+ @Return IMG_VOID
+
+******************************************************************************/
+#if !defined(RGX_FEATURE_S7_CACHE_HIERARCHY)
+
+#define RGX_INIT_SLC _RGXInitSLC
+
+static IMG_VOID _RGXInitSLC(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ IMG_UINT32 ui32Reg;
+ IMG_UINT32 ui32RegVal;
+
+#if defined(FIX_HW_BRN_36492)
+ /* Because the WA for this BRN forbids using SLC reset, need to inval it instead */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Invalidate the SLC");
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+ RGX_CR_SLC_CTRL_FLUSH_INVAL, RGX_CR_SLC_CTRL_FLUSH_INVAL_ALL_EN);
+ PDUMPREG32(RGX_PDUMPREG_NAME,
+ RGX_CR_SLC_CTRL_FLUSH_INVAL, RGX_CR_SLC_CTRL_FLUSH_INVAL_ALL_EN,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ /* poll for completion */
+ PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + RGX_CR_SLC_STATUS0),
+ 0x0,
+ RGX_CR_SLC_STATUS0_INVAL_PENDING_EN);
+
+ PDUMPREGPOL(RGX_PDUMPREG_NAME,
+ RGX_CR_SLC_STATUS0,
+ 0x0,
+ RGX_CR_SLC_STATUS0_INVAL_PENDING_EN,
+ PDUMP_FLAGS_CONTINUOUS,
+ PDUMP_POLL_OPERATOR_EQUAL);
+#endif
+
+ if (!PVRSRVSystemSnoopingOfCPUCache() && !PVRSRVSystemSnoopingOfDeviceCache())
+ {
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has NO cache snooping");
+ }
+ else
+ {
+ if (PVRSRVSystemSnoopingOfCPUCache())
+ {
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has CPU cache snooping");
+ }
+ if (PVRSRVSystemSnoopingOfDeviceCache())
+ {
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has DEVICE cache snooping");
+ }
+ }
+
+#if (RGX_FEATURE_SLC_SIZE_IN_BYTES < (128*1024))
+ /*
+ * SLC Bypass control
+ */
+ ui32Reg = RGX_CR_SLC_CTRL_BYPASS;
+
+ /* Bypass SLC for textures if the SLC size is less than 128kB */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Bypass SLC for TPU");
+ ui32RegVal = RGX_CR_SLC_CTRL_BYPASS_REQ_TPU_EN;
+
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32Reg, ui32RegVal);
+ PDUMPREG32(RGX_PDUMPREG_NAME, ui32Reg, ui32RegVal, PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+ /*
+ * SLC Bypass control
+ */
+ ui32Reg = RGX_CR_SLC_CTRL_MISC;
+ ui32RegVal = RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1;
+
+ /* Bypass burst combiner if SLC line size is smaller than 1024 bits */
+#if (RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS < 1024)
+ ui32RegVal |= RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_EN;
+#endif
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32Reg, ui32RegVal);
+ PDUMPREG32(RGX_PDUMPREG_NAME, ui32Reg, ui32RegVal, PDUMP_FLAGS_CONTINUOUS);
+
+}
+#endif /* RGX_FEATURE_S7_CACHE_HIERARCHY */
+
+
+/*!
+*******************************************************************************
+
+ @Function RGXInitSLC3
+
+ @Description Initialise RGX SLC3
+
+ @Input psDevInfo - device info structure
+
+ @Return IMG_VOID
+
+******************************************************************************/
+#if defined(RGX_FEATURE_S7_CACHE_HIERARCHY)
+
+#define RGX_INIT_SLC _RGXInitSLC3
+
+static IMG_VOID _RGXInitSLC3(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if (RGX_FEATURE_SLC_BANKS == 4) && (RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS == 512)
+ IMG_UINT32 ui32Reg;
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT64 ui64RegVal;
+
+ /*
+ * SLC control
+ */
+ ui32Reg = RGX_CR_SLC3_CTRL_MISC;
+ ui32RegVal = RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_SCRAMBLE_PVR_HASH;
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32Reg, ui32RegVal);
+ PDUMPREG32(RGX_PDUMPREG_NAME, ui32Reg, ui32RegVal, PDUMP_FLAGS_CONTINUOUS);
+
+ /*
+ * SLC scramble bits
+ */
+ ui32Reg = RGX_CR_SLC3_SCRAMBLE;
+ ui64RegVal = IMG_UINT64_C(0xB42DD24B4BD22DB4);
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, ui32Reg, ui64RegVal);
+ PDUMPREG64(RGX_PDUMPREG_NAME, ui32Reg, ui64RegVal, PDUMP_FLAGS_CONTINUOUS);
+
+ ui32Reg = RGX_CR_SLC3_SCRAMBLE2;
+ ui64RegVal = IMG_UINT64_C(0xB42DD24B4BD22DB4);
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, ui32Reg, ui64RegVal);
+ PDUMPREG64(RGX_PDUMPREG_NAME, ui32Reg, ui64RegVal, PDUMP_FLAGS_CONTINUOUS);
+#else
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+#endif
+
+#if defined(HW_ERN_45914)
+ /* Disable the forced SLC coherency which the hardware enables for compatibility with older pdumps */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: disable forced SLC coherency");
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_GARTEN_SLC, 0);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_GARTEN_SLC, 0, PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+}
+#endif
+
+
+/*!
+*******************************************************************************
+
+ @Function RGXInitBIF
+
+ @Description Initialise RGX BIF
+
+ @Input psDevInfo - device info structure
+
+ @Return IMG_VOID
+
+******************************************************************************/
+static IMG_VOID RGXInitBIF(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError;
+ IMG_DEV_PHYADDR sPCAddr;
+
+ /*
+ Acquire the address of the Kernel Page Catalogue.
+ */
+ eError = MMU_AcquireBaseAddr(psDevInfo->psKernelMMUCtx, &sPCAddr);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ /* Sanity check Cat-Base address */
+ PVR_ASSERT((((sPCAddr.uiAddr
+ >> psDevInfo->ui32KernelCatBaseAlignShift)
+ << psDevInfo->ui32KernelCatBaseShift)
+ & ~psDevInfo->ui64KernelCatBaseMask) == 0x0UL);
+
+ /*
+ Write the kernel catalogue base.
+ */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGX firmware MMU Page Catalogue");
+
+ if (psDevInfo->ui32KernelCatBaseIdReg != -1)
+ {
+ /* Set the mapping index */
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32KernelCatBaseIdReg,
+ psDevInfo->ui32KernelCatBaseId);
+
+ /* pdump mapping context */
+ PDUMPREG32(RGX_PDUMPREG_NAME,
+ psDevInfo->ui32KernelCatBaseIdReg,
+ psDevInfo->ui32KernelCatBaseId,
+ PDUMP_FLAGS_CONTINUOUS);
+ }
+
+ if (psDevInfo->ui32KernelCatBaseWordSize == 8)
+ {
+ /* Write the cat-base address */
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32KernelCatBaseReg,
+ ((sPCAddr.uiAddr
+ >> psDevInfo->ui32KernelCatBaseAlignShift)
+ << psDevInfo->ui32KernelCatBaseShift)
+ & psDevInfo->ui64KernelCatBaseMask);
+ }
+ else
+ {
+ /* Write the cat-base address */
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32KernelCatBaseReg,
+ (IMG_UINT32)(((sPCAddr.uiAddr
+ >> psDevInfo->ui32KernelCatBaseAlignShift)
+ << psDevInfo->ui32KernelCatBaseShift)
+ & psDevInfo->ui64KernelCatBaseMask));
+ }
+
+ /* pdump catbase address */
+ MMU_PDumpWritePageCatBase(psDevInfo->psKernelMMUCtx,
+ RGX_PDUMPREG_NAME,
+ psDevInfo->ui32KernelCatBaseReg,
+ psDevInfo->ui32KernelCatBaseWordSize,
+ psDevInfo->ui32KernelCatBaseAlignShift,
+ psDevInfo->ui32KernelCatBaseShift,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ /*
+ * Trusted META boot
+ */
+#if defined(SUPPORT_TRUSTED_DEVICE)
+ #if defined(TRUSTED_DEVICE_DEFAULT_ENABLED)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXInitBIF: Trusted Device enabled");
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_TRUST, RGX_CR_BIF_TRUST_ENABLE_EN);
+ PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_BIF_TRUST, RGX_CR_BIF_TRUST_ENABLE_EN, PDUMP_FLAGS_CONTINUOUS);
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_SYS_BUS_SECURE, RGX_CR_SYS_BUS_SECURE_ENABLE_EN);
+ PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_SYS_BUS_SECURE, RGX_CR_SYS_BUS_SECURE_ENABLE_EN, PDUMP_FLAGS_CONTINUOUS);
+ #else /* ! defined(TRUSTED_DEVICE_DEFAULT_ENABLED) */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXInitBIF: Trusted Device disabled");
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_BIF_TRUST, 0);
+ PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_BIF_TRUST, 0, PDUMP_FLAGS_CONTINUOUS);
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_SYS_BUS_SECURE, 0);
+ PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_SYS_BUS_SECURE, 0, PDUMP_FLAGS_CONTINUOUS);
+ #endif /* TRUSTED_DEVICE_DEFAULT_ENABLED */
+#endif
+
+}
+
+#if defined(RGX_FEATURE_AXI_ACELITE)
+/*!
+*******************************************************************************
+
+ @Function RGXAXIACELiteInit
+
+ @Description Initialise AXI-ACE Lite interface
+
+ @Input psDevInfo - device info structure
+
+ @Return IMG_VOID
+
+******************************************************************************/
+static IMG_VOID RGXAXIACELiteInit(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ IMG_UINT32 ui32RegAddr;
+ IMG_UINT64 ui64RegVal;
+
+ ui32RegAddr = RGX_CR_AXI_ACE_LITE_CONFIGURATION;
+
+ /* Setup AXI-ACE config. Set everything to outer cache */
+ ui64RegVal = (3U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_NON_SNOOPING_SHIFT) |
+ (3U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_NON_SNOOPING_SHIFT) |
+ (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_CACHE_MAINTENANCE_SHIFT) |
+ (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_COHERENT_SHIFT) |
+ (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_COHERENT_SHIFT) |
+ (((IMG_UINT64) 1) << RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITELINEUNIQUE_SHIFT) |
+ (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWCACHE_COHERENT_SHIFT) |
+ (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_COHERENT_SHIFT) |
+ (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_CACHE_MAINTENANCE_SHIFT);
+
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM,
+ ui32RegAddr,
+ ui64RegVal);
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Init AXI-ACE interface");
+ PDUMPREG64(RGX_PDUMPREG_NAME, ui32RegAddr, ui64RegVal, PDUMP_FLAGS_CONTINUOUS);
+}
+#endif
+
+
+/*!
+*******************************************************************************
+
+ @Function RGXStart
+
+ @Description
+
+ (client invoked) chip-reset and initialisation
+
+ @Input psDevInfo - device info structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR RGXStart(PVRSRV_RGXDEV_INFO *psDevInfo, PVRSRV_DEVICE_CONFIG *psDevConfig)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_INIT *psRGXFWInit;
+
+#if defined(FIX_HW_BRN_37453)
+ /* Force all clocks on*/
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: force all clocks on");
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_CLK_CTRL, RGX_CR_CLK_CTRL_ALL_ON);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_CLK_CTRL, RGX_CR_CLK_CTRL_ALL_ON, PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+#if defined(SUPPORT_SHARED_SLC) && !defined(FIX_HW_BRN_36492)
+ /* When the SLC is shared, the SLC reset is performed by the System layer when calling
+ * RGXInitSLC (before any device uses it), therefore mask out the SLC bit to avoid
+ * soft_resetting it here. If HW_BRN_36492, the bit is already masked out.
+ */
+#define RGX_CR_SOFT_RESET_ALL (RGX_CR_SOFT_RESET_MASKFULL ^ RGX_CR_SOFT_RESET_SLC_EN)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: Shared SLC (don't reset SLC as part of RGX reset)");
+#else
+#define RGX_CR_SOFT_RESET_ALL (RGX_CR_SOFT_RESET_MASKFULL)
+#endif
+
+ /* Set RGX in soft-reset */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: soft reset everything");
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL, PDUMP_FLAGS_CONTINUOUS);
+
+ /* Take Rascal and Dust out of reset */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: Rascal and Dust out of reset");
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL ^ RGX_CR_SOFT_RESET_RASCALDUSTS_EN);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL ^ RGX_CR_SOFT_RESET_RASCALDUSTS_EN, PDUMP_FLAGS_CONTINUOUS);
+
+ /* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
+ (IMG_VOID) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
+ PDUMPREGREAD64(RGX_PDUMPREG_NAME, RGX_CR_SOFT_RESET, PDUMP_FLAGS_CONTINUOUS);
+
+ /* Take everything out of reset but META */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: Take everything out of reset but META");
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN, PDUMP_FLAGS_CONTINUOUS);
+
+#if ! defined(FIX_HW_BRN_37453)
+ /*
+ * Enable clocks.
+ */
+ RGXEnableClocks(psDevInfo);
+#endif
+
+ /*
+ * Initialise SLC.
+ */
+#if !defined(SUPPORT_SHARED_SLC)
+ RGX_INIT_SLC(psDevInfo);
+#endif
+
+#if !defined(SUPPORT_META_SLAVE_BOOT)
+ /* Configure META to Master boot */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: META Master boot");
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_BOOT, RGX_CR_META_BOOT_MODE_EN);
+ PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_META_BOOT, RGX_CR_META_BOOT_MODE_EN, PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+ /* Set Garten IDLE to META idle and Set the Garten Wrapper BIF Fence address */
+ {
+ IMG_UINT64 ui32BIFFenceAddr = RGXFW_BOOTLDR_DEVV_ADDR | RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META;
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: Configure META wrapper");
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, ui32BIFFenceAddr);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, ui32BIFFenceAddr, PDUMP_FLAGS_CONTINUOUS);
+ }
+
+#if defined(RGX_FEATURE_AXI_ACELITE)
+ /*
+ We must init the AXI-ACE interface before 1st BIF transaction
+ */
+ RGXAXIACELiteInit(psDevInfo);
+#endif
+
+ /*
+ * Initialise BIF.
+ */
+ RGXInitBIF(psDevInfo);
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: Take META out of reset");
+ /* need to wait for at least 16 cycles before taking meta out of reset ... */
+ PVRSRVSystemWaitCycles(psDevConfig, 32);
+ PDUMPIDLWITHFLAGS(32, PDUMP_FLAGS_CONTINUOUS);
+
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, 0x0);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_SOFT_RESET, 0x0, PDUMP_FLAGS_CONTINUOUS);
+
+ (IMG_VOID) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
+ PDUMPREGREAD64(RGX_PDUMPREG_NAME, RGX_CR_SOFT_RESET, PDUMP_FLAGS_CONTINUOUS);
+
+ /* ... and afterwards */
+ PVRSRVSystemWaitCycles(psDevConfig, 32);
+ PDUMPIDLWITHFLAGS(32, PDUMP_FLAGS_CONTINUOUS);
+#if defined(FIX_HW_BRN_37453)
+ /* we rely on the 32 clk sleep from above */
+
+ /* switch clocks back to auto */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: set clocks back to auto");
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_CLK_CTRL, RGX_CR_CLK_CTRL_ALL_AUTO);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_CLK_CTRL, RGX_CR_CLK_CTRL_ALL_AUTO, PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+ /*
+ * Start the firmware.
+ */
+#if defined(SUPPORT_META_SLAVE_BOOT)
+ RGXStartFirmware(psDevInfo);
+#else
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXStart: RGX Firmware Master boot Start");
+#endif
+
+ OSMemoryBarrier();
+
+ /* Check whether the FW has started by polling on bFirmwareStarted flag */
+ eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc,
+ (IMG_VOID **)&psRGXFWInit);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXStart: Failed to acquire kernel fw if ctl (%u)", eError));
+ return eError;
+ }
+
+ if (PVRSRVPollForValueKM((IMG_UINT32 *)&psRGXFWInit->bFirmwareStarted,
+ IMG_TRUE,
+ 0xFFFFFFFF) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXStart: Polling for 'FW started' flag failed."));
+ eError = PVRSRV_ERROR_TIMEOUT;
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
+ return eError;
+ }
+
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Wait for the Firmware to start.");
+ eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfInitMemDesc,
+ offsetof(RGXFWIF_INIT, bFirmwareStarted),
+ IMG_TRUE,
+ 0xFFFFFFFFU,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXStart: problem pdumping POL for psRGXFWIfInitMemDesc (%d)", eError));
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
+ return eError;
+ }
+#endif
+
+ SetFirmwareStartTime(psRGXFWInit->ui32FirmwareStartedTimeStamp);
+
+ DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfInitMemDesc);
+
+ return eError;
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function RGXStop
+
+ @Description Stop RGX in preparation for power down
+
+ @Input psDevInfo - RGX device info
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR RGXStop(PVRSRV_RGXDEV_INFO *psDevInfo)
+
+{
+ PVRSRV_ERROR eError;
+
+
+ eError = RGXRunScript(psDevInfo, psDevInfo->psScripts->asDeinitCommands, RGX_MAX_DEINIT_COMMANDS, PDUMP_FLAGS_CONTINUOUS, IMG_NULL);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXStop: RGXRunScript failed (%d)", eError));
+ return eError;
+ }
+
+
+ return PVRSRV_OK;
+}
+
+/*
+ RGXInitSLC
+*/
+#if defined(SUPPORT_SHARED_SLC)
+PVRSRV_ERROR RGXInitSLC(IMG_HANDLE hDevHandle)
+{
+
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+
+ if (psDeviceNode == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+#if !defined(FIX_HW_BRN_36492)
+
+ /* reset the SLC */
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXInitSLC: soft reset SLC");
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_SLC_EN);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_SLC_EN, PDUMP_FLAGS_CONTINUOUS);
+
+ /* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
+ OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
+ PDUMPREGREAD64(RGX_PDUMPREG_NAME, RGX_CR_SOFT_RESET, PDUMP_FLAGS_CONTINUOUS);
+
+ /* Take everything out of reset */
+ OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, 0);
+ PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_SOFT_RESET, 0, PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+ RGX_INIT_SLC(psDevInfo);
+
+ return PVRSRV_OK;
+}
+#endif
+
+static IMG_VOID _RGXMakeTimeCorrData(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGX_DATA *psRGXData = (RGX_DATA*)psDeviceNode->psDevConfig->hDevData;
+ RGXFWIF_GPU_UTIL_FWCB *psGpuUtilFWCB = psDevInfo->psRGXFWIfGpuUtilFWCb;
+ RGXFWIF_TIME_CORR *psTimeCorr;
+ IMG_UINT32 ui32NewIndex;
+
+ ui32NewIndex = psGpuUtilFWCB->ui32TimeCorrCurrent + 1;
+ if(ui32NewIndex == RGXFWIF_TIME_CORR_ARRAY_SIZE)
+ {
+ ui32NewIndex = 0;
+ }
+ psTimeCorr = &psGpuUtilFWCB->sTimeCorr[ui32NewIndex];
+
+ psTimeCorr->ui64CRTimeStamp = RGXReadHWTimerReg(psDevInfo);
+ psTimeCorr->ui64OSTimeStamp = OSClockns64();
+ psTimeCorr->ui32DVFSClock = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
+
+ /* Make sure the values are written to memory before updating the index of the current entry */
+ OSWriteMemoryBarrier();
+
+ psGpuUtilFWCB->ui32TimeCorrCurrent = ui32NewIndex;
+
+ PVR_DPF((PVR_DBG_MESSAGE,"RGXMakeTimeCorrData: Correlating OS timestamp %llu (ns) with CR timestamp %llu, GPU clock speed %uHz",
+ psTimeCorr->ui64OSTimeStamp, psTimeCorr->ui64CRTimeStamp, psTimeCorr->ui32DVFSClock));
+}
+
+static IMG_VOID _RGXFWCBEntryAdd(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64TimeStamp, IMG_UINT32 ui32Type)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_GPU_UTIL_FWCB *psRGXFWIfGpuUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
+
+ switch(ui32Type)
+ {
+ case RGXFWIF_GPU_UTIL_FWCB_TYPE_CRTIME:
+ {
+ RGX_GPU_DVFS_HIST *psGpuDVFSHistory = psDevInfo->psGpuDVFSHistory;
+ RGX_DATA *psRGXData = (RGX_DATA*)psDeviceNode->psDevConfig->hDevData;
+
+ /* Advance DVFS history ID */
+ psGpuDVFSHistory->ui32CurrentDVFSId++;
+ if (psGpuDVFSHistory->ui32CurrentDVFSId >= RGX_GPU_DVFS_HIST_SIZE)
+ {
+ psGpuDVFSHistory->ui32CurrentDVFSId = 0;
+ }
+
+ /* Update DVFS history ID that is used by the Host to populate state changes CB */
+ psRGXFWIfGpuUtilFWCb->ui32CurrentDVFSId = psGpuDVFSHistory->ui32CurrentDVFSId;
+
+ /* Store new DVFS freq into DVFS history entry */
+ psGpuDVFSHistory->aui32DVFSClockCB[psGpuDVFSHistory->ui32CurrentDVFSId] = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
+ }
+ /* 'break;' missing on purpose */
+
+ case RGXFWIF_GPU_UTIL_FWCB_TYPE_END_CRTIME:
+ /* The DVFS history ID in this case is the same as the last one set by the Firmware,
+ * no need to add an identical copy in the DVFS history buffer */
+
+ /* Populate DVFS history entry (the GPU state is the same as in the last FW entry in this CB) */
+ psRGXFWIfGpuUtilFWCb->aui64CB[psRGXFWIfGpuUtilFWCb->ui32WriteOffset] =
+ ((ui64TimeStamp << RGXFWIF_GPU_UTIL_FWCB_TIMER_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_CR_TIMER_MASK) |
+ (((IMG_UINT64)psRGXFWIfGpuUtilFWCb->ui32LastGpuUtilState << RGXFWIF_GPU_UTIL_FWCB_STATE_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_STATE_MASK) |
+ (((IMG_UINT64)ui32Type << RGXFWIF_GPU_UTIL_FWCB_TYPE_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_TYPE_MASK) |
+ (((IMG_UINT64)psRGXFWIfGpuUtilFWCb->ui32CurrentDVFSId << RGXFWIF_GPU_UTIL_FWCB_ID_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_ID_MASK);
+ break;
+
+ case RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON:
+ case RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_OFF:
+ /* Populate DVFS history entry (the GPU state is the same as in the last FW entry in this CB) */
+ psRGXFWIfGpuUtilFWCb->aui64CB[psRGXFWIfGpuUtilFWCb->ui32WriteOffset] =
+ ((ui64TimeStamp << RGXFWIF_GPU_UTIL_FWCB_TIMER_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_OS_TIMER_MASK) |
+ (((IMG_UINT64)psRGXFWIfGpuUtilFWCb->ui32LastGpuUtilState << RGXFWIF_GPU_UTIL_FWCB_STATE_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_STATE_MASK) |
+ (((IMG_UINT64)ui32Type << RGXFWIF_GPU_UTIL_FWCB_TYPE_SHIFT) & RGXFWIF_GPU_UTIL_FWCB_TYPE_MASK);
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"RGXFWCBEntryAdd: Wrong entry type"));
+ break;
+ }
+
+ psRGXFWIfGpuUtilFWCb->ui32WriteOffset++;
+ if(psRGXFWIfGpuUtilFWCb->ui32WriteOffset >= RGXFWIF_GPU_UTIL_FWCB_SIZE)
+ {
+ psRGXFWIfGpuUtilFWCb->ui32WriteOffset = 0;
+ }
+}
+
+/*
+ RGXPrePowerState
+*/
+PVRSRV_ERROR RGXPrePowerState (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ IMG_BOOL bForced)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON))
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_KCCB_CMD sPowCmd;
+ RGXFWIF_TRACEBUF *psFWTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+ IMG_UINT32 ui32DM;
+
+ /* 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.uPoweReqData.bForced = bForced;
+
+ SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+
+ /* Send one pow command to each DM to make sure we flush all the DMs pipelines */
+ for (ui32DM = 0; ui32DM < RGXFWIF_DM_MAX; ui32DM++)
+ {
+ eError = RGXSendCommandRaw(psDevInfo,
+ ui32DM,
+ &sPowCmd,
+ sizeof(sPowCmd),
+ 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPrePowerState: Failed to send Power off request for DM%d", ui32DM));
+ 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 = PVRSRVPollForValueKM(psDevInfo->psPowSyncPrim->pui32LinAddr, 0x1, 0xFFFFFFFF);
+
+ /* Check the Power state after the answer */
+ if (eError == PVRSRV_OK)
+ {
+ /* Finally, de-initialise some registers. */
+ if (psFWTraceBuf->ePowState == RGXFWIF_POW_OFF)
+ {
+#if !defined(NO_HARDWARE)
+ /* Wait for the pending META to host interrupts to come back. */
+ eError = PVRSRVPollForValueKM(&g_ui32HostSampleIRQCount,
+ psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount,
+ 0xffffffff);
+#endif /* NO_HARDWARE */
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPrePowerState: Wait for pending interrupts failed. Host:%d, FW: %d",
+ g_ui32HostSampleIRQCount,
+ psDevInfo->psRGXFWIfTraceBuf->ui32InterruptCount));
+ }
+ else
+ {
+ IMG_UINT64 ui64CRTimeStamp = RGXReadHWTimerReg(psDevInfo);
+ IMG_UINT64 ui64OSTimeStamp = OSClockus64();
+
+ /* Add two entries to the GPU utilisation FWCB (current CR timestamp and current OS timestamp)
+ * so that RGXGetGpuUtilStats() can link a power-on period to a previous power-off period (this one) */
+ _RGXFWCBEntryAdd(psDeviceNode, ui64CRTimeStamp, RGXFWIF_GPU_UTIL_FWCB_TYPE_END_CRTIME);
+ _RGXFWCBEntryAdd(psDeviceNode, ui64OSTimeStamp, RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_OFF);
+
+ eError = RGXStop(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPrePowerState: RGXStop failed (%s)", PVRSRVGetErrorStringKM(eError)));
+ eError = PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE;
+ }
+ psDevInfo->bIgnoreFurtherIRQs = IMG_TRUE;
+ }
+ }
+ else
+ {
+ /* the sync was updated bu the pow state isn't off -> the FW denied the transition */
+ eError = PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED;
+ }
+ }
+ else if (eError == PVRSRV_ERROR_TIMEOUT)
+ {
+ /* timeout waiting for the FW to ack the request: return timeout */
+ PVR_DPF((PVR_DBG_WARNING,"RGXPrePowerState: Timeout waiting for powoff ack from the FW"));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPrePowerState: Error waiting for powoff ack from the FW (%s)", PVRSRVGetErrorStringKM(eError)));
+ eError = PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE;
+ }
+
+ }
+
+ return eError;
+}
+
+
+/*
+ RGXPostPowerState
+*/
+PVRSRV_ERROR RGXPostPowerState (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ IMG_BOOL bForced)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+ IMG_UINT64 ui64CRTimeStamp = RGXReadHWTimerReg(psDevInfo);
+ IMG_UINT64 ui64OSTimeStamp = OSClockus64();
+
+ /* Add two entries to the GPU utilisation FWCB (current OS timestamp and current CR timestamp)
+ * so that RGXGetGpuUtilStats() can link a power-on (this one) period to a previous power-off period */
+ _RGXFWCBEntryAdd(psDeviceNode, ui64OSTimeStamp, RGXFWIF_GPU_UTIL_FWCB_TYPE_POWER_ON);
+ _RGXFWCBEntryAdd(psDeviceNode, ui64CRTimeStamp, RGXFWIF_GPU_UTIL_FWCB_TYPE_CRTIME);
+
+ /* Update the timer correlation data */
+ _RGXMakeTimeCorrData(psDeviceNode);
+
+ /*
+ Run the RGX init script.
+ */
+ eError = RGXStart(psDevInfo, psDevConfig);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPostPowerState: RGXStart failed"));
+ return eError;
+ }
+
+ /* Coming up from off, re-allow RGX interrupts. */
+ psDevInfo->bIgnoreFurtherIRQs = IMG_FALSE;
+
+ }
+ }
+
+ PDUMPCOMMENT("RGXPostPowerState: Current state: %d, New state: %d", eCurrentPowerState, eNewPowerState);
+
+ return PVRSRV_OK;
+}
+
+
+/*
+ RGXPreClockSpeedChange
+*/
+PVRSRV_ERROR RGXPreClockSpeedChange (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ 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_TRACEBUF *psFWTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+
+ 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)
+ && (psFWTraceBuf->ePowState != RGXFWIF_POW_OFF))
+ {
+ if (bIdleDevice)
+ {
+ RGXFWIF_KCCB_CMD sPowCmd;
+
+ /* 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.uPoweReqData.bCancelForcedIdle = IMG_FALSE;
+
+ SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+
+ /* Clock speed changes aren't currently supported in pdumps */
+ PDUMPPOWCMDSTART();
+ /* Send one forced IDLE command to GP */
+ eError = RGXSendCommandRaw(psDevInfo,
+ RGXFWIF_DM_GP,
+ &sPowCmd,
+ sizeof(sPowCmd),
+ 0);
+ PDUMPPOWCMDEND();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPreClockSpeedChange: Failed to send IDLE request for DM%d", RGXFWIF_DM_GP));
+ return eError;
+ }
+
+ /* Wait for the firmware to complete processing. */
+ eError = PVRSRVPollForValueKM(psDevInfo->psPowSyncPrim->pui32LinAddr, 0x1, 0xFFFFFFFF);
+
+ /* Check the Power state after the answer */
+ if (eError == PVRSRV_OK)
+ {
+ if (psFWTraceBuf->ePowState != RGXFWIF_POW_FORCED_IDLE)
+ {
+ /* the sync was updated but the pow state isn't idle -> the FW denied the transition */
+ eError = PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED;
+ }
+ }
+ else if (eError == PVRSRV_ERROR_TIMEOUT)
+ {
+ /* timeout waiting for the FW to ack the request: return timeout */
+ PVR_DPF((PVR_DBG_ERROR,"RGXPreClockSpeedChange: Timeout waiting for idle ack from the FW"));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPreClockSpeedChange: Error waiting for idle ack from the FW (%s)", PVRSRVGetErrorStringKM(eError)));
+ eError = PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE;
+ }
+
+ if (eError != PVRSRV_OK)
+ {
+ RGXFWIF_KCCB_CMD sPowCmd;
+ PVRSRV_ERROR eError2;
+
+ /* 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.uPoweReqData.bCancelForcedIdle = IMG_TRUE;
+
+ SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+
+ PDUMPPOWCMDSTART();
+ /* Send one forced IDLE command to GP */
+ eError2 = RGXSendCommandRaw(psDevInfo,
+ RGXFWIF_DM_GP,
+ &sPowCmd,
+ sizeof(sPowCmd),
+ 0);
+ PDUMPPOWCMDEND();
+
+ if (eError2 != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPostClockSpeedChange: Failed to send Cancel IDLE request for DM%d", RGXFWIF_DM_GP));
+ }
+ }
+ }
+
+ if (eError == PVRSRV_OK)
+ {
+ /* Advance DVFS history ID */
+ psDevInfo->psGpuDVFSHistory->ui32CurrentDVFSId++;
+ if (psDevInfo->psGpuDVFSHistory->ui32CurrentDVFSId >= RGX_GPU_DVFS_HIST_SIZE)
+ {
+ psDevInfo->psGpuDVFSHistory->ui32CurrentDVFSId = 0;
+ }
+
+ /* Update DVFS history ID that is used by the FW to populate state changes CB */
+ psDevInfo->psRGXFWIfGpuUtilFWCb->ui32CurrentDVFSId = psDevInfo->psGpuDVFSHistory->ui32CurrentDVFSId;
+ /* Populate DVFS history entry */
+ psDevInfo->psGpuDVFSHistory->aui32DVFSClockCB[psDevInfo->psGpuDVFSHistory->ui32CurrentDVFSId] = 0;
+ }
+ }
+
+ return eError;
+}
+
+
+/*
+ RGXPostClockSpeedChange
+*/
+PVRSRV_ERROR RGXPostClockSpeedChange (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ 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_TRACEBUF *psFWTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+ IMG_UINT32 ui32NewClockSpeed = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
+
+ /* Update runtime configuration with the new value */
+ psDevInfo->psRGXFWIfRuntimeCfg->ui32CoreClockSpeed = ui32NewClockSpeed;
+
+ if ((eCurrentPowerState != PVRSRV_DEV_POWER_STATE_OFF)
+ && (psFWTraceBuf->ePowState != RGXFWIF_POW_OFF))
+ {
+ RGXFWIF_KCCB_CMD sCOREClkSpeedChangeCmd;
+
+ /* Update the timer correlation data */
+ _RGXMakeTimeCorrData(psDeviceNode);
+
+ 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();
+
+ /* Store new DVFS freq into DVFS history entry */
+ psDevInfo->psGpuDVFSHistory->aui32DVFSClockCB[psDevInfo->psGpuDVFSHistory->ui32CurrentDVFSId] = ui32NewClockSpeed;
+
+ PDUMPCOMMENT("Scheduling CORE clock speed change command");
+
+ PDUMPPOWCMDSTART();
+ eError = RGXSendCommandRaw(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sCOREClkSpeedChangeCmd,
+ sizeof(sCOREClkSpeedChangeCmd),
+ 0);
+ PDUMPPOWCMDEND();
+
+ if (eError != PVRSRV_OK)
+ {
+ PDUMPCOMMENT("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));
+ }
+
+ if ((eCurrentPowerState != PVRSRV_DEV_POWER_STATE_OFF)
+ && (psFWTraceBuf->ePowState == RGXFWIF_POW_FORCED_IDLE)
+ && bIdleDevice)
+ {
+ RGXFWIF_KCCB_CMD sPowCmd;
+
+ /* 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.uPoweReqData.bCancelForcedIdle = IMG_TRUE;
+
+ SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+
+ /* Clock speed changes aren't currently supported in pdumps */
+ PDUMPPOWCMDSTART();
+ /* Send one forced IDLE command to GP */
+ eError = RGXSendCommandRaw(psDevInfo,
+ RGXFWIF_DM_GP,
+ &sPowCmd,
+ sizeof(sPowCmd),
+ 0);
+ PDUMPPOWCMDEND();
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXPostClockSpeedChange: Failed to send Cancel IDLE request for DM%d", RGXFWIF_DM_GP));
+ return eError;
+ }
+ }
+
+ return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function RGXDustCountChange
+
+ @Description
+
+ Does change of number of DUSTs
+
+ @Input hDevHandle : RGX Device Node
+ @Input ui32NumberOfDusts : Number of DUSTs to make transition to
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXDustCountChange(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32NumberOfDusts)
+{
+
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+ RGXFWIF_KCCB_CMD sDustCountChange;
+ IMG_UINT32 ui32MaxAvailableDusts = RGX_FEATURE_NUM_CLUSTERS / 2;
+
+ PVR_ASSERT(ui32MaxAvailableDusts > 1);
+
+ if ((ui32NumberOfDusts == 0) || (ui32NumberOfDusts > ui32MaxAvailableDusts))
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ PVR_DPF((PVR_DBG_ERROR,
+ "RGXDustCountChange: Invalid number of DUSTs (%u) while expecting value within <1,%u>. Error:%u",
+ ui32NumberOfDusts,
+ ui32MaxAvailableDusts,
+ eError));
+ return eError;
+ }
+
+ SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+
+ sDustCountChange.eCmdType = RGXFWIF_KCCB_CMD_POW;
+ sDustCountChange.uCmdData.sPowData.ePowType = RGXFWIF_POW_NUMDUST_CHANGE;
+ sDustCountChange.uCmdData.sPowData.uPoweReqData.ui32NumOfDusts = ui32NumberOfDusts;
+
+ PDUMPCOMMENT("Scheduling command to change Dust Count to %u", ui32NumberOfDusts);
+ eError = RGXSendCommandRaw(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sDustCountChange,
+ sizeof(sDustCountChange),
+ 0);
+
+ if (eError != PVRSRV_OK)
+ {
+ PDUMPCOMMENT("Scheduling command to change Dust Count failed. Error:%u", eError);
+ PVR_DPF((PVR_DBG_ERROR, "RGXDustCountChange: Scheduling KCCB to change Dust Count failed. Error:%u", eError));
+ return eError;
+ }
+
+ /* Wait for the firmware to answer. */
+ eError = PVRSRVPollForValueKM(psDevInfo->psPowSyncPrim->pui32LinAddr, 0x1, 0xFFFFFFFF);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXDustCountChange: Timeout waiting for idle request"));
+ return eError;
+ }
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("RGXDustCountChange: 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 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;
+ PVRSRV_DEV_POWER_STATE ePowerState;
+
+ eError = PVRSRVPowerLock();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXAPMLatencyChange: Failed to acquire power lock"));
+ return eError;
+ }
+
+ /* Update runtime configuration with the new values */
+ psRuntimeCfg->ui32ActivePMLatencyms = ui32ActivePMLatencyms;
+ psRuntimeCfg->bActivePMLatencyPersistant = bActivePMLatencyPersistant;
+
+ eError = PVRSRVGetDevicePowerState(psDeviceNode->sDevId.ui32DeviceIndex, &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;
+ sActivePMLatencyChange.uCmdData.sPowData.uPoweReqData.ui32ActivePMLatencyms = ui32ActivePMLatencyms;
+
+ /* Ensure the new APM latency is written to memory before requesting the FW to read it */
+ OSMemoryBarrier();
+
+ PDUMPCOMMENT("Scheduling command to change APM latency to %u", ui32ActivePMLatencyms);
+ eError = RGXSendCommandRaw(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sActivePMLatencyChange,
+ sizeof(sActivePMLatencyChange),
+ 0);
+
+ if (eError != PVRSRV_OK)
+ {
+ PDUMPCOMMENT("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));
+ return eError;
+ }
+ }
+
+ PVRSRVPowerUnlock();
+
+ return PVRSRV_OK;
+}
+
+/*
+ RGXActivePowerRequest
+*/
+PVRSRV_ERROR RGXActivePowerRequest(IMG_HANDLE hDevHandle)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_TRACEBUF *psFWTraceBuf = psDevInfo->psRGXFWIfTraceBuf;
+
+ OSAcquireBridgeLock();
+ OSSetKeepPVRLock();
+
+ /* 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) */
+ eError = PVRSRVPowerLock();
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXActivePowerRequest: Failed to acquire PowerLock (device index: %d, error: %s)",
+ psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRVGetErrorStringKM(eError)));
+ goto _RGXActivePowerRequest_PowerLock_failed;
+ }
+
+ /* Check again for IDLE once we have the power lock */
+ if (psFWTraceBuf->ePowState == RGXFWIF_POW_IDLE)
+ {
+
+ psDevInfo->ui32ActivePMReqTotal++;
+
+ SetFirmwareHandshakeIdleTime(RGXReadHWTimerReg(psDevInfo)-psFWTraceBuf->ui64StartIdleTime);
+
+ PDUMPPOWCMDSTART();
+ eError =
+ PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ IMG_FALSE); /* forced */
+ PDUMPPOWCMDEND();
+
+ if (eError == PVRSRV_OK)
+ {
+ psDevInfo->ui32ActivePMReqOk++;
+ }
+ else if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED)
+ {
+ psDevInfo->ui32ActivePMReqDenied++;
+ }
+
+ }
+
+ PVRSRVPowerUnlock();
+
+_RGXActivePowerRequest_PowerLock_failed:
+ OSSetReleasePVRLock();
+ OSReleaseBridgeLock();
+
+ return eError;
+
+}
+
+
+/******************************************************************************
+ End of file (rgxpower.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxpower.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxpower.h
new file mode 100644
index 000000000000..d4658539fed3
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxpower.h
@@ -0,0 +1,189 @@
+/*************************************************************************/ /*!
+@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"
+
+
+/*!
+******************************************************************************
+
+ @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,
+ IMG_BOOL bForced);
+
+/*!
+******************************************************************************
+
+ @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,
+ IMG_BOOL bForced);
+
+
+/*!
+******************************************************************************
+
+ @Function RGXPreClockSpeedChange
+
+ @Description
+
+ Does processing required before an RGX clock speed change.
+
+ @Input hDevHandle : RGX Device Node
+ @Input bIdleDevice : Whether the firmware needs to be idled
+ @Input eCurrentPowerState : Power state of the device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+/*!
+******************************************************************************
+
+ @Function RGXPostClockSpeedChange
+
+ @Description
+
+ Does processing required after an RGX clock speed change.
+
+ @Input hDevHandle : RGX Device Node
+ @Input bIdleDevice : Whether the firmware had been idled previously
+ @Input eCurrentPowerState : Power state of the device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+
+/*!
+******************************************************************************
+
+ @Function RGXDustCountChange
+
+ @Description Change of number of DUSTs
+
+ @Input hDevHandle : RGX Device Node
+ @Input ui32NumberOfDusts : Number of DUSTs to make transition to
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXDustCountChange(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32NumberOfDusts);
+/*!
+******************************************************************************
+
+ @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 bPersistent : 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);
+
+#endif /* __RGXPOWER_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxregconfig.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxregconfig.c
new file mode 100644
index 000000000000..5a4ab228d704
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxregconfig.c
@@ -0,0 +1,227 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX Register configuration
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX Regconfig 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 "rgxregconfig.h"
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "device.h"
+#include "sync_internal.h"
+#include "pdump_km.h"
+#include "pvrsrv.h"
+PVRSRV_ERROR PVRSRVRGXSetRegConfigPIKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT8 ui8RegPowerIsland)
+{
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGX_REG_CONFIG *psRegCfg = &psDevInfo->sRegCongfig;
+ RGXFWIF_PWR_EVT ePowerIsland = (RGXFWIF_PWR_EVT) ui8RegPowerIsland;
+
+
+ if (ePowerIsland < psRegCfg->ePowerIslandToPush)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSetRegConfigPIKM: Register configuration must be in power island order."));
+ return PVRSRV_ERROR_REG_CONFIG_INVALID_PI;
+ }
+
+ psRegCfg->ePowerIslandToPush = ePowerIsland;
+
+ return eError;
+#else
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSetRegConfigPIKM: Feature disabled. Compile with SUPPORT_USER_REGISTER_CONFIGURATION"));
+ return PVRSRV_ERROR_REG_CONFIG_FEATURE_DISABLED;
+#endif
+}
+
+PVRSRV_ERROR PVRSRVRGXAddRegConfigKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT64 ui64RegValue)
+{
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sRegCfgCmd;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGX_REG_CONFIG *psRegCfg = &psDevInfo->sRegCongfig;
+
+ if (psRegCfg->bEnabled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSetRegConfigPIKM: Cannot add record whilst register configuration active."));
+ return PVRSRV_ERROR_REG_CONFIG_ENABLED;
+ }
+ if (psRegCfg->ui32NumRegRecords == RGXFWIF_REG_CFG_MAX_SIZE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSetRegConfigPIKM: Register configuration full."));
+ return PVRSRV_ERROR_REG_CONFIG_FULL;
+ }
+
+ sRegCfgCmd.eCmdType = RGXFWIF_KCCB_CMD_REGCONFIG;
+ sRegCfgCmd.uCmdData.sRegConfigData.sRegConfig.ui64Addr = (IMG_UINT64) ui32RegAddr;
+ sRegCfgCmd.uCmdData.sRegConfigData.sRegConfig.ui64Value = ui64RegValue;
+ sRegCfgCmd.uCmdData.sRegConfigData.eRegConfigPI = psRegCfg->ePowerIslandToPush;
+ sRegCfgCmd.uCmdData.sRegConfigData.eCmdType = RGXFWIF_REGCFG_CMD_ADD;
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sRegCfgCmd,
+ sizeof(sRegCfgCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXAddRegConfigKM: RGXScheduleCommand failed. Error:%u", eError));
+ return eError;
+ }
+
+ psRegCfg->ui32NumRegRecords++;
+
+ return eError;
+#else
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSetRegConfigPIKM: Feature disabled. Compile with SUPPORT_USER_REGISTER_CONFIGURATION"));
+ return PVRSRV_ERROR_REG_CONFIG_FEATURE_DISABLED;
+#endif
+}
+
+PVRSRV_ERROR PVRSRVRGXClearRegConfigKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sRegCfgCmd;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGX_REG_CONFIG *psRegCfg = &psDevInfo->sRegCongfig;
+
+ if (psRegCfg->bEnabled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSetRegConfigPIKM: Attempt to clear register configuration whilst active."));
+ return PVRSRV_ERROR_REG_CONFIG_ENABLED;
+ }
+
+ sRegCfgCmd.eCmdType = RGXFWIF_KCCB_CMD_REGCONFIG;
+ sRegCfgCmd.uCmdData.sRegConfigData.eCmdType = RGXFWIF_REGCFG_CMD_CLEAR;
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sRegCfgCmd,
+ sizeof(sRegCfgCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXClearRegConfigKM: RGXScheduleCommand failed. Error:%u", eError));
+ return eError;
+ }
+
+ psRegCfg->ui32NumRegRecords = 0;
+ psRegCfg->ePowerIslandToPush = RGXFWIF_PWR_EVT_PWR_ON; /* Default first PI */
+
+ return eError;
+#else
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXClearRegConfigKM: Feature disabled. Compile with SUPPORT_USER_REGISTER_CONFIGURATION"));
+ return PVRSRV_ERROR_REG_CONFIG_FEATURE_DISABLED;
+#endif
+}
+
+PVRSRV_ERROR PVRSRVRGXEnableRegConfigKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sRegCfgCmd;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGX_REG_CONFIG *psRegCfg = &psDevInfo->sRegCongfig;
+
+ sRegCfgCmd.eCmdType = RGXFWIF_KCCB_CMD_REGCONFIG;
+ sRegCfgCmd.uCmdData.sRegConfigData.eCmdType = RGXFWIF_REGCFG_CMD_ENABLE;
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sRegCfgCmd,
+ sizeof(sRegCfgCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXEnableRegConfigKM: RGXScheduleCommand failed. Error:%u", eError));
+ return eError;
+ }
+
+ psRegCfg->bEnabled = IMG_TRUE;
+
+ return eError;
+#else
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXEnableRegConfigKM: Feature disabled. Compile with SUPPORT_USER_REGISTER_CONFIGURATION"));
+ return PVRSRV_ERROR_REG_CONFIG_FEATURE_DISABLED;
+#endif
+}
+
+PVRSRV_ERROR PVRSRVRGXDisableRegConfigKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_KCCB_CMD sRegCfgCmd;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGX_REG_CONFIG *psRegCfg = &psDevInfo->sRegCongfig;
+
+ sRegCfgCmd.eCmdType = RGXFWIF_KCCB_CMD_REGCONFIG;
+ sRegCfgCmd.uCmdData.sRegConfigData.eCmdType = RGXFWIF_REGCFG_CMD_DISABLE;
+
+ eError = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sRegCfgCmd,
+ sizeof(sRegCfgCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXDisableRegConfigKM: RGXScheduleCommand failed. Error:%u", eError));
+ return eError;
+ }
+
+ psRegCfg->bEnabled = IMG_FALSE;
+
+ return eError;
+#else
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXDisableRegConfigKM: Feature disabled. Compile with SUPPORT_USER_REGISTER_CONFIGURATION"));
+ return PVRSRV_ERROR_REG_CONFIG_FEATURE_DISABLED;
+#endif
+}
+
+
+/******************************************************************************
+ End of file (rgxregconfig.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxregconfig.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxregconfig.h
new file mode 100644
index 000000000000..bbe15866f636
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxregconfig.h
@@ -0,0 +1,123 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX register configuration functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the RGX register configuration 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(__RGXREGCONFIG_H__)
+#define __RGXREGCONFIG_H__
+
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgx_fwif_km.h"
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXSetRegConfigPIKM
+
+ @Description
+ Server-side implementation of RGXSetRegConfig
+
+ @Input psDeviceNode - RGX Device node
+ @Input ui8RegPowerIsland - Reg configuration
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXSetRegConfigPIKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT8 ui8RegPowerIsland);
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXSetRegConfigKM
+
+ @Description
+ Server-side implementation of RGXSetRegConfig
+
+ @Input psDeviceNode - RGX Device node
+ @Input ui64RegAddr - Register address
+ @Input ui64RegValue - Reg value
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+
+PVRSRV_ERROR PVRSRVRGXAddRegConfigKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui64RegAddr,
+ IMG_UINT64 ui64RegValue);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXClearRegConfigKM
+
+ @Description
+ Server-side implementation of RGXClearRegConfig
+
+ @Input psDeviceNode - RGX Device node
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXClearRegConfigKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXEnableRegConfigKM
+
+ @Description
+ Server-side implementation of RGXEnableRegConfig
+
+ @Input psDeviceNode - RGX Device node
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXEnableRegConfigKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/*!
+*******************************************************************************
+ @Function PVRSRVRGXDisableRegConfigKM
+
+ @Description
+ Server-side implementation of RGXDisableRegConfig
+
+ @Input psDeviceNode - RGX Device node
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXDisableRegConfigKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#endif /* __RGXREGCONFIG_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxsync.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxsync.c
new file mode 100644
index 000000000000..f48ee413d3ff
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxsync.c
@@ -0,0 +1,197 @@
+/*************************************************************************/ /*!
+@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 "srvkm.h"
+#include "pdump_km.h"
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "osfunc.h"
+#include "rgxccb.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+
+#include "rgxsync.h"
+
+PVRSRV_ERROR RGXKickSyncKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+ RGXFWIF_DM eDM,
+ IMG_CHAR *pszCommandName,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress,
+ IMG_UINT32 *paui32ClientFenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress,
+ IMG_UINT32 *paui32ClientUpdateValue,
+ IMG_UINT32 ui32ServerSyncPrims,
+ IMG_UINT32 *paui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerSyncs,
+ IMG_BOOL bPDumpContinuous)
+{
+ RGXFWIF_KCCB_CMD sCmpKCCBCmd;
+ RGX_CCB_CMD_HELPER_DATA sCmdHelperData;
+ IMG_BOOL bKickRequired;
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError2;
+ IMG_UINT32 i;
+
+ /* Sanity check the server fences */
+ for (i=0;i<ui32ServerSyncPrims;i++)
+ {
+ if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on %s) must fence", __FUNCTION__, pszCommandName));
+ return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
+ }
+ }
+
+ eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psServerCommonContext),
+ ui32ClientFenceCount,
+ pauiClientFenceUFOAddress,
+ paui32ClientFenceValue,
+ ui32ClientUpdateCount,
+ pauiClientUpdateUFOAddress,
+ paui32ClientUpdateValue,
+ ui32ServerSyncPrims,
+ paui32ServerSyncFlags,
+ pasServerSyncs,
+ 0, /* ui32CmdSize */
+ IMG_NULL, /* pui8DMCmd */
+ IMG_NULL, /* ppPreAddr */
+ IMG_NULL, /* ppPostAddr */
+ IMG_NULL, /* ppRMWUFOAddr */
+ RGXFWIF_CCB_CMD_TYPE_NULL,
+ bPDumpContinuous,
+ pszCommandName,
+ &sCmdHelperData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_cmdinit;
+ }
+
+ eError = RGXCmdHelperAcquireCmdCCB(1, &sCmdHelperData, &bKickRequired);
+ if ((eError != PVRSRV_OK) && (!bKickRequired))
+ {
+ /*
+ Only bail if no new data was submitted into the client CCB, we might
+ have already submitted a padding packet which we should flush through
+ the FW.
+ */
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create client CCB command", __FUNCTION__));
+ goto fail_cmdaquire;
+ }
+
+
+ /*
+ We should reserved 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
+ */
+ RGXCmdHelperReleaseCmdCCB(1, &sCmdHelperData, pszCommandName, FWCommonContextGetFWAddress(psServerCommonContext).ui32Addr);
+ }
+
+ /* Construct the kernel compute CCB command. */
+ sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+ sCmpKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psServerCommonContext);
+ sCmpKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psServerCommonContext));
+ sCmpKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+ /*
+ * Submit the compute command to the firmware.
+ */
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError2 = RGXScheduleCommand(psDeviceNode->pvDevice,
+ eDM,
+ &sCmpKCCBCmd,
+ sizeof(sCmpKCCBCmd),
+ bPDumpContinuous);
+ 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. (0x%x)", __FUNCTION__, eError));
+ }
+ /*
+ * 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;
+ }
+
+ return PVRSRV_OK;
+
+fail_cmdaquire:
+fail_cmdinit:
+
+ return eError;
+}
+
+/******************************************************************************
+ End of file (rgxsync.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxsync.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxsync.h
new file mode 100644
index 000000000000..4b86f1bae46e
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxsync.h
@@ -0,0 +1,80 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX sync kick 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(__RGXSYNC__)
+#define __RGXSYNC_H__
+
+#include "devicemem.h"
+#include "device.h"
+#include "rgxfwutils.h"
+#include "rgx_fwif_resetframework.h"
+#include "rgxdebug.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "connection_server.h"
+
+/*!
+*******************************************************************************
+ @Function RGXKickSyncKM
+
+ @Description Send a sync kick command to the FW
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXKickSyncKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+ RGXFWIF_DM eDM,
+ IMG_CHAR *pszCommandName,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress,
+ IMG_UINT32 *paui32ClientFenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress,
+ IMG_UINT32 *paui32ClientUpdateValue,
+ IMG_UINT32 ui32ServerSyncPrims,
+ IMG_UINT32 *paui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerSyncs,
+ IMG_BOOL bPDumpContinuous);
+
+#endif /* __RGXSYNC_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxta3d.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxta3d.c
new file mode 100644
index 000000000000..e47c2c147372
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxta3d.c
@@ -0,0 +1,3423 @@
+/*************************************************************************/ /*!
+@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 */
+#include <stddef.h>
+
+#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 "rgxtimerquery.h"
+#include "rgxsync.h"
+
+#include "rgxdefs_km.h"
+#include "rgx_fwif_km.h"
+#include "physmem.h"
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "process_stats.h"
+#include "osfunc.h"
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#include "pvr_sync.h"
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+typedef struct _DEVMEM_REF_LOOKUP_
+{
+ IMG_UINT32 ui32ZSBufferID;
+ RGX_ZSBUFFER_DATA *psZSBuffer;
+} DEVMEM_REF_LOOKUP;
+
+typedef struct _DEVMEM_FREELIST_LOOKUP_
+{
+ IMG_UINT32 ui32FreeListID;
+ RGX_FREELIST *psFreeList;
+} DEVMEM_FREELIST_LOOKUP;
+
+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_ {
+ 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)
+ PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync;
+ DLLIST_NODE sListNode;
+};
+
+
+static
+#ifdef __GNUC__
+ __attribute__((noreturn))
+#endif
+void sleep_for_ever(void)
+{
+#if defined(__KLOCWORK__) // klocworks would report an infinite loop because of while(1).
+ PVR_ASSERT(0);
+#else
+ while(1)
+ {
+ OSSleepms(~0); // sleep the maximum amount of time possible
+ }
+#endif
+}
+
+
+/*
+ Static functions used by render context code
+*/
+
+static
+PVRSRV_ERROR _DestroyTAContext(RGX_SERVER_RC_TA_DATA *psTAData,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
+{
+ PVRSRV_ERROR eError;
+
+ /* Check if the FW has finished with this resource ... */
+ eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
+ FWCommonContextGetFWAddress(psTAData->psServerCommonContext),
+ psCleanupSync,
+ RGXFWIF_DM_TA);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ return eError;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+ __FUNCTION__,
+ PVRSRVGetErrorStringKM(eError)));
+ return eError;
+ }
+
+ /* ... it has so we can free it's resources */
+#if defined(DEBUG)
+ /* Log the number of TA context stores which occurred */
+ {
+ RGXFWIF_TACTX_STATE *psFWTAState;
+
+ eError = DevmemAcquireCpuVirtAddr(psTAData->psContextStateMemDesc,
+ (IMG_VOID**)&psFWTAState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Failed to map firmware render context state (%u)",
+ __FUNCTION__, eError));
+ }
+ else
+ {
+ /* Release the CPU virt addr */
+ DevmemReleaseCpuVirtAddr(psTAData->psContextStateMemDesc);
+ }
+ }
+#endif
+ FWCommonContextFree(psTAData->psServerCommonContext);
+ DevmemFwFree(psTAData->psContextStateMemDesc);
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR _Destroy3DContext(RGX_SERVER_RC_3D_DATA *ps3DData,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
+{
+ PVRSRV_ERROR eError;
+
+ /* Check if the FW has finished with this resource ... */
+ eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
+ FWCommonContextGetFWAddress(ps3DData->psServerCommonContext),
+ psCleanupSync,
+ RGXFWIF_DM_3D);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ return eError;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+ __FUNCTION__,
+ PVRSRVGetErrorStringKM(eError)));
+ return eError;
+ }
+
+ /* ... it has so we can free it's resources */
+#if defined(DEBUG)
+ /* Log the number of 3D context stores which occurred */
+ {
+ RGXFWIF_3DCTX_STATE *psFW3DState;
+
+ eError = DevmemAcquireCpuVirtAddr(ps3DData->psContextStateMemDesc,
+ (IMG_VOID**)&psFW3DState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Failed to map firmware render context state (%u)",
+ __FUNCTION__, eError));
+ }
+ else
+ {
+ /* Release the CPU virt addr */
+ DevmemReleaseCpuVirtAddr(ps3DData->psContextStateMemDesc);
+ }
+ }
+#endif
+
+ FWCommonContextFree(ps3DData->psServerCommonContext);
+ DevmemFwFree(ps3DData->psContextStateMemDesc);
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL _RGXDumpPMRPageList(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ 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 (%u) printing pmr %p", eError, psPMRNode->psPMR));
+ }
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL RGXDumpFreeListPageList(RGX_FREELIST *psFreeList)
+{
+ PVR_LOG(("Freelist FWAddr 0x%08x, ID = %d, CheckSum 0x%016llx",
+ psFreeList->sFreeListFWDevVAddr.ui32Addr,
+ psFreeList->ui32FreelistID,
+ psFreeList->ui64FreelistChecksum));
+
+ /* Dump Init FreeList page list */
+ PVR_LOG((" Initial Memory block"));
+ dllist_foreach_node(&psFreeList->sMemoryBlockInitHead,
+ _RGXDumpPMRPageList,
+ IMG_NULL);
+
+ /* Dump Grow FreeList page list */
+ PVR_LOG((" Grow Memory blocks"));
+ dllist_foreach_node(&psFreeList->sMemoryBlockHead,
+ _RGXDumpPMRPageList,
+ IMG_NULL);
+
+ return IMG_TRUE;
+}
+
+static PVRSRV_ERROR _UpdateFwFreelistSize(RGX_FREELIST *psFreeList,
+ IMG_BOOL bGrow,
+ IMG_UINT32 ui32DeltaSize)
+{
+ PVRSRV_ERROR eError;
+ RGXFWIF_KCCB_CMD sGPCCBCmd;
+
+ sGPCCBCmd.eCmdType = (bGrow) ? RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE : RGXFWIF_KCCB_CMD_FREELIST_SHRINK_UPDATE;
+ sGPCCBCmd.uCmdData.sFreeListGSData.psFreeListFWDevVAddr = psFreeList->sFreeListFWDevVAddr.ui32Addr;
+ sGPCCBCmd.uCmdData.sFreeListGSData.ui32DeltaSize = ui32DeltaSize;
+ sGPCCBCmd.uCmdData.sFreeListGSData.ui32NewSize = psFreeList->ui32CurrentFLPages;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Send FW update: freelist [FWAddr=0x%08x] has 0x%08x pages",
+ psFreeList->sFreeListFWDevVAddr.ui32Addr,
+ psFreeList->ui32CurrentFLPages));
+
+ /* Submit command to the firmware. */
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError = RGXScheduleCommand(psFreeList->psDevInfo,
+ RGXFWIF_DM_GP,
+ &sGPCCBCmd,
+ sizeof(sGPCCBCmd),
+ IMG_TRUE);
+ 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, "_UpdateFwFreelistSize: failed to update FW freelist size. (error = %u)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _FreeListCheckSum(RGX_FREELIST *psFreeList,
+ IMG_UINT64 *pui64CheckSum)
+{
+#if defined(NO_HARDWARE)
+ /* No checksum needed as we have all information in the pdumps */
+ PVR_UNREFERENCED_PARAMETER(psFreeList);
+ *pui64CheckSum = 0;
+ return PVRSRV_OK;
+#else
+ PVRSRV_ERROR eError;
+ IMG_SIZE_T uiNumBytes;
+ IMG_UINT8* pui8Buffer;
+ IMG_UINT32* pui32Buffer;
+ IMG_UINT32 ui32CheckSumAdd = 0;
+ IMG_UINT32 ui32CheckSumXor = 0;
+ IMG_UINT32 ui32Entry;
+ IMG_UINT32 ui32Entry2;
+
+ /* Allocate Buffer of the size of the freelist */
+ pui8Buffer = OSAllocMem(psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32));
+ if (pui8Buffer == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto _OSAllocMem_Exit;
+ }
+
+ /* Copy freelist content into Buffer */
+ eError = PMR_ReadBytes(psFreeList->psFreeListPMR,
+ psFreeList->uiFreeListPMROffset + (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages) * sizeof(IMG_UINT32),
+ pui8Buffer,
+ psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32),
+ &uiNumBytes);
+ if (eError != PVRSRV_OK)
+ {
+ goto _PMR_ReadBytes_Exit;
+ }
+
+ PVR_ASSERT(uiNumBytes == psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32));
+
+ /* Generate checksum */
+ pui32Buffer = (IMG_UINT32 *)pui8Buffer;
+ for(ui32Entry = 0; ui32Entry < psFreeList->ui32CurrentFLPages; ui32Entry++)
+ {
+ ui32CheckSumAdd += pui32Buffer[ui32Entry];
+ ui32CheckSumXor ^= pui32Buffer[ui32Entry];
+
+ /* Check for double entries */
+ for (ui32Entry2 = 0; ui32Entry2 < psFreeList->ui32CurrentFLPages; ui32Entry2++)
+ {
+ if ((ui32Entry != ui32Entry2) &&
+ (pui32Buffer[ui32Entry] == pui32Buffer[ui32Entry2]))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Freelist consistency failure: FW addr: 0x%08X, Double entry found 0x%08x on idx: %d and %d",
+ psFreeList->sFreeListFWDevVAddr.ui32Addr,
+ pui32Buffer[ui32Entry2],
+ ui32Entry,
+ ui32Entry2));
+ sleep_for_ever();
+// PVR_ASSERT(0);
+ }
+ }
+ }
+
+ OSFreeMem(pui8Buffer);
+
+ /* Set return value */
+ *pui64CheckSum = ((IMG_UINT64)ui32CheckSumXor << 32) | ui32CheckSumAdd;
+ PVR_ASSERT(eError == PVRSRV_OK);
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+_PMR_ReadBytes_Exit:
+ OSFreeMem(pui8Buffer);
+
+_OSAllocMem_Exit:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+#endif
+}
+
+PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
+ IMG_UINT32 ui32NumPages,
+ PDLLIST_NODE pListHeader)
+{
+ RGX_PMR_NODE *psPMRNode;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_BOOL bMappingTable = IMG_TRUE;
+ IMG_DEVMEM_OFFSET_T uiOffset;
+ IMG_DEVMEM_SIZE_T uiLength;
+ IMG_DEVMEM_SIZE_T uistartPage;
+ PVRSRV_ERROR eError;
+ IMG_UINT64 ui64CheckSum;
+ IMG_UINT32 ui32CheckSumXor;
+ IMG_UINT32 ui32CheckSumAdd;
+
+ /* Are we allowed to grow ? */
+ if ((psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages) < ui32NumPages)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"Freelist [0x%p]: grow by %u pages denied. Max PB size reached (current pages %u/%u)",
+ psFreeList,
+ ui32NumPages,
+ psFreeList->ui32CurrentFLPages,
+ psFreeList->ui32MaxFLPages));
+ return PVRSRV_ERROR_PBSIZE_ALREADY_MAX;
+ }
+
+ /* Allocate kernel memory block structure */
+ psPMRNode = OSAllocMem(sizeof(*psPMRNode));
+ if (psPMRNode == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXGrowFreeList: failed to allocate host data structure"));
+ 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);
+
+
+ psPMRNode->ui32NumPages = ui32NumPages;
+ psPMRNode->psFreeList = psFreeList;
+
+ /* Allocate Memory Block */
+ PDUMPCOMMENT("Allocate PB Block (Pages %08X)", ui32NumPages);
+ uiSize = (IMG_DEVMEM_SIZE_T)ui32NumPages * RGX_BIF_PM_PHYSICAL_PAGE_SIZE;
+ eError = PhysmemNewRamBackedPMR(psFreeList->psDevInfo->psDeviceNode,
+ uiSize,
+ uiSize,
+ 1,
+ 1,
+ &bMappingTable,
+ RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE,
+ &psPMRNode->psPMR);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "RGXGrowFreeList: Failed to allocate PB block of size: 0x%016llX",
+ (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,"RGXGrowFreeList: Failed to zero PMR %p of freelist %p with Error %d",
+ psPMRNode->psPMR,
+ psFreeList,
+ eError));
+ PVR_ASSERT(0);
+ }
+ }
+
+ uiLength = psPMRNode->ui32NumPages * sizeof(IMG_UINT32);
+ uistartPage = (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages - psPMRNode->ui32NumPages);
+ uiOffset = psFreeList->uiFreeListPMROffset + (uistartPage * sizeof(IMG_UINT32));
+
+ /* write Freelist with Memory Block physical addresses */
+ eError = PMRWritePMPageList(
+ /* Target PMR, offset, and length */
+ psFreeList->psFreeListPMR,
+ uiOffset,
+ uiLength,
+ /* Referenced PMR, and "page" granularity */
+ psPMRNode->psPMR,
+ RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
+ &psPMRNode->psPageList,
+ &ui64CheckSum);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "RGXGrowFreeList: Failed to write pages of Node %p",
+ psPMRNode));
+ goto ErrorPopulateFreelist;
+ }
+
+ /* 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 */
+ if (psFreeList->ui32NumHighPages < psFreeList->ui32CurrentFLPages)
+ {
+ psFreeList->ui32NumHighPages = psFreeList->ui32CurrentFLPages;
+ }
+
+ if (psFreeList->bCheckFreelist)
+ {
+ /* Update checksum */
+ ui32CheckSumAdd = (IMG_UINT32)(psFreeList->ui64FreelistChecksum + ui64CheckSum);
+ ui32CheckSumXor = (IMG_UINT32)((psFreeList->ui64FreelistChecksum ^ ui64CheckSum) >> 32);
+ psFreeList->ui64FreelistChecksum = ((IMG_UINT64)ui32CheckSumXor << 32) | ui32CheckSumAdd;
+ /* Note: We can't do a freelist check here, because the freelist is probably empty (OOM) */
+ }
+
+ OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
+
+ PVR_DPF((PVR_DBG_MESSAGE,"Freelist [%p]: grow by %u pages (current pages %u/%u)",
+ psFreeList,
+ ui32NumPages,
+ psFreeList->ui32CurrentFLPages,
+ psFreeList->ui32MaxFLPages));
+
+ 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,
+ "RGXRemoveBlockFromFreeListKM: Failed to unwrite pages of Node %p",
+ psPMRNode));
+ PVR_ASSERT(IMG_FALSE);
+ }
+
+ /* 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,
+ "RGXRemoveBlockFromFreeListKM: Failed to free PB block %p (error %u)",
+ psPMRNode->psPMR,
+ eError));
+ PVR_ASSERT(IMG_FALSE);
+ }
+
+ /* update available pages in freelist */
+ ui32OldValue = psFreeList->ui32CurrentFLPages;
+ psFreeList->ui32CurrentFLPages -= psPMRNode->ui32NumPages;
+
+ /* check underflow */
+ PVR_ASSERT(ui32OldValue > psFreeList->ui32CurrentFLPages);
+
+ 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 IMG_BOOL _FindFreeList(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ DEVMEM_FREELIST_LOOKUP *psRefLookUp = (DEVMEM_FREELIST_LOOKUP *)pvCallbackData;
+ RGX_FREELIST *psFreeList;
+
+ psFreeList = IMG_CONTAINER_OF(psNode, RGX_FREELIST, sNode);
+
+ if (psFreeList->ui32FreelistID == psRefLookUp->ui32FreeListID)
+ {
+ psRefLookUp->psFreeList = psFreeList;
+ return IMG_FALSE;
+ }
+ else
+ {
+ return IMG_TRUE;
+ }
+}
+
+IMG_VOID RGXProcessRequestGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32FreelistID)
+{
+ DEVMEM_FREELIST_LOOKUP sLookUp;
+ RGXFWIF_KCCB_CMD s3DCCBCmd;
+ IMG_UINT32 ui32GrowValue;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psDevInfo);
+
+ /* find the freelist with the corresponding ID */
+ sLookUp.ui32FreeListID = ui32FreelistID;
+ sLookUp.psFreeList = IMG_NULL;
+
+ OSLockAcquire(psDevInfo->hLockFreeList);
+ dllist_foreach_node(&psDevInfo->sFreeListHead, _FindFreeList, (IMG_PVOID)&sLookUp);
+ OSLockRelease(psDevInfo->hLockFreeList);
+
+ if (sLookUp.psFreeList)
+ {
+ RGX_FREELIST *psFreeList = sLookUp.psFreeList;
+
+ /* 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 (error %u)",
+ psFreeList,
+ eError));
+ }
+
+ /* send feedback */
+ s3DCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE;
+ s3DCCBCmd.uCmdData.sFreeListGSData.psFreeListFWDevVAddr = sLookUp.psFreeList->sFreeListFWDevVAddr.ui32Addr;
+ s3DCCBCmd.uCmdData.sFreeListGSData.ui32DeltaSize = ui32GrowValue;
+ s3DCCBCmd.uCmdData.sFreeListGSData.ui32NewSize = psFreeList->ui32CurrentFLPages;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError = RGXScheduleCommand(psDevInfo,
+ RGXFWIF_DM_3D,
+ &s3DCCBCmd,
+ sizeof(s3DCCBCmd),
+ IMG_FALSE);
+ 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);
+ }
+ else
+ {
+ /* Should never happen */
+ PVR_DPF((PVR_DBG_ERROR,"FreeList Lookup for FreeList ID 0x%08x failed (Populate)", sLookUp.ui32FreeListID));
+ PVR_ASSERT(IMG_FALSE);
+ }
+}
+
+static IMG_BOOL _RGXCheckFreeListReconstruction(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+
+ 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;
+ IMG_UINT64 ui64CheckSum;
+
+ 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));
+
+ PMRUnwritePMPageList(psPMRNode->psPageList);
+ psPMRNode->psPageList = IMG_NULL;
+ eError = PMRWritePMPageList(
+ /* Target PMR, offset, and length */
+ psFreeList->psFreeListPMR,
+ uiOffset,
+ uiLength,
+ /* Referenced PMR, and "page" granularity */
+ psPMRNode->psPMR,
+ RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
+ &psPMRNode->psPageList,
+ &ui64CheckSum);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Error (%u) writing FL 0x%08x", 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,"_RGXCheckFreeListReconstruction: Failed to zero PMR %p of freelist %p with Error %d",
+ psPMRNode->psPMR,
+ psFreeList,
+ eError));
+ PVR_ASSERT(0);
+ }
+ }
+
+ psFreeList->ui32CurrentFLPages += psPMRNode->ui32NumPages;
+
+ return IMG_TRUE;
+}
+
+IMG_VOID RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eDM,
+ IMG_UINT32 ui32FreelistsCount,
+ IMG_UINT32 *paui32Freelists)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_FREELIST_LOOKUP sLookUp;
+ IMG_UINT32 ui32Loop, ui32Loop2;
+ RGXFWIF_KCCB_CMD s3DCCBCmd;
+ IMG_UINT64 ui64CheckSum;
+
+ PVR_ASSERT(psDevInfo);
+
+ //PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Reconstructing %u freelist(s)", ui32FreelistsCount));
+
+ for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
+ {
+ /* check if there is more than one occurrence of FL on the list */
+ for (ui32Loop2 = ui32Loop + 1; ui32Loop2 < ui32FreelistsCount; ui32Loop2++)
+ {
+ if (paui32Freelists[ui32Loop] == paui32Freelists[ui32Loop2])
+ {
+ /* There is a duplicate on a list, skip current Freelist */
+ break;
+ }
+ }
+
+ if (ui32Loop2 < ui32FreelistsCount)
+ {
+ /* There is a duplicate on the list, skip current Freelist */
+ continue;
+ }
+
+ /* find the freelist with the corresponding ID */
+ sLookUp.ui32FreeListID = paui32Freelists[ui32Loop];
+ sLookUp.psFreeList = IMG_NULL;
+
+ //PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Looking for freelist %08X", (IMG_UINT32)sLookUp.ui32FreeListID));
+ OSLockAcquire(psDevInfo->hLockFreeList);
+ //PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Freelist head %08X", (IMG_UINT32)&psDevInfo->sFreeListHead));
+ dllist_foreach_node(&psDevInfo->sFreeListHead, _FindFreeList, (IMG_PVOID)&sLookUp);
+ OSLockRelease(psDevInfo->hLockFreeList);
+
+ if (sLookUp.psFreeList)
+ {
+ RGX_FREELIST *psFreeList = sLookUp.psFreeList;
+
+ //PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Reconstructing freelist %08X", (IMG_UINT32)psFreeList));
+
+ /* Do the FreeList Reconstruction */
+
+ psFreeList->ui32CurrentFLPages = 0;
+
+ /* Reconstructing Init FreeList pages */
+ dllist_foreach_node(&psFreeList->sMemoryBlockInitHead,
+ _RGXCheckFreeListReconstruction,
+ IMG_NULL);
+
+ /* Reconstructing Grow FreeList pages */
+ dllist_foreach_node(&psFreeList->sMemoryBlockHead,
+ _RGXCheckFreeListReconstruction,
+ IMG_NULL);
+
+ if (psFreeList->bCheckFreelist)
+ {
+ /* Get Freelist checksum (as the list is fully populated) */
+ eError = _FreeListCheckSum(psFreeList,
+ &ui64CheckSum);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "RGXProcessRequestFreelistsReconstruction: Failed to get freelist checksum Node %p",
+ psFreeList));
+ sleep_for_ever();
+// PVR_ASSERT(0);
+ }
+
+ /* Verify checksum with previous value */
+ if (psFreeList->ui64FreelistChecksum != ui64CheckSum)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXProcessRequestFreelistsReconstruction: Freelist [%p] checksum failed: before reconstruction = 0x%016llx, after reconstruction = 0x%016llx",
+ psFreeList,
+ psFreeList->ui64FreelistChecksum,
+ ui64CheckSum));
+ sleep_for_ever();
+ //PVR_ASSERT(0);
+ }
+ }
+
+ eError = PVRSRV_OK;
+
+ if (eError == PVRSRV_OK)
+ {
+ /* Freelist reconstruction successful */
+ s3DCCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] =
+ paui32Freelists[ui32Loop];
+ }
+ else
+ {
+ /* Freelist reconstruction failed */
+ s3DCCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] =
+ paui32Freelists[ui32Loop] | RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG;
+
+ PVR_DPF((PVR_DBG_ERROR,"Reconstructing of FreeList %p failed (error %u)",
+ psFreeList,
+ eError));
+ }
+ }
+ else
+ {
+ /* Should never happen */
+ PVR_DPF((PVR_DBG_ERROR,"FreeList Lookup for FreeList ID 0x%08x failed (Freelist reconstruction)", sLookUp.ui32FreeListID));
+ PVR_ASSERT(IMG_FALSE);
+ }
+ }
+
+ /* send feedback */
+ s3DCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_FREELISTS_RECONSTRUCTION_UPDATE;
+ s3DCCBCmd.uCmdData.sFreeListsReconstructionData.ui32FreelistsCount = ui32FreelistsCount;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError = RGXScheduleCommand(psDevInfo,
+ eDM,
+ &s3DCCBCmd,
+ sizeof(s3DCCBCmd),
+ IMG_FALSE);
+ 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 */
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateHWRTData(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 psRenderTarget,
+ IMG_DEV_VIRTADDR psPMMListDevVAddr,
+ IMG_DEV_VIRTADDR psVFPPageTableAddr,
+ RGX_FREELIST *apsFreeLists[RGXFW_MAX_FREELISTS],
+ RGX_RTDATA_CLEANUP_DATA **ppsCleanupData,
+ DEVMEM_MEMDESC **ppsRTACtlMemDesc,
+ IMG_UINT32 ui32PPPScreen,
+ IMG_UINT32 ui32PPPGridOffset,
+ IMG_UINT64 ui64PPPMultiSampleCtl,
+ 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_UINT16 ui16MaxRTs,
+ DEVMEM_MEMDESC **ppsMemDesc,
+ IMG_UINT32 *puiHWRTData)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+ RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
+ RGXFWIF_HWRTDATA *psHWRTData;
+ RGXFWIF_RTA_CTL *psRTACtl;
+ IMG_UINT32 ui32Loop;
+ RGX_RTDATA_CLEANUP_DATA *psTmpCleanup;
+
+ /* Prepare cleanup struct */
+ psTmpCleanup = OSAllocMem(sizeof(*psTmpCleanup));
+ if (psTmpCleanup == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto AllocError;
+ }
+
+ OSMemSet(psTmpCleanup, 0, sizeof(*psTmpCleanup));
+ *ppsCleanupData = psTmpCleanup;
+
+ /* Allocate cleanup sync */
+ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+ &psTmpCleanup->psCleanupSync,
+ "HWRTData cleanup");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate cleanup sync (0x%x)",
+ eError));
+ goto SyncAlloc;
+ }
+
+ 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 is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
+ */
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_HWRTDATA),
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_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_WRITE_COMBINE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
+ "FirmwareHWRTData",
+ ppsMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXCreateHWRTData: DevmemAllocate for RGX_FWIF_HWRTDATA failed"));
+ goto FWRTDataAllocateError;
+ }
+
+ psTmpCleanup->psDeviceNode = psDeviceNode;
+ psTmpCleanup->psFWHWRTDataMemDesc = *ppsMemDesc;
+
+ RGXSetFirmwareAddress(&pFirmwareAddr, *ppsMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+
+ *puiHWRTData = pFirmwareAddr.ui32Addr;
+
+ eError = DevmemAcquireCpuVirtAddr(*ppsMemDesc, (IMG_VOID **)&psHWRTData);
+ PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWRTDataCpuMapError);
+
+
+ psHWRTData->psPMMListDevVAddr = psPMMListDevVAddr;
+ psHWRTData->psParentRenderTarget.ui32Addr = psRenderTarget;
+ #if defined(SUPPORT_VFP)
+ psHWRTData->sVFPPageTableAddr = psVFPPageTableAddr;
+ #endif
+
+ psHWRTData->ui32PPPScreen = ui32PPPScreen;
+ psHWRTData->ui32PPPGridOffset = ui32PPPGridOffset;
+ psHWRTData->ui64PPPMultiSampleCtl = ui64PPPMultiSampleCtl;
+ 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;
+
+ OSLockAcquire(psDevInfo->hLockFreeList);
+ for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
+ {
+ psTmpCleanup->apsFreeLists[ui32Loop] = apsFreeLists[ui32Loop];
+ psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount++;
+ psHWRTData->apsFreeLists[ui32Loop] = *((PRGXFWIF_FREELIST *)&(psTmpCleanup->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 its safe to set it 0.
+ */
+ psHWRTData->aui32FreeListHWRSnapshot[ui32Loop] = 0;
+ }
+ OSLockRelease(psDevInfo->hLockFreeList);
+
+ PDUMPCOMMENT("Allocate RGXFW RTA control");
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_RTA_CTL),
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED |
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
+ "FirmwareRTAControl",
+ ppsRTACtlMemDesc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate RGX RTA control (%u)",
+ eError));
+ goto FWRTAAllocateError;
+ }
+ psTmpCleanup->psRTACtlMemDesc = *ppsRTACtlMemDesc;
+ RGXSetFirmwareAddress(&psHWRTData->psRTACtl,
+ *ppsRTACtlMemDesc,
+ 0, RFW_FWADDR_FLAG_NONE);
+
+ eError = DevmemAcquireCpuVirtAddr(*ppsRTACtlMemDesc, (IMG_VOID **)&psRTACtl);
+ PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWRTACpuMapError);
+ psRTACtl->ui32RenderTargetIndex = 0;
+ psRTACtl->ui32ActiveRenderTargets = 0;
+
+ if (ui16MaxRTs > 1)
+ {
+ /* Allocate memory for the checks */
+ PDUMPCOMMENT("Allocate memory for shadow render target cache");
+ eError = DevmemFwAllocate(psDevInfo,
+ ui16MaxRTs,
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
+ PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+ PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+ PVRSRV_MEMALLOCFLAG_UNCACHED|
+ PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
+ "FirmwareShadowRTCache",
+ &psTmpCleanup->psRTArrayMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate %d bytes for render target array (%u)",
+ ui16MaxRTs,
+ eError));
+ goto FWAllocateRTArryError;
+ }
+
+ RGXSetFirmwareAddress(&psRTACtl->paui32ValidRenderTargets,
+ psTmpCleanup->psRTArrayMemDesc,
+ 0, RFW_FWADDR_FLAG_NONE);
+ }
+ else
+ {
+ psRTACtl->paui32ValidRenderTargets.ui32Addr = 0;
+ }
+
+ PDUMPCOMMENT("Dump HWRTData 0x%08X", *puiHWRTData);
+ DevmemPDumpLoadMem(*ppsMemDesc, 0, sizeof(*psHWRTData), PDUMP_FLAGS_CONTINUOUS);
+ PDUMPCOMMENT("Dump RTACtl");
+ DevmemPDumpLoadMem(*ppsRTACtlMemDesc, 0, sizeof(*psRTACtl), PDUMP_FLAGS_CONTINUOUS);
+
+ DevmemReleaseCpuVirtAddr(*ppsMemDesc);
+ DevmemReleaseCpuVirtAddr(*ppsRTACtlMemDesc);
+ return PVRSRV_OK;
+
+ DevmemFwFree(psTmpCleanup->psRTArrayMemDesc);
+FWAllocateRTArryError:
+ DevmemReleaseCpuVirtAddr(*ppsRTACtlMemDesc);
+FWRTACpuMapError:
+ RGXUnsetFirmwareAddress(*ppsRTACtlMemDesc);
+ DevmemFwFree(*ppsRTACtlMemDesc);
+FWRTAAllocateError:
+ OSLockAcquire(psDevInfo->hLockFreeList);
+ for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
+ {
+ PVR_ASSERT(psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount > 0);
+ psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount--;
+ }
+ OSLockRelease(psDevInfo->hLockFreeList);
+ DevmemReleaseCpuVirtAddr(*ppsMemDesc);
+FWRTDataCpuMapError:
+ RGXUnsetFirmwareAddress(*ppsMemDesc);
+ DevmemFwFree(*ppsMemDesc);
+FWRTDataAllocateError:
+ SyncPrimFree(psTmpCleanup->psCleanupSync);
+SyncAlloc:
+ OSFreeMem(psTmpCleanup);
+
+AllocError:
+ return eError;
+}
+
+/* Destroy HWRTDataSet */
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyHWRTData(RGX_RTDATA_CLEANUP_DATA *psCleanupData)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+ PVRSRV_ERROR eError;
+ PRGXFWIF_HWRTDATA psHWRTData;
+ IMG_UINT32 ui32Loop;
+
+ PVR_ASSERT(psCleanupData);
+
+ RGXSetFirmwareAddress(&psHWRTData, psCleanupData->psFWHWRTDataMemDesc, 0, RFW_FWADDR_NOREF_FLAG);
+
+ /* Cleanup HWRTData in TA */
+ eError = RGXFWRequestHWRTDataCleanUp(psCleanupData->psDeviceNode,
+ psHWRTData,
+ psCleanupData->psCleanupSync,
+ RGXFWIF_DM_TA);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ return eError;
+ }
+
+ psDevInfo = psCleanupData->psDeviceNode->pvDevice;
+
+ /* Cleanup HWRTData in 3D */
+ eError = RGXFWRequestHWRTDataCleanUp(psCleanupData->psDeviceNode,
+ psHWRTData,
+ psCleanupData->psCleanupSync,
+ RGXFWIF_DM_3D);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ return eError;
+ }
+
+ /* If we got here then TA and 3D operations on this RTData have finished */
+ if(psCleanupData->psRTACtlMemDesc)
+ {
+ RGXUnsetFirmwareAddress(psCleanupData->psRTACtlMemDesc);
+ DevmemFwFree(psCleanupData->psRTACtlMemDesc);
+ }
+
+ RGXUnsetFirmwareAddress(psCleanupData->psFWHWRTDataMemDesc);
+ DevmemFwFree(psCleanupData->psFWHWRTDataMemDesc);
+
+ if(psCleanupData->psRTArrayMemDesc)
+ {
+ RGXUnsetFirmwareAddress(psCleanupData->psRTArrayMemDesc);
+ DevmemFwFree(psCleanupData->psRTArrayMemDesc);
+ }
+
+ SyncPrimFree(psCleanupData->psCleanupSync);
+
+ /* decrease freelist refcount */
+ OSLockAcquire(psDevInfo->hLockFreeList);
+ for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
+ {
+ PVR_ASSERT(psCleanupData->apsFreeLists[ui32Loop]->ui32RefCount > 0);
+ psCleanupData->apsFreeLists[ui32Loop]->ui32RefCount--;
+ }
+ OSLockRelease(psDevInfo->hLockFreeList);
+
+ OSFreeMem(psCleanupData);
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateFreeList(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32MaxFLPages,
+ IMG_UINT32 ui32InitFLPages,
+ IMG_UINT32 ui32GrowFLPages,
+ IMG_BOOL bCheckFreelist,
+ IMG_DEV_VIRTADDR sFreeListDevVAddr,
+ PMR *psFreeListPMR,
+ IMG_DEVMEM_OFFSET_T uiFreeListPMROffset,
+ RGX_FREELIST **ppsFreeList)
+{
+ PVRSRV_ERROR eError;
+ RGXFWIF_FREELIST *psFWFreeList;
+ DEVMEM_MEMDESC *psFWFreelistMemDesc;
+ RGX_FREELIST *psFreeList;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ /* Allocate kernel freelist struct */
+ psFreeList = OSAllocMem(sizeof(*psFreeList));
+ if (psFreeList == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXCreateFreeList: failed to allocate host data structure"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorAllocHost;
+ }
+ OSMemSet(psFreeList, 0, sizeof(*psFreeList));
+
+ /* Allocate cleanup sync */
+ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+ &psFreeList->psCleanupSync,
+ "ta3d free list cleanup");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXCreateFreeList: Failed to allocate cleanup sync (0x%x)",
+ eError));
+ goto SyncAlloc;
+ }
+
+ /*
+ * This FW FreeList 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 is 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_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_WRITE_COMBINE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
+ "FirmwareFreeList",
+ &psFWFreelistMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXCreateFreeList: DevmemAllocate for RGXFWIF_FREELIST failed"));
+ goto FWFreeListAlloc;
+ }
+
+ /* Initialise host data structures */
+ psFreeList->psDevInfo = psDevInfo;
+ psFreeList->psFreeListPMR = psFreeListPMR;
+ psFreeList->uiFreeListPMROffset = uiFreeListPMROffset;
+ psFreeList->psFWFreelistMemDesc = psFWFreelistMemDesc;
+ RGXSetFirmwareAddress(&psFreeList->sFreeListFWDevVAddr, psFWFreelistMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+ psFreeList->ui32FreelistID = psDevInfo->ui32FreelistCurrID++;
+ psFreeList->ui32MaxFLPages = ui32MaxFLPages;
+ psFreeList->ui32InitFLPages = ui32InitFLPages;
+ psFreeList->ui32GrowFLPages = ui32GrowFLPages;
+ psFreeList->ui32CurrentFLPages = 0;
+ psFreeList->ui64FreelistChecksum = 0;
+ psFreeList->ui32RefCount = 0;
+ psFreeList->bCheckFreelist = bCheckFreelist;
+ dllist_init(&psFreeList->sMemoryBlockHead);
+ dllist_init(&psFreeList->sMemoryBlockInitHead);
+
+
+ /* Add to list of freelists */
+ OSLockAcquire(psDevInfo->hLockFreeList);
+ dllist_add_to_tail(&psDevInfo->sFreeListHead, &psFreeList->sNode);
+ OSLockRelease(psDevInfo->hLockFreeList);
+
+
+ /* Initialise FW data structure */
+ eError = DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (IMG_VOID **)&psFWFreeList);
+ PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWFreeListCpuMap);
+ psFWFreeList->ui32MaxPages = ui32MaxFLPages;
+ psFWFreeList->ui32CurrentPages = ui32InitFLPages;
+ psFWFreeList->ui32GrowPages = ui32GrowFLPages;
+ psFWFreeList->ui64CurrentStackTop = ui32InitFLPages - 1;
+ psFWFreeList->psFreeListDevVAddr = sFreeListDevVAddr;
+ psFWFreeList->ui64CurrentDevVAddr = sFreeListDevVAddr.uiAddr + ((ui32MaxFLPages - ui32InitFLPages) * sizeof(IMG_UINT32));
+ psFWFreeList->ui32FreeListID = psFreeList->ui32FreelistID;
+ psFWFreeList->bGrowPending = IMG_FALSE;
+
+ PVR_DPF((PVR_DBG_MESSAGE,"Freelist %p created: Max pages 0x%08x, Init pages 0x%08x, Max FL base address 0x%016llx, Init FL base address 0x%016llx",
+ psFreeList,
+ ui32MaxFLPages,
+ ui32InitFLPages,
+ sFreeListDevVAddr.uiAddr,
+ psFWFreeList->psFreeListDevVAddr.uiAddr));
+
+ PDUMPCOMMENT("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");
+ DevmemPDumpLoadMemValue64(psFreeList->psFWFreelistMemDesc,
+ offsetof(RGXFWIF_FREELIST, ui32CurrentPages),
+ psFWFreeList->ui32CurrentPages,
+ PDUMP_FLAGS_CONTINUOUS);
+ PDUMPCOMMENT("FreeList StackPointer");
+ DevmemPDumpLoadMemValue64(psFreeList->psFWFreelistMemDesc,
+ offsetof(RGXFWIF_FREELIST, ui64CurrentStackTop),
+ psFWFreeList->ui64CurrentStackTop,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
+
+
+ /* Add initial PB block */
+ eError = RGXGrowFreeList(psFreeList,
+ ui32InitFLPages,
+ &psFreeList->sMemoryBlockInitHead);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "RGXCreateFreeList: failed to allocate initial memory block for free list 0x%016llx (error = %u)",
+ sFreeListDevVAddr.uiAddr,
+ eError));
+ goto ErrorAllocBlock;
+ }
+#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
+
+ psFreeList->ownerPid = OSGetCurrentProcessIDKM();
+ /* return values */
+ *ppsFreeList = psFreeList;
+
+ return PVRSRV_OK;
+
+ /* Error handling */
+
+ErrorAllocBlock:
+ DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
+
+FWFreeListCpuMap:
+ /* Remove freelists from list */
+ OSLockAcquire(psDevInfo->hLockFreeList);
+ dllist_remove_node(&psFreeList->sNode);
+ OSLockRelease(psDevInfo->hLockFreeList);
+
+ RGXUnsetFirmwareAddress(psFWFreelistMemDesc);
+ DevmemFwFree(psFWFreelistMemDesc);
+
+FWFreeListAlloc:
+ SyncPrimFree(psFreeList->psCleanupSync);
+
+SyncAlloc:
+ OSFreeMem(psFreeList);
+
+ErrorAllocHost:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+/*
+ RGXDestroyFreeList
+*/
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyFreeList(RGX_FREELIST *psFreeList)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT64 ui64CheckSum;
+
+ PVR_ASSERT(psFreeList);
+
+ if (psFreeList->ui32RefCount != 0)
+ {
+ /* Freelist still busy */
+ return PVRSRV_ERROR_RETRY;
+ }
+
+ /* Freelist is not in use => start firmware cleanup */
+ eError = RGXFWRequestFreeListCleanUp(psFreeList->psDevInfo,
+ psFreeList->sFreeListFWDevVAddr,
+ psFreeList->psCleanupSync);
+ 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;
+ }
+
+ if (psFreeList->bCheckFreelist)
+ {
+ /* Do consistency tests (as the list is fully populated) */
+ eError = _FreeListCheckSum(psFreeList,
+ &ui64CheckSum);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "RGXDestroyFreeList: Failed to get freelist checksum Node %p",
+ psFreeList));
+ sleep_for_ever();
+// PVR_ASSERT(0);
+ }
+
+ if (psFreeList->ui64FreelistChecksum != ui64CheckSum)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "RGXDestroyFreeList: Checksum mismatch [%p]! stored 0x%016llx, verified 0x%016llx %p",
+ psFreeList,
+ psFreeList->ui64FreelistChecksum,
+ ui64CheckSum,
+ psFreeList));
+ sleep_for_ever();
+// PVR_ASSERT(0);
+ }
+ }
+
+ /* Destroy FW structures */
+ RGXUnsetFirmwareAddress(psFreeList->psFWFreelistMemDesc);
+ DevmemFwFree(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);
+
+ /* Remove FreeList from list */
+ OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
+ dllist_remove_node(&psFreeList->sNode);
+ OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
+
+ SyncPrimFree(psFreeList->psCleanupSync);
+
+ /* free Freelist */
+ OSFreeMem(psFreeList);
+
+ return eError;
+}
+
+
+
+/*
+ RGXAddBlockToFreeListKM
+*/
+
+IMG_EXPORT
+PVRSRV_ERROR RGXAddBlockToFreeListKM(RGX_FREELIST *psFreeList,
+ IMG_UINT32 ui32NumPages)
+{
+ PVRSRV_ERROR eError;
+
+ /* Check if we have reference to freelist's PMR */
+ if (psFreeList->psFreeListPMR == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Freelist is not configured for grow"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* grow freelist */
+ eError = RGXGrowFreeList(psFreeList,
+ ui32NumPages,
+ &psFreeList->sMemoryBlockHead);
+ if(eError == PVRSRV_OK)
+ {
+ /* update freelist data in firmware */
+ _UpdateFwFreelistSize(psFreeList, IMG_TRUE, ui32NumPages);
+
+ psFreeList->ui32NumGrowReqByApp++;
+
+#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 eError;
+}
+
+/*
+ RGXRemoveBlockFromFreeListKM
+*/
+
+IMG_EXPORT
+PVRSRV_ERROR RGXRemoveBlockFromFreeListKM(RGX_FREELIST *psFreeList)
+{
+ PVRSRV_ERROR eError;
+
+ /*
+ * Make sure the pages part of the memory block are not in use anymore.
+ * Instruct the firmware to update the freelist pointers accordingly.
+ */
+
+ eError = RGXShrinkFreeList(&psFreeList->sMemoryBlockHead,
+ psFreeList);
+
+ return eError;
+}
+
+
+/*
+ RGXCreateRenderTarget
+*/
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateRenderTarget(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR psVHeapTableDevVAddr,
+ RGX_RT_CLEANUP_DATA **ppsCleanupData,
+ IMG_UINT32 *sRenderTargetFWDevVAddr)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ RGXFWIF_RENDER_TARGET *psRenderTarget;
+ RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGX_RT_CLEANUP_DATA *psCleanupData;
+
+ psCleanupData = OSAllocMem(sizeof(*psCleanupData));
+ if (psCleanupData == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_out;
+ }
+
+ OSMemSet(psCleanupData, 0, sizeof(*psCleanupData));
+ psCleanupData->psDeviceNode = psDeviceNode;
+ /*
+ * This FW render target 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 is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
+ */
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(*psRenderTarget),
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ 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_WRITE_COMBINE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
+ "FirmwareRenderTarget",
+ &psCleanupData->psRenderTargetMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXCreateRenderTarget: DevmemAllocate for Render Target failed"));
+ goto err_free;
+ }
+ RGXSetFirmwareAddress(&pFirmwareAddr, psCleanupData->psRenderTargetMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+ *sRenderTargetFWDevVAddr = pFirmwareAddr.ui32Addr;
+
+ eError = DevmemAcquireCpuVirtAddr(psCleanupData->psRenderTargetMemDesc, (IMG_VOID **)&psRenderTarget);
+ PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", err_fwalloc);
+
+ psRenderTarget->psVHeapTableDevVAddr = psVHeapTableDevVAddr;
+ psRenderTarget->bTACachesNeedZeroing = IMG_FALSE;
+ PDUMPCOMMENT("Dump RenderTarget");
+ DevmemPDumpLoadMem(psCleanupData->psRenderTargetMemDesc, 0, sizeof(*psRenderTarget), PDUMP_FLAGS_CONTINUOUS);
+ DevmemReleaseCpuVirtAddr(psCleanupData->psRenderTargetMemDesc);
+
+ *ppsCleanupData = psCleanupData;
+
+err_out:
+ return eError;
+
+err_free:
+ OSFreeMem(psCleanupData);
+ goto err_out;
+
+err_fwalloc:
+ DevmemFwFree(psCleanupData->psRenderTargetMemDesc);
+ goto err_free;
+
+}
+
+
+/*
+ RGXDestroyRenderTarget
+*/
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyRenderTarget(RGX_RT_CLEANUP_DATA *psCleanupData)
+{
+ RGXUnsetFirmwareAddress(psCleanupData->psRenderTargetMemDesc);
+
+ /*
+ Note:
+ When we get RT cleanup in the FW call that instead
+ */
+ /* Flush the the SLC before freeing */
+ {
+ RGXFWIF_KCCB_CMD sFlushInvalCmd;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = psCleanupData->psDeviceNode;
+
+ /* Schedule the SLC flush command ... */
+ #if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
+ #endif
+ sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
+ sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
+ sFlushInvalCmd.uCmdData.sSLCFlushInvalData.eDM = RGXFWIF_DM_2D; //Covers all of Sidekick
+ sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
+
+ eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
+ RGXFWIF_DM_GP,
+ &sFlushInvalCmd,
+ sizeof(sFlushInvalCmd),
+ IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXDestroyRenderTarget: Failed to schedule SLC flush command with error (%u)", eError));
+ }
+ else
+ {
+ /* Wait for the SLC flush to complete */
+ eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXDestroyRenderTarget: SLC flush and invalidate aborted with error (%u)", eError));
+ }
+ }
+ }
+
+ DevmemFwFree(psCleanupData->psRenderTargetMemDesc);
+ OSFreeMem(psCleanupData);
+ return PVRSRV_OK;
+}
+
+/*
+ RGXCreateZSBuffer
+*/
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateZSBufferKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ DEVMEMINT_RESERVATION *psReservation,
+ PMR *psPMR,
+ PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
+ RGX_ZSBUFFER_DATA **ppsZSBuffer,
+ IMG_UINT32 *pui32ZSBufferFWDevVAddr)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_FWZSBUFFER *psFWZSBuffer;
+ RGX_ZSBUFFER_DATA *psZSBuffer;
+ DEVMEM_MEMDESC *psFWZSBufferMemDesc;
+ IMG_BOOL bOnDemand = ((uiMapFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) > 0);
+
+ /* Allocate host data structure */
+ psZSBuffer = OSAllocMem(sizeof(*psZSBuffer));
+ if (psZSBuffer == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate cleanup data structure for ZS-Buffer"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorAllocCleanup;
+ }
+ OSMemSet(psZSBuffer, 0, sizeof(*psZSBuffer));
+
+ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+ &psZSBuffer->psCleanupSync,
+ "ta3d zs buffer cleanup");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate cleanup sync (0x%x)",
+ eError));
+ goto ErrorSyncAlloc;
+ }
+
+ /* 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 = psDevInfo->ui32ZSBufferCurrID++;
+ psZSBuffer->psMapping = IMG_NULL;
+
+ OSLockAcquire(psDevInfo->hLockZSBuffer);
+ dllist_add_to_tail(&psDevInfo->sZSBufferHead, &psZSBuffer->sNode);
+ OSLockRelease(psDevInfo->hLockZSBuffer);
+ }
+
+ /* Allocate firmware memory for ZS-Buffer. */
+ PDUMPCOMMENT("Allocate firmware ZS-Buffer data structure");
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(*psFWZSBuffer),
+ PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+ 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_WRITE_COMBINE |
+ PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
+ "FirmwareZSBuffer",
+ &psFWZSBufferMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate firmware ZS-Buffer (%u)", eError));
+ goto ErrorAllocFWZSBuffer;
+ }
+ psZSBuffer->psZSBufferMemDesc = psFWZSBufferMemDesc;
+
+ /* Temporarily map the firmware render context to the kernel. */
+ eError = DevmemAcquireCpuVirtAddr(psFWZSBufferMemDesc,
+ (IMG_VOID **)&psFWZSBuffer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to map firmware ZS-Buffer (%u)", eError));
+ goto ErrorAcquireFWZSBuffer;
+ }
+
+ /* Populate FW ZS-Buffer data structure */
+ psFWZSBuffer->bOnDemand = bOnDemand;
+ psFWZSBuffer->eState = (bOnDemand) ? RGXFWIF_ZSBUFFER_UNBACKED : RGXFWIF_ZSBUFFER_BACKED;
+ psFWZSBuffer->ui32ZSBufferID = psZSBuffer->ui32ZSBufferID;
+
+ /* Get firmware address of ZS-Buffer. */
+ RGXSetFirmwareAddress(&psZSBuffer->sZSBufferFWDevVAddr, psFWZSBufferMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+
+ /* Dump the ZS-Buffer and the memory content */
+ PDUMPCOMMENT("Dump firmware ZS-Buffer");
+ DevmemPDumpLoadMem(psFWZSBufferMemDesc, 0, sizeof(*psFWZSBuffer), PDUMP_FLAGS_CONTINUOUS);
+
+ /* Release address acquired above. */
+ DevmemReleaseCpuVirtAddr(psFWZSBufferMemDesc);
+
+
+ /* define return value */
+ *ppsZSBuffer = psZSBuffer;
+ *pui32ZSBufferFWDevVAddr = psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ZS-Buffer [%p] created (%s)",
+ psZSBuffer,
+ (bOnDemand) ? "On-Demand": "Up-front"));
+
+ psZSBuffer->owner=OSGetCurrentProcessIDKM();
+
+ return PVRSRV_OK;
+
+ /* error handling */
+
+ErrorAcquireFWZSBuffer:
+ DevmemFwFree(psFWZSBufferMemDesc);
+
+ErrorAllocFWZSBuffer:
+ SyncPrimFree(psZSBuffer->psCleanupSync);
+
+ErrorSyncAlloc:
+ OSFreeMem(psZSBuffer);
+
+ErrorAllocCleanup:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+/*
+ RGXDestroyZSBuffer
+*/
+IMG_EXPORT
+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,
+ psZSBuffer->psCleanupSync);
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Free the firmware render context. */
+ RGXUnsetFirmwareAddress(psZSBuffer->psZSBufferMemDesc);
+ DevmemFwFree(psZSBuffer->psZSBufferMemDesc);
+
+ /* 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);
+ }
+
+ SyncPrimFree(psZSBuffer->psCleanupSync);
+
+ 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->uiMapFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) == 0)
+ {
+ /* 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;
+
+ PVR_ASSERT(psZSBuffer->psMapping == IMG_NULL);
+
+ /* Get Heap */
+ eError = DevmemServerGetHeapHandle(psZSBuffer->psReservation, &hDevmemHeap);
+ PVR_ASSERT(psZSBuffer->psMapping == IMG_NULL);
+
+ 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] with error %u",
+ psZSBuffer,
+ psZSBuffer->ui32ZSBufferID,
+ 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 == IMG_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] with error %u",
+ psZSBuffer,
+ psZSBuffer->ui32ZSBufferID,
+ 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 IMG_BOOL _FindZSBuffer(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ DEVMEM_REF_LOOKUP *psRefLookUp = (DEVMEM_REF_LOOKUP *)pvCallbackData;
+ RGX_ZSBUFFER_DATA *psZSBuffer;
+
+ psZSBuffer = IMG_CONTAINER_OF(psNode, RGX_ZSBUFFER_DATA, sNode);
+
+ if (psZSBuffer->ui32ZSBufferID == psRefLookUp->ui32ZSBufferID)
+ {
+ psRefLookUp->psZSBuffer = psZSBuffer;
+ return IMG_FALSE;
+ }
+ else
+ {
+ return IMG_TRUE;
+ }
+}
+
+IMG_VOID RGXProcessRequestZSBufferBacking(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32ZSBufferID)
+{
+ DEVMEM_REF_LOOKUP sLookUp;
+ RGXFWIF_KCCB_CMD sTACCBCmd;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psDevInfo);
+
+ /* scan all deferred allocations */
+ sLookUp.ui32ZSBufferID = ui32ZSBufferID;
+ sLookUp.psZSBuffer = IMG_NULL;
+
+ OSLockAcquire(psDevInfo->hLockZSBuffer);
+ dllist_foreach_node(&psDevInfo->sZSBufferHead, _FindZSBuffer, (IMG_PVOID)&sLookUp);
+ OSLockRelease(psDevInfo->hLockZSBuffer);
+
+ if (sLookUp.psZSBuffer)
+ {
+ IMG_BOOL bBackingDone = IMG_TRUE;
+
+ /* Populate ZLS */
+ eError = RGXBackingZSBuffer(sLookUp.psZSBuffer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Populating ZS-Buffer failed 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.psZSBufferFWDevVAddr = sLookUp.psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
+ sTACCBCmd.uCmdData.sZSBufferBackingData.bDone = bBackingDone;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError = RGXScheduleCommand(psDevInfo,
+ RGXFWIF_DM_TA,
+ &sTACCBCmd,
+ sizeof(sTACCBCmd),
+ IMG_FALSE);
+ 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);
+
+ sLookUp.psZSBuffer->ui32NumReqByFW++;
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ PVRSRVStatsUpdateZSBufferStats(0,1,sLookUp.psZSBuffer->owner);
+#endif
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"ZS Buffer Lookup for ZS Buffer ID 0x%08x failed (Populate)", sLookUp.ui32ZSBufferID));
+ }
+}
+
+IMG_VOID RGXProcessRequestZSBufferUnbacking(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32ZSBufferID)
+{
+ DEVMEM_REF_LOOKUP sLookUp;
+ RGXFWIF_KCCB_CMD sTACCBCmd;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psDevInfo);
+
+ /* scan all deferred allocations */
+ sLookUp.ui32ZSBufferID = ui32ZSBufferID;
+ sLookUp.psZSBuffer = IMG_NULL;
+
+ OSLockAcquire(psDevInfo->hLockZSBuffer);
+ dllist_foreach_node(&psDevInfo->sZSBufferHead, _FindZSBuffer, (IMG_PVOID)&sLookUp);
+ OSLockRelease(psDevInfo->hLockZSBuffer);
+
+ if (sLookUp.psZSBuffer)
+ {
+ /* Unpopulate ZLS */
+ eError = RGXUnbackingZSBuffer(sLookUp.psZSBuffer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"UnPopulating ZS-Buffer failed 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.psZSBufferFWDevVAddr = sLookUp.psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
+ sTACCBCmd.uCmdData.sZSBufferBackingData.bDone = IMG_TRUE;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError = RGXScheduleCommand(psDevInfo,
+ RGXFWIF_DM_TA,
+ &sTACCBCmd,
+ sizeof(sTACCBCmd),
+ IMG_FALSE);
+ 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);
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"ZS Buffer Lookup for ZS Buffer ID 0x%08x failed (UnPopulate)", sLookUp.ui32ZSBufferID));
+ }
+}
+
+static
+PVRSRV_ERROR _CreateTAContext(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ DEVMEM_MEMDESC *psAllocatedMemDesc,
+ IMG_UINT32 ui32AllocatedOffset,
+ DEVMEM_MEMDESC *psFWMemContextMemDesc,
+ IMG_DEV_VIRTADDR sVDMCallStackAddr,
+ IMG_UINT32 ui32Priority,
+ RGX_COMMON_CONTEXT_INFO *psInfo,
+ RGX_SERVER_RC_TA_DATA *psTAData)
+{
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_TACTX_STATE *psContextState;
+ 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");
+
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_TACTX_STATE),
+ RGX_FWCOMCTX_ALLOCFLAGS,
+ "FirmwareTAContextState",
+ &psTAData->psContextStateMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate firmware GPU context suspend state (%u)",
+ eError));
+ goto fail_tacontextsuspendalloc;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psTAData->psContextStateMemDesc,
+ (IMG_VOID **)&psContextState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to map firmware render context state (%u)",
+ eError));
+ goto fail_suspendcpuvirtacquire;
+ }
+ psContextState->uTAReg_VDM_CALL_STACK_POINTER_Init = sVDMCallStackAddr.uiAddr;
+ DevmemReleaseCpuVirtAddr(psTAData->psContextStateMemDesc);
+
+ eError = FWCommonContextAllocate(psConnection,
+ psDeviceNode,
+ "TA",
+ psAllocatedMemDesc,
+ ui32AllocatedOffset,
+ psFWMemContextMemDesc,
+ psTAData->psContextStateMemDesc,
+ RGX_CCB_SIZE_LOG2,
+ ui32Priority,
+ psInfo,
+ &psTAData->psServerCommonContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to init TA fw common context (%u)",
+ eError));
+ goto fail_tacommoncontext;
+ }
+
+ /*
+ * Dump the FW 3D context suspend state buffer
+ */
+ PDUMPCOMMENT("Dump the TA context suspend state buffer");
+ DevmemPDumpLoadMem(psTAData->psContextStateMemDesc,
+ 0,
+ sizeof(RGXFWIF_TACTX_STATE),
+ PDUMP_FLAGS_CONTINUOUS);
+
+ psTAData->ui32Priority = ui32Priority;
+ return PVRSRV_OK;
+
+fail_tacommoncontext:
+fail_suspendcpuvirtacquire:
+ DevmemFwFree(psTAData->psContextStateMemDesc);
+fail_tacontextsuspendalloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+static
+PVRSRV_ERROR _Create3DContext(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ DEVMEM_MEMDESC *psAllocatedMemDesc,
+ IMG_UINT32 ui32AllocatedOffset,
+ DEVMEM_MEMDESC *psFWMemContextMemDesc,
+ IMG_UINT32 ui32Priority,
+ RGX_COMMON_CONTEXT_INFO *psInfo,
+ RGX_SERVER_RC_3D_DATA *ps3DData)
+{
+ 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("Allocate RGX firmware 3D context suspend state");
+
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_3DCTX_STATE),
+ RGX_FWCOMCTX_ALLOCFLAGS,
+ "Firmware3DContextState",
+ &ps3DData->psContextStateMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate firmware GPU context suspend state (%u)",
+ eError));
+ goto fail_3dcontextsuspendalloc;
+ }
+
+ eError = FWCommonContextAllocate(psConnection,
+ psDeviceNode,
+ "3D",
+ psAllocatedMemDesc,
+ ui32AllocatedOffset,
+ psFWMemContextMemDesc,
+ ps3DData->psContextStateMemDesc,
+ RGX_CCB_SIZE_LOG2,
+ ui32Priority,
+ psInfo,
+ &ps3DData->psServerCommonContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to init 3D fw common context (%u)",
+ eError));
+ goto fail_3dcommoncontext;
+ }
+
+ /*
+ * Dump the FW 3D context suspend state buffer
+ */
+ PDUMPCOMMENT("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:
+ DevmemFwFree(ps3DData->psContextStateMemDesc);
+fail_3dcontextsuspendalloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+
+/*
+ * PVRSRVRGXCreateRenderContextKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32Priority,
+ IMG_DEV_VIRTADDR sMCUFenceAddr,
+ IMG_DEV_VIRTADDR sVDMCallStackAddr,
+ IMG_UINT32 ui32FrameworkRegisterSize,
+ IMG_PBYTE pabyFrameworkRegisters,
+ IMG_HANDLE hMemCtxPrivData,
+ 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;
+
+ /* Prepare cleanup structure */
+ *ppsRenderContext = IMG_NULL;
+ psRenderContext = OSAllocMem(sizeof(*psRenderContext));
+ if (psRenderContext == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psRenderContext, 0, sizeof(*psRenderContext));
+ 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,
+ "FirmwareRenderContext",
+ &psRenderContext->psFWRenderContextMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_fwrendercontext;
+ }
+
+ /*
+ As the common context alloc will dump the TA and 3D common contexts
+ after the've been setup we skip of the 2 common contexts and dump the
+ rest of the structure
+ */
+ PDUMPCOMMENT("Dump shared part of render context context");
+ DevmemPDumpLoadMem(psRenderContext->psFWRenderContextMemDesc,
+ (sizeof(RGXFWIF_FWCOMMONCONTEXT) * 2),
+ sizeof(RGXFWIF_FWRENDERCONTEXT) - (sizeof(RGXFWIF_FWCOMMONCONTEXT) * 2),
+ PDUMP_FLAGS_CONTINUOUS);
+
+ /* Allocate cleanup sync */
+ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+ &psRenderContext->psCleanupSync,
+ "ta3d render context cleanup");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate cleanup sync (0x%x)",
+ eError));
+ goto fail_syncalloc;
+ }
+
+ /*
+ * Create the FW framework buffer
+ */
+ eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode,
+ &psRenderContext->psFWFrameworkMemDesc,
+ ui32FrameworkRegisterSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate firmware GPU framework state (%u)",
+ eError));
+ goto fail_frameworkcreate;
+ }
+
+ /* Copy the Framework client data into the framework buffer */
+ eError = PVRSRVRGXFrameworkCopyCommand(psRenderContext->psFWFrameworkMemDesc,
+ pabyFrameworkRegisters,
+ ui32FrameworkRegisterSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to populate the framework buffer (%u)",
+ eError));
+ goto fail_frameworkcopy;
+ }
+
+ sInfo.psFWFrameworkMemDesc = psRenderContext->psFWFrameworkMemDesc;
+ sInfo.psMCUFenceAddr = &sMCUFenceAddr;
+
+ eError = _CreateTAContext(psConnection,
+ psDeviceNode,
+ psRenderContext->psFWRenderContextMemDesc,
+ offsetof(RGXFWIF_FWRENDERCONTEXT, sTAContext),
+ psFWMemContextMemDesc,
+ sVDMCallStackAddr,
+ ui32Priority,
+ &sInfo,
+ &psRenderContext->sTAData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_tacontext;
+ }
+
+ eError = _Create3DContext(psConnection,
+ psDeviceNode,
+ psRenderContext->psFWRenderContextMemDesc,
+ offsetof(RGXFWIF_FWRENDERCONTEXT, s3DContext),
+ psFWMemContextMemDesc,
+ ui32Priority,
+ &sInfo,
+ &psRenderContext->s3DData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_3dcontext;
+ }
+
+ {
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock, DEVINFO_RENDERLIST);
+ dllist_add_to_tail(&(psDevInfo->sRenderCtxtListHead), &(psRenderContext->sListNode));
+ OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
+ }
+
+ *ppsRenderContext= psRenderContext;
+ return PVRSRV_OK;
+
+fail_3dcontext:
+ _DestroyTAContext(&psRenderContext->sTAData,
+ psDeviceNode,
+ psRenderContext->psCleanupSync);
+fail_tacontext:
+fail_frameworkcopy:
+ DevmemFwFree(psRenderContext->psFWFrameworkMemDesc);
+fail_frameworkcreate:
+ SyncPrimFree(psRenderContext->psCleanupSync);
+fail_syncalloc:
+ DevmemFwFree(psRenderContext->psFWRenderContextMemDesc);
+fail_fwrendercontext:
+ OSFreeMem(psRenderContext);
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+/*
+ * PVRSRVRGXDestroyRenderContextKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXDestroyRenderContextKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psRenderContext->psDeviceNode->pvDevice;
+
+ /* 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, DEVINFO_RENDERLIST);
+ dllist_remove_node(&(psRenderContext->sListNode));
+ OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
+
+ /* Cleanup the TA if we haven't already */
+ if ((psRenderContext->ui32CleanupStatus & RC_CLEANUP_TA_COMPLETE) == 0)
+ {
+ eError = _DestroyTAContext(&psRenderContext->sTAData,
+ psRenderContext->psDeviceNode,
+ psRenderContext->psCleanupSync);
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ 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,
+ psRenderContext->psCleanupSync);
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ psRenderContext->ui32CleanupStatus |= RC_CLEANUP_3D_COMPLETE;
+ }
+ else
+ {
+ goto e0;
+ }
+ }
+
+ /*
+ 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))
+ {
+ RGXFWIF_FWRENDERCONTEXT *psFWRenderContext;
+
+ /* Update SPM statistics */
+ eError = DevmemAcquireCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc,
+ (IMG_VOID **)&psFWRenderContext);
+ if (eError == PVRSRV_OK)
+ {
+ DevmemReleaseCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXDestroyRenderContextKM: Failed to map firmware render context (%u)",
+ eError));
+ }
+
+ /* Free the framework buffer */
+ DevmemFwFree(psRenderContext->psFWFrameworkMemDesc);
+
+ /* Free the firmware render context */
+ DevmemFwFree(psRenderContext->psFWRenderContextMemDesc);
+
+ /* Free the cleanup sync */
+ SyncPrimFree(psRenderContext->psCleanupSync);
+
+ OSFreeMem(psRenderContext);
+ }
+
+ return PVRSRV_OK;
+
+e0:
+ OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock, DEVINFO_RENDERLIST);
+ dllist_add_to_tail(&(psDevInfo->sRenderCtxtListHead), &(psRenderContext->sListNode));
+ OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
+ return eError;
+}
+
+
+
+/* 1 command for the TA */
+static RGX_CCB_CMD_HELPER_DATA sTACmdHelperData;
+/* Up to 3 commands for the 3D (partial render fence, partial reader, and render) */
+static RGX_CCB_CMD_HELPER_DATA as3DCmdHelperData[3];
+
+/*
+ * PVRSRVRGXKickTA3DKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+ IMG_UINT32 ui32ClientTAFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientTAFenceUFOAddress,
+ IMG_UINT32 *paui32ClientTAFenceValue,
+ IMG_UINT32 ui32ClientTAUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientTAUpdateUFOAddress,
+ IMG_UINT32 *paui32ClientTAUpdateValue,
+ IMG_UINT32 ui32ServerTASyncPrims,
+ IMG_UINT32 *paui32ServerTASyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerTASyncs,
+ IMG_UINT32 ui32Client3DFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClient3DFenceUFOAddress,
+ IMG_UINT32 *paui32Client3DFenceValue,
+ IMG_UINT32 ui32Client3DUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClient3DUpdateUFOAddress,
+ IMG_UINT32 *paui32Client3DUpdateValue,
+ IMG_UINT32 ui32Server3DSyncPrims,
+ IMG_UINT32 *paui32Server3DSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServer3DSyncs,
+ PRGXFWIF_UFO_ADDR uiPRFenceUFOAddress,
+ IMG_UINT32 ui32PRFenceValue,
+ IMG_UINT32 ui32NumFenceFDs,
+ IMG_INT32 *ai32FenceFDs,
+ IMG_UINT32 ui32TACmdSize,
+ IMG_PBYTE pui8TADMCmd,
+ IMG_UINT32 ui323DPRCmdSize,
+ IMG_PBYTE pui83DPRDMCmd,
+ IMG_UINT32 ui323DCmdSize,
+ IMG_PBYTE pui83DDMCmd,
+ IMG_UINT32 ui32ExtJobRef,
+ IMG_UINT32 ui32IntJobRef,
+ IMG_BOOL bLastTAInScene,
+ IMG_BOOL bKickTA,
+ IMG_BOOL bKickPR,
+ IMG_BOOL bKick3D,
+ IMG_BOOL bAbort,
+ IMG_BOOL bPDumpContinuous,
+ RGX_RTDATA_CLEANUP_DATA *psRTDataCleanup,
+ RGX_ZSBUFFER_DATA *psZBuffer,
+ RGX_ZSBUFFER_DATA *psSBuffer,
+ IMG_BOOL bCommitRefCountsTA,
+ IMG_BOOL bCommitRefCounts3D,
+ IMG_BOOL *pbCommittedRefCountsTA,
+ IMG_BOOL *pbCommittedRefCounts3D)
+{
+
+ IMG_UINT32 ui32TACmdCount=0;
+ IMG_UINT32 ui323DCmdCount=0;
+ IMG_BOOL bKickTADM = IMG_FALSE;
+ IMG_BOOL bKick3DDM = IMG_FALSE;
+ RGXFWIF_UFO sPRUFO;
+ IMG_UINT32 *paui32Server3DSyncFlagsPR = IMG_NULL;
+ IMG_UINT32 *paui32Server3DSyncFlags3D = IMG_NULL;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_ERROR eError2;
+
+ /* Internal client sync info, used to help with merging of Android fd syncs */
+ IMG_UINT32 ui32IntClientTAFenceCount = 0;
+ PRGXFWIF_UFO_ADDR *pauiIntClientTAFenceUFOAddress = IMG_NULL;
+ IMG_UINT32 *paui32IntClientTAFenceValue = IMG_NULL;
+
+ IMG_UINT32 ui32NumUpdateSyncs = 0;
+ PRGXFWIF_UFO_ADDR *puiUpdateFWAddrs = IMG_NULL;
+ IMG_UINT32 *pui32UpdateValues = IMG_NULL;
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ /* Android fd sync update info */
+ struct pvr_sync_append_data *psFDData = NULL;
+#endif
+
+ PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+ PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+ PRGXFWIF_UFO_ADDR pRMWUFOAddr;
+
+ *pbCommittedRefCountsTA = IMG_FALSE;
+ *pbCommittedRefCounts3D = IMG_FALSE;
+
+ /* Sanity check the server fences */
+ for (i=0;i<ui32ServerTASyncPrims;i++)
+ {
+ if (!(paui32ServerTASyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on TA) must fence", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
+ }
+ }
+
+ for (i=0;i<ui32Server3DSyncPrims;i++)
+ {
+ if (!(paui32Server3DSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on 3D) must fence", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
+ }
+ }
+
+ RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psRenderContext->psDeviceNode->pvDevice,
+ & pPreAddr,
+ & pPostAddr,
+ & pRMWUFOAddr);
+
+ /*
+ Sanity check we have a PR kick if there are client or server fences
+ */
+#if defined(UNDER_WDDM)
+ /* sanity check only applies to WDDM for a TA kick. 3D kicks don't have a PR kick
+ * but do have fences
+ */
+ if(bKickTA)
+ {
+#endif
+ if (!bKickPR & ((ui32Client3DFenceCount != 0) || (ui32Server3DSyncPrims != 0)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: 3D fence (client or server) passed without a PR kick", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+#if defined(UNDER_WDDM)
+ }
+#endif
+
+ /* Init and acquire to TA command if required */
+ if(bKickTA)
+ {
+ RGX_SERVER_RC_TA_DATA *psTAData = &psRenderContext->sTAData;
+
+ ui32IntClientTAFenceCount = ui32ClientTAFenceCount;
+ pauiIntClientTAFenceUFOAddress = pauiClientTAFenceUFOAddress;
+ paui32IntClientTAFenceValue = paui32ClientTAFenceValue;
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ if (ui32NumFenceFDs)
+ {
+ /*
+ This call is only using the Android fd sync to fence the
+ TA command. There is an update but this is used to
+ indicate that the fence has been finished with and so it
+ can happen after the PR as by then we've finished using
+ the fd sync
+ */
+ eError =
+ pvr_sync_append_fences("TA",
+ ui32NumFenceFDs,
+ ai32FenceFDs,
+ -1,
+ ui32NumUpdateSyncs,
+ puiUpdateFWAddrs,
+ pui32UpdateValues,
+ ui32IntClientTAFenceCount,
+ pauiIntClientTAFenceUFOAddress,
+ paui32IntClientTAFenceValue,
+ &psFDData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_fdsync;
+ }
+ ui32NumUpdateSyncs = psFDData->nr_updates;
+ puiUpdateFWAddrs = psFDData->update_ufo_addresses;
+ pui32UpdateValues = psFDData->update_values;
+ ui32IntClientTAFenceCount = psFDData->nr_checks;
+ pauiIntClientTAFenceUFOAddress = psFDData->check_ufo_addresses;
+ paui32IntClientTAFenceValue = psFDData->check_values;
+ }
+#endif /* PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC */
+
+ /* Init the TA command helper */
+ eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psTAData->psServerCommonContext),
+ ui32IntClientTAFenceCount,
+ pauiIntClientTAFenceUFOAddress,
+ paui32IntClientTAFenceValue,
+ ui32ClientTAUpdateCount,
+ pauiClientTAUpdateUFOAddress,
+ paui32ClientTAUpdateValue,
+ ui32ServerTASyncPrims,
+ paui32ServerTASyncFlags,
+ pasServerTASyncs,
+ ui32TACmdSize,
+ pui8TADMCmd,
+ & pPreAddr,
+ (bKick3D ? IMG_NULL : & pPostAddr),
+ (bKick3D ? IMG_NULL : & pRMWUFOAddr),
+ RGXFWIF_CCB_CMD_TYPE_TA,
+ bPDumpContinuous,
+ "TA",
+ &sTACmdHelperData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_tacmdinit;
+ }
+
+ eError = RGXCmdHelperAcquireCmdCCB(1,
+ &sTACmdHelperData,
+ &bKickTADM);
+ if (eError != PVRSRV_OK)
+ {
+ if (!bKickTADM)
+ {
+ goto fail_taacquirecmd;
+ }
+ else
+ {
+ /* commit the TA ref counting next time, when the CCB space is successfully
+ * acquired
+ */
+ bCommitRefCountsTA = IMG_FALSE;
+ }
+ }
+ else
+ {
+ ui32TACmdCount++;
+ }
+ }
+
+ /* Only kick the 3D if required */
+ if (eError == PVRSRV_OK)
+ {
+ if (bKickPR)
+ {
+ RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
+
+ if (ui32Server3DSyncPrims)
+ {
+ /*
+ The fence (and possible update) straddle multiple commands so
+ we have to modify the flags to do the right things at the right
+ time.
+ At this stage we should only fence, any updates will happen with
+ the normal 3D command.
+ */
+ paui32Server3DSyncFlagsPR = OSAllocMem(sizeof(IMG_UINT32) * ui32Server3DSyncPrims);
+ if (paui32Server3DSyncFlagsPR == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_prserversyncflagsallocpr;
+ }
+
+ /* Copy only the fence flag across */
+ for (i=0;i<ui32Server3DSyncPrims;i++)
+ {
+ paui32Server3DSyncFlagsPR[i] = paui32Server3DSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK;
+ }
+ }
+
+ /*
+ 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 */
+ eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
+ ui32Client3DFenceCount,
+ pauiClient3DFenceUFOAddress,
+ paui32Client3DFenceValue,
+ 0,
+ IMG_NULL,
+ IMG_NULL,
+ (bKick3D ? ui32Server3DSyncPrims : 0),
+ paui32Server3DSyncFlagsPR,
+ pasServer3DSyncs,
+ sizeof(sPRUFO),
+ (IMG_UINT8*) &sPRUFO,
+ IMG_NULL,
+ IMG_NULL,
+ IMG_NULL,
+ RGXFWIF_CCB_CMD_TYPE_FENCE_PR,
+ bPDumpContinuous,
+ "3D-PR Fence",
+ &as3DCmdHelperData[ui323DCmdCount++]);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_prfencecmdinit;
+ }
+
+ /* Init the 3D PR command helper */
+ /*
+ See note above PVRFDSyncQueryFencesKM as to why updates for android
+ syncs are passed in with the PR
+ */
+ eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
+ 0,
+ IMG_NULL,
+ IMG_NULL,
+ ui32NumUpdateSyncs,
+ puiUpdateFWAddrs,
+ pui32UpdateValues,
+ 0,
+ IMG_NULL,
+ IMG_NULL,
+ ui323DPRCmdSize,
+ pui83DPRDMCmd,
+ IMG_NULL,
+ IMG_NULL,
+ IMG_NULL,
+ RGXFWIF_CCB_CMD_TYPE_3D_PR,
+ bPDumpContinuous,
+ "3D-PR",
+ &as3DCmdHelperData[ui323DCmdCount++]);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_prcmdinit;
+ }
+ }
+
+ if (bKick3D || bAbort)
+ {
+ RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
+
+ if (ui32Server3DSyncPrims)
+ {
+ /*
+ Copy only the update flags for the 3D as the fences will be in
+ the PR command created above
+ */
+ paui32Server3DSyncFlags3D = OSAllocMem(sizeof(IMG_UINT32) * ui32Server3DSyncPrims);
+ if (paui32Server3DSyncFlags3D == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_prserversyncflagsalloc3d;
+ }
+
+ /* Copy only the update flag across */
+ for (i=0;i<ui32Server3DSyncPrims;i++)
+ {
+ paui32Server3DSyncFlags3D[i] = paui32Server3DSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE;
+ }
+ }
+
+ /* Init the 3D command helper */
+ eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
+ 0,
+ IMG_NULL,
+ IMG_NULL,
+ ui32Client3DUpdateCount,
+ pauiClient3DUpdateUFOAddress,
+ paui32Client3DUpdateValue,
+ ui32Server3DSyncPrims,
+ paui32Server3DSyncFlags3D,
+ pasServer3DSyncs,
+ ui323DCmdSize,
+ pui83DDMCmd,
+ (bKickTA ? IMG_NULL : & pPreAddr),
+ & pPostAddr,
+ & pRMWUFOAddr,
+ RGXFWIF_CCB_CMD_TYPE_3D,
+ bPDumpContinuous,
+ "3D",
+ &as3DCmdHelperData[ui323DCmdCount++]);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_3dcmdinit;
+ }
+ }
+
+ if (ui323DCmdCount)
+ {
+ PVR_ASSERT(bKickPR || bKick3D);
+
+ /* Acquire space for all the 3D command(s) */
+ eError = RGXCmdHelperAcquireCmdCCB(ui323DCmdCount,
+ as3DCmdHelperData,
+ &bKick3DDM);
+ if (eError != PVRSRV_OK)
+ {
+ if (!bKick3DDM && !bKickTADM)
+ {
+ goto fail_3dacquirecmd;
+ }
+ else
+ {
+ /*
+ There are no DM commands but we still need to kick the
+ DM to flush out the padding command.
+ Also reset the TA count as we're going to try again
+ */
+ ui32TACmdCount = 0;
+ ui323DCmdCount = 0;
+
+ /* commit the 3D ref counting next time, when the CCB space is
+ * successfully acquired
+ */
+ bCommitRefCounts3D = IMG_FALSE;
+ }
+ }
+ }
+ }
+
+ /*
+ 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)
+ {
+ RGXCmdHelperReleaseCmdCCB(ui32TACmdCount,
+ &sTACmdHelperData,
+ "TA",
+ FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext).ui32Addr);
+ }
+
+ if (ui323DCmdCount)
+ {
+ RGXCmdHelperReleaseCmdCCB(ui323DCmdCount,
+ as3DCmdHelperData,
+ "3D",
+ FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext).ui32Addr);
+ }
+
+ if (bKickTADM)
+ {
+ RGXFWIF_KCCB_CMD sTAKCCBCmd;
+
+ /* Construct the kernel TA CCB command. */
+ sTAKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+ sTAKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext);
+ sTAKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext));
+
+ if(bCommitRefCountsTA)
+ {
+ AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &sTAKCCBCmd.uCmdData.sCmdKickData.apsCleanupCtl,
+ &sTAKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl,
+ RGXFWIF_DM_TA,
+ bKickTA,
+ psRTDataCleanup,
+ psZBuffer,
+ psSBuffer);
+ *pbCommittedRefCountsTA = IMG_TRUE;
+ }
+ else
+ {
+ sTAKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+ }
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
+ RGXFWIF_DM_TA,
+ &sTAKCCBCmd,
+ sizeof(sTAKCCBCmd),
+ bPDumpContinuous);
+ if (eError2 != PVRSRV_ERROR_RETRY)
+ {
+ break;
+ }
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+ RGXHWPerfFTraceGPUEnqueueEvent(psRenderContext->psDeviceNode->pvDevice,
+ ui32ExtJobRef, ui32IntJobRef, "TA3D");
+#endif
+
+ }
+
+ if (bKick3DDM)
+ {
+ RGXFWIF_KCCB_CMD s3DKCCBCmd;
+
+ /* Construct the kernel 3D CCB command. */
+ s3DKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+ s3DKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext);
+ s3DKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext));
+
+ if(bCommitRefCounts3D)
+ {
+ AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &s3DKCCBCmd.uCmdData.sCmdKickData.apsCleanupCtl,
+ &s3DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl,
+ RGXFWIF_DM_3D,
+ bKick3D,
+ psRTDataCleanup,
+ psZBuffer,
+ psSBuffer);
+ *pbCommittedRefCounts3D = IMG_TRUE;
+ }
+ else
+ {
+ s3DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+ }
+
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
+ RGXFWIF_DM_3D,
+ &s3DKCCBCmd,
+ sizeof(s3DKCCBCmd),
+ bPDumpContinuous);
+ if (eError2 != PVRSRV_ERROR_RETRY)
+ {
+ break;
+ }
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+ }
+
+ /*
+ * 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_3dacquirecmd;
+ }
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#if defined(NO_HARDWARE)
+ pvr_sync_nohw_complete_fences(psFDData);
+#endif
+ pvr_sync_free_append_fences_data(psFDData);
+
+#endif
+ if(paui32Server3DSyncFlags3D)
+ {
+ OSFreeMem(paui32Server3DSyncFlags3D);
+ }
+
+ if(paui32Server3DSyncFlagsPR)
+ {
+ OSFreeMem(paui32Server3DSyncFlagsPR);
+ }
+
+ return PVRSRV_OK;
+
+fail_3dacquirecmd:
+fail_3dcmdinit:
+ if (paui32Server3DSyncFlags3D)
+ {
+ OSFreeMem(paui32Server3DSyncFlags3D);
+ }
+fail_prserversyncflagsalloc3d:
+fail_prcmdinit:
+fail_prfencecmdinit:
+ if (paui32Server3DSyncFlagsPR)
+ {
+ OSFreeMem(paui32Server3DSyncFlagsPR);
+ }
+fail_prserversyncflagsallocpr:
+fail_taacquirecmd:
+fail_tacmdinit:
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ pvr_sync_rollback_append_fences(psFDData);
+ pvr_sync_free_append_fences_data(psFDData);
+fail_fdsync:
+#endif
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXSetRenderContextPriorityKM(CONNECTION_DATA *psConnection,
+ RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+ IMG_UINT32 ui32Priority)
+{
+ PVRSRV_ERROR eError;
+
+ if (psRenderContext->sTAData.ui32Priority != ui32Priority)
+ {
+ eError = ContextSetPriority(psRenderContext->sTAData.psServerCommonContext,
+ psConnection,
+ psRenderContext->psDeviceNode->pvDevice,
+ ui32Priority,
+ RGXFWIF_DM_TA);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the TA part of the rendercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(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)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+ goto fail_3dcontext;
+ }
+ psRenderContext->s3DData.ui32Priority = ui32Priority;
+ }
+ return PVRSRV_OK;
+
+fail_3dcontext:
+fail_tacontext:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+/*
+ * PVRSRVRGXGetLastResetReason
+ */
+PVRSRV_ERROR PVRSRVRGXGetLastRenderContextResetReasonKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+ IMG_UINT32 *peLastResetReason)
+{
+ RGX_SERVER_RC_TA_DATA *psRenderCtxTAData = &(psRenderContext->sTAData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServerTACommonCtx = psRenderCtxTAData->psServerCommonContext;
+ RGX_SERVER_RC_3D_DATA *psRenderCtx3DData = &(psRenderContext->s3DData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServer3DCommonCtx = psRenderCtx3DData->psServerCommonContext;
+ RGXFWIF_CONTEXT_RESET_REASON eLastTAResetReason, eLast3DResetReason;
+
+ PVR_ASSERT(psRenderContext != IMG_NULL);
+ PVR_ASSERT(peLastResetReason != IMG_NULL);
+
+ /* Get the last reset reasons from both the TA and 3D so they are reset... */
+ eLastTAResetReason = FWCommonContextGetLastResetReason(psCurrentServerTACommonCtx);
+ eLast3DResetReason = FWCommonContextGetLastResetReason(psCurrentServer3DCommonCtx);
+
+ /* Combine the reset reason from TA and 3D into one... */
+ *peLastResetReason = (IMG_UINT32) eLast3DResetReason;
+ if (eLast3DResetReason == RGXFWIF_CONTEXT_RESET_REASON_NONE ||
+ ((eLast3DResetReason == RGXFWIF_CONTEXT_RESET_REASON_INNOCENT_LOCKUP ||
+ eLast3DResetReason == RGXFWIF_CONTEXT_RESET_REASON_INNOCENT_OVERRUNING) &&
+ (eLastTAResetReason == RGXFWIF_CONTEXT_RESET_REASON_GUILTY_LOCKUP ||
+ eLastTAResetReason == RGXFWIF_CONTEXT_RESET_REASON_GUILTY_OVERRUNING)))
+ {
+ *peLastResetReason = (IMG_UINT32) eLastTAResetReason;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+/*
+ * PVRSRVRGXGetPartialRenderCountKM
+ */
+PVRSRV_ERROR PVRSRVRGXGetPartialRenderCountKM(DEVMEM_MEMDESC *psHWRTDataMemDesc,
+ IMG_UINT32 *pui32NumPartialRenders)
+{
+ RGXFWIF_HWRTDATA *psHWRTData;
+ PVRSRV_ERROR eError;
+
+ eError = DevmemAcquireCpuVirtAddr(psHWRTDataMemDesc, (IMG_VOID **)&psHWRTData);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXGetPartialRenderCountKM: Failed to map Firmware Render Target Data (%u)", eError));
+ return eError;
+ }
+
+ *pui32NumPartialRenders = psHWRTData->ui32NumPartialRenders;
+
+ DevmemReleaseCpuVirtAddr(psHWRTDataMemDesc);
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_BOOL CheckForStalledRenderCtxtCommand(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ RGX_SERVER_RENDER_CONTEXT *psCurrentServerRenderCtx = IMG_CONTAINER_OF(psNode, RGX_SERVER_RENDER_CONTEXT, sListNode);
+ RGX_SERVER_RC_TA_DATA *psRenderCtxTAData = &(psCurrentServerRenderCtx->sTAData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServerTACommonCtx = psRenderCtxTAData->psServerCommonContext;
+ RGX_SERVER_RC_3D_DATA *psRenderCtx3DData = &(psCurrentServerRenderCtx->s3DData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServer3DCommonCtx = psRenderCtx3DData->psServerCommonContext;
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = pvCallbackData;
+
+
+ DumpStalledFWCommonContext(psCurrentServerTACommonCtx, pfnDumpDebugPrintf);
+ DumpStalledFWCommonContext(psCurrentServer3DCommonCtx, pfnDumpDebugPrintf);
+
+ return IMG_TRUE;
+}
+IMG_VOID CheckForStalledRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ OSWRLockAcquireRead(psDevInfo->hRenderCtxListLock, DEVINFO_RENDERLIST);
+ dllist_foreach_node(&(psDevInfo->sRenderCtxtListHead),
+ CheckForStalledRenderCtxtCommand, pfnDumpDebugPrintf);
+ OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
+}
+
+static IMG_BOOL CheckForStalledClientRenderCtxtCommand(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ PVRSRV_ERROR *peError = (PVRSRV_ERROR*)pvCallbackData;
+ RGX_SERVER_RENDER_CONTEXT *psCurrentServerRenderCtx = IMG_CONTAINER_OF(psNode, RGX_SERVER_RENDER_CONTEXT, sListNode);
+ RGX_SERVER_RC_TA_DATA *psRenderCtxTAData = &(psCurrentServerRenderCtx->sTAData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServerTACommonCtx = psRenderCtxTAData->psServerCommonContext;
+ RGX_SERVER_RC_3D_DATA *psRenderCtx3DData = &(psCurrentServerRenderCtx->s3DData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServer3DCommonCtx = psRenderCtx3DData->psServerCommonContext;
+
+ if (PVRSRV_ERROR_CCCB_STALLED == CheckStalledClientCommonContext(psCurrentServerTACommonCtx))
+ {
+ *peError = PVRSRV_ERROR_CCCB_STALLED;
+ }
+ if (PVRSRV_ERROR_CCCB_STALLED == CheckStalledClientCommonContext(psCurrentServer3DCommonCtx))
+ {
+ *peError = PVRSRV_ERROR_CCCB_STALLED;
+ }
+
+ return IMG_TRUE;
+}
+IMG_BOOL CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ OSWRLockAcquireRead(psDevInfo->hRenderCtxListLock, DEVINFO_RENDERLIST);
+ dllist_foreach_node(&(psDevInfo->sRenderCtxtListHead),
+ CheckForStalledClientRenderCtxtCommand, &eError);
+ OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
+ return (PVRSRV_ERROR_CCCB_STALLED == eError)? IMG_TRUE: IMG_FALSE;
+}
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXKickSyncTAKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+ IMG_UINT32 ui32TAClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiTAClientFenceUFOAddress,
+ IMG_UINT32 *paui32TAClientFenceValue,
+ IMG_UINT32 ui32TAClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiTAClientUpdateUFOAddress,
+ IMG_UINT32 *paui32TAClientUpdateValue,
+ IMG_UINT32 ui32TAServerSyncPrimsCount,
+ IMG_UINT32 *paui32TAServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasTAServerSyncs,
+ IMG_UINT32 ui323DClientFenceCount,
+ PRGXFWIF_UFO_ADDR *paui3DClientFenceUFOAddress,
+ IMG_UINT32 *paui323DClientFenceValue,
+ IMG_UINT32 ui323DClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *paui3DClientUpdateUFOAddress,
+ IMG_UINT32 *paui323DClientUpdateValue,
+ IMG_UINT32 ui323DServerSyncPrimsCount,
+ IMG_UINT32 *paui323DServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pas3DServerSyncs,
+ IMG_UINT32 ui32NumFenceFDs,
+ IMG_INT32 *pai32FenceFDs,
+ IMG_BOOL bPDumpContinuous)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ /* Android fd sync update info */
+ struct pvr_sync_append_data *psFDData = NULL;
+
+ /* Android FD fences are hardcoded to updates (IMG_TRUE below), Fences go to the TA and updates to the 3D */
+ if (ui32NumFenceFDs)
+ {
+ eError =
+ pvr_sync_append_fences("TA",
+ ui32NumFenceFDs,
+ pai32FenceFDs,
+ -1,
+ ui323DClientUpdateCount,
+ paui3DClientUpdateUFOAddress,
+ paui323DClientUpdateValue,
+ ui323DClientFenceCount,
+ paui3DClientFenceUFOAddress,
+ paui323DClientFenceValue,
+ &psFDData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_fdsync;
+ }
+ ui323DClientUpdateCount = psFDData->nr_updates;
+ paui3DClientUpdateUFOAddress = psFDData->update_ufo_addresses;
+ paui323DClientUpdateValue = psFDData->update_values;
+ ui323DClientFenceCount = psFDData->nr_checks;
+ paui3DClientFenceUFOAddress = psFDData->check_ufo_addresses;
+ paui323DClientFenceValue = psFDData->check_values;
+ }
+#endif
+
+ /* send one command through the TA */
+ if ((ui32TAClientFenceCount + ui32TAClientUpdateCount + ui32TAServerSyncPrimsCount) > 0)
+ {
+ eError = RGXKickSyncKM(psRenderContext->psDeviceNode,
+ psRenderContext->sTAData.psServerCommonContext,
+ RGXFWIF_DM_TA,
+ "SyncTA",
+ ui32TAClientFenceCount,
+ pauiTAClientFenceUFOAddress,
+ paui32TAClientFenceValue,
+ ui32TAClientUpdateCount,
+ pauiTAClientUpdateUFOAddress,
+ paui32TAClientUpdateValue,
+ ui32TAServerSyncPrimsCount,
+ paui32TAServerSyncFlags,
+ pasTAServerSyncs,
+ bPDumpContinuous);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to send TA sync command (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+ goto fail_kickTA;
+ }
+ }
+
+ /* and another one through the 3D */
+ if ((ui323DClientFenceCount + ui323DClientUpdateCount + ui323DServerSyncPrimsCount) > 0)
+ {
+ eError = RGXKickSyncKM(psRenderContext->psDeviceNode,
+ psRenderContext->s3DData.psServerCommonContext,
+ RGXFWIF_DM_3D,
+ "Sync3D",
+ ui323DClientFenceCount,
+ paui3DClientFenceUFOAddress,
+ paui323DClientFenceValue,
+ ui323DClientUpdateCount,
+ paui3DClientUpdateUFOAddress,
+ paui323DClientUpdateValue,
+ ui323DServerSyncPrimsCount,
+ paui323DServerSyncFlags,
+ pas3DServerSyncs,
+ bPDumpContinuous);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to send 3D sync command (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+ goto fail_kick3D;
+ }
+ }
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#if defined(NO_HARDWARE)
+ pvr_sync_nohw_complete_fences(psFDData);
+#endif /* NO_HARDWARE */
+ pvr_sync_free_append_fences_data(psFDData);
+#endif /* PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC */
+
+ return eError;
+
+fail_kick3D:
+fail_kickTA:
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ pvr_sync_rollback_append_fences(psFDData);
+ pvr_sync_free_append_fences_data(psFDData);
+fail_fdsync:
+#endif
+
+ return eError;
+}
+/******************************************************************************
+ End of file (rgxta3d.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxta3d.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxta3d.h
new file mode 100644
index 000000000000..61b40adb9298
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxta3d.h
@@ -0,0 +1,467 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+
+#if !defined(__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"
+
+typedef struct _RGX_SERVER_RENDER_CONTEXT_ RGX_SERVER_RENDER_CONTEXT;
+typedef struct _RGX_FREELIST_ RGX_FREELIST;
+typedef struct _RGX_PMR_NODE_ RGX_PMR_NODE;
+
+typedef struct {
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ DEVMEM_MEMDESC *psFWHWRTDataMemDesc;
+ DEVMEM_MEMDESC *psRTACtlMemDesc;
+ DEVMEM_MEMDESC *psRTArrayMemDesc;
+ RGX_FREELIST *apsFreeLists[RGXFW_MAX_FREELISTS];
+ PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync;
+} RGX_RTDATA_CLEANUP_DATA;
+
+struct _RGX_FREELIST_ {
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+
+ /* Free list PMR */
+ PMR *psFreeListPMR;
+ IMG_DEVMEM_OFFSET_T uiFreeListPMROffset;
+
+ /* Freelist config */
+ IMG_UINT32 ui32MaxFLPages;
+ IMG_UINT32 ui32InitFLPages;
+ IMG_UINT32 ui32CurrentFLPages;
+ IMG_UINT32 ui32GrowFLPages;
+ IMG_UINT32 ui32FreelistID;
+ 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;
+
+ /* FW data structures */
+ DEVMEM_MEMDESC *psFWFreelistMemDesc;
+ RGXFWIF_DEV_VIRTADDR sFreeListFWDevVAddr;
+
+ PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync;
+} ;
+
+struct _RGX_PMR_NODE_ {
+ RGX_FREELIST *psFreeList;
+ PMR *psPMR;
+ PMR_PAGELIST *psPageList;
+ DLLIST_NODE sMemoryBlock;
+ IMG_UINT32 ui32NumPages;
+ IMG_BOOL bInternal;
+} ;
+
+typedef struct {
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ DEVMEM_MEMDESC *psRenderTargetMemDesc;
+} RGX_RT_CLEANUP_DATA;
+
+typedef struct {
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+ DEVMEM_MEMDESC *psZSBufferMemDesc;
+ 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;
+
+ PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync;
+}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 */
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateHWRTData(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 psRenderTarget,
+ IMG_DEV_VIRTADDR psPMMListDevVAddr,
+ IMG_DEV_VIRTADDR psVFPPageTableAddr,
+ RGX_FREELIST *apsFreeLists[RGXFW_MAX_FREELISTS],
+ RGX_RTDATA_CLEANUP_DATA **ppsCleanupData,
+ DEVMEM_MEMDESC **ppsRTACtlMemDesc,
+ IMG_UINT32 ui32PPPScreen,
+ IMG_UINT32 ui32PPPGridOffset,
+ IMG_UINT64 ui64PPPMultiSampleCtl,
+ 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_UINT16 ui16MaxRTs,
+ DEVMEM_MEMDESC **psMemDesc,
+ IMG_UINT32 *puiHWRTData);
+
+/* Destroy HWRTData */
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyHWRTData(RGX_RTDATA_CLEANUP_DATA *psCleanupData);
+
+/* Create Render Target */
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateRenderTarget(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR psVHeapTableDevVAddr,
+ RGX_RT_CLEANUP_DATA **ppsCleanupData,
+ IMG_UINT32 *sRenderTargetFWDevVAddr);
+
+/* Destroy render target */
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyRenderTarget(RGX_RT_CLEANUP_DATA *psCleanupData);
+
+
+/*
+ RGXCreateZSBuffer
+*/
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateZSBufferKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ DEVMEMINT_RESERVATION *psReservation,
+ PMR *psPMR,
+ PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
+ RGX_ZSBUFFER_DATA **ppsZSBuffer,
+ IMG_UINT32 *sRenderTargetFWDevVAddr);
+
+/*
+ RGXDestroyZSBuffer
+*/
+IMG_EXPORT
+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)
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXPopulateZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer,
+ RGX_POPULATION **ppsPopulation);
+
+/*
+ * RGXUnbackingZSBuffer()
+ *
+ * Frees ZS-Buffer's physical pages
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXUnbackingZSBuffer(RGX_ZSBUFFER_DATA *psZSBuffer);
+
+/*
+ * RGXUnpopulateZSBufferKM()
+ *
+ * Frees ZS-Buffer's physical pages (called by Bridge calls )
+ */
+IMG_EXPORT
+PVRSRV_ERROR RGXUnpopulateZSBufferKM(RGX_POPULATION *psPopulation);
+
+/*
+ RGXProcessRequestZSBufferBacking
+*/
+IMG_EXPORT
+IMG_VOID RGXProcessRequestZSBufferBacking(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32ZSBufferID);
+
+/*
+ RGXProcessRequestZSBufferUnbacking
+*/
+IMG_EXPORT
+IMG_VOID RGXProcessRequestZSBufferUnbacking(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32ZSBufferID);
+
+/*
+ RGXGrowFreeList
+*/
+IMG_INTERNAL
+PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
+ IMG_UINT32 ui32NumPages,
+ PDLLIST_NODE pListHeader);
+
+/* Create free list */
+IMG_EXPORT
+PVRSRV_ERROR RGXCreateFreeList(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32MaxFLPages,
+ IMG_UINT32 ui32InitFLPages,
+ IMG_UINT32 ui32GrowFLPages,
+ IMG_BOOL bCheckFreelist,
+ IMG_DEV_VIRTADDR sFreeListDevVAddr,
+ PMR *psFreeListPMR,
+ IMG_DEVMEM_OFFSET_T uiFreeListPMROffset,
+ RGX_FREELIST **ppsFreeList);
+
+/* Destroy free list */
+IMG_EXPORT
+PVRSRV_ERROR RGXDestroyFreeList(RGX_FREELIST *psFreeList);
+
+/*
+ RGXProcessRequestGrow
+*/
+IMG_EXPORT
+IMG_VOID RGXProcessRequestGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32FreelistID);
+
+
+/* Grow free list */
+IMG_EXPORT
+PVRSRV_ERROR RGXAddBlockToFreeListKM(RGX_FREELIST *psFreeList,
+ IMG_UINT32 ui32NumPages);
+
+/* Shrink free list */
+IMG_EXPORT
+PVRSRV_ERROR RGXRemoveBlockFromFreeListKM(RGX_FREELIST *psFreeList);
+
+
+/* Reconstruct free list after Hardware Recovery */
+IMG_VOID RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGXFWIF_DM eDM,
+ IMG_UINT32 ui32FreelistsCount,
+ IMG_UINT32 *paui32Freelists);
+
+/*!
+*******************************************************************************
+
+ @Function PVRSRVRGXCreateRenderContextKM
+
+ @Description
+ Server-side implementation of RGXCreateRenderContext
+
+ @Input pvDeviceNode - device node
+ @Input psTACCBMemDesc - TA CCB Memory descriptor
+ @Input psTACCBCtlMemDesc - TA CCB Ctrl Memory descriptor
+ @Input ps3DCCBMemDesc - 3D CCB Memory descriptor
+ @Input ps3DCCBCtlMemDesc - 3D CCB Ctrl Memory descriptor
+ @Input ui32Priority - context priority
+ @Input sMCUFenceAddr - MCU Fence device virtual address
+ @Input psVDMStackPointer - VDM call stack device virtual address
+ @Input ui32FrameworkRegisterSize - framework register size
+ @Input pbyFrameworkRegisters - ptr to framework register
+ @Input hMemCtxPrivData - memory context private data
+ @Output ppsCleanupData - clean up data
+ @Output ppsFWRenderContextMemDesc - firmware render context memory descriptor
+ @Output ppsFWContextStateMemDesc - firmware context state memory descriptor
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32Priority,
+ IMG_DEV_VIRTADDR sMCUFenceAddr,
+ IMG_DEV_VIRTADDR sVDMCallStackAddr,
+ IMG_UINT32 ui32FrameworkCommandSize,
+ IMG_PBYTE pabyFrameworkCommand,
+ IMG_HANDLE hMemCtxPrivData,
+ RGX_SERVER_RENDER_CONTEXT **ppsRenderContext);
+
+
+/*!
+*******************************************************************************
+
+ @Function PVRSRVRGXDestroyRenderContextKM
+
+ @Description
+ Server-side implementation of RGXDestroyRenderContext
+
+ @Input psCleanupData - clean up data
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+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
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+ IMG_UINT32 ui32ClientTAFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientTAFenceUFOAddress,
+ IMG_UINT32 *paui32ClientTAFenceValue,
+ IMG_UINT32 ui32ClientTAUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdateTAUFOAddress,
+ IMG_UINT32 *paui32ClientTAUpdateValue,
+ IMG_UINT32 ui32ServerTASyncPrims,
+ IMG_UINT32 *paui32ServerTASyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerTASyncs,
+ IMG_UINT32 ui32Client3DFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClient3DFenceUFOAddress,
+ IMG_UINT32 *paui32Client3DFenceValue,
+ IMG_UINT32 ui32Client3DUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdate3DUFOAddress,
+ IMG_UINT32 *paui32Client3DUpdateValue,
+ IMG_UINT32 ui32Server3DSyncPrims,
+ IMG_UINT32 *paui32Server3DSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServer3DSyncs,
+ PRGXFWIF_UFO_ADDR uiPRFenceUFOAddress,
+ IMG_UINT32 ui32PRFenceValue,
+ IMG_UINT32 ui32NumFenceFds,
+ IMG_INT32 *pai32FenceFds,
+ IMG_UINT32 ui32TACmdSize,
+ IMG_PBYTE pui8TADMCmd,
+ IMG_UINT32 ui323DPRCmdSize,
+ IMG_PBYTE pui83DPRDMCmd,
+ IMG_UINT32 ui323DCmdSize,
+ IMG_PBYTE pui83DDMCmd,
+ IMG_UINT32 TAFrameNum,
+ IMG_UINT32 TARTData,
+ IMG_BOOL bLastTAInScene,
+ IMG_BOOL bKickTA,
+ IMG_BOOL bKickPR,
+ IMG_BOOL bKick3D,
+ IMG_BOOL bAbort,
+ IMG_BOOL bPDumpContinuous,
+ RGX_RTDATA_CLEANUP_DATA *psRTDataCleanup,
+ RGX_ZSBUFFER_DATA *psZBuffer,
+ RGX_ZSBUFFER_DATA *psSBuffer,
+ IMG_BOOL bCommitRefCountsTA,
+ IMG_BOOL bCommitRefCounts3D,
+ IMG_BOOL *pbCommittedRefCountsTA,
+ IMG_BOOL *pbCommittedRefCounts3D);
+
+
+PVRSRV_ERROR PVRSRVRGXSetRenderContextPriorityKM(CONNECTION_DATA *psConnection,
+ RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+ IMG_UINT32 ui32Priority);
+
+PVRSRV_ERROR PVRSRVRGXGetLastRenderContextResetReasonKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+ IMG_UINT32 *peLastResetReason);
+
+PVRSRV_ERROR PVRSRVRGXGetPartialRenderCountKM(DEVMEM_MEMDESC *psHWRTDataMemDesc,
+ IMG_UINT32 *pui32NumPartialRenders);
+
+/* Debug - check if render context is waiting on a fence */
+IMG_VOID CheckForStalledRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf);
+
+/* Debug/Watchdog - check if client contexts are stalled */
+IMG_BOOL CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVRGXKickSyncTAKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+ IMG_UINT32 ui32TAClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiTAClientFenceUFOAddress,
+ IMG_UINT32 *paui32TAClientFenceValue,
+ IMG_UINT32 ui32TAClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiTAClientUpdateUFOAddress,
+ IMG_UINT32 *paui32TAClientUpdateValue,
+ IMG_UINT32 ui32TAServerSyncPrims,
+ IMG_UINT32 *paui32TAServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasTAServerSyncs,
+ IMG_UINT32 ui323DClientFenceCount,
+ PRGXFWIF_UFO_ADDR *paui3DClientFenceUFOAddress,
+ IMG_UINT32 *paui323DClientFenceValue,
+ IMG_UINT32 ui323DClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *paui3DClientUpdateUFOAddress,
+ IMG_UINT32 *paui323DClientUpdateValue,
+ IMG_UINT32 ui323DServerSyncPrims,
+ IMG_UINT32 *paui323DServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pas3DServerSyncs,
+ IMG_UINT32 ui32NumFenceFDs,
+ IMG_INT32 *paui32FenceFDs,
+ IMG_BOOL bPDumpContinuous);
+
+#endif /* __RGXTA3D_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxtimerquery.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxtimerquery.c
new file mode 100644
index 000000000000..a8146472f6c3
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxtimerquery.c
@@ -0,0 +1,239 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX Timer queries
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX Regconfig 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 "rgxtimerquery.h"
+#include "rgxdevice.h"
+
+#include "rgxfwutils.h"
+
+PVRSRV_ERROR
+PVRSRVRGXBeginTimerQueryKM(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_UINT32 ui32QueryId)
+{
+ PVRSRV_RGXDEV_INFO * psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ if (ui32QueryId >= RGX_MAX_TIMER_QUERIES)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo->bSaveStart = IMG_TRUE;
+ psDevInfo->bSaveEnd = IMG_TRUE;
+
+ /* clear the stamps, in case there is no Kick */
+ psDevInfo->pui64StartTimeById[ui32QueryId] = 0UL;
+ psDevInfo->pui64EndTimeById[ui32QueryId] = 0UL;
+
+ /* save of the active query index */
+ psDevInfo->ui32ActiveQueryId = ui32QueryId;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+PVRSRVRGXEndTimerQueryKM(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+ PVRSRV_RGXDEV_INFO * psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ /* clear off the flags set by Begin(). Note that _START_TIME is
+ * probably already cleared by Kick()
+ */
+ psDevInfo->bSaveStart = IMG_FALSE;
+ psDevInfo->bSaveEnd = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+PVRSRVRGXQueryTimerKM(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_UINT32 ui32QueryId,
+ IMG_UINT64 * pui64StartTime,
+ IMG_UINT64 * pui64EndTime)
+{
+ PVRSRV_RGXDEV_INFO * psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+ IMG_UINT32 ui32Scheduled;
+ IMG_UINT32 ui32Completed;
+
+ if (ui32QueryId >= RGX_MAX_TIMER_QUERIES)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ ui32Scheduled = psDevInfo->aui32ScheduledOnId[ui32QueryId];
+ ui32Completed = psDevInfo->pui32CompletedById[ui32QueryId];
+
+ /* if there was no kick since the Begin() on this id we return 0-s as Begin cleared
+ * the stamps. If there was no begin the returned data is undefined - but still
+ * safe from services pov
+ */
+ if (ui32Completed >= ui32Scheduled)
+ {
+ * pui64StartTime = psDevInfo->pui64StartTimeById[ui32QueryId];
+ * pui64EndTime = psDevInfo->pui64EndTimeById[ui32QueryId];
+
+ return PVRSRV_OK;
+ }
+ else
+ {
+ return PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
+ }
+}
+
+
+PVRSRV_ERROR
+PVRSRVRGXCurrentTime(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_UINT64 * pui64Time)
+{
+ IMG_UINT64 ui64Result;
+ PVRSRV_RGXDEV_INFO * psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVPowerLock();
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCurrentTime: Failed to acquire PowerLock (device index: %d, error: %s)",
+ psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRVGetErrorStringKM(eError)));
+ return eError;
+ }
+
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, IMG_TRUE); /* forced */
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ ui64Result = RGXReadHWTimerReg(psDevInfo);
+
+ PVRSRVPowerUnlock();
+
+ *pui64Time = ui64Result;
+
+ return PVRSRV_OK;
+}
+
+
+
+/******************************************************************************
+ NOT BRIDGED/EXPORTED FUNCS
+******************************************************************************/
+/* writes a time stamp command in the client CCB */
+IMG_VOID
+RGXWriteTimestampCommand(IMG_PBYTE * ppbyPtr,
+ RGXFWIF_CCB_CMD_TYPE eCmdType,
+ PRGXFWIF_TIMESTAMP_ADDR pAddr)
+{
+ RGXFWIF_CCB_CMD_HEADER * psHeader;
+
+ psHeader = (RGXFWIF_CCB_CMD_HEADER *) (*ppbyPtr);
+
+ PVR_ASSERT(eCmdType == RGXFWIF_CCB_CMD_TYPE_PRE_TIMESTAMP
+ || eCmdType == RGXFWIF_CCB_CMD_TYPE_POST_TIMESTAMP);
+
+ psHeader->eCmdType = eCmdType;
+ psHeader->ui32CmdSize = (sizeof(RGXFWIF_DEV_VIRTADDR) + RGXFWIF_FWALLOC_ALIGN - 1) & ~(RGXFWIF_FWALLOC_ALIGN - 1);
+
+ (*ppbyPtr) += sizeof(RGXFWIF_CCB_CMD_HEADER);
+
+ (*(PRGXFWIF_TIMESTAMP_ADDR*)*ppbyPtr) = pAddr;
+
+ (*ppbyPtr) += psHeader->ui32CmdSize;
+}
+
+
+IMG_VOID
+RGX_GetTimestampCmdHelper(PVRSRV_RGXDEV_INFO * psDevInfo,
+ PRGXFWIF_TIMESTAMP_ADDR * ppPreAddr,
+ PRGXFWIF_TIMESTAMP_ADDR * ppPostAddr,
+ PRGXFWIF_UFO_ADDR * ppUpdate)
+{
+ if (ppPreAddr != IMG_NULL)
+ {
+ if (psDevInfo->bSaveStart)
+ {
+ /* drop the SaveStart on the first Kick */
+ psDevInfo->bSaveStart = IMG_FALSE;
+
+ RGXSetFirmwareAddress(ppPreAddr,
+ psDevInfo->psStartTimeMemDesc,
+ sizeof(IMG_UINT64) * psDevInfo->ui32ActiveQueryId,
+ RFW_FWADDR_NOREF_FLAG);
+ }
+ else
+ {
+ ppPreAddr->ui32Addr = 0;
+ }
+ }
+
+ if (ppPostAddr != IMG_NULL && ppUpdate != IMG_NULL)
+ {
+ if (psDevInfo->bSaveEnd)
+ {
+ RGXSetFirmwareAddress(ppPostAddr,
+ psDevInfo->psEndTimeMemDesc,
+ sizeof(IMG_UINT64) * psDevInfo->ui32ActiveQueryId,
+ RFW_FWADDR_NOREF_FLAG);
+
+ psDevInfo->aui32ScheduledOnId[psDevInfo->ui32ActiveQueryId]++;
+
+ RGXSetFirmwareAddress(ppUpdate,
+ psDevInfo->psCompletedMemDesc,
+ sizeof(IMG_UINT32) * psDevInfo->ui32ActiveQueryId,
+ RFW_FWADDR_NOREF_FLAG);
+ }
+ else
+ {
+ ppUpdate->ui32Addr = 0;
+ ppPostAddr->ui32Addr = 0;
+ }
+ }
+}
+
+
+/******************************************************************************
+ End of file (rgxtimerquery.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxtimerquery.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxtimerquery.h
new file mode 100644
index 000000000000..c991257bc01c
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxtimerquery.h
@@ -0,0 +1,129 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX Timer queries
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description RGX Regconfig 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 (_RGX_TIMERQUERIES_H_)
+#define _RGX_TIMERQUERIES_H_
+
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "device.h"
+#include "rgxdevice.h"
+
+/**************************************************************************/ /*!
+@Function PVRSRVRGXBeginTimerQuery
+@Description Opens a new timer query.
+
+@Input ui32QueryId an identifier between [ 0 and RGX_MAX_TIMER_QUERIES - 1 ]
+@Return PVRSRV_OK on success.
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVRGXBeginTimerQueryKM(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_UINT32 ui32QueryId);
+
+
+/**************************************************************************/ /*!
+@Function PVRSRVRGXEndTimerQuery
+@Description Closes a timer query
+
+ The lack of ui32QueryId argument expresses the fact that there can't
+ be overlapping queries open.
+@Return PVRSRV_OK on success.
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVRGXEndTimerQueryKM(PVRSRV_DEVICE_NODE * psDeviceNode);
+
+
+
+/**************************************************************************/ /*!
+@Function PVRSRVRGXQueryTimer
+@Description Queries the state of the specified timer
+
+@Input ui32QueryId an identifier between [ 0 and RGX_MAX_TIMER_QUERIES - 1 ]
+@Out pui64StartTime
+@Out pui64EndTime
+@Return PVRSRV_OK on success.
+ PVRSRV_ERROR_RESOURCE_UNAVAILABLE if the device is still busy with
+ operations from the queried period
+ other error code otherwise
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVRGXQueryTimerKM(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_UINT32 ui32QueryId,
+ IMG_UINT64 * pui64StartTime,
+ IMG_UINT64 * pui64EndTime);
+
+
+/**************************************************************************/ /*!
+@Function PVRSRVRGXCurrentTime
+@Description Returns the current state of the timer used in timer queries
+@Input psDevData Device data.
+@Out pui64Time
+@Return PVRSRV_OK on success.
+*/ /***************************************************************************/
+PVRSRV_ERROR
+PVRSRVRGXCurrentTime(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_UINT64 * pui64Time);
+
+
+/******************************************************************************
+ NON BRIDGED/EXPORTED interface
+******************************************************************************/
+
+/* write the timestamp cmd from the helper*/
+IMG_VOID
+RGXWriteTimestampCommand(IMG_PBYTE * ppui8CmdPtr,
+ RGXFWIF_CCB_CMD_TYPE eCmdType,
+ PRGXFWIF_TIMESTAMP_ADDR pAddr);
+
+/* get the relevant data from the Kick to the helper*/
+IMG_VOID
+RGX_GetTimestampCmdHelper(PVRSRV_RGXDEV_INFO * psDevInfo,
+ PRGXFWIF_TIMESTAMP_ADDR * ppPreAddr,
+ PRGXFWIF_TIMESTAMP_ADDR * ppPostAddr,
+ PRGXFWIF_UFO_ADDR * ppUpdate);
+
+#endif /* _RGX_TIMERQUERIES_H_ */
+
+/******************************************************************************
+ End of file (rgxtimerquery.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxtransfer.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxtransfer.c
new file mode 100644
index 000000000000..4dccc901db5a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxtransfer.c
@@ -0,0 +1,1084 @@
+/*************************************************************************/ /*!
+@File
+@Title Device specific 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 "rgxtransfer.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_fwif_resetframework.h"
+#include "rgx_memallocflags.h"
+#include "rgxccb.h"
+#include "rgxtimerquery.h"
+#include "rgxhwperf.h"
+#include "rgxsync.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#include "pvr_sync.h"
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+typedef struct {
+ DEVMEM_MEMDESC *psFWContextStateMemDesc;
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
+ IMG_UINT32 ui32Priority;
+} RGX_SERVER_TQ_3D_DATA;
+
+typedef struct {
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
+ IMG_UINT32 ui32Priority;
+} RGX_SERVER_TQ_2D_DATA;
+
+struct _RGX_SERVER_TQ_CONTEXT_ {
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ DEVMEM_MEMDESC *psFWFrameworkMemDesc;
+ IMG_UINT32 ui32Flags;
+#define RGX_SERVER_TQ_CONTEXT_FLAGS_2D (1<<0)
+#define RGX_SERVER_TQ_CONTEXT_FLAGS_3D (1<<1)
+ RGX_SERVER_TQ_3D_DATA s3DData;
+ RGX_SERVER_TQ_2D_DATA s2DData;
+ PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync;
+ DLLIST_NODE sListNode;
+};
+
+/*
+ Static functions used by transfer context code
+*/
+
+static PVRSRV_ERROR _Create3DTransferContext(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ DEVMEM_MEMDESC *psFWMemContextMemDesc,
+ IMG_UINT32 ui32Priority,
+ RGX_COMMON_CONTEXT_INFO *psInfo,
+ RGX_SERVER_TQ_3D_DATA *ps3DData)
+{
+ 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("Allocate RGX firmware TQ/3D context suspend state");
+
+ eError = DevmemFwAllocate(psDevInfo,
+ sizeof(RGXFWIF_3DCTX_STATE),
+ RGX_FWCOMCTX_ALLOCFLAGS,
+ "FirmwareTQ3DContext",
+ &ps3DData->psFWContextStateMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_contextswitchstate;
+ }
+
+ eError = FWCommonContextAllocate(psConnection,
+ psDeviceNode,
+ "TQ_3D",
+ IMG_NULL,
+ 0,
+ psFWMemContextMemDesc,
+ ps3DData->psFWContextStateMemDesc,
+ RGX_CCB_SIZE_LOG2,
+ ui32Priority,
+ psInfo,
+ &ps3DData->psServerCommonContext);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_contextalloc;
+ }
+
+
+ PDUMPCOMMENT("Dump 3D context suspend state buffer");
+ DevmemPDumpLoadMem(ps3DData->psFWContextStateMemDesc, 0, sizeof(RGXFWIF_3DCTX_STATE), PDUMP_FLAGS_CONTINUOUS);
+
+ ps3DData->ui32Priority = ui32Priority;
+ return PVRSRV_OK;
+
+fail_contextalloc:
+ DevmemFwFree(ps3DData->psFWContextStateMemDesc);
+fail_contextswitchstate:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+static PVRSRV_ERROR _Create2DTransferContext(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ DEVMEM_MEMDESC *psFWMemContextMemDesc,
+ IMG_UINT32 ui32Priority,
+ RGX_COMMON_CONTEXT_INFO *psInfo,
+ RGX_SERVER_TQ_2D_DATA *ps2DData)
+{
+ PVRSRV_ERROR eError;
+
+ eError = FWCommonContextAllocate(psConnection,
+ psDeviceNode,
+ "TQ_2D",
+ IMG_NULL,
+ 0,
+ psFWMemContextMemDesc,
+ IMG_NULL,
+ RGX_CCB_SIZE_LOG2,
+ ui32Priority,
+ psInfo,
+ &ps2DData->psServerCommonContext);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_contextalloc;
+ }
+
+ ps2DData->ui32Priority = ui32Priority;
+ return PVRSRV_OK;
+
+fail_contextalloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+static PVRSRV_ERROR _Destroy2DTransferContext(RGX_SERVER_TQ_2D_DATA *ps2DData,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
+{
+ PVRSRV_ERROR eError;
+
+ /* Check if the FW has finished with this resource ... */
+ eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
+ FWCommonContextGetFWAddress(ps2DData->psServerCommonContext),
+ psCleanupSync,
+ RGXFWIF_DM_2D);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ return eError;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+ __FUNCTION__,
+ PVRSRVGetErrorStringKM(eError)));
+ }
+
+ /* ... it has so we can free it's resources */
+ FWCommonContextFree(ps2DData->psServerCommonContext);
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _Destroy3DTransferContext(RGX_SERVER_TQ_3D_DATA *ps3DData,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
+{
+ PVRSRV_ERROR eError;
+
+ /* Check if the FW has finished with this resource ... */
+ eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
+ FWCommonContextGetFWAddress(ps3DData->psServerCommonContext),
+ psCleanupSync,
+ RGXFWIF_DM_3D);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ return eError;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+ __FUNCTION__,
+ PVRSRVGetErrorStringKM(eError)));
+ }
+
+ /* ... it has so we can free it's resources */
+ DevmemFwFree(ps3DData->psFWContextStateMemDesc);
+ FWCommonContextFree(ps3DData->psServerCommonContext);
+
+ return PVRSRV_OK;
+}
+
+/*
+ * PVRSRVCreateTransferContextKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32Priority,
+ IMG_DEV_VIRTADDR sMCUFenceAddr,
+ IMG_UINT32 ui32FrameworkCommandSize,
+ IMG_PBYTE pabyFrameworkCommand,
+ IMG_HANDLE hMemCtxPrivData,
+ RGX_SERVER_TQ_CONTEXT **ppsTransferContext)
+{
+ RGX_SERVER_TQ_CONTEXT *psTransferContext;
+ DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+ RGX_COMMON_CONTEXT_INFO sInfo;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ /* Allocate the server side structure */
+ *ppsTransferContext = IMG_NULL;
+ psTransferContext = OSAllocMem(sizeof(*psTransferContext));
+ if (psTransferContext == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psTransferContext, 0, sizeof(*psTransferContext));
+
+ psTransferContext->psDeviceNode = psDeviceNode;
+
+ /* Allocate cleanup sync */
+ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
+ &psTransferContext->psCleanupSync,
+ "transfer context cleanup");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to allocate cleanup sync (0x%x)",
+ eError));
+ goto fail_syncalloc;
+ }
+
+ /*
+ * Create the FW framework buffer
+ */
+ eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode,
+ &psTransferContext->psFWFrameworkMemDesc,
+ ui32FrameworkCommandSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to allocate firmware GPU framework state (%u)",
+ eError));
+ goto fail_frameworkcreate;
+ }
+
+ /* Copy the Framework client data into the framework buffer */
+ eError = PVRSRVRGXFrameworkCopyCommand(psTransferContext->psFWFrameworkMemDesc,
+ pabyFrameworkCommand,
+ ui32FrameworkCommandSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to populate the framework buffer (%u)",
+ eError));
+ goto fail_frameworkcopy;
+ }
+
+ sInfo.psFWFrameworkMemDesc = psTransferContext->psFWFrameworkMemDesc;
+ sInfo.psMCUFenceAddr = &sMCUFenceAddr;
+
+ eError = _Create3DTransferContext(psConnection,
+ psDeviceNode,
+ psFWMemContextMemDesc,
+ ui32Priority,
+ &sInfo,
+ &psTransferContext->s3DData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_3dtransfercontext;
+ }
+ psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_3D;
+
+ eError = _Create2DTransferContext(psConnection,
+ psDeviceNode,
+ psFWMemContextMemDesc,
+ ui32Priority,
+ &sInfo,
+ &psTransferContext->s2DData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_2dtransfercontext;
+ }
+ psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_2D;
+
+ {
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ OSWRLockAcquireWrite(psDevInfo->hTransferCtxListLock, DEVINFO_TRANSFERLIST);
+ dllist_add_to_tail(&(psDevInfo->sTransferCtxtListHead), &(psTransferContext->sListNode));
+ OSWRLockReleaseWrite(psDevInfo->hTransferCtxListLock);
+ }
+
+ *ppsTransferContext = psTransferContext;
+ return PVRSRV_OK;
+
+fail_2dtransfercontext:
+ _Destroy3DTransferContext(&psTransferContext->s3DData,
+ psTransferContext->psDeviceNode,
+ psTransferContext->psCleanupSync);
+fail_3dtransfercontext:
+fail_frameworkcopy:
+ DevmemFwFree(psTransferContext->psFWFrameworkMemDesc);
+fail_frameworkcreate:
+ SyncPrimFree(psTransferContext->psCleanupSync);
+fail_syncalloc:
+ OSFreeMem(psTransferContext);
+ PVR_ASSERT(eError != PVRSRV_OK);
+ *ppsTransferContext = IMG_NULL;
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXDestroyTransferContextKM(RGX_SERVER_TQ_CONTEXT *psTransferContext)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_RGXDEV_INFO *psDevInfo = psTransferContext->psDeviceNode->pvDevice;
+
+ /* remove node from list before calling destroy - as destroy, if successful
+ * will invalidate the node
+ * must be re-added if destroy fails
+ */
+ OSWRLockAcquireWrite(psDevInfo->hTransferCtxListLock, DEVINFO_TRANSFERLIST);
+ dllist_remove_node(&(psTransferContext->sListNode));
+ OSWRLockReleaseWrite(psDevInfo->hTransferCtxListLock);
+
+ if (psTransferContext->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D)
+ {
+ eError = _Destroy2DTransferContext(&psTransferContext->s2DData,
+ psTransferContext->psDeviceNode,
+ psTransferContext->psCleanupSync);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_destroy2d;
+ }
+ /* We've freed the 2D context, don't try to free it again */
+ psTransferContext->ui32Flags &= ~RGX_SERVER_TQ_CONTEXT_FLAGS_2D;
+ }
+
+ if (psTransferContext->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_3D)
+ {
+ eError = _Destroy3DTransferContext(&psTransferContext->s3DData,
+ psTransferContext->psDeviceNode,
+ psTransferContext->psCleanupSync);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_destroy3d;
+ }
+ /* We've freed the 3D context, don't try to free it again */
+ psTransferContext->ui32Flags &= ~RGX_SERVER_TQ_CONTEXT_FLAGS_3D;
+ }
+
+ DevmemFwFree(psTransferContext->psFWFrameworkMemDesc);
+ SyncPrimFree(psTransferContext->psCleanupSync);
+
+ OSFreeMem(psTransferContext);
+
+ return PVRSRV_OK;
+
+fail_destroy2d:
+fail_destroy3d:
+ OSWRLockAcquireWrite(psDevInfo->hTransferCtxListLock, DEVINFO_TRANSFERLIST);
+ dllist_add_to_tail(&(psDevInfo->sTransferCtxtListHead), &(psTransferContext->sListNode));
+ OSWRLockReleaseWrite(psDevInfo->hTransferCtxListLock);
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*
+ * PVRSRVSubmitTQ3DKickKM
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT *psTransferContext,
+ IMG_UINT32 ui32PrepareCount,
+ IMG_UINT32 *paui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR **papauiClientFenceUFOAddress,
+ IMG_UINT32 **papaui32ClientFenceValue,
+ IMG_UINT32 *paui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR **papauiClientUpdateUFOAddress,
+ IMG_UINT32 **papaui32ClientUpdateValue,
+ IMG_UINT32 *paui32ServerSyncCount,
+ IMG_UINT32 **papaui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE ***papapsServerSyncs,
+ IMG_UINT32 ui32NumFenceFDs,
+ IMG_INT32 *pai32FenceFDs,
+ IMG_UINT32 *paui32FWCommandSize,
+ IMG_UINT8 **papaui8FWCommand,
+ IMG_UINT32 *pui32TQPrepareFlags,
+ IMG_UINT32 ui32ExtJobRef,
+ IMG_UINT32 ui32IntJobRef)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = psTransferContext->psDeviceNode;
+#if defined(WDDM)
+ RGX_CCB_CMD_HELPER_DATA as3DCmdHelper[TQ_MAX_PREPARES_PER_SUBMIT];
+ RGX_CCB_CMD_HELPER_DATA as2DCmdHelper[TQ_MAX_PREPARES_PER_SUBMIT];
+#endif
+ RGX_CCB_CMD_HELPER_DATA *pas3DCmdHelper;
+ RGX_CCB_CMD_HELPER_DATA *pas2DCmdHelper;
+ IMG_UINT32 ui323DCmdCount = 0;
+ IMG_UINT32 ui322DCmdCount = 0;
+ IMG_BOOL bKick2D = IMG_FALSE;
+ IMG_BOOL bKick3D = IMG_FALSE;
+ IMG_BOOL bPDumpContinuous = IMG_FALSE;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32IntClientFenceCount = 0;
+ PRGXFWIF_UFO_ADDR *pauiIntFenceUFOAddress = IMG_NULL;
+ IMG_UINT32 *paui32IntFenceValue = IMG_NULL;
+ IMG_UINT32 ui32IntClientUpdateCount = 0;
+ PRGXFWIF_UFO_ADDR *pauiIntUpdateUFOAddress = IMG_NULL;
+ IMG_UINT32 *paui32IntUpdateValue = IMG_NULL;
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError2;
+
+ PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+ PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+ PRGXFWIF_UFO_ADDR pRMWUFOAddr;
+
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ struct pvr_sync_append_data *psFDFenceData = NULL;
+#endif
+
+ if (ui32PrepareCount == 0)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32NumFenceFDs != 0)
+ {
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ /* Fence FD's are only valid in the 3D case with no batching */
+ if ((ui32PrepareCount !=1) && (!TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[0], 3D)))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#else
+ /* We only support Fence FD's if built with PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+#endif
+ }
+#if defined(WDDM)
+ pas3DCmdHelper = &as3DCmdHelper;
+ pas2DCmdHelper = &as2DCmdHelper;
+#else
+ /* We can't allocate the required amount of stack space on all consumer architectures */
+ pas3DCmdHelper = OSAllocMem(sizeof(*pas3DCmdHelper) * ui32PrepareCount);
+ if (pas3DCmdHelper == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc3dhelper;
+ }
+ pas2DCmdHelper = OSAllocMem(sizeof(*pas2DCmdHelper) * ui32PrepareCount);
+ if (pas2DCmdHelper == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc2dhelper;
+ }
+#endif
+ /*
+ Ensure we do the right thing for server syncs which cross call bounderies
+ */
+ for (i=0;i<ui32PrepareCount;i++)
+ {
+ IMG_BOOL bHaveStartPrepare = pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_START;
+ IMG_BOOL bHaveEndPrepare = IMG_FALSE;
+
+ if (bHaveStartPrepare)
+ {
+ IMG_UINT32 k;
+ /*
+ We've at the start of a transfer operation (which might be made
+ up of multiple HW operations) so check if we also have then
+ end of the transfer operation in the batch
+ */
+ for (k=i;k<ui32PrepareCount;k++)
+ {
+ if (pui32TQPrepareFlags[k] & TQ_PREP_FLAGS_END)
+ {
+ bHaveEndPrepare = IMG_TRUE;
+ break;
+ }
+ }
+
+ if (!bHaveEndPrepare)
+ {
+ /*
+ We don't have the complete command passed in this call
+ so drop the update request. When we get called again with
+ the last HW command in this transfer operation we'll do
+ the update at that point.
+ */
+ for (k=0;k<paui32ServerSyncCount[i];k++)
+ {
+ papaui32ServerSyncFlags[i][k] &= ~PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE;
+ }
+ }
+ }
+ }
+
+
+ /*
+ Init the command helper commands for all the prepares
+ */
+ for (i=0;i<ui32PrepareCount;i++)
+ {
+ RGX_CLIENT_CCB *psClientCCB;
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonCtx;
+ IMG_CHAR *pszCommandName;
+ RGX_CCB_CMD_HELPER_DATA *psCmdHelper;
+ RGXFWIF_CCB_CMD_TYPE eType;
+
+ if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 3D))
+ {
+ psServerCommonCtx = psTransferContext->s3DData.psServerCommonContext;
+ psClientCCB = FWCommonContextGetClientCCB(psServerCommonCtx);
+ pszCommandName = "TQ-3D";
+ psCmdHelper = &pas3DCmdHelper[ui323DCmdCount++];
+ eType = RGXFWIF_CCB_CMD_TYPE_TQ_3D;
+ }
+ else if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 2D))
+ {
+ psServerCommonCtx = psTransferContext->s2DData.psServerCommonContext;
+ psClientCCB = FWCommonContextGetClientCCB(psServerCommonCtx);
+ pszCommandName = "TQ-2D";
+ psCmdHelper = &pas2DCmdHelper[ui322DCmdCount++];
+ eType = RGXFWIF_CCB_CMD_TYPE_TQ_2D;
+ }
+ else
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto fail_cmdtype;
+ }
+
+ if (i == 0)
+ {
+ bPDumpContinuous = ((pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_PDUMPCONTINUOUS) == TQ_PREP_FLAGS_PDUMPCONTINUOUS);
+ PDUMPCOMMENTWITHFLAGS((bPDumpContinuous) ? PDUMP_FLAGS_CONTINUOUS : 0,
+ "%s Command Server Submit on FWCtx %08x", pszCommandName, FWCommonContextGetFWAddress(psServerCommonCtx).ui32Addr);
+ }
+ else
+ {
+ IMG_BOOL bNewPDumpContinuous = ((pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_PDUMPCONTINUOUS) == TQ_PREP_FLAGS_PDUMPCONTINUOUS);
+
+ if (bNewPDumpContinuous != bPDumpContinuous)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ PVR_DPF((PVR_DBG_ERROR, "%s: Mixing of continuous and non-continuous command in a batch is not permitted", __FUNCTION__));
+ goto fail_pdumpcheck;
+ }
+ }
+
+ ui32IntClientFenceCount = paui32ClientFenceCount[i];
+ pauiIntFenceUFOAddress = papauiClientFenceUFOAddress[i];
+ paui32IntFenceValue = papaui32ClientFenceValue[i];
+ ui32IntClientUpdateCount = paui32ClientUpdateCount[i];
+ pauiIntUpdateUFOAddress = papauiClientUpdateUFOAddress[i];
+ paui32IntUpdateValue = papaui32ClientUpdateValue[i];
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ if (ui32NumFenceFDs)
+ {
+ eError =
+ pvr_sync_append_fences("TQ",
+ ui32NumFenceFDs,
+ pai32FenceFDs,
+ -1,
+ ui32IntClientUpdateCount,
+ pauiIntUpdateUFOAddress,
+ paui32IntUpdateValue,
+ ui32IntClientFenceCount,
+ pauiIntFenceUFOAddress,
+ paui32IntFenceValue,
+ &psFDFenceData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_syncinit;
+ }
+ ui32IntClientUpdateCount = psFDFenceData->nr_updates;
+ pauiIntUpdateUFOAddress = psFDFenceData->update_ufo_addresses;
+ paui32IntUpdateValue = psFDFenceData->update_values;
+ ui32IntClientFenceCount = psFDFenceData->nr_checks;
+ pauiIntFenceUFOAddress = psFDFenceData->check_ufo_addresses;
+ paui32IntFenceValue = psFDFenceData->check_values;
+ }
+#endif
+
+ RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psTransferContext->psDeviceNode->pvDevice,
+ & pPreAddr,
+ & pPostAddr,
+ & pRMWUFOAddr);
+
+ /*
+ Create the command helper data for this command
+ */
+ eError = RGXCmdHelperInitCmdCCB(psClientCCB,
+ ui32IntClientFenceCount,
+ pauiIntFenceUFOAddress,
+ paui32IntFenceValue,
+ ui32IntClientUpdateCount,
+ pauiIntUpdateUFOAddress,
+ paui32IntUpdateValue,
+ paui32ServerSyncCount[i],
+ papaui32ServerSyncFlags[i],
+ papapsServerSyncs[i],
+ paui32FWCommandSize[i],
+ papaui8FWCommand[i],
+ & pPreAddr,
+ & pPostAddr,
+ & pRMWUFOAddr,
+ eType,
+ bPDumpContinuous,
+ pszCommandName,
+ psCmdHelper);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_initcmd;
+ }
+ }
+
+ /*
+ Acquire space for all the commands in one go
+ */
+ if (ui323DCmdCount)
+ {
+
+ eError = RGXCmdHelperAcquireCmdCCB(ui323DCmdCount,
+ &pas3DCmdHelper[0],
+ &bKick3D);
+ if (eError != PVRSRV_OK)
+ {
+ if (bKick3D)
+ {
+ ui323DCmdCount = 0;
+ ui322DCmdCount = 0;
+ }
+ else
+ {
+ goto fail_3dcmdacquire;
+ }
+ }
+ }
+
+ if (ui322DCmdCount)
+ {
+ eError = RGXCmdHelperAcquireCmdCCB(ui322DCmdCount,
+ &pas2DCmdHelper[0],
+ &bKick2D);
+
+ if (eError != PVRSRV_OK)
+ {
+ if (bKick2D || bKick3D)
+ {
+ ui323DCmdCount = 0;
+ ui322DCmdCount = 0;
+ }
+ else
+ {
+ goto fail_2dcmdacquire;
+ }
+ }
+ }
+
+ /*
+ 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
+ */
+ if (ui323DCmdCount)
+ {
+ RGXCmdHelperReleaseCmdCCB(ui323DCmdCount,
+ &pas3DCmdHelper[0],
+ "TQ_3D",
+ FWCommonContextGetFWAddress(psTransferContext->s3DData.psServerCommonContext).ui32Addr);
+
+ }
+
+ if (ui322DCmdCount)
+ {
+ RGXCmdHelperReleaseCmdCCB(ui322DCmdCount,
+ &pas2DCmdHelper[0],
+ "TQ_2D",
+ FWCommonContextGetFWAddress(psTransferContext->s2DData.psServerCommonContext).ui32Addr);
+ }
+
+ /*
+ 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
+ */
+ if (bKick3D)
+ {
+ RGXFWIF_KCCB_CMD s3DKCCBCmd;
+
+ /* Construct the kernel 3D CCB command. */
+ s3DKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+ s3DKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psTransferContext->s3DData.psServerCommonContext);
+ s3DKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->s3DData.psServerCommonContext));
+ s3DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError2 = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_3D,
+ &s3DKCCBCmd,
+ sizeof(s3DKCCBCmd),
+ bPDumpContinuous);
+ if (eError2 != PVRSRV_ERROR_RETRY)
+ {
+ break;
+ }
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+ RGXHWPerfFTraceGPUEnqueueEvent(psDeviceNode->pvDevice,
+ ui32ExtJobRef, ui32IntJobRef, "TQ3D");
+#endif
+ }
+
+ if (bKick2D)
+ {
+ RGXFWIF_KCCB_CMD s2DKCCBCmd;
+
+ /* Construct the kernel 3D CCB command. */
+ s2DKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+ s2DKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psTransferContext->s2DData.psServerCommonContext);
+ s2DKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->s2DData.psServerCommonContext));
+ s2DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ eError2 = RGXScheduleCommand(psDeviceNode->pvDevice,
+ RGXFWIF_DM_2D,
+ &s2DKCCBCmd,
+ sizeof(s2DKCCBCmd),
+ bPDumpContinuous);
+ if (eError2 != PVRSRV_ERROR_RETRY)
+ {
+ break;
+ }
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+ RGXHWPerfFTraceGPUEnqueueEvent(psDeviceNode->pvDevice,
+ ui32ExtJobRef, ui32IntJobRef, "TQ2D");
+#endif
+ }
+
+ /*
+ * 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(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#if defined(NO_HARDWARE)
+ pvr_sync_nohw_complete_fences(psFDFenceData);
+#endif
+ /*
+ Free the merged sync memory if required
+ */
+ pvr_sync_free_append_fences_data(psFDFenceData);
+#endif
+
+#if !defined(WDDM)
+ OSFreeMem(pas2DCmdHelper);
+ OSFreeMem(pas3DCmdHelper);
+#endif
+
+ 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_initcmd:
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+fail_syncinit:
+ /* Relocated cleanup here as the loop could fail after the first iteration
+ * at the above goto tags at which point the psFDCheckData memory would
+ * have been allocated.
+ */
+ if (psFDFenceData)
+ {
+ pvr_sync_rollback_append_fences(psFDFenceData);
+ pvr_sync_free_append_fences_data(psFDFenceData);
+ psFDFenceData = NULL;
+ }
+#endif
+
+fail_pdumpcheck:
+fail_cmdtype:
+ PVR_ASSERT(eError != PVRSRV_OK);
+#if !defined(WDDM)
+ OSFreeMem(pas2DCmdHelper);
+fail_alloc2dhelper:
+ OSFreeMem(pas3DCmdHelper);
+fail_alloc3dhelper:
+#endif
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXSetTransferContextPriorityKM(CONNECTION_DATA *psConnection,
+ RGX_SERVER_TQ_CONTEXT *psTransferContext,
+ IMG_UINT32 ui32Priority)
+{
+ PVRSRV_ERROR eError;
+
+ if (psTransferContext->s2DData.ui32Priority != ui32Priority)
+ {
+ eError = ContextSetPriority(psTransferContext->s2DData.psServerCommonContext,
+ psConnection,
+ psTransferContext->psDeviceNode->pvDevice,
+ ui32Priority,
+ RGXFWIF_DM_2D);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the 2D part of the transfercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+ goto fail_2dcontext;
+ }
+ psTransferContext->s2DData.ui32Priority = ui32Priority;
+ }
+
+ if (psTransferContext->s3DData.ui32Priority != ui32Priority)
+ {
+ eError = ContextSetPriority(psTransferContext->s3DData.psServerCommonContext,
+ psConnection,
+ psTransferContext->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 transfercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+ goto fail_3dcontext;
+ }
+ psTransferContext->s3DData.ui32Priority = ui32Priority;
+ }
+ return PVRSRV_OK;
+
+fail_3dcontext:
+fail_2dcontext:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+static IMG_BOOL CheckForStalledTransferCtxtCommand(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ RGX_SERVER_TQ_CONTEXT *psCurrentServerTransferCtx = IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_CONTEXT, sListNode);
+ RGX_SERVER_TQ_2D_DATA *psTransferCtx2DData = &(psCurrentServerTransferCtx->s2DData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServerTQ2DCommonCtx = psTransferCtx2DData->psServerCommonContext;
+ RGX_SERVER_TQ_3D_DATA *psTransferCtx3DData = &(psCurrentServerTransferCtx->s3DData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServerTQ3DCommonCtx = psTransferCtx3DData->psServerCommonContext;
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = pvCallbackData;
+
+
+ DumpStalledFWCommonContext(psCurrentServerTQ2DCommonCtx, pfnDumpDebugPrintf);
+ DumpStalledFWCommonContext(psCurrentServerTQ3DCommonCtx, pfnDumpDebugPrintf);
+
+ return IMG_TRUE;
+}
+IMG_VOID CheckForStalledTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ OSWRLockAcquireRead(psDevInfo->hTransferCtxListLock, DEVINFO_TRANSFERLIST);
+ dllist_foreach_node(&(psDevInfo->sTransferCtxtListHead),
+ CheckForStalledTransferCtxtCommand, pfnDumpDebugPrintf);
+ OSWRLockReleaseRead(psDevInfo->hTransferCtxListLock);
+}
+
+static IMG_BOOL CheckForStalledClientTransferCtxtCommand(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
+{
+ PVRSRV_ERROR *peError = (PVRSRV_ERROR*)pvCallbackData;
+ RGX_SERVER_TQ_CONTEXT *psCurrentServerTransferCtx = IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_CONTEXT, sListNode);
+ RGX_SERVER_TQ_2D_DATA *psTransferCtx2DData = &(psCurrentServerTransferCtx->s2DData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServerTQ2DCommonCtx = psTransferCtx2DData->psServerCommonContext;
+ RGX_SERVER_TQ_3D_DATA *psTransferCtx3DData = &(psCurrentServerTransferCtx->s3DData);
+ RGX_SERVER_COMMON_CONTEXT *psCurrentServerTQ3DCommonCtx = psTransferCtx3DData->psServerCommonContext;
+
+ if (PVRSRV_ERROR_CCCB_STALLED == CheckStalledClientCommonContext(psCurrentServerTQ2DCommonCtx))
+ {
+ *peError = PVRSRV_ERROR_CCCB_STALLED;
+ }
+ if (PVRSRV_ERROR_CCCB_STALLED == CheckStalledClientCommonContext(psCurrentServerTQ3DCommonCtx))
+ {
+ *peError = PVRSRV_ERROR_CCCB_STALLED;
+ }
+
+ return IMG_TRUE;
+}
+IMG_BOOL CheckForStalledClientTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ OSWRLockAcquireRead(psDevInfo->hTransferCtxListLock, DEVINFO_TRANSFERLIST);
+ dllist_foreach_node(&(psDevInfo->sTransferCtxtListHead),
+ CheckForStalledClientTransferCtxtCommand, &eError);
+ OSWRLockReleaseRead(psDevInfo->hTransferCtxListLock);
+ return (PVRSRV_ERROR_CCCB_STALLED == eError)? IMG_TRUE: IMG_FALSE;
+}
+
+PVRSRV_ERROR PVRSRVRGXKickSyncTransferKM(RGX_SERVER_TQ_CONTEXT *psTransferContext,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress,
+ IMG_UINT32 *paui32ClientFenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress,
+ IMG_UINT32 *paui32ClientUpdateValue,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_UINT32 *pui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerSyncs,
+ IMG_UINT32 ui32NumFenceFDs,
+ IMG_INT32 *pai32FenceFDs,
+ IMG_UINT32 ui32TQPrepareFlags)
+{
+ PVRSRV_ERROR eError;
+ RGX_SERVER_COMMON_CONTEXT *psServerCommonCtx;
+ IMG_CHAR *pszCommandName;
+ RGXFWIF_DM eDM;
+ IMG_BOOL bPDumpContinuous;
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ /* Android fd sync update info */
+ struct pvr_sync_append_data *psFDFenceData = NULL;
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+
+ bPDumpContinuous = ((ui32TQPrepareFlags & TQ_PREP_FLAGS_PDUMPCONTINUOUS) == TQ_PREP_FLAGS_PDUMPCONTINUOUS);
+
+ if (TQ_PREP_FLAGS_COMMAND_IS(ui32TQPrepareFlags, 3D))
+ {
+ psServerCommonCtx = psTransferContext->s3DData.psServerCommonContext;
+ pszCommandName = "SyncTQ-3D";
+ eDM = RGXFWIF_DM_3D;
+ }
+ else if (TQ_PREP_FLAGS_COMMAND_IS(ui32TQPrepareFlags, 2D))
+ {
+ psServerCommonCtx = psTransferContext->s2DData.psServerCommonContext;
+ pszCommandName = "SyncTQ-2D";
+ eDM = RGXFWIF_DM_2D;
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ /* Android FD fences are hardcoded to updates (IMG_TRUE below), Fences go to the TA and updates to the 3D */
+ if (ui32NumFenceFDs)
+ {
+ /* Assumes there will only ever be one fence to update. Ignores others. */
+ eError =
+ pvr_sync_append_fences("TQ",
+ 0,
+ NULL,
+ *pai32FenceFDs,
+ ui32ClientUpdateCount,
+ pauiClientUpdateUFOAddress,
+ paui32ClientUpdateValue,
+ ui32ClientFenceCount,
+ pauiClientFenceUFOAddress,
+ paui32ClientFenceValue,
+ &psFDFenceData);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_fdsync;
+ }
+ ui32ClientUpdateCount = psFDFenceData->nr_updates;
+ pauiClientUpdateUFOAddress = psFDFenceData->update_ufo_addresses;
+ paui32ClientUpdateValue = psFDFenceData->update_values;
+ ui32ClientFenceCount = psFDFenceData->nr_checks;
+ pauiClientFenceUFOAddress = psFDFenceData->check_ufo_addresses;
+ paui32ClientFenceValue = psFDFenceData->check_values;
+ }
+#endif
+
+ eError =
+ RGXKickSyncKM(psTransferContext->psDeviceNode,
+ psServerCommonCtx,
+ eDM,
+ pszCommandName,
+ ui32ClientFenceCount,
+ pauiClientFenceUFOAddress,
+ paui32ClientFenceValue,
+ ui32ClientUpdateCount,
+ pauiClientUpdateUFOAddress,
+ paui32ClientUpdateValue,
+ ui32ServerSyncCount,
+ pui32ServerSyncFlags,
+ pasServerSyncs,
+ bPDumpContinuous);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Error calling RGXKickSyncKM (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
+ goto fail_kicksync;
+ }
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#if defined(NO_HARDWARE)
+ pvr_sync_nohw_complete_fences(psFDFenceData);
+#endif /* NO_HARDWARE */
+ pvr_sync_free_append_fences_data(psFDFenceData);
+#endif /* PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC */
+
+ return eError;
+
+fail_kicksync:
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ pvr_sync_rollback_append_fences(psFDFenceData);
+ pvr_sync_free_append_fences_data(psFDFenceData);
+fail_fdsync:
+#endif
+
+ return eError;
+}
+
+/**************************************************************************//**
+ End of file (rgxtransfer.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxtransfer.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxtransfer.h
new file mode 100644
index 000000000000..bd352d1eb021
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxtransfer.h
@@ -0,0 +1,155 @@
+/*************************************************************************/ /*!
+@File
+@Title RGX Transfer queue Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the RGX Transfer queue 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(__RGXTRANSFER_H__)
+#define __RGXTRANSFER_H__
+
+#include "devicemem.h"
+#include "device.h"
+#include "rgxdevice.h"
+#include "rgxfwutils.h"
+#include "rgx_fwif_resetframework.h"
+#include "rgxdebug.h"
+
+#include "sync_server.h"
+#include "connection_server.h"
+
+typedef struct _RGX_SERVER_TQ_CONTEXT_ RGX_SERVER_TQ_CONTEXT;
+
+/*!
+*******************************************************************************
+
+ @Function PVRSRVRGXCreateTransferContextKM
+
+ @Description
+ Server-side implementation of RGXCreateTransferContext
+
+ @Input pvDeviceNode - device node
+
+
+*/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32Priority,
+ IMG_DEV_VIRTADDR sMCUFenceAddr,
+ IMG_UINT32 ui32FrameworkCommandSize,
+ IMG_PBYTE pabyFrameworkCommand,
+ IMG_HANDLE hMemCtxPrivData,
+ RGX_SERVER_TQ_CONTEXT **ppsTransferContext);
+
+
+/*!
+*******************************************************************************
+
+ @Function PVRSRVRGXDestroyTransferContextKM
+
+ @Description
+ Server-side implementation of RGXDestroyTransferContext
+
+ @Input psTransferContext - Transfer context
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXDestroyTransferContextKM(RGX_SERVER_TQ_CONTEXT *psTransferContext);
+
+/*!
+*******************************************************************************
+
+ @Function PVRSRVSubmitTransferKM
+
+ @Description
+ Schedules one or more 2D or 3D HW commands on the firmware
+
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT *psTransferContext,
+ IMG_UINT32 ui32PrepareCount,
+ IMG_UINT32 *paui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR **papauiClientFenceUFOAddress,
+ IMG_UINT32 **papaui32ClientFenceValue,
+ IMG_UINT32 *paui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR **papauiClientUpdateUFOAddress,
+ IMG_UINT32 **papaui32ClientUpdateValue,
+ IMG_UINT32 *paui32ServerSyncCount,
+ IMG_UINT32 **papaui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE ***papapsServerSyncs,
+ IMG_UINT32 ui32NumFenceFDs,
+ IMG_INT32 *paui32FenceFDs,
+ IMG_UINT32 *paui32FWCommandSize,
+ IMG_UINT8 **papaui8FWCommand,
+ IMG_UINT32 *pui32TQPrepareFlags,
+ IMG_UINT32 ui32ExtJobRef,
+ IMG_UINT32 ui32IntJobRef);
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRGXSetTransferContextPriorityKM(CONNECTION_DATA *psConnection,
+ RGX_SERVER_TQ_CONTEXT *psTransferContext,
+ IMG_UINT32 ui32Priority);
+
+/* Debug - check if transfer context is waiting on a fence */
+IMG_VOID CheckForStalledTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf);
+
+/* Debug/Watchdog - check if client transfer contexts are stalled */
+IMG_BOOL CheckForStalledClientTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+PVRSRV_ERROR PVRSRVRGXKickSyncTransferKM(RGX_SERVER_TQ_CONTEXT *psTransferContext,
+ IMG_UINT32 ui32ClientFenceCount,
+ PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress,
+ IMG_UINT32 *paui32ClientFenceValue,
+ IMG_UINT32 ui32ClientUpdateCount,
+ PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress,
+ IMG_UINT32 *paui32ClientUpdateValue,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_UINT32 *pui32ServerSyncFlags,
+ SERVER_SYNC_PRIMITIVE **pasServerSyncs,
+ IMG_UINT32 ui32NumFenceFDs,
+ IMG_INT32 *paui32FenceFDs,
+ IMG_UINT32 ui32TQPrepareFlags);
+#endif /* __RGXTRANSFER_H__ */
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxutils.c b/drivers/gpu/rogue/services/server/devices/rgx/rgxutils.c
new file mode 100644
index 000000000000..077a2d50e08b
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxutils.c
@@ -0,0 +1,288 @@
+/*************************************************************************/ /*!
+@File
+@Title Device specific utility 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 <stddef.h>
+
+#include "rgx_fwif_km.h"
+#include "pdump_km.h"
+#include "osfunc.h"
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "power.h"
+#include "pvrsrv.h"
+#include "sync_internal.h"
+#include "rgxfwutils.h"
+
+/*
+ * RGXRunScript
+ */
+PVRSRV_ERROR RGXRunScript(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGX_INIT_COMMAND *psScript,
+ IMG_UINT32 ui32NumCommands,
+ IMG_UINT32 ui32PdumpFlags,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ IMG_UINT32 ui32PC;
+ RGX_INIT_COMMAND *psComm;
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32LastLoopPoint = 0xFFFFFFFF;
+#endif /* NO_HARDWARE */
+
+ for (ui32PC = 0, psComm = psScript;
+ ui32PC < ui32NumCommands;
+ ui32PC++, psComm++)
+ {
+ switch (psComm->eOp)
+ {
+ case RGX_INIT_OP_DBG_READ32_HW_REG:
+ {
+ IMG_UINT32 ui32RegVal;
+ ui32RegVal = OSReadHWReg32(psDevInfo->pvRegsBaseKM, psComm->sDBGReadHWReg.ui32Offset);
+ PVR_DUMPDEBUG_LOG(("%s: 0x%08X", psComm->sDBGReadHWReg.aszName, ui32RegVal));
+ break;
+ }
+ case RGX_INIT_OP_DBG_READ64_HW_REG:
+ {
+ IMG_UINT64 ui64RegVal;
+ ui64RegVal = OSReadHWReg64(psDevInfo->pvRegsBaseKM, psComm->sDBGReadHWReg.ui32Offset);
+ PVR_DUMPDEBUG_LOG(("%s: 0x%016llX", psComm->sDBGReadHWReg.aszName, ui64RegVal));
+ break;
+ }
+ case RGX_INIT_OP_WRITE_HW_REG:
+ {
+ if( !(ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
+ {
+ OSWriteHWReg32(psDevInfo->pvRegsBaseKM, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+ }
+ PDUMPCOMMENT("RGXRunScript: Write HW reg operation");
+ PDUMPREG32(RGX_PDUMPREG_NAME,
+ psComm->sWriteHWReg.ui32Offset,
+ psComm->sWriteHWReg.ui32Value,
+ ui32PdumpFlags);
+ break;
+ }
+ case RGX_INIT_OP_PDUMP_HW_REG:
+ {
+ PDUMPCOMMENT("RGXRunScript: Dump HW reg operation");
+ PDUMPREG32(RGX_PDUMPREG_NAME, psComm->sPDumpHWReg.ui32Offset,
+ psComm->sPDumpHWReg.ui32Value, ui32PdumpFlags);
+ break;
+ }
+ case RGX_INIT_OP_COND_POLL_HW_REG:
+ {
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32RegVal;
+
+ if( !(ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
+ {
+ /* read the register used as condition */
+ ui32RegVal = OSReadHWReg32(psDevInfo->pvRegsBaseKM, psComm->sCondPollHWReg.ui32CondOffset);
+
+ /* if the conditions succeeds, poll the register */
+ if ((ui32RegVal & psComm->sCondPollHWReg.ui32CondMask) == psComm->sCondPollHWReg.ui32CondValue)
+ {
+ if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + psComm->sCondPollHWReg.ui32Offset),
+ psComm->sCondPollHWReg.ui32Value,
+ psComm->sCondPollHWReg.ui32Mask) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXRunScript: Cond Poll for Reg (0x%x) failed -> Cancel script.", psComm->sCondPollHWReg.ui32Offset));
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "RGXRunScript: Skipping Poll for Reg (0x%x) because the condition is not met (Reg 0x%x ANDed with mask 0x%x equal to 0x%x but value 0x%x found instead).",
+ psComm->sCondPollHWReg.ui32Offset,
+ psComm->sCondPollHWReg.ui32CondOffset,
+ psComm->sCondPollHWReg.ui32CondMask,
+ psComm->sCondPollHWReg.ui32CondValue,
+ ui32RegVal));
+ }
+ }
+#endif
+ break;
+ }
+ case RGX_INIT_OP_POLL_64_HW_REG:
+ {
+ /* Split lower and upper words */
+ IMG_UINT32 ui32UpperValue = (IMG_UINT32) (psComm->sPoll64HWReg.ui64Value >> 32);
+ IMG_UINT32 ui32LowerValue = (IMG_UINT32) (psComm->sPoll64HWReg.ui64Value);
+
+ IMG_UINT32 ui32UpperMask = (IMG_UINT32) (psComm->sPoll64HWReg.ui64Mask >> 32);
+ IMG_UINT32 ui32LowerMask = (IMG_UINT32) (psComm->sPoll64HWReg.ui64Mask);
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "RGXRunScript: 64 bit HW offset: %x", psComm->sPoll64HWReg.ui32Offset);
+
+ if( !(ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
+ {
+ if (PVRSRVPollForValueKM((IMG_UINT32 *)(((IMG_UINT8*)psDevInfo->pvRegsBaseKM) + psComm->sPoll64HWReg.ui32Offset + 4),
+ ui32UpperValue,
+ ui32UpperMask) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXRunScript: Poll for upper part of Reg (0x%x) failed -> Cancel script.", psComm->sPoll64HWReg.ui32Offset));
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+ }
+ PDUMPREGPOL(RGX_PDUMPREG_NAME,
+ psComm->sPoll64HWReg.ui32Offset + 4,
+ ui32UpperValue,
+ ui32UpperMask,
+ ui32PdumpFlags,
+ PDUMP_POLL_OPERATOR_EQUAL);
+
+ if( !(ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
+ {
+ if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + psComm->sPoll64HWReg.ui32Offset),
+ ui32LowerValue,
+ ui32LowerMask) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXRunScript: Poll for lower part of Reg (0x%x) failed -> Cancel script.", psComm->sPoll64HWReg.ui32Offset));
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+ }
+ PDUMPREGPOL(RGX_PDUMPREG_NAME,
+ psComm->sPoll64HWReg.ui32Offset,
+ ui32LowerValue,
+ ui32LowerMask,
+ ui32PdumpFlags,
+ PDUMP_POLL_OPERATOR_EQUAL);
+
+ break;
+ }
+ case RGX_INIT_OP_POLL_HW_REG:
+ {
+ if( !(ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
+ {
+ if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + psComm->sPollHWReg.ui32Offset),
+ psComm->sPollHWReg.ui32Value,
+ psComm->sPollHWReg.ui32Mask) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RGXRunScript: Poll for Reg (0x%x) failed -> Cancel script.", psComm->sPollHWReg.ui32Offset));
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+ }
+ PDUMPREGPOL(RGX_PDUMPREG_NAME,
+ psComm->sPollHWReg.ui32Offset,
+ psComm->sPollHWReg.ui32Value,
+ psComm->sPollHWReg.ui32Mask,
+ ui32PdumpFlags,
+ PDUMP_POLL_OPERATOR_EQUAL);
+
+ break;
+ }
+
+ case RGX_INIT_OP_LOOP_POINT:
+ {
+#if !defined(NO_HARDWARE)
+ ui32LastLoopPoint = ui32PC;
+#endif /* NO_HARDWARE */
+ break;
+ }
+
+ case RGX_INIT_OP_COND_BRANCH:
+ {
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32RegVal = OSReadHWReg32(psDevInfo->pvRegsBaseKM,
+ psComm->sConditionalBranchPoint.ui32Offset);
+
+ if((ui32RegVal & psComm->sConditionalBranchPoint.ui32Mask) != psComm->sConditionalBranchPoint.ui32Value)
+ {
+ ui32PC = ui32LastLoopPoint - 1;
+ }
+#endif /* NO_HARDWARE */
+
+ PDUMPIDLWITHFLAGS(30, ui32PdumpFlags);
+ break;
+ }
+ case RGX_INIT_OP_DBG_CALC:
+ {
+ IMG_UINT32 ui32RegVal1;
+ IMG_UINT32 ui32RegVal2;
+ IMG_UINT32 ui32RegVal3;
+ ui32RegVal1 = OSReadHWReg32(psDevInfo->pvRegsBaseKM, psComm->sDBGCalc.ui32Offset1);
+ ui32RegVal2 = OSReadHWReg32(psDevInfo->pvRegsBaseKM, psComm->sDBGCalc.ui32Offset2);
+ ui32RegVal3 = OSReadHWReg32(psDevInfo->pvRegsBaseKM, psComm->sDBGCalc.ui32Offset3);
+ if (ui32RegVal1 + ui32RegVal2 > ui32RegVal3)
+ {
+ PVR_DUMPDEBUG_LOG(("%s: 0x%08X", psComm->sDBGCalc.aszName, ui32RegVal1 + ui32RegVal2 - ui32RegVal3));
+ }
+ else
+ {
+ PVR_DUMPDEBUG_LOG(("%s: 0x%08X", psComm->sDBGCalc.aszName, 0));
+ }
+ break;
+ }
+ case RGX_INIT_OP_DBG_WAIT:
+ {
+ OSWaitus(psComm->sDBGWait.ui32WaitInUs);
+ break;
+ }
+ case RGX_INIT_OP_DBG_STRING:
+ {
+ PVR_DUMPDEBUG_LOG(("%s", psComm->sDBGString.aszString));
+ break;
+ }
+ case RGX_INIT_OP_HALT:
+ {
+ return PVRSRV_OK;
+ }
+ case RGX_INIT_OP_ILLEGAL:
+ /* FALLTHROUGH */
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,"RGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
+ return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+ }
+ }
+
+ }
+
+ return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+}
+
+/******************************************************************************
+ End of file (rgxutils.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/devices/rgx/rgxutils.h b/drivers/gpu/rogue/services/server/devices/rgx/rgxutils.h
new file mode 100644
index 000000000000..f075f43807a2
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/devices/rgx/rgxutils.h
@@ -0,0 +1,69 @@
+/*************************************************************************/ /*!
+@File
+@Title Device specific utility routines declarations
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Inline functions/structures specific to RGX
+@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 "device.h"
+#include "rgxdevice.h"
+#include "rgxdebug.h"
+#include "pvrsrv.h"
+
+/*!
+******************************************************************************
+
+ @Function RGXRunScript
+
+ @Description Execute the commands in the script
+
+ @Input
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXRunScript(PVRSRV_RGXDEV_INFO *psDevInfo,
+ RGX_INIT_COMMAND *psScript,
+ IMG_UINT32 ui32NumCommands,
+ IMG_UINT32 ui32PdumpFlags,
+ DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf);
+
+/******************************************************************************
+ End of file (rgxutils.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/env/linux/Kbuild.mk b/drivers/gpu/rogue/services/server/env/linux/Kbuild.mk
new file mode 100644
index 000000000000..a6757d41d611
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/Kbuild.mk
@@ -0,0 +1,459 @@
+########################################################################### ###
+#@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-y += \
+ services/server/env/linux/event.o \
+ services/server/env/linux/mm.o \
+ services/server/env/linux/mmap.o \
+ services/server/env/linux/module.o \
+ services/server/env/linux/devicemem_mmap_stub.o \
+ services/server/env/linux/osfunc.o \
+ services/server/env/linux/allocmem.o \
+ services/server/env/linux/osconnection_server.o \
+ services/server/env/linux/pdump.o \
+ services/server/env/linux/physmem_osmem_linux.o \
+ services/server/env/linux/pvr_debugfs.o \
+ services/server/env/linux/pvr_bridge_k.o \
+ services/server/env/linux/pvr_debug.o \
+ services/server/env/linux/physmem_tdmetacode_linux.o \
+ services/server/env/linux/physmem_tdsecbuf_linux.o \
+ services/server/common/devicemem_heapcfg.o \
+ services/shared/common/devicemem.o \
+ services/shared/common/devicemem_utils.o \
+ services/shared/common/hash.o \
+ services/shared/common/ra.o \
+ services/shared/common/sync.o \
+ services/shared/common/dllist.o \
+ services/server/common/devicemem_server.o \
+ services/server/common/handle.o \
+ services/server/common/lists.o \
+ services/server/common/mmu_common.o \
+ services/server/common/connection_server.o \
+ services/server/common/physheap.o \
+ services/server/common/physmem.o \
+ services/server/common/physmem_lma.o \
+ services/server/common/pmr.o \
+ services/server/common/power.o \
+ services/server/common/process_stats.o \
+ services/server/common/pvrsrv.o \
+ services/server/common/resman.o \
+ services/server/common/srvcore.o \
+ services/server/common/sync_server.o \
+ services/server/common/tlintern.o \
+ services/shared/common/tlclient.o \
+ services/server/common/tlserver.o \
+ services/server/common/tlstream.o \
+ services/server/common/tutils.o \
+ services/shared/common/uniq_key_splay_tree.o
+
+ifeq ($(SUPPORT_DISPLAY_CLASS),1)
+pvrsrvkm-y += \
+ services/server/common/dc_server.o \
+ services/server/common/scp.o
+endif
+
+ifeq ($(PVR_RI_DEBUG),1)
+pvrsrvkm-y += services/server/common/ri_server.o
+endif
+
+ifeq ($(PVR_HANDLE_BACKEND),generic)
+pvrsrvkm-y += services/server/common/handle_generic.o
+else
+ifeq ($(PVR_HANDLE_BACKEND),idr)
+pvrsrvkm-y += services/server/env/linux/handle_idr.o
+endif
+endif
+
+ifeq ($(SUPPORT_GPUTRACE_EVENTS),1)
+pvrsrvkm-y += services/server/env/linux/pvr_gputrace.o
+endif
+
+
+pvrsrvkm-$(CONFIG_X86) += services/server/env/linux/osfunc_x86.o
+pvrsrvkm-$(CONFIG_ARM) += services/server/env/linux/osfunc_arm.o
+pvrsrvkm-$(CONFIG_ARM64) += services/server/env/linux/osfunc_arm64.o
+pvrsrvkm-$(CONFIG_METAG) += services/server/env/linux/osfunc_metag.o
+pvrsrvkm-$(CONFIG_MIPS) += services/server/env/linux/osfunc_mips.o
+
+pvrsrvkm-$(CONFIG_EVENT_TRACING) += services/server/env/linux/trace_events.o
+
+ifneq ($(W),1)
+CFLAGS_mm.o := -Werror
+CFLAGS_mmap.o := -Werror
+CFLAGS_module.o := -Werror
+CFLAGS_mutils.o := -Werror
+CFLAGS_devicemem_mmap_stub.o := -Werror
+CFLAGS_osfunc.o := -Werror
+CFLAGS_osfunc_x86.o := -Werror
+CFLAGS_osconnection_server.o := -Werror
+CFLAGS_pdump.o := -Werror
+CFLAGS_pvr_debugfs.o := -Werror
+CFLAGS_pvr_bridge_k.o := -Werror
+CFLAGS_devicemem_heapcfg.o := -Werror
+CFLAGS_devicemem.o := -Werror
+CFLAGS_devicemem_utils.o = -Werror
+CFLAGS_devicemem_pdump.o = -Werror
+CFLAGS_hash.o := -Werror
+CFLAGS_ra.o := -Werror
+CFLAGS_sync.o := -Werror
+CFLAGS_devicemem_server.o := -Werror
+CFLAGS_handle.o := -Werror
+CFLAGS_lists.o := -Werror
+CFLAGS_mem_debug.o := -Werror
+CFLAGS_mmu_common.o := -Werror
+CFLAGS_connection_server.o := -Werror
+CFLAGS_physmem.o := -Werror
+CFLAGS_physmem_lma.o := -Werror
+CFLAGS_physmem_pmmif.o := -Werror
+CFLAGS_pmr.o := -Werror
+CFLAGS_power.o := -Werror
+CFLAGS_process_stats.o := -Werror
+CFLAGS_pvrsrv.o := -Werror
+CFLAGS_resman.o := -Werror
+#CFLAGS_srvcore.o := -Werror
+CFLAGS_sync_server.o := -Werror
+CFLAGS_tlintern.o := -Werror
+CFLAGS_tlclient.o := -Werror
+CFLAGS_tlserver.o := -Werror
+CFLAGS_tlstream.o := -Werror
+CFLAGS_tutils.o := -Werror
+
+ifeq ($(SUPPORT_DISPLAY_CLASS),1)
+CFLAGS_dc_server.o := -Werror
+CFLAGS_scp.o := -Werror
+endif
+
+ifeq ($(PVR_RI_DEBUG),1)
+CFLAGS_ri_server.o := -Werror
+endif
+ifeq ($(SUPPORT_GPUTRACE_EVENTS),1)
+CFLAGS_pvr_gputrace.o := -Werror
+endif
+endif
+
+# With certain build configurations, e.g., ARM, Werror, we get a build
+# failure in the ftrace Linux kernel header. So disable the relevant check.
+CFLAGS_trace_events.o := -Wno-missing-prototypes
+
+ifeq ($(PDUMP),1)
+pvrsrvkm-y += \
+ services/server/common/pdump_common.o \
+ services/server/common/pdump_mmu.o \
+ services/server/common/pdump_physmem.o \
+ services/shared/common/devicemem_pdump.o
+ifneq ($(W),1)
+CFLAGS_pdump_common.o := -Werror
+CFLAGS_pdump_mmu.o := -Werror
+CFLAGS_pdump_physmem.o := -Werror
+CFLAGS_devicemem_pdump.o := -Werror
+endif
+endif
+
+pvrsrvkm-y += \
+ services/server/devices/rgx/rgxinit.o \
+ services/server/devices/rgx/rgxdebug.o \
+ services/server/devices/rgx/rgxhwperf.o \
+ services/server/devices/rgx/rgxmem.o \
+ services/server/devices/rgx/rgxta3d.o \
+ services/server/devices/rgx/rgxcompute.o \
+ services/server/devices/rgx/rgxccb.o \
+ services/server/devices/rgx/rgxmmuinit.o \
+ services/server/devices/rgx/rgxpower.o \
+ services/server/devices/rgx/rgxtransfer.o \
+ services/server/devices/rgx/rgxutils.o \
+ services/server/devices/rgx/rgxfwutils.o \
+ services/server/devices/rgx/rgxbreakpoint.o \
+ services/server/devices/rgx/debugmisc_server.o \
+ services/shared/devices/rgx/rgx_compat_bvnc.o \
+ services/server/devices/rgx/rgxregconfig.o \
+ services/server/devices/rgx/rgxtimerquery.o \
+ services/server/devices/rgx/rgxsync.o
+
+ifeq ($(SUPPORT_RAY_TRACING),1)
+pvrsrvkm-y += services/server/devices/rgx/rgxray.o
+endif
+
+
+ifneq ($(W),1)
+CFLAGS_rgxinit.o := -Werror
+CFLAGS_rgxdebug.o := -Werror
+CFLAGS_rgxhwperf.o := -Werror
+CFLAGS_rgxmem.o := -Werror
+CFLAGS_rgxta3d.o := -Werror
+CFLAGS_rgxcompute.o := -Werror
+CFLAGS_rgxccb.o := -Werror
+CFLAGS_rgxmmuinit.o := -Werror
+CFLAGS_rgxpower.o := -Werror
+CFLAGS_rgxsharedpb.o := -Werror
+CFLAGS_rgxtransfer.o := -Werror
+CFLAGS_rgxutils.o := -Werror
+CFLAGS_rgxfwutils.o := -Werror
+CFLAGS_rgxbreakpoint.o := -Werror
+CFLAGS_debugmisc_server.o := -Werror
+CFLAGS_rgxray.o := -Werror
+CFLAGS_rgxregconfig.o := -Werror
+CFLAGS_rgxsync.o := -Werror
+endif
+
+ifeq ($(PDUMP),1)
+pvrsrvkm-y += services/server/devices/rgx/rgxpdump.o
+ifneq ($(W),1)
+CFLAGS_rgxpdump.o := -Werror
+endif
+endif
+
+# Bridge headers and source files
+ccflags-y += \
+ -I$(bridge_base)/dmm_bridge \
+ -I$(bridge_base)/mm_bridge \
+ -I$(bridge_base)/cmm_bridge \
+ -I$(bridge_base)/pdumpmm_bridge \
+ -I$(bridge_base)/pdumpcmm_bridge \
+ -I$(bridge_base)/pdump_bridge \
+ -I$(bridge_base)/rgxtq_bridge \
+ -I$(bridge_base)/rgxinit_bridge \
+ -I$(bridge_base)/rgxta3d_bridge \
+ -I$(bridge_base)/rgxcmp_bridge \
+ -I$(bridge_base)/srvcore_bridge \
+ -I$(bridge_base)/dsync_bridge \
+ -I$(bridge_base)/sync_bridge \
+ -I$(bridge_base)/breakpoint_bridge \
+ -I$(bridge_base)/debugmisc_bridge \
+ -I$(bridge_base)/rgxpdump_bridge \
+ -I$(bridge_base)/pvrtl_bridge \
+ -I$(bridge_base)/dpvrtl_bridge \
+ -I$(bridge_base)/rgxhwperf_bridge \
+ -I$(bridge_base)/regconfig_bridge \
+ -I$(bridge_base)/timerquery_bridge
+
+ifeq ($(PVR_RI_DEBUG),1)
+ccflags-y += \
+ -I$(bridge_base)/ri_bridge \
+ -I$(bridge_base)/dri_bridge
+endif
+
+
+ifeq ($(SUPPORT_RAY_TRACING),1)
+ccflags-y += -I$(bridge_base)/rgxray_bridge
+endif
+
+# Compatibility BVNC
+ccflags-y += \
+ -I$(TOP)/services/shared/devices/rgx
+
+# Errata files
+ccflags-y += \
+ -I$(TOP)/hwdefs
+
+ccflags-y += -I$(TOP)/services/include/env/linux
+
+ifeq ($(SUPPORT_DISPLAY_CLASS),1)
+ccflags-y += \
+ -I$(bridge_base)/dc_bridge
+endif
+
+ifeq ($(CACHEFLUSH_TYPE),CACHEFLUSH_GENERIC)
+ccflags-y += -I$(bridge_base)/cachegeneric_bridge
+endif
+
+ifeq ($(SUPPORT_SECURE_EXPORT),1)
+ccflags-y += \
+ -I$(bridge_base)/syncsexport_bridge \
+ -I$(bridge_base)/smm_bridge
+endif
+ifeq ($(SUPPORT_INSECURE_EXPORT),1)
+ccflags-y += \
+ -I$(bridge_base)/syncexport_bridge
+endif
+
+ifeq ($(SUPPORT_PMMIF),1)
+ccflags-y += -I$(bridge_base)/pmmif_bridge
+endif
+
+ifeq ($(SUPPORT_ION),1)
+ccflags-y += -I$(bridge_base)/dmabuf_bridge
+endif
+
+ifeq ($(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC),1)
+ccflags-y += -I$(TOP)/kernel/drivers/staging/imgtec
+pvrsrvkm-y += kernel/drivers/staging/imgtec/pvr_sync.o
+endif
+
+pvrsrvkm-y += \
+ generated/mm_bridge/server_mm_bridge.o \
+ generated/dmm_bridge/client_mm_bridge.o \
+ generated/pdumpmm_bridge/server_pdumpmm_bridge.o \
+ generated/dpdumpmm_bridge/client_pdumpmm_bridge.o \
+ generated/cmm_bridge/server_cmm_bridge.o \
+ generated/pdumpcmm_bridge/server_pdumpcmm_bridge.o \
+ generated/pdump_bridge/server_pdump_bridge.o \
+ generated/rgxtq_bridge/server_rgxtq_bridge.o \
+ generated/rgxinit_bridge/server_rgxinit_bridge.o \
+ generated/rgxta3d_bridge/server_rgxta3d_bridge.o \
+ generated/rgxcmp_bridge/server_rgxcmp_bridge.o \
+ generated/srvcore_bridge/server_srvcore_bridge.o \
+ generated/sync_bridge/server_sync_bridge.o \
+ generated/dsync_bridge/client_sync_bridge.o \
+ generated/breakpoint_bridge/server_breakpoint_bridge.o \
+ generated/debugmisc_bridge/server_debugmisc_bridge.o \
+ generated/rgxpdump_bridge/server_rgxpdump_bridge.o \
+ generated/pvrtl_bridge/server_pvrtl_bridge.o \
+ generated/dpvrtl_bridge/client_pvrtl_bridge.o \
+ generated/rgxhwperf_bridge/server_rgxhwperf_bridge.o \
+ generated/regconfig_bridge/server_regconfig_bridge.o \
+ generated/timerquery_bridge/server_timerquery_bridge.o
+ifeq ($(PVR_RI_DEBUG),1)
+pvrsrvkm-y += \
+ generated/ri_bridge/server_ri_bridge.o \
+ generated/dri_bridge/client_ri_bridge.o
+endif
+
+ifeq ($(SUPPORT_DISPLAY_CLASS),1)
+pvrsrvkm-y += \
+ generated/dc_bridge/server_dc_bridge.o
+endif
+
+ifeq ($(SUPPORT_RAY_TRACING),1)
+pvrsrvkm-y += generated/rgxray_bridge/server_rgxray_bridge.o
+endif
+
+ifeq ($(CACHEFLUSH_TYPE),CACHEFLUSH_GENERIC)
+pvrsrvkm-y += \
+ services/server/common/cache_generic.o \
+ generated/cachegeneric_bridge/server_cachegeneric_bridge.o
+endif
+
+ifeq ($(SUPPORT_SECURE_EXPORT),1)
+pvrsrvkm-y += \
+ services/server/env/linux/ossecure_export.o \
+ generated/smm_bridge/server_smm_bridge.o \
+ generated/syncsexport_bridge/server_syncsexport_bridge.o
+endif
+ifeq ($(SUPPORT_INSECURE_EXPORT),1)
+pvrsrvkm-y += \
+ generated/syncexport_bridge/server_syncexport_bridge.o
+endif
+
+ifeq ($(SUPPORT_PMMIF),1)
+pvrsrvkm-y += \
+ services/server/common/physmem_pmmif.o \
+ generated/pmmif_bridge/server_pmmif_bridge.o
+endif
+
+ifeq ($(SUPPORT_ION),1)
+pvrsrvkm-y += generated/dmabuf_bridge/server_dmabuf_bridge.o
+pvrsrvkm-y += services/server/env/linux/physmem_dmabuf.o
+endif # SUPPORT_ION
+
+ifneq ($(W),1)
+CFLAGS_server_mm_bridge.o := -Werror
+CFLAGS_server_cmm_bridge.o := -Werror
+CFLAGS_client_mm_bridge.o := -Werror
+CFLAGS_client_pdumpmm_bridge.o := -Werror
+CFLAGS_server_pdump_bridge.o := -Werror
+CFLAGS_server_sync_bridge.o := -Werror
+CFLAGS_server_rgxtq_bridge.o := -Werror
+CFLAGS_server_rgxinit_bridge.o := -Werror
+CFLAGS_server_rgxta3d_bridge.o := -Werror
+CFLAGS_server_rgxcmp_bridge.o := -Werror
+CFLAGS_server_srvcore_bridge.o := -Werror
+CFLAGS_server_breakpoint_bridge.o := -Werror
+CFLAGS_server_debugmisc_bridge.o := -Werror
+CFLAGS_server_rgxpdump_bridge.o := -Werror
+CFLAGS_server_pdumpmm_bridge.o := -Werror
+CFLAGS_client_pdumpmm_bridge.o := -Werror
+CFLAGS_server_pdumpcmm_bridge.o := -Werror
+CFLAGS_server_rgxray_bridge.o := -Werror
+CFLAGS_server_regconfig_bridge.o := -Werror
+CFLAGS_server_timerquery_bridge.o := -Werror
+
+ifeq ($(SUPPORT_DISPLAY_CLASS),1)
+CFLAGS_server_dc_bridge.o := -Werror
+endif
+ifeq ($(CACHEFLUSH_TYPE),CACHEFLUSH_GENERIC)
+CFLAGS_cache_generic.o := -Werror
+CFLAGS_server_cachegeneric_bridge.o := -Werror
+endif
+ifeq ($(SUPPORT_SECURE_EXPORT),1)
+CFLAGS_ossecure_export.o := -Werror
+CFLAGS_server_smm_bridge.o := -Werror
+CFLAGS_server_syncsexport_bridge.o := -Werror
+endif
+ifeq ($(SUPPORT_INSECURE_EXPORT),1)
+CFLAGS_server_syncexport_bridge.o := -Werror
+endif
+ifeq ($(SUPPORT_PMMIF),1)
+CFLAGS_physmem_pmmif.o := -Werror
+CFLAGS_server_pmmif_bridge.o = -Werror
+endif
+CFLAGS_server_pvrtl_bridge.o := -Werror
+CFLAGS_client_pvrtl_bridge.o := -Werror
+CFLAGS_server_rgxhwperf_bridge.o := -Werror
+ifeq ($(PVR_RI_DEBUG),1)
+CFLAGS_server_ri_bridge.o := -Werror
+CFLAGS_client_ri_bridge.o := -Werror
+endif
+ifeq ($(SUPPORT_ION),1)
+CFLAGS_physmem_dmabuf.o := -Werror
+CFLAGS_server_dmabuf_bridge.o = -Werror
+endif
+endif
+
+ifeq ($(SUPPORT_DRM),1)
+pvrsrvkm-y += \
+ services/server/env/linux/pvr_drm.o \
+ services/server/env/linux/pvr_drm_gem.o \
+ services/server/env/linux/pvr_drm_prime.o
+
+ifeq ($(SUPPORT_DRM_DC_MODULE),1)
+pvrsrvkm-y += \
+ services/server/common/scp.o \
+ services/server/env/linux/pvr_drm_display.o
+
+CFLAGS_scp.o := -Werror
+endif
+
+ccflags-y += \
+ -Iinclude/drm \
+ -I$(TOP)/services/include/env/linux
+endif # SUPPORT_DRM
+
+include $(TOP)/services/system/$(PVR_SYSTEM)/Kbuild.mk
diff --git a/drivers/gpu/rogue/services/server/env/linux/Linux.mk b/drivers/gpu/rogue/services/server/env/linux/Linux.mk
new file mode 100644
index 000000000000..7d15d880682f
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/Linux.mk
@@ -0,0 +1,46 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+modules := srvkm
+
+srvkm_type := kernel_module
+srvkm_target := pvrsrvkm.ko
+srvkm_makefile := $(THIS_DIR)/Kbuild.mk
diff --git a/drivers/gpu/rogue/services/server/env/linux/allocmem.c b/drivers/gpu/rogue/services/server/env/linux/allocmem.c
new file mode 100644
index 000000000000..214b15ad694a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/allocmem.c
@@ -0,0 +1,184 @@
+/*************************************************************************/ /*!
+@File
+@Title Host memory management implementation for Linux
+@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 <linux/vmalloc.h>
+#include <linux/mm.h>
+
+#include "pvr_debug.h"
+#include "img_defs.h"
+#include "allocmem.h"
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#include "process_stats.h"
+#endif
+
+IMG_INTERNAL IMG_PVOID OSAllocMem(IMG_UINT32 ui32Size)
+{
+ IMG_PVOID pvRet;
+
+ if (ui32Size > PVR_LINUX_VMALLOC_ALLOCATION_THRESHOLD)
+ {
+ pvRet = vmalloc(ui32Size);
+ }
+ else
+ {
+ pvRet = kmalloc(ui32Size, GFP_KERNEL);
+ }
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ if (pvRet != IMG_NULL)
+ {
+ IMG_UINT32 uiStatSize;
+ IMG_UINT32 uiAllocType;
+
+
+ if (!is_vmalloc_addr(pvRet))
+ {
+ uiStatSize = ksize(pvRet);
+ uiAllocType = PVRSRV_MEM_ALLOC_TYPE_KMALLOC;
+
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ PVRSRVStatsIncrMemAllocStat(uiAllocType, uiStatSize);
+#endif
+ }
+ else
+ {
+ uiStatSize = ((ui32Size + PAGE_SIZE -1) & ~(PAGE_SIZE-1));
+ uiAllocType = PVRSRV_MEM_ALLOC_TYPE_VMALLOC;
+
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ PVRSRVStatsIncrMemAllocStatAndTrack(uiAllocType, uiStatSize, (IMG_UINT64)(IMG_UINTPTR_T) pvRet);
+#endif
+ }
+
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
+ {
+ IMG_CPU_PHYADDR sCpuPAddr;
+ sCpuPAddr.uiAddr = 0;
+
+ PVRSRVStatsAddMemAllocRecord(uiAllocType,
+ pvRet,
+ sCpuPAddr,
+ uiStatSize,
+ IMG_NULL);
+ }
+#endif
+
+ }
+#endif
+
+ return pvRet;
+}
+IMG_INTERNAL IMG_PVOID OSAllocMemstatMem(IMG_UINT32 ui32Size)
+{
+ IMG_PVOID pvRet = kmalloc(ui32Size, GFP_KERNEL);
+
+ return pvRet;
+}
+
+IMG_INTERNAL IMG_PVOID OSReallocMem(IMG_PVOID pvPrev, IMG_UINT32 ui32Size)
+{
+ IMG_PVOID pvRet = krealloc(pvPrev, ui32Size, GFP_KERNEL);
+ return pvRet;
+}
+
+IMG_INTERNAL IMG_PVOID OSAllocZMem(IMG_UINT32 ui32Size)
+{
+ IMG_PVOID pvRet = kzalloc(ui32Size, GFP_KERNEL);
+
+ if (pvRet != IMG_NULL)
+ {
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_KMALLOC, ksize(pvRet));
+#else
+ IMG_CPU_PHYADDR sCpuPAddr;
+ sCpuPAddr.uiAddr = 0;
+
+ PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_KMALLOC,
+ pvRet,
+ sCpuPAddr,
+ ksize(pvRet),
+ IMG_NULL);
+#endif
+#endif
+ }
+
+ return pvRet;
+}
+
+IMG_INTERNAL void OSFreeMem(IMG_PVOID pvMem)
+{
+
+ if ( !is_vmalloc_addr(pvMem) )
+ {
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ if (pvMem != IMG_NULL)
+ {
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_KMALLOC, ksize(pvMem));
+#else
+ PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_KMALLOC, (IMG_UINT64)(IMG_UINTPTR_T) pvMem);
+#endif
+ }
+#endif
+ kfree(pvMem);
+ }
+ else
+ {
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ if (pvMem != IMG_NULL)
+ {
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE_VMALLOC, (IMG_UINT64)(IMG_UINTPTR_T) pvMem);
+#else
+ PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_VMALLOC, (IMG_UINT64)(IMG_UINTPTR_T) pvMem);
+#endif
+ }
+#endif
+ vfree(pvMem);
+ }
+}
+IMG_INTERNAL void OSFreeMemstatMem(IMG_PVOID pvMem)
+{
+ kfree(pvMem);
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/devicemem_mmap_stub.c b/drivers/gpu/rogue/services/server/env/linux/devicemem_mmap_stub.c
new file mode 100644
index 000000000000..2badc35e49cf
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/devicemem_mmap_stub.c
@@ -0,0 +1,133 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS abstraction for the mmap2 interface for mapping PMRs into
+ User Mode memory
+@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.
+*/ /**************************************************************************/
+
+/* our exported API */
+#include "devicemem_mmap.h"
+
+/* include/ */
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+
+/* services/include/ */
+
+/* services/include/srvhelper/ */
+#include "ra.h"
+
+/* autogenerated bridge */
+#include "client_mm_bridge.h"
+
+#include "pmr.h"
+
+IMG_INTERNAL PVRSRV_ERROR
+OSMMapPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_SIZE_T uiPMRSize,
+ IMG_HANDLE *phOSMMapPrivDataOut,
+ void **ppvMappingAddressOut,
+ IMG_SIZE_T *puiMappingLengthOut)
+{
+ PVRSRV_ERROR eError;
+ PMR *psPMR;
+ void *pvKernelAddress;
+ IMG_SIZE_T uiLength;
+ IMG_HANDLE hPriv;
+
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+
+ /*
+ Normally this function would mmap a PMR into the memory space of
+ user process, but in this case we're taking a PMR and mapping it
+ into kernel virtual space. We keep the same function name for
+ symmetry as this allows the higher layers of the software stack
+ to not care whether they are user mode or kernel
+ */
+
+ psPMR = hPMR;
+
+ eError = PMRAcquireKernelMappingData(psPMR,
+ 0,
+ 0,
+ &pvKernelAddress,
+ &uiLength,
+ &hPriv);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ *phOSMMapPrivDataOut = hPriv;
+ *ppvMappingAddressOut = pvKernelAddress;
+ *puiMappingLengthOut = uiLength;
+
+ PVR_ASSERT(*puiMappingLengthOut == uiPMRSize);
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_INTERNAL void
+OSMUnmapPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_HANDLE hOSMMapPrivData,
+ void *pvMappingAddress,
+ IMG_SIZE_T uiMappingLength)
+{
+ PMR *psPMR;
+
+ PVR_UNREFERENCED_PARAMETER(hBridge);
+ PVR_UNREFERENCED_PARAMETER(pvMappingAddress);
+ PVR_UNREFERENCED_PARAMETER(uiMappingLength);
+
+ psPMR = hPMR;
+ PMRReleaseKernelMappingData(psPMR,
+ hOSMMapPrivData);
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/driverlock.h b/drivers/gpu/rogue/services/server/env/linux/driverlock.h
new file mode 100644
index 000000000000..bb442654f8b7
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/driverlock.h
@@ -0,0 +1,57 @@
+/*************************************************************************/ /*!
+@File driverlock.h
+@Title Main driver lock
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description The main driver lock, held in most places in
+ the driver.
+@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 __DRIVERLOCK_H__
+#define __DRIVERLOCK_H__
+
+/*
+ * Main driver lock, used to ensure driver code is single threaded.
+ * There are some places where this lock must not be taken, such as
+ * in the mmap related deriver entry points.
+ */
+extern struct mutex gPVRSRVLock;
+
+#endif /* __DRIVERLOCK_H__ */
+/*****************************************************************************
+ End of file (driverlock.h)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/env/linux/env_connection.h b/drivers/gpu/rogue/services/server/env/linux/env_connection.h
new file mode 100644
index 000000000000..02f59699ffc9
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/env_connection.h
@@ -0,0 +1,114 @@
+/*************************************************************************/ /*!
+@File
+@Title Server side connection management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Linux specific server side connection management
+@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(_ENV_CONNECTION_H_)
+#define _ENV_CONNECTION_H_
+
+#include <linux/list.h>
+
+#include "handle.h"
+#include "pvr_debug.h"
+
+#if defined(SUPPORT_ION)
+#include PVR_ANDROID_ION_HEADER
+#include "ion_sys.h"
+#include "allocmem.h"
+#endif
+
+#if defined(SUPPORT_DRM)
+#include <drm/drmP.h>
+#endif
+
+#if defined(SUPPORT_ION)
+#define ION_CLIENT_NAME_SIZE 50
+
+typedef struct _ENV_ION_CONNECTION_DATA_
+{
+ IMG_CHAR azIonClientName[ION_CLIENT_NAME_SIZE];
+ struct ion_device *psIonDev;
+ struct ion_client *psIonClient;
+ IMG_UINT32 ui32IonClientRefCount;
+} ENV_ION_CONNECTION_DATA;
+#endif
+
+typedef struct _ENV_CONNECTION_DATA_
+{
+#if defined(SUPPORT_DRM)
+ struct drm_file *psFile;
+#else
+ struct file *psFile;
+#endif
+#if defined(SUPPORT_ION)
+ ENV_ION_CONNECTION_DATA *psIonData;
+#endif
+#if defined(SUPPORT_DRM)
+ IMG_BOOL bAuthenticated;
+#endif
+} ENV_CONNECTION_DATA;
+
+#if defined(SUPPORT_ION)
+static inline struct ion_client *EnvDataIonClientAcquire(ENV_CONNECTION_DATA *psEnvData)
+{
+ PVR_ASSERT(psEnvData->psIonData != IMG_NULL);
+ PVR_ASSERT(psEnvData->psIonData->psIonClient != IMG_NULL);
+ PVR_ASSERT(psEnvData->psIonData->ui32IonClientRefCount > 0);
+ psEnvData->psIonData->ui32IonClientRefCount++;
+ return psEnvData->psIonData->psIonClient;
+}
+
+static inline void EnvDataIonClientRelease(ENV_ION_CONNECTION_DATA *psIonData)
+{
+ PVR_ASSERT(psIonData != IMG_NULL);
+ PVR_ASSERT(psIonData->psIonClient != IMG_NULL);
+ PVR_ASSERT(psIonData->ui32IonClientRefCount > 0);
+ if (--psIonData->ui32IonClientRefCount == 0)
+ {
+ ion_client_destroy(psIonData->psIonClient);
+ IonDevRelease(psIonData->psIonDev);
+ OSFreeMem(psIonData);
+ psIonData = IMG_NULL;
+ }
+}
+#endif /* defined(SUPPORT_ION) */
+
+#endif /* !defined(_ENV_CONNECTION_H_) */
diff --git a/drivers/gpu/rogue/services/server/env/linux/env_data.h b/drivers/gpu/rogue/services/server/env/linux/env_data.h
new file mode 100644
index 000000000000..f861ed18b19c
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/env_data.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@File
+@Title Environmental Data header file
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Linux-specific part of system data.
+@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 _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#include <linux/workqueue.h>
+#endif
+
+/*
+ * Env data specific to linux - convenient place to put this
+ */
+
+/* Fairly arbitrary sizes - hopefully enough for all bridge calls */
+#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x2000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000
+
+typedef struct _ENV_DATA_TAG
+{
+ void *pvBridgeData;
+ struct pm_dev *psPowerDevice;
+} ENV_DATA;
+
+ENV_DATA *OSGetEnvData(void);
+
+#endif /* _ENV_DATA_ */
+/*****************************************************************************
+ End of file (env_data.h)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/env/linux/event.c b/drivers/gpu/rogue/services/server/env/linux/event.c
new file mode 100644
index 000000000000..2ec5c0496a5a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/event.c
@@ -0,0 +1,362 @@
+/*************************************************************************/ /*!
+@File
+@Title Event Object
+@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 <asm/io.h>
+#include <asm/page.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) )
+#include <asm/system.h>
+#endif
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "allocmem.h"
+#include "mm.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "driverlock.h"
+#include "event.h"
+#include "pvr_debug.h"
+#include "pvrsrv.h"
+
+#include "osfunc.h"
+
+/* Returns pointer to task_struct that belongs to thread which acquired
+ * bridge lock. */
+extern struct task_struct *OSGetBridgeLockOwner(void);
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
+{
+ rwlock_t sLock;
+ struct list_head sList;
+
+} PVRSRV_LINUX_EVENT_OBJECT_LIST;
+
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
+{
+ atomic_t sTimeStamp;
+ IMG_UINT32 ui32TimeStampPrevious;
+#if defined(DEBUG)
+ IMG_UINT ui32Stats;
+#endif
+ wait_queue_head_t sWait;
+ struct list_head sList;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+} PVRSRV_LINUX_EVENT_OBJECT;
+
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectListCreate
+
+ @Description
+
+ Linux wait object list creation
+
+ @Output hOSEventKM : Pointer to the event object list handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList;
+
+ psEvenObjectList = OSAllocMem(sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST));
+ if (psEvenObjectList == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psEvenObjectList->sList);
+
+ rwlock_init(&psEvenObjectList->sLock);
+
+ *phEventObjectList = (IMG_HANDLE *) psEvenObjectList;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectListDestroy
+
+ @Description
+
+ Linux wait object list destruction
+
+ @Input hOSEventKM : Event object list handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
+{
+
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ;
+
+ if(psEvenObjectList)
+ {
+ if (!list_empty(&psEvenObjectList->sList))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty"));
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+ }
+ OSFreeMem(psEvenObjectList);
+ /*not nulling pointer, copy on stack*/
+ }
+ return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectDelete
+
+ @Description
+
+ Linux wait object removal
+
+ @Input hOSEventObject : Event object handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObject)
+{
+ if(hOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList;
+
+ write_lock_bh(&psLinuxEventObjectList->sLock);
+ list_del(&psLinuxEventObject->sList);
+ write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+#if defined(DEBUG)
+// PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDelete: Event object waits: %u", psLinuxEventObject->ui32Stats));
+#endif
+
+ OSFreeMem(psLinuxEventObject);
+ /*not nulling pointer, copy on stack*/
+
+ return PVRSRV_OK;
+ }
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+}
+
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectAdd
+
+ @Description
+
+ Linux wait object addition
+
+ @Input hOSEventObjectList : Event object list handle
+ @Output phOSEventObject : Pointer to the event object handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+
+ /* allocate completion variable */
+ psLinuxEventObject = OSAllocMem(sizeof(PVRSRV_LINUX_EVENT_OBJECT));
+ if (psLinuxEventObject == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+ atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+ psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats = 0;
+#endif
+ init_waitqueue_head(&psLinuxEventObject->sWait);
+
+ psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+ write_lock_bh(&psLinuxEventObjectList->sLock);
+ list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+ write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+ *phOSEventObject = psLinuxEventObject;
+
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectSignal
+
+ @Description
+
+ Linux wait object signaling function
+
+ @Input hOSEventObjectList : Event object list handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+ struct list_head *psListEntry, *psListEntryTemp, *psList;
+ psList = &psLinuxEventObjectList->sList;
+
+ read_lock_bh(&psLinuxEventObjectList->sLock);
+ list_for_each_safe(psListEntry, psListEntryTemp, psList)
+ {
+
+ psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList);
+
+ atomic_inc(&psLinuxEventObject->sTimeStamp);
+ wake_up_interruptible(&psLinuxEventObject->sWait);
+ }
+ read_unlock_bh(&psLinuxEventObjectList->sLock);
+
+ return PVRSRV_OK;
+
+}
+
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectWait
+
+ @Description
+
+ Linux wait object routine
+
+ @Input hOSEventObject : Event object handle
+
+ @Input ui32MSTimeout : Time out value in msec
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
+{
+ IMG_UINT32 ui32TimeStamp;
+ IMG_BOOL bReleasePVRLock;
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ DEFINE_WAIT(sWait);
+
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
+
+ IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+
+ /* Check if the driver is good shape */
+ if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+ {
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+
+ do
+ {
+ prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
+ ui32TimeStamp = (IMG_UINT32)atomic_read(&psLinuxEventObject->sTimeStamp);
+
+ if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+ {
+ break;
+ }
+
+ /* Check thread holds the current PVR/bridge lock before obeying the
+ * 'release before deschedule' behaviour. Some threads choose not to
+ * hold the bridge lock in their implementation.
+ */
+ bReleasePVRLock = (OSGetReleasePVRLock() && mutex_is_locked(&gPVRSRVLock) && current == OSGetBridgeLockOwner());
+ if (bReleasePVRLock == IMG_TRUE)
+ {
+ OSReleaseBridgeLock();
+ }
+
+ ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+
+ if (bReleasePVRLock == IMG_TRUE)
+ {
+ OSAcquireBridgeLock();
+ }
+
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats++;
+#endif
+
+
+ } while (ui32TimeOutJiffies);
+
+ finish_wait(&psLinuxEventObject->sWait, &sWait);
+
+ psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+ return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/event.h b/drivers/gpu/rogue/services/server/env/linux/event.h
new file mode 100644
index 000000000000..dd55b85a83d4
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/event.h
@@ -0,0 +1,48 @@
+/*************************************************************************/ /*!
+@File
+@Title Event Object
+@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.
+*/ /**************************************************************************/
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObject);
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout);
diff --git a/drivers/gpu/rogue/services/server/env/linux/linkage.h b/drivers/gpu/rogue/services/server/env/linux/linkage.h
new file mode 100644
index 000000000000..c7972dbdae92
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/linkage.h
@@ -0,0 +1,64 @@
+/*************************************************************************/ /*!
+@File
+@Title Linux specific Services code internal interfaces
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Interfaces between various parts of the Linux specific
+ Services code, that don't have any other obvious
+ header file to go into.
+@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(__LINKAGE_H__)
+#define __LINKAGE_H__
+
+#if !defined(SUPPORT_DRM)
+long PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
+
+#if defined(CONFIG_COMPAT)
+long PVRSRV_BridgeCompatDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
+#endif
+#endif
+
+void PVRDPFInit(void);
+PVRSRV_ERROR PVROSFuncInit(void);
+void PVROSFuncDeInit(void);
+
+int PVRDebugCreateDebugFSEntries(void);
+void PVRDebugRemoveDebugFSEntries(void);
+
+#endif /* !defined(__LINKAGE_H__) */
diff --git a/drivers/gpu/rogue/services/server/env/linux/mm.c b/drivers/gpu/rogue/services/server/env/linux/mm.c
new file mode 100644
index 000000000000..53243edc81fc
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/mm.c
@@ -0,0 +1,105 @@
+/*************************************************************************/ /*!
+@File
+@Title Misc memory management utility functions for Linux
+@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 <asm/io.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "mm.h"
+#include "pvrsrv_memallocflags.h"
+#include "devicemem_server_utils.h"
+
+#if defined(CONFIG_ARM)
+#define ioremap_cache(x,y) ioremap_cached(x,y)
+#endif
+
+void *
+_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ void *pvIORemapCookie;
+ IMG_UINT32 ui32CPUCacheMode = DevmemCPUCacheMode(ui32MappingFlags);
+
+ switch (ui32CPUCacheMode)
+ {
+ case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
+ pvIORemapCookie = (void *)ioremap_nocache(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
+#if defined(CONFIG_X86) || defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+ pvIORemapCookie = (void *)ioremap_wc(BasePAddr.uiAddr, ui32Bytes);
+#else
+ pvIORemapCookie = (void *)ioremap_nocache(BasePAddr.uiAddr, ui32Bytes);
+#endif
+ break;
+ case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
+#if defined(CONFIG_X86) || defined(CONFIG_ARM)
+ pvIORemapCookie = (void *)ioremap_cache(BasePAddr.uiAddr, ui32Bytes);
+#else
+ pvIORemapCookie = (void *)ioremap(BasePAddr.uiAddr, ui32Bytes);
+#endif
+ break;
+ default:
+ return IMG_NULL;
+ break;
+ }
+
+
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+
+ return pvIORemapCookie;
+}
+
+
+void
+_IOUnmapWrapper(void *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+
+
+ iounmap(pvIORemapCookie);
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/mm.h b/drivers/gpu/rogue/services/server/env/linux/mm.h
new file mode 100644
index 000000000000..e8a444701686
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/mm.h
@@ -0,0 +1,86 @@
+/*************************************************************************/ /*!
+@File
+@Title Declares various memory management utility functions for Linux.
+@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_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <asm/io.h>
+/*!
+ *******************************************************************************
+ * @brief Reserve physical IO memory and create a CPU virtual mapping for it
+ *
+ * @param BasePAddr
+ * @param ui32Bytes
+ * @param ui32MappingFlags
+ *
+ * @return
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
+#else
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
+#endif
+void *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line);
+
+/*!
+ ******************************************************************************
+ * @brief Unmaps an IO memory mapping created using IORemap
+ *
+ * @param pvIORemapCookie
+ *
+ * @return
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
+#else
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, NULL, 0)
+#endif
+void _IOUnmapWrapper(void *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+#endif /* __IMG_LINUX_MM_H__ */
diff --git a/drivers/gpu/rogue/services/server/env/linux/mmap.c b/drivers/gpu/rogue/services/server/env/linux/mmap.c
new file mode 100644
index 000000000000..ad16d58bd7c6
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/mmap.c
@@ -0,0 +1,498 @@
+/*************************************************************************/ /*!
+@File
+@Title Linux mmap interface
+@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 <asm/io.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+
+#include "img_defs.h"
+#include "mmap.h"
+#include "pvr_debug.h"
+#include "handle.h"
+#include "pvrsrv.h"
+#include "connection_server.h"
+#include "devicemem_server_utils.h"
+
+#include "private_data.h"
+#include "driverlock.h"
+
+#if defined(SUPPORT_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if !defined(PVR_SECURE_HANDLES)
+#error "The mmap code requires PVR_SECURE_HANDLES"
+#endif
+
+/* WARNING!
+ * The mmap code has its own mutex, to prevent a possible deadlock,
+ * when using the bridge lock.
+ * The Linux kernel takes the mm->mmap_sem before calling the mmap
+ * entry points (PVRMMap, MMapVOpen, MMapVClose), but the ioctl
+ * entry point may take mm->mmap_sem during fault handling, or
+ * before calling get_user_pages. If the bridge lock was used in the
+ * mmap entry points, a deadlock could result, due to the ioctl
+ * and mmap code taking the two locks in different orders.
+ * As a corollary to this, the mmap entry points must not call
+ * any driver code that relies on the bridge lock is held.
+ */
+static struct mutex g_sMMapMutex;
+
+#include "pmr.h"
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#include "process_stats.h"
+#endif
+static void MMapPMROpen(struct vm_area_struct* ps_vma)
+{
+ /* Our VM flags should ensure this function never gets called */
+ PVR_ASSERT(0);
+}
+
+static void MMapPMRClose(struct vm_area_struct *ps_vma)
+{
+ PMR *psPMR;
+ IMG_UINTPTR_T vAddr = ps_vma->vm_start;
+ IMG_SIZE_T pageSize = OSGetPageSize();
+
+ psPMR = ps_vma->vm_private_data;
+ while (vAddr < ps_vma->vm_end)
+ {
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ /* USER MAPPING */
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES, PAGE_SIZE);
+#else
+ PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES, (IMG_UINT64)vAddr);
+#endif
+#endif
+ vAddr += pageSize;
+ }
+
+ PMRUnlockSysPhysAddresses(psPMR);
+ PMRUnrefPMR(psPMR);
+}
+
+/*
+ * This vma operation is used to read data from mmap regions. It is called
+ * by access_process_vm, which is called to handle PTRACE_PEEKDATA ptrace
+ * requests and reads from /proc/<pid>/mem.
+ */
+static int MMapVAccess(struct vm_area_struct *ps_vma, unsigned long addr,
+ void *buf, int len, int write)
+{
+ PMR *psPMR;
+ unsigned long ulOffset;
+ IMG_SIZE_T uiBytesCopied;
+ PVRSRV_ERROR eError;
+ int iRetVal = -EINVAL;
+
+ psPMR = ps_vma->vm_private_data;
+
+ ulOffset = addr - ps_vma->vm_start;
+
+ if (write)
+ {
+ eError = PMR_WriteBytes(psPMR,
+ (IMG_DEVMEM_OFFSET_T) ulOffset,
+ buf,
+ len,
+ &uiBytesCopied);
+ }
+ else
+ {
+ eError = PMR_ReadBytes(psPMR,
+ (IMG_DEVMEM_OFFSET_T) ulOffset,
+ buf,
+ len,
+ &uiBytesCopied);
+ }
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Error from %s (%d)",
+ __FUNCTION__,
+ write?"PMR_WriteBytes":"PMR_ReadBytes",
+ eError));
+ }
+ else
+ {
+ iRetVal = uiBytesCopied;
+ }
+
+ return iRetVal;
+}
+
+static struct vm_operations_struct gsMMapOps =
+{
+ .open=&MMapPMROpen,
+ .close=&MMapPMRClose,
+ .access=MMapVAccess,
+};
+
+int MMapPMR(struct file *pFile, struct vm_area_struct *ps_vma)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hSecurePMRHandle;
+ IMG_SIZE_T uiLength;
+ IMG_DEVMEM_OFFSET_T uiOffset;
+ unsigned long uiPFN;
+ IMG_HANDLE hPMRResmanHandle;
+ PMR *psPMR;
+ PMR_FLAGS_T ulPMRFlags;
+ IMG_UINT32 ui32CPUCacheFlags;
+ unsigned long ulNewFlags = 0;
+ pgprot_t sPageProt;
+#if defined(SUPPORT_DRM)
+ CONNECTION_DATA *psConnection = LinuxConnectionFromFile(PVR_DRM_FILE_FROM_FILE(pFile));
+#else
+ CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
+#endif
+
+#if defined(PVR_MMAP_USE_VM_INSERT)
+ IMG_BOOL bMixedMap = IMG_FALSE;
+#endif
+ /*
+ * The pmr lock used here to protect both handle related operations and PMR
+ * operations.
+ * This was introduced to fix lockdep issue.
+ */
+ mutex_lock(&g_sMMapMutex);
+ PMRLock();
+
+#if defined(SUPPORT_DRM_DC_MODULE)
+ psPMR = PVRSRVGEMMMapLookupPMR(pFile, ps_vma);
+ if (!psPMR)
+#endif
+ {
+ hSecurePMRHandle = (IMG_HANDLE)((IMG_UINTPTR_T)ps_vma->vm_pgoff);
+
+ eError = PVRSRVLookupHandle(psConnection->psHandleBase,
+ (IMG_HANDLE *) &hPMRResmanHandle,
+ hSecurePMRHandle,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ eError = ResManFindPrivateDataByPtr(hPMRResmanHandle,
+ (void **)&psPMR);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+ }
+
+ /*
+ * Take a reference on the PMR, make's sure that it can't be freed
+ * while it's mapped into the user process
+ */
+ PMRRefPMR(psPMR);
+
+ PMRUnlock();
+
+ eError = PMRLockSysPhysAddresses(psPMR, PAGE_SHIFT);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
+ ((ps_vma->vm_flags & VM_SHARED) == 0))
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e1;
+ }
+
+ /*
+ * We ought to call PMR_Flags() here to check the permissions
+ * against the requested mode, and possibly to set up the cache
+ * control protflags
+ */
+ eError = PMR_Flags(psPMR, &ulPMRFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ ulNewFlags = ps_vma->vm_flags;
+#if 0
+ /* Discard user read/write request, we will pull these flags from the PMR */
+ ulNewFlags &= ~(VM_READ | VM_WRITE);
+
+ if (ulPMRFlags & PVRSRV_MEMALLOCFLAG_CPU_READABLE)
+ {
+ ulNewFlags |= VM_READ;
+ }
+ if (ulPMRFlags & PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE)
+ {
+ ulNewFlags |= VM_WRITE;
+ }
+#endif
+
+ ps_vma->vm_flags = ulNewFlags;
+
+#if defined (CONFIG_ARM64)
+ sPageProt = __pgprot_modify(ps_vma->vm_page_prot, 0, vm_get_page_prot(ulNewFlags));
+#elif defined(CONFIG_ARM)
+ sPageProt = __pgprot_modify(ps_vma->vm_page_prot, L_PTE_MT_MASK, vm_get_page_prot(ulNewFlags));
+#elif defined(CONFIG_X86)
+ sPageProt = pgprot_modify(ps_vma->vm_page_prot, vm_get_page_prot(ulNewFlags));
+#elif defined(CONFIG_METAG) || defined(CONFIG_MIPS)
+ sPageProt = vm_get_page_prot(ulNewFlags);
+#else
+#error Please add pgprot_modify equivalent for your system
+#endif
+ ui32CPUCacheFlags = DevmemCPUCacheMode(ulPMRFlags);
+ switch (ui32CPUCacheFlags)
+ {
+ case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
+ sPageProt = pgprot_noncached(sPageProt);
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
+ sPageProt = pgprot_writecombine(sPageProt);
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
+ break;
+
+ default:
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e1;
+ }
+ ps_vma->vm_page_prot = sPageProt;
+
+ uiLength = ps_vma->vm_end - ps_vma->vm_start;
+
+ ps_vma->vm_flags |= VM_IO;
+
+/* Don't include the mapping in core dumps */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
+ ps_vma->vm_flags |= VM_DONTDUMP;
+#else
+ ps_vma->vm_flags |= VM_RESERVED;
+#endif
+
+ /*
+ * Disable mremap because our nopage handler assumes all
+ * page requests have already been validated.
+ */
+ ps_vma->vm_flags |= VM_DONTEXPAND;
+
+ /* Don't allow mapping to be inherited across a process fork */
+ ps_vma->vm_flags |= VM_DONTCOPY;
+
+#if defined(PVR_MMAP_USE_VM_INSERT)
+ {
+ /* Scan the map range for pfns without struct page* handling. If we find
+ * one, this is a mixed map, and we can't use vm_insert_page().
+ */
+ for (uiOffset = 0; uiOffset < uiLength; uiOffset += 1ULL<<PAGE_SHIFT)
+ {
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_BOOL bValid;
+
+ eError = PMR_CpuPhysAddr(psPMR, uiOffset, &sCpuPAddr, &bValid);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ if (eError)
+ {
+ goto e2;
+ }
+
+ if (bValid)
+ {
+ uiPFN = sCpuPAddr.uiAddr >> PAGE_SHIFT;
+ PVR_ASSERT(((IMG_UINT64)uiPFN << PAGE_SHIFT) == sCpuPAddr.uiAddr);
+
+ if (!pfn_valid(uiPFN) || page_count(pfn_to_page(uiPFN)) == 0)
+ {
+ bMixedMap = IMG_TRUE;
+ }
+ }
+ }
+
+ if (bMixedMap)
+ {
+ ps_vma->vm_flags |= VM_MIXEDMAP;
+ }
+ }
+#endif /* defined(PVR_MMAP_USE_VM_INSERT) */
+
+ for (uiOffset = 0; uiOffset < uiLength; uiOffset += 1ULL<<PAGE_SHIFT)
+ {
+ IMG_SIZE_T uiNumContiguousBytes;
+ IMG_INT32 iStatus;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_BOOL bValid;
+
+ uiNumContiguousBytes = 1ULL<<PAGE_SHIFT;
+ eError = PMR_CpuPhysAddr(psPMR,
+ uiOffset,
+ &sCpuPAddr,
+ &bValid);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ if (eError)
+ {
+ goto e2;
+ }
+
+ /*
+ Only map in pages that are valid, any that aren't will be picked up
+ by the nopage handler which will return a zeroed page for us
+ */
+ if (bValid)
+ {
+ uiPFN = sCpuPAddr.uiAddr >> PAGE_SHIFT;
+ PVR_ASSERT(((IMG_UINT64)uiPFN << PAGE_SHIFT) == sCpuPAddr.uiAddr);
+
+#if defined(PVR_MMAP_USE_VM_INSERT)
+ if (bMixedMap)
+ {
+ /* This path is just for debugging. It should be equivalent
+ * to the remap_pfn_range() path.
+ */
+ iStatus = vm_insert_mixed(ps_vma,
+ ps_vma->vm_start + uiOffset,
+ uiPFN);
+ }
+ else
+ {
+ iStatus = vm_insert_page(ps_vma,
+ ps_vma->vm_start + uiOffset,
+ pfn_to_page(uiPFN));
+ }
+#else /* defined(PVR_MMAP_USE_VM_INSERT) */
+ iStatus = remap_pfn_range(ps_vma,
+ ps_vma->vm_start + uiOffset,
+ uiPFN,
+ uiNumContiguousBytes,
+ ps_vma->vm_page_prot);
+#endif /* defined(PVR_MMAP_USE_VM_INSERT) */
+
+ PVR_ASSERT(iStatus == 0);
+ if(iStatus)
+ {
+ // N.B. not the right error code, but, it doesn't get propagated anyway... :(
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ goto e2;
+ }
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ /* USER MAPPING*/
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES, PAGE_SIZE);
+#else
+ PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES,
+ (IMG_VOID*)(IMG_UINTPTR_T)(ps_vma->vm_start + uiOffset),
+ sCpuPAddr,
+ PAGE_SIZE,
+ IMG_NULL);
+#endif
+#endif
+ }
+ (void)pFile;
+ }
+
+ /* let us see the PMR so we can unlock it later */
+ ps_vma->vm_private_data = psPMR;
+
+ /* Install open and close handlers for ref-counting */
+ ps_vma->vm_ops = &gsMMapOps;
+
+ mutex_unlock(&g_sMMapMutex);
+
+ return 0;
+
+ /*
+ error exit paths follow
+ */
+ e2:
+ PVR_DPF((PVR_DBG_ERROR, "don't know how to handle this error. Abort!"));
+ PMRUnlockSysPhysAddresses(psPMR);
+ e1:
+ PMRUnrefPMR(psPMR);
+ goto em1;
+ e0:
+ PVR_DPF((PVR_DBG_ERROR, "Error in MMapPMR critical section"));
+ PMRUnlock();
+ em1:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ PVR_DPF((PVR_DBG_ERROR, "unable to translate error %d", eError));
+ mutex_unlock(&g_sMMapMutex);
+
+ return -ENOENT; // -EAGAIN // or what?
+}
+
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapInit
+
+ @Description
+
+ MMap initialisation code
+
+ ******************************************************************************/
+void
+PVRMMapInit(void)
+{
+ mutex_init(&g_sMMapMutex);
+ return;
+}
+
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapCleanup
+
+ @Description
+
+ Mmap deinitialisation code
+
+ ******************************************************************************/
+void
+PVRMMapCleanup(void)
+{
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/mmap.h b/drivers/gpu/rogue/services/server/env/linux/mmap.h
new file mode 100644
index 000000000000..321c90cf99e1
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/mmap.h
@@ -0,0 +1,84 @@
+/*************************************************************************/ /*!
+@File
+@Title Linux mmap interface declaration
+@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(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+
+/*!
+ *******************************************************************************
+ * @brief Mmap initialisation code
+ *
+ * @param void
+ *
+ * @return
+ ******************************************************************************/
+void PVRMMapInit(void);
+
+
+/*!
+ *******************************************************************************
+ * @brief Mmap de-initialisation code
+ *
+ * @param void
+ *
+ * @return
+ ******************************************************************************/
+void PVRMMapCleanup(void);
+
+
+/*!
+ *******************************************************************************
+ * @brief driver mmap entry point
+ *
+ * @param pFile : user file structure
+ *
+ * @param ps_vma : vm area structure
+ *
+ * @return 0 for success, -errno for failure.
+ ******************************************************************************/
+int MMapPMR(struct file* pFile, struct vm_area_struct* ps_vma);
+
+
+#endif /* __MMAP_H__ */
+
diff --git a/drivers/gpu/rogue/services/server/env/linux/module.c b/drivers/gpu/rogue/services/server/env/linux/module.c
new file mode 100755
index 000000000000..3e1d33e4ed8e
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/module.c
@@ -0,0 +1,1234 @@
+/*************************************************************************/ /*!
+@File
+@Title Linux module setup
+@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 (!defined(LDM_PLATFORM) && !defined(LDM_PCI)) || \
+ (defined(LDM_PLATFORM) && defined(LDM_PCI))
+ #error "LDM_PLATFORM or LDM_PCI must be defined"
+#endif
+
+#if defined(SUPPORT_DRM)
+#define PVR_MOD_STATIC
+#else
+#define PVR_MOD_STATIC static
+#endif
+
+#if defined(PVR_LDM_PLATFORM_PRE_REGISTERED)
+#define PVR_USE_PRE_REGISTERED_PLATFORM_DEV
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+
+
+#if defined(SUPPORT_DRM_AUTH_IMPORT)
+#include <linux/list.h>
+#endif
+
+#if defined(SUPPORT_DRM)
+#include <drm/drmP.h>
+#endif
+
+#if defined(LDM_PLATFORM)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(LDM_PCI)
+#include <linux/pci.h>
+#endif
+
+#include <linux/device.h>
+
+#include "img_defs.h"
+#include "kerneldisplay.h"
+#include "mm.h"
+#include "allocmem.h"
+#include "mmap.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "connection_server.h"
+#include "handle.h"
+#include "pvr_debugfs.h"
+#include "pvrmodule.h"
+#include "private_data.h"
+#include "driverlock.h"
+#include "linkage.h"
+#include "power.h"
+#include "env_connection.h"
+#include "sysinfo.h"
+#include "pvrsrv.h"
+#include "process_stats.h"
+
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) || defined(SUPPORT_DRM)
+#include "syscommon.h"
+#endif
+
+#if defined(SUPPORT_DRM)
+#include "pvr_drm.h"
+#endif
+#if defined(SUPPORT_AUTH)
+#include "osauth.h"
+#endif
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#include "pvr_sync.h"
+#endif
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+#include "pvr_gputrace.h"
+#endif
+
+#if defined(SUPPORT_KERNEL_HWPERF) || defined(SUPPORT_SHARED_SLC)
+#include "rgxapi_km.h"
+#endif
+#include "pvrversion.h" //add by zxl
+
+#if defined(CONFIG_OF)
+#include <linux/of.h>
+#include <linux/of_device.h>
+#endif
+
+/*
+ * DRVNAME is the name we use to register our driver.
+ * DEVNAME is the name we use to register actual device nodes.
+ */
+#define DRVNAME PVR_LDM_DRIVER_REGISTRATION_NAME
+#define DEVNAME PVRSRV_MODNAME
+
+#if defined(SUPPORT_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+/*
+ * This is all module configuration stuff required by the linux kernel.
+ */
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+#include <linux/moduleparam.h>
+extern IMG_UINT32 gPVRDebugLevel;
+module_param(gPVRDebugLevel, uint, 0644);
+MODULE_PARM_DESC(gPVRDebugLevel, "Sets the level of debug output (default 0x7)");
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
+
+/*
+ * Newer kernels no longer support __devinitdata, __devinit, __devexit, or
+ * __devexit_p.
+ */
+#if !defined(__devinitdata)
+#define __devinitdata
+#endif
+#if !defined(__devinit)
+#define __devinit
+#endif
+#if !defined(__devexit)
+#define __devexit
+#endif
+#if !defined(__devexit_p)
+#define __devexit_p(x) (&(x))
+#endif
+
+#if defined(SUPPORT_DISPLAY_CLASS)
+/* Display class interface */
+EXPORT_SYMBOL(DCRegisterDevice);
+EXPORT_SYMBOL(DCUnregisterDevice);
+EXPORT_SYMBOL(DCDisplayConfigurationRetired);
+EXPORT_SYMBOL(DCImportBufferAcquire);
+EXPORT_SYMBOL(DCImportBufferRelease);
+#endif
+
+/* Physmem interface (required by LMA DC drivers) */
+EXPORT_SYMBOL(PhysHeapAcquire);
+EXPORT_SYMBOL(PhysHeapRelease);
+EXPORT_SYMBOL(PhysHeapGetType);
+EXPORT_SYMBOL(PhysHeapGetAddress);
+EXPORT_SYMBOL(PhysHeapGetSize);
+EXPORT_SYMBOL(PhysHeapCpuPAddrToDevPAddr);
+
+/* System interface (required by DC drivers) */
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) && !defined(SUPPORT_DRM)
+EXPORT_SYMBOL(SysInstallDeviceLISR);
+EXPORT_SYMBOL(SysUninstallDeviceLISR);
+#endif
+
+EXPORT_SYMBOL(PVRSRVCheckStatus);
+EXPORT_SYMBOL(PVRSRVGetErrorStringKM);
+
+#if defined(SUPPORT_KERNEL_HWPERF)
+EXPORT_SYMBOL(RGXHWPerfConnect);
+EXPORT_SYMBOL(RGXHWPerfDisconnect);
+EXPORT_SYMBOL(RGXHWPerfControl);
+EXPORT_SYMBOL(RGXHWPerfConfigureAndEnableCounters);
+EXPORT_SYMBOL(RGXHWPerfDisableCounters);
+EXPORT_SYMBOL(RGXHWPerfAcquireData);
+EXPORT_SYMBOL(RGXHWPerfReleaseData);
+#endif
+
+#if defined(SUPPORT_SHARED_SLC)
+EXPORT_SYMBOL(RGXInitSLC);
+#endif
+
+#if !defined(SUPPORT_DRM)
+/*
+ * Device class used for /sys entries (and udev device node creation)
+ */
+static struct class *psPvrClass;
+
+/*
+ * This is the major number we use for all nodes in /dev.
+ */
+static int AssignedMajorNumber;
+
+static const struct of_device_id rockchip_gpu_dt_ids[] = {
+ { .compatible = "arm,rogue-G6110", },
+ { .compatible = "arm,rk3368-gpu", },
+ {},
+};
+
+/*
+ * These are the operations that will be associated with the device node
+ * we create.
+ *
+ * With gcc -W, specifying only the non-null members produces "missing
+ * initializer" warnings.
+*/
+static int PVRSRVOpen(struct inode* pInode, struct file* pFile);
+static int PVRSRVRelease(struct inode* pInode, struct file* pFile);
+
+static struct file_operations pvrsrv_fops =
+{
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = PVRSRV_BridgeDispatchKM,
+#if defined(CONFIG_COMPAT)
+ .compat_ioctl = PVRSRV_BridgeCompatDispatchKM,
+#endif
+ .open = PVRSRVOpen,
+ .release = PVRSRVRelease,
+ .mmap = MMapPMR,
+};
+#endif /* !defined(SUPPORT_DRM) */
+
+struct mutex gPVRSRVLock;
+
+#if defined(SUPPORT_DRM_AUTH_IMPORT)
+static LIST_HEAD(sDRMAuthListHead);
+#endif
+
+#if defined(LDM_PLATFORM)
+#define LDM_DEV struct platform_device
+#define LDM_DRV struct platform_driver
+#define TO_LDM_DEV(d) to_platform_device(d)
+#endif /*LDM_PLATFORM */
+
+#if defined(LDM_PCI)
+#define LDM_DEV struct pci_dev
+#define LDM_DRV struct pci_driver
+#define TO_LDM_DEV(d) to_pci_device(d)
+#endif /* LDM_PCI */
+
+#if defined(LDM_PLATFORM)
+static int PVRSRVDriverRemove(LDM_DEV *device);
+static int PVRSRVDriverProbe(LDM_DEV *device);
+#endif
+
+#if defined(LDM_PCI)
+static void PVRSRVDriverRemove(LDM_DEV *device);
+static int PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
+#endif
+
+static void PVRSRVDriverShutdown(LDM_DEV *device);
+static int PVRSRVDriverSuspend(struct device *device);
+static int PVRSRVDriverResume(struct device *device);
+
+#if defined(LDM_PCI)
+/* This structure is used by the Linux module code */
+struct pci_device_id powervr_id_table[] __devinitdata = {
+ {PCI_DEVICE(SYS_RGX_DEV_VENDOR_ID, SYS_RGX_DEV_DEVICE_ID)},
+#if defined (SYS_RGX_DEV1_DEVICE_ID)
+ {PCI_DEVICE(SYS_RGX_DEV_VENDOR_ID, SYS_RGX_DEV1_DEVICE_ID)},
+#endif
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, powervr_id_table);
+#endif /*defined(LDM_PCI) */
+
+#if defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+static struct platform_device_id powervr_id_table[] __devinitdata = {
+ {SYS_RGX_DEV_NAME, 0},
+ {}
+};
+#endif
+
+static struct dev_pm_ops powervr_dev_pm_ops = {
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+};
+
+static LDM_DRV powervr_driver = {
+#if defined(LDM_PLATFORM)
+ .driver = {
+ .name = DRVNAME,
+ .pm = &powervr_dev_pm_ops,
+ .of_match_table = of_match_ptr(rockchip_gpu_dt_ids),
+ },
+#endif
+#if defined(LDM_PCI)
+ .name = DRVNAME,
+ .driver.pm = &powervr_dev_pm_ops,
+#endif
+#if defined(LDM_PCI) || defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+ .id_table = powervr_id_table,
+#endif
+ .probe = PVRSRVDriverProbe,
+#if defined(LDM_PLATFORM)
+ .remove = PVRSRVDriverRemove,
+#endif
+#if defined(LDM_PCI)
+ .remove = __devexit_p(PVRSRVDriverRemove),
+#endif
+ .shutdown = PVRSRVDriverShutdown,
+};
+
+LDM_DEV *gpsPVRLDMDev;
+EXPORT_SYMBOL(gpsPVRLDMDev);
+
+#if defined(LDM_PLATFORM)
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+/*static void PVRSRVDeviceRelease(struct device unref__ *pDevice)
+{
+}
+
+static struct platform_device powervr_device = {
+ .name = DEVNAME,
+ .id = -1,
+ .dev = {
+ .release = PVRSRVDeviceRelease
+ }
+};*/
+//time:2012-09-08
+//move platform_device_register from devices.c to sgx
+static struct resource resources_sgx[] = {
+ [0] = {
+ .name = "gpu_irq",
+ .start = IRQ_GPU,
+ .end = IRQ_GPU,
+ .flags = IORESOURCE_IRQ,
+ },
+ [1] = {
+ .name = "gpu_base",
+ .start = RK30_GPU_PHYS ,
+ .end = RK30_GPU_PHYS + RK30_GPU_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+static struct platform_device powervr_device = {
+ .name = DEVNAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(resources_sgx),
+ .resource = resources_sgx,
+};
+#else
+static struct platform_device_info powervr_device_info =
+{
+ .name = DEVNAME,
+ .id = -1,
+ .dma_mask = DMA_BIT_MASK(32),
+};
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)) */
+#endif /* defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) */
+#endif /* defined(LDM_PLATFORM) */
+
+static IMG_BOOL bCalledSysInit = IMG_FALSE;
+static IMG_BOOL bDriverProbeSucceeded = IMG_FALSE;
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVSystemInit
+
+ @Description
+
+ Wrapper for PVRSRVInit.
+
+ @input pDevice - the device for which a probe is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(SUPPORT_DRM)
+int PVRSRVSystemInit(struct drm_device *pDevice)
+#else
+static int PVRSRVSystemInit(LDM_DEV *pDevice)
+#endif
+{
+ PVR_TRACE(("PVRSRVSystemInit (pDevice=%p)", pDevice));
+
+// ssleep(30);
+
+ /* PVRSRVInit is only designed to be called once */
+ if (bCalledSysInit == IMG_FALSE)
+ {
+#if defined(SUPPORT_DRM)
+
+#if defined(LDM_PLATFORM)
+ gpsPVRLDMDev = pDevice->platformdev;
+#elif defined(LDM_PCI)
+ gpsPVRLDMDev = pDevice->pdev;
+#else
+#error Only platform and pci devices are supported
+#endif
+
+#else /* SUPPORT_DRM */
+ gpsPVRLDMDev = pDevice;
+#endif
+
+ bCalledSysInit = IMG_TRUE;
+
+ if (PVRSRVInit() != PVRSRV_OK)
+ {
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVSystemDeInit
+
+ @Description
+
+ Wrapper for PVRSRVDeInit.
+
+ @input none
+ @Return nothing.
+
+*****************************************************************************/
+PVR_MOD_STATIC void PVRSRVSystemDeInit(void)
+{
+ PVR_TRACE(("PVRSRVSystemDeInit"));
+
+ PVRSRVDeInit();
+
+#if !defined(LDM_PLATFORM) || (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+ gpsPVRLDMDev = IMG_NULL;
+#endif
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverProbe
+
+ @Description
+
+ See whether a given device is really one we can drive.
+
+ @input pDevice - the device for which a probe is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(LDM_PLATFORM)
+static int PVRSRVDriverProbe(LDM_DEV *pDevice)
+#endif
+#if defined(LDM_PCI)
+static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device_id *pID)
+#endif
+{
+ int result = 0;
+
+ PVR_TRACE(("PVRSRVDriverProbe (pDevice=%p)", pDevice));
+
+#if defined(SUPPORT_DRM)
+#if defined(LDM_PLATFORM)
+ result = drm_platform_init(&sPVRDRMDriver, pDevice);
+#endif
+#if defined(LDM_PCI)
+ result = drm_get_pci_dev(pDevice, pID, &sPVRDRMDriver);
+#endif
+#else /* defined(SUPPORT_DRM) */
+ result = PVRSRVSystemInit(pDevice);
+#endif /* defined(SUPPORT_DRM) */
+ bDriverProbeSucceeded = (result == 0);
+ return result;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverRemove
+
+ @Description
+
+ This call is the opposite of the probe call; it is called when the device is
+ being removed from the driver's control.
+
+ @input pDevice - the device for which driver detachment is happening
+
+ @Return 0, or no return value at all, depending on the device type.
+
+*****************************************************************************/
+#if defined (LDM_PLATFORM)
+static int PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+#if defined(LDM_PCI)
+static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+{
+ PVR_TRACE(("PVRSRVDriverRemove (pDevice=%p)", pDevice));
+
+#if defined(SUPPORT_DRM)
+#if defined(LDM_PLATFORM)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+ drm_platform_exit(&sPVRDRMDriver, pDevice);
+#else
+ drm_put_dev(platform_get_drvdata(pDevice));
+#endif
+#endif /* defined(LDM_PLATFORM) */
+#if defined(LDM_PCI)
+ drm_put_dev(pci_get_drvdata(pDevice));
+#endif
+#else /* defined(SUPPORT_DRM) */
+ PVRSRVSystemDeInit();
+#endif /* defined(SUPPORT_DRM) */
+#if defined(LDM_PLATFORM)
+ return 0;
+#endif
+}
+
+static struct mutex gsPMMutex;
+static IMG_BOOL bDriverIsSuspended;
+static IMG_BOOL bDriverIsShutdown;
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverShutdown
+
+ @Description
+
+ Suspend device operation for system shutdown. This is called as part of the
+ system halt/reboot process. The driver is put into a quiescent state by
+ setting the power state to D3.
+
+ @input pDevice - the device for which shutdown is requested
+
+ @Return nothing
+
+*****************************************************************************/
+static void PVRSRVDriverShutdown(LDM_DEV *pDevice)
+{
+ PVR_TRACE(("PVRSRVDriverShutdown (pDevice=%p)", pDevice));
+
+ mutex_lock(&gsPMMutex);
+
+ if (!bDriverIsShutdown && !bDriverIsSuspended)
+ {
+ /*
+ * Take the bridge mutex, and never release it, to stop
+ * processes trying to use the driver after it has been
+ * shutdown.
+ */
+ OSAcquireBridgeLock();
+
+ (void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_OFF, IMG_TRUE);
+ }
+
+ bDriverIsShutdown = IMG_TRUE;
+
+ /* The bridge mutex is held on exit */
+ mutex_unlock(&gsPMMutex);
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverSuspend
+
+ @Description
+
+ Suspend device operation.
+
+ @input pDevice - the device for which resume is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+static int PVRSRVDriverSuspend(struct device *pDevice)
+{
+ int res = 0;
+
+ PVR_TRACE(( "PVRSRVDriverSuspend (pDevice=%p)", pDevice));
+
+ mutex_lock(&gsPMMutex);
+
+ if (!bDriverIsSuspended && !bDriverIsShutdown)
+ {
+ OSAcquireBridgeLock();
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_OFF, IMG_TRUE) == PVRSRV_OK)
+ {
+ /* The bridge mutex will be held until we resume */
+ bDriverIsSuspended = IMG_TRUE;
+ }
+ else
+ {
+ OSReleaseBridgeLock();
+ res = -EINVAL;
+ }
+ }
+
+ mutex_unlock(&gsPMMutex);
+
+ return res;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverResume
+
+ @Description
+
+ Resume device operation.
+
+ @input pDevice - the device for which resume is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+static int PVRSRVDriverResume(struct device *pDevice)
+{
+ int res = 0;
+
+ PVR_TRACE(("PVRSRVDriverResume (pDevice=%p)", pDevice));
+
+ mutex_lock(&gsPMMutex);
+
+ if (bDriverIsSuspended && !bDriverIsShutdown)
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_ON, IMG_TRUE) == PVRSRV_OK)
+ {
+ bDriverIsSuspended = IMG_FALSE;
+ OSReleaseBridgeLock();
+ }
+ else
+ {
+ /* The bridge mutex is not released on failure */
+ res = -EINVAL;
+ }
+ }
+
+ mutex_unlock(&gsPMMutex);
+
+ return res;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVOpen
+
+ @Description
+
+ Open the PVR services node.
+
+ @input pInode - the inode for the file being openeded.
+ @input dev - the DRM device corresponding to this driver.
+
+ @input pFile - the file handle data for the actual file being opened
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(SUPPORT_DRM)
+int PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static int PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ int iRet = -ENOMEM;
+ PVRSRV_ERROR eError;
+
+ if (!try_module_get(THIS_MODULE))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Failed to get module"));
+ return iRet;
+ }
+
+ OSAcquireBridgeLock();
+
+ psPrivateData = OSAllocMem(sizeof(PVRSRV_FILE_PRIVATE_DATA));
+
+ if(psPrivateData == IMG_NULL)
+ goto err_unlock;
+
+ /*
+ 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 it's connection
+ */
+ eError = PVRSRVConnectionConnect(&psPrivateData->pvConnectionData, (IMG_PVOID) pFile);
+ if (eError != PVRSRV_OK)
+ {
+ OSFreeMem(psPrivateData);
+ goto err_unlock;
+ }
+
+#if defined(PVR_SECURE_FD_EXPORT)
+ psPrivateData->hKernelMemInfo = NULL;
+#endif
+#if defined(SUPPORT_DRM_AUTH_IMPORT)
+ psPrivateData->uPID = OSGetCurrentProcessIDKM();
+ list_add_tail(&psPrivateData->sDRMAuthListItem, &sDRMAuthListHead);
+#endif
+ PRIVATE_DATA(pFile) = psPrivateData;
+ OSReleaseBridgeLock();
+ return 0;
+
+err_unlock:
+ OSReleaseBridgeLock();
+ module_put(THIS_MODULE);
+ return iRet;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVRelease
+
+ @Description
+
+ Release access the PVR services node - called when a file is closed, whether
+ at exit or using close(2) system call.
+
+ @input pInode - the inode for the file being released
+ @input pvPrivData - driver private data
+
+ @input pFile - the file handle data for the actual file being released
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(SUPPORT_DRM)
+void PVRSRVRelease(void *pvPrivData)
+#else
+static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+
+ OSAcquireBridgeLock();
+
+#if defined(SUPPORT_DRM)
+ psPrivateData = (PVRSRV_FILE_PRIVATE_DATA *)pvPrivData;
+#else
+ psPrivateData = PRIVATE_DATA(pFile);
+#endif
+ if (psPrivateData != IMG_NULL)
+ {
+#if defined(SUPPORT_DRM_AUTH_IMPORT)
+ list_del(&psPrivateData->sDRMAuthListItem);
+#endif
+ PVRSRVConnectionDisconnect(psPrivateData->pvConnectionData);
+
+ OSFreeMem(psPrivateData);
+
+#if !defined(SUPPORT_DRM)
+ PRIVATE_DATA(pFile) = IMG_NULL;
+#endif
+ }
+
+ OSReleaseBridgeLock();
+ module_put(THIS_MODULE);
+#if defined(SUPPORT_DRM)
+ return;
+#else
+ return 0;
+#endif
+}
+
+#if defined(SUPPORT_DRM)
+CONNECTION_DATA *LinuxConnectionFromFile(struct drm_file *pFile)
+#else
+CONNECTION_DATA *LinuxConnectionFromFile(struct file *pFile)
+#endif
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ return psPrivateData->pvConnectionData;
+}
+
+struct file *LinuxFileFromEnvConnection(ENV_CONNECTION_DATA *psEnvConnection)
+{
+ PVR_ASSERT(psEnvConnection != NULL);
+
+#if defined(SUPPORT_DRM)
+ return psEnvConnection->psFile->filp;
+#else
+ return psEnvConnection->psFile;
+#endif
+}
+
+#if defined(SUPPORT_DRM_AUTH_IMPORT)
+static IMG_BOOL PVRDRMCheckAuthentication(struct drm_file *pFile, IMG_PID uPID)
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+
+ BUG_ON(!mutex_is_locked(&gPVRSRVLock));
+
+ list_for_each_entry(psPrivateData, &sDRMAuthListHead, sDRMAuthListItem)
+ {
+ if (uPID == psPrivateData->uPID)
+ {
+ ENV_CONNECTION_DATA *psEnvConnection = PVRSRVConnectionPrivateData(psPrivateData->pvConnectionData);
+
+ if (psEnvConnection != IMG_NULL && pFile->master == psEnvConnection->psFile->master)
+ {
+ if (psEnvConnection->psFile->authenticated)
+ {
+ return IMG_TRUE;
+ }
+ }
+ }
+ }
+
+ return IMG_FALSE;
+}
+
+PVRSRV_ERROR OSCheckAuthentication(CONNECTION_DATA *psConnection, IMG_UINT32 ui32Level)
+{
+ ENV_CONNECTION_DATA *psEnvConnection;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ IMG_BOOL bAuthenticated = IMG_FALSE;
+
+ if (ui32Level == 0)
+ {
+ return PVRSRV_OK;
+ }
+
+ psEnvConnection = PVRSRVConnectionPrivateData(psConnection);
+ if (psEnvConnection == IMG_NULL)
+ {
+ return PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
+ }
+
+ bAuthenticated |= psEnvConnection->bAuthenticated;
+ bAuthenticated |= psEnvConnection->psFile->authenticated;
+ if (bAuthenticated)
+ {
+ goto check_auth_exit;
+ }
+
+ psPrivateData = PRIVATE_DATA(psEnvConnection->psFile);
+
+ /*
+ * If our connection was not authenticated, see if we have another
+ * one that is.
+ */
+ bAuthenticated = PVRDRMCheckAuthentication(psEnvConnection->psFile, psPrivateData->uPID);
+
+check_auth_exit:
+ if (!bAuthenticated)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: PVR Services Connection not authenticated", __FUNCTION__));
+ return PVRSRV_ERROR_NOT_AUTHENTICATED;
+ }
+
+ psEnvConnection->bAuthenticated = bAuthenticated;
+
+ return PVRSRV_OK;
+}
+#endif /* defined(SUPPORT_DRM_AUTH_IMPORT) */
+
+/*!
+******************************************************************************
+
+ @Function PVRCore_Init
+
+ @Description
+
+ Insert the driver into the kernel.
+
+ Readable and/or writable debugfs entries under /sys/kernel/debug/pvr are
+ created with PVRDebugFSCreateEntry(). These can be read at runtime to get
+ information about the device (eg. 'cat /sys/kernel/debug/pvr/nodes')
+
+ __init places the function in a special memory section that the kernel frees
+ once the function has been run. Refer also to module_init() macro call below.
+
+ @input none
+
+ @Return none
+
+*****************************************************************************/
+
+
+PVRSRV_ERROR LinuxBridgeInit(void);
+void LinuxBridgeDeInit(void);
+
+static int __init PVRCore_Init(void)
+{
+ int error;
+#if defined(PVRSRV_ENABLE_PROCESS_STATS) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ PVRSRV_ERROR eError;
+#endif
+#if !defined(SUPPORT_DRM)
+ struct device *psDev;
+#endif
+
+ /*
+ * Must come before attempting to print anything via Services.
+ * For DRM, the initialisation will already have been done.
+ */
+ PVRDPFInit();
+
+ PVR_TRACE(("PVRCore_Init"));
+
+ //zxl:print gpu version on boot time
+ printk("PVR_K: sys.gpvr.version=%s\n",RKVERSION);
+
+#if defined(SUPPORT_DRM)
+#if defined(PDUMP)
+ error = dbgdrv_init();
+ if (error != 0)
+ {
+ return error;
+ }
+#endif
+#endif
+
+ mutex_init(&gsPMMutex);
+
+ mutex_init(&gPVRSRVLock);
+
+ error = PVRDebugFSInit();
+ if (error != 0)
+ {
+ goto dbgdrv_cleanup;
+ }
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ eError = PVRSRVStatsInitialise();
+ if (eError != PVRSRV_OK)
+ {
+ error = -ENOMEM;
+
+ goto debugfs_deinit;
+ }
+#endif
+
+ if (PVROSFuncInit() != PVRSRV_OK)
+ {
+ error = -ENOMEM;
+ goto init_failed;
+ }
+
+ LinuxBridgeInit();
+
+ PVRMMapInit();
+
+#if defined(LDM_PLATFORM)
+ if ((error = platform_driver_register(&powervr_driver)) != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform driver (%d)", error));
+
+ goto init_failed;
+ }
+
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+ error = platform_device_register(&powervr_device);
+#else
+ gpsPVRLDMDev = platform_device_register_full(&powervr_device_info);
+ error = IS_ERR(gpsPVRLDMDev) ? PTR_ERR(gpsPVRLDMDev) : 0;
+#endif
+ if (error != 0)
+ {
+ gpsPVRLDMDev = NULL;
+ platform_driver_unregister(&powervr_driver);
+
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform device (%d)", error));
+
+ goto init_failed;
+ }
+#endif /* defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) */
+#endif /* defined(LDM_PLATFORM) */
+
+#if defined(LDM_PCI)
+#if defined(SUPPORT_DRM)
+ error = drm_pci_init(&sPVRDRMDriver, &powervr_driver);
+#else
+ error = pci_register_driver(&powervr_driver);
+#endif
+ if (error != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error));
+
+ goto init_failed;
+ }
+#endif /* LDM_PCI */
+
+ /* Check that the driver probe function was called */
+ if (!bDriverProbeSucceeded)
+ {
+ PVR_TRACE(("PVRCore_Init: PVRSRVDriverProbe has not been called or did not succeed - check that hardware is detected"));
+ goto init_failed;
+ }
+
+#if !defined(SUPPORT_DRM)
+ AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
+
+ if (AssignedMajorNumber <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to get major number"));
+
+ error = -EBUSY;
+ goto sys_deinit;
+ }
+
+ PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
+
+ /*
+ * This code facilitates automatic device node creation on platforms
+ * with udev (or similar).
+ */
+ psPvrClass = class_create(THIS_MODULE, "pvr");
+
+ if (IS_ERR(psPvrClass))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create class (%ld)", PTR_ERR(psPvrClass)));
+ error = -EBUSY;
+ goto unregister_device;
+ }
+
+ psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
+ NULL, DEVNAME);
+ if (IS_ERR(psDev))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create device (%ld)", PTR_ERR(psDev)));
+ error = -EBUSY;
+ goto destroy_class;
+ }
+#endif /* !defined(SUPPORT_DRM) */
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ eError = pvr_sync_init();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create sync (%d)", eError));
+ error = -EBUSY;
+ goto destroy_class;
+
+ }
+#endif
+
+ error = PVRDebugCreateDebugFSEntries();
+ if (error != 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRCore_Init: failed to create default debugfs entries (%d)", error));
+ }
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+ error = PVRGpuTraceInit();
+ if (error != 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRCore_Init: failed to initialise PVR GPU Tracing (%d)", error));
+ }
+#endif
+
+ return 0;
+
+#if !defined(SUPPORT_DRM)
+destroy_class:
+ class_destroy(psPvrClass);
+unregister_device:
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME);
+sys_deinit:
+#if defined(LDM_PCI)
+#if defined(SUPPORT_DRM)
+ drm_pci_exit(&sPVRDRMDriver, &powervr_driver);
+#else
+ pci_unregister_driver(&powervr_driver);
+#endif
+#endif
+
+#if defined (LDM_PLATFORM)
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+ platform_device_unregister(&powervr_device);
+#else
+ PVR_ASSERT(gpsPVRLDMDev != NULL);
+ platform_device_unregister(gpsPVRLDMDev);
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)) */
+#endif /* defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) */
+ platform_driver_unregister(&powervr_driver);
+#endif /* defined (LDM_PLATFORM) */
+#endif /* !defined(SUPPORT_DRM) */
+
+init_failed:
+ PVRMMapCleanup();
+ LinuxBridgeDeInit();
+ PVROSFuncDeInit();
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ PVRSRVStatsDestroy();
+debugfs_deinit:
+#endif
+ PVRDebugFSDeInit();
+dbgdrv_cleanup:
+#if defined(SUPPORT_DRM)
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+#endif
+ return error;
+
+} /*PVRCore_Init*/
+
+
+/*!
+*****************************************************************************
+
+ @Function PVRCore_Cleanup
+
+ @Description
+
+ Remove the driver from the kernel.
+
+ There's no way we can get out of being unloaded other than panicking; we
+ just do everything and plough on regardless of error.
+
+ __exit places the function in a special memory section that the kernel frees
+ once the function has been run. Refer also to module_exit() macro call below.
+
+ @input none
+
+ @Return none
+
+*****************************************************************************/
+static void __exit PVRCore_Cleanup(void)
+{
+ PVR_TRACE(("PVRCore_Cleanup"));
+
+#if defined(SUPPORT_GPUTRACE_EVENTS)
+ PVRGpuTraceDeInit();
+#endif
+
+ PVRDebugRemoveDebugFSEntries();
+
+#if defined(SUPPORT_DRM_AUTH_IMPORT)
+ BUG_ON(!list_empty(&sDRMAuthListHead));
+#endif
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ pvr_sync_deinit();
+#endif
+
+#if !defined(SUPPORT_DRM)
+ device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psPvrClass);
+
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME);
+#endif
+
+#if defined(LDM_PCI)
+#if defined(SUPPORT_DRM)
+ drm_pci_exit(&sPVRDRMDriver, &powervr_driver);
+#else
+ pci_unregister_driver(&powervr_driver);
+#endif
+#endif /* defined(LDM_PCI) */
+
+#if defined (LDM_PLATFORM)
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+ platform_device_unregister(&powervr_device);
+#else
+ PVR_ASSERT(gpsPVRLDMDev != NULL);
+ platform_device_unregister(gpsPVRLDMDev);
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)) */
+#endif /* defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) */
+ platform_driver_unregister(&powervr_driver);
+#endif /* defined (LDM_PLATFORM) */
+
+ PVRMMapCleanup();
+
+ LinuxBridgeDeInit();
+
+ PVROSFuncDeInit();
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+ PVRSRVStatsDestroy();
+#endif
+ PVRDebugFSDeInit();
+
+#if defined(SUPPORT_DRM)
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+#endif
+ PVR_TRACE(("PVRCore_Cleanup: unloading"));
+}
+
+/*
+ * These macro calls define the initialisation and removal functions of the
+ * driver. Although they are prefixed `module_', they apply when compiling
+ * statically as well; in both cases they define the function the kernel will
+ * run to start/stop the driver.
+*/
+module_init(PVRCore_Init);
+module_exit(PVRCore_Cleanup);
diff --git a/drivers/gpu/rogue/services/server/env/linux/osconnection_server.c b/drivers/gpu/rogue/services/server/env/linux/osconnection_server.c
new file mode 100755
index 000000000000..7239503f0e29
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/osconnection_server.c
@@ -0,0 +1,132 @@
+/*************************************************************************/ /*!
+@File
+@Title Linux specific per process data functions
+@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 "connection_server.h"
+#include "osconnection_server.h"
+
+#include "env_connection.h"
+#include "allocmem.h"
+#include "pvr_debug.h"
+
+#if defined (SUPPORT_ION)
+#include <linux/err.h>
+#include PVR_ANDROID_ION_HEADER
+
+/*
+ The ion device (the base object for all requests)
+ gets created by the system and we acquire it via
+ linux specific functions provided by the system layer
+*/
+#include "ion_sys.h"
+#endif
+
+PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateData, IMG_PVOID pvOSData)
+{
+ ENV_CONNECTION_DATA *psEnvConnection;
+#if defined(SUPPORT_ION)
+ ENV_ION_CONNECTION_DATA *psIonConnection;
+#endif
+
+ *phOsPrivateData = OSAllocMem(sizeof(ENV_CONNECTION_DATA));
+
+ if (*phOsPrivateData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed", __FUNCTION__));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psEnvConnection = (ENV_CONNECTION_DATA *)*phOsPrivateData;
+ OSMemSet(psEnvConnection, 0, sizeof(*psEnvConnection));
+
+ /* Save the pointer to our struct file */
+ psEnvConnection->psFile = pvOSData;
+
+#if defined(SUPPORT_ION)
+ psIonConnection = (ENV_ION_CONNECTION_DATA *)OSAllocMem(sizeof(ENV_ION_CONNECTION_DATA));
+ if (psIonConnection == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed", __FUNCTION__));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psIonConnection, 0, sizeof(*psIonConnection));
+ psEnvConnection->psIonData = psIonConnection;
+ /*
+ We can have more then one connection per process so we need more then
+ the PID to have a unique name
+ */
+ psEnvConnection->psIonData->psIonDev = IonDevAcquire();
+ OSSNPrintf(psEnvConnection->psIonData->azIonClientName, ION_CLIENT_NAME_SIZE, "pvr_ion_client-%p-%d", *phOsPrivateData, OSGetCurrentProcessIDKM());
+ psEnvConnection->psIonData->psIonClient =
+ ion_client_create(psEnvConnection->psIonData->psIonDev,
+ psEnvConnection->psIonData->azIonClientName);
+
+ if (IS_ERR_OR_NULL(psEnvConnection->psIonData->psIonClient))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSConnectionPrivateDataInit: Couldn't create "
+ "ion client for per connection data"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ psEnvConnection->psIonData->ui32IonClientRefCount = 1;
+#endif /* SUPPORT_ION */
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSConnectionPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+ ENV_CONNECTION_DATA *psEnvConnection;
+
+ if (hOsPrivateData == IMG_NULL)
+ {
+ return PVRSRV_OK;
+ }
+
+ psEnvConnection = hOsPrivateData;
+
+#if defined(SUPPORT_ION)
+ EnvDataIonClientRelease(psEnvConnection->psIonData);
+#endif
+
+ OSFreeMem(hOsPrivateData);
+ /*not nulling pointer, copy on stack*/
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/osfunc.c b/drivers/gpu/rogue/services/server/env/linux/osfunc.c
new file mode 100644
index 000000000000..66455008cd9e
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/osfunc.c
@@ -0,0 +1,2048 @@
+/*************************************************************************/ /*!
+@File
+@Title Environment related functions
+@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 <asm/io.h>
+#include <asm/page.h>
+#include <asm/div64.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/genalloc.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <asm/tlbflush.h>
+#include <asm/page.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || \
+ defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) || \
+ defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || \
+ defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) || \
+ defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+#include <linux/kthread.h>
+#include <asm/atomic.h>
+
+#include "osfunc.h"
+#include "img_types.h"
+#include "mm.h"
+#include "allocmem.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "pvr_debugfs.h"
+#include "event.h"
+#include "linkage.h"
+#include "pvr_uaccess.h"
+#include "pvr_debug.h"
+#include "driverlock.h"
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#include "process_stats.h"
+#endif
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+#include "syscommon.h"
+#endif
+
+#if defined(EMULATOR) || defined(VIRTUAL_PLATFORM)
+#define EVENT_OBJECT_TIMEOUT_MS (2000)
+#else
+#define EVENT_OBJECT_TIMEOUT_MS (100)
+#endif /* EMULATOR */
+
+ENV_DATA *gpsEnvData = IMG_NULL;
+
+struct task_struct *OSGetBridgeLockOwner(void);
+
+/*
+ Create a 4MB pool which should be more then enough in most cases,
+ if it becomes full then the calling code will fall back to
+ vm_map_ram.
+*/
+
+#if defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0))
+#define POOL_SIZE (4*1024*1024)
+static struct gen_pool *pvrsrv_pool_writecombine = NULL;
+static char *pool_start;
+
+static void deinit_pvr_pool(void)
+{
+ gen_pool_destroy(pvrsrv_pool_writecombine);
+ pvrsrv_pool_writecombine = NULL;
+ vfree(pool_start);
+ pool_start = NULL;
+}
+
+static void init_pvr_pool(void)
+{
+ struct vm_struct *tmp_area;
+ int ret = -1;
+
+ /* Create the pool to allocate vm space from */
+ pvrsrv_pool_writecombine = gen_pool_create(PAGE_SHIFT, -1);
+ if (!pvrsrv_pool_writecombine) {
+ printk(KERN_ERR "%s: create pvrsrv_pool failed\n", __func__);
+ return;
+ }
+
+ /* Reserve space in the vmalloc vm range */
+ tmp_area = __get_vm_area(POOL_SIZE, VM_ALLOC,
+ VMALLOC_START, VMALLOC_END);
+ if (!tmp_area) {
+ printk(KERN_ERR "%s: __get_vm_area failed\n", __func__);
+ gen_pool_destroy(pvrsrv_pool_writecombine);
+ pvrsrv_pool_writecombine = NULL;
+ return;
+ }
+
+ pool_start = tmp_area->addr;
+
+ if (!pool_start) {
+ printk(KERN_ERR "%s:No vm space to create POOL\n",
+ __func__);
+ gen_pool_destroy(pvrsrv_pool_writecombine);
+ pvrsrv_pool_writecombine = NULL;
+ return;
+ } else {
+ /* Add our reserved space into the pool */
+ ret = gen_pool_add(pvrsrv_pool_writecombine,
+ (unsigned long) pool_start, POOL_SIZE, -1);
+ if (ret) {
+ printk(KERN_ERR "%s:could not remainder pool\n",
+ __func__);
+ deinit_pvr_pool();
+ return;
+ }
+ }
+ return;
+}
+
+static inline IMG_BOOL vmap_from_pool(void *pvCPUVAddr)
+{
+ IMG_CHAR *pcTmp = pvCPUVAddr;
+ if ((pcTmp >= pool_start) && (pcTmp <= (pool_start + POOL_SIZE)))
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+#endif /* defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0))*/
+
+PVRSRV_ERROR OSMMUPxAlloc(PVRSRV_DEVICE_NODE *psDevNode, IMG_SIZE_T uiSize,
+ Px_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr)
+{
+ IMG_CPU_PHYADDR sCpuPAddr;
+ struct page *psPage;
+
+ /*
+ Check that we're not doing multiple pages worth of
+ import as it's not supported a.t.m.
+ */
+ PVR_ASSERT(uiSize == PAGE_SIZE);
+
+ psPage = alloc_page(GFP_KERNEL);
+ if (psPage == NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+#if defined (CONFIG_X86)
+ {
+ IMG_PVOID pvPageVAddr = page_address(psPage);
+ int ret;
+ ret = set_memory_wc((unsigned long)pvPageVAddr, 1);
+
+ if (ret)
+ {
+ __free_page(psPage);
+ return PVRSRV_ERROR_UNABLE_TO_SET_CACHE_MODE;
+ }
+ }
+#endif
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined (CONFIG_METAG)
+ {
+ IMG_CPU_PHYADDR sCPUPhysAddrStart, sCPUPhysAddrEnd;
+ IMG_PVOID pvPageVAddr = kmap(psPage);
+
+ sCPUPhysAddrStart.uiAddr = page_to_phys(psPage);
+ sCPUPhysAddrEnd.uiAddr = sCPUPhysAddrStart.uiAddr + PAGE_SIZE;
+
+ OSInvalidateCPUCacheRangeKM(pvPageVAddr,
+ pvPageVAddr + PAGE_SIZE,
+ sCPUPhysAddrStart,
+ sCPUPhysAddrEnd);
+ }
+#endif
+
+ psMemHandle->u.pvHandle = psPage;
+ sCpuPAddr.uiAddr = page_to_phys(psPage);
+
+ PhysHeapCpuPAddrToDevPAddr(psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL], psDevPAddr, &sCpuPAddr);
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA, PAGE_SIZE);
+#else
+ PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA,
+ psPage,
+ sCpuPAddr,
+ PAGE_SIZE,
+ IMG_NULL);
+#endif
+#endif
+
+ return PVRSRV_OK;
+}
+
+void OSMMUPxFree(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle)
+{
+ struct page *psPage = (struct page*) psMemHandle->u.pvHandle;
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA, PAGE_SIZE);
+#else
+ PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA, (IMG_UINT64)(IMG_UINTPTR_T)psPage);
+#endif
+#endif
+
+#if defined (CONFIG_X86)
+ {
+ IMG_PVOID pvPageVAddr;
+ int ret;
+
+ pvPageVAddr = page_address(psPage);
+ ret = set_memory_wb((unsigned long) pvPageVAddr, 1);
+ if (ret)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to reset page attribute", __FUNCTION__));
+ }
+ }
+#endif
+ __free_page(psPage);
+}
+
+PVRSRV_ERROR OSMMUPxMap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle,
+ IMG_SIZE_T uiSize, IMG_DEV_PHYADDR *psDevPAddr,
+ void **pvPtr)
+{
+ struct page **ppsPage = (struct page **) &psMemHandle->u.pvHandle;
+ IMG_UINTPTR_T uiCPUVAddr;
+ pgprot_t prot = PAGE_KERNEL;
+ PVR_UNREFERENCED_PARAMETER(psDevNode);
+
+ prot = pgprot_writecombine(prot);
+
+#if defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0))
+ uiCPUVAddr = gen_pool_alloc(pvrsrv_pool_writecombine, PAGE_SIZE);
+
+ if (uiCPUVAddr) {
+ int ret = 0;
+ struct vm_struct tmp_area;
+
+ /* vmalloc and friends expect a guard page so we need to take that into account */
+ tmp_area.addr = (void *)uiCPUVAddr;
+ tmp_area.size = 2 * PAGE_SIZE;
+ ret = map_vm_area(&tmp_area, prot, &ppsPage);
+ if (ret) {
+ gen_pool_free(pvrsrv_pool_writecombine, uiCPUVAddr, PAGE_SIZE);
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Cannot map page to pool",
+ __func__));
+ /* Failed the pool alloc so fall back to the vm_map path */
+ uiCPUVAddr = 0;
+ }
+ }
+
+ /* Not else as if the poll alloc fails it resets uiCPUVAddr to 0 */
+ if (uiCPUVAddr == 0)
+#endif /* defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0)) */
+ {
+ uiCPUVAddr = (IMG_UINTPTR_T) vm_map_ram(ppsPage,
+ 1,
+ -1,
+ prot);
+ }
+
+ /* Check that one of the above methods got us an address */
+ if (((void *)uiCPUVAddr) == IMG_NULL)
+ {
+ return PVRSRV_ERROR_FAILED_TO_MAP_KERNELVIRTUAL;
+ }
+
+ *pvPtr = (void *) ((uiCPUVAddr & (~OSGetPageMask())) |
+ ((IMG_UINTPTR_T) (psDevPAddr->uiAddr & OSGetPageMask())));
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Mapping is done a page at a time */
+ PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA, PAGE_SIZE);
+#else
+ {
+ IMG_CPU_PHYADDR sCpuPAddr;
+ sCpuPAddr.uiAddr = 0;
+
+ PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA,
+ (void *)uiCPUVAddr,
+ sCpuPAddr,
+ uiSize,
+ IMG_NULL);
+ }
+#endif
+#endif
+
+ return PVRSRV_OK;
+}
+
+void OSMMUPxUnmap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle, void *pvPtr)
+{
+ PVR_UNREFERENCED_PARAMETER(psDevNode);
+ PVR_UNREFERENCED_PARAMETER(psMemHandle);
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Mapping is done a page at a time */
+ PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA, PAGE_SIZE);
+#else
+ PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA, (IMG_UINT64)(IMG_UINTPTR_T)pvPtr);
+#endif
+#endif
+
+#if defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0))
+ if (vmap_from_pool(pvPtr))
+ {
+ unsigned long addr = (unsigned long)pvPtr;
+
+ /* Flush the data cache */
+ flush_cache_vunmap(addr, addr + PAGE_SIZE);
+ /* Unmap the page */
+ unmap_kernel_range_noflush(addr, PAGE_SIZE);
+ /* Flush the TLB */
+ __flush_tlb_single(addr);
+ /* Free the page back to the pool */
+ gen_pool_free(pvrsrv_pool_writecombine, addr, PAGE_SIZE);
+ }
+ else
+#endif /* defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0)) */
+ {
+ vm_unmap_ram(pvPtr, 1);
+ }
+}
+
+/*************************************************************************/ /*!
+@Function OSMemCopy
+@Description Copies memory around
+@Input pvDst Pointer to dst
+@Output pvSrc Pointer to src
+@Input ui32Size Bytes to copy
+*/ /**************************************************************************/
+void OSMemCopy(void *pvDst, const void *pvSrc, IMG_SIZE_T ui32Size)
+{
+ memcpy(pvDst, pvSrc, ui32Size);
+}
+
+
+/*************************************************************************/ /*!
+@Function OSMemSet
+@Description Function that does the same as the C memset() functions
+@Modified *pvDest Pointer to start of buffer to be set
+@Input ui8Value Value to set each byte to
+@Input ui32Size Number of bytes to set
+*/ /**************************************************************************/
+void OSMemSet(void *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size)
+{
+ memset(pvDest, (char) ui8Value, (size_t) ui32Size);
+}
+
+IMG_INT OSMemCmp(void *pvBufA, void *pvBufB, IMG_SIZE_T uiLen)
+{
+ return (IMG_INT) memcmp(pvBufA, pvBufB, uiLen);
+}
+
+/*************************************************************************/ /*!
+@Function OSStringNCopy
+@Description strcpy
+*/ /**************************************************************************/
+IMG_CHAR *OSStringNCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, IMG_SIZE_T uSize)
+{
+ return strncpy(pszDest, pszSrc, uSize);
+}
+
+/*************************************************************************/ /*!
+@Function OSSNPrintf
+@Description snprintf
+@Return the chars written or -1 on error
+*/ /**************************************************************************/
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T ui32Size, const IMG_CHAR *pszFormat, ...)
+{
+ va_list argList;
+ IMG_INT32 iCount;
+
+ va_start(argList, pszFormat);
+ iCount = vsnprintf(pStr, (size_t)ui32Size, pszFormat, argList);
+ va_end(argList);
+
+ return iCount;
+}
+
+IMG_SIZE_T OSStringLength(const IMG_CHAR *pStr)
+{
+ return strlen(pStr);
+}
+
+IMG_SIZE_T OSStringNLength(const IMG_CHAR *pStr, IMG_SIZE_T uiCount)
+{
+ return strnlen(pStr, uiCount);
+}
+
+IMG_INT32 OSStringCompare(const IMG_CHAR *pStr1, const IMG_CHAR *pStr2)
+{
+ return strcmp(pStr1, pStr2);
+}
+
+/*************************************************************************/ /*!
+@Function OSInitEnvData
+@Description Allocates space for env specific data
+@Input ppvEnvSpecificData Pointer to pointer in which to return
+ allocated data.
+@Input ui32MMUMode MMU mode.
+@Return PVRSRV_OK
+*/ /**************************************************************************/
+PVRSRV_ERROR OSInitEnvData(void)
+{
+ /* allocate env specific data */
+ gpsEnvData = OSAllocMem(sizeof(ENV_DATA));
+ if (gpsEnvData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ gpsEnvData->pvBridgeData = OSAllocMem(PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE);
+ if (gpsEnvData->pvBridgeData == IMG_NULL)
+ {
+ OSFreeMem(gpsEnvData);
+ /*not nulling pointer, out of scope*/
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+#if defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0))
+ /*
+ vm_ram_ram works with 2MB blocks to avoid excessive
+ TLB flushing but our allocations are always small and have
+ a long lifetime which then leads to fragmentation of vmalloc space.
+ To workaround this we create a virtual address pool in the vmap range
+ for mapping our page tables into so we don't fragment vmalloc space.
+ */
+ if (!pvrsrv_pool_writecombine)
+ {
+ init_pvr_pool();
+ }
+#endif /* defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0)) */
+
+ return PVRSRV_OK;
+}
+
+
+/*************************************************************************/ /*!
+@Function OSDeInitEnvData
+@Description frees env specific data memory
+@Input pvEnvSpecificData Pointer to private structure
+@Return PVRSRV_OK on success else PVRSRV_ERROR_OUT_OF_MEMORY
+*/ /**************************************************************************/
+void OSDeInitEnvData(void)
+{
+ ENV_DATA *psEnvData = gpsEnvData;
+
+#if defined(CONFIG_GENERIC_ALLOCATOR) && defined(CONFIG_X86) && (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0))
+ if (pvrsrv_pool_writecombine)
+ {
+ deinit_pvr_pool();
+ }
+#endif
+
+ OSFreeMem(psEnvData->pvBridgeData);
+ psEnvData->pvBridgeData = IMG_NULL;
+
+ OSFreeMem(psEnvData);
+}
+
+ENV_DATA *OSGetEnvData(void)
+{
+ return gpsEnvData;
+}
+
+/*************************************************************************/ /*!
+@Function OSReleaseThreadQuanta
+@Description Releases thread quanta
+*/ /**************************************************************************/
+void OSReleaseThreadQuanta(void)
+{
+ schedule();
+}
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+static inline IMG_UINT32 Clockus(void)
+{
+ return (jiffies * (1000000 / HZ));
+}
+#else
+/* Not matching/aligning this API to the Clockus() API above to avoid necessary
+ * multiplication/division operations in calling code.
+ */
+static inline IMG_UINT64 Clockns64(void)
+{
+ IMG_UINT64 timenow;
+
+ /* Kernel thread preempt protection. Some architecture implementations
+ * (ARM) of sched_clock are not preempt safe when the kernel is configured
+ * as such e.g. CONFIG_PREEMPT and others.
+ */
+ preempt_disable();
+
+ /* Using sched_clock instead of ktime_get since we need a time stamp that
+ * correlates with that shown in kernel logs and trace data not one that
+ * is a bit behind. */
+ timenow = sched_clock();
+
+ preempt_enable();
+
+ return timenow;
+}
+#endif
+
+/*************************************************************************/ /*!
+ @Function OSClockns64
+ @Description
+ This function returns the clock in nanoseconds. Unlike OSClockus,
+ OSClockus64 has a near 64-bit range
+*/ /**************************************************************************/
+IMG_UINT64 OSClockns64(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
+ return Clockns64();
+#else
+ return ((IMG_UINT64)Clockus()) * 1000ULL;
+#endif
+}
+
+/*************************************************************************/ /*!
+ @Function OSClockus64
+ @Description
+ This function returns the clock in microseconds. Unlike OSClockus,
+ OSClockus64 has a near 64-bit range
+*/ /**************************************************************************/
+IMG_UINT64 OSClockus64(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
+ IMG_UINT64 timenow = Clockns64();
+ IMG_UINT32 remainder;
+ return OSDivide64r64(timenow, 1000, &remainder);
+#else
+ return ((IMG_UINT64)Clockus());
+#endif
+}
+
+
+/*************************************************************************/ /*!
+@Function OSClockus
+@Description This function returns the clock in microseconds
+@Return clock (us)
+*/ /**************************************************************************/
+IMG_UINT32 OSClockus(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
+ return (IMG_UINT32) OSClockus64();
+#else
+ return Clockus();
+#endif
+}
+
+
+/*************************************************************************/ /*!
+@Function OSClockms
+@Description This function returns the clock in milliseconds
+@Return clock (ms)
+*/ /**************************************************************************/
+IMG_UINT32 OSClockms(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
+ IMG_UINT64 timenow = Clockns64();
+ IMG_UINT32 remainder;
+
+ return OSDivide64(timenow, 1000000, &remainder);
+#else
+ IMG_UINT64 time, j = (IMG_UINT32)jiffies;
+
+ time = j * (((1 << 16) * 1000) / HZ);
+ time >>= 16;
+
+ return (IMG_UINT32)time;
+#endif
+}
+
+
+/*
+ OSWaitus
+*/
+void OSWaitus(IMG_UINT32 ui32Timeus)
+{
+ udelay(ui32Timeus);
+}
+
+
+/*
+ OSSleepms
+*/
+void OSSleepms(IMG_UINT32 ui32Timems)
+{
+ msleep(ui32Timems);
+}
+
+
+/*************************************************************************/ /*!
+@Function OSGetCurrentProcessIDKM
+@Description Returns ID of current process (thread group)
+@Return ID of current process
+*****************************************************************************/
+IMG_PID OSGetCurrentProcessIDKM(void)
+{
+ if (in_interrupt())
+ {
+ return KERNEL_ID;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ return (IMG_PID)current->pgrp;
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ return (IMG_PID)task_tgid_nr(current);
+#else
+ return (IMG_PID)current->tgid;
+#endif
+#endif
+}
+
+/*************************************************************************/ /*!
+@Function OSGetCurrentProcessNameKM
+@Description gets name of current process
+@Return process name
+*****************************************************************************/
+IMG_CHAR *OSGetCurrentProcessNameKM(void)
+{
+ return current->comm;
+}
+
+/*************************************************************************/ /*!
+@Function OSGetCurrentThreadIDKM
+@Description Returns ID for current thread
+@Return ID of current thread
+*****************************************************************************/
+IMG_UINTPTR_T OSGetCurrentThreadIDKM(void)
+{
+ if (in_interrupt())
+ {
+ return KERNEL_ID;
+ }
+
+ return current->pid;
+}
+
+/*************************************************************************/ /*!
+@Function OSGetPageSize
+@Description gets page size
+@Return page size
+*/ /**************************************************************************/
+IMG_SIZE_T OSGetPageSize(void)
+{
+ return PAGE_SIZE;
+}
+
+/*************************************************************************/ /*!
+@Function OSGetPageShift
+@Description gets page size
+@Return page size
+*/ /**************************************************************************/
+IMG_SIZE_T OSGetPageShift(void)
+{
+ return PAGE_SHIFT;
+}
+
+/*************************************************************************/ /*!
+@Function OSGetPageMask
+@Description gets page mask
+@Return page size
+*/ /**************************************************************************/
+IMG_SIZE_T OSGetPageMask(void)
+{
+ return (OSGetPageSize()-1);
+}
+
+#if !defined (SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+typedef struct _LISR_DATA_ {
+ PFN_LISR pfnLISR;
+ void *pvData;
+ IMG_UINT32 ui32IRQ;
+} LISR_DATA;
+
+/*
+ DeviceISRWrapper
+*/
+static irqreturn_t DeviceISRWrapper(int irq, void *dev_id)
+{
+ LISR_DATA *psLISRData = (LISR_DATA *) dev_id;
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+ bStatus = psLISRData->pfnLISR(psLISRData->pvData);
+
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+}
+#endif
+
+/*
+ OSInstallDeviceLISR
+*/
+PVRSRV_ERROR OSInstallDeviceLISR(PVRSRV_DEVICE_CONFIG *psDevConfig,
+ IMG_HANDLE *hLISRData,
+ PFN_LISR pfnLISR,
+ void *pvData)
+{
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+ return SysInstallDeviceLISR(psDevConfig->ui32IRQ,
+ psDevConfig->pszName,
+ pfnLISR,
+ pvData,
+ hLISRData);
+#else
+ LISR_DATA *psLISRData;
+ unsigned long flags = 0;
+
+ psLISRData = kmalloc(sizeof(LISR_DATA), GFP_KERNEL);
+
+ psLISRData->pfnLISR = pfnLISR;
+ psLISRData->pvData = pvData;
+ psLISRData->ui32IRQ = psDevConfig->ui32IRQ;
+
+ if (psDevConfig->bIRQIsShared)
+ {
+ flags |= IRQF_SHARED;
+ }
+
+ if (psDevConfig->eIRQActiveLevel == PVRSRV_DEVICE_IRQ_ACTIVE_HIGH)
+ {
+ flags |= IRQF_TRIGGER_HIGH;
+ }
+ else if (psDevConfig->eIRQActiveLevel == PVRSRV_DEVICE_IRQ_ACTIVE_LOW)
+ {
+ flags |= IRQF_TRIGGER_LOW;
+ }
+
+ PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %p", psDevConfig->pszName, psDevConfig->ui32IRQ, pvData));
+
+ if(request_irq(psDevConfig->ui32IRQ, DeviceISRWrapper,
+ flags, psDevConfig->pszName, psLISRData))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", psDevConfig->ui32IRQ));
+
+ return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+ }
+
+ *hLISRData = (IMG_HANDLE) psLISRData;
+
+ return PVRSRV_OK;
+#endif
+}
+
+/*
+ OSUninstallDeviceLISR
+*/
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_HANDLE hLISRData)
+{
+#if defined (SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+ return SysUninstallDeviceLISR(hLISRData);
+#else
+ LISR_DATA *psLISRData = (LISR_DATA *) hLISRData;
+
+ PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %p", psLISRData->ui32IRQ, psLISRData->pvData));
+
+ free_irq(psLISRData->ui32IRQ, psLISRData);
+ kfree(psLISRData);
+
+ return PVRSRV_OK;
+#endif
+}
+
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+typedef struct _MISR_DATA_ {
+ struct workqueue_struct *psWorkQueue;
+ struct work_struct sMISRWork;
+ PFN_MISR pfnMISR;
+ void *hData;
+} MISR_DATA;
+
+/*
+ MISRWrapper
+*/
+static void MISRWrapper(struct work_struct *data)
+{
+ MISR_DATA *psMISRData = container_of(data, MISR_DATA, sMISRWork);
+
+ psMISRData->pfnMISR(psMISRData->hData);
+}
+
+/*
+ OSInstallMISR
+*/
+PVRSRV_ERROR OSInstallMISR(IMG_HANDLE *hMISRData, PFN_MISR pfnMISR,
+ void *hData)
+{
+ MISR_DATA *psMISRData;
+
+ psMISRData = kmalloc(sizeof(MISR_DATA), GFP_KERNEL);
+ if (psMISRData == NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psMISRData->hData = hData;
+ psMISRData->pfnMISR = pfnMISR;
+
+ PVR_TRACE(("Installing MISR with cookie %p", psMISRData));
+
+ psMISRData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue");
+
+ if (psMISRData->psWorkQueue == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: create_singlethreaded_workqueue failed"));
+ kfree(psMISRData);
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+ }
+
+ INIT_WORK(&psMISRData->sMISRWork, MISRWrapper);
+
+ *hMISRData = (IMG_HANDLE) psMISRData;
+
+ return PVRSRV_OK;
+}
+
+/*
+ OSUninstallMISR
+*/
+PVRSRV_ERROR OSUninstallMISR(IMG_HANDLE hMISRData)
+{
+ MISR_DATA *psMISRData = (MISR_DATA *) hMISRData;
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ destroy_workqueue(psMISRData->psWorkQueue);
+ kfree(psMISRData);
+
+ return PVRSRV_OK;
+}
+
+/*
+ OSScheduleMISR
+*/
+PVRSRV_ERROR OSScheduleMISR(IMG_HANDLE hMISRData)
+{
+ MISR_DATA *psMISRData = (MISR_DATA *) hMISRData;
+
+ /*
+ Note:
+
+ In the case of NO_HARDWARE we want the driver to be synchronous so
+ that we don't have to worry about waiting for previous operations
+ to complete
+ */
+#if defined(NO_HARDWARE)
+ psMISRData->pfnMISR(psMISRData->hData);
+#else
+ queue_work(psMISRData->psWorkQueue, &psMISRData->sMISRWork);
+#endif
+ return PVRSRV_OK;
+}
+#else /* defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+typedef struct _MISR_DATA_ {
+ struct work_struct sMISRWork;
+ PFN_MISR pfnMISR;
+ void *hData;
+} MISR_DATA;
+
+/*
+ MISRWrapper
+*/
+static void MISRWrapper(struct work_struct *data)
+{
+ MISR_DATA *psMISRData = container_of(data, MISR_DATA, sMISRWork);
+
+ psMISRData->pfnMISR(psMISRData->hData);
+}
+
+/*
+ OSInstallMISR
+*/
+PVRSRV_ERROR OSInstallMISR(IMG_HANDLE *hMISRData, PFN_MISR pfnMISR, void *hData)
+{
+ MISR_DATA *psMISRData;
+
+ psMISRData = kmalloc(sizeof(MISR_DATA), GFP_KERNEL);
+ if (psMISRData == NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psMISRData->hData = hData;
+ psMISRData->pfnMISR = pfnMISR;
+
+ PVR_TRACE(("Installing MISR with cookie %p", psMISRData));
+
+ INIT_WORK(&psMISRData->sMISRWork, MISRWrapper);
+
+ *hMISRData = (IMG_HANDLE) psMISRData;
+
+ return PVRSRV_OK;
+}
+
+
+/*
+ OSUninstallMISR
+*/
+PVRSRV_ERROR OSUninstallMISR(IMG_HANDLE hMISRData)
+{
+ PVR_TRACE(("Uninstalling MISR"));
+
+ flush_scheduled_work();
+
+ kfree(hMISRData);
+
+ return PVRSRV_OK;
+}
+
+/*
+ OSScheduleMISR
+*/
+PVRSRV_ERROR OSScheduleMISR(IMG_HANDLE hMISRData)
+{
+ MISR_DATA *psMISRData = hMISRData;
+#if defined(NO_HARDWARE)
+ psMISRData->pfnMISR(psMISRData->hData);
+#else
+ schedule_work(&psMISRData->sMISRWork);
+#endif
+ return PVRSRV_OK;
+}
+
+#else /* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */
+typedef struct _MISR_DATA_ {
+ struct tasklet_struct sMISRTasklet;
+ PFN_MISR pfnMISR;
+ void *hData;
+} MISR_DATA;
+
+/*
+ MISRWrapper
+*/
+static void MISRWrapper(unsigned long data)
+{
+ MISR_DATA *psMISRData = (MISR_DATA *) data;
+
+ psMISRData->pfnMISR(psMISRData->hData);
+}
+
+/*
+ OSInstallMISR
+*/
+PVRSRV_ERROR OSInstallMISR(IMG_HANDLE *hMISRData, PFN_MISR pfnMISR, void *hData)
+{
+ MISR_DATA *psMISRData;
+
+ psMISRData = kmalloc(sizeof(MISR_DATA), GFP_KERNEL);
+ if (psMISRData == NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psMISRData->hData = hData;
+ psMISRData->pfnMISR = pfnMISR;
+
+ PVR_TRACE(("Installing MISR with cookie %p", psMISRData));
+
+ tasklet_init(&psMISRData->sMISRTasklet, MISRWrapper, (unsigned long)psMISRData);
+
+ *hMISRData = (IMG_HANDLE) psMISRData;
+
+ return PVRSRV_OK;
+}
+
+/*
+ OSUninstallMISR
+*/
+PVRSRV_ERROR OSUninstallMISR(IMG_HANDLE hMISRData)
+{
+ MISR_DATA *psMISRData = (MISR_DATA *) hMISRData;
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ tasklet_kill(&psMISRData->sMISRTasklet);
+
+ return PVRSRV_OK;
+}
+
+/*
+ OSScheduleMISR
+*/
+PVRSRV_ERROR OSScheduleMISR(IMG_HANDLE hMISRData)
+{
+ MISR_DATA *psMISRData = (MISR_DATA *) hMISRData;
+
+#if defined(NO_HARDWARE)
+ psMISRData->pfnMISR(psMISRData->hData);
+#else
+ tasklet_schedule(&psMISRData->sMISRTasklet);
+#endif
+ return PVRSRV_OK;
+}
+
+#endif /* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */
+#endif /* #if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
+
+/* OS specific values for thread priority */
+const IMG_INT32 ai32OSPriorityValues[LAST_PRIORITY] = { -20, /* HIGHEST_PRIORITY */
+ -10, /* HIGH_PRIRIOTY */
+ 0, /* NORMAL_PRIORITY */
+ 9, /* LOW_PRIORITY */
+ 19, /* LOWEST_PRIORITY */
+ -22};/* NOSET_PRIORITY */
+
+typedef struct {
+ struct task_struct *kthread;
+ PFN_THREAD pfnThread;
+ void *hData;
+ OS_THREAD_LEVEL eThreadPriority;
+} OSThreadData;
+
+static int OSThreadRun(void *data)
+{
+ OSThreadData *psOSThreadData = data;
+
+ /* If i32NiceValue is acceptable, set the nice value for the new thread */
+ if (psOSThreadData->eThreadPriority != NOSET_PRIORITY &&
+ psOSThreadData->eThreadPriority < LAST_PRIORITY)
+ set_user_nice(current, ai32OSPriorityValues[psOSThreadData->eThreadPriority]);
+
+ /* Call the client's kernel thread with the client's data pointer */
+ psOSThreadData->pfnThread(psOSThreadData->hData);
+
+ /* Wait for OSThreadDestroy() to call kthread_stop() */
+ while (!kthread_should_stop())
+ {
+ schedule();
+ }
+
+ return 0;
+}
+
+PVRSRV_ERROR OSThreadCreate(IMG_HANDLE *phThread,
+ IMG_CHAR *pszThreadName,
+ PFN_THREAD pfnThread,
+ void *hData)
+{
+ /* Call OSThreadCreatePriority with an invalid nice value */
+ return OSThreadCreatePriority(phThread, pszThreadName, pfnThread, hData, NOSET_PRIORITY);
+}
+
+PVRSRV_ERROR OSThreadCreatePriority(IMG_HANDLE *phThread,
+ IMG_CHAR *pszThreadName,
+ PFN_THREAD pfnThread,
+ void *hData,
+ OS_THREAD_LEVEL eThreadPriority)
+{
+ OSThreadData *psOSThreadData;
+ PVRSRV_ERROR eError;
+
+ psOSThreadData = kmalloc(sizeof(OSThreadData), GFP_KERNEL);
+ if (psOSThreadData == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ psOSThreadData->pfnThread = pfnThread;
+ psOSThreadData->hData = hData;
+ psOSThreadData->eThreadPriority= eThreadPriority;
+ psOSThreadData->kthread = kthread_run(OSThreadRun, psOSThreadData, pszThreadName);
+
+ if (IS_ERR(psOSThreadData->kthread))
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_kthread;
+ }
+
+ *phThread = psOSThreadData;
+
+ return PVRSRV_OK;
+
+fail_kthread:
+ kfree(psOSThreadData);
+fail_alloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR OSThreadDestroy(IMG_HANDLE hThread)
+{
+ OSThreadData *psOSThreadData = hThread;
+ int ret;
+
+ /* Let the thread know we are ready for it to end and wait for it. */
+ ret = kthread_stop(psOSThreadData->kthread);
+ PVR_ASSERT(ret == 0);
+ kfree(psOSThreadData);
+
+ return PVRSRV_OK;
+}
+
+void OSPanic(void)
+{
+ BUG();
+
+#if defined(__KLOCWORK__)
+ /* Klocworks does not understand that BUG is terminal... */
+ abort();
+#endif
+}
+
+/*************************************************************************/ /*!
+@Function OSMapPhysToLin
+@Description Maps the physical memory into linear addr range
+@Input BasePAddr Physical cpu address
+@Input ui32Bytes Bytes to map
+@Input ui32CacheType Cache type
+@Return Linear addr of mapping on success, else NULL
+ */ /**************************************************************************/
+void *
+OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32MappingFlags)
+{
+ void *pvIORemapCookie;
+
+ pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(pvIORemapCookie == IMG_NULL)
+ {
+ PVR_ASSERT(0);
+ return IMG_NULL;
+ }
+
+ return pvIORemapCookie;
+}
+
+
+/*************************************************************************/ /*!
+@Function OSUnMapPhysToLin
+@Description Unmaps memory that was mapped with OSMapPhysToLin
+@Input pvLinAddr
+@Input ui32Bytes
+@Return TRUE on success, else FALSE
+*/ /**************************************************************************/
+IMG_BOOL
+OSUnMapPhysToLin(void *pvLinAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32MappingFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ IOUnmapWrapper(pvLinAddr);
+
+ return IMG_TRUE;
+}
+
+/*
+ OSReadHWReg8
+*/
+IMG_UINT8 OSReadHWReg8(IMG_PVOID pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+ return (IMG_UINT8) readb((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ return 0x4e;
+#endif
+}
+
+/*
+ OSReadHWReg16
+*/
+IMG_UINT16 OSReadHWReg16(IMG_PVOID pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+ return (IMG_UINT16) readw((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ return 0x3a4e;
+#endif
+}
+
+/*
+ OSReadHWReg32
+*/
+IMG_UINT32 OSReadHWReg32(IMG_PVOID pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+ return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ return 0x30f73a4e;
+#endif
+}
+
+
+/*
+ OSReadHWReg64
+*/
+IMG_UINT64 OSReadHWReg64(IMG_PVOID pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset)
+{
+ IMG_UINT64 ui64Result;
+
+ ui64Result = OSReadHWReg32(pvLinRegBaseAddr, ui32Offset + 4);
+ ui64Result <<= 32;
+ ui64Result |= (IMG_UINT64)OSReadHWReg32(pvLinRegBaseAddr, ui32Offset);
+
+ return ui64Result;
+}
+
+/*
+ OSReadHWRegBank
+*/
+IMG_DEVMEM_SIZE_T OSReadHWRegBank(IMG_PVOID pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8DstBuf,
+ IMG_DEVMEM_SIZE_T uiDstBufLen)
+{
+#if !defined(NO_HARDWARE)
+ IMG_DEVMEM_SIZE_T uiCounter;
+
+
+
+ for(uiCounter = 0; uiCounter < uiDstBufLen; uiCounter++) {
+ *(pui8DstBuf + uiCounter) =
+ readb(pvLinRegBaseAddr + ui32Offset + uiCounter);
+ }
+
+ return uiCounter;
+#else
+ return uiDstBufLen;
+#endif
+}
+
+/*
+ OSWriteHWReg8
+*/
+void OSWriteHWReg8(void *pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 ui8Value)
+{
+#if !defined(NO_HARDWARE)
+ writeb(ui8Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+/*
+ OSWriteHWReg16
+*/
+void OSWriteHWReg16(void *pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT16 ui16Value)
+{
+#if !defined(NO_HARDWARE)
+ writew(ui16Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+/*
+ OSWriteHWReg32
+*/
+void OSWriteHWReg32(void *pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+ writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+
+/*
+ OSWriteHWReg64
+*/
+void OSWriteHWReg64(void *pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT64 ui64Value)
+{
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32ValueLow, ui32ValueHigh;
+
+ ui32ValueLow = ui64Value & 0xffffffff;
+ ui32ValueHigh = ((IMG_UINT64) (ui64Value >> 32)) & 0xffffffff;
+
+ writel(ui32ValueLow, pvLinRegBaseAddr + ui32Offset);
+ writel(ui32ValueHigh, pvLinRegBaseAddr + ui32Offset + 4);
+#endif
+}
+
+IMG_DEVMEM_SIZE_T OSWriteHWRegBank(void *pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8SrcBuf,
+ IMG_DEVMEM_SIZE_T uiSrcBufLen)
+{
+#if !defined(NO_HARDWARE)
+ IMG_DEVMEM_SIZE_T uiCounter;
+
+
+
+ for(uiCounter = 0; uiCounter < uiSrcBufLen; uiCounter++) {
+ writeb(*(pui8SrcBuf + uiCounter),
+ pvLinRegBaseAddr + ui32Offset + uiCounter);
+ }
+
+ return uiCounter;
+#else
+ return uiSrcBufLen;
+#endif
+}
+
+#define OS_MAX_TIMERS 8
+
+/* Timer callback strucure used by OSAddTimer */
+typedef struct TIMER_CALLBACK_DATA_TAG
+{
+ IMG_BOOL bInUse;
+ PFN_TIMER_FUNC pfnTimerFunc;
+ void *pvData;
+ struct timer_list sTimer;
+ IMG_UINT32 ui32Delay;
+ IMG_BOOL bActive;
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ struct work_struct sWork;
+#endif
+}TIMER_CALLBACK_DATA;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static struct workqueue_struct *psTimerWorkQueue;
+#endif
+
+static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+DEFINE_MUTEX(sTimerStructLock);
+#else
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+/* The lock is used to control access to sTimers */
+static spinlock_t sTimerStructLock = SPIN_LOCK_UNLOCKED;
+#else
+static DEFINE_SPINLOCK(sTimerStructLock);
+#endif
+#endif
+
+static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
+{
+ if (!psTimerCBData->bActive)
+ return;
+
+ /* call timer callback */
+ psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+
+ /* reset timer */
+ mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+
+/*************************************************************************/ /*!
+@Function OSTimerCallbackWrapper
+@Description OS specific timer callback wrapper function
+@Input uData Timer callback data
+*/ /**************************************************************************/
+static void OSTimerCallbackWrapper(IMG_UINTPTR_T uData)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)uData;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ int res;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ res = queue_work(psTimerWorkQueue, &psTimerCBData->sWork);
+#else
+ res = schedule_work(&psTimerCBData->sWork);
+#endif
+ if (res == 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "OSTimerCallbackWrapper: work already queued"));
+ }
+#else
+ OSTimerCallbackBody(psTimerCBData);
+#endif
+}
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = container_of(psWork, TIMER_CALLBACK_DATA, sWork);
+
+ OSTimerCallbackBody(psTimerCBData);
+}
+#endif
+
+/*************************************************************************/ /*!
+@Function OSAddTimer
+@Description OS specific function to install a timer callback
+@Input pfnTimerFunc Timer callback
+@Input *pvData Callback data
+@Input ui32MsTimeout Callback period
+@Return Valid handle success, NULL failure
+*/ /**************************************************************************/
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, void *pvData, IMG_UINT32 ui32MsTimeout)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData;
+ IMG_UINT32 ui32i;
+#if !(defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE))
+ unsigned long ulLockFlags;
+#endif
+
+ /* check callback */
+ if(!pfnTimerFunc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
+ return IMG_NULL;
+ }
+
+ /* Allocate timer callback data structure */
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ mutex_lock(&sTimerStructLock);
+#else
+ spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
+#endif
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ psTimerCBData = &sTimers[ui32i];
+ if (!psTimerCBData->bInUse)
+ {
+ psTimerCBData->bInUse = IMG_TRUE;
+ break;
+ }
+ }
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ mutex_unlock(&sTimerStructLock);
+#else
+ spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
+#endif
+ if (ui32i >= OS_MAX_TIMERS)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use"));
+ return IMG_NULL;
+ }
+
+ psTimerCBData->pfnTimerFunc = pfnTimerFunc;
+ psTimerCBData->pvData = pvData;
+ psTimerCBData->bActive = IMG_FALSE;
+
+ /*
+ HZ = ticks per second
+ ui32MsTimeout = required ms delay
+ ticks = (Hz * ui32MsTimeout) / 1000
+ */
+ psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
+ ? 1
+ : ((HZ * ui32MsTimeout) / 1000);
+ /* initialise object */
+ init_timer(&psTimerCBData->sTimer);
+
+ /* setup timer object */
+ psTimerCBData->sTimer.function = (void *)OSTimerCallbackWrapper;
+ psTimerCBData->sTimer.data = (IMG_UINTPTR_T)psTimerCBData;
+
+ return (IMG_HANDLE)(IMG_UINTPTR_T)(ui32i + 1);
+}
+
+
+static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
+{
+ IMG_UINT32 ui32i = (IMG_UINT32)((IMG_UINTPTR_T)hTimer) - 1;
+
+ PVR_ASSERT(ui32i < OS_MAX_TIMERS);
+
+ return &sTimers[ui32i];
+}
+
+/*************************************************************************/ /*!
+@Function OSRemoveTimer
+@Description OS specific function to remove a timer callback
+@Input hTimer : timer handle
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+ /* free timer callback data struct */
+ psTimerCBData->bInUse = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+/*************************************************************************/ /*!
+@Function OSEnableTimer
+@Description OS specific function to enable a timer callback
+@Input hTimer Timer handle
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+ /* Start timer arming */
+ psTimerCBData->bActive = IMG_TRUE;
+
+ /* set the expire time */
+ psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+ /* Add the timer to the list */
+ add_timer(&psTimerCBData->sTimer);
+
+ return PVRSRV_OK;
+}
+
+
+/*************************************************************************/ /*!
+@Function OSDisableTimer
+@Description OS specific function to disable a timer callback
+@Input hTimer Timer handle
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(psTimerCBData->bActive);
+
+ /* Stop timer from arming */
+ psTimerCBData->bActive = IMG_FALSE;
+ smp_mb();
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ flush_scheduled_work();
+#endif
+
+ /* remove timer */
+ del_timer_sync(&psTimerCBData->sTimer);
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ /*
+ * This second flush is to catch the case where the timer ran
+ * before we managed to delete it, in which case, it will have
+ * queued more work for the workqueue. Since the bActive flag
+ * has been cleared, this second flush won't result in the
+ * timer being rearmed.
+ */
+ flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ flush_scheduled_work();
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+/*************************************************************************/ /*!
+@Function OSEventObjectCreate
+@Description OS specific function to create an event object
+@Input pszName Globally unique event object name (if null name must be autogenerated)
+@Output hEventObject OS event object info structure
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName, IMG_HANDLE *hEventObject)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVR_UNREFERENCED_PARAMETER(pszName);
+
+ if(hEventObject)
+ {
+ if(LinuxEventObjectListCreate(hEventObject) != PVRSRV_OK)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: hEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT;
+ }
+
+ return eError;
+}
+
+
+/*************************************************************************/ /*!
+@Function OSEventObjectDestroy
+@Description OS specific function to destroy an event object
+@Input hEventObject OS event object info structure
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEventObjectDestroy(IMG_HANDLE hEventObject)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(hEventObject)
+ {
+ LinuxEventObjectListDestroy(hEventObject);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: hEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function OSEventObjectWaitTimeout
+@Description Wait for an event with timeout as supplied. Called from client
+@Input hOSEventKM OS and kernel specific handle to event object
+@Input uiTimeoutMs Non zero time period in milliseconds to wait
+@Return PVRSRV_ERROR_TIMEOUT : Wait reached wait limit and timed out
+@Return PVRSRV_ERROR : any other system error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEventObjectWaitTimeout(IMG_HANDLE hOSEventKM, IMG_UINT32 uiTimeoutMs)
+{
+ PVRSRV_ERROR eError;
+
+ if(hOSEventKM && uiTimeoutMs > 0)
+ {
+ eError = LinuxEventObjectWait(hOSEventKM, uiTimeoutMs);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWait: invalid arguments %p, %d", hOSEventKM, uiTimeoutMs ));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function OSEventObjectWait
+@Description OS specific function to wait for an event object. Called
+ from client. Uses a default wait with 100ms timeout.
+@Input hOSEventKM OS and kernel specific handle to event object
+@Return PVRSRV_ERROR_TIMEOUT : Reached wait limit and timed out
+@Return PVRSRV_ERROR : any other system error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM)
+{
+ return OSEventObjectWaitTimeout(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+}
+
+/*************************************************************************/ /*!
+@Function OSEventObjectOpen
+@Description OS specific function to open an event object. Called from client
+@Input hEventObject Pointer to an event object
+@Output phOSEvent OS and kernel specific handle to event object
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEventObjectOpen(IMG_HANDLE hEventObject,
+ IMG_HANDLE *phOSEvent)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(hEventObject)
+ {
+ if(LinuxEventObjectAdd(hEventObject, phOSEvent) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectOpen: hEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function OSEventObjectClose
+@Description OS specific function to close an event object. Called from client
+@Input hOSEventKM OS and kernel specific handle to event object
+@Return PVRSRV_ERROR :
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEventObjectClose(IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(hOSEventKM)
+ {
+ if(LinuxEventObjectDelete(hOSEventKM) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectDelete: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: hEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function OSEventObjectSignal
+@Description OS specific function to 'signal' an event object. Called from L/MISR
+@Input hOSEventKM OS and kernel specific handle to event object
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hEventObject)
+{
+ PVRSRV_ERROR eError;
+
+ if(hEventObject)
+ {
+ eError = LinuxEventObjectSignal(hEventObject);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectSignal: hOSEventKM is not a valid handle"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function OSProcHasPrivSrvInit
+@Description Does the process have sufficient privileges to initialise services?
+@Return IMG_BOOL
+*/ /**************************************************************************/
+IMG_BOOL OSProcHasPrivSrvInit(void)
+{
+ return capable(CAP_SYS_ADMIN) != 0;
+}
+
+/*************************************************************************/ /*!
+@Function OSCopyToUser
+@Description Copy a block of data into user space
+@Input pvSrc
+@Output pvDest
+@Input ui32Bytes
+@Return PVRSRV_ERROR :
+*/ /**************************************************************************/
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
+ void *pvDest,
+ const void *pvSrc,
+ IMG_SIZE_T ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(pvr_copy_to_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+/*************************************************************************/ /*!
+@Function OSCopyFromUser
+@Description Copy a block of data from the user space
+@Output pvDest
+@Input pvSrc
+@Input ui32Bytes
+@Return PVRSRV_ERROR :
+*/ /**************************************************************************/
+PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess,
+ void *pvDest,
+ const void *pvSrc,
+ IMG_SIZE_T ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(pvr_copy_from_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+/*************************************************************************/ /*!
+@Function OSAccessOK
+@Description Checks if a user space pointer is valide
+@Input eVerification
+@Input pvUserPtr
+@Input ui32Bytes
+@Return IMG_BOOL :
+*/ /**************************************************************************/
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, void *pvUserPtr, IMG_SIZE_T ui32Bytes)
+{
+ IMG_INT linuxType;
+
+ if (eVerification == PVR_VERIFY_READ)
+ {
+ linuxType = VERIFY_READ;
+ }
+ else
+ {
+ PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
+ linuxType = VERIFY_WRITE;
+ }
+
+ return access_ok(linuxType, pvUserPtr, ui32Bytes);
+}
+
+
+void OSWriteMemoryBarrier(void)
+{
+ wmb();
+}
+
+
+void OSMemoryBarrier(void)
+{
+ mb();
+}
+
+PVRSRV_ERROR OSWRLockCreate(POSWR_LOCK *ppsLock)
+{
+ POSWR_LOCK psLock;
+
+ psLock = kmalloc(sizeof(*psLock), GFP_KERNEL);
+ if (psLock == NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ init_rwsem(&psLock->sRWLock);
+
+ *ppsLock = psLock;
+
+ return PVRSRV_OK;
+}
+
+void OSWRLockDestroy(POSWR_LOCK psLock)
+{
+ kfree(psLock);
+}
+
+IMG_UINT64 OSDivide64r64(IMG_UINT64 ui64Divident, IMG_UINT32 ui32Divisor, IMG_UINT32 *pui32Remainder)
+{
+ *pui32Remainder = do_div(ui64Divident, ui32Divisor);
+
+ return ui64Divident;
+}
+
+IMG_UINT32 OSDivide64(IMG_UINT64 ui64Divident, IMG_UINT32 ui32Divisor, IMG_UINT32 *pui32Remainder)
+{
+ *pui32Remainder = do_div(ui64Divident, ui32Divisor);
+
+ return (IMG_UINT32) ui64Divident;
+}
+
+/* One time osfunc initialisation */
+PVRSRV_ERROR PVROSFuncInit(void)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ {
+ psTimerWorkQueue = create_workqueue("pvr_timer");
+ if (psTimerWorkQueue == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__));
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+ }
+ }
+#endif
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ {
+ IMG_UINT32 ui32i;
+
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ TIMER_CALLBACK_DATA *psTimerCBData = &sTimers[ui32i];
+
+ INIT_WORK(&psTimerCBData->sWork, OSTimerWorkQueueCallBack);
+ }
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+/*
+ * Osfunc deinitialisation.
+ * Note that PVROSFuncInit may not have been called
+ */
+void PVROSFuncDeInit(void)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ if (psTimerWorkQueue != NULL)
+ {
+ destroy_workqueue(psTimerWorkQueue);
+ }
+#endif
+}
+
+static IMG_BOOL gbDoRelease = IMG_TRUE;
+void OSSetReleasePVRLock(void){ gbDoRelease = IMG_TRUE; }
+void OSSetKeepPVRLock(void) { gbDoRelease = IMG_FALSE;}
+IMG_BOOL OSGetReleasePVRLock(void){ return gbDoRelease;}
+
+void OSDumpStack(void)
+{
+ dump_stack();
+}
+
+static struct task_struct *gsOwner;
+
+void OSAcquireBridgeLock(void)
+{
+ mutex_lock(&gPVRSRVLock);
+ gsOwner = current;
+}
+
+void OSReleaseBridgeLock(void)
+{
+ gsOwner = NULL;
+ mutex_unlock(&gPVRSRVLock);
+}
+
+struct task_struct *OSGetBridgeLockOwner(void)
+{
+ return gsOwner;
+}
+
+
+/*************************************************************************/ /*!
+@Function OSCreateStatisticEntry
+@Description Create a statistic entry in the specified folder.
+@Input pszName String containing the name for the entry.
+@Input pvFolder Reference from OSCreateStatisticFolder() of the
+ folder to create the entry in, or IMG_NULL for the
+ root.
+@Input pfnGetElement Pointer to function that can be used to obtain the
+ value of the statistic.
+@Input pvData OS specific reference that can be used by
+ pfnGetElement.
+@Return Pointer void reference to the entry created, which can be
+ passed to OSRemoveStatisticEntry() to remove the entry.
+*/ /**************************************************************************/
+IMG_PVOID OSCreateStatisticEntry(IMG_CHAR* pszName, IMG_PVOID pvFolder,
+ OS_GET_STATS_ELEMENT_FUNC* pfnGetElement,
+ IMG_PVOID pvData)
+{
+ return PVRDebugFSCreateStatisticEntry(pszName, pvFolder, pfnGetElement, pvData);
+} /* OSCreateStatisticEntry */
+
+
+/*************************************************************************/ /*!
+@Function OSRemoveStatisticEntry
+@Description Removes a statistic entry.
+@Input pvEntry Pointer void reference to the entry created by
+ OSCreateStatisticEntry().
+*/ /**************************************************************************/
+void OSRemoveStatisticEntry(IMG_PVOID pvEntry)
+{
+ PVRDebugFSRemoveStatisticEntry(pvEntry);
+} /* OSRemoveStatisticEntry */
+
+
+/*************************************************************************/ /*!
+@Function OSCreateStatisticFolder
+@Description Create a statistic folder to hold statistic entries.
+@Input pszName String containing the name for the folder.
+@Input pvFolder Reference from OSCreateStatisticFolder() of the folder
+ to create the folder in, or IMG_NULL for the root.
+@Return Pointer void reference to the folder created, which can be
+ passed to OSRemoveStatisticFolder() to remove the folder.
+*/ /**************************************************************************/
+IMG_PVOID OSCreateStatisticFolder(IMG_CHAR *pszName, IMG_PVOID pvFolder)
+{
+ struct dentry *psDir;
+ int iResult;
+
+ iResult = PVRDebugFSCreateEntryDir(pszName, pvFolder, &psDir);
+
+ return (iResult == 0) ? psDir : IMG_NULL;
+} /* OSCreateStatisticFolder */
+
+
+/*************************************************************************/ /*!
+@Function OSRemoveStatisticFolder
+@Description Removes a statistic folder.
+@Input pvFolder Reference from OSCreateStatisticFolder() of the
+ folder that should be removed.
+*/ /**************************************************************************/
+void OSRemoveStatisticFolder(IMG_PVOID pvFolder)
+{
+ PVRDebugFSRemoveEntryDir((struct dentry *)pvFolder);
+} /* OSRemoveStatisticFolder */
diff --git a/drivers/gpu/rogue/services/server/env/linux/osfunc_arm.c b/drivers/gpu/rogue/services/server/env/linux/osfunc_arm.c
new file mode 100644
index 000000000000..bd5b0281d36a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/osfunc_arm.c
@@ -0,0 +1,171 @@
+/*************************************************************************/ /*!
+@File
+@Title arm specific OS functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS functions who's implementation are processor specific
+@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/dma-mapping.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
+#else
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
+#endif
+
+static void per_cpu_cache_flush(void *arg)
+{
+ PVR_UNREFERENCED_PARAMETER(arg);
+ flush_cache_all();
+}
+
+void OSCPUOperation(PVRSRV_CACHE_OP uiCacheOp)
+{
+ switch(uiCacheOp)
+ {
+ /* Fall-through */
+ case PVRSRV_CACHE_OP_CLEAN:
+ /* No full (inner) cache clean op */
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE)
+ outer_clean_range(0, ULONG_MAX);
+#endif
+ break;
+
+ case PVRSRV_CACHE_OP_FLUSH:
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE) && \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ /* To use the "deferred flush" (not clean) DDK feature you need a kernel
+ * implementation of outer_flush_all() for ARM CPUs with an outer cache
+ * controller (e.g. PL310, common with Cortex A9 and later).
+ *
+ * Reference DDKs don't require this functionality, as they will only
+ * clean the cache, never flush (clean+invalidate) it.
+ */
+ outer_flush_all();
+#endif
+ break;
+
+ case PVRSRV_CACHE_OP_NONE:
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Invalid cache operation type %d",
+ __FUNCTION__, uiCacheOp));
+ PVR_ASSERT(0);
+ break;
+ }
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
+static inline size_t pvr_dmac_range_len(const void *pvStart, const void *pvEnd)
+{
+ return (size_t)((char *)pvEnd - (char *)pvStart);
+}
+#endif
+
+void OSFlushCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
+ arm_dma_ops.sync_single_for_device(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_TO_DEVICE);
+ arm_dma_ops.sync_single_for_cpu(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_FROM_DEVICE);
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
+ /* Inner cache */
+ dmac_flush_range(pvVirtStart, pvVirtEnd);
+
+ /* Outer cache */
+ outer_flush_range(sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
+}
+
+void OSCleanCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
+ arm_dma_ops.sync_single_for_device(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_TO_DEVICE);
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
+ /* Inner cache */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+ dmac_clean_range(pvVirtStart, pvVirtEnd);
+#else
+ dmac_map_area(pvVirtStart, pvr_dmac_range_len(pvVirtStart, pvVirtEnd), DMA_TO_DEVICE);
+#endif
+
+ /* Outer cache */
+ outer_clean_range(sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
+}
+
+void OSInvalidateCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
+ arm_dma_ops.sync_single_for_cpu(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_FROM_DEVICE);
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
+#if defined(PVR_LINUX_DONT_USE_RANGE_BASED_INVALIDATE)
+ OSCleanCPUCacheRangeKM(pvVirtStart, pvVirtEnd, sCPUPhysStart, sCPUPhysEnd);
+#else
+ /* Inner cache */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+ dmac_inv_range(pvVirtStart, pvVirtEnd);
+#else
+ dmac_map_area(pvVirtStart, pvr_dmac_range_len(pvVirtStart, pvVirtEnd), DMA_FROM_DEVICE);
+#endif
+
+ /* Outer cache */
+ outer_inv_range(sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr);
+#endif
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) */
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/osfunc_arm64.c b/drivers/gpu/rogue/services/server/env/linux/osfunc_arm64.c
new file mode 100644
index 000000000000..b0edc18d6d59
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/osfunc_arm64.c
@@ -0,0 +1,118 @@
+/*************************************************************************/ /*!
+@File
+@Title arm specific OS functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS functions who's implementation are processor specific
+@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/dma-mapping.h>
+#include <asm/cacheflush.h>
+
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+
+#if defined(CONFIG_OUTER_CACHE)
+ /* 32-bit ARM CPUs often have an outer cache controller (e.g. PL310,
+ * common with Cortex A9 and later). Hopefully ARM have now followed
+ * Intel's footsteps and made the cache hierarchy transparent so that
+ * these never appear on 64-bit ARM CPUs. But just in case they do, let
+ * the developer know that there is work to do.
+ */
+ #error "CONFIG_OUTER_CACHE not supported on arm64."
+#endif
+
+
+static void per_cpu_cache_flush(void *arg)
+{
+ PVR_UNREFERENCED_PARAMETER(arg);
+ flush_cache_all();
+}
+
+void OSCPUOperation(PVRSRV_CACHE_OP uiCacheOp)
+{
+ switch(uiCacheOp)
+ {
+ /* Fall-through */
+ case PVRSRV_CACHE_OP_CLEAN:
+ /* No full (inner) cache clean op */
+ on_each_cpu(per_cpu_cache_flush, NULL, 1);
+ break;
+
+ case PVRSRV_CACHE_OP_FLUSH:
+ on_each_cpu(per_cpu_cache_flush, NULL, 1);
+ break;
+
+ case PVRSRV_CACHE_OP_NONE:
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Invalid cache operation type %d",
+ __FUNCTION__, uiCacheOp));
+ PVR_ASSERT(0);
+ break;
+ }
+}
+
+void OSFlushCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd)
+{
+ dma_ops->sync_single_for_device(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_TO_DEVICE);
+ dma_ops->sync_single_for_cpu(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_FROM_DEVICE);
+}
+
+void OSCleanCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd)
+{
+ dma_ops->sync_single_for_device(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_TO_DEVICE);
+}
+
+void OSInvalidateCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd)
+{
+ dma_ops->sync_single_for_cpu(NULL, sCPUPhysStart.uiAddr, sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr, DMA_FROM_DEVICE);
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/osfunc_x86.c b/drivers/gpu/rogue/services/server/env/linux/osfunc_x86.c
new file mode 100644
index 000000000000..857db4136b2a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/osfunc_x86.c
@@ -0,0 +1,143 @@
+/*************************************************************************/ /*!
+@File
+@Title x86 specific OS functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS functions who's implementation are processor specific
+@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/smp.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+#include <asm/system.h>
+#endif
+
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "img_defs.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
+#else
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
+#endif
+
+#define ROUND_UP(x,a) (((x) + (a) - 1) & ~((a) - 1))
+
+static void per_cpu_cache_flush(void *arg)
+{
+ PVR_UNREFERENCED_PARAMETER(arg);
+ wbinvd();
+}
+
+void OSCPUOperation(PVRSRV_CACHE_OP uiCacheOp)
+{
+ switch(uiCacheOp)
+ {
+ /* Fall-through */
+ case PVRSRV_CACHE_OP_CLEAN:
+ case PVRSRV_CACHE_OP_FLUSH:
+ case PVRSRV_CACHE_OP_INVALIDATE:
+ on_each_cpu(per_cpu_cache_flush, NULL, 1);
+ break;
+
+ case PVRSRV_CACHE_OP_NONE:
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Invalid cache operation type %d",
+ __FUNCTION__, uiCacheOp));
+ PVR_ASSERT(0);
+ break;
+ }
+}
+
+static void x86_flush_cache_range(const void *pvStart, const void *pvEnd)
+{
+ IMG_BYTE *pbStart = (IMG_BYTE *)pvStart;
+ IMG_BYTE *pbEnd = (IMG_BYTE *)pvEnd;
+ IMG_BYTE *pbBase;
+
+ pbEnd = (IMG_BYTE *)ROUND_UP((IMG_UINTPTR_T)pbEnd,
+ boot_cpu_data.x86_clflush_size);
+
+ mb();
+ for(pbBase = pbStart; pbBase < pbEnd; pbBase += boot_cpu_data.x86_clflush_size)
+ {
+ clflush(pbBase);
+ }
+ mb();
+}
+
+void OSFlushCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd)
+{
+ PVR_UNREFERENCED_PARAMETER(sCPUPhysStart);
+ PVR_UNREFERENCED_PARAMETER(sCPUPhysEnd);
+
+ x86_flush_cache_range(pvVirtStart, pvVirtEnd);
+}
+
+
+void OSCleanCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd)
+{
+ PVR_UNREFERENCED_PARAMETER(sCPUPhysStart);
+ PVR_UNREFERENCED_PARAMETER(sCPUPhysEnd);
+
+ /* No clean feature on x86 */
+ x86_flush_cache_range(pvVirtStart, pvVirtEnd);
+}
+
+void OSInvalidateCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd)
+{
+ PVR_UNREFERENCED_PARAMETER(sCPUPhysStart);
+ PVR_UNREFERENCED_PARAMETER(sCPUPhysEnd);
+
+ /* No invalidate-only support */
+ x86_flush_cache_range(pvVirtStart, pvVirtEnd);
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/ossecure_export.c b/drivers/gpu/rogue/services/server/env/linux/ossecure_export.c
new file mode 100644
index 000000000000..1488553e6a0d
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/ossecure_export.c
@@ -0,0 +1,192 @@
+/*************************************************************************/ /*!
+@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/dcache.h>
+#include <linux/mount.h>
+#include <linux/sched.h>
+#include <linux/cred.h>
+
+#include "img_types.h"
+#include "ossecure_export.h"
+#include "env_connection.h"
+#include "private_data.h"
+#include "pvr_debug.h"
+#include "driverlock.h"
+
+#if defined(SUPPORT_DRM)
+#include "pvr_drm.h"
+#endif
+
+PVRSRV_ERROR OSSecureExport(CONNECTION_DATA *psConnection,
+ IMG_PVOID pvData,
+ IMG_SECURE_TYPE *phSecure,
+ CONNECTION_DATA **ppsSecureConnection)
+{
+ ENV_CONNECTION_DATA *psEnvConnection;
+ CONNECTION_DATA *psSecureConnection;
+ struct file *connection_file;
+ struct file *secure_file;
+ struct dentry *secure_dentry;
+ struct vfsmount *secure_mnt;
+ int secure_fd;
+ IMG_BOOL bPmrUnlocked = IMG_FALSE;
+ PVRSRV_ERROR eError;
+
+ /* Obtain the current connections struct file */
+ psEnvConnection = PVRSRVConnectionPrivateData(psConnection);
+ connection_file = LinuxFileFromEnvConnection(psEnvConnection);
+
+ /* Allocate a fd number */
+ secure_fd = get_unused_fd();
+ if (secure_fd < 0)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+
+ /*
+ Get a reference to the dentry so when close is called we don't
+ drop the last reference too early and delete the file
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
+ secure_dentry = dget(connection_file->f_path.dentry);
+ secure_mnt = mntget(connection_file->f_path.mnt);
+#else
+ secure_dentry = dget(connection_file->f_dentry);
+ secure_mnt = mntget(connection_file->f_vfsmnt);
+#endif
+
+ /* PMR lock needs to be released before bridge lock to keep lock hierarchy
+ * and avoid deadlock situation.
+ * OSSecureExport() can be called from functions that are not acquiring
+ * PMR lock (e.g. by PVRSRVSyncPrimServerSecureExportKM()) so we have to
+ * check if PMR lock is locked. */
+ if (PMRIsLockedByMe())
+ {
+ PMRUnlock();
+ bPmrUnlocked = IMG_TRUE;
+ }
+ OSReleaseBridgeLock();
+
+ /* Open our device (using the file information from our current connection) */
+ secure_file = dentry_open(
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
+ &connection_file->f_path,
+#else
+ connection_file->f_dentry,
+ connection_file->f_vfsmnt,
+#endif
+ connection_file->f_flags,
+ current_cred());
+
+ OSAcquireBridgeLock();
+ if (bPmrUnlocked)
+ PMRLock();
+
+ /* Bail if the open failed */
+ 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);
+
+ /* Return the new services connection our secure data created */
+#if defined(SUPPORT_DRM)
+ psSecureConnection = LinuxConnectionFromFile(PVR_DRM_FILE_FROM_FILE(secure_file));
+#else
+ psSecureConnection = LinuxConnectionFromFile(secure_file);
+#endif
+
+ /* Save the private data */
+ PVR_ASSERT(psSecureConnection->hSecureData == IMG_NULL);
+ psSecureConnection->hSecureData = pvData;
+
+ *phSecure = secure_fd;
+ *ppsSecureConnection = psSecureConnection;
+ return PVRSRV_OK;
+
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR OSSecureImport(IMG_SECURE_TYPE hSecure, IMG_PVOID *ppvData)
+{
+ struct file *secure_file;
+ CONNECTION_DATA *psSecureConnection;
+ PVRSRV_ERROR eError;
+
+ secure_file = fget(hSecure);
+
+ if (!secure_file)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err_out;
+ }
+
+#if defined(SUPPORT_DRM)
+ psSecureConnection = LinuxConnectionFromFile(PVR_DRM_FILE_FROM_FILE(secure_file));
+#else
+ psSecureConnection = LinuxConnectionFromFile(secure_file);
+#endif
+ if (psSecureConnection->hSecureData == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err_fput;
+ }
+
+ *ppvData = psSecureConnection->hSecureData;
+ fput(secure_file);
+ return PVRSRV_OK;
+
+err_fput:
+ fput(secure_file);
+err_out:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/pdump.c b/drivers/gpu/rogue/services/server/env/linux/pdump.c
new file mode 100644
index 000000000000..bc526f7cdb04
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/pdump.c
@@ -0,0 +1,462 @@
+/*************************************************************************/ /*!
+@File
+@Title Parameter dump macro target routines
+@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 (PDUMP)
+
+#include <asm/atomic.h>
+#include <stdarg.h>
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+#include "pvrsrv.h"
+#include "osfunc.h"
+
+#include "dbgdrvif_srv5.h"
+#include "mm.h"
+#include "allocmem.h"
+#include "pdump_km.h"
+#include "pdump_osfunc.h"
+
+#include <linux/kernel.h> // sprintf
+#include <linux/string.h> // strncpy, strlen
+#include <linux/mutex.h>
+
+#define PDUMP_DATAMASTER_PIXEL (1)
+#define PDUMP_DATAMASTER_EDM (3)
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+
+typedef struct PDBG_PDUMP_STATE_TAG
+{
+ PDBG_STREAM psStream[PDUMP_NUM_CHANNELS];
+
+ IMG_CHAR *pszMsg;
+ IMG_CHAR *pszScript;
+ IMG_CHAR *pszFile;
+
+} PDBG_PDUMP_STATE;
+
+static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, IMG_NULL, IMG_NULL, IMG_NULL};
+
+#define SZ_MSG_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_SCRIPT_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_FILENAME_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+
+static struct mutex gsPDumpMutex;
+
+void DBGDrvGetServiceTable(void **fn_table);
+
+
+/*!
+ * \name PDumpOSGetScriptString
+ */
+PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
+ *pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
+ if (!*phScript)
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+ }
+ return PVRSRV_OK;
+}
+
+/*!
+ * \name PDumpOSGetMessageString
+ */
+PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *ppszMsg = gsDBGPdumpState.pszMsg;
+ *pui32MaxLen = SZ_MSG_SIZE_MAX;
+ if (!*ppszMsg)
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+ }
+ return PVRSRV_OK;
+}
+
+/*!
+ * \name PDumpOSGetFilenameString
+ */
+PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *ppszFile = gsDBGPdumpState.pszFile;
+ *pui32MaxLen = SZ_FILENAME_SIZE_MAX;
+ if (!*ppszFile)
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+ }
+ return PVRSRV_OK;
+}
+
+/*!
+ * \name PDumpOSBufprintf
+ */
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
+{
+ IMG_CHAR* pszBuf = hBuf;
+ IMG_INT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+ g_ui32EveryLineCounter++;
+#endif
+
+ /* Put line ending sequence at the end if it isn't already there */
+ PDumpOSVerifyLineEnding(pszBuf, ui32ScriptSizeMax);
+
+ return PVRSRV_OK;
+}
+
+/*!
+ * \name PDumpOSVSprintf
+ */
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+{
+ IMG_INT32 n;
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+/*!
+ * \name PDumpOSDebugPrintf
+ */
+void PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
+{
+ PVR_UNREFERENCED_PARAMETER(pszFormat);
+
+
+}
+
+/*!
+ * \name PDumpOSSprintf
+ */
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
+{
+ IMG_INT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+/*!
+ * \name PDumpOSBuflen
+ */
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_CHAR* pszBuf = hBuffer;
+ IMG_UINT32 ui32Count = 0;
+
+ while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
+ {
+ ui32Count++;
+ }
+ return(ui32Count);
+}
+
+/*!
+ * \name PDumpOSVerifyLineEnding
+ */
+void PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_UINT32 ui32Count;
+ IMG_CHAR* pszBuf = hBuffer;
+
+ /* strlen */
+ ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
+
+ /* Put \n sequence at the end if it isn't already there */
+ if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
+ {
+ pszBuf[ui32Count] = '\n';
+ ui32Count++;
+ pszBuf[ui32Count] = '\0';
+ }
+}
+
+
+
+/*!
+ * \name PDumpOSGetStreamOffset
+ */
+IMG_BOOL PDumpOSSetSplitMarker(IMG_HANDLE hStream, IMG_UINT32 ui32Marker)
+{
+ PDBG_STREAM psStream = (PDBG_STREAM) hStream;
+
+ PVR_ASSERT(gpfnDbgDrv);
+ gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+ return IMG_TRUE;
+}
+
+/*!
+ * \name PDumpOSDebugDriverWrite
+ */
+IMG_UINT32 PDumpOSDebugDriverWrite( IMG_HANDLE psStream,
+ IMG_UINT8 *pui8Data,
+ IMG_UINT32 ui32BCount)
+{
+ PVR_ASSERT(gpfnDbgDrv != IMG_NULL);
+
+ return gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount);
+}
+
+/*!
+ * \name PDumpOSReleaseExecution
+ */
+void PDumpOSReleaseExecution(void)
+{
+ OSReleaseThreadQuanta();
+}
+
+/**************************************************************************
+ * Function Name : PDumpOSInit
+ * Outputs : None
+ * Returns :
+ * Description : Reset connection to vldbgdrv
+ * Then try to connect to PDUMP streams
+**************************************************************************/
+PVRSRV_ERROR PDumpOSInit(PDUMP_CHANNEL* psParam, PDUMP_CHANNEL* psScript,
+ IMG_UINT32* pui32InitCapMode, IMG_CHAR** ppszEnvComment)
+{
+ PVRSRV_ERROR eError;
+
+ *pui32InitCapMode = DEBUG_CAPMODE_FRAMED;
+ *ppszEnvComment = IMG_NULL;
+
+ /* If we tried this earlier, then we might have connected to the driver
+ * But if pdump.exe was running then the stream connected would fail
+ */
+ if (!gpfnDbgDrv)
+ {
+ DBGDrvGetServiceTable((void **)&gpfnDbgDrv);
+
+ // If something failed then no point in trying to connect streams
+ if (gpfnDbgDrv == IMG_NULL)
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ }
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ if(!gsDBGPdumpState.pszFile)
+ {
+ gsDBGPdumpState.pszFile = OSAllocMem(SZ_FILENAME_SIZE_MAX);
+ if (gsDBGPdumpState.pszFile == IMG_NULL)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszMsg)
+ {
+ gsDBGPdumpState.pszMsg = OSAllocMem(SZ_MSG_SIZE_MAX);
+ if (gsDBGPdumpState.pszMsg == IMG_NULL)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszScript)
+ {
+ gsDBGPdumpState.pszScript = OSAllocMem(SZ_SCRIPT_SIZE_MAX);
+ if (gsDBGPdumpState.pszScript == IMG_NULL)
+ {
+ goto init_failed;
+ }
+ }
+
+ eError = PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
+ if (!gpfnDbgDrv->pfnCreateStream(PDUMP_PARAM_CHANNEL_NAME, 0, 10, &psParam->hInit, &psParam->hMain, &psParam->hDeinit))
+ {
+ goto init_failed;
+ }
+ gsDBGPdumpState.psStream[PDUMP_CHANNEL_PARAM] = psParam->hMain;
+
+
+ if (!gpfnDbgDrv->pfnCreateStream(PDUMP_SCRIPT_CHANNEL_NAME, 0, 10, &psScript->hInit, &psScript->hMain, &psScript->hDeinit))
+ {
+ goto init_failed;
+ }
+ gsDBGPdumpState.psStream[PDUMP_CHANNEL_SCRIPT] = psScript->hMain;
+ }
+
+ return PVRSRV_OK;
+
+init_failed:
+ PDumpOSDeInit(psParam, psScript);
+ return eError;
+}
+
+
+void PDumpOSDeInit(PDUMP_CHANNEL* psParam, PDUMP_CHANNEL* psScript)
+{
+ gpfnDbgDrv->pfnDestroyStream(psScript->hInit, psScript->hMain, psScript->hDeinit);
+ gpfnDbgDrv->pfnDestroyStream(psParam->hInit, psParam->hMain, psParam->hDeinit);
+
+ if(gsDBGPdumpState.pszFile)
+ {
+ OSFreeMem(gsDBGPdumpState.pszFile);
+ gsDBGPdumpState.pszFile = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszScript)
+ {
+ OSFreeMem(gsDBGPdumpState.pszScript);
+ gsDBGPdumpState.pszScript = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszMsg)
+ {
+ OSFreeMem(gsDBGPdumpState.pszMsg);
+ gsDBGPdumpState.pszMsg = IMG_NULL;
+ }
+
+ gpfnDbgDrv = IMG_NULL;
+}
+
+PVRSRV_ERROR PDumpOSCreateLock(void)
+{
+ mutex_init(&gsPDumpMutex);
+ return PVRSRV_OK;
+}
+
+void PDumpOSDestroyLock(void)
+{
+ /* no destruction work to do, just assert
+ * the lock is not held */
+ PVR_ASSERT(mutex_is_locked(&gsPDumpMutex) == 0);
+}
+
+void PDumpOSLock(void)
+{
+ mutex_lock(&gsPDumpMutex);
+}
+
+void PDumpOSUnlock(void)
+{
+ mutex_unlock(&gsPDumpMutex);
+}
+
+IMG_UINT32 PDumpOSGetCtrlState(IMG_HANDLE hDbgStream,
+ IMG_UINT32 ui32StateID)
+{
+ return (gpfnDbgDrv->pfnGetCtrlState((PDBG_STREAM)hDbgStream, ui32StateID));
+}
+
+void PDumpOSSetFrame(IMG_UINT32 ui32Frame)
+{
+ gpfnDbgDrv->pfnSetFrame(ui32Frame);
+ return;
+}
+
+IMG_BOOL PDumpOSAllowInitPhaseToComplete(IMG_UINT32 eModuleID)
+{
+ return (eModuleID != IMG_PDUMPCTRL);
+}
+
+#if defined(PVR_TESTING_UTILS)
+void PDumpOSDumpState(void);
+
+void PDumpOSDumpState(void)
+{
+ PVR_LOG(("---- PDUMP LINUX: gpfnDbgDrv( %p ) gpfnDbgDrv.ui32Size( %d )",
+ gpfnDbgDrv, gpfnDbgDrv->ui32Size));
+
+ PVR_LOG(("---- PDUMP LINUX: gsDBGPdumpState( %p )",
+ &gsDBGPdumpState));
+
+ PVR_LOG(("---- PDUMP LINUX: gsDBGPdumpState.psStream[0]( %p )",
+ gsDBGPdumpState.psStream[0]));
+
+ (void) gpfnDbgDrv->pfnGetCtrlState(gsDBGPdumpState.psStream[0], 0xFE);
+
+ PVR_LOG(("---- PDUMP LINUX: gsDBGPdumpState.psStream[1]( %p )",
+ gsDBGPdumpState.psStream[1]));
+
+ (void) gpfnDbgDrv->pfnGetCtrlState(gsDBGPdumpState.psStream[1], 0xFE);
+
+ /* Now dump non-stream specific info */
+ (void) gpfnDbgDrv->pfnGetCtrlState(gsDBGPdumpState.psStream[1], 0xFF);
+}
+#endif
+
+#endif /* #if defined (PDUMP) */
+/*****************************************************************************
+ End of file (PDUMP.C)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/env/linux/physmem_dmabuf.c b/drivers/gpu/rogue/services/server/env/linux/physmem_dmabuf.c
new file mode 100644
index 000000000000..477310fadbe5
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/physmem_dmabuf.c
@@ -0,0 +1,663 @@
+/*************************************************************************/ /*!
+@File physmem_dmabuf.c
+@Title dmabuf memory allocator
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is responsible for
+ implementing the function callbacks for dmabuf memory.
+@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 "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+
+#include "allocmem.h"
+#include "osfunc.h"
+#include "pvrsrv.h"
+#include "physmem_lma.h"
+#include "pdump_physmem.h"
+#include "pmr.h"
+#include "pmr_impl.h"
+#include "physmem_dmabuf.h"
+#include "ion_sys.h"
+#include "hash.h"
+
+#if defined(PVR_RI_DEBUG)
+#include "ri_server.h"
+#endif
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/dma-buf.h>
+#include <linux/scatterlist.h>
+
+typedef struct _PMR_DMA_BUF_DATA_
+{
+ struct dma_buf_attachment *psAttachment;
+ struct sg_table *psSgTable;
+ struct dma_buf *psDmaBuf;
+
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_PVOID *pvKernAddr;
+
+ IMG_DEV_PHYADDR *pasDevPhysAddr;
+ IMG_UINT32 ui32PageCount;
+ PHYS_HEAP *psPhysHeap;
+
+ IMG_BOOL bPoisonOnFree;
+ IMG_BOOL bPDumpMalloced;
+ IMG_HANDLE hPDumpAllocInfo;
+} PMR_DMA_BUF_DATA;
+
+/* Start size of the g_psDmaBufHash hash table */
+#define DMA_BUF_HASH_SIZE 20
+
+static HASH_TABLE *g_psDmaBufHash = IMG_NULL;
+static IMG_UINT32 g_ui32HashRefCount = 0;
+
+#if defined(PVR_ANDROID_ION_USE_SG_LENGTH)
+#define pvr_sg_length(sg) ((sg)->length)
+#else
+#define pvr_sg_length(sg) sg_dma_len(sg)
+#endif
+
+/*****************************************************************************
+ * DMA-BUF specific functions *
+ *****************************************************************************/
+
+/*
+ Obtain a list of physical pages from the dmabuf.
+*/
+static PVRSRV_ERROR DmaBufPhysAddrAcquire(PMR_DMA_BUF_DATA *psPrivData, int fd)
+{
+ struct dma_buf_attachment *psAttachment = psPrivData->psAttachment;
+ IMG_DEV_PHYADDR *pasDevPhysAddr = NULL;
+ IMG_CPU_PHYADDR sCpuPhysAddr;
+ IMG_UINT32 ui32PageCount = 0;
+ struct scatterlist *sg;
+ struct sg_table *table;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+
+ table = dma_buf_map_attachment(psAttachment, DMA_NONE);
+ if (!table)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exitFailMap;
+ }
+
+ /*
+ We do a two pass process, 1st workout how many pages there
+ are, 2nd fill in the data.
+ */
+ for_each_sg(table->sgl, sg, table->nents, i)
+ {
+ ui32PageCount += PAGE_ALIGN(pvr_sg_length(sg)) / PAGE_SIZE;
+ }
+
+ if (WARN_ON(!ui32PageCount))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to import dmabuf with no pages",
+ __func__));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exitFailMap;
+ }
+
+ pasDevPhysAddr = OSAllocMem(sizeof(IMG_DEV_PHYADDR)*ui32PageCount);
+ if (!pasDevPhysAddr)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exitFailAlloc;
+ }
+
+ ui32PageCount = 0;
+
+ for_each_sg(table->sgl, sg, table->nents, i)
+ {
+ IMG_UINT32 j;
+
+ for (j = 0; j < pvr_sg_length(sg); j += PAGE_SIZE)
+ {
+ /* Pass 2: Get the page data */
+ sCpuPhysAddr.uiAddr = sg_phys(sg);
+
+ pasDevPhysAddr[ui32PageCount] =
+ IonCPUPhysToDevPhys(sCpuPhysAddr, j);
+ ui32PageCount++;
+ }
+ }
+
+ psPrivData->pasDevPhysAddr = pasDevPhysAddr;
+ psPrivData->ui32PageCount = ui32PageCount;
+ psPrivData->uiSize = (IMG_DEVMEM_SIZE_T)ui32PageCount * PAGE_SIZE;
+ psPrivData->psSgTable = table;
+
+ return PVRSRV_OK;
+
+exitFailAlloc:
+exitFailMap:
+ PVR_ASSERT(eError!= PVRSRV_OK);
+ return eError;
+}
+
+static void DmaBufPhysAddrRelease(PMR_DMA_BUF_DATA *psPrivData)
+{
+ struct dma_buf_attachment *psAttachment = psPrivData->psAttachment;
+ struct sg_table *psSgTable = psPrivData->psSgTable;
+
+ dma_buf_unmap_attachment(psAttachment, psSgTable, DMA_NONE);
+
+ OSFreeMem(psPrivData->pasDevPhysAddr);
+}
+
+static IMG_BOOL _DmaBufKeyCompare(IMG_SIZE_T uKeySize, void *pKey1, void *pKey2)
+{
+ IMG_DEV_PHYADDR *psKey1 = pKey1;
+ IMG_DEV_PHYADDR *psKey2 = pKey2;
+ PVR_ASSERT(uKeySize == sizeof(IMG_DEV_PHYADDR));
+
+ return psKey1->uiAddr == psKey2->uiAddr;
+}
+
+/*****************************************************************************
+ * PMR callback functions *
+ *****************************************************************************/
+
+
+static void _Poison(IMG_PVOID pvKernAddr, IMG_DEVMEM_SIZE_T uiBufferSize,
+ const IMG_CHAR *pacPoisonData, IMG_SIZE_T uiPoisonSize)
+{
+ IMG_DEVMEM_SIZE_T uiDestByteIndex;
+ IMG_CHAR *pcDest = pvKernAddr;
+ IMG_UINT32 uiSrcByteIndex = 0;
+
+ for(uiDestByteIndex=0; uiDestByteIndex<uiBufferSize; uiDestByteIndex++)
+ {
+ pcDest[uiDestByteIndex] = pacPoisonData[uiSrcByteIndex];
+ uiSrcByteIndex++;
+ if (uiSrcByteIndex == uiPoisonSize)
+ {
+ uiSrcByteIndex = 0;
+ }
+ }
+}
+
+static const IMG_CHAR _AllocPoison[] = "^PoIsOn";
+static const IMG_UINT32 _AllocPoisonSize = 7;
+static const IMG_CHAR _FreePoison[] = "<DEAD-BEEF>";
+static const IMG_UINT32 _FreePoisonSize = 11;
+
+static PVRSRV_ERROR PMRFinalizeDmaBuf(PMR_IMPL_PRIVDATA pvPriv)
+{
+ PMR_DMA_BUF_DATA *psPrivData = pvPriv;
+
+ HASH_Remove_Extended(g_psDmaBufHash, &psPrivData->pasDevPhysAddr[0]);
+ g_ui32HashRefCount--;
+ if (g_ui32HashRefCount == 0)
+ {
+ HASH_Delete(g_psDmaBufHash);
+ g_psDmaBufHash = IMG_NULL;
+ }
+
+ if (psPrivData->bPDumpMalloced)
+ {
+ PDumpPMRFree(psPrivData->hPDumpAllocInfo);
+ }
+
+ if (psPrivData->bPoisonOnFree)
+ {
+ IMG_PVOID pvKernAddr;
+ int i, err;
+
+ err = dma_buf_begin_cpu_access(psPrivData->psDmaBuf, 0,
+ psPrivData->uiSize, DMA_NONE);
+ if (err)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to begin cpu access", __func__));
+ PVR_ASSERT(IMG_FALSE);
+ }
+
+ for (i = 0; i < psPrivData->uiSize / PAGE_SIZE; i++)
+ {
+ pvKernAddr = dma_buf_kmap(psPrivData->psDmaBuf, i);
+
+ if (IS_ERR_OR_NULL(pvKernAddr))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to poison allocation before free", __func__));
+ PVR_ASSERT(IMG_FALSE);
+ }
+
+ _Poison(pvKernAddr, PAGE_SIZE, _FreePoison, _FreePoisonSize);
+
+ dma_buf_kunmap(psPrivData->psDmaBuf, i, pvKernAddr);
+ }
+
+ dma_buf_end_cpu_access(psPrivData->psDmaBuf, 0,
+ psPrivData->uiSize, DMA_NONE);
+ }
+
+ DmaBufPhysAddrRelease(psPrivData);
+ dma_buf_detach(psPrivData->psDmaBuf, psPrivData->psAttachment);
+ dma_buf_put(psPrivData->psDmaBuf);
+ PhysHeapRelease(psPrivData->psPhysHeap);
+ OSFreeMem(psPrivData);
+
+ return PVRSRV_OK;
+}
+
+/*
+ Lock and unlock function for physical address
+ don't do anything for as we acquire the physical
+ address at create time.
+*/
+static PVRSRV_ERROR PMRLockPhysAddressesDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_UINT32 uiLog2DevPageSize)
+{
+ PVR_UNREFERENCED_PARAMETER(pvPriv);
+ PVR_UNREFERENCED_PARAMETER(uiLog2DevPageSize);
+
+ return PVRSRV_OK;
+
+}
+
+static PVRSRV_ERROR PMRUnlockPhysAddressesDmaBuf(PMR_IMPL_PRIVDATA pvPriv)
+{
+ PVR_UNREFERENCED_PARAMETER(pvPriv);
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR PMRDevPhysAddrDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PMR_DMA_BUF_DATA *psPrivData = pvPriv;
+ IMG_UINT32 ui32PageCount;
+ IMG_UINT32 ui32PageIndex;
+ IMG_UINT32 ui32InPageOffset;
+
+ ui32PageCount = psPrivData->ui32PageCount;
+
+ ui32PageIndex = uiOffset >> PAGE_SHIFT;
+ ui32InPageOffset = uiOffset - ((IMG_DEVMEM_OFFSET_T)ui32PageIndex << PAGE_SHIFT);
+ PVR_ASSERT(ui32PageIndex < ui32PageCount);
+ PVR_ASSERT(ui32InPageOffset < PAGE_SIZE);
+
+ psDevPAddr->uiAddr = psPrivData->pasDevPhysAddr[ui32PageIndex].uiAddr + ui32InPageOffset;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PMRAcquireKernelMappingDataDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ void **ppvKernelAddressOut,
+ IMG_HANDLE *phHandleOut,
+ PMR_FLAGS_T ulFlags)
+{
+ PMR_DMA_BUF_DATA *psPrivData = pvPriv;
+ IMG_PVOID pvKernAddr;
+ PVRSRV_ERROR eError;
+ int err;
+
+ PVR_ASSERT(psPrivData->pvKernAddr == IMG_NULL);
+
+ err = dma_buf_begin_cpu_access(psPrivData->psDmaBuf, 0,
+ psPrivData->uiSize, DMA_NONE);
+ if (err)
+ {
+ eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
+ goto fail;
+ }
+
+ pvKernAddr = dma_buf_vmap(psPrivData->psDmaBuf);
+ if (IS_ERR_OR_NULL(pvKernAddr))
+ {
+ eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
+ goto fail_kmap;
+ }
+
+ *ppvKernelAddressOut = pvKernAddr + uiOffset;
+ psPrivData->pvKernAddr = pvKernAddr;
+ return PVRSRV_OK;
+
+fail_kmap:
+ dma_buf_end_cpu_access(psPrivData->psDmaBuf, 0,
+ psPrivData->uiSize, DMA_NONE);
+fail:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+static void PMRReleaseKernelMappingDataDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_HANDLE hHandle)
+{
+ PMR_DMA_BUF_DATA *psPrivData = pvPriv;
+
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+
+ dma_buf_vunmap(psPrivData->psDmaBuf, psPrivData->pvKernAddr);
+ psPrivData->pvKernAddr = IMG_NULL;
+
+ dma_buf_end_cpu_access(psPrivData->psDmaBuf, 0,
+ psPrivData->uiSize, DMA_NONE);
+}
+
+static PMR_IMPL_FUNCTAB _sPMRDmaBufFuncTab =
+{
+ .pfnLockPhysAddresses = PMRLockPhysAddressesDmaBuf,
+ .pfnUnlockPhysAddresses = PMRUnlockPhysAddressesDmaBuf,
+ .pfnDevPhysAddr = PMRDevPhysAddrDmaBuf,
+ .pfnAcquireKernelMappingData = PMRAcquireKernelMappingDataDmaBuf,
+ .pfnReleaseKernelMappingData = PMRReleaseKernelMappingDataDmaBuf,
+ .pfnFinalize = PMRFinalizeDmaBuf,
+};
+
+/*****************************************************************************
+ * Public facing interface *
+ *****************************************************************************/
+
+PVRSRV_ERROR
+PhysmemImportDmaBuf(CONNECTION_DATA *psConnection,
+ IMG_INT fd,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr,
+ IMG_DEVMEM_SIZE_T *puiSize,
+ IMG_DEVMEM_ALIGN_T *puiAlign)
+{
+ PMR_DMA_BUF_DATA *psPrivData = IMG_NULL;
+ IMG_HANDLE hPDumpAllocInfo = IMG_NULL;
+ IMG_BOOL bMappingTable = IMG_TRUE;
+ IMG_BOOL bPoisonOnAlloc;
+ IMG_BOOL bPoisonOnFree;
+ PMR_FLAGS_T uiPMRFlags;
+ PMR *psPMR = IMG_NULL;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bZero;
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+ {
+ bZero = IMG_TRUE;
+ }
+ else
+ {
+ bZero = IMG_FALSE;
+ }
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC)
+ {
+ bPoisonOnAlloc = IMG_TRUE;
+ }
+ else
+ {
+ bPoisonOnAlloc = IMG_FALSE;
+ }
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE)
+ {
+ bPoisonOnFree = IMG_TRUE;
+ }
+ else
+ {
+ bPoisonOnFree = IMG_FALSE;
+ }
+
+ if ((uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &&
+ (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
+ {
+ /* Zero on Alloc and Poison on Alloc are mutually exclusive */
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto fail_params;
+ }
+
+ if (!psConnection)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto fail_params;
+ }
+
+ psPrivData = OSAllocMem(sizeof(*psPrivData));
+ if (psPrivData == NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_privalloc;
+ }
+
+ /*
+ Get the physical heap for this PMR
+
+ Note:
+ While we have no way to determine the type of the buffer
+ we just assume that all dmabufs are from the same
+ physical heap.
+ */
+ eError = PhysHeapAcquire(IonPhysHeapID(), &psPrivData->psPhysHeap);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed PhysHeapAcquire", __func__));
+ goto fail_physheap;
+ }
+
+ /* Get the buffer handle */
+ psPrivData->psDmaBuf = dma_buf_get(fd);
+
+ if (IS_ERR_OR_NULL(psPrivData->psDmaBuf))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: dma_buf_get failed", __func__));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto fail_dma_buf_get;
+ }
+
+ /* Attach a fake device to to the dmabuf */
+ psPrivData->psAttachment = dma_buf_attach(psPrivData->psDmaBuf, (void *)0x1);
+
+ if (IS_ERR_OR_NULL(psPrivData->psAttachment))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: dma_buf_get failed", __func__));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto fail_attach;
+ }
+
+ /*
+ Note:
+
+ We could defer the import until lock address time but we
+ do it here as then we can detect any errors at import time.
+ Also we need to know the dmabuf size here and there seems
+ to be no other way to find that other then map the buffer for dma.
+ */
+ eError = DmaBufPhysAddrAcquire(psPrivData, fd);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: DmaBufPhysAddrAcquire failed", __func__));
+ goto fail_acquire;
+ }
+
+ if (g_psDmaBufHash == IMG_NULL)
+ {
+ /*
+ As different processes may import the same dmabuf we need to
+ create a hash table so we don't generate a duplicate PMR but
+ rather just take a reference on an existing one.
+ */
+ g_psDmaBufHash = HASH_Create_Extended(DMA_BUF_HASH_SIZE, sizeof(psPrivData->pasDevPhysAddr[0]), HASH_Func_Default, _DmaBufKeyCompare);
+ if (g_psDmaBufHash == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ /*
+ We have a hash table so check if have already seen this
+ this dmabuf before
+ */
+ psPMR = (PMR *) HASH_Retrieve_Extended(g_psDmaBufHash, &psPrivData->pasDevPhysAddr[0]);
+ if (psPMR != IMG_NULL)
+ {
+ /*
+ We already know about this dmabuf but we had to do a bunch
+ for work to determine that so here we have to undo it
+ */
+ DmaBufPhysAddrRelease(psPrivData);
+ dma_buf_detach(psPrivData->psDmaBuf, psPrivData->psAttachment);
+ dma_buf_put(psPrivData->psDmaBuf);
+ PhysHeapRelease(psPrivData->psPhysHeap);
+ OSFreeMem(psPrivData);
+
+ /* Reuse the PMR we already created */
+ PMRRefPMR(psPMR);
+
+ *ppsPMRPtr = psPMR;
+ psPrivData = PMRGetPrivateDataHack(psPMR, &_sPMRDmaBufFuncTab);
+ *puiSize = psPrivData->uiSize;
+ *puiAlign = PAGE_SIZE;
+ return PVRSRV_OK;
+ }
+ }
+
+ if (bZero || bPoisonOnAlloc)
+ {
+ IMG_PVOID pvKernAddr;
+ int i, err;
+
+ err = dma_buf_begin_cpu_access(psPrivData->psDmaBuf, 0,
+ psPrivData->uiSize, DMA_NONE);
+ if (err)
+ {
+ eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
+ goto fail_begin;
+ }
+
+ for (i = 0; i < psPrivData->uiSize / PAGE_SIZE; i++)
+ {
+ pvKernAddr = dma_buf_kmap(psPrivData->psDmaBuf, i);
+
+ if (IS_ERR_OR_NULL(pvKernAddr))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to poison allocation before free", __func__));
+ eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
+ goto fail_kmap;
+ }
+
+ if (bZero)
+ {
+ memset(pvKernAddr, 0, PAGE_SIZE);
+ }
+ else
+ {
+ _Poison(pvKernAddr, PAGE_SIZE, _AllocPoison, _AllocPoisonSize);
+ }
+
+ dma_buf_kunmap(psPrivData->psDmaBuf, i, pvKernAddr);
+ }
+
+ dma_buf_end_cpu_access(psPrivData->psDmaBuf, 0,
+ psPrivData->uiSize, DMA_NONE);
+ }
+
+ psPrivData->bPoisonOnFree = bPoisonOnFree;
+
+ uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
+ /* check no significant bits were lost in cast due to different
+ bit widths for flags */
+ PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
+
+ eError = PMRCreatePMR(psPrivData->psPhysHeap,
+ psPrivData->uiSize,
+ psPrivData->uiSize,
+ 1,
+ 1,
+ &bMappingTable,
+ PAGE_SHIFT,
+ uiPMRFlags,
+ "PMRDMABUF",
+ &_sPMRDmaBufFuncTab,
+ psPrivData,
+ &psPMR,
+ &hPDumpAllocInfo,
+ IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create PMR", __func__));
+ goto fail_pmrcreate;
+ }
+
+#if defined(PVR_RI_DEBUG)
+ {
+ eError = RIWritePMREntryKM (psPMR,
+ sizeof("DMABUF"),
+ "DMABUF",
+ psPrivData->uiSize);
+ }
+#endif
+
+ psPrivData->hPDumpAllocInfo = hPDumpAllocInfo;
+ psPrivData->bPDumpMalloced = IMG_TRUE;
+
+ /* First time we've seen this dmabuf so store it in the hash table */
+ HASH_Insert_Extended(g_psDmaBufHash, &psPrivData->pasDevPhysAddr[0], (IMG_UINTPTR_T) psPMR);
+ g_ui32HashRefCount++;
+
+ *ppsPMRPtr = psPMR;
+ *puiSize = psPrivData->uiSize;
+ *puiAlign = PAGE_SIZE;
+ return PVRSRV_OK;
+
+fail_pmrcreate:
+fail_kmap:
+ dma_buf_end_cpu_access(psPrivData->psDmaBuf, 0,
+ psPrivData->uiSize, DMA_NONE);
+fail_begin:
+ DmaBufPhysAddrRelease(psPrivData);
+fail_acquire:
+ dma_buf_detach(psPrivData->psDmaBuf, psPrivData->psAttachment);
+fail_attach:
+ dma_buf_put(psPrivData->psDmaBuf);
+fail_dma_buf_get:
+ PhysHeapRelease(psPrivData->psPhysHeap);
+fail_physheap:
+ OSFreeMem(psPrivData);
+
+fail_privalloc:
+fail_params:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.c b/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.c
new file mode 100755
index 000000000000..4299add0737f
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/physmem_osmem_linux.c
@@ -0,0 +1,1640 @@
+/*************************************************************************/ /*!
+@File
+@Title Implementation of PMR functions for OS managed memory
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is responsible for
+ implementing the function callbacks for physical memory borrowed
+ from that normally managed by the operating system.
+@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.
+*/ /**************************************************************************/
+
+/* include5/ */
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+
+/* services/server/include/ */
+#include "allocmem.h"
+#include "osfunc.h"
+#include "pdump_physmem.h"
+#include "pdump_km.h"
+#include "pmr.h"
+#include "pmr_impl.h"
+#include "devicemem_server_utils.h"
+
+/* ourselves */
+#include "physmem_osmem.h"
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#include "process_stats.h"
+#endif
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0))
+#include <linux/mm.h>
+#define PHYSMEM_SUPPORTS_SHRINKER
+#endif
+
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/mm_types.h>
+#include <linux/vmalloc.h>
+#include <linux/gfp.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#if defined(CONFIG_X86)
+#include <asm/cacheflush.h>
+#endif
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined (CONFIG_METAG)
+#include "osfunc.h"
+#endif
+
+/* Provide SHRINK_STOP definition for kernel older than 3.12 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0))
+#define SHRINK_STOP (~0UL)
+#endif
+
+struct _PMR_OSPAGEARRAY_DATA_ {
+ /*
+ uiNumPages:
+
+ number of "pages" (a.k.a. macro pages, compound pages, higher
+ order pages, etc...)
+ */
+ IMG_UINT32 uiNumPages;
+
+ /*
+ uiLog2PageSize;
+
+ size of each "page" -- this would normally be the same as
+ PAGE_SHIFT, but we support the idea that we may allocate pages
+ in larger chunks for better contiguity, using order>0 in the
+ call to alloc_pages()
+ */
+ IMG_UINT32 uiLog2PageSize;
+
+ /*
+ the pages thusly allocated... N.B.. One entry per compound page,
+ where compound pages are used.
+ */
+ struct page **pagearray;
+
+ /*
+ for pdump...
+ */
+ IMG_BOOL bPDumpMalloced;
+ IMG_HANDLE hPDumpAllocInfo;
+
+ /*
+ record at alloc time whether poisoning will be required when the
+ PMR is freed.
+ */
+ IMG_BOOL bZero;
+ IMG_BOOL bPoisonOnFree;
+ IMG_BOOL bPoisonOnAlloc;
+ IMG_BOOL bHasOSPages;
+ IMG_BOOL bOnDemand;
+ /*
+ The cache mode of the PMR (required at free time)
+ Boolean used to track if we need to revert the cache attributes
+ of the pages used in this allocation. Depends on OS/architecture.
+ */
+ IMG_UINT32 ui32CPUCacheFlags;
+ IMG_BOOL bUnsetMemoryType;
+};
+
+/***********************************
+ * Page pooling for uncached pages *
+ ***********************************/
+
+static void
+_FreeOSPage(IMG_UINT32 ui32CPUCacheFlags,
+ IMG_UINT32 uiOrder,
+ IMG_BOOL bUnsetMemoryType,
+ IMG_BOOL bFreeToOS,
+ struct page *psPage);
+
+typedef struct
+{
+ /* Linkage for page pool LRU list */
+ struct list_head sPagePoolItem;
+
+ struct page *psPage;
+} LinuxPagePoolEntry;
+
+/* Track what is live */
+static IMG_UINT32 g_ui32PagePoolEntryCount = 0;
+static IMG_UINT32 g_ui32PagePoolMaxEntries = PVR_LINUX_PYSMEM_MAX_POOL_PAGES;
+static IMG_UINT32 g_ui32LiveAllocs = 0;
+
+/* Global structures we use to manage the page pool */
+static struct kmem_cache *g_psLinuxPagePoolCache = IMG_NULL;
+static LIST_HEAD(g_sPagePoolList);
+static DEFINE_MUTEX(g_sPagePoolMutex);
+static LIST_HEAD(g_sUncachedPagePoolList);
+
+static inline void
+_PagePoolLock(void)
+{
+ mutex_lock(&g_sPagePoolMutex);
+}
+
+static inline int
+_PagePoolTrylock(void)
+{
+ return mutex_trylock(&g_sPagePoolMutex);
+}
+
+static inline void
+_PagePoolUnlock(void)
+{
+ mutex_unlock(&g_sPagePoolMutex);
+}
+
+static LinuxPagePoolEntry *
+_LinuxPagePoolEntryAlloc(void)
+{
+ return kmem_cache_zalloc(g_psLinuxPagePoolCache, GFP_KERNEL);
+}
+
+static inline IMG_BOOL _GetPoolListHead(IMG_UINT32 ui32CPUCacheFlags, struct list_head **ppsPoolHead)
+{
+ switch(ui32CPUCacheFlags)
+ {
+ case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
+/*
+ For x86 we need to keep different lists for uncached
+ and write-combined as we must always honour the PAT
+ setting which cares about this difference.
+*/
+#if defined(CONFIG_X86)
+ *ppsPoolHead = &g_sUncachedPagePoolList;
+ break;
+#else
+ /* Fall-through */
+#endif
+ case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
+ *ppsPoolHead = &g_sPagePoolList;
+ break;
+ default:
+ return IMG_FALSE;
+ }
+ return IMG_TRUE;
+}
+
+static void
+_LinuxPagePoolEntryFree(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ kmem_cache_free(g_psLinuxPagePoolCache, psPagePoolEntry);
+}
+
+static inline IMG_BOOL
+_AddEntryToPool(struct page *psPage, IMG_UINT32 ui32CPUCacheFlags)
+{
+ LinuxPagePoolEntry *psEntry;
+ struct list_head *psPoolHead = IMG_NULL;
+
+ if (!_GetPoolListHead(ui32CPUCacheFlags, &psPoolHead))
+ {
+ return IMG_FALSE;
+ }
+
+ psEntry = _LinuxPagePoolEntryAlloc();
+ if (psEntry == NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ psEntry->psPage = psPage;
+ _PagePoolLock();
+ list_add_tail(&psEntry->sPagePoolItem, psPoolHead);
+ g_ui32PagePoolEntryCount++;
+ _PagePoolUnlock();
+
+ return IMG_TRUE;
+}
+
+static inline void
+_RemoveEntryFromPoolUnlocked(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ list_del(&psPagePoolEntry->sPagePoolItem);
+ g_ui32PagePoolEntryCount--;
+}
+
+static inline struct page *
+_RemoveFirstEntryFromPool(IMG_UINT32 ui32CPUCacheFlags)
+{
+ LinuxPagePoolEntry *psPagePoolEntry;
+ struct page *psPage;
+ struct list_head *psPoolHead = IMG_NULL;
+
+ if (!_GetPoolListHead(ui32CPUCacheFlags, &psPoolHead))
+ {
+ return NULL;
+ }
+
+ _PagePoolLock();
+ if (list_empty(psPoolHead))
+ {
+ _PagePoolUnlock();
+ return NULL;
+ }
+
+ PVR_ASSERT(g_ui32PagePoolEntryCount > 0);
+ psPagePoolEntry = list_first_entry(psPoolHead, LinuxPagePoolEntry, sPagePoolItem);
+ _RemoveEntryFromPoolUnlocked(psPagePoolEntry);
+ psPage = psPagePoolEntry->psPage;
+ _LinuxPagePoolEntryFree(psPagePoolEntry);
+ _PagePoolUnlock();
+
+ return psPage;
+}
+
+#if defined(PHYSMEM_SUPPORTS_SHRINKER)
+static struct shrinker g_sShrinker;
+
+static unsigned long
+_CountObjectsInPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl)
+{
+ int remain;
+
+ PVR_ASSERT(psShrinker == &g_sShrinker);
+ (void)psShrinker;
+ (void)psShrinkControl;
+
+ /* In order to avoid possible deadlock use mutex_trylock in place of mutex_lock */
+ if (_PagePoolTrylock() == 0)
+ return 0;
+ remain = g_ui32PagePoolEntryCount;
+ _PagePoolUnlock();
+
+ return remain;
+}
+
+static unsigned long
+_ScanObjectsInPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl)
+{
+ unsigned long uNumToScan = psShrinkControl->nr_to_scan;
+ LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
+ int remain;
+
+ PVR_ASSERT(psShrinker == &g_sShrinker);
+ (void)psShrinker;
+
+ /* In order to avoid possible deadlock use mutex_trylock in place of mutex_lock */
+ if (_PagePoolTrylock() == 0)
+ return SHRINK_STOP;
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
+ {
+ _RemoveEntryFromPoolUnlocked(psPagePoolEntry);
+
+ /*
+ We don't want to save the cache type and is we need to unset the
+ memory type as it would double the page pool structure and the
+ values are always going to be the same anyway which is why the
+ page is in the pool (well the page could be UNCACHED or
+ WRITE_COMBINE but we don't even need the cache type for freeing
+ back to the OS).
+ */
+ _FreeOSPage(PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE,
+ 0,
+ IMG_TRUE,
+ IMG_TRUE,
+ psPagePoolEntry->psPage);
+ _LinuxPagePoolEntryFree(psPagePoolEntry);
+
+ if (--uNumToScan == 0)
+ {
+ break;
+ }
+ }
+
+ /*
+ Note:
+ For anything other then x86 this list will be empty but we want to
+ keep differences between compiled code to a minimum and so
+ this isn't wrapped in #if defined(CONFIG_X86)
+ */
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sUncachedPagePoolList, sPagePoolItem)
+ {
+ _RemoveEntryFromPoolUnlocked(psPagePoolEntry);
+
+ /*
+ We don't want to save the cache type and is we need to unset the
+ memory type as it would double the page pool structure and the
+ values are always going to be the same anyway which is why the
+ page is in the pool (well the page could be UNCACHED or
+ WRITE_COMBINE but we don't even need the cache type for freeing
+ back to the OS).
+ */
+ _FreeOSPage(PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
+ 0,
+ IMG_TRUE,
+ IMG_TRUE,
+ psPagePoolEntry->psPage);
+ _LinuxPagePoolEntryFree(psPagePoolEntry);
+
+ if (--uNumToScan == 0)
+ {
+ break;
+ }
+ }
+
+ if (list_empty(&g_sPagePoolList) && list_empty(&g_sUncachedPagePoolList))
+ {
+ PVR_ASSERT(g_ui32PagePoolEntryCount == 0);
+ }
+ remain = g_ui32PagePoolEntryCount;
+ _PagePoolUnlock();
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0))
+ return remain;
+#else
+ return psShrinkControl->nr_to_scan - uNumToScan;
+#endif
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0))
+static int
+_ShrinkPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl)
+{
+ if (psShrinkControl->nr_to_scan != 0)
+ {
+ return _ScanObjectsInPagePool(psShrinker, psShrinkControl);
+ }
+ else
+ {
+ /* No pages are being reclaimed so just return the page count */
+ return _CountObjectsInPagePool(psShrinker, psShrinkControl);
+ }
+}
+
+static struct shrinker g_sShrinker =
+{
+ .shrink = _ShrinkPagePool,
+ .seeks = DEFAULT_SEEKS
+};
+#else
+static struct shrinker g_sShrinker =
+{
+ .count_objects = _CountObjectsInPagePool,
+ .scan_objects = _ScanObjectsInPagePool,
+ .seeks = DEFAULT_SEEKS
+};
+#endif
+#endif /* defined(PHYSMEM_SUPPORTS_SHRINKER) */
+
+static void DisableOOMKiller(void)
+{
+ /* PF_DUMPCORE is treated by the VM as if the OOM killer was disabled.
+ *
+ * As oom_killer_disable() is an inline, non-exported function, we
+ * can't use it from a modular driver. Furthermore, the OOM killer
+ * API doesn't look thread safe, which `current' is.
+ */
+ WARN_ON(current->flags & PF_DUMPCORE);
+ current->flags |= PF_DUMPCORE;
+}
+
+static void _InitPagePool(void)
+{
+ IMG_UINT32 ui32Flags = 0;
+
+ _PagePoolLock();
+#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS)
+ ui32Flags |= SLAB_POISON|SLAB_RED_ZONE;
+#endif
+ g_psLinuxPagePoolCache = kmem_cache_create("img-pp", sizeof(LinuxPagePoolEntry), 0, ui32Flags, NULL);
+
+#if defined(PHYSMEM_SUPPORTS_SHRINKER)
+ /* Only create the shrinker if we created the cache OK */
+ if (g_psLinuxPagePoolCache)
+ {
+ register_shrinker(&g_sShrinker);
+ }
+#endif
+ _PagePoolUnlock();
+}
+
+static void _DeinitPagePool(void)
+{
+ LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
+
+ _PagePoolLock();
+ /* Evict all the pages from the pool */
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
+ {
+ _RemoveEntryFromPoolUnlocked(psPagePoolEntry);
+
+ /*
+ We don't want to save the cache type and is we need to unset the
+ memory type as it would double the page pool structure and the
+ values are always going to be the same anyway which is why the
+ page is in the pool (well the page could be UNCACHED or
+ WRITE_COMBINE but we don't even need the cache type for freeing
+ back to the OS).
+ */
+ _FreeOSPage(PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE,
+ 0,
+ IMG_TRUE,
+ IMG_TRUE,
+ psPagePoolEntry->psPage);
+ _LinuxPagePoolEntryFree(psPagePoolEntry);
+ }
+
+ /*
+ Note:
+ For anything other then x86 this will be a no-op but we want to
+ keep differences between compiled code to a minimum and so
+ this isn't wrapped in #if defined(CONFIG_X86)
+ */
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sUncachedPagePoolList, sPagePoolItem)
+ {
+ _RemoveEntryFromPoolUnlocked(psPagePoolEntry);
+
+ /*
+ We don't want to save the cache type and is we need to unset the
+ memory type as it would double the page pool structure and the
+ values are always going to be the same anyway which is why the
+ page is in the pool (well the page could be UNCACHED or
+ WRITE_COMBINE but we don't even need the cache type for freeing
+ back to the OS).
+ */
+ _FreeOSPage(PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
+ 0,
+ IMG_TRUE,
+ IMG_TRUE,
+ psPagePoolEntry->psPage);
+ _LinuxPagePoolEntryFree(psPagePoolEntry);
+ }
+
+ PVR_ASSERT(g_ui32PagePoolEntryCount == 0);
+
+ /* Free the page cache */
+ kmem_cache_destroy(g_psLinuxPagePoolCache);
+
+#if defined(PHYSMEM_SUPPORTS_SHRINKER)
+ unregister_shrinker(&g_sShrinker);
+#endif
+ _PagePoolUnlock();
+}
+
+static void EnableOOMKiller(void)
+{
+ current->flags &= ~PF_DUMPCORE;
+}
+
+static void
+_PoisonPages(struct page *page,
+ IMG_UINT32 uiOrder,
+ const IMG_CHAR *pacPoisonData,
+ IMG_SIZE_T uiPoisonSize)
+{
+ void *kvaddr;
+ IMG_UINT32 uiSrcByteIndex;
+ IMG_UINT32 uiDestByteIndex;
+ IMG_UINT32 uiSubPageIndex;
+ IMG_CHAR *pcDest;
+
+ uiSrcByteIndex = 0;
+ for (uiSubPageIndex = 0; uiSubPageIndex < (1U << uiOrder); uiSubPageIndex++)
+ {
+ kvaddr = kmap(page + uiSubPageIndex);
+
+ pcDest = kvaddr;
+
+ for(uiDestByteIndex=0; uiDestByteIndex<PAGE_SIZE; uiDestByteIndex++)
+ {
+ pcDest[uiDestByteIndex] = pacPoisonData[uiSrcByteIndex];
+ uiSrcByteIndex++;
+ if (uiSrcByteIndex == uiPoisonSize)
+ {
+ uiSrcByteIndex = 0;
+ }
+ }
+ kunmap(page + uiSubPageIndex);
+ }
+}
+
+static const IMG_CHAR _AllocPoison[] = "^PoIsOn";
+static const IMG_UINT32 _AllocPoisonSize = 7;
+static const IMG_CHAR _FreePoison[] = "<DEAD-BEEF>";
+static const IMG_UINT32 _FreePoisonSize = 11;
+
+static PVRSRV_ERROR
+_AllocOSPageArray(PMR_SIZE_T uiSize,
+ IMG_UINT32 uiLog2PageSize,
+ IMG_BOOL bZero,
+ IMG_BOOL bPoisonOnAlloc,
+ IMG_BOOL bPoisonOnFree,
+ IMG_BOOL bOnDemand,
+ IMG_UINT32 ui32CPUCacheFlags,
+ struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr)
+{
+ PVRSRV_ERROR eError;
+ void *pvData;
+ IMG_UINT32 uiNumPages;
+
+ struct page **ppsPageArray;
+ struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData;
+
+ if (uiSize >= 0x1000000000ULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "physmem_osmem_linux.c: Do you really want 64GB of physical memory in one go? This is likely a bug"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e_freed_pvdata;
+ }
+
+ PVR_ASSERT(PAGE_SHIFT <= uiLog2PageSize);
+ if ((uiSize & ((1ULL << uiLog2PageSize) - 1)) != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Allocation size "PMR_SIZE_FMTSPEC" is not multiple of page size 2^%u !",
+ uiSize,
+ uiLog2PageSize));
+
+ eError = PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE;
+ goto e_freed_pvdata;
+ }
+
+ /* Use of cast below is justified by the assertion that follows to
+ prove that no significant bits have been truncated */
+ uiNumPages = (IMG_UINT32)(((uiSize-1)>>uiLog2PageSize) + 1);
+ PVR_ASSERT(((PMR_SIZE_T)uiNumPages << uiLog2PageSize) == uiSize);
+
+ pvData = OSAllocMem(sizeof(struct _PMR_OSPAGEARRAY_DATA_) +
+ sizeof(struct page *) * uiNumPages);
+ if (pvData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "physmem_osmem_linux.c: OS refused the memory allocation for the table of pages. Did you ask for too much?"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e_freed_pvdata;
+ }
+ PVR_ASSERT(pvData != IMG_NULL);
+
+ psPageArrayData = pvData;
+ ppsPageArray = pvData + sizeof(struct _PMR_OSPAGEARRAY_DATA_);
+ psPageArrayData->pagearray = ppsPageArray;
+ psPageArrayData->uiLog2PageSize = uiLog2PageSize;
+ psPageArrayData->uiNumPages = uiNumPages;
+ psPageArrayData->bZero = bZero;
+ psPageArrayData->ui32CPUCacheFlags = ui32CPUCacheFlags;
+ psPageArrayData->bPoisonOnAlloc = bPoisonOnAlloc;
+ psPageArrayData->bPoisonOnFree = bPoisonOnFree;
+ psPageArrayData->bHasOSPages = IMG_FALSE;
+ psPageArrayData->bOnDemand = bOnDemand;
+
+ psPageArrayData->bPDumpMalloced = IMG_FALSE;
+
+ psPageArrayData->bUnsetMemoryType = IMG_FALSE;
+
+ *ppsPageArrayDataPtr = psPageArrayData;
+
+ return PVRSRV_OK;
+
+e_freed_pvdata:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+
+}
+
+static PVRSRV_ERROR
+_AllocOSPage(IMG_UINT32 ui32CPUCacheFlags,
+ unsigned int gfp_flags,
+ IMG_BOOL bFlush,
+ IMG_UINT32 uiOrder,
+ struct page **ppsPage,
+ IMG_BOOL *pbPageFromPool)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_PVOID pvPageVAddr;
+ struct page *psPage = IMG_NULL;
+ *pbPageFromPool = IMG_FALSE;
+
+ /* Does the requested page contiguity match the CPU page size? */
+ if (uiOrder == 0)
+ {
+ psPage = _RemoveFirstEntryFromPool(ui32CPUCacheFlags);
+ if (psPage != IMG_NULL)
+ {
+ *pbPageFromPool = IMG_TRUE;
+ }
+ }
+
+ /*
+ Did we check the page pool and/or was it a page pool miss,
+ either the pool was empty or it was for a cached page so we
+ must ask the OS and do the cache management as required.
+ */
+ if (!*pbPageFromPool)
+ {
+ DisableOOMKiller();
+ psPage = alloc_pages(gfp_flags, uiOrder);
+ EnableOOMKiller();
+
+#if defined (CONFIG_ARM) || defined(CONFIG_ARM64) || defined (CONFIG_METAG)
+ /*
+ On ARM kernels we can be given pages which still remain in the cache.
+ In order to make sure that the data we write through our mappings
+ doesn't get over written by later cache evictions we invalidate the
+ pages that get given to us.
+
+ Note:
+ This still seems to be true if we request cold pages, it's just less
+ likely to be in the cache.
+ */
+ if (psPage != IMG_NULL)
+ {
+ pvPageVAddr = kmap(psPage);
+
+ if (ui32CPUCacheFlags != PVRSRV_MEMALLOCFLAG_CPU_CACHED)
+ {
+ IMG_CPU_PHYADDR sCPUPhysAddrStart, sCPUPhysAddrEnd;
+
+ sCPUPhysAddrStart.uiAddr = page_to_phys(psPage);
+ sCPUPhysAddrEnd.uiAddr = sCPUPhysAddrStart.uiAddr + PAGE_SIZE;
+
+ /* If we're zeroing, we need to make sure the cleared memory is pushed out
+ of the cache before the cache lines are invalidated */
+ if (bFlush)
+ {
+ OSFlushCPUCacheRangeKM(pvPageVAddr,
+ pvPageVAddr + PAGE_SIZE,
+ sCPUPhysAddrStart,
+ sCPUPhysAddrEnd);
+ }
+ else
+ {
+ OSInvalidateCPUCacheRangeKM(pvPageVAddr,
+ pvPageVAddr + PAGE_SIZE,
+ sCPUPhysAddrStart,
+ sCPUPhysAddrEnd);
+ }
+ }
+ kunmap(psPage);
+ }
+#endif
+ }
+ else
+ {
+ /*
+ The kernel will zero the page for us when we allocate it, but if it
+ comes from the pool then we must do this ourselves.
+ */
+ if (psPage != IMG_NULL && gfp_flags & __GFP_ZERO)
+ {
+ pvPageVAddr = kmap(psPage);
+ memset(pvPageVAddr, 0, PAGE_SIZE);
+
+#if defined (CONFIG_ARM) || defined(CONFIG_ARM64) || defined (CONFIG_METAG)
+ if (ui32CPUCacheFlags != PVRSRV_MEMALLOCFLAG_CPU_CACHED)
+ {
+ IMG_CPU_PHYADDR sCPUPhysAddrStart, sCPUPhysAddrEnd;
+
+ sCPUPhysAddrStart.uiAddr = page_to_phys(psPage);
+ sCPUPhysAddrEnd.uiAddr = sCPUPhysAddrStart.uiAddr + PAGE_SIZE;
+
+ if (bFlush)
+ {
+ OSFlushCPUCacheRangeKM(pvPageVAddr,
+ pvPageVAddr + PAGE_SIZE,
+ sCPUPhysAddrStart,
+ sCPUPhysAddrEnd);
+ }
+ else
+ {
+ OSInvalidateCPUCacheRangeKM(pvPageVAddr,
+ pvPageVAddr + PAGE_SIZE,
+ sCPUPhysAddrStart,
+ sCPUPhysAddrEnd);
+ }
+ }
+#endif
+
+ kunmap(psPage);
+ }
+ }
+
+ if(IMG_NULL == (*ppsPage = psPage)){
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ return eError;
+}
+
+
+/*
+ Note:
+ We must _only_ check bUnsetMemoryType in the case where we need to free
+ the page back to the OS since we may have to revert the cache properties
+ of the page to the default as given by the OS when it was allocated.
+*/
+static void
+_FreeOSPage(IMG_UINT32 ui32CPUCacheFlags,
+ IMG_UINT32 uiOrder,
+ IMG_BOOL bUnsetMemoryType,
+ IMG_BOOL bFreeToOS,
+ struct page *psPage)
+{
+ IMG_BOOL bAddedToPool = IMG_FALSE;
+#if defined (CONFIG_X86)
+ IMG_PVOID pvPageVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(bUnsetMemoryType);
+#endif
+
+ /* Only zero order pages can be managed in the pool */
+ if ((uiOrder == 0) && (!bFreeToOS))
+ {
+ _PagePoolLock();
+ bAddedToPool = g_ui32PagePoolEntryCount < g_ui32PagePoolMaxEntries;
+ _PagePoolUnlock();
+
+ if (bAddedToPool)
+ {
+ if (!_AddEntryToPool(psPage, ui32CPUCacheFlags))
+ {
+ bAddedToPool = IMG_FALSE;
+ }
+ }
+ }
+
+ if (!bAddedToPool)
+ {
+#if defined(CONFIG_X86)
+ pvPageVAddr = page_address(psPage);
+ if (pvPageVAddr && bUnsetMemoryType == IMG_TRUE)
+ {
+ int ret;
+
+ ret = set_memory_wb((unsigned long)pvPageVAddr, 1);
+ if (ret)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to reset page attribute", __FUNCTION__));
+ }
+ }
+#endif
+ __free_pages(psPage, uiOrder);
+ }
+}
+
+static PVRSRV_ERROR
+_AllocOSPages(struct _PMR_OSPAGEARRAY_DATA_ **ppsPageArrayDataPtr)
+{
+ /* Allocate a bunch of physical memory. Must be whole number of
+ pages worth */
+ PVRSRV_ERROR eError;
+ IMG_UINT32 uiOrder;
+ IMG_UINT32 uiPageIndex;
+ IMG_UINT32 ui32CPUCacheFlags;
+ IMG_BOOL bPageFromPool = IMG_FALSE;
+
+ struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData = *ppsPageArrayDataPtr;
+ struct page **ppsPageArray = psPageArrayData->pagearray;
+
+ unsigned int gfp_flags;
+
+#if defined (CONFIG_X86)
+ /* On x86 we might have to change the page cache attributes.
+ * We do this by storing references to all the changed pages that are not
+ * from the page pool and then set the attribute of all the pages at once.
+ * This saves us calling set_memory_XX() and therefore a cache flush every time
+ */
+ struct page **apsUnsetPages = OSAllocMem(sizeof(struct page*) * psPageArrayData->uiNumPages);
+ IMG_UINT32 uiUnsetPagesIndex = 0;
+
+ if (apsUnsetPages == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "physmem_osmem_linux.c: Could not allocate temporary structure, system probably OOM"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e_exit;
+ }
+
+#endif
+
+
+
+ PVR_ASSERT(!psPageArrayData->bHasOSPages);
+
+ /* Try and create the page pool if required */
+ if ((g_ui32PagePoolMaxEntries > 0) && (g_psLinuxPagePoolCache == NULL))
+ {
+ _InitPagePool();
+ }
+
+ uiOrder = psPageArrayData->uiLog2PageSize - PAGE_SHIFT;
+ ui32CPUCacheFlags = psPageArrayData->ui32CPUCacheFlags;
+
+ gfp_flags = GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC;
+
+#if defined(CONFIG_X86)
+ gfp_flags |= __GFP_DMA32;
+#else
+ gfp_flags |= __GFP_HIGHMEM;
+#endif
+
+ if (psPageArrayData->bZero)
+ {
+ gfp_flags |= __GFP_ZERO;
+ }
+
+ /*
+ Unset memory type is set to true as although in the "normal" case
+ (where we free the page back to the pool) we don't want to unset
+ it, we _must_ unset it in the case where the page pool was full
+ and thus we have to give the page back to the OS.
+ */
+ if (ui32CPUCacheFlags == PVRSRV_MEMALLOCFLAG_CPU_UNCACHED
+ ||ui32CPUCacheFlags == PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE)
+ {
+ psPageArrayData->bUnsetMemoryType = IMG_TRUE;
+ }
+ else
+ {
+ psPageArrayData->bUnsetMemoryType = IMG_FALSE;
+ }
+
+ /* Allocate pages one at a time. Note that the _device_ memory
+ page size may be different from the _host_ cpu page size - we
+ have a concept of a minimum contiguity requirement, which must
+ be sufficient to meet the requirement of both device and host
+ page size (and possibly other devices or other external
+ constraints). We are allocating ONE "minimum contiguity unit"
+ (in practice, generally a _device_ page, but not necessarily)
+ at a time, by asking the OS for 2**uiOrder _host_ pages at a
+ time. */
+ for (uiPageIndex = 0;
+ uiPageIndex < psPageArrayData->uiNumPages;
+ uiPageIndex++)
+ {
+ /* For now we don't support compound pages */
+ PVR_ASSERT(uiOrder == 0);
+
+ eError = _AllocOSPage(ui32CPUCacheFlags,
+ gfp_flags,
+ psPageArrayData->bZero,
+ uiOrder,
+ &ppsPageArray[uiPageIndex],
+ &bPageFromPool);
+
+#if defined(CONFIG_X86)
+ if (!bPageFromPool)
+ {
+ apsUnsetPages[uiUnsetPagesIndex] = ppsPageArray[uiPageIndex];
+ uiUnsetPagesIndex++;
+ }
+#endif
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "physmem_osmem_linux.c: alloc_pages failed to honour request at %d of %d (%s)",
+ uiPageIndex,
+ psPageArrayData->uiNumPages,
+ PVRSRVGetErrorStringKM(eError)));
+ for(--uiPageIndex;uiPageIndex < psPageArrayData->uiNumPages;--uiPageIndex)
+ {
+ _FreeOSPage(ui32CPUCacheFlags,
+ uiOrder,
+ IMG_TRUE,
+ IMG_TRUE,
+ ppsPageArray[uiPageIndex]);
+ }
+ eError = PVRSRV_ERROR_PMR_FAILED_TO_ALLOC_PAGES;
+ goto e_freed_pages;
+ }
+
+ /* Can't ask us to zero it and poison it */
+ PVR_ASSERT(!psPageArrayData->bZero || !psPageArrayData->bPoisonOnAlloc);
+
+ if (psPageArrayData->bPoisonOnAlloc)
+ {
+ _PoisonPages(ppsPageArray[uiPageIndex],
+ uiOrder,
+ _AllocPoison,
+ _AllocPoisonSize);
+ }
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Allocation is done a page at a time */
+ PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, PAGE_SIZE);
+#else
+ {
+ IMG_CPU_PHYADDR sCPUPhysAddr;
+ sCPUPhysAddr.uiAddr = page_to_phys(ppsPageArray[uiPageIndex]);
+ PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES,
+ IMG_NULL,
+ sCPUPhysAddr,
+ PAGE_SIZE,
+ IMG_NULL);
+ }
+#endif
+#endif
+ }
+
+#if defined (CONFIG_X86)
+ /*
+ On X86 if we already have a mapping we need to change the mode of
+ current mapping before we map it ourselves
+ */
+ {
+ int ret = IMG_FALSE;
+
+ switch (ui32CPUCacheFlags)
+ {
+ case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
+ ret = set_pages_array_uc(apsUnsetPages, uiUnsetPagesIndex);
+ if (ret)
+ {
+ eError = PVRSRV_ERROR_UNABLE_TO_SET_CACHE_MODE;
+ PVR_DPF((PVR_DBG_ERROR, "Setting Linux page caching mode to UC failed, returned %d", ret));
+ }
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
+ ret = set_pages_array_wc(apsUnsetPages, uiUnsetPagesIndex);
+ if (ret)
+ {
+ eError = PVRSRV_ERROR_UNABLE_TO_SET_CACHE_MODE;
+ PVR_DPF((PVR_DBG_ERROR, "Setting Linux page caching mode to WC failed, returned %d", ret));
+ }
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
+ break;
+
+ default:
+ break;
+ }
+
+ if (ret)
+ {
+ for(uiPageIndex = 0;uiPageIndex < psPageArrayData->uiNumPages; uiPageIndex++)
+ {
+ _FreeOSPage(ui32CPUCacheFlags,
+ uiOrder,
+ IMG_FALSE,
+ IMG_FALSE,
+ ppsPageArray[uiPageIndex]);
+ }
+
+ goto e_freed_pages;
+ }
+
+ }
+
+ OSFreeMem(apsUnsetPages);
+#endif
+
+
+ /* OS Pages have been allocated */
+ psPageArrayData->bHasOSPages = IMG_TRUE;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "physmem_osmem_linux.c: allocated OS memory for PMR @0x%p", psPageArrayData));
+ g_ui32LiveAllocs++;
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow:
+ */
+
+e_freed_pages:
+#if defined (CONFIG_X86)
+ OSFreeMem(apsUnsetPages);
+e_exit:
+#endif
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+static PVRSRV_ERROR
+_FreeOSPagesArray(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
+{
+ PVR_DPF((PVR_DBG_MESSAGE, "physmem_osmem_linux.c: freed OS memory for PMR @0x%p", psPageArrayData));
+
+ OSFreeMem(psPageArrayData);
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_FreeOSPages(struct _PMR_OSPAGEARRAY_DATA_ *psPageArrayData)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 uiNumPages;
+ IMG_UINT32 uiOrder;
+ IMG_UINT32 uiPageIndex;
+ struct page **ppsPageArray;
+ IMG_BOOL bAddedToPool = IMG_FALSE;
+
+#if defined (CONFIG_X86)
+ IMG_UINT32 uiUnsetPagesIndex = 0;
+ struct page **apsUnsetPages = OSAllocMem(sizeof(struct page *) * psPageArrayData->uiNumPages);
+
+ if (apsUnsetPages == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Could not allocate temporary structure, "
+ "system probably OOM. Cannot free pages now.", __FUNCTION__));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e_exit;
+ }
+#endif
+
+ PVR_ASSERT(psPageArrayData->bHasOSPages);
+ g_ui32LiveAllocs--;
+
+ ppsPageArray = psPageArrayData->pagearray;
+
+ uiNumPages = psPageArrayData->uiNumPages;
+
+ uiOrder = psPageArrayData->uiLog2PageSize - PAGE_SHIFT;
+
+ for (uiPageIndex = 0;
+ uiPageIndex < uiNumPages;
+ uiPageIndex++)
+ {
+ if (psPageArrayData->bPoisonOnFree)
+ {
+ _PoisonPages(ppsPageArray[uiPageIndex],
+ uiOrder,
+ _FreePoison,
+ _FreePoisonSize);
+ }
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+ /* Allocation is done a page at a time */
+ PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, PAGE_SIZE);
+#else
+ {
+ IMG_CPU_PHYADDR sCPUPhysAddr;
+ sCPUPhysAddr.uiAddr = page_to_phys(ppsPageArray[uiPageIndex]);
+ PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, sCPUPhysAddr.uiAddr);
+ }
+#endif
+#endif
+
+
+ /* Only zero order pages can be managed in the pool */
+ if (uiOrder == 0)
+ {
+ _PagePoolLock();
+ bAddedToPool = g_ui32PagePoolEntryCount < g_ui32PagePoolMaxEntries;
+ _PagePoolUnlock();
+
+ if (bAddedToPool)
+ {
+ if (!_AddEntryToPool(ppsPageArray[uiPageIndex], psPageArrayData->ui32CPUCacheFlags))
+ {
+ bAddedToPool = IMG_FALSE;
+ }
+ }
+ }
+
+ if (!bAddedToPool)
+ {
+#if defined(CONFIG_X86)
+ if (psPageArrayData->bUnsetMemoryType == IMG_TRUE)
+ {
+ /* Keeping track of the pages for which the caching needs to change */
+ apsUnsetPages[uiUnsetPagesIndex] = ppsPageArray[uiPageIndex];
+ uiUnsetPagesIndex++;
+ }
+ else
+#endif
+ {
+ __free_pages(ppsPageArray[uiPageIndex], uiOrder);
+ }
+ }
+ }
+
+#if defined(CONFIG_X86)
+ if (uiUnsetPagesIndex != 0)
+ {
+ int ret;
+ ret = set_pages_array_wb(apsUnsetPages, uiUnsetPagesIndex);
+
+ if (ret)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to reset page attributes", __FUNCTION__));
+ }
+
+ for (uiPageIndex = 0;
+ uiPageIndex < uiUnsetPagesIndex;
+ uiPageIndex++)
+ {
+ __free_pages(apsUnsetPages[uiPageIndex], uiOrder);
+ }
+ }
+
+ OSFreeMem(apsUnsetPages);
+#endif
+
+ eError = PVRSRV_OK;
+
+ psPageArrayData->bHasOSPages = IMG_FALSE;
+
+ /* Destroy the page pool if required */
+ if ((g_ui32PagePoolMaxEntries > 0) && (g_psLinuxPagePoolCache != NULL) && (g_ui32LiveAllocs == 0))
+ {
+ _DeinitPagePool();
+ }
+#if defined(CONFIG_X86)
+e_exit:
+#endif
+ return eError;
+}
+
+/*
+ *
+ * Implementation of callback functions
+ *
+ */
+
+/* destructor func is called after last reference disappears, but
+ before PMR itself is freed. */
+static PVRSRV_ERROR
+PMRFinalizeOSMem(PMR_IMPL_PRIVDATA pvPriv
+ //struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData
+ )
+{
+ PVRSRV_ERROR eError;
+ struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
+
+ psOSPageArrayData = pvPriv;
+
+ /* Conditionally do the PDump free, because if CreatePMR failed we
+ won't have done the PDump MALLOC. */
+ if (psOSPageArrayData->bPDumpMalloced)
+ {
+ PDumpPMRFree(psOSPageArrayData->hPDumpAllocInfo);
+ }
+
+ /* We can't free pages until now. */
+ if (psOSPageArrayData->bHasOSPages)
+ {
+ eError = _FreeOSPages(psOSPageArrayData);
+ PVR_ASSERT (eError == PVRSRV_OK); /* can we do better? */
+ }
+
+ eError = _FreeOSPagesArray(psOSPageArrayData);
+ PVR_ASSERT (eError == PVRSRV_OK); /* can we do better? */
+
+ return PVRSRV_OK;
+}
+
+/* callback function for locking the system physical page addresses.
+ This function must be called before the lookup address func. */
+static PVRSRV_ERROR
+PMRLockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv,
+ // struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData,
+ IMG_UINT32 uiLog2DevPageSize)
+{
+ PVRSRV_ERROR eError;
+ struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
+
+ psOSPageArrayData = pvPriv;
+
+ if (psOSPageArrayData->bOnDemand)
+ {
+ /* Allocate Memory for deferred allocation */
+ eError = _AllocOSPages(&psOSPageArrayData);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ /* Physical page addresses are already locked down in this
+ implementation, so there is no need to acquire physical
+ addresses. We do need to verify that the physical contiguity
+ requested by the caller (i.e. page size of the device they
+ intend to map this memory into) is compatible with (i.e. not of
+ coarser granularity than) our already known physicial
+ contiguity of the pages */
+ if (uiLog2DevPageSize > psOSPageArrayData->uiLog2PageSize)
+ {
+ /* or NOT_MAPPABLE_TO_THIS_PAGE_SIZE ? */
+ eError = PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
+ return eError;
+ }
+
+ eError = PVRSRV_OK;
+ return eError;
+
+}
+
+static PVRSRV_ERROR
+PMRUnlockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv
+ //struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData
+ )
+{
+ /* Just drops the refcount. */
+
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
+
+ psOSPageArrayData = pvPriv;
+ if (psOSPageArrayData->bOnDemand)
+ {
+ /* Free Memory for deferred allocation */
+ eError = _FreeOSPages(psOSPageArrayData);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ PVR_ASSERT (eError == PVRSRV_OK);
+ return eError;
+}
+
+/* N.B. It is assumed that PMRLockSysPhysAddressesOSMem() is called _before_ this function! */
+static PVRSRV_ERROR
+PMRSysPhysAddrOSMem(PMR_IMPL_PRIVDATA pvPriv,
+ //const struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEV_PHYADDR *psDevPAddr
+ )
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 uiPageSize;
+ IMG_UINT32 uiNumPages;
+ IMG_UINT32 uiPageIndex;
+ IMG_UINT32 uiInPageOffset;
+ struct page **ppsPageArray;
+ const struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
+
+ psOSPageArrayData = pvPriv;
+ ppsPageArray = psOSPageArrayData->pagearray;
+
+ uiNumPages = psOSPageArrayData->uiNumPages;
+ uiPageSize = 1U << psOSPageArrayData->uiLog2PageSize;
+
+ uiPageIndex = uiOffset >> psOSPageArrayData->uiLog2PageSize;
+ uiInPageOffset = uiOffset - ((IMG_DEVMEM_OFFSET_T)uiPageIndex << psOSPageArrayData->uiLog2PageSize);
+ PVR_ASSERT(uiPageIndex < uiNumPages);
+ PVR_ASSERT(uiInPageOffset < uiPageSize);
+
+ psDevPAddr->uiAddr = page_to_phys(ppsPageArray[uiPageIndex]) + uiInPageOffset;
+
+ eError = PVRSRV_OK;
+
+ return eError;
+}
+
+typedef struct _PMR_OSPAGEARRAY_KERNMAP_DATA_ {
+ void *pvBase;
+ IMG_UINT32 ui32PageCount;
+} PMR_OSPAGEARRAY_KERNMAP_DATA;
+
+static PVRSRV_ERROR
+PMRAcquireKernelMappingDataOSMem(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ void **ppvKernelAddressOut,
+ IMG_HANDLE *phHandleOut,
+ PMR_FLAGS_T ulFlags)
+{
+ PVRSRV_ERROR eError;
+ struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
+ void *pvAddress;
+ pgprot_t prot = PAGE_KERNEL;
+ IMG_UINT32 ui32CPUCacheFlags;
+ IMG_UINT32 ui32PageOffset;
+ IMG_SIZE_T uiMapOffset;
+ IMG_UINT32 ui32PageCount;
+ PMR_OSPAGEARRAY_KERNMAP_DATA *psData;
+
+ psOSPageArrayData = pvPriv;
+ ui32CPUCacheFlags = DevmemCPUCacheMode(ulFlags);
+
+ /*
+ Zero offset and size as a special meaning which means map in the
+ whole of the PMR, this is due to fact that the places that call
+ this callback might not have access to be able to determine the
+ physical size
+ */
+ if ((uiOffset == 0) && (uiSize == 0))
+ {
+ ui32PageOffset = 0;
+ uiMapOffset = 0;
+ ui32PageCount = psOSPageArrayData->uiNumPages;
+ }
+ else
+ {
+ IMG_SIZE_T uiEndoffset;
+
+ ui32PageOffset = uiOffset >> psOSPageArrayData->uiLog2PageSize;
+ uiMapOffset = uiOffset - (ui32PageOffset << psOSPageArrayData->uiLog2PageSize);
+ uiEndoffset = uiOffset + uiSize - 1;
+ // Add one as we want the count, not the offset
+ ui32PageCount = (uiEndoffset >> psOSPageArrayData->uiLog2PageSize) + 1;
+ ui32PageCount -= ui32PageOffset;
+ }
+
+ if (psOSPageArrayData->uiLog2PageSize != PAGE_SHIFT)
+ {
+ /* we only know how to use vmap on allocations comprising
+ individual pages. Higher-order "pages" are not supported
+ with this. */
+ eError = PVRSRV_ERROR_PMR_INCOMPATIBLE_CONTIGUITY;
+ goto e0;
+ }
+
+#if defined(CONFIG_ARM64)
+ //zxl:ARM64 use noncached,which is setted MT_DEVICE,And Device type may unsupport some operations.
+ // Force to use pgprot_writecombine now.
+ if(ui32CPUCacheFlags == PVRSRV_MEMALLOCFLAG_CPU_UNCACHED)
+ {
+ ui32CPUCacheFlags = PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE;
+ }
+#endif
+
+ switch (ui32CPUCacheFlags)
+ {
+ case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
+ prot = pgprot_noncached(prot);
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
+ prot = pgprot_writecombine(prot);
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_CPU_CACHED:
+ break;
+
+ default:
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ psData = OSAllocMem(sizeof(PMR_OSPAGEARRAY_KERNMAP_DATA));
+ if (psData == NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+
+ pvAddress = vm_map_ram(&psOSPageArrayData->pagearray[ui32PageOffset],
+ ui32PageCount,
+ -1,
+ prot);
+ if (pvAddress == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e1;
+ }
+
+ *ppvKernelAddressOut = pvAddress + uiMapOffset;
+ psData->pvBase = pvAddress;
+ psData->ui32PageCount = ui32PageCount;
+ *phHandleOut = psData;
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+ e1:
+ OSFreeMem(psData);
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+static void PMRReleaseKernelMappingDataOSMem(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_HANDLE hHandle)
+{
+ struct _PMR_OSPAGEARRAY_DATA_ *psOSPageArrayData;
+ PMR_OSPAGEARRAY_KERNMAP_DATA *psData;
+
+ psOSPageArrayData = pvPriv;
+ psData = hHandle;
+ vm_unmap_ram(psData->pvBase, psData->ui32PageCount);
+ OSFreeMem(psData);
+}
+
+static PMR_IMPL_FUNCTAB _sPMROSPFuncTab = {
+ .pfnLockPhysAddresses = &PMRLockSysPhysAddressesOSMem,
+ .pfnUnlockPhysAddresses = &PMRUnlockSysPhysAddressesOSMem,
+ .pfnDevPhysAddr = &PMRSysPhysAddrOSMem,
+ .pfnAcquireKernelMappingData = &PMRAcquireKernelMappingDataOSMem,
+ .pfnReleaseKernelMappingData = &PMRReleaseKernelMappingDataOSMem,
+ .pfnReadBytes = IMG_NULL,
+ .pfnWriteBytes = IMG_NULL,
+ .pfnFinalize = &PMRFinalizeOSMem
+};
+
+static PVRSRV_ERROR
+_NewOSAllocPagesPMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError2;
+ PMR *psPMR;
+ struct _PMR_OSPAGEARRAY_DATA_ *psPrivData;
+ IMG_HANDLE hPDumpAllocInfo = IMG_NULL;
+ PMR_FLAGS_T uiPMRFlags;
+ IMG_BOOL bZero;
+ IMG_BOOL bPoisonOnAlloc;
+ IMG_BOOL bPoisonOnFree;
+ IMG_BOOL bOnDemand = ((uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) > 0);
+ IMG_BOOL bCpuLocal = ((uiFlags & PVRSRV_MEMALLOCFLAG_CPU_LOCAL) > 0);
+ IMG_UINT32 ui32CPUCacheFlags = (IMG_UINT32) DevmemCPUCacheMode(uiFlags);
+
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+ {
+ bZero = IMG_TRUE;
+ }
+ else
+ {
+ bZero = IMG_FALSE;
+ }
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC)
+ {
+ bPoisonOnAlloc = IMG_TRUE;
+ }
+ else
+ {
+ bPoisonOnAlloc = IMG_FALSE;
+ }
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE)
+ {
+ bPoisonOnFree = IMG_TRUE;
+ }
+ else
+ {
+ bPoisonOnFree = IMG_FALSE;
+ }
+
+ if ((uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &&
+ (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
+ {
+ /* Zero on Alloc and Poison on Alloc are mutually exclusive */
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto errorOnParam;
+ }
+
+ /* Silently round up alignment/pagesize if request was less that
+ PAGE_SHIFT, because it would never be harmful for memory to be
+ _more_ contiguous that was desired */
+ uiLog2PageSize = PAGE_SHIFT > uiLog2PageSize
+ ? PAGE_SHIFT
+ : uiLog2PageSize;
+
+ /* Create Array structure that hold the physical pages */
+ eError = _AllocOSPageArray(uiChunkSize * ui32NumPhysChunks,
+ uiLog2PageSize,
+ bZero,
+ bPoisonOnAlloc,
+ bPoisonOnFree,
+ bOnDemand,
+ ui32CPUCacheFlags,
+ &psPrivData);
+ if (eError != PVRSRV_OK)
+ {
+ goto errorOnAllocPageArray;
+ }
+
+ if (!bOnDemand)
+ {
+ /* Allocate the physical pages */
+ eError = _AllocOSPages(&psPrivData);
+ if (eError != PVRSRV_OK)
+ {
+ goto errorOnAllocPages;
+ }
+ }
+
+ /* In this instance, we simply pass flags straight through.
+
+ Generically, uiFlags can include things that control the PMR
+ factory, but we don't need any such thing (at the time of
+ writing!), and our caller specifies all PMR flags so we don't
+ need to meddle with what was given to us.
+ */
+ uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
+ /* check no significant bits were lost in cast due to different
+ bit widths for flags */
+ PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
+
+ if (bOnDemand)
+ {
+ PDUMPCOMMENT("Deferred Allocation PMR (UMA)");
+ }
+ if (bCpuLocal)
+ {
+ PDUMPCOMMENT("CPU_LOCAL allocation requested");
+ }
+ eError = PMRCreatePMR(psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL],
+ uiSize,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ pabMappingTable,
+ uiLog2PageSize,
+ uiPMRFlags,
+ "PMROSAP",
+ &_sPMROSPFuncTab,
+ psPrivData,
+ &psPMR,
+ &hPDumpAllocInfo,
+ IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ goto errorOnCreate;
+ }
+
+ psPrivData->hPDumpAllocInfo = hPDumpAllocInfo;
+ psPrivData->bPDumpMalloced = IMG_TRUE;
+
+ *ppsPMRPtr = psPMR;
+ return PVRSRV_OK;
+
+errorOnCreate:
+ if (!bOnDemand)
+ {
+ eError2 = _FreeOSPages(psPrivData);
+ PVR_ASSERT(eError2 == PVRSRV_OK);
+ }
+
+errorOnAllocPages:
+ eError2 = _FreeOSPagesArray(psPrivData);
+ PVR_ASSERT(eError2 == PVRSRV_OK);
+
+errorOnAllocPageArray:
+errorOnParam:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+PVRSRV_ERROR
+PhysmemNewOSRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr)
+{
+ return _NewOSAllocPagesPMR(psDevNode,
+ uiSize,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ pabMappingTable,
+ uiLog2PageSize,
+ uiFlags,
+ ppsPMRPtr);
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/physmem_tdmetacode_linux.c b/drivers/gpu/rogue/services/server/env/linux/physmem_tdmetacode_linux.c
new file mode 100644
index 000000000000..aac9cfe67045
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/physmem_tdmetacode_linux.c
@@ -0,0 +1,375 @@
+/*************************************************************************/ /*!
+@File
+@Title Implementation of PMR functions for Trusted Device firmware code memory
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is responsible for
+ implementing the function callbacks for physical memory borrowed
+ from that normally managed by the operating system.
+@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.
+*/ /**************************************************************************/
+
+/* include5/ */
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+
+/* services/server/include/ */
+#include "allocmem.h"
+#include "osfunc.h"
+#include "pdump_physmem.h"
+#include "pdump_km.h"
+#include "pmr.h"
+#include "pmr_impl.h"
+
+/* ourselves */
+#include "physmem_osmem.h"
+
+#if defined(PVR_RI_DEBUG)
+#include "ri_server.h"
+#endif
+
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/mm_types.h>
+#include <linux/vmalloc.h>
+#include <linux/gfp.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#if defined(CONFIG_X86)
+#include <asm/cacheflush.h>
+#endif
+#if defined(__arm__)
+#include "osfunc.h"
+#endif
+
+#include "rgxdevice.h"
+
+/* This is a placeholder implementation of a PMR factory to wrap allocations into
+ the protected META code regions. It has been consciously heavily inspired by the
+ standard osmem PMR factory to supply dummy functionality. Most things here will
+ change in a real implementation.
+
+ Your starting point for re-implementing this module should be by inspecting the
+ sTDMETACodePMRFuncTab structure below and determining which callbacks you need
+ to implement for your system.
+*/
+
+typedef struct {
+ void *token;
+ IMG_UINT32 ui32Log2PageSizeBytes;
+ struct page **apsPageArray;
+ IMG_UINT64 ui64NumPages;
+
+ PHYS_HEAP *psTDMetaCodePhysHeap;
+ IMG_HANDLE hPDumpAllocInfo;
+} sTDMetaCodePageList;
+
+static void
+_FreeTDMetaCodePageContainer(void *pvPagecontainer)
+{
+ sTDMetaCodePageList *psPageContainer = (sTDMetaCodePageList *) pvPagecontainer;
+
+ if(! psPageContainer)
+ {
+ return;
+ }
+
+ if(psPageContainer->apsPageArray)
+ {
+ IMG_UINT64 i;
+ for(i = 0; i < psPageContainer->ui64NumPages; i++)
+ {
+ if(psPageContainer->apsPageArray[i])
+ {
+ __free_page(psPageContainer->apsPageArray[i]);
+ }
+ }
+ OSFreeMem(psPageContainer->apsPageArray);
+ }
+
+ PhysHeapRelease(psPageContainer->psTDMetaCodePhysHeap);
+
+ PDumpPMRFree(psPageContainer->hPDumpAllocInfo);
+
+ OSFreeMem(psPageContainer);
+}
+
+static PVRSRV_ERROR
+PMRSysPhysAddrTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ sTDMetaCodePageList *psPageContainer = (sTDMetaCodePageList *) pvPriv;
+ IMG_UINT64 ui64PageNum = uiOffset >> psPageContainer->ui32Log2PageSizeBytes;
+ IMG_UINT32 ui32PageOffset = uiOffset - (ui64PageNum << psPageContainer->ui32Log2PageSizeBytes);
+
+ PVR_ASSERT(ui64PageNum < psPageContainer->ui64NumPages);
+ psDevPAddr->uiAddr = page_to_phys(psPageContainer->apsPageArray[ui64PageNum]) + ui32PageOffset;
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR
+PMRFinalizeTDMetaCode(PMR_IMPL_PRIVDATA pvPriv)
+{
+ _FreeTDMetaCodePageContainer((void *) pvPriv);
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PMRReadBytesTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes)
+{
+ sTDMetaCodePageList *psPageContainer = (sTDMetaCodePageList *) pvPriv;
+ IMG_UINT8 *pvMapping;
+ IMG_UINT32 uiPageSize = 1 << psPageContainer->ui32Log2PageSizeBytes;
+ IMG_UINT32 uiPageIndex;
+ IMG_UINT32 uiReadOffset;
+ IMG_UINT32 uiReadBytes;
+
+ *puiNumBytes = 0;
+
+ while(uiBufSz)
+ {
+ uiPageIndex = uiOffset >> psPageContainer->ui32Log2PageSizeBytes;
+ uiReadOffset = uiOffset - uiPageIndex * uiPageSize;
+ uiReadBytes = uiPageSize - uiReadOffset;
+
+ if(uiReadBytes > uiBufSz)
+ {
+ uiReadBytes = uiBufSz;
+ }
+
+ pvMapping = kmap(psPageContainer->apsPageArray[uiPageIndex]);
+ PVR_ASSERT(pvMapping);
+ memcpy(pcBuffer, pvMapping + uiReadOffset, uiReadBytes);
+ kunmap(psPageContainer->apsPageArray[uiPageIndex]);
+
+ uiBufSz -= uiReadBytes;
+ pcBuffer += uiReadBytes;
+ *puiNumBytes += uiReadBytes;
+
+ uiOffset += uiReadBytes;
+ }
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PMRKernelMapTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ void **ppvKernelAddressOut,
+ IMG_HANDLE *phHandleOut,
+ PMR_FLAGS_T ulFlags)
+{
+ sTDMetaCodePageList *psPageContainer;
+ void *pvAddress;
+
+ psPageContainer = pvPriv;
+
+ pvAddress = vm_map_ram(psPageContainer->apsPageArray,
+ psPageContainer->ui64NumPages,
+ -1,
+ PAGE_KERNEL);
+
+ if(! pvAddress)
+ {
+ return PVRSRV_ERROR_MAP_TDMETACODE_PAGES_FAIL;
+ }
+
+ *ppvKernelAddressOut = pvAddress + uiOffset;
+ *phHandleOut = pvAddress;
+
+ return PVRSRV_OK;
+}
+
+static void
+PMRKernelUnmapTDMetaCode(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_HANDLE hHandle)
+{
+ sTDMetaCodePageList *psPageContainer;
+ psPageContainer = pvPriv;
+ vm_unmap_ram(hHandle, psPageContainer->ui64NumPages);
+}
+
+static PMR_IMPL_FUNCTAB sTDMETACodePMRFuncTab = {
+ .pfnLockPhysAddresses = IMG_NULL, /* pages are always available in these PMRs */
+ .pfnUnlockPhysAddresses = IMG_NULL, /* as above */
+ .pfnDevPhysAddr = PMRSysPhysAddrTDMetaCode,
+ .pfnPDumpSymbolicAddr = IMG_NULL, /* nothing special needed */
+ .pfnAcquireKernelMappingData = PMRKernelMapTDMetaCode,
+ .pfnReleaseKernelMappingData = PMRKernelUnmapTDMetaCode,
+ .pfnReadBytes = PMRReadBytesTDMetaCode,
+ .pfnFinalize = PMRFinalizeTDMetaCode
+};
+
+
+static PVRSRV_ERROR
+_AllocTDMetaCodePageContainer(IMG_UINT64 ui64NumPages,
+ IMG_UINT32 uiLog2PageSize,
+ PHYS_HEAP *psTDMetaCodePhysHeap,
+ void **ppvPageContainer)
+{
+ IMG_UINT64 i;
+ PVRSRV_ERROR eStatus = PVRSRV_OK;
+ sTDMetaCodePageList *psPageContainer;
+
+ psPageContainer = OSAllocMem(sizeof(sTDMetaCodePageList));
+ if(!psPageContainer)
+ {
+ eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ psPageContainer->ui32Log2PageSizeBytes = uiLog2PageSize;
+ psPageContainer->ui64NumPages = ui64NumPages;
+ psPageContainer->psTDMetaCodePhysHeap = psTDMetaCodePhysHeap;
+ psPageContainer->apsPageArray = OSAllocMem(ui64NumPages * sizeof(psPageContainer->apsPageArray[0]));
+ if(!psPageContainer->apsPageArray)
+ {
+ eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ for(i = 0; i < ui64NumPages; i++)
+ {
+ psPageContainer->apsPageArray[i] = IMG_NULL;
+ }
+
+ for(i = 0; i < ui64NumPages; i++)
+ {
+ psPageContainer->apsPageArray[i] = alloc_page(GFP_KERNEL);
+ if(! psPageContainer->apsPageArray[i])
+ {
+ eStatus = PVRSRV_ERROR_REQUEST_TDMETACODE_PAGES_FAIL;
+ goto fail;
+ }
+ }
+
+ *ppvPageContainer = psPageContainer;
+ return eStatus;
+
+fail:
+ _FreeTDMetaCodePageContainer((void *) psPageContainer);
+ *ppvPageContainer = IMG_NULL;
+ return eStatus;
+}
+
+PVRSRV_ERROR
+PhysmemNewTDMetaCodePMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr)
+{
+ sTDMetaCodePageList *psPageContainer = IMG_NULL;
+ IMG_UINT32 uiPageSize = 1 << uiLog2PageSize;
+ IMG_UINT64 ui64NumPages = (uiSize >> uiLog2PageSize) + ((uiSize & (uiPageSize-1)) != 0);
+ PVRSRV_ERROR eStatus;
+ PHYS_HEAP *psTDMetaCodePhysHeap;
+ IMG_BOOL bMappingTable = IMG_TRUE;
+ IMG_HANDLE hPDumpAllocInfo = IMG_NULL;
+ RGX_DATA *psRGXData;
+
+ IMG_UINT32 uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
+ /* check no significant bits were lost in cast due to different
+ bit widths for flags */
+ PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
+
+ /* get the physical heap for TD Meta Code */
+ psRGXData = (RGX_DATA *)(psDevNode->psDevConfig->hDevData);
+ if(! psRGXData->bHasTDMetaCodePhysHeap)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed allocation from non-existent Trusted Device physical heap!"));
+ eStatus = PVRSRV_ERROR_REQUEST_TDMETACODE_PAGES_FAIL;
+ goto fail;
+ }
+ eStatus = PhysHeapAcquire(psRGXData->uiTDMetaCodePhysHeapID,
+ &psTDMetaCodePhysHeap);
+ if(eStatus)
+ {
+ goto fail;
+ }
+
+ /* allocate and initialize the page container structure */
+ eStatus = _AllocTDMetaCodePageContainer(ui64NumPages,
+ uiLog2PageSize,
+ psTDMetaCodePhysHeap,
+ (void *)&psPageContainer);
+ if(eStatus)
+ {
+ goto fail;
+ }
+
+ /* wrap the container in a PMR */
+ eStatus = PMRCreatePMR(psTDMetaCodePhysHeap,
+ ui64NumPages * uiPageSize,
+ ui64NumPages * uiPageSize,
+ 1,
+ 1,
+ &bMappingTable,
+ uiLog2PageSize,
+ uiPMRFlags,
+ "PMRTDMETACODE",
+ &sTDMETACodePMRFuncTab,
+ (void *)psPageContainer,
+ ppsPMRPtr,
+ &hPDumpAllocInfo,
+ IMG_FALSE);
+
+#if defined(PVR_RI_DEBUG)
+ {
+ RIWritePMREntryKM (*ppsPMRPtr,
+ sizeof("TD META Code"),
+ "TD META Code",
+ (ui64NumPages * uiPageSize));
+ }
+#endif
+
+ /* this is needed when the allocation is finalized and we need to free it. */
+ psPageContainer->hPDumpAllocInfo = hPDumpAllocInfo;
+
+ return eStatus;
+
+ /* error cleanup */
+
+fail:
+ return eStatus;
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/physmem_tdsecbuf_linux.c b/drivers/gpu/rogue/services/server/env/linux/physmem_tdsecbuf_linux.c
new file mode 100644
index 000000000000..734acb73c34f
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/physmem_tdsecbuf_linux.c
@@ -0,0 +1,375 @@
+/*************************************************************************/ /*!
+@File
+@Title Implementation of PMR functions for Trusted Device secure buffers
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is responsible for
+ implementing the function callbacks for physical memory borrowed
+ from that normally managed by the operating system.
+@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.
+*/ /**************************************************************************/
+
+/* include5/ */
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+
+/* services/server/include/ */
+#include "allocmem.h"
+#include "osfunc.h"
+#include "pdump_physmem.h"
+#include "pdump_km.h"
+#include "pmr.h"
+#include "pmr_impl.h"
+
+/* ourselves */
+#include "physmem_osmem.h"
+
+#if defined(PVR_RI_DEBUG)
+#include "ri_server.h"
+#endif
+
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/mm_types.h>
+#include <linux/vmalloc.h>
+#include <linux/gfp.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#if defined(CONFIG_X86)
+#include <asm/cacheflush.h>
+#endif
+#if defined(__arm__)
+#include "osfunc.h"
+#endif
+
+#include "rgxdevice.h"
+
+/* This is a placeholder implementation of a PMR factory to wrap allocations into
+ the secure buffer regions. It has been consciously heavily inspired by the
+ standard osmem PMR factory to supply dummy functionality. Most things here will
+ change in a real implementation.
+
+ Your starting point for re-implementing this module should be by inspecting the
+ sTDSecureBufPMRFuncTab structure below and determining which callbacks you need
+ to implement for your system.
+*/
+
+typedef struct {
+ void *token;
+ IMG_UINT32 ui32Log2PageSizeBytes;
+ struct page **apsPageArray;
+ IMG_UINT64 ui64NumPages;
+
+ PHYS_HEAP *psTDSecureBufPhysHeap;
+ IMG_HANDLE hPDumpAllocInfo;
+} sTDSecureBufPageList;
+
+static void
+_FreeTDSecureBufPageContainer(void *pvPagecontainer)
+{
+ sTDSecureBufPageList *psPageContainer = (sTDSecureBufPageList *) pvPagecontainer;
+
+ if(! psPageContainer)
+ {
+ return;
+ }
+
+ if(psPageContainer->apsPageArray)
+ {
+ IMG_UINT64 i;
+ for(i = 0; i < psPageContainer->ui64NumPages; i++)
+ {
+ if(psPageContainer->apsPageArray[i])
+ {
+ __free_page(psPageContainer->apsPageArray[i]);
+ }
+ }
+ OSFreeMem(psPageContainer->apsPageArray);
+ }
+
+ PhysHeapRelease(psPageContainer->psTDSecureBufPhysHeap);
+
+ PDumpPMRFree(psPageContainer->hPDumpAllocInfo);
+
+ OSFreeMem(psPageContainer);
+}
+
+static PVRSRV_ERROR
+PMRSysPhysAddrTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ sTDSecureBufPageList *psPageContainer = (sTDSecureBufPageList *) pvPriv;
+ IMG_UINT64 ui64PageNum = uiOffset >> psPageContainer->ui32Log2PageSizeBytes;
+ IMG_UINT32 ui32PageOffset = uiOffset - (ui64PageNum << psPageContainer->ui32Log2PageSizeBytes);
+
+ PVR_ASSERT(ui64PageNum < psPageContainer->ui64NumPages);
+ psDevPAddr->uiAddr = page_to_phys(psPageContainer->apsPageArray[ui64PageNum]) + ui32PageOffset;
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR
+PMRFinalizeTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv)
+{
+ _FreeTDSecureBufPageContainer((void *) pvPriv);
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PMRReadBytesTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes)
+{
+ sTDSecureBufPageList *psPageContainer = (sTDSecureBufPageList *) pvPriv;
+ IMG_UINT8 *pvMapping;
+ IMG_UINT32 uiPageSize = 1 << psPageContainer->ui32Log2PageSizeBytes;
+ IMG_UINT32 uiPageIndex;
+ IMG_UINT32 uiReadOffset;
+ IMG_UINT32 uiReadBytes;
+
+ *puiNumBytes = 0;
+
+ while(uiBufSz)
+ {
+ uiPageIndex = uiOffset >> psPageContainer->ui32Log2PageSizeBytes;
+ uiReadOffset = uiOffset - uiPageIndex * uiPageSize;
+ uiReadBytes = uiPageSize - uiReadOffset;
+
+ if(uiReadBytes > uiBufSz)
+ {
+ uiReadBytes = uiBufSz;
+ }
+
+ pvMapping = kmap(psPageContainer->apsPageArray[uiPageIndex]);
+ PVR_ASSERT(pvMapping);
+ memcpy(pcBuffer, pvMapping + uiReadOffset, uiReadBytes);
+ kunmap(psPageContainer->apsPageArray[uiPageIndex]);
+
+ uiBufSz -= uiReadBytes;
+ pcBuffer += uiReadBytes;
+ *puiNumBytes += uiReadBytes;
+
+ uiOffset += uiReadBytes;
+ }
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PMRKernelMapTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ void **ppvKernelAddressOut,
+ IMG_HANDLE *phHandleOut,
+ PMR_FLAGS_T ulFlags)
+{
+ sTDSecureBufPageList *psPageContainer;
+ void *pvAddress;
+
+ psPageContainer = pvPriv;
+
+ pvAddress = vm_map_ram(psPageContainer->apsPageArray,
+ psPageContainer->ui64NumPages,
+ -1,
+ PAGE_KERNEL);
+
+ if(! pvAddress)
+ {
+ return PVRSRV_ERROR_MAP_TDSECUREBUF_PAGES_FAIL;
+ }
+
+ *ppvKernelAddressOut = pvAddress + uiOffset;
+ *phHandleOut = pvAddress;
+
+ return PVRSRV_OK;
+}
+
+static void
+PMRKernelUnmapTDSecureBuf(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_HANDLE hHandle)
+{
+ sTDSecureBufPageList *psPageContainer;
+ psPageContainer = pvPriv;
+ vm_unmap_ram(hHandle, psPageContainer->ui64NumPages);
+}
+
+static PMR_IMPL_FUNCTAB sTDSecureBufPMRFuncTab = {
+ .pfnLockPhysAddresses = IMG_NULL, /* pages are always available in these PMRs */
+ .pfnUnlockPhysAddresses = IMG_NULL, /* as above */
+ .pfnDevPhysAddr = PMRSysPhysAddrTDSecureBuf,
+ .pfnPDumpSymbolicAddr = IMG_NULL, /* nothing special needed */
+ .pfnAcquireKernelMappingData = PMRKernelMapTDSecureBuf,
+ .pfnReleaseKernelMappingData = PMRKernelUnmapTDSecureBuf,
+ .pfnReadBytes = PMRReadBytesTDSecureBuf,
+ .pfnFinalize = PMRFinalizeTDSecureBuf
+};
+
+
+static PVRSRV_ERROR
+_AllocTDSecureBufPageContainer(IMG_UINT64 ui64NumPages,
+ IMG_UINT32 uiLog2PageSize,
+ PHYS_HEAP *psTDSecureBufPhysHeap,
+ void **ppvPageContainer)
+{
+ IMG_UINT64 i;
+ PVRSRV_ERROR eStatus = PVRSRV_OK;
+ sTDSecureBufPageList *psPageContainer;
+
+ psPageContainer = OSAllocMem(sizeof(sTDSecureBufPageList));
+ if(!psPageContainer)
+ {
+ eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ psPageContainer->ui32Log2PageSizeBytes = uiLog2PageSize;
+ psPageContainer->ui64NumPages = ui64NumPages;
+ psPageContainer->psTDSecureBufPhysHeap = psTDSecureBufPhysHeap;
+ psPageContainer->apsPageArray = OSAllocMem(ui64NumPages * sizeof(psPageContainer->apsPageArray[0]));
+ if(!psPageContainer->apsPageArray)
+ {
+ eStatus = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ for(i = 0; i < ui64NumPages; i++)
+ {
+ psPageContainer->apsPageArray[i] = IMG_NULL;
+ }
+
+ for(i = 0; i < ui64NumPages; i++)
+ {
+ psPageContainer->apsPageArray[i] = alloc_page(GFP_KERNEL);
+ if(! psPageContainer->apsPageArray[i])
+ {
+ eStatus = PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL;
+ goto fail;
+ }
+ }
+
+ *ppvPageContainer = psPageContainer;
+ return eStatus;
+
+fail:
+ _FreeTDSecureBufPageContainer((void *) psPageContainer);
+ *ppvPageContainer = IMG_NULL;
+ return eStatus;
+}
+
+PVRSRV_ERROR
+PhysmemNewTDSecureBufPMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr)
+{
+ sTDSecureBufPageList *psPageContainer = IMG_NULL;
+ IMG_UINT32 uiPageSize = 1 << uiLog2PageSize;
+ IMG_UINT64 ui64NumPages = (uiSize >> uiLog2PageSize) + ((uiSize & (uiPageSize-1)) != 0);
+ PVRSRV_ERROR eStatus;
+ PHYS_HEAP *psTDSecureBufPhysHeap;
+ IMG_BOOL bMappingTable = IMG_TRUE;
+ IMG_HANDLE hPDumpAllocInfo = IMG_NULL;
+ RGX_DATA *psRGXData;
+
+ IMG_UINT32 uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK);
+ /* check no significant bits were lost in cast due to different
+ bit widths for flags */
+ PVR_ASSERT(uiPMRFlags == (uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK));
+
+ /* get the physical heap for TD secure buffers */
+ psRGXData = (RGX_DATA *)(psDevNode->psDevConfig->hDevData);
+ if(! psRGXData->bHasTDSecureBufPhysHeap)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed allocation from non-existent Trusted Device physical heap!"));
+ eStatus = PVRSRV_ERROR_REQUEST_TDSECUREBUF_PAGES_FAIL;
+ goto fail;
+ }
+ eStatus = PhysHeapAcquire(psRGXData->uiTDSecureBufPhysHeapID,
+ &psTDSecureBufPhysHeap);
+ if(eStatus)
+ {
+ goto fail;
+ }
+
+ /* allocate and initialize the page container structure */
+ eStatus = _AllocTDSecureBufPageContainer(ui64NumPages,
+ uiLog2PageSize,
+ psTDSecureBufPhysHeap,
+ (void *)&psPageContainer);
+ if(eStatus)
+ {
+ goto fail;
+ }
+
+ /* wrap the container in a PMR */
+ eStatus = PMRCreatePMR(psTDSecureBufPhysHeap,
+ ui64NumPages * uiPageSize,
+ ui64NumPages * uiPageSize,
+ 1,
+ 1,
+ &bMappingTable,
+ uiLog2PageSize,
+ uiPMRFlags,
+ "PMRTDSECUREBUF",
+ &sTDSecureBufPMRFuncTab,
+ (void *)psPageContainer,
+ ppsPMRPtr,
+ &hPDumpAllocInfo,
+ IMG_FALSE);
+
+#if defined(PVR_RI_DEBUG)
+ {
+ RIWritePMREntryKM (*ppsPMRPtr,
+ sizeof("TD Secure Buffer"),
+ "TD Secure Buffer",
+ (ui64NumPages * uiPageSize));
+ }
+#endif
+
+ /* this is needed when the allocation is finalized and we need to free it. */
+ psPageContainer->hPDumpAllocInfo = hPDumpAllocInfo;
+
+ return eStatus;
+
+ /* error cleanup */
+
+fail:
+ return eStatus;
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/private_data.h b/drivers/gpu/rogue/services/server/env/linux/private_data.h
new file mode 100644
index 000000000000..91fca11bac2d
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/private_data.h
@@ -0,0 +1,96 @@
+/*************************************************************************/ /*!
+@File
+@Title Linux private data structure
+@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(__INCLUDED_PRIVATE_DATA_H_)
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#if defined(SUPPORT_DRM_AUTH_IMPORT)
+#include <linux/list.h>
+#endif
+#if defined(SUPPORT_DRM)
+#include <linux/atomic.h>
+#include <drm/drmP.h>
+#endif
+
+#include <linux/fs.h>
+
+#include "connection_server.h"
+#include "env_connection.h"
+
+/* This structure is required in the rare case that a process creates
+ * a connection to services, but before closing the file descriptor,
+ * does a fork(). This fork() will duplicate the file descriptor in the
+ * child process. If the parent process dies before the child, this can
+ * cause the PVRSRVRelease() method to be called in a different process
+ * context than the original PVRSRVOpen(). This is bad because we need
+ * to update the per-process data reference count and/or free the
+ * per-process data. So we must keep a record of which PID's per-process
+ * data to inspect during ->release().
+ */
+
+typedef struct
+{
+ IMG_PVOID pvConnectionData;
+
+#if defined(PVR_SECURE_FD_EXPORT)
+ /* Global kernel MemInfo handle */
+ IMG_HANDLE hKernelMemInfo;
+#endif /* defined(PVR_SECURE_FD_EXPORT) */
+
+#if defined(SUPPORT_DRM_AUTH_IMPORT)
+ struct list_head sDRMAuthListItem;
+
+ IMG_PID uPID;
+#endif
+}
+PVRSRV_FILE_PRIVATE_DATA;
+
+#if defined(SUPPORT_DRM)
+CONNECTION_DATA *LinuxConnectionFromFile(struct drm_file *pFile);
+#else
+CONNECTION_DATA *LinuxConnectionFromFile(struct file *pFile);
+#endif
+
+struct file *LinuxFileFromEnvConnection(ENV_CONNECTION_DATA *psEnvConnection);
+
+#endif /* !defined(__INCLUDED_PRIVATE_DATA_H_) */
+
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_bridge_k.c b/drivers/gpu/rogue/services/server/env/linux/pvr_bridge_k.c
new file mode 100644
index 000000000000..7ba442cd3762
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_bridge_k.c
@@ -0,0 +1,595 @@
+/*************************************************************************/ /*!
+@File
+@Title PVR Bridge Module (kernel side)
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Receives calls from the user portion of services and
+ despatches them to functions in the kernel portion.
+@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 "pvr_bridge.h"
+#include "connection_server.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "pvr_debugfs.h"
+#include "private_data.h"
+#include "linkage.h"
+#include "driverlock.h"
+
+#if defined(SUPPORT_DRM)
+#include <drm/drmP.h>
+#include "pvr_drm.h"
+#if defined(PVR_DRM_SECURE_AUTH_EXPORT)
+#include "env_connection.h"
+#endif
+#endif /* defined(SUPPORT_DRM) */
+
+/* RGX: */
+#if defined(SUPPORT_RGX)
+#include "rgx_bridge.h"
+#endif
+
+#include "srvcore.h"
+#include "common_srvcore_bridge.h"
+#include "cache_defines.h"
+
+#if defined(MODULE_TEST)
+/************************************************************************/
+// additional includes for services testing
+/************************************************************************/
+#include "pvr_test_bridge.h"
+#include "kern_test.h"
+/************************************************************************/
+// end of additional includes
+/************************************************************************/
+#endif
+
+
+#if defined(SUPPORT_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+static struct dentry *gpsPVRDebugFSBridgeStatsEntry = NULL;
+static struct seq_operations gsBridgeStatsReadOps;
+#endif
+
+PVRSRV_ERROR RegisterPDUMPFunctions(void);
+#if defined(SUPPORT_DISPLAY_CLASS)
+PVRSRV_ERROR RegisterDCFunctions(void);
+#endif
+PVRSRV_ERROR RegisterMMFunctions(void);
+PVRSRV_ERROR RegisterCMMFunctions(void);
+PVRSRV_ERROR RegisterPDUMPMMFunctions(void);
+PVRSRV_ERROR RegisterPDUMPCMMFunctions(void);
+PVRSRV_ERROR RegisterSRVCOREFunctions(void);
+PVRSRV_ERROR RegisterSYNCFunctions(void);
+#if defined(SUPPORT_INSECURE_EXPORT)
+PVRSRV_ERROR RegisterSYNCEXPORTFunctions(void);
+#endif
+#if defined(SUPPORT_SECURE_EXPORT)
+PVRSRV_ERROR RegisterSYNCSEXPORTFunctions(void);
+#endif
+#if defined (SUPPORT_RGX)
+PVRSRV_ERROR RegisterRGXINITFunctions(void);
+PVRSRV_ERROR RegisterRGXTA3DFunctions(void);
+PVRSRV_ERROR RegisterRGXTQFunctions(void);
+PVRSRV_ERROR RegisterRGXCMPFunctions(void);
+PVRSRV_ERROR RegisterBREAKPOINTFunctions(void);
+PVRSRV_ERROR RegisterDEBUGMISCFunctions(void);
+PVRSRV_ERROR RegisterRGXPDUMPFunctions(void);
+PVRSRV_ERROR RegisterRGXHWPERFFunctions(void);
+#if defined(RGX_FEATURE_RAY_TRACING)
+PVRSRV_ERROR RegisterRGXRAYFunctions(void);
+#endif /* RGX_FEATURE_RAY_TRACING */
+PVRSRV_ERROR RegisterREGCONFIGFunctions(void);
+PVRSRV_ERROR RegisterTIMERQUERYFunctions(void);
+#endif /* SUPPORT_RGX */
+#if (CACHEFLUSH_TYPE == CACHEFLUSH_GENERIC)
+PVRSRV_ERROR RegisterCACHEGENERICFunctions(void);
+#endif
+#if defined(SUPPORT_SECURE_EXPORT)
+PVRSRV_ERROR RegisterSMMFunctions(void);
+#endif
+#if defined(SUPPORT_PMMIF)
+PVRSRV_ERROR RegisterPMMIFFunctions(void);
+#endif
+PVRSRV_ERROR RegisterPVRTLFunctions(void);
+#if defined(PVR_RI_DEBUG)
+PVRSRV_ERROR RegisterRIFunctions(void);
+#endif
+#if defined(SUPPORT_ION)
+PVRSRV_ERROR RegisterDMABUFFunctions(void);
+#endif
+
+/* These and their friends above will go when full bridge gen comes in */
+PVRSRV_ERROR
+LinuxBridgeInit(void);
+void
+LinuxBridgeDeInit(void);
+
+PVRSRV_ERROR
+LinuxBridgeInit(void)
+{
+ PVRSRV_ERROR eError;
+#if defined(DEBUG_BRIDGE_KM)
+ IMG_INT iResult;
+
+ iResult = PVRDebugFSCreateEntry("bridge_stats",
+ NULL,
+ &gsBridgeStatsReadOps,
+ NULL,
+ &g_BridgeDispatchTable[0],
+ &gpsPVRDebugFSBridgeStatsEntry);
+ if (iResult != 0)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+#endif
+
+ eError = RegisterSRVCOREFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = RegisterSYNCFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+#if defined(SUPPORT_INSECURE_EXPORT)
+ eError = RegisterSYNCEXPORTFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+#if defined(SUPPORT_SECURE_EXPORT)
+ eError = RegisterSYNCSEXPORTFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+ eError = RegisterPDUMPFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ eError = RegisterMMFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ eError = RegisterCMMFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ eError = RegisterPDUMPMMFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ eError = RegisterPDUMPCMMFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+#if defined(SUPPORT_PMMIF)
+ eError = RegisterPMMIFFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+#if defined(SUPPORT_ION)
+ eError = RegisterDMABUFFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+#if defined(SUPPORT_DISPLAY_CLASS)
+ eError = RegisterDCFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+#if (CACHEFLUSH_TYPE == CACHEFLUSH_GENERIC)
+ eError = RegisterCACHEGENERICFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+#if defined(SUPPORT_SECURE_EXPORT)
+ eError = RegisterSMMFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+ eError = RegisterPVRTLFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ #if defined(PVR_RI_DEBUG)
+ eError = RegisterRIFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ #endif
+
+ #if defined (SUPPORT_RGX)
+ eError = RegisterRGXTQFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = RegisterRGXCMPFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = RegisterRGXINITFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = RegisterRGXTA3DFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = RegisterBREAKPOINTFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = RegisterDEBUGMISCFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = RegisterRGXPDUMPFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = RegisterRGXHWPERFFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+#if defined(RGX_FEATURE_RAY_TRACING)
+ eError = RegisterRGXRAYFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif /* RGX_FEATURE_RAY_TRACING */
+
+ eError = RegisterREGCONFIGFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = RegisterTIMERQUERYFunctions();
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+#endif /* SUPPORT_RGX */
+
+ return eError;
+}
+
+void
+LinuxBridgeDeInit(void)
+{
+#if defined(DEBUG_BRIDGE_KM)
+ PVRDebugFSRemoveEntry(gpsPVRDebugFSBridgeStatsEntry);
+ gpsPVRDebugFSBridgeStatsEntry = NULL;
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+static void *BridgeStatsSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
+{
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psDispatchTable = (PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *)psSeqFile->private;
+
+ OSAcquireBridgeLock();
+
+ if (psDispatchTable == NULL || (*puiPosition) > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+ {
+ return NULL;
+ }
+
+ if ((*puiPosition) == 0)
+ {
+ return SEQ_START_TOKEN;
+ }
+
+ return &(psDispatchTable[(*puiPosition) - 1]);
+}
+
+static void BridgeStatsSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+
+ OSReleaseBridgeLock();
+}
+
+static void *BridgeStatsSeqNext(struct seq_file *psSeqFile,
+ void *pvData,
+ loff_t *puiPosition)
+{
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psDispatchTable = (PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *)psSeqFile->private;
+
+ PVR_UNREFERENCED_PARAMETER(pvData);
+
+ (*puiPosition)++;
+
+ if ((*puiPosition) > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+ {
+ return NULL;
+ }
+
+ return &(psDispatchTable[(*puiPosition) - 1]);
+}
+
+static int BridgeStatsSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ if (pvData == SEQ_START_TOKEN)
+ {
+ seq_printf(psSeqFile,
+ "Total ioctl call count = %u\n"
+ "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"
+ "%-60s | %-48s | %10s | %20s | %10s\n",
+ g_BridgeGlobalStats.ui32IOCTLCount,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes + g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ "Bridge Name",
+ "Wrapper Function",
+ "Call Count",
+ "copy_from_user Bytes",
+ "copy_to_user Bytes");
+ }
+ else if (pvData != NULL)
+ {
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *)pvData;
+
+ seq_printf(psSeqFile,
+ "%-60s %-48s %-10u %-20u %-10u\n",
+ psEntry->pszIOCName,
+ psEntry->pszFunctionName,
+ psEntry->ui32CallCount,
+ psEntry->ui32CopyFromUserTotalBytes,
+ psEntry->ui32CopyToUserTotalBytes);
+ }
+
+ return 0;
+}
+
+static struct seq_operations gsBridgeStatsReadOps =
+{
+ .start = BridgeStatsSeqStart,
+ .stop = BridgeStatsSeqStop,
+ .next = BridgeStatsSeqNext,
+ .show = BridgeStatsSeqShow,
+};
+#endif /* defined(DEBUG_BRIDGE_KM) */
+
+
+#if defined(SUPPORT_DRM)
+int
+PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg, struct drm_file *pFile)
+#else
+long
+PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsigned long arg)
+#endif
+{
+#if !defined(SUPPORT_DRM)
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+#endif
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+ CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
+ IMG_INT err = -EFAULT;
+
+ OSAcquireBridgeLock();
+
+#if defined(SUPPORT_DRM)
+ PVR_UNREFERENCED_PARAMETER(dev);
+
+ psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+ PVR_UNREFERENCED_PARAMETER(ioctlCmd);
+
+ psBridgePackageKM = &sBridgePackageKM;
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+ __FUNCTION__));
+
+ goto unlock_and_return;
+ }
+
+
+ if(OSCopyFromUser(IMG_NULL,
+ psBridgePackageKM,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE))
+ != PVRSRV_OK)
+ {
+ goto unlock_and_return;
+ }
+#endif
+
+#if defined(DEBUG_BRIDGE_CALLS)
+ {
+ IMG_UINT32 mangledID;
+ mangledID = psBridgePackageKM->ui32BridgeID;
+
+ psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+
+ PVR_DPF((PVR_DBG_WARNING, "Bridge ID (x%8x) %8u (mangled: x%8x) ", psBridgePackageKM->ui32BridgeID, psBridgePackageKM->ui32BridgeID, mangledID));
+ }
+#else
+ psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+#endif
+
+ err = BridgedDispatchKM(psConnection, psBridgePackageKM);
+
+#if !defined(SUPPORT_DRM)
+unlock_and_return:
+#endif
+ OSReleaseBridgeLock();
+ return err;
+}
+
+
+#if defined(CONFIG_COMPAT)
+#if defined(SUPPORT_DRM)
+int
+#else
+long
+#endif
+PVRSRV_BridgeCompatDispatchKM(struct file *pFile,
+ unsigned int unref__ ioctlCmd,
+ unsigned long arg)
+{
+ struct bridge_package_from_32
+ {
+ IMG_UINT32 bridge_id; /*!< ioctl/drvesc index */
+ IMG_UINT32 size; /*!< size of structure */
+ IMG_UINT32 addr_param_in; /*!< input data buffer */
+ IMG_UINT32 in_buffer_size; /*!< size of input data buffer */
+ IMG_UINT32 addr_param_out; /*!< output data buffer */
+ IMG_UINT32 out_buffer_size; /*!< size of output data buffer */
+ };
+
+ IMG_INT err = -EFAULT;
+ PVRSRV_BRIDGE_PACKAGE params_for_64;
+ struct bridge_package_from_32 params;
+ struct bridge_package_from_32 * const params_addr = &params;
+#if !defined(SUPPORT_DRM)
+ CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
+#else
+ struct drm_file *file_priv = pFile->private_data;
+ CONNECTION_DATA *psConnection = LinuxConnectionFromFile(file_priv);
+#endif
+ // make sure there is no padding inserted by compiler
+ PVR_ASSERT(sizeof(struct bridge_package_from_32) == 6 * sizeof(IMG_UINT32));
+
+ OSAcquireBridgeLock();
+
+ if(!OSAccessOK(PVR_VERIFY_READ, (void *) arg,
+ sizeof(struct bridge_package_from_32)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+ __FUNCTION__));
+
+ goto unlock_and_return;
+ }
+
+ if(OSCopyFromUser(NULL, params_addr, (void*) arg,
+ sizeof(struct bridge_package_from_32))
+ != PVRSRV_OK)
+ {
+ goto unlock_and_return;
+ }
+
+ PVR_ASSERT(params_addr->size == sizeof(struct bridge_package_from_32));
+
+ params_addr->bridge_id = PVRSRV_GET_BRIDGE_ID(params_addr->bridge_id);
+
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_MESSAGE, "ioctl %s -> func %s",
+ g_BridgeDispatchTable[params_addr->bridge_id].pszIOCName,
+ g_BridgeDispatchTable[params_addr->bridge_id].pszFunctionName));
+#endif
+
+ params_for_64.ui32BridgeID = params_addr->bridge_id;
+ params_for_64.ui32Size = sizeof(params_for_64);
+ params_for_64.pvParamIn = (void*) ((size_t) params_addr->addr_param_in);
+ params_for_64.pvParamOut = (void*) ((size_t) params_addr->addr_param_out);
+ params_for_64.ui32InBufferSize = params_addr->in_buffer_size;
+ params_for_64.ui32OutBufferSize = params_addr->out_buffer_size;
+
+ err = BridgedDispatchKM(psConnection, &params_for_64);
+
+unlock_and_return:
+ OSReleaseBridgeLock();
+ return err;
+}
+#endif /* defined(CONFIG_COMPAT) */
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_debug.c b/drivers/gpu/rogue/services/server/env/linux/pvr_debug.c
new file mode 100755
index 000000000000..ec647497faf1
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_debug.c
@@ -0,0 +1,1479 @@
+/*************************************************************************/ /*!
+@File
+@Title Debug Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides kernel side Debug 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 <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <stdarg.h>
+
+#include "pvrversion.h"
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "pvr_debugfs.h"
+#include "linkage.h"
+#include "pvr_uaccess.h"
+#include "pvrsrv.h"
+#include "rgxdevice.h"
+#include "rgxdebug.h"
+#include "lists.h"
+#include "osfunc.h"
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+/******** BUFFERED LOG MESSAGES ********/
+
+/* Because we don't want to have to handle CCB wrapping, each buffered
+ * message is rounded up to PVRSRV_DEBUG_CCB_MESG_MAX bytes. This means
+ * there is the same fixed number of messages that can be stored,
+ * regardless of message length.
+ */
+
+#if defined(PVRSRV_DEBUG_CCB_MAX)
+
+#define PVRSRV_DEBUG_CCB_MESG_MAX PVR_MAX_DEBUG_MESSAGE_LEN
+
+#include <linux/syscalls.h>
+#include <linux/time.h>
+
+typedef struct
+{
+ const IMG_CHAR *pszFile;
+ IMG_INT iLine;
+ IMG_UINT32 ui32TID;
+ IMG_CHAR pcMesg[PVRSRV_DEBUG_CCB_MESG_MAX];
+ struct timeval sTimeVal;
+}
+PVRSRV_DEBUG_CCB;
+
+static PVRSRV_DEBUG_CCB gsDebugCCB[PVRSRV_DEBUG_CCB_MAX] = { { 0 } };
+
+static IMG_UINT giOffset = 0;
+
+static struct mutex gsDebugCCBMutex;
+
+static void
+AddToBufferCCB(const IMG_CHAR *pszFileName, IMG_UINT32 ui32Line,
+ const IMG_CHAR *szBuffer)
+{
+ mutex_lock(&gsDebugCCBMutex);
+
+ gsDebugCCB[giOffset].pszFile = pszFileName;
+ gsDebugCCB[giOffset].iLine = ui32Line;
+ gsDebugCCB[giOffset].ui32TID = current->tgid;
+
+ do_gettimeofday(&gsDebugCCB[giOffset].sTimeVal);
+
+ strncpy(gsDebugCCB[giOffset].pcMesg, szBuffer, PVRSRV_DEBUG_CCB_MESG_MAX - 1);
+ gsDebugCCB[giOffset].pcMesg[PVRSRV_DEBUG_CCB_MESG_MAX - 1] = 0;
+
+ giOffset = (giOffset + 1) % PVRSRV_DEBUG_CCB_MAX;
+
+ mutex_unlock(&gsDebugCCBMutex);
+}
+
+IMG_EXPORT void PVRSRVDebugPrintfDumpCCB(void)
+{
+ int i;
+
+ mutex_lock(&gsDebugCCBMutex);
+
+ for (i = 0; i < PVRSRV_DEBUG_CCB_MAX; i++)
+ {
+ PVRSRV_DEBUG_CCB *psDebugCCBEntry =
+ &gsDebugCCB[(giOffset + i) % PVRSRV_DEBUG_CCB_MAX];
+
+ /* Early on, we won't have PVRSRV_DEBUG_CCB_MAX messages */
+ if (!psDebugCCBEntry->pszFile)
+ {
+ continue;
+ }
+
+ printk(KERN_ERR "%s:%d: (%ld.%ld,tid=%u) %s\n",
+ psDebugCCBEntry->pszFile,
+ psDebugCCBEntry->iLine,
+ (long)psDebugCCBEntry->sTimeVal.tv_sec,
+ (long)psDebugCCBEntry->sTimeVal.tv_usec,
+ psDebugCCBEntry->ui32TID,
+ psDebugCCBEntry->pcMesg);
+
+ /* Clear this entry so it doesn't get printed the next time again. */
+ psDebugCCBEntry->pszFile = IMG_NULL;
+ }
+
+ mutex_unlock(&gsDebugCCBMutex);
+}
+
+#else /* defined(PVRSRV_DEBUG_CCB_MAX) */
+static INLINE void
+AddToBufferCCB(const IMG_CHAR *pszFileName, IMG_UINT32 ui32Line,
+ const IMG_CHAR *szBuffer)
+{
+ (void)pszFileName;
+ (void)szBuffer;
+ (void)ui32Line;
+}
+
+IMG_EXPORT void PVRSRVDebugPrintfDumpCCB(void)
+{
+ /* Not available */
+}
+
+#endif /* defined(PVRSRV_DEBUG_CCB_MAX) */
+
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
+ const IMG_CHAR *pszFormat, va_list VArgs)
+ IMG_FORMAT_PRINTF(3, 0);
+
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#define PVR_MAX_FILEPATH_LEN 256
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
+ const IMG_CHAR *pszFormat, ...)
+ IMG_FORMAT_PRINTF(3, 4);
+
+/* NOTE: Must NOT be static! Used in module.c.. */
+IMG_UINT32 gPVRDebugLevel =
+ (
+ DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING
+
+#if defined(PVRSRV_DEBUG_CCB_MAX)
+ | DBGPRIV_BUFFERED
+#endif /* defined(PVRSRV_DEBUG_CCB_MAX) */
+
+#if defined(PVR_DPF_ADHOC_DEBUG_ON)
+ | DBGPRIV_DEBUG
+#endif /* defined(PVR_DPF_ADHOC_DEBUG_ON) */
+ );
+
+#endif /* defined(PVRSRV_NEED_PVR_DPF) || defined(PVRSRV_NEED_PVR_TRACE) */
+
+#define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+/* Message buffer for non-IRQ messages */
+static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+
+/* Message buffer for IRQ messages */
+static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+
+/* The lock is used to control access to gszBufferNonIRQ */
+static struct mutex gsDebugMutexNonIRQ;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+/* The lock is used to control access to gszBufferIRQ */
+static spinlock_t gsDebugLockIRQ = SPIN_LOCK_UNLOCKED;
+#else
+static DEFINE_SPINLOCK(gsDebugLockIRQ);
+#endif
+
+#define USE_SPIN_LOCK (in_interrupt() || !preemptible())
+
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+ if (USE_SPIN_LOCK)
+ {
+ spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+ }
+ else
+ {
+ mutex_lock(&gsDebugMutexNonIRQ);
+ }
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+ if (USE_SPIN_LOCK)
+ {
+ spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+ }
+ else
+ {
+ mutex_unlock(&gsDebugMutexNonIRQ);
+ }
+}
+
+static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
+{
+ if (USE_SPIN_LOCK)
+ {
+ *ppszBuf = gszBufferIRQ;
+ *pui32BufSiz = sizeof(gszBufferIRQ);
+ }
+ else
+ {
+ *ppszBuf = gszBufferNonIRQ;
+ *pui32BufSiz = sizeof(gszBufferNonIRQ);
+ }
+}
+
+/*
+ * Append a string to a buffer using formatted conversion.
+ * The function takes a variable number of arguments, pointed
+ * to by the var args list.
+ */
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, va_list VArgs)
+{
+ IMG_UINT32 ui32Used;
+ IMG_UINT32 ui32Space;
+ IMG_INT32 i32Len;
+
+ ui32Used = strlen(pszBuf);
+ BUG_ON(ui32Used >= ui32BufSiz);
+ ui32Space = ui32BufSiz - ui32Used;
+
+ i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+ pszBuf[ui32BufSiz - 1] = 0;
+
+ /* Return true if string was truncated */
+ return i32Len < 0 || i32Len >= (IMG_INT32)ui32Space;
+}
+
+/* Actually required for ReleasePrintf too */
+
+void PVRDPFInit(void)
+{
+ mutex_init(&gsDebugMutexNonIRQ);
+#if defined(PVRSRV_DEBUG_CCB_MAX) && defined(PVRSRV_NEED_PVR_DPF)
+ mutex_init(&gsDebugCCBMutex);
+#endif
+}
+
+/*************************************************************************/ /*!
+@Function PVRSRVReleasePrintf
+@Description To output an important message to the user in release builds
+@Input pszFormat The message format string
+@Input ... Zero or more arguments for use by the format string
+*/ /**************************************************************************/
+void PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
+{
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+ strncpy(pszBuf, "PVR_K: ", (ui32BufSiz - 2));
+ pszBuf[ui32BufSiz - 1] = '\0';
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_ERR "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_ERR "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+ va_end(vaArgs);
+}
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+/*************************************************************************/ /*!
+@Function PVRTrace
+@Description To output a debug message to the user
+@Input pszFormat The message format string
+@Input ... Zero or more arguments for use by the format string
+*/ /**************************************************************************/
+void PVRSRVTrace(const IMG_CHAR *pszFormat, ...)
+{
+ va_list VArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(VArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+ strncpy(pszBuf, "PVR: ", (ui32BufSiz - 2));
+ pszBuf[ui32BufSiz - 1] = '\0';
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+ {
+ printk(KERN_ERR "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_ERR "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end(VArgs);
+}
+
+#endif /* defined(PVRSRV_NEED_PVR_TRACE) */
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+/*
+ * Append a string to a buffer using formatted conversion.
+ * The function takes a variable number of arguments, calling
+ * VBAppend to do the actual work.
+ */
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
+{
+ va_list VArgs;
+ IMG_BOOL bTrunc;
+
+ va_start (VArgs, pszFormat);
+
+ bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
+
+ va_end (VArgs);
+
+ return bTrunc;
+}
+
+/*************************************************************************/ /*!
+@Function PVRSRVDebugPrintf
+@Description To output a debug message to the user
+@Input uDebugLevel The current debug level
+@Input pszFile The source file generating the message
+@Input uLine The line of the source file
+@Input pszFormat The message format string
+@Input ... Zero or more arguments for use by the format string
+*/ /**************************************************************************/
+void PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR *pszFullFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR *pszFormat,
+ ...)
+{
+ IMG_BOOL bNoLoc;
+ const IMG_CHAR *pszFileName = pszFullFileName;
+ IMG_CHAR *pszLeafName;
+
+ bNoLoc = (IMG_BOOL)((ui32DebugLevel & DBGPRIV_CALLTRACE) |
+ (ui32DebugLevel & DBGPRIV_BUFFERED)) ? IMG_TRUE : IMG_FALSE;
+
+ if (gPVRDebugLevel & ui32DebugLevel)
+ {
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+ switch (ui32DebugLevel)
+ {
+ case DBGPRIV_FATAL:
+ {
+ strncpy(pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz - 2));
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ strncpy(pszBuf, "PVR_K:(Error): ", (ui32BufSiz - 2));
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ strncpy(pszBuf, "PVR_K:(Warn): ", (ui32BufSiz - 2));
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ strncpy(pszBuf, "PVR_K:(Mesg): ", (ui32BufSiz - 2));
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ strncpy(pszBuf, "PVR_K:(Verb): ", (ui32BufSiz - 2));
+ break;
+ }
+ case DBGPRIV_DEBUG:
+ {
+ strncpy(pszBuf, "PVR_K:(Debug): ", (ui32BufSiz - 2));
+ break;
+ }
+ case DBGPRIV_CALLTRACE:
+ case DBGPRIV_ALLOC:
+ case DBGPRIV_BUFFERED:
+ default:
+ {
+ strncpy(pszBuf, "PVR_K: ", (ui32BufSiz - 2));
+ break;
+ }
+ }
+ pszBuf[ui32BufSiz - 1] = '\0';
+
+ (void) BAppend(pszBuf, ui32BufSiz, "%u: ", current->pid);
+
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_ERR "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+#if !defined(__sh__)
+ pszLeafName = (IMG_CHAR *)strrchr (pszFileName, '/');
+
+ if (pszLeafName)
+ {
+ pszFileName = pszLeafName+1;
+ }
+#endif /* __sh__ */
+
+ if (BAppend(pszBuf, ui32BufSiz, " [%u, %s]", ui32Line, pszFileName))
+ {
+ printk(KERN_ERR "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ if (ui32DebugLevel & DBGPRIV_BUFFERED)
+ {
+ AddToBufferCCB(pszFileName, ui32Line, pszBuf);
+ }
+ else
+ {
+ printk(KERN_ERR "%s\n", pszBuf);
+ }
+ }
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end (vaArgs);
+ }
+}
+
+#endif /* PVRSRV_NEED_PVR_DPF */
+
+
+/*************************************************************************/ /*!
+ Version DebugFS entry
+*/ /**************************************************************************/
+
+static void *_DebugVersionCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode,
+ va_list va)
+{
+ loff_t *puiCurrentPosition = va_arg(va, loff_t *);
+ loff_t uiPosition = va_arg(va, loff_t);
+ loff_t uiCurrentPosition = *puiCurrentPosition;
+
+ (*puiCurrentPosition)++;
+
+ return (uiCurrentPosition == uiPosition) ? psDevNode : NULL;
+}
+
+static void *_DebugVersionSeqStart(struct seq_file *psSeqFile,
+ loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ if (*puiPosition == 0)
+ {
+ return SEQ_START_TOKEN;
+ }
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugVersionCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static void _DebugVersionSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+}
+
+static void *_DebugVersionSeqNext(struct seq_file *psSeqFile,
+ void *pvData,
+ loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ PVR_UNREFERENCED_PARAMETER(pvData);
+
+ (*puiPosition)++;
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugVersionCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static int _DebugVersionSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ if (pvData == SEQ_START_TOKEN)
+ {
+ const IMG_CHAR *pszSystemVersionString = PVRSRVGetSystemName();
+
+ seq_printf(psSeqFile, "Version %s (%s) %s\n",
+ PVRVERSION_STRING,
+ PVR_BUILD_TYPE, PVR_BUILD_DIR);
+
+ seq_printf(psSeqFile, "System Version String: %s\n", pszSystemVersionString);
+ }
+ else if (pvData != NULL)
+ {
+ PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *)pvData;
+
+ if (psDevNode->pfnDeviceVersionString)
+ {
+ IMG_CHAR *pszDeviceVersionString;
+
+ if (psDevNode->pfnDeviceVersionString(psDevNode, &pszDeviceVersionString) == PVRSRV_OK)
+ {
+ seq_printf(psSeqFile, "%s\n", pszDeviceVersionString);
+
+ kfree(pszDeviceVersionString);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static struct seq_operations gsDebugVersionReadOps =
+{
+ .start = _DebugVersionSeqStart,
+ .stop = _DebugVersionSeqStop,
+ .next = _DebugVersionSeqNext,
+ .show = _DebugVersionSeqShow,
+};
+
+#if 0
+static void *_DebugFreqSeqStart(struct seq_file *psSeqFile,
+ loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ if (*puiPosition == 0)
+ {
+ return SEQ_START_TOKEN;
+ }
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugVersionCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static void _DebugFreqSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+}
+
+static void *_DebugFreqSeqNext(struct seq_file *psSeqFile,
+ void *pvData,
+ loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ PVR_UNREFERENCED_PARAMETER(pvData);
+
+ (*puiPosition)++;
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugVersionCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static int _DebugFreqSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ if (pvData == SEQ_START_TOKEN)
+ {
+ const IMG_CHAR *pszSystemVersionString = PVRSRVGetSystemName();
+
+ seq_printf(psSeqFile, "Freq %s (%s) %s\n",
+ PVRVERSION_STRING,
+ PVR_BUILD_TYPE, PVR_BUILD_DIR);
+
+ seq_printf(psSeqFile, "Freq: %s\n", pszSystemVersionString);
+ }
+ else if (pvData != NULL)
+ {
+ PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *)pvData;
+
+ if (psDevNode->pfnDeviceVersionString)
+ {
+ IMG_CHAR *pszDeviceVersionString;
+
+ if (psDevNode->pfnDeviceVersionString(psDevNode, &pszDeviceVersionString) == PVRSRV_OK)
+ {
+ seq_printf(psSeqFile, "%s\n", pszDeviceVersionString);
+
+ kfree(pszDeviceVersionString);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static struct seq_operations gsDebugFreqReadOps =
+{
+ .start = _DebugFreqSeqStart,
+ .stop = _DebugFreqSeqStop,
+ .next = _DebugFreqSeqNext,
+ .show = _DebugFreqSeqShow,
+};
+#endif
+
+/*************************************************************************/ /*!
+ Nodes DebugFS entry
+*/ /**************************************************************************/
+
+static const IMG_CHAR *_DebugNodesDevTypeToString(PVRSRV_DEVICE_TYPE eDeviceType)
+{
+ switch (eDeviceType)
+ {
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ OSSNPrintf(text, sizeof(text), "?%x", (IMG_UINT)eDeviceType);
+
+ return text;
+ }
+ }
+}
+
+static const IMG_CHAR *_DebugNodesDevClassToString(PVRSRV_DEVICE_CLASS eDeviceClass)
+{
+ switch (eDeviceClass)
+ {
+ case PVRSRV_DEVICE_CLASS_3D:
+ {
+ return "3D";
+ }
+ case PVRSRV_DEVICE_CLASS_DISPLAY:
+ {
+ return "display";
+ }
+ case PVRSRV_DEVICE_CLASS_BUFFER:
+ {
+ return "buffer";
+ }
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ OSSNPrintf(text, sizeof(text), "?%x", (IMG_UINT)eDeviceClass);
+ return text;
+ }
+ }
+}
+
+static void *_DebugNodesCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode, va_list va)
+{
+ loff_t *puiCurrentPosition = va_arg(va, loff_t *);
+ loff_t uiPosition = va_arg(va, loff_t);
+ loff_t uiCurrentPosition = *puiCurrentPosition;
+
+ (*puiCurrentPosition)++;
+
+ return (uiCurrentPosition == uiPosition) ? psDevNode : NULL;
+}
+
+static void *_DebugNodesSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ if (*puiPosition == 0)
+ {
+ return SEQ_START_TOKEN;
+ }
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugNodesCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static void _DebugNodesSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+}
+
+static void *_DebugNodesSeqNext(struct seq_file *psSeqFile,
+ void *pvData,
+ loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ PVR_UNREFERENCED_PARAMETER(pvData);
+
+ (*puiPosition)++;
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugVersionCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static int _DebugNodesSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ if (pvData == SEQ_START_TOKEN)
+ {
+ seq_printf(psSeqFile,
+ "Registered nodes\n"
+ "Addr Type Class Index Ref pvDev Size\n");
+ }
+ else if (pvData != NULL)
+ {
+ PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *)pvData;
+
+ seq_printf(psSeqFile,
+ "%p %-8s %-8s %4d %2u %p %3u\n",
+ psDevNode,
+ _DebugNodesDevTypeToString(psDevNode->sDevId.eDeviceType),
+ _DebugNodesDevClassToString(psDevNode->sDevId.eDeviceClass),
+ psDevNode->sDevId.eDeviceClass,
+ psDevNode->ui32RefCount,
+ psDevNode->pvDevice,
+ psDevNode->ui32pvDeviceSize);
+ }
+
+ return 0;
+}
+
+static struct seq_operations gsDebugNodesReadOps =
+{
+ .start = _DebugNodesSeqStart,
+ .stop = _DebugNodesSeqStop,
+ .next = _DebugNodesSeqNext,
+ .show = _DebugNodesSeqShow,
+};
+
+
+/*************************************************************************/ /*!
+ Status DebugFS entry
+*/ /**************************************************************************/
+
+static void *_DebugStatusCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode,
+ va_list va)
+{
+ loff_t *puiCurrentPosition = va_arg(va, loff_t *);
+ loff_t uiPosition = va_arg(va, loff_t);
+ loff_t uiCurrentPosition = *puiCurrentPosition;
+
+ (*puiCurrentPosition)++;
+
+ return (uiCurrentPosition == uiPosition) ? psDevNode : NULL;
+}
+
+static void *_DebugStatusSeqStart(struct seq_file *psSeqFile,
+ loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ if (*puiPosition == 0)
+ {
+ return SEQ_START_TOKEN;
+ }
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugStatusCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static void _DebugStatusSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+}
+
+static void *_DebugStatusSeqNext(struct seq_file *psSeqFile,
+ void *pvData,
+ loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ PVR_UNREFERENCED_PARAMETER(pvData);
+
+ (*puiPosition)++;
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugVersionCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static int _DebugStatusSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ if (pvData == SEQ_START_TOKEN)
+ {
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+
+ if (psPVRSRVData != NULL)
+ {
+ switch (psPVRSRVData->eServicesState)
+ {
+ case PVRSRV_SERVICES_STATE_OK:
+ seq_printf(psSeqFile, "Driver Status: OK\n");
+ break;
+ case PVRSRV_SERVICES_STATE_BAD:
+ seq_printf(psSeqFile, "Driver Status: BAD\n");
+ break;
+ default:
+ seq_printf(psSeqFile, "Driver Status: %d\n", psPVRSRVData->eServicesState);
+ break;
+ }
+ }
+ }
+ else if (pvData != NULL)
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+
+ /* Update the health status now if possible... */
+ if (psDeviceNode->pfnUpdateHealthStatus)
+ {
+ psDeviceNode->pfnUpdateHealthStatus(psDeviceNode, IMG_FALSE);
+ }
+
+ /* Write the device status to the sequence file... */
+ if (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_RGX)
+ {
+ switch (psDeviceNode->eHealthStatus)
+ {
+ case PVRSRV_DEVICE_HEALTH_STATUS_OK:
+ seq_printf(psSeqFile, "Firmware Status: OK\n");
+ break;
+ case PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING:
+ seq_printf(psSeqFile, "Firmware Status: NOT RESPONDING\n");
+ break;
+ case PVRSRV_DEVICE_HEALTH_STATUS_DEAD:
+ seq_printf(psSeqFile, "Firmware Status: DEAD\n");
+ break;
+ default:
+ seq_printf(psSeqFile, "Firmware Status: UNKNOWN (%d)\n", psDeviceNode->eHealthStatus);
+ break;
+ }
+
+ /* Write other useful stats to aid the test cycle... */
+ if (psDeviceNode->pvDevice != NULL)
+ {
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBuf;
+
+ /* Calculate the number of HWR events in total across all the DMs... */
+ if (psRGXFWIfTraceBufCtl != NULL)
+ {
+ IMG_UINT32 ui32HWREventCount = 0;
+ IMG_UINT32 ui32CRREventCount = 0;
+ IMG_UINT32 ui32DMIndex;
+
+ for (ui32DMIndex = 0; ui32DMIndex < RGXFWIF_DM_MAX; ui32DMIndex++)
+ {
+ ui32HWREventCount += psRGXFWIfTraceBufCtl->aui16HwrDmLockedUpCount[ui32DMIndex];
+ ui32CRREventCount += psRGXFWIfTraceBufCtl->aui16HwrDmOverranCount[ui32DMIndex];
+ }
+
+ seq_printf(psSeqFile, "HWR Event Count: %d\n", ui32HWREventCount);
+ seq_printf(psSeqFile, "CRR Event Count: %d\n", ui32CRREventCount);
+ }
+
+ /* Write the number of APM events... */
+ seq_printf(psSeqFile, "APM Event Count: %d\n", psDevInfo->ui32ActivePMReqTotal);
+ }
+ }
+ else
+ {
+ switch (psDeviceNode->eHealthStatus)
+ {
+ case PVRSRV_DEVICE_HEALTH_STATUS_OK:
+ seq_printf(psSeqFile, "Device %d Status: OK\n", psDeviceNode->sDevId.ui32DeviceIndex);
+ break;
+ case PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING:
+ seq_printf(psSeqFile, "Device %d Status: NOT RESPONDING\n", psDeviceNode->sDevId.ui32DeviceIndex);
+ break;
+ case PVRSRV_DEVICE_HEALTH_STATUS_DEAD:
+ seq_printf(psSeqFile, "Device %d Status: DEAD\n", psDeviceNode->sDevId.ui32DeviceIndex);
+ break;
+ default:
+ seq_printf(psSeqFile, "Device %d Status: %d\n",
+ psDeviceNode->sDevId.ui32DeviceIndex,
+ psDeviceNode->eHealthStatus);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static IMG_INT DebugStatusSet(const char __user *pcBuffer,
+ size_t uiCount,
+ loff_t uiPosition,
+ void *pvData)
+{
+ IMG_CHAR acDataBuffer[6];
+
+ if (uiPosition != 0)
+ {
+ return -EIO;
+ }
+
+ if (uiCount > (sizeof(acDataBuffer) / sizeof(acDataBuffer[0])))
+ {
+ return -EINVAL;
+ }
+
+ if (pvr_copy_from_user(acDataBuffer, pcBuffer, uiCount))
+ {
+ return -EINVAL;
+ }
+
+ if (acDataBuffer[uiCount - 1] != '\n')
+ {
+ return -EINVAL;
+ }
+
+ if (((acDataBuffer[0] == 'k') || ((acDataBuffer[0] == 'K'))) && uiCount == 2)
+ {
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ psPVRSRVData->eServicesState = PVRSRV_SERVICES_STATE_BAD;
+ }
+ else
+ {
+ return -EINVAL;
+ }
+
+ return uiCount;
+}
+
+static struct seq_operations gsDebugStatusReadOps =
+{
+ .start = _DebugStatusSeqStart,
+ .stop = _DebugStatusSeqStop,
+ .next = _DebugStatusSeqNext,
+ .show = _DebugStatusSeqShow,
+};
+
+/*************************************************************************/ /*!
+ Dump Debug DebugFS entry
+*/ /**************************************************************************/
+
+static void *_DebugDumpDebugCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode, va_list va)
+{
+ loff_t *puiCurrentPosition = va_arg(va, loff_t *);
+ loff_t uiPosition = va_arg(va, loff_t);
+ loff_t uiCurrentPosition = *puiCurrentPosition;
+
+ (*puiCurrentPosition)++;
+
+ return (uiCurrentPosition == uiPosition) ? psDevNode : NULL;
+}
+
+static void *_DebugDumpDebugSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ if (*puiPosition == 0)
+ {
+ return SEQ_START_TOKEN;
+ }
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugDumpDebugCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static void _DebugDumpDebugSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+}
+
+static void *_DebugDumpDebugSeqNext(struct seq_file *psSeqFile,
+ void *pvData,
+ loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ PVR_UNREFERENCED_PARAMETER(pvData);
+
+ (*puiPosition)++;
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugDumpDebugCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static struct seq_file *gpsDumpDebugPrintfSeqFile = IMG_NULL;
+
+static void _DumpDebugSeqPrintf(const IMG_CHAR *pszFormat, ...)
+{
+ if (gpsDumpDebugPrintfSeqFile)
+ {
+ IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
+ va_list ArgList;
+
+ va_start(ArgList, pszFormat);
+ vsnprintf(szBuffer, PVR_MAX_DEBUG_MESSAGE_LEN, pszFormat, ArgList);
+ seq_printf(gpsDumpDebugPrintfSeqFile, "%s\n", szBuffer);
+ va_end(ArgList);
+ }
+}
+
+static int _DebugDumpDebugSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ if (pvData != NULL && pvData != SEQ_START_TOKEN)
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+
+ if (psDeviceNode->pvDevice != NULL)
+ {
+ gpsDumpDebugPrintfSeqFile = psSeqFile;
+ PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX, _DumpDebugSeqPrintf);
+ gpsDumpDebugPrintfSeqFile = IMG_NULL;
+
+ }
+ }
+
+ return 0;
+}
+
+static struct seq_operations gsDumpDebugReadOps =
+{
+ .start = _DebugDumpDebugSeqStart,
+ .stop = _DebugDumpDebugSeqStop,
+ .next = _DebugDumpDebugSeqNext,
+ .show = _DebugDumpDebugSeqShow,
+};
+/*************************************************************************/ /*!
+ Firmware Trace DebugFS entry
+*/ /**************************************************************************/
+
+#if defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS)
+static void *_DebugFWTraceCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode, va_list va)
+{
+ loff_t *puiCurrentPosition = va_arg(va, loff_t *);
+ loff_t uiPosition = va_arg(va, loff_t);
+ loff_t uiCurrentPosition = *puiCurrentPosition;
+
+ (*puiCurrentPosition)++;
+
+ return (uiCurrentPosition == uiPosition) ? psDevNode : NULL;
+}
+
+static void *_DebugFWTraceSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ if (*puiPosition == 0)
+ {
+ return SEQ_START_TOKEN;
+ }
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugFWTraceCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static void _DebugFWTraceSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+}
+
+static void *_DebugFWTraceSeqNext(struct seq_file *psSeqFile,
+ void *pvData,
+ loff_t *puiPosition)
+{
+ PVRSRV_DATA *psPVRSRVData = (PVRSRV_DATA *)psSeqFile->private;
+ loff_t uiCurrentPosition = 1;
+
+ PVR_UNREFERENCED_PARAMETER(pvData);
+
+ (*puiPosition)++;
+
+ return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+ _DebugFWTraceCompare_AnyVaCb,
+ &uiCurrentPosition,
+ *puiPosition);
+}
+
+static struct seq_file *gpsFWTracePrintfSeqFile = IMG_NULL;
+
+static void _FWTraceSeqPrintf(const IMG_CHAR *pszFormat, ...)
+{
+ if (gpsFWTracePrintfSeqFile)
+ {
+ IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
+ va_list ArgList;
+
+ va_start(ArgList, pszFormat);
+ vsnprintf(szBuffer, PVR_MAX_DEBUG_MESSAGE_LEN, pszFormat, ArgList);
+ seq_printf(gpsFWTracePrintfSeqFile, "%s\n", szBuffer);
+ va_end(ArgList);
+ }
+}
+
+static int _DebugFWTraceSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ if (pvData != NULL && pvData != SEQ_START_TOKEN)
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+
+ if (psDeviceNode->pvDevice != NULL)
+ {
+ PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ gpsFWTracePrintfSeqFile = psSeqFile;
+ RGXDumpFirmwareTrace(_FWTraceSeqPrintf, psDevInfo);
+ gpsFWTracePrintfSeqFile = IMG_NULL;
+ }
+ }
+
+ return 0;
+}
+
+static struct seq_operations gsFWTraceReadOps =
+{
+ .start = _DebugFWTraceSeqStart,
+ .stop = _DebugFWTraceSeqStop,
+ .next = _DebugFWTraceSeqNext,
+ .show = _DebugFWTraceSeqShow,
+};
+#endif
+
+
+/*************************************************************************/ /*!
+ Debug level DebugFS entry
+*/ /**************************************************************************/
+
+#if defined(DEBUG)
+static void *DebugLevelSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
+{
+ if (*puiPosition == 0)
+ {
+ return psSeqFile->private;
+ }
+
+ return NULL;
+}
+
+static void DebugLevelSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+}
+
+static void *DebugLevelSeqNext(struct seq_file *psSeqFile,
+ void *pvData,
+ loff_t *puiPosition)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+ PVR_UNREFERENCED_PARAMETER(puiPosition);
+
+ return NULL;
+}
+
+static int DebugLevelSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ if (pvData != NULL)
+ {
+ IMG_UINT32 uiDebugLevel = *((IMG_UINT32 *)pvData);
+
+ seq_printf(psSeqFile, "%u\n", uiDebugLevel);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static struct seq_operations gsDebugLevelReadOps =
+{
+ .start = DebugLevelSeqStart,
+ .stop = DebugLevelSeqStop,
+ .next = DebugLevelSeqNext,
+ .show = DebugLevelSeqShow,
+};
+
+
+static IMG_INT DebugLevelSet(const char __user *pcBuffer,
+ size_t uiCount,
+ loff_t uiPosition,
+ void *pvData)
+{
+ IMG_UINT32 *uiDebugLevel = (IMG_UINT32 *)pvData;
+ IMG_CHAR acDataBuffer[6];
+
+ if (uiPosition != 0)
+ {
+ return -EIO;
+ }
+
+ if (uiCount > (sizeof(acDataBuffer) / sizeof(acDataBuffer[0])))
+ {
+ return -EINVAL;
+ }
+
+ if (pvr_copy_from_user(acDataBuffer, pcBuffer, uiCount))
+ {
+ return -EINVAL;
+ }
+
+ if (acDataBuffer[uiCount - 1] != '\n')
+ {
+ return -EINVAL;
+ }
+
+ if (sscanf(acDataBuffer, "%u", &gPVRDebugLevel) == 0)
+ {
+ return -EINVAL;
+ }
+
+ /* As this is Linux the next line uses a GCC builtin function */
+ (*uiDebugLevel) &= (1 << __builtin_ffsl(DBGPRIV_LAST)) - 1;
+
+ return uiCount;
+}
+#endif /* defined(DEBUG) */
+
+static struct dentry *gpsVersionDebugFSEntry;
+static struct dentry *gpsNodesDebugFSEntry;
+static struct dentry *gpsStatusDebugFSEntry;
+static struct dentry *gpsDumpDebugDebugFSEntry;
+
+#if defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS)
+static struct dentry *gpsFWTraceDebugFSEntry;
+#endif
+
+#if defined(DEBUG)
+static struct dentry *gpsDebugLevelDebugFSEntry;
+#endif
+
+int PVRDebugCreateDebugFSEntries(void)
+{
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ int iResult;
+
+ PVR_ASSERT(psPVRSRVData != NULL);
+ PVR_ASSERT(gpsVersionDebugFSEntry == NULL);
+
+ iResult = PVRDebugFSCreateEntry("version",
+ NULL,
+ &gsDebugVersionReadOps,
+ NULL,
+ psPVRSRVData,
+ &gpsVersionDebugFSEntry);
+ if (iResult != 0)
+ {
+ return iResult;
+ }
+
+ iResult = PVRDebugFSCreateEntry("nodes",
+ NULL,
+ &gsDebugNodesReadOps,
+ NULL,
+ psPVRSRVData,
+ &gpsNodesDebugFSEntry);
+ if (iResult != 0)
+ {
+ goto ErrorRemoveVersionEntry;
+ }
+
+ iResult = PVRDebugFSCreateEntry("status",
+ NULL,
+ &gsDebugStatusReadOps,
+ (PVRSRV_ENTRY_WRITE_FUNC *)DebugStatusSet,
+ psPVRSRVData,
+ &gpsStatusDebugFSEntry);
+ if (iResult != 0)
+ {
+ goto ErrorRemoveNodesEntry;
+ }
+
+ iResult = PVRDebugFSCreateEntry("debug_dump",
+ NULL,
+ &gsDumpDebugReadOps,
+ NULL,
+ psPVRSRVData,
+ &gpsDumpDebugDebugFSEntry);
+ if (iResult != 0)
+ {
+ goto ErrorRemoveStatusEntry;
+ }
+
+#if defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS)
+ iResult = PVRDebugFSCreateEntry("firmware_trace",
+ NULL,
+ &gsFWTraceReadOps,
+ NULL,
+ psPVRSRVData,
+ &gpsFWTraceDebugFSEntry);
+ if (iResult != 0)
+ {
+ goto ErrorRemoveDumpDebugEntry;
+ }
+#endif
+
+#if defined(DEBUG)
+ iResult = PVRDebugFSCreateEntry("debug_level",
+ NULL,
+ &gsDebugLevelReadOps,
+ (PVRSRV_ENTRY_WRITE_FUNC *)DebugLevelSet,
+ &gPVRDebugLevel,
+ &gpsDebugLevelDebugFSEntry);
+ if (iResult != 0)
+ {
+#if defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS)
+ goto ErrorRemoveFWTraceLogEntry;
+#else
+ goto ErrorRemoveDumpDebugEntry;
+#endif
+ }
+#endif
+
+ return 0;
+
+#if (defined(DEBUG) && defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS))
+ErrorRemoveFWTraceLogEntry:
+ PVRDebugFSRemoveEntry(gpsFWTraceDebugFSEntry);
+ gpsFWTraceDebugFSEntry = NULL;
+#endif
+
+#if (defined(DEBUG) || defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS))
+ErrorRemoveDumpDebugEntry:
+ PVRDebugFSRemoveEntry(gpsDumpDebugDebugFSEntry);
+ gpsDumpDebugDebugFSEntry = NULL;
+#endif
+
+ErrorRemoveStatusEntry:
+ PVRDebugFSRemoveEntry(gpsStatusDebugFSEntry);
+ gpsStatusDebugFSEntry = NULL;
+
+ErrorRemoveNodesEntry:
+ PVRDebugFSRemoveEntry(gpsNodesDebugFSEntry);
+ gpsNodesDebugFSEntry = NULL;
+
+ErrorRemoveVersionEntry:
+ PVRDebugFSRemoveEntry(gpsVersionDebugFSEntry);
+ gpsVersionDebugFSEntry = NULL;
+
+ return iResult;
+}
+
+void PVRDebugRemoveDebugFSEntries(void)
+{
+#if defined(DEBUG)
+ if (gpsDebugLevelDebugFSEntry != NULL)
+ {
+ PVRDebugFSRemoveEntry(gpsDebugLevelDebugFSEntry);
+ gpsDebugLevelDebugFSEntry = NULL;
+ }
+#endif
+
+#if defined(PVRSRV_ENABLE_FW_TRACE_DEBUGFS)
+ if (gpsFWTraceDebugFSEntry != NULL)
+ {
+ PVRDebugFSRemoveEntry(gpsFWTraceDebugFSEntry);
+ gpsFWTraceDebugFSEntry = NULL;
+ }
+#endif
+
+ if (gpsDumpDebugDebugFSEntry != NULL)
+ {
+ PVRDebugFSRemoveEntry(gpsDumpDebugDebugFSEntry);
+ gpsDumpDebugDebugFSEntry = NULL;
+ }
+
+ if (gpsStatusDebugFSEntry != NULL)
+ {
+ PVRDebugFSRemoveEntry(gpsStatusDebugFSEntry);
+ gpsStatusDebugFSEntry = NULL;
+ }
+
+ if (gpsNodesDebugFSEntry != NULL)
+ {
+ PVRDebugFSRemoveEntry(gpsNodesDebugFSEntry);
+ gpsNodesDebugFSEntry = NULL;
+ }
+
+ if (gpsVersionDebugFSEntry != NULL)
+ {
+ PVRDebugFSRemoveEntry(gpsVersionDebugFSEntry);
+ gpsVersionDebugFSEntry = NULL;
+ }
+}
+
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.c b/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.c
new file mode 100644
index 000000000000..044622cda23d
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.c
@@ -0,0 +1,454 @@
+/*************************************************************************/ /*!
+@File
+@Title Functions for creating debugfs directories and entries.
+@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/module.h>
+#include <linux/slab.h>
+
+#include "pvr_debug.h"
+#include "pvr_debugfs.h"
+
+#define PVR_DEBUGFS_DIR_NAME "pvr"
+
+static struct dentry *gpsPVRDebugFSEntryDir = NULL;
+
+
+/*************************************************************************/ /*!
+ Statistic entry read functions
+*/ /**************************************************************************/
+
+typedef struct _PVR_DEBUGFS_DRIVER_STAT_
+{
+ struct dentry *psEntry;
+ void *pvData;
+ PVRSRV_GET_NEXT_STAT_FUNC *pfnGetNextStat;
+ IMG_INT32 i32StatValue;
+ IMG_CHAR *pszStatFormat;
+} PVR_DEBUGFS_DRIVER_STAT;
+
+
+static void *_DebugFSStatisticSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
+{
+ PVR_DEBUGFS_DRIVER_STAT *psStatData = (PVR_DEBUGFS_DRIVER_STAT *)psSeqFile->private;
+ IMG_BOOL bResult;
+
+ bResult = psStatData->pfnGetNextStat(psStatData->pvData,
+ (IMG_UINT32)(*puiPosition),
+ &psStatData->i32StatValue,
+ &psStatData->pszStatFormat);
+
+ return bResult ? psStatData : NULL;
+}
+
+static void _DebugFSStatisticSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+}
+
+static void *_DebugFSStatisticSeqNext(struct seq_file *psSeqFile,
+ void *pvData,
+ loff_t *puiPosition)
+{
+ PVR_DEBUGFS_DRIVER_STAT *psStatData = (PVR_DEBUGFS_DRIVER_STAT *)psSeqFile->private;
+ IMG_BOOL bResult;
+
+ (*puiPosition)++;
+
+ bResult = psStatData->pfnGetNextStat(psStatData->pvData,
+ (IMG_UINT32)(*puiPosition),
+ &psStatData->i32StatValue,
+ &psStatData->pszStatFormat);
+
+ return bResult ? psStatData : NULL;
+}
+
+static int _DebugFSStatisticSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_DEBUGFS_DRIVER_STAT *psStatData = (PVR_DEBUGFS_DRIVER_STAT *)pvData;
+
+ if (psStatData != NULL)
+ {
+ if (psStatData->pszStatFormat == NULL)
+ {
+ return -EINVAL;
+ }
+
+ seq_printf(psSeqFile, psStatData->pszStatFormat, psStatData->i32StatValue);
+ }
+
+ return 0;
+}
+
+static struct seq_operations gsDebugFSStatisticReadOps =
+{
+ .start = _DebugFSStatisticSeqStart,
+ .stop = _DebugFSStatisticSeqStop,
+ .next = _DebugFSStatisticSeqNext,
+ .show = _DebugFSStatisticSeqShow,
+};
+
+
+/*************************************************************************/ /*!
+ Common internal API
+*/ /**************************************************************************/
+
+typedef struct _PVR_DEBUGFS_PRIV_DATA_
+{
+ struct seq_operations *psReadOps;
+ PVRSRV_ENTRY_WRITE_FUNC *pfnWrite;
+ void *pvData;
+} PVR_DEBUGFS_PRIV_DATA;
+
+static int _DebugFSFileOpen(struct inode *psINode, struct file *psFile)
+{
+ PVR_DEBUGFS_PRIV_DATA *psPrivData = (PVR_DEBUGFS_PRIV_DATA *)psINode->i_private;
+ int iResult;
+
+ iResult = seq_open(psFile, psPrivData->psReadOps);
+ if (iResult == 0)
+ {
+ struct seq_file *psSeqFile = psFile->private_data;
+
+ psSeqFile->private = psPrivData->pvData;
+ }
+
+ return iResult;
+}
+
+static ssize_t _DebugFSFileWrite(struct file *psFile,
+ const char __user *pszBuffer,
+ size_t uiCount,
+ loff_t *puiPosition)
+{
+ struct inode *psINode = psFile->f_path.dentry->d_inode;
+ PVR_DEBUGFS_PRIV_DATA *psPrivData = (PVR_DEBUGFS_PRIV_DATA *)psINode->i_private;
+
+ if (psPrivData->pfnWrite == NULL)
+ {
+ return -EIO;
+ }
+
+ return psPrivData->pfnWrite(pszBuffer, uiCount, *puiPosition, psPrivData->pvData);
+}
+
+static const struct file_operations gsPVRDebugFSFileOps =
+{
+ .owner = THIS_MODULE,
+ .open = _DebugFSFileOpen,
+ .read = seq_read,
+ .write = _DebugFSFileWrite,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+
+/*************************************************************************/ /*!
+ Public API
+*/ /**************************************************************************/
+
+/*************************************************************************/ /*!
+@Function PVRDebugFSInit
+@Description Initialise PVR debugfs support. This should be called before
+ using any PVRDebugFS functions.
+@Return int On success, returns 0. Otherwise, returns an
+ error code.
+*/ /**************************************************************************/
+int PVRDebugFSInit(void)
+{
+ PVR_ASSERT(gpsPVRDebugFSEntryDir == NULL);
+
+ gpsPVRDebugFSEntryDir = debugfs_create_dir(PVR_DEBUGFS_DIR_NAME, NULL);
+ if (gpsPVRDebugFSEntryDir == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Cannot create '%s' debugfs root directory",
+ __FUNCTION__, PVR_DEBUGFS_DIR_NAME));
+
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/*************************************************************************/ /*!
+@Function PVRDebugFSDeInit
+@Description Deinitialise PVR debugfs support. This should be called only
+ if PVRDebugFSInit() has already been called. All debugfs
+ directories and entries should be removed otherwise this
+ function will fail.
+@Return void
+*/ /**************************************************************************/
+void PVRDebugFSDeInit(void)
+{
+ PVR_ASSERT(gpsPVRDebugFSEntryDir != NULL);
+
+ debugfs_remove(gpsPVRDebugFSEntryDir);
+ gpsPVRDebugFSEntryDir = NULL;
+}
+
+/*************************************************************************/ /*!
+@Function PVRDebugFSCreateEntryDir
+@Description Create a directory for debugfs entries that will be located
+ under the root directory, as created by
+ PVRDebugFSCreateEntries().
+@Input pszName String containing the name for the directory.
+@Input psParentDir The parent directory in which to create the new
+ directory. This should either be NULL, meaning it
+ should be created in the root directory, or a
+ pointer to a directory as returned by this
+ function.
+@Output ppsDir On success, points to the newly created
+ directory.
+@Return int On success, returns 0. Otherwise, returns an
+ error code.
+*/ /**************************************************************************/
+int PVRDebugFSCreateEntryDir(IMG_CHAR *pszName,
+ struct dentry *psParentDir,
+ struct dentry **ppsDir)
+{
+ struct dentry *psDir;
+
+ PVR_ASSERT(gpsPVRDebugFSEntryDir != NULL);
+
+ if (pszName == NULL || ppsDir == NULL)
+ {
+ return -EINVAL;
+ }
+
+ psDir = debugfs_create_dir(pszName,
+ (psParentDir) ? psParentDir : gpsPVRDebugFSEntryDir);
+ if (psDir == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Cannot create '%s' debugfs directory",
+ __FUNCTION__, pszName));
+
+ return -ENOMEM;
+ }
+
+ *ppsDir = psDir;
+
+ return 0;
+}
+
+/*************************************************************************/ /*!
+@Function PVRDebugFSRemoveEntryDir
+@Description Remove a directory that was created by
+ PVRDebugFSCreateEntryDir(). Any directories or files created
+ under the directory being removed should be removed first.
+@Input psDir Pointer representing the directory to be removed.
+@Return void
+*/ /**************************************************************************/
+void PVRDebugFSRemoveEntryDir(struct dentry *psDir)
+{
+ debugfs_remove(psDir);
+}
+
+/*************************************************************************/ /*!
+@Function PVRDebugFSCreateEntry
+@Description Create an entry in the specified directory.
+@Input pszName String containing the name for the entry.
+@Input pvDir Pointer from PVRDebugFSCreateEntryDir()
+ representing the directory in which to create
+ the entry or NULL for the root directory.
+@Input psReadOps Pointer to structure containing the necessary
+ functions to read from the entry.
+@Input pfnWrite Callback function used to write to the entry.
+@Input pvData Private data to be passed to the read
+ functions, in the seq_file private member, and
+ the write function callback.
+@Output ppsEntry On success, points to the newly created entry.
+@Return int On success, returns 0. Otherwise, returns an
+ error code.
+*/ /**************************************************************************/
+int PVRDebugFSCreateEntry(const char *pszName,
+ void *pvDir,
+ struct seq_operations *psReadOps,
+ PVRSRV_ENTRY_WRITE_FUNC *pfnWrite,
+ void *pvData,
+ struct dentry **ppsEntry)
+{
+ PVR_DEBUGFS_PRIV_DATA *psPrivData;
+ struct dentry *psEntry;
+ umode_t uiMode;
+
+ PVR_ASSERT(gpsPVRDebugFSEntryDir != NULL);
+
+ psPrivData = kmalloc(sizeof(*psPrivData), GFP_KERNEL);
+ if (psPrivData == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ psPrivData->psReadOps = psReadOps;
+ psPrivData->pfnWrite = pfnWrite;
+ psPrivData->pvData = pvData;
+
+ uiMode = S_IFREG;
+
+ if (psReadOps != NULL)
+ {
+ uiMode |= S_IRUGO;
+ }
+
+ if (pfnWrite != NULL)
+ {
+ uiMode |= S_IWUSR;
+ }
+
+ psEntry = debugfs_create_file(pszName,
+ uiMode,
+ (pvDir != NULL) ? (struct dentry *)pvDir : gpsPVRDebugFSEntryDir,
+ psPrivData,
+ &gsPVRDebugFSFileOps);
+ if (IS_ERR(psEntry))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Cannot create debugfs '%s' file",
+ __FUNCTION__, pszName));
+
+ return PTR_ERR(psEntry);
+ }
+
+ /* take reference on inode (for allocation held in d_inode->i_private) - stops
+ * inode being removed until we have freed the memory allocated in i_private */
+ igrab(psEntry->d_inode);
+
+ *ppsEntry = psEntry;
+
+ return 0;
+}
+
+/*************************************************************************/ /*!
+@Function PVRDebugFSRemoveEntry
+@Description Removes an entry that was created by PVRDebugFSCreateEntry().
+@Input psEntry Pointer representing the entry to be removed.
+@Return void
+*/ /**************************************************************************/
+void PVRDebugFSRemoveEntry(struct dentry *psEntry)
+{
+ if(psEntry != IMG_NULL)
+ {
+ /* Free any private data that was provided to debugfs_create_file() */
+ if (psEntry->d_inode->i_private != NULL)
+ {
+ kfree(psEntry->d_inode->i_private);
+ /* drop reference on inode now that we have freed the allocated memory*/
+ iput(psEntry->d_inode);
+ }
+
+ debugfs_remove(psEntry);
+ }
+}
+
+/*************************************************************************/ /*!
+@Function PVRDebugFSCreateStatisticEntry
+@Description Create a statistic entry in the specified directory.
+@Input pszName String containing the name for the entry.
+@Input pvDir Pointer from PVRDebugFSCreateEntryDir()
+ representing the directory in which to create
+ the entry or NULL for the root directory.
+@Input pfnGetNextStat A callback function used to get the next
+ statistic when reading from the statistic
+ entry.
+@Input pvData Private data to be passed to the provided
+ callback function.
+@Return void * On success, a pointer representing the newly
+ created statistic entry. Otherwise, NULL.
+*/ /**************************************************************************/
+void *PVRDebugFSCreateStatisticEntry(const char *pszName,
+ void *pvDir,
+ PVRSRV_GET_NEXT_STAT_FUNC *pfnGetNextStat,
+ void *pvData)
+{
+ PVR_DEBUGFS_DRIVER_STAT *psStatData;
+ int iResult;
+
+ if (pszName == NULL || pfnGetNextStat == NULL)
+ {
+ return NULL;
+ }
+
+ psStatData = kzalloc(sizeof(*psStatData), GFP_KERNEL);
+ if (psStatData == NULL)
+ {
+ return NULL;
+ }
+
+ psStatData->pvData = pvData;
+ psStatData->pfnGetNextStat = pfnGetNextStat;
+
+ iResult = PVRDebugFSCreateEntry(pszName,
+ pvDir,
+ &gsDebugFSStatisticReadOps,
+ NULL,
+ psStatData,
+ &psStatData->psEntry);
+ if (iResult != 0)
+ {
+ kfree(psStatData);
+ return NULL;
+ }
+
+ return psStatData;
+}
+
+/*************************************************************************/ /*!
+@Function PVRDebugFSRemoveStatisticEntry
+@Description Removes a statistic entry that was created by
+ PVRDebugFSCreateStatisticEntry().
+@Input pvEntry Pointer representing the statistic entry to be
+ removed.
+@Return void
+*/ /**************************************************************************/
+void PVRDebugFSRemoveStatisticEntry(void *pvStatEntry)
+{
+ PVR_DEBUGFS_DRIVER_STAT *psStatData = (PVR_DEBUGFS_DRIVER_STAT *)pvStatEntry;
+
+ if (psStatData != NULL)
+ {
+ PVRDebugFSRemoveEntry(psStatData->psEntry);
+
+ kfree(psStatData);
+ }
+}
+
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.h b/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.h
new file mode 100644
index 000000000000..7ac45888bf66
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_debugfs.h
@@ -0,0 +1,83 @@
+/*************************************************************************/ /*!
+@File
+@Title Functions for creating debugfs directories and entries.
+@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(__PVR_DEBUGFS_H__)
+#define __PVR_DEBUGFS_H__
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "img_types.h"
+
+typedef ssize_t (PVRSRV_ENTRY_WRITE_FUNC)(const char __user *pszBuffer,
+ size_t uiCount,
+ loff_t uiPosition,
+ void *pvData);
+
+typedef IMG_BOOL (PVRSRV_GET_NEXT_STAT_FUNC)(void *pvStatPtr,
+ IMG_UINT32 uiStatNumber,
+ IMG_INT32 *piStatData,
+ IMG_CHAR **ppszStatFmtText);
+
+int PVRDebugFSInit(void);
+void PVRDebugFSDeInit(void);
+
+int PVRDebugFSCreateEntryDir(IMG_CHAR *pszName,
+ struct dentry *psParentDir,
+ struct dentry **ppsDir);
+void PVRDebugFSRemoveEntryDir(struct dentry *psDir);
+
+int PVRDebugFSCreateEntry(const char *pszName,
+ void *pvDir,
+ struct seq_operations *psReadOps,
+ PVRSRV_ENTRY_WRITE_FUNC *pfnWrite,
+ void *pvData,
+ struct dentry **ppsEntry);
+void PVRDebugFSRemoveEntry(struct dentry *psEntry);
+
+void *PVRDebugFSCreateStatisticEntry(const char *pszName,
+ void *pvDir,
+ PVRSRV_GET_NEXT_STAT_FUNC *pfnGetNextStat,
+ void *pvData);
+void PVRDebugFSRemoveStatisticEntry(void *pvStatEntry);
+
+#endif /* !defined(__PVR_DEBUGFS_H__) */
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.c b/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.c
new file mode 100644
index 000000000000..9bb0e920c972
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.c
@@ -0,0 +1,408 @@
+/*************************************************************************/ /*!
+@File pvr_gputrace.c
+@Title PVR GPU Trace module Linux implementation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "pvrsrv_error.h"
+#include "srvkm.h"
+#include "pvr_debug.h"
+#include "pvr_debugfs.h"
+#include "pvr_uaccess.h"
+
+#include "pvr_gputrace.h"
+
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/gpu.h>
+
+#define KM_FTRACE_NO_PRIORITY (0)
+
+
+/******************************************************************************
+ Module internal implementation
+******************************************************************************/
+
+/* Circular buffer sizes, must be a power of two */
+#define PVRSRV_KM_FTRACE_JOB_MAX (512)
+#define PVRSRV_KM_FTRACE_CTX_MAX (16)
+
+#define PVRSRV_FTRACE_JOB_FLAG_MASK (0xFF000000)
+#define PVRSRV_FTRACE_JOB_ID_MASK (0x00FFFFFF)
+#define PVRSRV_FTRACE_JOB_FLAG_ENQUEUED (0x80000000)
+
+#define PVRSRV_FTRACE_JOB_GET_ID(pa) ((pa)->ui32FlagsAndID & PVRSRV_FTRACE_JOB_ID_MASK)
+#define PVRSRV_FTRACE_JOB_SET_ID_CLR_FLAGS(pa, id) ((pa)->ui32FlagsAndID = PVRSRV_FTRACE_JOB_ID_MASK & (id))
+
+#define PVRSRV_FTRACE_JOB_GET_FLAGS(pa) ((pa)->ui32FlagsAndID & PVRSRV_FTRACE_JOB_FLAG_MASK)
+#define PVRSRV_FTRACE_JOB_SET_FLAGS(pa, fl) ((pa)->ui32FlagsAndID |= PVRSRV_FTRACE_JOB_FLAG_MASK & (fl))
+
+typedef struct _PVRSRV_FTRACE_JOB_
+{
+ /* Job ID calculated, no need to store it. */
+ IMG_UINT32 ui32FlagsAndID;
+ IMG_UINT32 ui32ExtJobRef;
+ IMG_UINT32 ui32IntJobRef;
+} PVRSRV_FTRACE_GPU_JOB;
+
+
+typedef struct _PVRSRV_FTRACE_GPU_CTX_
+{
+ /* Context ID is calculated, no need to store it IMG_UINT32 ui32CtxID; */
+ IMG_UINT32 ui32PID;
+
+ /* Every context has a circular buffer of jobs */
+ IMG_UINT16 ui16JobWrite; /*!< Next position to write to */
+ PVRSRV_FTRACE_GPU_JOB asJobs[PVRSRV_KM_FTRACE_JOB_MAX];
+} PVRSRV_FTRACE_GPU_CTX;
+
+
+typedef struct _PVRSRV_FTRACE_GPU_DATA_
+{
+ IMG_UINT16 ui16CtxWrite; /*!< Next position to write to */
+ PVRSRV_FTRACE_GPU_CTX asFTraceContext[PVRSRV_KM_FTRACE_CTX_MAX];
+} PVRSRV_FTRACE_GPU_DATA;
+
+PVRSRV_FTRACE_GPU_DATA gsFTraceGPUData;
+
+static void CreateJob(IMG_UINT32 ui32PID, IMG_UINT32 ui32ExtJobRef,
+ IMG_UINT32 ui32IntJobRef)
+{
+ PVRSRV_FTRACE_GPU_CTX* psContext = IMG_NULL;
+ PVRSRV_FTRACE_GPU_JOB* psJob = IMG_NULL;
+ IMG_UINT32 i;
+
+ /* Search for a previously created CTX object */
+ for (i = 0; i < PVRSRV_KM_FTRACE_CTX_MAX; ++i)
+ {
+ if(gsFTraceGPUData.asFTraceContext[i].ui32PID == ui32PID)
+ {
+ psContext = &(gsFTraceGPUData.asFTraceContext[i]);
+ break;
+ }
+ }
+
+ /* If not present in the CB history, create it */
+ if (psContext == NULL)
+ {
+ /*
+ We overwrite old contexts as we don't get a "finished" indication
+ so we assume PVRSRV_KM_FTRACE_CTX_MAX is a sufficient number of
+ process contexts in use at any one time.
+ */
+ i = gsFTraceGPUData.ui16CtxWrite;
+
+ gsFTraceGPUData.asFTraceContext[i].ui32PID = ui32PID;
+ gsFTraceGPUData.asFTraceContext[i].ui16JobWrite = 0;
+ psContext = &(gsFTraceGPUData.asFTraceContext[i]);
+
+ /* Advance the write position of the context CB. */
+ gsFTraceGPUData.ui16CtxWrite = (i+1) & (PVRSRV_KM_FTRACE_CTX_MAX-1);
+ }
+
+ /*
+ This is just done during the first kick so it is assumed the job is not
+ in the CB of jobs yet so we create it. Clear flags.
+ */
+ psJob = &(psContext->asJobs[psContext->ui16JobWrite]);
+ PVRSRV_FTRACE_JOB_SET_ID_CLR_FLAGS(psJob, 1001+psContext->ui16JobWrite);
+ psJob->ui32ExtJobRef = ui32ExtJobRef;
+ psJob->ui32IntJobRef = ui32IntJobRef;
+
+ /*
+ Advance the write position of the job CB. Overwrite oldest job
+ when buffer overflows
+ */
+ psContext->ui16JobWrite = (psContext->ui16JobWrite + 1) & (PVRSRV_KM_FTRACE_JOB_MAX-1);
+}
+
+
+static PVRSRV_ERROR GetCtxAndJobID(IMG_UINT32 ui32PID,
+ IMG_UINT32 ui32ExtJobRef, IMG_UINT32 ui32IntJobRef,
+ IMG_UINT32 *pui32CtxID, PVRSRV_FTRACE_GPU_JOB** ppsJob)
+{
+ PVRSRV_FTRACE_GPU_CTX* psContext = IMG_NULL;
+ IMG_UINT32 i;
+
+ /* Search for the process context object in the CB */
+ for (i = 0; i < PVRSRV_KM_FTRACE_CTX_MAX; ++i)
+ {
+ if(gsFTraceGPUData.asFTraceContext[i].ui32PID == ui32PID)
+ {
+ psContext = &(gsFTraceGPUData.asFTraceContext[i]);
+ /* Derive context ID from CB index: 101..101+PVRSRV_KM_FTRACE_CTX_MAX */
+ *pui32CtxID = 101+i;
+ break;
+ }
+ }
+
+ /* If not found, return an error, let caller trace the error */
+ if (psContext == NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"GetCtxAndJobID: Failed to find context ID for PID %d", ui32PID));
+ return PVRSRV_ERROR_PROCESS_NOT_FOUND;
+ }
+
+ /* Look for the JobID in the jobs CB */
+ for(i = 0; i < PVRSRV_KM_FTRACE_JOB_MAX; ++i)
+ {
+ if((psContext->asJobs[i].ui32ExtJobRef == ui32ExtJobRef) &&
+ (psContext->asJobs[i].ui32IntJobRef == ui32IntJobRef))
+ {
+ /* Derive job ID from CB index: 1001..1001+PVRSRV_KM_FTRACE_JOB_MAX */
+ *ppsJob = &psContext->asJobs[i];
+ return PVRSRV_OK;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,"GetCtxAndJobID: Failed to find job ID for extJobRef %d, intJobRef %x", ui32ExtJobRef, ui32IntJobRef));
+ return PVRSRV_ERROR_NOT_FOUND;
+}
+
+
+/* DebugFS entry for the feature's on/off file */
+static struct dentry* gpsPVRDebugFSGpuTracingOnEntry = NULL;
+
+
+/*
+ If SUPPORT_GPUTRACE_EVENTS is defined the drive is built with support
+ to route RGX HWPerf packets to the Linux FTrace mechanism. To allow
+ this routing feature to be switched on and off at run-time the following
+ debugfs entry is created:
+ /sys/kernel/debug/pvr/gpu_tracing_on
+ To enable GPU events in the FTrace log type the following on the target:
+ echo Y > /sys/kernel/debug/pvr/gpu_tracing_on
+ To disable, type:
+ echo N > /sys/kernel/debug/pvr/gpu_tracing_on
+
+ It is also possible to enable this feature at driver load by setting the
+ default application hint "EnableFTraceGPU=1" in /etc/powervr.ini.
+*/
+
+static void *GpuTracingSeqStart(struct seq_file *psSeqFile, loff_t *puiPosition)
+{
+ if (*puiPosition == 0)
+ {
+ /* We want only one entry in the sequence, one call to show() */
+ return (void*)1;
+ }
+
+ return NULL;
+}
+
+
+static void GpuTracingSeqStop(struct seq_file *psSeqFile, void *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+}
+
+
+static void *GpuTracingSeqNext(struct seq_file *psSeqFile, void *pvData, loff_t *puiPosition)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ return NULL;
+}
+
+
+static int GpuTracingSeqShow(struct seq_file *psSeqFile, void *pvData)
+{
+ IMG_BOOL bValue = PVRGpuTraceEnabled();
+
+ PVR_UNREFERENCED_PARAMETER(pvData);
+
+ seq_puts(psSeqFile, (bValue ? "Y\n" : "N\n"));
+ return 0;
+}
+
+
+static struct seq_operations gsGpuTracingReadOps =
+{
+ .start = GpuTracingSeqStart,
+ .stop = GpuTracingSeqStop,
+ .next = GpuTracingSeqNext,
+ .show = GpuTracingSeqShow,
+};
+
+
+static IMG_INT GpuTracingSet(const IMG_CHAR *buffer, size_t count, loff_t uiPosition, void *data)
+{
+ IMG_CHAR cFirstChar;
+
+ PVR_UNREFERENCED_PARAMETER(uiPosition);
+ PVR_UNREFERENCED_PARAMETER(data);
+
+ if (!count)
+ {
+ return -EINVAL;
+ }
+
+ if (pvr_copy_from_user(&cFirstChar, buffer, 1))
+ {
+ return -EFAULT;
+ }
+
+ switch (cFirstChar)
+ {
+ case '0':
+ case 'n':
+ case 'N':
+ {
+ PVRGpuTraceEnabledSet(IMG_FALSE);
+ PVR_TRACE(("DISABLED GPU FTrace"));
+ break;
+ }
+ case '1':
+ case 'y':
+ case 'Y':
+ {
+ PVRGpuTraceEnabledSet(IMG_TRUE);
+ PVR_TRACE(("ENABLED GPU FTrace"));
+ break;
+ }
+ }
+
+ return count;
+}
+
+
+/******************************************************************************
+ Module In-bound API
+******************************************************************************/
+
+
+void PVRGpuTraceClientWork(
+ const IMG_UINT32 ui32Pid,
+ const IMG_UINT32 ui32ExtJobRef,
+ const IMG_UINT32 ui32IntJobRef,
+ const IMG_CHAR* pszKickType)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_FTRACE_GPU_JOB* psJob;
+ IMG_UINT32 ui32CtxId = 0;
+
+ PVR_ASSERT(pszKickType);
+
+ PVR_DPF((PVR_DBG_VERBOSE, "PVRGpuTraceClientKick(%s): PID %u, extJobRef %u, intJobRef %u", pszKickType, ui32Pid, ui32ExtJobRef, ui32IntJobRef));
+
+ CreateJob(ui32Pid, ui32ExtJobRef, ui32IntJobRef);
+
+ /*
+ Always create jobs for client work above but only emit the enqueue
+ trace if the feature is enabled.
+ This keeps the lookup tables up to date when the gpu_tracing_on is
+ disabled so that when it is re-enabled the packets that might be in
+ the HWPerf buffer can be decoded in the switch event processing below.
+ */
+ if (PVRGpuTraceEnabled())
+ {
+ eError = GetCtxAndJobID(ui32Pid, ui32ExtJobRef, ui32IntJobRef, &ui32CtxId, &psJob);
+ PVR_LOGRN_IF_ERROR(eError, "GetCtxAndJobID");
+
+ trace_gpu_job_enqueue(ui32CtxId, PVRSRV_FTRACE_JOB_GET_ID(psJob), pszKickType);
+
+ PVRSRV_FTRACE_JOB_SET_FLAGS(psJob, PVRSRV_FTRACE_JOB_FLAG_ENQUEUED);
+ }
+}
+
+
+void PVRGpuTraceWorkSwitch(
+ IMG_UINT64 ui64HWTimestampInOSTime,
+ const IMG_UINT32 ui32Pid,
+ const IMG_UINT32 ui32ExtJobRef,
+ const IMG_UINT32 ui32IntJobRef,
+ const IMG_CHAR* pszWorkType,
+ PVR_GPUTRACE_SWITCH_TYPE eSwType)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_FTRACE_GPU_JOB* psJob = IMG_NULL;
+ IMG_UINT32 ui32CtxId;
+
+ PVR_ASSERT(pszWorkType);
+
+ eError = GetCtxAndJobID(ui32Pid, ui32ExtJobRef, ui32IntJobRef, &ui32CtxId, &psJob);
+ PVR_LOGRN_IF_ERROR(eError, "GetCtxAndJobID");
+
+ PVR_ASSERT(psJob);
+
+ /*
+ Only trace switch event if the job's enqueue event was traced. Necessary
+ for when the GPU tracing is disabled, apps run and re-enabled to avoid
+ orphan switch events from appearing in the trace file.
+ */
+ if (PVRSRV_FTRACE_JOB_GET_FLAGS(psJob) & PVRSRV_FTRACE_JOB_FLAG_ENQUEUED)
+ {
+ if (eSwType == PVR_GPUTRACE_SWITCH_TYPE_END)
+ {
+ /* When the GPU goes idle, we need to trace a switch with a context
+ * ID of 0.
+ */
+ ui32CtxId = 0;
+ }
+
+ trace_gpu_sched_switch(pszWorkType, ui64HWTimestampInOSTime,
+ ui32CtxId, KM_FTRACE_NO_PRIORITY, PVRSRV_FTRACE_JOB_GET_ID(psJob));
+ }
+}
+
+
+PVRSRV_ERROR PVRGpuTraceInit(void)
+{
+ return PVRDebugFSCreateEntry("gpu_tracing_on",
+ NULL,
+ &gsGpuTracingReadOps,
+ (PVRSRV_ENTRY_WRITE_FUNC *)GpuTracingSet,
+ NULL,
+ &gpsPVRDebugFSGpuTracingOnEntry);
+}
+
+
+void PVRGpuTraceDeInit(void)
+{
+ /* Can be NULL if driver startup failed */
+ if (gpsPVRDebugFSGpuTracingOnEntry)
+ {
+ PVRDebugFSRemoveEntry(gpsPVRDebugFSGpuTracingOnEntry);
+ gpsPVRDebugFSGpuTracingOnEntry = NULL;
+ }
+}
+
+
+/******************************************************************************
+ End of file (pvr_gputrace.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.h b/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.h
new file mode 100644
index 000000000000..b681bbe64636
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_gputrace.h
@@ -0,0 +1,96 @@
+/*************************************************************************/ /*!
+@File pvr_gputrace.h
+@Title PVR GPU Trace module common environment interface
+@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 PVR_GPUTRACE_H_
+#define PVR_GPUTRACE_H_
+
+#include "img_types.h"
+
+
+/******************************************************************************
+ Module out-bound API
+******************************************************************************/
+
+/*
+ The device layer of the KM driver defines these two APIs to allow a
+ platform module to set and retrieve the feature's on/off state.
+*/
+extern void PVRGpuTraceEnabledSet(IMG_BOOL bNewValue);
+extern IMG_BOOL PVRGpuTraceEnabled(void);
+
+
+/******************************************************************************
+ Module In-bound API
+******************************************************************************/
+
+typedef enum {
+ PVR_GPUTRACE_SWITCH_TYPE_UNDEF = 0,
+
+ PVR_GPUTRACE_SWITCH_TYPE_BEGIN = 1,
+ PVR_GPUTRACE_SWITCH_TYPE_END = 2
+
+} PVR_GPUTRACE_SWITCH_TYPE;
+
+
+void PVRGpuTraceClientWork(
+ const IMG_UINT32 ui32Pid,
+ const IMG_UINT32 ui32ExtJobRef,
+ const IMG_UINT32 ui32IntJobRef,
+ const IMG_CHAR* pszKickType);
+
+
+void PVRGpuTraceWorkSwitch(
+ IMG_UINT64 ui64OSTimestamp,
+ const IMG_UINT32 ui32Pid,
+ const IMG_UINT32 ui32ExtJobRef,
+ const IMG_UINT32 ui32IntJobRef,
+ const IMG_CHAR* pszWorkType,
+ PVR_GPUTRACE_SWITCH_TYPE eSwType);
+
+
+PVRSRV_ERROR PVRGpuTraceInit(void);
+
+
+void PVRGpuTraceDeInit(void);
+
+
+#endif /* PVR_GPUTRACE_H_ */
diff --git a/drivers/gpu/rogue/services/server/env/linux/pvr_uaccess.h b/drivers/gpu/rogue/services/server/env/linux/pvr_uaccess.h
new file mode 100644
index 000000000000..53c8f0a725d5
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/pvr_uaccess.h
@@ -0,0 +1,106 @@
+/*************************************************************************/ /*!
+@File
+@Title Utility functions for user space access
+@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 __PVR_UACCESS_H__
+#define __PVR_UACCESS_H__
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <asm/uaccess.h>
+
+static inline unsigned long pvr_copy_to_user(void __user *pvTo, const void *pvFrom, unsigned long ulBytes)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+ if (access_ok(VERIFY_WRITE, pvTo, ulBytes))
+ {
+ return __copy_to_user(pvTo, pvFrom, ulBytes);
+ }
+ return ulBytes;
+#else
+ return copy_to_user(pvTo, pvFrom, ulBytes);
+#endif
+}
+
+
+#if defined(__KLOCWORK__)
+ /* this part is only to tell Klocwork not to report false positive because
+ it doesn't understand that pvr_copy_from_user will initialise the memory
+ pointed to by pvTo */
+#include <linux/string.h> /* get the memset prototype */
+static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pvFrom, unsigned long ulBytes)
+{
+ if (pvTo != NULL)
+ {
+ memset(pvTo, 0xAA, ulBytes);
+ return 0;
+ }
+ return 1;
+}
+
+#else /* real implementation */
+
+static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pvFrom, unsigned long ulBytes)
+{
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+ /*
+ * The compile time correctness checking introduced for copy_from_user in
+ * Linux 2.6.33 isn't fully compatible with our usage of the function.
+ */
+ if (access_ok(VERIFY_READ, pvFrom, ulBytes))
+ {
+ return __copy_from_user(pvTo, pvFrom, ulBytes);
+ }
+ return ulBytes;
+#else
+ return copy_from_user(pvTo, pvFrom, ulBytes);
+#endif
+}
+#endif /* klocworks */
+
+#endif /* __PVR_UACCESS_H__ */
+
diff --git a/drivers/gpu/rogue/services/server/env/linux/rogue_trace_events.h b/drivers/gpu/rogue/services/server/env/linux/rogue_trace_events.h
new file mode 100644
index 000000000000..84195c803632
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/rogue_trace_events.h
@@ -0,0 +1,152 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM rogue
+
+#if !defined(_ROGUE_TRACE_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _ROGUE_TRACE_EVENTS_H
+
+#include <linux/tracepoint.h>
+#include <linux/time.h>
+
+TRACE_EVENT(rogue_fence_update,
+
+ TP_PROTO(const char *comm, const char *dm, u32 fw_ctx, u32 offset,
+ u32 sync_fwaddr, u32 sync_value),
+
+ TP_ARGS(comm, dm, fw_ctx, offset, sync_fwaddr, sync_value),
+
+ TP_STRUCT__entry(
+ __string( comm, comm )
+ __string( dm, dm )
+ __field( u32, fw_ctx )
+ __field( u32, offset )
+ __field( u32, sync_fwaddr )
+ __field( u32, sync_value )
+ ),
+
+ TP_fast_assign(
+ __assign_str(comm, comm);
+ __assign_str(dm, dm);
+ __entry->fw_ctx = fw_ctx;
+ __entry->offset = offset;
+ __entry->sync_fwaddr = sync_fwaddr;
+ __entry->sync_value = sync_value;
+ ),
+
+ TP_printk("comm=%s dm=%s fw_ctx=%lx offset=%lu sync_fwaddr=%lx sync_value=%lx",
+ __get_str(comm),
+ __get_str(dm),
+ (unsigned long)__entry->fw_ctx,
+ (unsigned long)__entry->offset,
+ (unsigned long)__entry->sync_fwaddr,
+ (unsigned long)__entry->sync_value)
+);
+
+TRACE_EVENT(rogue_fence_check,
+
+ TP_PROTO(const char *comm, const char *dm, u32 fw_ctx, u32 offset,
+ u32 sync_fwaddr, u32 sync_value),
+
+ TP_ARGS(comm, dm, fw_ctx, offset, sync_fwaddr, sync_value),
+
+ TP_STRUCT__entry(
+ __string( comm, comm )
+ __string( dm, dm )
+ __field( u32, fw_ctx )
+ __field( u32, offset )
+ __field( u32, sync_fwaddr )
+ __field( u32, sync_value )
+ ),
+
+ TP_fast_assign(
+ __assign_str(comm, comm);
+ __assign_str(dm, dm);
+ __entry->fw_ctx = fw_ctx;
+ __entry->offset = offset;
+ __entry->sync_fwaddr = sync_fwaddr;
+ __entry->sync_value = sync_value;
+ ),
+
+ TP_printk("comm=%s dm=%s fw_ctx=%lx offset=%lu sync_fwaddr=%lx sync_value=%lx",
+ __get_str(comm),
+ __get_str(dm),
+ (unsigned long)__entry->fw_ctx,
+ (unsigned long)__entry->offset,
+ (unsigned long)__entry->sync_fwaddr,
+ (unsigned long)__entry->sync_value)
+);
+
+TRACE_EVENT(rogue_create_fw_context,
+
+ TP_PROTO(const char *comm, const char *dm, u32 fw_ctx),
+
+ TP_ARGS(comm, dm, fw_ctx),
+
+ TP_STRUCT__entry(
+ __string( comm, comm )
+ __string( dm, dm )
+ __field( u32, fw_ctx )
+ ),
+
+ TP_fast_assign(
+ __assign_str(comm, comm);
+ __assign_str(dm, dm);
+ __entry->fw_ctx = fw_ctx;
+ ),
+
+ TP_printk("comm=%s dm=%s fw_ctx=%lx",
+ __get_str(comm),
+ __get_str(dm),
+ (unsigned long)__entry->fw_ctx)
+);
+
+#endif /* _ROGUE_TRACE_EVENTS_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+
+/* This is needed because the name of this file doesn't match TRACE_SYSTEM. */
+#define TRACE_INCLUDE_FILE rogue_trace_events
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/rogue/services/server/env/linux/trace_events.c b/drivers/gpu/rogue/services/server/env/linux/trace_events.c
new file mode 100644
index 000000000000..0946156201fa
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/trace_events.c
@@ -0,0 +1,79 @@
+/*************************************************************************/ /*!
+@Title Linux trace event helper functions
+@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/sched.h>
+
+#include "img_types.h"
+#include "rgx_fwif_km.h"
+
+#define CREATE_TRACE_POINTS
+#include "trace_events.h"
+
+/* This is a helper that calls trace_rogue_fence_update for each fence in an
+ * array.
+ */
+void trace_rogue_fence_updates(const char *dm, IMG_UINT32 ui32FWContext,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT uCount,
+ PRGXFWIF_UFO_ADDR *pauiAddresses,
+ IMG_UINT32 *paui32Values)
+{
+ IMG_UINT i;
+ for (i = 0; i < uCount; i++)
+ {
+ trace_rogue_fence_update(current->comm, dm, ui32FWContext, ui32Offset,
+ pauiAddresses[i].ui32Addr, paui32Values[i]);
+ }
+}
+
+void trace_rogue_fence_checks(const char *dm, IMG_UINT32 ui32FWContext,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT uCount,
+ PRGXFWIF_UFO_ADDR *pauiAddresses,
+ IMG_UINT32 *paui32Values)
+{
+ IMG_UINT i;
+ for (i = 0; i < uCount; i++)
+ {
+ trace_rogue_fence_check(current->comm, dm, ui32FWContext, ui32Offset,
+ pauiAddresses[i].ui32Addr, paui32Values[i]);
+ }
+}
diff --git a/drivers/gpu/rogue/services/server/env/linux/trace_events.h b/drivers/gpu/rogue/services/server/env/linux/trace_events.h
new file mode 100644
index 000000000000..64c19e7b114b
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/env/linux/trace_events.h
@@ -0,0 +1,83 @@
+/*************************************************************************/ /*!
+@Title Linux trace events and event helper functions
+@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(TRACE_EVENTS_H)
+#define TRACE_EVENTS_H
+
+#include "rogue_trace_events.h"
+
+/* We need to make these functions do nothing if CONFIG_EVENT_TRACING isn't
+ * enabled, just like the actual trace event functions that the kernel
+ * defines for us.
+ */
+#ifdef CONFIG_EVENT_TRACING
+void trace_rogue_fence_updates(const char *dm, IMG_UINT32 ui32FWContext,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT uCount,
+ PRGXFWIF_UFO_ADDR *pauiAddresses,
+ IMG_UINT32 *paui32Values);
+
+void trace_rogue_fence_checks(const char *dm, IMG_UINT32 ui32FWContext,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT uCount,
+ PRGXFWIF_UFO_ADDR *pauiAddresses,
+ IMG_UINT32 *paui32Values);
+#else /* CONFIG_TRACE_EVENTS */
+static inline
+void trace_rogue_fence_updates(const char *dm, IMG_UINT32 ui32FWContext,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT uCount,
+ PRGXFWIF_UFO_ADDR *pauiAddresses,
+ IMG_UINT32 *paui32Values)
+{
+}
+
+static inline
+void trace_rogue_fence_checks(const char *dm, IMG_UINT32 ui32FWContext,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT uCount,
+ PRGXFWIF_UFO_ADDR *pauiAddresses,
+ IMG_UINT32 *paui32Values)
+{
+}
+#endif /* CONFIG_TRACE_EVENTS */
+
+#endif /* TRACE_EVENTS_H */
diff --git a/drivers/gpu/rogue/services/server/include/cache_generic.h b/drivers/gpu/rogue/services/server/include/cache_generic.h
new file mode 100644
index 000000000000..07ec973b163f
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/cache_generic.h
@@ -0,0 +1,52 @@
+/*************************************************************************/ /*!
+@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 _CACHE_GENERIC_H_
+#define _CACHE_GENERIC_H_
+
+#include "img_types.h"
+#include "cache_external.h"
+#include "device.h"
+#include "pvrsrv_error.h"
+
+PVRSRV_ERROR CacheOpQueue(PVRSRV_CACHE_OP uiCacheOp);
+
+#endif /* _CACHE_GENERIC_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/connection_server.h b/drivers/gpu/rogue/services/server/include/connection_server.h
new file mode 100644
index 000000000000..791cd148fb21
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/connection_server.h
@@ -0,0 +1,98 @@
+/**************************************************************************/ /*!
+@File
+@Title Server side connection management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description API for server side connection management
+@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 _CONNECTION_SERVER_H_
+#define _CONNECTION_SERVER_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "resman.h"
+
+#include "handle.h"
+
+typedef struct _CONNECTION_DATA_
+{
+ PRESMAN_CONTEXT hResManContext;
+ PVRSRV_HANDLE_BASE *psHandleBase;
+ struct _SYNC_CONNECTION_DATA_ *psSyncConnectionData;
+ struct _PDUMP_CONNECTION_DATA_ *psPDumpConnectionData;
+
+ /* True if the process is the initialisation server. */
+ IMG_BOOL bInitProcess;
+
+ /*
+ * OS specific data can be stored via this handle.
+ * See osconnection_server.h for a generic mechanism
+ * for initialising this field.
+ */
+ IMG_HANDLE hOsPrivateData;
+
+ IMG_PVOID hSecureData;
+
+ IMG_HANDLE hProcessStats;
+} CONNECTION_DATA;
+
+PVRSRV_ERROR PVRSRVConnectionConnect(IMG_PVOID *ppvPrivData, IMG_PVOID pvOSData);
+IMG_VOID PVRSRVConnectionDisconnect(IMG_PVOID pvPrivData);
+
+PVRSRV_ERROR PVRSRVConnectionInit(IMG_VOID);
+PVRSRV_ERROR PVRSRVConnectionDeInit(IMG_VOID);
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVConnectionPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVConnectionPrivateData(CONNECTION_DATA *psConnection)
+{
+ return (psConnection != IMG_NULL) ? psConnection->hOsPrivateData : IMG_NULL;
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* _CONNECTION_SERVER_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/dc_server.h b/drivers/gpu/rogue/services/server/include/dc_server.h
new file mode 100644
index 000000000000..c039b06be402
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/dc_server.h
@@ -0,0 +1,156 @@
+/**************************************************************************/ /*!
+@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 _DC_SERVER_H_
+#define _DC_SERVER_H_
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "sync_external.h"
+#include "pvrsrv_surface.h"
+#include "pmr.h"
+#include "kerneldisplay.h"
+#include "sync_server.h"
+
+typedef struct _DC_DEVICE_ DC_DEVICE;
+typedef struct _DC_DISPLAY_CONTEXT_ DC_DISPLAY_CONTEXT;
+typedef struct _DC_BUFFER_ DC_BUFFER;
+typedef DC_BUFFER* DC_PIN_HANDLE;
+
+PVRSRV_ERROR DCDevicesQueryCount(IMG_UINT32 *pui32DeviceCount);
+
+PVRSRV_ERROR DCDevicesEnumerate(IMG_UINT32 ui32DeviceArraySize,
+ IMG_UINT32 *pui32DeviceCount,
+ IMG_UINT32 *paui32DeviceIndex);
+
+PVRSRV_ERROR DCDeviceAcquire(IMG_UINT32 ui32DeviceIndex,
+ DC_DEVICE **ppsDevice);
+
+PVRSRV_ERROR DCDeviceRelease(DC_DEVICE *psDevice);
+
+PVRSRV_ERROR DCGetInfo(DC_DEVICE *psDevice,
+ DC_DISPLAY_INFO *psDisplayInfo);
+
+PVRSRV_ERROR DCPanelQueryCount(DC_DEVICE *psDevice,
+ IMG_UINT32 *pui32NumPanels);
+
+PVRSRV_ERROR DCPanelQuery(DC_DEVICE *psDevice,
+ IMG_UINT32 ui32PanelsArraySize,
+ IMG_UINT32 *pui32NumPanels,
+ PVRSRV_PANEL_INFO *pasPanelInfo);
+
+PVRSRV_ERROR DCFormatQuery(DC_DEVICE *psDevice,
+ IMG_UINT32 ui32FormatArraySize,
+ PVRSRV_SURFACE_FORMAT *pasFormat,
+ IMG_UINT32 *pui32Supported);
+
+PVRSRV_ERROR DCDimQuery(DC_DEVICE *psDevice,
+ IMG_UINT32 ui32DimSize,
+ PVRSRV_SURFACE_DIMS *pasDim,
+ IMG_UINT32 *pui32Supported);
+
+PVRSRV_ERROR DCSetBlank(DC_DEVICE *psDevice,
+ IMG_BOOL bEnabled);
+
+PVRSRV_ERROR DCSetVSyncReporting(DC_DEVICE *psDevice,
+ IMG_BOOL bEnabled);
+
+PVRSRV_ERROR DCLastVSyncQuery(DC_DEVICE *psDevice,
+ IMG_INT64 *pi64Timestamp);
+
+PVRSRV_ERROR DCSystemBufferAcquire(DC_DEVICE *psDevice,
+ IMG_UINT32 *pui32ByteStride,
+ DC_BUFFER **ppsBuffer);
+
+PVRSRV_ERROR DCSystemBufferRelease(DC_BUFFER *psBuffer);
+
+PVRSRV_ERROR DCDisplayContextCreate(DC_DEVICE *psDevice,
+ DC_DISPLAY_CONTEXT **ppsDisplayContext);
+
+PVRSRV_ERROR DCDisplayContextFlush(IMG_VOID);
+
+PVRSRV_ERROR DCDisplayContextConfigureCheck(DC_DISPLAY_CONTEXT *psDisplayContext,
+ IMG_UINT32 ui32PipeCount,
+ PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+ DC_BUFFER **papsBuffers);
+
+PVRSRV_ERROR DCDisplayContextConfigure(DC_DISPLAY_CONTEXT *psDisplayContext,
+ IMG_UINT32 ui32PipeCount,
+ PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
+ DC_BUFFER **papsBuffers,
+ IMG_UINT32 ui32SyncOpCount,
+ SERVER_SYNC_PRIMITIVE **papsSync,
+ IMG_BOOL *pabUpdate,
+ IMG_UINT32 ui32DisplayPeriod,
+ IMG_UINT32 ui32MaxDepth,
+ IMG_INT32 i32AcquireFenceFd,
+ IMG_INT32 *pi32ReleaseFenceFd);
+
+PVRSRV_ERROR DCDisplayContextDestroy(DC_DISPLAY_CONTEXT *psDisplayContext);
+
+PVRSRV_ERROR DCBufferAlloc(DC_DISPLAY_CONTEXT *psDisplayContext,
+ DC_BUFFER_CREATE_INFO *psSurfInfo,
+ IMG_UINT32 *pui32ByteStride,
+ DC_BUFFER **ppsBuffer);
+
+PVRSRV_ERROR DCBufferFree(DC_BUFFER *psBuffer);
+
+PVRSRV_ERROR DCBufferImport(DC_DISPLAY_CONTEXT *psDisplayContext,
+ IMG_UINT32 ui32NumPlanes,
+ PMR **papsImport,
+ DC_BUFFER_IMPORT_INFO *psSurfAttrib,
+ DC_BUFFER **ppsBuffer);
+
+PVRSRV_ERROR DCBufferUnimport(DC_BUFFER *psBuffer);
+
+PVRSRV_ERROR DCBufferAcquire(DC_BUFFER *psBuffer,
+ PMR **psPMR);
+
+PVRSRV_ERROR DCBufferRelease(PMR *psPMR);
+
+PVRSRV_ERROR DCBufferPin(DC_BUFFER *psBuffer, DC_PIN_HANDLE *phPin);
+
+PVRSRV_ERROR DCBufferUnpin(DC_PIN_HANDLE hPin);
+
+PVRSRV_ERROR DCInit(IMG_VOID);
+PVRSRV_ERROR DCDeInit(IMG_VOID);
+
+#endif /*_DC_SERVER_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/debug_request_ids.h b/drivers/gpu/rogue/services/server/include/debug_request_ids.h
new file mode 100644
index 000000000000..9de4988b395f
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/debug_request_ids.h
@@ -0,0 +1,59 @@
+/*************************************************************************/ /*!
+@File
+@Title Debug requester ID's
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header contains the defines for the debug ID's for all the
+ services components
+@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 __DEBUG_REQUEST_IDS__
+#define __DEBUG_REQUEST_IDS__
+
+/* Services controlled devices should be 1st */
+#define DEBUG_REQUEST_RGX (0)
+#define DEBUG_REQUEST_DC (1)
+#define DEBUG_REQUEST_SERVERSYNC (2)
+#define DEBUG_REQUEST_SYS (3)
+#define DEBUG_REQUEST_ANDROIDSYNC (4)
+
+#endif /* __DEBUG_REQUEST_IDS__ */
+
+/******************************************************************************
+ End of file (pvr_tl.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/include/device.h b/drivers/gpu/rogue/services/server/include/device.h
new file mode 100644
index 000000000000..5deddd70f75e
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/device.h
@@ -0,0 +1,300 @@
+/**************************************************************************/ /*!
+@File
+@Title Common Device header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Device related function templates and defines
+@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 __DEVICE_H__
+#define __DEVICE_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "devicemem_heapcfg.h"
+#include "mmu_common.h"
+#include "ra.h" /* RA_ARENA */
+#include "resman.h" /* PRESMAN_ITEM */
+#include "pvrsrv_device.h"
+#include "srvkm.h"
+#include "devicemem.h"
+#include "physheap.h"
+#include "sync.h"
+#include "dllist.h"
+#include "cache_external.h"
+
+#include "lock.h"
+
+/* BM context forward reference */
+typedef struct _BM_CONTEXT_ BM_CONTEXT;
+
+/*********************************************************************/ /*!
+ @Function AllocUFOCallback
+ @Description Device specific callback for allocation of an UFO block
+
+ @Input psDeviceNode Pointer to device node to allocate
+ the UFO for.
+ @Output ppsMemDesc Pointer to pointer for the memdesc of
+ the allocation
+ @Output pui32SyncAddr FW Base address of the UFO block
+ @Output puiSyncPrimBlockSize Size of the UFO block
+
+ @Return PVRSRV_OK if allocation was successful
+ */
+/*********************************************************************/
+typedef PVRSRV_ERROR (*AllocUFOBlockCallback)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ DEVMEM_MEMDESC **ppsMemDesc,
+ IMG_UINT32 *pui32SyncAddr,
+ IMG_UINT32 *puiSyncPrimBlockSize);
+
+/*********************************************************************/ /*!
+ @Function FreeUFOCallback
+ @Description Device specific callback for freeing of an UFO
+
+ @Input psDeviceNode Pointer to device node that the UFO block was
+ allocated from.
+ @Input psMemDesc Pointer to pointer for the memdesc of
+ the UFO block to free.
+ */
+/*********************************************************************/
+typedef IMG_VOID (*FreeUFOBlockCallback)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ DEVMEM_MEMDESC *psMemDesc);
+
+
+typedef struct _DEVICE_MEMORY_INFO_
+{
+ /* size of address space, as log2 */
+ IMG_UINT32 ui32AddressSpaceSizeLog2;
+
+ /*
+ flags, includes physical memory resource types available to the system.
+ Allows for validation at heap creation, define PVRSRV_BACKINGSTORE_XXX
+ */
+ IMG_UINT32 ui32Flags;
+
+ /* heap count. Doesn't include additional heaps from PVRSRVCreateDeviceMemHeap */
+ IMG_UINT32 ui32HeapCount;
+
+ /* BM kernel context for the device */
+ BM_CONTEXT *pBMKernelContext;
+
+ /* BM context list for the device*/
+ BM_CONTEXT *pBMContext;
+
+ /* Blueprints for creating new device memory contexts */
+ IMG_UINT32 uiNumHeapConfigs;
+ DEVMEM_HEAP_CONFIG *psDeviceMemoryHeapConfigArray;
+ DEVMEM_HEAP_BLUEPRINT *psDeviceMemoryHeap;
+} DEVICE_MEMORY_INFO;
+
+
+typedef struct _Px_HANDLE_
+{
+ union
+ {
+ IMG_VOID *pvHandle;
+ IMG_UINT64 ui64Handle;
+ }u;
+} Px_HANDLE;
+
+typedef enum _PVRSRV_DEVICE_STATE_
+{
+ PVRSRV_DEVICE_STATE_UNDEFINED = 0,
+ PVRSRV_DEVICE_STATE_INIT,
+ PVRSRV_DEVICE_STATE_ACTIVE,
+ PVRSRV_DEVICE_STATE_DEINIT,
+} PVRSRV_DEVICE_STATE;
+
+typedef enum _PVRSRV_DEVICE_HEALTH_
+{
+ PVRSRV_DEVICE_HEALTH_STATUS_OK = 0,
+ PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING,
+ PVRSRV_DEVICE_HEALTH_STATUS_DEAD
+} PVRSRV_DEVICE_HEALTH_STATUS;
+
+#define PRVSRV_DEVICE_FLAGS_LMA (1 << 0)
+
+typedef PVRSRV_ERROR (*FN_CREATERAMBACKEDPMR)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr);
+typedef struct _PVRSRV_DEVICE_NODE_
+{
+ PVRSRV_DEVICE_IDENTIFIER sDevId;
+ IMG_UINT32 ui32RefCount;
+
+ PVRSRV_DEVICE_STATE eDevState;
+ PVRSRV_DEVICE_HEALTH_STATUS eHealthStatus;
+
+ /* device specific MMU attributes */
+ MMU_DEVICEATTRIBS *psMMUDevAttrs;
+
+ /*
+ callbacks the device must support:
+ */
+
+ FN_CREATERAMBACKEDPMR pfnCreateRamBackedPMR[PVRSRV_DEVICE_PHYS_HEAP_LAST];
+
+ PVRSRV_ERROR (*pfnMMUPxAlloc)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, IMG_SIZE_T uiSize,
+ Px_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr);
+
+ IMG_VOID (*pfnMMUPxFree)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, Px_HANDLE *psMemHandle);
+
+ PVRSRV_ERROR (*pfnMMUPxMap)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, Px_HANDLE *pshMemHandle,
+ IMG_SIZE_T uiSize, IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_VOID **pvPtr);
+
+ IMG_VOID (*pfnMMUPxUnmap)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+ Px_HANDLE *psMemHandle, IMG_VOID *pvPtr);
+
+ IMG_UINT32 uiMMUPxLog2AllocGran;
+ IMG_CHAR *pszMMUPxPDumpMemSpaceName;
+
+ IMG_VOID (*pfnMMUCacheInvalidate)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+ IMG_HANDLE hDeviceData,
+ MMU_LEVEL eLevel,
+ IMG_BOOL bUnmap);
+
+ PVRSRV_ERROR (*pfnSLCCacheInvalidateRequest)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+ PMR *psPmr);
+
+ IMG_VOID (*pfnDumpDebugInfo)(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
+
+ PVRSRV_ERROR (*pfnUpdateHealthStatus)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+ IMG_BOOL bIsTimerPoll);
+
+ PVRSRV_ERROR (*pfnResetHWRLogs)(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
+
+ /* Method to drain device HWPerf packets from firmware buffer to host buffer */
+ PVRSRV_ERROR (*pfnServiceHWPerf)(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
+
+ PVRSRV_ERROR (*pfnDeviceVersionString)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, IMG_CHAR **ppszVersionString);
+
+ PVRSRV_ERROR (*pfnDeviceClockSpeed)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, IMG_PUINT32 pui32RGXClockSpeed);
+
+ PVRSRV_ERROR (*pfnSoftReset)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, IMG_UINT64 ui64ResetValue);
+
+ PVRSRV_DEVICE_CONFIG *psDevConfig;
+
+ /* device post-finalise compatibility check */
+ PVRSRV_ERROR (*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*,IMG_UINT32 ui32ClientBuildOptions);
+
+ /* Flag indicating that command complete callback needs to be reprocessed */
+ IMG_BOOL bReProcessDeviceCommandComplete;
+
+ /* information about the device's address space and heaps */
+ DEVICE_MEMORY_INFO sDevMemoryInfo;
+
+ /* private device information */
+ IMG_VOID *pvDevice;
+ IMG_UINT32 ui32pvDeviceSize; /* required by GetClassDeviceInfo API */
+
+ IMG_UINT32 ui32Flags;
+
+ IMG_CHAR szRAName[50];
+
+ RA_ARENA *psLocalDevMemArena;
+
+ /*
+ * Pointers to the device's physical memory heap(s)
+ * The first entry (apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]) will be used for allocations
+ * where the PVRSRV_MEMALLOCFLAG_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_DEVICE_PHYS_HEAP_CPU_LOCAL]) will be used for allocations
+ * where the PVRSRV_MEMALLOCFLAG_CPU_LOCAL flag is set. Normally this will be a UMA heap
+ * (but the configuration could specify an LMA heap here, if desired)
+ * 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
+ */
+ PHYS_HEAP *apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_LAST];
+
+ struct _PVRSRV_DEVICE_NODE_ *psNext;
+ struct _PVRSRV_DEVICE_NODE_ **ppsThis;
+
+ /* Functions for notification about memory contexts */
+ PVRSRV_ERROR (*pfnRegisterMemoryContext)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ MMU_CONTEXT *psMMUContext,
+ IMG_HANDLE *hPrivData);
+ IMG_VOID (*pfnUnregisterMemoryContext)(IMG_HANDLE hPrivData);
+
+ /* Funtions for allocation/freeing of UFOs */
+ AllocUFOBlockCallback pfnAllocUFOBlock; /*!< Callback for allocation of a block of UFO memory */
+ FreeUFOBlockCallback pfnFreeUFOBlock; /*!< Callback for freeing of a block of UFO memory */
+
+ PSYNC_PRIM_CONTEXT hSyncPrimContext;
+
+ PVRSRV_CLIENT_SYNC_PRIM *psSyncPrim;
+
+ PVRSRV_CLIENT_SYNC_PRIM *psSyncPrimPreKick;
+
+ IMG_HANDLE hCmdCompNotify;
+ IMG_HANDLE hDbgReqNotify;
+
+#if defined(PDUMP)
+ /* device-level callback which is called when pdump.exe starts.
+ * Should be implemented in device-specific init code, e.g. rgxinit.c
+ */
+ PVRSRV_ERROR (*pfnPDumpInitDevice)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+ /* device-level callback to return pdump ID associated to a memory context */
+ IMG_UINT32 (*pfnMMUGetContextID)(IMG_HANDLE hDevMemContext);
+#endif
+} PVRSRV_DEVICE_NODE;
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccesful,
+ IMG_UINT32 ui32ClientBuildOptions);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32ClientBuildOptions);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __DEVICE_H__ */
+
+/******************************************************************************
+ End of file (device.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/include/devicemem_heapcfg.h b/drivers/gpu/rogue/services/server/include/devicemem_heapcfg.h
new file mode 100644
index 000000000000..39bc7153e207
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/devicemem_heapcfg.h
@@ -0,0 +1,145 @@
+/**************************************************************************/ /*!
+@File
+@Title Temporary Device Memory 2 stuff
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Device memory management
+@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 __DEVICEMEMHEAPCFG_H__
+#define __DEVICEMEMHEAPCFG_H__
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+
+struct _PVRSRV_DEVICE_NODE_;
+
+/*
+ A "heap config" is a blueprint to be used for initial setting up of
+ heaps when a device memory context is created.
+
+ We define a data structure to define this, but it's really down to
+ the caller to populate it. This is all expected to be in-kernel.
+ We provide an API that client code can use to enquire about the
+ blueprint, such that it may do the heap setup during the context
+ creation call on behalf of the user */
+
+/* blueprint for a single heap */
+typedef struct _DEVMEM_HEAP_BLUEPRINT_
+{
+ /* Name of this heap - for debug purposes, and perhaps for lookup
+ by name? */
+ const IMG_CHAR *pszName;
+
+ /* Virtual address of the beginning of the heap. This _must_ be a
+ multiple of the data page size for the heap. It is
+ _recommended_ that it be coarser than that - especially, it
+ should begin on a boundary appropriate to the MMU for the
+ device. For Rogue, this is a Page Directory boundary, or 1GB
+ (virtual address a multiple of 0x0040000000). */
+ IMG_DEV_VIRTADDR sHeapBaseAddr;
+
+ /* Length of the heap. Given that the END address of the heap has
+ a similar restriction to that of the _beginning_ of the heap.
+ That is the heap length _must_ be a whole number of data pages.
+ Again, the recommendation is that it ends on a 1GB boundary.
+ Again, this is not essential, but we do know that (at the time
+ of writing) the current implementation of mmu_common.c is such
+ that no two heaps may share a page directory, thus the
+ remaining virtual space would be wasted if the length were not
+ a multiple of 1GB */
+ IMG_DEVMEM_SIZE_T uiHeapLength;
+
+ /* Data page size. This is the page size that is going to get
+ programmed into the MMU, so it needs to be a valid one for the
+ device. Importantly, the start address and length _must_ be
+ multiples of this page size. Note that the page size is
+ specified as the log 2 relative to 1 byte (e.g. 12 indicates
+ 4kB) */
+ IMG_UINT32 uiLog2DataPageSize;
+} DEVMEM_HEAP_BLUEPRINT;
+
+/* entire named heap config */
+typedef struct _DEVMEM_HEAP_CONFIG_
+{
+ /* Name of this heap config - for debug and maybe lookup */
+ const IMG_CHAR *pszName;
+
+ /* Number of heaps in this config */
+ IMG_UINT32 uiNumHeaps;
+
+ /* Array of individual heap blueprints as defined above */
+ DEVMEM_HEAP_BLUEPRINT *psHeapBlueprintArray;
+} DEVMEM_HEAP_CONFIG;
+
+
+extern PVRSRV_ERROR
+HeapCfgHeapConfigCount(
+ const struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ IMG_UINT32 *puiNumHeapConfigsOut
+);
+
+extern PVRSRV_ERROR
+HeapCfgHeapCount(
+ const struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 *puiNumHeapsOut
+);
+
+extern PVRSRV_ERROR
+HeapCfgHeapConfigName(
+ const struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 uiHeapConfigNameBufSz,
+ IMG_CHAR *pszHeapConfigNameOut
+);
+
+extern PVRSRV_ERROR
+HeapCfgHeapDetails(
+ const struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 uiHeapIndex,
+ IMG_UINT32 uiHeapNameBufSz,
+ IMG_CHAR *pszHeapNameOut,
+ IMG_DEV_VIRTADDR *psDevVAddrBaseOut,
+ IMG_DEVMEM_SIZE_T *puiHeapLengthOut,
+ IMG_UINT32 *puiLog2DataPageSizeOut
+);
+
+#endif
diff --git a/drivers/gpu/rogue/services/server/include/devicemem_server.h b/drivers/gpu/rogue/services/server/include/devicemem_server.h
new file mode 100644
index 000000000000..040c948e5e29
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/devicemem_server.h
@@ -0,0 +1,357 @@
+/**************************************************************************/ /*!
+@File
+@Title Device Memory Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header file for server side component of device memory management
+@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 __DEVICEMEM_SERVER_H__
+#define __DEVICEMEM_SERVER_H__
+
+#include "device.h" /* For device node */
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+
+#include "pmr.h"
+
+typedef struct _DEVMEMINT_CTX_ DEVMEMINT_CTX;
+typedef struct _DEVMEMINT_CTX_EXPORT_ DEVMEMINT_CTX_EXPORT;
+typedef struct _DEVMEMINT_HEAP_ DEVMEMINT_HEAP;
+
+typedef struct _DEVMEMINT_RESERVATION_ DEVMEMINT_RESERVATION;
+typedef struct _DEVMEMINT_MAPPING_ DEVMEMINT_MAPPING;
+
+/*
+ * DevmemServerGetImportHandle()
+ *
+ * For given exportable memory descriptor returns PMR handle
+ *
+ */
+PVRSRV_ERROR
+DevmemServerGetImportHandle(DEVMEM_MEMDESC *psMemDesc,
+ IMG_HANDLE *phImport);
+
+/*
+ * DevmemServerGetHeapHandle()
+ *
+ * For given reservation returns the Heap handle
+ *
+ */
+PVRSRV_ERROR
+DevmemServerGetHeapHandle(DEVMEMINT_RESERVATION *psReservation,
+ IMG_HANDLE *phHeap);
+
+/*
+ * DevmemIntCtxCreate()
+ *
+ * Create a Server-side Device Memory Context. This is usually the
+ * counterpart of the client side memory context, and indeed is
+ * usually created at the same time.
+ *
+ * You must have one of these before creating any heaps.
+ *
+ * All heaps must have been destroyed before calling
+ * DevmemIntCtxDestroy()
+ *
+ * If you call DevmemIntCtxCreate() (and it succeeds) you are promising
+ * to later call DevmemIntCtxDestroy()
+ *
+ * Note that this call will cause the device MMU code to do some work
+ * for creating the device memory context, but it does not guarantee
+ * that a page catalogue will have been created, as this may be
+ * deferred until first allocation.
+ *
+ * Caller to provide storage for a pointer to the DEVMEM_CTX object
+ * that will be created by this call.
+ */
+extern PVRSRV_ERROR
+DevmemIntCtxCreate(
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ /* devnode / perproc / resman context etc */
+
+ DEVMEMINT_CTX **ppsDevmemCtxPtr,
+ IMG_HANDLE *hPrivData
+ );
+/*
+ * DevmemIntCtxDestroy()
+ *
+ * Undoes a prior DevmemIntCtxCreate or DevmemIntCtxImport.
+ */
+extern PVRSRV_ERROR
+DevmemIntCtxDestroy(
+ DEVMEMINT_CTX *psDevmemCtx
+ );
+
+/*
+ * DevmemIntCtxExport()
+ *
+ * Export a device memory context created with DevmemIntCtxCreate to another
+ * process
+ */
+
+extern PVRSRV_ERROR
+DevmemIntCtxExport(DEVMEMINT_CTX *psDevmemCtx,
+ DEVMEMINT_CTX_EXPORT **ppsExport);
+
+/*
+ * DevmemIntCtxUnexport
+ *
+ * Unexport an exported a device memory context.
+ */
+extern PVRSRV_ERROR
+DevmemIntCtxUnexport(DEVMEMINT_CTX_EXPORT *psExport);
+
+/*
+ * DevmemIntCtxImport
+ *
+ * Import an exported a device memory context.
+ */
+extern PVRSRV_ERROR
+DevmemIntCtxImport(DEVMEMINT_CTX_EXPORT *psExport,
+ DEVMEMINT_CTX **ppsDevmemCtxPtr,
+ IMG_HANDLE *hPrivData);
+
+/*
+ * DevmemIntHeapCreate()
+ *
+ * Creates a new heap in this device memory context. This will cause
+ * a call into the MMU code to allocate various data structures for
+ * managing this heap. It will not necessarily cause any page tables
+ * to be set up, as this can be deferred until first allocation.
+ * (i.e. we shouldn't care - it's up to the MMU code)
+ *
+ * Note that the data page size must be specified (as log 2). The
+ * data page size as specified here will be communicated to the mmu
+ * module, and thus may determine the page size configured in page
+ * directory entries for subsequent allocations from this heap. It is
+ * essential that the page size here is less than or equal to the
+ * "minimum contiguity guarantee" of any PMR that you subsequently
+ * attempt to map to this heap.
+ *
+ * If you call DevmemIntHeapCreate() (and the call succeeds) you are
+ * promising that you shall subsequently call DevmemIntHeapDestroy()
+ *
+ * Caller to provide storage for a pointer to the DEVMEM_HEAP object
+ * that will be created by this call.
+ */
+extern PVRSRV_ERROR
+DevmemIntHeapCreate(
+ DEVMEMINT_CTX *psDevmemCtx,
+ IMG_DEV_VIRTADDR sHeapBaseAddr,
+ IMG_DEVMEM_SIZE_T uiHeapLength,
+ IMG_UINT32 uiLog2DataPageSize,
+ DEVMEMINT_HEAP **ppsDevmemHeapPtr
+ );
+/*
+ * DevmemIntHeapDestroy()
+ *
+ * Destroys a heap previously created with DevmemIntHeapCreate()
+ *
+ * All allocations from his heap must have been freed before this
+ * call.
+ */
+extern PVRSRV_ERROR
+DevmemIntHeapDestroy(
+ DEVMEMINT_HEAP *psDevmemHeap
+ );
+
+/*
+ * DevmemIntMapPMR()
+ *
+ * Maps the given PMR to the virtual range previously allocated with
+ * DevmemIntReserveRange()
+ *
+ * If appropriate, the PMR must have had its physical backing
+ * committed, as this call will call into the MMU code to set up the
+ * page tables for this allocation, which shall in turn request the
+ * physical addresses from the PMR. Alternatively, the PMR
+ * implementation can choose to do so off the back of the "lock"
+ * callback, which it will receive as a result (indirectly) of this
+ * call.
+ *
+ * This function makes no promise w.r.t. the circumstances that it can
+ * be called, and these would be "inherited" from the implementation
+ * of the PMR. For example if the PMR "lock" callback causes pages to
+ * be pinned at that time (which may cause scheduling or disk I/O
+ * etc.) then it would not be legal to "Map" the PMR in a context
+ * where scheduling events are disallowed.
+ *
+ * If you call DevmemIntMapPMR() (and the call succeeds) then you are
+ * promising that you shall later call DevmemIntUnmapPMR()
+ */
+extern PVRSRV_ERROR
+DevmemIntMapPMR(DEVMEMINT_HEAP *psDevmemHeap,
+ DEVMEMINT_RESERVATION *psReservation,
+ PMR *psPMR,
+ PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
+ DEVMEMINT_MAPPING **ppsMappingPtr);
+/*
+ * DevmemIntUnmapPMR()
+ *
+ * Reverses the mapping caused by DevmemIntMapPMR()
+ */
+extern PVRSRV_ERROR
+DevmemIntUnmapPMR(DEVMEMINT_MAPPING *psMapping);
+
+/*
+ * DevmemIntReserveRange()
+ *
+ * Indicates that the specified range should be reserved from the
+ * given heap.
+ *
+ * In turn causes the page tables to be allocated to cover the
+ * specified range.
+ *
+ * If you call DevmemIntReserveRange() (and the call succeeds) then you
+ * are promising that you shall later call DevmemIntUnreserveRange()
+ */
+extern PVRSRV_ERROR
+DevmemIntReserveRange(DEVMEMINT_HEAP *psDevmemHeap,
+ IMG_DEV_VIRTADDR sAllocationDevVAddr,
+ IMG_DEVMEM_SIZE_T uiAllocationSize,
+ DEVMEMINT_RESERVATION **ppsReservationPtr);
+/*
+ * DevmemIntUnreserveRange()
+ *
+ * Undoes the state change caused by DevmemIntReserveRage()
+ */
+extern PVRSRV_ERROR
+DevmemIntUnreserveRange(DEVMEMINT_RESERVATION *psDevmemReservation);
+
+/*
+ * SLCFlushInvalRequest()
+ *
+ * Schedules an SLC Flush & Invalidate on the firmware if required.
+ * If the request is performed depends on the caching attributes
+ * of the allocation and hence depends on the underlying PMR
+ */
+extern PVRSRV_ERROR
+DevmemSLCFlushInvalRequest(PVRSRV_DEVICE_NODE *psDeviceNode, PMR *psPmr);
+
+#if defined(PDUMP)
+/*
+ * DevmemIntPDumpSaveToFileVirtual()
+ *
+ * Writes out PDump "SAB" commands with the data found in memory at
+ * the given virtual address.
+ */
+
+extern PVRSRV_ERROR
+DevmemIntPDumpSaveToFileVirtual(DEVMEMINT_CTX *psDevmemCtx,
+ IMG_DEV_VIRTADDR sDevAddrStart,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 uiArraySize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32PDumpFlags);
+
+extern IMG_UINT32
+DevmemIntMMUContextID(DEVMEMINT_CTX *psDevMemContext);
+
+extern PVRSRV_ERROR
+DevmemIntPDumpBitmap(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);
+#else /* PDUMP */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSyncPrimPDumpPolKM)
+#endif
+static INLINE PVRSRV_ERROR
+DevmemIntPDumpSaveToFileVirtual(DEVMEMINT_CTX *psDevmemCtx,
+ IMG_DEV_VIRTADDR sDevAddrStart,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 uiArraySize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psDevmemCtx);
+ PVR_UNREFERENCED_PARAMETER(sDevAddrStart);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
+ PVR_UNREFERENCED_PARAMETER(uiArraySize);
+ PVR_UNREFERENCED_PARAMETER(pszFilename);
+ PVR_UNREFERENCED_PARAMETER(ui32FileOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSyncPrimPDumpPolKM)
+#endif
+static INLINE PVRSRV_ERROR
+DevmemIntPDumpBitmap(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(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;
+}
+#endif /* PDUMP */
+#endif /* ifndef __DEVICEMEM_SERVER_H__ */
diff --git a/drivers/gpu/rogue/services/server/include/devicemem_server_utils.h b/drivers/gpu/rogue/services/server/include/devicemem_server_utils.h
new file mode 100644
index 000000000000..f49204024484
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/devicemem_server_utils.h
@@ -0,0 +1,191 @@
+/**************************************************************************/ /*!
+@File
+@Title Device Memory Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header file utilities that are specific to device memory 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 "img_types.h"
+#include "pvrsrv_memallocflags.h"
+#include "pvrsrv.h"
+
+static INLINE IMG_UINT32 DevmemCPUCacheMode(PVRSRV_MEMALLOCFLAGS_T ulFlags)
+{
+ IMG_UINT32 ui32CPUCacheMode = ulFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK;
+ IMG_UINT32 ui32Ret;
+
+ PVR_ASSERT(ui32CPUCacheMode == (ulFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
+
+ switch (ui32CPUCacheMode)
+ {
+ case PVRSRV_MEMALLOCFLAG_CPU_UNCACHED:
+ ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_UNCACHED;
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE:
+ ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE;
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT:
+ ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_CACHED;
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT:
+ /* Fall through */
+ case PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT:
+ /*
+ If the allocation needs to be coherent what we end up doing
+ depends on the snooping features of the system
+ */
+ if (PVRSRVSystemSnoopingOfCPUCache())
+ {
+ /*
+ If the system has CPU cache snooping (tested above)
+ then the allocation should be cached ...
+ */
+ ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_CACHED;
+ }
+ else
+ {
+ /* ... otherwise it should be uncached */
+ ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_UNCACHED;
+ }
+ break;
+
+ default:
+ PVR_LOG(("DevmemCPUCacheMode: Unknown CPU cache mode 0x%08x", ui32CPUCacheMode));
+ PVR_ASSERT(0);
+ /*
+ We should never get here, but if we do then setting the mode
+ to uncached is the safest thing to do.
+ */
+ ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_UNCACHED;
+ break;
+ }
+
+ return ui32Ret;
+}
+
+static INLINE IMG_UINT32 DevmemDeviceCacheMode(PVRSRV_MEMALLOCFLAGS_T ulFlags)
+{
+ IMG_UINT32 ui32DeviceCacheMode = ulFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK;
+ IMG_UINT32 ui32Ret;
+
+ PVR_ASSERT(ui32DeviceCacheMode == (ulFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK));
+
+ switch (ui32DeviceCacheMode)
+ {
+ case PVRSRV_MEMALLOCFLAG_GPU_UNCACHED:
+ ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_UNCACHED;
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE:
+ ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_WRITE_COMBINE;
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT:
+ ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_CACHED;
+ break;
+
+ case PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT:
+ /* Fall through */
+ case PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT:
+ /*
+ If the allocation needs to be coherent what we end up doing
+ depends on the snooping features of the system
+ */
+ if (PVRSRVSystemSnoopingOfDeviceCache())
+ {
+ /*
+ If the system has GPU cache snooping (tested above)
+ then the allocation should be cached ...
+ */
+ ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_CACHED;
+ }
+ else
+ {
+ /* ... otherwise it should be uncached */
+ ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_UNCACHED;
+ }
+ break;
+
+ default:
+ PVR_LOG(("DevmemDeviceCacheMode: Unknown device cache mode 0x%08x", ui32DeviceCacheMode));
+ PVR_ASSERT(0);
+ /*
+ We should never get here, but if we do then setting the mode
+ to uncached is the safest thing to do.
+ */
+ ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_UNCACHED;
+ break;
+ }
+
+ return ui32Ret;
+}
+
+static INLINE IMG_BOOL DevmemCPUCacheCoherency(PVRSRV_MEMALLOCFLAGS_T ulFlags)
+{
+ IMG_UINT32 ui32CPUCacheMode = ulFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK;
+ IMG_BOOL bRet = IMG_FALSE;
+
+ PVR_ASSERT(ui32CPUCacheMode == (ulFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
+
+ if ((ui32CPUCacheMode == PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT) ||
+ (ui32CPUCacheMode == PVRSRV_MEMALLOCFLAG_CPU_CACHED_CACHE_COHERENT))
+ {
+ bRet = PVRSRVSystemSnoopingOfDeviceCache();
+ }
+ return bRet;
+}
+
+static INLINE IMG_BOOL DevmemDeviceCacheCoherency(PVRSRV_MEMALLOCFLAGS_T ulFlags)
+{
+ IMG_UINT32 ui32DeviceCacheMode = ulFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK;
+ IMG_BOOL bRet = IMG_FALSE;
+
+ PVR_ASSERT(ui32DeviceCacheMode == (ulFlags & PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK));
+
+ if ((ui32DeviceCacheMode == PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT) ||
+ (ui32DeviceCacheMode == PVRSRV_MEMALLOCFLAG_GPU_CACHED_CACHE_COHERENT))
+ {
+ bRet = PVRSRVSystemSnoopingOfCPUCache();
+ }
+ return bRet;
+}
diff --git a/drivers/gpu/rogue/services/server/include/handle.h b/drivers/gpu/rogue/services/server/include/handle.h
new file mode 100644
index 000000000000..8f45e538edb0
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/handle.h
@@ -0,0 +1,451 @@
+/**************************************************************************/ /*!
+@File
+@Title Handle Manager API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide handle management
+@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 __HANDLE_H__
+#define __HANDLE_H__
+
+/*
+ * Handle API
+ * ----------
+ * The handle API is intended to provide handles for kernel resources,
+ * which can then be passed back to user space processes.
+ *
+ * The following functions comprise the API. Each function takes a
+ * pointer to a PVRSRV_HANDLE_BASE strcture, one of which is allocated
+ * for each process, and stored in the per-process data area. Use
+ * KERNEL_HANDLE_BASE for handles not allocated for a particular process,
+ * or for handles that need to be allocated before the PVRSRV_HANDLE_BASE
+ * structure for the process is available.
+ *
+ * PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType,
+ * PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+ *
+ * Allocate a handle phHandle, for the resource of type eType pointed to by
+ * pvData.
+ *
+ * For handles that have a definite lifetime, where the corresponding
+ * resource is explicitly created and destroyed, eFlag should be zero.
+ *
+ * If the resource is not explicitly created and destroyed, eFlag should be
+ * set to PVRSRV_HANDLE_ALLOC_FLAG_SHARED. For a given process, the same
+ * handle will be returned each time a handle for the resource is allocated
+ * with the PVRSRV_HANDLE_ALLOC_FLAG_SHARED flag.
+ *
+ * If a particular resource may be referenced multiple times by a
+ * given process, setting eFlag to PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+ * will allow multiple handles to be allocated for the resource.
+ * Such handles cannot be found with PVRSRVFindHandle.
+ *
+ * PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType,
+ * PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+ *
+ * This function is similar to PVRSRVAllocHandle, except that the allocated
+ * handles are associated with a parent handle, hParent, that has been
+ * allocated previously. Subhandles are automatically deallocated when their
+ * parent handle is dealloacted.
+ * Subhandles can be treated as ordinary handles. For example, they may
+ * have subhandles of their own, and may be explicity deallocated using
+ * PVRSRVReleaseHandle (see below).
+ *
+ * PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Find the handle previously allocated for the resource pointed to by
+ * pvData, of type eType. Handles allocated with the flag
+ * PVRSRV_HANDLE_ALLOC_FLAG_MULTI cannot be found using this
+ * function.
+ *
+ * PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Given a handle for a resource of type eType, return the pointer to the
+ * resource.
+ *
+ * PVRSRV_ERROR PVRSRVLookuSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType,
+ * IMH_HANDLE hAncestor);
+ *
+ * Similar to PVRSRVLookupHandle, but checks the handle is a descendent
+ * of hAncestor.
+ *
+ * PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+ *
+ * This function returns the resource pointer corresponding to the
+ * given handle, and the resource type in peType. This function is
+ * intended for situations where a handle may be one of several types,
+ * but the type isn't known beforehand.
+ *
+ * PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Deallocate a handle of given type.
+ *
+ * PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * This function combines the functionality of PVRSRVLookupHandle and
+ * PVRSRVReleaseHandle, deallocating the handle after looking it up.
+ *
+ * PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Return the parent of a handle in *phParent, or IMG_NULL if the handle has
+ * no parent.
+ */
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "hash.h"
+#include "resman.h"
+
+typedef enum
+{
+ PVRSRV_HANDLE_TYPE_NONE = 0,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ PVRSRV_HANDLE_TYPE_BUF_INFO,
+ PVRSRV_HANDLE_TYPE_DEVICE_BUFFER,
+ PVRSRV_HANDLE_TYPE_RGX_HW_TRANSFER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_RGX_HW_2D_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_TYPE_MMAP_INFO,
+ PVRSRV_HANDLE_TYPE_SOC_TIMER,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_CTX,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_MMAP_DATA,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION,
+ PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING,
+ PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
+ PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP,
+ PVRSRV_HANDLE_TYPE_RGX_FREELIST,
+ PVRSRV_HANDLE_TYPE_RGX_MEMORY_BLOCK,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
+ PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT,
+ PVRSRV_HANDLE_TYPE_RGX_RAY_CLEANUP,
+ PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE,
+ PVRSRV_HANDLE_TYPE_SERVER_EXPORTCOOKIE,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE,
+ PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
+ PVRSRV_HANDLE_TYPE_SERVER_SYNC_EXPORT,
+ PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_HWRTDATA,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_RENDERTARGET,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER,
+ PVRSRV_HANDLE_TYPE_RGX_POPULATION,
+ PVRSRV_HANDLE_TYPE_RGX_FWIF_FREELIST,
+ PVRSRV_HANDLE_TYPE_DC_DEVICE,
+ PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT,
+ PVRSRV_HANDLE_TYPE_DC_BUFFER,
+ PVRSRV_HANDLE_TYPE_DC_PIN_HANDLE,
+ PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT,
+ PVRSRV_HANDLE_TYPE_DEVMEM_MEM_EXPORT,
+ PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_PAGELIST,
+ PVRSRV_HANDLE_TYPE_PVR_TL_SD,
+ PVRSRV_HANDLE_TYPE_RI_HANDLE,
+ PVRSRV_HANDLE_TYPE_MM_PLAT_CLEANUP
+} PVRSRV_HANDLE_TYPE;
+
+typedef enum
+{
+ /* No flags */
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE = 0,
+ /* Share a handle that already exists for a given data pointer */
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 0x01,
+ /* Muliple handles can point at the given data pointer */
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 0x02,
+ /* Subhandles are allocated in a private handle space */
+ PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 0x04
+} PVRSRV_HANDLE_ALLOC_FLAG;
+
+typedef struct _HANDLE_BASE_ PVRSRV_HANDLE_BASE;
+
+#if defined(PVR_SECURE_HANDLES)
+extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+#define KERNEL_HANDLE_BASE (gpsKernelHandleBase)
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor);
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase);
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID);
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID);
+
+#else /* defined(PVR_SECURE_HANDLES) */
+
+#define KERNEL_HANDLE_BASE IMG_NULL
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(eFlag);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(eFlag);
+ PVR_UNREFERENCED_PARAMETER(hParent);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandleAnyType)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ /*
+ * Unlike the other functions here, the returned results will need
+ * to be handled differently for the secure and non-secure cases.
+ */
+ *peType = PVRSRV_HANDLE_TYPE_NONE;
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(hAncestor);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetParentHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+
+ *phParent = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupAndReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPurgeHandles)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+ *ppsBase = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFreeHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleDeInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#endif /* defined(PVR_SECURE_HANDLES) */
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __HANDLE_H__ */
+
+/******************************************************************************
+ End of file (handle.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/include/handle_impl.h b/drivers/gpu/rogue/services/server/include/handle_impl.h
new file mode 100644
index 000000000000..ad696acefe41
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/handle_impl.h
@@ -0,0 +1,86 @@
+/**************************************************************************/ /*!
+@File
+@Title Implementation Callbacks for Handle Manager API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the handle manager API. This file is for declarations
+ and definitions that are private/internal to the handle manager
+ API but need to be shared between the generic handle manager
+ code and the various handle manager backends, i.e. the code that
+ implements the various callbacks.
+@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(__HANDLE_IMPL_H__)
+#define __HANDLE_IMPL_H__
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+typedef struct _HANDLE_IMPL_BASE_ HANDLE_IMPL_BASE;
+
+typedef PVRSRV_ERROR (*PFN_HANDLE_ITER)(IMG_HANDLE hHandle, IMG_VOID *pvData);
+
+typedef struct _HANDLE_IMPL_FUNCTAB_
+{
+ /* Acquire a new handle which is associated with the given data */
+ PVRSRV_ERROR (*pfnAcquireHandle)(HANDLE_IMPL_BASE *psHandleBase, IMG_HANDLE *phHandle, IMG_VOID *pvData);
+
+ /* Release the given handle (optionally returning the data associated with it) */
+ PVRSRV_ERROR (*pfnReleaseHandle)(HANDLE_IMPL_BASE *psHandleBase, IMG_HANDLE hHandle, IMG_VOID **ppvData);
+
+ /* Get the data associated with the given handle */
+ PVRSRV_ERROR (*pfnGetHandleData)(HANDLE_IMPL_BASE *psHandleBase, IMG_HANDLE hHandle, IMG_VOID **ppvData);
+
+ PVRSRV_ERROR (*pfnIterateOverHandles)(HANDLE_IMPL_BASE *psHandleBase, PFN_HANDLE_ITER pfnHandleIter, IMG_VOID *pvHandleIterData);
+
+ /* Enable handle purging on the given handle base */
+ PVRSRV_ERROR (*pfnEnableHandlePurging)(HANDLE_IMPL_BASE *psHandleBase);
+
+ /* Purge handles on the given handle base */
+ PVRSRV_ERROR (*pfnPurgeHandles)(HANDLE_IMPL_BASE *psHandleBase);
+
+ /* Create handle base */
+ PVRSRV_ERROR (*pfnCreateHandleBase)(HANDLE_IMPL_BASE **psHandleBase);
+
+ /* Destroy handle base */
+ PVRSRV_ERROR (*pfnDestroyHandleBase)(HANDLE_IMPL_BASE *psHandleBase);
+} HANDLE_IMPL_FUNCTAB;
+
+PVRSRV_ERROR PVRSRVHandleGetFuncTable(HANDLE_IMPL_FUNCTAB const **ppsFuncs);
+
+#endif /* !defined(__HANDLE_IMPL_H__) */
diff --git a/drivers/gpu/rogue/services/server/include/lists.h b/drivers/gpu/rogue/services/server/include/lists.h
new file mode 100644
index 000000000000..a0e7cc44b6f4
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/lists.h
@@ -0,0 +1,336 @@
+/*************************************************************************/ /*!
+@File
+@Title Linked list shared functions templates.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Definition of the linked list function templates.
+@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 __LISTS_UTILS__
+#define __LISTS_UTILS__
+
+/* instruct QAC to ignore warnings about the following custom formatted macros */
+/* PRQA S 0881,3410 ++ */
+#include <stdarg.h>
+#include "img_types.h"
+#include "device.h"
+#include "power.h"
+
+/*
+ - USAGE -
+
+ The list functions work with any structure that provides the fields psNext and
+ ppsThis. In order to make a function available for a given type, it is required
+ to use the funcion template macro that creates the actual code.
+
+ There are 4 main types of functions:
+ - INSERT : given a pointer to the head pointer of the list and a pointer to
+ the node, inserts it as the new head.
+ - REMOVE : given a pointer to a node, removes it from its list.
+ - FOR EACH : apply a function over all the elements of a list.
+ - ANY : apply a function over the elements of a list, until one of them
+ return a non null value, and then returns it.
+
+ The two last functions can have a variable argument form, with allows to pass
+ additional parameters to the callback function. In order to do this, the
+ callback function must take two arguments, the first is the current node and
+ the second is a list of variable arguments (va_list).
+
+ The ANY functions have also another for wich specifies the return type of the
+ callback function and the default value returned by the callback function.
+
+*/
+
+/*************************************************************************/ /*!
+@Function List_##TYPE##_ForEach
+@Description Apply a callback function to all the elements of a list.
+@Input psHead The head of the list to be processed.
+@Input pfnCallBack The function to be applied to each element of the list.
+*/ /**************************************************************************/
+#define DECLARE_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))\
+{\
+ while(psHead)\
+ {\
+ pfnCallBack(psHead);\
+ psHead = psHead->psNext;\
+ }\
+}
+
+/*************************************************************************/ /*!
+@Function List_##TYPE##_ForEachSafe
+@Description Apply a callback function to all the elements of a list. Do it
+ in a safe way that handles the fact that a node might remove itself
+ from the list during the iteration.
+@Input psHead The head of the list to be processed.
+@Input pfnCallBack The function to be applied to each element of the list.
+*/ /**************************************************************************/
+#define DECLARE_LIST_FOR_EACH_SAFE(TYPE) \
+IMG_VOID List_##TYPE##_ForEachSafe(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_FOR_EACH_SAFE(TYPE) \
+IMG_VOID List_##TYPE##_ForEachSafe(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))\
+{\
+ TYPE *psNext;\
+\
+ while(psHead)\
+ {\
+ psNext = psHead->psNext; \
+ pfnCallBack(psHead);\
+ psHead = psNext;\
+ }\
+}
+
+
+#define DECLARE_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...) \
+{\
+ va_list ap;\
+ while(psHead)\
+ {\
+ va_start(ap, pfnCallBack);\
+ pfnCallBack(psHead, ap);\
+ psHead = psHead->psNext;\
+ va_end(ap);\
+ }\
+}
+
+
+/*************************************************************************/ /*!
+@Function List_##TYPE##_Any
+@Description Applies a callback function to the elements of a list until the function
+ returns a non null value, then returns it.
+@Input psHead The head of the list to be processed.
+@Input pfnCallBack The function to be applied to each element of the list.
+@Return The first non null value returned by the callback function.
+*/ /**************************************************************************/
+#define DECLARE_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))\
+{ \
+ IMG_VOID *pResult;\
+ TYPE *psNextNode;\
+ pResult = IMG_NULL;\
+ psNextNode = psHead;\
+ while(psHead && !pResult)\
+ {\
+ psNextNode = psNextNode->psNext;\
+ pResult = pfnCallBack(psHead);\
+ psHead = psNextNode;\
+ }\
+ return pResult;\
+}
+
+
+/*with variable arguments, that will be passed as a va_list to the callback function*/
+
+#define DECLARE_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+ va_list ap;\
+ TYPE *psNextNode;\
+ IMG_VOID* pResult = IMG_NULL;\
+ while(psHead && !pResult)\
+ {\
+ psNextNode = psHead->psNext;\
+ va_start(ap, pfnCallBack);\
+ pResult = pfnCallBack(psHead, ap);\
+ va_end(ap);\
+ psHead = psNextNode;\
+ }\
+ return pResult;\
+}
+
+/*those ones are for extra type safety, so there's no need to use castings for the results*/
+
+#define DECLARE_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))\
+{ \
+ RTYPE result;\
+ TYPE *psNextNode;\
+ result = CONTINUE;\
+ psNextNode = psHead;\
+ while(psHead && result == CONTINUE)\
+ {\
+ psNextNode = psNextNode->psNext;\
+ result = pfnCallBack(psHead);\
+ psHead = psNextNode;\
+ }\
+ return result;\
+}
+
+
+#define DECLARE_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+ va_list ap;\
+ TYPE *psNextNode;\
+ RTYPE result = CONTINUE;\
+ while(psHead && result == CONTINUE)\
+ {\
+ psNextNode = psHead->psNext;\
+ va_start(ap, pfnCallBack);\
+ result = pfnCallBack(psHead, ap);\
+ va_end(ap);\
+ psHead = psNextNode;\
+ }\
+ return result;\
+}
+
+
+/*************************************************************************/ /*!
+@Function List_##TYPE##_Remove
+@Description Removes a given node from the list.
+@Input psNode The pointer to the node to be removed.
+*/ /**************************************************************************/
+#define DECLARE_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)
+
+#define IMPLEMENT_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)\
+{\
+ (*psNode->ppsThis)=psNode->psNext;\
+ if(psNode->psNext)\
+ {\
+ psNode->psNext->ppsThis = psNode->ppsThis;\
+ }\
+}
+
+/*************************************************************************/ /*!
+@Function List_##TYPE##_Insert
+@Description Inserts a given node at the beginnning of the list.
+@Input psHead The pointer to the pointer to the head node.
+@Input psNode The pointer to the node to be inserted.
+*/ /**************************************************************************/
+#define DECLARE_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)
+
+#define IMPLEMENT_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)\
+{\
+ psNewNode->ppsThis = ppsHead;\
+ psNewNode->psNext = *ppsHead;\
+ *ppsHead = psNewNode;\
+ if(psNewNode->psNext)\
+ {\
+ psNewNode->psNext->ppsThis = &(psNewNode->psNext);\
+ }\
+}
+
+/*************************************************************************/ /*!
+@Function List_##TYPE##_Reverse
+@Description Reverse a list in place
+@Input ppsHead The pointer to the pointer to the head node.
+*/ /**************************************************************************/
+#define DECLARE_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)
+
+#define IMPLEMENT_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)\
+{\
+ TYPE *psTmpNode1; \
+ TYPE *psTmpNode2; \
+ TYPE *psCurNode; \
+ psTmpNode1 = IMG_NULL; \
+ psCurNode = *ppsHead; \
+ while(psCurNode) { \
+ psTmpNode2 = psCurNode->psNext; \
+ psCurNode->psNext = psTmpNode1; \
+ psTmpNode1 = psCurNode; \
+ psCurNode = psTmpNode2; \
+ if(psCurNode) \
+ { \
+ psTmpNode1->ppsThis = &(psCurNode->psNext); \
+ } \
+ else \
+ { \
+ psTmpNode1->ppsThis = ppsHead; \
+ } \
+ } \
+ *ppsHead = psTmpNode1; \
+}
+
+#define IS_LAST_ELEMENT(x) ((x)->psNext == IMG_NULL)
+
+
+DECLARE_LIST_ANY(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+DECLARE_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_INSERT(PVRSRV_POWER_DEV);
+DECLARE_LIST_REMOVE(PVRSRV_POWER_DEV);
+
+#undef DECLARE_LIST_ANY_2
+#undef DECLARE_LIST_ANY_VA
+#undef DECLARE_LIST_ANY_VA_2
+#undef DECLARE_LIST_FOR_EACH
+#undef DECLARE_LIST_FOR_EACH_VA
+#undef DECLARE_LIST_INSERT
+#undef DECLARE_LIST_REMOVE
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
+
+#endif
+
+/* re-enable warnings */
+/* PRQA S 0881,3410 -- */
diff --git a/drivers/gpu/rogue/services/server/include/mmu_common.h b/drivers/gpu/rogue/services/server/include/mmu_common.h
new file mode 100644
index 000000000000..14ec706ee00f
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/mmu_common.h
@@ -0,0 +1,534 @@
+/**************************************************************************/ /*!
+@File
+@Title Common MMU Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements basic low level control of MMU.
+@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 MMU_COMMON_H
+#define MMU_COMMON_H
+
+/*
+ The Memory Management Unit (MMU) performs device virtual to physical translation.
+
+ Terminology:
+ - page catalogue, PC (optional, 3 tier MMU)
+ - page directory, PD
+ - page table, PT (can be variable sized)
+ - data page, DP (can be variable sized)
+ Note: PD and PC are fixed size and can't be larger than
+ the native physical (CPU) page size
+ Shifts and AlignShift variables:
+ - 'xxxShift' represent the number of bits a bitfield is shifted left from bit0
+ - 'xxxAlignShift' is used to convert a bitfield (based at bit0) into byte units
+ by applying a bit shift left by 'xxxAlignShift' bits
+*/
+
+/*
+ Device Virtual Address Config:
+
+ Incoming Device Virtual Address is deconstructed into up to 4
+ fields, where the virtual address is up to 64bits:
+ MSB-----------------------------------------------LSB
+ | PC Index: | PD Index: | PT Index: | DP offset: |
+ | d bits | c bits | b-v bits | a+v bits |
+ -----------------------------------------------------
+ where v is the variable page table modifier, e.g.
+ v == 0 -> 4KB DP
+ v == 2 -> 16KB DP
+ v == 4 -> 64KB DP
+ v == 6 -> 256KB DP
+ v == 8 -> 1MB DP
+ v == 10 -> 4MB DP
+*/
+
+/* services/server/include/ */
+#include "pmr.h"
+
+/* include/ */
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "servicesext.h"
+
+/*!
+ The level of the MMU
+*/
+typedef enum
+{
+ MMU_LEVEL_0 = 0, /* Level 0 = Page */
+
+ MMU_LEVEL_1,
+ MMU_LEVEL_2,
+ MMU_LEVEL_3,
+ MMU_LEVEL_LAST
+} MMU_LEVEL;
+
+/* moved after declaration of MMU_LEVEL, as pdump_mmu.h references it */
+#include "pdump_mmu.h"
+
+#define MMU_MAX_LEVEL 3
+
+struct _MMU_DEVVADDR_CONFIG_;
+
+/*!
+ MMU device attributes. This structure is the interface between the generic
+ MMU code and the device specific MMU code.
+*/
+typedef struct _MMU_DEVICEATTRIBS_
+{
+ PDUMP_MMU_TYPE eMMUType;
+
+ /*! The type of the top level object */
+ MMU_LEVEL eTopLevel;
+
+ /*! Alignment requirement of the base object */
+ IMG_UINT32 ui32BaseAlign;
+
+ /*! HW config of the base object */
+ struct _MMU_PxE_CONFIG_ *psBaseConfig;
+
+ /*! Address split for the base object */
+ const struct _MMU_DEVVADDR_CONFIG_ *psTopLevelDevVAddrConfig;
+
+ /*! Callback for creating protection bits for the page catalogue entry with 8 byte entry */
+ IMG_UINT64 (*pfnDerivePCEProt8)(IMG_UINT32, IMG_UINT8);
+ /*! Callback for creating protection bits for the page catalogue entry with 4 byte entry */
+ IMG_UINT32 (*pfnDerivePCEProt4)(IMG_UINT32);
+ /*! Callback for creating protection bits for the page directory entry with 8 byte entry */
+ IMG_UINT64 (*pfnDerivePDEProt8)(IMG_UINT32, IMG_UINT8);
+ /*! Callback for creating protection bits for the page directory entry with 4 byte entry */
+ IMG_UINT32 (*pfnDerivePDEProt4)(IMG_UINT32);
+ /*! Callback for creating protection bits for the page table entry with 8 byte entry */
+ IMG_UINT64 (*pfnDerivePTEProt8)(IMG_UINT32, IMG_UINT8);
+ /*! Callback for creating protection bits for the page table entry with 4 byte entry */
+ IMG_UINT32 (*pfnDerivePTEProt4)(IMG_UINT32);
+
+ /*! Callback for getting the MMU configuration based on the specified page size */
+ PVRSRV_ERROR (*pfnGetPageSizeConfiguration)(IMG_UINT32 ui32DataPageSize,
+ const struct _MMU_PxE_CONFIG_ **ppsMMUPDEConfig,
+ const struct _MMU_PxE_CONFIG_ **ppsMMUPTEConfig,
+ const struct _MMU_DEVVADDR_CONFIG_ **ppsMMUDevVAddrConfig,
+ IMG_HANDLE *phPriv2);
+ /*! Callback for putting the MMU configuration obtained from pfnGetPageSizeConfiguration */
+ PVRSRV_ERROR (*pfnPutPageSizeConfiguration)(IMG_HANDLE hPriv);
+
+ /*! Callback for getting the page size from the PDE for the page table entry with 4 byte entry */
+ PVRSRV_ERROR (*pfnGetPageSizeFromPDE4)(IMG_UINT32, IMG_UINT32 *);
+ /*! Callback for getting the page size from the PDE for the page table entry with 8 byte entry */
+ PVRSRV_ERROR (*pfnGetPageSizeFromPDE8)(IMG_UINT64, IMG_UINT32 *);
+
+ /*! Private data handle */
+ IMG_HANDLE hGetPageSizeFnPriv;
+} MMU_DEVICEATTRIBS;
+
+/*!
+ MMU virtual address split
+*/
+typedef struct _MMU_DEVVADDR_CONFIG_
+{
+ /*! Page catalogue index mask */
+ IMG_UINT64 uiPCIndexMask;
+ /*! Page catalogue index shift */
+ IMG_UINT8 uiPCIndexShift;
+ /*! Page directory mask */
+ IMG_UINT64 uiPDIndexMask;
+ /*! Page directory shift */
+ IMG_UINT8 uiPDIndexShift;
+ /*! Page table mask */
+ IMG_UINT64 uiPTIndexMask;
+ /*! Page index shift */
+ IMG_UINT8 uiPTIndexShift;
+ /*! Page offset mask */
+ IMG_UINT64 uiPageOffsetMask;
+ /*! Page offset shift */
+ IMG_UINT8 uiPageOffsetShift;
+} MMU_DEVVADDR_CONFIG;
+
+/*
+ P(C/D/T) Entry Config:
+
+ MSB-----------------------------------------------LSB
+ | PT Addr: | variable PT ctrl | protection flags: |
+ | bits c+v | b bits | a bits |
+ -----------------------------------------------------
+ where v is the variable page table modifier and is optional
+*/
+/*!
+ Generic MMU page * entry description. This is used to describe PC, PD and PT
+*/
+typedef struct _MMU_PxE_CONFIG_
+{
+ /*! Size of an entry in bytes */
+ IMG_UINT8 uiBytesPerEntry;
+
+ /*! Physical address mask */
+ IMG_UINT64 uiAddrMask;
+ /*! Physical address shift */
+ IMG_UINT8 uiAddrShift;
+ /*! Log 2 alignment */
+ IMG_UINT8 uiLog2Align;
+
+ /*! Variable control mask */
+ IMG_UINT64 uiVarCtrlMask;
+ /*! Variable control shift */
+ IMG_UINT8 uiVarCtrlShift;
+
+ /*! Protection flags mask */
+ IMG_UINT64 uiProtMask;
+ /*! Protection flags shift */
+ IMG_UINT8 uiProtShift;
+} MMU_PxE_CONFIG;
+
+/* MMU Protection flags */
+
+
+/* These are specified generically and in a h/w independent way, and
+ are interpreted at each level (PC/PD/PT) separately. */
+
+/* The following flags are for internal use only, and should not
+ traverse the API */
+#define MMU_PROTFLAGS_INVALID 0x80000000U
+
+typedef IMG_UINT32 MMU_PROTFLAGS_T;
+
+/* The following flags should be supplied by the caller: */
+#define MMU_PROTFLAGS_READABLE (1U<<0)
+#define MMU_PROTFLAGS_WRITEABLE (1U<<1)
+#define MMU_PROTFLAGS_CACHE_COHERENT (1U<<2)
+#define MMU_PROTFLAGS_CACHED (1U<<3)
+
+/* Device specific flags*/
+#define MMU_PROTFLAGS_DEVICE_OFFSET 16
+#define MMU_PROTFLAGS_DEVICE_MASK 0x000f0000UL
+#define MMU_PROTFLAGS_DEVICE(n) \
+ (((n) << MMU_PROTFLAGS_DEVICE_OFFSET) & \
+ MMU_PROTFLAGS_DEVICE_MASK)
+
+typedef struct _MMU_CONTEXT_ MMU_CONTEXT;
+
+struct _PVRSRV_DEVICE_NODE_;
+
+/*************************************************************************/ /*!
+@Function MMU_ContextCreate
+
+@Description Create a new MMU context
+
+@Input psDevNode Device node of the device to create the
+ MMU context for
+
+@Output ppsMMUContext The created MMU context
+
+@Return PVRSRV_OK if the MMU context was successfully created
+*/
+/*****************************************************************************/
+extern PVRSRV_ERROR
+MMU_ContextCreate (struct _PVRSRV_DEVICE_NODE_ *psDevNode, MMU_CONTEXT **ppsMMUContext);
+
+
+/*************************************************************************/ /*!
+@Function MMU_ContextDestroy
+
+@Description Destroy a MMU context
+
+@Input ppsMMUContext MMU context to destroy
+
+@Return None
+*/
+/*****************************************************************************/
+extern IMG_VOID
+MMU_ContextDestroy (MMU_CONTEXT *psMMUContext);
+
+/*************************************************************************/ /*!
+@Function MMU_Alloc
+
+@Description Allocate the page tables required for the specified virtual range
+
+@Input psMMUContext MMU context to operate on
+
+@Input uSize The size of the allocation
+
+@Output puActualSize Actual size of allocation
+
+@Input uiProtFlags Generic MMU protection flags
+
+@Input uDevVAddrAlignment Alignment requirement of the virtual
+ allocation
+
+@Input psDevVAddr Virtual address to start the allocation
+ from
+
+@Return PVRSRV_OK if the allocation of the page tables was successful
+*/
+/*****************************************************************************/
+extern PVRSRV_ERROR
+MMU_Alloc (MMU_CONTEXT *psMMUContext,
+ IMG_DEVMEM_SIZE_T uSize,
+ IMG_DEVMEM_SIZE_T *puActualSize,
+ IMG_UINT32 uiProtFlags,
+ IMG_DEVMEM_SIZE_T uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_UINT8 uiLog2PageSize);
+
+
+/*************************************************************************/ /*!
+@Function MMU_Free
+
+@Description Free the page tables of the specified virtual range
+
+@Input psMMUContext MMU context to operate on
+
+@Input psDevVAddr Virtual address to start the free
+ from
+
+@Input uSize The size of the allocation
+
+@Return None
+*/
+/*****************************************************************************/
+extern IMG_VOID
+MMU_Free (MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT8 uiLog2PageSize);
+
+/*************************************************************************/ /*!
+@Function MMU_UnmapPages
+
+@Description Unmap pages from the MMU.
+
+@Input psMMUContext MMU context to operate on
+
+@Input psDevVAddr Device virtual address of the 1st page
+
+@Input ui32PageCount Number of pages to unmap
+
+@Return None
+*/
+/*****************************************************************************/
+extern IMG_VOID
+MMU_UnmapPages (MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_UINT8 uiLog2PageSize);
+
+/*************************************************************************/ /*!
+@Function MMU_MapPMR
+
+@Description Map a PMR into the MMU.
+
+@Input psMMUContext MMU context to operate on
+
+@Input sDevVAddr Device virtual address to map the PMR
+ into
+
+@Input psPMR PMR to map
+
+@Input uiSizeBytes Size in bytes to map
+
+@Input uiMappingFlags Memalloc flags for the mapping
+
+@Return PVRSRV_OK if the PMR was successfully mapped
+*/
+/*****************************************************************************/
+extern PVRSRV_ERROR
+MMU_MapPMR (MMU_CONTEXT *psMMUContext,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ const PMR *psPMR,
+ IMG_DEVMEM_SIZE_T uiSizeBytes,
+ PVRSRV_MEMALLOCFLAGS_T uiMappingFlags,
+ IMG_UINT8 uiLog2PageSize);
+
+/*************************************************************************/ /*!
+@Function MMU_AcquireBaseAddr
+
+@Description Acquire the device physical address of the base level MMU object
+
+@Input psMMUContext MMU context to operate on
+
+@Output psPhysAddr Device physical address of the base level
+ MMU object
+
+@Return PVRSRV_OK if successful
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+MMU_AcquireBaseAddr(MMU_CONTEXT *psMMUContext, IMG_DEV_PHYADDR *psPhysAddr);
+
+/*************************************************************************/ /*!
+@Function MMU_ReleaseBaseAddr
+
+@Description Release the device physical address of the base level MMU object
+
+@Input psMMUContext MMU context to operate on
+
+@Return PVRSRV_OK if successful
+*/
+/*****************************************************************************/
+IMG_VOID
+MMU_ReleaseBaseAddr(MMU_CONTEXT *psMMUContext);
+
+/*************************************************************************/ /*!
+@Function MMU_SetDeviceData
+
+@Description Set the device specific callback data
+
+@Input psMMUContext MMU context to store the data on
+
+@Input hDevData Device data
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID MMU_SetDeviceData(MMU_CONTEXT *psMMUContext, IMG_HANDLE hDevData);
+
+/*************************************************************************/ /*!
+@Function MMU_CheckFaultAddress
+
+@Description Check the specified MMU context to see if the provided address
+ should be valid
+
+@Input psMMUContext MMU context to store the data on
+
+@Input psDevVAddr Address to check
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID MMU_CheckFaultAddress(MMU_CONTEXT *psMMUContext, IMG_DEV_VIRTADDR *psDevVAddr);
+
+#if defined(PDUMP)
+/*************************************************************************/ /*!
+@Function MMU_ContextDerivePCPDumpSymAddr
+
+@Description Derives a PDump Symbolic address for the top level MMU object
+
+@Input psMMUContext MMU context to operate on
+
+@Input pszPDumpSymbolicNameBuffer Buffer to write the PDump symbolic
+ address to
+
+@Input uiPDumpSymbolicNameBufferSize Size of the buffer
+
+@Return PVRSRV_OK if successful
+*/
+/*****************************************************************************/
+extern PVRSRV_ERROR MMU_ContextDerivePCPDumpSymAddr(MMU_CONTEXT *psMMUContext,
+ IMG_CHAR *pszPDumpSymbolicNameBuffer,
+ IMG_SIZE_T uiPDumpSymbolicNameBufferSize);
+
+/*************************************************************************/ /*!
+@Function MMU_PDumpWritePageCatBase
+
+@Description PDump write of the top level MMU object to a device register
+
+@Input psMMUContext MMU context to operate on
+
+@Input pszSpaceName PDump name of the mem/reg space
+
+@Input uiOffset Offset to write the address to
+
+@Return PVRSRV_OK if successful
+*/
+/*****************************************************************************/
+PVRSRV_ERROR MMU_PDumpWritePageCatBase(MMU_CONTEXT *psMMUContext,
+ const IMG_CHAR *pszSpaceName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32WordSize,
+ IMG_UINT32 ui32AlignShift,
+ IMG_UINT32 ui32Shift,
+ PDUMP_FLAGS_T uiPdumpFlags);
+
+/*************************************************************************/ /*!
+@Function MMU_AcquirePDumpMMUContext
+
+@Description Acquire a reference to the PDump MMU context for this MMU
+ context
+
+@Input psMMUContext MMU context to operate on
+
+@Input pszRegSpaceName PDump name of the register space
+
+@Output pui32PDumpMMUContextID PDump MMU context ID
+
+@Return PVRSRV_OK if successful
+*/
+/*****************************************************************************/
+PVRSRV_ERROR MMU_AcquirePDumpMMUContext(MMU_CONTEXT *psMMUContext, IMG_UINT32 *pui32PDumpMMUContextID);
+
+/*************************************************************************/ /*!
+@Function MMU_ReleasePDumpMMUContext
+
+@Description Release a reference to the PDump MMU context for this MMU context
+
+@Input psMMUContext MMU context to operate on
+
+@Input pszRegSpaceName PDump name of the register space
+
+@Output pui32PDumpMMUContextID PDump MMU context ID
+
+@Return PVRSRV_OK if successful
+*/
+/*****************************************************************************/
+PVRSRV_ERROR MMU_ReleasePDumpMMUContext(MMU_CONTEXT *psMMUContext);
+#else /* PDUMP */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(MMU_PDumpWritePageCatBase)
+#endif
+static INLINE IMG_VOID
+MMU_PDumpWritePageCatBase(MMU_CONTEXT *psMMUContext,
+ const IMG_CHAR *pszSpaceName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32WordSize,
+ IMG_UINT32 ui32AlignShift,
+ IMG_UINT32 ui32Shift,
+ PDUMP_FLAGS_T uiPdumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psMMUContext);
+ PVR_UNREFERENCED_PARAMETER(pszSpaceName);
+ PVR_UNREFERENCED_PARAMETER(uiOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32WordSize);
+ PVR_UNREFERENCED_PARAMETER(ui32AlignShift);
+ PVR_UNREFERENCED_PARAMETER(ui32Shift);
+ PVR_UNREFERENCED_PARAMETER(uiPdumpFlags);
+}
+#endif /* PDUMP */
+
+
+#endif /* #ifdef MMU_COMMON_H */
diff --git a/drivers/gpu/rogue/services/server/include/osconnection_server.h b/drivers/gpu/rogue/services/server/include/osconnection_server.h
new file mode 100644
index 000000000000..0be30fdd92ac
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/osconnection_server.h
@@ -0,0 +1,95 @@
+/**************************************************************************/ /*!
+@File
+@Title Server side connection management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description API for OS specific callbacks from server side connection
+ management
+@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 _OSCONNECTION_SERVER_H_
+#define _OSCONNECTION_SERVER_H_
+
+#include "handle.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__) || defined(__QNXNTO__)
+PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateData, IMG_PVOID pvOSData);
+PVRSRV_ERROR OSConnectionPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
+
+PVRSRV_ERROR OSConnectionSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+#else /* defined(__linux__) */
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSConnectionPrivateDataInit)
+#endif
+static INLINE PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateData, IMG_PVOID pvOSData)
+{
+ PVR_UNREFERENCED_PARAMETER(phOsPrivateData);
+ PVR_UNREFERENCED_PARAMETER(pvOSData);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSConnectionPrivateDataDeInit)
+#endif
+static INLINE PVRSRV_ERROR OSConnectionPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+ PVR_UNREFERENCED_PARAMETER(hOsPrivateData);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessSetHandleOptions)
+#endif
+static INLINE PVRSRV_ERROR OSConnectionSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psHandleBase);
+
+ return PVRSRV_OK;
+}
+#endif /* defined(__linux__) */
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* _OSCONNECTION_SERVER_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/osfunc.h b/drivers/gpu/rogue/services/server/include/osfunc.h
new file mode 100644
index 000000000000..0183527561b0
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/osfunc.h
@@ -0,0 +1,433 @@
+/**************************************************************************/ /*!
+@File
+@Title OS functions header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS specific API definitions
+@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.
+*/ /***************************************************************************/
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG 1
+#endif
+
+#ifndef __OSFUNC_H__
+#define __OSFUNC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(KERNEL) && defined(ANDROID)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+
+#include "img_types.h"
+#include "pvrsrv_device.h"
+#include "device.h"
+
+/******************************************************************************
+ * Static defines
+ *****************************************************************************/
+#define KERNEL_ID 0xffffffffL
+#define ISR_ID 0xfffffffdL
+
+IMG_UINT64 OSClockns64(IMG_VOID);
+IMG_UINT64 OSClockus64(IMG_VOID);
+IMG_UINT32 OSClockus(IMG_VOID);
+IMG_UINT32 OSClockms(IMG_VOID);
+
+IMG_SIZE_T OSGetPageSize(IMG_VOID);
+IMG_SIZE_T OSGetPageShift(IMG_VOID);
+IMG_SIZE_T OSGetPageMask(IMG_VOID);
+
+typedef IMG_VOID (*PFN_THREAD)(IMG_PVOID pvData);
+
+PVRSRV_ERROR OSInstallDeviceLISR(PVRSRV_DEVICE_CONFIG *psDevConfig,
+ IMG_HANDLE *hLISRData,
+ PFN_LISR pfnLISR,
+ IMG_VOID *hData);
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_HANDLE hLISRData);
+
+PVRSRV_ERROR OSInstallMISR(IMG_HANDLE *hMISRData,
+ PFN_MISR pfnMISR,
+ IMG_VOID *hData);
+PVRSRV_ERROR OSUninstallMISR(IMG_HANDLE hMISRData);
+PVRSRV_ERROR OSScheduleMISR(IMG_HANDLE hMISRData);
+
+
+/*************************************************************************/ /*!
+@Function OSThreadCreate
+@Description Creates a kernel thread and starts it running. The caller
+ is responsible for informing the thread that it must finish
+ and return from the pfnThread function. It is not possible
+ to kill or terminate it. The new thread runs with the default
+ priority provided by the Operating System.
+@Output phThread Returned handle to the thread.
+@Input pszThreadName Name to assign to the thread.
+@Input pfnThread Thread entry point function.
+@Input hData Thread specific data pointer for pfnThread().
+@Return Standard PVRSRV_ERROR error code.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSThreadCreate(IMG_HANDLE *phThread,
+ IMG_CHAR *pszThreadName,
+ PFN_THREAD pfnThread,
+ IMG_VOID *hData);
+
+/*! Available priority levels for the creation of a new Kernel Thread. */
+typedef enum priority_levels
+{
+ HIGHEST_PRIORITY = 0,
+ HIGH_PRIRIOTY,
+ NORMAL_PRIORITY,
+ LOW_PRIORITY,
+ LOWEST_PRIORITY,
+ NOSET_PRIORITY, /* With this option the priority level is is the default for the given OS */
+ LAST_PRIORITY /* This must be always the last entry */
+} OS_THREAD_LEVEL;
+
+/*************************************************************************/ /*!
+@Function OSThreadCreatePriority
+@Description As OSThreadCreate, this function creates a kernel thread and
+ starts it running. The difference is that with this function
+ is possible to specify the priority used to schedule the new
+ thread.
+
+@Output phThread Returned handle to the thread.
+@Input pszThreadName Name to assign to the thread.
+@Input pfnThread Thread entry point function.
+@Input hData Thread specific data pointer for pfnThread().
+@Input eThreadPriority Priority level to assign to the new thread.
+@Return Standard PVRSRV_ERROR error code.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSThreadCreatePriority(IMG_HANDLE *phThread,
+ IMG_CHAR *pszThreadName,
+ PFN_THREAD pfnThread,
+ IMG_VOID *hData,
+ OS_THREAD_LEVEL eThreadPriority);
+
+/*************************************************************************/ /*!
+@Function OSThreadDestroy
+@Description Waits for the thread to end and then destroys the thread
+ handle memory. This function will block and wait for the
+ thread to finish successfully, thereby providing a sync point
+ for the thread completing its work. No attempt is made to kill
+ or otherwise terminate the thread.
+@Input phThread The thread handle returned by OSThreadCreate().
+@Return Standard PVRSRV_ERROR error code.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSThreadDestroy(IMG_HANDLE hThread);
+
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, const IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags);
+IMG_BOOL OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags);
+
+
+IMG_VOID OSCPUOperation(PVRSRV_CACHE_OP eCacheOp);
+
+IMG_VOID OSFlushCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd);
+
+
+IMG_VOID OSCleanCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd);
+
+IMG_VOID OSInvalidateCPUCacheRangeKM(IMG_PVOID pvVirtStart,
+ IMG_PVOID pvVirtEnd,
+ IMG_CPU_PHYADDR sCPUPhysStart,
+ IMG_CPU_PHYADDR sCPUPhysEnd);
+
+
+IMG_PID OSGetCurrentProcessIDKM(IMG_VOID);
+IMG_CHAR *OSGetCurrentProcessNameKM(IMG_VOID);
+IMG_UINTPTR_T OSGetCurrentThreadIDKM(IMG_VOID);
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+IMG_INT OSMemCmp(IMG_VOID *pvBufA, IMG_VOID *pvBufB, IMG_SIZE_T uiLen);
+
+PVRSRV_ERROR OSMMUPxAlloc(PVRSRV_DEVICE_NODE *psDevNode, IMG_SIZE_T uiSize,
+ Px_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr);
+
+IMG_VOID OSMMUPxFree(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle);
+
+PVRSRV_ERROR OSMMUPxMap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle,
+ IMG_SIZE_T uiSize, IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_VOID **pvPtr);
+
+IMG_VOID OSMMUPxUnmap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle, IMG_VOID *pvPtr);
+
+
+PVRSRV_ERROR OSInitEnvData(IMG_VOID);
+IMG_VOID OSDeInitEnvData(IMG_VOID);
+
+IMG_CHAR* OSStringNCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, IMG_SIZE_T uSize);
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T ui32Size, const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+IMG_SIZE_T OSStringLength(const IMG_CHAR *pStr);
+IMG_SIZE_T OSStringNLength(const IMG_CHAR *pStr, IMG_SIZE_T uiCount);
+IMG_INT32 OSStringCompare(const IMG_CHAR *pStr1, const IMG_CHAR *pStr2);
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName,
+ IMG_HANDLE *EventObject);
+PVRSRV_ERROR OSEventObjectDestroy(IMG_HANDLE hEventObject);
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hEventObject);
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectWaitTimeout(IMG_HANDLE hOSEventKM, IMG_UINT32 uiTimeoutMs);
+PVRSRV_ERROR OSEventObjectOpen(IMG_HANDLE hEventObject,
+ IMG_HANDLE *phOSEvent);
+PVRSRV_ERROR OSEventObjectClose(IMG_HANDLE hOSEventKM);
+
+/* Avoid macros so we don't evaluate pszSrc twice */
+static INLINE IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
+{
+ return OSStringNCopy(pszDest, pszSrc, OSStringLength(pszSrc) + 1);
+}
+
+/*!
+******************************************************************************
+
+ @Function OSWaitus
+
+ @Description
+ This function implements a busy wait of the specified microseconds
+ This function does NOT release thread quanta
+
+ @Input ui32Timeus - (us)
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus);
+
+
+/*!
+******************************************************************************
+
+ @Function OSSleepms
+
+ @Description
+ This function implements a sleep of the specified milliseconds
+ This function may allow pre-emption if implemented
+
+ @Input ui32Timems - (ms)
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID OSSleepms(IMG_UINT32 ui32Timems);
+
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID);
+
+IMG_UINT8 OSReadHWReg8(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+IMG_UINT16 OSReadHWReg16(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+IMG_UINT32 OSReadHWReg32(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+IMG_UINT64 OSReadHWReg64(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+IMG_UINT64 OSReadHWRegBank(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT8 *pui8DstBuf, IMG_UINT64 ui64DstBufLen);
+
+IMG_VOID OSWriteHWReg8(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT8 ui32Value);
+IMG_VOID OSWriteHWReg16(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT16 ui32Value);
+IMG_VOID OSWriteHWReg32(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+IMG_VOID OSWriteHWReg64(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT64 ui64Value);
+IMG_UINT64 OSWriteHWRegBank(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT8 *pui8SrcBuf, IMG_UINT64 ui64rcBufLen);
+
+typedef IMG_VOID (*PFN_TIMER_FUNC)(IMG_VOID*);
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout);
+PVRSRV_ERROR OSRemoveTimer(IMG_HANDLE hTimer);
+PVRSRV_ERROR OSEnableTimer(IMG_HANDLE hTimer);
+PVRSRV_ERROR OSDisableTimer(IMG_HANDLE hTimer);
+
+
+/******************************************************************************
+
+ @Function OSPanic
+
+ @Description Take action in response to an unrecoverable driver error
+
+ @Input IMG_VOID
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID OSPanic(IMG_VOID);
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID);
+
+typedef enum _img_verify_test
+{
+ PVR_VERIFY_WRITE = 0,
+ PVR_VERIFY_READ
+} IMG_VERIFY_TEST;
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_SIZE_T ui32Bytes);
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, const IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, const IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+
+
+IMG_VOID OSWriteMemoryBarrier(IMG_VOID);
+IMG_VOID OSMemoryBarrier(IMG_VOID);
+
+/* These functions alter the behaviour of OSEventObjectWait*() calls.
+ * When ReleasePVRLock is set the PVR/bridge lock is released prior to the
+ * thread entering the descheduled wait state to allow other bridge call
+ * activity. When KeepPVRLock is set the bridge lock is not released and is
+ * held while the thread is descheduled in a wait state. ReleasePVRLock
+ * is considered the default state and it is recommended any use of
+ * KeepPVRLock is paired with a call to the RelasePVRLock in the same scope.
+ * NOTE: This release/keep state may only be changed by the thread (by calling
+ * these Set functions) when it has been able to obtain the bridge lock first.
+ */
+IMG_VOID OSSetReleasePVRLock(IMG_VOID);
+IMG_VOID OSSetKeepPVRLock(IMG_VOID);
+IMG_BOOL OSGetReleasePVRLock(IMG_VOID);
+
+typedef struct _OSWR_LOCK_ *POSWR_LOCK;
+
+#if defined(__linux__) || (UNDER_CE) || defined(__QNXNTO__)
+
+PVRSRV_ERROR OSWRLockCreate(POSWR_LOCK *ppsLock);
+IMG_VOID OSWRLockDestroy(POSWR_LOCK psLock);
+
+/* Linux kernel requires these functions defined as macros to avoid
+ * lockdep issues */
+#if defined(__linux__) && defined(__KERNEL__)
+
+struct _OSWR_LOCK_
+{
+ struct rw_semaphore sRWLock;
+};
+
+/* Lock classes used for each rw semaphore */
+typedef enum RWLockClasses
+{
+ GLOBAL_DBGNOTIFY = 0,
+ GLOBAL_NOTIFY,
+ DEVINFO_RENDERLIST,
+ DEVINFO_COMPUTELIST,
+ DEVINFO_TRANSFERLIST,
+ DEVINFO_RAYTRACELIST,
+ DEVINFO_MEMORYLIST
+} RWLOCKCLASSES;
+
+#define OSWRLockAcquireRead(psLock, ui32class) ({down_read_nested(&psLock->sRWLock, ui32class); PVRSRV_OK;})
+#define OSWRLockReleaseRead(psLock) ({up_read(&psLock->sRWLock); PVRSRV_OK;})
+#define OSWRLockAcquireWrite(psLock, ui32class) ({down_write_nested(&psLock->sRWLock, ui32class); PVRSRV_OK;})
+#define OSWRLockReleaseWrite(psLock) ({up_write(&psLock->sRWLock); PVRSRV_OK;})
+
+#else /* defined(__linux__) && defined(__KERNEL__) */
+
+IMG_VOID OSWRLockAcquireRead(POSWR_LOCK psLock, IMG_UINT32 ui32class);
+IMG_VOID OSWRLockReleaseRead(POSWR_LOCK psLock);
+IMG_VOID OSWRLockAcquireWrite(POSWR_LOCK psLock, IMG_UINT32 ui32class);
+IMG_VOID OSWRLockReleaseWrite(POSWR_LOCK psLock);
+
+#endif /* defined(__linux__) && defined(__KERNEL__) */
+
+#else /* defined(__linux__) || (UNDER_CE) || defined(__QNXNTO__) */
+struct _OSWR_LOCK_ {
+ IMG_UINT32 ui32Dummy;
+};
+static INLINE PVRSRV_ERROR OSWRLockCreate(POSWR_LOCK *ppsLock)
+{
+ PVR_UNREFERENCED_PARAMETER(ppsLock);
+ return PVRSRV_OK;
+}
+
+static INLINE IMG_VOID OSWRLockDestroy(POSWR_LOCK psLock)
+{
+ PVR_UNREFERENCED_PARAMETER(psLock);
+}
+
+static INLINE IMG_VOID OSWRLockAcquireRead(POSWR_LOCK psLock)
+{
+ PVR_UNREFERENCED_PARAMETER(psLock);
+}
+
+static INLINE IMG_VOID OSWRLockReleaseRead(POSWR_LOCK psLock)
+{
+ PVR_UNREFERENCED_PARAMETER(psLock);
+}
+
+static INLINE IMG_VOID OSWRLockAcquireWrite(POSWR_LOCK psLock)
+{
+ PVR_UNREFERENCED_PARAMETER(psLock);
+}
+
+static INLINE IMG_VOID OSWRLockReleaseWrite(POSWR_LOCK psLock)
+{
+ PVR_UNREFERENCED_PARAMETER(psLock);
+}
+#endif /* defined(__linux__) || (UNDER_CE) || defined(__QNXNTO__) */
+
+IMG_UINT64 OSDivide64r64(IMG_UINT64 ui64Divident, IMG_UINT32 ui32Divisor, IMG_UINT32 *pui32Remainder);
+IMG_UINT32 OSDivide64(IMG_UINT64 ui64Divident, IMG_UINT32 ui32Divisor, IMG_UINT32 *pui32Remainder);
+
+IMG_VOID OSDumpStack(IMG_VOID);
+
+IMG_VOID OSAcquireBridgeLock(IMG_VOID);
+IMG_VOID OSReleaseBridgeLock(IMG_VOID);
+
+
+/*
+ * Functions for providing support for PID statistics.
+ */
+typedef IMG_BOOL (OS_GET_STATS_ELEMENT_FUNC)(IMG_PVOID pvStatPtr,
+ IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData,
+ IMG_CHAR** ppszStatFmtText);
+
+IMG_PVOID OSCreateStatisticEntry(IMG_CHAR* pszName, IMG_PVOID pvFolder,
+ OS_GET_STATS_ELEMENT_FUNC* pfnGetElement,
+ IMG_PVOID pvData);
+IMG_VOID OSRemoveStatisticEntry(IMG_PVOID pvEntry);
+IMG_PVOID OSCreateStatisticFolder(IMG_CHAR *pszName, IMG_PVOID pvFolder);
+IMG_VOID OSRemoveStatisticFolder(IMG_PVOID pvFolder);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __OSFUNC_H__ */
+
+/******************************************************************************
+ End of file (osfunc.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/server/include/ossecure_export.h b/drivers/gpu/rogue/services/server/include/ossecure_export.h
new file mode 100644
index 000000000000..c1c43e1a7cc2
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/ossecure_export.h
@@ -0,0 +1,52 @@
+/**************************************************************************/ /*!
+@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"
+
+PVRSRV_ERROR OSSecureExport(CONNECTION_DATA *psConnection,
+ IMG_PVOID pvData,
+ IMG_SECURE_TYPE *phSecure,
+ CONNECTION_DATA **ppsSecureConnection);
+
+PVRSRV_ERROR OSSecureImport(IMG_SECURE_TYPE hSecure, IMG_PVOID *ppvData);
+
diff --git a/drivers/gpu/rogue/services/server/include/pdump_km.h b/drivers/gpu/rogue/services/server/include/pdump_km.h
new file mode 100644
index 000000000000..5034c14ae94b
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/pdump_km.h
@@ -0,0 +1,742 @@
+/*************************************************************************/ /*!
+@File
+@Title pdump functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for 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.
+*/ /**************************************************************************/
+
+#ifndef _PDUMP_KM_H_
+#define _PDUMP_KM_H_
+
+/* services/srvkm/include/ */
+#include "device.h"
+
+/* include/ */
+#include "pvrsrv_error.h"
+#include "services.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(KERNEL) && defined(ANDROID)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+
+#include "connection_server.h"
+#include "sync_server.h"
+/*
+ * Pull in pdump flags from services include
+ */
+#include "pdump.h"
+#include "pdumpdefs.h"
+
+/* Define this to enable the PDUMP_HERE trace in the server */
+#undef PDUMP_TRACE
+
+#if defined(PDUMP_TRACE)
+#define PDUMP_HERE(a) if (ui32Flags & PDUMP_FLAGS_DEBUG) PVR_DPF((PVR_DBG_WARNING, "HERE %d", (a)))
+#define PDUMP_HEREA(a) PVR_DPF((PVR_DBG_WARNING, "HERE ALWAYS %d", (a)))
+#else
+#define PDUMP_HERE(a) (void)(a);
+#define PDUMP_HEREA(a) (void)(a);
+#endif
+
+#define PDUMP_PD_UNIQUETAG (IMG_HANDLE)0
+#define PDUMP_PT_UNIQUETAG (IMG_HANDLE)0
+
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+/* counter increments each time debug write is called */
+extern IMG_UINT32 g_ui32EveryLineCounter;
+#endif
+
+typedef struct _PDUMP_CONNECTION_DATA_ PDUMP_CONNECTION_DATA;
+typedef PVRSRV_ERROR (*PFN_PDUMP_TRANSITION)(IMG_PVOID *pvData, IMG_BOOL bInto, IMG_BOOL bContinuous);
+
+/*! Macro used to record a panic in the PDump script stream */
+#define PDUMP_PANIC(_type, _id, _msg) do \
+ { PVRSRV_ERROR _eE;\
+ _eE = PDumpPanic((PVRSRV_DEVICE_TYPE_ ## _type)<<16 | ((_type ## _PDUMP_PANIC_ ## _id)&0xFFFF), _msg, __FUNCTION__, __LINE__);\
+ PVR_LOG_IF_ERROR(_eE, "PDumpPanic");\
+ MSC_SUPPRESS_4127\
+ } while (0)
+
+#ifdef PDUMP
+ /* Shared across pdump_x files */
+ PVRSRV_ERROR PDumpInitCommon(IMG_VOID);
+ IMG_VOID PDumpDeInitCommon(IMG_VOID);
+ IMG_BOOL PDumpReady(IMG_VOID);
+ IMG_VOID PDumpGetParameterZeroPageInfo(PDUMP_FILEOFFSET_T *puiZeroPageOffset,
+ IMG_SIZE_T *puiZeroPageSize,
+ const IMG_CHAR **ppszZeroPageFilename);
+
+ IMG_VOID PDumpConnectionNotify(IMG_VOID);
+
+ PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID);
+ PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_MODULE_ID eModuleID);
+ PVRSRV_ERROR PDumpSetFrameKM(CONNECTION_DATA *psConnection, IMG_UINT32 ui32Frame);
+ PVRSRV_ERROR PDumpGetFrameKM(CONNECTION_DATA *psConnection, IMG_UINT32* pui32Frame);
+ PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpSetDefaultCaptureParamsKM(IMG_UINT32 ui32Mode,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32End,
+ IMG_UINT32 ui32Interval,
+ IMG_UINT32 ui32MaxParamFileSize);
+
+
+ PVRSRV_ERROR PDumpReg32(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpReg64(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT64 ui64RegValue,
+ IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpLDW(IMG_CHAR *pcBuffer,
+ IMG_CHAR *pszDevSpaceName,
+ IMG_UINT32 ui32OffsetBytes,
+ IMG_UINT32 ui32NumLoadBytes,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+ PVRSRV_ERROR PDumpSAW(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,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags,
+ PDUMP_POLL_OPERATOR eOperator);
+
+ IMG_IMPORT 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);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR *pszPDumpRegName,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpComment(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+ PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags,
+ IMG_CHAR* pszFormat,
+ ...) IMG_FORMAT_PRINTF(2, 3);
+
+ PVRSRV_ERROR PDumpPanic(IMG_UINT32 ui32PanicNo,
+ IMG_CHAR* pszPanicMsg,
+ 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);
+
+ IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID);
+
+ PVRSRV_ERROR PDumpIsCaptureFrameKM(IMG_BOOL *bIsCapturing);
+
+ IMG_VOID PDumpMallocPagesPhys(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_UINT64 ui64DevVAddr,
+ IMG_PUINT32 pui32PhysPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 *pui32MMUContextID,
+ IMG_UINT32 ui32MMUType,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvPDCPUAddr);
+ PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32MMUType);
+
+ PVRSRV_ERROR PDumpRegRead32(IMG_CHAR *pszPDumpRegName,
+ const IMG_UINT32 dwRegOffset,
+ IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpRegRead64(IMG_CHAR *pszPDumpRegName,
+ const IMG_UINT32 dwRegOffset,
+ IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpHWPerfCBKM(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpTRG(IMG_CHAR *pszMemSpace,
+ IMG_UINT32 ui32MMUCtxID,
+ IMG_UINT32 ui32RegionID,
+ IMG_BOOL bEnable,
+ IMG_UINT64 ui64VAddr,
+ IMG_UINT64 ui64LenBytes,
+ IMG_UINT32 ui32XStride,
+ IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpCreateLockKM(IMG_VOID);
+ IMG_VOID PDumpDestroyLockKM(IMG_VOID);
+ IMG_VOID PDumpLockKM(IMG_VOID);
+ IMG_VOID PDumpUnlockKM(IMG_VOID);
+
+ /*
+ Process persistence common API for use by common
+ clients e.g. mmu and physmem.
+ */
+ IMG_BOOL PDumpIsPersistent(IMG_VOID);
+ PVRSRV_ERROR PDumpAddPersistantProcess(IMG_VOID);
+
+ PVRSRV_ERROR PDumpIfKM(IMG_CHAR *pszPDumpCond);
+ PVRSRV_ERROR PDumpElseKM(IMG_CHAR *pszPDumpCond);
+ PVRSRV_ERROR PDumpFiKM(IMG_CHAR *pszPDumpCond);
+
+ IMG_VOID PDumpCtrlInit(IMG_UINT32 ui32InitCapMode);
+ IMG_VOID PDumpCtrlSetDefaultCaptureParams(IMG_UINT32 ui32Mode, IMG_UINT32 ui32Start, IMG_UINT32 ui32End, IMG_UINT32 ui32Interval);
+ IMG_BOOL PDumpCtrlCapModIsFramed(IMG_VOID);
+ IMG_BOOL PDumpCtrlCapModIsContinuous(IMG_VOID);
+ IMG_UINT32 PDumpCtrlGetCurrentFrame(IMG_VOID);
+ IMG_VOID PDumpCtrlSetCurrentFrame(IMG_UINT32 ui32Frame);
+ IMG_BOOL PDumpCtrlCaptureOn(IMG_VOID);
+ IMG_BOOL PDumpCtrlCaptureRangePast(IMG_VOID);
+ IMG_BOOL PDumpCtrlCaptureRangeUnset(IMG_VOID);
+ IMG_BOOL PDumpCtrIsLastCaptureFrame(IMG_VOID);
+ IMG_BOOL PDumpCtrlInitPhaseComplete(IMG_VOID);
+ IMG_VOID PDumpCtrlSetInitPhaseComplete(IMG_BOOL bIsComplete);
+ IMG_VOID PDumpCtrlSuspend(IMG_VOID);
+ IMG_VOID PDumpCtrlResume(IMG_VOID);
+ IMG_BOOL PDumpCtrlIsDumpSuspended(IMG_VOID);
+ IMG_VOID PDumpCtrlPowerTransitionStart(IMG_VOID);
+ IMG_VOID PDumpCtrlPowerTransitionEnd(IMG_VOID);
+ IMG_BOOL PDumpCtrlInPowerTransition(IMG_VOID);
+
+ /*!
+ * @name PDumpWriteParameter
+ * @brief General function for writing to PDump stream. Used
+ * mainly for memory dumps to parameter stream.
+ * Usually more convenient to use PDumpWriteScript below
+ * for the script stream.
+ * @param psui8Data - data to write
+ * @param ui32Size - size of write
+ * @param ui32Flags - PDump flags
+ * @param pui32FileOffset - on return contains the file offset to
+ * the start of the parameter data
+ * @param aszFilenameStr - pointer to at least a 20 char buffer to
+ * return the parameter filename
+ * @return error
+ */
+ PVRSRV_ERROR PDumpWriteParameter(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 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);
+
+ /*
+ PDumpWriteShiftedMaskedValue():
+
+ loads the "reference" address into an internal PDump register,
+ optionally shifts it right,
+ optionally shifts it left,
+ optionally masks it
+ then finally writes the computed value to the given destination address
+
+ i.e. it emits pdump language equivalent to this expression:
+
+ dest = ((&ref) >> SHRamount << SHLamount) & MASK
+ */
+extern PVRSRV_ERROR
+PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
+ const IMG_CHAR *pszDestSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiDestOffset,
+ const IMG_CHAR *pszRefRegspaceName,
+ const IMG_CHAR *pszRefSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiRefOffset,
+ IMG_UINT32 uiSHRAmount,
+ IMG_UINT32 uiSHLAmount,
+ IMG_UINT32 uiMask,
+ IMG_DEVMEM_SIZE_T uiWordSize,
+ IMG_UINT32 uiPDumpFlags);
+
+ /*
+ PDumpWriteSymbAddress():
+
+ writes the address of the "reference" to the offset given
+ */
+extern PVRSRV_ERROR
+PDumpWriteSymbAddress(const IMG_CHAR *pszDestSpaceName,
+ IMG_DEVMEM_OFFSET_T uiDestOffset,
+ const IMG_CHAR *pszRefSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiRefOffset,
+ const IMG_CHAR *pszPDumpDevName,
+ IMG_UINT32 ui32WordSize,
+ IMG_UINT32 ui32AlignShift,
+ IMG_UINT32 ui32Shift,
+ IMG_UINT32 uiPDumpFlags);
+
+/* Register the connection with the PDump subsystem */
+extern PVRSRV_ERROR PDumpRegisterConnection(SYNC_CONNECTION_DATA *psSyncConnectionData,
+ PDUMP_CONNECTION_DATA **ppsPDumpConnectionData);
+
+/* Unregister the connection with the PDump subsystem */
+extern IMG_VOID PDumpUnregisterConnection(PDUMP_CONNECTION_DATA *psPDumpConnectionData);
+
+/* Register for notification of PDump Transition into/out of capture range */
+extern PVRSRV_ERROR PDumpRegisterTransitionCallback(PDUMP_CONNECTION_DATA *psPDumpConnectionData,
+ PFN_PDUMP_TRANSITION pfnCallback,
+ IMG_PVOID hPrivData,
+ IMG_PVOID *ppvHandle);
+
+/* Unregister notification of PDump Transition */
+extern IMG_VOID PDumpUnregisterTransitionCallback(IMG_PVOID pvHandle);
+
+/* Notify PDump of a Transition into/out of capture range */
+extern PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, IMG_BOOL bInto, IMG_BOOL bContinuous);
+
+ #define PDUMP_LOCK PDumpLockKM
+ #define PDUMP_UNLOCK PDumpUnlockKM
+
+ #define PDUMPINIT PDumpInitCommon
+ #define PDUMPDEINIT PDumpDeInitCommon
+ #define PDUMPREG32 PDumpReg32
+ #define PDUMPREG64 PDumpReg64
+ #define PDUMPREGREAD32 PDumpRegRead32
+ #define PDUMPREGREAD64 PDumpRegRead64
+ #define PDUMPCOMMENT PDumpComment
+ #define PDUMPCOMMENTWITHFLAGS PDumpCommentWithFlags
+ #define PDUMPREGPOL PDumpRegPolKM
+ #define PDUMPSETMMUCONTEXT PDumpSetMMUContext
+ #define PDUMPCLEARMMUCONTEXT PDumpClearMMUContext
+ #define PDUMPPDREG PDumpPDReg
+ #define PDUMPPDREGWITHFLAGS PDumpPDRegWithFlags
+ #define PDUMPREGBASEDCBP PDumpRegBasedCBP
+ #define PDUMPENDINITPHASE PDumpStopInitPhaseKM
+ #define PDUMPIDLWITHFLAGS PDumpIDLWithFlags
+ #define PDUMPIDL PDumpIDL
+ #define PDUMPPOWCMDSTART PDumpCtrlPowerTransitionStart
+ #define PDUMPPOWCMDEND PDumpCtrlPowerTransitionEnd
+ #define PDUMPPOWCMDINTRANS PDumpCtrlInPowerTransition
+ #define PDUMPIF PDumpIfKM
+ #define PDUMPELSE PDumpElseKM
+ #define PDUMPFI PDumpFiKM
+#else
+ /*
+ We should be clearer about which functions can be called
+ across the bridge as this looks rather unblanced
+ */
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpInitCommon)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpInitCommon(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpConnectionNotify)
+#endif
+static INLINE IMG_VOID
+PDumpConnectionNotify(IMG_VOID)
+{
+ return;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpCreateLockKM)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpCreateLockKM(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpDestroyLockKM)
+#endif
+static INLINE IMG_VOID
+PDumpDestroyLockKM(IMG_VOID)
+{
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpLockKM)
+#endif
+static INLINE IMG_VOID
+PDumpLockKM(IMG_VOID)
+{
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpUnlockKM)
+#endif
+static INLINE IMG_VOID
+PDumpUnlockKM(IMG_VOID)
+{
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpAddPersistantProcess)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpAddPersistantProcess(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpStartInitPhaseKM)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpStartInitPhaseKM(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpStopInitPhaseKM)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpStopInitPhaseKM(IMG_MODULE_ID eModuleID)
+{
+ PVR_UNREFERENCED_PARAMETER(eModuleID);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpSetFrameKM)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpSetFrameKM(CONNECTION_DATA *psConnection, IMG_UINT32 ui32Frame)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(ui32Frame);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpGetFrameKM)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpGetFrameKM(CONNECTION_DATA *psConnection, IMG_UINT32* pui32Frame)
+{
+ PVR_UNREFERENCED_PARAMETER(psConnection);
+ PVR_UNREFERENCED_PARAMETER(pui32Frame);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpCommentKM)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+{
+ PVR_UNREFERENCED_PARAMETER(pszComment);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ return PVRSRV_OK;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpCommentKM)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpSetDefaultCaptureParamsKM(IMG_UINT32 ui32Mode,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32End,
+ IMG_UINT32 ui32Interval,
+ IMG_UINT32 ui32MaxParamFileSize)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Mode);
+ PVR_UNREFERENCED_PARAMETER(ui32Start);
+ PVR_UNREFERENCED_PARAMETER(ui32End);
+ PVR_UNREFERENCED_PARAMETER(ui32Interval);
+ PVR_UNREFERENCED_PARAMETER(ui32MaxParamFileSize);
+
+ return PVRSRV_OK;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpPanic)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpPanic(IMG_UINT32 ui32PanicNo,
+ IMG_CHAR* pszPanicMsg,
+ const IMG_CHAR* pszPPFunc,
+ IMG_UINT32 ui32PPline)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32PanicNo);
+ PVR_UNREFERENCED_PARAMETER(pszPanicMsg);
+ PVR_UNREFERENCED_PARAMETER(pszPPFunc);
+ PVR_UNREFERENCED_PARAMETER(ui32PPline);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpIsLastCaptureFrameKM)
+#endif
+static INLINE IMG_BOOL
+PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+ return IMG_FALSE;
+}
+
+#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(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)
+{
+ 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;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpRegisterConnection)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpRegisterConnection(SYNC_CONNECTION_DATA *psSyncConnectionData,
+ PDUMP_CONNECTION_DATA **ppsPDumpConnectionData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSyncConnectionData);
+ PVR_UNREFERENCED_PARAMETER(ppsPDumpConnectionData);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpUnregisterConnection)
+#endif
+static INLINE
+IMG_VOID PDumpUnregisterConnection(PDUMP_CONNECTION_DATA *psPDumpConnectionData)
+{
+ PVR_UNREFERENCED_PARAMETER(psPDumpConnectionData);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpRegisterTransitionCallback)
+#endif
+static INLINE
+PVRSRV_ERROR PDumpRegisterTransitionCallback(PDUMP_CONNECTION_DATA *psPDumpConnectionData,
+ PFN_PDUMP_TRANSITION pfnCallback,
+ IMG_PVOID hPrivData,
+ IMG_PVOID *ppvHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(psPDumpConnectionData);
+ PVR_UNREFERENCED_PARAMETER(pfnCallback);
+ PVR_UNREFERENCED_PARAMETER(hPrivData);
+ PVR_UNREFERENCED_PARAMETER(ppvHandle);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpUnregisterTransitionCallback)
+#endif
+static INLINE
+IMG_VOID PDumpUnregisterTransitionCallback(IMG_PVOID pvHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pvHandle);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PDumpTransition)
+#endif
+static INLINE
+PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, IMG_BOOL bInto, IMG_BOOL bContinuous)
+{
+ PVR_UNREFERENCED_PARAMETER(psPDumpConnectionData);
+ PVR_UNREFERENCED_PARAMETER(bInto);
+ PVR_UNREFERENCED_PARAMETER(bContinuous);
+ return PVRSRV_OK;
+}
+
+ #if defined WIN32 || defined UNDER_WDDM
+ #define PDUMPINIT PDumpInitCommon
+ #define PDUMPDEINIT(...) / ## * PDUMPDEINIT(__VA_ARGS__) * ## /
+ #define PDUMPREG32(...) / ## * PDUMPREG32(__VA_ARGS__) * ## /
+ #define PDUMPREG64(...) / ## * PDUMPREG64(__VA_ARGS__) * ## /
+ #define PDUMPREGREAD32(...) / ## * PDUMPREGREAD32(__VA_ARGS__) * ## /
+ #define PDUMPREGREAD64(...) / ## * PDUMPREGREAD64(__VA_ARGS__) * ## /
+ #define PDUMPCOMMENT(...) / ## * PDUMPCOMMENT(__VA_ARGS__) * ## /
+ #define PDUMPREGPOL(...) / ## * PDUMPREGPOL(__VA_ARGS__) * ## /
+ #define PDUMPSETMMUCONTEXT(...) / ## * PDUMPSETMMUCONTEXT(__VA_ARGS__) * ## /
+ #define PDUMPCLEARMMUCONTEXT(...) / ## * PDUMPCLEARMMUCONTEXT(__VA_ARGS__) * ## /
+ #define PDUMPPDREG(...) / ## * PDUMPPDREG(__VA_ARGS__) * ## /
+ #define PDUMPPDREGWITHFLAGS(...) / ## * PDUMPPDREGWITHFLAGS(__VA_ARGS__) * ## /
+ #define PDUMPSYNC(...) / ## * PDUMPSYNC(__VA_ARGS__) * ## /
+ #define PDUMPCOPYTOMEM(...) / ## * PDUMPCOPYTOMEM(__VA_ARGS__) * ## /
+ #define PDUMPWRITE(...) / ## * PDUMPWRITE(__VA_ARGS__) * ## /
+ #define PDUMPCBP(...) / ## * PDUMPCBP(__VA_ARGS__) * ## /
+ #define PDUMPREGBASEDCBP(...) / ## * PDUMPREGBASEDCBP(__VA_ARGS__) * ## /
+ #define PDUMPCOMMENTWITHFLAGS(...) / ## * PDUMPCOMMENTWITHFLAGS(__VA_ARGS__) * ## /
+ #define PDUMPMALLOCPAGESPHYS(...) / ## * PDUMPMALLOCPAGESPHYS(__VA_ARGS__) * ## /
+ #define PDUMPENDINITPHASE(...) / ## * PDUMPENDINITPHASE(__VA_ARGS__) * ## /
+ #define PDUMPMSVDXREG(...) / ## * PDUMPMSVDXREG(__VA_ARGS__) * ## /
+ #define PDUMPMSVDXREGWRITE(...) / ## * PDUMPMSVDXREGWRITE(__VA_ARGS__) * ## /
+ #define PDUMPMSVDXREGREAD(...) / ## * PDUMPMSVDXREGREAD(__VA_ARGS__) * ## /
+ #define PDUMPMSVDXPOLEQ(...) / ## * PDUMPMSVDXPOLEQ(__VA_ARGS__) * ## /
+ #define PDUMPMSVDXPOL(...) / ## * PDUMPMSVDXPOL(__VA_ARGS__) * ## /
+ #define PDUMPIDLWITHFLAGS(...) / ## * PDUMPIDLWITHFLAGS(__VA_ARGS__) * ## /
+ #define PDUMPIDL(...) / ## * PDUMPIDL(__VA_ARGS__) * ## /
+ #define PDUMPPOWCMDSTART(...) / ## * PDUMPPOWCMDSTART(__VA_ARGS__) * ## /
+ #define PDUMPPOWCMDEND(...) / ## * PDUMPPOWCMDEND(__VA_ARGS__) * ## /
+ #define PDUMP_LOCK / ## * PDUMP_LOCK(__VA_ARGS__) * ## /
+ #define PDUMP_UNLOCK / ## * PDUMP_UNLOCK(__VA_ARGS__) * ## /
+ #else
+ #if defined LINUX || defined GCC_IA32 || defined GCC_ARM || defined __QNXNTO__
+ #define PDUMPINIT PDumpInitCommon
+ #define PDUMPDEINIT(args...)
+ #define PDUMPREG32(args...)
+ #define PDUMPREG64(args...)
+ #define PDUMPREGREAD32(args...)
+ #define PDUMPREGREAD64(args...)
+ #define PDUMPCOMMENT(args...)
+ #define PDUMPREGPOL(args...)
+ #define PDUMPSETMMUCONTEXT(args...)
+ #define PDUMPCLEARMMUCONTEXT(args...)
+ #define PDUMPPDREG(args...)
+ #define PDUMPPDREGWITHFLAGS(args...)
+ #define PDUMPSYNC(args...)
+ #define PDUMPCOPYTOMEM(args...)
+ #define PDUMPWRITE(args...)
+ #define PDUMPREGBASEDCBP(args...)
+ #define PDUMPCOMMENTWITHFLAGS(args...)
+ #define PDUMPENDINITPHASE(args...)
+ #define PDUMPIDLWITHFLAGS(args...)
+ #define PDUMPIDL(args...)
+ #define PDUMPPOWCMDSTART(args...)
+ #define PDUMPPOWCMDEND(args...)
+ #define PDUMP_LOCK(args...)
+ #define PDUMP_UNLOCK(args...)
+
+ #else
+ #error Compiler not specified
+ #endif
+ #endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* _PDUMP_KM_H_ */
+
+/******************************************************************************
+ End of file (pdump_km.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/include/pdump_mmu.h b/drivers/gpu/rogue/services/server/include/pdump_mmu.h
new file mode 100644
index 000000000000..638241045f99
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/pdump_mmu.h
@@ -0,0 +1,175 @@
+/**************************************************************************/ /*!
+@File
+@Title Common MMU Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements basic low level control of MMU.
+@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 SRVKM_PDUMP_MMU_H
+#define SRVKM_PDUMP_MMU_H
+
+/* services/server/include/ */
+#include "pdump_symbolicaddr.h"
+/* include/ */
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+#include "mmu_common.h"
+
+/*
+ PDUMP MMU attributes
+*/
+typedef struct _PDUMP_MMU_ATTRIB_DEVICE_
+{
+ /* Per-Device Pdump attribs */
+
+ /*!< Pdump memory bank name */
+ IMG_CHAR *pszPDumpMemDevName;
+
+ /*!< Pdump register bank name */
+ IMG_CHAR *pszPDumpRegDevName;
+
+} PDUMP_MMU_ATTRIB_DEVICE;
+
+typedef struct _PDUMP_MMU_ATTRIB_CONTEXT_
+{
+ IMG_UINT32 ui32Dummy;
+} PDUMP_MMU_ATTRIB_CONTEXT;
+
+typedef struct _PDUMP_MMU_ATTRIB_HEAP_
+{
+ /* data page info */
+ IMG_UINT32 ui32DataPageMask;
+} PDUMP_MMU_ATTRIB_HEAP;
+
+typedef struct _PDUMP_MMU_ATTRIB_
+{
+
+ struct _PDUMP_MMU_ATTRIB_DEVICE_ sDevice;
+ struct _PDUMP_MMU_ATTRIB_CONTEXT_ sContext;
+ struct _PDUMP_MMU_ATTRIB_HEAP_ sHeap;
+} PDUMP_MMU_ATTRIB;
+
+#if defined(PDUMP)
+ extern PVRSRV_ERROR PDumpMMUMalloc(const IMG_CHAR *pszPDumpDevName,
+ MMU_LEVEL eMMULevel,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Align);
+
+ extern PVRSRV_ERROR PDumpMMUFree(const IMG_CHAR *pszPDumpDevName,
+ MMU_LEVEL eMMULevel,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+ extern PVRSRV_ERROR PDumpMMUMalloc2(const IMG_CHAR *pszPDumpDevName,
+ const IMG_CHAR *pszTableType,/* PAGE_CATALOGUE, PAGE_DIRECTORY, PAGE_TABLE */
+ const IMG_CHAR *pszSymbolicAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Align);
+
+ extern PVRSRV_ERROR PDumpMMUFree2(const IMG_CHAR *pszPDumpDevName,
+ const IMG_CHAR *pszTableType,/* PAGE_CATALOGUE, PAGE_DIRECTORY, PAGE_TABLE */
+ const IMG_CHAR *pszSymbolicAddr);
+
+ extern PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
+ const IMG_CHAR *pszPDumpDevName,
+ IMG_VOID *pvPxMem,
+ IMG_DEV_PHYADDR sPxDevPAddr,
+ IMG_UINT32 uiFirstEntry,
+ IMG_UINT32 uiNumEntries,
+ const IMG_CHAR *pszMemspaceName,
+ const IMG_CHAR *pszSymbolicAddr,
+ IMG_UINT64 uiSymbolicAddrOffset,
+ IMG_UINT32 uiBytesPerEntry,
+ IMG_UINT32 uiLog2Align,
+ IMG_UINT32 uiAddrShift,
+ IMG_UINT64 uiAddrMask,
+ IMG_UINT64 uiPxEProtMask,
+ IMG_UINT32 ui32Flags);
+
+ extern PVRSRV_ERROR PDumpMMUAllocMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
+ IMG_DEV_PHYADDR sPCDevPAddr,
+ PDUMP_MMU_TYPE eMMUType,
+ IMG_UINT32 *pui32MMUContextID);
+
+ extern PVRSRV_ERROR PDumpMMUFreeMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
+ IMG_UINT32 ui32MMUContextID);
+
+ extern PVRSRV_ERROR PDumpMMUActivateCatalog(const IMG_CHAR *pszPDumpRegSpaceName,
+ const IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 uiRegAddr,
+ const IMG_CHAR *pszPDumpPCSymbolicName);
+
+
+extern PVRSRV_ERROR
+PDumpMMUSAB(const IMG_CHAR *pszPDumpMemNamespace,
+ IMG_UINT32 uiPDumpMMUCtx,
+ IMG_DEV_VIRTADDR sDevAddrStart,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 uiFileOffset,
+ IMG_UINT32 ui32PDumpFlags);
+
+ #define PDUMP_MMU_MALLOC_DP(pszPDumpMemDevName, aszSymbolicAddr, ui32Size, ui32Align) \
+ PDumpMMUMalloc2(pszPDumpMemDevName, "DATA_PAGE", aszSymbolicAddr, ui32Size, ui32Align)
+ #define PDUMP_MMU_FREE_DP(pszPDumpMemDevName, aszSymbolicAddr) \
+ PDumpMMUFree2(pszPDumpMemDevName, "DATA_PAGE", aszSymbolicAddr)
+
+ #define PDUMP_MMU_ALLOC_MMUCONTEXT(pszPDumpMemDevName, sPCDevPAddr, eMMUType, puiPDumpCtxID) \
+ PDumpMMUAllocMMUContext(pszPDumpMemDevName, \
+ sPCDevPAddr, \
+ eMMUType, \
+ puiPDumpCtxID)
+
+ #define PDUMP_MMU_FREE_MMUCONTEXT(pszPDumpMemDevName, uiPDumpCtxID) \
+ PDumpMMUFreeMMUContext(pszPDumpMemDevName, uiPDumpCtxID)
+#else
+
+ #define PDUMP_MMU_MALLOC_DP(pszPDumpMemDevName, pszDevPAddr, ui32Size, ui32Align) \
+ ((IMG_VOID)0)
+ #define PDUMP_MMU_FREE_DP(pszPDumpMemDevName, psDevPAddr) \
+ ((IMG_VOID)0)
+ #define PDUMP_MMU_ALLOC_MMUCONTEXT(pszPDumpMemDevName, sPCDevPAddr, puiPDumpCtxID) \
+ ((IMG_VOID)0)
+ #define PDUMP_MMU_FREE_MMUCONTEXT(pszPDumpMemDevName, uiPDumpCtxID) \
+ ((IMG_VOID)0)
+
+#endif // defined(PDUMP)
+
+#endif
diff --git a/drivers/gpu/rogue/services/server/include/pdump_osfunc.h b/drivers/gpu/rogue/services/server/include/pdump_osfunc.h
new file mode 100644
index 000000000000..171eec608f59
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/pdump_osfunc.h
@@ -0,0 +1,347 @@
+/*************************************************************************/ /*!
+@File
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS-independent interface to helper functions for pdump
+@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 <stdarg.h>
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_device_types.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+
+#define MAX_PDUMP_STRING_LENGTH (256)
+#if defined(WIN32)
+#define PDUMP_GET_SCRIPT_STRING() \
+ IMG_CHAR pszScript[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1; \
+ IMG_HANDLE hScript = (IMG_HANDLE)pszScript;
+
+#define PDUMP_GET_MSG_STRING() \
+ IMG_CHAR pszMsg[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1;
+
+#define PDUMP_GET_FILE_STRING() \
+ IMG_CHAR pszFileName[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING() \
+ IMG_CHAR pszScript[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_CHAR pszFileName[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLenScript = MAX_PDUMP_STRING_LENGTH-1; \
+ IMG_UINT32 ui32MaxLenFileName = MAX_PDUMP_STRING_LENGTH-1; \
+ IMG_HANDLE hScript = (IMG_HANDLE)pszScript;
+
+#else /* WIN32 */
+
+#if defined(__QNXNTO__)
+
+#define PDUMP_GET_SCRIPT_STRING() \
+ IMG_CHAR pszScript[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1; \
+ IMG_HANDLE hScript = (IMG_HANDLE)pszScript;
+
+#define PDUMP_GET_MSG_STRING() \
+ IMG_CHAR pszMsg[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1;
+
+#define PDUMP_GET_FILE_STRING() \
+ IMG_CHAR pszFileName[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING() \
+ IMG_CHAR pszScript[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_CHAR pszFileName[MAX_PDUMP_STRING_LENGTH]; \
+ IMG_UINT32 ui32MaxLenScript = MAX_PDUMP_STRING_LENGTH-1; \
+ IMG_UINT32 ui32MaxLenFileName = MAX_PDUMP_STRING_LENGTH-1; \
+ IMG_HANDLE hScript = (IMG_HANDLE)pszScript;
+
+#else /* __QNXNTO__ */
+
+ /*
+ * Linux
+ */
+#define PDUMP_GET_SCRIPT_STRING() \
+ IMG_HANDLE hScript; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eErrorPDump; \
+ eErrorPDump = PDumpOSGetScriptString(&hScript, &ui32MaxLen);\
+ PVR_LOGR_IF_ERROR(eErrorPDump, "PDumpOSGetScriptString");
+
+#define PDUMP_GET_MSG_STRING() \
+ IMG_CHAR *pszMsg; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eErrorPDump; \
+ eErrorPDump = PDumpOSGetMessageString(&pszMsg, &ui32MaxLen);\
+ PVR_LOGR_IF_ERROR(eErrorPDump, "PDumpOSGetMessageString");
+
+#define PDUMP_GET_FILE_STRING() \
+ IMG_CHAR *pszFileName; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eErrorPDump; \
+ eErrorPDump = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLen);\
+ PVR_LOGR_IF_ERROR(eErrorPDump, "PDumpOSGetFilenameString");
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING() \
+ IMG_HANDLE hScript; \
+ IMG_CHAR *pszFileName; \
+ IMG_UINT32 ui32MaxLenScript; \
+ IMG_UINT32 ui32MaxLenFileName; \
+ PVRSRV_ERROR eErrorPDump; \
+ eErrorPDump = PDumpOSGetScriptString(&hScript, &ui32MaxLenScript);\
+ PVR_LOGR_IF_ERROR(eErrorPDump, "PDumpOSGetScriptString");\
+ eErrorPDump = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
+ PVR_LOGR_IF_ERROR(eErrorPDump, "PDumpOSGetFilenameString");
+
+ /*!
+ * @name PDumpOSGetScriptString
+ * @brief Get the "script" buffer
+ * @param phScript - buffer handle for pdump script
+ * @param pui32MaxLen - max length of the script buffer
+ *
+*/
+ PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
+
+ /*!
+ * @name PDumpOSGetMessageString
+ * @brief Get the "message" buffer
+ * @param pszMsg - buffer pointer for pdump messages
+ * @param pui32MaxLen - max length of the message buffer
+ *
+*/
+ PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, IMG_UINT32 *pui32MaxLen);
+
+ /*!
+ * @name PDumpOSGetFilenameString
+ * @brief Get the "filename" buffer
+ * @param ppszFile - buffer pointer for filename
+ * @param pui32MaxLen - max length of the filename buffer
+ *
+*/
+ PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
+
+#endif /* __QNXNTO__ */
+#endif /* WIN32 */
+
+
+/*
+ * PDump streams, channels, init and deinit routines (common to all OSes)
+ */
+
+typedef struct
+{
+ IMG_HANDLE hInit; /*!< Driver initialisation PDump stream */
+ IMG_HANDLE hMain; /*!< App framed PDump stream */
+ IMG_HANDLE hDeinit; /*!< Driver/HW de-initialisation PDump stream */
+} PDUMP_CHANNEL;
+
+PVRSRV_ERROR PDumpOSInit(PDUMP_CHANNEL* psParam, PDUMP_CHANNEL* psScript,
+ IMG_UINT32* pui32InitCapMode, IMG_CHAR** ppszEnvComment);
+
+IMG_VOID PDumpOSDeInit(PDUMP_CHANNEL* psParam, PDUMP_CHANNEL* psScript);
+
+/*!
+ * @name PDumpOSSetSplitMarker
+ * @brief Inform the PDump client to start a new file at the given marker.
+ * @param hStream - stream
+ * @param ui32Marker - byte file position
+ */
+IMG_BOOL PDumpOSSetSplitMarker(IMG_HANDLE hStream, IMG_UINT32 ui32Marker);
+
+/*
+ PDumpOSDebugDriverWrite - ENV layer write entry point from COMMON layer
+ A call back down the PDump software layer
+ */
+IMG_UINT32 PDumpOSDebugDriverWrite(IMG_HANDLE psStream,
+ IMG_UINT8 *pui8Data,
+ IMG_UINT32 ui32BCount);
+
+/*
+ * Define macro for processing variable args list in OS-independent
+ * manner. See e.g. PDumpComment().
+ */
+#define PDUMP_va_list va_list
+#define PDUMP_va_start va_start
+#define PDUMP_va_end va_end
+
+
+/*!
+ * @name PDumpOSBufprintf
+ * @brief Printf to OS-specific pdump state buffer
+ * @param hBuf - buffer handle to write into
+ * @param ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
+ * @param pszFormat - format string
+ */
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+/*!
+ * @name PDumpOSDebugPrintf
+ * @brief Debug message during pdumping
+ * @param pszFormat - format string
+ */
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+/*
+ * Write into a IMG_CHAR* on all OSes. Can be allocated on the stack or heap.
+ */
+/*!
+ * @name PDumpOSSprintf
+ * @brief Printf to IMG char array
+ * @param pszComment - char array to print into
+ * @param pszFormat - format string
+ */
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+/*!
+ * @name PDumpOSVSprintf
+ * @brief Printf to IMG string using variable args (see stdarg.h). This is necessary
+ * because the ... notation does not support nested function calls.
+ * @param pszMsg - char array to print into
+ * @param ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
+ * @param pszFormat - format string
+ * @param vaArgs - variable args structure (from stdarg.h)
+ */
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) IMG_FORMAT_PRINTF(3, 0);
+
+/*!
+ * @name PDumpOSBuflen
+ * @param hBuffer - handle to buffer
+ * @param ui32BuffeRSizeMax - max size of buffer (chars)
+ * @return length of buffer, will always be <= ui32BufferSizeMax
+ */
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+/*!
+ * @name PDumpOSVerifyLineEnding
+ * @brief Put line ending sequence at the end if it isn't already there
+ * @param hBuffer - handle to buffer
+ * @param ui32BufferSizeMax - max size of buffer (chars)
+ */
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+/*!
+ * @name PDumpOSCPUVAddrToDevPAddr
+ * @brief OS function to convert CPU virtual to device physical for dumping pages
+ * @param hOSMemHandle mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
+ * @param ui32Offset dword offset into allocation (for use with mem handle, e.g. linux)
+ * @param pui8LinAddr CPU linear addr (usually a kernel virtual address)
+ * @param ui32PageSize page size, used for assertion check
+ * @return psDevPAddr device physical addr
+ */
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8LinAddr,
+ IMG_UINT32 ui32PageSize,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+/*!
+ * @name PDumpOSCPUVAddrToPhysPages
+ * @brief OS function to convert CPU virtual to backing physical pages
+ * @param hOSMemHandle mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
+ * @param ui32Offset offset within mem allocation block
+ * @param pui8LinAddr CPU linear addr
+ * @param ui32DataPageMask mask for data page (= data page size -1)
+ * @return pui32PageOffset CPU page offset (same as device page offset if page sizes equal)
+ */
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_PUINT8 pui8LinAddr,
+ IMG_UINT32 ui32DataPageMask,
+ IMG_UINT32 *pui32PageOffset);
+
+/*!
+ * @name PDumpOSReleaseExecution
+ * @brief OS function to switch to another process, to clear pdump buffers
+ */
+IMG_VOID PDumpOSReleaseExecution(IMG_VOID);
+
+/*!
+ * @name PDumpOSCreateLock
+ * @brief Create the global pdump lock
+ */
+PVRSRV_ERROR PDumpOSCreateLock(IMG_VOID);
+
+/*!
+ * @name PDumpOSDestroyLock
+ * @brief Destroy the global pdump lock
+ */
+IMG_VOID PDumpOSDestroyLock(IMG_VOID);
+
+/*!
+ * @name PDumpOSLock
+ * @brief Acquire the global pdump lock
+ */
+IMG_VOID PDumpOSLock(IMG_VOID);
+
+/*!
+ * @name PDumpOSUnlock
+ * @brief Release the global pdump lock
+ */
+IMG_VOID PDumpOSUnlock(IMG_VOID);
+
+/*!
+ * @name PDumpOSGetCtrlState
+ * @brief Retrieve some state from the debug driver or debug driver stream
+ */
+IMG_UINT32 PDumpOSGetCtrlState(IMG_HANDLE hDbgStream, IMG_UINT32 ui32StateID);
+
+/*!
+ * @name PDumpOSSetFrame
+ * @brief Set the current frame value mirrored in the debug driver
+ */
+IMG_VOID PDumpOSSetFrame(IMG_UINT32 ui32Frame);
+
+/*!
+ * @name PDumpOSAllowInitPhaseToComplete
+ * @brief Some platforms wish to control when the init phase is marked as
+ * complete depending on who is instructing it so.
+ */
+IMG_BOOL PDumpOSAllowInitPhaseToComplete(IMG_UINT32 eModuleID);
+
+
+#if defined (__cplusplus)
+}
+#endif
diff --git a/drivers/gpu/rogue/services/server/include/pdump_physmem.h b/drivers/gpu/rogue/services/server/include/pdump_physmem.h
new file mode 100644
index 000000000000..c75202b05f8d
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/pdump_physmem.h
@@ -0,0 +1,212 @@
+/**************************************************************************/ /*!
+@File
+@Title pdump functions to assist with physmem allocations
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements basic low level control of MMU.
+@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 SRVSRV_PDUMP_PHYSMEM_H
+#define SRVSRV_PDUMP_PHYSMEM_H
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pmr.h"
+
+
+typedef struct _PDUMP_PHYSMEM_INFO_T_ PDUMP_PHYSMEM_INFO_T;
+
+#if defined(PDUMP)
+extern PVRSRV_ERROR
+PDumpPMRMalloc(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicAddress,
+ IMG_UINT64 ui64Size,
+ /* alignment is alignment of start of buffer _and_
+ minimum contiguity - i.e. smallest allowable
+ page-size. */
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ IMG_BOOL bForcePersistent,
+ IMG_HANDLE *phHandlePtr);
+
+IMG_INTERNAL IMG_VOID
+PDumpPMRMallocPMR(const PMR *psPMR,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiBlockSize,
+ IMG_BOOL bForcePersistent,
+ IMG_HANDLE *phPDumpAllocInfoPtr);
+
+extern
+PVRSRV_ERROR PDumpPMRFree(IMG_HANDLE hPDumpAllocationInfoHandle);
+#else /* PDUMP */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSyncPrimPDumpPolKM)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpPMRMalloc(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicAddress,
+ IMG_UINT64 ui64Size,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ IMG_BOOL bForcePersistent,
+ IMG_HANDLE *phHandlePtr)
+{
+ PVR_UNREFERENCED_PARAMETER(pszDevSpace);
+ PVR_UNREFERENCED_PARAMETER(pszSymbolicAddress);
+ PVR_UNREFERENCED_PARAMETER(ui64Size);
+ PVR_UNREFERENCED_PARAMETER(uiAlign);
+ PVR_UNREFERENCED_PARAMETER(bForcePersistent);
+ PVR_UNREFERENCED_PARAMETER(phHandlePtr);
+ PVR_UNREFERENCED_PARAMETER(bForcePersistent);
+ return PVRSRV_OK;
+}
+
+static INLINE IMG_VOID
+PDumpPMRMallocPMR(const PMR *psPMR,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiBlockSize,
+ IMG_BOOL bForcePersistent,
+ IMG_HANDLE *phPDumpAllocInfoPtr)
+{
+ PVR_UNREFERENCED_PARAMETER(psPMR);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
+ PVR_UNREFERENCED_PARAMETER(uiBlockSize);
+ PVR_UNREFERENCED_PARAMETER(bForcePersistent);
+ PVR_UNREFERENCED_PARAMETER(phPDumpAllocInfoPtr);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSyncPrimPDumpPolKM)
+#endif
+static INLINE PVRSRV_ERROR
+PDumpPMRFree(IMG_HANDLE hPDumpAllocationInfoHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(hPDumpAllocationInfoHandle);
+ return PVRSRV_OK;
+}
+#endif /* PDUMP */
+
+#define PMR_DEFAULT_PREFIX "PMR"
+#define PMR_SYMBOLICADDR_FMTSPEC "%s%llu"
+
+#if defined(PDUMP)
+#define PDUMP_PHYSMEM_MALLOC_OSPAGES(pszPDumpMemDevName, ui32SerialNum, ui32Size, ui32Align, phHandlePtr) \
+ PDumpPMRMalloc(pszPDumpMemDevName, PMR_OSALLOCPAGES_PREFIX, ui32SerialNum, ui32Size, ui32Align, phHandlePtr)
+#define PDUMP_PHYSMEM_FREE_OSPAGES(hHandle) \
+ PDumpPMRFree(hHandle)
+#else
+#define PDUMP_PHYSMEM_MALLOC_OSPAGES(pszPDumpMemDevName, ui32SerialNum, ui32Size, ui32Align, phHandlePtr) \
+ ((IMG_VOID)(*phHandlePtr=IMG_NULL))
+#define PDUMP_PHYSMEM_FREE_OSPAGES(hHandle) \
+ ((IMG_VOID)(0))
+#endif // defined(PDUMP)
+
+extern PVRSRV_ERROR
+PDumpPMRWRW32(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+extern PVRSRV_ERROR
+PDumpPMRWRW64(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT64 ui64Value,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+extern PVRSRV_ERROR
+PDumpPMRLDB(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 uiFileOffset,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+extern PVRSRV_ERROR
+PDumpPMRSAB(const IMG_CHAR *pszDevSpace,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFileName,
+ IMG_UINT32 uiFileOffset);
+
+/*
+ PDumpPMRPOL()
+
+ emits a POL to the PDUMP.
+*/
+extern PVRSRV_ERROR
+PDumpPMRPOL(const IMG_CHAR *pszMempaceName,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 uiCount,
+ IMG_UINT32 uiDelay,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+extern PVRSRV_ERROR
+PDumpPMRCBP(const IMG_CHAR *pszMemspaceName,
+ const IMG_CHAR *pszSymbolicName,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize);
+
+/*
+ * PDumpWriteBuffer()
+ *
+ * writes a binary blob to the pdump param stream containing the
+ * current contents of the memory, and returns the filename and offset
+ * of where that blob is located (for use in a subsequent LDB, for
+ * example)
+ *
+ * Caller to provide buffer to receive filename, and declare the size
+ * of that buffer
+ */
+extern PVRSRV_ERROR
+PDumpWriteBuffer(IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiNumBytes,
+ PDUMP_FLAGS_T uiPDumpFlags,
+ IMG_CHAR *pszFilenameOut,
+ IMG_SIZE_T uiFilenameBufSz,
+ PDUMP_FILEOFFSET_T *puiOffsetOut);
+
+#endif /* #ifndef SRVSRV_PDUMP_PHYSMEM_H */
diff --git a/drivers/gpu/rogue/services/server/include/pdump_symbolicaddr.h b/drivers/gpu/rogue/services/server/include/pdump_symbolicaddr.h
new file mode 100644
index 000000000000..ed912a5096c9
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/pdump_symbolicaddr.h
@@ -0,0 +1,55 @@
+/**************************************************************************/ /*!
+@File
+@Title Abstraction of PDUMP symbolic address derivation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Allows pdump functions to derive symbolic addresses on-the-fly
+@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 SRVKM_PDUMP_SYMBOLICADDR_H
+#define SRVKM_PDUMP_SYMBOLICADDR_H
+
+#include "img_types.h"
+
+#include "pvrsrv_error.h"
+
+/* pdump symbolic addresses are generated on-the-fly with a callback */
+
+typedef PVRSRV_ERROR (*PVRSRV_SYMADDRFUNCPTR)(IMG_HANDLE hPriv, IMG_UINT32 uiOffset, IMG_CHAR *pszSymbolicAddr, IMG_UINT32 ui32SymbolicAddrLen, IMG_UINT32 *pui32NewOffset);
+
+#endif /* #ifndef SRVKM_PDUMP_SYMBOLICADDR_H */
diff --git a/drivers/gpu/rogue/services/server/include/physmem.h b/drivers/gpu/rogue/services/server/include/physmem.h
new file mode 100644
index 000000000000..c7389c9ddbd9
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/physmem.h
@@ -0,0 +1,102 @@
+/*************************************************************************/ /*!
+@File
+@Title Physmem header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for common entry point for creation of RAM backed PMR's
+@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 _SRVSRV_PHYSMEM_H_
+#define _SRVSRV_PHYSMEM_H_
+
+/* include/ */
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+
+/* services/server/include/ */
+#include "pmr.h"
+#include "pmr_impl.h"
+
+/*
+ * PhysmemNewRamBackedPMR
+ *
+ * This function will create a RAM backed PMR using the device specific
+ * callback, this allows control at a per-devicenode level to select the
+ * memory source thus supporting mixed UMA/LMA systems.
+ *
+ * The size must be a multiple of page size. The page size is
+ * specified in log2. It should be regarded as a minimum contiguity
+ * of which the that the resulting memory must be a multiple. It may
+ * be that this should be a fixed number. It may be that the
+ * allocation size needs to be a multiple of some coarser "page size"
+ * than that specified in the page size argument. For example, take
+ * an OS whose page granularity is a fixed 16kB, but the caller
+ * requests memory in page sizes of 4kB. The request can be satisfied
+ * if and only if the SIZE requested is a multiple of 16kB. If the
+ * arguments supplied are such that this OS cannot grant the request,
+ * PVRSRV_ERROR_INVALID_PARAMS will be returned.
+ *
+ * The caller should supply storage of a pointer. Upon successful
+ * return a PMR object will have been created and a pointer to it
+ * returned in the PMROut argument.
+ *
+ * A PMR thusly created should be destroyed with PhysmemUnrefPMR.
+ *
+ * Note that this function may cause memory allocations and on some
+ * OSes this may cause scheduling events, so it is important that this
+ * function be called with interrupts enabled and in a context where
+ * scheduling events and memory allocations are permitted.
+ *
+ * The flags may be used by the implementation to change its behaviour
+ * if required. The flags will also be stored in the PMR as immutable
+ * metadata and returned to mmu_common when it asks for it.
+ *
+ */
+extern PVRSRV_ERROR
+PhysmemNewRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMROut);
+
+#endif /* _SRVSRV_PHYSMEM_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/physmem_dmabuf.h b/drivers/gpu/rogue/services/server/include/physmem_dmabuf.h
new file mode 100644
index 000000000000..0996afdb67db
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/physmem_dmabuf.h
@@ -0,0 +1,63 @@
+/**************************************************************************/ /*!
+@File physmem_dmabuf.h
+@Title Header for dmabuf PMR factory
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is responsible for
+ implementing the function callbacks importing Ion allocations
+@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 _PHYSMEM_DMABUF_H_
+#define _PHYSMEM_DMABUF_H_
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+#include "connection_server.h"
+
+#include "pmr.h"
+
+PVRSRV_ERROR
+PhysmemImportDmaBuf(CONNECTION_DATA *psConnection,
+ IMG_INT fd,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr,
+ IMG_DEVMEM_SIZE_T *puiSize,
+ IMG_DEVMEM_ALIGN_T *puiAlign);
+
+#endif /* _PHYSMEM_DMABUF_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/physmem_lma.h b/drivers/gpu/rogue/services/server/include/physmem_lma.h
new file mode 100644
index 000000000000..c51970b207b2
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/physmem_lma.h
@@ -0,0 +1,74 @@
+/**************************************************************************/ /*!
+@File
+@Title Header for local card memory allocator
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is responsible for
+ implementing the function callbacks for local card memory.
+@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 _SRVSRV_PHYSMEM_LMA_H_
+#define _SRVSRV_PHYSMEM_LMA_H_
+
+/* include/ */
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+
+/* services/server/include/ */
+#include "pmr.h"
+#include "pmr_impl.h"
+
+/*
+ * PhysmemNewLocalRamBackedPMR
+ *
+ * This function will create a PMR using the local card memory and is OS
+ * agnostic.
+ */
+PVRSRV_ERROR
+PhysmemNewLocalRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr);
+
+#endif /* #ifndef _SRVSRV_PHYSMEM_LMA_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/physmem_osmem.h b/drivers/gpu/rogue/services/server/include/physmem_osmem.h
new file mode 100644
index 000000000000..706c859d8d02
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/physmem_osmem.h
@@ -0,0 +1,114 @@
+/**************************************************************************/ /*!
+@File
+@Title PMR implementation of OS derived physical memory
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is
+ responsible for the an implementation of the "PMR"
+ abstraction. This interface is for the
+ PhysmemNewOSRamBackedPMR() "PMR Factory" which is
+ responsible for claiming chunks of memory (in
+ particular physically contiguous quanta) from the
+ Operating System.
+
+ As such, this interface will be implemented on a
+ Per-OS basis, in the "env" directory for that system.
+ A dummy implementation is available in
+ physmem_osmem_dummy.c for operating systems that
+ cannot, or do not wish to, offer this 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 _SRVSRV_PHYSMEM_OSMEM_H_
+#define _SRVSRV_PHYSMEM_OSMEM_H_
+
+/* include/ */
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+
+/* services/server/include/ */
+#include "pmr.h"
+#include "pmr_impl.h"
+
+/*
+ * PhysmemNewOSRamBackedPMR
+ *
+ * To be overridden on a per-OS basis.
+ *
+ * This function will create a PMR using the default "OS supplied" physical pages
+ * method, assuming such is available on a particular operating system. (If not,
+ * PVRSRV_ERROR_NOT_SUPPORTED should be returned)
+ */
+extern PVRSRV_ERROR
+PhysmemNewOSRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMROut);
+
+/*
+ * PhysmemNewTDMetaCodePMR
+ *
+ * This function is used as part of the facility to provide secure META firmware
+ * memory. A default implementation is provided which must be replaced by the SoC
+ * implementor.
+ *
+ * Calling this function will return a PMR for a memory allocation made in "secure
+ * META code memory". It will only be writable by a hypervisor, and when the feature
+ * is enabled on the SoC, the META will only be able to perform instruction reads from
+ * memory that is secured that way.
+ */
+PVRSRV_ERROR
+PhysmemNewTDMetaCodePMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr);
+
+PVRSRV_ERROR
+PhysmemNewTDSecureBufPMR(PVRSRV_DEVICE_NODE *psDevNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 uiLog2PageSize,
+ PVRSRV_MEMALLOCFLAGS_T uiFlags,
+ PMR **ppsPMRPtr);
+
+
+#endif /* #ifndef _SRVSRV_PHYSMEM_OSMEM_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/pmr.h b/drivers/gpu/rogue/services/server/include/pmr.h
new file mode 100644
index 000000000000..f7ffaa825617
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/pmr.h
@@ -0,0 +1,813 @@
+/**************************************************************************/ /*!
+@File
+@Title Physmem (PMR) abstraction
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This module is responsible for
+ the "PMR" abstraction. A PMR (Physical Memory Resource)
+ represents some unit of physical memory which is
+ allocated/freed/mapped/unmapped as an indivisible unit
+ (higher software levels provide an abstraction above that
+ to deal with dividing this down into smaller manageable units).
+ Importantly, this module knows nothing of virtual memory, or
+ of MMUs etc., with one excuseable exception. We have the
+ concept of a "page size", which really means nothing in
+ physical memory, but represents a "contiguity quantum" such
+ that the higher level modules which map this memory are able
+ to verify that it matches the needs of the page size for the
+ virtual realm into which it is being mapped.
+@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 _SRVSRV_PMR_H_
+#define _SRVSRV_PMR_H_
+
+/* include/ */
+#include "img_types.h"
+#include "pdumpdefs.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+#include "devicemem_typedefs.h" /* Required for export DEVMEM_EXPORTCOOKIE */
+
+/* services/include */
+#include "pdump.h"
+
+/* services/server/include/ */
+#include "pmr_impl.h"
+#include "physheap.h"
+/* A typical symbolic address for physical memory may look like:
+ :MEMORYSPACE:SUBSYS_NNNNNN_0X1234567890_XYZ. That example is quite
+ extreme, they are likely shorter than that. We'll make the define
+ here plentiful, however, note that this is _advisory_ not
+ _mandatory_ - in other words, it's the allocator's responsibility
+ to choose the amount of memory to set aside, and it's up to us to
+ honour the size passed in by the caller. i.e. this define is for
+ GUIDANCE ONLY.
+*/
+#define PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT (60)
+#define PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT (20)
+#define PMR_MAX_MEMSPNAME_SYMB_ADDR_LENGTH_DEFAULT (PMR_MAX_SYMBOLIC_ADDRESS_LENGTH_DEFAULT + PMR_MAX_MEMSPACE_NAME_LENGTH_DEFAULT)
+#define PMR_MAX_PARAMSTREAM_FILENAME_LENGTH_DEFAULT (100)
+
+typedef IMG_UINT64 PMR_BASE_T;
+typedef IMG_UINT64 PMR_SIZE_T;
+#define PMR_SIZE_FMTSPEC "0x%010llX"
+#define PMR_VALUE32_FMTSPEC "0x%08X"
+#define PMR_VALUE64_FMTSPEC "0x%016llX"
+typedef IMG_UINT32 PMR_LOG2ALIGN_T;
+typedef IMG_UINT64 PMR_PASSWORD_T;
+
+typedef struct _PMR_ PMR;
+typedef struct _PMR_EXPORT_ PMR_EXPORT;
+
+typedef struct _PMR_PAGELIST_ PMR_PAGELIST;
+
+struct _PVRSRV_DEVICE_NODE_;
+
+/*
+ * PMRCreatePMR
+ *
+ * Not to be called directly, only via implementations of PMR
+ * factories, e.g. in physmem_osmem.c, deviceclass.c, etc.
+ *
+ * Creates a PMR object, with callbacks and private data as per the
+ * FuncTab/PrivData args.
+ *
+ * Note that at creation time the PMR must set in stone the "logical
+ * size" and the "contiguity guarantee"
+ *
+ * Flags are also set at this time. (T.B.D. flags also immutable for
+ * the life of the PMR?)
+ *
+ * Logical size is the amount of Virtual space this allocation would
+ * take up when mapped. Note that this does not have to be the same
+ * as the actual physical size of the memory. For example, consider
+ * the sparsely allocated non-power-of-2 texture case. In this
+ * instance, the "logical size" would be the virtual size of the
+ * rounded-up power-of-2 texture. That some pages of physical memory
+ * may not exist does not affect the logical size calculation.
+ *
+ * The PMR must also supply the "contiguity guarantee" which is the
+ * finest granularity of alignment and size of physical pages that the
+ * PMR will provide after LockSysPhysAddresses is called. Note that
+ * the calling code may choose to call PMRSysPhysAddr with a finer
+ * granularity than this, for example if it were to map into a device
+ * MMU with a smaller page size, and it's also OK for the PMR to
+ * supply physical memory in larger chunks than this. But
+ * importantly, never the other way around.
+ *
+ * More precisely, the following inequality must be maintained
+ * whenever mappings and/or physical addresses exist:
+ *
+ * (device MMU page size) <= 2**(uiLog2ContiguityGuarantee) <= (actual contiguity of physical memory)
+ *
+ *
+ * Note also that the implementation may supply pszPDumpFlavour and
+ * pszPDumpDefaultMemspaceName, which are irrelevant where the PMR
+ * implementation overrides the default symbolic name construction
+ * routine. Where the function pointer for PDump symbolic name
+ * derivation is not overridden (i.e. IMG_NULL appears in the relevant
+ * entry of the functab) and default implementation shall be used
+ * which will copy the PDumpDefaultMemspaceName into the namespace
+ * argument, and create the symbolic name by concatenating the
+ * "PDumpFlavour" and a numeric representation of the PMR's serial
+ * number.
+ *
+ * The implementation must guarantee that the storage for these two
+ * strings, and the function table, are maintained, as copies are not
+ * made, the pointer is simply stored.
+ *
+ * The function table will contain the following callbacks which may
+ * be overridden by the PMR implementation:
+ *
+ * pfnLockPhysAddresses
+ *
+ * Called when someone locks requests that Physical pages are to
+ * be locked down via the PMRLockSysPhysAddresses() API. Note
+ * that if physical pages are prefaulted at PMR creation time and
+ * therefore static, it would not be necessary to override this
+ * function, in which case IMG_NULL may be supplied.
+ *
+ * pfnUnlockPhysAddresses
+ *
+ * The reverse of pfnLockPhysAddresses. Note that this should be
+ * IMG_NULL if and only if pfnLockPhysAddresses is IMG_NULL
+ *
+ * pfnSysPhysAddr
+ *
+ * This function is mandatory. This is the one which returns the
+ * system physical address for a given offset into this PMR. The
+ * "lock" function will have been called, if overridden, before
+ * this function, thus the implementation should not increase any
+ * refcount when answering this call. Refcounting, if necessary,
+ * should be done in the lock/unlock calls. Refcounting would
+ * not be necessary in the prefaulted/static scenario, as the
+ * pmr.c abstraction will handle the refcounting for the whole
+ * PMR.
+ *
+ * pfnPDumpSymbolicAddr
+ *
+ * Derives the PDump symbolic address for the given offset. The
+ * default implementation will copy the PDumpDefaultMemspaceName
+ * into the namespace argument (or use SYSMEM if none was
+ * supplied), and create the symbolic name by concatenating the
+ * "PDumpFlavour" and a numeric representation of the PMR's
+ * serial number.
+ *
+ * pfnFinalize
+ *
+ * Called when the PMR's refcount reaches zero and it gets
+ * destroyed. This allows the implementation to free up any
+ * resource acquired during creation time.
+ *
+ */
+extern PVRSRV_ERROR
+PMRCreatePMR(PHYS_HEAP *psPhysHeap,
+ PMR_SIZE_T uiLogicalSize,
+ PMR_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ PMR_LOG2ALIGN_T uiLog2ContiguityGuarantee,
+ PMR_FLAGS_T uiFlags,
+ const IMG_CHAR *pszPDumpFlavour,
+ const PMR_IMPL_FUNCTAB *psFuncTab,
+ PMR_IMPL_PRIVDATA pvPrivData,
+ PMR **ppsPMRPtr,
+ IMG_HANDLE *phPDumpAllocInfo,
+ IMG_BOOL bForcePersistent);
+
+/*
+ * PMRLockSysPhysAddresses()
+ *
+ * Calls the relevant callback to lock down the system physical addresses of the memory that makes up the whole PMR.
+ *
+ * Before this call, it is not valid to use any of the information
+ * getting APIs: PMR_Flags(), PMR_SysPhysAddr(),
+ * PMR_PDumpSymbolicAddr() [ see note below about lock/unlock
+ * semantics ]
+ *
+ * The caller of this function does not have to care about how the PMR
+ * is implemented. He only has to know that he is allowed access to
+ * the physical addresses _after_ calling this function and _until_
+ * calling PMRUnlockSysPhysAddresses().
+ *
+ *
+ * Notes to callback implementers (authors of PMR Factories):
+ *
+ * Some PMR implementations will be such that the physical memory
+ * exists for the lifetime of the PMR, with a static address, (and
+ * normally flags and symbolic address are static too) and so it is
+ * legal for a PMR implementation to not provide an implementation for
+ * the lock callback.
+ *
+ * Some PMR implementation may wish to page memory in from secondary
+ * storage on demand. The lock/unlock callbacks _may_ be the place to
+ * do this. (more likely, there would be a separate API for doing
+ * this, but this API provides a useful place to assert that it has
+ * been done)
+ */
+
+extern PVRSRV_ERROR
+PMRLockSysPhysAddresses(PMR *psPMR,
+ IMG_UINT32 uiLog2DevPageSize);
+
+extern PVRSRV_ERROR
+PMRLockSysPhysAddressesNested(PMR *psPMR,
+ IMG_UINT32 uiLog2DevPageSize,
+ IMG_UINT32 ui32NestingLevel);
+
+/*
+ * PMRUnlockSysPhysAddresses()
+ *
+ * the reverse of PMRLockSysPhysAddresses()
+ */
+extern PVRSRV_ERROR
+PMRUnlockSysPhysAddresses(PMR *psPMR);
+
+IMG_VOID PMRLock(void);
+IMG_VOID PMRUnlock(void);
+IMG_BOOL PMRIsLocked(void);
+IMG_BOOL PMRIsLockedByMe(void);
+
+/*
+ * PhysmemPMRExport()
+ *
+ * Given a PMR, creates a PMR "Export", which is a handle that
+ * provides sufficient data to be able to "import" this PMR elsewhere.
+ * The PMR Export is an object in its own right, whose existance
+ * implies a reference on the PMR, thus the PMR cannot be destroyed
+ * while the PMR Export exists. The intention is that the PMR Export
+ * will be wrapped in the devicemem layer by a cross process handle,
+ * and some IPC by which to communicate the handle value and password
+ * to other processes. The receiving process is able to unwrap this
+ * to gain access to the same PMR Export in this layer, and, via
+ * PhysmemPMRImport(), obtain a reference to the original PMR.
+ *
+ * The caller receives, along with the PMR Export object, information
+ * about the size and contiguity guarantee for the PMR, and also the
+ * PMRs secret password, in order to authenticate the subsequent
+ * import.
+ *
+ * N.B. If you call PMRExportPMR() (and it succeeds), you are
+ * promising to later call PMRUnexportPMR()
+ */
+extern PVRSRV_ERROR
+PMRExportPMR(PMR *psPMR,
+ PMR_EXPORT **ppsPMRExport,
+ PMR_SIZE_T *puiSize,
+ PMR_LOG2ALIGN_T *puiLog2Contig,
+ PMR_PASSWORD_T *puiPassword);
+
+/*
+ * PMRMakeServerExportClientExport()
+ *
+ * This is a "special case" function for making a server export cookie
+ * which went through the direct bridge into an export cookie that can
+ * be passed through the client bridge.
+ */
+PVRSRV_ERROR
+PMRMakeServerExportClientExport(DEVMEM_EXPORTCOOKIE *psPMRExportIn,
+ PMR_EXPORT **ppsPMRExportPtr,
+ PMR_SIZE_T *puiSize,
+ PMR_LOG2ALIGN_T *puiLog2Contig,
+ PMR_PASSWORD_T *puiPassword);
+
+PVRSRV_ERROR
+PMRUnmakeServerExportClientExport(PMR_EXPORT *psPMRExport);
+
+/*
+ * PMRUnexporPMRt()
+ *
+ * The reverse of PMRExportPMR(). This causes the PMR to no
+ * longer be exported. If the PMR has already been imported, the
+ * imported PMR reference will still be valid, but no further imports
+ * will be possible.
+ */
+extern PVRSRV_ERROR
+PMRUnexportPMR(PMR_EXPORT *psPMRExport);
+
+/*
+ * PMRImportPMR()
+ *
+ * Takes a PMR Export object, as obtained by PMRExportPMR(), and
+ * obtains a reference to the original PMR.
+ *
+ * The password must match, and is assumed to have been (by whatever
+ * means, IPC etc.) preserved intact from the former call to
+ * PMRExportPMR()
+ *
+ * The size and contiguity arguments are entirely irrelevant for the
+ * import, however they are verified in order to trap bugs.
+ *
+ * N.B. If you call PhysmemPMRImport() (and it succeeds), you are
+ * promising to later call PhysmemPMRUnimport()
+ */
+extern PVRSRV_ERROR
+PMRImportPMR(PMR_EXPORT *psPMRExport,
+ PMR_PASSWORD_T uiPassword,
+ PMR_SIZE_T uiSize,
+ PMR_LOG2ALIGN_T uiLog2Contig,
+ PMR **ppsPMR);
+
+/*
+ * PMRUnimportPMR()
+ *
+ * releases the reference on the PMR as obtained by PMRImportPMR()
+ */
+extern PVRSRV_ERROR
+PMRUnimportPMR(PMR *psPMR);
+
+PVRSRV_ERROR
+PMRLocalImportPMR(PMR *psPMR,
+ PMR **ppsPMR,
+ IMG_DEVMEM_SIZE_T *puiSize,
+ IMG_DEVMEM_ALIGN_T *puiAlign);
+
+/*
+ * Equivalent mapping functions when in kernel mode - TOOD: should
+ * unify this and the PMRAcquireMMapArgs API with a suitable
+ * abstraction
+ */
+extern PVRSRV_ERROR
+PMRAcquireKernelMappingData(PMR *psPMR,
+ IMG_SIZE_T uiLogicalOffset,
+ IMG_SIZE_T uiSize,
+ IMG_VOID **ppvKernelAddressOut,
+ IMG_SIZE_T *puiLengthOut,
+ IMG_HANDLE *phPrivOut);
+extern PVRSRV_ERROR
+PMRReleaseKernelMappingData(PMR *psPMR,
+ IMG_HANDLE hPriv);
+
+
+/*
+ * PMR_ReadBytes()
+ *
+ * calls into the PMR implementation to read up to uiBufSz bytes,
+ * returning the actual number read in *puiNumBytes
+ *
+ * this will read up to the end of the PMR, or the next symbolic name
+ * boundary, or until the requested number of bytes is read, whichever
+ * comes first
+ *
+ * In the case of sparse PMR's the caller doesn't know what offsets are
+ * valid and which ones aren't so we will just write 0 to invalid offsets
+ */
+extern PVRSRV_ERROR
+PMR_ReadBytes(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes);
+
+/*
+ * PMR_WriteBytes()
+ *
+ * calls into the PMR implementation to write up to uiBufSz bytes,
+ * returning the actual number read in *puiNumBytes
+ *
+ * this will write up to the end of the PMR, or the next symbolic name
+ * boundary, or until the requested number of bytes is written, whichever
+ * comes first
+ *
+ * In the case of sparse PMR's the caller doesn't know what offsets are
+ * valid and which ones aren't so we will just ignore data at invalid offsets
+ */
+extern PVRSRV_ERROR
+PMR_WriteBytes(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes);
+
+/*
+ * PMRRefPMR()
+ *
+ * Take a reference on the passed in PMR
+ */
+extern IMG_VOID
+PMRRefPMR(PMR *psPMR);
+
+/*
+ * PMRUnrefPMR()
+ *
+ * This undoes a call to any of the PhysmemNew* family of APIs
+ * (i.e. any PMR factory "constructor")
+ *
+ * This relinquishes a reference to the PMR, and, where the refcount
+ * reaches 0, causes the PMR to be destroyed (calling the finalizer
+ * callback on the PMR, if there is one)
+ */
+extern PVRSRV_ERROR
+PMRUnrefPMR(PMR *psPMR);
+
+
+/*
+ * PMR_Flags()
+ *
+ * Flags are static and guaranteed for the life of the PMR. Thus this
+ * function is idempotent and acquire/release semantics is not
+ * required.
+ *
+ * Returns the flags as specified on the PMR. The flags are to be
+ * interpreted as mapping permissions
+ */
+extern PVRSRV_ERROR
+PMR_Flags(const PMR *psPMR,
+ PMR_FLAGS_T *puiMappingFlags);
+
+extern PVRSRV_ERROR
+PMR_LogicalSize(const PMR *psPMR,
+ IMG_DEVMEM_SIZE_T *puiLogicalSize);
+
+/*
+ * PMR_SysPhysAddr()
+ *
+ * A note regarding Lock/Unlock semantics
+ * ======================================
+ *
+ * PMR_SysPhysAddr may only be called after PMRLockSysPhysAddresses()
+ * has been called. The data returned may be used only until
+ * PMRUnlockSysPhysAddresses() is called after which time the licence
+ * to use the data is revoked and the information may be invalid.
+ *
+ * Given an offset, this function returns the device physical address of the
+ * corresponding page in the PMR. It may be called multiple times
+ * until the address of all relevant pages has been determined.
+ *
+ */
+extern PVRSRV_ERROR
+PMR_DevPhysAddr(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_DEV_PHYADDR *psDevAddr,
+ IMG_BOOL *pbValid);
+
+/*
+ * PMR_CpuPhysAddr()
+ *
+ * See note above about Lock/Unlock semantics.
+ *
+ * Given an offset, this function returns the CPU physical address of the
+ * corresponding page in the PMR. It may be called multiple times
+ * until the address of all relevant pages has been determined.
+ *
+ */
+extern PVRSRV_ERROR
+PMR_CpuPhysAddr(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_CPU_PHYADDR *psCpuAddrPtr,
+ IMG_BOOL *pbValid);
+
+PVRSRV_ERROR
+PMRGetUID(PMR *psPMR,
+ IMG_UINT64 *pui64UID);
+
+#if defined(PDUMP)
+/*
+ * PMR_PDumpSymbolicAddr()
+ *
+ * Given an offset, returns the pdump memspace name and symbolic
+ * address of the corresponding page in the PMR.
+ *
+ * Note that PDump memspace names and symbolic addresses are static
+ * and valid for the lifetime of the PMR, therefore we don't require
+ * acquire/release semantics here.
+ *
+ * Note that it is expected that the pdump "mapping" code will call
+ * this function multiple times as each page is mapped in turn
+ *
+ * Note that NextSymName is the offset from the base of the PMR to the
+ * next pdump symbolic address (or the end of the PMR if the PMR only
+ * had one PDUMPMALLOC
+ */
+extern PVRSRV_ERROR
+PMR_PDumpSymbolicAddr(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT32 ui32NamespaceNameLen,
+ IMG_CHAR *pszNamespaceName,
+ IMG_UINT32 ui32SymbolicAddrLen,
+ IMG_CHAR *pszSymbolicAddr,
+ IMG_DEVMEM_OFFSET_T *puiNewOffset,
+ IMG_DEVMEM_OFFSET_T *puiNextSymName
+ );
+
+/*
+ * PMRPDumpLoadMemValue32()
+ *
+ * writes the current contents of a dword in PMR memory to the pdump
+ * script stream. Useful for patching a buffer by simply editing the
+ * script output file in ASCII plain text.
+ *
+ */
+extern PVRSRV_ERROR
+PMRPDumpLoadMemValue32(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT32 ui32Value,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+/*
+ * PMRPDumpLoadMemValue64()
+ *
+ * writes the current contents of a dword in PMR memory to the pdump
+ * script stream. Useful for patching a buffer by simply editing the
+ * script output file in ASCII plain text.
+ *
+ */
+extern PVRSRV_ERROR
+PMRPDumpLoadMemValue64(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT64 ui64Value,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+/*
+ * PMRPDumpLoadMem()
+ *
+ * writes the current contents of the PMR memory to the pdump PRM
+ * stream, and emits some PDump code to the script stream to LDB said
+ * bytes from said file. If bZero is IMG_TRUE then the PDump zero page
+ * is used as the source for the LDB.
+ *
+ */
+extern PVRSRV_ERROR
+PMRPDumpLoadMem(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ PDUMP_FLAGS_T uiPDumpFlags,
+ IMG_BOOL bZero);
+
+/*
+ * PMRPDumpSaveToFile()
+ *
+ * emits some PDump that does an SAB (save bytes) using the PDump
+ * symbolic address of the PMR. Note that this is generally not the
+ * preferred way to dump the buffer contents. There is an equivalent
+ * function in devicemem_server.h which also emits SAB but using the
+ * virtual address, which is the "right" way to dump the buffer
+ * contents to a file. This function exists just to aid testing by
+ * providing a means to dump the PMR directly by symbolic address
+ * also.
+ */
+extern PVRSRV_ERROR
+PMRPDumpSaveToFile(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 uiArraySize,
+ const IMG_CHAR *pszFilename);
+#else /* PDUMP */
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PMR_PDumpSymbolicAddr)
+#endif
+static INLINE PVRSRV_ERROR
+PMR_PDumpSymbolicAddr(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT32 ui32NamespaceNameLen,
+ IMG_CHAR *pszNamespaceName,
+ IMG_UINT32 ui32SymbolicAddrLen,
+ IMG_CHAR *pszSymbolicAddr,
+ IMG_DEVMEM_OFFSET_T *puiNewOffset,
+ IMG_DEVMEM_OFFSET_T *puiNextSymName)
+{
+ PVR_UNREFERENCED_PARAMETER(psPMR);
+ PVR_UNREFERENCED_PARAMETER(uiLogicalOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32NamespaceNameLen);
+ PVR_UNREFERENCED_PARAMETER(pszNamespaceName);
+ PVR_UNREFERENCED_PARAMETER(ui32SymbolicAddrLen);
+ PVR_UNREFERENCED_PARAMETER(pszSymbolicAddr);
+ PVR_UNREFERENCED_PARAMETER(puiNewOffset);
+ PVR_UNREFERENCED_PARAMETER(puiNextSymName);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PMRPDumpLoadMemValue)
+#endif
+static INLINE PVRSRV_ERROR
+PMRPDumpLoadMemValue32(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT32 ui32Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psPMR);
+ PVR_UNREFERENCED_PARAMETER(uiLogicalOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PMRPDumpLoadMemValue)
+#endif
+static INLINE PVRSRV_ERROR
+PMRPDumpLoadMemValue64(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT64 ui64Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psPMR);
+ PVR_UNREFERENCED_PARAMETER(uiLogicalOffset);
+ PVR_UNREFERENCED_PARAMETER(ui64Value);
+ PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PMRPDumpLoadMem)
+#endif
+static INLINE PVRSRV_ERROR
+PMRPDumpLoadMem(PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ PDUMP_FLAGS_T uiPDumpFlags,
+ IMG_BOOL bZero)
+{
+ PVR_UNREFERENCED_PARAMETER(psPMR);
+ PVR_UNREFERENCED_PARAMETER(uiLogicalOffset);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
+ PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+ PVR_UNREFERENCED_PARAMETER(bZero);
+ return PVRSRV_OK;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PMRPDumpSaveToFile)
+#endif
+static INLINE PVRSRV_ERROR
+PMRPDumpSaveToFile(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_UINT32 uiArraySize,
+ const IMG_CHAR *pszFilename)
+{
+ PVR_UNREFERENCED_PARAMETER(psPMR);
+ PVR_UNREFERENCED_PARAMETER(uiLogicalOffset);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
+ PVR_UNREFERENCED_PARAMETER(uiArraySize);
+ PVR_UNREFERENCED_PARAMETER(pszFilename);
+ return PVRSRV_OK;
+}
+
+#endif /* PDUMP */
+
+/* This function returns the private data that a pmr subtype
+ squirrelled in here. We use the function table pointer as
+ "authorization" that this function is being called by the pmr
+ subtype implementation. We can assume (assert) that. It would be
+ a bug in the implementation of the pmr subtype if this assertion
+ ever fails. */
+extern IMG_VOID *
+PMRGetPrivateDataHack(const PMR *psPMR,
+ const PMR_IMPL_FUNCTAB *psFuncTab);
+
+extern PVRSRV_ERROR
+PMRZeroingPMR(PMR *psPMR,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize);
+
+PVRSRV_ERROR
+PMRDumpPageList(PMR *psReferencePMR,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize);
+
+extern PVRSRV_ERROR
+PMRWritePMPageList(/* Target PMR, offset, and length */
+ PMR *psPageListPMR,
+ IMG_DEVMEM_OFFSET_T uiTableOffset,
+ IMG_DEVMEM_SIZE_T uiTableLength,
+ /* Referenced PMR, and "page" granularity */
+ PMR *psReferencePMR,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize,
+ PMR_PAGELIST **ppsPageList,
+ IMG_UINT64 *pui64CheckSum);
+
+/* Doesn't actually erase the page list - just releases the appropriate refcounts */
+extern PVRSRV_ERROR // should be IMG_VOID, surely
+PMRUnwritePMPageList(PMR_PAGELIST *psPageList);
+
+extern PVRSRV_ERROR
+PMRWriteVFPPageList(/* Target PMR, offset, and length */
+ PMR *psPageListPMR,
+ IMG_DEVMEM_OFFSET_T uiTableOffset,
+ IMG_DEVMEM_SIZE_T uiTableLength,
+ IMG_UINT32 ui32TableBase,
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize);
+
+#if defined(PDUMP)
+extern PVRSRV_ERROR
+PMRPDumpPol32(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiFlags);
+
+extern PVRSRV_ERROR
+PMRPDumpCBP(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize);
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PMRPDumpPol32)
+#endif
+static INLINE PVRSRV_ERROR
+PMRPDumpPol32(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiLogicalOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psPMR);
+ PVR_UNREFERENCED_PARAMETER(uiLogicalOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ PVR_UNREFERENCED_PARAMETER(ui32Mask);
+ PVR_UNREFERENCED_PARAMETER(eOperator);
+ PVR_UNREFERENCED_PARAMETER(uiFlags);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PMRPDumpCBP)
+#endif
+static INLINE PVRSRV_ERROR
+PMRPDumpCBP(const PMR *psPMR,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize)
+{
+ PVR_UNREFERENCED_PARAMETER(psPMR);
+ PVR_UNREFERENCED_PARAMETER(uiReadOffset);
+ PVR_UNREFERENCED_PARAMETER(uiWriteOffset);
+ PVR_UNREFERENCED_PARAMETER(uiPacketSize);
+ PVR_UNREFERENCED_PARAMETER(uiBufferSize);
+ return PVRSRV_OK;
+}
+#endif
+/*
+ * PMRInit()
+ *
+ * To be called once and only once to initialise the internal data in
+ * the PMR module (mutexes and such)
+ *
+ * Not for general use. Only PVRSRVInit(); should be calling this.
+ */
+extern PVRSRV_ERROR
+PMRInit(IMG_VOID);
+
+/*
+ * PMRDeInit()
+ *
+ * To be called once and only once to deinitialise the internal data in
+ * the PMR module (mutexes and such) and for debug checks
+ *
+ * Not for general use. Only PVRSRVDeInit(); should be calling this.
+ */
+extern PVRSRV_ERROR
+PMRDeInit(IMG_VOID);
+
+#if defined(PVR_RI_DEBUG)
+extern PVRSRV_ERROR
+PMRStoreRIHandle(PMR *psPMR,
+ IMG_PVOID hRIHandle);
+#endif
+
+#endif /* #ifdef _SRVSRV_PMR_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/pmr_impl.h b/drivers/gpu/rogue/services/server/include/pmr_impl.h
new file mode 100644
index 000000000000..577b6b07588a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/pmr_impl.h
@@ -0,0 +1,178 @@
+/**************************************************************************/ /*!
+@File
+@Title Implementation Callbacks for Physmem (PMR) abstraction
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Part of the memory management. This file is for definitions that
+ are private to the world of PMRs, but that needs to be shared between
+ pmr.c itself and the modules that implement the callbacks for the
+ PMR.
+@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 _SRVSRV_PMR_IMPL_H_
+#define _SRVSRV_PMR_IMPL_H_
+
+/* include/ */
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+/* stuff that per-flavour callbacks need to share with pmr.c */
+
+typedef IMG_VOID *PMR_IMPL_PRIVDATA;
+
+typedef PVRSRV_MEMALLOCFLAGS_T PMR_FLAGS_T;
+
+typedef struct {
+ /*
+ * LockPhysAddresses() and UnlockPhysAddresses()
+ *
+ * locks down the physical addresses for the whole PMR. If memory
+ * is "prefaulted", i.e. exists phsycally at PMR creation time,
+ * then there is no need to override this callback. The default
+ * implementation is to simply increment a lock-count for
+ * debugging purposes.
+ *
+ * If overridden, this function will be called when someone first
+ * requires a physical addresses, and the UnlockPhysAddresses()
+ * counterpart will be called when the last such reference is
+ * released.
+ *
+ * The PMR implementation may assume that physical addresses will
+ * have been "locked" in this manner before any call is made to
+ * the SysPhysAddr() callback
+ */
+ PVRSRV_ERROR (*pfnLockPhysAddresses)(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_UINT32 uiLog2DevPageSize);
+ PVRSRV_ERROR (*pfnUnlockPhysAddresses)(PMR_IMPL_PRIVDATA pvPriv);
+ /*
+ * called iteratively to obtain the physical address of each page
+ * in turn ("page" might be device mmu page, or host cpu mmu page,
+ * or something else entirely... the PMR implementation should
+ * make no assumption, and honour the request for a physical
+ * address of any byte in the PMR)
+ *
+ * [ it's the callers responsibility to ensure that no addresses
+ * are missed, by calling this at least as often as once per
+ * "1<<contiguityguarantee" ]
+ *
+ * the LockPhysAddresses callback (if overridden) is guaranteed to
+ * have been called prior to calling this one, and the caller
+ * promises not to rely on the physical address thus obtained
+ * after the UnlockPhysAddresses callback is called.
+ *
+ * Overriding this callback is mandatory in all PMR
+ * implementations.
+ */
+ PVRSRV_ERROR (*pfnDevPhysAddr)(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEV_PHYADDR *psDevAddrPtr);
+ /*
+ * called iteratively to obtain PDump symbolic addresses. Behaves
+ * just like SysPhysAddr callback, except for returning Symbolic
+ * Addresses.
+ *
+ * It is optional to override this callback. The default
+ * implementation will construct an address from the PMR type and
+ * serial number
+ */
+ PVRSRV_ERROR (*pfnPDumpSymbolicAddr)(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_CHAR *pszMemspaceName,
+ IMG_UINT32 ui32MemspaceNameLen,
+ IMG_CHAR *pszSymbolicAddr,
+ IMG_UINT32 ui32SymbolicAddrLen,
+ IMG_DEVMEM_OFFSET_T *puiNewOffset,
+ IMG_DEVMEM_OFFSET_T *puiNextSymName);
+ /*
+ * AcquireKernelMappingData()/ReleaseKernelMappingData()
+ *
+ * called to obtain a kernel virtual address for the PMR for use
+ * internally in services.
+ *
+ * It is not necessary to override this callback, but failure to
+ * do so will mean that kernel mappings will not be possible
+ */
+ PVRSRV_ERROR (*pfnAcquireKernelMappingData)(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ IMG_VOID **ppvKernelAddressOut,
+ IMG_HANDLE *phHandleOut,
+ PMR_FLAGS_T ulFlags);
+ IMG_VOID (*pfnReleaseKernelMappingData)(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_HANDLE hHandle);
+ /*
+ * Read up to uiBufSz bytes from the PMR.
+ * The pmr will be already locked.
+ *
+ * Overriding this is optional. The default implementation will
+ * acquire a kernel virtual address with
+ * pfnAcquireKernelMappingData and OSMemCopy the data directly
+ */
+ PVRSRV_ERROR (*pfnReadBytes)(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes);
+
+ /*
+ * Write up to uiBufSz bytes into the PMR.
+ * The pmr will be already locked.
+ *
+ * Overriding this is optional. The default implementation will
+ * acquire a kernel virtual address with
+ * pfnAcquireKernelMappingData and OSMemCopy the data directly
+ *
+ * Note:
+ * This function callback is optional and unlike pfnReadBytes
+ * isn't required if pfnAcquireKernelMappingData isn't provided
+ */
+ PVRSRV_ERROR (*pfnWriteBytes)(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT8 *pcBuffer,
+ IMG_SIZE_T uiBufSz,
+ IMG_SIZE_T *puiNumBytes);
+ /*
+ * Finalize()
+ *
+ * This callback will be called once when the last reference to
+ * the PMR has disappeared.
+ */
+ PVRSRV_ERROR (*pfnFinalize)(PMR_IMPL_PRIVDATA pvPriv);
+} PMR_IMPL_FUNCTAB;
+
+#endif /* of #ifndef _SRVSRV_PHYSMEM_PRIV_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/power.h b/drivers/gpu/rogue/services/server/include/power.h
new file mode 100644
index 000000000000..f08f5c6b71cd
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/power.h
@@ -0,0 +1,144 @@
+/*************************************************************************/ /*!
+@File
+@Title Power Management Functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for power management 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.
+*/ /**************************************************************************/
+#ifndef POWER_H
+#define POWER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "pvrsrv_device.h"
+
+/*!
+ *****************************************************************************
+ * Power management
+ *****************************************************************************/
+
+typedef struct _PVRSRV_POWER_DEV_TAG_
+{
+ PFN_PRE_POWER pfnDevicePrePower;
+ PFN_POST_POWER pfnDevicePostPower;
+ PFN_SYS_DEV_PRE_POWER pfnSystemPrePower;
+ PFN_SYS_DEV_POST_POWER pfnSystemPostPower;
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange;
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState;
+ struct _PVRSRV_POWER_DEV_TAG_ *psNext;
+ struct _PVRSRV_POWER_DEV_TAG_ **ppsThis;
+
+} PVRSRV_POWER_DEV;
+
+typedef enum _PVRSRV_INIT_SERVER_STATE_
+{
+ PVRSRV_INIT_SERVER_Unspecified = -1,
+ PVRSRV_INIT_SERVER_RUNNING = 0,
+ PVRSRV_INIT_SERVER_RAN = 1,
+ PVRSRV_INIT_SERVER_SUCCESSFUL = 2,
+ PVRSRV_INIT_SERVER_NUM = 3,
+ PVRSRV_INIT_SERVER_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_INIT_SERVER_STATE, *PPVRSRV_INIT_SERVER_STATE;
+
+IMG_IMPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState);
+
+
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVPowerLock(IMG_VOID);
+IMG_IMPORT IMG_VOID PVRSRVForcedPowerLock(IMG_VOID);
+IMG_IMPORT IMG_VOID PVRSRVPowerUnlock(IMG_VOID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_BOOL bForced);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM (PVRSRV_SYS_POWER_STATE ePVRState, IMG_BOOL bForced);
+
+/* Type PFN_DC_REGISTER_POWER */
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
+ PFN_PRE_POWER pfnDevicePrePower,
+ PFN_POST_POWER pfnDevicePostPower,
+ PFN_SYS_DEV_PRE_POWER pfnSystemPrePower,
+ PFN_SYS_DEV_POST_POWER pfnSystemPostPower,
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange,
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDevicePowerState(IMG_UINT32 ui32DeviceIndex, PPVRSRV_DEV_POWER_STATE pePowerState);
+
+IMG_IMPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo);
+
+IMG_IMPORT
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* POWER_H */
+
+/******************************************************************************
+ End of file (power.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/include/process_stats.h b/drivers/gpu/rogue/services/server/include/process_stats.h
new file mode 100644
index 000000000000..b0c3d50000f6
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/process_stats.h
@@ -0,0 +1,172 @@
+/*************************************************************************/ /*!
+@File
+@Title Functions for creating and reading proc filesystem entries.
+@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 __PROCESS_STATS_H__
+#define __PROCESS_STATS_H__
+
+#include "pvrsrv_error.h"
+
+/*
+ * The publishing of Process Stats is controlled by the
+ * PVRSRV_ENABLE_PROCESS_STATS build option. The recording of all Memory
+ * allocations is controlled by the PVRSRV_ENABLE_MEMORY_STATS build option.
+ *
+ * Note: There will be a performance degradation with memory allocation
+ * recording enabled!
+ */
+
+
+/*
+ * Memory types which can be tracked...
+ */
+typedef enum {
+ PVRSRV_MEM_ALLOC_TYPE_KMALLOC,
+ PVRSRV_MEM_ALLOC_TYPE_VMALLOC,
+ PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA, /* pages allocated from UMA to hold page table information */
+ PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA, /* ALLOC_PAGES_PT_UMA mapped to kernel address space */
+ PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA, /* pages allocated from LMA to hold page table information */
+ PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA, /* ALLOC_PAGES_PT_LMA mapped to kernel address space */
+ PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES, /* pages allocated from LMA */
+ PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES, /* pages allocated from UMA */
+ PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES, /* mapped UMA/LMA pages */
+
+ /* Must be the last enum...*/
+ PVRSRV_MEM_ALLOC_TYPE_COUNT
+} PVRSRV_MEM_ALLOC_TYPE;
+
+
+/*
+ * Functions for managing the processes recorded...
+ */
+PVRSRV_ERROR PVRSRVStatsInitialise(IMG_VOID);
+
+IMG_VOID PVRSRVStatsDestroy(IMG_VOID);
+
+PVRSRV_ERROR PVRSRVStatsRegisterProcess(IMG_HANDLE* phProcessStats);
+
+IMG_VOID PVRSRVStatsDeregisterProcess(IMG_HANDLE hProcessStats);
+
+#define MAX_POWER_STAT_ENTRIES 51
+
+/*
+ * Functions for recording the statistics...
+ */
+IMG_VOID PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_VOID *pvCpuVAddr,
+ IMG_CPU_PHYADDR sCpuPAddr,
+ IMG_SIZE_T uiBytes,
+ IMG_PVOID pvPrivateData);
+
+IMG_VOID PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_UINT64 ui64Key);
+
+IMG_VOID PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_SIZE_T uiBytes);
+
+/*
+ * Increases the memory stat for eAllocType. Tracks the allocation size value
+ * by inserting a value into a hash table with uiCpuVAddr as key.
+ * Pair with PVRSRVStatsDecrMemAllocStatAndUntrack().
+ */
+IMG_VOID PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_SIZE_T uiBytes,
+ IMG_UINT64 uiCpuVAddr);
+
+IMG_VOID PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_SIZE_T uiBytes);
+
+/*
+ * Decrease the memory stat for eAllocType. Takes the allocation size value from the
+ * hash table with uiCpuVAddr as key. Pair with PVRSRVStatsIncrMemAllocStatAndTrack().
+ */
+IMG_VOID PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE eAllocType,
+ IMG_UINT64 uiCpuVAddr);
+
+IMG_VOID PVRSRVStatsUpdateRenderContextStats(IMG_UINT32 ui32TotalNumPartialRenders,
+ IMG_UINT32 ui32TotalNumOutOfMemory,
+ IMG_UINT32 ui32TotalTAStores,
+ IMG_UINT32 ui32Total3DStores,
+ IMG_UINT32 ui32TotalSHStores,
+ IMG_UINT32 ui32TotalCDMStores,
+ IMG_PID owner);
+
+IMG_VOID PVRSRVStatsUpdateZSBufferStats(IMG_UINT32 ui32NumReqByApp,
+ IMG_UINT32 ui32NumReqByFW,
+ IMG_PID owner);
+
+IMG_VOID PVRSRVStatsUpdateFreelistStats(IMG_UINT32 ui32NumGrowReqByApp,
+ IMG_UINT32 ui32NumGrowReqByFW,
+ IMG_UINT32 ui32InitFLPages,
+ IMG_UINT32 ui32NumHighPages,
+ IMG_PID ownerPid);
+
+
+/*
+ * Functions for obtaining the information stored...
+ */
+IMG_BOOL PVRSRVStatsObtainElement(IMG_PVOID pvStatPtr,
+ IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData,
+ IMG_CHAR** ppszStatFmtText);
+
+IMG_BOOL PVRSRVPowerStatsObtainElement(IMG_PVOID pvStatPtr,
+ IMG_UINT32 ui32StatNumber,
+ IMG_INT32* pi32StatData,
+ IMG_CHAR** ppszStatFmtText);
+
+typedef enum
+{
+ PVRSRV_POWER_ENTRY_TYPE_PRE,
+ PVRSRV_POWER_ENTRY_TYPE_POST
+} PVRSRV_POWER_ENTRY_TYPE;
+
+IMG_VOID InsertPowerTimeStatistic(PVRSRV_POWER_ENTRY_TYPE bType,
+ IMG_INT32 ui32CurrentState, IMG_INT32 ui32NextState,
+ IMG_UINT64 ui64SysStartTime, IMG_UINT64 ui64SysEndTime,
+ IMG_UINT64 ui64DevStartTime, IMG_UINT64 ui64DevEndTime,
+ IMG_BOOL bForced);
+
+IMG_VOID SetFirmwareStartTime(IMG_UINT32 ui32TimeStamp);
+
+IMG_VOID SetFirmwareHandshakeIdleTime(IMG_UINT64 ui64Duration);
+
+#endif /* __PROCESS_STATS_H__ */
diff --git a/drivers/gpu/rogue/services/server/include/pvrsrv.h b/drivers/gpu/rogue/services/server/include/pvrsrv.h
new file mode 100644
index 000000000000..1a15a72de3f4
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/pvrsrv.h
@@ -0,0 +1,477 @@
+/**************************************************************************/ /*!
+@File
+@Title PowerVR services server header 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_H
+#define PVRSRV_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(KERNEL) && defined(ANDROID)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+
+#include "device.h"
+#include "resman.h"
+#include "power.h"
+#include "sysinfo.h"
+#include "physheap.h"
+
+typedef struct _SYS_DEVICE_ID_TAG
+{
+ IMG_UINT32 uiID;
+ IMG_BOOL bInUse;
+
+} SYS_DEVICE_ID;
+
+
+typedef struct PVRSRV_DATA_TAG
+{
+ IMG_UINT32 ui32NumDevices; /*!< number of devices in system */
+ SYS_DEVICE_ID sDeviceID[SYS_DEVICE_COUNT];
+ PVRSRV_DEVICE_NODE *apsRegisteredDevNodes[SYS_DEVICE_COUNT];
+ IMG_UINT32 ui32RegisteredDevices;
+ IMG_UINT32 ui32CurrentOSPowerState; /*!< current OS specific power state */
+ PVRSRV_DEVICE_NODE *psDeviceNodeList; /*!< List head of device nodes */
+ struct _DEVICE_COMMAND_DATA_ *apsDeviceCommandData[SYS_DEVICE_COUNT];
+
+ IMG_UINT32 ui32RegisteredPhysHeaps;
+ PHYS_HEAP *apsRegisteredPhysHeaps[SYS_PHYS_HEAP_COUNT];
+
+ PVRSRV_POWER_DEV *psPowerDeviceList; /*!< list of devices registered with the power manager */
+ POS_LOCK hPowerLock; /*!< lock for power state transitions */
+ PVRSRV_SYS_POWER_STATE eCurrentPowerState; /*!< current Kernel services power state */
+ PVRSRV_SYS_POWER_STATE eFailedPowerState; /*!< Kernel services power state (Failed to transition to) */
+
+ PVRSRV_SERVICES_STATE eServicesState; /*!< global driver state */
+
+ IMG_HANDLE hGlobalEventObject; /*!< OS Global Event Object */
+ IMG_UINT32 ui32GEOConsecutiveTimeouts; /*!< OS Global Event Object Timeouts */
+
+ PVRSRV_CACHE_OP uiCacheOp; /*!< Pending cache operations in the system */
+ PRESMAN_DEFER_CONTEXTS_LIST hResManDeferContext; /*!< Device driver global deferred resman contexts list */
+
+ IMG_HANDLE hCleanupThread; /*!< Cleanup thread */
+ IMG_HANDLE hCleanupEventObject; /*!< Event object to drive cleanup thread */
+
+ IMG_HANDLE hDevicesWatchdogThread; /*!< Devices Watchdog thread */
+ IMG_HANDLE hDevicesWatchdogEvObj; /*! Event object to drive devices watchdog thread */
+ volatile IMG_UINT32 ui32DevicesWatchdogPwrTrans;/*! Number of off -> on power state transitions */
+ volatile IMG_UINT32 ui32DevicesWatchdogTimeout; /*! Timeout for the Devices Watchdog Thread */
+#ifdef PVR_TESTING_UTILS
+ volatile IMG_UINT32 ui32DevicesWdWakeupCounter; /* Need this for the unit tests. */
+#endif
+
+ IMG_BOOL bUnload; /*!< Driver unload is in progress */
+} PVRSRV_DATA;
+
+
+typedef IMG_HANDLE PVRSRV_CMDCOMP_HANDLE;
+typedef IMG_VOID (*PFN_CMDCOMP_NOTIFY) (PVRSRV_CMDCOMP_HANDLE hCmdCompHandle);
+
+typedef struct PVRSRV_CMDCOMP_NOTIFY_TAG
+{
+ PVRSRV_CMDCOMP_HANDLE hCmdCompHandle;
+ PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify;
+
+ DLLIST_NODE sListNode;
+} PVRSRV_CMDCOMP_NOTIFY;
+
+#define DEBUG_REQUEST_VERBOSITY_LOW 0
+#define DEBUG_REQUEST_VERBOSITY_MEDIUM 1
+#define DEBUG_REQUEST_VERBOSITY_HIGH 2
+
+#define DEBUG_REQUEST_VERBOSITY_MAX (DEBUG_REQUEST_VERBOSITY_HIGH)
+
+typedef IMG_HANDLE PVRSRV_DBGREQ_HANDLE;
+typedef IMG_VOID (*PFN_DBGREQ_NOTIFY) (PVRSRV_DBGREQ_HANDLE hDebugRequestHandle, IMG_UINT32 ui32VerbLevel);
+
+typedef struct PVRSRV_DBGREQ_NOTIFY_TAG
+{
+ PVRSRV_DBGREQ_HANDLE hDbgRequestHandle;
+ PFN_DBGREQ_NOTIFY pfnDbgRequestNotify;
+ IMG_UINT32 ui32RequesterID;
+
+ DLLIST_NODE sListNode;
+} PVRSRV_DBGREQ_NOTIFY;
+
+/*!
+*******************************************************************************
+
+ @Description
+
+ Macro used within debug dump functions to send output either to PVR_LOG or
+ a custom function.
+
+******************************************************************************/
+#define PVR_DUMPDEBUG_LOG(x) \
+ do \
+ { \
+ if (pfnDumpDebugPrintf) \
+ { \
+ pfnDumpDebugPrintf x; \
+ } \
+ else \
+ { \
+ PVR_LOG(x); \
+ } \
+ } while(0)
+
+/*!
+*******************************************************************************
+
+ @Description
+
+ Typedef for custom debug dump output functions.
+
+******************************************************************************/
+typedef void (DUMPDEBUG_PRINTF_FUNC)(const IMG_CHAR *pszFormat, ...);
+
+extern DUMPDEBUG_PRINTF_FUNC *g_pfnDumpDebugPrintf;
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetPVRSRVData
+
+ @Description Get a pointer to the global data
+
+ @Return PVRSRV_DATA *
+
+******************************************************************************/
+PVRSRV_DATA *PVRSRVGetPVRSRVData(IMG_VOID);
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+ PVRSRV_DEVICE_TYPE *peDeviceType,
+ PVRSRV_DEVICE_CLASS *peDeviceClass,
+ IMG_UINT32 *pui32DeviceIndex);
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
+ PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE *phDevCookie);
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseDeviceDataKM (IMG_HANDLE hDevCookie);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 *pui32DeviceIndex,
+ IMG_UINT32 ui32PhysHeapID);
+
+IMG_VOID IMG_CALLCONV PVRSRVUnregisterExtDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSysPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState, IMG_BOOL bForced);
+
+PVRSRV_ERROR LMA_MMUPxAlloc(PVRSRV_DEVICE_NODE *psDevNode, IMG_SIZE_T uiSize,
+ Px_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr);
+
+IMG_VOID LMA_MMUPxFree(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle);
+
+PVRSRV_ERROR LMA_MMUPxMap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle,
+ IMG_SIZE_T uiSize, IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_VOID **pvPtr);
+
+IMG_VOID LMA_MMUPxUnmap(PVRSRV_DEVICE_NODE *psDevNode, Px_HANDLE *psMemHandle,
+ IMG_VOID *pvPtr);
+
+
+/*!
+******************************************************************************
+ @Function PVRSRVPollForValueKM
+
+ @Description
+ Polls for a value to match a masked read
+
+ @Input pui32LinMemAddr : CPU linear address to poll
+ @Input ui32Value : required value
+ @Input ui32Mask : Mask
+
+ @Return PVRSRV_ERROR :
+******************************************************************************/
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVPollForValueKM(volatile IMG_UINT32 *pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask);
+
+/*!
+******************************************************************************
+ @Function PVRSRVWaitForValueKM
+
+ @Description
+ Waits (using EventObjects) for a value to match a masked read
+
+ @Input pui32LinMemAddr : CPU linear address to poll
+ @Input ui32Value : required value
+ @Input ui32Mask : Mask
+
+ @Return PVRSRV_ERROR :
+******************************************************************************/
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVWaitForValueKM(volatile IMG_UINT32 *pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVSystemDebugInfo
+
+ @Description : Dump the system debug info
+
+@Input pfnDumpDebugPrintf : Used to specify the appropriate printf function.
+ If this argument is IMG_NULL, then PVR_LOG() will
+ be used as the default printing function.
+
+*****************************************************************************/
+PVRSRV_ERROR PVRSRVSystemDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVGetSystemName
+
+ @Description : Gets the system name string
+
+ @Return : The system name
+*****************************************************************************/
+const IMG_CHAR *PVRSRVGetSystemName(IMG_VOID);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVSystemHasCacheSnooping
+
+ @Description : Returns whether the system has cache snooping
+
+ @Return : IMG_TRUE if the system has cache snooping
+*****************************************************************************/
+IMG_BOOL PVRSRVSystemHasCacheSnooping(IMG_VOID);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVSystemSnoopingOfCPUCache
+
+ @Description : Returns whether the system supports snooping of the CPU cache
+
+ @Return : IMG_TRUE if the system has CPU cache snooping
+*****************************************************************************/
+IMG_BOOL PVRSRVSystemSnoopingOfCPUCache(IMG_VOID);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVSystemSnoopingOfDeviceCache
+
+ @Description : Returns whether the system supports snooping of the device cache
+
+ @Return : IMG_TRUE if the system has device cache snooping
+*****************************************************************************/
+IMG_BOOL PVRSRVSystemSnoopingOfDeviceCache(IMG_VOID);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVSystemWaitCycles
+
+ @Description : Waits for at least ui32Cycles of the Device clk.
+
+*****************************************************************************/
+IMG_VOID PVRSRVSystemWaitCycles(PVRSRV_DEVICE_CONFIG *psDevConfig, IMG_UINT32 ui32Cycles);
+
+
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVCheckStatus
+
+ @Description : Notify any registered cmd complete function (except if its
+ hPrivData matches the hCmdCompHandle handler) and raise the global
+ event object.
+
+ @Input hCmdCompHandle : Identify the caller by the handler used when
+ registering for cmd complete. IMG_NULL calls all
+ the notify functions.
+
+*****************************************************************************/
+IMG_VOID IMG_CALLCONV PVRSRVCheckStatus(PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVKickDevicesKM(IMG_VOID);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVResetHWRLogsKM
+
+ @Description : Resets the HWR Logs buffer (the hardware recovery count is not reset)
+
+ @Input psDeviceNode : Pointer to the device
+
+ @Return PVRSRV_ERROR : PVRSRV_OK on success. Otherwise, a PVRSRV_ error code
+*****************************************************************************
+ */
+PVRSRV_ERROR PVRSRVResetHWRLogsKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVRegisterCmdCompleteNotify
+
+ @Description : Register a notify function which is called when some device
+ finishes some work (that is, when someone calls to PVRSRVCheckStatus).
+
+ @Input phNotify : Pointer to the Cmd complete notify handler
+
+ @Input pfnCmdCompleteNotify : Notify function
+
+ @Input hPrivData : Handler to data passed to the Notify function when called
+
+*****************************************************************************/
+PVRSRV_ERROR PVRSRVRegisterCmdCompleteNotify(IMG_HANDLE *phNotify, PFN_CMDCOMP_NOTIFY pfnCmdCompleteNotify, PVRSRV_CMDCOMP_HANDLE hPrivData);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVUnregisterCmdCompleteNotify
+
+ @Description : Unregister a previously registered notify func.
+
+ @Input hNotify : Cmd complete notify handler registered previously
+
+*****************************************************************************/
+PVRSRV_ERROR PVRSRVUnregisterCmdCompleteNotify(IMG_HANDLE hNotify);
+
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVDebugRequest
+
+ @Description : Notify any registered debug request handler that a debug
+ request has been made and at what level. It dumps information
+ for all debug handlers unlike RGXDumpDebugInfo
+
+ @Input ui32VerbLevel : The maximum verbosity level to dump
+
+ @Input pfnDumpDebugPrintf : Used to specify the appropriate printf function.
+ If this argument is IMG_NULL, then PVR_LOG() will
+ be used as the default printing function.
+
+*****************************************************************************/
+IMG_VOID IMG_CALLCONV PVRSRVDebugRequest(IMG_UINT32 ui32VerbLevel, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVRegisterDebugRequestNotify
+
+ @Description : Register a notify function which is called when a debug
+ request is made into the driver (that is, when someone
+ calls to PVRSRVDebugRequest). There are a number of levels
+ of verbosity, starting at 0 and going to
+ DEBUG_REQUEST_VERBOSITY_MAX. For each level that's required
+ a new call to the notify function will be made.
+
+ @Input phNotify : Pointer to the debug request notify handler
+
+ @Input pfnDbgRequestNotify : Notify function
+
+ @Input ui32RequesterID : Used to determine the order debug request callbacks get
+ called in with the table passed into
+
+ @Input hDbgReqeustHandle : Handler to data passed to the Notify function when called
+
+*****************************************************************************/
+PVRSRV_ERROR PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify, PFN_DBGREQ_NOTIFY pfnDbgRequestNotify, IMG_UINT32 ui32RequesterID, PVRSRV_DBGREQ_HANDLE hDbgReqeustHandle);
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVUnregisterDebugRequestNotify
+
+ @Description : Unregister a previously registered notify func.
+
+ @Input hNotify : Debug request notify handler registered previously
+
+*****************************************************************************/
+PVRSRV_ERROR PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify);
+
+/*!
+*****************************************************************************
+ @Function : AcquireGlobalEventObjectServer
+
+ @Description : Acquire the global event object.
+
+ @Output phGlobalEventObject : Handle to the global event object
+
+*****************************************************************************/
+PVRSRV_ERROR AcquireGlobalEventObjectServer(IMG_HANDLE *phGlobalEventObject);
+
+/*!
+*****************************************************************************
+ @Function : ReleaseGlobalEventObjectServer
+
+ @Description : Release the global event object.
+
+ @Input hGlobalEventObject : Handle to the global event object
+
+*****************************************************************************/
+PVRSRV_ERROR ReleaseGlobalEventObjectServer(IMG_HANDLE hGlobalEventObject);
+
+
+/*!
+*****************************************************************************
+ @Function : GetBIFTilingHeapXStride
+
+ @Description : return the default x-stride configuration for the given
+ BIF tiling heap number
+
+ @Input uiHeapNum: BIF tiling heap number, starting from 1
+
+ @Output puiXStride: pointer to x-stride output of the requested heap
+
+*****************************************************************************/
+PVRSRV_ERROR GetBIFTilingHeapXStride(IMG_UINT32 uiHeapNum, IMG_UINT32 *puiXStride);
+
+/*!
+*****************************************************************************
+ @Function : GetNumBIFTilingHeaps
+
+ @Description : return the number of BIF tiling heaps on this system
+
+ @Output puiNumHeaps: pointer to uint to hold number of heaps
+
+*****************************************************************************/
+PVRSRV_ERROR GetNumBifTilingHeapConfigs(IMG_UINT32 *puiNumHeaps);
+
+#endif /* PVRSRV_H */
diff --git a/drivers/gpu/rogue/services/server/include/pvrsrv_device.h b/drivers/gpu/rogue/services/server/include/pvrsrv_device.h
new file mode 100644
index 000000000000..22437ea93ae7
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/pvrsrv_device.h
@@ -0,0 +1,194 @@
+/**************************************************************************/ /*!
+@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_DEVICE_H__
+#define __PVRSRV_DEVICE_H__
+
+#include "servicesext.h"
+#include "pvrsrv_device_types.h"
+#include "img_types.h"
+#include "ra.h"
+#include "physheap.h"
+#include "rgx_fwif_km.h"
+#include "pmr.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef struct _PVRSRV_DEVICE_CONFIG_ PVRSRV_DEVICE_CONFIG;
+
+/*! The CPU physical base of the LMA physical heap is used as the base for
+ * device memory physical heap allocations */
+#define PVRSRV_DEVICE_CONFIG_LMA_USE_CPU_ADDR (1<<0)
+
+/*
+ * The maximum number of physical heaps associated
+ * with a device
+ */
+typedef enum
+{
+ PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL = 0,
+ PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL = 1,
+ PVRSRV_DEVICE_PHYS_HEAP_LAST
+}PVRSRV_DEVICE_PHYS_HEAP;
+
+typedef enum
+{
+ PVRSRV_DEVICE_IRQ_ACTIVE_SYSDEFAULT = 0,
+ PVRSRV_DEVICE_IRQ_ACTIVE_LOW,
+ PVRSRV_DEVICE_IRQ_ACTIVE_HIGH
+}PVRSRV_DEVICE_IRQ_ACTIVE_LEVEL;
+
+typedef IMG_VOID (*PFN_MISR)(IMG_VOID *pvData);
+
+typedef IMG_BOOL (*PFN_LISR)(IMG_VOID *pvData);
+
+typedef IMG_UINT32 (*PFN_SYS_DEV_CLK_FREQ_GET)(IMG_HANDLE hSysData);
+
+typedef PVRSRV_ERROR (*PFN_SYS_DEV_PRE_POWER)(PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ IMG_BOOL bForced);
+
+
+typedef PVRSRV_ERROR (*PFN_SYS_DEV_POST_POWER)(PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ IMG_BOOL bForced);
+
+typedef IMG_VOID (*PFN_SYS_DEV_INTERRUPT_HANDLED)(PVRSRV_DEVICE_CONFIG *psDevConfig);
+
+typedef PVRSRV_ERROR (*PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+ IMG_UINT64 ui64MemSize);
+
+struct _PVRSRV_DEVICE_CONFIG_
+{
+ /*! Configuration flags */
+ IMG_UINT32 uiFlags;
+
+ /*! Name of the device (used when registering the IRQ) */
+ IMG_CHAR *pszName;
+
+ /*! Type of device this is */
+ PVRSRV_DEVICE_TYPE eDeviceType;
+
+ /*! Register bank address */
+ IMG_CPU_PHYADDR sRegsCpuPBase;
+ /*! Register bank size */
+ IMG_UINT32 ui32RegsSize;
+ /*! Device interrupt number */
+ IMG_UINT32 ui32IRQ;
+
+ /*! The device interrupt is shared */
+ IMG_BOOL bIRQIsShared;
+
+ /*! IRQ polarity */
+ PVRSRV_DEVICE_IRQ_ACTIVE_LEVEL eIRQActiveLevel;
+
+ /*! Device specific data handle */
+ IMG_HANDLE hDevData;
+
+ /*! System specific data. This gets passed into system callback functions */
+ IMG_HANDLE hSysData;
+
+ /*! ID of the Physical memory heap to use
+ *! The first entry (aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL]) will be used for allocations
+ *! where the PVRSRV_MEMALLOCFLAG_CPU_LOCAL flag is not set. Normally this will be the PhysHeapID
+ *! of an LMA heap (but the configuration could specify a UMA heap here, if desired)
+ *! The second entry (aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL]) will be used for allocations
+ *! where the PVRSRV_MEMALLOCFLAG_CPU_LOCAL flag is set. Normally this will be the PhysHeapID
+ *! of a UMA heap (but the configuration could specify an LMA heap here, if desired)
+ *! In the event of there being only one Physical Heap, the configuration should specify the
+ *! same heap details in both entries */
+ IMG_UINT32 aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_LAST];
+
+ /*! Callback to inform the device we about to change power state */
+ PFN_SYS_DEV_PRE_POWER pfnPrePowerState;
+
+ /*! Callback to inform the device we have finished the power state change */
+ PFN_SYS_DEV_POST_POWER pfnPostPowerState;
+
+ /*! Callback to obtain the clock frequency from the device */
+ PFN_SYS_DEV_CLK_FREQ_GET pfnClockFreqGet;
+
+ /*! Callback to inform the device that an interrupt has been handled */
+ PFN_SYS_DEV_INTERRUPT_HANDLED pfnInterruptHandled;
+
+ /*! Callback to handle memory budgeting */
+ PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE pfnCheckMemAllocSize;
+
+ /*! Current breakpoint data master */
+ RGXFWIF_DM eBPDM;
+ /*! A Breakpoint has been set */
+ IMG_BOOL bBPSet;
+};
+
+typedef PVRSRV_ERROR (*PFN_SYSTEM_PRE_POWER_STATE)(PVRSRV_SYS_POWER_STATE eNewPowerState);
+typedef PVRSRV_ERROR (*PFN_SYSTEM_POST_POWER_STATE)(PVRSRV_SYS_POWER_STATE eNewPowerState);
+
+typedef enum _PVRSRV_SYSTEM_SNOOP_MODE_ {
+ PVRSRV_SYSTEM_SNOOP_NONE = 0,
+ PVRSRV_SYSTEM_SNOOP_CPU_ONLY,
+ PVRSRV_SYSTEM_SNOOP_DEVICE_ONLY,
+ PVRSRV_SYSTEM_SNOOP_CROSS,
+} PVRSRV_SYSTEM_SNOOP_MODE;
+
+typedef struct _PVRSRV_SYSTEM_CONFIG_
+{
+ IMG_UINT32 uiSysFlags;
+ IMG_CHAR *pszSystemName;
+ IMG_UINT32 uiDeviceCount;
+ PVRSRV_DEVICE_CONFIG *pasDevices;
+ PFN_SYSTEM_PRE_POWER_STATE pfnSysPrePowerState;
+ PFN_SYSTEM_POST_POWER_STATE pfnSysPostPowerState;
+ PVRSRV_SYSTEM_SNOOP_MODE eCacheSnoopingMode;
+
+ PHYS_HEAP_CONFIG *pasPhysHeaps;
+ IMG_UINT32 ui32PhysHeapCount;
+
+ IMG_UINT32 *pui32BIFTilingHeapConfigs;
+ IMG_UINT32 ui32BIFTilingHeapCount;
+} PVRSRV_SYSTEM_CONFIG;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __PVRSRV_DEVICE_H__*/
diff --git a/drivers/gpu/rogue/services/server/include/resman.h b/drivers/gpu/rogue/services/server/include/resman.h
new file mode 100644
index 000000000000..76c41bb7bd39
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/resman.h
@@ -0,0 +1,199 @@
+/**************************************************************************/ /*!
+@File
+@Title Resource Manager API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource management
+@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 __RESMAN_H__
+#define __RESMAN_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "servicesext.h"
+
+/******************************************************************************
+ * resman definitions
+ *****************************************************************************/
+
+enum {
+ /* SGX: */
+ RESMAN_TYPE_SHARED_PB_DESC = 1, /*!< Parameter buffer kernel stubs */
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, /*!< Shared parameter buffer creation lock */
+
+ /* MSVDX: TBD */
+
+ /* DISPLAY CLASS: */
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, /*!< Display Class Swapchain Reference Resource */
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE, /*!< Display Class Device Resource */
+
+ /* BUFFER CLASS: */
+ RESMAN_TYPE_BUFFERCLASS_DEVICE, /*!< Buffer Class Device Resource */
+
+ /* OS specific User mode Mappings: */
+ RESMAN_TYPE_OS_USERMODE_MAPPING, /*!< OS specific User mode mappings */
+
+ /* COMMON: */
+ RESMAN_TYPE_DC_DEVICE,
+ RESMAN_TYPE_DC_DISPLAY_CONTEXT,
+ RESMAN_TYPE_DC_PIN_HANDLE,
+ RESMAN_TYPE_DC_BUFFER,
+ RESMAN_TYPE_DEVMEM_MEM_EXPORT,
+ RESMAN_TYPE_PMR,
+ RESMAN_TYPE_PMR_EXPORT,
+ RESMAN_TYPE_PMR_PAGELIST, /*!< Device Memory page list Resource */
+ RESMAN_TYPE_DEVICEMEM2_CONTEXT, /*!< Device Memory Context Resource */
+ RESMAN_TYPE_DEVICEMEM2_CONTEXT_EXPORT, /*!< Device Memory Context export Resource */
+ RESMAN_TYPE_DEVICEMEM2_HEAP, /*!< Device Memory Heap Resource */
+ RESMAN_TYPE_DEVICEMEM2_RESERVATION, /*!< Device Memory Reservation Resource */
+ RESMAN_TYPE_DEVICEMEM2_MAPPING, /*!< Device Memory Mapping Resource */
+ RESMAN_TYPE_DEVICEMEM_CONTEXT, /*!< Device Memory Context Resource */
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING, /*!< Device Memory Mapping Resource */
+ RESMAN_TYPE_DEVICEMEM_MAPPING, /*!< Device Memory Mapping Resource */
+ RESMAN_TYPE_DEVICEMEM_WRAP, /*!< Device Memory Wrap Resource */
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION, /*!< Device Memory Allocation Resource */
+ RESMAN_TYPE_EVENT_OBJECT, /*!< Event Object */
+ RESMAN_TYPE_SHARED_MEM_INFO, /*!< Shared system memory meminfo */
+ RESMAN_TYPE_MODIFY_SYNC_OPS, /*!< Syncobject synchronisation Resource*/
+ RESMAN_TYPE_SYNC_INFO, /*!< Syncobject Resource*/
+ PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA, /*!< Private Data Resource*/
+ RESMAN_TYPE_SYNC_RECORD_HANDLE, /*!< Sync record handle */
+ RESMAN_TYPE_SYNC_PRIMITIVE, /*!< Sync primitive resource */
+ RESMAN_TYPE_SYNC_PRIMITIVE_BLOCK, /*!< Sync primitive block resource */
+ RESMAN_TYPE_SERVER_SYNC_PRIMITIVE, /*!< Server sync primitive resource */
+ RESMAN_TYPE_SERVER_SYNC_EXPORT, /*!< Server sync export resource */
+ RESMAN_TYPE_SERVER_OP_COOKIE, /*!< Server operation cookie resource */
+ RESMAN_TYPE_SHARED_EVENT_OBJECT, /*!< Shared event object resource */
+
+ /* RGX: */
+ RESMAN_TYPE_RGX_SERVER_RENDER_CONTEXT, /*!< RGX Render Context Resource */
+ RESMAN_TYPE_RGX_SERVER_TQ_CONTEXT, /*!< RGX Transfer Queue Context Resource */
+ RESMAN_TYPE_RGX_SERVER_COMPUTE_CONTEXT, /*!< RGX Compute Context Resource */
+ RESMAN_TYPE_RGX_SERVER_RAY_CONTEXT, /*!< RGX Ray Context Resource */
+ RESMAN_TYPE_RGX_MEMORY_BLOCK, /*!< RGX Freelist Memory Block Resource */
+ RESMAN_TYPE_RGX_FWIF_HWRTDATA, /*! < FW HWRTDATA structure */
+ RESMAN_TYPE_RGX_FWIF_RENDERTARGET, /*! < FW RENDER_TARGET structure */
+ RESMAN_TYPE_RGX_FWIF_ZSBUFFER, /*!< FW ZS-Buffer structure */
+ RESMAN_TYPE_RGX_POPULATION, /*!< ZS-Buffer population structure */
+ RESMAN_TYPE_RGX_FWIF_FREELIST, /*! < FW FREELIST structure */
+
+ /* KERNEL: */
+ RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION, /*!< Device Memory Allocation Resource */
+
+ /* TRANSPORT LAYER: */
+ RESMAN_TYPE_TL_STREAM_DESC, /*!< Transport Layer stream descriptor resource */
+
+ /* RI: */
+ RESMAN_TYPE_RI_HANDLE /*!< RI resource */
+};
+
+#define RESMAN_CRITERIA_ALL 0x00000000 /*!< match by criteria all */
+#define RESMAN_CRITERIA_RESTYPE 0x00000001 /*!< match by criteria type */
+#define RESMAN_CRITERIA_PVOID_PARAM 0x00000002 /*!< match by criteria param1 */
+
+/* Set the maximum time the freeing of the resources can keep the lock */
+#define RESMAN_DEFERRED_CLEANUP_TIMESLICE_NS 3000*1000 /* 3ms */
+
+typedef PVRSRV_ERROR (*RESMAN_FREE_FN)(IMG_PVOID pvParam);
+
+typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
+typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
+typedef struct _RESMAN_DEFER_CONTEXTS_LIST_ *PRESMAN_DEFER_CONTEXTS_LIST;
+
+/******************************************************************************
+ * resman functions
+ *****************************************************************************/
+
+PVRSRV_ERROR ResManInit(IMG_VOID);
+IMG_VOID ResManDeInit(IMG_VOID);
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT hResManContext,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ RESMAN_FREE_FN pfnFreeResource);
+
+PVRSRV_ERROR ResManFreeResByPtr(PRESMAN_ITEM psResItem);
+
+/*!
+******************************************************************************
+ @Function ResManFindPrivateDataByPtr
+
+ @Description finds the private date for a resource by matching on pointer type
+
+ @inputs psResItem - pointer to resource item
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+extern PVRSRV_ERROR
+ResManFindPrivateDataByPtr(
+ PRESMAN_ITEM psResItem,
+ IMG_PVOID *ppvParam1
+ );
+
+PVRSRV_ERROR ResManDissociateRes(PRESMAN_ITEM psResItem,
+ PRESMAN_CONTEXT psNewResManContext);
+
+PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT hResManContext,
+ PRESMAN_ITEM psItem);
+
+PVRSRV_ERROR PVRSRVResManConnect(PRESMAN_DEFER_CONTEXTS_LIST hDeferContext,
+ PRESMAN_CONTEXT *phResManContext);
+
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT hResManContext);
+
+PVRSRV_ERROR PVRSRVResManCreateDeferContext(IMG_HANDLE hEventObj,
+ PRESMAN_DEFER_CONTEXTS_LIST *phDeferContext);
+
+IMG_BOOL PVRSRVResManFlushDeferContext(PRESMAN_DEFER_CONTEXTS_LIST hDeferContext,
+ IMG_UINT64 ui64TimesliceLimit);
+
+IMG_VOID PVRSRVResManDestroyDeferContext(PRESMAN_DEFER_CONTEXTS_LIST hDeferContext);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __RESMAN_H__ */
+
+/******************************************************************************
+ End of file (resman.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/server/include/ri_server.h b/drivers/gpu/rogue/services/server/include/ri_server.h
new file mode 100644
index 000000000000..4a1bdb63df27
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/ri_server.h
@@ -0,0 +1,87 @@
+/*************************************************************************/ /*!
+@File ri_server.h
+@Title Resource Information abstraction
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Resource Information (RI) 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.
+*/ /**************************************************************************/
+
+#ifndef _RI_SERVER_H_
+#define _RI_SERVER_H_
+
+#include <img_defs.h>
+#include <ri_typedefs.h>
+#include <pmr.h>
+#include <pvrsrv_error.h>
+
+PVRSRV_ERROR RIInitKM(IMG_VOID);
+IMG_VOID RIDeInitKM(IMG_VOID);
+
+PVRSRV_ERROR RIWritePMREntryKM(PMR *hPMR,
+ IMG_UINT32 ui32TextASize,
+ const IMG_CHAR ai8TextA[RI_MAX_TEXT_LEN+1],
+ IMG_SIZE_T uiLogicalSize);
+
+PVRSRV_ERROR RIWriteMEMDESCEntryKM(PMR *hPMR,
+ IMG_UINT32 ui32TextBSize,
+ const IMG_CHAR ai8TextB[RI_MAX_TEXT_LEN+1],
+ IMG_SIZE_T uiOffset,
+ IMG_SIZE_T uiSize,
+ IMG_BOOL bIsImport,
+ IMG_BOOL bIsExportable,
+ RI_HANDLE *phRIHandle);
+
+PVRSRV_ERROR RIUpdateMEMDESCAddrKM(RI_HANDLE hRIHandle,
+ IMG_DEV_VIRTADDR sVAddr);
+
+PVRSRV_ERROR RIDeletePMREntryKM(RI_HANDLE hRIHandle);
+PVRSRV_ERROR RIDeleteMEMDESCEntryKM(RI_HANDLE hRIHandle);
+
+PVRSRV_ERROR RIDeleteListKM(IMG_VOID);
+
+PVRSRV_ERROR RIDumpListKM(PMR *hPMR);
+
+PVRSRV_ERROR RIDumpAllKM(IMG_VOID);
+
+PVRSRV_ERROR RIDumpProcessKM(IMG_PID pid);
+
+IMG_BOOL RIGetListEntryKM(IMG_PID pid,
+ IMG_HANDLE **ppHandle,
+ IMG_CHAR **ppszEntryString);
+
+#endif /* #ifndef _RI_SERVER_H _*/
diff --git a/drivers/gpu/rogue/services/server/include/scp.h b/drivers/gpu/rogue/services/server/include/scp.h
new file mode 100644
index 000000000000..31944bc8f43a
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/scp.h
@@ -0,0 +1,224 @@
+/**************************************************************************/ /*!
+@File
+@Title Software Command Processor header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines the interface for the software command processor
+@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 SCP_H
+#define SCP_H
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "sync_server.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef struct _SCP_CONTEXT_ SCP_CONTEXT; /*!< Opaque handle to a software command processor context */
+
+typedef IMG_BOOL (*SCPReady)(IMG_PVOID pvReadyData);
+typedef IMG_VOID (*SCPDo)(IMG_PVOID pvReadyData, IMG_PVOID pvCompleteData);
+
+/*************************************************************************/ /*!
+@Function SCPCreate
+
+@Description Create a software command processor
+
+@Input ui32CCBSizeLog2 Log2 of the CCB size
+
+@Output ppvBufferSpace Pointer to space allocated
+
+@Return PVRSRV_OK if the software command processor was created
+*/
+/*****************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV SCPCreate(IMG_UINT32 ui32CCBSizeLog2,
+ SCP_CONTEXT **ppsContext);
+
+/*************************************************************************/ /*!
+@Function SCPAllocCommand
+
+@Description Allocate space in the software command processor and return
+ the data pointers for the callback data.
+
+ Once any command ready data and command complete have been setup
+ the command can be submitted for processing by calling
+ SCPSubmitCommand.
+
+ When any fences the command has have been meet then the command
+ ready callback will be called with the command ready data.
+ Once the command has completed the command complete callback will
+ be called with the command complete data.
+
+@Input psSCPContext Context to allocate from
+
+@Input ui32SyncPrimCount Number of Sync Prim operations
+
+@Input papsSync Pointer to array of pointers to server syncs
+
+@Input pfnCommandReady Callback to call if the command is ready
+
+@Input pfnCommandDo Callback to the function to run
+
+@Input ui32ReadyDataSize Size of command ready data to allocate in bytes
+
+@Input pfnCommandComplete Callback to call when the command has completed
+
+@Input ui32CompleteDataSize Size of command complete data to allocate
+
+@Output ppvReadyData Pointer to memory allocated for command
+ ready callback data
+
+@Output ppvCompleteData Pointer to memory allocated for command
+ complete callback data
+
+@Return PVRSRV_OK if the allocate was successfull
+*/
+/*****************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV SCPAllocCommand(SCP_CONTEXT *psSCPContext,
+ IMG_UINT32 ui32SyncPrimCount,
+ SERVER_SYNC_PRIMITIVE **papsSync,
+ IMG_BOOL *pabUpdate,
+ IMG_INT32 i32AcquireFenceFd,
+ SCPReady pfnCommandReady,
+ SCPDo pfnCommandDo,
+ IMG_SIZE_T ui32ReadyDataByteSize,
+ IMG_SIZE_T ui32CompleteDataByteSize,
+ IMG_PVOID *ppvReadyData,
+ IMG_PVOID *ppvCompleteData,
+ IMG_INT32 *pi32ReleaseFenceFd);
+
+/*************************************************************************/ /*!
+@Function SCPSubmitCommand
+
+@Description Submit a command for processing. We don't actually try to
+ run the command in this call as it might not be valid to do
+ from the same thread that this function is being called from
+
+@Input psSCPContext Context to allocate on which to submit
+ the command
+
+@Return PVRSRV_OK if the command was submitted
+*/
+/*****************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR SCPSubmitCommand(SCP_CONTEXT *psContext);
+
+
+/*************************************************************************/ /*!
+@Function SCPRun
+
+@Description Run the software command processor to see if any commands are
+ now ready.
+
+@Input psSCPContext Context to process
+
+@Return PVRSRV_OK if the software command processor was run
+*/
+/*****************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR SCPRun(SCP_CONTEXT *psContext);
+
+/*************************************************************************/ /*!
+@Function SCPCommandComplete
+
+@Description Complete a command which the software command processor
+ has previously issued.
+ Note: Commands _MUST_ be completed in order
+
+@Input psSCPContext Context to process
+
+@Return PVRSRV_OK if the software command processor was run
+*/
+/*****************************************************************************/
+IMG_IMPORT
+IMG_VOID SCPCommandComplete(SCP_CONTEXT *psContext);
+
+/*************************************************************************/ /*!
+@Function SCPFlush
+
+@Description Flush the software command processor.
+
+@Input psSCPContext Context to process
+
+@Return PVRSRV_OK if all commands have been completed, otherwise
+ PVRSRV_ERROR_RETRY
+*/
+/*****************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR SCPFlush(SCP_CONTEXT *psContext);
+
+/*************************************************************************/ /*!
+@Function SCPDumpStatus
+
+@Description Dump the status of the provided software command processor.
+
+@Input psSCPContext Context to dump
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV SCPDumpStatus(SCP_CONTEXT *psContext);
+
+/*************************************************************************/ /*!
+@Function SCPDestroy
+
+@Description Destroy a software command processor.
+
+@Input psSCPContext Context to destroy
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_IMPORT
+IMG_VOID IMG_CALLCONV SCPDestroy(SCP_CONTEXT *psContext);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* SCP_H */
+
+/******************************************************************************
+ End of file (queue.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/include/secure_export.h b/drivers/gpu/rogue/services/server/include/secure_export.h
new file mode 100644
index 000000000000..55aac8c5c5cf
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/secure_export.h
@@ -0,0 +1,65 @@
+/**************************************************************************/ /*!
+@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 "pmr.h"
+#include "connection_server.h"
+
+typedef struct _SECURE_CLEANUP_DATA_ {
+ PMR *psPMR;
+} SECURE_CLEANUP_DATA;
+
+PVRSRV_ERROR PMRSecureExportPMR(CONNECTION_DATA *psConnection,
+ PMR *psPMR,
+ IMG_SECURE_TYPE *phSecure,
+ PMR **ppsPMR,
+ CONNECTION_DATA **ppsSecureConnection);
+
+PVRSRV_ERROR PMRSecureUnexportPMR(PMR *psPMR);
+
+PVRSRV_ERROR PMRSecureImportPMR(IMG_SECURE_TYPE hSecure,
+ PMR **ppsPMR,
+ IMG_DEVMEM_SIZE_T *puiSize,
+ IMG_DEVMEM_ALIGN_T *puiAlign);
+
+PVRSRV_ERROR PMRSecureUnimportPMR(PMR *psPMR);
+
diff --git a/drivers/gpu/rogue/services/server/include/srvcore.h b/drivers/gpu/rogue/services/server/include/srvcore.h
new file mode 100644
index 000000000000..99bf60a5841d
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/srvcore.h
@@ -0,0 +1,219 @@
+/**************************************************************************/ /*!
+@File
+@Title PVR Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@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 __BRIDGED_PVR_BRIDGE_H__
+#define __BRIDGED_PVR_BRIDGE_H__
+
+#include "connection_server.h"
+#include "pvr_debug.h"
+
+#include "pvr_bridge.h"
+#if defined(SUPPORT_RGX)
+#include "rgx_bridge.h"
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+#define PVRSRV_GET_BRIDGE_ID(X) _IOC_NR(X)
+#else
+#define PVRSRV_GET_BRIDGE_ID(X) ((X) - PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST))
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#ifndef EFAULT
+#define EFAULT 14
+#endif
+#ifndef ENOTTY
+#define ENOTTY 25
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(CONNECTION_DATA *psConnection,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size);
+PVRSRV_ERROR
+CopyToUserWrapper(CONNECTION_DATA *psConnection,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size);
+#else
+#define CopyFromUserWrapper(psConnection, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyFromUser(psConnection, pvDest, pvSrc, ui32Size)
+#define CopyToUserWrapper(psConnection, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyToUser(psConnection, pvDest, pvSrc, ui32Size)
+#endif
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ CONNECTION_DATA *psConnection);
+
+typedef IMG_INT (*BridgeWrapperFunction)(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ CONNECTION_DATA *psConnection);
+
+typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+{
+ BridgeWrapperFunction pfFunction; /*!< The wrapper function that validates the ioctl
+ arguments before calling into srvkm proper */
+#if defined(DEBUG_BRIDGE_KM)
+ const IMG_CHAR *pszIOCName; /*!< Name of the ioctl: e.g. "PVRSRV_BRIDGE_CONNECT_SERVICES" */
+ const IMG_CHAR *pszFunctionName; /*!< Name of the wrapper function: e.g. "PVRSRVConnectBW" */
+ IMG_UINT32 ui32CallCount; /*!< The total number of times the ioctl has been called */
+ IMG_UINT32 ui32CopyFromUserTotalBytes; /*!< The total number of bytes copied from
+ userspace within this ioctl */
+ IMG_UINT32 ui32CopyToUserTotalBytes; /*!< The total number of bytes copied from
+ userspace within this ioctl */
+#endif
+}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
+
+#if defined(SUPPORT_VGX) || defined(SUPPORT_MSVDX)
+ #if defined(SUPPORT_VGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_VGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_VGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_MSVDX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_MSVDX_CMD
+ #endif
+#else
+ #if defined(SUPPORT_RGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_RGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_RGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD
+ #endif
+#endif
+
+extern PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+ const IMG_CHAR *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const IMG_CHAR *pszFunctionName);
+
+
+/* PRQA S 0884,3410 2*/ /* macro relies on the lack of brackets */
+#define SetDispatchTableEntry(ui32Index, pfFunction) \
+ _SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction)
+
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+
+#if defined(DEBUG)
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_ASSERT(X == PVRSRV_GET_BRIDGE_ID(Y))
+#else
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_UNREFERENCED_PARAMETER(X)
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+typedef struct _PVRSRV_BRIDGE_GLOBAL_STATS
+{
+ IMG_UINT32 ui32IOCTLCount;
+ IMG_UINT32 ui32TotalCopyFromUserBytes;
+ IMG_UINT32 ui32TotalCopyToUserBytes;
+} PVRSRV_BRIDGE_GLOBAL_STATS;
+
+/* 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) */
+extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+
+IMG_INT BridgedDispatchKM(CONNECTION_DATA * psConnection,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM);
+
+
+PVRSRV_ERROR
+PVRSRVConnectKM(CONNECTION_DATA *psConnection,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32ClientBuildOptions,
+ IMG_UINT32 ui32ClientDDKVersion,
+ IMG_UINT32 ui32ClientDDKBuild,
+ IMG_UINT8 *pui8KernelArch,
+ IMG_UINT32 *ui32Log2PageSize);
+
+PVRSRV_ERROR
+PVRSRVDisconnectKM(IMG_VOID);
+
+PVRSRV_ERROR
+PVRSRVInitSrvDisconnectKM(CONNECTION_DATA *psConnection,
+ IMG_BOOL bInitSuccesful,
+ IMG_UINT32 ui32ClientBuildOptions);
+
+PVRSRV_ERROR
+PVRSRVDumpDebugInfoKM(IMG_UINT32 ui32VerbLevel);
+
+PVRSRV_ERROR
+PVRSRVGetDevClockSpeedKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_PUINT32 pui32RGXClockSpeed);
+
+PVRSRV_ERROR
+PVRSRVHWOpTimeoutKM(IMG_VOID);
+
+/* performs a SOFT_RESET on the given device node */
+PVRSRV_ERROR
+PVRSRVSoftResetKM(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64ResetValue);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __BRIDGED_PVR_BRIDGE_H__ */
+
+/******************************************************************************
+ End of file (bridged_pvr_bridge.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/server/include/srvkm.h b/drivers/gpu/rogue/services/server/include/srvkm.h
new file mode 100644
index 000000000000..d4aa515929b6
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/srvkm.h
@@ -0,0 +1,197 @@
+/**************************************************************************/ /*!
+@File
+@Title Services kernel module internal header 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 SRVKM_H
+#define SRVKM_H
+
+#include "servicesext.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(KERNEL) && defined(ANDROID)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+
+/** Use PVR_DPF() unless message is necessary in release build
+ */
+#ifdef PVR_DISABLE_LOGGING
+#define PVR_LOG(X)
+#else
+/* PRQA S 3410 1 */ /* this macro requires no brackets in order to work */
+#define PVR_LOG(X) PVRSRVReleasePrintf X;
+#endif
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVInit
+
+ @Description Initialise services
+
+ @Input psSysData : sysdata structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(IMG_VOID);
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDeInit
+
+ @Description De-Initialise services
+
+ @Input psSysData : sysdata structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(IMG_VOID);
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVScheduleDevicesKM
+
+ @Description Schedules all Services-Managed Devices to check their pending
+ command queues. The intention is that ScheduleDevices be called by the
+ 3rd party BC driver after it has finished writing new data to its output
+ texture.
+
+ @Input bInLISR
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_IMPORT IMG_VOID PVRSRVScheduleDevicesKM(IMG_BOOL bInLISR);
+
+IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, IMG_SIZE_T *puiBufSize, IMG_BOOL bSave);
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVScheduleDeviceCallbacks
+
+ @Description Schedule all device callbacks
+
+ @Input ui32CallerID
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_UINT32 ui32CallerID);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+/******************
+HIGHER LEVEL MACROS
+*******************/
+
+/*----------------------------------------------------------------------------
+Repeats the body of the loop for a certain minimum time, or until the body
+exits by its own means (break, return, goto, etc.)
+
+Example of usage:
+
+LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+{
+ if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
+ {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+} END_LOOP_UNTIL_TIMEOUT();
+
+-----------------------------------------------------------------------------*/
+
+/* uiNotLastLoop will remain at 1 until the timeout has expired, at which time
+ * it will be decremented and the loop executed one final time. This is necessary
+ * when preemption is enabled.
+ */
+/* PRQA S 3411,3431 12 */ /* critical format, leave alone */
+#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
+{\
+ IMG_UINT32 uiOffset, uiStart, uiCurrent; \
+ IMG_INT32 iNotLastLoop; \
+ for(uiOffset = 0, uiStart = OSClockus(), uiCurrent = uiStart + 1, iNotLastLoop = 1;\
+ ((uiCurrent - uiStart + uiOffset) < (TIMEOUT)) || iNotLastLoop--; \
+ uiCurrent = OSClockus(), \
+ uiOffset = uiCurrent < uiStart ? IMG_UINT32_MAX - uiStart : uiOffset, \
+ uiStart = uiCurrent < uiStart ? 0 : uiStart)
+
+#define END_LOOP_UNTIL_TIMEOUT() \
+}
+
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVGetErrorStringKM
+
+ @Description Returns a text string relating to the PVRSRV_ERROR enum.
+
+ ******************************************************************************/
+IMG_IMPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError);
+
+
+typedef struct _SERVER_SYNC_PRIM_
+{
+ /* Placeholder until structure is properly implemented */
+ IMG_UINT32 ui32Placeholder;
+} SERVER_SYNC_PRIM;
+
+
+#endif /* SRVKM_H */
diff --git a/drivers/gpu/rogue/services/server/include/sync_server.h b/drivers/gpu/rogue/services/server/include/sync_server.h
new file mode 100644
index 000000000000..2344acd00d8b
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/sync_server.h
@@ -0,0 +1,318 @@
+/**************************************************************************/ /*!
+@File
+@Title Server side synchronisation interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Describes the server side synchronisation 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_types.h"
+#include "device.h"
+#include "devicemem.h"
+#include "pdump.h"
+#include "pvrsrv_error.h"
+#include "connection_server.h"
+
+#ifndef _SYNC_SERVER_H_
+#define _SYNC_SERVER_H_
+
+typedef struct _SERVER_OP_COOKIE_ SERVER_OP_COOKIE;
+typedef struct _SERVER_SYNC_PRIMITIVE_ SERVER_SYNC_PRIMITIVE;
+typedef struct _SYNC_PRIMITIVE_BLOCK_ SYNC_PRIMITIVE_BLOCK;
+typedef struct _SERVER_SYNC_EXPORT_ SERVER_SYNC_EXPORT;
+typedef struct _SYNC_CONNECTION_DATA_ SYNC_CONNECTION_DATA;
+typedef struct SYNC_RECORD* SYNC_RECORD_HANDLE;
+
+PVRSRV_ERROR
+PVRSRVAllocSyncPrimitiveBlockKM(CONNECTION_DATA *psConnection,
+ PVRSRV_DEVICE_NODE *psDevNode,
+ SYNC_PRIMITIVE_BLOCK **ppsSyncBlk,
+ IMG_UINT32 *puiSyncPrimVAddr,
+ IMG_UINT32 *puiSyncPrimBlockSize,
+ DEVMEM_EXPORTCOOKIE **psExportCookie);
+
+PVRSRV_ERROR
+PVRSRVExportSyncPrimitiveBlockKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk,
+ DEVMEM_EXPORTCOOKIE **psExportCookie);
+
+PVRSRV_ERROR
+PVRSRVUnexportSyncPrimitiveBlockKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk);
+
+PVRSRV_ERROR
+PVRSRVFreeSyncPrimitiveBlockKM(SYNC_PRIMITIVE_BLOCK *ppsSyncBlk);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimSetKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Index,
+ IMG_UINT32 ui32Value);
+
+PVRSRV_ERROR
+PVRSRVServerSyncPrimSetKM(SERVER_SYNC_PRIMITIVE *psServerSync, IMG_UINT32 ui32Value);
+
+#if defined(SUPPORT_INSECURE_EXPORT)
+PVRSRV_ERROR
+PVRSRVSyncPrimServerExportKM(SERVER_SYNC_PRIMITIVE *psSync,
+ SERVER_SYNC_EXPORT **ppsExport);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimServerUnexportKM(SERVER_SYNC_EXPORT *psExport);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimServerImportKM(SERVER_SYNC_EXPORT *psExport,
+ SERVER_SYNC_PRIMITIVE **ppsSync,
+ IMG_UINT32 *pui32SyncPrimVAddr);
+#endif
+
+#if defined(SUPPORT_SECURE_EXPORT)
+PVRSRV_ERROR
+PVRSRVSyncPrimServerSecureExportKM(CONNECTION_DATA *psConnection,
+ SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_SECURE_TYPE *phSecure,
+ SERVER_SYNC_EXPORT **ppsExport,
+ CONNECTION_DATA **ppsSecureConnection);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimServerSecureUnexportKM(SERVER_SYNC_EXPORT *psExport);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimServerSecureImportKM(IMG_SECURE_TYPE hSecure,
+ SERVER_SYNC_PRIMITIVE **ppsSync,
+ IMG_UINT32 *pui32SyncPrimVAddr);
+#endif
+
+IMG_UINT32 PVRSRVServerSyncRequesterRegisterKM(IMG_UINT32 *pui32SyncRequesterID);
+IMG_VOID PVRSRVServerSyncRequesterUnregisterKM(IMG_UINT32 ui32SyncRequesterID);
+
+PVRSRV_ERROR
+PVRSRVSyncRecordAddKM(
+ SYNC_RECORD_HANDLE * phRecord,
+ SYNC_PRIMITIVE_BLOCK * hServerSyncPrimBlock,
+ IMG_UINT32 ui32FwBlockAddr,
+ IMG_UINT32 ui32SyncOffset,
+ IMG_BOOL bServerSync,
+ IMG_UINT32 ui32ClassNameSize,
+ const IMG_CHAR *pszClassName);
+PVRSRV_ERROR
+PVRSRVSyncRecordRemoveByHandleKM(
+ SYNC_RECORD_HANDLE hRecord);
+
+PVRSRV_ERROR
+PVRSRVServerSyncAllocKM(PVRSRV_DEVICE_NODE *psDevNode,
+ SERVER_SYNC_PRIMITIVE **ppsSync,
+ IMG_UINT32 *pui32SyncPrimVAddr,
+ IMG_UINT32 ui32ClassNameSize,
+ const IMG_CHAR *szClassName);
+PVRSRV_ERROR
+PVRSRVServerSyncFreeKM(SERVER_SYNC_PRIMITIVE *psSync);
+
+PVRSRV_ERROR
+PVRSRVServerSyncGetStatusKM(IMG_UINT32 ui32SyncCount,
+ SERVER_SYNC_PRIMITIVE **papsSyncs,
+ IMG_UINT32 *pui32UID,
+ IMG_UINT32 *pui32FWAddr,
+ IMG_UINT32 *pui32CurrentOp,
+ IMG_UINT32 *pui32NextOp);
+
+PVRSRV_ERROR
+PVRSRVServerSyncQueueSWOpKM(SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_UINT32 *pui32FenceValue,
+ IMG_UINT32 *pui32UpdateValue,
+ IMG_UINT32 ui32SyncRequesterID,
+ IMG_BOOL bUpdate,
+ IMG_BOOL *pbFenceRequired);
+
+PVRSRV_ERROR
+PVRSRVServerSyncQueueHWOpKM(SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_BOOL bUpdate,
+ IMG_UINT32 *pui32FenceValue,
+ IMG_UINT32 *pui32UpdateValue);
+
+IMG_BOOL
+ServerSyncFenceIsMet(SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_UINT32 ui32FenceValue);
+
+IMG_VOID
+ServerSyncCompleteOp(SERVER_SYNC_PRIMITIVE *psSync,
+ IMG_BOOL bDoUpdate,
+ IMG_UINT32 ui32UpdateValue);
+
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpCreateKM(IMG_UINT32 ui32SyncBlockCount,
+ SYNC_PRIMITIVE_BLOCK **papsSyncPrimBlock,
+ IMG_UINT32 ui32ClientSyncCount,
+ IMG_UINT32 *paui32SyncBlockIndex,
+ IMG_UINT32 *paui32Index,
+ IMG_UINT32 ui32ServerSyncCount,
+ SERVER_SYNC_PRIMITIVE **papsServerSync,
+ SERVER_OP_COOKIE **ppsServerCookie);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpTakeKM(SERVER_OP_COOKIE *psServerCookie,
+ IMG_UINT32 ui32ClientSyncCount,
+ IMG_UINT32 *paui32Flags,
+ IMG_UINT32 *paui32FenceValue,
+ IMG_UINT32 *paui32UpdateValue,
+ IMG_UINT32 ui32ServerSyncCount,
+ IMG_UINT32 *paui32ServerFlags);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpReadyKM(SERVER_OP_COOKIE *psServerCookie,
+ IMG_BOOL *pbReady);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpCompleteKM(SERVER_OP_COOKIE *psServerCookie);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpDestroyKM(SERVER_OP_COOKIE *psServerCookie);
+
+IMG_UINT32 ServerSyncGetId(SERVER_SYNC_PRIMITIVE *psSync);
+
+IMG_UINT32 ServerSyncGetFWAddr(SERVER_SYNC_PRIMITIVE *psSync);
+
+IMG_UINT32 ServerSyncGetValue(SERVER_SYNC_PRIMITIVE *psSync);
+
+IMG_UINT32 ServerSyncGetNextValue(SERVER_SYNC_PRIMITIVE *psSync);
+
+IMG_VOID ServerSyncDumpPending(IMG_VOID);
+
+PVRSRV_ERROR SyncRegisterConnection(SYNC_CONNECTION_DATA **ppsSyncConnectionData);
+IMG_VOID SyncUnregisterConnection(SYNC_CONNECTION_DATA *ppsSyncConnectionData);
+IMG_VOID SyncConnectionPDumpSyncBlocks(SYNC_CONNECTION_DATA *ppsSyncConnectionData);
+
+PVRSRV_ERROR ServerSyncInit(IMG_VOID);
+IMG_VOID ServerSyncDeinit(IMG_VOID);
+
+#if defined(PDUMP)
+PVRSRV_ERROR
+PVRSRVSyncPrimPDumpKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimPDumpValueKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimPDumpPolKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value, IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiDumpFlags);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimOpPDumpPolKM(SERVER_OP_COOKIE *psServerCookie,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T ui32PDumpFlags);
+
+PVRSRV_ERROR
+PVRSRVSyncPrimPDumpCBPKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT64 ui32Offset,
+ IMG_UINT64 uiWriteOffset, IMG_UINT64 uiPacketSize,
+ IMG_UINT64 uiBufferSize);
+
+#else /* PDUMP */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSyncPrimPDumpKM)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVSyncPrimPDumpKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset)
+{
+ PVR_UNREFERENCED_PARAMETER(psSyncBlk);
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSyncPrimPDumpValueKM)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVSyncPrimPDumpValueKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value)
+{
+ PVR_UNREFERENCED_PARAMETER(psSyncBlk);
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSyncPrimPDumpPolKM)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVSyncPrimPDumpPolKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value, IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psSyncBlk);
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ PVR_UNREFERENCED_PARAMETER(ui32Mask);
+ PVR_UNREFERENCED_PARAMETER(eOperator);
+ PVR_UNREFERENCED_PARAMETER(uiDumpFlags);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSyncPrimOpPDumpPolKM)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVSyncPrimOpPDumpPolKM(SERVER_OP_COOKIE *psServerCookie,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T uiDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psServerCookie);
+ PVR_UNREFERENCED_PARAMETER(eOperator);
+ PVR_UNREFERENCED_PARAMETER(uiDumpFlags);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSyncPrimPDumpCBPKM)
+#endif
+static INLINE PVRSRV_ERROR
+PVRSRVSyncPrimPDumpCBPKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT64 ui32Offset,
+ IMG_UINT64 uiWriteOffset, IMG_UINT64 uiPacketSize,
+ IMG_UINT64 uiBufferSize)
+{
+ PVR_UNREFERENCED_PARAMETER(psSyncBlk);
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+ PVR_UNREFERENCED_PARAMETER(uiWriteOffset);
+ PVR_UNREFERENCED_PARAMETER(uiPacketSize);
+ PVR_UNREFERENCED_PARAMETER(uiBufferSize);
+ return PVRSRV_OK;
+}
+#endif /* PDUMP */
+#endif /*_SYNC_SERVER_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/sync_server_internal.h b/drivers/gpu/rogue/services/server/include/sync_server_internal.h
new file mode 100644
index 000000000000..3a913df40eff
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/sync_server_internal.h
@@ -0,0 +1,55 @@
+/**************************************************************************/ /*!
+@File
+@Title Server side internal synchronisation interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Describes the server side internal synchronisation 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.
+*/ /***************************************************************************/
+
+#ifndef _SYNC_SERVER_INTERNAL_H_
+#define _SYNC_SERVER_INTERNAL_H_
+
+#include "img_types.h"
+
+IMG_VOID
+ServerSyncRef(SERVER_SYNC_PRIMITIVE *psSync);
+
+IMG_VOID
+ServerSyncUnref(SERVER_SYNC_PRIMITIVE *psSync);
+
+#endif /*_SYNC_SERVER_INTERNAL_H_ */
diff --git a/drivers/gpu/rogue/services/server/include/tlintern.h b/drivers/gpu/rogue/services/server/include/tlintern.h
new file mode 100644
index 000000000000..714f79b05230
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/tlintern.h
@@ -0,0 +1,210 @@
+/*************************************************************************/ /*!
+@File
+@Title Transport Layer internals
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Transport Layer header used by TL internally
+@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 __TLINTERN_H__
+#define __TLINTERN_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "devicemem_typedefs.h"
+#include "pvr_tlcommon.h"
+#include "device.h"
+//Thread Safety: Not yet implemented #include "lock.h"
+
+/* Forward declarations */
+typedef struct _TL_SNODE_* PTL_SNODE;
+
+/*! TL stream structure container.
+ * pbyBuffer holds the circular buffer.
+ * ui32Read points to the beginning of the buffer, ie to where data to
+ * Read begin.
+ * ui32Write points to the end of data that have been committed, ie this is
+ * where new data will be written.
+ * ui32Pending number of bytes reserved in last reserve call which have not
+ * yet been submitted. Therefore these data are not ready to
+ * be transported.
+ *
+ * ui32Read < ui32Write <= ui32Pending
+ * where < and <= operators are overloaded to make sense in a circular way.
+ */
+typedef struct _TL_STREAM_
+{
+ IMG_CHAR szName[PRVSRVTL_MAX_STREAM_NAME_SIZE]; /*!< String name identifier */
+ IMG_BOOL bDrop; /*!< Flag: When buffer is full drop new data instead of
+ overwriting older data */
+ IMG_BOOL bBlock; /*!< Flag: When buffer is full reserve will block until there is
+ enough free space in the buffer to fullfil the request. */
+ IMG_BOOL bWaitForEmptyOnDestroy; /*!< Flag: On destroying a non empty stream block until
+ stream is drained. */
+ IMG_BOOL bNoSignalOnCommit; /*!< Flag: Used to avoid the TL signalling waiting consumers
+ that new data is available on every commit. Producers
+ using this flag will need to manually signal when
+ appropriate using the TLStreamSync() API */
+
+ IMG_VOID (*pfProducerCallback)(IMG_VOID); /*!< Optional producer callback of type TL_STREAM_SOURCECB */
+ IMG_PVOID pvProducerUserData; /*!< Producer callback user data */
+
+ volatile IMG_UINT32 ui32Read; /*!< Pointer to the beginning of available data */
+ volatile IMG_UINT32 ui32Write; /*!< Pointer to already committed data which are ready to be
+ copied to user space*/
+ IMG_UINT32 ui32BufferUt; /*!< Buffer utilisation high watermark, see
+ * TL_BUFFER_UTILIZATION in tlstream.c */
+ IMG_UINT32 ui32Pending; /*!< Count pending bytes reserved in buffer */
+ IMG_UINT32 ui32Size; /*!< Buffer size */
+ IMG_BYTE *pbyBuffer; /*!< Actual data buffer */
+
+ PTL_SNODE psNode; /*!< Ptr to parent stream node */
+ DEVMEM_MEMDESC *psStreamMemDesc; /*!< MemDescriptor used to allocate buffer space through PMR */
+ DEVMEM_EXPORTCOOKIE sExportCookie; /*!< Export cookie for stream DEVMEM */
+
+ IMG_HANDLE hProducerEvent; /*!< Handle to wait on if there is not enough space */
+ IMG_HANDLE hProducerEventObj; /*!< Handle to signal blocked reserve calls */
+
+//Thread Safety: Not yet implemented POS_LOCK hLock; /*!< lock this structure */
+ IMG_INT uiRefCount; /*!< Stream reference count */
+} TL_STREAM, *PTL_STREAM;
+
+/* there need to be enough space reserved in the buffer for 2 minimal packets
+ * and it needs to be aligned the same way the buffer is or there will be a
+ * compile error.*/
+#define BUFFER_RESERVED_SPACE 2*PVRSRVTL_PACKET_ALIGNMENT
+
+/* ensure the space reserved follows the buffer's alignment */
+BLD_ASSERT(!(BUFFER_RESERVED_SPACE&(PVRSRVTL_PACKET_ALIGNMENT-1)), tlintern_h);
+
+/* Define the largest value that a uint that matches the
+ * PVRSRVTL_PACKET_ALIGNMENT size can hold */
+#define MAX_UINT 0xffffFFFF
+
+/*! Defines the value used for TL_STREAM.ui32Pending when no reserve is
+ * outstanding on the stream. */
+#define NOTHING_PENDING IMG_UINT32_MAX
+
+
+/*
+ * Transport Layer Stream Descriptor types/defs
+ */
+typedef struct _TL_STREAM_DESC_
+{
+ PTL_SNODE psNode; /*!< Ptr to parent stream node */
+ IMG_UINT32 ui32Flags;
+ IMG_HANDLE hDataEvent; /*!< For wait call */
+} TL_STREAM_DESC, *PTL_STREAM_DESC;
+
+PTL_STREAM_DESC TLMakeStreamDesc(PTL_SNODE f1, IMG_UINT32 f2, IMG_HANDLE f3);
+
+#define TL_STREAM_KM_FLAG_MASK 0xFFFF0000
+#define TL_STREAM_FLAG_TEST 0x10000000
+#define TL_STREAM_FLAG_WRAPREAD 0x00010000
+
+#define TL_STREAM_UM_FLAG_MASK 0x0000FFFF
+
+/*
+ * Transport Layer stream list node
+ */
+typedef struct _TL_SNODE_
+{
+ struct _TL_SNODE_* psNext;
+ IMG_HANDLE hDataEventObj;
+ PTL_STREAM psStream;
+ PTL_STREAM_DESC psDesc;
+} TL_SNODE;
+
+PTL_SNODE TLMakeSNode(IMG_HANDLE f2, TL_STREAM *f3, TL_STREAM_DESC *f4);
+
+/*
+ * Transport Layer global top types and variables
+ * Use access function to obtain pointer.
+ */
+typedef struct _TL_GDATA_
+{
+ IMG_PVOID psRgxDevNode; /* Device node to use for buffer allocations */
+ IMG_HANDLE hTLEventObj; /* Global TL signal object, new streams, etc */
+
+ IMG_UINT uiClientCnt; /* Counter to track the number of client stream connections. */
+ PTL_SNODE psHead; /* List of Streams, only 1 node supported at present */
+
+} TL_GLOBAL_DATA, *PTL_GLOBAL_DATA;
+
+/*
+ * Transport Layer Internal Kernel-Mode Server API
+ */
+TL_GLOBAL_DATA* TLGGD(IMG_VOID); /* TLGetGlobalData() */
+
+PVRSRV_ERROR TLInit(PVRSRV_DEVICE_NODE *psDevNode);
+IMG_VOID TLDeInit(IMG_VOID);
+
+PVRSRV_DEVICE_NODE* TLGetGlobalRgxDevice(IMG_VOID);
+
+IMG_VOID TLAddStreamNode(PTL_SNODE psAdd);
+PTL_SNODE TLFindStreamNodeByName(IMG_PCHAR pszName);
+PTL_SNODE TLFindStreamNodeByDesc(PTL_STREAM_DESC psDesc);
+IMG_VOID TLRemoveStreamAndTryFreeStreamNode(PTL_SNODE psRemove);
+IMG_VOID TLRemoveDescAndTryFreeStreamNode(PTL_SNODE psRemove);
+
+/*
+ * Transport Layer stream interface to server part declared here to avoid
+ * circular dependency.
+ */
+IMG_UINT32 TLStreamAcquireReadPos(PTL_STREAM psStream, IMG_UINT32* puiReadOffset);
+IMG_VOID TLStreamAdvanceReadPos(PTL_STREAM psStream, IMG_UINT32 uiReadLen);
+
+DEVMEM_EXPORTCOOKIE* TLStreamGetBufferCookie(PTL_STREAM psStream);
+IMG_BOOL TLStreamEOS(PTL_STREAM psStream);
+
+/*
+ * Test related functions
+ */
+PVRSRV_ERROR TUtilsInit (IMG_VOID);
+PVRSRV_ERROR TUtilsDeinit (IMG_VOID);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __TLINTERN_H__ */
+/******************************************************************************
+ End of file (tlintern.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/server/include/tlserver.h b/drivers/gpu/rogue/services/server/include/tlserver.h
new file mode 100644
index 000000000000..3873dc9025aa
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/tlserver.h
@@ -0,0 +1,100 @@
+/*************************************************************************/ /*!
+@File
+@Title KM server Transport Layer implementation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main bridge APIs for Transport Layer client 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.
+*/ /**************************************************************************/
+
+#ifndef __TLSERVER_H_
+#define __TLSERVER_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+
+#include "tlintern.h"
+
+/*
+ * Transport Layer Client API Kernel-Mode bridge implementation
+ */
+
+PVRSRV_ERROR TLServerConnectKM(CONNECTION_DATA *psConnection);
+PVRSRV_ERROR TLServerDisconnectKM(CONNECTION_DATA *psConnection);
+
+PVRSRV_ERROR TLServerOpenStreamKM(IMG_PCHAR pszName,
+ IMG_UINT32 ui32Mode,
+ PTL_STREAM_DESC* ppsSD,
+ DEVMEM_EXPORTCOOKIE** ppsBufCookie);
+
+PVRSRV_ERROR TLServerCloseStreamKM(PTL_STREAM_DESC psSD);
+
+PVRSRV_ERROR TLServerAcquireDataKM(PTL_STREAM_DESC psSD,
+ IMG_UINT32* puiReadOffset,
+ IMG_UINT32* puiReadLen);
+
+PVRSRV_ERROR TLServerReleaseDataKM(PTL_STREAM_DESC psSD,
+ IMG_UINT32 uiReadOffset,
+ IMG_UINT32 uiReadLen);
+
+/*
+ * TEST INTERNAL ONLY
+ */
+
+PVRSRV_ERROR TLServerTestIoctlKM(IMG_UINT32 uiCmd,
+ IMG_PBYTE uiIn1,
+ IMG_UINT32 uiIn2,
+ IMG_UINT32* puiOut1,
+ IMG_UINT32* puiOut2);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __TLSERVER_H_ */
+
+/*****************************************************************************
+ End of file (tlserver.h)
+*****************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/server/include/tlstream.h b/drivers/gpu/rogue/services/server/include/tlstream.h
new file mode 100644
index 000000000000..faac3b59b12e
--- /dev/null
+++ b/drivers/gpu/rogue/services/server/include/tlstream.h
@@ -0,0 +1,336 @@
+/*************************************************************************/ /*!
+@File
+@Title Transport Layer kernel side API.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description TL provides driver components with a way to copy data from kernel
+ space to user space (e.g. screen/file).
+
+ Data can be passed to the Transport Layer through the
+ TL Stream (kernel space) API interface.
+
+ The buffer provided to every stream is a modified version of a
+ circular buffer. Which CB version is created is specified by
+ relevant flags when creating a stream. Currently two types
+ of buffer are available:
+ - TL_FLAG_DROP_DATA:
+ When the buffer is full, incoming data are dropped
+ (instead of overwriting older data) and a marker is set
+ to let the user know that data have been lost.
+ - TL_FLAG_BLOCKING_RESERVE:
+ When the circular buffer is full, reserve/write calls block
+ until enough space is freed.
+
+ All size/space requests are in bytes. However, the actual
+ implementation uses native word sizes (i.e. 4 byte aligned).
+
+ The user does not need to provide space for the stream buffer
+ as the TL handles memory allocations and usage.
+
+ Inserting data to a stream's buffer can be done either:
+ - by using TLReserve/TLCommit: User is provided with a buffer
+ to write data to.
+ - or by using TLWrite: User provides a buffer with
+ data to be committed. The TL
+ copies the data from the
+ buffer into the stream buffer
+ and returns.
+ Users should be aware that there are implementation overheads
+ associated with every stream buffer. If you find that less
+ data are captured than expected then try increasing the
+ stream buffer size or use TLInfo to obtain buffer parameters
+ and calculate optimum required values at run time.
+@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 __TLSTREAM_H__
+#define __TLSTREAM_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+#include "img_types.h"
+
+/*! Flags specifying stream and circular buffer behaviour */
+/*! Discard new data if the buffer is full */
+#define TL_FLAG_DROP_DATA (1U<<0)
+/*! Block Reserve (subsequently Write) calls if there is not enough space
+ * until some space is freed. */
+#define TL_FLAG_BLOCKING_RESERVE (1U<<1)
+/*! Do not destroy stream if there still are data that have not been
+ * copied in user space. BLock until the stream is emptied. */
+#define TL_FLAG_FORCE_FLUSH (1U<<2)
+/*! Do not signal consumers on commit automatically when the stream buffer
+ * transitions from empty to non-empty. Producer responsible for signal when
+ * it chooses. */
+#define TL_FLAG_NO_SIGNAL_ON_COMMIT (1U<<3)
+
+/*! Structure used to pass internal TL stream sizes information to users.*/
+typedef struct _TL_STREAM_INFO_
+{
+ IMG_UINT32 headerSize; /*!< Packet header size in bytes */
+ IMG_UINT32 minReservationSize; /*!< Minimum data size reserved in bytes */
+ IMG_UINT32 pageSize; /*!< Page size in bytes */
+ IMG_UINT32 pageAlign; /*!< Page alignment in bytes */
+} TL_STREAM_INFO, *PTL_STREAM_INFO;
+
+/*! Callback operations or notifications that a stream producer may handle
+ * when requested by the Transport Layer.
+ */
+#define TL_SOURCECB_OP_CLIENT_EOS 0x01 /*!< Client has reached end of stream,
+ * can anymore data be supplied?
+ * ui32Resp ignored in this operation */
+
+/*! Function pointer type for the callback handler into the "producer" code
+ * that writes data to the TL stream. Producer should handle the notification
+ * or operation supplied in ui32ReqOp on stream hStream. The
+ * Operations and notifications are defined above in TL_SOURCECB_OP */
+typedef PVRSRV_ERROR (*TL_STREAM_SOURCECB)(IMG_HANDLE hStream,
+ IMG_UINT32 ui32ReqOp, IMG_UINT32* ui32Resp, IMG_VOID* pvUser);
+
+/*************************************************************************/ /*!
+ @Function TLStreamCreate
+ @Description Request the creation of a new stream and open a handle.
+ If creating a stream which should continue to exist after the
+ current context is finished, then TLStreamCreate must be
+ followed by a TLStreamOpen call. On any case, the number of
+ create/open calls must balance with the number of close calls
+ used. This ensures the resources of a stream are released when
+ it is no longer required.
+ @Output phStream Pointer to handle to store the new stream.
+ @Input szStreamName Name of stream, maximum length:
+ PRVSRVTL_MAX_STREAM_NAME_SIZE.
+ If a longer string is provided,creation fails.
+ @Input ui32Size Desired buffer size in bytes.
+ @Input ui32StreamFlags Flags that configure buffer behaviour.See above.
+ @Input pfProducerDB Optional callback, may be null.
+ @Input pvProducerData Optional user data for callback, may be null.
+ @Return PVRSRV_ERROR_INVALID_PARAMS NULL stream handle or string name
+ exceeded MAX_STREAM_NAME_SIZE
+ @Return PVRSRV_ERROR_OUT_OF_MEMORY Failed to allocate space for stream
+ handle.
+ @Return PVRSRV_ERROR_DUPLICATE_VALUE There already exists a stream with
+ the same stream name string.
+ @Return eError Internal services call returned
+ eError error number.
+ @Return PVRSRV_OK
+*/ /**************************************************************************/
+PVRSRV_ERROR
+TLStreamCreate(IMG_HANDLE *phStream,
+ IMG_CHAR *szStreamName,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32StreamFlags,
+ TL_STREAM_SOURCECB pfProducerCB,
+ IMG_PVOID pvProducerUD);
+
+/*************************************************************************/ /*!
+ @Function TLStreamOpen
+ @Description Attach to existing stream that has already been created by a
+ TLStreamCreate call. A handle is returned to the stream.
+ @Output phStream Pointer to handle to store the stream.
+ @Input szStreamName Name of stream, should match an already
+ existing stream name
+ @Return PVRSRV_ERROR_NOT_FOUND None of the streams matched the
+ requested stream name.
+ PVRSRV_ERROR_INVALID_PARAMS non NULL pointer to stream
+ handler is required.
+ @Return PVRSRV_OK Success.
+*/ /**************************************************************************/
+PVRSRV_ERROR
+TLStreamOpen(IMG_HANDLE *phStream,
+ IMG_CHAR *szStreamName);
+
+/*************************************************************************/ /*!
+ @Function TLStreamClose
+ @Description Detach from the stream associated with the given handle. If
+ the current handle is the last one accessing the stream
+ (i.e. the number of TLStreamCreate+TLStreamOpen calls matches
+ the number of TLStreamClose calls) then the stream is also
+ deleted.
+ On return the handle is no longer valid.
+ @Input hStream Handle to stream that will be closed.
+ @Return None.
+*/ /**************************************************************************/
+IMG_VOID
+TLStreamClose(IMG_HANDLE hStream);
+
+/*************************************************************************/ /*!
+ @Function TLStreamReserve
+ @Description Reserve space in stream buffer. When successful every
+ TLStreamReserve call must be followed by a matching
+ TLStreamCommit call. While a TLStreamCommit call is pending
+ for a stream, subsequent TLStreamReserve calls for this
+ stream will fail.
+ @Input hStream Stream handle.
+ @Output ppui8Data Pointer to a pointer to a location in the
+ buffer. The caller can then use this address
+ in writing data into the stream.
+ @Input ui32Size Number of bytes to reserve in buffer.
+ @Return PVRSRV_INVALID_PARAMS NULL stream handler.
+ @Return PVRSRV_ERROR_NOT_READY There are data previously reserved
+ that are pending to be committed.
+ @Return PVRSRV_ERROR_STREAM_MISUSE Misusing the stream by trying to
+ reserve more space than the
+ buffer size.
+ PVRSRV_ERROR_STREAM_FULL Stream buffer full, data not written
+ @Return PVRSRV_OK Success, output arguments valid.
+*/ /**************************************************************************/
+PVRSRV_ERROR
+TLStreamReserve(IMG_HANDLE hStream,
+ IMG_UINT8 **ppui8Data,
+ IMG_UINT32 ui32Size);
+
+/*************************************************************************/ /*!
+ @Function TLStreamReserve2
+ @Description Reserve space in stream buffer. When successful every
+ TLStreamReserve call must be followed by a matching
+ TLStreamCommit call. While a TLStreamCommit call is pending
+ for a stream, subsequent TLStreamReserve calls for this
+ stream will fail.
+ @Input hStream Stream handle.
+ @Output ppui8Data Pointer to a pointer to a location in the
+ buffer. The caller can then use this address
+ in writing data into the stream.
+ @Input ui32Size Ideal number of bytes to reserve in buffer.
+ @Input ui32SizeMin Minimum number of bytes to reserve in buffer.
+ @Input pui32Available Optional, but when present and the FULL error
+ is returned, a size suggestion is returned
+ in this argument which the caller can attempt
+ to reserve again for a successful allocation.
+ @Return PVRSRV_INVALID_PARAMS NULL stream handler.
+ @Return PVRSRV_ERROR_NOT_READY There are data previously reserved
+ that are pending to be committed.
+ @Return PVRSRV_ERROR_STREAM_MISUSE Misusing the stream by trying to
+ reserve more space than the
+ buffer size.
+ PVRSRV_ERROR_STREAM_FULL Stream buffer full, data not written
+ @Return PVRSRV_OK Success, output arguments valid.
+*/ /**************************************************************************/
+PVRSRV_ERROR
+TLStreamReserve2(IMG_HANDLE hStream,
+ IMG_UINT8 **ppui8Data,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32SizeMin,
+ IMG_UINT32* pui32Available);
+
+/*************************************************************************/ /*!
+ @Function TLStreamCommit
+ @Description Notify TL that data have been written in the stream buffer.
+ Should always follow and match TLStreamReserve call.
+ @Input hStream Stream handle.
+ @Input ui32Size Number of bytes that have been added to the
+ stream.
+ @Return PVRSRV_ERROR_INVALID_PARAMS NULL stream handle.
+ @Return PVRSRV_ERROR_STREAM_MISUSE Commit results in more data
+ committed than the buffer size,
+ the stream is misused.
+ @Return eError Commit was successful but
+ internal services call returned
+ eError error number.
+ @Return PVRSRV_OK
+*/ /**************************************************************************/
+PVRSRV_ERROR
+TLStreamCommit(IMG_HANDLE hStream,
+ IMG_UINT32 ui32Size);
+
+/*************************************************************************/ /*!
+ @Function TLStreamWrite
+ @Description Combined Reserve/Commit call. This function Reserves space in
+ the specified stream buffer, copies ui32Size bytes of data
+ from the array pui8Src points to and Commits in an "atomic"
+ style operation.
+ @Input hStream Stream handle.
+ @Input pui8Src Source to read data from.
+ @Input ui32Size Number of bytes to copy and commit.
+ @Return PVRSRV_ERROR_INVALID_PARAMS NULL stream handler.
+ @Return eError Error codes returned by either
+ Reserve or Commit.
+ @Return PVRSRV_OK
+ */ /**************************************************************************/
+PVRSRV_ERROR
+TLStreamWrite(IMG_HANDLE hStream,
+ IMG_UINT8 *pui8Src,
+ IMG_UINT32 ui32Size);
+
+/*************************************************************************/ /*!
+ @Function TLStreamSync
+ @Description Signal the consumer to start acquiring data from the stream
+ buffer. Called by producers that use the TL_FLAG_NO_SIGNAL_ON_COMMIT
+ flag to manually control when consumers starting reading the
+ stream. Used when multiple small writes need to be batched.
+ @Input hStream Stream handle.
+ @Return PVRSRV_ERROR_INVALID_PARAMS NULL stream handle.
+ @Return eError Error codes returned by either
+ Reserve or Commit.
+ @Return PVRSRV_OK
+ */ /**************************************************************************/
+PVRSRV_ERROR
+TLStreamSync(IMG_HANDLE hStream);
+
+
+/*************************************************************************/ /*!
+ @Function TLStreamMarkEOS
+ @Description Insert a EOS marker packet in the given stream.
+ @Input hStream Stream handle.
+ @Return PVRSRV_ERROR_INVALID_PARAMS NULL stream handler.
+ @Return eError Error codes returned by either
+ Reserve or Commit.
+ @Return PVRSRV_OK Success.
+*/ /**************************************************************************/
+PVRSRV_ERROR
+TLStreamMarkEOS(IMG_HANDLE hStream);
+
+/*************************************************************************/ /*!
+ @Function TLStreamInfo
+ @Description Run time information about buffer elemental sizes.
+ It sets psInfo members accordingly. Users can use those values
+ to calculate the parameters they use in TLStreamCreate and
+ TLStreamReserve.
+ @Output psInfo pointer to stream info structure.
+ @Return None.
+*/ /**************************************************************************/
+IMG_VOID
+TLStreamInfo(PTL_STREAM_INFO psInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __TLSTREAM_H__ */
+/*****************************************************************************
+ End of file (tlstream.h)
+*****************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/shared/common/devicemem.c b/drivers/gpu/rogue/services/shared/common/devicemem.c
new file mode 100755
index 000000000000..b4d49d67fd4b
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/devicemem.c
@@ -0,0 +1,1951 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Front End (nominally Client side part, but now invokable
+ from server too) of device memory management
+@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 "devicemem.h"
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "allocmem.h"
+#include "ra.h"
+#include "osfunc.h"
+#include "devicemem_mmap.h"
+#include "devicemem_utils.h"
+#include "client_mm_bridge.h"
+#if defined(PDUMP)
+#include "devicemem_pdump.h"
+#endif
+#if defined(PVR_RI_DEBUG)
+#include "client_ri_bridge.h"
+#endif
+
+#if defined(__KERNEL__)
+#include "pvrsrv.h"
+#if defined(LINUX)
+#include "linux/kernel.h"
+#endif
+#endif
+
+/* Storing the page size here so we do not have to hard code it in the code anymore
+ Should be initialised to the correct value at driver init time.
+ Use macros from devicemem.h to access from outside.
+ */
+IMG_UINT32 g_uiLog2PageSize = 0;
+
+static PVRSRV_ERROR
+_Mapping_Export(DEVMEM_IMPORT *psImport,
+ DEVMEM_EXPORTHANDLE *phPMRExportHandlePtr,
+ DEVMEM_EXPORTKEY *puiExportKeyPtr,
+ DEVMEM_SIZE_T *puiSize,
+ DEVMEM_LOG2ALIGN_T *puiLog2Contig)
+{
+ /* Gets an export handle and key for the PMR used for this mapping */
+ /* Can only be done if there are no suballocations for this mapping */
+
+ PVRSRV_ERROR eError;
+ DEVMEM_EXPORTHANDLE hPMRExportHandle;
+ DEVMEM_EXPORTKEY uiExportKey;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2Contig;
+
+ if (psImport == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto failParams;
+ }
+
+ if (!psImport->bExportable)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_CANT_EXPORT_SUBALLOCATION;
+ goto failParams;
+ }
+
+ eError = BridgePMRExportPMR(psImport->hBridge,
+ psImport->hPMR,
+ &hPMRExportHandle,
+ &uiSize,
+ &uiLog2Contig,
+ &uiExportKey);
+ if (eError != PVRSRV_OK)
+ {
+ goto failExport;
+ }
+
+ PVR_ASSERT(uiSize == psImport->uiSize);
+
+ *phPMRExportHandlePtr = hPMRExportHandle;
+ *puiExportKeyPtr = uiExportKey;
+ *puiSize = uiSize;
+ *puiLog2Contig = uiLog2Contig;
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+failExport:
+failParams:
+
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+
+}
+
+static IMG_VOID
+_Mapping_Unexport(DEVMEM_IMPORT *psImport,
+ DEVMEM_EXPORTHANDLE hPMRExportHandle)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT (psImport != IMG_NULL);
+
+ eError = BridgePMRUnexportPMR(psImport->hBridge,
+ hPMRExportHandle);
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+/*****************************************************************************
+ * Sub allocation internals *
+ *****************************************************************************/
+
+static PVRSRV_ERROR
+_AllocateDeviceMemory(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 uiLog2Quantum,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags,
+ IMG_BOOL bExportable,
+ DEVMEM_IMPORT **ppsImport)
+{
+ DEVMEM_IMPORT *psImport;
+ DEVMEM_FLAGS_T uiPMRFlags;
+ IMG_HANDLE hPMR;
+ PVRSRV_ERROR eError;
+
+ eError = _DevmemImportStructAlloc(hBridge,
+ bExportable,
+ &psImport);
+ if (eError != PVRSRV_OK)
+ {
+ goto failAlloc;
+ }
+
+ /* Check the size is a multiple of the quantum */
+ PVR_ASSERT((uiSize & ((1ULL<<uiLog2Quantum)-1)) == 0);
+
+ /* Pass only the PMR flags down */
+ uiPMRFlags = uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK;
+
+ eError = BridgePhysmemNewRamBackedPMR(hBridge,
+ hDeviceNode,
+ uiSize,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ pabMappingTable,
+ uiLog2Quantum,
+ uiPMRFlags,
+ &hPMR);
+ if (eError != PVRSRV_OK)
+ {
+ /* Our check above should have ensured this the "not page
+ multiple" error never happens */
+ PVR_ASSERT(eError != PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE);
+
+ goto failPMR;
+ }
+
+ _DevmemImportStructInit(psImport,
+ uiSize,
+ uiAlign,
+ uiFlags,
+ hPMR);
+
+ *ppsImport = psImport;
+ return PVRSRV_OK;
+
+failPMR:
+ _DevmemImportDiscard(psImport);
+failAlloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+static IMG_VOID
+_FreeDeviceMemory(DEVMEM_IMPORT *psImport)
+{
+ _DevmemImportStructRelease(psImport);
+}
+
+static IMG_BOOL
+_SubAllocImportAlloc(RA_PERARENA_HANDLE hArena,
+ RA_LENGTH_T uiSize,
+ RA_FLAGS_T _flags,
+ /* returned data */
+ RA_BASE_T *puiBase,
+ RA_LENGTH_T *puiActualSize,
+ RA_PERISPAN_HANDLE *phImport)
+{
+ /* When suballocations need a new lump of memory, the RA calls
+ back here. Later, in the kernel, we must construct a new PMR
+ and a pairing between the new lump of virtual memory and the
+ PMR (whether or not such PMR is backed by physical memory) */
+ DEVMEM_HEAP *psHeap;
+ DEVMEM_IMPORT *psImport;
+ IMG_DEVMEM_ALIGN_T uiAlign;
+ DEVMEM_FLAGS_T uiFlags;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bMappingTable = IMG_TRUE;
+
+ uiFlags = (DEVMEM_FLAGS_T) _flags;
+
+ /* Per-arena private handle is, for us, the heap */
+ psHeap = hArena;
+
+ /* align to the l.s.b. of the size... e.g. 96kiB aligned to
+ 32kiB. NB: There is an argument to say that the RA should never
+ ask us for Non-power-of-2 size anyway, but I don't want to make
+ that restriction arbitrarily now */
+ uiAlign = uiSize & ~(uiSize-1);
+
+ /* The RA should not have invoked us with a size that is not a
+ multiple of the quantum anyway */
+ PVR_ASSERT((uiSize & ((1ULL<<psHeap->uiLog2Quantum)-1)) == 0);
+
+ eError = _AllocateDeviceMemory(psHeap->psCtx->hBridge,
+ psHeap->psCtx->hDeviceNode,
+ psHeap->uiLog2Quantum,
+ uiSize,
+ uiSize,
+ 1,
+ 1,
+ &bMappingTable,
+ uiAlign,
+ uiFlags,
+ IMG_FALSE,
+ &psImport);
+ if (eError != PVRSRV_OK)
+ {
+ goto failAlloc;
+ }
+
+#if defined(PVR_RI_DEBUG)
+ {
+ eError = BridgeRIWritePMREntry (psImport->hBridge,
+ psImport->hPMR,
+ sizeof("PMR sub-allocated"),
+ "PMR sub-allocated",
+ psImport->uiSize);
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
+ }
+ }
+#endif
+ /*
+ Suballocations always get mapped into the device was we need to
+ key the RA off something and as we can't export suballocations
+ there is no valid reason to request an allocation an not map it
+ */
+ eError = _DevmemImportStructDevMap(psHeap,
+ IMG_TRUE,
+ psImport);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMap;
+ }
+
+ *puiBase = psImport->sDeviceImport.sDevVAddr.uiAddr;
+ *puiActualSize = uiSize;
+ *phImport = psImport;
+
+ return IMG_TRUE;
+
+ /*
+ error exit paths follow
+ */
+failMap:
+ _FreeDeviceMemory(psImport);
+failAlloc:
+
+ return IMG_FALSE;
+}
+
+static IMG_VOID
+_SubAllocImportFree(RA_PERARENA_HANDLE hArena,
+ RA_BASE_T uiBase,
+ RA_PERISPAN_HANDLE hImport)
+{
+ DEVMEM_IMPORT *psImport = hImport;
+
+ PVR_ASSERT(psImport != IMG_NULL);
+ PVR_ASSERT(hArena == psImport->sDeviceImport.psHeap);
+ PVR_ASSERT(uiBase == psImport->sDeviceImport.sDevVAddr.uiAddr);
+
+ _DevmemImportStructDevUnmap(psImport);
+ _DevmemImportStructRelease(psImport);
+}
+
+/*****************************************************************************
+ * Devmem context internals *
+ *****************************************************************************/
+
+static PVRSRV_ERROR
+_PopulateContextFromBlueprint(struct _DEVMEM_CONTEXT_ *psCtx,
+ IMG_HANDLE hDeviceNode,
+ DEVMEM_HEAPCFGID uiHeapBlueprintID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError2;
+ struct _DEVMEM_HEAP_ **ppsHeapArray;
+ IMG_UINT32 uiNumHeaps;
+ IMG_UINT32 uiHeapsToUnwindOnError;
+ IMG_UINT32 uiHeapIndex;
+ IMG_DEV_VIRTADDR sDevVAddrBase;
+ IMG_CHAR aszHeapName[DEVMEM_HEAPNAME_MAXLENGTH];
+ IMG_DEVMEM_SIZE_T uiHeapLength;
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2DataPageSize;
+
+ eError = DevmemHeapCount(psCtx->hBridge,
+ hDeviceNode,
+ uiHeapBlueprintID,
+ &uiNumHeaps);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ if (uiNumHeaps == 0)
+ {
+ ppsHeapArray = IMG_NULL;
+ }
+ else
+ {
+ ppsHeapArray = OSAllocMem(sizeof(*ppsHeapArray) * uiNumHeaps);
+ if (ppsHeapArray == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+ }
+
+ uiHeapsToUnwindOnError = 0;
+
+ for (uiHeapIndex = 0; uiHeapIndex < uiNumHeaps; uiHeapIndex++)
+ {
+ eError = DevmemHeapDetails(psCtx->hBridge,
+ hDeviceNode,
+ uiHeapBlueprintID,
+ uiHeapIndex,
+ &aszHeapName[0],
+ sizeof(aszHeapName),
+ &sDevVAddrBase,
+ &uiHeapLength,
+ &uiLog2DataPageSize);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ eError = DevmemCreateHeap(psCtx,
+ sDevVAddrBase,
+ uiHeapLength,
+ uiLog2DataPageSize,
+ aszHeapName,
+ &ppsHeapArray[uiHeapIndex]);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ uiHeapsToUnwindOnError = uiHeapIndex + 1;
+ }
+
+ psCtx->uiAutoHeapCount = uiNumHeaps;
+ psCtx->ppsAutoHeapArray = ppsHeapArray;
+
+ PVR_ASSERT(psCtx->uiNumHeaps >= psCtx->uiAutoHeapCount);
+ PVR_ASSERT(psCtx->uiAutoHeapCount == uiNumHeaps);
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths
+ */
+ e1:
+ for (uiHeapIndex = 0; uiHeapIndex < uiHeapsToUnwindOnError; uiHeapIndex++)
+ {
+ eError2 = DevmemDestroyHeap(ppsHeapArray[uiHeapIndex]);
+ PVR_ASSERT(eError2 == PVRSRV_OK);
+ }
+
+ if (uiNumHeaps != 0)
+ {
+ OSFreeMem(ppsHeapArray);
+ }
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+static IMG_VOID
+_UnpopulateContextFromBlueprint(struct _DEVMEM_CONTEXT_ *psCtx)
+{
+ PVRSRV_ERROR eError2;
+ IMG_UINT32 uiHeapIndex;
+ IMG_BOOL bDoCheck = IMG_TRUE;
+#if defined(__KERNEL__)
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+ {
+ bDoCheck = IMG_FALSE;
+ }
+#endif
+
+ PVR_ASSERT(psCtx->uiNumHeaps >= psCtx->uiAutoHeapCount);
+
+ for (uiHeapIndex = 0; uiHeapIndex < psCtx->uiAutoHeapCount; uiHeapIndex++)
+ {
+ eError2 = DevmemDestroyHeap(psCtx->ppsAutoHeapArray[uiHeapIndex]);
+ if (bDoCheck)
+ {
+ PVR_ASSERT(eError2 == PVRSRV_OK);
+ }
+ }
+
+ if (psCtx->uiAutoHeapCount != 0)
+ {
+ OSFreeMem(psCtx->ppsAutoHeapArray);
+ psCtx->ppsAutoHeapArray = IMG_NULL;
+ }
+ psCtx->uiAutoHeapCount = 0;
+
+ PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
+ PVR_ASSERT(psCtx->ppsAutoHeapArray == IMG_NULL);
+}
+
+
+/*****************************************************************************
+ * Devmem context functions *
+ *****************************************************************************/
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemCreateContext(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ DEVMEM_HEAPCFGID uiHeapBlueprintID,
+ DEVMEM_CONTEXT **ppsCtxPtr)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_CONTEXT *psCtx;
+ /* handle to the server-side counterpart of the device memory
+ context (specifically, for handling mapping to device MMU) */
+ IMG_HANDLE hDevMemServerContext;
+ IMG_HANDLE hPrivData;
+
+
+ if (ppsCtxPtr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ psCtx = OSAllocMem(sizeof *psCtx);
+ if (psCtx == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+
+ psCtx->uiNumHeaps = 0;
+
+ psCtx->hBridge = hBridge;
+
+ /* Create (server-side) Device Memory context */
+ eError = BridgeDevmemIntCtxCreate(psCtx->hBridge,
+ hDeviceNode,
+ &hDevMemServerContext,
+ &hPrivData);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+ psCtx->hDeviceNode = hDeviceNode;
+ psCtx->hDevMemServerContext = hDevMemServerContext;
+ psCtx->hPrivData = hPrivData;
+
+ /* automagic heap creation */
+ psCtx->uiAutoHeapCount = 0;
+
+ eError = _PopulateContextFromBlueprint(psCtx, hDeviceNode, uiHeapBlueprintID);
+ if (eError != PVRSRV_OK)
+ {
+ goto e2;
+ }
+
+
+ *ppsCtxPtr = psCtx;
+
+
+ PVR_ASSERT(psCtx->uiNumHeaps == psCtx->uiAutoHeapCount);
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+ e2:
+ PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
+ PVR_ASSERT(psCtx->uiNumHeaps == 0);
+ BridgeDevmemIntCtxDestroy(psCtx->hBridge, hDevMemServerContext);
+
+ e1:
+ OSFreeMem(psCtx);
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemAcquireDevPrivData(DEVMEM_CONTEXT *psCtx,
+ IMG_HANDLE *hPrivData)
+{
+ PVRSRV_ERROR eError;
+
+ if ((psCtx == IMG_NULL) || (hPrivData == IMG_NULL))
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ *hPrivData = psCtx->hPrivData;
+ return PVRSRV_OK;
+
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemReleaseDevPrivData(DEVMEM_CONTEXT *psCtx)
+{
+ PVRSRV_ERROR eError;
+
+ if (psCtx == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+ return PVRSRV_OK;
+
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemFindHeapByName(const struct _DEVMEM_CONTEXT_ *psCtx,
+ const IMG_CHAR *pszHeapName,
+ struct _DEVMEM_HEAP_ **ppsHeapRet)
+{
+ IMG_UINT32 uiHeapIndex;
+
+ /* N.B. This func is only useful for finding "automagic" heaps by name */
+ for (uiHeapIndex = 0;
+ uiHeapIndex < psCtx->uiAutoHeapCount;
+ uiHeapIndex++)
+ {
+ if (!OSStringCompare(psCtx->ppsAutoHeapArray[uiHeapIndex]->pszName, pszHeapName))
+ {
+ *ppsHeapRet = psCtx->ppsAutoHeapArray[uiHeapIndex];
+ return PVRSRV_OK;
+ }
+ }
+
+ return PVRSRV_ERROR_DEVICEMEM_INVALID_HEAP_INDEX;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemDestroyContext(DEVMEM_CONTEXT *psCtx)
+{
+ PVRSRV_ERROR eError;
+ IMG_BOOL bDoCheck = IMG_TRUE;
+
+#if defined(__KERNEL__)
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+ {
+ bDoCheck = IMG_FALSE;
+ }
+#endif
+
+ if (psCtx == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* should be only the automagically instantiated heaps left */
+ if (psCtx->uiNumHeaps != psCtx->uiAutoHeapCount)
+ {
+ return PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
+ }
+
+ _UnpopulateContextFromBlueprint(psCtx);
+
+ if (bDoCheck)
+ {
+ PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
+ PVR_ASSERT(psCtx->uiNumHeaps == 0);
+ }
+ eError = BridgeDevmemIntCtxDestroy(psCtx->hBridge,
+ psCtx->hDevMemServerContext);
+ if (bDoCheck)
+ {
+ PVR_ASSERT (eError == PVRSRV_OK);
+ }
+
+ OSFreeMem(psCtx);
+
+ return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ * Devmem heap query functions *
+ *****************************************************************************/
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemHeapConfigCount(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 *puiNumHeapConfigsOut)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgeHeapCfgHeapConfigCount(hBridge,
+ hDeviceNode,
+ puiNumHeapConfigsOut);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemHeapCount(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 *puiNumHeapsOut)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgeHeapCfgHeapCount(hBridge,
+ hDeviceNode,
+ uiHeapConfigIndex,
+ puiNumHeapsOut);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemHeapConfigName(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_CHAR *pszConfigNameOut,
+ IMG_UINT32 uiConfigNameBufSz)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgeHeapCfgHeapConfigName(hBridge,
+ hDeviceNode,
+ uiHeapConfigIndex,
+ uiConfigNameBufSz,
+ pszConfigNameOut);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemHeapDetails(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 uiHeapIndex,
+ IMG_CHAR *pszHeapNameOut,
+ IMG_UINT32 uiHeapNameBufSz,
+ IMG_DEV_VIRTADDR *psDevVAddrBaseOut,
+ IMG_DEVMEM_SIZE_T *puiHeapLengthOut,
+ IMG_UINT32 *puiLog2DataPageSizeOut)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgeHeapCfgHeapDetails(hBridge,
+ hDeviceNode,
+ uiHeapConfigIndex,
+ uiHeapIndex,
+ uiHeapNameBufSz,
+ pszHeapNameOut,
+ psDevVAddrBaseOut,
+ puiHeapLengthOut,
+ puiLog2DataPageSizeOut);
+
+ VG_MARK_INITIALIZED(pszHeapNameOut,uiHeapNameBufSz);
+
+ return eError;
+}
+
+/*****************************************************************************
+ * Devmem heap functions *
+ *****************************************************************************/
+
+/* See devicemem.h for important notes regarding the arguments
+ to this function */
+IMG_INTERNAL PVRSRV_ERROR
+DevmemCreateHeap(DEVMEM_CONTEXT *psCtx,
+ IMG_DEV_VIRTADDR sBaseAddress,
+ IMG_DEVMEM_SIZE_T uiLength,
+ IMG_UINT32 ui32Log2Quantum,
+ const IMG_CHAR *pszName,
+ DEVMEM_HEAP **ppsHeapPtr)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_ERROR eError2;
+ DEVMEM_HEAP *psHeap;
+ /* handle to the server-side counterpart of the device memory
+ heap (specifically, for handling mapping to device MMU */
+ IMG_HANDLE hDevMemServerHeap;
+
+ IMG_CHAR aszBuf[100];
+ IMG_CHAR *pszStr;
+
+ if (ppsHeapPtr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ psHeap = OSAllocMem(sizeof *psHeap);
+ if (psHeap == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+
+ /* Need to keep local copy of heap name, so caller may free
+ theirs */
+ pszStr = OSAllocMem(OSStringLength(pszName)+1);
+ if (pszStr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e1;
+ }
+ OSStringCopy(pszStr, pszName);
+ psHeap->pszName = pszStr;
+
+ psHeap->sBaseAddress = sBaseAddress;
+ psHeap->uiImportCount = 0;
+
+ OSSNPrintf(aszBuf, sizeof(aszBuf),
+ "NDM heap '%s' (suballocs) ctx:%p",
+ pszName, psCtx);
+ pszStr = OSAllocMem(OSStringLength(aszBuf)+1);
+ if (pszStr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e2;
+ }
+ OSStringCopy(pszStr, aszBuf);
+ psHeap->pszSubAllocRAName = pszStr;
+
+ psHeap->psSubAllocRA = RA_Create(psHeap->pszSubAllocRAName,
+ /* Subsequent imports: */
+ ui32Log2Quantum,
+ RA_LOCKCLASS_2,
+ _SubAllocImportAlloc,
+ _SubAllocImportFree,
+ (RA_PERARENA_HANDLE) psHeap);
+ if (psHeap->psSubAllocRA == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
+ goto e3;
+ }
+
+ psHeap->uiLog2Quantum = ui32Log2Quantum;
+
+ OSSNPrintf(aszBuf, sizeof(aszBuf),
+ "NDM heap '%s' (QVM) ctx:%p",
+ pszName, psCtx);
+ pszStr = OSAllocMem(OSStringLength(aszBuf)+1);
+ if (pszStr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e4;
+ }
+ OSStringCopy(pszStr, aszBuf);
+ psHeap->pszQuantizedVMRAName = pszStr;
+
+ psHeap->psQuantizedVMRA = RA_Create(psHeap->pszQuantizedVMRAName,
+ /* Subsequent import: */
+ 0, RA_LOCKCLASS_1, IMG_NULL, IMG_NULL,
+ (RA_PERARENA_HANDLE) psHeap);
+
+ if (psHeap->psQuantizedVMRA == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
+ goto e5;
+ }
+
+ if (!RA_Add(psHeap->psQuantizedVMRA,
+ (RA_BASE_T)sBaseAddress.uiAddr,
+ (RA_LENGTH_T)uiLength,
+ (RA_FLAGS_T)0, /* This RA doesn't use or need flags */
+ IMG_NULL /* per ispan handle */))
+ {
+ RA_Delete(psHeap->psQuantizedVMRA);
+ eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
+ goto e5;
+ }
+
+
+ psHeap->psCtx = psCtx;
+
+
+ /* Create server-side counterpart of Device Memory heap */
+ eError = BridgeDevmemIntHeapCreate(psCtx->hBridge,
+ psCtx->hDevMemServerContext,
+ sBaseAddress,
+ uiLength,
+ ui32Log2Quantum,
+ &hDevMemServerHeap);
+ if (eError != PVRSRV_OK)
+ {
+ goto e6;
+ }
+ psHeap->hDevMemServerHeap = hDevMemServerHeap;
+
+ eError = OSLockCreate(&psHeap->hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto e7;
+ }
+
+ psHeap->psCtx->uiNumHeaps ++;
+ *ppsHeapPtr = psHeap;
+
+#if defined PVRSRV_NEWDEVMEM_SUPPORT_MEM_TRACKING
+ psHeap->psMemDescList = IMG_NULL;
+#endif /* PVRSRV_NEWDEVMEM_SUPPORT_MEM_TRACKING */
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths
+ */
+ e7:
+ eError2 = BridgeDevmemIntHeapDestroy(psCtx->hBridge,
+ psHeap->hDevMemServerHeap);
+ PVR_ASSERT (eError2 == PVRSRV_OK);
+ e6:
+ RA_Delete(psHeap->psQuantizedVMRA);
+ e5:
+ OSFreeMem(psHeap->pszQuantizedVMRAName);
+ e4:
+ RA_Delete(psHeap->psSubAllocRA);
+ e3:
+ OSFreeMem(psHeap->pszSubAllocRAName);
+ e2:
+ OSFreeMem(psHeap->pszName);
+ e1:
+ OSFreeMem(psHeap);
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetHeapBaseDevVAddr(struct _DEVMEM_HEAP_ *psHeap,
+ IMG_DEV_VIRTADDR *pDevVAddr)
+{
+ if (psHeap == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *pDevVAddr = psHeap->sBaseAddress;
+
+ return PVRSRV_OK;
+}
+
+IMG_INTERNAL IMG_VOID
+DevmemExportalignAdjustSizeAndAlign(DEVMEM_HEAP *psHeap, IMG_DEVMEM_SIZE_T *puiSize, IMG_DEVMEM_ALIGN_T *puiAlign)
+{
+ IMG_DEVMEM_SIZE_T uiSize = *puiSize;
+ IMG_DEVMEM_ALIGN_T uiAlign = *puiAlign;
+ IMG_UINT32 uiLog2Quantum;
+
+ if (psHeap)
+ {
+ uiLog2Quantum = psHeap->uiLog2Quantum;
+ }
+ else
+ {
+ uiLog2Quantum = GET_LOG2_PAGESIZE();
+ }
+
+ if ((1ULL << uiLog2Quantum) > uiAlign)
+ {
+ uiAlign = 1ULL << uiLog2Quantum;
+ }
+ uiSize = (uiSize + uiAlign - 1) & ~(uiAlign - 1);
+
+ *puiSize = uiSize;
+ *puiAlign = uiAlign;
+}
+
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemDestroyHeap(DEVMEM_HEAP *psHeap)
+{
+ PVRSRV_ERROR eError;
+
+ if (psHeap == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (psHeap->uiImportCount > 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%d(%s) leaks remain", psHeap->uiImportCount, psHeap->pszName));
+ return PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
+ }
+
+ OSLockDestroy(psHeap->hLock);
+
+ PVR_ASSERT(psHeap->psCtx->uiNumHeaps > 0);
+ psHeap->psCtx->uiNumHeaps --;
+
+ eError = BridgeDevmemIntHeapDestroy(psHeap->psCtx->hBridge,
+ psHeap->hDevMemServerHeap);
+ PVR_ASSERT (eError == PVRSRV_OK);
+
+ RA_Delete(psHeap->psQuantizedVMRA);
+ OSFreeMem(psHeap->pszQuantizedVMRAName);
+
+ RA_Delete(psHeap->psSubAllocRA);
+ OSFreeMem(psHeap->pszSubAllocRAName);
+
+ OSFreeMem(psHeap->pszName);
+
+ OSFreeMem(psHeap);
+
+ return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ * Devmem allocation/free functions *
+ *****************************************************************************/
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemAllocate(DEVMEM_HEAP *psHeap,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags,
+ const IMG_PCHAR pszText,
+ DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+ IMG_BOOL bStatus; /* eError for RA */
+ RA_BASE_T uiAllocatedAddr;
+ RA_LENGTH_T uiAllocatedSize;
+ RA_PERISPAN_HANDLE hImport; /* the "import" from which this sub-allocation came */
+ RA_FLAGS_T uiFlagsForRA;
+ PVRSRV_ERROR eError;
+ DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
+ IMG_DEVMEM_OFFSET_T uiOffset = 0;
+ DEVMEM_IMPORT *psImport;
+ IMG_VOID *pvAddr;
+
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
+ {
+ /* Deferred Allocation not supported on SubAllocs*/
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto failParams;
+ }
+
+ if (psHeap == IMG_NULL || ppsMemDescPtr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto failParams;
+ }
+
+ eError = _DevmemValidateParams(uiSize,
+ uiAlign,
+ uiFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto failParams;
+ }
+
+ eError =_DevmemMemDescAlloc(&psMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMemDescAlloc;
+ }
+
+ /*
+ No request for exportable memory so use the RA
+ */
+ uiFlagsForRA = (RA_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK);
+ /* Check that the cast didn't lose any flags due to different integer widths */
+ PVR_ASSERT(uiFlagsForRA == (uiFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK));
+
+ /*
+ When the RA suballocates memory from a Span it does not zero it. It only zeroes the
+ memory if it allocates a new Span; but we don't know what is going to happen for this
+ RA_Alloc call. Therefore, we zero the mem after the allocation below.
+ */
+ uiFlagsForRA &= ~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+ bStatus = RA_Alloc(psHeap->psSubAllocRA,
+ uiSize,
+ uiFlagsForRA,
+ uiAlign,
+ &uiAllocatedAddr,
+ &uiAllocatedSize,
+ &hImport);
+ if (!bStatus)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto failDeviceMemAlloc;
+ }
+
+ psImport = hImport;
+ uiOffset = uiAllocatedAddr - psImport->sDeviceImport.sDevVAddr.uiAddr;
+
+ _DevmemMemDescInit(psMemDesc,
+ uiOffset,
+ psImport);
+
+ /* zero the memory */
+ if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+ {
+ eError = DevmemAcquireCpuVirtAddr(psMemDesc, &pvAddr);
+ if (eError != PVRSRV_OK)
+ {
+ goto failZero;
+ }
+
+
+#if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
+ PVR_ASSERT(uiSize<IMG_UINT32_MAX);
+#endif
+
+#if defined(CONFIG_ARM64) || defined(__arm64__) || defined(__aarch64__)
+ {
+ IMG_UINT32 i;
+ IMG_BYTE * pbyPtr;
+
+ pbyPtr = (IMG_BYTE*) pvAddr;
+ for (i = 0; i < uiSize; i++)
+ *pbyPtr++ = 0;
+ }
+
+#else
+ OSMemSet(pvAddr, 0x0, (IMG_SIZE_T) uiSize);
+#endif
+
+ DevmemReleaseCpuVirtAddr(psMemDesc);
+
+#if defined(PDUMP)
+ DevmemPDumpLoadZeroMem(psMemDesc, 0, uiSize, PDUMP_FLAGS_CONTINUOUS);
+#endif
+ }
+
+
+#if defined(PVR_RI_DEBUG)
+ {
+ /* Attach RI information */
+ eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ OSStringNLength(pszText, RI_MAX_TEXT_LEN),
+ pszText,
+ psMemDesc->uiOffset,
+ uiAllocatedSize,
+ IMG_FALSE,
+ IMG_FALSE,
+ &(psMemDesc->hRIHandle));
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
+ }
+ }
+#else /* if defined(PVR_RI_DEBUG) */
+ PVR_UNREFERENCED_PARAMETER (pszText);
+#endif /* if defined(PVR_RI_DEBUG) */
+
+ *ppsMemDescPtr = psMemDesc;
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+failZero:
+ _DevmemMemDescRelease(psMemDesc);
+ psMemDesc = IMG_NULL; /* Make sure we don't do a discard after the release */
+failDeviceMemAlloc:
+ if (psMemDesc)
+ _DevmemMemDescDiscard(psMemDesc);
+failMemDescAlloc:
+failParams:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemAllocateExportable(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags,
+ const IMG_PCHAR pszText,
+ DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
+ DEVMEM_IMPORT *psImport;
+ IMG_BOOL bMappingTable = IMG_TRUE;
+
+
+ DevmemExportalignAdjustSizeAndAlign(IMG_NULL,
+ &uiSize,
+ &uiAlign);
+
+ eError = _DevmemValidateParams(uiSize,
+ uiAlign,
+ uiFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto failParams;
+ }
+
+
+ eError =_DevmemMemDescAlloc(&psMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMemDescAlloc;
+ }
+
+ /*
+ Note:
+ In the case of exportable memory we have no heap to
+ query the pagesize from, so we assume host pagesize.
+ */
+ eError = _AllocateDeviceMemory(hBridge,
+ hDeviceNode,
+ GET_LOG2_PAGESIZE(),
+ uiSize,
+ uiSize,
+ 1,
+ 1,
+ &bMappingTable,
+ uiAlign,
+ uiFlags,
+ IMG_TRUE,
+ &psImport);
+ if (eError != PVRSRV_OK)
+ {
+ goto failDeviceMemAlloc;
+ }
+
+ _DevmemMemDescInit(psMemDesc,
+ 0,
+ psImport);
+
+ *ppsMemDescPtr = psMemDesc;
+
+#if defined(PVR_RI_DEBUG)
+ {
+ eError = BridgeRIWritePMREntry (psImport->hBridge,
+ psImport->hPMR,
+ OSStringNLength(pszText, RI_MAX_TEXT_LEN),
+ (IMG_CHAR *)pszText,
+ psImport->uiSize);
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
+ }
+
+ /* Attach RI information */
+ eError = BridgeRIWriteMEMDESCEntry (psImport->hBridge,
+ psImport->hPMR,
+ sizeof("^"),
+ "^",
+ psMemDesc->uiOffset,
+ uiSize,
+ IMG_FALSE,
+ IMG_TRUE,
+ &psMemDesc->hRIHandle);
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
+ }
+ }
+#else /* if defined(PVR_RI_DEBUG) */
+ PVR_UNREFERENCED_PARAMETER (pszText);
+#endif /* if defined(PVR_RI_DEBUG) */
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+failDeviceMemAlloc:
+ _DevmemMemDescDiscard(psMemDesc);
+
+failMemDescAlloc:
+failParams:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemAllocateSparse(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags,
+ const IMG_PCHAR pszText,
+ DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
+ DEVMEM_IMPORT *psImport;
+
+
+ DevmemExportalignAdjustSizeAndAlign(IMG_NULL,
+ &uiSize,
+ &uiAlign);
+
+ eError = _DevmemValidateParams(uiSize,
+ uiAlign,
+ uiFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto failParams;
+ }
+
+
+ eError =_DevmemMemDescAlloc(&psMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMemDescAlloc;
+ }
+
+ /*
+ Note:
+ In the case of sparse memory we have no heap to
+ query the pagesize from, so we assume host pagesize.
+ */
+ eError = _AllocateDeviceMemory(hBridge,
+ hDeviceNode,
+ GET_LOG2_PAGESIZE(),
+ uiSize,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ pabMappingTable,
+ uiAlign,
+ uiFlags,
+ IMG_TRUE,
+ &psImport);
+ if (eError != PVRSRV_OK)
+ {
+ goto failDeviceMemAlloc;
+ }
+
+ _DevmemMemDescInit(psMemDesc,
+ 0,
+ psImport);
+
+#if defined(PVR_RI_DEBUG)
+ {
+ eError = BridgeRIWritePMREntry (psImport->hBridge,
+ psImport->hPMR,
+ OSStringNLength(pszText, RI_MAX_TEXT_LEN),
+ (IMG_CHAR *)pszText,
+ psImport->uiSize);
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
+ }
+
+ /* Attach RI information */
+ eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ sizeof("^"),
+ "^",
+ psMemDesc->uiOffset,
+ uiSize,
+ IMG_FALSE,
+ IMG_TRUE,
+ &psMemDesc->hRIHandle);
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
+ }
+ }
+#else /* if defined(PVR_RI_DEBUG) */
+ PVR_UNREFERENCED_PARAMETER (pszText);
+#endif /* if defined(PVR_RI_DEBUG) */
+
+ *ppsMemDescPtr = psMemDesc;
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+failDeviceMemAlloc:
+ _DevmemMemDescDiscard(psMemDesc);
+
+failMemDescAlloc:
+failParams:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*****************************************************************************
+ * Devmem unsecure export functions *
+ *****************************************************************************/
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemExport(DEVMEM_MEMDESC *psMemDesc,
+ DEVMEM_EXPORTCOOKIE *psExportCookie)
+{
+ /* Caller to provide storage for export cookie struct */
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hPMRExportHandle = 0;
+ IMG_UINT64 uiPMRExportPassword = 0;
+ IMG_DEVMEM_SIZE_T uiSize = 0;
+ IMG_DEVMEM_LOG2ALIGN_T uiLog2Contig = 0;
+
+ if (psMemDesc == IMG_NULL || psExportCookie == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto e0;
+ }
+
+ eError = _Mapping_Export(psMemDesc->psImport,
+ &hPMRExportHandle,
+ &uiPMRExportPassword,
+ &uiSize,
+ &uiLog2Contig);
+ if (eError != PVRSRV_OK)
+ {
+ psExportCookie->uiSize = 0;
+ goto e0;
+ }
+
+ psExportCookie->hPMRExportHandle = hPMRExportHandle;
+ psExportCookie->uiPMRExportPassword = uiPMRExportPassword;
+ psExportCookie->uiSize = uiSize;
+ psExportCookie->uiLog2ContiguityGuarantee = uiLog2Contig;
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemMakeServerExportClientExport(DEVMEM_BRIDGE_HANDLE hBridge,
+ DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie,
+ DEVMEM_EXPORTCOOKIE *psExportCookie)
+{
+ DEVMEM_EXPORTHANDLE hPMRExportHandle;
+ IMG_DEVMEM_SIZE_T uiPMRSize;
+ IMG_DEVMEM_LOG2ALIGN_T uiPMRLog2Contig;
+ DEVMEM_EXPORTKEY uiPMRExportKey;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ eError = BridgePMRMakeServerExportClientExport(hBridge,
+ hServerExportCookie,
+ &hPMRExportHandle,
+ &uiPMRSize,
+ &uiPMRLog2Contig,
+ &uiPMRExportKey);
+
+ if (eError == PVRSRV_OK)
+ {
+ psExportCookie->hPMRExportHandle = hPMRExportHandle;
+ psExportCookie->uiPMRExportPassword = uiPMRExportKey;
+ psExportCookie->uiSize = uiPMRSize;
+ psExportCookie->uiLog2ContiguityGuarantee = uiPMRLog2Contig;
+ }
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemUnmakeServerExportClientExport(DEVMEM_BRIDGE_HANDLE hBridge,
+ DEVMEM_EXPORTCOOKIE *psExportCookie)
+{
+ return BridgePMRUnmakeServerExportClientExport(hBridge, psExportCookie->hPMRExportHandle);
+}
+
+IMG_INTERNAL IMG_BOOL
+DevmemIsValidExportCookie(DEVMEM_EXPORTCOOKIE *psExportCookie)
+{
+ /* Assume that if the size is set, the export cookie is used */
+ return (psExportCookie->uiSize != 0x0);
+}
+
+IMG_INTERNAL IMG_VOID
+DevmemUnexport(DEVMEM_MEMDESC *psMemDesc,
+ DEVMEM_EXPORTCOOKIE *psExportCookie)
+{
+ _Mapping_Unexport(psMemDesc->psImport,
+ psExportCookie->hPMRExportHandle);
+
+ psExportCookie->uiSize = 0;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemImport(IMG_HANDLE hBridge,
+ DEVMEM_EXPORTCOOKIE *psCookie,
+ DEVMEM_FLAGS_T uiFlags,
+ DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+ DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
+ DEVMEM_IMPORT *psImport;
+ IMG_HANDLE hPMR;
+ PVRSRV_ERROR eError;
+
+ if (ppsMemDescPtr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto failParams;
+ }
+
+ eError =_DevmemMemDescAlloc(&psMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMemDescAlloc;
+ }
+
+ eError = _DevmemImportStructAlloc(hBridge,
+ IMG_TRUE,
+ &psImport);
+ if (eError != PVRSRV_OK)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto failImportAlloc;
+ }
+
+
+ /* Get a handle to the PMR (inc refcount, checks authorization) */
+ eError = BridgePMRImportPMR(hBridge,
+ psCookie->hPMRExportHandle,
+ psCookie->uiPMRExportPassword,
+ psCookie->uiSize, /* not trusted - just for sanity checks */
+ psCookie->uiLog2ContiguityGuarantee, /* not trusted - just for sanity checks */
+ &hPMR);
+ if (eError != PVRSRV_OK)
+ {
+ goto failImport;
+ }
+
+ _DevmemImportStructInit(psImport,
+ psCookie->uiSize,
+ 1ULL << psCookie->uiLog2ContiguityGuarantee,
+ uiFlags,
+ hPMR);
+
+ _DevmemMemDescInit(psMemDesc,
+ 0,
+ psImport);
+
+ *ppsMemDescPtr = psMemDesc;
+
+#if defined(PVR_RI_DEBUG)
+ {
+ /* Attach RI information */
+ eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ sizeof("^"),
+ "^",
+ psMemDesc->uiOffset,
+ psMemDesc->psImport->uiSize,
+ IMG_TRUE,
+ IMG_FALSE,
+ &psMemDesc->hRIHandle);
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
+ }
+ }
+#endif /* if defined(PVR_RI_DEBUG) */
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+failImport:
+ _DevmemImportDiscard(psImport);
+failImportAlloc:
+ _DevmemMemDescDiscard(psMemDesc);
+failMemDescAlloc:
+failParams:
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+/*****************************************************************************
+ * Common MemDesc functions *
+ *****************************************************************************/
+
+/*
+ This function is called for freeing any class of memory
+*/
+IMG_INTERNAL IMG_VOID
+DevmemFree(DEVMEM_MEMDESC *psMemDesc)
+{
+#if defined(PVR_RI_DEBUG)
+ if (psMemDesc->hRIHandle)
+ {
+ PVRSRV_ERROR eError;
+
+ eError = BridgeRIDeleteMEMDESCEntry(psMemDesc->psImport->hBridge,
+ psMemDesc->hRIHandle);
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIDeleteMEMDESCEntry failed (eError=%d)", __func__, eError));
+ }
+ }
+#endif /* if defined(PVR_RI_DEBUG) */
+ _DevmemMemDescRelease(psMemDesc);
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemMapToDevice(DEVMEM_MEMDESC *psMemDesc,
+ DEVMEM_HEAP *psHeap,
+ IMG_DEV_VIRTADDR *psDevVirtAddr)
+{
+ DEVMEM_IMPORT *psImport;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bMap = IMG_TRUE;
+
+ OSLockAcquire(psMemDesc->sDeviceMemDesc.hLock);
+ if (psHeap == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto failParams;
+ }
+
+ if (psMemDesc->sDeviceMemDesc.ui32RefCount != 0)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_ALREADY_MAPPED;
+ goto failCheck;
+ }
+
+ /* Don't map memory for deferred allocations */
+ if (psMemDesc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
+ {
+ PVR_ASSERT(psMemDesc->psImport->bExportable);
+ bMap = IMG_FALSE;
+ }
+
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psMemDesc,
+ psMemDesc->sDeviceMemDesc.ui32RefCount,
+ psMemDesc->sDeviceMemDesc.ui32RefCount+1);
+
+ psImport = psMemDesc->psImport;
+ _DevmemMemDescAcquire(psMemDesc);
+
+ eError = _DevmemImportStructDevMap(psHeap,
+ bMap,
+ psImport);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMap;
+ }
+
+ sDevVAddr.uiAddr = psImport->sDeviceImport.sDevVAddr.uiAddr;
+ sDevVAddr.uiAddr += psMemDesc->uiOffset;
+ psMemDesc->sDeviceMemDesc.sDevVAddr = sDevVAddr;
+ psMemDesc->sDeviceMemDesc.ui32RefCount++;
+
+ *psDevVirtAddr = psMemDesc->sDeviceMemDesc.sDevVAddr;
+
+ OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
+
+#if defined(PVR_RI_DEBUG)
+ if (psMemDesc->hRIHandle)
+ {
+ eError = BridgeRIUpdateMEMDESCAddr(psImport->hBridge,
+ psMemDesc->hRIHandle,
+ psImport->sDeviceImport.sDevVAddr);
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCAddr failed (eError=%d)", __func__, eError));
+ }
+ }
+#endif
+
+ return PVRSRV_OK;
+
+failMap:
+ _DevmemMemDescRelease(psMemDesc);
+failCheck:
+failParams:
+ OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemAcquireDevVirtAddr(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEV_VIRTADDR *psDevVirtAddr)
+{
+ PVRSRV_ERROR eError;
+
+ OSLockAcquire(psMemDesc->sDeviceMemDesc.hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psMemDesc,
+ psMemDesc->sDeviceMemDesc.ui32RefCount,
+ psMemDesc->sDeviceMemDesc.ui32RefCount+1);
+
+ if (psMemDesc->sDeviceMemDesc.ui32RefCount == 0)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_NO_MAPPING;
+ goto failCheck;
+ }
+ psMemDesc->sDeviceMemDesc.ui32RefCount++;
+
+ *psDevVirtAddr = psMemDesc->sDeviceMemDesc.sDevVAddr;
+ OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
+
+ return PVRSRV_OK;
+
+failCheck:
+ OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+IMG_INTERNAL IMG_VOID
+DevmemReleaseDevVirtAddr(DEVMEM_MEMDESC *psMemDesc)
+{
+ PVR_ASSERT(psMemDesc != IMG_NULL);
+
+ OSLockAcquire(psMemDesc->sDeviceMemDesc.hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psMemDesc,
+ psMemDesc->sDeviceMemDesc.ui32RefCount,
+ psMemDesc->sDeviceMemDesc.ui32RefCount-1);
+
+ PVR_ASSERT(psMemDesc->sDeviceMemDesc.ui32RefCount != 0);
+
+ if (--psMemDesc->sDeviceMemDesc.ui32RefCount == 0)
+ {
+ _DevmemImportStructDevUnmap(psMemDesc->psImport);
+ OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
+
+ _DevmemMemDescRelease(psMemDesc);
+ }
+ else
+ {
+ OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
+ }
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemAcquireCpuVirtAddr(DEVMEM_MEMDESC *psMemDesc,
+ IMG_VOID **ppvCpuVirtAddr)
+{
+ PVRSRV_ERROR eError;
+
+ OSLockAcquire(psMemDesc->sCPUMemDesc.hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psMemDesc,
+ psMemDesc->sCPUMemDesc.ui32RefCount,
+ psMemDesc->sCPUMemDesc.ui32RefCount+1);
+
+ if (psMemDesc->sCPUMemDesc.ui32RefCount++ == 0)
+ {
+ DEVMEM_IMPORT *psImport = psMemDesc->psImport;
+ IMG_UINT8 *pui8CPUVAddr;
+
+ _DevmemMemDescAcquire(psMemDesc);
+ eError = _DevmemImportStructCPUMap(psImport);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMap;
+ }
+
+ pui8CPUVAddr = psImport->sCPUImport.pvCPUVAddr;
+ pui8CPUVAddr += psMemDesc->uiOffset;
+ psMemDesc->sCPUMemDesc.pvCPUVAddr = pui8CPUVAddr;
+ }
+ *ppvCpuVirtAddr = psMemDesc->sCPUMemDesc.pvCPUVAddr;
+
+ VG_MARK_INITIALIZED(*ppvCpuVirtAddr, psMemDesc->psImport->uiSize);
+
+ OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
+
+ return PVRSRV_OK;
+
+failMap:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ psMemDesc->sCPUMemDesc.ui32RefCount--;
+ _DevmemMemDescRelease(psMemDesc);
+ OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
+
+ return eError;
+}
+
+IMG_INTERNAL IMG_VOID
+DevmemReleaseCpuVirtAddr(DEVMEM_MEMDESC *psMemDesc)
+{
+ PVR_ASSERT(psMemDesc != IMG_NULL);
+
+ OSLockAcquire(psMemDesc->sCPUMemDesc.hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psMemDesc,
+ psMemDesc->sCPUMemDesc.ui32RefCount,
+ psMemDesc->sCPUMemDesc.ui32RefCount-1);
+
+ PVR_ASSERT(psMemDesc->sCPUMemDesc.ui32RefCount != 0);
+
+ if (--psMemDesc->sCPUMemDesc.ui32RefCount == 0)
+ {
+ OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
+ _DevmemImportStructCPUUnmap(psMemDesc->psImport);
+ _DevmemMemDescRelease(psMemDesc);
+ }
+ else
+ {
+ OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
+ }
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetImportUID(DEVMEM_MEMDESC *psMemDesc,
+ IMG_UINT64 *pui64UID)
+{
+ DEVMEM_IMPORT *psImport = psMemDesc->psImport;
+ PVRSRV_ERROR eError;
+
+ eError = BridgePMRGetUID(psImport->hBridge,
+ psImport->hPMR,
+ pui64UID);
+
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetReservation(DEVMEM_MEMDESC *psMemDesc,
+ IMG_HANDLE *hReservation)
+{
+ DEVMEM_IMPORT *psImport;
+
+ PVR_ASSERT(psMemDesc);
+ psImport = psMemDesc->psImport;
+
+ PVR_ASSERT(psImport);
+ *hReservation = psImport->sDeviceImport.hReservation;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+DevmemGetPMRData(DEVMEM_MEMDESC *psMemDesc,
+ IMG_HANDLE *phPMR,
+ IMG_DEVMEM_OFFSET_T *puiPMROffset)
+{
+ DEVMEM_IMPORT *psImport;
+
+ PVR_ASSERT(psMemDesc);
+ *puiPMROffset = psMemDesc->uiOffset;
+ psImport = psMemDesc->psImport;
+
+ PVR_ASSERT(psImport);
+ *phPMR = psImport->hPMR;
+
+ return PVRSRV_OK;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetFlags(DEVMEM_MEMDESC *psMemDesc,
+ DEVMEM_FLAGS_T *puiFlags)
+{
+ DEVMEM_IMPORT *psImport;
+
+ PVR_ASSERT(psMemDesc);
+ psImport = psMemDesc->psImport;
+
+ PVR_ASSERT(psImport);
+ *puiFlags = psImport->uiFlags;
+
+ return PVRSRV_OK;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemLocalImport(IMG_HANDLE hBridge,
+ IMG_HANDLE hExtHandle,
+ DEVMEM_FLAGS_T uiFlags,
+ DEVMEM_MEMDESC **ppsMemDescPtr,
+ IMG_DEVMEM_SIZE_T *puiSizePtr)
+{
+ DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
+ DEVMEM_IMPORT *psImport;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_DEVMEM_ALIGN_T uiAlign;
+ IMG_HANDLE hPMR;
+ PVRSRV_ERROR eError;
+
+ if (ppsMemDescPtr == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto failParams;
+ }
+
+ eError =_DevmemMemDescAlloc(&psMemDesc);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMemDescAlloc;
+ }
+
+ eError = _DevmemImportStructAlloc(hBridge,
+ IMG_TRUE,
+ &psImport);
+ if (eError != PVRSRV_OK)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto failImportAlloc;
+ }
+
+ /* Get the PMR handle and it's size from the server */
+ eError = BridgePMRLocalImportPMR(hBridge,
+ hExtHandle,
+ &hPMR,
+ &uiSize,
+ &uiAlign);
+ if (eError != PVRSRV_OK)
+ {
+ goto failImport;
+ }
+
+ _DevmemImportStructInit(psImport,
+ uiSize,
+ uiAlign,
+ uiFlags,
+ hPMR);
+
+ _DevmemMemDescInit(psMemDesc,
+ 0,
+ psImport);
+
+ *ppsMemDescPtr = psMemDesc;
+ if (puiSizePtr)
+ *puiSizePtr = uiSize;
+
+#if defined(PVR_RI_DEBUG)
+ {
+ /* Attach RI information */
+ eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ sizeof("^"),
+ "^",
+ psMemDesc->uiOffset,
+ psMemDesc->psImport->uiSize,
+ IMG_TRUE,
+ IMG_FALSE,
+ &(psMemDesc->hRIHandle));
+ if( eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
+ }
+ }
+#endif /* if defined(PVR_RI_DEBUG) */
+ return PVRSRV_OK;
+
+failImport:
+ _DevmemImportDiscard(psImport);
+failImportAlloc:
+ _DevmemMemDescDiscard(psMemDesc);
+failMemDescAlloc:
+failParams:
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
diff --git a/drivers/gpu/rogue/services/shared/common/devicemem_pdump.c b/drivers/gpu/rogue/services/shared/common/devicemem_pdump.c
new file mode 100644
index 000000000000..1e0a727cfc69
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/devicemem_pdump.c
@@ -0,0 +1,323 @@
+/*************************************************************************/ /*!
+@File
+@Title Shared device memory management PDump functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements common (client & server) PDump functions for the
+ memory management code
+@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 "allocmem.h"
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pdump.h"
+#include "devicemem_utils.h"
+#include "devicemem_pdump.h"
+#include "client_pdumpmm_bridge.h"
+
+IMG_INTERNAL IMG_VOID
+DevmemPDumpLoadMem(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(uiOffset + uiSize <= psMemDesc->psImport->uiSize);
+
+ eError = BridgePMRPDumpLoadMem(psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ psMemDesc->uiOffset + uiOffset,
+ uiSize,
+ uiPDumpFlags,
+ IMG_FALSE);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+IMG_INTERNAL IMG_VOID
+DevmemPDumpLoadZeroMem(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(uiOffset + uiSize <= psMemDesc->psImport->uiSize);
+
+ eError = BridgePMRPDumpLoadMem(psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ psMemDesc->uiOffset + uiOffset,
+ uiSize,
+ uiPDumpFlags,
+ IMG_TRUE);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+IMG_INTERNAL IMG_VOID
+DevmemPDumpLoadMemValue32(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgePMRPDumpLoadMemValue32(psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ psMemDesc->uiOffset + uiOffset,
+ ui32Value,
+ uiPDumpFlags);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+IMG_INTERNAL IMG_VOID
+DevmemPDumpLoadMemValue64(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT64 ui64Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgePMRPDumpLoadMemValue64(psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ psMemDesc->uiOffset + uiOffset,
+ ui64Value,
+ uiPDumpFlags);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemPDumpPageCatBaseToSAddr(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T *puiMemOffset,
+ IMG_CHAR *pszName,
+ IMG_UINT32 ui32Size)
+{
+ PVRSRV_ERROR eError;
+ IMG_CHAR aszMemspaceName[100];
+ IMG_CHAR aszSymbolicName[100];
+ IMG_DEVMEM_OFFSET_T uiNextSymName;
+
+ *puiMemOffset += psMemDesc->uiOffset;
+
+ eError = BridgePMRPDumpSymbolicAddr(psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ *puiMemOffset,
+ sizeof(aszMemspaceName),
+ &aszMemspaceName[0],
+ sizeof(aszSymbolicName),
+ &aszSymbolicName[0],
+ puiMemOffset,
+ &uiNextSymName);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ OSSNPrintf(pszName, ui32Size, "%s:%s", &aszMemspaceName[0], &aszSymbolicName[0]);
+ return eError;
+}
+
+IMG_INTERNAL IMG_VOID
+DevmemPDumpSaveToFile(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgePMRPDumpSaveToFile(psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ psMemDesc->uiOffset + uiOffset,
+ uiSize,
+ OSStringLength(pszFilename) + 1,
+ pszFilename);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+
+IMG_INTERNAL IMG_VOID
+DevmemPDumpSaveToFileVirtual(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32PdumpFlags)
+{
+ PVRSRV_ERROR eError;
+ IMG_DEV_VIRTADDR sDevAddrStart;
+
+ sDevAddrStart = psMemDesc->psImport->sDeviceImport.sDevVAddr;
+ sDevAddrStart.uiAddr += psMemDesc->uiOffset;
+ sDevAddrStart.uiAddr += uiOffset;
+
+ eError = BridgeDevmemIntPDumpSaveToFileVirtual(psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->sDeviceImport.psHeap->psCtx->hDevMemServerContext,
+ sDevAddrStart,
+ uiSize,
+ OSStringLength(pszFilename) + 1,
+ pszFilename,
+ ui32FileOffset,
+ ui32PdumpFlags);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemPDumpDevmemPol32(const DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ IMG_DEVMEM_SIZE_T uiNumBytes;
+
+ uiNumBytes = 4;
+
+ if (psMemDesc->uiOffset + uiOffset + uiNumBytes >= psMemDesc->psImport->uiSize)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
+ goto e0;
+ }
+
+ eError = BridgePMRPDumpPol32(psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ psMemDesc->uiOffset + uiOffset,
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ ui32PDumpFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ return PVRSRV_OK;
+
+ /*
+ error exit paths follow
+ */
+
+ e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemPDumpCBP(const DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize)
+{
+ PVRSRV_ERROR eError;
+
+ if ((psMemDesc->uiOffset + uiReadOffset) > psMemDesc->psImport->uiSize)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
+ goto e0;
+ }
+
+ eError = BridgePMRPDumpCBP(psMemDesc->psImport->hBridge,
+ psMemDesc->psImport->hPMR,
+ psMemDesc->uiOffset + uiReadOffset,
+ uiWriteOffset,
+ uiPacketSize,
+ uiBufferSize);
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+
+ return PVRSRV_OK;
+
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+#endif /* PDUMP */
+
diff --git a/drivers/gpu/rogue/services/shared/common/devicemem_utils.c b/drivers/gpu/rogue/services/shared/common/devicemem_utils.c
new file mode 100644
index 000000000000..d1817ad9af77
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/devicemem_utils.c
@@ -0,0 +1,704 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management internal utility functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Utility functions used internally by device memory management
+ code.
+@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 "allocmem.h"
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "ra.h"
+#include "devicemem_utils.h"
+#include "client_mm_bridge.h"
+
+#if !defined(__KERNEL__) && defined(SUPPORT_ION)
+#include <sys/mman.h>
+#endif
+
+/*
+ The Devmem import structure is the structure we use
+ to manage memory that is "imported" (which is page
+ granular) from the server into our process, this
+ includes allocations.
+
+ This allows memory to be imported without requiring
+ any CPU or device mapping. Memory can then be mapped
+ into the device or CPU on demand, but neither is
+ required.
+*/
+
+IMG_INTERNAL
+IMG_VOID _DevmemImportStructAcquire(DEVMEM_IMPORT *psImport)
+{
+ OSLockAcquire(psImport->hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psImport,
+ psImport->ui32RefCount,
+ psImport->ui32RefCount+1);
+
+ psImport->ui32RefCount++;
+ OSLockRelease(psImport->hLock);
+}
+
+IMG_INTERNAL
+IMG_VOID _DevmemImportStructRelease(DEVMEM_IMPORT *psImport)
+{
+ PVR_ASSERT(psImport->ui32RefCount != 0);
+
+ OSLockAcquire(psImport->hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psImport,
+ psImport->ui32RefCount,
+ psImport->ui32RefCount-1);
+
+ if (--psImport->ui32RefCount == 0)
+ {
+ OSLockRelease(psImport->hLock);
+
+ BridgePMRUnrefPMR(psImport->hBridge,
+ psImport->hPMR);
+ OSLockDestroy(psImport->sCPUImport.hLock);
+ OSLockDestroy(psImport->sDeviceImport.hLock);
+ OSLockDestroy(psImport->hLock);
+ OSFreeMem(psImport);
+ }
+ else
+ {
+ OSLockRelease(psImport->hLock);
+ }
+}
+
+IMG_INTERNAL
+IMG_VOID _DevmemImportDiscard(DEVMEM_IMPORT *psImport)
+{
+ PVR_ASSERT(psImport->ui32RefCount == 0);
+ OSLockDestroy(psImport->sCPUImport.hLock);
+ OSLockDestroy(psImport->sDeviceImport.hLock);
+ OSLockDestroy(psImport->hLock);
+ OSFreeMem(psImport);
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR _DevmemMemDescAlloc(DEVMEM_MEMDESC **ppsMemDesc)
+{
+ DEVMEM_MEMDESC *psMemDesc;
+ PVRSRV_ERROR eError;
+
+ psMemDesc = OSAllocMem(sizeof(DEVMEM_MEMDESC));
+
+ if (psMemDesc == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto failAlloc;
+ }
+
+ /* Structure must be zero'd incase it needs to be freed before it is initialised! */
+ OSMemSet(psMemDesc, 0, sizeof(DEVMEM_MEMDESC));
+
+ eError = OSLockCreate(&psMemDesc->hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMDLock;
+ }
+
+ eError = OSLockCreate(&psMemDesc->sDeviceMemDesc.hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto failDMDLock;
+ }
+
+ eError = OSLockCreate(&psMemDesc->sCPUMemDesc.hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto failCMDLock;
+ }
+
+ *ppsMemDesc = psMemDesc;
+
+ return PVRSRV_OK;
+
+failCMDLock:
+ OSLockDestroy(psMemDesc->sDeviceMemDesc.hLock);
+failDMDLock:
+ OSLockDestroy(psMemDesc->hLock);
+failMDLock:
+ OSFreeMem(psMemDesc);
+failAlloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+/*
+ Init the MemDesc structure
+*/
+IMG_INTERNAL
+IMG_VOID _DevmemMemDescInit(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ DEVMEM_IMPORT *psImport)
+{
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psMemDesc,
+ 0,
+ 1);
+
+ psMemDesc->psImport = psImport;
+ psMemDesc->uiOffset = uiOffset;
+
+ psMemDesc->sDeviceMemDesc.ui32RefCount = 0;
+ psMemDesc->sCPUMemDesc.ui32RefCount = 0;
+ psMemDesc->ui32RefCount = 1;
+}
+
+IMG_INTERNAL
+IMG_VOID _DevmemMemDescAcquire(DEVMEM_MEMDESC *psMemDesc)
+{
+ OSLockAcquire(psMemDesc->hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psMemDesc,
+ psMemDesc->ui32RefCount,
+ psMemDesc->ui32RefCount+1);
+
+ psMemDesc->ui32RefCount++;
+ OSLockRelease(psMemDesc->hLock);
+}
+
+IMG_INTERNAL
+IMG_VOID _DevmemMemDescRelease(DEVMEM_MEMDESC *psMemDesc)
+{
+ PVR_ASSERT(psMemDesc != NULL);
+ PVR_ASSERT(psMemDesc->ui32RefCount != 0);
+
+ OSLockAcquire(psMemDesc->hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psMemDesc,
+ psMemDesc->ui32RefCount,
+ psMemDesc->ui32RefCount-1);
+
+ if (--psMemDesc->ui32RefCount == 0)
+ {
+ OSLockRelease(psMemDesc->hLock);
+
+ if (!psMemDesc->psImport->bExportable)
+ {
+ RA_Free(psMemDesc->psImport->sDeviceImport.psHeap->psSubAllocRA,
+ psMemDesc->psImport->sDeviceImport.sDevVAddr.uiAddr +
+ psMemDesc->uiOffset);
+ }
+ else
+ {
+ _DevmemImportStructRelease(psMemDesc->psImport);
+ }
+
+ OSLockDestroy(psMemDesc->sCPUMemDesc.hLock);
+ OSLockDestroy(psMemDesc->sDeviceMemDesc.hLock);
+ OSLockDestroy(psMemDesc->hLock);
+ OSFreeMem(psMemDesc);
+ }
+ else
+ {
+ OSLockRelease(psMemDesc->hLock);
+ }
+}
+
+IMG_INTERNAL
+IMG_VOID _DevmemMemDescDiscard(DEVMEM_MEMDESC *psMemDesc)
+{
+ PVR_ASSERT(psMemDesc->ui32RefCount == 0);
+
+ OSLockDestroy(psMemDesc->sCPUMemDesc.hLock);
+ OSLockDestroy(psMemDesc->sDeviceMemDesc.hLock);
+ OSLockDestroy(psMemDesc->hLock);
+ OSFreeMem(psMemDesc);
+}
+
+
+IMG_INTERNAL
+PVRSRV_ERROR _DevmemValidateParams(IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags)
+{
+ if (!(uiFlags & PVRSRV_MEMALLOCFLAG_GPU_READABLE))
+ {
+ /* Don't support memory not GPU readable currently */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if ((uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &&
+ (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
+ {
+ /* Zero on Alloc and Poison on Alloc are mutually exclusive */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (uiAlign & (uiAlign-1))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Verify that size is a positive integer multiple of alignment */
+#if 0 //
+ if (uiSize & (uiAlign-1))
+ {
+ /* Size not a multiple of alignment */
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+#endif
+ if (uiSize == 0)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+/*
+ Allocate and init an import structure
+*/
+IMG_INTERNAL
+PVRSRV_ERROR _DevmemImportStructAlloc(IMG_HANDLE hBridge,
+ IMG_BOOL bExportable,
+ DEVMEM_IMPORT **ppsImport)
+{
+ DEVMEM_IMPORT *psImport;
+ PVRSRV_ERROR eError;
+
+ psImport = OSAllocMem(sizeof *psImport);
+ if (psImport == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Setup some known bad values for things we don't have yet */
+ psImport->sDeviceImport.hReservation = LACK_OF_RESERVATION_POISON;
+ psImport->sDeviceImport.hMapping = LACK_OF_MAPPING_POISON;
+ psImport->sDeviceImport.psHeap = IMG_NULL;
+ psImport->sDeviceImport.bMapped = IMG_FALSE;
+
+ eError = OSLockCreate(&psImport->sDeviceImport.hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto failDIOSLockCreate;
+ }
+
+ psImport->sCPUImport.hOSMMapData = IMG_NULL;
+ psImport->sCPUImport.pvCPUVAddr = IMG_NULL;
+
+ eError = OSLockCreate(&psImport->sCPUImport.hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto failCIOSLockCreate;
+ }
+
+ /* Set up common elements */
+ psImport->hBridge = hBridge;
+ psImport->bExportable = bExportable;
+
+ /* Setup refcounts */
+ psImport->sDeviceImport.ui32RefCount = 0;
+ psImport->sCPUImport.ui32RefCount = 0;
+ psImport->ui32RefCount = 0;
+
+ /* Create the lock */
+ eError = OSLockCreate(&psImport->hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto failILockAlloc;
+ }
+
+#if !defined(__KERNEL__) && defined(SUPPORT_ION)
+ psImport->sCPUImport.iDmaBufFd = -1;
+#endif
+
+ *ppsImport = psImport;
+
+ return PVRSRV_OK;
+
+failILockAlloc:
+ OSLockDestroy(psImport->sCPUImport.hLock);
+failCIOSLockCreate:
+ OSLockDestroy(psImport->sDeviceImport.hLock);
+failDIOSLockCreate:
+ OSFreeMem(psImport);
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+/*
+ Initialise the import structure
+*/
+IMG_INTERNAL
+IMG_VOID _DevmemImportStructInit(DEVMEM_IMPORT *psImport,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags,
+ IMG_HANDLE hPMR)
+{
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psImport,
+ 0,
+ 1);
+
+ psImport->uiSize = uiSize;
+ psImport->uiAlign = uiAlign;
+ psImport->uiFlags = uiFlags;
+ psImport->hPMR = hPMR;
+ psImport->ui32RefCount = 1;
+}
+
+/*
+ Map an import to the device
+*/
+IMG_INTERNAL
+PVRSRV_ERROR _DevmemImportStructDevMap(DEVMEM_HEAP *psHeap,
+ IMG_BOOL bMap,
+ DEVMEM_IMPORT *psImport)
+{
+ DEVMEM_DEVICE_IMPORT *psDeviceImport;
+ IMG_BOOL bStatus;
+ RA_BASE_T uiAllocatedAddr;
+ RA_LENGTH_T uiAllocatedSize;
+ IMG_DEV_VIRTADDR sBase;
+ IMG_HANDLE hReservation;
+ PVRSRV_ERROR eError;
+
+ psDeviceImport = &psImport->sDeviceImport;
+
+ OSLockAcquire(psDeviceImport->hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psImport,
+ psDeviceImport->ui32RefCount,
+ psDeviceImport->ui32RefCount+1);
+
+ if (psDeviceImport->ui32RefCount++ == 0)
+ {
+ _DevmemImportStructAcquire(psImport);
+
+ OSLockAcquire(psHeap->hLock);
+ psHeap->uiImportCount++;
+ OSLockRelease(psHeap->hLock);
+
+ if (psHeap->psCtx->hBridge != psImport->hBridge)
+ {
+ /*
+ The import was done with a different connection then the
+ memory context which means they are not compatible.
+ */
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto failCheck;
+ }
+
+ /* Allocate space in the VM */
+ bStatus = RA_Alloc(psHeap->psQuantizedVMRA,
+ psImport->uiSize,
+ 0, /* flags: this RA doesn't use flags*/
+ psImport->uiAlign,
+ &uiAllocatedAddr,
+ &uiAllocatedSize,
+ IMG_NULL /* don't care about per-import priv data */
+ );
+ if (!bStatus)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_DEVICE_VM;
+ goto failVMRAAlloc;
+ }
+
+ /* No reason for the allocated virtual size to be different from
+ the PMR's size */
+ PVR_ASSERT(uiAllocatedSize == psImport->uiSize);
+
+ sBase.uiAddr = uiAllocatedAddr;
+
+ /* Setup page tables for the allocated VM space */
+ eError = BridgeDevmemIntReserveRange(psHeap->psCtx->hBridge,
+ psHeap->hDevMemServerHeap,
+ sBase,
+ uiAllocatedSize,
+ &hReservation);
+ if (eError != PVRSRV_OK)
+ {
+ goto failReserve;
+ }
+
+ if (bMap)
+ {
+ DEVMEM_FLAGS_T uiMapFlags;
+
+ uiMapFlags = psImport->uiFlags & PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK;
+
+ /* Actually map the PMR to allocated VM space */
+ eError = BridgeDevmemIntMapPMR(psHeap->psCtx->hBridge,
+ psHeap->hDevMemServerHeap,
+ hReservation,
+ psImport->hPMR,
+ uiMapFlags,
+ &psDeviceImport->hMapping);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMap;
+ }
+ psDeviceImport->bMapped = IMG_TRUE;
+ }
+
+ /* Setup device mapping specific parts of the mapping info */
+ psDeviceImport->hReservation = hReservation;
+ psDeviceImport->sDevVAddr.uiAddr = uiAllocatedAddr;
+ psDeviceImport->psHeap = psHeap;
+ }
+ else
+ {
+ /*
+ Check that we've been asked to map it into the
+ same heap 2nd time around
+ */
+ if (psHeap != psDeviceImport->psHeap)
+ {
+ eError = PVRSRV_ERROR_INVALID_HEAP;
+ goto failParams;
+ }
+ }
+ OSLockRelease(psDeviceImport->hLock);
+
+ return PVRSRV_OK;
+
+failMap:
+ BridgeDevmemIntUnreserveRange(psHeap->psCtx->hBridge,
+ hReservation);
+failReserve:
+ RA_Free(psHeap->psQuantizedVMRA,
+ uiAllocatedAddr);
+failVMRAAlloc:
+failCheck:
+ _DevmemImportStructRelease(psImport);
+ OSLockAcquire(psHeap->hLock);
+ psHeap->uiImportCount--;
+ OSLockRelease(psHeap->hLock);
+failParams:
+ OSLockRelease(psDeviceImport->hLock);
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*
+ Unmap an import from the Device
+*/
+IMG_INTERNAL
+IMG_VOID _DevmemImportStructDevUnmap(DEVMEM_IMPORT *psImport)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_DEVICE_IMPORT *psDeviceImport;
+
+ psDeviceImport = &psImport->sDeviceImport;
+
+ OSLockAcquire(psDeviceImport->hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psImport,
+ psDeviceImport->ui32RefCount,
+ psDeviceImport->ui32RefCount-1);
+
+ if (--psDeviceImport->ui32RefCount == 0)
+ {
+ DEVMEM_HEAP *psHeap = psDeviceImport->psHeap;
+
+ if (psDeviceImport->bMapped)
+ {
+ eError = BridgeDevmemIntUnmapPMR(psImport->hBridge,
+ psDeviceImport->hMapping);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+
+ eError = BridgeDevmemIntUnreserveRange(psImport->hBridge,
+ psDeviceImport->hReservation);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ RA_Free(psHeap->psQuantizedVMRA,
+ psDeviceImport->sDevVAddr.uiAddr);
+
+ OSLockRelease(psDeviceImport->hLock);
+
+ _DevmemImportStructRelease(psImport);
+
+ OSLockAcquire(psHeap->hLock);
+ psHeap->uiImportCount--;
+ OSLockRelease(psHeap->hLock);
+ }
+ else
+ {
+ OSLockRelease(psDeviceImport->hLock);
+ }
+}
+
+/*
+ Map an import into the CPU
+*/
+IMG_INTERNAL
+PVRSRV_ERROR _DevmemImportStructCPUMap(DEVMEM_IMPORT *psImport)
+{
+ PVRSRV_ERROR eError;
+ DEVMEM_CPU_IMPORT *psCPUImport;
+ IMG_SIZE_T uiMappingLength;
+
+ psCPUImport = &psImport->sCPUImport;
+
+ OSLockAcquire(psCPUImport->hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psImport,
+ psCPUImport->ui32RefCount,
+ psCPUImport->ui32RefCount+1);
+
+ if (psCPUImport->ui32RefCount++ == 0)
+ {
+ _DevmemImportStructAcquire(psImport);
+
+#if !defined(__KERNEL__) && defined(SUPPORT_ION)
+ if (psImport->sCPUImport.iDmaBufFd >= 0)
+ {
+ void *pvCPUVAddr;
+
+ /* For ion imports, use the ion fd and mmap facility to map the
+ * buffer to user space. We can bypass the services bridge in
+ * this case and possibly save some time.
+ *
+ *
+*/
+ pvCPUVAddr = mmap(NULL, psImport->uiSize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, psImport->sCPUImport.iDmaBufFd, 0);
+
+ if (pvCPUVAddr == MAP_FAILED)
+ {
+ eError = PVRSRV_ERROR_DEVICEMEM_MAP_FAILED;
+ goto failMap;
+ }
+
+ psCPUImport->hOSMMapData = pvCPUVAddr;
+ psCPUImport->pvCPUVAddr = pvCPUVAddr;
+ uiMappingLength = psImport->uiSize;
+ }
+ else
+#endif
+ {
+ eError = OSMMapPMR(psImport->hBridge,
+ psImport->hPMR,
+ psImport->uiSize,
+ &psCPUImport->hOSMMapData,
+ &psCPUImport->pvCPUVAddr,
+ &uiMappingLength);
+ if (eError != PVRSRV_OK)
+ {
+ goto failMap;
+ }
+ }
+
+ /* There is no reason the mapping length is different to the size */
+ PVR_ASSERT(uiMappingLength == psImport->uiSize);
+ }
+ OSLockRelease(psCPUImport->hLock);
+
+ return PVRSRV_OK;
+
+failMap:
+ psCPUImport->ui32RefCount--;
+ _DevmemImportStructRelease(psImport);
+ OSLockRelease(psCPUImport->hLock);
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+/*
+ Unmap an import from the CPU
+*/
+IMG_INTERNAL
+IMG_VOID _DevmemImportStructCPUUnmap(DEVMEM_IMPORT *psImport)
+{
+ DEVMEM_CPU_IMPORT *psCPUImport;
+
+ psCPUImport = &psImport->sCPUImport;
+
+ OSLockAcquire(psCPUImport->hLock);
+ DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
+ __FUNCTION__,
+ psImport,
+ psCPUImport->ui32RefCount,
+ psCPUImport->ui32RefCount-1);
+
+ if (--psCPUImport->ui32RefCount == 0)
+ {
+
+#if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
+ PVR_ASSERT(psImport->uiSize<IMG_UINT32_MAX);
+#endif
+
+#if !defined(__KERNEL__) && defined(SUPPORT_ION)
+ if (psImport->sCPUImport.iDmaBufFd >= 0)
+ {
+ munmap(psCPUImport->hOSMMapData, psImport->uiSize);
+ }
+ else
+#endif
+ {
+ OSMUnmapPMR(psImport->hBridge,
+ psImport->hPMR,
+ psCPUImport->hOSMMapData,
+ psCPUImport->pvCPUVAddr,
+ (IMG_SIZE_T)psImport->uiSize);
+ }
+
+ OSLockRelease(psCPUImport->hLock);
+
+ _DevmemImportStructRelease(psImport);
+ }
+ else
+ {
+ OSLockRelease(psCPUImport->hLock);
+ }
+}
+
+
diff --git a/drivers/gpu/rogue/services/shared/common/dllist.c b/drivers/gpu/rogue/services/shared/common/dllist.c
new file mode 100644
index 000000000000..ae164277a141
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/dllist.c
@@ -0,0 +1,77 @@
+/*************************************************************************/ /*!
+@File
+@Title Services implementation of double linked lists
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements a double linked list
+@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 "dllist.h"
+
+
+/* Walk through all the nodes on the list until the end or a callback returns FALSE */
+#if defined(RGX_FIRMWARE)
+RGXFW_COREMEM_CODE_IRQ3
+#endif
+IMG_VOID dllist_foreach_node(PDLLIST_NODE psListHead,
+ PFN_NODE_CALLBACK pfnCallBack,
+ IMG_PVOID pvCallbackData)
+{
+ PDLLIST_NODE psWalker = psListHead->psNextNode;
+ PDLLIST_NODE psNextWalker;
+
+ while (psWalker != psListHead)
+ {
+ /*
+ The callback function could remove itself from the list
+ so to avoid NULL pointer deference save the next node pointer
+ before calling the callback
+ */
+ psNextWalker = psWalker->psNextNode;
+ if (pfnCallBack(psWalker, pvCallbackData))
+ {
+ psWalker = psNextWalker;
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
diff --git a/drivers/gpu/rogue/services/shared/common/hash.c b/drivers/gpu/rogue/services/shared/common/hash.c
new file mode 100644
index 000000000000..2fa8ebf9ca2b
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/hash.c
@@ -0,0 +1,669 @@
+/*************************************************************************/ /*!
+@File
+@Title Self scaling hash tables.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description
+ Implements simple self scaling hash tables. Hash collisions are
+ handled by chaining entries together. Hash tables are increased in
+ size when they become more than (50%?) full and decreased in size
+ when less than (25%?) full. Hash tables are never decreased below
+ their initial size.
+@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/ */
+#include "img_defs.h"
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+
+/* services/shared/include/ */
+#include "hash.h"
+
+/* services/client/include/ or services/server/include/ */
+#include "osfunc.h"
+#include "allocmem.h"
+
+#if defined(__KERNEL__)
+#include "pvrsrv.h"
+#endif
+
+#define PRIVATE_MAX(a,b) ((a)>(b)?(a):(b))
+
+#define KEY_TO_INDEX(pHash, key, uSize) \
+ ((pHash)->pfnHashFunc((pHash)->uKeySize, (key), (uSize)) % (uSize))
+
+#define KEY_COMPARE(pHash, pKey1, pKey2) \
+ ((pHash)->pfnKeyComp((pHash)->uKeySize, (pKey1), (pKey2)))
+
+/* Each entry in a hash table is placed into a bucket */
+struct _BUCKET_
+{
+ /* the next bucket on the same chain */
+ struct _BUCKET_ *pNext;
+
+ /* entry value */
+ IMG_UINTPTR_T v;
+
+ /* entry key */
+#if defined (WIN32)
+ IMG_UINTPTR_T k[1];
+#else
+ IMG_UINTPTR_T k[]; /* PRQA S 0642 */ /* override dynamic array declaration warning */
+#endif
+};
+typedef struct _BUCKET_ BUCKET;
+
+struct _HASH_TABLE_
+{
+ /* current size of the hash table */
+ IMG_UINT32 uSize;
+
+ /* number of entries currently in the hash table */
+ IMG_UINT32 uCount;
+
+ /* the minimum size that the hash table should be re-sized to */
+ IMG_UINT32 uMinimumSize;
+
+ /* size of key in bytes */
+ IMG_UINT32 uKeySize;
+
+ /* hash function */
+ HASH_FUNC *pfnHashFunc;
+
+ /* key comparison function */
+ HASH_KEY_COMP *pfnKeyComp;
+
+ /* the hash table array */
+ BUCKET **ppBucketTable;
+};
+
+/*************************************************************************/ /*!
+@Function HASH_Func_Default
+@Description Hash function intended for hashing keys composed of
+ IMG_UINTPTR_T arrays.
+@Input uKeySize The size of the hash key, in bytes.
+@Input pKey A pointer to the key to hash.
+@Input uHashTabLen The length of the hash table.
+@Return The hash value.
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_UINT32
+HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
+{
+ IMG_UINTPTR_T *p = (IMG_UINTPTR_T *)pKey;
+ IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+ IMG_UINT32 ui;
+ IMG_UINT32 uHashKey = 0;
+
+ PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+
+ PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++)
+ {
+ IMG_UINT32 uHashPart = (IMG_UINT32)*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;
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Key_Comp_Default
+@Description Compares keys composed of IMG_UINTPTR_T arrays.
+@Input uKeySize The size of the hash key, in bytes.
+@Input pKey1 Pointer to first hash key to compare.
+@Input pKey2 Pointer to second hash key to compare.
+@Return IMG_TRUE The keys match.
+ IMG_FALSE The keys don't match.
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_BOOL
+HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
+{
+ IMG_UINTPTR_T *p1 = (IMG_UINTPTR_T *)pKey1;
+ IMG_UINTPTR_T *p2 = (IMG_UINTPTR_T *)pKey2;
+ IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+ IMG_UINT32 ui;
+
+ PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++)
+ {
+ if (*p1++ != *p2++)
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+/*************************************************************************/ /*!
+@Function _ChainInsert
+@Description Insert a bucket into the appropriate hash table chain.
+@Input pBucket The bucket
+@Input ppBucketTable The hash table
+@Input uSize The size of the hash table
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+static PVRSRV_ERROR
+_ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
+{
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT (pBucket != IMG_NULL);
+ PVR_ASSERT (ppBucketTable != IMG_NULL);
+ PVR_ASSERT (uSize != 0);
+
+ if ((pBucket == IMG_NULL) || (ppBucketTable == IMG_NULL) || (uSize == 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_ChainInsert: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize); /* PRQA S 0432,0541 */ /* ignore dynamic array warning */
+ pBucket->pNext = ppBucketTable[uIndex];
+ ppBucketTable[uIndex] = pBucket;
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function _Rehash
+@Description Iterate over every entry in an old hash table and
+ rehash into the new table.
+@Input ppOldTable The old hash table
+@Input uOldSize The size of the old hash table
+@Input ppNewTable The new hash table
+@Input uNewSize The size of the new hash table
+@Return None
+*/ /**************************************************************************/
+static PVRSRV_ERROR
+_Rehash (HASH_TABLE *pHash,
+ BUCKET **ppOldTable, IMG_UINT32 uOldSize,
+ BUCKET **ppNewTable, IMG_UINT32 uNewSize)
+{
+ IMG_UINT32 uIndex;
+ for (uIndex=0; uIndex< uOldSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ pBucket = ppOldTable[uIndex];
+ while (pBucket != IMG_NULL)
+ {
+ PVRSRV_ERROR eError;
+ BUCKET *pNextBucket = pBucket->pNext;
+ eError = _ChainInsert (pHash, pBucket, ppNewTable, uNewSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_Rehash: call to _ChainInsert failed"));
+ return eError;
+ }
+ pBucket = pNextBucket;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function _Resize
+@Description Attempt to resize a hash table, failure to allocate a
+ new larger hash table is not considered a hard failure.
+ We simply continue and allow the table to fill up, the
+ effect is to allow hash chains to become longer.
+@Input pHash Hash table to resize.
+@Input uNewSize Required table size.
+@Return IMG_TRUE Success
+ IMG_FALSE Failed
+*/ /**************************************************************************/
+static IMG_BOOL
+_Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
+{
+ if (uNewSize != pHash->uSize)
+ {
+ BUCKET **ppNewTable;
+ IMG_UINT32 uIndex;
+
+ ppNewTable = OSAllocMem(sizeof (BUCKET *) * uNewSize);
+ if (ppNewTable == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ for (uIndex=0; uIndex<uNewSize; uIndex++)
+ ppNewTable[uIndex] = IMG_NULL;
+
+ if (_Rehash (pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable, uNewSize) != PVRSRV_OK)
+ {
+ /*
+ If we fail the rehash then there is nothing we can do as we've already
+ started to modify some of the entries if we just return FALSE here then
+ we will have dropped some items off the hash table.
+ The only reason the rehash can fail if is there is bug in another part
+ of the driver so in reality we should never hit this
+ */
+ PVR_ASSERT(IMG_FALSE);
+ return IMG_FALSE;
+ }
+
+ OSFreeMem(pHash->ppBucketTable);
+ /*not nulling pointer, being reassigned just below*/
+ pHash->ppBucketTable = ppNewTable;
+ pHash->uSize = uNewSize;
+ }
+ return IMG_TRUE;
+}
+
+
+/*************************************************************************/ /*!
+@Function HASH_Create_Extended
+@Description Create a self scaling hash table, using the supplied
+ key size, and the supplied hash and key comparsion
+ functions.
+@Input uInitialLen Initial and minimum length of the
+ hash table, where the length refers to the number
+ of entries in the hash table, not its size in
+ bytes.
+@Input uKeySize The size of the key, in bytes.
+@Input pfnHashFunc Pointer to hash function.
+@Input pfnKeyComp Pointer to key comparsion function.
+@Return IMG_NULL or hash table handle.
+*/ /**************************************************************************/
+IMG_INTERNAL
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp)
+{
+ HASH_TABLE *pHash;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Create_Extended: InitialSize=0x%x", uInitialLen));
+
+ pHash = OSAllocMem(sizeof(HASH_TABLE));
+ if (pHash == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+
+ pHash->uCount = 0;
+ pHash->uSize = uInitialLen;
+ pHash->uMinimumSize = uInitialLen;
+ pHash->uKeySize = uKeySize;
+ pHash->pfnHashFunc = pfnHashFunc;
+ pHash->pfnKeyComp = pfnKeyComp;
+
+ pHash->ppBucketTable = OSAllocMem(sizeof (BUCKET *) * pHash->uSize);
+ if (pHash->ppBucketTable == IMG_NULL)
+ {
+ OSFreeMem(pHash);
+ /*not nulling pointer, out of scope*/
+ return IMG_NULL;
+ }
+
+ for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+ pHash->ppBucketTable[uIndex] = IMG_NULL;
+ return pHash;
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Create
+@Description Create a self scaling hash table with a key
+ consisting of a single IMG_UINTPTR_T, and using
+ the default hash and key comparison functions.
+@Input uInitialLen Initial and minimum length of the
+ hash table, where the length refers to the
+ number of entries in the hash table, not its size
+ in bytes.
+@Return IMG_NULL or hash table handle.
+*/ /**************************************************************************/
+IMG_INTERNAL
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen)
+{
+ return HASH_Create_Extended(uInitialLen, sizeof(IMG_UINTPTR_T),
+ &HASH_Func_Default, &HASH_Key_Comp_Default);
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Delete
+@Description Delete a hash table created by HASH_Create_Extended or
+ HASH_Create. All entries in the table must have been
+ removed before calling this function.
+@Input pHash Hash table
+@Return None
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_VOID
+HASH_Delete (HASH_TABLE *pHash)
+{
+ IMG_BOOL bDoCheck = IMG_TRUE;
+#if defined(__KERNEL__) && !defined(__QNXNTO__)
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+ if (psPVRSRVData != IMG_NULL)
+ {
+ if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+ {
+ bDoCheck = IMG_FALSE;
+ }
+ }
+
+#endif
+ if (pHash != IMG_NULL)
+ {
+ if (bDoCheck)
+ {
+ PVR_ASSERT (pHash->uCount==0);
+ }
+ if(pHash->uCount != 0)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "HASH_Delete: leak detected in hash table!"));
+ PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+ }
+ OSFreeMem(pHash->ppBucketTable);
+ pHash->ppBucketTable = IMG_NULL;
+ OSFreeMem(pHash);
+ /*not nulling pointer, copy on stack*/
+ }
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Insert_Extended
+@Description Insert a key value pair into a hash table created
+ with HASH_Create_Extended.
+@Input pHash Hash table
+@Input pKey Pointer to the key.
+@Input v The value associated with the key.
+@Return IMG_TRUE - success
+ IMG_FALSE - failure
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_BOOL
+HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
+{
+ BUCKET *pBucket;
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Insert_Extended: invalid parameter"));
+ return IMG_FALSE;
+ }
+
+ pBucket = OSAllocMem(sizeof(BUCKET) + pHash->uKeySize);
+ if (pBucket == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ pBucket->v = v;
+ /* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k (linux)*/
+ OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
+ if (_ChainInsert (pHash, pBucket, pHash->ppBucketTable, pHash->uSize) != PVRSRV_OK)
+ {
+ OSFreeMem(pBucket);
+ return IMG_FALSE;
+ }
+
+ pHash->uCount++;
+
+ /* check if we need to think about re-balancing */
+ if (pHash->uCount << 1 > pHash->uSize)
+ {
+ /* Ignore the return code from _Resize because the hash table is
+ still in a valid state and although not ideally sized, it is still
+ functional */
+ _Resize (pHash, pHash->uSize << 1);
+ }
+
+
+ return IMG_TRUE;
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Insert
+@Description Insert a key value pair into a hash table created with
+ HASH_Create.
+@Input pHash Hash table
+@Input k The key value.
+@Input v The value associated with the key.
+@Return IMG_TRUE - success.
+ IMG_FALSE - failure.
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_BOOL
+HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
+{
+ return HASH_Insert_Extended(pHash, &k, v);
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Remove_Extended
+@Description Remove a key from a hash table created with
+ HASH_Create_Extended.
+@Input pHash Hash table
+@Input pKey Pointer to key.
+@Return 0 if the key is missing, or the value associated with the key.
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_UINTPTR_T
+HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+ BUCKET **ppBucket;
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Remove_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+ {
+ /* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k */
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+ {
+ BUCKET *pBucket = *ppBucket;
+ IMG_UINTPTR_T v = pBucket->v;
+ (*ppBucket) = pBucket->pNext;
+
+ OSFreeMem(pBucket);
+ /*not nulling original pointer, already overwritten*/
+
+ pHash->uCount--;
+
+ /* check if we need to think about re-balancing */
+ if (pHash->uSize > (pHash->uCount << 2) &&
+ pHash->uSize > pHash->uMinimumSize)
+ {
+ /* Ignore the return code from _Resize because the
+ hash table is still in a valid state and although
+ not ideally sized, it is still functional */
+ _Resize (pHash,
+ PRIVATE_MAX (pHash->uSize >> 1,
+ pHash->uMinimumSize));
+ }
+
+ return v;
+ }
+ }
+ return 0;
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Remove
+@Description Remove a key value pair from a hash table created
+ with HASH_Create.
+@Input pHash Hash table
+@Input k The key
+@Return 0 if the key is missing, or the value associated with the key.
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_UINTPTR_T
+HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+ return HASH_Remove_Extended(pHash, &k);
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Retrieve_Extended
+@Description Retrieve a value from a hash table created with
+ HASH_Create_Extended.
+@Input pHash Hash table
+@Input pKey Pointer to the key.
+@Return 0 if the key is missing, or the value associated with the key.
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_UINTPTR_T
+HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+ BUCKET **ppBucket;
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Retrieve_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+ {
+ /* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k */
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+ {
+ BUCKET *pBucket = *ppBucket;
+ IMG_UINTPTR_T v = pBucket->v;
+
+ return v;
+ }
+ }
+ return 0;
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Retrieve
+@Description Retrieve a value from a hash table created with
+ HASH_Create.
+@Input pHash Hash table
+@Input k The key
+@Return 0 if the key is missing, or the value associated with the key.
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_UINTPTR_T
+HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+ return HASH_Retrieve_Extended(pHash, &k);
+}
+
+/*************************************************************************/ /*!
+@Function HASH_Iterate
+@Description Iterate over every entry in the hash table
+@Input pHash - Hash table to iterate
+@Input pfnCallback - Callback to call with the key and data for each
+ entry in the hash table
+@Return Callback error if any, otherwise PVRSRV_OK
+*/ /**************************************************************************/
+IMG_INTERNAL PVRSRV_ERROR
+HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback)
+{
+ IMG_UINT32 uIndex;
+ for (uIndex=0; uIndex < pHash->uSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ pBucket = pHash->ppBucketTable[uIndex];
+ while (pBucket != IMG_NULL)
+ {
+ PVRSRV_ERROR eError;
+ BUCKET *pNextBucket = pBucket->pNext;
+
+ eError = pfnCallback((IMG_UINTPTR_T) ((IMG_VOID *) *(pBucket->k)), (IMG_UINTPTR_T) pBucket->v);
+
+ /* The callback might want us to break out early */
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ pBucket = pNextBucket;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+
+#ifdef HASH_TRACE
+/*************************************************************************/ /*!
+@Function HASH_Dump
+@Description To dump the contents of a hash table in human readable
+ form.
+@Input pHash Hash table
+*/ /**************************************************************************/
+IMG_VOID
+HASH_Dump (HASH_TABLE *pHash)
+{
+ IMG_UINT32 uIndex;
+ IMG_UINT32 uMaxLength=0;
+ IMG_UINT32 uEmptyCount=0;
+
+ PVR_ASSERT (pHash != IMG_NULL);
+ for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ IMG_UINT32 uLength = 0;
+ if (pHash->ppBucketTable[uIndex] == IMG_NULL)
+ {
+ uEmptyCount++;
+ }
+ for (pBucket=pHash->ppBucketTable[uIndex];
+ pBucket != IMG_NULL;
+ pBucket = pBucket->pNext)
+ {
+ uLength++;
+ }
+ uMaxLength = PRIVATE_MAX (uMaxLength, uLength);
+ }
+
+ PVR_TRACE(("hash table: uMinimumSize=%d size=%d count=%d",
+ pHash->uMinimumSize, pHash->uSize, pHash->uCount));
+ PVR_TRACE((" empty=%d max=%d", uEmptyCount, uMaxLength));
+}
+#endif
diff --git a/drivers/gpu/rogue/services/shared/common/ra.c b/drivers/gpu/rogue/services/shared/common/ra.c
new file mode 100644
index 000000000000..3162e6d08889
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/ra.c
@@ -0,0 +1,1339 @@
+/*************************************************************************/ /*!
+@File
+@Title Resource Allocator
+@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.
+
+@Description
+ Implements generic resource allocation. The resource
+ allocator was originally intended to manage address spaces. In
+ practice the resource allocator is generic and can manage arbitrary
+ sets of integers.
+
+ Resources are allocated from arenas. Arena's can be created with an
+ initial span of resources. Further resources spans can be added to
+ arenas. A call back mechanism allows an arena to request further
+ resource spans on demand.
+
+ Each arena maintains an ordered list of resource segments each
+ described by a boundary tag. Each boundary tag describes a segment
+ of resources which are either 'free', available for allocation, or
+ 'busy' currently allocated. Adjacent 'free' segments are always
+ coallesced to avoid fragmentation.
+
+ For allocation, all 'free' segments are kept on lists of 'free'
+ segments in a table index by pvr_log2(segment size). ie Each table index
+ n holds 'free' segments in the size range 2^n -> 2^(n+1) - 1.
+
+ Allocation policy is based on an *almost* good fit strategy.
+
+ Allocated segments are inserted into a self scaling hash table which
+ maps the base resource of the span to the relevant boundary
+ tag. This allows the code to get back to the bounary tag without
+ exporting explicit boundary tag references through the API.
+
+ Each arena has an associated quantum size, all allocations from the
+ arena are made in multiples of the basic quantum.
+
+ On resource exhaustion in an arena, a callback if provided will be
+ used to request further resources. Resouces spans allocated by the
+ callback mechanism will be returned when freed (through one of the
+ two callbacks).
+*/ /**************************************************************************/
+
+/* Issues:
+ * - flags, flags are passed into the resource allocator but are not currently used.
+ * - determination, of import size, is currently braindead.
+ * - debug code should be moved out to own module and #ifdef'd
+ */
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "uniq_key_splay_tree.h"
+
+#include "hash.h"
+#include "ra.h"
+
+#include "osfunc.h"
+#include "allocmem.h"
+#include "lock.h"
+
+/* The initial, and minimum size of the live address -> boundary tag
+ structure hash table. The value 64 is a fairly arbitrary
+ choice. The hash table resizes on demand so the value choosen is
+ not critical. */
+#define MINIMUM_HASH_SIZE (64)
+
+
+/* #define RA_VALIDATE */
+
+#if defined(__KLOCWORK__)
+ /* make sure Klocworks analyse all the code (including the debug one) */
+ #if !defined(RA_VALIDATE)
+ #define RA_VALIDATE
+ #endif
+#endif
+
+#if (!defined(PVRSRV_NEED_PVR_ASSERT)) || (!defined(RA_VALIDATE))
+ /* Disable the asserts unless explicitly told otherwise. They slow the driver
+ too much for other people */
+
+ #undef PVR_ASSERT
+ /* let's use a macro that really do not do anything when compiling in release
+ mode! */
+ #define PVR_ASSERT(x)
+#endif
+
+/* boundary tags, used to describe a resource segment */
+struct _BT_
+{
+ enum bt_type
+ {
+ btt_free, /* free resource segment */
+ btt_live /* allocated resource segment */
+ } type;
+
+ unsigned int is_leftmost;
+ unsigned int is_rightmost;
+ unsigned int free_import;
+
+ /* The base resource and extent of this segment */
+ RA_BASE_T base;
+ RA_LENGTH_T uSize;
+
+ /* doubly linked ordered list of all segments within the arena */
+ struct _BT_ *pNextSegment;
+ struct _BT_ *pPrevSegment;
+
+ /* doubly linked un-ordered list of free segments with the same flags. */
+ struct _BT_ * next_free;
+ struct _BT_ * prev_free;
+
+ /* a user reference associated with this span, user references are
+ * currently only provided in the callback mechanism */
+ IMG_HANDLE hPriv;
+
+ /* Flags to match on this span */
+ IMG_UINT32 uFlags;
+
+};
+typedef struct _BT_ BT;
+
+
+/* resource allocation arena */
+struct _RA_ARENA_
+{
+ /* arena name for diagnostics output */
+ IMG_CHAR *name;
+
+ /* allocations within this arena are quantum sized */
+ RA_LENGTH_T uQuantum;
+
+ /* import interface, if provided */
+ IMG_BOOL (*pImportAlloc)(RA_PERARENA_HANDLE h,
+ RA_LENGTH_T uSize,
+ IMG_UINT32 uFlags,
+ RA_BASE_T *pBase,
+ RA_LENGTH_T *pActualSize,
+ RA_PERISPAN_HANDLE *phPriv);
+ IMG_VOID (*pImportFree) (RA_PERARENA_HANDLE,
+ RA_BASE_T,
+ RA_PERISPAN_HANDLE hPriv);
+
+ /* arbitrary handle provided by arena owner to be passed into the
+ * import alloc and free hooks */
+ IMG_VOID *pImportHandle;
+
+ IMG_PSPLAY_TREE per_flags_buckets;
+
+ /* resource segment list */
+ BT *pHeadSegment;
+
+ /* segment address to boundary tag hash table */
+ HASH_TABLE *pSegmentHash;
+
+ /* Lock for this arena */
+ POS_LOCK hLock;
+
+ /* LockClass of this arena. This is used within lockdep to decide if a
+ * recursive call sequence with the same lock class is allowed or not. */
+ IMG_UINT32 ui32LockClass;
+};
+
+/*************************************************************************/ /*!
+@Function _RequestAllocFail
+@Description Default callback allocator used if no callback is
+ specified, always fails to allocate further resources to the
+ arena.
+@Input _h - callback handle
+@Input _uSize - requested allocation size
+@Output _pActualSize - actual allocation size
+@Input _pRef - user reference
+@Input _uflags - allocation flags
+@Input _pBase - receives allocated base
+@Return IMG_FALSE, this function always fails to allocate.
+*/ /**************************************************************************/
+static IMG_BOOL
+_RequestAllocFail (RA_PERARENA_HANDLE _h,
+ RA_LENGTH_T _uSize,
+ IMG_UINT32 _uFlags,
+ RA_BASE_T *_pBase,
+ RA_LENGTH_T *_pActualSize,
+ RA_PERISPAN_HANDLE *_phPriv)
+{
+ PVR_UNREFERENCED_PARAMETER (_h);
+ PVR_UNREFERENCED_PARAMETER (_uSize);
+ PVR_UNREFERENCED_PARAMETER (_pActualSize);
+ PVR_UNREFERENCED_PARAMETER (_phPriv);
+ PVR_UNREFERENCED_PARAMETER (_uFlags);
+ PVR_UNREFERENCED_PARAMETER (_pBase);
+
+ return IMG_FALSE;
+}
+
+
+#if defined (HAS_BUILTIN_CTZLL)
+ /* make sure to trigger an error if someone change the buckets or the bHasEltsMapping size
+ the bHasEltsMapping is used to quickly determine the smallest bucket containing elements.
+ therefore it must have at least as many bits has the buckets array have buckets. The RA
+ implementation actually uses one more bit. */
+ BLD_ASSERT((sizeof(((IMG_PSPLAY_TREE) 0)->buckets) / sizeof(((IMG_PSPLAY_TREE) 0)->buckets[0]))
+ < 8 * sizeof(((IMG_PSPLAY_TREE) 0)->bHasEltsMapping), ra_c);
+#endif
+
+
+/*************************************************************************/ /*!
+@Function pvr_log2
+@Description Computes the floor of the log base 2 of a unsigned integer
+@Input n Unsigned integer
+@Return Floor(Log2(n))
+*/ /**************************************************************************/
+#if defined(__GNUC__)
+/* make sure to trigger a problem if someone changes the RA_LENGTH_T type
+ indeed the __builtin_clzll is for unsigned long long variables.
+
+ if someone changes RA_LENGTH to unsigned long, then use __builtin_clzl
+ if it changes to unsigned int, use __builtin_clz
+
+ if it changes for something bigger than unsigned long long,
+ then revert the pvr_log2 to the classic implementation */
+BLD_ASSERT(sizeof(RA_LENGTH_T) == sizeof(unsigned long long), ra_c);
+
+static inline IMG_UINT32 pvr_log2(RA_LENGTH_T n)
+{
+ PVR_ASSERT( n != 0 ); /* Log2 is not defined on 0 */
+
+ return (8 * sizeof(RA_LENGTH_T)) - 1 - __builtin_clzll(n);
+}
+#else
+static IMG_UINT32
+pvr_log2 (RA_LENGTH_T n)
+{
+ IMG_UINT32 l = 0;
+
+ PVR_ASSERT( n != 0 ); /* Log2 is not defined on 0 */
+
+ n>>=1;
+ while (n>0)
+ {
+ n>>=1;
+ l++;
+ }
+ return l;
+}
+#endif
+
+
+#if defined(RA_VALIDATE)
+/*************************************************************************/ /*!
+@Function _IsInSegmentList
+@Description Tests if a BT is in the segment list.
+@Input pArena The arena.
+@Input pBT The boundary tag to look for.
+@Return IMG_FALSE BT was not in the arena's segment list.
+ IMG_TRUE BT was in the arena's segment list.
+*/ /**************************************************************************/
+static IMG_BOOL
+_IsInSegmentList (RA_ARENA *pArena,
+ BT *pBT)
+{
+ BT* pBTScan;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+ PVR_ASSERT (pBT != IMG_NULL);
+
+ /* Walk the segment list until we see the BT pointer... */
+ pBTScan = pArena->pHeadSegment;
+ while (pBTScan != IMG_NULL && pBTScan != pBT)
+ {
+ pBTScan = pBTScan->pNextSegment;
+ }
+
+ /* Test if we found it and then return */
+ return (pBTScan == pBT);
+}
+
+/*************************************************************************/ /*!
+@Function _IsInFreeList
+@Description Tests if a BT is in the free list.
+@Input pArena The arena.
+@Input pBT The boundary tag to look for.
+@Return IMG_FALSE BT was not in the arena's free list.
+ IMG_TRUE BT was in the arena's free list.
+*/ /**************************************************************************/
+static IMG_BOOL
+_IsInFreeList (RA_ARENA *pArena,
+ BT *pBT)
+{
+ BT* pBTScan;
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+ PVR_ASSERT (pBT != IMG_NULL);
+
+ /* Look for the free list that holds BTs of this size... */
+ uIndex = pvr_log2 (pBT->uSize);
+ PVR_ASSERT (uIndex < FREE_TABLE_LIMIT);
+
+ pArena->per_flags_buckets = PVRSRVSplay(pBT->uFlags, pArena->per_flags_buckets);
+ if ((pArena->per_flags_buckets == NULL) || (pArena->per_flags_buckets->flags != pBT->uFlags))
+ {
+ return 0;
+ }
+ else
+ {
+ pBTScan = pArena->per_flags_buckets->buckets[uIndex];
+ while (pBTScan != IMG_NULL && pBTScan != pBT)
+ {
+ pBTScan = pBTScan->next_free;
+ }
+
+ /* Test if we found it and then return */
+ return (pBTScan == pBT);
+ }
+}
+
+/* is_arena_valid should only be used in debug mode.
+ it checks that some properties an arena must have are verified */
+static int is_arena_valid(struct _RA_ARENA_ * arena)
+{
+ struct _BT_ * chunk;
+#if defined(HAS_BUILTIN_CTZLL)
+ unsigned int i;
+#endif
+
+ for (chunk = arena->pHeadSegment; chunk != NULL; chunk = chunk->pNextSegment)
+ {
+ /* if next segment is NULL, then it must be a rightmost */
+ PVR_ASSERT((chunk->pNextSegment != NULL) || (chunk->is_rightmost));
+ /* if prev segment is NULL, then it must be a leftmost */
+ PVR_ASSERT((chunk->pPrevSegment != NULL) || (chunk->is_leftmost));
+
+ if (chunk->type == btt_free)
+ {
+ /* checks the correctness of the type field */
+ PVR_ASSERT(_IsInFreeList(arena, chunk));
+
+ /* check that there can't be two consecutive free chunks.
+ Indeed, instead of having two consecutive free chunks,
+ there should be only one that span the size of the two. */
+ PVR_ASSERT((chunk->is_leftmost) || (chunk->pPrevSegment->type != btt_free));
+ PVR_ASSERT((chunk->is_rightmost) || (chunk->pNextSegment->type != btt_free));
+ }
+ else
+ {
+ /* checks the correctness of the type field */
+ PVR_ASSERT(!_IsInFreeList(arena, chunk));
+ }
+
+ PVR_ASSERT((chunk->is_leftmost) || (chunk->pPrevSegment->base + chunk->pPrevSegment->uSize == chunk->base));
+ PVR_ASSERT((chunk->is_rightmost) || (chunk->base + chunk->uSize == chunk->pNextSegment->base));
+
+ /* all segments of the same imports must have the same flags ... */
+ PVR_ASSERT((chunk->is_rightmost) || (chunk->uFlags == chunk->pNextSegment->uFlags));
+ /* ... and the same import handle */
+ PVR_ASSERT((chunk->is_rightmost) || (chunk->hPriv == chunk->pNextSegment->hPriv));
+
+
+ /* if a free chunk spans a whole import, then it must be an 'not to free import'.
+ Otherwise it should have been freed. */
+ PVR_ASSERT((!chunk->is_leftmost) || (!chunk->is_rightmost) || (chunk->type == btt_live) || (!chunk->free_import));
+ }
+
+#if defined(HAS_BUILTIN_CTZLL)
+ if (arena->per_flags_buckets != NULL)
+ {
+ for (i = 0; i < FREE_TABLE_LIMIT; ++i)
+ {
+ /* verify that the bHasEltsMapping is correct for this flags bucket */
+ PVR_ASSERT(
+ ((arena->per_flags_buckets->buckets[i] == NULL) &&
+ (( (arena->per_flags_buckets->bHasEltsMapping & ((IMG_ELTS_MAPPINGS) 1 << i)) == 0)))
+ ||
+ ((arena->per_flags_buckets->buckets[i] != NULL) &&
+ (( (arena->per_flags_buckets->bHasEltsMapping & ((IMG_ELTS_MAPPINGS) 1 << i)) != 0)))
+ );
+ }
+ }
+#endif
+
+ /* if arena was not valid, one of the assert before should have triggered */
+ return 1;
+}
+#endif
+/*************************************************************************/ /*!
+@Function _SegmentListInsertAfter
+@Description Insert a boundary tag into an arena segment list after a
+ specified boundary tag.
+@Input pInsertionPoint The insertion point.
+@Input pBT The boundary tag to insert.
+@Return PVRSRV_OK (doesn't fail)
+*/ /**************************************************************************/
+static INLINE PVRSRV_ERROR
+_SegmentListInsertAfter (BT *pInsertionPoint,
+ BT *pBT)
+{
+ PVR_ASSERT (pBT != IMG_NULL);
+ PVR_ASSERT (pInsertionPoint != IMG_NULL);
+
+ pBT->pNextSegment = pInsertionPoint->pNextSegment;
+ pBT->pPrevSegment = pInsertionPoint;
+ if (pInsertionPoint->pNextSegment != IMG_NULL)
+ {
+ pInsertionPoint->pNextSegment->pPrevSegment = pBT;
+ }
+ pInsertionPoint->pNextSegment = pBT;
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function _SegmentListInsert
+@Description Insert a boundary tag into an arena segment list
+@Input pArena The arena.
+@Input pBT The boundary tag to insert.
+@Return PVRSRV_OK (doesn't fail)
+*/ /**************************************************************************/
+static INLINE PVRSRV_ERROR
+_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVR_ASSERT (!_IsInSegmentList(pArena, pBT));
+
+ /* insert into the segment chain */
+ pBT->pNextSegment = pArena->pHeadSegment;
+ pArena->pHeadSegment = pBT;
+ if (pBT->pNextSegment != NULL)
+ {
+ pBT->pNextSegment->pPrevSegment = pBT;
+ }
+
+ pBT->pPrevSegment = NULL;
+
+ return eError;
+}
+
+/*************************************************************************/ /*!
+@Function _SegmentListRemove
+@Description Remove a boundary tag from an arena segment list.
+@Input pArena The arena.
+@Input pBT The boundary tag to remove.
+*/ /**************************************************************************/
+static IMG_VOID
+_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
+{
+ PVR_ASSERT (_IsInSegmentList(pArena, pBT));
+
+ if (pBT->pPrevSegment == IMG_NULL)
+ pArena->pHeadSegment = pBT->pNextSegment;
+ else
+ pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
+
+ if (pBT->pNextSegment != IMG_NULL)
+ pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
+}
+
+
+/*************************************************************************/ /*!
+@Function _BuildBT
+@Description Construct a boundary tag for a free segment.
+@Input base The base of the resource segment.
+@Input uSize The extent of the resouce segment.
+@Input uFlags The flags to give to the boundary tag
+@Return Boundary tag or NULL
+*/ /**************************************************************************/
+static BT *
+_BuildBT (RA_BASE_T base,
+ RA_LENGTH_T uSize,
+ RA_FLAGS_T uFlags
+ )
+{
+ BT *pBT;
+
+ pBT = OSAllocMem(sizeof(BT));
+ if (pBT == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pBT, 0, sizeof(BT));
+
+ pBT->is_leftmost = 1;
+ pBT->is_rightmost = 1;
+ pBT->type = btt_live;
+ pBT->base = base;
+ pBT->uSize = uSize;
+ pBT->uFlags = uFlags;
+ pBT->free_import = 0;
+
+ return pBT;
+}
+
+
+/*************************************************************************/ /*!
+@Function _SegmentSplit
+@Description Split a segment into two, maintain the arena segment list. The
+ boundary tag should not be in the free table. Neither the
+ original or the new neighbour bounary tag will be in the free
+ table.
+@Input pBT The boundary tag to split.
+@Input uSize The required segment size of boundary tag after
+ splitting.
+@Return New neighbour boundary tag or NULL.
+*/ /**************************************************************************/
+static BT *
+_SegmentSplit (BT *pBT, RA_LENGTH_T uSize)
+{
+ BT *pNeighbour;
+
+ pNeighbour = _BuildBT(pBT->base + uSize, pBT->uSize - uSize, pBT->uFlags);
+ if (pNeighbour == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+
+ _SegmentListInsertAfter(pBT, pNeighbour);
+
+ pNeighbour->is_leftmost = 0;
+ pNeighbour->is_rightmost = pBT->is_rightmost;
+ pNeighbour->free_import = pBT->free_import;
+ pBT->is_rightmost = 0;
+ pNeighbour->hPriv = pBT->hPriv;
+ pBT->uSize = uSize;
+ pNeighbour->uFlags = pBT->uFlags;
+
+ return pNeighbour;
+}
+
+/*************************************************************************/ /*!
+@Function _FreeListInsert
+@Description Insert a boundary tag into an arena free table.
+@Input pArena The arena.
+@Input pBT The boundary tag.
+*/ /**************************************************************************/
+static IMG_VOID
+_FreeListInsert (RA_ARENA *pArena, BT *pBT)
+{
+ IMG_UINT32 uIndex;
+ uIndex = pvr_log2 (pBT->uSize);
+
+ PVR_ASSERT (uIndex < FREE_TABLE_LIMIT);
+ PVR_ASSERT (!_IsInFreeList(pArena, pBT));
+
+ pBT->type = btt_free;
+
+ pArena->per_flags_buckets = PVRSRVSplay(pBT->uFlags, pArena->per_flags_buckets);
+ /* the flags item in the splay tree must have been created before-hand by
+ _InsertResource */
+ PVR_ASSERT(pArena->per_flags_buckets != NULL);
+ PVR_ASSERT(pArena->per_flags_buckets->buckets != NULL);
+
+ pBT->next_free = pArena->per_flags_buckets->buckets[uIndex];
+ if (pBT->next_free != NULL)
+ {
+ pBT->next_free->prev_free = pBT;
+ }
+ pBT->prev_free = NULL;
+ pArena->per_flags_buckets->buckets[uIndex] = pBT;
+
+#if defined(HAS_BUILTIN_CTZLL)
+ /* tells that bucket[index] now contains elements */
+ pArena->per_flags_buckets->bHasEltsMapping |= ((IMG_ELTS_MAPPINGS) 1 << uIndex);
+#endif
+}
+
+/*************************************************************************/ /*!
+@Function _FreeListRemove
+@Description Remove a boundary tag from an arena free table.
+@Input pArena The arena.
+@Input pBT The boundary tag.
+*/ /**************************************************************************/
+static IMG_VOID
+_FreeListRemove (RA_ARENA *pArena, BT *pBT)
+{
+ IMG_UINT32 uIndex;
+ uIndex = pvr_log2 (pBT->uSize);
+
+ PVR_ASSERT (uIndex < FREE_TABLE_LIMIT);
+ PVR_ASSERT (_IsInFreeList(pArena, pBT));
+
+ if (pBT->next_free != NULL)
+ {
+ pBT->next_free->prev_free = pBT->prev_free;
+ }
+
+ if (pBT->prev_free != NULL)
+ {
+ pBT->prev_free->next_free = pBT->next_free;
+ }
+ else
+ {
+ pArena->per_flags_buckets = PVRSRVSplay(pBT->uFlags, pArena->per_flags_buckets);
+ /* the flags item in the splay tree must have already been created
+ (otherwise how could there be a segment with these flags */
+ PVR_ASSERT(pArena->per_flags_buckets != NULL);
+ PVR_ASSERT(pArena->per_flags_buckets->buckets != NULL);
+
+ pArena->per_flags_buckets->buckets[uIndex] = pBT->next_free;
+#if defined(HAS_BUILTIN_CTZLL)
+ if (pArena->per_flags_buckets->buckets[uIndex] == NULL)
+ {
+ /* there is no more elements in this bucket. Update the mapping. */
+ pArena->per_flags_buckets->bHasEltsMapping &= ~((IMG_ELTS_MAPPINGS) 1 << uIndex);
+ }
+#endif
+ }
+
+
+ PVR_ASSERT (!_IsInFreeList(pArena, pBT));
+ pBT->type = btt_live;
+}
+
+
+/*************************************************************************/ /*!
+@Function _InsertResource
+@Description Add a free resource segment to an arena.
+@Input pArena The arena.
+@Input base The base of the resource segment.
+@Input uSize The extent of the resource segment.
+@Input uFlags The flags of the new resources.
+@Return New bucket pointer
+ IMG_NULL on failure
+*/ /**************************************************************************/
+static BT *
+_InsertResource (RA_ARENA *pArena,
+ RA_BASE_T base,
+ RA_LENGTH_T uSize,
+ RA_FLAGS_T uFlags
+ )
+{
+ BT *pBT;
+ PVR_ASSERT (pArena!=IMG_NULL);
+
+ pBT = _BuildBT (base, uSize, uFlags);
+
+ if (pBT != IMG_NULL)
+ {
+ IMG_PSPLAY_TREE tmp = PVRSRVInsert(pBT->uFlags, pArena->per_flags_buckets);
+ if (tmp == NULL)
+ {
+ OSFreeMem(pBT);
+ return NULL;
+ }
+
+ pArena->per_flags_buckets = tmp;
+ _SegmentListInsert (pArena, pBT);
+ _FreeListInsert (pArena, pBT);
+ }
+ return pBT;
+}
+
+/*************************************************************************/ /*!
+@Function _InsertResourceSpan
+@Description Add a free resource span to an arena, marked for free_import.
+@Input pArena The arena.
+@Input base The base of the resource segment.
+@Input uSize The extent of the resource segment.
+@Return The boundary tag representing the free resource segment,
+ or IMG_NULL on failure.
+*/ /**************************************************************************/
+static INLINE BT *
+_InsertResourceSpan (RA_ARENA *pArena,
+ RA_BASE_T base,
+ RA_LENGTH_T uSize,
+ RA_FLAGS_T uFlags)
+{
+ BT *pBT = _InsertResource(pArena, base, uSize, uFlags);
+ if (pBT != NULL)
+ {
+ pBT->free_import = 1;
+ }
+ return pBT;
+}
+
+
+/*************************************************************************/ /*!
+@Function _RemoveResourceSpan
+@Description Frees a resource span from an arena, returning the imported
+ span via the callback.
+@Input pArena The arena.
+@Input pBT The boundary tag to free.
+@Return IMG_FALSE failure - span was still in use
+ IMG_TRUE success - span was removed and returned
+*/ /**************************************************************************/
+static INLINE IMG_BOOL
+_RemoveResourceSpan (RA_ARENA *pArena, BT *pBT)
+{
+ PVR_ASSERT (pArena!=IMG_NULL);
+ PVR_ASSERT (pBT!=IMG_NULL);
+
+ if (pBT->free_import &&
+ pBT->is_leftmost &&
+ pBT->is_rightmost)
+ {
+ _SegmentListRemove (pArena, pBT);
+ pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->hPriv);
+ OSFreeMem(pBT);
+
+ return IMG_TRUE;
+ }
+
+
+ return IMG_FALSE;
+}
+
+
+/*************************************************************************/ /*!
+@Function _FreeBT
+@Description Free a boundary tag taking care of the segment list and the
+ boundary tag free table.
+@Input pArena The arena.
+@Input pBT The boundary tag to free.
+*/ /**************************************************************************/
+static IMG_VOID
+_FreeBT (RA_ARENA *pArena, BT *pBT)
+{
+ BT *pNeighbour;
+
+ PVR_ASSERT (pArena!=IMG_NULL);
+ PVR_ASSERT (pBT!=IMG_NULL);
+ PVR_ASSERT (!_IsInFreeList(pArena, pBT));
+
+ /* try and coalesce with left neighbour */
+ pNeighbour = pBT->pPrevSegment;
+ if ((!pBT->is_leftmost) && (pNeighbour->type == btt_free))
+ {
+ /* Sanity check. */
+ PVR_ASSERT(pNeighbour->base + pNeighbour->uSize == pBT->base);
+
+ _FreeListRemove (pArena, pNeighbour);
+ _SegmentListRemove (pArena, pNeighbour);
+ pBT->base = pNeighbour->base;
+
+ pBT->uSize += pNeighbour->uSize;
+ pBT->is_leftmost = pNeighbour->is_leftmost;
+ OSFreeMem(pNeighbour);
+ }
+
+ /* try to coalesce with right neighbour */
+ pNeighbour = pBT->pNextSegment;
+ if ((!pBT->is_rightmost) && (pNeighbour->type == btt_free))
+ {
+ /* sanity check */
+ PVR_ASSERT(pBT->base + pBT->uSize == pNeighbour->base);
+
+ _FreeListRemove (pArena, pNeighbour);
+ _SegmentListRemove (pArena, pNeighbour);
+ pBT->uSize += pNeighbour->uSize;
+ pBT->is_rightmost = pNeighbour->is_rightmost;
+ OSFreeMem(pNeighbour);
+ }
+
+ if (_RemoveResourceSpan(pArena, pBT) == IMG_FALSE)
+ {
+ _FreeListInsert (pArena, pBT);
+ PVR_ASSERT( (!pBT->is_rightmost) || (!pBT->is_leftmost) || (!pBT->free_import) );
+ }
+
+ PVR_ASSERT(is_arena_valid(pArena));
+}
+
+
+/*
+ This function returns the first element in a bucket that can be split
+ in a way that one of the subsegment can meet the size and alignment
+ criteria.
+
+ The first_elt is the bucket to look into. Remember that a bucket is
+ implemented as a pointer to the first element of the linked list.
+
+ nb_max_try is used to limit the number of elements considered.
+ This is used to only consider the first nb_max_try elements in the
+ free-list. The special value ~0 is used to say unlimited i.e. consider
+ all elements in the free list
+ */
+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)
+{
+ struct _BT_ * walker;
+
+ for (walker = first_elt; (walker != NULL) && (nb_max_try != 0); walker = walker->next_free)
+ {
+ const RA_BASE_T aligned_base = (uAlignment > 1) ?
+ (walker->base + uAlignment - 1) & ~(uAlignment - 1)
+ : walker->base;
+
+ if (walker->base + walker->uSize >= aligned_base + uSize)
+ {
+ return walker;
+ }
+
+ /* 0xFFFF...FFFF is used has nb_max_try = infinity. */
+ if (nb_max_try != (unsigned int) ~0)
+ {
+ nb_max_try--;
+ }
+ }
+
+ return NULL;
+}
+
+
+/*************************************************************************/ /*!
+@Function _AttemptAllocAligned
+@Description Attempt an allocation from an arena.
+@Input pArena The arena.
+@Input uSize The requested allocation size.
+@Output phPriv The user references associated with
+ the imported segment. (optional)
+@Input flags Allocation flags
+@Input uAlignment Required uAlignment, or 0.
+ Must be a power of 2 if not 0
+@Output base Allocated resource base (non optional, must not be NULL)
+@Return IMG_FALSE failure
+ IMG_TRUE success
+*/ /**************************************************************************/
+static IMG_BOOL
+_AttemptAllocAligned (RA_ARENA *pArena,
+ RA_LENGTH_T uSize,
+ IMG_UINT32 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!=IMG_NULL);
+ PVR_ASSERT (base != NULL);
+
+ pArena->per_flags_buckets = PVRSRVSplay(uFlags, pArena->per_flags_buckets);
+ if ((pArena->per_flags_buckets == NULL) || (pArena->per_flags_buckets->ui32Flags != uFlags))
+ {
+ /* no chunks with these flags. */
+ return IMG_FALSE;
+ }
+
+ index_low = pvr_log2(uSize);
+ index_high = pvr_log2(uSize + uAlignment - 1);
+
+ PVR_ASSERT(index_low < FREE_TABLE_LIMIT);
+ PVR_ASSERT(index_high < FREE_TABLE_LIMIT);
+ PVR_ASSERT(index_low <= index_high);
+
+#if defined(HAS_BUILTIN_CTZLL)
+ i = __builtin_ctzll((IMG_ELTS_MAPPINGS) (~((1 << (index_high + 1)) - 1)) & pArena->per_flags_buckets->bHasEltsMapping);
+#else
+ for (i = index_high + 1; (i < FREE_TABLE_LIMIT) && (pArena->per_flags_buckets->buckets[i] == NULL); ++i)
+ {
+ }
+#endif
+ PVR_ASSERT(i <= FREE_TABLE_LIMIT);
+
+ if (i != FREE_TABLE_LIMIT)
+ {
+ /* since we start at index_high + 1, we are guarantee to exit */
+ pBT = find_chunk_in_bucket(pArena->per_flags_buckets->buckets[i], uSize, uAlignment, 1);
+ }
+ else
+ {
+ for (i = index_high; (i != index_low - 1) && (pBT == NULL); --i)
+ {
+ pBT = find_chunk_in_bucket(pArena->per_flags_buckets->buckets[i], uSize, uAlignment, (unsigned int) ~0);
+ }
+ }
+
+ if (pBT == NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ aligned_base = (uAlignment > 1) ? (pBT->base + uAlignment - 1) & ~(uAlignment - 1) : pBT->base;
+
+ _FreeListRemove (pArena, pBT);
+
+ /* 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", __FUNCTION__));
+ /* 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", __FUNCTION__));
+ /* Put pBT back in the list */
+ _FreeListInsert (pArena, pBT);
+ return IMG_FALSE;
+ }
+
+ _FreeListInsert (pArena, pNeighbour);
+ }
+
+ pBT->type = btt_live;
+
+ if (!HASH_Insert_Extended (pArena->pSegmentHash, &pBT->base, (IMG_UINTPTR_T)pBT))
+ {
+ _FreeBT (pArena, pBT);
+ return IMG_FALSE;
+ }
+
+ if (phPriv != IMG_NULL)
+ *phPriv = pBT->hPriv;
+
+ *base = pBT->base;
+
+ return IMG_TRUE;
+}
+
+
+
+/*************************************************************************/ /*!
+@Function RA_Create
+@Description To create a resource arena.
+@Input name The name of the arena for diagnostic purposes.
+@Input base The base of an initial resource span or 0.
+@Input uSize The size of an initial resource span or 0.
+@Input uFlags The flags of an initial resource span or 0.
+@Input ulog2Quantum The arena allocation quantum.
+@Input imp_alloc A resource allocation callback or 0.
+@Input imp_free A resource de-allocation callback or 0.
+@Input pImportHandle Handle passed to alloc and free or 0.
+@Return arena handle, or IMG_NULL.
+*/ /**************************************************************************/
+IMG_INTERNAL RA_ARENA *
+RA_Create (IMG_CHAR *name,
+ RA_LOG2QUANTUM_T uLog2Quantum,
+ IMG_UINT32 ui32LockClass,
+ IMG_BOOL (*imp_alloc)(RA_PERARENA_HANDLE h,
+ RA_LENGTH_T uSize,
+ RA_FLAGS_T _flags,
+ /* returned data */
+ RA_BASE_T *pBase,
+ RA_LENGTH_T *pActualSize,
+ RA_PERISPAN_HANDLE *phPriv),
+ IMG_VOID (*imp_free) (RA_PERARENA_HANDLE,
+ RA_BASE_T,
+ RA_PERISPAN_HANDLE),
+ RA_PERARENA_HANDLE arena_handle)
+{
+ RA_ARENA *pArena;
+ PVRSRV_ERROR eError;
+
+ if (name == NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "RA_Create: invalid parameter 'name' (NULL not accepted)"));
+ return NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "RA_Create: name='%s'", name));
+
+ pArena = OSAllocMem(sizeof (*pArena));
+ if (pArena == IMG_NULL)
+ {
+ goto arena_fail;
+ }
+
+ eError = OSLockCreate(&pArena->hLock, LOCK_TYPE_PASSIVE);
+ if (eError != PVRSRV_OK)
+ {
+ goto lock_fail;
+ }
+
+ pArena->pSegmentHash = HASH_Create_Extended(MINIMUM_HASH_SIZE, sizeof(RA_BASE_T), HASH_Func_Default, HASH_Key_Comp_Default);
+
+ if (pArena->pSegmentHash==IMG_NULL)
+ {
+ goto hash_fail;
+ }
+
+ pArena->name = name;
+ pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : &_RequestAllocFail;
+ pArena->pImportFree = imp_free;
+ pArena->pImportHandle = arena_handle;
+ pArena->pHeadSegment = IMG_NULL;
+ pArena->uQuantum = (IMG_UINT64) (1 << uLog2Quantum);
+ pArena->per_flags_buckets = NULL;
+ pArena->ui32LockClass = ui32LockClass;
+
+ PVR_ASSERT(is_arena_valid(pArena));
+ return pArena;
+
+hash_fail:
+ OSLockDestroy(pArena->hLock);
+lock_fail:
+ OSFreeMem(pArena);
+ /*not nulling pointer, out of scope*/
+arena_fail:
+ return IMG_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 IMG_VOID
+RA_Delete (RA_ARENA *pArena)
+{
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT(pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena"));
+ return;
+ }
+
+ PVR_ASSERT(is_arena_valid(pArena));
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Delete: name='%s'", pArena->name));
+
+ while (pArena->pHeadSegment != IMG_NULL)
+ {
+ BT *pBT = pArena->pHeadSegment;
+
+ if (pBT->type != btt_free)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "RA_Delete: allocations still exist in the arena that is being destroyed"));
+ PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+ PVR_DPF ((PVR_DBG_ERROR, "RA_Delete: base = " RA_BASE_FMTSPEC " "
+ "size=" RA_LENGTH_FMTSPEC, pBT->base, pBT->uSize));
+ }
+ else
+ {
+ _FreeListRemove(pArena, pBT);
+ }
+
+ _SegmentListRemove (pArena, pBT);
+ OSFreeMem(pBT);
+ /*not nulling original pointer, it has changed*/
+ }
+
+ while (pArena->per_flags_buckets != NULL)
+ {
+ for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++)
+ {
+ PVR_ASSERT(pArena->per_flags_buckets->buckets[uIndex] == IMG_NULL);
+ }
+
+ pArena->per_flags_buckets = PVRSRVDelete(pArena->per_flags_buckets->ui32Flags, pArena->per_flags_buckets);
+ }
+
+ HASH_Delete (pArena->pSegmentHash);
+ OSLockDestroy(pArena->hLock);
+ OSFreeMem(pArena);
+ /*not nulling pointer, copy on stack*/
+}
+
+/*************************************************************************/ /*!
+@Function RA_Add
+@Description To add a resource span to an arena. The span must not
+ overlapp 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)
+{
+ struct _BT_* bt;
+ PVR_ASSERT (pArena != IMG_NULL);
+ PVR_ASSERT (uSize != 0);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+ OSLockAcquireNested(pArena->hLock, pArena->ui32LockClass);
+ PVR_ASSERT(is_arena_valid(pArena));
+ PVR_DPF ((PVR_DBG_MESSAGE, "RA_Add: name='%s', "
+ "base=" RA_BASE_FMTSPEC ", size=" RA_LENGTH_FMTSPEC,
+ pArena->name, base, uSize));
+
+ uSize = (uSize + pArena->uQuantum - 1) & ~(pArena->uQuantum - 1);
+ bt = _InsertResource(pArena, base, uSize, uFlags);
+ if (bt != NULL)
+ {
+ bt->hPriv = hPriv;
+ }
+
+ PVR_ASSERT(is_arena_valid(pArena));
+ 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.
+@Output pActualSize The actual size of resource segment
+ allocated, typcially rounded up by quantum.
+@Output phPriv The user reference associated with allocated resource span.
+@Input uFlags 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.
+@Output base Allocated base resource
+@Return IMG_TRUE - success
+ IMG_FALSE - failure
+*/ /**************************************************************************/
+IMG_INTERNAL IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+ RA_LENGTH_T uRequestSize,
+ RA_FLAGS_T uFlags,
+ RA_LENGTH_T uAlignment,
+ RA_BASE_T *base,
+ RA_LENGTH_T *pActualSize,
+ RA_PERISPAN_HANDLE *phPriv)
+{
+ IMG_BOOL bResult;
+ RA_LENGTH_T uSize = uRequestSize;
+
+ PVR_ASSERT (pArena!=IMG_NULL);
+ PVR_ASSERT (uSize > 0);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+ OSLockAcquireNested(pArena->hLock, pArena->ui32LockClass);
+ PVR_ASSERT(is_arena_valid(pArena));
+
+ if (pActualSize != IMG_NULL)
+ {
+ *pActualSize = uSize;
+ }
+
+ /* Must be a power of 2 or 0 */
+ PVR_ASSERT((uAlignment == 0) || (uAlignment & (uAlignment - 1)) == 0);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: arena='%s', size=" RA_LENGTH_FMTSPEC "(" RA_LENGTH_FMTSPEC "), "
+ "alignment=" RA_ALIGN_FMTSPEC, pArena->name, uSize, uRequestSize, uAlignment));
+
+ /* if allocation failed then we might have an import source which
+ can provide more resource, else we will have to fail the
+ allocation to the caller. */
+ 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)
+ {
+ uImportSize += (uAlignment - pArena->uQuantum);
+ }
+
+ /* ensure that we import according to the quanta of this arena */
+ uImportSize = (uImportSize + pArena->uQuantum - 1) & ~(pArena->uQuantum - 1);
+
+ bResult =
+ pArena->pImportAlloc (pArena->pImportHandle, uImportSize, uFlags,
+ &import_base, &uImportSize, &hPriv);
+ if (bResult)
+ {
+ 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 == IMG_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, "RA_Alloc: name='%s', "
+ "size=" RA_LENGTH_FMTSPEC " failed!", pArena->name, uSize));
+ /* RA_Dump (arena); */
+ OSLockRelease(pArena->hLock);
+ return IMG_FALSE;
+ }
+
+
+ pBT->hPriv = hPriv;
+
+ bResult = _AttemptAllocAligned(pArena, uSize, uFlags, uAlignment, base, phPriv);
+ if (!bResult)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,
+ "RA_Alloc: name='%s' second alloc failed!",
+ 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.
+ */
+ _FreeBT(pArena, pBT);
+ }
+ 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,
+ "RA_Alloc: name='%s' alloc did not occur in the imported span!",
+ 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);
+ }
+ }
+ }
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "RA_Alloc: name='%s', size=" RA_LENGTH_FMTSPEC ", "
+ "*base=" RA_BASE_FMTSPEC " = %d",pArena->name, uSize, *base, bResult));
+
+ PVR_ASSERT(is_arena_valid(pArena));
+
+ OSLockRelease(pArena->hLock);
+ return bResult;
+}
+
+
+
+
+/*************************************************************************/ /*!
+@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 IMG_VOID
+RA_Free (RA_ARENA *pArena, RA_BASE_T base)
+{
+ BT *pBT;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena"));
+ return;
+ }
+
+ OSLockAcquireNested(pArena->hLock, pArena->ui32LockClass);
+ PVR_ASSERT(is_arena_valid(pArena));
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "RA_Free: name='%s', base=" RA_BASE_FMTSPEC, pArena->name, base));
+
+ pBT = (BT *) HASH_Remove_Extended (pArena->pSegmentHash, &base);
+ PVR_ASSERT (pBT != IMG_NULL);
+
+ if (pBT)
+ {
+ PVR_ASSERT (pBT->base == base);
+ _FreeBT (pArena, pBT);
+ }
+
+ PVR_ASSERT(is_arena_valid(pArena));
+ OSLockRelease(pArena->hLock);
+}
diff --git a/drivers/gpu/rogue/services/shared/common/sync.c b/drivers/gpu/rogue/services/shared/common/sync.c
new file mode 100644
index 000000000000..0f41e881acc6
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/sync.c
@@ -0,0 +1,1762 @@
+/*************************************************************************/ /*!
+@File
+@Title Services synchronisation interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements client side code for services synchronisation
+ interface
+@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 "client_sync_bridge.h"
+#include "allocmem.h"
+#include "osfunc.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "pvr_debug.h"
+#include "dllist.h"
+#include "sync.h"
+#include "sync_internal.h"
+#include "lock.h"
+#include "pvr_debug.h"
+
+#if defined(__KERNEL__)
+#include "pvrsrv.h"
+#endif
+
+
+#define SYNC_BLOCK_LIST_CHUNCK_SIZE 10
+
+/*
+ This defines the maximum amount of synchronisation memory
+ that can be allocated per SyncPrim context.
+ In reality this number is meaningless as we would run out
+ of synchronisation memory before we reach this limit, but
+ we need to provide a size to the span RA.
+*/
+#define MAX_SYNC_MEM (4 * 1024 * 1024)
+
+typedef struct _SYNC_BLOCK_LIST_
+{
+ IMG_UINT32 ui32BlockCount; /*!< Number of contexts in the list */
+ IMG_UINT32 ui32BlockListSize; /*!< Size of the array contexts */
+ SYNC_PRIM_BLOCK **papsSyncPrimBlock; /*!< Array of syncprim blocks */
+} SYNC_BLOCK_LIST;
+
+typedef struct _SYNC_OP_COOKIE_
+{
+ IMG_UINT32 ui32SyncCount;
+ IMG_UINT32 ui32ClientSyncCount;
+ IMG_UINT32 ui32ServerSyncCount;
+ IMG_BOOL bHaveServerSync;
+ IMG_HANDLE hBridge;
+ IMG_HANDLE hServerCookie;
+
+ SYNC_BLOCK_LIST *psSyncBlockList;
+ PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim;
+ /*
+ Client sync(s) info.
+ If this changes update the calculation of ui32ClientAllocSize
+ */
+ IMG_UINT32 *paui32SyncBlockIndex;
+ IMG_UINT32 *paui32Index;
+ IMG_UINT32 *paui32Flags;
+ IMG_UINT32 *paui32FenceValue;
+ IMG_UINT32 *paui32UpdateValue;
+
+ /*
+ Server sync(s) info
+ If this changes update the calculation of ui32ServerAllocSize
+ */
+ IMG_HANDLE *pahServerSync;
+ IMG_UINT32 *paui32ServerFlags;
+} SYNC_OP_COOKIE;
+
+/*
+ Internal interfaces for management of synchronisation block memory
+*/
+static PVRSRV_ERROR
+AllocSyncPrimitiveBlock(SYNC_PRIM_CONTEXT *psContext,
+ SYNC_PRIM_BLOCK **ppsSyncBlock)
+{
+ SYNC_PRIM_BLOCK *psSyncBlk;
+ DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie;
+ DEVMEM_EXPORTCOOKIE sExportCookie;
+ PVRSRV_ERROR eError;
+
+ psSyncBlk = OSAllocMem(sizeof(SYNC_PRIM_BLOCK));
+ if (psSyncBlk == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+ psSyncBlk->psContext = psContext;
+
+ /* Allocate sync prim block */
+ eError = BridgeAllocSyncPrimitiveBlock(psContext->hBridge,
+ psContext->hDeviceNode,
+ &psSyncBlk->hServerSyncPrimBlock,
+ &psSyncBlk->ui32FirmwareAddr,
+ &psSyncBlk->ui32SyncBlockSize,
+ &hServerExportCookie);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_blockalloc;
+ }
+
+ /* Make it mappable by the client */
+ eError = DevmemMakeServerExportClientExport(psContext->hBridge,
+ hServerExportCookie,
+ &sExportCookie);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_export;
+ }
+
+ /* Get CPU mapping of the memory block */
+ eError = DevmemImport(psContext->hBridge,
+ &sExportCookie,
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE,
+ &psSyncBlk->hMemDesc);
+
+ /*
+ Regardless of success or failure we "undo" the export
+ */
+ DevmemUnmakeServerExportClientExport(psContext->hBridge,
+ &sExportCookie);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_import;
+ }
+
+ eError = DevmemAcquireCpuVirtAddr(psSyncBlk->hMemDesc,
+ (IMG_PVOID *) &psSyncBlk->pui32LinAddr);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_cpuvaddr;
+ }
+
+ *ppsSyncBlock = psSyncBlk;
+ return PVRSRV_OK;
+
+fail_cpuvaddr:
+ DevmemFree(psSyncBlk->hMemDesc);
+fail_import:
+fail_export:
+ BridgeFreeSyncPrimitiveBlock(psContext->hBridge,
+ psSyncBlk->hServerSyncPrimBlock);
+fail_blockalloc:
+ OSFreeMem(psSyncBlk);
+fail_alloc:
+ return eError;
+}
+
+static IMG_VOID
+FreeSyncPrimitiveBlock(SYNC_PRIM_BLOCK *psSyncBlk)
+{
+ SYNC_PRIM_CONTEXT *psContext = psSyncBlk->psContext;
+
+ DevmemReleaseCpuVirtAddr(psSyncBlk->hMemDesc);
+ DevmemFree(psSyncBlk->hMemDesc);
+ BridgeFreeSyncPrimitiveBlock(psContext->hBridge,
+ psSyncBlk->hServerSyncPrimBlock);
+ OSFreeMem(psSyncBlk);
+}
+
+static IMG_BOOL
+SyncPrimBlockImport(RA_PERARENA_HANDLE hArena,
+ RA_LENGTH_T uSize,
+ RA_FLAGS_T uFlags,
+ RA_BASE_T *puiBase,
+ RA_LENGTH_T *puiActualSize,
+ RA_PERISPAN_HANDLE *phImport)
+{
+ SYNC_PRIM_CONTEXT *psContext = hArena;
+ SYNC_PRIM_BLOCK *psSyncBlock = IMG_NULL;
+ RA_LENGTH_T uiSpanSize;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bRet;
+ PVR_UNREFERENCED_PARAMETER(uFlags);
+
+ PVR_ASSERT(hArena != IMG_NULL);
+
+ /* Check we've not be called with an unexpected size */
+ PVR_ASSERT(uSize == sizeof(IMG_UINT32));
+
+ /*
+ Ensure the synprim context doesn't go away while we have sync blocks
+ attached to it
+ */
+ OSLockAcquire(psContext->hLock);
+ psContext->ui32RefCount++;
+ OSLockRelease(psContext->hLock);
+
+ /* Allocate the block of memory */
+ eError = AllocSyncPrimitiveBlock(psContext, &psSyncBlock);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Failed to allocation syncprim block (%d)", eError));
+ goto fail_syncblockalloc;
+ }
+
+ /* Allocate a span for it */
+ bRet = RA_Alloc(psContext->psSpanRA,
+ psSyncBlock->ui32SyncBlockSize,
+ 0,
+ psSyncBlock->ui32SyncBlockSize,
+ &psSyncBlock->uiSpanBase,
+ &uiSpanSize,
+ IMG_NULL);
+ if (bRet == IMG_FALSE)
+ {
+ goto fail_spanalloc;
+ }
+
+ /*
+ There is no reason the span RA should return an allocation larger
+ then we request
+ */
+ PVR_ASSERT(uiSpanSize == psSyncBlock->ui32SyncBlockSize);
+
+ *puiBase = psSyncBlock->uiSpanBase;
+ *puiActualSize = psSyncBlock->ui32SyncBlockSize;
+ *phImport = psSyncBlock;
+ return IMG_TRUE;
+
+fail_spanalloc:
+ FreeSyncPrimitiveBlock(psSyncBlock);
+fail_syncblockalloc:
+ OSLockAcquire(psContext->hLock);
+ psContext->ui32RefCount--;
+ OSLockRelease(psContext->hLock);
+
+ return IMG_FALSE;
+}
+
+static IMG_VOID
+SyncPrimBlockUnimport(RA_PERARENA_HANDLE hArena,
+ RA_BASE_T uiBase,
+ RA_PERISPAN_HANDLE hImport)
+{
+ SYNC_PRIM_CONTEXT *psContext = hArena;
+ SYNC_PRIM_BLOCK *psSyncBlock = hImport;
+
+ PVR_ASSERT(psContext != IMG_NULL);
+ PVR_ASSERT(psSyncBlock != IMG_NULL);
+
+ PVR_ASSERT(uiBase == psSyncBlock->uiSpanBase);
+
+ /* Free the span this import is using */
+ RA_Free(psContext->psSpanRA, uiBase);
+
+ /* Free the syncpim block */
+ FreeSyncPrimitiveBlock(psSyncBlock);
+
+ /* Drop our reference to the syncprim context */
+ OSLockAcquire(psContext->hLock);
+ psContext->ui32RefCount--;
+ OSLockRelease(psContext->hLock);
+}
+
+static INLINE IMG_UINT32 SyncPrimGetOffset(SYNC_PRIM *psSyncInt)
+{
+ IMG_UINT64 ui64Temp;
+
+ PVR_ASSERT(psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL);
+
+
+ ui64Temp = psSyncInt->u.sLocal.uiSpanAddr - psSyncInt->u.sLocal.psSyncBlock->uiSpanBase;
+ PVR_ASSERT(ui64Temp<IMG_UINT32_MAX);
+ return (IMG_UINT32)ui64Temp;
+}
+
+static IMG_VOID SyncPrimGetCPULinAddr(SYNC_PRIM *psSyncInt)
+{
+ SYNC_PRIM_BLOCK *psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
+
+ psSyncInt->sCommon.pui32LinAddr = psSyncBlock->pui32LinAddr +
+ (SyncPrimGetOffset(psSyncInt)/sizeof(IMG_UINT32));
+}
+
+static IMG_VOID SyncPrimLocalFree(SYNC_PRIM *psSyncInt)
+{
+ SYNC_PRIM_BLOCK *psSyncBlock;
+ SYNC_PRIM_CONTEXT *psContext;
+
+ PVR_ASSERT(psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL);
+ psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
+ psContext = psSyncBlock->psContext;
+
+ RA_Free(psContext->psSubAllocRA, psSyncInt->u.sLocal.uiSpanAddr);
+}
+
+static IMG_VOID SyncPrimServerFree(SYNC_PRIM *psSyncInt)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgeServerSyncFree(psSyncInt->u.sServer.hBridge,
+ psSyncInt->u.sServer.hServerSync);
+ if (eError != PVRSRV_OK)
+ {
+ /* Doesn't matter if the free fails as resman will cleanup */
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimServerFree failed"));
+ }
+}
+
+static IMG_UINT32 SyncPrimGetFirmwareAddrLocal(SYNC_PRIM *psSyncInt)
+{
+ SYNC_PRIM_BLOCK *psSyncBlock;
+
+ psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
+ return psSyncBlock->ui32FirmwareAddr + SyncPrimGetOffset(psSyncInt);
+}
+
+static IMG_UINT32 SyncPrimGetFirmwareAddrServer(SYNC_PRIM *psSyncInt)
+{
+ return psSyncInt->u.sServer.ui32FirmwareAddr;
+}
+
+#if !defined(__KERNEL__)
+static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandleLocal(SYNC_PRIM *psSyncInt)
+{
+ return psSyncInt->u.sLocal.psSyncBlock->psContext->hBridge;
+}
+
+static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandleServer(SYNC_PRIM *psSyncInt)
+{
+ return psSyncInt->u.sServer.hBridge;
+}
+
+static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+{
+ SYNC_PRIM *psSyncInt;
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+
+ if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
+ {
+ return _SyncPrimGetBridgeHandleLocal(psSyncInt);
+ }
+ else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
+ {
+ return _SyncPrimGetBridgeHandleServer(psSyncInt);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_SyncPrimGetBridgeHandle: Invalid sync type"));
+ /*
+ Either the client has given us a bad pointer or there is an
+ error in this module
+ */
+ PVR_ASSERT(IMG_FALSE);
+ return 0;
+ }
+}
+#endif
+
+/*
+ Internal interfaces for management of syncprim block lists
+*/
+static SYNC_BLOCK_LIST *_SyncPrimBlockListCreate(IMG_VOID)
+{
+ SYNC_BLOCK_LIST *psBlockList;
+
+ psBlockList = OSAllocMem(sizeof(SYNC_BLOCK_LIST) +
+ (sizeof(SYNC_PRIM_BLOCK *)
+ * SYNC_BLOCK_LIST_CHUNCK_SIZE));
+ if (!psBlockList)
+ {
+ return IMG_NULL;
+ }
+
+ psBlockList->ui32BlockCount = 0;
+ psBlockList->ui32BlockListSize = SYNC_BLOCK_LIST_CHUNCK_SIZE;
+
+ psBlockList->papsSyncPrimBlock = OSAllocMem(sizeof(SYNC_PRIM_BLOCK *)
+ * SYNC_BLOCK_LIST_CHUNCK_SIZE);
+ if (!psBlockList->papsSyncPrimBlock)
+ {
+ OSFreeMem(psBlockList);
+ return IMG_NULL;
+ }
+
+ OSMemSet(psBlockList->papsSyncPrimBlock,
+ 0,
+ sizeof(SYNC_PRIM_BLOCK *) * psBlockList->ui32BlockListSize);
+
+ return psBlockList;
+}
+
+static PVRSRV_ERROR _SyncPrimBlockListAdd(SYNC_BLOCK_LIST *psBlockList,
+ SYNC_PRIM_BLOCK *psSyncPrimBlock)
+{
+ IMG_UINT32 i;
+
+ /* Check the context isn't already on the list */
+ for (i=0;i<psBlockList->ui32BlockCount;i++)
+ {
+ if (psBlockList->papsSyncPrimBlock[i] == psSyncPrimBlock)
+ {
+ return PVRSRV_OK;
+ }
+ }
+
+ /* Check we have space for a new item */
+ if (psBlockList->ui32BlockCount == psBlockList->ui32BlockListSize)
+ {
+ SYNC_PRIM_BLOCK **papsNewSyncPrimBlock;
+
+ papsNewSyncPrimBlock = OSAllocMem(sizeof(SYNC_PRIM_BLOCK *) *
+ (psBlockList->ui32BlockCount +
+ SYNC_BLOCK_LIST_CHUNCK_SIZE));
+ if (!papsNewSyncPrimBlock)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psBlockList->papsSyncPrimBlock,
+ 0,
+ sizeof(SYNC_PRIM_BLOCK *) * psBlockList->ui32BlockListSize);
+ OSMemCopy(papsNewSyncPrimBlock,
+ psBlockList->papsSyncPrimBlock,
+ sizeof(SYNC_PRIM_CONTEXT *) *
+ psBlockList->ui32BlockCount);
+
+ OSFreeMem(psBlockList->papsSyncPrimBlock);
+
+ psBlockList->papsSyncPrimBlock = papsNewSyncPrimBlock;
+ psBlockList->ui32BlockListSize += SYNC_BLOCK_LIST_CHUNCK_SIZE;
+ }
+
+ /* Add the context to the list */
+ psBlockList->papsSyncPrimBlock[psBlockList->ui32BlockCount++] = psSyncPrimBlock;
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _SyncPrimBlockListBlockToIndex(SYNC_BLOCK_LIST *psBlockList,
+ SYNC_PRIM_BLOCK *psSyncPrimBlock,
+ IMG_UINT32 *pui32Index)
+{
+ IMG_UINT32 i;
+
+ for (i=0;i<psBlockList->ui32BlockCount;i++)
+ {
+ if (psBlockList->papsSyncPrimBlock[i] == psSyncPrimBlock)
+ {
+ *pui32Index = i;
+ return PVRSRV_OK;
+ }
+ }
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+static PVRSRV_ERROR _SyncPrimBlockListHandleArrayCreate(SYNC_BLOCK_LIST *psBlockList,
+ IMG_UINT32 *pui32BlockHandleCount,
+ IMG_HANDLE **ppahHandleList)
+{
+ IMG_HANDLE *pahHandleList;
+ IMG_UINT32 i;
+
+ pahHandleList = OSAllocMem(sizeof(IMG_HANDLE) *
+ psBlockList->ui32BlockCount);
+ if (!pahHandleList)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ for (i=0;i<psBlockList->ui32BlockCount;i++)
+ {
+ pahHandleList[i] = psBlockList->papsSyncPrimBlock[i]->hServerSyncPrimBlock;
+ }
+
+ *ppahHandleList = pahHandleList;
+ *pui32BlockHandleCount = psBlockList->ui32BlockCount;
+
+ return PVRSRV_OK;
+}
+
+static IMG_VOID _SyncPrimBlockListHandleArrayDestroy(IMG_HANDLE *pahHandleList)
+{
+ OSFreeMem(pahHandleList);
+}
+
+static IMG_UINT32 _SyncPrimBlockListGetClientValue(SYNC_BLOCK_LIST *psBlockList,
+ IMG_UINT32 ui32BlockIndex,
+ IMG_UINT32 ui32Index)
+{
+ return psBlockList->papsSyncPrimBlock[ui32BlockIndex]->pui32LinAddr[ui32Index];
+}
+
+static IMG_VOID _SyncPrimBlockListDestroy(SYNC_BLOCK_LIST *psBlockList)
+{
+ OSFreeMem(psBlockList->papsSyncPrimBlock);
+ OSFreeMem(psBlockList);
+}
+
+static INLINE IMG_UINT32 _Log2(IMG_UINT32 ui32Align)
+{
+ IMG_UINT32 ui32Log2Align = 0;
+ while (!(ui32Align & 1))
+ {
+ ui32Log2Align++;
+ ui32Align = ui32Align >> 1;
+ }
+ PVR_ASSERT(ui32Align == 1);
+
+ return ui32Log2Align;
+}
+
+/*
+ External interfaces
+*/
+
+IMG_INTERNAL PVRSRV_ERROR
+SyncPrimContextCreate(SYNC_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ PSYNC_PRIM_CONTEXT *phSyncPrimContext)
+{
+ SYNC_PRIM_CONTEXT *psContext;
+ PVRSRV_ERROR eError;
+
+ psContext = OSAllocMem(sizeof(SYNC_PRIM_CONTEXT));
+ if (psContext == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ psContext->hBridge = hBridge;
+ psContext->hDeviceNode = hDeviceNode;
+
+ eError = OSLockCreate(&psContext->hLock, LOCK_TYPE_PASSIVE);
+ if ( eError != PVRSRV_OK)
+ {
+ goto fail_lockcreate;
+ }
+
+ OSSNPrintf(psContext->azName, SYNC_PRIM_NAME_SIZE, "Sync Prim RA-%p", psContext);
+ OSSNPrintf(psContext->azSpanName, SYNC_PRIM_NAME_SIZE, "Sync Prim span RA-%p", psContext);
+
+ /*
+ Create the RA for sub-allocations of the SynPrim's
+
+ Note:
+ The import size doesn't matter here as the server will pass
+ back the blocksize when does the import which overrides
+ what we specify here.
+ */
+
+ psContext->psSubAllocRA = RA_Create(psContext->azName,
+ /* Params for imports */
+ _Log2(sizeof(IMG_UINT32)),
+ RA_LOCKCLASS_2,
+ SyncPrimBlockImport,
+ SyncPrimBlockUnimport,
+ psContext);
+ if (psContext->psSubAllocRA == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_suballoc;
+ }
+
+ /*
+ Create the span-management RA
+
+ The RA requires that we work with linear spans. For our use
+ here we don't require this behaviour as we're always working
+ within offsets of blocks (imports). However, we need to keep
+ the RA happy so we create the "span" management RA which
+ ensures that all are imports are added to the RA in a linear
+ fashion
+ */
+ psContext->psSpanRA = RA_Create(psContext->azSpanName,
+ /* Params for imports */
+ 0,
+ RA_LOCKCLASS_1,
+ IMG_NULL,
+ IMG_NULL,
+ IMG_NULL);
+ if (psContext->psSpanRA == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_span;
+ }
+
+ if (!RA_Add(psContext->psSpanRA, 0, MAX_SYNC_MEM, 0, IMG_NULL))
+ {
+ RA_Delete(psContext->psSpanRA);
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_span;
+ }
+
+ psContext->ui32RefCount = 1;
+
+ *phSyncPrimContext = psContext;
+ return PVRSRV_OK;
+fail_span:
+ RA_Delete(psContext->psSubAllocRA);
+fail_suballoc:
+ OSLockDestroy(psContext->hLock);
+fail_lockcreate:
+ OSFreeMem(psContext);
+fail_alloc:
+ return eError;
+}
+
+IMG_INTERNAL IMG_VOID SyncPrimContextDestroy(PSYNC_PRIM_CONTEXT hSyncPrimContext)
+{
+ SYNC_PRIM_CONTEXT *psContext = hSyncPrimContext;
+ IMG_BOOL bDoRefCheck = IMG_TRUE;
+
+
+#if defined(__KERNEL__)
+ PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+ if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
+ {
+ bDoRefCheck = IMG_FALSE;
+ }
+#endif
+ OSLockAcquire(psContext->hLock);
+ if (--psContext->ui32RefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimContextDestroy: Refcount non-zero: %d", psContext->ui32RefCount));
+
+ if (bDoRefCheck)
+ {
+ PVR_ASSERT(0);
+ }
+ return;
+ }
+ /*
+ If we fail above then we won't release the lock. However, if that
+ happens things have already gone very wrong and we bail to save
+ freeing memory which might still be in use and holding this lock
+ will show up if anyone is trying to use this context after it has
+ been destroyed.
+ */
+ OSLockRelease(psContext->hLock);
+
+ RA_Delete(psContext->psSpanRA);
+ RA_Delete(psContext->psSubAllocRA);
+ OSLockDestroy(psContext->hLock);
+ OSFreeMem(psContext);
+}
+
+IMG_INTERNAL PVRSRV_ERROR SyncPrimAlloc(PSYNC_PRIM_CONTEXT hSyncPrimContext,
+ PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
+ const IMG_CHAR *pszClassName)
+{
+ SYNC_PRIM_CONTEXT *psContext = hSyncPrimContext;
+ SYNC_PRIM_BLOCK *psSyncBlock;
+ SYNC_PRIM *psNewSync;
+ PVRSRV_ERROR eError;
+ RA_BASE_T uiSpanAddr;
+
+ psNewSync = OSAllocMem(sizeof(SYNC_PRIM));
+ if (psNewSync == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_alloc;
+ }
+
+ if (!RA_Alloc(psContext->psSubAllocRA,
+ sizeof(IMG_UINT32),
+ 0,
+ sizeof(IMG_UINT32),
+ &uiSpanAddr,
+ IMG_NULL,
+ (RA_PERISPAN_HANDLE *) &psSyncBlock))
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto fail_raalloc;
+ }
+ psNewSync->eType = SYNC_PRIM_TYPE_LOCAL;
+ psNewSync->u.sLocal.uiSpanAddr = uiSpanAddr;
+ psNewSync->u.sLocal.psSyncBlock = psSyncBlock;
+ SyncPrimGetCPULinAddr(psNewSync);
+ *ppsSync = &psNewSync->sCommon;
+
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+ {
+ IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN];
+ if(pszClassName)
+ {
+ /* Copy the class name annotation into a fixed-size array */
+ OSStringNCopy(szClassName, pszClassName, SYNC_MAX_CLASS_NAME_LEN - 1);
+ szClassName[SYNC_MAX_CLASS_NAME_LEN - 1] = 0;
+ }
+ else
+ {
+ /* No class name annotation */
+ szClassName[0] = 0;
+ }
+ /* record this sync */
+ eError = BridgeSyncRecordAdd(
+ psSyncBlock->psContext->hBridge,
+ &psNewSync->u.sLocal.hRecord,
+ psSyncBlock->hServerSyncPrimBlock,
+ psSyncBlock->ui32FirmwareAddr,
+ SyncPrimGetOffset(psNewSync),
+#if defined(__KERNEL__)
+ IMG_TRUE,
+#else
+ IMG_FALSE,
+#endif
+ OSStringNLength(szClassName, SYNC_MAX_CLASS_NAME_LEN),
+ szClassName);
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszClassName);
+#endif /* if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
+
+ return PVRSRV_OK;
+
+fail_raalloc:
+ OSFreeMem(psNewSync);
+fail_alloc:
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+IMG_INTERNAL IMG_VOID SyncPrimFree(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+{
+ SYNC_PRIM *psSyncInt;
+
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+
+ if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
+ {
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+ PVRSRV_ERROR eError;
+ /* remove this sync record */
+ eError = BridgeSyncRecordRemoveByHandle(
+ psSyncInt->u.sLocal.psSyncBlock->psContext->hBridge,
+ psSyncInt->u.sLocal.hRecord);
+ PVR_ASSERT(PVRSRV_OK == eError);
+#endif
+ SyncPrimLocalFree(psSyncInt);
+ }
+ else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
+ {
+ SyncPrimServerFree(psSyncInt);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimFree: Invalid sync type"));
+ /*
+ Either the client has given us a bad pointer or there is an
+ error in this module
+ */
+ PVR_ASSERT(IMG_FALSE);
+ return;
+ }
+
+ OSFreeMem(psSyncInt);
+}
+
+static IMG_VOID
+_SyncPrimSetValue(SYNC_PRIM *psSyncInt, IMG_UINT32 ui32Value)
+{
+ PVRSRV_ERROR eError;
+
+ if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
+ {
+ SYNC_PRIM_BLOCK *psSyncBlock;
+ SYNC_PRIM_CONTEXT *psContext;
+
+ psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
+ psContext = psSyncBlock->psContext;
+
+ eError = BridgeSyncPrimSet(psContext->hBridge,
+ psSyncBlock->hServerSyncPrimBlock,
+ SyncPrimGetOffset(psSyncInt)/sizeof(IMG_UINT32),
+ ui32Value);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+ else
+ {
+ eError = BridgeServerSyncPrimSet(psSyncInt->u.sServer.hBridge,
+ psSyncInt->u.sServer.hServerSync,
+ ui32Value);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ }
+}
+
+#if defined(NO_HARDWARE)
+IMG_INTERNAL IMG_VOID
+SyncPrimNoHwUpdate(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
+{
+ SYNC_PRIM *psSyncInt;
+
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+
+ /* There is no check for the psSyncInt to be LOCAL as this call
+ substitutes the Firmware updating a sync and that sync could
+ be a server one */
+
+ _SyncPrimSetValue(psSyncInt, ui32Value);
+}
+#endif
+
+IMG_INTERNAL IMG_VOID
+SyncPrimSet(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
+{
+ SYNC_PRIM *psSyncInt;
+
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+
+ if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimSet: Invalid sync type"));
+ /*PVR_ASSERT(IMG_FALSE);*/
+ return;
+ }
+
+ _SyncPrimSetValue(psSyncInt, ui32Value);
+
+#if defined(PDUMP)
+ SyncPrimPDump(psSync);
+#endif
+
+}
+
+IMG_INTERNAL IMG_UINT32 SyncPrimGetFirmwareAddr(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+{
+ SYNC_PRIM *psSyncInt;
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+
+ if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
+ {
+ return SyncPrimGetFirmwareAddrLocal(psSyncInt);
+ }
+ else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
+ {
+ return SyncPrimGetFirmwareAddrServer(psSyncInt);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimGetFirmwareAddr: Invalid sync type"));
+ /*
+ Either the client has given us a bad pointer or there is an
+ error in this module
+ */
+ PVR_ASSERT(IMG_FALSE);
+ return 0;
+ }
+}
+
+#if !defined(__KERNEL__)
+IMG_INTERNAL PVRSRV_ERROR SyncPrimDumpSyncs(IMG_UINT32 ui32SyncCount, PVRSRV_CLIENT_SYNC_PRIM **papsSync, const IMG_CHAR *pcszExtraInfo)
+{
+#if defined(PVRSRV_NEED_PVR_DPF)
+ SYNC_PRIM *psSyncInt;
+ PVRSRV_CLIENT_SYNC_PRIM **papsServerSync;
+ IMG_UINT32 ui32ServerSyncs = 0;
+ IMG_UINT32 *pui32UID = IMG_NULL;
+ IMG_UINT32 *pui32FWAddr = IMG_NULL;
+ IMG_UINT32 *pui32CurrentOp = IMG_NULL;
+ IMG_UINT32 *pui32NextOp = IMG_NULL;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ papsServerSync = OSAllocMem(ui32SyncCount * sizeof(PVRSRV_CLIENT_SYNC_PRIM *));
+ if (!papsServerSync)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ for (i = 0; i < ui32SyncCount; i++)
+ {
+ psSyncInt = IMG_CONTAINER_OF(papsSync[i], SYNC_PRIM, sCommon);
+ if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: sync=local fw=0x%x curr=0x%04x",
+ pcszExtraInfo,
+ SyncPrimGetFirmwareAddrLocal(psSyncInt),
+ *psSyncInt->sCommon.pui32LinAddr));
+ }
+ else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
+ {
+ papsServerSync[ui32ServerSyncs++] = papsSync[i];
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimDumpSyncs: Invalid sync type"));
+ /*
+ Either the client has given us a bad pointer or there is an
+ error in this module
+ */
+ PVR_ASSERT(IMG_FALSE);
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto err_free;
+ }
+ }
+
+ if (ui32ServerSyncs > 0)
+ {
+ pui32UID = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
+ if (!pui32UID)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free;
+ }
+ pui32FWAddr = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
+ if (!pui32FWAddr)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free;
+ }
+ pui32CurrentOp = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
+ if (!pui32CurrentOp)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free;
+ }
+ pui32NextOp = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
+ if (!pui32NextOp)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_free;
+ }
+ eError = SyncPrimServerGetStatus(ui32ServerSyncs, papsServerSync,
+ pui32UID,
+ pui32FWAddr,
+ pui32CurrentOp,
+ pui32NextOp);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimDumpSyncs: Error querying server sync status (%d)",
+ eError));
+ goto err_free;
+ }
+ for (i = 0; i < ui32ServerSyncs; i++)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: sync=server fw=0x%x curr=0x%04x next=0x%04x id=%u%s",
+ pcszExtraInfo,
+ pui32FWAddr[i],
+ pui32CurrentOp[i],
+ pui32NextOp[i],
+ pui32UID[i],
+ (pui32NextOp[i] - pui32CurrentOp[i] == 1) ? " *" :
+ (pui32NextOp[i] - pui32CurrentOp[i] > 1) ? " **" :
+ ""));
+ }
+ }
+
+err_free:
+ OSFreeMem(papsServerSync);
+ if (pui32UID)
+ {
+ OSFreeMem(pui32UID);
+ }
+ if (pui32FWAddr)
+ {
+ OSFreeMem(pui32FWAddr);
+ }
+ if (pui32CurrentOp)
+ {
+ OSFreeMem(pui32CurrentOp);
+ }
+ if (pui32NextOp)
+ {
+ OSFreeMem(pui32NextOp);
+ }
+ return eError;
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32SyncCount);
+ PVR_UNREFERENCED_PARAMETER(papsSync);
+ PVR_UNREFERENCED_PARAMETER(pcszExtraInfo);
+ return PVRSRV_OK;
+#endif
+}
+#endif
+
+IMG_INTERNAL
+PVRSRV_ERROR SyncPrimOpCreate(IMG_UINT32 ui32SyncCount,
+ PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim,
+ PSYNC_OP_COOKIE *ppsCookie)
+{
+ SYNC_OP_COOKIE *psNewCookie;
+ SYNC_BLOCK_LIST *psSyncBlockList;
+ IMG_UINT32 ui32ServerSyncCount = 0;
+ IMG_UINT32 ui32ClientSyncCount = 0;
+ IMG_UINT32 ui32ServerAllocSize;
+ IMG_UINT32 ui32ClientAllocSize;
+ IMG_UINT32 ui32TotalAllocSize;
+ IMG_UINT32 ui32ServerIndex = 0;
+ IMG_UINT32 ui32ClientIndex = 0;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32SyncBlockCount;
+ IMG_HANDLE hBridge;
+ IMG_HANDLE *pahHandleList;
+ IMG_CHAR *pcPtr;
+ PVRSRV_ERROR eError;
+
+ psSyncBlockList = _SyncPrimBlockListCreate();
+
+ if (!psSyncBlockList)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+
+ for (i=0;i<ui32SyncCount;i++)
+ {
+ if (SyncPrimIsServerSync(papsSyncPrim[i]))
+ {
+ ui32ServerSyncCount++;
+ }
+ else
+ {
+ SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[i];
+
+ ui32ClientSyncCount++;
+ eError = _SyncPrimBlockListAdd(psSyncBlockList, psSync->u.sLocal.psSyncBlock);
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+ }
+ }
+
+ ui32ServerAllocSize = ui32ServerSyncCount * (sizeof(IMG_HANDLE) + sizeof(IMG_UINT32));
+ ui32ClientAllocSize = ui32ClientSyncCount * (5 * sizeof(IMG_UINT32));
+ ui32TotalAllocSize = sizeof(SYNC_OP_COOKIE) +
+ (sizeof(PVRSRV_CLIENT_SYNC_PRIM *) * ui32SyncCount) +
+ ui32ServerAllocSize +
+ ui32ClientAllocSize;
+
+ psNewCookie = OSAllocMem(ui32TotalAllocSize);
+ pcPtr = (IMG_CHAR *) psNewCookie;
+
+ if (!psNewCookie)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e1;
+ }
+
+ /* Setup the pointers */
+ pcPtr += sizeof(SYNC_OP_COOKIE);
+ psNewCookie->papsSyncPrim = (PVRSRV_CLIENT_SYNC_PRIM **) pcPtr;
+
+ pcPtr += sizeof(PVRSRV_CLIENT_SYNC_PRIM *) * ui32SyncCount;
+ psNewCookie->paui32SyncBlockIndex = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->paui32Index = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->paui32Flags = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->paui32FenceValue = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->paui32UpdateValue = (IMG_UINT32 *) pcPtr;
+
+ pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
+ psNewCookie->pahServerSync =(IMG_HANDLE *) pcPtr;
+ pcPtr += sizeof(IMG_HANDLE) * ui32ServerSyncCount;
+
+ psNewCookie->paui32ServerFlags =(IMG_UINT32 *) pcPtr;
+ pcPtr += sizeof(IMG_UINT32) * ui32ServerSyncCount;
+
+ /* Check the pointer setup went ok */
+ PVR_ASSERT(pcPtr == (((IMG_CHAR *) psNewCookie) + ui32TotalAllocSize));
+
+ psNewCookie->ui32SyncCount = ui32SyncCount;
+ psNewCookie->ui32ServerSyncCount = ui32ServerSyncCount;
+ psNewCookie->ui32ClientSyncCount = ui32ClientSyncCount;
+ psNewCookie->psSyncBlockList = psSyncBlockList;
+
+ /*
+ Get the bridge handle from the 1st sync.
+
+ Note: We assume the all syncs have been created with the same
+ services connection.
+ */
+ if (SyncPrimIsServerSync(papsSyncPrim[0]))
+ {
+ SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0];
+
+ hBridge = psSync->u.sServer.hBridge;
+ }
+ else
+ {
+ SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0];
+
+ hBridge = psSync->u.sLocal.psSyncBlock->psContext->hBridge;
+ }
+
+ psNewCookie->hBridge = hBridge;
+
+ if (ui32ServerSyncCount)
+ {
+ psNewCookie->bHaveServerSync = IMG_TRUE;
+ }
+ else
+ {
+ psNewCookie->bHaveServerSync = IMG_FALSE;
+ }
+
+ /* Fill in the server and client sync data */
+ for (i=0;i<ui32SyncCount;i++)
+ {
+ SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[i];
+
+ if (SyncPrimIsServerSync(papsSyncPrim[i]))
+ {
+ psNewCookie->pahServerSync[ui32ServerIndex] = psSync->u.sServer.hServerSync;
+
+ ui32ServerIndex++;
+ }
+ else
+ {
+ /* Location of sync */
+ eError = _SyncPrimBlockListBlockToIndex(psSyncBlockList,
+ psSync->u.sLocal.psSyncBlock,
+ &psNewCookie->paui32SyncBlockIndex[ui32ClientIndex]);
+ if (eError != PVRSRV_OK)
+ {
+ goto e2;
+ }
+
+ /* Workout the index to sync */
+ psNewCookie->paui32Index[ui32ClientIndex] =
+ SyncPrimGetOffset(psSync)/sizeof(IMG_UINT32);
+
+ ui32ClientIndex++;
+ }
+
+ psNewCookie->papsSyncPrim[i] = papsSyncPrim[i];
+ }
+
+ eError = _SyncPrimBlockListHandleArrayCreate(psSyncBlockList,
+ &ui32SyncBlockCount,
+ &pahHandleList);
+ if (eError !=PVRSRV_OK)
+ {
+ goto e2;
+ }
+
+ /*
+ Create the server side cookie. Here we pass in all the unchanging
+ data so we only need to pass in the minimum at takeop time
+ */
+ eError = BridgeSyncPrimOpCreate(hBridge,
+ ui32SyncBlockCount,
+ pahHandleList,
+ psNewCookie->ui32ClientSyncCount,
+ psNewCookie->paui32SyncBlockIndex,
+ psNewCookie->paui32Index,
+ psNewCookie->ui32ServerSyncCount,
+ psNewCookie->pahServerSync,
+ &psNewCookie->hServerCookie);
+
+ /* Free the handle list regardless of error */
+ _SyncPrimBlockListHandleArrayDestroy(pahHandleList);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto e2;
+ }
+
+ *ppsCookie = psNewCookie;
+ return PVRSRV_OK;
+
+e2:
+ OSFreeMem(psNewCookie);
+e1:
+ _SyncPrimBlockListDestroy(psSyncBlockList);
+e0:
+ return eError;
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR SyncPrimOpTake(PSYNC_OP_COOKIE psCookie,
+ IMG_UINT32 ui32SyncCount,
+ PVRSRV_CLIENT_SYNC_PRIM_OP *pasSyncOp)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32ServerIndex = 0;
+ IMG_UINT32 ui32ClientIndex = 0;
+ IMG_UINT32 i;
+
+ /* Copy client sync operations */
+ for (i=0;i<ui32SyncCount;i++)
+ {
+ /*
+ Sanity check the client passes in the same syncs as the
+ ones we got at create time
+ */
+ if (psCookie->papsSyncPrim[i] != pasSyncOp[i].psSync)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (SyncPrimIsServerSync(pasSyncOp[i].psSync))
+ {
+ psCookie->paui32ServerFlags[ui32ServerIndex] =
+ pasSyncOp[i].ui32Flags;
+
+ ui32ServerIndex++;
+ }
+ else
+ {
+ /* Client operation information */
+ psCookie->paui32Flags[ui32ClientIndex] =
+ pasSyncOp[i].ui32Flags;
+ psCookie->paui32FenceValue[ui32ClientIndex] =
+ pasSyncOp[i].ui32FenceValue;
+ psCookie->paui32UpdateValue[ui32ClientIndex] =
+ pasSyncOp[i].ui32UpdateValue;
+
+ ui32ClientIndex++;
+ }
+ }
+
+ eError = BridgeSyncPrimOpTake(psCookie->hBridge,
+ psCookie->hServerCookie,
+ psCookie->ui32ClientSyncCount,
+ psCookie->paui32Flags,
+ psCookie->paui32FenceValue,
+ psCookie->paui32UpdateValue,
+ psCookie->ui32ServerSyncCount,
+ psCookie->paui32ServerFlags);
+
+ return eError;
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR SyncPrimOpReady(PSYNC_OP_COOKIE psCookie,
+ IMG_BOOL *pbReady)
+{
+ PVRSRV_ERROR eError;
+ PVR_ASSERT(psCookie != IMG_NULL);
+
+ /*
+ If we have a server sync we have no choice
+ but to do the check in the server
+ */
+ if (psCookie->bHaveServerSync)
+ {
+ eError = BridgeSyncPrimOpReady(psCookie->hBridge,
+ psCookie->hServerCookie,
+ pbReady);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Failed to do sync check in server (Error = %d)",
+ __FUNCTION__, eError));
+ goto e0;
+ }
+ }
+ else
+ {
+ IMG_UINT32 i;
+ IMG_UINT32 ui32SnapShot;
+ IMG_BOOL bReady = IMG_TRUE;
+
+ for (i=0;i<psCookie->ui32ClientSyncCount;i++)
+ {
+ if ((psCookie->paui32Flags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK) == 0)
+ {
+ continue;
+ }
+
+ ui32SnapShot = _SyncPrimBlockListGetClientValue(psCookie->psSyncBlockList,
+ psCookie->paui32SyncBlockIndex[i],
+ psCookie->paui32Index[i]);
+ if (ui32SnapShot != psCookie->paui32FenceValue[i])
+ {
+ bReady = IMG_FALSE;
+ break;
+ }
+ }
+
+ *pbReady = bReady;
+ }
+
+ return PVRSRV_OK;
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR SyncPrimOpComplete(PSYNC_OP_COOKIE psCookie)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgeSyncPrimOpComplete(psCookie->hBridge,
+ psCookie->hServerCookie);
+
+ return eError;
+}
+
+IMG_INTERNAL
+IMG_VOID SyncPrimOpDestroy(PSYNC_OP_COOKIE psCookie)
+{
+ PVRSRV_ERROR eError;
+
+ eError = BridgeSyncPrimOpDestroy(psCookie->hBridge,
+ psCookie->hServerCookie);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ _SyncPrimBlockListDestroy(psCookie->psSyncBlockList);
+ OSFreeMem(psCookie);
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR SyncPrimOpResolve(PSYNC_OP_COOKIE psCookie,
+ IMG_UINT32 *pui32SyncCount,
+ PVRSRV_CLIENT_SYNC_PRIM_OP **ppsSyncOp)
+{
+ IMG_UINT32 ui32ServerIndex = 0;
+ IMG_UINT32 ui32ClientIndex = 0;
+ PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOps;
+ IMG_UINT32 i;
+
+ psSyncOps = OSAllocMem(sizeof(PVRSRV_CLIENT_SYNC_PRIM_OP) *
+ psCookie->ui32SyncCount);
+ if (!psSyncOps)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ for (i=0; i<psCookie->ui32SyncCount; i++)
+ {
+ psSyncOps[i].psSync = psCookie->papsSyncPrim[i];
+ if (SyncPrimIsServerSync(psCookie->papsSyncPrim[i]))
+ {
+ psSyncOps[i].ui32FenceValue = 0;
+ psSyncOps[i].ui32UpdateValue = 0;
+ psSyncOps[i].ui32Flags = psCookie->paui32ServerFlags[ui32ServerIndex];
+ ui32ServerIndex++;
+ }
+ else
+ {
+ psSyncOps[i].ui32FenceValue = psCookie->paui32FenceValue[ui32ClientIndex];
+ psSyncOps[i].ui32UpdateValue = psCookie->paui32UpdateValue[ui32ClientIndex];
+ psSyncOps[i].ui32Flags = psCookie->paui32Flags[ui32ClientIndex];
+ ui32ClientIndex++;
+ }
+ }
+
+ *ppsSyncOp = psSyncOps;
+ *pui32SyncCount = psCookie->ui32SyncCount;
+
+ return PVRSRV_OK;
+}
+
+#if !defined(__KERNEL__)
+IMG_INTERNAL
+PVRSRV_ERROR SyncPrimServerAlloc(SYNC_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
+ const IMG_CHAR *pszClassName
+ PVR_DBG_FILELINE_PARAM)
+{
+ IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN];
+ SYNC_PRIM *psNewSync;
+ PVRSRV_ERROR eError;
+
+#if !defined(PVR_SYNC_PRIM_ALLOC_TRACE)
+ PVR_DBG_FILELINE_UNREF();
+#endif
+ psNewSync = OSAllocMem(sizeof(SYNC_PRIM));
+ if (psNewSync == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+ OSMemSet(psNewSync, 0, sizeof(SYNC_PRIM));
+
+ if(pszClassName)
+ {
+ /* Copy the class name annotation into a fixed-size array */
+ OSStringNCopy(szClassName, pszClassName, SYNC_MAX_CLASS_NAME_LEN - 1);
+ szClassName[SYNC_MAX_CLASS_NAME_LEN - 1] = 0;
+ }
+ else
+ {
+ /* No class name annotation */
+ szClassName[0] = 0;
+ }
+
+ eError = BridgeServerSyncAlloc(hBridge,
+ hDeviceNode,
+ &psNewSync->u.sServer.hServerSync,
+ &psNewSync->u.sServer.ui32FirmwareAddr,
+ OSStringNLength(szClassName, SYNC_MAX_CLASS_NAME_LEN),
+ szClassName);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto e1;
+ }
+
+#if defined(PVR_SYNC_PRIM_ALLOC_TRACE)
+ PVR_DPF((PVR_DBG_WARNING, "Allocated sync=server fw=0x%x [%p]" PVR_DBG_FILELINE_FMT,
+ psNewSync->u.sServer.ui32FirmwareAddr, &psNewSync->sCommon PVR_DBG_FILELINE_ARG));
+#endif
+
+ psNewSync->eType = SYNC_PRIM_TYPE_SERVER;
+ psNewSync->u.sServer.hBridge = hBridge;
+ *ppsSync = &psNewSync->sCommon;
+
+ return PVRSRV_OK;
+e1:
+ OSFreeMem(psNewSync);
+e0:
+ return eError;
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR SyncPrimServerGetStatus(IMG_UINT32 ui32SyncCount,
+ PVRSRV_CLIENT_SYNC_PRIM **papsSync,
+ IMG_UINT32 *pui32UID,
+ IMG_UINT32 *pui32FWAddr,
+ IMG_UINT32 *pui32CurrentOp,
+ IMG_UINT32 *pui32NextOp)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+ SYNC_BRIDGE_HANDLE hBridge = _SyncPrimGetBridgeHandle(papsSync[0]);
+ IMG_HANDLE *pahServerHandle;
+
+ pahServerHandle = OSAllocMem(sizeof(IMG_HANDLE) * ui32SyncCount);
+ if (pahServerHandle == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto e0;
+ }
+
+ /*
+ Check that all the sync we've been passed are server syncs
+ and that they all are on the same connection.
+ */
+ for (i=0;i<ui32SyncCount;i++)
+ {
+ SYNC_PRIM *psIntSync = IMG_CONTAINER_OF(papsSync[i], SYNC_PRIM, sCommon);
+
+ if (!SyncPrimIsServerSync(papsSync[i]))
+ {
+ eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
+ goto e1;
+ }
+
+ if (hBridge != _SyncPrimGetBridgeHandle(papsSync[i]))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncServerGetStatus: Sync connection is different\n"));
+ eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
+ goto e1;
+ }
+
+ pahServerHandle[i] = psIntSync->u.sServer.hServerSync;
+ }
+
+ eError = BridgeServerSyncGetStatus(hBridge,
+ ui32SyncCount,
+ pahServerHandle,
+ pui32UID,
+ pui32FWAddr,
+ pui32CurrentOp,
+ pui32NextOp);
+ OSFreeMem(pahServerHandle);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto e0;
+ }
+ return PVRSRV_OK;
+
+e1:
+ OSFreeMem(pahServerHandle);
+e0:
+ PVR_ASSERT(eError != PVRSRV_OK);
+ return eError;
+}
+
+#endif
+
+IMG_INTERNAL
+IMG_BOOL SyncPrimIsServerSync(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+{
+ SYNC_PRIM *psSyncInt;
+
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+ if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
+ {
+ return IMG_TRUE;
+ }
+
+ return IMG_FALSE;
+}
+
+IMG_INTERNAL
+IMG_HANDLE SyncPrimGetServerHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+{
+ SYNC_PRIM *psSyncInt;
+
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+ PVR_ASSERT(psSyncInt->eType == SYNC_PRIM_TYPE_SERVER);
+
+ return psSyncInt->u.sServer.hServerSync;
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR SyncPrimServerQueueOp(PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOp)
+{
+ SYNC_PRIM *psSyncInt;
+ IMG_BOOL bUpdate;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psSyncOp != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSyncOp->psSync, SYNC_PRIM, sCommon);
+ if (psSyncInt->eType != SYNC_PRIM_TYPE_SERVER)
+ {
+ return PVRSRV_ERROR_INVALID_SYNC_PRIM;
+ }
+
+ PVR_ASSERT(psSyncOp->ui32Flags != 0);
+ if (psSyncOp->ui32Flags & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)
+ {
+ bUpdate = IMG_TRUE;
+ }else
+ {
+ bUpdate = IMG_FALSE;
+ }
+
+ eError = BridgeServerSyncQueueHWOp(psSyncInt->u.sServer.hBridge,
+ psSyncInt->u.sServer.hServerSync,
+ bUpdate,
+ &psSyncOp->ui32FenceValue,
+ &psSyncOp->ui32UpdateValue);
+ return eError;
+}
+
+#if defined(PDUMP)
+IMG_INTERNAL IMG_VOID SyncPrimPDump(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+{
+ SYNC_PRIM *psSyncInt;
+ SYNC_PRIM_BLOCK *psSyncBlock;
+ SYNC_PRIM_CONTEXT *psContext;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+
+ if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDump: Invalid sync type"));
+ PVR_ASSERT(IMG_FALSE);
+ return;
+ }
+
+ psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
+ psContext = psSyncBlock->psContext;
+
+ eError = BridgeSyncPrimPDump(psContext->hBridge,
+ psSyncBlock->hServerSyncPrimBlock,
+ SyncPrimGetOffset(psSyncInt));
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+IMG_INTERNAL IMG_VOID SyncPrimPDumpValue(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
+{
+ SYNC_PRIM *psSyncInt;
+ SYNC_PRIM_BLOCK *psSyncBlock;
+ SYNC_PRIM_CONTEXT *psContext;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+
+ if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDump: Invalid sync type"));
+ PVR_ASSERT(IMG_FALSE);
+ return;
+ }
+
+ psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
+ psContext = psSyncBlock->psContext;
+
+ eError = BridgeSyncPrimPDumpValue(psContext->hBridge,
+ psSyncBlock->hServerSyncPrimBlock,
+ SyncPrimGetOffset(psSyncInt),
+ ui32Value);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+IMG_INTERNAL IMG_VOID SyncPrimPDumpPol(PVRSRV_CLIENT_SYNC_PRIM *psSync,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ SYNC_PRIM *psSyncInt;
+ SYNC_PRIM_BLOCK *psSyncBlock;
+ SYNC_PRIM_CONTEXT *psContext;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+
+ if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDumpPol: Invalid sync type (expected SYNC_PRIM_TYPE_LOCAL)"));
+ PVR_ASSERT(IMG_FALSE);
+ return;
+ }
+
+ psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
+ psContext = psSyncBlock->psContext;
+
+ eError = BridgeSyncPrimPDumpPol(psContext->hBridge,
+ psSyncBlock->hServerSyncPrimBlock,
+ SyncPrimGetOffset(psSyncInt),
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ ui32PDumpFlags);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+IMG_INTERNAL IMG_VOID SyncPrimOpPDumpPol(PSYNC_OP_COOKIE psCookie,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psCookie != IMG_NULL);
+
+ eError = BridgeSyncPrimOpPDumpPol(psCookie->hBridge,
+ psCookie->hServerCookie,
+ eOperator,
+ ui32PDumpFlags);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+IMG_INTERNAL IMG_VOID SyncPrimPDumpCBP(PVRSRV_CLIENT_SYNC_PRIM *psSync,
+ IMG_UINT64 uiWriteOffset,
+ IMG_UINT64 uiPacketSize,
+ IMG_UINT64 uiBufferSize)
+{
+ SYNC_PRIM *psSyncInt;
+ SYNC_PRIM_BLOCK *psSyncBlock;
+ SYNC_PRIM_CONTEXT *psContext;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psSync != IMG_NULL);
+ psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
+
+ if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDumpCBP: Invalid sync type"));
+ PVR_ASSERT(IMG_FALSE);
+ return;
+ }
+
+ psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
+ psContext = psSyncBlock->psContext;
+
+
+#if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
+ PVR_ASSERT(uiWriteOffset<IMG_UINT32_MAX);
+ PVR_ASSERT(uiPacketSize<IMG_UINT32_MAX);
+ PVR_ASSERT(uiBufferSize<IMG_UINT32_MAX);
+#endif
+ eError = BridgeSyncPrimPDumpCBP(psContext->hBridge,
+ psSyncBlock->hServerSyncPrimBlock,
+ SyncPrimGetOffset(psSyncInt),
+ (IMG_UINT32)uiWriteOffset,
+ (IMG_UINT32)uiPacketSize,
+ (IMG_UINT32)uiBufferSize);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed with error %d",
+ __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+#endif
+
diff --git a/drivers/gpu/rogue/services/shared/common/tlclient.c b/drivers/gpu/rogue/services/shared/common/tlclient.c
new file mode 100644
index 000000000000..4d35f8fab04d
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/tlclient.c
@@ -0,0 +1,365 @@
+/*************************************************************************/ /*!
+@File tlclient.c
+@Title Services Transport Layer shared API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Transport layer common API used in both clients and server
+@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.
+*/ /**************************************************************************/
+
+/* DESIGN NOTE
+ * This transport layer consumer-role API was created as a shared API when a
+ * client wanted to read the data of a TL stream from within the KM server
+ * driver. This was in addition to the existing clients supported externally
+ * by the UM client library component via PVR API layer.
+ * This shared API is thus used by the PVR TL API in the client library and
+ * by clients internal to the server driver module. It depends on
+ * client entry points of the TL and DEVMEM bridge modules. These entry points
+ * encapsulate from the TL shared API whether a direct bridge or an indirect
+ * (ioctl) bridge is used.
+ * One reason for needing this layer centres around the fact that some of the
+ * API functions make multiple bridge calls and the logic that glues these
+ * together is common regardless of client location. Further this layer has
+ * allowed the defensive coding that checks parameters to move into the PVR
+ * API layer where untrusted clients enter giving a more efficient KM code path.
+ */
+
+#include "img_defs.h"
+#include "pvrsrv_error.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+
+#include "allocmem.h"
+#include "devicemem.h"
+
+#include "tlclient.h"
+#include "client_pvrtl_bridge.h"
+
+/* Defines/Constants
+ */
+
+#define PVR_CONNECT_NO_FLAGS 0x00U
+#define NO_ACQUIRE 0xffffffffU
+#define DIRECT_BRIDGE_HANDLE ((IMG_HANDLE)0xDEADBEEFU)
+
+/* User-side stream descriptor structure.
+ */
+typedef struct _TL_STREAM_DESC_
+{
+ /* Handle on kernel-side stream descriptor*/
+ IMG_HANDLE hServerSD;
+
+ /* Stream data buffer variables */
+ DEVMEM_EXPORTCOOKIE sExportCookie;
+ DEVMEM_MEMDESC* psUMmemDesc;
+ IMG_PBYTE pBaseAddr;
+
+ /* Offset in bytes into the circular buffer and valid only after
+ * an Acquire call and undefined after a release. */
+ IMG_UINT32 uiReadOffset;
+
+ /* Always a positive integer when the Acquire call returns and a release
+ * is outstanding. Undefined at all other times. */
+ IMG_UINT32 uiReadLen;
+
+} TL_STREAM_DESC, *PTL_STREAM_DESC;
+
+
+/* Used in direct connections only */
+IMG_INTERNAL
+PVRSRV_ERROR TLClientConnect(IMG_HANDLE* phSrvHandle)
+{
+ /* Check the caller provided valid pointer*/
+ if(!phSrvHandle)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "TLClientConnect: Null connection handle"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *phSrvHandle = DIRECT_BRIDGE_HANDLE;
+
+ return PVRSRV_OK;
+
+
+}
+
+
+/* Used in direct connections only */
+IMG_INTERNAL
+PVRSRV_ERROR IMG_CALLCONV TLClientDisconnect(IMG_HANDLE hSrvHandle)
+{
+ if (hSrvHandle != (IMG_HANDLE)0xDEADBEEF)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "TLClientDisconnect: Invalid connection handle"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_INTERNAL
+PVRSRV_ERROR TLClientOpenStream(IMG_HANDLE hSrvHandle,
+ IMG_PCHAR pszName,
+ IMG_UINT32 ui32Mode,
+ IMG_HANDLE* phSD)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TL_STREAM_DESC* psSD = 0;
+ DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie;
+
+ PVR_ASSERT(hSrvHandle);
+ PVR_ASSERT(pszName);
+ PVR_ASSERT(phSD);
+ *phSD = NULL;
+
+ /* Allocate memory for the stream descriptor object, initialise with
+ * "no data read" yet. */
+ psSD = OSAllocZMem(sizeof(TL_STREAM_DESC));
+ if (psSD == NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ PVR_DPF((PVR_DBG_ERROR, "BridgeTLOpenStream: KM returned %d", eError));
+ goto e0;
+ }
+ psSD->uiReadLen = psSD->uiReadOffset = NO_ACQUIRE;
+
+ /* Send open stream request to kernel server to get stream handle and
+ * buffer cookie so we can get access to the buffer in this process. */
+ eError = BridgeTLOpenStream(hSrvHandle, pszName, ui32Mode,
+ &psSD->hServerSD, &hServerExportCookie);
+ if (eError != PVRSRV_OK)
+ {
+ if ((ui32Mode & PVRSRV_STREAM_FLAG_OPEN_WAIT) &&
+ (eError == PVRSRV_ERROR_TIMEOUT))
+ {
+ goto e1;
+ }
+ PVR_LOGG_IF_ERROR(eError, "BridgeTLOpenStream", e1);
+ }
+
+ /* Convert server export cookie into a cookie for use by this client */
+ eError = DevmemMakeServerExportClientExport(hSrvHandle,
+ hServerExportCookie, &psSD->sExportCookie);
+ PVR_LOGG_IF_ERROR(eError, "DevmemMakeServerExportClientExport", e2);
+
+ /* Now convert client cookie into a client handle on the buffer's
+ * physical memory region */
+ eError = DevmemImport(hSrvHandle, &psSD->sExportCookie,
+ PVRSRV_MEMALLOCFLAG_CPU_READABLE, &psSD->psUMmemDesc);
+ PVR_LOGG_IF_ERROR(eError, "DevmemImport", e3);
+
+ /* Now map the memory into the virtual address space of this process. */
+ eError = DevmemAcquireCpuVirtAddr(psSD->psUMmemDesc, (IMG_PVOID *)
+ &psSD->pBaseAddr);
+ PVR_LOGG_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", e4);
+
+ /* Return client descriptor handle to caller */
+ *phSD = psSD;
+ return PVRSRV_OK;
+
+/* Clean up post buffer setup */
+e4:
+ DevmemFree(psSD->psUMmemDesc);
+e3:
+ (void) DevmemUnmakeServerExportClientExport(hSrvHandle,
+ &psSD->sExportCookie);
+/* Clean up post stream open */
+e2:
+ BridgeTLCloseStream(hSrvHandle, psSD->hServerSD);
+
+/* Cleanup post allocation of the descriptor object */
+e1:
+ OSFreeMem(psSD);
+
+e0:
+ return eError;
+}
+
+
+IMG_INTERNAL
+PVRSRV_ERROR TLClientCloseStream(IMG_HANDLE hSrvHandle,
+ IMG_HANDLE hSD)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TL_STREAM_DESC* psSD = (TL_STREAM_DESC*) hSD;
+
+ PVR_ASSERT(hSrvHandle);
+ PVR_ASSERT(hSD);
+
+ /* Check the caller provided connection is valid */
+ if(!psSD->hServerSD)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "TLClientCloseStream: descriptor already closed/not open"));
+ return PVRSRV_ERROR_HANDLE_NOT_FOUND;
+ }
+
+ /* Check if acquire is outstanding, perform release if it is, ignore result
+ * as there is not much we can do if it is an error other than close */
+ if (psSD->uiReadLen != NO_ACQUIRE)
+ {
+ (void) BridgeTLReleaseData(hSrvHandle, psSD->hServerSD,
+ psSD->uiReadOffset, psSD->uiReadLen);
+ psSD->uiReadLen = psSD->uiReadOffset = NO_ACQUIRE;
+ }
+
+ /* Clean up DevMem resources used for this stream in this client */
+ DevmemReleaseCpuVirtAddr(psSD->psUMmemDesc);
+
+ DevmemFree(psSD->psUMmemDesc);
+
+ /* Ignore error, not much that can be done */
+ (void) DevmemUnmakeServerExportClientExport(hSrvHandle,
+ &psSD->sExportCookie);
+
+
+ /* Send close to server to clean up kernel mode resources for this
+ * handle and release the memory. */
+ eError = BridgeTLCloseStream(hSrvHandle, psSD->hServerSD);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BridgeTLCloseStream: KM returned %d", eError));
+ /*/ Not much we can do with error, fall through to clean up
+ * return eError; */
+ }
+
+ OSMemSet(psSD, 0x00, sizeof(TL_STREAM_DESC));
+ OSFreeMem (psSD);
+
+ return eError;
+}
+
+
+IMG_INTERNAL
+PVRSRV_ERROR TLClientAcquireData(IMG_HANDLE hSrvHandle,
+ IMG_HANDLE hSD,
+ IMG_PBYTE* ppPacketBuf,
+ IMG_UINT32* pui32BufLen)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TL_STREAM_DESC* psSD = (TL_STREAM_DESC*) hSD;
+
+ PVR_ASSERT(hSrvHandle);
+ PVR_ASSERT(hSD);
+ PVR_ASSERT(ppPacketBuf);
+ PVR_ASSERT(pui32BufLen);
+
+ /* Check Acquire has not been called twice in a row without a release */
+ if (psSD->uiReadOffset != NO_ACQUIRE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "TLClientAcquireData: acquire already outstanding"));
+ return PVRSRV_ERROR_RETRY;
+ }
+
+ *pui32BufLen = 0;
+ /* Ask the kernel server for the next chunk of data to read */
+ eError = BridgeTLAcquireData(hSrvHandle, psSD->hServerSD,
+ &psSD->uiReadOffset, &psSD->uiReadLen);
+ if (eError != PVRSRV_OK)
+ {
+ if ((eError != PVRSRV_ERROR_RESOURCE_UNAVAILABLE) &&
+ (eError != PVRSRV_ERROR_TIMEOUT))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BridgeTLAcquireData: KM returned %d", eError));
+ }
+ psSD->uiReadOffset = psSD->uiReadLen = NO_ACQUIRE;
+ return eError;
+ }
+
+ /* Return the data offset and length to the caller if bytes are available
+ * to be read. Could be zero for non-blocking mode. */
+ if (psSD->uiReadLen)
+ {
+ *ppPacketBuf = psSD->pBaseAddr + psSD->uiReadOffset;
+ *pui32BufLen = psSD->uiReadLen;
+ }
+ else
+ {
+ /* On non blocking, zero length data could be returned from server
+ * Which is basically a no-acquire operation */
+ *ppPacketBuf = 0;
+ *pui32BufLen = 0;
+ }
+
+ return eError;
+}
+
+
+IMG_INTERNAL
+PVRSRV_ERROR TLClientReleaseData(IMG_HANDLE hSrvHandle,
+ IMG_HANDLE hSD)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ TL_STREAM_DESC* psSD = (TL_STREAM_DESC*) hSD;
+
+ PVR_ASSERT(hSrvHandle);
+ PVR_ASSERT(hSD);
+
+ /* the previous acquire did not return any data, this is a no-operation */
+ if (psSD->uiReadLen == 0)
+ {
+ return PVRSRV_OK;
+ }
+
+ /* Check release has not been called twice in a row without an acquire */
+ if (psSD->uiReadOffset == NO_ACQUIRE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "TLClientReleaseData_: no acquire to release"));
+ return PVRSRV_ERROR_RETRY;
+ }
+
+ /* Inform the kernel to release the data from the buffer */
+ eError = BridgeTLReleaseData(hSrvHandle, psSD->hServerSD,
+ psSD->uiReadOffset, psSD->uiReadLen);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BridgeTLReleaseData: KM returned %d", eError));
+ /* Need to continue to keep client data consistent, fall through
+ * return eError */
+ }
+
+ /* Reset state to indicate no outstanding acquire */
+ psSD->uiReadLen = psSD->uiReadOffset = NO_ACQUIRE;
+
+ return eError;
+}
+
+
+/******************************************************************************
+ End of file (tlclient.c)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/shared/common/uniq_key_splay_tree.c b/drivers/gpu/rogue/services/shared/common/uniq_key_splay_tree.c
new file mode 100644
index 000000000000..d275edf7528b
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/uniq_key_splay_tree.c
@@ -0,0 +1,244 @@
+/*************************************************************************/ /*!
+@File
+@Title Provides splay-trees.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implementation of splay-trees.
+@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 "allocmem.h" /* for OSMemAlloc / OSMemFree */
+#include "osfunc.h" /* for OSMemFree */
+#include "pvr_debug.h"
+#include "uniq_key_splay_tree.h"
+
+/**
+ * This function performs a simple top down splay
+ *
+ * @param ui32Flags the flags that must splayed to the root (if possible).
+ * @param psTree The tree to splay.
+ * @return the resulting tree after the splay operation.
+ */
+IMG_INTERNAL
+IMG_PSPLAY_TREE PVRSRVSplay (IMG_UINT32 ui32Flags, IMG_PSPLAY_TREE psTree)
+{
+ IMG_SPLAY_TREE sTmp1;
+ IMG_PSPLAY_TREE psLeft;
+ IMG_PSPLAY_TREE psRight;
+ IMG_PSPLAY_TREE psTmp2;
+
+ if (psTree == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+
+ sTmp1.psLeft = IMG_NULL;
+ sTmp1.psRight = IMG_NULL;
+
+ psLeft = &sTmp1;
+ psRight = &sTmp1;
+
+ for (;;)
+ {
+ if (ui32Flags < psTree->ui32Flags)
+ {
+ if (psTree->psLeft == IMG_NULL)
+ {
+ break;
+ }
+
+ if (ui32Flags < psTree->psLeft->ui32Flags)
+ {
+ /* if we get to this point, we need to rotate right the tree */
+ psTmp2 = psTree->psLeft;
+ psTree->psLeft = psTmp2->psRight;
+ psTmp2->psRight = psTree;
+ psTree = psTmp2;
+ if (psTree->psLeft == IMG_NULL)
+ {
+ break;
+ }
+ }
+
+ /* if we get to this point, we need to link right */
+ psRight->psLeft = psTree;
+ psRight = psTree;
+ psTree = psTree->psLeft;
+ }
+ else
+ {
+ if (ui32Flags > psTree->ui32Flags)
+ {
+ if (psTree->psRight == IMG_NULL)
+ {
+ break;
+ }
+
+ if (ui32Flags > psTree->psRight->ui32Flags)
+ {
+ /* if we get to this point, we need to rotate leftthe tree */
+ psTmp2 = psTree->psRight;
+ psTree->psRight = psTmp2->psLeft;
+ psTmp2->psLeft = psTree;
+ psTree = psTmp2;
+ if (psTree->psRight == IMG_NULL)
+ {
+ break;
+ }
+ }
+
+ /* if we get to this point, we need to link left */
+ psLeft->psRight = psTree;
+ psLeft = psTree;
+ psTree = psTree->psRight;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ /* at this point re-assemble the tree */
+ psLeft->psRight = psTree->psLeft;
+ psRight->psLeft = psTree->psRight;
+ psTree->psLeft = sTmp1.psRight;
+ psTree->psRight = sTmp1.psLeft;
+ return psTree;
+}
+
+
+/**
+ * This function inserts a node into the Tree (unless it is already present, in
+ * which case it is equivalent to performing only a splay operation
+ *
+ * @param ui32Flags the key of the new node
+ * @param psTree The tree into which one wants to add a new node
+ * @return The resulting with the node in it
+ */
+IMG_INTERNAL
+IMG_PSPLAY_TREE PVRSRVInsert(IMG_UINT32 ui32Flags, IMG_PSPLAY_TREE psTree)
+{
+ IMG_PSPLAY_TREE psNew;
+
+ if (psTree != IMG_NULL)
+ {
+ psTree = PVRSRVSplay(ui32Flags, psTree);
+ if (psTree->ui32Flags == ui32Flags)
+ {
+ return psTree;
+ }
+ }
+
+ psNew = (IMG_PSPLAY_TREE) OSAllocMem(sizeof(IMG_SPLAY_TREE));
+ if (psNew == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "Error: failed to allocate memory to add a node to the splay tree."));
+ return IMG_NULL;
+ }
+
+ psNew->ui32Flags = ui32Flags;
+ OSMemSet(&(psNew->buckets[0]), 0, sizeof(psNew->buckets));
+
+#if defined(HAS_BUILTIN_CTZLL)
+ psNew->bHasEltsMapping = ~(((IMG_ELTS_MAPPINGS) 1 << (sizeof(psNew->buckets) / (sizeof(psNew->buckets[0])))) - 1);
+#endif
+
+ if (psTree == IMG_NULL)
+ {
+ psNew->psLeft = IMG_NULL;
+ psNew->psRight = IMG_NULL;
+ return psNew;
+ }
+
+ if (ui32Flags < psTree->ui32Flags)
+ {
+ psNew->psLeft = psTree->psLeft;
+ psNew->psRight = psTree;
+ psTree->psLeft = IMG_NULL;
+ }
+ else
+ {
+ psNew->psRight = psTree->psRight;
+ psNew->psLeft = psTree;
+ psTree->psRight = IMG_NULL;
+ }
+
+ return psNew;
+}
+
+
+/**
+ * Deletes a node from the tree (unless it is not there, in which case it is
+ * equivalent to a splay operation)
+ *
+ * @param ui32Flags the value of the node to remove
+ * @param psTree the tree into which the node must be removed
+ * @return the resulting tree
+ */
+IMG_INTERNAL
+IMG_PSPLAY_TREE PVRSRVDelete(IMG_UINT32 ui32Flags, IMG_PSPLAY_TREE psTree)
+{
+ IMG_PSPLAY_TREE psTmp;
+ if (psTree == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+
+ psTree = PVRSRVSplay(ui32Flags, psTree);
+ if (ui32Flags == psTree->ui32Flags)
+ {
+ /* The value was present in the tree */
+ if (psTree->psLeft == IMG_NULL)
+ {
+ psTmp = psTree->psRight;
+ }
+ else
+ {
+ psTmp = PVRSRVSplay(ui32Flags, psTree->psLeft);
+ psTmp->psRight = psTree->psRight;
+ }
+ OSFreeMem(psTree);
+ return psTmp;
+ }
+
+ /* the value was not present in the tree, so just return it as is (after the
+ * splay) */
+ return psTree;
+}
+
+
diff --git a/drivers/gpu/rogue/services/shared/common/uniq_key_splay_tree.h b/drivers/gpu/rogue/services/shared/common/uniq_key_splay_tree.h
new file mode 100644
index 000000000000..e58c0b7f169d
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/common/uniq_key_splay_tree.h
@@ -0,0 +1,95 @@
+/*************************************************************************/ /*!
+@File
+@Title Splay trees interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides debug 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 UNIQ_KEY_SPLAY_TREE_H_
+#define UNIQ_KEY_SPLAY_TREE_H_
+
+#include "img_types.h"
+
+#if defined(__GNUC__) && defined(__x86_64__)
+ /* note, the 64 bits requirements should not be necessary.
+ Unfortunately, linking against the __ctzdi function (in 32bits) failed. */
+
+ #define HAS_BUILTIN_CTZLL
+#endif
+
+#if defined(HAS_BUILTIN_CTZLL)
+ /* if the compiler can provide this builtin, then map the is_bucket_n_free?
+ into an int. This way, the driver can find the first non empty without loop */
+
+ typedef IMG_UINT64 IMG_ELTS_MAPPINGS;
+#endif
+
+
+/* head of list of free boundary tags for indexed by pvr_log2 of the
+ boundary tag size */
+#define FREE_TABLE_LIMIT 40
+
+struct _BT_;
+
+typedef struct img_splay_tree
+{
+ /* left child/subtree */
+ struct img_splay_tree * psLeft;
+
+ /* right child/subtree */
+ struct img_splay_tree * psRight;
+
+ /* Flags to match on this span, used as the key. */
+ IMG_UINT32 ui32Flags;
+
+#if defined(HAS_BUILTIN_CTZLL)
+ /* each bit of this int is a boolean telling if the corresponding
+ bucket is empty or not */
+ IMG_ELTS_MAPPINGS bHasEltsMapping;
+#endif
+
+ struct _BT_ * buckets[FREE_TABLE_LIMIT];
+} IMG_SPLAY_TREE, *IMG_PSPLAY_TREE;
+
+IMG_PSPLAY_TREE PVRSRVSplay (IMG_UINT32 ui32Flags, IMG_PSPLAY_TREE psTree);
+IMG_PSPLAY_TREE PVRSRVInsert(IMG_UINT32 ui32Flags, IMG_PSPLAY_TREE psTree);
+IMG_PSPLAY_TREE PVRSRVDelete(IMG_UINT32 ui32Flags, IMG_PSPLAY_TREE psTree);
+
+
+#endif /* !UNIQ_KEY_SPLAY_TREE_H_ */
diff --git a/drivers/gpu/rogue/services/shared/devices/rgx/rgx_compat_bvnc.c b/drivers/gpu/rogue/services/shared/devices/rgx/rgx_compat_bvnc.c
new file mode 100644
index 000000000000..66cc3d3270d9
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/devices/rgx/rgx_compat_bvnc.c
@@ -0,0 +1,165 @@
+/*************************************************************************/ /*!
+@File
+@Title Functions for BVNC manipulating
+
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Utility functions used internally by device memory management
+ code.
+@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.
+*/ /**************************************************************************/
+
+/******************************************************************************
+ * RGX Version packed into 24-bit (BNC) and string (V) to be used by Compatibility Check
+ *****************************************************************************/
+
+#include "rgx_compat_bvnc.h"
+
+IMG_VOID rgx_bvnc_packed(IMG_UINT32 *pui32OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
+ IMG_UINT32 ui32B, IMG_CHAR *pszV, IMG_UINT32 ui32N, IMG_UINT32 ui32C)
+{
+#if 0
+ IMG_UINT32 i = ui32OutVMaxLen;
+#endif
+ IMG_UINT32 ui32InVLen = 0;
+ IMG_CHAR *pszPointer;
+ IMG_UINT32 ui32V = 0;
+
+ *pui32OutBNC = (((ui32B & 0xFF) << 16) | ((ui32N & 0xFF) << 8) |
+ (ui32C & 0xFF));
+
+ /* Using dword accesses instead of byte accesses when forming V part of BVNC */
+ ui32OutVMaxLen = ui32OutVMaxLen;
+ pszPointer = pszV;
+ while (*pszPointer)
+ {
+ ui32InVLen++;
+ pszPointer++;
+ }
+
+ if (ui32InVLen == 1)
+ {
+ ui32V = ((IMG_UINT32)pszV[0]) & 0xFF;
+ }
+ else if (ui32InVLen == 2)
+ {
+ ui32V = ((((IMG_UINT32)pszV[0]) & 0xFF) << 0) | ((((IMG_UINT32)pszV[1]) & 0xFF) << 8);
+ }
+ else if (ui32InVLen == 3)
+ {
+ ui32V = ((((IMG_UINT32)pszV[0]) & 0xFF) << 0) | ((((IMG_UINT32)pszV[1]) & 0xFF) << 8) | ((((IMG_UINT32)pszV[2]) & 0xFF) << 16);
+ }
+
+ *((IMG_UINT32 *)pszOutV) = ui32V;
+
+#if 0
+ for (i = 0; i < (ui32OutVMaxLen + 1); i++)
+ pszOutV[i] = '\0';
+
+ while ((ui32OutVMaxLen > 0) && *pszV)
+ {
+ *pszOutV++ = *pszV++;
+ ui32OutVMaxLen--;
+ }
+#endif
+}
+
+IMG_VOID rgx_bvnc_pack_hw(IMG_UINT32 *pui32OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
+ IMG_UINT32 ui32B, IMG_CHAR *pszFwV, IMG_UINT32 ui32V, IMG_UINT32 ui32N, IMG_UINT32 ui32C)
+{
+ IMG_UINT32 i = ui32OutVMaxLen;
+ IMG_CHAR *pszPointer;
+
+ *pui32OutBNC = (((ui32B & 0xFF) << 16) | ((ui32N & 0xFF) << 8) |
+ (ui32C & 0xFF));
+
+ for (i = 0; i < (ui32OutVMaxLen + 1); i++)
+ pszOutV[i] = '\0';
+
+ /* find out whether pszFwV is integer number or not */
+ pszPointer = pszFwV;
+ while (*pszPointer)
+ {
+ if ((*pszPointer < '0') || (*pszPointer > '9'))
+ {
+ break;
+ }
+ pszPointer++;
+ }
+
+ if (*pszPointer)
+ {
+ /* pszFwV is not a number, so taking V from it */
+ pszPointer = pszFwV;
+ while ((ui32OutVMaxLen > 0) && *pszPointer)
+ {
+ *pszOutV++ = *pszPointer++;
+ ui32OutVMaxLen--;
+ }
+ }
+ else
+ {
+ /* pszFwV is a number, taking V from ui32V */
+ IMG_CHAR aszBuf[4];
+
+ pszPointer = aszBuf;
+
+ if (ui32V > 99)
+ pszPointer+=3;
+ else if (ui32V > 9)
+ pszPointer+=2;
+ else
+ pszPointer+=1;
+
+ *pszPointer-- = '\0';
+ *pszPointer = '0';
+
+ while (ui32V > 0)
+ {
+ *pszPointer-- = (ui32V % 10) + '0';
+ ui32V /= 10;
+ }
+
+ pszPointer = aszBuf;
+ while ((ui32OutVMaxLen > 0) && *pszPointer)
+ {
+ *pszOutV++ = *pszPointer++;
+ ui32OutVMaxLen--;
+ }
+ }
+}
+
diff --git a/drivers/gpu/rogue/services/shared/devices/rgx/rgx_compat_bvnc.h b/drivers/gpu/rogue/services/shared/devices/rgx/rgx_compat_bvnc.h
new file mode 100644
index 000000000000..61e11f080416
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/devices/rgx/rgx_compat_bvnc.h
@@ -0,0 +1,96 @@
+/*************************************************************************/ /*!
+@File
+@Title Functions for BVNC manipulating
+
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Utility functions used internally by device memory management
+ code.
+@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 (__RGX_COMPAT_BVNC_H__)
+#define __RGX_COMPAT_BVNC_H__
+
+#include "img_types.h"
+
+/******************************************************************************
+ * RGX Version packed into 24-bit (BNC) and string (V) to be used by Compatibility Check
+ *****************************************************************************/
+
+#define RGX_BVNC_PACK_MASK_B 0x00FF0000
+#define RGX_BVNC_PACK_MASK_N 0x0000FF00
+#define RGX_BVNC_PACK_MASK_C 0x000000FF
+
+#define RGX_BVNC_PACKED_EXTR_B(BVNC) (((BVNC).ui32BNC >> 16) & 0xFF)
+#define RGX_BVNC_PACKED_EXTR_V(BVNC) ((BVNC).aszV)
+#define RGX_BVNC_PACKED_EXTR_N(BVNC) (((BVNC).ui32BNC >> 8) & 0xFF)
+#define RGX_BVNC_PACKED_EXTR_C(BVNC) (((BVNC).ui32BNC >> 0) & 0xFF)
+
+#define RGX_BVNC_EQUAL(L,R,all,version,lenmax,bnc,v) do { \
+ (lenmax) = IMG_FALSE; \
+ (bnc) = IMG_FALSE; \
+ (v) = IMG_FALSE; \
+ (version) = ((L).ui32LayoutVersion == (R).ui32LayoutVersion); \
+ if (version) \
+ { \
+ (lenmax) = ((L).ui32VLenMax == (R).ui32VLenMax); \
+ } \
+ if (lenmax) \
+ { \
+ (bnc) = ((L).ui32BNC == (R).ui32BNC); \
+ } \
+ if (bnc) \
+ { \
+ (L).aszV[(L).ui32VLenMax] = '\0'; \
+ (R).aszV[(R).ui32VLenMax] = '\0'; \
+ (v) = (OSStringCompare((L).aszV, (R).aszV)==0); \
+ } \
+ (all) = (version) && (lenmax) && (bnc) && (v); \
+ } while (0)
+
+IMG_VOID rgx_bvnc_packed(IMG_UINT32 *pui32OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
+ IMG_UINT32 ui32B, IMG_CHAR *pszV, IMG_UINT32 ui32N, IMG_UINT32 ui32C);
+IMG_VOID rgx_bvnc_pack_hw(IMG_UINT32 *pui32OutBNC, IMG_CHAR *pszOutV, IMG_UINT32 ui32OutVMaxLen,
+ IMG_UINT32 ui32B, IMG_CHAR *pszFwV, IMG_UINT32 ui32V, IMG_UINT32 ui32N, IMG_UINT32 ui32C);
+
+#endif /* __RGX_COMPAT_BVNC_H__ */
+
+/******************************************************************************
+ End of file (rgx_compat_bvnc.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/shared/include/cache_internal.h b/drivers/gpu/rogue/services/shared/include/cache_internal.h
new file mode 100644
index 000000000000..83267247d486
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/cache_internal.h
@@ -0,0 +1,58 @@
+/*************************************************************************/ /*!
+@File
+@Title Services cache management header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines for cache management which are visible internally only.
+@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 _CACHE_INTERNAL_H_
+#define _CACHE_INTERNAL_H_
+#include "img_types.h"
+#include "pvrsrv_devmem.h"
+#include "cache_external.h"
+
+typedef struct _CACHE_BATCH_OP_ENTRY_
+{
+ IMG_UINT32 ui32PMREntryIndex;
+ PVRSRV_CACHE_OP eCacheOp;
+ IMG_DEVMEM_SIZE_T uiSize;
+ IMG_DEVMEM_OFFSET_T uiOffset;
+} CACHE_BATCH_OP_ENTRY;
+
+#endif /* _CACHE_INTERNAL_H_ */
diff --git a/drivers/gpu/rogue/services/shared/include/devicemem.h b/drivers/gpu/rogue/services/shared/include/devicemem.h
new file mode 100644
index 000000000000..5539fb73eff5
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/devicemem.h
@@ -0,0 +1,543 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management core internal
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Services internal interface to core device memory management
+ functions that are shared between client and server code.
+@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 SRVCLIENT_DEVICEMEM_H
+#define SRVCLIENT_DEVICEMEM_H
+
+/********************************************************************************
+ * *
+ * +------------+ +------------+ +--------------+ +--------------+ *
+ * | a sub- | | a sub- | | an | | allocation | *
+ * | allocation | | allocation | | allocation | | also mapped | *
+ * | | | | | in proc 1 | | into proc 2 | *
+ * +------------+ +------------+ +--------------+ +--------------+ *
+ * | | | | *
+ * +--------------+ +--------------+ +--------------+ *
+ * | page gran- | | page gran- | | page gran- | *
+ * | ular mapping | | ular mapping | | ular mapping | *
+ * +--------------+ +--------------+ +--------------+ *
+ * | | | *
+ * | | | *
+ * | | | *
+ * +--------------+ +--------------+ *
+ * | | | | *
+ * | A "P.M.R." | | A "P.M.R." | *
+ * | | | | *
+ * +--------------+ +--------------+ *
+ * *
+ ********************************************************************************/
+
+/*
+ All device memory allocations are ultimately a view upon (not
+ necessarily the whole of) a "PMR".
+
+ A PMR is a "Physical Memory Resource", which may be a
+ "pre-faulted" lump of physical memory, or it may be a
+ representation of some physical memory that will be instantiated
+ at some future time.
+
+ PMRs always represent multiple of some power-of-2 "contiguity"
+ promised by the PMR, which will allow them to be mapped in whole
+ pages into the device MMU. As memory allocations may be smaller
+ than a page, these mappings may be suballocated and thus shared
+ between multiple allocations in one process. A PMR may also be
+ mapped simultaneously into multiple device memory contexts
+ (cross-process scenario), however, for security reasons, it is not
+ legal to share a PMR "both ways" at once, that is, mapped into
+ multiple processes and divided up amongst several suballocations.
+
+ This PMR terminology is introduced here for background
+ information, but is generally of little concern to the caller of
+ this API. This API handles suballocations and mappings, and the
+ caller thus deals primarily with MEMORY DESCRIPTORS representing
+ an allocation or suballocation, HEAPS representing ranges of
+ virtual addresses in a CONTEXT.
+*/
+
+/*
+ |<---------------------------context------------------------------>|
+ |<-------heap------->| |<-------heap------->|<-------heap------->|
+ |<-alloc->| | |<-alloc->|<-alloc->|| |<-alloc->| |
+*/
+
+#include "img_types.h"
+#include "devicemem_typedefs.h"
+#include "pdumpdefs.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_memallocflags.h"
+
+#include "pdump.h"
+
+/* Use GET and SET function to access this */
+IMG_INTERNAL extern IMG_UINT32 g_uiLog2PageSize;
+
+#define GET_LOG2_PAGESIZE() ( (const IMG_UINT32) g_uiLog2PageSize )
+#define SET_LOG2_PAGESIZE(ui32Log2PageSize) \
+ { \
+ PVR_ASSERT( (ui32Log2PageSize > 11) && (ui32Log2PageSize < 22) ); \
+ g_uiLog2PageSize = (IMG_UINT32) ui32Log2PageSize; \
+ }
+
+typedef IMG_UINT32 DEVMEM_HEAPCFGID;
+#define DEVMEM_HEAPCFG_FORCLIENTS 0
+#define DEVMEM_HEAPCFG_META 1
+#define DEVMEM_HEAPCFG_PMMIF 0
+
+/*
+ In order to call the server side functions, we need a bridge handle.
+ We abstract that here, as we may wish to change its form.
+ */
+
+typedef IMG_HANDLE DEVMEM_BRIDGE_HANDLE;
+
+/*
+ * DevmemCreateContext()
+ *
+ * Create a device memory context
+ *
+ * This must be called before any heap is created in this context
+ *
+ * Caller to provide bridge handle which will be squirreled away
+ * internally and used for all future operations on items from this
+ * memory context. Caller also to provide devicenode handle, as this
+ * is used for MMU configuration and also to determine the heap
+ * configuration for the auto-instantiated heaps.
+ *
+ * Note that when compiled in services/server, the hBridge is not used
+ * and is thrown away by the "fake" direct bridge. (This may change.
+ * It is recommended that IMG_NULL be passed for the handle for now)
+ *
+ * hDeviceNode and uiHeapBlueprintID shall together dictate which
+ * heap-config to use.
+ *
+ * This will cause the server side counterpart to be created also
+ * (with appropriate resman stuff where applicable)
+ *
+ * If you call DevmemCreateContext() (and the call succeeds) you
+ * are promising that you will later call Devmem_ContextDestroy(),
+ * except for abnormal process termination in which case it is
+ * expected that ResMan will do this on your behalf.
+ *
+ * Caller to provide storage for the pointer to the NEWDEVMEM_CONTEXT
+ * object thusly created.
+ */
+extern PVRSRV_ERROR
+DevmemCreateContext(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ DEVMEM_HEAPCFGID uiHeapBlueprintID,
+ DEVMEM_CONTEXT **ppsCtxPtr);
+
+/*
+ * DevmemAcquireDevPrivData()
+ *
+ * Acquire the device private data for this memory context
+ */
+PVRSRV_ERROR
+DevmemAcquireDevPrivData(DEVMEM_CONTEXT *psCtx,
+ IMG_HANDLE *hPrivData);
+
+/*
+ * DevmemReleaseDevPrivData()
+ *
+ * Release the device private data for this memory context
+ */
+PVRSRV_ERROR
+DevmemReleaseDevPrivData(DEVMEM_CONTEXT *psCtx);
+
+/*
+ * DevmemDestroyContext()
+ *
+ * Undoes that done by DevmemCreateContext()
+ */
+extern PVRSRV_ERROR
+DevmemDestroyContext(DEVMEM_CONTEXT *psCtx);
+
+/*
+ * DevmemCreateHeap()
+ *
+ * Create a heap in the given context.
+ *
+ * N.B. Not intended to be called directly, though it can be.
+ * Normally, heaps are instantiated at context creation time according
+ * to the specified blueprint. See DevmemCreateContext() for details.
+ *
+ * This will cause MMU code to set up data structures for the heap,
+ * but may not cause page tables to be modified until allocations are
+ * made from the heap.
+ *
+ * The "Quantum" is both the device MMU page size to be configured for
+ * this heap, and the unit multiples of which "quantized" allocations
+ * are made (allocations smaller than this, known as "suballocations"
+ * will be made from a "sub alloc RA" and will "import" chunks
+ * according to this quantum)
+ *
+ * Where imported PMRs (or, for example, PMRs created by device class
+ * buffers) are mapped into this heap, it is important that the
+ * physical contiguity guarantee offered by the PMR is greater than or
+ * equal to the quantum size specified here, otherwise the attempt to
+ * map it will fail. "Normal" allocations via Devmem_Allocate
+ * shall automatically meet this requirement, as each "import" will
+ * trigger the creation of a PMR with the desired contiguity. The
+ * supported quantum sizes in that case shall be dictated by the OS
+ * specific implementation of PhysmemNewOSRamBackedPMR() (see)
+ */
+extern PVRSRV_ERROR
+DevmemCreateHeap(DEVMEM_CONTEXT *psCtxPtr,
+ /* base and length of heap */
+ IMG_DEV_VIRTADDR sBaseAddress,
+ IMG_DEVMEM_SIZE_T uiLength,
+ /* log2 of allocation quantum, i.e. "page" size.
+ All allocations (that go to server side) are
+ multiples of this. We use a client-side RA to
+ make sub-allocations from this */
+ IMG_UINT32 ui32Log2Quantum,
+ /* Name of heap for debug */
+ /* N.B. Okay to exist on caller's stack - this
+ func takes a copy if it needs it. */
+ const IMG_CHAR *pszName,
+ DEVMEM_HEAP **ppsHeapPtr);
+/*
+ * DevmemDestroyHeap()
+ *
+ * Reverses DevmemCreateHeap()
+ *
+ * N.B. All allocations must have been freed and all mappings must
+ * have been unmapped before invoking this call
+ */
+extern PVRSRV_ERROR
+DevmemDestroyHeap(DEVMEM_HEAP *psHeap);
+
+/*
+ * DevmemExportalignAdjustSizeAndAlign()
+ * Compute the Size and Align passed to avoid suballocations (used when allocation with PVRSRV_MEMALLOCFLAG_EXPORTALIGN)
+ */
+IMG_INTERNAL IMG_VOID
+DevmemExportalignAdjustSizeAndAlign(DEVMEM_HEAP *psHeap, IMG_DEVMEM_SIZE_T *puiSize, IMG_DEVMEM_ALIGN_T *puiAlign);
+
+/*
+ * DevmemAllocate()
+ *
+ * Makes an allocation (possibly a "suballocation", as described
+ * below) of device virtual memory from this heap.
+ *
+ * The size and alignment of the allocation will be honoured by the RA
+ * that allocates the "suballocation". The resulting allocation will
+ * be mapped into GPU virtual memory and the physical memory to back
+ * it will exist, by the time this call successfully completes.
+ *
+ * The size must be a positive integer multiple of the alignment.
+ * (i.e. the aligment specifies the alignment of both the start and
+ * the end of the resulting allocation.)
+ *
+ * Allocations made via this API are routed though a "suballocation
+ * RA" which is responsible for ensuring that small allocations can be
+ * made without wasting physical memory in the server. Furthermore,
+ * such suballocations can be made entirely client side without
+ * needing to go to the server unless the allocation spills into a new
+ * page.
+ *
+ * Such suballocations cause many allocations to share the same "PMR".
+ * This happens only when the flags match exactly.
+ *
+ */
+
+PVRSRV_ERROR DevmemAllocate(DEVMEM_HEAP *psHeap,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags,
+ const IMG_PCHAR pszText,
+ DEVMEM_MEMDESC **ppsMemDescPtr);
+
+PVRSRV_ERROR
+DevmemAllocateExportable(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags,
+ const IMG_PCHAR pszText,
+ DEVMEM_MEMDESC **ppsMemDescPtr);
+
+PVRSRV_ERROR
+DevmemAllocateSparse(IMG_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_SIZE_T uiChunkSize,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_BOOL *pabMappingTable,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags,
+ const IMG_PCHAR pszText,
+ DEVMEM_MEMDESC **ppsMemDescPtr);
+
+/*
+ * DevmemFree()
+ *
+ * Reverses that done by DevmemAllocate() N.B. The underlying
+ * mapping and server side allocation _may_ not be torn down, for
+ * example, if the allocation has been exported, or if multiple
+ * allocations were suballocated from the same mapping, but this is
+ * properly refcounted, so the caller does not have to care.
+ */
+
+extern IMG_VOID
+DevmemFree(DEVMEM_MEMDESC *psMemDesc);
+
+/*
+ DevmemMapToDevice:
+
+ Map an allocation to the device is was allocated from.
+ This function _must_ be called before any call to
+ DevmemAcquireDevVirtAddr is made as it binds the allocation
+ to the heap.
+ DevmemReleaseDevVirtAddr is used to release the reference
+ to the device mapping this function created, but it doesn't
+ mean that the memory will actually be unmapped from the
+ device as other references to the mapping obtained via
+ DevmemAcquireDevVirtAddr could still be active.
+*/
+PVRSRV_ERROR DevmemMapToDevice(DEVMEM_MEMDESC *psMemDesc,
+ DEVMEM_HEAP *psHeap,
+ IMG_DEV_VIRTADDR *psDevVirtAddr);
+
+/*
+ DevmemAcquireDevVirtAddr
+
+ Acquire the MemDesc's device virtual address.
+ This function _must_ be called after DevmemMapToDevice
+ and is expected to be used be functions which didn't allocate
+ the MemDesc but need to know it's address
+ */
+PVRSRV_ERROR DevmemAcquireDevVirtAddr(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEV_VIRTADDR *psDevVirtAddrRet);
+/*
+ * DevmemReleaseDevVirtAddr()
+ *
+ * give up the licence to use the device virtual address that was
+ * acquired by "Acquire" or "MapToDevice"
+ */
+extern IMG_VOID
+DevmemReleaseDevVirtAddr(DEVMEM_MEMDESC *psMemDesc);
+
+/*
+ * DevmemAcquireCpuVirtAddr()
+ *
+ * Acquires a license to use the cpu virtual address of this mapping.
+ * Note that the memory may not have been mapped into cpu virtual
+ * memory prior to this call. On first "acquire" the memory will be
+ * mapped in (if it wasn't statically mapped in) and on last put it
+ * _may_ become unmapped. Later calling "Acquire" again, _may_ cause
+ * the memory to be mapped at a different address.
+ */
+PVRSRV_ERROR DevmemAcquireCpuVirtAddr(DEVMEM_MEMDESC *psMemDesc,
+ IMG_VOID **ppvCpuVirtAddr);
+/*
+ * DevmemReleaseDevVirtAddr()
+ *
+ * give up the licence to use the cpu virtual address that was granted
+ * with the "Get" call.
+ */
+extern IMG_VOID
+DevmemReleaseCpuVirtAddr(DEVMEM_MEMDESC *psMemDesc);
+
+/*
+ * DevmemExport()
+ *
+ * Given a memory allocation allocated with DevmemAllocateExportable()
+ * create a "cookie" that can be passed intact by the caller's own choice
+ * of secure IPC to another process and used as the argument to "map"
+ * to map this memory into a heap in the target processes. N.B. This can
+ * also be used to map into multiple heaps in one process, though that's not
+ * the intention.
+ *
+ * Note, the caller must later call Unexport before freeing the
+ * memory.
+ */
+PVRSRV_ERROR DevmemExport(DEVMEM_MEMDESC *psMemDesc,
+ DEVMEM_EXPORTCOOKIE *psExportCookie);
+
+
+IMG_VOID DevmemUnexport(DEVMEM_MEMDESC *psMemDesc,
+ DEVMEM_EXPORTCOOKIE *psExportCookie);
+
+PVRSRV_ERROR
+DevmemImport(IMG_HANDLE hBridge,
+ DEVMEM_EXPORTCOOKIE *psCookie,
+ DEVMEM_FLAGS_T uiFlags,
+ DEVMEM_MEMDESC **ppsMemDescPtr);
+
+/*
+ * DevmemIsValidExportCookie()
+ * Check whether the Export Cookie contains a valid export */
+IMG_BOOL
+DevmemIsValidExportCookie(DEVMEM_EXPORTCOOKIE *psExportCookie);
+
+/*
+ * DevmemMakeServerExportClientExport()
+ *
+ * This is a "special case" function for making a server export cookie
+ * which went through the direct bridge into an export cookie that can
+ * be passed through the client bridge.
+ */
+PVRSRV_ERROR
+DevmemMakeServerExportClientExport(DEVMEM_BRIDGE_HANDLE hBridge,
+ DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie,
+ DEVMEM_EXPORTCOOKIE *psExportCookie);
+
+/*
+ * DevmemUnmakeServerExportClientExport()
+ *
+ * Free any resource associated with the Make operation
+ */
+PVRSRV_ERROR
+DevmemUnmakeServerExportClientExport(DEVMEM_BRIDGE_HANDLE hBridge,
+ DEVMEM_EXPORTCOOKIE *psExportCookie);
+
+/*
+ *
+ * The following set of functions is specific to the heap "blueprint"
+ * stuff, for automatic creation of heaps when a context is created
+ *
+ */
+
+
+/* Devmem_HeapConfigCount: returns the number of heap configs that
+ this device has. Note that there is no acquire/release semantics
+ required, as this data is guaranteed to be constant for the
+ lifetime of the device node */
+extern PVRSRV_ERROR
+DevmemHeapConfigCount(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 *puiNumHeapConfigsOut);
+
+/* Devmem_HeapCount: returns the number of heaps that a given heap
+ config on this device has. Note that there is no acquire/release
+ semantics required, as this data is guaranteed to be constant for
+ the lifetime of the device node */
+extern PVRSRV_ERROR
+DevmemHeapCount(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 *puiNumHeapsOut);
+/* Devmem_HeapConfigName: return the name of the given heap config.
+ The caller is to provide the storage for the returned string and
+ indicate the number of bytes (including null terminator) for such
+ string in the BufSz arg. Note that there is no acquire/release
+ semantics required, as this data is guaranteed to be constant for
+ the lifetime of the device node.
+ */
+extern PVRSRV_ERROR
+DevmemHeapConfigName(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_CHAR *pszConfigNameOut,
+ IMG_UINT32 uiConfigNameBufSz);
+
+/* Devmem_HeapDetails: fetches all the metadata that is recorded in
+ this heap "blueprint". Namely: heap name (caller to provide
+ storage, and indicate buffer size (including null terminator) in
+ BufSz arg), device virtual address and length, log2 of data page
+ size (will be one of 12, 14, 16, 18, 20, 21, at time of writing).
+ Note that there is no acquire/release semantics required, as this
+ data is guaranteed to be constant for the lifetime of the device
+ node. */
+extern PVRSRV_ERROR
+DevmemHeapDetails(DEVMEM_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ IMG_UINT32 uiHeapConfigIndex,
+ IMG_UINT32 uiHeapIndex,
+ IMG_CHAR *pszHeapNameOut,
+ IMG_UINT32 uiHeapNameBufSz,
+ IMG_DEV_VIRTADDR *psDevVAddrBaseOut,
+ IMG_DEVMEM_SIZE_T *puiHeapLengthOut,
+ IMG_UINT32 *puiLog2DataPageSize);
+
+/*
+ * Devmem_FindHeapByName()
+ *
+ * returns the heap handle for the named _automagic_ heap in this
+ * context. "automagic" heaps are those that are born with the
+ * context from a blueprint
+ */
+extern PVRSRV_ERROR
+DevmemFindHeapByName(const DEVMEM_CONTEXT *psCtx,
+ const IMG_CHAR *pszHeapName,
+ DEVMEM_HEAP **ppsHeapRet);
+
+/*
+ * DevmemGetHeapBaseDevVAddr()
+ *
+ * returns the device virtual address of the base of the heap.
+ */
+
+PVRSRV_ERROR
+DevmemGetHeapBaseDevVAddr(DEVMEM_HEAP *psHeap,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+
+
+extern PVRSRV_ERROR
+DevmemGetImportUID(DEVMEM_MEMDESC *psMemDesc,
+ IMG_UINT64 *pui64UID);
+
+PVRSRV_ERROR
+DevmemGetReservation(DEVMEM_MEMDESC *psMemDesc,
+ IMG_HANDLE *hReservation);
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetPMRData(DEVMEM_MEMDESC *psMemDesc,
+ IMG_HANDLE *hPMR,
+ IMG_DEVMEM_OFFSET_T *puiPMROffset);
+
+IMG_INTERNAL PVRSRV_ERROR
+DevmemGetFlags(DEVMEM_MEMDESC *psMemDesc,
+ DEVMEM_FLAGS_T *puiFlags);
+
+PVRSRV_ERROR
+DevmemLocalImport(IMG_HANDLE hBridge,
+ IMG_HANDLE hExtHandle,
+ DEVMEM_FLAGS_T uiFlags,
+ DEVMEM_MEMDESC **ppsMemDescPtr,
+ IMG_DEVMEM_SIZE_T *puiSizePtr);
+
+#endif /* #ifndef SRVCLIENT_DEVICEMEM_CLIENT_H */
diff --git a/drivers/gpu/rogue/services/shared/include/devicemem_mmap.h b/drivers/gpu/rogue/services/shared/include/devicemem_mmap.h
new file mode 100644
index 000000000000..acfc96febf87
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/devicemem_mmap.h
@@ -0,0 +1,102 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS abstraction for the mmap2 interface for mapping PMRs into
+ User Mode memory
+@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 _DEVICEMEM_MMAP_H_
+#define _DEVICEMEM_MMAP_H_
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+/*
+ *
+ * OSMMapPMR
+ *
+ * Causes this PMR to be mapped into CPU memory that the user process
+ * may access.
+ *
+ * Whether the memory is mapped readonly, readwrite, or not at all, is
+ * dependent on the PMR itself.
+ *
+ * The PMR handle is opaque to the user, and lower levels of this
+ * stack ensure that the handle is private to this process, such that
+ * this API cannot be abused to gain access to other people's PMRs.
+ *
+ * The OS implementation of this function should return the virtual
+ * address and length for the User to use. The "PrivData" is to be
+ * stored opaquely by the caller (N.B. he should make no assumptions,
+ * in particular, IMG_NULL is a valid handle) and given back to the
+ * call to OSMunmapPMR.
+ *
+ * The OS implementation is free to use the PrivData handle for any
+ * purpose it sees fit.
+ */
+
+extern PVRSRV_ERROR
+OSMMapPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_DEVMEM_SIZE_T uiPMRLength,
+ IMG_HANDLE *phOSMMapPrivDataOut,
+ IMG_VOID **ppvMappingAddressOut,
+ IMG_SIZE_T *puiMappingLengthOut);
+
+/*
+ *
+ * OSMUnmapPMR
+ *
+ * The reverse of OSMMapPMR
+ *
+ * The caller is required to pass the PMR handle back in along with
+ * the same 3-tuple of information as was returned by the call to
+ * OSMMapPMR
+ *
+ */
+
+extern IMG_VOID
+OSMUnmapPMR(IMG_HANDLE hBridge,
+ IMG_HANDLE hPMR,
+ IMG_HANDLE hOSMMapPrivData,
+ IMG_VOID *pvMappingAddress,
+ IMG_SIZE_T uiMappingLength);
+
+#endif
diff --git a/drivers/gpu/rogue/services/shared/include/devicemem_pdump.h b/drivers/gpu/rogue/services/shared/include/devicemem_pdump.h
new file mode 100644
index 000000000000..b86602ac399f
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/devicemem_pdump.h
@@ -0,0 +1,343 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management PDump internal
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Services internal interface to PDump device memory management
+ functions that are shared between client and server code.
+@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 _DEVICEMEM_PDUMP_H_
+#define _DEVICEMEM_PDUMP_H_
+
+#include "devicemem.h"
+#include "pdumpdefs.h"
+#include "pdump.h"
+
+#if defined(PDUMP)
+/*
+ * DevmemPDumpMem()
+ *
+ * takes a memory descriptor, offset, and size, and takes the current
+ * contents of the memory at that location and writes it to the prm
+ * pdump file, and emits a pdump LDB to load the data from that file.
+ * The intention here is that the contents of the simulated buffer
+ * upon pdump playback will be made to be the same as they are when
+ * this command is run, enabling pdump of cases where the memory has
+ * been modified externally, i.e. by the host cpu or by a third
+ * party.
+ */
+extern IMG_VOID
+DevmemPDumpLoadMem(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+/*
+ * DevmemPDumpZeroMem()
+ *
+ * as DevmemPDumpMem() but the PDump allocation will be populated with zeros from
+ * the zero page in the parameter stream
+ */
+extern IMG_VOID
+DevmemPDumpLoadZeroMem(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+/*
+ * DevmemPDumpMemValue()
+ *
+ * As above but dumps the value at a dword-aligned address in plain
+ * text to the pdump script2 file. Useful for patching a buffer at
+ * pdump playback by simply editing the script output file.
+ *
+ * (The same functionality can be achieved by the above function but
+ * the binary PARAM file must be patched in that case.)
+ */
+IMG_INTERNAL IMG_VOID
+DevmemPDumpLoadMemValue32(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+/*
+ * DevmemPDumpMemValue64()
+ *
+ * As above but dumps the 64bit-value at a dword-aligned address in plain
+ * text to the pdump script2 file. Useful for patching a buffer at
+ * pdump playback by simply editing the script output file.
+ *
+ * (The same functionality can be achieved by the above function but
+ * the binary PARAM file must be patched in that case.)
+ */
+IMG_INTERNAL IMG_VOID
+DevmemPDumpLoadMemValue64(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT64 ui64Value,
+ PDUMP_FLAGS_T uiPDumpFlags);
+
+/*
+ * DevmemPDumpPageCatBaseToSAddr()
+ *
+ * Returns the symbolic address of a piece of memory represented
+ * by an offset into the mem descriptor.
+ */
+extern PVRSRV_ERROR
+DevmemPDumpPageCatBaseToSAddr(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T *puiMemOffset,
+ IMG_CHAR *pszName,
+ IMG_UINT32 ui32Size);
+
+/*
+ * DevmemPDumpSaveToFile()
+ *
+ * emits a pdump SAB to cause the current contents of the memory to be
+ * written to the given file during playback
+ */
+extern IMG_VOID
+DevmemPDumpSaveToFile(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename);
+
+/*
+ * DevmemPDumpSaveToFileVirtual()
+ *
+ * emits a pdump SAB, just like DevmemPDumpSaveToFile(), but uses the
+ * virtual address and device MMU context to cause the pdump player to
+ * traverse the MMU page tables itself.
+ */
+extern IMG_VOID
+DevmemPDumpSaveToFileVirtual(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32PdumpFlags);
+
+
+/*
+ *
+ * Devmem_PDumpDevmemPol32()
+ *
+ * writes a PDump 'POL' command to wait for a masked 32-bit memory
+ * location to become the specified value
+ */
+extern PVRSRV_ERROR
+DevmemPDumpDevmemPol32(const DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T ui32PDumpFlags);
+
+/*
+ * DevmemPDumpCBP()
+ *
+ * Polls for space in circular buffer. Reads the read offset
+ * from memory and waits until there is enough space to write
+ * the packet.
+ *
+ * hMemDesc - MemDesc which contains the read offset
+ * uiReadOffset - Offset into MemDesc to the read offset
+ * uiWriteOffset - Current write offset
+ * uiPacketSize - Size of packet to write
+ * uiBufferSize - Size of circular buffer
+ */
+extern PVRSRV_ERROR
+DevmemPDumpCBP(const DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize);
+
+#else /* PDUMP */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(DevmemPDumpLoadMem)
+#endif
+static INLINE IMG_VOID
+DevmemPDumpLoadMem(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemDesc);
+ PVR_UNREFERENCED_PARAMETER(uiOffset);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
+ PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(DevmemPDumpLoadMemValue32)
+#endif
+static INLINE IMG_VOID
+DevmemPDumpLoadMemValue32(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemDesc);
+ PVR_UNREFERENCED_PARAMETER(uiOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(DevmemPDumpLoadMemValue64)
+#endif
+static INLINE IMG_VOID
+DevmemPDumpLoadMemValue64(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT64 ui64Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemDesc);
+ PVR_UNREFERENCED_PARAMETER(uiOffset);
+ PVR_UNREFERENCED_PARAMETER(ui64Value);
+ PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(DevmemPDumpLoadMemValue)
+#endif
+static INLINE IMG_VOID
+DevmemPDumpLoadMemValue(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ PDUMP_FLAGS_T uiPDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemDesc);
+ PVR_UNREFERENCED_PARAMETER(uiOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(DevmemPDumpPageCatBaseToSAddr)
+#endif
+static INLINE PVRSRV_ERROR
+DevmemPDumpPageCatBaseToSAddr(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T *puiMemOffset,
+ IMG_CHAR *pszName,
+ IMG_UINT32 ui32Size)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemDesc);
+ PVR_UNREFERENCED_PARAMETER(puiMemOffset);
+ PVR_UNREFERENCED_PARAMETER(pszName);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(DevmemPDumpSaveToFile)
+#endif
+static INLINE IMG_VOID
+DevmemPDumpSaveToFile(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemDesc);
+ PVR_UNREFERENCED_PARAMETER(uiOffset);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
+ PVR_UNREFERENCED_PARAMETER(pszFilename);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(DevmemPDumpSaveToFileVirtual)
+#endif
+static INLINE IMG_VOID
+DevmemPDumpSaveToFileVirtual(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_DEVMEM_SIZE_T uiSize,
+ const IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32PdumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemDesc);
+ PVR_UNREFERENCED_PARAMETER(uiOffset);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
+ PVR_UNREFERENCED_PARAMETER(pszFilename);
+ PVR_UNREFERENCED_PARAMETER(ui32FileOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32PdumpFlags);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(DevmemPDumpDevmemPol32)
+#endif
+static INLINE PVRSRV_ERROR
+DevmemPDumpDevmemPol32(const DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ PDUMP_FLAGS_T ui32PDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemDesc);
+ PVR_UNREFERENCED_PARAMETER(uiOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ PVR_UNREFERENCED_PARAMETER(ui32Mask);
+ PVR_UNREFERENCED_PARAMETER(eOperator);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(DevmemPDumpCBP)
+#endif
+static INLINE PVRSRV_ERROR
+DevmemPDumpCBP(const DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiReadOffset,
+ IMG_DEVMEM_OFFSET_T uiWriteOffset,
+ IMG_DEVMEM_SIZE_T uiPacketSize,
+ IMG_DEVMEM_SIZE_T uiBufferSize)
+{
+ PVR_UNREFERENCED_PARAMETER(psMemDesc);
+ PVR_UNREFERENCED_PARAMETER(uiReadOffset);
+ PVR_UNREFERENCED_PARAMETER(uiWriteOffset);
+ PVR_UNREFERENCED_PARAMETER(uiPacketSize);
+ PVR_UNREFERENCED_PARAMETER(uiBufferSize);
+
+ return PVRSRV_OK;
+}
+#endif /* PDUMP */
+#endif /* _DEVICEMEM_PDUMP_H_ */
diff --git a/drivers/gpu/rogue/services/shared/include/devicemem_utils.h b/drivers/gpu/rogue/services/shared/include/devicemem_utils.h
new file mode 100644
index 000000000000..92b8985ccc29
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/devicemem_utils.h
@@ -0,0 +1,378 @@
+/*************************************************************************/ /*!
+@File
+@Title Device Memory Management internal utility functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Utility functions used internally by device memory management
+ code.
+@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 _DEVICEMEM_UTILS_H_
+#define _DEVICEMEM_UTILS_H_
+
+#include "devicemem.h"
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pvr_debug.h"
+#include "allocmem.h"
+#include "ra.h"
+#include "osfunc.h"
+#include "lock.h"
+#include "devicemem_mmap.h"
+#include "devicemem_utils.h"
+
+#define DEVMEM_HEAPNAME_MAXLENGTH 160
+
+
+#if defined(DEVMEM_DEBUG) && defined(REFCOUNT_DEBUG)
+#define DEVMEM_REFCOUNT_PRINT(fmt, ...) PVRSRVDebugPrintf(PVR_DBG_ERROR, __FILE__, __LINE__, fmt, __VA_ARGS__)
+#else
+#define DEVMEM_REFCOUNT_PRINT(fmt, ...)
+#endif
+
+
+/* If we need a "hMapping" but we don't have a server-side mapping, we
+ poison the entry with this value so that it's easily recognised in
+ the debugger. Note that this is potentially a valid handle, but
+ then so is IMG_NULL, which is no better, indeed worse, as it's not
+ obvious in the debugger. The value doesn't matter. We _never_ use
+ it (and because it's valid, we never assert it isn't this) but it's
+ nice to have a value in the source code that we can grep for when
+ things go wrong. */
+#define LACK_OF_MAPPING_POISON ((IMG_HANDLE)0x6116dead)
+#define LACK_OF_RESERVATION_POISON ((IMG_HANDLE)0x7117dead)
+
+struct _DEVMEM_CONTEXT_ {
+ /* Cookie of the device on which this memory context resides */
+ IMG_HANDLE hDeviceNode;
+
+ /* Number of heaps that have been created in this context
+ (regardless of whether they have allocations) */
+ IMG_UINT32 uiNumHeaps;
+
+ /* Sometimes we need to talk to Kernel Services. In order to do
+ so, we need the connection handle */
+ DEVMEM_BRIDGE_HANDLE hBridge;
+
+ /*
+ Each "DEVMEM_CONTEXT" has a counterpart in the server,
+ which is responsible for handling the mapping into device MMU.
+ We have a handle to that here.
+ */
+ IMG_HANDLE hDevMemServerContext;
+
+ /* Number of automagically created heaps in this context,
+ i.e. those that are born at context creation time from the
+ chosen "heap config" or "blueprint" */
+ IMG_UINT32 uiAutoHeapCount;
+
+ /* pointer to array of such heaps */
+ struct _DEVMEM_HEAP_ **ppsAutoHeapArray;
+
+ /* Private data handle for device specific data */
+ IMG_HANDLE hPrivData;
+};
+
+struct _DEVMEM_HEAP_ {
+ /* Name of heap - for debug and lookup purposes. */
+ IMG_CHAR *pszName;
+
+ /* Number of live imports in the heap */
+ IMG_UINT32 uiImportCount;
+
+ /*
+ * Base address of heap, required by clients due to some requesters
+ * not being full range
+ */
+ IMG_DEV_VIRTADDR sBaseAddress;
+
+ /* This RA is for managing sub-allocations in virtual space. Two
+ more RA's will be used under the Hood for managing the coarser
+ allocation of virtual space from the heap, and also for
+ managing the physical backing storage. */
+ RA_ARENA *psSubAllocRA;
+ IMG_CHAR *pszSubAllocRAName;
+ /*
+ This RA is for the coarse allocation of virtual space from the heap
+ */
+ RA_ARENA *psQuantizedVMRA;
+ IMG_CHAR *pszQuantizedVMRAName;
+
+ /* We also need to store a copy of the quantum size in order to
+ feed this down to the server */
+ IMG_UINT32 uiLog2Quantum;
+
+ /* The parent memory context for this heap */
+ struct _DEVMEM_CONTEXT_ *psCtx;
+
+ POS_LOCK hLock; /*!< Lock to protect this structure */
+
+ /*
+ Each "DEVMEM_HEAP" has a counterpart in the server,
+ which is responsible for handling the mapping into device MMU.
+ We have a handle to that here.
+ */
+ IMG_HANDLE hDevMemServerHeap;
+};
+
+
+typedef struct _DEVMEM_DEVICE_IMPORT_ {
+ DEVMEM_HEAP *psHeap; /*!< Heap this import is bound to */
+ IMG_DEV_VIRTADDR sDevVAddr; /*!< Device virtual address of the import */
+ IMG_UINT32 ui32RefCount; /*!< Refcount of the device virtual address */
+ IMG_HANDLE hReservation; /*!< Device memory reservation handle */
+ IMG_HANDLE hMapping; /*!< Device mapping handle */
+ IMG_BOOL bMapped; /*!< This is import mapped? */
+ POS_LOCK hLock; /*!< Lock to protect the device import */
+} DEVMEM_DEVICE_IMPORT;
+
+typedef struct _DEVMEM_CPU_IMPORT_ {
+ IMG_PVOID pvCPUVAddr; /*!< CPU virtual address of the import */
+ IMG_UINT32 ui32RefCount; /*!< Refcount of the CPU virtual address */
+ IMG_HANDLE hOSMMapData; /*!< CPU mapping handle */
+ POS_LOCK hLock; /*!< Lock to protect the CPU import */
+#if !defined(__KERNEL__) && defined(SUPPORT_ION)
+ int iDmaBufFd; /*!< >=0 if this was an imported ion allocation */
+#endif
+} DEVMEM_CPU_IMPORT;
+
+typedef struct _DEVMEM_IMPORT_ {
+ DEVMEM_BRIDGE_HANDLE hBridge; /*!< Bridge connection for the server */
+ IMG_DEVMEM_ALIGN_T uiAlign; /*!< Alignment requirement */
+ DEVMEM_SIZE_T uiSize; /*!< Size of import */
+ IMG_UINT32 ui32RefCount; /*!< Refcount for this import */
+ IMG_BOOL bExportable; /*!< Is this import exportable? */
+ IMG_HANDLE hPMR; /*!< Handle to the PMR */
+ DEVMEM_FLAGS_T uiFlags; /*!< Flags for this import */
+ POS_LOCK hLock; /*!< Lock to protect the import */
+
+ DEVMEM_DEVICE_IMPORT sDeviceImport; /*!< Device specifics of the import */
+ DEVMEM_CPU_IMPORT sCPUImport; /*!< CPU specifics of the import */
+} DEVMEM_IMPORT;
+
+typedef struct _DEVMEM_DEVICE_MEMDESC_ {
+ IMG_DEV_VIRTADDR sDevVAddr; /*!< Device virtual address of the allocation */
+ IMG_UINT32 ui32RefCount; /*!< Refcount of the device virtual address */
+ POS_LOCK hLock; /*!< Lock to protect device memdesc */
+} DEVMEM_DEVICE_MEMDESC;
+
+typedef struct _DEVMEM_CPU_MEMDESC_ {
+ IMG_PVOID pvCPUVAddr; /*!< CPU virtual address of the import */
+ IMG_UINT32 ui32RefCount; /*!< Refcount of the device CPU address */
+ POS_LOCK hLock; /*!< Lock to protect CPU memdesc */
+} DEVMEM_CPU_MEMDESC;
+
+struct _DEVMEM_MEMDESC_ {
+ DEVMEM_IMPORT *psImport; /*!< Import this memdesc is on */
+ IMG_DEVMEM_OFFSET_T uiOffset; /*!< Offset into import where our allocation starts */
+ IMG_UINT32 ui32RefCount; /*!< Refcount of the memdesc */
+ POS_LOCK hLock; /*!< Lock to protect memdesc */
+
+ DEVMEM_DEVICE_MEMDESC sDeviceMemDesc; /*!< Device specifics of the memdesc */
+ DEVMEM_CPU_MEMDESC sCPUMemDesc; /*!< CPU specifics of the memdesc */
+
+#if defined(PVR_RI_DEBUG)
+ IMG_HANDLE hRIHandle; /*!< Handle to RI information */
+#endif
+};
+
+/******************************************************************************
+@Function _DevmemValidateParams
+@Description Check if flags are conflicting and if align is a size multiple.
+
+@Input uiSize Size of the import.
+@Input uiAlign Alignment of the import.
+@Input uiFlags Flags for the import.
+@return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR _DevmemValidateParams(IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ DEVMEM_FLAGS_T uiFlags);
+
+/******************************************************************************
+@Function _DevmemImportStructAlloc
+@Description Allocates memory for an import struct. Does not allocate a PMR!
+ Create locks for CPU and Devmem mappings.
+
+@Input hBridge Bridge to use for calls from the import.
+@Input bExportable Is this import is exportable?
+@Input ppsImport The import to allocate.
+@return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR _DevmemImportStructAlloc(IMG_HANDLE hBridge,
+ IMG_BOOL bExportable,
+ DEVMEM_IMPORT **ppsImport);
+
+/******************************************************************************
+@Function _DevmemImportStructInit
+@Description Initialises the import struct with the given parameters.
+ Set it's refcount to 1!
+
+@Input psImport The import to initialise.
+@Input uiSize Size of the import.
+@Input uiAlign Alignment of allocations in the import.
+@Input uiMapFlags
+@Input hPMR Reference to the PMR of this import struct.
+******************************************************************************/
+IMG_VOID _DevmemImportStructInit(DEVMEM_IMPORT *psImport,
+ IMG_DEVMEM_SIZE_T uiSize,
+ IMG_DEVMEM_ALIGN_T uiAlign,
+ PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
+ IMG_HANDLE hPMR);
+
+/******************************************************************************
+@Function _DevmemImportStructDevMap
+@Description NEVER call after the last _DevmemMemDescRelease()
+ Maps the PMR referenced by the import struct to the device's
+ virtual address space.
+ Does nothing but increase the cpu mapping refcount if the
+ import struct was already mapped.
+
+@Input psHeap The heap to map to.
+@Input bMap Caller can choose if the import should be really
+ mapped in the page tables or if just a virtual range
+ should be reserved and the refcounts increased.
+@Input psImport The import we want to map.
+@return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR _DevmemImportStructDevMap(DEVMEM_HEAP *psHeap,
+ IMG_BOOL bMap,
+ DEVMEM_IMPORT *psImport);
+
+/******************************************************************************
+@Function _DevmemImportStructDevUnmap
+@Description Unmaps the PMR referenced by the import struct from the
+ device's virtual address space.
+ If this was not the last remaining CPU mapping on the import
+ struct only the cpu mapping refcount is decreased.
+******************************************************************************/
+IMG_VOID _DevmemImportStructDevUnmap(DEVMEM_IMPORT *psImport);
+
+/******************************************************************************
+@Function _DevmemImportStructCPUMap
+@Description NEVER call after the last _DevmemMemDescRelease()
+ Maps the PMR referenced by the import struct to the CPU's
+ virtual address space.
+ Does nothing but increase the cpu mapping refcount if the
+ import struct was already mapped.
+@return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR _DevmemImportStructCPUMap(DEVMEM_IMPORT *psImport);
+
+/******************************************************************************
+@Function _DevmemImportStructCPUUnmap
+@Description Unmaps the PMR referenced by the import struct from the CPU's
+ virtual address space.
+ If this was not the last remaining CPU mapping on the import
+ struct only the cpu mapping refcount is decreased.
+******************************************************************************/
+IMG_VOID _DevmemImportStructCPUUnmap(DEVMEM_IMPORT *psImport);
+
+
+/******************************************************************************
+@Function _DevmemImportStructAcquire
+@Description Acquire an import struct by increasing it's refcount.
+******************************************************************************/
+IMG_VOID _DevmemImportStructAcquire(DEVMEM_IMPORT *psImport);
+
+/******************************************************************************
+@Function _DevmemImportStructRelease
+@Description Reduces the refcount of the import struct.
+ Destroys the import in the case it was the last reference.
+ Destroys underlying PMR if this import was the last reference
+ to it.
+@return A boolean to signal if the import was destroyed. True = yes.
+******************************************************************************/
+IMG_VOID _DevmemImportStructRelease(DEVMEM_IMPORT *psImport);
+
+/******************************************************************************
+@Function _DevmemImportDiscard
+@Description Discard a created, but unitilised import structure.
+ This must only be called before _DevmemImportStructInit
+ after which _DevmemImportStructRelease must be used to
+ "free" the import structure.
+******************************************************************************/
+IMG_VOID _DevmemImportDiscard(DEVMEM_IMPORT *psImport);
+
+/******************************************************************************
+@Function _DevmemMemDescAlloc
+@Description Allocates a MemDesc and create it's various locks.
+ Zero the allocated memory.
+@return PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR _DevmemMemDescAlloc(DEVMEM_MEMDESC **ppsMemDesc);
+
+/******************************************************************************
+@Function _DevmemMemDescInit
+@Description Sets the given offset and import struct fields in the MemDesc.
+ Initialises refcount to 1 and other values to 0.
+
+@Input psMemDesc MemDesc to initialise.
+@Input uiOffset Offset in the import structure.
+@Input psImport Import the MemDesc is on.
+******************************************************************************/
+IMG_VOID _DevmemMemDescInit(DEVMEM_MEMDESC *psMemDesc,
+ IMG_DEVMEM_OFFSET_T uiOffset,
+ DEVMEM_IMPORT *psImport);
+
+/******************************************************************************
+@Function _DevmemMemDescAcquire
+@Description Acquires the MemDesc by increasing it's refcount.
+******************************************************************************/
+IMG_VOID _DevmemMemDescAcquire(DEVMEM_MEMDESC *psMemDesc);
+
+/******************************************************************************
+@Function _DevmemMemDescRelease
+@Description Releases the MemDesc by reducing it's refcount.
+ Destroy the MemDesc if it's recount is 0.
+ Destroy the import struct the MemDesc is on if that was the
+ last MemDesc on the import, probably following the destruction
+ of the underlying PMR.
+******************************************************************************/
+IMG_VOID _DevmemMemDescRelease(DEVMEM_MEMDESC *psMemDesc);
+
+/******************************************************************************
+@Function _DevmemMemDescDiscard
+@Description Discard a created, but unitilised MemDesc structure.
+ This must only be called before _DevmemMemDescInit
+ after which _DevmemMemDescRelease must be used to
+ "free" the MemDesc structure.
+******************************************************************************/
+IMG_VOID _DevmemMemDescDiscard(DEVMEM_MEMDESC *psMemDesc);
+
+#endif /* _DEVICEMEM_UTILS_H_ */
diff --git a/drivers/gpu/rogue/services/shared/include/dllist.h b/drivers/gpu/rogue/services/shared/include/dllist.h
new file mode 100644
index 000000000000..37e664f4bce5
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/dllist.h
@@ -0,0 +1,292 @@
+/*************************************************************************/ /*!
+@File
+@Title Double linked list header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Double linked list interface
+@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 _DLLIST_
+#define _DLLIST_
+
+#include "img_types.h"
+
+/*!
+ Pointer to a linked list node
+*/
+typedef struct _DLLIST_NODE_ *PDLLIST_NODE;
+
+
+/*!
+ Node in a linked list
+*/
+/*
+ * Note: the following structure's size is architecture-dependent and
+ * clients may need to create a mirror the structure definition if it needs
+ * to be used in a structure shared between host and device. Consider such
+ * clients if any changes are made to this structure.
+ */
+typedef struct _DLLIST_NODE_
+{
+ struct _DLLIST_NODE_ *psPrevNode;
+ struct _DLLIST_NODE_ *psNextNode;
+} DLLIST_NODE;
+
+
+/*!
+ Static initialiser
+*/
+#define DECLARE_DLLIST(n) \
+DLLIST_NODE n = {&n, &n}
+
+
+/*************************************************************************/ /*!
+@Function dllist_init
+
+@Description Initialize a new double linked list
+
+@Input psListHead List head Node
+
+*/
+/*****************************************************************************/
+static INLINE
+IMG_VOID dllist_init(PDLLIST_NODE psListHead)
+{
+ psListHead->psPrevNode = psListHead;
+ psListHead->psNextNode = psListHead;
+}
+
+
+/*************************************************************************/ /*!
+@Function dllist_is_empty
+
+@Description Returns whether the list is empty
+
+@Input psListHead List head Node
+
+*/
+/*****************************************************************************/
+static INLINE
+IMG_BOOL dllist_is_empty(PDLLIST_NODE psListHead)
+{
+ return ((psListHead->psPrevNode == psListHead)
+ && (psListHead->psNextNode == psListHead));
+}
+
+
+/*************************************************************************/ /*!
+@Function dllist_add_to_head
+
+@Description Add psNewNode to head of list psListHead
+
+@Input psListHead Head Node
+@Input psNewNode New Node
+
+*/
+/*****************************************************************************/
+static INLINE
+IMG_VOID dllist_add_to_head(PDLLIST_NODE psListHead, PDLLIST_NODE psNewNode)
+{
+ PDLLIST_NODE psTmp;
+
+ psTmp = psListHead->psNextNode;
+
+ psListHead->psNextNode = psNewNode;
+ psNewNode->psNextNode = psTmp;
+
+ psTmp->psPrevNode = psNewNode;
+ psNewNode->psPrevNode = psListHead;
+}
+
+
+/*************************************************************************/ /*!
+@Function dllist_add_to_tail
+
+@Description Add psNewNode to tail of list psListHead
+
+@Input psListHead Head Node
+@Input psNewNode New Node
+
+*/
+/*****************************************************************************/
+static INLINE
+IMG_VOID dllist_add_to_tail(PDLLIST_NODE psListHead, PDLLIST_NODE psNewNode)
+{
+ PDLLIST_NODE psTmp;
+
+ psTmp = psListHead->psPrevNode;
+
+ psListHead->psPrevNode = psNewNode;
+ psNewNode->psPrevNode = psTmp;
+
+ psTmp->psNextNode = psNewNode;
+ psNewNode->psNextNode = psListHead;
+}
+
+
+/*************************************************************************/ /*!
+@Function dllist_node_is_in_list
+
+@Description Returns IMG_TRUE if psNode is in a list
+
+@Input psNode List node
+
+*/
+/*****************************************************************************/
+static INLINE
+IMG_BOOL dllist_node_is_in_list(PDLLIST_NODE psNode)
+{
+ return (psNode->psNextNode != 0);
+}
+
+
+/*************************************************************************/ /*!
+@Function dllist_get_next_node
+
+@Description Returns the list node after psListHead or IMG_NULL psListHead
+ is the only element in the list.
+
+@Input psListHead List node to start the operation
+
+*/
+/*****************************************************************************/
+static INLINE
+PDLLIST_NODE dllist_get_next_node(PDLLIST_NODE psListHead)
+{
+ if (psListHead->psNextNode == psListHead)
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psListHead->psNextNode;
+ }
+}
+
+
+/*************************************************************************/ /*!
+@Function dllist_remove_next_node
+
+@Description Remove the list node after psListHead
+
+@Input psListHead List node to start the operation
+
+*/
+/*****************************************************************************/
+static INLINE
+IMG_VOID dllist_remove_next_node(PDLLIST_NODE psListHead)
+{
+ PDLLIST_NODE psTmp;
+
+ psTmp = psListHead->psNextNode;
+
+ psListHead->psNextNode = psTmp->psNextNode;
+ psTmp->psNextNode->psPrevNode = psListHead;
+}
+
+
+/*************************************************************************/ /*!
+@Function dllist_move_next_node_to_tail
+
+@Description Move the node after psListHead to the tail of the list
+
+@Input psListHead List node to start the operation
+
+*/
+/*****************************************************************************/
+static INLINE
+IMG_VOID dllist_move_next_node_to_tail(PDLLIST_NODE psListHead)
+{
+ PDLLIST_NODE psTmp;
+
+ psTmp = dllist_get_next_node(psListHead);
+ if (psTmp != IMG_NULL)
+ {
+ dllist_remove_next_node(psListHead);
+ dllist_add_to_tail(psListHead, psTmp);
+ }
+}
+
+
+/*************************************************************************/ /*!
+@Function dllist_remove_node
+
+@Description Removes psListNode from the list where it currently belongs
+
+@Input psListNode List node to be removed
+
+*/
+/*****************************************************************************/
+static INLINE
+IMG_VOID dllist_remove_node(PDLLIST_NODE psListNode)
+{
+ psListNode->psNextNode->psPrevNode = psListNode->psPrevNode;
+ psListNode->psPrevNode->psNextNode = psListNode->psNextNode;
+
+ /* Clear the node to show it's not on a list */
+ psListNode->psPrevNode = 0;
+ psListNode->psNextNode = 0;
+}
+
+
+/*!
+ Callback function called on each element of the list
+*/
+typedef IMG_BOOL (*PFN_NODE_CALLBACK)(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData);
+
+
+/*************************************************************************/ /*!
+@Function dllist_foreach_node
+
+@Description Walk through all the nodes on the list until the
+ end or a callback returns FALSE
+
+@Input psListHead List node to start the operation
+@Input pfnCallBack PFN_NODE_CALLBACK function called on each element
+@Input pvCallbackData Data passed to pfnCallBack alongside the current Node
+
+*/
+/*****************************************************************************/
+IMG_INTERNAL
+IMG_VOID dllist_foreach_node(PDLLIST_NODE psListHead,
+ PFN_NODE_CALLBACK pfnCallBack,
+ IMG_PVOID pvCallbackData);
+
+
+#endif /* _DLLIST_ */
+
diff --git a/drivers/gpu/rogue/services/shared/include/sync.h b/drivers/gpu/rogue/services/shared/include/sync.h
new file mode 100644
index 000000000000..670b77ea0301
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/sync.h
@@ -0,0 +1,373 @@
+/*************************************************************************/ /*!
+@File
+@Title Synchronisation interface header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines the client side interface for 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.
+*/ /**************************************************************************/
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "sync_external.h"
+#include "pdumpdefs.h"
+#include "dllist.h"
+#include "pvr_debug.h"
+
+#ifndef _SYNC_
+#define _SYNC_
+
+#if defined(KERNEL) && defined(ANDROID)
+#define __pvrsrv_defined_struct_enum__
+#include <services_kernel_client.h>
+#endif
+
+/*************************************************************************/ /*!
+@Function SyncPrimContextCreate
+
+@Description Create a new synchronisation context
+
+@Input hBridge Bridge handle
+
+@Input hDeviceNode Device node handle
+
+@Output hSyncPrimContext Handle to the created synchronisation
+ primitive context
+
+@Return PVRSRV_OK if the synchronisation primitive context was
+ successfully created
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+SyncPrimContextCreate(SYNC_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ PSYNC_PRIM_CONTEXT *hSyncPrimContext);
+
+/*************************************************************************/ /*!
+@Function SyncPrimContextDestroy
+
+@Description Destroy a synchronisation context
+
+@Input hSyncPrimContext Handle to the synchronisation
+ primitive context to destroy
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID
+SyncPrimContextDestroy(PSYNC_PRIM_CONTEXT hSyncPrimContext);
+
+/*************************************************************************/ /*!
+@Function SyncPrimAlloc
+
+@Description Allocate a new synchronisation primitive on the specified
+ synchronisation context
+
+@Input hSyncPrimContext Handle to the synchronisation
+ primitive context
+
+@Output ppsSync Created synchronisation primitive
+
+@Return PVRSRV_OK if the synchronisation primitive was
+ successfully created
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+SyncPrimAlloc(PSYNC_PRIM_CONTEXT hSyncPrimContext,
+ PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
+ const IMG_CHAR *pszClassName);
+
+/*************************************************************************/ /*!
+@Function SyncPrimFree
+
+@Description Free a synchronisation primitive
+
+@Input psSync The synchronisation primitive to free
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID
+SyncPrimFree(PVRSRV_CLIENT_SYNC_PRIM *psSync);
+
+/*************************************************************************/ /*!
+@Function SyncPrimSet
+
+@Description Set the synchronisation primitive to a value
+
+@Input psSync The synchronisation primitive to set
+
+@Input ui32Value Value to set it to
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID
+SyncPrimSet(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value);
+
+#if defined(NO_HARDWARE)
+
+/*************************************************************************/ /*!
+@Function SyncPrimNoHwUpdate
+
+@Description Updates the synchronisation primitive value (in NoHardware drivers)
+
+@Input psSync The synchronisation primitive to update
+
+@Input ui32Value Value to update it to
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID
+SyncPrimNoHwUpdate(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value);
+#endif
+
+PVRSRV_ERROR
+SyncPrimServerAlloc(SYNC_BRIDGE_HANDLE hBridge,
+ IMG_HANDLE hDeviceNode,
+ PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
+ const IMG_CHAR *pszClassName
+ PVR_DBG_FILELINE_PARAM);
+
+PVRSRV_ERROR
+SyncPrimServerGetStatus(IMG_UINT32 ui32SyncCount,
+ PVRSRV_CLIENT_SYNC_PRIM **papsSync,
+ IMG_UINT32 *pui32UID,
+ IMG_UINT32 *pui32FWAddr,
+ IMG_UINT32 *pui32CurrentOp,
+ IMG_UINT32 *pui32NextOp);
+
+PVRSRV_ERROR
+SyncPrimServerQueueOp(PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOp);
+
+IMG_BOOL
+SyncPrimIsServerSync(PVRSRV_CLIENT_SYNC_PRIM *psSync);
+
+IMG_HANDLE
+SyncPrimGetServerHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync);
+
+
+
+PVRSRV_ERROR
+SyncPrimOpCreate(IMG_UINT32 ui32SyncCount,
+ PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim,
+ PSYNC_OP_COOKIE *ppsCookie);
+
+PVRSRV_ERROR
+SyncPrimOpTake(PSYNC_OP_COOKIE psCookie,
+ IMG_UINT32 ui32SyncCount,
+ PVRSRV_CLIENT_SYNC_PRIM_OP *pasSyncOp);
+
+PVRSRV_ERROR
+SyncPrimOpReady(PSYNC_OP_COOKIE psCookie,
+ IMG_BOOL *pbReady);
+
+PVRSRV_ERROR
+SyncPrimOpComplete(PSYNC_OP_COOKIE psCookie);
+
+IMG_VOID
+SyncPrimOpDestroy(PSYNC_OP_COOKIE psCookie);
+
+PVRSRV_ERROR
+SyncPrimOpResolve(PSYNC_OP_COOKIE psCookie,
+ IMG_UINT32 *pui32SyncCount,
+ PVRSRV_CLIENT_SYNC_PRIM_OP **ppsSyncOp);
+
+PVRSRV_ERROR
+SyncPrimDumpSyncs(IMG_UINT32 ui32SyncCount, PVRSRV_CLIENT_SYNC_PRIM **papsSync, const IMG_CHAR *pcszExtraInfo);
+
+#if defined(PDUMP)
+/*************************************************************************/ /*!
+@Function SyncPrimPDump
+
+@Description PDump the current value of the synchronisation primitive
+
+@Input psSync The synchronisation primitive to PDump
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID
+SyncPrimPDump(PVRSRV_CLIENT_SYNC_PRIM *psSync);
+
+/*************************************************************************/ /*!
+@Function SyncPrimPDumpValue
+
+@Description PDump the ui32Value as the value of the synchronisation
+ primitive (regardless of the current value).
+
+@Input psSync The synchronisation primitive to PDump
+@Input ui32Value Value to give to the sync prim on the pdump
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID
+SyncPrimPDumpValue(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value);
+
+/*************************************************************************/ /*!
+@Function SyncPrimPDumpPol
+
+@Description Do a PDump poll of the synchronisation primitive
+
+@Input psSync The synchronisation primitive to PDump
+
+@Input ui32Value Value to poll for
+
+@Input ui32Mask PDump mask operator
+
+@Input ui32PDumpFlags PDump flags
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID
+SyncPrimPDumpPol(PVRSRV_CLIENT_SYNC_PRIM *psSync,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32PDumpFlags);
+
+/*************************************************************************/ /*!
+@Function SyncPrimOpPDumpPol
+
+@Description Do a PDump poll all the synchronisation primitives on this
+ Operation cookie.
+
+@Input psCookie Operation cookie
+
+@Input ui32PDumpFlags PDump flags
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID
+SyncPrimOpPDumpPol(PSYNC_OP_COOKIE psCookie,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32PDumpFlags);
+
+/*************************************************************************/ /*!
+@Function SyncPrimPDumpCBP
+
+@Description Do a PDump CB poll using the synchronisation primitive
+
+@Input psSync The synchronisation primitive to PDump
+
+@Input uiWriteOffset Current write offset of buffer
+
+@Input uiPacketSize Size of the packet to write into CB
+
+@Input uiBufferSize Size of the CB
+
+@Return None
+*/
+/*****************************************************************************/
+IMG_VOID
+SyncPrimPDumpCBP(PVRSRV_CLIENT_SYNC_PRIM *psSync,
+ IMG_UINT64 uiWriteOffset,
+ IMG_UINT64 uiPacketSize,
+ IMG_UINT64 uiBufferSize);
+
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncPrimPDumpValue)
+#endif
+static INLINE IMG_VOID
+SyncPrimPDumpValue(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
+{
+ PVR_UNREFERENCED_PARAMETER(psSync);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncPrimPDump)
+#endif
+static INLINE IMG_VOID
+SyncPrimPDump(PVRSRV_CLIENT_SYNC_PRIM *psSync)
+{
+ PVR_UNREFERENCED_PARAMETER(psSync);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncPrimPDumpPol)
+#endif
+static INLINE IMG_VOID
+SyncPrimPDumpPol(PVRSRV_CLIENT_SYNC_PRIM *psSync,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psSync);
+ PVR_UNREFERENCED_PARAMETER(ui32Value);
+ PVR_UNREFERENCED_PARAMETER(ui32Mask);
+ PVR_UNREFERENCED_PARAMETER(eOperator);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncPrimServerPDumpPol)
+#endif
+static INLINE IMG_VOID
+SyncPrimServerPDumpPol(PVRSRV_CLIENT_SYNC_PRIM *psSync,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVR_UNREFERENCED_PARAMETER(psSync);
+ PVR_UNREFERENCED_PARAMETER(eOperator);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncPrimPDumpCBP)
+#endif
+static INLINE IMG_VOID
+SyncPrimPDumpCBP(PVRSRV_CLIENT_SYNC_PRIM *psSync,
+ IMG_UINT64 uiWriteOffset,
+ IMG_UINT64 uiPacketSize,
+ IMG_UINT64 uiBufferSize)
+{
+ PVR_UNREFERENCED_PARAMETER(psSync);
+ PVR_UNREFERENCED_PARAMETER(uiWriteOffset);
+ PVR_UNREFERENCED_PARAMETER(uiPacketSize);
+ PVR_UNREFERENCED_PARAMETER(uiBufferSize);
+}
+#endif /* PDUMP */
+#endif /* _PVRSRV_SYNC_ */
+
diff --git a/drivers/gpu/rogue/services/shared/include/sync_internal.h b/drivers/gpu/rogue/services/shared/include/sync_internal.h
new file mode 100644
index 000000000000..fddda283a418
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/sync_internal.h
@@ -0,0 +1,120 @@
+/*************************************************************************/ /*!
+@File
+@Title Services internal synchronisation interface header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines the internal client side interface for services
+ 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.
+*/ /**************************************************************************/
+
+#ifndef _SYNC_INTERNAL_
+#define _SYNC_INTERNAL_
+
+#include "img_types.h"
+#include "sync_external.h"
+#include "ra.h"
+#include "dllist.h"
+#include "lock.h"
+#include "devicemem.h"
+
+/*
+ Private structure's
+*/
+#define SYNC_PRIM_NAME_SIZE 50
+typedef struct SYNC_PRIM_CONTEXT
+{
+ SYNC_BRIDGE_HANDLE hBridge; /*!< Bridge handle */
+ IMG_HANDLE hDeviceNode; /*!< The device we're operating on */
+ IMG_CHAR azName[SYNC_PRIM_NAME_SIZE]; /*!< Name of the RA */
+ RA_ARENA *psSubAllocRA; /*!< RA context */
+ IMG_CHAR azSpanName[SYNC_PRIM_NAME_SIZE];/*!< Name of the span RA */
+ RA_ARENA *psSpanRA; /*!< RA used for span management of SubAllocRA */
+ IMG_UINT32 ui32RefCount; /*!< Refcount for this context */
+ POS_LOCK hLock; /*!< Lock for this context */
+} SYNC_PRIM_CONTEXT;
+
+typedef struct _SYNC_PRIM_BLOCK_
+{
+ SYNC_PRIM_CONTEXT *psContext; /*!< Our copy of the services connection */
+ IMG_HANDLE hServerSyncPrimBlock; /*!< Server handle for this block */
+ IMG_UINT32 ui32SyncBlockSize; /*!< Size of the sync prim block */
+ IMG_UINT32 ui32FirmwareAddr; /*!< Firmware address */
+ DEVMEM_MEMDESC *hMemDesc; /*!< Host mapping handle */
+ IMG_UINT32 *pui32LinAddr; /*!< User CPU mapping */
+ IMG_UINT64 uiSpanBase; /*!< Base of this import in the span RA */
+ DLLIST_NODE sListNode; /*!< List node for the sync block list */
+} SYNC_PRIM_BLOCK;
+
+typedef enum _SYNC_PRIM_TYPE_
+{
+ SYNC_PRIM_TYPE_UNKNOWN = 0,
+ SYNC_PRIM_TYPE_LOCAL,
+ SYNC_PRIM_TYPE_SERVER,
+} SYNC_PRIM_TYPE;
+
+typedef struct _SYNC_PRIM_LOCAL_
+{
+ SYNC_PRIM_BLOCK *psSyncBlock; /*!< Synchronisation block this primitive is allocated on */
+ IMG_UINT64 uiSpanAddr; /*!< Span address of the sync */
+#if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
+ IMG_HANDLE hRecord; /*!< Sync record handle */
+#endif
+} SYNC_PRIM_LOCAL;
+
+typedef struct _SYNC_PRIM_SERVER_
+{
+ SYNC_BRIDGE_HANDLE hBridge; /*!< Bridge handle */
+ IMG_HANDLE hServerSync; /*!< Handle to the server sync */
+ IMG_UINT32 ui32FirmwareAddr; /*!< Firmware address of the sync */
+} SYNC_PRIM_SERVER;
+
+typedef struct _SYNC_PRIM_
+{
+ PVRSRV_CLIENT_SYNC_PRIM sCommon; /*!< Client visible part of the sync prim */
+ SYNC_PRIM_TYPE eType; /*!< Sync primative type */
+ union {
+ SYNC_PRIM_LOCAL sLocal; /*!< Local sync primative data */
+ SYNC_PRIM_SERVER sServer; /*!< Server sync primative data */
+ } u;
+} SYNC_PRIM;
+
+
+
+IMG_INTERNAL IMG_UINT32 SyncPrimGetFirmwareAddr(PVRSRV_CLIENT_SYNC_PRIM *psSync);
+
+#endif /* _SYNC_INTERNAL_ */
diff --git a/drivers/gpu/rogue/services/shared/include/tlclient.h b/drivers/gpu/rogue/services/shared/include/tlclient.h
new file mode 100644
index 000000000000..3a81ef6cdcb2
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/tlclient.h
@@ -0,0 +1,169 @@
+/*************************************************************************/ /*!
+@File tlclient.h
+@Title Services Transport Layer shared API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Transport layer common API used in both clients and server
+@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 TLCLIENT_H_
+#define TLCLIENT_H_
+
+
+#include "img_defs.h"
+#include "pvrsrv_error.h"
+#include "services.h"
+
+#include "pvr_tlcommon.h"
+
+
+/**************************************************************************/ /*!
+ @Function TLClientConnect
+ @Description Initialise direct connection to Services kernel server
+ transport layer
+ @Output phSrvHandle Address of a pointer to a connection object
+ @Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientConnect(IMG_HANDLE* phSrvHandle);
+
+
+/**************************************************************************/ /*!
+ @Function TLClientDisconnect
+ @Description Disconnect from the direct connected Services kernel server
+ transport layer
+ @Input hSrvHandle Handle to connection object as returned from
+ TLClientConnect()
+ @Return PVRSRV_ERROR: for system error codes
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientDisconnect(IMG_HANDLE hSrvHandle);
+
+
+/**************************************************************************/ /*!
+ @Function TLClientOpenStream
+ @Description Open a descriptor onto an existing kernel transport stream.
+ @Input hSrvHandle Address of a pointer to a connection object
+ @Input pszName Address of the stream name string, no longer
+ than PRVSRVTL_MAX_STREAM_NAME_SIZE.
+ @Input ui32Mode Unused
+ @Output phSD Address of a pointer to an stream object
+ @Return PVRSRV_ERROR_NOT_FOUND: when named stream not found
+ @Return PVRSRV_ERROR_ALREADY_OPEN: stream already open by another
+ @Return PVRSRV_ERROR_STREAM_ERROR: internal driver state error
+ @Return PVRSRV_ERROR_TIMEOUT: block timed out, stream not found
+ @Return PVRSRV_ERROR: for other system codes
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientOpenStream(IMG_HANDLE hSrvHandle,
+ IMG_PCHAR pszName,
+ IMG_UINT32 ui32Mode,
+ IMG_HANDLE* phSD);
+
+
+/**************************************************************************/ /*!
+ @Function TLClientCloseStream
+ @Description Close and release the stream connection to Services kernel
+ server transport layer. Any outstanding Acquire will be
+ released.
+ @Input hSrvHandle Address of a pointer to a connection object
+ @Input hSD Handle of the stream object to close
+ @Return PVRSRV_ERROR_HANDLE_NOT_FOUND: when SD handle is not known
+ @Return PVRSRV_ERROR_STREAM_ERROR: internal driver state error
+ @Return PVRSRV_ERROR: for system codes
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientCloseStream(IMG_HANDLE hSrvHandle,
+ IMG_HANDLE hSD);
+
+
+/**************************************************************************/ /*!
+ @Function TLClientAcquireData
+ @Description When there is data available in the stream buffer this call
+ returns with the address and length of the data buffer the
+ client can safely read. This buffer may contain one or more
+ packets of data.
+ If no data is available then this call blocks until it becomes
+ available. However if the stream has been destroyed while
+ waiting then a resource unavailable error will be returned
+ to the caller. Clients must pair this call with a
+ ReleaseData call.
+ @Input hSrvHandle Address of a pointer to a connection object
+ @Input hSD Handle of the stream object to read
+ @Output ppPacketBuf Address of a pointer to an byte buffer. On exit
+ pointer contains address of buffer to read from
+ @Output puiBufLen Pointer to an integer. On exit it is the size
+ of the data to read from the packet buffer
+ @Return PVRSRV_ERROR_RESOURCE_UNAVAILABLE: when stream no longer exists
+ @Return PVRSRV_ERROR_HANDLE_NOT_FOUND: when SD handle not known
+ @Return PVRSRV_ERROR_STREAM_ERROR: internal driver state error
+ @Return PVRSRV_ERROR_RETRY: release not called beforehand
+ @Return PVRSRV_ERROR_TIMEOUT: block timed out, no data
+ @Return PVRSRV_ERROR: for other system codes
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientAcquireData(IMG_HANDLE hSrvHandle,
+ IMG_HANDLE hSD,
+ IMG_PBYTE* ppPacketBuf,
+ IMG_UINT32* puiBufLen);
+
+
+/**************************************************************************/ /*!
+ @Function TLClientReleaseData
+ @Description Called after client has read the stream data out of the buffer
+ The data is subsequently flushed from the stream buffer to make
+ room for more data packets from the stream source.
+ @Input hSrvHandle Address of a pointer to a connection object
+ @Input hSD Handle of the stream object to read
+ @Return PVRSRV_ERROR_RESOURCE_UNAVAILABLE: when stream no longer exists
+ @Return PVRSRV_ERROR_HANDLE_NOT_FOUND: when SD handle not known to TL
+ @Return PVRSRV_ERROR_STREAM_ERROR: internal driver state error
+ @Return PVRSRV_ERROR_RETRY: acquire not called beforehand
+ @Return PVRSRV_ERROR: for system codes
+*/ /***************************************************************************/
+IMG_INTERNAL
+PVRSRV_ERROR TLClientReleaseData(IMG_HANDLE hSrvHandle,
+ IMG_HANDLE hSD);
+
+
+
+#endif /* TLCLIENT_H_ */
+
+/******************************************************************************
+ End of file (tlclient.h)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/shared/include/tltestdefs.h b/drivers/gpu/rogue/services/shared/include/tltestdefs.h
new file mode 100644
index 000000000000..e4eb5d2e561e
--- /dev/null
+++ b/drivers/gpu/rogue/services/shared/include/tltestdefs.h
@@ -0,0 +1,164 @@
+/*************************************************************************/ /*!
+@File tltestdefs.h
+@Title Transport Layer internals
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Transport Layer header used by TL internally
+@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 __TLTESTDEFS_H__
+#define __TLTESTDEFS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "pvr_tlcommon.h"
+
+/******************************************************************************
+ *
+ * TEST Related definitions and constants
+ */
+#define PVR_TL_TEST_STREAM_BRIDGE_NAME "TLBRIDGE_TEST"
+#define PVR_TL_TEST_UMBASE 0x00202000
+#define PVR_TL_TEST_OFFSET 0x0008
+#define PVR_TL_TEST_LEN 0x0010
+
+#define PVR_TL_TEST_STREAM2_NAME "TLSTREAM2_TEST"
+#define PVR_TL_TEST_STREAM2_SIZE 2
+
+#define PVR_TL_TEST_STREAM3_NAME "TLSTREAM3_TEST"
+#define PVR_TL_TEST_STREAM3_SIZE 256
+
+// This constant, when used as a parameter in StreamCreate, lessens the size of
+// the buffer that is created for a stream, to avoid going over a page boundary.
+#define PVR_TL_TEST_STREAM_BUFFER_REDUCTION 32
+
+#define PVR_TL_TEST_CMD_SOURCE_START 10
+typedef struct _PVR_TL_TEST_CMD_SOURCE_START_IN_
+{
+ /* Stream name must always be first in struct */
+ IMG_CHAR pszStreamName[PRVSRVTL_MAX_STREAM_NAME_SIZE];
+ IMG_UINT16 uiStreamSizeInPages; /* # of 4Kb pages */
+ IMG_UINT16 uiInterval; /* in milliseconds */
+ IMG_UINT16 uiCallbackKicks; /* 0 for no limit of timer call backs */
+ IMG_UINT16 uiEOSMarkerKicks; /* Insert EOS Marker every N Kicks, 0 for none */
+ IMG_UINT16 uiPacketSizeInBytes; /* 0 for random size between 1..255 size in bytes */
+ IMG_UINT32 uiStreamCreateFlags; /* See TLStreamCreate() */
+ IMG_UINT16 uiStartDelay; /* 0 for normal uiInterval delay, one off delay in ms */
+ IMG_BOOL bDoNotDeleteStream; /* When true the stream is not deleted on self
+ * cleanup sources only the timers and other resources are */
+ IMG_BOOL bDelayStreamCreate; /* When true the stream used in the source is created
+ * in the first kick. False for normal behaviour where
+ * the stream is created in the bridge source start context */
+} PVR_TL_TEST_CMD_SOURCE_START_IN;
+
+
+#define PVR_TL_TEST_CMD_SOURCE_STOP 11
+typedef struct _PVR_TL_TEST_CMD_SOURCE_STOP_IN_
+{
+ /* Stream name must always be first in struct */
+ IMG_CHAR pszStreamName[PRVSRVTL_MAX_STREAM_NAME_SIZE];
+ IMG_BOOL bDoNotDeleteStream;
+} PVR_TL_TEST_CMD_SOURCE_STOP_IN;
+
+#define PVR_TL_TEST_CMD_SOURCE_START2 12 /* Uses two stage data submit */
+typedef PVR_TL_TEST_CMD_SOURCE_START_IN PVR_TL_TEST_CMD_SOURCE_START2_IN;
+
+#define PVR_TL_TEST_CMD_DEBUG_LEVEL 13
+/* No typedef, uses integer uiIn1 in union */
+
+#define PVR_TL_TEST_CMD_DUMP_TL_STATE 14
+/* No typedef, uses integer uiIn1 in union */
+
+#define PVR_TL_TEST_CMD_STREAM_CREATE 15
+typedef struct _PVR_TL_TEST_CMD_STREAM_CREATE_IN_
+{
+ /* Stream name must always be first in struct */
+ IMG_CHAR pszStreamName[PRVSRVTL_MAX_STREAM_NAME_SIZE];
+ IMG_UINT16 uiStreamSizeInPages;
+ IMG_UINT32 uiStreamCreateFlags;
+} PVR_TL_TEST_CMD_STREAM_CREATE_IN;
+
+#define PVR_TL_TEST_CMD_STREAM_CLOSE 16
+typedef struct _PVR_TL_TEST_CMD_STREAM_NAME_IN_
+{
+ IMG_CHAR pszStreamName[PRVSRVTL_MAX_STREAM_NAME_SIZE];
+} PVR_TL_TEST_CMD_STREAM_NAME_IN;
+
+#define PVR_TL_TEST_CMD_STREAM_OPEN 17
+
+#define PVR_TL_TEST_CMD_DUMP_HWPERF_STATE 18
+
+#define PVR_TL_TEST_CMD_FLUSH_HWPERF_FWBUF 19
+
+#define PVR_TL_TEST_CMD_SIGNAL_PE 20
+
+#define PVR_TL_TEST_CMD_DUMP_PDUMP_STATE 21
+
+typedef union _PVR_TL_TEST_CMD_IN_
+{
+ PVR_TL_TEST_CMD_SOURCE_START_IN sStart;
+ PVR_TL_TEST_CMD_SOURCE_STOP_IN sStop;
+/* PVR_TL_TEST_CMD_SOURCE_START_IN sStart2; Used by #12, use sStart instead */
+ IMG_UINT32 uiIn1; /* Used by #13, #14 */
+ PVR_TL_TEST_CMD_STREAM_CREATE_IN sCreate;
+ PVR_TL_TEST_CMD_STREAM_NAME_IN sName;
+ IMG_UINT32 uiParams[6];
+} PVR_TL_TEST_CMD_IN;
+
+/* Has to be the largest test IN structure */
+#define PVR_TL_TEST_PARAM_MAX_SIZE (sizeof(PVR_TL_TEST_CMD_IN)+4)
+
+#define PVR_TL_TEST_CMD_SET_PWR_STATE 22
+#define PVR_TL_TEST_CMD_GET_PWR_STATE 23
+#define PVR_TL_TEST_CMD_SET_DWT_PWR_CHANGE_COUNTER 24
+#define PVR_TL_TEST_CMD_GET_DWT_PWR_CHANGE_COUNTER 25
+
+#define PVR_TL_TEST_PWR_STATE_ON 1
+#define PVR_TL_TEST_PWR_STATE_OFF 0
+
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __TLINTERN_H__ */
+
+/******************************************************************************
+ End of file (tltestdefs.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/rogue/services/system/rgx_linux_apollo/Kbuild.mk b/drivers/gpu/rogue/services/system/rgx_linux_apollo/Kbuild.mk
new file mode 100644
index 000000000000..bc4bb638ffd4
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_linux_apollo/Kbuild.mk
@@ -0,0 +1,50 @@
+########################################################################### ###
+#@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-y += \
+ services/system/$(PVR_SYSTEM)/sysconfig.o \
+ services/system/common/env/linux/pci_support.o
+
+ccflags-y += \
+ -I$(TOP)/services/system/common/env/linux \
+ -I$(TOP)/services/linux/include \
+ -I$(TOP)/kernel/drivers/staging/imgtec \
+ -I$(TOP)/include/system/rgx_tc
diff --git a/drivers/gpu/rogue/services/system/rgx_linux_apollo/apollo.h b/drivers/gpu/rogue/services/system/rgx_linux_apollo/apollo.h
new file mode 100644
index 000000000000..5d6f25c12303
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_linux_apollo/apollo.h
@@ -0,0 +1,56 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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(__APOLLO_H__)
+#define __APOLLO_H__
+
+#define TC_SYSTEM_NAME "Rogue Test Chip"
+
+/* Valid values for the TC_MEMORY_CONFIG configuration option */
+#define TC_MEMORY_LOCAL (1)
+#define TC_MEMORY_HOST (2)
+#define TC_MEMORY_HYBRID (3)
+#define TC_MEMORY_DIRECT_MAPPED (4)
+
+#endif /* if !defined(__APOLLO_H__) */
+
diff --git a/drivers/gpu/rogue/services/system/rgx_linux_apollo/sysconfig.c b/drivers/gpu/rogue/services/system/rgx_linux_apollo/sysconfig.c
new file mode 100644
index 000000000000..e992b83cdc61
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_linux_apollo/sysconfig.c
@@ -0,0 +1,675 @@
+/*************************************************************************/ /*!
+@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 "sysinfo.h"
+#include "apollo.h"
+#include "apollo_regs.h"
+
+#include "pvrsrv_device.h"
+#include "rgxdevice.h"
+#include "syscommon.h"
+#include "allocmem.h"
+#include PVR_ANDROID_ION_HEADER
+#include "ion_support.h"
+#include "ion_sys.h"
+#include "pvr_debug.h"
+
+#include "apollo_drv.h"
+
+#include <linux/platform_device.h>
+
+#if !defined(LMA)
+#error Apollo only supports LMA at the minute
+#endif
+
+#if TC_MEMORY_CONFIG != TC_MEMORY_LOCAL
+#error Apollo only supports TC_MEMORY_LOCAL at the minute
+#endif
+
+#define SYS_RGX_ACTIVE_POWER_LATENCY_MS (10)
+
+static PVRSRV_SYSTEM_CONFIG gsSysConfig;
+
+static RGX_TIMING_INFORMATION gsRGXTimingInfo =
+{
+ /* ui32CoreClockSpeed */
+ 0, /* Initialize to 0, real value will be set in PCIInitDev() */
+ /* bEnableActivePM */
+ IMG_FALSE,
+ /* bEnableRDPowIsland */
+ IMG_FALSE,
+ /* ui32ActivePMLatencyms */
+ SYS_RGX_ACTIVE_POWER_LATENCY_MS
+};
+
+static RGX_DATA gsRGXData =
+{
+ /* psRGXTimingInfo */
+ &gsRGXTimingInfo
+};
+static PVRSRV_DEVICE_CONFIG gsDevices[] =
+{
+ {
+ /* uiFlags */
+ 0,
+ /* pszName */
+ "RGX",
+ /* eDeviceType */
+ PVRSRV_DEVICE_TYPE_RGX,
+
+ /* Device setup information */
+ /* sRegsCpuPBase.uiAddr */
+ { 0 },
+ /* ui32RegsSize */
+ 0,
+
+ /* ui32IRQ */
+ APOLLO_INTERRUPT_ROGUE,
+ /* bIRQIsShared */
+ IMG_TRUE,
+ /* eIRQActiveLevel */
+ PVRSRV_DEVICE_IRQ_ACTIVE_SYSDEFAULT,
+
+ /* hDevData */
+ &gsRGXData,
+ /* hSysData */
+ IMG_NULL,
+
+ /* usable ui32PhysHeapIDs */
+ { 0, 0 },
+ /* pfnPrePowerState */
+ IMG_NULL,
+ /* pfnPostPowerState */
+ IMG_NULL,
+
+ /* pfnClockFreqGet */
+ IMG_NULL,
+
+ /* pfnInterruptHandled */
+ IMG_NULL,
+
+ /* pfnCheckMemAllocSize */
+ SysCheckMemAllocSize,
+
+ /* eBPDM */
+ RGXFWIF_DM_TA,
+ /* bBPSet */
+ IMG_FALSE
+ }
+};
+
+static IMG_VOID TCLocalCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr);
+
+static IMG_VOID TCLocalDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+static PHYS_HEAP_FUNCTIONS gsLocalPhysHeapFuncs =
+{
+ /* pfnCpuPAddrToDevPAddr */
+ TCLocalCpuPAddrToDevPAddr,
+ /* pfnDevPAddrToCpuPAddr */
+ TCLocalDevPAddrToCpuPAddr,
+};
+
+static IMG_VOID TCIonCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr);
+
+static IMG_VOID TCIonDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+static PHYS_HEAP_FUNCTIONS gsIonPhysHeapFuncs =
+{
+ /* pfnCpuPAddrToDevPAddr */
+ TCIonCpuPAddrToDevPAddr,
+ /* pfnDevPAddrToCpuPAddr */
+ TCIonDevPAddrToCpuPAddr,
+};
+
+static PHYS_HEAP_CONFIG gsPhysHeapConfig[] =
+{
+ {
+ /* ui32PhysHeapID */
+ 0,
+ /* eType */
+ PHYS_HEAP_TYPE_LMA,
+ /* sStartAddr */
+ { 0 },
+ /* uiSize */
+ 0,
+ /* pszPDumpMemspaceName */
+ "LMA",
+ /* psMemFuncs */
+ &gsLocalPhysHeapFuncs,
+ /* hPrivData */
+ (IMG_HANDLE)&gsSysConfig,
+ },
+ {
+ /* ui32PhysHeapID */
+ 1,
+ /* eType */
+ PHYS_HEAP_TYPE_LMA,
+ /* sStartAddr */
+ { 0 },
+ /* uiSize */
+ 0,
+ /* pszPDumpMemspaceName */
+ "LMA",
+ /* psMemFuncs */
+ &gsIonPhysHeapFuncs,
+ /* hPrivData */
+ (IMG_HANDLE)&gsSysConfig,
+ }
+};
+
+/* default BIF tiling heap x-stride configurations. */
+static IMG_UINT32 gauiBIFTilingHeapXStrides[RGXFWIF_NUM_BIF_TILING_CONFIGS] =
+{
+ 0, /* BIF tiling heap 1 x-stride */
+ 1, /* BIF tiling heap 2 x-stride */
+ 2, /* BIF tiling heap 3 x-stride */
+ 3 /* BIF tiling heap 4 x-stride */
+};
+
+static PVRSRV_SYSTEM_CONFIG gsSysConfig =
+{
+ /* uiSysFlags */
+ 0,
+ /* pszSystemName */
+ TC_SYSTEM_NAME,
+ /* uiDeviceCount */
+ (IMG_UINT32)(sizeof(gsDevices) / sizeof(PVRSRV_DEVICE_CONFIG)),
+ /* pasDevices */
+ &gsDevices[0],
+
+ /* No power management on no HW system */
+ /* pfnSysPrePowerState */
+ IMG_NULL,
+ /* pfnSysPostPowerState */
+ IMG_NULL,
+
+ /* no cache snooping */
+ /* eCacheSnoopingMode */
+ PVRSRV_SYSTEM_SNOOP_NONE,
+
+ /* Physcial memory heaps */
+ /* pasPhysHeaps */
+ &gsPhysHeapConfig[0],
+ /* ui32PhysHeapCount */
+ (IMG_UINT32)(sizeof(gsPhysHeapConfig) / sizeof(PHYS_HEAP_CONFIG)),
+
+ /* BIF tiling heap config */
+ &gauiBIFTilingHeapXStrides[0],
+ IMG_ARR_NUM_ELEMS(gauiBIFTilingHeapXStrides),
+};
+
+
+typedef struct _SYS_DATA_ SYS_DATA;
+
+extern struct platform_device *gpsPVRLDMDev;
+
+struct _SYS_DATA_
+{
+ IMG_UINT32 uiRefCount;
+
+ struct pci_dev *pcidev;
+
+ struct platform_device *pdev;
+
+ struct apollo_rogue_platform_data *pdata;
+
+ IMG_CHAR *pszSystemInfoString;
+
+ PVRSRV_SYS_POWER_STATE ePowerState;
+
+ struct ion_client *ion_client;
+ struct ion_handle *ion_rogue_allocation;
+
+ IMG_HANDLE hFlashData;
+
+};
+
+static IMG_CHAR *GetSystemInfoString(SYS_DATA *psSysData)
+{
+
+ return NULL;
+}
+
+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_PCI_CALL_FAILED;
+ 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_PCI_CALL_FAILED;
+ 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;
+}
+
+IMG_DEV_PHYADDR IonCPUPhysToDevPhys(IMG_CPU_PHYADDR sCPUPhysAddr,
+ IMG_UINT32 ui32Offset)
+{
+ IMG_DEV_PHYADDR sDevPAddr =
+ {
+ .uiAddr = sCPUPhysAddr.uiAddr + ui32Offset -
+ gpsIonPrivateData->pdata->apollo_memory_base,
+ };
+
+ PVR_ASSERT(sCPUPhysAddr.uiAddr + ui32Offset
+ >= gpsIonPrivateData->pdata->pdp_heap_memory_base);
+ PVR_ASSERT(sCPUPhysAddr.uiAddr + ui32Offset
+ < gpsIonPrivateData->pdata->pdp_heap_memory_base
+ + gpsIonPrivateData->pdata->pdp_heap_memory_size);
+
+ return sDevPAddr;
+}
+
+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);
+}
+
+IMG_UINT32 IonPhysHeapID(void)
+{
+ /* This seems to be the services heap that ION allocations should be mapped into
+ *
+*/
+ return 1;
+}
+
+static PVRSRV_ERROR PCIInitDev(SYS_DATA *psSysData)
+{
+ PVRSRV_DEVICE_CONFIG *psDevice = &gsSysConfig.pasDevices[0];
+ PVRSRV_ERROR eError;
+ int err = 0;
+
+ err = pci_enable_device(psSysData->pcidev);
+ if (err)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to enable PCI device (%d)", __func__, err));
+ eError = PVRSRV_ERROR_PCI_CALL_FAILED;
+ goto err_out;
+ }
+
+ eError = IonInit(psSysData);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to initialise ION", __func__));
+ goto ErrorPCIReleaseDevice;
+ }
+
+
+
+ gsPhysHeapConfig[0].uiSize =
+ psSysData->pdata->rogue_heap_memory_size;
+
+ gsPhysHeapConfig[0].sStartAddr.uiAddr =
+ psSysData->pdata->rogue_heap_memory_base;
+
+
+
+ gsPhysHeapConfig[1].uiSize = psSysData->pdata->pdp_heap_memory_size;
+ gsPhysHeapConfig[1].sStartAddr.uiAddr = psSysData->pdata->pdp_heap_memory_base;
+
+ /* Setup Rogue register information */
+ psDevice->sRegsCpuPBase.uiAddr = pci_resource_start(psSysData->pcidev, SYS_RGX_REG_PCI_BASENUM);
+ psDevice->ui32RegsSize = pci_resource_len(psSysData->pcidev, SYS_RGX_REG_PCI_BASENUM);
+
+ /* Save data for this device */
+ psDevice->hSysData = (IMG_HANDLE)psSysData;
+
+ /* Check the address range is large enough. */
+ if (psDevice->ui32RegsSize < SYS_RGX_REG_REGION_SIZE)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Rogue register region isn't big enough (was 0x%08x, required 0x%08x)",
+ __FUNCTION__, psDevice->ui32RegsSize, SYS_RGX_REG_REGION_SIZE));
+
+ eError = PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
+ goto ErrorDeInitION;
+ }
+
+ /* Reserve the address range */
+ err = pci_request_region(psSysData->pcidev, SYS_RGX_REG_PCI_BASENUM, SYS_RGX_DEV_NAME);
+ if (err)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Rogue register memory region not available", __FUNCTION__));
+ eError = PVRSRV_ERROR_PCI_CALL_FAILED;
+
+ goto ErrorDeInitION;
+ }
+
+ /* Override the system name if we can get the system info string */
+ psSysData->pszSystemInfoString = GetSystemInfoString(psSysData);
+ if (psSysData->pszSystemInfoString)
+ {
+ gsSysConfig.pszSystemName = psSysData->pszSystemInfoString;
+ }
+
+ /* Make the core clock speed value available to the driver */
+ ((RGX_DATA *)psDevice->hDevData)->psRGXTimingInfo->ui32CoreClockSpeed = apollo_core_clock_speed(&psSysData->pdev->dev) * 6;
+
+ return PVRSRV_OK;
+ErrorDeInitION:
+ IonDeinit();
+ErrorPCIReleaseDevice:
+ pci_disable_device(psSysData->pcidev);
+err_out:
+ return eError;
+}
+
+static IMG_VOID PCIDeInitDev(SYS_DATA *psSysData)
+{
+ PVRSRV_DEVICE_CONFIG *psDevice = &gsSysConfig.pasDevices[0];
+
+ if (psSysData->pszSystemInfoString)
+ {
+ OSFreeMem(psSysData->pszSystemInfoString);
+ psSysData->pszSystemInfoString = NULL;
+ }
+ IonDeinit();
+
+ pci_release_region(psSysData->pcidev, SYS_RGX_REG_PCI_BASENUM);
+ psDevice->sRegsCpuPBase.uiAddr = 0;
+ psDevice->ui32RegsSize = 0;
+
+ pci_disable_device(psSysData->pcidev);
+ psSysData->pcidev = NULL;
+}
+
+static IMG_VOID TCLocalCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr)
+{
+ PVRSRV_SYSTEM_CONFIG *psSysConfig = (PVRSRV_SYSTEM_CONFIG *)hPrivData;
+ psDevPAddr->uiAddr = psCpuPAddr->uiAddr - psSysConfig->pasPhysHeaps[0].sStartAddr.uiAddr;
+}
+
+static IMG_VOID TCLocalDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVRSRV_SYSTEM_CONFIG *psSysConfig = (PVRSRV_SYSTEM_CONFIG *)hPrivData;
+ psCpuPAddr->uiAddr = psDevPAddr->uiAddr + psSysConfig->pasPhysHeaps[0].sStartAddr.uiAddr;
+}
+
+
+static IMG_VOID TCIonCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr)
+{
+ PVRSRV_SYSTEM_CONFIG *psSysConfig = (PVRSRV_SYSTEM_CONFIG *)hPrivData;
+ SYS_DATA *psSysData = psSysConfig->pasDevices[0].hSysData;
+ psDevPAddr->uiAddr = psCpuPAddr->uiAddr - psSysData->pdata->apollo_memory_base;
+}
+
+static IMG_VOID TCIonDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVRSRV_SYSTEM_CONFIG *psSysConfig = (PVRSRV_SYSTEM_CONFIG *)hPrivData;
+ SYS_DATA *psSysData = psSysConfig->pasDevices[0].hSysData;
+ psCpuPAddr->uiAddr = psDevPAddr->uiAddr + psSysData->pdata->apollo_memory_base;
+}
+
+PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ psSysData = OSAllocMem(sizeof *psSysData);
+ if (psSysData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psSysData, 0, sizeof *psSysData);
+
+ PVR_ASSERT(gpsPVRLDMDev != NULL);
+
+ psSysData->pdev = gpsPVRLDMDev;
+ psSysData->pdata = ((struct platform_device*)gpsPVRLDMDev)->dev.platform_data;
+ psSysData->pcidev = psSysData->pdata->pdev;
+
+ eError = PCIInitDev(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorFreeSysData;
+ }
+
+ (void)SysAcquireSystemData((IMG_HANDLE)psSysData);
+
+ *ppsSysConfig = &gsSysConfig;
+
+ return PVRSRV_OK;
+
+ErrorFreeSysData:
+ OSFreeMem(psSysData);
+
+ return eError;
+}
+
+IMG_VOID SysDestroyConfigData(PVRSRV_SYSTEM_CONFIG *psSysConfig)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)psSysConfig->pasDevices[0].hSysData;
+
+ PCIDeInitDev(psSysData);
+
+ (void)SysReleaseSystemData((IMG_HANDLE)psSysData);
+}
+
+PVRSRV_ERROR SysAcquireSystemData(IMG_HANDLE hSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)hSysData;
+
+ if (psSysData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSysData->uiRefCount++;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysReleaseSystemData(IMG_HANDLE hSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)hSysData;
+
+ if (psSysData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ PVR_ASSERT(psSysData->uiRefCount != 0);
+ psSysData->uiRefCount--;
+
+ if (psSysData->uiRefCount == 0)
+ {
+ OSFreeMem(psSysData);
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysDebugInfo(PVRSRV_SYSTEM_CONFIG *psSysConfig, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ u32 tmp;
+ u32 pll;
+
+ struct apollo_rogue_platform_data *pdata = ((struct platform_device*)gpsPVRLDMDev)->dev.platform_data;
+
+ PVR_UNREFERENCED_PARAMETER(psSysConfig);
+
+ PVR_DUMPDEBUG_LOG(("------[ rgx_tc system debug ]------"));
+
+ if (apollo_sysinfo(&pdata->pdev->dev, &tmp, &pll))
+ goto err_out;
+
+ PVR_DUMPDEBUG_LOG(("Chip temperature: %d degrees C", tmp));
+ PVR_DUMPDEBUG_LOG(("PLL status: %x", pll));
+
+err_out:
+ return eError;
+}
+
+typedef struct
+{
+ struct device *psDev;
+ int iInterruptID;
+ void *pvData;
+ PFN_LISR pfnLISR;
+} LISR_DATA;
+
+static void ApolloInterruptHandler(void* pvData)
+{
+ LISR_DATA *psLISRData = pvData;
+ psLISRData->pfnLISR(psLISRData->pvData);
+}
+
+PVRSRV_ERROR SysInstallDeviceLISR(IMG_UINT32 ui32IRQ,
+ IMG_CHAR *pszName,
+ PFN_LISR pfnLISR,
+ IMG_PVOID pvData,
+ IMG_HANDLE *phLISRData)
+{
+ LISR_DATA *psLISRData;
+ PVRSRV_ERROR eError;
+ int err;
+ struct apollo_rogue_platform_data *pdata = ((struct platform_device*)gpsPVRLDMDev)->dev.platform_data;
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: Trying to install LISR %p to irq %u", __func__, pfnLISR, ui32IRQ));
+ psLISRData = kzalloc(sizeof(LISR_DATA), GFP_KERNEL);
+ if (!psLISRData)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto err_out;
+ }
+ psLISRData->pfnLISR = pfnLISR;
+ psLISRData->pvData = pvData;
+ psLISRData->iInterruptID = APOLLO_INTERRUPT_ROGUE;
+ psLISRData->psDev = &pdata->pdev->dev;
+ err = apollo_set_interrupt_handler(psLISRData->psDev, psLISRData->iInterruptID, ApolloInterruptHandler, psLISRData);
+ if (err)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: apollo_set_interrupt_handler() failed (%d)", __func__, err));
+ eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+ goto err_free_data;
+ }
+ err = apollo_enable_interrupt(psLISRData->psDev, psLISRData->iInterruptID);
+ if (err)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: apollo_enable_interrupt() failed (%d)", __func__, err));
+ eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+ goto err_unset_interrupt_handler;
+ }
+
+ *phLISRData = psLISRData;
+ eError = PVRSRV_OK;
+err_out:
+ return eError;
+err_unset_interrupt_handler:
+ apollo_set_interrupt_handler(psLISRData->psDev, psLISRData->iInterruptID, NULL, NULL);
+err_free_data:
+ kfree(psLISRData);
+ goto err_out;
+}
+
+PVRSRV_ERROR SysUninstallDeviceLISR(IMG_HANDLE hLISRData)
+{
+ LISR_DATA *psLISRData = (LISR_DATA *) hLISRData;
+ int err = apollo_disable_interrupt(psLISRData->psDev, psLISRData->iInterruptID);
+ if (err)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: apollo_enable_interrupt() failed (%d)", __func__, err));
+ }
+ err = apollo_set_interrupt_handler(psLISRData->psDev, psLISRData->iInterruptID, NULL, NULL);
+ if (err)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: apollo_set_interrupt_handler() failed (%d)", __func__, err));
+ }
+ kfree(psLISRData);
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/services/system/rgx_linux_apollo/sysinfo.h b/drivers/gpu/rogue/services/system/rgx_linux_apollo/sysinfo.h
new file mode 100644
index 000000000000..b5f3dce4a5d9
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_linux_apollo/sysinfo.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+#define SYS_RGX_DEV_VENDOR_ID (0x1010)
+#define SYS_RGX_DEV_DEVICE_ID (0x1CF2)
+
+/*!< System specific poll/timeout details */
+#define MAX_HW_TIME_US (500000)
+#define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT (10000)
+#define DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT (3600000)
+#define WAIT_TRY_COUNT (10000)
+
+/* RGX, DISPLAY (external), BUFFER (external) */
+#define SYS_DEVICE_COUNT (3)
+
+/* This should be one higher than the highest possible physical heap ID */
+#define SYS_PHYS_HEAP_COUNT 2
+
+#if defined(__linux__)
+#define SYS_RGX_DEV_NAME "apollo_rogue"
+#endif /* defined(__linux__) */
+
+#define SYS_RGX_LMA_RESERVED_SIZE (32*1024*1024)
+
+#endif /* !defined(__SYSINFO_H__) */
diff --git a/drivers/gpu/rogue/services/system/rgx_nohw/Kbuild.mk b/drivers/gpu/rogue/services/system/rgx_nohw/Kbuild.mk
new file mode 100644
index 000000000000..54bebc4e3c1d
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_nohw/Kbuild.mk
@@ -0,0 +1,46 @@
+########################################################################### ###
+#@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-y += services/system/$(PVR_SYSTEM)/sysconfig.o
+
+ifeq ($(SUPPORT_ION),1)
+pvrsrvkm-y += services/system/common/env/linux/ion_support_generic.o
+endif
diff --git a/drivers/gpu/rogue/services/system/rgx_nohw/sysconfig.c b/drivers/gpu/rogue/services/system/rgx_nohw/sysconfig.c
new file mode 100644
index 000000000000..c785901f6dc5
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_nohw/sysconfig.c
@@ -0,0 +1,236 @@
+/*************************************************************************/ /*!
+@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 "sysconfig.h"
+#include "physheap.h"
+#if defined(SUPPORT_ION)
+#include "ion_support.h"
+#endif
+
+static RGX_TIMING_INFORMATION gsRGXTimingInfo;
+static RGX_DATA gsRGXData;
+static PVRSRV_DEVICE_CONFIG gsDevices[1];
+static PVRSRV_SYSTEM_CONFIG gsSysConfig;
+
+static PHYS_HEAP_FUNCTIONS gsPhysHeapFuncs;
+#if defined(TDMETACODE)
+static PHYS_HEAP_CONFIG gsPhysHeapConfig[3];
+#else
+static PHYS_HEAP_CONFIG gsPhysHeapConfig[1];
+#endif
+
+/*
+ CPU to Device physcial address translation
+*/
+static
+IMG_VOID UMAPhysHeapCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(hPrivData);
+
+ psDevPAddr->uiAddr = psCpuPAddr->uiAddr;
+}
+
+/*
+ Device to CPU physcial address translation
+*/
+static
+IMG_VOID UMAPhysHeapDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(hPrivData);
+
+ psCpuPAddr->uiAddr = psDevPAddr->uiAddr;
+}
+
+/*
+ SysCreateConfigData
+*/
+PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig)
+{
+ /*
+ * Setup information about physical memory heap(s) we have
+ */
+ gsPhysHeapFuncs.pfnCpuPAddrToDevPAddr = UMAPhysHeapCpuPAddrToDevPAddr;
+ gsPhysHeapFuncs.pfnDevPAddrToCpuPAddr = UMAPhysHeapDevPAddrToCpuPAddr;
+
+ gsPhysHeapConfig[0].ui32PhysHeapID = 0;
+ gsPhysHeapConfig[0].pszPDumpMemspaceName = "SYSMEM";
+ gsPhysHeapConfig[0].eType = PHYS_HEAP_TYPE_UMA;
+ gsPhysHeapConfig[0].psMemFuncs = &gsPhysHeapFuncs;
+ gsPhysHeapConfig[0].hPrivData = IMG_NULL;
+
+#if defined(TDMETACODE)
+ gsPhysHeapConfig[1].ui32PhysHeapID = 1;
+ gsPhysHeapConfig[1].pszPDumpMemspaceName = "TDMETACODEMEM";
+ gsPhysHeapConfig[1].eType = PHYS_HEAP_TYPE_UMA;
+ gsPhysHeapConfig[1].psMemFuncs = &gsPhysHeapFuncs;
+ gsPhysHeapConfig[1].hPrivData = IMG_NULL;
+
+ gsPhysHeapConfig[2].ui32PhysHeapID = 2;
+ gsPhysHeapConfig[2].pszPDumpMemspaceName = "TDSECUREBUFMEM";
+ gsPhysHeapConfig[2].eType = PHYS_HEAP_TYPE_UMA;
+ gsPhysHeapConfig[2].psMemFuncs = &gsPhysHeapFuncs;
+ gsPhysHeapConfig[2].hPrivData = IMG_NULL;
+#endif
+
+ gsSysConfig.pasPhysHeaps = &(gsPhysHeapConfig[0]);
+ gsSysConfig.ui32PhysHeapCount = IMG_ARR_NUM_ELEMS(gsPhysHeapConfig);
+
+ gsSysConfig.pui32BIFTilingHeapConfigs = gauiBIFTilingHeapXStrides;
+ gsSysConfig.ui32BIFTilingHeapCount = IMG_ARR_NUM_ELEMS(gauiBIFTilingHeapXStrides);
+
+ /*
+ * Setup RGX specific timing data
+ */
+ gsRGXTimingInfo.ui32CoreClockSpeed = RGX_NOHW_CORE_CLOCK_SPEED;
+ gsRGXTimingInfo.bEnableActivePM = IMG_FALSE;
+ gsRGXTimingInfo.bEnableRDPowIsland = IMG_FALSE;
+ gsRGXTimingInfo.ui32ActivePMLatencyms = SYS_RGX_ACTIVE_POWER_LATENCY_MS;
+
+ /*
+ *Setup RGX specific data
+ */
+ gsRGXData.psRGXTimingInfo = &gsRGXTimingInfo;
+#if defined(TDMETACODE)
+ gsRGXData.bHasTDMetaCodePhysHeap = IMG_TRUE;
+ gsRGXData.uiTDMetaCodePhysHeapID = 1;
+
+ gsRGXData.bHasTDSecureBufPhysHeap = IMG_TRUE;
+ gsRGXData.uiTDSecureBufPhysHeapID = 2;
+#endif
+
+ /*
+ * Setup RGX device
+ */
+ gsDevices[0].eDeviceType = PVRSRV_DEVICE_TYPE_RGX;
+ gsDevices[0].pszName = "RGX";
+
+ /* Device setup information */
+ gsDevices[0].sRegsCpuPBase.uiAddr = 0x00f00baa;
+ gsDevices[0].ui32RegsSize = 0x4000;
+ gsDevices[0].ui32IRQ = 0x00000bad;
+ gsDevices[0].bIRQIsShared = IMG_FALSE;
+
+ /* Device's physical heap IDs */
+ gsDevices[0].aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] = 0;
+ gsDevices[0].aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL] = 0;
+
+ /* No power management on no HW system */
+ gsDevices[0].pfnPrePowerState = IMG_NULL;
+ gsDevices[0].pfnPostPowerState = IMG_NULL;
+
+ /* No clock frequency either */
+ gsDevices[0].pfnClockFreqGet = IMG_NULL;
+
+ /* No interrupt handled either */
+ gsDevices[0].pfnInterruptHandled = IMG_NULL;
+
+ gsDevices[0].pfnCheckMemAllocSize = SysCheckMemAllocSize;
+
+ gsDevices[0].hDevData = &gsRGXData;
+
+ /*
+ * Setup system config
+ */
+ gsSysConfig.pszSystemName = RGX_NOHW_SYSTEM_NAME;
+ gsSysConfig.uiDeviceCount = sizeof(gsDevices)/sizeof(gsDevices[0]);
+ gsSysConfig.pasDevices = &gsDevices[0];
+
+ /* No power management on no HW system */
+ gsSysConfig.pfnSysPrePowerState = IMG_NULL;
+ gsSysConfig.pfnSysPostPowerState = IMG_NULL;
+
+ /* no cache snooping */
+ gsSysConfig.eCacheSnoopingMode = PVRSRV_SYSTEM_SNOOP_NONE;
+
+ /* Setup other system specific stuff */
+#if defined(SUPPORT_ION)
+ IonInit(NULL);
+#endif
+
+ *ppsSysConfig = &gsSysConfig;
+
+ return PVRSRV_OK;
+}
+
+/*
+ SysDestroyConfigData
+*/
+IMG_VOID SysDestroyConfigData(PVRSRV_SYSTEM_CONFIG *psSysConfig)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysConfig);
+
+#if defined(SUPPORT_ION)
+ IonDeinit();
+#endif
+}
+
+PVRSRV_ERROR SysAcquireSystemData(IMG_HANDLE hSysData)
+{
+ PVR_UNREFERENCED_PARAMETER(hSysData);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+PVRSRV_ERROR SysReleaseSystemData(IMG_HANDLE hSysData)
+{
+ PVR_UNREFERENCED_PARAMETER(hSysData);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+PVRSRV_ERROR SysDebugInfo(PVRSRV_SYSTEM_CONFIG *psSysConfig, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysConfig);
+ PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
+ return PVRSRV_OK;
+}
+
+/******************************************************************************
+ End of file (sysconfig.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/services/system/rgx_nohw/sysconfig.h b/drivers/gpu/rogue/services/system/rgx_nohw/sysconfig.h
new file mode 100644
index 000000000000..38a9f9f8ea30
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_nohw/sysconfig.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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 "rgxdevice.h"
+
+#if !defined(__SYSCCONFIG_H__)
+#define __SYSCCONFIG_H__
+
+
+#define RGX_NOHW_CORE_CLOCK_SPEED 100000000
+#define RGX_NOHW_SYSTEM_NAME "RGX No HW"
+#define SYS_RGX_ACTIVE_POWER_LATENCY_MS (100)
+
+/* default BIF tiling heap x-stride configurations. */
+static IMG_UINT32 gauiBIFTilingHeapXStrides[RGXFWIF_NUM_BIF_TILING_CONFIGS] =
+{
+ 0, /* BIF tiling heap 1 x-stride */
+ 1, /* BIF tiling heap 2 x-stride */
+ 2, /* BIF tiling heap 3 x-stride */
+ 3 /* BIF tiling heap 4 x-stride */
+};
+
+/*****************************************************************************
+ * system specific data structures
+ *****************************************************************************/
+
+#endif /* __SYSCCONFIG_H__ */
diff --git a/drivers/gpu/rogue/services/system/rgx_nohw/sysinfo.h b/drivers/gpu/rogue/services/system/rgx_nohw/sysinfo.h
new file mode 100644
index 000000000000..b7efa09f28cf
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_nohw/sysinfo.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+/*!< System specific poll/timeout details */
+#define MAX_HW_TIME_US (500000)
+#define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT (10000)
+#define DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT (3600000)
+#define WAIT_TRY_COUNT (10000)
+
+#define SYS_DEVICE_COUNT 3 /* RGX, DISPLAY (external), BUFFER (external) */
+
+#if defined(TDMETACODE)
+/* 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 SYS_PHYS_HEAP_COUNT 3
+#else
+#define SYS_PHYS_HEAP_COUNT 1
+#endif
+
+#if defined(__linux__)
+#define SYS_RGX_DEV_NAME "rgxnohw"
+#endif
+
+#endif /* !defined(__SYSINFO_H__) */
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/Kbuild.mk b/drivers/gpu/rogue/services/system/rgx_tc/Kbuild.mk
new file mode 100644
index 000000000000..266d099a4881
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_tc/Kbuild.mk
@@ -0,0 +1,67 @@
+########################################################################### ###
+#@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-y += \
+ services/system/$(PVR_SYSTEM)/sysconfig.o \
+ services/system/$(PVR_SYSTEM)/apollo_flasher_linux.o \
+ services/system/common/env/linux/pci_support.o
+
+ifneq ($(SUPPORT_DRM),1)
+pvrsrvkm-y += services/system/common/env/linux/interrupt_support.o
+endif
+
+ifeq ($(SUPPORT_ION),1)
+ifeq ($(LMA),1)
+# For LMA, use the TC-specific ion heap.
+pvrsrvkm-y += \
+ services/system/$(PVR_SYSTEM)/ion_support_tc.o \
+ services/system/common/env/linux/lma_heap_ion.o
+else
+# For UMA, use the generic ion support code, which creates heaps from system
+# memory.
+pvrsrvkm-y += \
+ services/system/common/env/linux/ion_support_generic.o
+endif # LMA
+endif # SUPPORT_ION
+
+ccflags-y += \
+ -I$(TOP)/services/system/common/env/linux \
+ -I$(TOP)/include/system/$(PVR_SYSTEM)
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/apollo.h b/drivers/gpu/rogue/services/system/rgx_tc/apollo.h
new file mode 100644
index 000000000000..3a7a2d9fb034
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_tc/apollo.h
@@ -0,0 +1,93 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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(__APOLLO_H__)
+#define __APOLLO_H__
+
+#define TC_SYSTEM_NAME "Rogue Test Chip"
+
+/* Valid values for the TC_MEMORY_CONFIG configuration option */
+#define TC_MEMORY_LOCAL (1)
+#define TC_MEMORY_HOST (2)
+#define TC_MEMORY_HYBRID (3)
+#define TC_MEMORY_DIRECT_MAPPED (4)
+
+#if defined(SUPPORT_DISPLAY_CLASS) || defined(SUPPORT_DRM_DC_MODULE)
+/* Memory reserved for use by the PDP DC. */
+#define RGX_TC_RESERVE_DC_MEM_SIZE (32 * 1024 * 1024)
+#endif
+
+#if defined(SUPPORT_ION)
+/* Memory reserved for use by ion. */
+#define RGX_TC_RESERVE_ION_MEM_SIZE (384 * 1024 * 1024)
+#endif
+
+/* Offsets for flashing Apollo PROMs from base 0 */
+#define APOLLO_FLASH_STAT_OFFSET (0x4058)
+#define APOLLO_FLASH_DATA_WRITE_OFFSET (0x4050)
+#define APOLLO_FLASH_RESET_OFFSET (0x4060)
+
+#define APOLLO_FLASH_FIFO_STATUS_MASK (0xF)
+#define APOLLO_FLASH_FIFO_STATUS_SHIFT (0)
+#define APOLLO_FLASH_PROGRAM_STATUS_MASK (0xF)
+#define APOLLO_FLASH_PROGAM_STATUS_SHIFT (16)
+
+#define APOLLO_FLASH_PROG_COMPLETE_BIT (0x1)
+#define APOLLO_FLASH_PROG_PROGRESS_BIT (0x2)
+#define APOLLO_FLASH_PROG_FAILED_BIT (0x4)
+#define APOLLO_FLASH_INV_FILETYPE_BIT (0x8)
+
+#define APOLLO_FLASH_FIFO_SIZE (8)
+
+/* RGX reg on base register 1 */
+#define SYS_RGX_REG_PCI_BASENUM (1)
+#define SYS_RGX_REG_REGION_SIZE (0x00004000)
+
+/* Device memory (including HP mapping) on base register 2 */
+#define SYS_DEV_MEM_PCI_BASENUM (2)
+
+/* Number of bytes that are broken */
+#define SYS_DEV_MEM_BROKEN_BYTES (1024 * 1024)
+#define SYS_DEV_MEM_REGION_SIZE (0x40000000 - SYS_DEV_MEM_BROKEN_BYTES)
+
+#endif /* if !defined(__APOLLO_H__) */
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher.h b/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher.h
new file mode 100644
index 000000000000..754ee3bd1c10
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher.h
@@ -0,0 +1,70 @@
+/*************************************************************************/ /*!
+@File
+@Title Apollo flashing support
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Apollo flashing support interface
+@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(__APOLLO_FLASHER_H_C__)
+#define __APOLLO_FLASHER_H_C__
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+typedef enum _FLASH_STATUS_
+{
+ FLASH_STATUS_NOT_STARTED = 0,
+ FLASH_STATUS_WAITING,
+ FLASH_STATUS_IN_PROGRESS,
+ FLASH_STATUS_FINISHED,
+ FLASH_STATUS_FAILED,
+} FLASH_STATUS;
+
+typedef PVRSRV_ERROR (*PFN_APOLLO_FLASH_INIT)(IMG_VOID *pvData);
+typedef PVRSRV_ERROR (*PFN_APOLLO_FLASH_WRITE)(IMG_VOID *pvData, const IMG_UINT32 *uiWord);
+typedef PVRSRV_ERROR (*PFN_APOLLO_FLASH_GET_STATUS)(IMG_VOID *pvData, IMG_UINT32 *puiWriteSpace, FLASH_STATUS *peFlashStatus);
+
+PVRSRV_ERROR ApolloFlasherSetup(IMG_HANDLE *phFlasher,
+ PFN_APOLLO_FLASH_INIT pfnFlashInit,
+ PFN_APOLLO_FLASH_WRITE pfnFlashWrite,
+ PFN_APOLLO_FLASH_GET_STATUS pfnFlashGetStatus,
+ IMG_VOID *pvData);
+PVRSRV_ERROR ApolloFlasherCleanup(IMG_HANDLE hFlasher);
+
+#endif /* !defined(__APOLLO_FLASHER_H_C__) */
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher_linux.c b/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher_linux.c
new file mode 100644
index 000000000000..0d54ed69989e
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_tc/apollo_flasher_linux.c
@@ -0,0 +1,252 @@
+/*************************************************************************/ /*!
+@File
+@Title Apollo flashing support
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Apollo flashing support for Linux
+@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 "allocmem.h"
+#include "pvr_debugfs.h"
+#include "apollo_flasher.h"
+
+typedef struct _FLASH_DATA_
+{
+ IMG_UINT32 ui32ReadEntry;
+ IMG_BOOL bEnteredResetMode;
+
+ struct dentry *debugFSEntry;
+ PFN_APOLLO_FLASH_INIT pfnFlashInit;
+ PFN_APOLLO_FLASH_WRITE pfnFlashWrite;
+ PFN_APOLLO_FLASH_GET_STATUS pfnFlashGetStatus;
+
+ IMG_VOID *pvSysData;
+} FLASH_DATA;
+
+static ssize_t ApolloFlashWrite(const IMG_CHAR *pszData, size_t uiLength, loff_t uiOffset, IMG_VOID *pvData)
+{
+ FLASH_DATA *psFlashData = (FLASH_DATA *) pvData;
+ IMG_UINT32 ui32FifoWriteSpace;
+ FLASH_STATUS eProgramStatus;
+
+ PVR_UNREFERENCED_PARAMETER(uiOffset);
+
+ if (uiLength > 4)
+ {
+ return -EFBIG;
+ }
+
+ if (psFlashData->pfnFlashGetStatus(psFlashData->pvSysData, &ui32FifoWriteSpace, &eProgramStatus) != PVRSRV_OK)
+ {
+ return -EIO;
+ }
+
+ if (eProgramStatus == FLASH_STATUS_FAILED)
+ {
+ return -EIO;
+ }
+
+ if (!psFlashData->bEnteredResetMode)
+ {
+ if (eProgramStatus != FLASH_STATUS_WAITING)
+ {
+ return -EINVAL;
+ }
+
+ if (psFlashData->pfnFlashInit(psFlashData->pvSysData) != PVRSRV_OK)
+ {
+ return -EIO;
+ }
+
+ psFlashData->bEnteredResetMode = IMG_TRUE;
+ }
+
+ if (ui32FifoWriteSpace < 2)
+ {
+ return -ENOSPC;
+ }
+ else
+ {
+ if (psFlashData->pfnFlashWrite(psFlashData->pvSysData, (IMG_UINT32 *)pszData) != PVRSRV_OK)
+ {
+ return -EIO;
+ }
+ }
+
+ return uiLength;
+}
+
+static const IMG_CHAR *ApolloFlashGetStatusString(FLASH_STATUS eFlashStatus)
+{
+ if (eFlashStatus == FLASH_STATUS_WAITING)
+ {
+ return "Waiting to flash!";
+ }
+ else if (eFlashStatus == FLASH_STATUS_IN_PROGRESS)
+ {
+ return "Flashing currently in progress!";
+ }
+ else if (eFlashStatus == FLASH_STATUS_FINISHED)
+ {
+ return "Flashing completed successfully!";
+ }
+ else if (eFlashStatus == FLASH_STATUS_FAILED)
+ {
+ return "Flashing failed!";
+ }
+
+ return "Error with the in kernel Apollo flashing module!";
+}
+
+static IMG_VOID *ApolloFlashReadStart(struct seq_file *psSeqFile, loff_t *puiPosition)
+{
+ FLASH_DATA *psFlashData = (FLASH_DATA *)psSeqFile->private;
+
+ PVR_UNREFERENCED_PARAMETER(puiPosition);
+
+ if (psFlashData->ui32ReadEntry == 1)
+ {
+ psFlashData->ui32ReadEntry = 0;
+ return NULL;
+ }
+
+ return psSeqFile->private;
+}
+
+static IMG_VOID ApolloFlashReadStop(struct seq_file *psSeqFile, IMG_VOID *pvData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+}
+
+static IMG_VOID *ApolloFlashReadNext(struct seq_file *psSeqFile,
+ IMG_VOID *pvData,
+ loff_t *puiPosition)
+{
+ PVR_UNREFERENCED_PARAMETER(psSeqFile);
+ PVR_UNREFERENCED_PARAMETER(pvData);
+ PVR_UNREFERENCED_PARAMETER(puiPosition);
+
+ return NULL;
+}
+
+static int ApolloFlashReadShow(struct seq_file *psSeqFile, IMG_VOID *pvData)
+{
+ FLASH_DATA *psFlashData = (FLASH_DATA *)pvData;
+ IMG_UINT32 ui32FifoStatus;
+ IMG_UINT32 ui32ProgramStatus;
+
+ if (psFlashData->pfnFlashGetStatus(psFlashData->pvSysData, &ui32FifoStatus, &ui32ProgramStatus) != PVRSRV_OK)
+ {
+ return -EIO;
+ }
+
+ psFlashData->ui32ReadEntry = 1;
+ return seq_printf(psSeqFile, "%s\n", ApolloFlashGetStatusString(ui32ProgramStatus));
+}
+
+static struct seq_operations gsFlasherReadOps =
+{
+ .start = ApolloFlashReadStart,
+ .stop = ApolloFlashReadStop,
+ .next = ApolloFlashReadNext,
+ .show = ApolloFlashReadShow,
+};
+
+PVRSRV_ERROR ApolloFlasherSetup(IMG_HANDLE *phFlasher,
+ PFN_APOLLO_FLASH_INIT pfnFlashInit,
+ PFN_APOLLO_FLASH_WRITE pfnFlashWrite,
+ PFN_APOLLO_FLASH_GET_STATUS pfnFlashGetStatus,
+ IMG_VOID *pvData)
+{
+ FLASH_DATA *psApolloFlashData;
+
+ if (phFlasher == IMG_NULL ||
+ pfnFlashInit == IMG_NULL ||
+ pfnFlashWrite == IMG_NULL ||
+ pfnFlashGetStatus == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psApolloFlashData = OSAllocMem(sizeof *psApolloFlashData);
+ if (psApolloFlashData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psApolloFlashData->bEnteredResetMode = IMG_FALSE;
+ psApolloFlashData->pfnFlashInit = pfnFlashInit;
+ psApolloFlashData->pfnFlashWrite = pfnFlashWrite;
+ psApolloFlashData->pfnFlashGetStatus = pfnFlashGetStatus;
+ psApolloFlashData->pvSysData = pvData;
+
+ if (PVRDebugFSCreateEntry("apollo_flash",
+ IMG_NULL,
+ &gsFlasherReadOps,
+ (PVRSRV_ENTRY_WRITE_FUNC *)ApolloFlashWrite,
+ (IMG_VOID *)psApolloFlashData,
+ &psApolloFlashData->debugFSEntry) < 0)
+ {
+ OSFreeMem(psApolloFlashData);
+
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ *phFlasher = (IMG_HANDLE)psApolloFlashData;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR ApolloFlasherCleanup(IMG_HANDLE hFlasher)
+{
+ FLASH_DATA *psFlashData = (FLASH_DATA *) hFlasher;
+
+ if (psFlashData != IMG_NULL)
+ {
+ if (psFlashData->debugFSEntry != NULL)
+ {
+ PVRDebugFSRemoveEntry(psFlashData->debugFSEntry);
+ }
+
+ OSFreeMem(hFlasher);
+ }
+
+ return PVRSRV_OK;
+}
+
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/ion_support_tc.c b/drivers/gpu/rogue/services/system/rgx_tc/ion_support_tc.c
new file mode 100644
index 000000000000..f3dd88d8f6c5
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_tc/ion_support_tc.c
@@ -0,0 +1,173 @@
+/*************************************************************************/ /*!
+@File ion_support.c
+@Title Test chip ion support
+@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_ANDROID_ION_HEADER
+#include <linux/slab.h>
+#include <linux/version.h>
+#include PVR_ANDROID_ION_PRIV_HEADER
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "pvr_debug.h"
+#include "ion_support.h"
+#include "ion_sys.h"
+#include "ion_sys_private.h"
+#include "lma_heap_ion.h"
+
+struct ion_platform_data gsTCIonConfig = {
+ .nr = 1,
+ .heaps =
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,39))
+#else
+ (struct ion_platform_heap [])
+#endif
+ {
+ {
+ /* This heap must be first. The base address and size are filled
+ in from data passed down by sysconfig.c. */
+ .type = ION_HEAP_TYPE_CUSTOM,
+ .name = "tc_local_mem",
+ .id = ION_HEAP_TYPE_CUSTOM + 1,
+ .base = 0, /* filled in later */
+ .size = 0, /* filled in later */
+ }
+ }
+};
+
+struct ion_heap **gapsIonHeaps;
+struct ion_device *gpsIonDev;
+ION_TC_PRIVATE_DATA sPrivateData;
+
+PVRSRV_ERROR IonInit(void *pvPrivateData)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ int i;
+
+ sPrivateData = *(ION_TC_PRIVATE_DATA *)pvPrivateData;
+
+ /* Fill in the heap base and size according to the private data. */
+ gsTCIonConfig.heaps[0].base = sPrivateData.uiHeapBase;
+ gsTCIonConfig.heaps[0].size = sPrivateData.uiHeapSize;
+
+ gapsIonHeaps = kzalloc(sizeof(struct ion_heap *) * gsTCIonConfig.nr,
+ GFP_KERNEL);
+ gpsIonDev = ion_device_create(NULL);
+ if (IS_ERR_OR_NULL(gpsIonDev))
+ {
+ kfree(gapsIonHeaps);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ for (i = 0; i < gsTCIonConfig.nr; i++)
+ {
+ struct ion_platform_heap *psPlatHeapData = &gsTCIonConfig.heaps[i];
+
+ switch (psPlatHeapData->type)
+ {
+ case ION_HEAP_TYPE_CUSTOM:
+ /* Custom heap: this is used to mean a TC-specific heap,
+ which allocates from local memory. */
+ gapsIonHeaps[i] = lma_heap_create(psPlatHeapData);
+ break;
+ default:
+ /* For any other type of heap, hand this to ion to create as
+ appropriate. We don't necessarily need any of these -
+ this just gives us the flexibility to have another kind
+ of heap if necessary. */
+ gapsIonHeaps[i] = ion_heap_create(psPlatHeapData);
+ break;
+ }
+
+ if (IS_ERR_OR_NULL(gapsIonHeaps[i]))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create ion heap '%s'",
+ __func__, psPlatHeapData->name));
+ goto err_destroy_heaps;
+ }
+
+ ion_device_add_heap(gpsIonDev, gapsIonHeaps[i]);
+ }
+
+out:
+ return eError;
+
+err_destroy_heaps:
+ IonDeinit();
+ goto out;
+}
+
+struct ion_device *IonDevAcquire(IMG_VOID)
+{
+ return gpsIonDev;
+}
+
+IMG_VOID IonDevRelease(struct ion_device *psIonDev)
+{
+ /* Nothing to do, sanity check the pointer we're passed back */
+ PVR_ASSERT(psIonDev == gpsIonDev);
+}
+
+IMG_UINT32 IonPhysHeapID(IMG_VOID)
+{
+ return sPrivateData.ui32IonPhysHeapID;
+}
+
+#if defined(LMA)
+IMG_DEV_PHYADDR IonCPUPhysToDevPhys(IMG_CPU_PHYADDR sCPUPhysAddr,
+ IMG_UINT32 ui32Offset)
+{
+ return (IMG_DEV_PHYADDR){
+ .uiAddr = sCPUPhysAddr.uiAddr + ui32Offset
+ - sPrivateData.sPCIAddrRangeStart.uiAddr,
+ };
+}
+#endif /* defined(LMA) */
+
+IMG_VOID IonDeinit(void)
+{
+ int i;
+ for (i = 0; i < gsTCIonConfig.nr; i++)
+ if (gapsIonHeaps[i])
+ ion_heap_destroy(gapsIonHeaps[i]);
+ kfree(gapsIonHeaps);
+ ion_device_destroy(gpsIonDev);
+}
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/ion_sys_private.h b/drivers/gpu/rogue/services/system/rgx_tc/ion_sys_private.h
new file mode 100644
index 000000000000..62ee83eff80c
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_tc/ion_sys_private.h
@@ -0,0 +1,51 @@
+/*************************************************************************/ /*!
+@File ion_sys_private.h
+@Title System-specific private data for ion support code
+@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_ANDROID_ION_HEADER
+
+typedef struct
+{
+ ion_phys_addr_t uiHeapBase;
+ size_t uiHeapSize;
+ IMG_UINT32 ui32IonPhysHeapID;
+ IMG_CPU_PHYADDR sPCIAddrRangeStart;
+} ION_TC_PRIVATE_DATA;
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/sysconfig.c b/drivers/gpu/rogue/services/system/rgx_tc/sysconfig.c
new file mode 100644
index 000000000000..2040b12bc5a2
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_tc/sysconfig.c
@@ -0,0 +1,2106 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+
+#if defined(_WIN32)
+#include <string.h>
+#endif
+
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "allocmem.h"
+#include "pvrsrv_device.h"
+#include "syscommon.h"
+#include "power.h"
+#include "sysinfo.h"
+#include "apollo.h"
+#include "apollo_regs.h"
+#include "sysconfig.h"
+#include "physheap.h"
+#include "apollo_flasher.h"
+#include "pci_support.h"
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+#include "interrupt_support.h"
+#endif
+#include "tcf_clk_ctrl.h"
+#include "tcf_pll.h"
+#if defined(SUPPORT_ION)
+#include PVR_ANDROID_ION_HEADER
+#include "ion_support.h"
+#include "ion_sys_private.h"
+#endif
+
+#if defined(LMA)
+#define HOST_PCI_INIT_FLAGS 0
+#else
+#define HOST_PCI_INIT_FLAGS HOST_PCI_INIT_FLAG_BUS_MASTER
+#endif
+
+#if defined(LDM_PCI) || defined(SUPPORT_DRM)
+/* The following is exported by the Linux module code */
+extern struct pci_dev *gpsPVRLDMDev;
+#endif
+
+/* Clock speed module parameters */
+static IMG_UINT32 ui32MemClockSpeed = RGX_TC_MEM_CLOCK_SPEED;
+static IMG_UINT32 ui32CoreClockSpeed = RGX_TC_CORE_CLOCK_SPEED;
+
+#if defined(LINUX)
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+module_param_named(sys_mem_clk_speed, ui32MemClockSpeed, uint, S_IRUGO | S_IWUSR);
+module_param_named(sys_core_clk_speed, ui32CoreClockSpeed, uint, S_IRUGO | S_IWUSR);
+#endif
+
+typedef struct _SYS_DATA_ SYS_DATA;
+
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+typedef struct _SYS_INTERRUPT_DATA_
+{
+ SYS_DATA *psSysData;
+ IMG_CHAR *pszName;
+ PFN_LISR pfnLISR;
+ IMG_VOID *pvData;
+ IMG_UINT32 ui32InterruptFlag;
+} SYS_INTERRUPT_DATA;
+#endif
+
+struct _SYS_DATA_
+{
+ IMG_UINT32 uiRefCount;
+
+ IMG_HANDLE hRGXPCI;
+
+ IMG_CHAR *pszSystemInfoString;
+
+ IMG_CPU_PHYADDR sSystemRegCpuPBase;
+ IMG_VOID *pvSystemRegCpuVBase;
+ IMG_SIZE_T uiSystemRegSize;
+
+ IMG_CPU_PHYADDR sLocalMemCpuPBase;
+ IMG_SIZE_T uiLocalMemSize;
+
+ PVRSRV_SYS_POWER_STATE ePowerState;
+
+ IMG_HANDLE hFlashData;
+
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+#if !defined(SUPPORT_DRM)
+ IMG_HANDLE hLISR;
+#endif
+ IMG_UINT32 ui32IRQ;
+ SYS_INTERRUPT_DATA sInterruptData[SYS_DEVICE_COUNT];
+#endif
+};
+
+#define SYSTEM_INFO_FORMAT_STRING "%s\tFPGA Revision: %s.%s.%s\tTCF Core Revision: %s.%s.%s\tTCF Core Target Build ID: %s\tPCI Version: %s\tMacro Version: %s.%s"
+#define SYSTEM_INFO_REV_NUM_LEN 3
+
+#define HEXIDECIMAL_TO_DECIMAL(hexIntVal) ((((hexIntVal) >> 4) * 10) + ((hexIntVal) & 0x0F))
+
+static PVRSRV_ERROR InitMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData);
+static INLINE void DeInitMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData);
+
+static PVRSRV_ERROR ApolloFlashInit(IMG_VOID *pvData);
+static PVRSRV_ERROR ApolloFlashWrite(IMG_VOID *pvData, const IMG_UINT32 *puiWord);
+static PVRSRV_ERROR ApolloFlashGetStatus(IMG_VOID *pvData,
+ IMG_UINT32 *puiWriteSpace,
+ FLASH_STATUS *peFlashStatus);
+
+static IMG_CHAR *GetSystemInfoString(SYS_DATA *psSysData)
+{
+ IMG_CHAR apszFPGARev[3][SYSTEM_INFO_REV_NUM_LEN];
+ IMG_CHAR apszCoreRev[3][SYSTEM_INFO_REV_NUM_LEN];
+ IMG_CHAR apszConfigRev[SYSTEM_INFO_REV_NUM_LEN];
+ IMG_CHAR apszPCIVer[SYSTEM_INFO_REV_NUM_LEN];
+ IMG_CHAR apszMacroVer[2][SYSTEM_INFO_REV_NUM_LEN];
+ IMG_CHAR *pszSystemInfoString;
+ IMG_UINT32 ui32StringLength;
+ IMG_UINT32 ui32Value;
+ IMG_CPU_PHYADDR sHostFPGARegCpuPBase;
+ IMG_VOID *pvHostFPGARegCpuVBase;
+
+ /* To get some of the version information we need to read from a register that we don't normally have
+ mapped. Map it temporarily (without trying to reserve it) to get the information we need. */
+ sHostFPGARegCpuPBase.uiAddr = OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM) + 0x40F0;
+ pvHostFPGARegCpuVBase = OSMapPhysToLin(sHostFPGARegCpuPBase, 0x04, 0);
+ if (pvHostFPGARegCpuVBase == NULL)
+ {
+ return NULL;
+ }
+
+ /* Create the components of the PCI and macro versions */
+ ui32Value = OSReadHWReg32(pvHostFPGARegCpuVBase, 0);
+ OSSNPrintf(&apszPCIVer[0], SYSTEM_INFO_REV_NUM_LEN, "%d", HEXIDECIMAL_TO_DECIMAL((ui32Value & 0x00FF0000) >> 16));
+ OSSNPrintf(&apszMacroVer[0][0], SYSTEM_INFO_REV_NUM_LEN, "%d", ((ui32Value & 0x00000F00) >> 8));
+ OSSNPrintf(&apszMacroVer[1][0], SYSTEM_INFO_REV_NUM_LEN, "%d", HEXIDECIMAL_TO_DECIMAL((ui32Value & 0x000000FF) >> 0));
+
+ /* Unmap the register now that we no longer need it */
+ OSUnMapPhysToLin(pvHostFPGARegCpuVBase, 0x04, 0);
+
+ /* Create the components of the FPGA revision number */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_FPGA_REV_REG);
+ OSSNPrintf(&apszFPGARev[0][0], SYSTEM_INFO_REV_NUM_LEN, "%d", HEXIDECIMAL_TO_DECIMAL((ui32Value & FPGA_REV_REG_MAJOR_MASK) >> FPGA_REV_REG_MAJOR_SHIFT));
+ OSSNPrintf(&apszFPGARev[1][0], SYSTEM_INFO_REV_NUM_LEN, "%d", HEXIDECIMAL_TO_DECIMAL((ui32Value & FPGA_REV_REG_MINOR_MASK) >> FPGA_REV_REG_MINOR_SHIFT));
+ OSSNPrintf(&apszFPGARev[2][0], SYSTEM_INFO_REV_NUM_LEN, "%d", HEXIDECIMAL_TO_DECIMAL((ui32Value & FPGA_REV_REG_MAINT_MASK) >> FPGA_REV_REG_MAINT_SHIFT));
+
+ /* Create the components of the TCF core revision number */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TCF_CORE_REV_REG);
+ OSSNPrintf(&apszCoreRev[0][0], SYSTEM_INFO_REV_NUM_LEN, "%d", HEXIDECIMAL_TO_DECIMAL((ui32Value & TCF_CORE_REV_REG_MAJOR_MASK) >> TCF_CORE_REV_REG_MAJOR_SHIFT));
+ OSSNPrintf(&apszCoreRev[1][0], SYSTEM_INFO_REV_NUM_LEN, "%d", HEXIDECIMAL_TO_DECIMAL((ui32Value & TCF_CORE_REV_REG_MINOR_MASK) >> TCF_CORE_REV_REG_MINOR_SHIFT));
+ OSSNPrintf(&apszCoreRev[2][0], SYSTEM_INFO_REV_NUM_LEN, "%d", HEXIDECIMAL_TO_DECIMAL((ui32Value & TCF_CORE_REV_REG_MAINT_MASK) >> TCF_CORE_REV_REG_MAINT_SHIFT));
+
+ /* Create the component of the TCF core target build ID */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TCF_CORE_TARGET_BUILD_CFG);
+ OSSNPrintf(&apszConfigRev[0], SYSTEM_INFO_REV_NUM_LEN, "%d", (ui32Value & TCF_CORE_TARGET_BUILD_ID_MASK) >> TCF_CORE_TARGET_BUILD_ID_SHIFT);
+
+ /* Calculate how much space we need to allocate for the string */
+ ui32StringLength = OSStringLength(SYSTEM_INFO_FORMAT_STRING);
+ ui32StringLength += OSStringLength(TC_SYSTEM_NAME);
+ ui32StringLength += OSStringLength(&apszFPGARev[0][0]) + OSStringLength(&apszFPGARev[1][0]) + OSStringLength(&apszFPGARev[2][0]);
+ ui32StringLength += OSStringLength(&apszCoreRev[0][0]) + OSStringLength(&apszCoreRev[1][0]) + OSStringLength(&apszCoreRev[2][0]);
+ ui32StringLength += OSStringLength(&apszConfigRev[0]);
+ ui32StringLength += OSStringLength(&apszPCIVer[0]);
+ ui32StringLength += OSStringLength(&apszMacroVer[0][0]) + OSStringLength(&apszMacroVer[1][0]);
+
+ /* Create the system info string */
+ pszSystemInfoString = OSAllocZMem(ui32StringLength * sizeof(IMG_CHAR));
+ if (pszSystemInfoString)
+ {
+ OSSNPrintf(&pszSystemInfoString[0], ui32StringLength, SYSTEM_INFO_FORMAT_STRING, TC_SYSTEM_NAME,
+ &apszFPGARev[0][0], &apszFPGARev[1][0], &apszFPGARev[2][0],
+ &apszCoreRev[0][0], &apszCoreRev[1][0], &apszCoreRev[2][0],
+ &apszConfigRev[0], &apszPCIVer[0],
+ &apszMacroVer[0][0], &apszMacroVer[1][0]);
+ }
+
+ return pszSystemInfoString;
+}
+
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+#if !defined(SUPPORT_DRM)
+static
+#endif
+IMG_BOOL SystemISRHandler(IMG_VOID *pvData)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)pvData;
+ IMG_UINT32 ui32InterruptClear = 0;
+ IMG_UINT32 ui32InterruptStatus;
+ IMG_UINT32 i;
+
+ ui32InterruptStatus = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_STATUS);
+
+ for (i = 0; i < SYS_DEVICE_COUNT; i++)
+ {
+ if ((ui32InterruptStatus & psSysData->sInterruptData[i].ui32InterruptFlag) != 0)
+ {
+ psSysData->sInterruptData[i].pfnLISR(psSysData->sInterruptData[i].pvData);
+
+ ui32InterruptClear |= psSysData->sInterruptData[i].ui32InterruptFlag;
+ }
+ }
+
+ if (ui32InterruptClear)
+ {
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_CLEAR, ui32InterruptClear);
+
+ /*
+ CPU-PCI-WRITE-BUFFER
+
+ On CEPC platforms, this BIOS performance enhancing feature controls the chipset's
+ CPU-to-PCI write buffer used to store PCI writes from the CPU before being written
+ onto the PCI bus. By reading from the register, this CPU-to-PCI write
+ buffer is flushed.
+
+ Without this read, at times the CE kernel reports "Unwanted IRQ(11)" due to above INTR
+ clear not being reflected on the IRQ line after exit from the INTR handler SystemISRWrapper
+ which calls InterruptDone notifying CE kernel of handler completion.
+ */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_CLEAR);
+
+ return IMG_TRUE;
+ }
+
+ return IMG_FALSE;
+}
+#else
+IMG_VOID SystemISRHandler(PVRSRV_DEVICE_CONFIG *psDevConfig)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)psDevConfig->hSysData;
+ IMG_UINT32 ui32InterruptClear = 0;
+ IMG_UINT32 ui32InterruptStatus;
+
+ ui32InterruptStatus = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_STATUS);
+
+ if (ui32InterruptStatus & PDP1_INT_MASK)
+ {
+ ui32InterruptClear |= (0x1 << PDP1_INT_SHIFT);
+ }
+
+ if (ui32InterruptStatus & EXT_INT_MASK)
+ {
+ ui32InterruptClear = (0x1 << EXT_INT_SHIFT);
+ }
+
+ if (ui32InterruptClear)
+ {
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_CLEAR, ui32InterruptClear);
+ }
+}
+#endif /* defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) */
+
+#if defined(TC_APOLLO_ES2)
+
+static IMG_VOID SPI_Write(IMG_VOID *pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value)
+{
+ OSWriteHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_ADDR_RDNWR, ui32Offset);
+ OSWriteHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_WDATA, ui32Value);
+ OSWriteHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_GO, TCF_SPI_MST_GO_MASK);
+ OSWaitus(1000);
+}
+
+static PVRSRV_ERROR SPI_Read(IMG_VOID *pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 *pui32Value)
+{
+ IMG_UINT32 ui32Count = 0;
+
+ OSWriteHWReg32(pvLinRegBaseAddr,
+ TCF_CLK_CTRL_TCF_SPI_MST_ADDR_RDNWR,
+ 0x40000 | ui32Offset);
+ OSWriteHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_GO, TCF_SPI_MST_GO_MASK);
+ OSWaitus(100);
+
+ while (((OSReadHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_STATUS)) != 0x08) &&
+ (ui32Count < 10000))
+ {
+ ui32Count++;
+ }
+
+ if (ui32Count < 10000)
+ {
+ *pui32Value = OSReadHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_RDATA);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SPI_Read: Time out reading SPI register (0x%x)", ui32Offset));
+ return PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ }
+
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL IsInterfaceAligned(
+ IMG_UINT32 ui32Eyes,
+ IMG_UINT32 ui32ClkTaps,
+ IMG_UINT32 ui32TrainAck)
+{
+
+ IMG_UINT32 ui32MaxEyeStart = ui32Eyes >> 16;
+ IMG_UINT32 ui32MinEyeEnd = ui32Eyes & 0xffff;
+
+ IMG_BOOL bTrainingComplete = (ui32ClkTaps & 0x10000);
+
+ IMG_BOOL bTrainAckComplete = (ui32TrainAck & 0x100);
+ IMG_UINT32 ui32FailedAcks = (ui32TrainAck & 0xf0) >> 4;
+
+
+ //If either the training or training ack failed, we haven't aligned
+ if (!bTrainingComplete || !bTrainAckComplete)
+ {
+ return IMG_FALSE;
+ }
+
+ //If the max eye >= min eye it means the readings are nonsense
+ if (ui32MaxEyeStart >= ui32MinEyeEnd)
+ {
+ return IMG_FALSE;
+ }
+
+ //If we failed the ack pattern more than 4 times
+ if (ui32FailedAcks > 4)
+ {
+ return IMG_FALSE;
+ }
+
+ //If there is less than 7 taps
+ //(240ps @40ps/tap, this number should be lower for the fpga, since its taps are bigger
+ //We should really calculate the "7" based on the interface clock speed.
+ if ((ui32MinEyeEnd - ui32MaxEyeStart) < 7)
+ {
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_UINT32 SAI_Read(void *base, IMG_UINT32 addr)
+{
+ OSWriteHWReg32(base, 0x300, 0x200 | addr);
+ OSWriteHWReg32(base, 0x318, 1);
+ return OSReadHWReg32(base, 0x310);
+}
+
+static PVRSRV_ERROR ApolloHardReset(SYS_DATA *psSysData)
+{
+ IMG_UINT32 ui32ClkResetN;
+ IMG_UINT32 ui32DUTCtrl;
+
+ IMG_BOOL bAlignmentOK = IMG_FALSE;
+ IMG_INT resetAttempts = 0;
+
+ //This is required for SPI reset which is not yet implemented.
+ //IMG_UINT32 ui32AuxResetsN;
+
+ //power down
+ ui32DUTCtrl = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_DUT_CONTROL_1);
+ ui32DUTCtrl &= ~DUT_CTRL_VCC_0V9EN;
+ ui32DUTCtrl &= ~DUT_CTRL_VCC_1V8EN;
+ ui32DUTCtrl |= DUT_CTRL_VCC_IO_INH;
+ ui32DUTCtrl |= DUT_CTRL_VCC_CORE_INH;
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_DUT_CONTROL_1, ui32DUTCtrl);
+
+ OSSleepms(500);
+
+ //set clock speed here, before reset.
+#if 0
+ //This is if 0 out since the current FPGA builds do not like their core clocks being set (it takes apollo down).
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, 0x1000 | TCF_PLL_PLL_CORE_CLK0, ui32CoreClockSpeed / 1000000);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, 0x1000 | TCF_PLL_PLL_CORE_DRP_GO, 1);
+#endif
+
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, 0x1000 | TCF_PLL_PLL_MEMIF_CLK0, ui32MemClockSpeed / 1000000);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, 0x1000 | TCF_PLL_PLL_MEM_DRP_GO, 1);
+
+ printk(KERN_ERR "Setting clocks to %uMHz/%uMHz\n", ui32CoreClockSpeed / 1000000, ui32MemClockSpeed / 1000000);
+
+ OSWaitus(400);
+
+ //Put DCM, DUT, DDR, PDP1, and PDP2 into reset
+ ui32ClkResetN = (0x1 << GLB_CLKG_EN_SHIFT);
+ ui32ClkResetN |= (0x1 << SCB_RESETN_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_CLK_AND_RST_CTRL, ui32ClkResetN);
+
+ OSSleepms(100);
+
+ //Enable the voltage control regulators on DUT
+ ui32DUTCtrl = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_DUT_CONTROL_1);
+ ui32DUTCtrl |= DUT_CTRL_VCC_0V9EN;
+ ui32DUTCtrl |= DUT_CTRL_VCC_1V8EN;
+ ui32DUTCtrl &= ~DUT_CTRL_VCC_IO_INH;
+ ui32DUTCtrl &= ~DUT_CTRL_VCC_CORE_INH;
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_DUT_CONTROL_1, ui32DUTCtrl);
+
+ OSSleepms(300);
+
+
+ //Take DCM, DDR, PDP1, and PDP2 out of reset
+ ui32ClkResetN |= (0x1 << DDR_RESETN_SHIFT);
+ ui32ClkResetN |= (0x1 << DUT_DCM_RESETN_SHIFT);
+ ui32ClkResetN |= (0x1 << PDP1_RESETN_SHIFT);
+ ui32ClkResetN |= (0x1 << PDP2_RESETN_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_CLK_AND_RST_CTRL, ui32ClkResetN);
+
+ //Set ODT to a specific value that seems to provide the most stable signals.
+ SPI_Write(psSysData->pvSystemRegCpuVBase, 0x11, 0x413130);
+
+ //Take DUT out of reset
+ ui32ClkResetN |= (0x1 << DUT_RESETN_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_CLK_AND_RST_CTRL, ui32ClkResetN);
+ OSSleepms(100);
+
+ //try to enable the core clock PLL
+ {
+ IMG_UINT32 ui32DUTResets;
+ IMG_UINT32 ui32DUTGPIO1;
+ IMG_UINT32 ui32PLLStatus = 0;
+
+ /* Un-bypass the PLL on the DUT */
+ SPI_Write(psSysData->pvSystemRegCpuVBase, 0x1, 0x0);
+ ui32DUTResets = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, 0x320);
+ ui32DUTResets |= 0x1;
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, 0x320, ui32DUTResets);
+ ui32DUTResets &= 0xfffffffe;
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, 0x320, ui32DUTResets);
+ OSSleepms(1000);
+
+ if (SPI_Read(psSysData->pvSystemRegCpuVBase, 0x2, &ui32PLLStatus) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Unable to read PLL status"));
+ }
+
+ if (ui32PLLStatus != 0x1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PLL has failed to lock, status = %x", ui32PLLStatus));
+ }
+ else
+ {
+ /* Select DUT PLL as core clock */
+ ui32DUTGPIO1 = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, 0x108);
+ ui32DUTGPIO1 &= 0xfffffff7;
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, 0x108, ui32DUTGPIO1);
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PLL has been set to 6x"));
+ }
+
+ while (!bAlignmentOK && resetAttempts < 10)
+ {
+ IMG_UINT32 ui32Eyes = 0;
+ IMG_UINT32 ui32ClkTaps = 0;
+ IMG_UINT32 ui32TrainAck = 0;
+
+ IMG_INT bank;
+
+
+ resetAttempts += 1;
+
+ //reset the DUT to allow the SAI to retrain
+ ui32ClkResetN &= ~(0x1 << DUT_RESETN_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_CLK_AND_RST_CTRL, ui32ClkResetN);
+ OSWaitus(100);
+ ui32ClkResetN |= (0x1 << DUT_RESETN_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_CLK_AND_RST_CTRL, ui32ClkResetN);
+ OSWaitus(100);
+
+ //Assume aligment passed, if any bank fails on either DUT or FPGA
+ //we will set this to false and try again for a max of 10 times.
+ bAlignmentOK = IMG_TRUE;
+
+ //for each of the banks
+ for (bank = 0; bank < 10; bank++)
+ {
+
+ //check alignment on the DUT
+ IMG_UINT32 ui32BankBase = 0x7000 + (0x1000 * bank);
+
+ SPI_Read(psSysData->pvSystemRegCpuVBase, ui32BankBase + 0x4, &ui32Eyes);
+ SPI_Read(psSysData->pvSystemRegCpuVBase, ui32BankBase + 0x3, &ui32ClkTaps);
+ SPI_Read(psSysData->pvSystemRegCpuVBase, ui32BankBase + 0x6, &ui32TrainAck);
+
+ if (!IsInterfaceAligned(ui32Eyes, ui32ClkTaps, ui32TrainAck))
+ {
+ bAlignmentOK = IMG_FALSE;
+ break;
+ }
+
+ //check alignment on the FPGA
+ ui32BankBase = 0xb0 + (0x10 * bank);
+
+ ui32Eyes = SAI_Read(psSysData->pvSystemRegCpuVBase, ui32BankBase + 0x4);
+ ui32ClkTaps = SAI_Read(psSysData->pvSystemRegCpuVBase, ui32BankBase + 0x3);
+ ui32TrainAck = SAI_Read(psSysData->pvSystemRegCpuVBase, ui32BankBase + 0x6);
+
+ if (!IsInterfaceAligned(ui32Eyes, ui32ClkTaps, ui32TrainAck))
+ {
+ bAlignmentOK = IMG_FALSE;
+ break;
+ }
+ }
+ }
+
+ if (!bAlignmentOK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Unable to intialise the testchip (interface alignment failure), please restart the system."));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ if (resetAttempts > 1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Note: The testchip required more than one reset to find a good interface alingment!"));
+ PVR_DPF((PVR_DBG_ERROR, " This should be harmless, but if you do suspect foul play, please reset the machine."));
+ PVR_DPF((PVR_DBG_ERROR, " If you continue to see this message you may want to report it to IMGWORKS."));
+ }
+
+ /* Enable the temperature sensor */
+ SPI_Write(psSysData->pvSystemRegCpuVBase, 0xc, 0); //power up
+ SPI_Write(psSysData->pvSystemRegCpuVBase, 0xc, 2); //reset
+ SPI_Write(psSysData->pvSystemRegCpuVBase, 0xc, 6); //init & run
+
+ {
+ IMG_UINT32 ui32RevID = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, 0x10);
+
+ IMG_UINT32 ui32BuildInc = (ui32RevID >> 12) & 0xff;
+
+ if (ui32BuildInc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BE WARNED: You are not running a tagged release of the FPGA image!"));
+ PVR_DPF((PVR_DBG_ERROR, "Owner: 0x%01x, Inc: 0x%02x", (ui32RevID >> 20) & 0xf, ui32BuildInc));
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "FPGA Release: %u.%02u", ui32RevID >> 8 & 0xf, ui32RevID & 0xff));
+
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR PCIInitDev(SYS_DATA *psSysData)
+{
+ PVRSRV_DEVICE_CONFIG *psDevice = &gsSysConfig.pasDevices[0];
+ IMG_CPU_PHYADDR sApolloRegCpuPBase;
+ IMG_UINT32 uiApolloRegSize;
+ PVRSRV_ERROR eError;
+
+#if defined(LDM_PCI) || defined(SUPPORT_DRM)
+ /* Use the pci_dev structure pointer from module.c */
+ PVR_ASSERT(gpsPVRLDMDev != IMG_NULL);
+
+ psSysData->hRGXPCI = OSPCISetDev((IMG_VOID *)gpsPVRLDMDev, HOST_PCI_INIT_FLAGS);
+#else
+ psSysData->hRGXPCI = OSPCIAcquireDev(SYS_RGX_DEV_VENDOR_ID, SYS_RGX_DEV_DEVICE_ID, HOST_PCI_INIT_FLAGS);
+#endif /* defined(LDM_PCI) || defined(SUPPORT_DRM) */
+ if (!psSysData->hRGXPCI)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire PCI device", __FUNCTION__));
+ return PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND;
+ }
+
+ /* Get Apollo register information */
+ sApolloRegCpuPBase.uiAddr = OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM);
+ uiApolloRegSize = OSPCIAddrRangeLen(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM);
+
+ /* Check the address range is large enough. */
+ if (uiApolloRegSize < SYS_APOLLO_REG_REGION_SIZE)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Apollo register region isn't big enough (was 0x%08X, required 0x%08X)",
+ __FUNCTION__, uiApolloRegSize, SYS_APOLLO_REG_REGION_SIZE));
+
+ eError = PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
+ goto ErrorPCIReleaseDevice;
+ }
+
+ /* The Apollo register range contains several register regions. Request only the system control register region */
+ eError = OSPCIRequestAddrRegion(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM, SYS_APOLLO_REG_SYS_OFFSET, SYS_APOLLO_REG_SYS_SIZE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to request the system register region", __FUNCTION__));
+
+ goto ErrorPCIReleaseDevice;
+ }
+ psSysData->sSystemRegCpuPBase.uiAddr = sApolloRegCpuPBase.uiAddr + SYS_APOLLO_REG_SYS_OFFSET;
+ psSysData->uiSystemRegSize = SYS_APOLLO_REG_REGION_SIZE;
+
+ /* Setup Rogue register information */
+ psDevice->sRegsCpuPBase.uiAddr = OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_RGX_REG_PCI_BASENUM);
+ psDevice->ui32RegsSize = OSPCIAddrRangeLen(psSysData->hRGXPCI, SYS_RGX_REG_PCI_BASENUM);
+
+ /* Save data for this device */
+ psDevice->hSysData = (IMG_HANDLE)psSysData;
+
+ /* Check the address range is large enough. */
+ if (psDevice->ui32RegsSize < SYS_RGX_REG_REGION_SIZE)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Rogue register region isn't big enough (was 0x%08x, required 0x%08x)",
+ __FUNCTION__, psDevice->ui32RegsSize, SYS_RGX_REG_REGION_SIZE));
+
+ eError = PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
+ goto ErrorSystemRegReleaseAddrRegion;
+ }
+
+ /* Reserve the address range */
+ eError = OSPCIRequestAddrRange(psSysData->hRGXPCI, SYS_RGX_REG_PCI_BASENUM);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Rogue register memory region not available", __FUNCTION__));
+
+ goto ErrorSystemRegReleaseAddrRegion;
+ }
+
+ /* Map in system registers so we can:
+ - Configure the memory mode (LMA, UMA or LMA/UMA hybrid)
+ - Hard reset Apollo
+ - Clear interrupts
+ */
+ psSysData->pvSystemRegCpuVBase = OSMapPhysToLin(psSysData->sSystemRegCpuPBase, psSysData->uiSystemRegSize, 0);
+ if (psSysData->pvSystemRegCpuVBase == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map system registers", __FUNCTION__));
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorRGXRegReleaseAddrRange;
+ }
+
+ eError = ApolloFlasherSetup(&psSysData->hFlashData,
+ ApolloFlashInit,
+ ApolloFlashWrite,
+ ApolloFlashGetStatus,
+ (IMG_VOID *)psSysData);
+
+ if (eError != PVRSRV_OK)
+ {
+ if (eError != PVRSRV_ERROR_NOT_IMPLEMENTED)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Apollo flash setup failed. You will not be able to flash Apollo.", __FUNCTION__));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Support for flashing Apollo has not been implemented.", __FUNCTION__));
+ }
+ psSysData->hFlashData = NULL;
+ }
+
+
+ eError = ApolloHardReset(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorCleanupFlashingModule;
+ }
+
+ /* Make the core clock speed value available to the driver (matching the one set by ApolloHardReset()) */
+ ((RGX_DATA *)psDevice->hDevData)->psRGXTimingInfo->ui32CoreClockSpeed = ui32CoreClockSpeed * 6;
+
+
+ eError = InitMemory(&gsSysConfig, psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorCleanupFlashingModule;
+ }
+
+ /* Override the system name if we can get the system info string */
+ psSysData->pszSystemInfoString = GetSystemInfoString(psSysData);
+ if (psSysData->pszSystemInfoString)
+ {
+ gsSysConfig.pszSystemName = psSysData->pszSystemInfoString;
+ }
+
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+ eError = OSPCIIRQ(psSysData->hRGXPCI, &psSysData->ui32IRQ);
+#else
+ eError = OSPCIIRQ(psSysData->hRGXPCI, &psDevice->ui32IRQ);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't get IRQ", __FUNCTION__));
+
+ goto ErrorDeInitMemory;
+ }
+
+#if !defined(SUPPORT_DRM)
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+ /* Register our handler */
+ eError = OSInstallSystemLISR(&psSysData->hLISR,
+ psSysData->ui32IRQ,
+#if !defined(UNDER_CE)
+ IMG_NULL,
+#else
+ (PVR_IRQ_PRIV_DATA *)&psSysData->sSystemRegCpuPBase,
+#endif
+ SystemISRHandler,
+ psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to install the system device interrupt handler", __FUNCTION__));
+
+ goto ErrorDeInitMemory;
+ }
+#else
+ psDevice->pfnInterruptHandled = SystemISRHandler;
+
+ EnableInterrupt(psSysData, (0x1 << EXT_INT_SHIFT) | (0x1 << PDP1_INT_SHIFT));
+#endif
+#endif /* !defined(SUPPORT_DRM) */
+
+ return PVRSRV_OK;
+
+ErrorDeInitMemory:
+ DeInitMemory(&gsSysConfig, psSysData);
+
+ErrorCleanupFlashingModule:
+ if (psSysData->hFlashData != NULL)
+ {
+ ApolloFlasherCleanup(psSysData->hFlashData);
+ }
+
+ OSUnMapPhysToLin(psSysData->pvSystemRegCpuVBase, psSysData->uiSystemRegSize, 0);
+ psSysData->pvSystemRegCpuVBase = NULL;
+
+ErrorRGXRegReleaseAddrRange:
+ OSPCIReleaseAddrRange(psSysData->hRGXPCI, SYS_RGX_REG_PCI_BASENUM);
+ psDevice->sRegsCpuPBase.uiAddr = 0;
+ psDevice->ui32RegsSize = 0;
+
+ErrorSystemRegReleaseAddrRegion:
+ OSPCIReleaseAddrRegion(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM, SYS_APOLLO_REG_SYS_OFFSET, SYS_APOLLO_REG_SYS_SIZE);
+ psSysData->sSystemRegCpuPBase.uiAddr = 0;
+ psSysData->uiSystemRegSize = 0;
+
+ErrorPCIReleaseDevice:
+ OSPCIReleaseDev(psSysData->hRGXPCI);
+ psSysData->hRGXPCI = IMG_NULL;
+
+ return eError;
+}
+
+PVRSRV_ERROR SysDebugInfo(PVRSRV_SYSTEM_CONFIG *psSysConfig, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData = psSysConfig->pasDevices[0].hSysData;
+ IMG_UINT32 ui32RegVal;
+
+ PVR_UNREFERENCED_PARAMETER(psSysConfig);
+
+ PVR_DUMPDEBUG_LOG(("------[ rgx_tc system debug ]------"));
+
+ /* Read the temperature */
+ eError = SPI_Read(psSysData->pvSystemRegCpuVBase, TCF_TEMP_SENSOR_SPI_OFFSET, &ui32RegVal);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SysDebugInfo: SPI_Read failed for register 0x%x (0x%x)", TCF_TEMP_SENSOR_SPI_OFFSET, eError));
+ goto SysDebugInfo_exit;
+ }
+
+ PVR_DUMPDEBUG_LOG(("Chip temperature: %d degrees C", TCF_TEMP_SENSOR_TO_C(ui32RegVal)));
+
+ eError = SPI_Read(psSysData->pvSystemRegCpuVBase, 0x2, &ui32RegVal);
+ PVR_DUMPDEBUG_LOG(("PLL status: %x", ui32RegVal));
+
+SysDebugInfo_exit:
+ return eError;
+}
+
+#else
+
+static IMG_VOID SPI_Write(IMG_VOID *pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value)
+{
+ OSWriteHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_ADDR_RDNWR, ui32Offset);
+ OSWriteHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_WDATA, ui32Value);
+ OSWriteHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_GO, TCF_SPI_MST_GO_MASK);
+ OSWaitus(1000);
+}
+
+static PVRSRV_ERROR SPI_Read(IMG_VOID *pvLinRegBaseAddr,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 *pui32Value)
+{
+ IMG_UINT32 ui32Count = 0;
+
+ OSWriteHWReg32(pvLinRegBaseAddr,
+ TCF_CLK_CTRL_TCF_SPI_MST_ADDR_RDNWR,
+ TCF_SPI_MST_RDNWR_MASK | ui32Offset);
+ OSWriteHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_GO, TCF_SPI_MST_GO_MASK);
+ OSWaitus(1000);
+
+ while (((OSReadHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_STATUS)) != 0x08) &&
+ (ui32Count < 10000))
+ {
+ ui32Count++;
+ }
+
+ if (ui32Count < 10000)
+ {
+ *pui32Value = OSReadHWReg32(pvLinRegBaseAddr, TCF_CLK_CTRL_TCF_SPI_MST_RDATA);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SPI_Read: Time out reading SPI register (0x%x)", ui32Offset));
+ return PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ }
+
+ return PVRSRV_OK;
+}
+
+#define pol(base,reg,val,msk) \
+ do { \
+ int polnum; \
+ for (polnum = 0; polnum < 500; polnum++) \
+ { \
+ if ((OSReadHWReg32(base, reg) & msk) == val) \
+ { \
+ break; \
+ } \
+ OSSleepms(1); \
+ } \
+ if (polnum == 500) \
+ { \
+ PVR_DPF((PVR_DBG_WARNING, "Pol failed for register: 0x%08X", (unsigned int)reg)); \
+ } \
+ } while (0)
+
+#define polrgx(reg,val,msk) pol(pvRegsBaseKM, reg, val, msk)
+
+static IMG_VOID RGXInitBistery(IMG_CPU_PHYADDR sRegisters, IMG_UINT32 ui32Size)
+{
+ IMG_VOID *pvRegsBaseKM = OSMapPhysToLin(sRegisters, ui32Size, 0);
+ IMG_UINT instance;
+ IMG_UINT i;
+
+ /* Force clocks on */
+ OSWriteHWReg32(pvRegsBaseKM, 0, 0x55555555);
+ OSWriteHWReg32(pvRegsBaseKM, 4, 0x55555555);
+
+ polrgx(0xa18, 0x05000000, 0x05000000);
+ OSWriteHWReg32(pvRegsBaseKM, 0xa10, 0x048000b0);
+ OSWriteHWReg32(pvRegsBaseKM, 0xa08, 0x55111111);
+ polrgx(0xa18, 0x05000000, 0x05000000);
+
+ /* Clear PDS CSRM and USRM to prevent ERRORs at end of test */
+ OSWriteHWReg32(pvRegsBaseKM, 0x630, 0x1);
+ OSWriteHWReg32(pvRegsBaseKM, 0x648, 0x1);
+ OSWriteHWReg32(pvRegsBaseKM, 0x608, 0x1);
+
+ /* Run BIST for SLC (43) */
+ /* Reset BIST */
+ OSWriteHWReg32(pvRegsBaseKM, 0x7000, 0x8);
+ OSWaitus(100);
+
+ /* Clear BIST controller */
+ OSWriteHWReg32(pvRegsBaseKM, 0x7000, 0x10);
+ OSWriteHWReg32(pvRegsBaseKM, 0x7000, 0);
+ OSWaitus(100);
+
+ for (i = 0; i < 3; i++)
+ {
+ IMG_UINT32 ui32Pol = i == 2 ? 0x10000 : 0x20000;
+
+ /* Start BIST */
+ OSWriteHWReg32(pvRegsBaseKM, 0x7000, 0x4);
+
+ OSWaitus(100);
+
+ /* Wait for pause */
+ polrgx(0x7000, ui32Pol, ui32Pol);
+ }
+ OSWaitus(100);
+
+ /* Check results for 43 RAMs */
+ polrgx(0x7010, 0xffffffff, 0xffffffff);
+ polrgx(0x7014, 0x7, 0x7);
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7000, 8);
+ OSWriteHWReg32(pvRegsBaseKM, 0x7008, 0);
+ OSWriteHWReg32(pvRegsBaseKM, 0x7000, 6);
+ polrgx(0x7000, 0x00010000, 0x00010000);
+ OSWaitus(100);
+
+ polrgx(0x75B0, 0, ~0U);
+ polrgx(0x75B4, 0, ~0U);
+ polrgx(0x75B8, 0, ~0U);
+ polrgx(0x75BC, 0, ~0U);
+ polrgx(0x75C0, 0, ~0U);
+ polrgx(0x75C4, 0, ~0U);
+ polrgx(0x75C8, 0, ~0U);
+ polrgx(0x75CC, 0, ~0U);
+
+ /* Sidekick */
+ OSWriteHWReg32(pvRegsBaseKM, 0x7040, 8);
+ OSWaitus(100);
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7040, 0x10);
+ //OSWriteHWReg32(pvRegsBaseKM, 0x7000, 0);
+ OSWaitus(100);
+
+ for (i = 0; i < 3; i++)
+ {
+ IMG_UINT32 ui32Pol = i == 2 ? 0x10000 : 0x20000;
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7040, 4);
+ OSWaitus(100);
+ polrgx(0x7040, ui32Pol, ui32Pol);
+ }
+
+ OSWaitus(100);
+ polrgx(0x7050, 0xffffffff, 0xffffffff);
+ polrgx(0x7054, 0xffffffff, 0xffffffff);
+ polrgx(0x7058, 0x1, 0x1);
+
+ /* USC */
+ for (instance = 0; instance < 4; instance++)
+ {
+ OSWriteHWReg32(pvRegsBaseKM, 0x8010, instance);
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7088, 8);
+ OSWaitus(100);
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7088, 0x10);
+ OSWaitus(100);
+
+ for (i = 0; i < 3; i++)
+ {
+ IMG_UINT32 ui32Pol = i == 2 ? 0x10000 : 0x20000;
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7088, 4);
+ OSWaitus(100);
+ polrgx(0x7088, ui32Pol, ui32Pol);
+ }
+
+ OSWaitus(100);
+ polrgx(0x7098, 0xffffffff, 0xffffffff);
+ polrgx(0x709c, 0xffffffff, 0xffffffff);
+ polrgx(0x70a0, 0x3f, 0x3f);
+ }
+
+ /* tpumcul0 DustA and DustB */
+ for (instance = 0; instance < 2; instance++)
+ {
+ OSWriteHWReg32(pvRegsBaseKM, 0x8018, instance);
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7380, 8);
+ OSWaitus(100);
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7380, 0x10);
+ OSWaitus(100);
+
+ for (i = 0; i < 3; i++)
+ {
+ IMG_UINT32 ui32Pol = i == 2 ? 0x10000 : 0x20000;
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7380, 4);
+ OSWaitus(100);
+ polrgx(0x7380, ui32Pol, ui32Pol);
+ }
+
+ OSWaitus(100);
+ polrgx(0x7390, 0x1fff, 0x1fff);
+ }
+
+ /* TA */
+ OSWriteHWReg32(pvRegsBaseKM, 0x7500, 8);
+ OSWaitus(100);
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7500, 0x10);
+ OSWaitus(100);
+
+ for (i = 0; i < 3; i++)
+ {
+ IMG_UINT32 ui32Pol = i == 2 ? 0x10000 : 0x20000;
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7500, 4);
+ OSWaitus(100);
+ polrgx(0x7500, ui32Pol, ui32Pol);
+ }
+
+ OSWaitus(100);
+ polrgx(0x7510, 0x1fffffff, 0x1fffffff);
+
+ /* Rasterisation */
+ OSWriteHWReg32(pvRegsBaseKM, 0x7540, 8);
+ OSWaitus(100);
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7540, 0x10);
+ OSWaitus(100);
+
+ for (i = 0; i < 3; i++)
+ {
+ IMG_UINT32 ui32Pol = i == 2 ? 0x10000 : 0x20000;
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7540, 4);
+ OSWaitus(100);
+ polrgx(0x7540, ui32Pol, ui32Pol);
+ }
+
+ OSWaitus(100);
+ polrgx(0x7550, 0xffffffff, 0xffffffff);
+ polrgx(0x7554, 0xffffffff, 0xffffffff);
+ polrgx(0x7558, 0xf, 0xf);
+
+ /* hub_bifpmache */
+ OSWriteHWReg32(pvRegsBaseKM, 0x7588, 8);
+ OSWaitus(100);
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7588, 0x10);
+ OSWaitus(100);
+
+ for (i = 0; i < 3; i++)
+ {
+ IMG_UINT32 ui32Pol = i == 2 ? 0x10000 : 0x20000;
+
+ OSWriteHWReg32(pvRegsBaseKM, 0x7588, 4);
+ OSWaitus(100);
+ polrgx(0x7588, ui32Pol, ui32Pol);
+ }
+
+ OSWaitus(100);
+ polrgx(0x7598, 0xffffffff, 0xffffffff);
+ polrgx(0x759c, 0xffffffff, 0xffffffff);
+ polrgx(0x75a0, 0x1111111f, 0x1111111f);
+
+ OSUnMapPhysToLin(pvRegsBaseKM, ui32Size, 0);
+}
+
+static IMG_VOID ApolloHardReset(SYS_DATA *psSysData)
+{
+ IMG_UINT32 ui32Value;
+
+ ui32Value = (0x1 << GLB_CLKG_EN_SHIFT);
+ ui32Value |= (0x1 << SCB_RESETN_SHIFT);
+ ui32Value |= (0x1 << PDP2_RESETN_SHIFT);
+ ui32Value |= (0x1 << PDP1_RESETN_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_CLK_AND_RST_CTRL, ui32Value);
+
+ ui32Value |= (0x1 << DDR_RESETN_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_CLK_AND_RST_CTRL, ui32Value);
+
+ ui32Value |= (0x1 << DUT_RESETN_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_CLK_AND_RST_CTRL, ui32Value);
+
+ ui32Value |= (0x1 << DUT_DCM_RESETN_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_CLK_AND_RST_CTRL, ui32Value);
+
+ OSSleepms(4);
+ pol(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_DCM_LOCK_STATUS, 0x7, DCM_LOCK_STATUS_MASK);
+}
+
+#undef pol
+#undef polrgx
+
+static PVRSRV_ERROR SetClocks(SYS_DATA *psSysData, IMG_UINT32 ui32CoreClock, IMG_UINT32 ui32MemClock)
+{
+ IMG_CPU_PHYADDR sPLLRegCpuPBase;
+ IMG_VOID *pvPLLRegCpuVBase;
+ IMG_UINT32 ui32Value;
+ PVRSRV_ERROR eError;
+
+ /* Reserve the PLL register region and map the registers in */
+ eError = OSPCIRequestAddrRegion(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM, SYS_APOLLO_REG_PLL_OFFSET, SYS_APOLLO_REG_PLL_SIZE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to request the PLL register region (%d)", __FUNCTION__, eError));
+
+ return eError;
+ }
+ sPLLRegCpuPBase.uiAddr = OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM) + SYS_APOLLO_REG_PLL_OFFSET;
+
+ pvPLLRegCpuVBase = OSMapPhysToLin(sPLLRegCpuPBase, SYS_APOLLO_REG_PLL_SIZE, 0);
+ if (pvPLLRegCpuVBase == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map PLL registers", __FUNCTION__));
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Modify the core clock */
+ OSWriteHWReg32(pvPLLRegCpuVBase, TCF_PLL_PLL_CORE_CLK0, (ui32CoreClock / 1000000));
+
+ ui32Value = 0x1 << PLL_CORE_DRP_GO_SHIFT;
+ OSWriteHWReg32(pvPLLRegCpuVBase, TCF_PLL_PLL_CORE_DRP_GO, ui32Value);
+
+ OSSleepms(600);
+
+ /* Modify the memory clock */
+ OSWriteHWReg32(pvPLLRegCpuVBase, TCF_PLL_PLL_MEMIF_CLK0, (ui32MemClock / 1000000));
+
+ ui32Value = 0x1 << PLL_MEM_DRP_GO_SHIFT;
+ OSWriteHWReg32(pvPLLRegCpuVBase, TCF_PLL_PLL_MEM_DRP_GO, ui32Value);
+
+ OSSleepms(600);
+
+ /* Unmap and release the PLL registers since we no longer need access to them */
+ OSUnMapPhysToLin(pvPLLRegCpuVBase, SYS_APOLLO_REG_PLL_SIZE, 0);
+ OSPCIReleaseAddrRegion(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM, SYS_APOLLO_REG_PLL_OFFSET, SYS_APOLLO_REG_PLL_SIZE);
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR PCIInitDev(SYS_DATA *psSysData)
+{
+ PVRSRV_DEVICE_CONFIG *psDevice = &gsSysConfig.pasDevices[0];
+ IMG_CPU_PHYADDR sApolloRegCpuPBase;
+ IMG_UINT32 uiApolloRegSize;
+ IMG_UINT32 ui32Value;
+ PVRSRV_ERROR eError;
+
+#if defined(LDM_PCI) || defined(SUPPORT_DRM)
+ /* Use the pci_dev structure pointer from module.c */
+ PVR_ASSERT(gpsPVRLDMDev != IMG_NULL);
+
+ psSysData->hRGXPCI = OSPCISetDev((IMG_VOID *)gpsPVRLDMDev, HOST_PCI_INIT_FLAGS);
+#else
+ psSysData->hRGXPCI = OSPCIAcquireDev(SYS_RGX_DEV_VENDOR_ID, SYS_RGX_DEV_DEVICE_ID, HOST_PCI_INIT_FLAGS);
+#endif /* defined(LDM_PCI) || defined(SUPPORT_DRM) */
+ if (!psSysData->hRGXPCI)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire PCI device", __FUNCTION__));
+ return PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND;
+ }
+
+ /* Get Apollo register information */
+ sApolloRegCpuPBase.uiAddr = OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM);
+ uiApolloRegSize = OSPCIAddrRangeLen(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM);
+
+ /* Check the address range is large enough. */
+ if (uiApolloRegSize < SYS_APOLLO_REG_REGION_SIZE)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Apollo register region isn't big enough (was 0x%08X, required 0x%08X)",
+ __FUNCTION__, uiApolloRegSize, SYS_APOLLO_REG_REGION_SIZE));
+
+ eError = PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
+ goto ErrorPCIReleaseDevice;
+ }
+
+ /* The Apollo register range contains several register regions. Request only the system control register region */
+ eError = OSPCIRequestAddrRegion(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM, SYS_APOLLO_REG_SYS_OFFSET, SYS_APOLLO_REG_SYS_SIZE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to request the system register region", __FUNCTION__));
+
+ goto ErrorPCIReleaseDevice;
+ }
+ psSysData->sSystemRegCpuPBase.uiAddr = sApolloRegCpuPBase.uiAddr + SYS_APOLLO_REG_SYS_OFFSET;
+ psSysData->uiSystemRegSize = SYS_APOLLO_REG_REGION_SIZE;
+
+ /* Setup Rogue register information */
+ psDevice->sRegsCpuPBase.uiAddr = OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_RGX_REG_PCI_BASENUM);
+ psDevice->ui32RegsSize = OSPCIAddrRangeLen(psSysData->hRGXPCI, SYS_RGX_REG_PCI_BASENUM);
+
+ /* Save data for this device */
+ psDevice->hSysData = (IMG_HANDLE)psSysData;
+
+ /* Check the address range is large enough. */
+ if (psDevice->ui32RegsSize < SYS_RGX_REG_REGION_SIZE)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Rogue register region isn't big enough (was 0x%08x, required 0x%08x)",
+ __FUNCTION__, psDevice->ui32RegsSize, SYS_RGX_REG_REGION_SIZE));
+
+ eError = PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
+ goto ErrorSystemRegReleaseAddrRegion;
+ }
+
+ /* Reserve the address range */
+ eError = OSPCIRequestAddrRange(psSysData->hRGXPCI, SYS_RGX_REG_PCI_BASENUM);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Rogue register memory region not available", __FUNCTION__));
+
+ goto ErrorSystemRegReleaseAddrRegion;
+ }
+
+ /* Map in system registers so we can:
+ - Configure the memory mode (LMA, UMA or LMA/UMA hybrid)
+ - Hard reset Apollo
+ - Run BIST
+ - Clear interrupts
+ */
+ psSysData->pvSystemRegCpuVBase = OSMapPhysToLin(psSysData->sSystemRegCpuPBase, psSysData->uiSystemRegSize, 0);
+ if (psSysData->pvSystemRegCpuVBase == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map system registers", __FUNCTION__));
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorRGXRegReleaseAddrRange;
+ }
+
+ eError = ApolloFlasherSetup(&psSysData->hFlashData,
+ ApolloFlashInit,
+ ApolloFlashWrite,
+ ApolloFlashGetStatus,
+ (IMG_VOID *)psSysData);
+
+ if (eError != PVRSRV_OK)
+ {
+ if (eError != PVRSRV_ERROR_NOT_IMPLEMENTED)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Apollo flash setup failed. You will not be able to flash Apollo.", __FUNCTION__));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Support for flashing Apollo has not been implemented.", __FUNCTION__));
+ }
+ psSysData->hFlashData = NULL;
+ }
+
+ ApolloHardReset(psSysData);
+ RGXInitBistery(psDevice->sRegsCpuPBase, psDevice->ui32RegsSize);
+ ApolloHardReset(psSysData);
+
+ eError = InitMemory(&gsSysConfig, psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorCleanupFlashingModule;
+ }
+
+ if (SetClocks(psSysData, ui32CoreClockSpeed, ui32MemClockSpeed) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the core and memory clocks", __FUNCTION__));
+ }
+
+ /* Enable the rogue PLL (defaults to 3x), giving a Rogue clock of 3 x RGX_TC_CORE_CLOCK_SPEED */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_DUT_CONTROL_1);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_DUT_CONTROL_1, ui32Value & 0xFFFFFFFB);
+
+ ((RGX_DATA *)psDevice->hDevData)->psRGXTimingInfo->ui32CoreClockSpeed = ui32CoreClockSpeed * 3;
+
+ OSSleepms(600);
+
+ /* Enable the temperature sensor */
+ SPI_Write(psSysData->pvSystemRegCpuVBase, 0x3, 0x46);
+
+
+ /* Override the system name if we can get the system info string */
+ psSysData->pszSystemInfoString = GetSystemInfoString(psSysData);
+ if (psSysData->pszSystemInfoString)
+ {
+ gsSysConfig.pszSystemName = psSysData->pszSystemInfoString;
+ }
+
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+ eError = OSPCIIRQ(psSysData->hRGXPCI, &psSysData->ui32IRQ);
+#else
+ eError = OSPCIIRQ(psSysData->hRGXPCI, &psDevice->ui32IRQ);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't get IRQ", __FUNCTION__));
+
+ goto ErrorDeInitMemory;
+ }
+
+#if !defined(SUPPORT_DRM)
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+ /* Register our handler */
+ eError = OSInstallSystemLISR(&psSysData->hLISR,
+ psSysData->ui32IRQ,
+#if !defined(UNDER_CE)
+ IMG_NULL,
+#else
+ (PVR_IRQ_PRIV_DATA *)&psSysData->sSystemRegCpuPBase,
+#endif
+ SystemISRHandler,
+ psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to install the system device interrupt handler", __FUNCTION__));
+
+ goto ErrorDeInitMemory;
+ }
+#else
+ psDevice->pfnInterruptHandled = SystemISRHandler;
+
+ EnableInterrupt(psSysData, (0x1 << EXT_INT_SHIFT) | (0x1 << PDP1_INT_SHIFT));
+#endif
+#endif /* !defined(SUPPORT_DRM) */
+
+ return PVRSRV_OK;
+
+ErrorDeInitMemory:
+ DeInitMemory(&gsSysConfig, psSysData);
+
+ErrorCleanupFlashingModule:
+ if (psSysData->hFlashData != NULL)
+ {
+ ApolloFlasherCleanup(psSysData->hFlashData);
+ }
+
+ OSUnMapPhysToLin(psSysData->pvSystemRegCpuVBase, psSysData->uiSystemRegSize, 0);
+ psSysData->pvSystemRegCpuVBase = NULL;
+
+ErrorRGXRegReleaseAddrRange:
+ OSPCIReleaseAddrRange(psSysData->hRGXPCI, SYS_RGX_REG_PCI_BASENUM);
+ psDevice->sRegsCpuPBase.uiAddr = 0;
+ psDevice->ui32RegsSize = 0;
+
+ErrorSystemRegReleaseAddrRegion:
+ OSPCIReleaseAddrRegion(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM, SYS_APOLLO_REG_SYS_OFFSET, SYS_APOLLO_REG_SYS_SIZE);
+ psSysData->sSystemRegCpuPBase.uiAddr = 0;
+ psSysData->uiSystemRegSize = 0;
+
+ErrorPCIReleaseDevice:
+ OSPCIReleaseDev(psSysData->hRGXPCI);
+ psSysData->hRGXPCI = IMG_NULL;
+
+ return eError;
+}
+
+PVRSRV_ERROR SysDebugInfo(PVRSRV_SYSTEM_CONFIG *psSysConfig, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData = psSysConfig->pasDevices[0].hSysData;
+ IMG_UINT32 ui32RegOffset;
+ IMG_UINT32 ui32RegVal;
+
+ PVR_DUMPDEBUG_LOG(("------[ rgx_tc system debug ]------"));
+
+ /* Read the temperature */
+ ui32RegOffset = 0x5;
+ eError = SPI_Read(psSysData->pvSystemRegCpuVBase, ui32RegOffset, &ui32RegVal);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SysDebugInfo: SPI_Read failed for register 0x%x (0x%x)", ui32RegOffset, eError));
+ goto SysDebugInfo_exit;
+ }
+
+ PVR_DUMPDEBUG_LOG(("Chip temperature: %d degrees C", (ui32RegVal * 233 / 4096) - 66));
+
+SysDebugInfo_exit:
+ return eError;
+}
+
+#endif
+
+#if (TC_MEMORY_CONFIG == TC_MEMORY_LOCAL) || (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID) || (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED)
+static PVRSRV_ERROR AcquireLocalMemory(SYS_DATA *psSysData, IMG_CPU_PHYADDR *psMemCpuPAddr, IMG_SIZE_T *puiMemSize)
+{
+ IMG_UINT16 uiDevID;
+ IMG_UINT32 uiMemSize;
+ IMG_UINT32 uiMemLimit;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32PCIVersion;
+ PVRSRV_ERROR eError;
+ IMG_CPU_PHYADDR sHostFPGARegCpuPBase;
+ IMG_VOID *pvHostFPGARegCpuVBase;
+
+ OSPCIDevID(psSysData->hRGXPCI, &uiDevID);
+ if (uiDevID != SYS_RGX_DEV_DEVICE_ID)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unexpected device ID 0x%X", __FUNCTION__, uiDevID));
+
+ return PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND;
+ }
+
+ /* To get some of the version information we need to read from a register that we don't normally have
+ mapped. Map it temporarily (without trying to reserve it) to get the information we need. */
+ sHostFPGARegCpuPBase.uiAddr = OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM) + 0x40F0;
+ pvHostFPGARegCpuVBase = OSMapPhysToLin(sHostFPGARegCpuPBase, 0x04, 0);
+
+ ui32Value = OSReadHWReg32(pvHostFPGARegCpuVBase, 0);
+
+ /* Unmap the register now that we no longer need it */
+ OSUnMapPhysToLin(pvHostFPGARegCpuVBase, 0x04, 0);
+
+ ui32PCIVersion = HEXIDECIMAL_TO_DECIMAL((ui32Value & 0x00FF0000) >> 16);
+
+ if (ui32PCIVersion < 18)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"\n*********************************************************************************"));
+ PVR_DPF((PVR_DBG_WARNING, "%s: You have an outdated test chip fpga image.", __FUNCTION__));
+ PVR_DPF((PVR_DBG_WARNING, "Restricting available graphics memory to 512mb as a workaround."));
+ PVR_DPF((PVR_DBG_WARNING, "This restriction may cause test failures for those tests"));
+ PVR_DPF((PVR_DBG_WARNING, "that require a large amount of graphics memory."));
+ PVR_DPF((PVR_DBG_WARNING, "Please speak to your customer support representative about"));
+ PVR_DPF((PVR_DBG_WARNING, "upgrading your test chip fpga image."));
+ PVR_DPF((PVR_DBG_WARNING, "\n********************************************************************************"));
+
+ /* limit to 512mb */
+ uiMemLimit = 512 * 1024 * 1024;
+
+ uiMemSize = OSPCIAddrRangeLen(psSysData->hRGXPCI, SYS_DEV_MEM_PCI_BASENUM);
+ }
+ else
+ {
+ uiMemLimit = SYS_DEV_MEM_REGION_SIZE;
+
+ uiMemSize = OSPCIAddrRangeLen(psSysData->hRGXPCI, SYS_DEV_MEM_PCI_BASENUM) - SYS_DEV_MEM_BROKEN_BYTES;
+ }
+
+ if (uiMemLimit > uiMemSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: Device memory region smaller than requested (got 0x%08X, requested 0x%08X)",
+ __FUNCTION__, uiMemSize, uiMemLimit));
+ }
+ else if (uiMemLimit < uiMemSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: Limiting device memory region size to 0x%08X from 0x%08X",
+ __FUNCTION__, uiMemLimit, uiMemSize));
+
+ uiMemSize = uiMemLimit;
+ }
+
+ /* Reserve the address region */
+ eError = OSPCIRequestAddrRegion(psSysData->hRGXPCI, SYS_DEV_MEM_PCI_BASENUM, 0, uiMemSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Device memory region not available", __FUNCTION__));
+
+ return eError;
+ }
+
+ /* Clear any BIOS-configured MTRRs */
+ eError = OSPCIClearResourceMTRRs(psSysData->hRGXPCI, SYS_DEV_MEM_PCI_BASENUM);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Failed to clear BIOS MTRRs", __FUNCTION__));
+ /* Soft-fail, the driver can limp along. */
+ }
+
+ psMemCpuPAddr->uiAddr = IMG_CAST_TO_CPUPHYADDR_UINT(OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_DEV_MEM_PCI_BASENUM));
+ *puiMemSize = (IMG_SIZE_T)uiMemSize;
+
+ return PVRSRV_OK;
+}
+
+static INLINE void ReleaseLocalMemory(SYS_DATA *psSysData, IMG_CPU_PHYADDR *psMemCpuPAddr, IMG_SIZE_T uiMemSize)
+{
+ IMG_CPU_PHYADDR sMemCpuPBaseAddr;
+ IMG_UINT32 uiOffset;
+
+ sMemCpuPBaseAddr.uiAddr = IMG_CAST_TO_CPUPHYADDR_UINT(OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_DEV_MEM_PCI_BASENUM));
+
+ PVR_ASSERT(psMemCpuPAddr->uiAddr >= sMemCpuPBaseAddr.uiAddr);
+
+ uiOffset = (IMG_UINT32)(IMG_UINTPTR_T)(psMemCpuPAddr->uiAddr - sMemCpuPBaseAddr.uiAddr);
+
+ OSPCIReleaseAddrRegion(psSysData->hRGXPCI, SYS_DEV_MEM_PCI_BASENUM, uiOffset, (IMG_UINT32)uiMemSize);
+}
+#endif /* (TC_MEMORY_CONFIG == TC_MEMORY_LOCAL) || (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID) || (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED) */
+
+#if (TC_MEMORY_CONFIG == TC_MEMORY_LOCAL)
+static PVRSRV_ERROR InitLocalMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+ IMG_UINT32 ui32HeapNum = 0;
+ IMG_UINT32 ui32Value;
+ PVRSRV_ERROR eError;
+
+ eError = AcquireLocalMemory(psSysData, &psSysData->sLocalMemCpuPBase, &psSysData->uiLocalMemSize);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ /* Setup the Rogue heap */
+ psSysConfig->pasPhysHeaps[ui32HeapNum].sStartAddr.uiAddr =
+ psSysData->sLocalMemCpuPBase.uiAddr;
+ psSysConfig->pasPhysHeaps[ui32HeapNum].uiSize =
+ psSysData->uiLocalMemSize
+#if defined(SUPPORT_DISPLAY_CLASS) || defined(SUPPORT_DRM_DC_MODULE)
+ - RGX_TC_RESERVE_DC_MEM_SIZE
+#endif
+#if defined(SUPPORT_ION)
+ - RGX_TC_RESERVE_ION_MEM_SIZE
+#endif
+ ;
+ ui32HeapNum++;
+
+#if defined(SUPPORT_DISPLAY_CLASS) || defined(SUPPORT_DRM_DC_MODULE)
+ /* Setup the DC heap */
+ psSysConfig->pasPhysHeaps[ui32HeapNum].sStartAddr.uiAddr =
+ psSysConfig->pasPhysHeaps[ui32HeapNum - 1].sStartAddr.uiAddr +
+ psSysConfig->pasPhysHeaps[ui32HeapNum - 1].uiSize;
+ psSysConfig->pasPhysHeaps[ui32HeapNum].uiSize = RGX_TC_RESERVE_DC_MEM_SIZE;
+ ui32HeapNum++;
+#endif
+
+#if defined(SUPPORT_ION)
+ /* Setup the ion heap */
+ psSysConfig->pasPhysHeaps[ui32HeapNum].sStartAddr.uiAddr =
+ psSysConfig->pasPhysHeaps[ui32HeapNum - 1].sStartAddr.uiAddr +
+ psSysConfig->pasPhysHeaps[ui32HeapNum - 1].uiSize;
+ psSysConfig->pasPhysHeaps[ui32HeapNum].uiSize = RGX_TC_RESERVE_ION_MEM_SIZE;
+ ui32HeapNum++;
+#endif
+
+ /* Configure Apollo for regression compatibility (i.e. local memory) mode */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ ui32Value &= ~(ADDRESS_FORCE_MASK | PCI_TEST_MODE_MASK | HOST_ONLY_MODE_MASK | HOST_PHY_MODE_MASK);
+ ui32Value |= (0x1 << ADDRESS_FORCE_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL, ui32Value);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ OSWaitus(10);
+
+ return PVRSRV_OK;
+}
+
+static void DeInitLocalMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+ ReleaseLocalMemory(psSysData, &psSysData->sLocalMemCpuPBase, psSysData->uiLocalMemSize);
+
+ psSysConfig->pasPhysHeaps[0].sStartAddr.uiAddr = 0;
+ psSysConfig->pasPhysHeaps[0].uiSize = 0;
+ psSysConfig->pasPhysHeaps[1].sStartAddr.uiAddr = 0;
+ psSysConfig->pasPhysHeaps[1].uiSize = 0;
+
+ /* Set the register back to the default value */
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL, 0x1 << ADDRESS_FORCE_SHIFT);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ OSWaitus(10);
+}
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HOST)
+static PVRSRV_ERROR InitHostMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+ IMG_UINT32 ui32Value;
+
+ PVR_UNREFERENCED_PARAMETER(psSysConfig);
+
+ /* Configure Apollo for host only mode */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ ui32Value &= ~(ADDRESS_FORCE_MASK | PCI_TEST_MODE_MASK | HOST_ONLY_MODE_MASK | HOST_PHY_MODE_MASK);
+ ui32Value |= (0x1 << HOST_ONLY_MODE_SHIFT);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL, ui32Value);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ OSWaitus(10);
+
+ return PVRSRV_OK;
+}
+
+static void DeInitHostMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysConfig);
+
+ /* Set the register back to the default value */
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL, 0x1 << ADDRESS_FORCE_SHIFT);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ OSWaitus(10);
+}
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID)
+static PVRSRV_ERROR InitHybridMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+ IMG_UINT32 ui32Value;
+ PVRSRV_ERROR eError;
+
+ eError = AcquireLocalMemory(psSysData, &psSysData->sLocalMemCpuPBase, &psSysData->uiLocalMemSize);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ /* Rogue is using system memory so there is no additional heap setup needed */
+
+ /* Setup the DC heap */
+ psSysConfig->pasPhysHeaps[1].sStartAddr.uiAddr = psSysData->sLocalMemCpuPBase.uiAddr;
+ psSysConfig->pasPhysHeaps[1].uiSize = psSysData->uiLocalMemSize;
+
+ /* Configure Apollo for host physical (i.e. hybrid) mode */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ ui32Value &= ~(ADDRESS_FORCE_MASK | PCI_TEST_MODE_MASK | HOST_ONLY_MODE_MASK | HOST_PHY_MODE_MASK);
+ ui32Value |= ((0x1 << HOST_ONLY_MODE_SHIFT) | (0x1 << HOST_PHY_MODE_SHIFT));
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL, ui32Value);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ OSWaitus(10);
+
+ /* Setup the start address of the 1GB window which is redirected to local memory */
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_HOST_PHY_OFFSET, psSysData->sLocalMemCpuPBase.uiAddr);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_HOST_PHY_OFFSET);
+ OSWaitus(10);
+
+ return PVRSRV_OK;
+}
+
+static void DeInitHybridMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+ ReleaseLocalMemory(psSysData, &psSysData->sLocalMemCpuPBase, psSysData->uiLocalMemSize);
+
+ psSysConfig->pasPhysHeaps[1].sStartAddr.uiAddr = 0;
+ psSysConfig->pasPhysHeaps[1].uiSize = 0;
+
+ /* Set the register back to the default value */
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL, 0x1 << ADDRESS_FORCE_SHIFT);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ OSWaitus(10);
+}
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED)
+static PVRSRV_ERROR InitDirectMappedMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+ IMG_UINT32 ui32Value;
+ PVRSRV_ERROR eError;
+
+ eError = AcquireLocalMemory(psSysData, &psSysData->sLocalMemCpuPBase, &psSysData->uiLocalMemSize);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ /* Setup the RGX heap */
+ psSysConfig->pasPhysHeaps[0].sStartAddr.uiAddr = psSysData->sLocalMemCpuPBase.uiAddr;
+ psSysConfig->pasPhysHeaps[0].uiSize = RGX_TC_RESERVE_SERVICES_MEM_SIZE;
+
+ PVR_ASSERT(psSysData->uiLocalMemSize >= psSysConfig->pasPhysHeaps[0].uiSize);
+
+ /* Configure Apollo for direct mapping mode */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ ui32Value &= ~(ADDRESS_FORCE_MASK | PCI_TEST_MODE_MASK | HOST_ONLY_MODE_MASK | HOST_PHY_MODE_MASK);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL, ui32Value);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ OSWaitus(10);
+
+ return PVRSRV_OK;
+}
+
+static void DeInitDirectMappedMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+ ReleaseLocalMemory(psSysData, &psSysData->sLocalMemCpuPBase, psSysData->uiLocalMemSize);
+
+ psSysConfig->pasPhysHeaps[0].sStartAddr.uiAddr = 0;
+ psSysConfig->pasPhysHeaps[0].uiSize = 0;
+
+ /* Set the register back to the default value */
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL, 0x1 << ADDRESS_FORCE_SHIFT);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_TEST_CTRL);
+ OSWaitus(10);
+}
+#endif
+
+static PVRSRV_ERROR InitMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+#if (TC_MEMORY_CONFIG == TC_MEMORY_LOCAL)
+ return InitLocalMemory(psSysConfig, psSysData);
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HOST)
+ return InitHostMemory(psSysConfig, psSysData);
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID)
+ return InitHybridMemory(psSysConfig, psSysData);
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED)
+ return InitDirectMappedMemory(psSysConfig, psSysData);
+#endif
+}
+
+static INLINE void DeInitMemory(PVRSRV_SYSTEM_CONFIG *psSysConfig, SYS_DATA *psSysData)
+{
+#if (TC_MEMORY_CONFIG == TC_MEMORY_LOCAL)
+ DeInitLocalMemory(psSysConfig, psSysData);
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HOST)
+ DeInitHostMemory(psSysConfig, psSysData);
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID)
+ DeInitHybridMemory(psSysConfig, psSysData);
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED)
+ DeInitDirectMappedMemory(psSysConfig, psSysData);
+#endif
+}
+
+static IMG_VOID EnableInterrupt(SYS_DATA *psSysData, IMG_UINT32 ui32InterruptFlag)
+{
+ IMG_UINT32 ui32Value;
+
+ /* Set sense to active high */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_OP_CFG);
+ ui32Value &= ~(INT_SENSE_MASK);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_OP_CFG, ui32Value);
+ OSWaitus(1000);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_OP_CFG);
+
+ /* Enable Rogue and PDP1 interrupts */
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_ENABLE);
+ ui32Value |= ui32InterruptFlag;
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_ENABLE, ui32Value);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_ENABLE);
+ OSWaitus(10);
+}
+
+static IMG_VOID DisableInterrupt(SYS_DATA *psSysData, IMG_UINT32 ui32InterruptFlag)
+{
+ IMG_UINT32 ui32Value;
+
+ ui32Value = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_ENABLE);
+ ui32Value &= ~(ui32InterruptFlag);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_ENABLE, ui32Value);
+
+ /* Flush register write */
+ (void)OSReadHWReg32(psSysData->pvSystemRegCpuVBase, TCF_CLK_CTRL_INTERRUPT_ENABLE);
+ OSWaitus(10);
+}
+
+static PVRSRV_ERROR ApolloFlashInit(IMG_VOID *pvData)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)pvData;
+
+ if (PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN) ||
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) ||
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "You cannot flash while the driver is running. Please unload the driver and run the tool again.\n"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ if (psSysData == NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ ApolloHardReset(psSysData);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Resetting Apollo to prepare for programming.\n"));
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, APOLLO_FLASH_RESET_OFFSET, 0);
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, APOLLO_FLASH_RESET_OFFSET, 1);
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR ApolloFlashWrite(IMG_VOID *pvData, const IMG_UINT32 *puiWord)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)pvData;
+
+ if (psSysData == NULL)
+ {
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ OSWriteHWReg32(psSysData->pvSystemRegCpuVBase, APOLLO_FLASH_DATA_WRITE_OFFSET, *puiWord);
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR ApolloFlashGetStatus(IMG_VOID *pvData,
+ IMG_UINT32 *puiWriteSpace,
+ FLASH_STATUS *peFlashStatus)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)pvData;
+ IMG_UINT32 uiStatus;
+ IMG_UINT16 uiProgramStatus;
+ IMG_UINT16 uiFifoStatus;
+
+ if (psSysData == NULL)
+ {
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ uiStatus = OSReadHWReg32(psSysData->pvSystemRegCpuVBase, APOLLO_FLASH_STAT_OFFSET);
+ uiFifoStatus = (uiStatus >> APOLLO_FLASH_FIFO_STATUS_SHIFT) & APOLLO_FLASH_FIFO_STATUS_MASK;
+ uiProgramStatus = (uiStatus >> APOLLO_FLASH_PROGAM_STATUS_SHIFT) & APOLLO_FLASH_PROGRAM_STATUS_MASK;
+
+ if (uiProgramStatus & APOLLO_FLASH_PROG_COMPLETE_BIT)
+ {
+ *peFlashStatus = FLASH_STATUS_FINISHED;
+ }
+ else if (uiProgramStatus & APOLLO_FLASH_PROG_FAILED_BIT)
+ {
+ *peFlashStatus = FLASH_STATUS_FAILED;
+ }
+ else if (!(uiProgramStatus & APOLLO_FLASH_INV_FILETYPE_BIT))
+ {
+ *peFlashStatus = FLASH_STATUS_FAILED;
+ }
+ else if (uiProgramStatus & APOLLO_FLASH_PROG_PROGRESS_BIT)
+ {
+ *peFlashStatus = FLASH_STATUS_IN_PROGRESS;
+ }
+ else
+ {
+ *peFlashStatus = FLASH_STATUS_WAITING;
+ }
+
+ *puiWriteSpace = APOLLO_FLASH_FIFO_SIZE - uiFifoStatus;
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_VOID PCIDeInitDev(SYS_DATA *psSysData)
+{
+ PVRSRV_DEVICE_CONFIG *psDevice = &gsSysConfig.pasDevices[0];
+
+#if !defined(SUPPORT_DRM)
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+ OSUninstallSystemLISR(psSysData->hLISR);
+ psSysData->hLISR = NULL;
+#else
+ DisableInterrupt(psSysData, (0x1 << EXT_INT_SHIFT) | (0x1 << PDP1_INT_SHIFT));
+#endif
+#endif
+
+ if (psSysData->pszSystemInfoString)
+ {
+ OSFreeMem(psSysData->pszSystemInfoString);
+ psSysData->pszSystemInfoString = NULL;
+ }
+
+ if (psSysData->hFlashData != NULL)
+ {
+ ApolloFlasherCleanup(psSysData->hFlashData);
+ }
+
+ DeInitMemory(&gsSysConfig, psSysData);
+
+ OSUnMapPhysToLin(psSysData->pvSystemRegCpuVBase, psSysData->uiSystemRegSize, 0);
+ psSysData->pvSystemRegCpuVBase = NULL;
+
+ OSPCIReleaseAddrRange(psSysData->hRGXPCI, SYS_RGX_REG_PCI_BASENUM);
+ psDevice->sRegsCpuPBase.uiAddr = 0;
+ psDevice->ui32RegsSize = 0;
+
+ OSPCIReleaseAddrRegion(psSysData->hRGXPCI, SYS_APOLLO_REG_PCI_BASENUM, SYS_APOLLO_REG_SYS_OFFSET, SYS_APOLLO_REG_SYS_SIZE);
+ psSysData->sSystemRegCpuPBase.uiAddr = 0;
+ psSysData->uiSystemRegSize = 0;
+
+ OSPCIReleaseDev(psSysData->hRGXPCI);
+ psSysData->hRGXPCI = IMG_NULL;
+}
+
+#if (TC_MEMORY_CONFIG == TC_MEMORY_LOCAL)
+static IMG_VOID TCLocalCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr)
+{
+ PVRSRV_SYSTEM_CONFIG *psSysConfig = (PVRSRV_SYSTEM_CONFIG *)hPrivData;
+
+ psDevPAddr->uiAddr = psCpuPAddr->uiAddr - psSysConfig->pasPhysHeaps[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL].sStartAddr.uiAddr;
+}
+
+static IMG_VOID TCLocalDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVRSRV_SYSTEM_CONFIG *psSysConfig = (PVRSRV_SYSTEM_CONFIG *)hPrivData;
+
+ psCpuPAddr->uiAddr = psDevPAddr->uiAddr + psSysConfig->pasPhysHeaps[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL].sStartAddr.uiAddr;
+}
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HOST) || (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID) || (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED)
+static IMG_VOID TCSystemCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(hPrivData);
+
+ psDevPAddr->uiAddr = psCpuPAddr->uiAddr;
+}
+
+static IMG_VOID TCSystemDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(hPrivData);
+
+ psCpuPAddr->uiAddr = (IMG_UINTPTR_T)psDevPAddr->uiAddr;
+}
+#endif /* (TC_MEMORY_CONFIG == TC_MEMORY_HOST) || (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID) || (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED) */
+
+PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ psSysData = OSAllocMem(sizeof *psSysData);
+ if (psSysData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psSysData, 0, sizeof *psSysData);
+
+ eError = PCIInitDev(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorFreeSysData;
+ }
+
+#if defined(SUPPORT_ION)
+#if TC_MEMORY_CONFIG == TC_MEMORY_LOCAL
+ {
+ /* Set up the ion heap according to the physical heap we created, by
+ passing down a private data struct that this system's IonInit()
+ should understand. This lets the ion support code continue to
+ work if the heap configuration changes. */
+ ION_TC_PRIVATE_DATA sIonPrivateData = {
+ .uiHeapBase = gsSysConfig.pasPhysHeaps[2].sStartAddr.uiAddr,
+ .uiHeapSize = RGX_TC_RESERVE_ION_MEM_SIZE,
+ .ui32IonPhysHeapID = gsSysConfig.pasPhysHeaps[2].ui32PhysHeapID,
+ .sPCIAddrRangeStart = gsSysConfig.pasPhysHeaps[0].sStartAddr
+ };
+
+ IonInit(&sIonPrivateData);
+ }
+#elif TC_MEMORY_CONFIG == TC_MEMORY_HYBRID
+ IonInit(NULL);
+#else
+#error Ion support requires TC_MEMORY_LOCAL or TC_MEMORY_HYBRID
+#endif /* TC_MEMORY_CONFIG */
+#endif /* defined(SUPPORT_ION) */
+
+ (void)SysAcquireSystemData((IMG_HANDLE)psSysData);
+
+ *ppsSysConfig = &gsSysConfig;
+
+ return PVRSRV_OK;
+
+ErrorFreeSysData:
+ OSFreeMem(psSysData);
+
+ return eError;
+}
+
+IMG_VOID SysDestroyConfigData(PVRSRV_SYSTEM_CONFIG *psSysConfig)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)psSysConfig->pasDevices[0].hSysData;
+
+ PCIDeInitDev(psSysData);
+
+ (void)SysReleaseSystemData((IMG_HANDLE)psSysData);
+}
+
+PVRSRV_ERROR SysAcquireSystemData(IMG_HANDLE hSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)hSysData;
+
+ if (psSysData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSysData->uiRefCount++;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysReleaseSystemData(IMG_HANDLE hSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)hSysData;
+
+ if (psSysData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ PVR_ASSERT(psSysData->uiRefCount != 0);
+ psSysData->uiRefCount--;
+
+ if (psSysData->uiRefCount == 0)
+ {
+ OSFreeMem(psSysData);
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+PVRSRV_ERROR SysInstallDeviceLISR(IMG_UINT32 ui32IRQ,
+ IMG_CHAR *pszName,
+ PFN_LISR pfnLISR,
+ IMG_PVOID pvData,
+ IMG_HANDLE *phLISRData)
+{
+ PVRSRV_DEVICE_CONFIG *psDevice = &gsSysConfig.pasDevices[0];
+ SYS_DATA *psSysData = (SYS_DATA *)psDevice->hSysData;
+ IMG_UINT32 ui32InterruptFlag;
+
+ switch (ui32IRQ)
+ {
+ case 0:
+ ui32InterruptFlag = (0x1 << EXT_INT_SHIFT);
+ break;
+ case 1:
+ ui32InterruptFlag = (0x1 << PDP1_INT_SHIFT);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: No device matching IRQ %d", __FUNCTION__, ui32IRQ));
+ return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+ }
+
+ if (psSysData->sInterruptData[ui32IRQ].pfnLISR)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: ISR for %s already installed!", __FUNCTION__, pszName));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ psSysData->sInterruptData[ui32IRQ].psSysData = psSysData;
+ psSysData->sInterruptData[ui32IRQ].pszName = pszName;
+ psSysData->sInterruptData[ui32IRQ].pfnLISR = pfnLISR;
+ psSysData->sInterruptData[ui32IRQ].pvData = pvData;
+ psSysData->sInterruptData[ui32IRQ].ui32InterruptFlag = ui32InterruptFlag;
+
+ *phLISRData = &psSysData->sInterruptData[ui32IRQ];
+
+ EnableInterrupt(psSysData, psSysData->sInterruptData[ui32IRQ].ui32InterruptFlag);
+
+ PVR_LOG(("Installed device LISR %s on IRQ %d", pszName, psSysData->ui32IRQ));
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysUninstallDeviceLISR(IMG_HANDLE hLISRData)
+{
+ SYS_INTERRUPT_DATA *psInterruptData = (SYS_INTERRUPT_DATA *)hLISRData;
+
+ PVR_ASSERT(psInterruptData);
+
+ PVR_LOG(("Uninstalling device LISR %s on IRQ %d", psInterruptData->pszName, psInterruptData->psSysData->ui32IRQ));
+
+ /* Disable interrupts for this device */
+ DisableInterrupt(psInterruptData->psSysData, psInterruptData->ui32InterruptFlag);
+
+ /* Reset the interrupt data */
+ psInterruptData->pszName = NULL;
+ psInterruptData->psSysData = NULL;
+ psInterruptData->pfnLISR = NULL;
+ psInterruptData->pvData = NULL;
+ psInterruptData->ui32InterruptFlag = 0;
+
+ return PVRSRV_OK;
+}
+#endif /* defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) */
+
+#if defined(_WIN32)
+IMG_VOID GetCpuVBase(IMG_VOID ** ppvSystemRegCpuVBase)
+{
+ SYS_DATA *psSysData = (SYS_DATA *)gsSysConfig.pasDevices[0].hSysData;
+
+ if (psSysData)
+ {
+ *ppvSystemRegCpuVBase = psSysData->pvSystemRegCpuVBase;
+ }
+ else
+ {
+ *ppvSystemRegCpuVBase = IMG_NULL;
+ }
+
+}
+
+/* used by local wddmconfig.c as psSysData is not exported */
+IMG_UINT32 GetRGXMemBase()
+{
+ SYS_DATA *psSysData = (SYS_DATA *)gsSysConfig.pasDevices[0].hSysData;
+ PVR_ASSERT(psSysData != IMG_NULL);
+
+ return OSPCIAddrRangeStart(psSysData->hRGXPCI, SYS_DEV_MEM_PCI_BASENUM);
+}
+
+IMG_UINT64 GetRGXMemHeapSize()
+{
+ return gsSysConfig.pasPhysHeaps[0].uiSize;
+}
+#endif
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/sysconfig.h b/drivers/gpu/rogue/services/system/rgx_tc/sysconfig.h
new file mode 100644
index 000000000000..0b663741ddc9
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_tc/sysconfig.h
@@ -0,0 +1,372 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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(__SYSCONFIG_H__)
+#define __SYSCONFIG_H__
+
+#include "pvrsrv_device.h"
+#include "rgxdevice.h"
+
+#define SYS_RGX_ACTIVE_POWER_LATENCY_MS (10)
+static PVRSRV_SYSTEM_CONFIG gsSysConfig;
+
+static RGX_TIMING_INFORMATION gsRGXTimingInfo =
+{
+ /* ui32CoreClockSpeed */
+ 0, /* Initialize to 0, real value will be set in PCIInitDev() */
+ /* bEnableActivePM */
+#if defined (VIRTUAL_PLATFORM)
+ IMG_FALSE,
+#else
+ IMG_TRUE,
+#endif
+ /* bEnableRDPowIsland */
+ IMG_FALSE,
+ /* ui32ActivePMLatencyms */
+ SYS_RGX_ACTIVE_POWER_LATENCY_MS
+};
+
+static RGX_DATA gsRGXData =
+{
+ /* psRGXTimingInfo */
+ &gsRGXTimingInfo
+};
+static PVRSRV_DEVICE_CONFIG gsDevices[] =
+{
+ {
+ /* uiFlags */
+#if (TC_MEMORY_CONFIG != TC_MEMORY_DIRECT_MAPPED)
+ 0,
+#else
+ PVRSRV_DEVICE_CONFIG_LMA_USE_CPU_ADDR,
+#endif
+ /* pszName */
+ "RGX",
+ /* eDeviceType */
+ PVRSRV_DEVICE_TYPE_RGX,
+
+ /* Device setup information */
+ /* sRegsCpuPBase.uiAddr */
+ { 0 },
+ /* ui32RegsSize */
+ 0,
+
+ /* ui32IRQ */
+ 0,
+ /* bIRQIsShared */
+ IMG_TRUE,
+ /* eIRQActiveLevel */
+ PVRSRV_DEVICE_IRQ_ACTIVE_SYSDEFAULT,
+
+ /* hDevData */
+ &gsRGXData,
+ /* hSysData */
+ IMG_NULL,
+
+#if (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID)
+ /*
+ * PhysHeapIDs.
+ * NB. Where allowing both LMA
+ * and a UMA physical heaps, be
+ * sure to provide the ID of
+ * the LMA Heap first and that
+ * of the UMA heap second.
+ */
+ { 1, 0 },
+#else
+ /* usable ui32PhysHeapIDs */
+ { 0, 0 },
+#endif
+ /* pfnPrePowerState */
+ IMG_NULL,
+ /* pfnPostPowerState */
+ IMG_NULL,
+
+ /* pfnClockFreqGet */
+ IMG_NULL,
+
+ /* pfnInterruptHandled */
+ IMG_NULL,
+
+ /* pfnCheckMemAllocSize */
+ SysCheckMemAllocSize,
+
+ /* eBPDM */
+ RGXFWIF_DM_TA,
+ /* bBPSet */
+ IMG_FALSE
+ }
+};
+
+#if (TC_MEMORY_CONFIG == TC_MEMORY_LOCAL)
+static IMG_VOID TCLocalCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr);
+
+static IMG_VOID TCLocalDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HOST) || (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID) || (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED)
+static IMG_VOID TCSystemCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr);
+
+static IMG_VOID TCSystemDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+#endif /* (TC_MEMORY_CONFIG == TC_MEMORY_HOST) || (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID) || (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED) */
+
+#if (TC_MEMORY_CONFIG == TC_MEMORY_LOCAL)
+static PHYS_HEAP_FUNCTIONS gsLocalPhysHeapFuncs =
+{
+ /* pfnCpuPAddrToDevPAddr */
+ TCLocalCpuPAddrToDevPAddr,
+ /* pfnDevPAddrToCpuPAddr */
+ TCLocalDevPAddrToCpuPAddr,
+};
+
+static PHYS_HEAP_CONFIG gsPhysHeapConfig[] =
+{
+ {
+ /* ui32PhysHeapID */
+ 0,
+ /* eType */
+ PHYS_HEAP_TYPE_LMA,
+ /* sStartAddr */
+ { 0 },
+ /* uiSize */
+ 0,
+ /* pszPDumpMemspaceName */
+ "LMA",
+ /* psMemFuncs */
+ &gsLocalPhysHeapFuncs,
+ /* hPrivData */
+ (IMG_HANDLE)&gsSysConfig,
+ },
+#if defined(SUPPORT_DISPLAY_CLASS) || defined(SUPPORT_DRM_DC_MODULE)
+ {
+ /* ui32PhysHeapID */
+ 1,
+ /* eType */
+ PHYS_HEAP_TYPE_LMA,
+ /* sStartAddr */
+ { 0 },
+ /* uiSize */
+ 0,
+ /* pszPDumpMemspaceName */
+ "LMA",
+ /* psMemFuncs */
+ &gsLocalPhysHeapFuncs,
+ /* hPrivData */
+ (IMG_HANDLE)&gsSysConfig,
+ },
+#endif
+#if defined(SUPPORT_ION)
+ {
+ /* ui32PhysHeapID */
+ 2,
+ /* eType */
+ PHYS_HEAP_TYPE_LMA,
+ /* sStartAddr */
+ { 0 },
+ /* uiSize */
+ 0,
+ /* pszPDumpMemspaceName */
+ "LMA",
+ /* psMemFuncs */
+ &gsLocalPhysHeapFuncs,
+ /* hPrivData */
+ (IMG_HANDLE)&gsSysConfig,
+ },
+#endif
+};
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HOST)
+static PHYS_HEAP_FUNCTIONS gsSystemPhysHeapFuncs =
+{
+ /* pfnCpuPAddrToDevPAddr */
+ TCSystemCpuPAddrToDevPAddr,
+ /* pfnDevPAddrToCpuPAddr */
+ TCSystemDevPAddrToCpuPAddr,
+};
+
+static PHYS_HEAP_CONFIG gsPhysHeapConfig[] =
+{
+ {
+ /* ui32PhysHeapID */
+ 0,
+ /* eType */
+ PHYS_HEAP_TYPE_UMA,
+ /* sStartAddr */
+ { 0 },
+ /* uiSize */
+ 0,
+ /* pszPDumpMemspaceName */
+ "SYSMEM",
+ /* psMemFuncs */
+ &gsSystemPhysHeapFuncs,
+ /* hPrivData */
+ (IMG_HANDLE)&gsSysConfig,
+ }
+};
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_HYBRID)
+static PHYS_HEAP_FUNCTIONS gsHybridPhysHeapFuncs =
+{
+ /* pfnCpuPAddrToDevPAddr */
+ TCSystemCpuPAddrToDevPAddr,
+ /* pfnDevPAddrToCpuPAddr */
+ TCSystemDevPAddrToCpuPAddr,
+};
+
+static PHYS_HEAP_CONFIG gsPhysHeapConfig[] =
+{
+ {
+ /* ui32PhysHeapID */
+ 0,
+ /* eType */
+ PHYS_HEAP_TYPE_UMA,
+ /* sStartAddr */
+ { 0 },
+ /* uiSize */
+ 0,
+ /* pszPDumpMemspaceName */
+ "SYSMEM",
+ /* psMemFuncs */
+ &gsHybridPhysHeapFuncs,
+ /* hPrivData */
+ (IMG_HANDLE)&gsSysConfig,
+ },
+ {
+ /* ui32PhysHeapID */
+ 1,
+ /* eType */
+ PHYS_HEAP_TYPE_LMA,
+ /* sStartAddr */
+ { 0 },
+ /* uiSize */
+ 0,
+ /* pszPDumpMemspaceName */
+ "LMA",
+ /* psMemFuncs */
+ &gsHybridPhysHeapFuncs,
+ /* hPrivData */
+ (IMG_HANDLE)&gsSysConfig,
+ }
+};
+#elif (TC_MEMORY_CONFIG == TC_MEMORY_DIRECT_MAPPED)
+static PHYS_HEAP_FUNCTIONS gsDirectMappedPhysHeapFuncs =
+{
+ /* pfnCpuPAddrToDevPAddr */
+ TCSystemCpuPAddrToDevPAddr,
+ /* pfnDevPAddrToCpuPAddr */
+ TCSystemDevPAddrToCpuPAddr,
+};
+
+static PHYS_HEAP_CONFIG gsPhysHeapConfig[] =
+{
+ {
+ /* ui32PhysHeapID */
+ 0,
+ /* eType */
+ PHYS_HEAP_TYPE_LMA,
+ /* sStartAddr */
+ { 0 },
+ /* uiSize */
+ 0,
+ /* pszPDumpMemspaceName */
+ "LMA",
+ /* psMemFuncs */
+ &gsDirectMappedPhysHeapFuncs,
+ /* hPrivData */
+ (IMG_HANDLE)&gsSysConfig,
+ }
+};
+#else
+#error "TC_MEMORY_CONFIG not valid"
+#endif
+
+/* default BIF tiling heap x-stride configurations. */
+static IMG_UINT32 gauiBIFTilingHeapXStrides[RGXFWIF_NUM_BIF_TILING_CONFIGS] =
+{
+ 0, /* BIF tiling heap 1 x-stride */
+ 1, /* BIF tiling heap 2 x-stride */
+ 2, /* BIF tiling heap 3 x-stride */
+ 3 /* BIF tiling heap 4 x-stride */
+};
+
+static PVRSRV_SYSTEM_CONFIG gsSysConfig =
+{
+ /* uiSysFlags */
+ 0,
+ /* pszSystemName */
+ TC_SYSTEM_NAME,
+ /* uiDeviceCount */
+ (IMG_UINT32)(sizeof(gsDevices) / sizeof(PVRSRV_DEVICE_CONFIG)),
+ /* pasDevices */
+ &gsDevices[0],
+
+ /* No power management on no HW system */
+ /* pfnSysPrePowerState */
+ IMG_NULL,
+ /* pfnSysPostPowerState */
+ IMG_NULL,
+
+ /* no cache snooping */
+ /* eCacheSnoopingMode */
+ PVRSRV_SYSTEM_SNOOP_NONE,
+
+ /* Physcial memory heaps */
+ /* pasPhysHeaps */
+ &gsPhysHeapConfig[0],
+ /* ui32PhysHeapCount */
+ (IMG_UINT32)(sizeof(gsPhysHeapConfig) / sizeof(PHYS_HEAP_CONFIG)),
+
+ /* BIF tiling heap config */
+ &gauiBIFTilingHeapXStrides[0],
+ IMG_ARR_NUM_ELEMS(gauiBIFTilingHeapXStrides),
+};
+
+/*****************************************************************************
+ * system specific data structures
+ *****************************************************************************/
+
+#endif /* !defined(__SYSCONFIG_H__) */
diff --git a/drivers/gpu/rogue/services/system/rgx_tc/sysinfo.h b/drivers/gpu/rogue/services/system/rgx_tc/sysinfo.h
new file mode 100644
index 000000000000..12cda5bf27eb
--- /dev/null
+++ b/drivers/gpu/rogue/services/system/rgx_tc/sysinfo.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+#define SYS_RGX_DEV_VENDOR_ID (0x1010)
+#define SYS_RGX_DEV_DEVICE_ID (0x1CF2)
+
+/*!< System specific poll/timeout details */
+#if defined(VIRTUAL_PLATFORM)
+#define MAX_HW_TIME_US (5000000)
+#else
+#define MAX_HW_TIME_US (500000)
+#endif
+
+#define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT (10000)
+#define DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT (3600000)
+#define WAIT_TRY_COUNT (10000)
+
+/* RGX, DISPLAY (external), BUFFER (external) */
+#define SYS_DEVICE_COUNT (3)
+
+/* This should be one higher than the highest possible physical heap ID */
+#define SYS_PHYS_HEAP_COUNT 3
+
+#if defined(__linux__)
+#define SYS_RGX_DEV_NAME "rgxtc"
+#endif /* defined(__linux__) */
+
+#endif /* !defined(__SYSINFO_H__) */
diff --git a/drivers/gpu/rogue/system/common/interrupt_linux.h b/drivers/gpu/rogue/system/common/interrupt_linux.h
new file mode 100644
index 000000000000..3a547249480e
--- /dev/null
+++ b/drivers/gpu/rogue/system/common/interrupt_linux.h
@@ -0,0 +1,52 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+
+#if !defined(__INTERRUPT_LINUX_H__)
+#define __INTERRUPT_LINUX_H__
+
+#include "img_types.h"
+
+struct _PVR_IRQ_PRIV_DATA_
+{
+ IMG_UINT32 ui32Dummy;
+};
+
+#endif /* !defined(__INTERRUPT_LINUX_H__) */
diff --git a/drivers/gpu/rogue/system/common/interrupt_support.c b/drivers/gpu/rogue/system/common/interrupt_support.c
new file mode 100644
index 000000000000..01ae59d11f39
--- /dev/null
+++ b/drivers/gpu/rogue/system/common/interrupt_support.c
@@ -0,0 +1,159 @@
+/*************************************************************************/ /*!
+@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"
+#include "interrupt_linux.h"
+
+#if !defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+#error Usage of these functions requires that SUPPORT_SYSTEM_INTERRUPT_HANDLING be enabled in the build
+#endif
+
+typedef struct LISR_DATA_TAG
+{
+ IMG_UINT32 ui32IRQ;
+ PFN_SYS_LISR pfnLISR;
+ IMG_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", __FUNCTION__));
+ }
+
+ return IRQ_NONE;
+}
+
+/*************************************************************************/ /*!
+@Function OSInstallSystemLISR
+@Description Install a system interrupt handler
+@Output phLISR On return, contains a handle to the
+ installed LISR
+@Input ui32IRQ The IRQ number for which the
+ interrupt handler should be installed
+@Input psPrivData A pointer to OS specific private data.
+ It is the responsibility of the caller
+ to free this data once it is no longer
+ in use. This will typically be after
+ calling OSUninstallSystemLISR()
+@Input pfnLISR A pointer to an interrupt handler
+ function
+@Input pvData A pointer to data that should be passed
+ to pfnLISR when it is called
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR OSInstallSystemLISR(IMG_HANDLE *phLISR,
+ IMG_UINT32 ui32IRQ,
+ PVR_IRQ_PRIV_DATA *psPrivData,
+ PFN_SYS_LISR pfnLISR,
+ IMG_VOID *pvData)
+{
+ LISR_DATA *psLISRData;
+
+ PVR_UNREFERENCED_PARAMETER(psPrivData);
+
+ if (pfnLISR == IMG_NULL || pvData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psLISRData = OSAllocMem(sizeof *psLISRData);
+ if (psLISRData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psLISRData->ui32IRQ = ui32IRQ;
+ psLISRData->pfnLISR = pfnLISR;
+ psLISRData->pvData = pvData;
+
+ if (request_irq(ui32IRQ, SystemISRWrapper, IRQF_SHARED, PVRSRV_MODNAME, psLISRData))
+ {
+ OSFreeMem(psLISRData);
+
+ return PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER;
+ }
+
+ *phLISR = (IMG_HANDLE)psLISRData;
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function OSUninstallSystemLISR
+@Description Uninstall a system interrupt handler
+@Input hLISR Handle to the LISR that should be
+ uninstalled
+@Return PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_HANDLE hLISR)
+{
+ LISR_DATA *psLISRData = (LISR_DATA *)hLISR;
+
+ if (psLISRData == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ free_irq(psLISRData->ui32IRQ, psLISRData);
+
+ OSFreeMem(psLISRData);
+
+ return PVRSRV_OK;
+}
+
diff --git a/drivers/gpu/rogue/system/common/ion_support_generic.c b/drivers/gpu/rogue/system/common/ion_support_generic.c
new file mode 100644
index 000000000000..277c3b523bee
--- /dev/null
+++ b/drivers/gpu/rogue/system/common/ion_support_generic.c
@@ -0,0 +1,161 @@
+/*************************************************************************/ /*!
+@File ion_support.c
+@Title Generic Ion support
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This file does the Ion initialisation and De-initialistion for
+ systems that don't already have Ion.
+ For systems that do have Ion it's expected they they init Ion
+ as per their requirements and then implement IonDevAcquire and
+ IonDevRelease which provides access to the ion device.
+@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_error.h"
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "ion_support.h"
+#include "ion_sys.h"
+
+#include <linux/version.h>
+#include PVR_ANDROID_ION_HEADER
+#include PVR_ANDROID_ION_PRIV_HEADER
+#include <linux/err.h>
+#include <linux/slab.h>
+
+/* Just the system heaps are used by the generic implementation */
+static struct ion_platform_data generic_config = {
+ .nr = 2,
+ .heaps =
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,39))
+#else
+ (struct ion_platform_heap [])
+#endif
+ {
+ {
+ .type = ION_HEAP_TYPE_SYSTEM_CONTIG,
+ .name = "system_contig",
+ .id = ION_HEAP_TYPE_SYSTEM_CONTIG,
+ },
+ {
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .name = "system",
+ .id = ION_HEAP_TYPE_SYSTEM,
+ }
+ }
+};
+
+struct ion_heap **g_apsIonHeaps;
+struct ion_device *g_psIonDev;
+
+PVRSRV_ERROR IonInit(void *phPrivateData)
+{
+ int uiHeapCount = generic_config.nr;
+ int uiError;
+ int i;
+
+ PVR_UNREFERENCED_PARAMETER(phPrivateData);
+
+ g_apsIonHeaps = kzalloc(sizeof(struct ion_heap *) * uiHeapCount, GFP_KERNEL);
+
+ /* Create the ion devicenode */
+ g_psIonDev = ion_device_create(NULL);
+ if (IS_ERR_OR_NULL(g_psIonDev)) {
+ kfree(g_apsIonHeaps);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Register all the heaps */
+ for (i = 0; i < generic_config.nr; i++)
+ {
+ struct ion_platform_heap *psPlatHeapData = &generic_config.heaps[i];
+
+ g_apsIonHeaps[i] = ion_heap_create(psPlatHeapData);
+ if (IS_ERR_OR_NULL(g_apsIonHeaps[i]))
+ {
+ uiError = PTR_ERR(g_apsIonHeaps[i]);
+ goto failHeapCreate;
+ }
+ ion_device_add_heap(g_psIonDev, g_apsIonHeaps[i]);
+ }
+
+ return PVRSRV_OK;
+
+failHeapCreate:
+ for (i = 0; i < uiHeapCount; i++) {
+ if (g_apsIonHeaps[i])
+ {
+ ion_heap_destroy(g_apsIonHeaps[i]);
+ }
+ }
+ kfree(g_apsIonHeaps);
+ ion_device_destroy(g_psIonDev);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+struct ion_device *IonDevAcquire(IMG_VOID)
+{
+ return g_psIonDev;
+}
+
+IMG_VOID IonDevRelease(struct ion_device *psIonDev)
+{
+ /* Nothing to do, sanity check the pointer we're passed back */
+ PVR_ASSERT(psIonDev == g_psIonDev);
+}
+
+IMG_UINT32 IonPhysHeapID(IMG_VOID)
+{
+ return 0;
+}
+
+IMG_VOID IonDeinit(IMG_VOID)
+{
+ int uiHeapCount = generic_config.nr;
+ int i;
+
+ for (i = 0; i < uiHeapCount; i++) {
+ if (g_apsIonHeaps[i])
+ {
+ ion_heap_destroy(g_apsIonHeaps[i]);
+ }
+ }
+ kfree(g_apsIonHeaps);
+ ion_device_destroy(g_psIonDev);
+}
+
diff --git a/drivers/gpu/rogue/system/common/lma_heap_ion.c b/drivers/gpu/rogue/system/common/lma_heap_ion.c
new file mode 100644
index 000000000000..c28cfacd5f94
--- /dev/null
+++ b/drivers/gpu/rogue/system/common/lma_heap_ion.c
@@ -0,0 +1,205 @@
+/*************************************************************************/ /*!
+@File lma_heap_ion.c
+@Title Ion heap for local memory
+@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_ANDROID_ION_HEADER
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+#include <linux/scatterlist.h>
+#include PVR_ANDROID_ION_PRIV_HEADER
+
+#include "lma_heap_ion.h"
+#include "pvr_debug.h"
+
+struct lma_heap
+{
+ struct ion_heap heap;
+ /* Base address in local physical memory to start allocating from. */
+ unsigned long base;
+ /* Size of the memory region we're responsible for */
+ size_t size;
+ /* Pool to manage allocations from this memory region. */
+ struct gen_pool *pool;
+};
+
+static int lma_heap_allocate(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ unsigned long len, unsigned long align,
+ unsigned long flags)
+{
+ struct lma_heap *psHeap = container_of(heap, struct lma_heap, heap);
+ int err = 0;
+
+ buffer->priv_phys = gen_pool_alloc(psHeap->pool, len);
+ if (!buffer->priv_phys)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Out of space in local memory pool",
+ __func__));
+ err = -ENOMEM;
+ }
+
+ return err;
+}
+
+static void lma_heap_free(struct ion_buffer *buffer)
+{
+ struct lma_heap *psHeap =
+ container_of(buffer->heap, struct lma_heap, heap);
+ gen_pool_free(psHeap->pool, buffer->priv_phys, buffer->size);
+}
+
+static int lma_heap_phys(struct ion_heap *heap, struct ion_buffer *buffer,
+ ion_phys_addr_t *addr, size_t *len)
+{
+ *addr = buffer->priv_phys;
+ *len = buffer->size;
+ return 0;
+}
+
+static struct sg_table *lma_heap_map_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct sg_table *psTable;
+
+ psTable = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
+ if (!psTable)
+ return NULL;
+
+ if (sg_alloc_table(psTable, 1, GFP_KERNEL))
+ {
+ kfree(psTable);
+ return NULL;
+ }
+
+
+#if defined(CONFIG_FLATMEM)
+ sg_set_page(psTable->sgl, pfn_to_page(PFN_DOWN(buffer->priv_phys)),
+ buffer->size, 0);
+#else
+#error ion_lma_heap requires CONFIG_FLATMEM
+#endif
+
+ return psTable;
+}
+
+static void lma_heap_unmap_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ sg_free_table(buffer->sg_table);
+ kfree(buffer->sg_table);
+}
+
+static void *lma_heap_map_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ return ioremap_wc(buffer->priv_phys, buffer->size);
+}
+
+static void lma_heap_unmap_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ iounmap(buffer->vaddr);
+}
+
+static int lma_heap_map_user(struct ion_heap *mapper, struct ion_buffer *buffer,
+ struct vm_area_struct *vma)
+{
+ return remap_pfn_range(vma, vma->vm_start,
+ PFN_DOWN(buffer->priv_phys) + vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ pgprot_writecombine(vma->vm_page_prot));
+}
+
+static struct ion_heap_ops lma_heap_ops =
+{
+ .allocate = lma_heap_allocate,
+ .free = lma_heap_free,
+ .phys = lma_heap_phys,
+ .map_dma = lma_heap_map_dma,
+ .unmap_dma = lma_heap_unmap_dma,
+ .map_kernel = lma_heap_map_kernel,
+ .unmap_kernel = lma_heap_unmap_kernel,
+ .map_user = lma_heap_map_user
+};
+
+struct ion_heap *lma_heap_create(struct ion_platform_heap *data)
+{
+ struct lma_heap *psHeap;
+ struct gen_pool *psPool;
+
+ /* Check that sysconfig.c filled out the information we need. */
+ if (!data->size)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: System code did not set up a sensible "
+ "heap size", __func__));
+ goto err_out;
+ }
+
+ psHeap = kzalloc(sizeof(struct lma_heap), GFP_KERNEL);
+ if (!psHeap)
+ goto err_out;
+
+ psPool = gen_pool_create(PAGE_SHIFT, -1);
+ if (!psPool)
+ goto err_free;
+
+ psHeap->heap.type = ION_HEAP_TYPE_CUSTOM;
+ psHeap->heap.ops = &lma_heap_ops;
+ psHeap->heap.name = data->name;
+ psHeap->heap.id = data->id;
+ psHeap->base = data->base;
+ psHeap->size = data->size;
+
+ /* Tell the pool allocator about the region of physical address space we
+ want it to allocate from. */
+ if (gen_pool_add(psPool, psHeap->base, psHeap->size, -1))
+ goto err_pool_destroy;
+
+ psHeap->pool = psPool;
+ return &psHeap->heap;
+
+err_pool_destroy:
+ gen_pool_destroy(psPool);
+err_free:
+ kfree(psHeap);
+err_out:
+ return NULL;
+}
diff --git a/drivers/gpu/rogue/system/common/lma_heap_ion.h b/drivers/gpu/rogue/system/common/lma_heap_ion.h
new file mode 100644
index 000000000000..da595a26ae32
--- /dev/null
+++ b/drivers/gpu/rogue/system/common/lma_heap_ion.h
@@ -0,0 +1,45 @@
+/*************************************************************************/ /*!
+@File lma_heap_ion.h
+@Title Ion heap for local memory
+@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_ANDROID_ION_HEADER
+
+struct ion_heap *lma_heap_create(struct ion_platform_heap *data);
diff --git a/drivers/gpu/rogue/system/common/pci_support.c b/drivers/gpu/rogue/system/common/pci_support.c
new file mode 100644
index 000000000000..6374ff576317
--- /dev/null
+++ b/drivers/gpu/rogue/system/common/pci_support.c
@@ -0,0 +1,657 @@
+/*************************************************************************/ /*!
+@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/pci.h>
+#include <linux/version.h>
+#include <asm/mtrr.h>
+
+#include "pci_support.h"
+
+typedef struct _PVR_PCI_DEV_TAG
+{
+ struct pci_dev *psPCIDev;
+ HOST_PCI_INIT_FLAGS ePCIFlags;
+ IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+} PVR_PCI_DEV;
+
+/*************************************************************************/ /*!
+@Function OSPCISetDev
+@Description Set a PCI device for subsequent use.
+@Input pvPCICookie Pointer to OS specific PCI structure
+@Input eFlags Flags
+@Return PVRSRV_PCI_DEV_HANDLE Pointer to PCI device handle
+*/ /**************************************************************************/
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
+{
+ int err;
+ IMG_UINT32 i;
+ PVR_PCI_DEV *psPVRPCI;
+
+ psPVRPCI = kmalloc(sizeof(*psPVRPCI), GFP_KERNEL);
+ if (psPVRPCI == IMG_NULL)
+ {
+ printk(KERN_ERR "OSPCISetDev: Couldn't allocate PVR PCI structure\n");
+ return IMG_NULL;
+ }
+
+ psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie;
+ psPVRPCI->ePCIFlags = eFlags;
+
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ printk(KERN_ERR "OSPCISetDev: Couldn't enable device (%d)\n", err);
+ kfree(psPVRPCI);
+ return IMG_NULL;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */
+ {
+ pci_set_master(psPVRPCI->psPCIDev);
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI) /* PRQA S 3358 */ /* misuse of enums */
+ {
+#if defined(CONFIG_PCI_MSI)
+ err = pci_enable_msi(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ printk(KERN_ERR "OSPCISetDev: Couldn't enable MSI (%d)", err);
+ psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI; /* PRQA S 1474,3358,4130 */ /* misuse of enums */
+ }
+#else
+ printk(KERN_ERR "OSPCISetDev: MSI support not enabled in the kernel");
+#endif
+}
+
+ /* Initialise the PCI resource tracking array */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+
+ return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI;
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIAcquireDev
+@Description Acquire a PCI device for subsequent use.
+@Input ui16VendorID Vendor PCI ID
+@Input ui16DeviceID Device PCI ID
+@Input eFlags Flags
+@Return PVRSRV_PCI_DEV_HANDLE Pointer to PCI device handle
+*/ /**************************************************************************/
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID,
+ IMG_UINT16 ui16DeviceID,
+ HOST_PCI_INIT_FLAGS eFlags)
+{
+ struct pci_dev *psPCIDev;
+
+ psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL);
+ if (psPCIDev == NULL)
+ {
+ return IMG_NULL;
+ }
+
+ return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags);
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIDevID
+@Description Get the PCI device ID.
+@Input hPVRPCI PCI device handle
+@Output pui16DeviceID Pointer to where the device ID should
+ be returned
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCIDevID(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT16 *pui16DeviceID)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ if (pui16DeviceID == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *pui16DeviceID = psPVRPCI->psPCIDev->device;
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIIRQ
+@Description Get the interrupt number for the device.
+@Input hPVRPCI PCI device handle
+@Output pui16DeviceID Pointer to where the interrupt number
+ should be returned
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ if (pui32IRQ == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *pui32IRQ = psPVRPCI->psPCIDev->irq;
+
+ return PVRSRV_OK;
+}
+
+/* Functions supported by OSPCIAddrRangeFunc */
+enum HOST_PCI_ADDR_RANGE_FUNC
+{
+ HOST_PCI_ADDR_RANGE_FUNC_LEN,
+ HOST_PCI_ADDR_RANGE_FUNC_START,
+ HOST_PCI_ADDR_RANGE_FUNC_END,
+ HOST_PCI_ADDR_RANGE_FUNC_REQUEST,
+ HOST_PCI_ADDR_RANGE_FUNC_RELEASE
+};
+
+/*************************************************************************/ /*!
+@Function OSPCIAddrRangeFunc
+@Description Internal support function for various address range related
+ functions
+@Input eFunc Function to perform
+@Input hPVRPCI PCI device handle
+@Input ui32Index Address range index
+@Return IMG_UINT32 Function dependent value
+*/ /**************************************************************************/
+static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
+ PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ if (ui32Index >= DEVICE_COUNT_RESOURCE)
+ {
+ printk(KERN_ERR "OSPCIAddrRangeFunc: Index out of range");
+ return 0;
+ }
+
+ switch (eFunc)
+ {
+ case HOST_PCI_ADDR_RANGE_FUNC_LEN:
+ {
+ return pci_resource_len(psPVRPCI->psPCIDev, ui32Index);
+ }
+ case HOST_PCI_ADDR_RANGE_FUNC_START:
+ {
+ return pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+ }
+ case HOST_PCI_ADDR_RANGE_FUNC_END:
+ {
+ return pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+ }
+ case HOST_PCI_ADDR_RANGE_FUNC_REQUEST:
+ {
+ int err = pci_request_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index, PVRSRV_MODNAME);
+ if (err != 0)
+ {
+ printk(KERN_ERR "OSPCIAddrRangeFunc: pci_request_region_failed (%d)", err);
+ return 0;
+ }
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE;
+ return 1;
+ }
+ case HOST_PCI_ADDR_RANGE_FUNC_RELEASE:
+ {
+ if (psPVRPCI->abPCIResourceInUse[ui32Index])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index);
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE;
+ }
+ return 1;
+ }
+ default:
+ {
+ printk(KERN_ERR "OSPCIAddrRangeFunc: Unknown function");
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIAddrRangeLen
+@Description Returns length of a given address range
+@Input hPVRPCI PCI device handle
+@Input ui32Index Address range index
+@Return IMG_UINT32 Length of address range or 0 if no
+ such range
+*/ /**************************************************************************/
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index);
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIAddrRangeStart
+@Description Returns the start of a given address range
+@Input hPVRPCI PCI device handle
+@Input ui32Index Address range index
+@Return IMG_UINT32 Start of address range or 0 if no
+ such range
+*/ /**************************************************************************/
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index);
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIAddrRangeEnd
+@Description Returns the end of a given address range
+@Input hPVRPCI PCI device handle
+@Input ui32Index Address range index
+@Return IMG_UINT32 End of address range or 0 if no such
+ range
+*/ /**************************************************************************/
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index);
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIRequestAddrRange
+@Description Request a given address range index for subsequent use
+@Input hPVRPCI PCI device handle
+@Input ui32Index Address range index
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ if (OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0)
+ {
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+ else
+ {
+ return PVRSRV_OK;
+ }
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIReleaseAddrRange
+@Description Release a given address range that is no longer being used
+@Input hPVRPCI PCI device handle
+@Input ui32Index Address range index
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ if (OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0)
+ {
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+ else
+ {
+ return PVRSRV_OK;
+ }
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIRequestAddrRegion
+@Description Request a given region from an address range for subsequent use
+@Input hPVRPCI PCI device handle
+@Input ui32Index Address range index
+@Input ui32Offset Offset into the address range that forms
+ the start of the region
+@Input ui32Length Length of the region
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCIRequestAddrRegion(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Length)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ resource_size_t start;
+ resource_size_t end;
+
+ start = pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+ end = pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+
+ /* Check that the requested region is valid */
+ if ((start + ui32Offset + ui32Length - 1) > end)
+ {
+ return PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH;
+ }
+
+ if (pci_resource_flags(psPVRPCI->psPCIDev, ui32Index) & IORESOURCE_IO)
+ {
+ if (request_region(start + ui32Offset, ui32Length, PVRSRV_MODNAME) == NULL)
+ {
+ return PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
+ }
+ }
+ else
+ {
+ if (request_mem_region(start + ui32Offset, ui32Length, PVRSRV_MODNAME) == NULL)
+ {
+ return PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIReleaseAddrRegion
+@Description Release a given region, from an address range, that is no
+ longer in use
+@Input hPVRPCI PCI device handle
+@Input ui32Index Address range index
+@Input ui32Offset Offset into the address range that forms
+ the start of the region
+@Input ui32Length Length of the region
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCIReleaseAddrRegion(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Length)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ resource_size_t start;
+ resource_size_t end;
+
+ start = pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+ end = pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+
+ /* Check that the region is valid */
+ if ((start + ui32Offset + ui32Length - 1) > end)
+ {
+ return PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH;
+ }
+
+ if (pci_resource_flags(psPVRPCI->psPCIDev, ui32Index) & IORESOURCE_IO)
+ {
+ release_region(start + ui32Offset, ui32Length);
+ }
+ else
+ {
+ release_mem_region(start + ui32Offset, ui32Length);
+ }
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIReleaseDev
+@Description Release a PCI device that is no longer being used
+@Input hPVRPCI PCI device handle
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int i;
+
+ /* Release all PCI regions that are currently in use */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, i);
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+ }
+
+#if defined(CONFIG_PCI_MSI)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI) /* PRQA S 3358 */ /* misuse of enums */
+ {
+ pci_disable_msi(psPVRPCI->psPCIDev);
+ }
+#endif
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */
+ {
+ pci_clear_master(psPVRPCI->psPCIDev);
+ }
+
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ kfree((IMG_VOID *)psPVRPCI);
+ /*not nulling pointer, copy on stack*/
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function OSPCISuspendDev
+@Description Prepare PCI device to be turned off by power management
+@Input hPVRPCI PCI device handle
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int i;
+ int err;
+
+ /* Release all PCI regions that are currently in use */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, i);
+ }
+ }
+
+ err = pci_save_state(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ printk(KERN_ERR "OSPCISuspendDev: pci_save_state_failed (%d)", err);
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_SUSPEND));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ printk(KERN_ERR "OSPCISuspendDev: device doesn't support PCI PM");
+ break;
+ case -EINVAL:
+ printk(KERN_ERR "OSPCISuspendDev: can't enter requested power state");
+ break;
+ default:
+ printk(KERN_ERR "OSPCISuspendDev: pci_set_power_state failed (%d)", err);
+ break;
+ }
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIResumeDev
+@Description Prepare a PCI device to be resumed by power management
+@Input hPVRPCI PCI device handle
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int err;
+ int i;
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ printk(KERN_ERR "OSPCIResumeDev: device doesn't support PCI PM");
+ break;
+ case -EINVAL:
+ printk(KERN_ERR "OSPCIResumeDev: can't enter requested power state");
+ return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+ default:
+ printk(KERN_ERR "OSPCIResumeDev: pci_set_power_state failed (%d)", err);
+ return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ pci_restore_state(psPVRPCI->psPCIDev);
+#else
+ err = pci_restore_state(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ printk(KERN_ERR "OSPCIResumeDev: pci_restore_state failed (%d)", err);
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+#endif
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ printk(KERN_ERR "OSPCIResumeDev: Couldn't enable device (%d)", err);
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */
+ pci_set_master(psPVRPCI->psPCIDev);
+
+ /* Restore the PCI resource tracking array */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ err = pci_request_region(psPVRPCI->psPCIDev, i, PVRSRV_MODNAME);
+ if (err != 0)
+ {
+ printk(KERN_ERR "OSPCIResumeDev: pci_request_region_failed (region %d, error %d)", i, err);
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function OSPCIClearResourceMTRRs
+@Description Clear any BIOS-configured MTRRs for a PCI memory region
+@Input hPVRPCI PCI device handle
+@Input ui32Index Address range index
+@Return PVRSRV_ERROR Services error code
+*/ /**************************************************************************/
+PVRSRV_ERROR OSPCIClearResourceMTRRs(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ resource_size_t start, end;
+ int err;
+
+ start = pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+ end = pci_resource_end(psPVRPCI->psPCIDev, ui32Index) + 1;
+
+ err = mtrr_add(start, end - start, MTRR_TYPE_UNCACHABLE, 0);
+ if (err < 0)
+ {
+ printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_add failed (%d)", err);
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ err = mtrr_del(err, start, end - start);
+ if (err < 0)
+ {
+ printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_del failed (%d)", err);
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ /* Workaround for overlapping MTRRs. */
+ {
+ IMG_BOOL bGotMTRR0 = IMG_FALSE;
+
+ /* Current mobo BIOSes will normally set up a WRBACK MTRR spanning
+ * 0->4GB, and then another 4GB->6GB. If the PCI card's automatic &
+ * overlapping UNCACHABLE MTRR is deleted, we see WRBACK behaviour.
+ *
+ * WRBACK is incompatible with some PCI devices, so try to split
+ * the UNCACHABLE regions up and insert a WRCOMB region instead.
+ */
+ err = mtrr_add(start, end - start, MTRR_TYPE_WRBACK, 0);
+ if (err < 0)
+ {
+ /* If this fails, services has probably run before and created
+ * a write-combined MTRR for the test chip. Assume it has, and
+ * don't return an error here.
+ */
+ return PVRSRV_OK;
+ }
+
+ if(err == 0)
+ bGotMTRR0 = IMG_TRUE;
+
+ err = mtrr_del(err, start, end - start);
+ if(err < 0)
+ {
+ printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_del failed (%d)", err);
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ if(bGotMTRR0)
+ {
+ /* Replace 0 with a non-overlapping WRBACK MTRR */
+ err = mtrr_add(0, start, MTRR_TYPE_WRBACK, 0);
+ if(err < 0)
+ {
+ printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_add failed (%d)", err);
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ /* Add a WRCOMB MTRR for the PCI device memory bar */
+ err = mtrr_add(start, end - start, MTRR_TYPE_WRCOMB, 0);
+ if(err < 0)
+ {
+ printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_add failed (%d)", err);
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/rogue/system/include/interrupt_support.h b/drivers/gpu/rogue/system/include/interrupt_support.h
new file mode 100644
index 000000000000..946cd860f0b1
--- /dev/null
+++ b/drivers/gpu/rogue/system/include/interrupt_support.h
@@ -0,0 +1,59 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+
+#if !defined(__INTERRUPT_SUPPORT_H__)
+#define __INTERRUPT_SUPPORT_H__
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+typedef struct _PVR_IRQ_PRIV_DATA_ PVR_IRQ_PRIV_DATA;
+typedef IMG_BOOL (*PFN_SYS_LISR)(IMG_VOID *pvData);
+
+PVRSRV_ERROR OSInstallSystemLISR(IMG_HANDLE *phLISR,
+ IMG_UINT32 ui32IRQ,
+ PVR_IRQ_PRIV_DATA *psPrivData,
+ PFN_SYS_LISR pfnLISR,
+ IMG_VOID *pvData);
+
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_HANDLE hLISRData);
+
+#endif /* !defined(__INTERRUPT_SUPPORT_H__) */
diff --git a/drivers/gpu/rogue/system/include/ion_support.h b/drivers/gpu/rogue/system/include/ion_support.h
new file mode 100644
index 000000000000..341038da0fb6
--- /dev/null
+++ b/drivers/gpu/rogue/system/include/ion_support.h
@@ -0,0 +1,46 @@
+/*************************************************************************/ /*!
+@File ion_support.h
+@Title Generic Ion support header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This file defines the API for generic Ion support.
+@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.
+*/ /**************************************************************************/
+
+PVRSRV_ERROR IonInit(void *pvPrivateData);
+
+IMG_VOID IonDeinit(IMG_VOID);
diff --git a/drivers/gpu/rogue/system/include/pci_support.h b/drivers/gpu/rogue/system/include/pci_support.h
new file mode 100644
index 000000000000..66ff8f31e375
--- /dev/null
+++ b/drivers/gpu/rogue/system/include/pci_support.h
@@ -0,0 +1,74 @@
+/*************************************************************************/ /*!
+@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 __PCI_SUPPORT_H__
+#define __PCI_SUPPORT_H__
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+typedef enum _HOST_PCI_INIT_FLAGS_
+{
+ HOST_PCI_INIT_FLAG_BUS_MASTER = 0x00000001,
+ HOST_PCI_INIT_FLAG_MSI = 0x00000002,
+ HOST_PCI_INIT_FLAG_FORCE_I32 = 0x7fffffff
+} HOST_PCI_INIT_FLAGS;
+
+struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_ *PVRSRV_PCI_DEV_HANDLE;
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIDevID(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT16 *pui16DeviceID);
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ);
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIRequestAddrRegion(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Length);
+PVRSRV_ERROR OSPCIReleaseAddrRegion(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Length);
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIClearResourceMTRRs(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+
+#endif /* __PCI_SUPPORT_H__ */
diff --git a/drivers/gpu/rogue/system/include/syscommon.h b/drivers/gpu/rogue/system/include/syscommon.h
new file mode 100644
index 000000000000..8ace64c13363
--- /dev/null
+++ b/drivers/gpu/rogue/system/include/syscommon.h
@@ -0,0 +1,167 @@
+/*************************************************************************/ /*!
+@File
+@Title Common System APIs and structures
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides common system-specific declarations and macros
+ that are supported by all systems
+@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 _SYSCOMMON_H
+#define _SYSCOMMON_H
+
+#include "osfunc.h"
+
+#if defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__)
+#include <asm/io.h>
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+#include "pvrsrv.h"
+
+PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig);
+IMG_VOID SysDestroyConfigData(PVRSRV_SYSTEM_CONFIG *psSysConfig);
+PVRSRV_ERROR SysAcquireSystemData(IMG_HANDLE hSysData);
+PVRSRV_ERROR SysReleaseSystemData(IMG_HANDLE hSysData);
+PVRSRV_ERROR SysDebugInfo(PVRSRV_SYSTEM_CONFIG *psSysConfig, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf);
+
+#if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING)
+PVRSRV_ERROR SysInstallDeviceLISR(IMG_UINT32 ui32IRQ,
+ IMG_CHAR *pszName,
+ PFN_LISR pfnLISR,
+ IMG_PVOID pvData,
+ IMG_HANDLE *phLISRData);
+
+PVRSRV_ERROR SysUninstallDeviceLISR(IMG_HANDLE hLISRData);
+
+#if defined(SUPPORT_DRM)
+IMG_BOOL SystemISRHandler(IMG_VOID *pvData);
+#endif
+#endif /* defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) */
+
+
+/*
+ * SysReadHWReg and SysWriteHWReg differ from OSReadHWReg and OSWriteHWReg
+ * in that they are always intended for use with real hardware, even on
+ * NO_HARDWARE systems.
+ */
+#if !(defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__))
+#define SysReadHWReg(p, o) OSReadHWReg(p, o)
+#define SysWriteHWReg(p, o, v) OSWriteHWReg(p, o, v)
+#else /* !(defined(NO_HARDWARE) && defined(__linux__)) */
+/*!
+******************************************************************************
+
+ @Function SysReadHWReg
+
+ @Description
+
+ register read function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset :
+
+ @Return register value
+
+******************************************************************************/
+static inline IMG_UINT32 SysReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+ return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
+}
+
+/*!
+******************************************************************************
+
+ @Function SysWriteHWReg
+
+ @Description
+
+ register write function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset :
+
+ @input ui32Value :
+
+ @Return none
+
+******************************************************************************/
+static inline IMG_VOID SysWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+ writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+}
+#endif /* !(defined(NO_HARDWARE) && defined(__linux__)) */
+
+/*!
+******************************************************************************
+
+ @Function SysCheckMemAllocSize
+
+ @Description Function to apply memory budgeting policies
+
+ @input psDevNode
+
+ @input uiChunkSize
+
+ @input ui32NumPhysChunks
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+FORCE_INLINE PVRSRV_ERROR SysCheckMemAllocSize(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+ IMG_UINT64 ui64MemSize)
+{
+ PVR_UNREFERENCED_PARAMETER(psDevNode);
+ PVR_UNREFERENCED_PARAMETER(ui64MemSize);
+
+ return PVRSRV_OK;
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
+/*****************************************************************************
+ End of file (syscommon.h)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/system/rk3368/Kbuild.mk b/drivers/gpu/rogue/system/rk3368/Kbuild.mk
new file mode 100644
index 000000000000..df218fceae0b
--- /dev/null
+++ b/drivers/gpu/rogue/system/rk3368/Kbuild.mk
@@ -0,0 +1,49 @@
+########################################################################### ###
+#@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-y += \
+ services/system/$(PVR_SYSTEM)/rk_init.o \
+ services/system/$(PVR_SYSTEM)/sysconfig.o
+
+#zxl:to support rockchip ion
+ifeq ($(SUPPORT_ION),1)
+#pvrsrvkm-y += services/system/common/env/linux/ion_support_generic.o
+endif
diff --git a/drivers/gpu/rogue/system/rk3368/rk_init.c b/drivers/gpu/rogue/system/rk3368/rk_init.c
new file mode 100755
index 000000000000..8c456b47d8a4
--- /dev/null
+++ b/drivers/gpu/rogue/system/rk3368/rk_init.c
@@ -0,0 +1,1897 @@
+#if defined(SUPPORT_ION)
+#include "ion_sys.h"
+#endif /* defined(SUPPORT_ION) */
+
+#include <linux/hardirq.h>
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+#include <linux/rk_fb.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/rockchip/dvfs.h>
+#include <linux/rockchip/common.h>
+#include <linux/workqueue.h>
+#include <linux/clkdev.h>
+#include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include "power.h"
+#include "rk_init.h"
+
+
+extern struct platform_device *gpsPVRLDMDev;
+
+#if RK33_DVFS_SUPPORT
+#define gpu_temp_limit 110
+#define gpu_temp_statis_time 1
+#define level0_threshold_min 0
+#define level0_threshold_max 40
+#define levelf_threshold_max 100
+#define level0_coef_max 95
+
+static IMG_UINT32 div_dvfs = 0 ;
+
+/*dvfs status*/
+static struct workqueue_struct *rgx_dvfs_wq = IMG_NULL;
+spinlock_t rgx_dvfs_spinlock;
+struct mutex rgx_set_clock_lock;
+struct mutex rgx_enable_clock_lock;
+static struct cpufreq_frequency_table *rgx_freq_table = NULL;
+#endif
+
+/* voltage clock min_threshold max_threshold time */
+static rgx_dvfs_info rgx_dvfs_infotbl[] =
+{
+ {925, 100, 0, 70, 0, 100},
+ {925, 160, 50, 65, 0, 95},
+ {1025, 266, 60, 78, 0, 90},
+ {1075, 350, 65, 75, 0, 85},
+ {1125, 400, 70, 75, 0, 80},
+ {1200, 500, 90, 100, 0, 75},
+};
+rgx_dvfs_info *p_rgx_dvfs_infotbl = rgx_dvfs_infotbl;
+
+unsigned int RGX_DVFS_STEP = ARRAY_SIZE(rgx_dvfs_infotbl);
+
+static int rk33_clk_set_normal_node(struct clk* node, unsigned long rate)
+{
+ int ret = 0;
+ if (!node)
+ {
+ printk("rk33_clk_set_normal_node error \r\n");
+ ret = -1;
+ }
+ ret = clk_set_rate(node, rate * ONE_MHZ);
+ if (ret)
+ {
+ printk("clk_set_rate error \r\n");
+ }
+ return ret;
+}
+
+#if RK33_DVFS_SUPPORT
+static int rk33_clk_set_dvfs_node(struct dvfs_node *node, unsigned long rate)
+{
+ int ret = 0;
+ if (!node)
+ {
+ printk("rk33_clk_set_dvfs_node error \r\n");
+ ret = -1;
+ }
+ ret = dvfs_clk_set_rate(node, rate * ONE_MHZ);
+ if (ret)
+ {
+ printk("dvfs_clk_set_rate error \r\n");
+ }
+ return ret;
+}
+
+#define dividend 7
+#define fix_float(a) ((((a)*dividend)%10)?((((a)*dividend)/10)+1):(((a)*dividend)/10))
+static IMG_BOOL calculate_dvfs_max_min_threshold(IMG_UINT32 level)
+{
+ IMG_UINT32 pre_level;
+ IMG_UINT32 tmp ;
+
+ if (0 == level)
+ {
+ if ((RGX_DVFS_STEP - 1) == level)
+ {
+ rgx_dvfs_infotbl[level].min_threshold = level0_threshold_min;
+ rgx_dvfs_infotbl[level].max_threshold = levelf_threshold_max;
+ }
+ else
+ {
+ rgx_dvfs_infotbl[level].min_threshold = level0_threshold_min;
+ rgx_dvfs_infotbl[level].max_threshold = level0_threshold_max;
+ }
+#if RK33_USE_CL_COUNT_UTILS
+ rgx_dvfs_infotbl[level].coef = level0_coef_max;
+#endif
+ }
+ else
+ {
+ pre_level = level - 1;
+ if ((RGX_DVFS_STEP - 1) == level)
+ {
+ rgx_dvfs_infotbl[level].max_threshold = levelf_threshold_max;
+ }
+ else
+ {
+ rgx_dvfs_infotbl[level].max_threshold = rgx_dvfs_infotbl[pre_level].max_threshold + div_dvfs;
+ }
+ rgx_dvfs_infotbl[level].min_threshold = (rgx_dvfs_infotbl[pre_level].max_threshold * (rgx_dvfs_infotbl[pre_level].clock))
+ / (rgx_dvfs_infotbl[level].clock);
+
+ tmp = rgx_dvfs_infotbl[level].max_threshold - rgx_dvfs_infotbl[level].min_threshold;
+
+ rgx_dvfs_infotbl[level].min_threshold += fix_float(tmp);
+#if RK33_USE_CL_COUNT_UTILS
+ rgx_dvfs_infotbl[level].coef = (rgx_dvfs_infotbl[pre_level].clock * rgx_dvfs_infotbl[pre_level].coef + 2000)
+ / (rgx_dvfs_infotbl[level].clock);
+#endif
+ }
+
+#if 1
+ printk("rgx_dvfs_infotbl[%d].clock=%d,min_threshold=%d,max_threshold=%d,coef=%d\n", level,
+ rgx_dvfs_infotbl[level].clock,
+ rgx_dvfs_infotbl[level].min_threshold,
+ rgx_dvfs_infotbl[level].max_threshold,
+ rgx_dvfs_infotbl[level].coef
+ );
+#endif
+ return IMG_TRUE;
+}
+
+static void rk33_dvfs_set_clock(int freq)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (NULL == platform)
+ panic("oops");
+
+ if (!platform->gpu_clk_node || !platform->aclk_gpu_mem || !platform->gpu_clk_node)
+ {
+ printk("gpu_clk_node not init\n");
+ return;
+ }
+
+ rk33_clk_set_normal_node(platform->aclk_gpu_mem, freq);
+ rk33_clk_set_normal_node(platform->aclk_gpu_cfg, freq);
+ rk33_clk_set_dvfs_node(platform->gpu_clk_node, freq);
+
+ return;
+}
+
+#if RK33_DVFS_FREQ_LIMIT
+static int rk33_dvfs_get_freq(int level)
+{
+ if (WARN_ON((level >= RGX_DVFS_STEP) || (level < 0)))
+ {
+ printk("unkown rgx dvfs level:level = %d,set clock not done \n", level);
+ return -1;
+ }
+ return (rgx_dvfs_infotbl[level].clock);
+}
+#endif
+
+static int rk33_dvfs_get_level(int freq)
+{
+ int i;
+ for (i = 0; i < RGX_DVFS_STEP; i++)
+ {
+ if (rgx_dvfs_infotbl[i].clock == freq)
+ return i;
+ }
+ return -1;
+}
+
+static void rk33_dvfs_set_level(int level)
+{
+ static int prev_level = -1;
+
+ if (level == prev_level)
+ return;
+
+ if (WARN_ON((level >= RGX_DVFS_STEP) || (level < 0)))
+ {
+ printk("unkown rgx dvfs level:level = %d,set clock not done \n", level);
+ return ;
+ }
+ /*panic("invalid level");*/
+#if 0
+ if (mali_dvfs_status_current.upper_lock >= 0 && level > mali_dvfs_status_current.upper_lock)
+ level = mali_dvfs_status_current.upper_lock;
+ if (mali_dvfs_status_current.under_lock >= 0 && level < mali_dvfs_status_current.under_lock)
+ level = mali_dvfs_status_current.under_lock;
+#endif
+
+ mutex_lock(&rgx_set_clock_lock);
+
+ rk33_dvfs_set_clock(rgx_dvfs_infotbl[level].clock);
+#if 0
+ update_time_in_state(prev_level);
+#endif
+ prev_level = level;
+
+ mutex_unlock(&rgx_set_clock_lock);
+}
+
+static int rk33_dvfs_get_enable_status(void)
+{
+ struct rk_context *platform;
+ unsigned long flags;
+ int enable;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ spin_lock_irqsave(&platform->timer_lock, flags);
+ enable = platform->timer_active;
+ spin_unlock_irqrestore(&platform->timer_lock, flags);
+
+ return enable;
+}
+
+#if RK_RESERVED
+static int rk33_dvfs_enable(bool enable, int freq)
+{
+ struct rk_context *platform;
+ unsigned long flags;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ BUG_ON(platform == NULL);
+
+ mutex_lock(&rgx_enable_clock_lock);
+
+ if (enable != platform->timer_active)
+ {
+ if (enable)
+ {
+ spin_lock_irqsave(&platform->timer_lock, flags);
+ platform->timer_active = IMG_TRUE;
+ spin_unlock_irqrestore(&platform->timer_lock, flags);
+ hrtimer_start(&platform->timer,
+ HR_TIMER_DELAY_MSEC(RK33_DEFAULT_CLOCK),
+ HRTIMER_MODE_REL);
+ }
+ else
+ {
+ spin_lock_irqsave(&platform->timer_lock, flags);
+ platform->timer_active = IMG_FALSE;
+ spin_unlock_irqrestore(&platform->timer_lock, flags);
+ hrtimer_cancel(&platform->timer);
+ }
+ }
+
+ if (freq != RGX_DVFS_CURRENT_FREQ)
+ {
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ platform->time_tick = 0;
+ platform->time_busy = 0;
+ platform->time_idle = 0;
+ platform->utilisation = 0;
+ platform->freq_level = rk33_dvfs_get_level(freq);
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+ rk33_dvfs_set_level(platform->freq_level);
+ }
+
+ mutex_unlock(&rgx_enable_clock_lock);
+
+ return IMG_TRUE;
+}
+#endif
+
+
+#if RK33_USE_CL_COUNT_UTILS
+static void rk33_dvfs_event_proc(struct work_struct *w)
+{
+ unsigned long flags;
+ static IMG_UINT32 temp_tmp;
+ IMG_UINT32 fps = 0;
+ IMG_UINT32 fps_limit;
+ IMG_UINT32 policy;
+ IMG_INT32 absload;
+ IMG_INT32 new_index;
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ mutex_lock(&rgx_enable_clock_lock);
+
+ if (!rk33_dvfs_get_enable_status())
+ {
+ mutex_unlock(&rgx_enable_clock_lock);
+ return;
+ }
+
+ fps = rk_get_real_fps(0);
+
+ platform->temperature_time++;
+ /*
+ temp_tmp += rockchip_tsadc_get_temp(2);
+ */
+ if (platform->temperature_time >= gpu_temp_statis_time)
+ {
+ platform->temperature_time = 0;
+ platform->temperature = temp_tmp / gpu_temp_statis_time;
+ temp_tmp = 0;
+ /*pr_info("platform->temperature = %d\n",platform->temperature);*/
+ }
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+
+ platform->abs_load[0] = platform->abs_load[1];
+ platform->abs_load[1] = platform->abs_load[2];
+ platform->abs_load[2] = platform->abs_load[3];
+ platform->abs_load[3] = (platform->utilisation * rgx_dvfs_infotbl[platform->freq_level].clock * rgx_dvfs_infotbl[platform->freq_level].coef) / 100;
+ absload = (platform->abs_load[3] * 4 + platform->abs_load[2] * 3 + platform->abs_load[1] * 2 + platform->abs_load[0]);
+
+ /*
+ policy = rockchip_pm_get_policy();
+ */
+ policy = ROCKCHIP_PM_POLICY_NORMAL;
+
+ if (ROCKCHIP_PM_POLICY_PERFORMANCE == policy)
+ {
+ platform->freq_level = RGX_DVFS_STEP - 1; /*Highest level when performance mode*/
+ }
+ else if (platform->fix_freq > 0)
+ {
+ platform->freq_level = rk33_dvfs_get_level(platform->fix_freq);
+
+ if (platform->debug_level == DBG_HIGH)
+ printk("fix clock=%d\n", platform->fix_freq);
+ }
+ else
+ {
+ fps_limit = (ROCKCHIP_PM_POLICY_NORMAL == policy) ? LIMIT_FPS : LIMIT_FPS_POWER_SAVE;
+ /*
+ printk("policy : %d , fps_limit = %d\n",policy,fps_limit);
+ */
+
+
+ /*give priority to temperature unless in performance mode */
+ if (platform->temperature > gpu_temp_limit)
+ {
+ if (platform->freq_level > 0)
+ platform->freq_level--;
+
+ if (gpu_temp_statis_time > 1)
+ platform->temperature = 0;
+ }
+ else if (absload == 0 || platform->gpu_active == IMG_FALSE)
+ {
+ platform->freq_level = 0;
+ }
+ else if ((platform->freq_level < RGX_DVFS_STEP - 1) && fps < fps_limit)
+ {
+ //freq_hint=0 or freq_hint>sRK30_DVFS.u8FreqNums, select freq automatically, find the right index
+ for (new_index = 0; new_index < RGX_DVFS_STEP; new_index++)
+ {
+ if (absload <= (rgx_dvfs_infotbl[new_index].clock*rgx_dvfs_infotbl[new_index].coef*9))
+ {
+ if (platform->debug_level == DBG_HIGH)
+ printk("absload=%d,cur_coef[%d]=%d\n", absload, new_index, rgx_dvfs_infotbl[new_index].clock*rgx_dvfs_infotbl[new_index].coef*9);
+ break;
+ }
+ }
+
+ //ensure the new_index in the reasonable range
+ if (new_index >= RGX_DVFS_STEP)
+ {
+ new_index = RGX_DVFS_STEP - 1;
+ }
+
+ //if fps>=50, should not run at the higher frequency
+ if (new_index > platform->freq_level && fps >= fps_limit)
+ {
+ new_index = platform->freq_level;
+ }
+ //if running at highest frequency & fps>53 & absload<90%, try to run at a lower frequency
+ else if (platform->freq_level == RGX_DVFS_STEP - 1 && fps > 53 && absload <= (rgx_dvfs_infotbl[new_index].clock*rgx_dvfs_infotbl[new_index].coef*9))
+ {
+ new_index = platform->freq_level - 1;
+ }
+ if (platform->debug_level == DBG_HIGH)
+ printk("absload=%d,freq_level=%d,freq=%dM\n", absload, new_index, rgx_dvfs_infotbl[new_index].clock);
+
+ platform->freq_level = new_index;
+ }
+ }
+#if RK33_SYSFS_FILE_SUPPORT && RK33_DVFS_FREQ_LIMIT
+ if ((platform->up_level >= 0) && (platform->freq_level > platform->up_level))
+ {
+ platform->freq_level = platform->up_level;
+ }
+
+ if ((platform->down_level >= 0) && (platform->freq_level < platform->down_level))
+ {
+ platform->freq_level = platform->down_level;
+ }
+#endif
+
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+ rk33_dvfs_set_level(platform->freq_level);
+
+ platform->time_busy = 0;
+ platform->time_idle = 0;
+ platform->utilisation = 0;
+
+ mutex_unlock(&rgx_enable_clock_lock);
+}
+#else
+static void rk33_dvfs_event_proc(struct work_struct *w)
+{
+ unsigned long flags;
+ static int level_down_time = 0;
+ static int level_up_time = 0;
+ static IMG_UINT32 temp_tmp;
+ IMG_UINT32 fps = 0;
+ IMG_UINT32 fps_limit;
+ IMG_UINT32 policy;
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ mutex_lock(&rgx_enable_clock_lock);
+
+ if (!rk33_dvfs_get_enable_status())
+ {
+ mutex_unlock(&rgx_enable_clock_lock);
+ return;
+ }
+
+ fps = rk_get_real_fps(0);
+
+ platform->temperature_time++;
+ /*
+ temp_tmp += rockchip_tsadc_get_temp(2);
+ */
+ if (platform->temperature_time >= gpu_temp_statis_time)
+ {
+ platform->temperature_time = 0;
+ platform->temperature = temp_tmp / gpu_temp_statis_time;
+ temp_tmp = 0;
+ /*pr_info("platform->temperature = %d\n",platform->temperature);*/
+ }
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ /*
+ policy = rockchip_pm_get_policy();
+ */
+ policy = ROCKCHIP_PM_POLICY_NORMAL;
+
+ if (ROCKCHIP_PM_POLICY_PERFORMANCE == policy)
+ {
+ platform->freq_level = RGX_DVFS_STEP - 1; /*Highest level when performance mode*/
+ }
+ else if (platform->fix_freq > 0)
+ {
+ platform->freq_level = rk33_dvfs_get_level(platform->fix_freq);
+
+ if (platform->debug_level == DBG_HIGH)
+ printk("fix clock=%d\n", platform->fix_freq);
+ }
+ else
+ {
+ fps_limit = (ROCKCHIP_PM_POLICY_NORMAL == policy) ? LIMIT_FPS : LIMIT_FPS_POWER_SAVE;
+#if 0
+ printk("policy : %d , fps_limit = %d\n", policy, fps_limit);
+#endif
+
+ /*give priority to temperature unless in performance mode */
+ if (platform->temperature > gpu_temp_limit)
+ {
+ if (platform->freq_level > 0)
+ platform->freq_level--;
+
+ if (gpu_temp_statis_time > 1)
+ platform->temperature = 0;
+ }
+ else if ((platform->utilisation > rgx_dvfs_infotbl[platform->freq_level].max_threshold) && (platform->freq_level < RGX_DVFS_STEP - 1) && fps < fps_limit)
+ {
+ level_up_time++;
+ if (level_up_time == RGX_DVFS_LEVEL_INTERVAL)
+ {
+ if (platform->debug_level == DBG_HIGH)
+ printk("up,utilisation=%d,current clock=%d,fps = %d\n", platform->utilisation, rgx_dvfs_infotbl[platform->freq_level].clock, fps);
+
+ platform->freq_level++;
+ level_up_time = 0;
+
+ if (platform->debug_level == DBG_HIGH)
+ printk(" next clock=%d\n", rgx_dvfs_infotbl[platform->freq_level].clock);
+
+ BUG_ON(platform->freq_level >= RGX_DVFS_STEP);
+ }
+ level_down_time = 0;
+ }
+ else if ((platform->freq_level > 0) && (platform->utilisation < rgx_dvfs_infotbl[platform->freq_level].min_threshold))
+ /*else if((dvfs_status->step > 0) && (platform->time_tick == RGX_DVFS_LEVEL_INTERVAL) && (platform->utilisation < mali_dvfs_infotbl[dvfs_status->step].min_threshold)) */
+ {
+ level_down_time++;
+ if (level_down_time == RGX_DVFS_LEVEL_INTERVAL)
+ {
+ if (platform->debug_level == DBG_HIGH)
+ printk("down,utilisation=%d,current clock=%d,fps = %d\n", platform->utilisation, rgx_dvfs_infotbl[platform->freq_level].clock, fps);
+
+ BUG_ON(platform->freq_level <= 0);
+ platform->freq_level--;
+ level_down_time = 0;
+
+ if (platform->debug_level == DBG_HIGH)
+ printk(" next clock=%d\n", rgx_dvfs_infotbl[platform->freq_level].clock);
+ }
+ level_up_time = 0;
+ }
+ else
+ {
+ level_down_time = 0;
+ level_up_time = 0;
+
+ if (platform->debug_level == DBG_HIGH)
+ printk("keep,utilisation=%d,current clock=%d,fps = %d\n", platform->utilisation, rgx_dvfs_infotbl[platform->freq_level].clock, fps);
+ }
+ }
+#if RK33_SYSFS_FILE_SUPPORT && RK33_DVFS_FREQ_LIMIT
+ if ((platform->up_level >= 0) && (platform->freq_level > platform->up_level))
+ {
+ platform->freq_level = platform->up_level;
+ }
+
+ if ((platform->down_level >= 0) && (platform->freq_level < platform->down_level))
+ {
+ platform->freq_level = platform->down_level;
+ }
+#endif
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+ rk33_dvfs_set_level(platform->freq_level);
+
+ platform->time_busy = 0;
+ platform->time_idle = 0;
+ platform->utilisation = 0;
+
+ mutex_unlock(&rgx_enable_clock_lock);
+}
+#endif
+static DECLARE_WORK(rgx_dvfs_work, rk33_dvfs_event_proc);
+
+static IMG_BOOL rk33_dvfs_event(RGXFWIF_GPU_UTIL_STATS* psUtilStats)
+{
+ struct rk_context *platform;
+#if !RK33_USE_CUSTOMER_GET_GPU_UTIL
+ IMG_UINT32 time_busy = 0;
+ IMG_UINT32 time_idle = 0;
+#endif
+ unsigned long flags;
+#if RK33_USE_CUSTOMER_GET_GPU_UTIL
+ ktime_t now = ktime_get();
+ ktime_t diff;
+ IMG_INT i;
+#endif
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ PVR_ASSERT(platform != NULL);
+
+#if RK33_USE_RGX_GET_GPU_UTIL
+ PVR_ASSERT(psUtilStats != NULL);
+
+ if (platform->debug_level == DBG_HIGH)
+ printk("GPU util info:valid[%d],bIncompleteData[%d],ActiveHigh[%d],ActiveLow[%d],Blocked[%d],Idle[%d]\n",
+ psUtilStats->bValid, psUtilStats->bIncompleteData,
+ psUtilStats->ui32GpuStatActiveHigh, psUtilStats->ui32GpuStatActiveLow,
+ psUtilStats->ui32GpuStatBlocked, psUtilStats->ui32GpuStatIdle);
+
+ if (psUtilStats->bValid /*&& psUtilStats->bIncompleteData*/)
+ {
+ time_busy = psUtilStats->ui32GpuStatActiveHigh + psUtilStats->ui32GpuStatActiveLow ;
+ time_idle = psUtilStats->ui32GpuStatIdle + psUtilStats->ui32GpuStatBlocked;
+
+ //check valid
+ if (time_busy + time_idle == 0)
+ {
+ goto err;
+ }
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ platform->time_busy += time_busy;
+ platform->time_idle += time_idle;
+ platform->utilisation = (time_busy * 100) / (time_busy + time_idle);
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+ queue_work_on(0, rgx_dvfs_wq, &rgx_dvfs_work);
+ }
+#elif RK33_USE_CUSTOMER_GET_GPU_UTIL
+
+ diff = ktime_sub(now, platform->time_period_start);
+
+ if (platform->gpu_active)
+ {
+ platform->time_busy += (IMG_UINT32)(ktime_to_ns(diff) >> RK_PM_TIME_SHIFT);
+ platform->time_period_start = now;
+ }
+ else
+ {
+ platform->time_idle += (IMG_UINT32)(ktime_to_ns(diff) >> RK_PM_TIME_SHIFT);
+ platform->time_period_start = now;
+ }
+
+
+ //check valid
+ if (platform->time_busy + platform->time_idle == 0)
+ {
+ goto err;
+ }
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ for(i=0;i<RK33_MAX_UTILIS-1;i++)
+ {
+ platform->stUtilis.time_busys[i]=platform->stUtilis.time_busys[i+1];
+ platform->stUtilis.time_idles[i]=platform->stUtilis.time_idles[i+1];
+ platform->stUtilis.utilis[i]=platform->stUtilis.utilis[i+1];
+ }
+ platform->stUtilis.time_busys[RK33_MAX_UTILIS-1] = platform->time_busy;
+ platform->stUtilis.time_idles[RK33_MAX_UTILIS-1] = platform->time_idle;
+ platform->stUtilis.utilis[RK33_MAX_UTILIS-1] = (platform->time_busy * 10) / (platform->time_busy + platform->time_idle);
+ platform->utilisation = platform->stUtilis.utilis[3] * 4 + platform->stUtilis.utilis[2] * 3 +\
+ platform->stUtilis.utilis[1] * 2 + platform->stUtilis.utilis[0] * 1;
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+
+ if (platform->debug_level == DBG_HIGH)
+ printk("GPU util info:time_busy=%d,time_idle=%d,utilisation=%d\n",platform->time_busy,platform->time_idle,platform->utilisation);
+
+ queue_work_on(0, rgx_dvfs_wq, &rgx_dvfs_work);
+#endif
+
+ return IMG_TRUE;
+
+err:
+
+ platform->time_busy = 0;
+ platform->time_idle = 0;
+ platform->utilisation = 0;
+
+ return IMG_FALSE;
+}
+
+
+static enum hrtimer_restart dvfs_callback(struct hrtimer *timer)
+{
+ unsigned long flags;
+ struct rk_context *platform;
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+
+ PVR_ASSERT(timer != NULL);
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ PVR_ASSERT(platform != NULL);
+
+#if 0
+ if (platform->psDeviceNode == NULL)
+ {
+ //Fix dvfs_callback crash problem when psDeviceNode hasn't been set.
+ PVR_DPF((PVR_DBG_WARNING, "%s:line=%d, DeviceNode is null", __func__, __LINE__));
+ spin_lock_irqsave(&platform->timer_lock, flags);
+ if (platform->timer_active)
+ hrtimer_start(timer,
+ HR_TIMER_DELAY_MSEC(10*RK33_DVFS_FREQ), //delay 500ms
+ HRTIMER_MODE_REL);
+ spin_unlock_irqrestore(&platform->timer_lock, flags);
+ }
+ else
+#endif
+ {
+ psDevInfo = platform->psDeviceNode->pvDevice;
+
+ if(psDevInfo && psDevInfo->pfnGetGpuUtilStats)
+ {
+ //Measuring GPU Utilisation
+ platform->sUtilStats = ((psDevInfo->pfnGetGpuUtilStats)(platform->psDeviceNode));
+ rk33_dvfs_event(&platform->sUtilStats);
+ }
+ else
+ {
+ if(!psDevInfo)
+ PVR_DPF((PVR_DBG_ERROR,"%s:line=%d,psDevInfo=%p\n",__func__,__LINE__,psDevInfo));
+ else
+ PVR_DPF((PVR_DBG_ERROR,"%s:line=%d,pfnGetGpuUtilStats=%p\n",__func__,__LINE__,psDevInfo->pfnGetGpuUtilStats));
+ }
+
+ spin_lock_irqsave(&platform->timer_lock, flags);
+ if (platform->timer_active)
+ hrtimer_start(timer,
+ HR_TIMER_DELAY_MSEC(RK33_DVFS_FREQ),
+ HRTIMER_MODE_REL);
+ spin_unlock_irqrestore(&platform->timer_lock, flags);
+ }
+
+ return HRTIMER_NORESTART;
+}
+static IMG_VOID rk33_dvfs_utils_init(struct rk_context *platform)
+{
+ static bool timer_inited = false;
+#if RK33_USE_CUSTOMER_GET_GPU_UTIL
+ IMG_INT i;
+#endif
+ PVR_ASSERT(platform != NULL);
+
+// spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+
+ platform->utilisation = 0;
+ platform->freq_level = 0;
+ platform->freq = 0;
+ platform->time_tick = 0;
+#if RK33_USE_CUSTOMER_GET_GPU_UTIL
+ platform->time_period_start = ktime_get();
+ for(i=0;i<RK33_MAX_UTILIS;i++)
+ {
+ platform->stUtilis.time_busys[i]=0;
+ platform->stUtilis.time_idles[i]=0;
+ platform->stUtilis.utilis[i]=0;
+ }
+#endif
+ platform->gpu_active = IMG_FALSE;
+ platform->time_busy = 0;
+ platform->time_idle = 0;
+ platform->temperature = 0;
+ platform->temperature_time = 0;
+ platform->timer_active = IMG_TRUE;
+ platform->dvfs_enabled = IMG_TRUE;
+
+#if RK33_USE_CL_COUNT_UTILS
+ platform->abs_load[0] = platform->abs_load[1] = platform->abs_load[2] = platform->abs_load[3] = 0;
+#endif
+#if RK33_SYSFS_FILE_SUPPORT
+ platform->debug_level = DBG_OFF;
+ platform->fix_freq = 0;
+ platform->fps_gap = FPS_DEFAULT_GAP;
+#if RK33_DVFS_FREQ_LIMIT
+ platform->up_level = -1;
+ platform->down_level = -1;
+#endif //RK33_DVFS_FREQ_LIMIT
+#endif //RK33_SYSFS_FILE_SUPPORT
+
+ //dvfs timer
+ spin_lock_init(&platform->timer_lock);
+
+ if (!timer_inited)
+ {
+ hrtimer_init(&platform->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ timer_inited = true;
+ }
+ platform->timer.function = dvfs_callback;
+
+ //spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+}
+
+static void rk33_dvfs_utils_term(struct rk_context *platform)
+{
+ unsigned long flags;
+
+ PVR_ASSERT(platform != NULL);
+
+ spin_lock_irqsave(&platform->timer_lock, flags);
+ platform->timer_active = IMG_FALSE;
+ spin_unlock_irqrestore(&platform->timer_lock, flags);
+
+ hrtimer_cancel(&platform->timer);
+}
+
+#if RK33_USE_CUSTOMER_GET_GPU_UTIL
+/*caller needs to hold kbdev->pm.metrics.lock before calling this function*/
+static void rk33_dvfs_record_busy_utils(struct rk_context *platform)
+{
+ ktime_t now;
+ ktime_t diff;
+ IMG_UINT32 ns_time;
+
+ PVR_ASSERT(platform != NULL);
+
+ now = ktime_get();
+ diff = ktime_sub(now, platform->time_period_start);
+
+ ns_time = (IMG_UINT32)(ktime_to_ns(diff) >> RK_PM_TIME_SHIFT);
+ platform->time_busy += ns_time;
+ platform->time_period_start = now;
+}
+
+static void rk33_dvfs_record_idle_utils(struct rk_context *platform)
+{
+ ktime_t now;
+ ktime_t diff;
+ IMG_UINT32 ns_time;
+
+ PVR_ASSERT(platform != NULL);
+
+ now = ktime_get();
+ diff = ktime_sub(now, platform->time_period_start);
+
+ ns_time = (IMG_UINT32)(ktime_to_ns(diff) >> RK_PM_TIME_SHIFT);
+ platform->time_idle += ns_time;
+ platform->time_period_start = now;
+}
+#endif
+
+static void rk33_dvfs_record_gpu_idle(struct rk_context *platform)
+{
+ unsigned long flags;
+
+ PVR_ASSERT(platform != NULL);
+
+ spin_lock_irqsave(&platform->timer_lock, flags);
+
+ //PVR_ASSERT(platform->gpu_active == IMG_TRUE);
+
+ platform->gpu_active = IMG_FALSE;
+#if RK33_USE_CUSTOMER_GET_GPU_UTIL
+ rk33_dvfs_record_busy_utils(platform);
+#endif
+ spin_unlock_irqrestore(&platform->timer_lock, flags);
+}
+
+
+static void rk33_dvfs_record_gpu_active(struct rk_context *platform)
+{
+ unsigned long flags;
+
+ PVR_ASSERT(platform != NULL);
+
+ spin_lock_irqsave(&platform->timer_lock, flags);
+
+ //PVR_ASSERT(platform->gpu_active == IMG_FALSE);
+
+ platform->gpu_active = IMG_TRUE;
+#if RK33_USE_CUSTOMER_GET_GPU_UTIL
+ rk33_dvfs_record_idle_utils(platform);
+#endif
+
+ spin_unlock_irqrestore(&platform->timer_lock, flags);
+}
+
+static IMG_BOOL rk33_dvfs_get_freq_table(struct rk_context *platform)
+{
+ IMG_INT i;
+
+ PVR_ASSERT(platform != NULL);
+
+ //get freq table
+ rgx_freq_table = dvfs_get_freq_volt_table(platform->gpu_clk_node);
+
+ if (rgx_freq_table == NULL)
+ {
+ printk("rgx freq table not assigned yet,use default\n");
+ return IMG_FALSE ;
+ }
+ else
+ {
+ /*recalculte step*/
+ RGX_DVFS_STEP = 0;
+
+ PVR_DPF((PVR_DBG_WARNING, "The raw GPU freq_table:"));
+ for (i = 0; rgx_freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+ {
+ rgx_dvfs_infotbl[i].clock = rgx_freq_table[i].frequency / ONE_KHZ;
+ PVR_DPF((PVR_DBG_WARNING, "%dM,", rgx_dvfs_infotbl[i].clock));
+ RGX_DVFS_STEP++;
+ }
+
+ if (RGX_DVFS_STEP > 1)
+ div_dvfs = round_up(((levelf_threshold_max - level0_threshold_max) / (RGX_DVFS_STEP - 1)), 1);
+
+ PVR_DPF((PVR_DBG_WARNING, "RGX_DVFS_STEP=%d,div_dvfs=%d\n", RGX_DVFS_STEP, div_dvfs));
+
+ for (i = 0;i < RGX_DVFS_STEP;i++)
+ {
+ calculate_dvfs_max_min_threshold(i);
+ }
+ p_rgx_dvfs_infotbl = rgx_dvfs_infotbl;
+ }
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL rk33_dvfs_init(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (IMG_FALSE == rk33_dvfs_get_freq_table(platform))
+ return IMG_FALSE;
+
+ if (!rgx_dvfs_wq)
+ rgx_dvfs_wq = create_singlethread_workqueue("rgx_dvfs");
+
+ spin_lock_init(&rgx_dvfs_spinlock);
+ mutex_init(&rgx_set_clock_lock);
+ mutex_init(&rgx_enable_clock_lock);
+
+ rk33_dvfs_utils_init(platform);
+
+ return IMG_TRUE;
+}
+
+
+IMG_VOID rk33_dvfs_term(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ PVR_ASSERT(platform != NULL);
+
+ rk33_dvfs_utils_term(platform);
+
+ if (rgx_dvfs_wq)
+ destroy_workqueue(rgx_dvfs_wq);
+
+ rgx_dvfs_wq = NULL;
+}
+
+#if RK33_SYSFS_FILE_SUPPORT
+#if RK33_DVFS_FREQ_LIMIT
+static int rk33_dvfs_up_limit_on(int level)
+{
+ struct rk_context *platform;
+ unsigned long flags;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (!platform || level < 0)
+ return -ENODEV;
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ if (platform->down_level >= 0 &&
+ platform->down_level > level)
+ {
+ PVR_DPF((PVR_DBG_ERROR, " rk33_dvfs_up_limit_on : Attempting to set upper lock (%d) to below under lock(%d)\n", level, platform->down_level));
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+ return -1;
+ }
+ platform->up_level = level;
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+
+ PVR_DPF((PVR_DBG_WARNING, " Up Level Set : %d\n", level));
+
+ return 0;
+}
+
+static int rk33_dvfs_up_limit_off(void)
+{
+ struct rk_context *platform;
+ unsigned long flags;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (!platform)
+ return -ENODEV;
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ platform->up_level = -1;
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+
+ PVR_DPF((PVR_DBG_WARNING, "Up Level Unset\n"));
+
+ return 0;
+}
+
+static int rk33_dvfs_down_limit_on(int level)
+{
+ struct rk_context *platform;
+ unsigned long flags;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (!platform || level < 0)
+ return -ENODEV;
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ if (platform->up_level >= 0 &&
+ platform->up_level < level)
+ {
+ PVR_DPF((PVR_DBG_ERROR, " rk33_dvfs_down_limit_on : Attempting to set under lock (%d) to above upper lock(%d)\n", level, platform->up_level));
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+ return -1;
+ }
+ platform->down_level = level;
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+
+ PVR_DPF((PVR_DBG_WARNING, " Down Level Set : %d\n", level));
+
+ return 0;
+}
+
+static int rk33_dvfs_down_limit_off(void)
+{
+ struct rk_context *platform;
+ unsigned long flags;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (!platform)
+ return -ENODEV;
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ platform->down_level = -1;
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+
+ PVR_DPF((PVR_DBG_WARNING, "Up Level Unset\n"));
+
+ return 0;
+}
+
+static int rk33_dvfs_get_dvfs_up_limit_freq(void)
+{
+ struct rk_context *platform;
+ unsigned long flags;
+ int up_level = -1;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (!platform)
+ return -ENODEV;
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ up_level = rk33_dvfs_get_freq(platform->up_level);
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+
+ return up_level;
+}
+
+static int rk33_dvfs_get_dvfs_down_limit_freq(void)
+{
+ struct rk_context *platform;
+ unsigned long flags;
+ int down_level = -1;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (!platform)
+ return -ENODEV;
+
+ spin_lock_irqsave(&rgx_dvfs_spinlock, flags);
+ down_level = rk33_dvfs_get_freq(platform->down_level);
+ spin_unlock_irqrestore(&rgx_dvfs_spinlock, flags);
+
+ return down_level;
+}
+#endif //end of RK33_DVFS_FREQ_LIMIT
+
+static ssize_t show_freq(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct rk_context *platform;
+ ssize_t ret = 0;
+ unsigned int clkrate;
+ int i ;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (!platform)
+ return -ENODEV;
+
+ if (platform->debug_level > DBG_OFF)
+ {
+#if RK33_DVFS_SUPPORT
+ if (!platform->gpu_clk_node)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "gpu_clk_node not init!"));
+ return -ENODEV;
+ }
+ clkrate = dvfs_clk_get_rate(platform->gpu_clk_node);
+#else
+ if (!platform->aclk_gpu_mem)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "aclk_gpu_mem not init!"));
+ return -ENODEV;
+ }
+ clkrate = clk_get_rate(platform->aclk_gpu_mem);
+#endif
+ if (platform->dvfs_enabled)
+ {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "DVFS is on");
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\nCurrent clk rgx = %dMhz", clkrate / ONE_MHZ);
+ /* To be revised */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\nPossible settings:");
+ for (i = 0;i < RGX_DVFS_STEP;i++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d ", p_rgx_dvfs_infotbl[i].clock);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "Mhz");
+ }
+ else
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "DVFS is off");
+
+ if (ret < PAGE_SIZE - 1)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+ else
+ {
+ buf[PAGE_SIZE - 2] = '\n';
+ buf[PAGE_SIZE - 1] = '\0';
+ ret = PAGE_SIZE - 1;
+ }
+ }
+ return ret;
+}
+
+static ssize_t set_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct rk_context *platform;
+ unsigned int tmp = 0, freq = 0;
+ tmp = 0;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+ if (!platform)
+ return -ENODEV;
+
+ if (!platform->gpu_clk_node)
+ return -ENODEV;
+#if 0
+ if (sysfs_streq("500", buf))
+ {
+ freq = 500;
+ }
+ else if (sysfs_streq("400", buf))
+ {
+ freq = 400;
+ }
+ else if (sysfs_streq("350", buf))
+ {
+ freq = 350;
+ }
+ else if (sysfs_streq("266", buf))
+ {
+ freq = 266;
+ }
+ else if (sysfs_streq("160", buf))
+ {
+ freq = 160;
+ }
+ else if (sysfs_streq("100", buf))
+ {
+ freq = 100;
+ }
+ else
+ {
+ dev_err(dev, "set_clock: invalid value\n");
+ return -ENOENT;
+ }
+#endif
+
+ if (memcmp(buf, "debug_hi", 8) == 0)
+ {
+ platform->debug_level = DBG_HIGH;
+ return (count);
+ }
+ if (memcmp(buf, "debug_lo", 8) == 0)
+ {
+ platform->debug_level = DBG_LOW;
+ return (count);
+ }
+ else if (memcmp(buf, "debug_off", 9) == 0)
+ {
+ platform->debug_level = DBG_OFF;
+ return (count);
+ }
+
+// freq = simple_strtoul(buf, NULL, 10);
+ if (sscanf(buf, "%i", &freq) == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "invalid value"));
+ return -EINVAL;
+ }
+ else
+ {
+ if (rk33_dvfs_get_level(freq) >= RGX_DVFS_STEP || rk33_dvfs_get_level(freq) < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "invalid freq(%d)", freq));
+ platform->fix_freq = 0; //open dvfs
+ return count;
+ }
+ }
+
+ rk33_dvfs_set_level(rk33_dvfs_get_level(freq));
+
+ platform->fix_freq = freq; //close dvfs
+
+ return count;
+}
+
+static ssize_t show_utilisation(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct rk_context *platform;
+ PVRSRV_RGXDEV_INFO *psDevInfo;
+ IMG_INT utilisation;
+ IMG_UINT32 time_busy;
+ IMG_UINT32 time_idle;
+ ssize_t ret = 0;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+ if (!platform || !platform->psDeviceNode)
+ return -ENODEV;
+
+ if (platform->debug_level > DBG_OFF)
+ {
+ psDevInfo = platform->psDeviceNode->pvDevice;
+
+ //Measuring GPU Utilisation
+ platform->sUtilStats = ((psDevInfo->pfnGetGpuUtilStats)(platform->psDeviceNode));
+ time_busy = platform->sUtilStats.ui32GpuStatActiveHigh + platform->sUtilStats.ui32GpuStatActiveLow;
+ time_idle = platform->sUtilStats.ui32GpuStatIdle + platform->sUtilStats.ui32GpuStatBlocked;
+ utilisation = (time_busy * 100) / (time_busy + time_idle);
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "Utilisation=%d", utilisation);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\nDetail: ActiveHigh=%d,ActiveLow=%d,Blocked=%d,Idle=%d", \
+ platform->sUtilStats.ui32GpuStatActiveHigh, platform->sUtilStats.ui32GpuStatActiveLow, platform->sUtilStats.ui32GpuStatBlocked, platform->sUtilStats.ui32GpuStatIdle);
+
+ if (ret < PAGE_SIZE - 1)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+ else
+ {
+ buf[PAGE_SIZE - 2] = '\n';
+ buf[PAGE_SIZE - 1] = '\0';
+ ret = PAGE_SIZE - 1;
+ }
+ }
+ return ret;
+}
+
+static ssize_t set_utilisation(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int utilisation = 0;
+ utilisation = simple_strtoul(buf, NULL, 10);
+
+ return count;
+}
+
+static ssize_t show_fbdev(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < num_registered_fb; i++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "fb[%d] xres=%d, yres=%d, addr=0x%lx\n", i, registered_fb[i]->var.xres, registered_fb[i]->var.yres, registered_fb[i]->fix.smem_start);
+
+ if (ret < PAGE_SIZE - 1)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+ else
+ {
+ buf[PAGE_SIZE - 2] = '\n';
+ buf[PAGE_SIZE - 1] = '\0';
+ ret = PAGE_SIZE - 1;
+ }
+
+ return ret;
+}
+
+static ssize_t show_fps(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret = 0;
+ IMG_UINT32 fps = 0;
+
+ fps = rk_get_real_fps(0);
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "fbs=%d", fps);
+
+ if (ret < PAGE_SIZE - 1)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+ else
+ {
+ buf[PAGE_SIZE - 2] = '\n';
+ buf[PAGE_SIZE - 1] = '\0';
+ ret = PAGE_SIZE - 1;
+ }
+
+ return ret;
+}
+static enum hrtimer_restart fps_callback(struct hrtimer *timer)
+{
+ struct rk_context *platform;
+ IMG_UINT32 fps = 0;
+
+ PVR_ASSERT(timer != NULL);
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+ PVR_ASSERT(platform != NULL);
+
+ fps = rk_get_real_fps(0);
+ printk("Current fps=%d\n", fps);
+
+ hrtimer_start(timer,
+ HR_TIMER_DELAY_MSEC(platform->fps_gap),
+ HRTIMER_MODE_REL);
+
+ return HRTIMER_NORESTART;
+}
+
+static ssize_t set_fps(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct rk_context *platform;
+ static IMG_BOOL bOpen = IMG_FALSE;
+ static struct hrtimer timer;
+ IMG_UINT gap = FPS_DEFAULT_GAP;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (!platform)
+ return -ENODEV;
+
+ gap = simple_strtoul(buf, NULL, 10);
+
+ if (sysfs_streq("on", buf) && !bOpen)
+ {
+ bOpen = IMG_TRUE;
+ hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ timer.function = fps_callback;
+ hrtimer_start(&timer, HR_TIMER_DELAY_MSEC(platform->fps_gap), HRTIMER_MODE_REL);
+ printk("on fps\n");
+ }
+ else if (sysfs_streq("off", buf))
+ {
+ printk("off fps\n");
+
+ bOpen = IMG_FALSE;
+ hrtimer_cancel(&timer);
+ }
+ else
+ {
+ if (gap > 0 && gap < FPS_MAX_GAP)
+ platform->fps_gap = gap;
+ }
+
+ return count;
+}
+
+#if RK33_DVFS_FREQ_LIMIT
+static ssize_t show_up_limit(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct rk_context *platform;
+ ssize_t ret = 0;
+ int i;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+ if (!platform)
+ return -ENODEV;
+
+ if (platform->up_level >= 0 && platform->up_level < RGX_DVFS_STEP)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "Current Up limit freq = %dMhz", rk33_dvfs_get_dvfs_up_limit_freq());
+ else
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "Unset the up limit level");
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\nPossible settings :");
+ for (i = 0;i < RGX_DVFS_STEP;i++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d ", p_rgx_dvfs_infotbl[i].clock);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "Mhz");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, ", If you want to unlock : off");
+
+ if (ret < PAGE_SIZE - 1)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+ else
+ {
+ buf[PAGE_SIZE - 2] = '\n';
+ buf[PAGE_SIZE - 1] = '\0';
+ ret = PAGE_SIZE - 1;
+ }
+
+ return ret;
+}
+
+static ssize_t set_up_limit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct rk_context *platform;
+ unsigned int freq = 0;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+ if (!platform)
+ return -ENODEV;
+
+ freq = simple_strtoul(buf, NULL, 10);
+
+ if (sysfs_streq("off", buf))
+ {
+ rk33_dvfs_up_limit_off();
+ }
+ else
+ {
+ rk33_dvfs_up_limit_on(rk33_dvfs_get_level(freq));
+ }
+
+ return count;
+}
+
+static ssize_t show_down_limit(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct rk_context *platform;
+ ssize_t ret = 0;
+ int i;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+ if (!platform)
+ return -ENODEV;
+
+ if (platform->down_level >= 0 && platform->down_level < RGX_DVFS_STEP)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "Current down limit freq = %dMhz", rk33_dvfs_get_dvfs_down_limit_freq());
+ else
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "Unset the down limit level");
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\nPossible settings :");
+ for (i = 0;i < RGX_DVFS_STEP;i++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d ", p_rgx_dvfs_infotbl[i].clock);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "Mhz");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, ", If you want to unlock : off");
+
+ if (ret < PAGE_SIZE - 1)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+ else
+ {
+ buf[PAGE_SIZE - 2] = '\n';
+ buf[PAGE_SIZE - 1] = '\0';
+ ret = PAGE_SIZE - 1;
+ }
+
+ return ret;
+}
+
+static ssize_t set_down_limit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct rk_context *platform;
+ unsigned int freq = 0;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+ if (!platform)
+ return -ENODEV;
+
+ freq = simple_strtoul(buf, NULL, 10);
+
+ if (sysfs_streq("off", buf))
+ {
+ rk33_dvfs_down_limit_off();
+ }
+ else
+ {
+ rk33_dvfs_down_limit_on(rk33_dvfs_get_level(freq));
+ }
+
+ return count;
+}
+#endif
+
+/** The sysfs file @c clock, fbdev.
+ *
+ * This is used for obtaining information about the mali t6xx operating clock & framebuffer address,
+ */
+DEVICE_ATTR(freq, S_IRUGO | S_IWUSR, show_freq, set_freq);
+DEVICE_ATTR(util, S_IRUGO | S_IWUSR, show_utilisation, set_utilisation);
+DEVICE_ATTR(fbdev, S_IRUGO, show_fbdev, NULL);
+DEVICE_ATTR(fps, S_IRUGO | S_IWUSR, show_fps, set_fps);
+#if RK33_DVFS_FREQ_LIMIT
+DEVICE_ATTR(dvfs_up_limit, S_IRUGO | S_IWUSR, show_up_limit, set_up_limit);
+DEVICE_ATTR(dvfs_down_limit, S_IRUGO | S_IWUSR, show_down_limit, set_down_limit);
+#endif
+
+static IMG_INT rk_create_sysfs_file(struct device *dev)
+{
+ if (device_create_file(dev, &dev_attr_freq))
+ {
+ dev_err(dev, "Couldn't create sysfs file [freq]\n");
+ goto out;
+ }
+
+ if (device_create_file(dev, &dev_attr_util))
+ {
+ dev_err(dev, "Couldn't create sysfs file [utilisation]\n");
+ goto out;
+ }
+
+ if (device_create_file(dev, &dev_attr_fbdev))
+ {
+ dev_err(dev, "Couldn't create sysfs file [fbdev]\n");
+ goto out;
+ }
+
+ if (device_create_file(dev, &dev_attr_fps))
+ {
+ dev_err(dev, "Couldn't create sysfs file [fbdev]\n");
+ goto out;
+ }
+
+#if RK33_DVFS_FREQ_LIMIT
+ if (device_create_file(dev, &dev_attr_dvfs_up_limit))
+ {
+ dev_err(dev, "Couldn't create sysfs file [dvfs_upper_lock]\n");
+ goto out;
+ }
+
+ if (device_create_file(dev, &dev_attr_dvfs_down_limit))
+ {
+ dev_err(dev, "Couldn't create sysfs file [dvfs_under_lock]\n");
+ goto out;
+ }
+#endif
+
+ return 0;
+out:
+ return -ENOENT;
+}
+
+static IMG_VOID rk_remove_sysfs_file(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_freq);
+ device_remove_file(dev, &dev_attr_util);
+ device_remove_file(dev, &dev_attr_fbdev);
+ device_remove_file(dev, &dev_attr_fps);
+#if RK33_DVFS_FREQ_LIMIT
+ device_remove_file(dev, &dev_attr_dvfs_up_limit);
+ device_remove_file(dev, &dev_attr_dvfs_down_limit);
+#endif
+}
+
+
+
+#endif //end of RK33_SYSFS_FILE_SUPPORT
+
+#endif //end of RK33_DVFS_SUPPORT
+
+IMG_BOOL rk33_set_device_node(IMG_HANDLE hDevCookie)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if(platform)
+ {
+ platform->psDeviceNode = (PVRSRV_DEVICE_NODE*)hDevCookie;
+ //start timer
+ if(platform->psDeviceNode)
+ hrtimer_start(&platform->timer, HR_TIMER_DELAY_MSEC(RK33_DVFS_FREQ), HRTIMER_MODE_REL);
+ }
+ else
+ {
+ //call PVRSRVRegisterPowerDevice before RgxRkInit.
+ PVR_DPF((PVR_DBG_ERROR,"PVR_K:%s platform is null\n",__func__));
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL rk33_clear_device_node(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if(platform)
+ {
+ //cacel timer
+ hrtimer_cancel(&platform->timer);
+ platform->psDeviceNode = NULL;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVR_K:%s platform is null\n",__func__));
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+
+
+static IMG_VOID RgxEnableClock(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (
+#if RK33_DVFS_SUPPORT
+ platform->gpu_clk_node &&
+#endif
+ platform->aclk_gpu_mem && platform->aclk_gpu_cfg && !platform->bEnableClk)
+ {
+#if RK33_DVFS_SUPPORT
+ dvfs_clk_prepare_enable(platform->gpu_clk_node);
+#endif
+ clk_prepare_enable(platform->aclk_gpu_mem);
+ clk_prepare_enable(platform->aclk_gpu_cfg);
+ platform->bEnableClk = IMG_TRUE;
+
+#if RK33_DVFS_SUPPORT
+ rk33_dvfs_record_gpu_active(platform);
+#endif
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Failed to enable clock!"));
+ }
+}
+
+static IMG_VOID RgxDisableClock(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ if (
+#if RK33_DVFS_SUPPORT
+ platform->gpu_clk_node &&
+#endif
+ platform->aclk_gpu_mem && platform->aclk_gpu_cfg && platform->bEnableClk)
+ {
+ clk_disable_unprepare(platform->aclk_gpu_cfg);
+ clk_disable_unprepare(platform->aclk_gpu_mem);
+#if RK33_DVFS_SUPPORT
+ dvfs_clk_disable_unprepare(platform->gpu_clk_node);
+#endif
+ platform->bEnableClk = IMG_FALSE;
+#if RK33_DVFS_SUPPORT
+ rk33_dvfs_record_gpu_idle(platform);
+#endif
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Failed to disable clock!"));
+ }
+}
+
+#if RK_RESERVED
+static IMG_BOOL RgxIsPowerOn(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ PVR_ASSERT(platform != NULL);
+
+ return platform->bEnablePd;
+}
+#endif
+
+#if OPEN_GPU_PD
+/*
+ * The power management
+ * software must power down pd_gpu_1 before power down pd_gpu_0,
+ * and power up pd_gpu_1 after power up pd_gpu_0.
+ */
+static IMG_VOID RgxEnablePower(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ PVR_ASSERT(platform != NULL);
+
+ if (!platform->bEnablePd && platform->pd_gpu_0 && platform->pd_gpu_1)
+ {
+ clk_prepare_enable(platform->pd_gpu_0);
+ clk_prepare_enable(platform->pd_gpu_1);
+ platform->bEnablePd = IMG_TRUE;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Failed to enable gpu_pd clock!"));
+ }
+}
+
+static IMG_VOID RgxDisablePower(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+ PVR_ASSERT(platform != NULL);
+
+ if (platform->bEnablePd && platform->pd_gpu_0 && platform->pd_gpu_1)
+ {
+ clk_disable_unprepare(platform->pd_gpu_1);
+ clk_disable_unprepare(platform->pd_gpu_0);
+ platform->bEnablePd = IMG_FALSE;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Failed to enable gpu_pd clock!"));
+ }
+}
+#endif
+
+IMG_VOID RgxResume(IMG_VOID)
+{
+#if OPEN_GPU_PD
+ RgxEnablePower();
+#endif
+ //mdelay(2);
+
+ /* set external isolation invalid */
+ //writel(0, SUNXI_R_PRCM_VBASE + GPU_PWROFF_GATING);
+
+ //DeAssertGpuResetSignal();
+ RgxEnableClock();
+
+ /* delay for internal power stability */
+ //writel(0x100, SUNXI_GPU_CTRL_VBASE + 0x18);
+}
+
+IMG_VOID RgxSuspend(IMG_VOID)
+{
+ RgxDisableClock();
+
+ //AssertGpuResetSignal();
+
+ /* set external isolation valid */
+ //writel(1, SUNXI_R_PRCM_VBASE + GPU_PWROFF_GATING);
+
+#if OPEN_GPU_PD
+ RgxDisablePower();
+#endif
+}
+
+PVRSRV_ERROR RkPrePowerState(PVRSRV_DEV_POWER_STATE eNewPowerState, PVRSRV_DEV_POWER_STATE eCurrentPowerState, IMG_BOOL bForced)
+{
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ RgxResume();
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RkPostPowerState(PVRSRV_DEV_POWER_STATE eNewPowerState, PVRSRV_DEV_POWER_STATE eCurrentPowerState, IMG_BOOL bForced)
+{
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+ RgxSuspend();
+ }
+ return PVRSRV_OK;
+}
+
+IMG_VOID RgxRkInit(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = kzalloc(sizeof(struct rk_context), GFP_KERNEL);
+
+ if (NULL == platform)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to kmalloc rk_context"));
+ return;
+ }
+
+ dev_set_drvdata(&gpsPVRLDMDev->dev, platform);
+
+ platform->bEnableClk = IMG_FALSE;
+#if OPEN_GPU_PD
+ platform->bEnablePd = IMG_FALSE;
+#endif
+ platform->cmu_pmu_status = 0;
+ platform->psDeviceNode = NULL;
+
+ spin_lock_init(&platform->cmu_pmu_lock);
+
+#if OPEN_GPU_PD
+ platform->pd_gpu_0 = devm_clk_get(&gpsPVRLDMDev->dev, "pd_gpu_0");
+ if (IS_ERR(platform->pd_gpu_0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find pd_gpu_0 clock source"));
+ goto fail0;
+ }
+
+ platform->pd_gpu_1 = devm_clk_get(&gpsPVRLDMDev->dev, "pd_gpu_1");
+ if (IS_ERR(platform->pd_gpu_1))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find pd_gpu_1 clock source"));
+ goto fail1;
+ }
+#endif
+
+ platform->aclk_gpu_mem = devm_clk_get(&gpsPVRLDMDev->dev, "aclk_gpu_mem");
+ if (IS_ERR(platform->aclk_gpu_mem))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find aclk_gpu_mem clock source"));
+ goto fail2;
+ }
+
+ platform->aclk_gpu_cfg = devm_clk_get(&gpsPVRLDMDev->dev, "aclk_gpu_cfg");
+ if (IS_ERR(platform->aclk_gpu_cfg))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find aclk_gpu_cfg clock source"));
+ goto fail3;
+ }
+
+#if RK33_DVFS_SUPPORT
+ platform->gpu_clk_node = clk_get_dvfs_node("clk_gpu");
+ if (IS_ERR(platform->gpu_clk_node))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "RgxRkInit: Failed to find gpu_clk_node clock source"));
+ goto fail4;
+ }
+#endif
+
+ rk33_clk_set_normal_node(platform->aclk_gpu_mem, RK33_DEFAULT_CLOCK);
+ rk33_clk_set_normal_node(platform->aclk_gpu_cfg, RK33_DEFAULT_CLOCK);
+#if RK33_DVFS_SUPPORT
+ rk33_clk_set_dvfs_node(platform->gpu_clk_node, RK33_DEFAULT_CLOCK);
+ rk33_dvfs_init();
+#if RK33_SYSFS_FILE_SUPPORT
+ //create sysfs file node
+ rk_create_sysfs_file(&gpsPVRLDMDev->dev);
+#endif
+
+#endif //end of RK33_DVFS_SUPPORT
+
+ RgxResume();
+
+ return;
+
+
+fail4:
+ devm_clk_put(&gpsPVRLDMDev->dev, platform->aclk_gpu_cfg);
+ platform->aclk_gpu_cfg = NULL;
+fail3:
+ devm_clk_put(&gpsPVRLDMDev->dev, platform->aclk_gpu_mem);
+ platform->aclk_gpu_mem = NULL;
+fail2:
+#if OPEN_GPU_PD
+ devm_clk_put(&gpsPVRLDMDev->dev, platform->pd_gpu_1);
+ platform->pd_gpu_1 = NULL;
+fail1:
+ devm_clk_put(&gpsPVRLDMDev->dev, platform->pd_gpu_0);
+ platform->pd_gpu_0 = NULL;
+fail0:
+#endif
+ kfree(platform);
+}
+
+IMG_VOID RgxRkUnInit(IMG_VOID)
+{
+ struct rk_context *platform;
+
+ platform = dev_get_drvdata(&gpsPVRLDMDev->dev);
+
+#if RK33_DVFS_SUPPORT
+#if RK33_SYSFS_FILE_SUPPORT
+ rk_remove_sysfs_file(&gpsPVRLDMDev->dev);
+#endif
+ rk33_dvfs_term();
+#endif
+
+ kfree(platform);
+ RgxSuspend();
+}
+
+
+#if defined(SUPPORT_ION)
+struct ion_device *g_psIonDev;
+extern struct ion_device *rockchip_ion_dev;
+
+PVRSRV_ERROR IonInit(void *phPrivateData)
+{
+ g_psIonDev = rockchip_ion_dev;
+ return PVRSRV_OK;
+}
+
+struct ion_device *IonDevAcquire(IMG_VOID)
+{
+ return g_psIonDev;
+}
+
+IMG_VOID IonDevRelease(struct ion_device *psIonDev)
+{
+ /* Nothing to do, sanity check the pointer we're passed back */
+ PVR_ASSERT(psIonDev == g_psIonDev);
+}
+
+IMG_UINT32 IonPhysHeapID(IMG_VOID)
+{
+ return 0;
+}
+
+IMG_VOID IonDeinit(IMG_VOID)
+{
+ g_psIonDev = NULL;
+}
+#endif /* defined(SUPPORT_ION) */
diff --git a/drivers/gpu/rogue/system/rk3368/rk_init.h b/drivers/gpu/rogue/system/rk3368/rk_init.h
new file mode 100755
index 000000000000..21f8d72938df
--- /dev/null
+++ b/drivers/gpu/rogue/system/rk3368/rk_init.h
@@ -0,0 +1,160 @@
+#if !defined(__RK_INIT__)
+#define __RK_INIT__
+
+#include <linux/hrtimer.h>
+#include "rgxdevice.h"
+#include "device.h"
+
+/****************************************************************************
+ Add Rockchip modificatons here!
+*****************************************************************************/
+#define RK33_DVFS_SUPPORT 1 // 1:DVFS on 0:DVFS off
+#define RK33_SYSFS_FILE_SUPPORT 1 // 1:add information nodes in /sys/devices/ffa30000.gpu/
+#define RK33_USE_RGX_GET_GPU_UTIL 1
+#define RK33_USE_CUSTOMER_GET_GPU_UTIL 0
+#define RK33_USE_CL_COUNT_UTILS 0
+#define OPEN_GPU_PD 1
+
+#define RK33_MAX_UTILIS 4
+#define RK33_DVFS_FREQ 50
+#define RK33_DEFAULT_CLOCK 400
+#define RK33_DVFS_FREQ_LIMIT 1
+#define RK_RESERVED 0
+#define RGX_DVFS_CURRENT_FREQ 0
+
+#define FPS_DEFAULT_GAP 300
+#define FPS_MAX_GAP 5000
+#define LIMIT_FPS 60
+#define LIMIT_FPS_POWER_SAVE 50
+#define ONE_KHZ 1000
+#define ONE_MHZ 1000000
+#define HZ_TO_MHZ(m) ((m) / ONE_MHZ)
+/* Conversion helpers for setting up high resolution timers */
+#define HR_TIMER_DELAY_MSEC(x) (ns_to_ktime((x)*1000000U))
+#define HR_TIMER_DELAY_NSEC(x) (ns_to_ktime(x))
+#define RGX_DVFS_LEVEL_INTERVAL 2
+
+/* Shift used for kbasep_pm_metrics_data.time_busy/idle - units of (1 << 8) ns
+ This gives a maximum period between samples of 2^(32+8)/100 ns = slightly under 11s.
+ Exceeding this will cause overflow */
+#define RK_PM_TIME_SHIFT 8
+
+#define RK_EXPORT_API(func) EXPORT_SYMBOL(func);
+
+typedef struct _rgx_dvfs_info
+{
+ IMG_UINT voltage;
+ IMG_UINT clock;
+ IMG_INT min_threshold;
+ IMG_INT max_threshold;
+ IMG_UINT64 time;
+ IMG_UINT coef;
+} rgx_dvfs_info;
+
+typedef struct _rgx_dvfs_status_type
+{
+ IMG_INT step;
+ IMG_INT utilisation;
+ IMG_UINT32 temperature;
+ IMG_UINT32 temperature_time;
+#if 0
+ IMG_INT upper_lock;
+ IMG_INT under_lock;
+#endif
+
+} rgx_dvfs_status;
+
+enum
+{
+ DBG_OFF = 0,
+ DBG_LOW,
+ DBG_HIGH,
+};
+
+struct rk_utilis
+{
+ IMG_INT utilis[RK33_MAX_UTILIS];
+ IMG_INT time_busys[RK33_MAX_UTILIS];
+ IMG_INT time_idles[RK33_MAX_UTILIS];
+};
+
+struct rk_context
+{
+ /** Indicator if system clock to mail-t604 is active */
+ IMG_INT cmu_pmu_status;
+ /** cmd & pmu lock */
+ spinlock_t cmu_pmu_lock;
+
+ /*clock*/
+ IMG_BOOL bEnableClk;
+#if OPEN_GPU_PD
+ IMG_BOOL bEnablePd;
+ struct clk *pd_gpu_0;
+ struct clk *pd_gpu_1;
+#endif
+ //struct clk *aclk_gpu;
+ struct clk *aclk_gpu_mem;
+ struct clk *aclk_gpu_cfg;
+ struct dvfs_node *gpu_clk_node;
+
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ RGXFWIF_GPU_UTIL_STATS sUtilStats;
+
+#if RK33_DVFS_SUPPORT
+ IMG_BOOL gpu_active;
+#if RK33_USE_CUSTOMER_GET_GPU_UTIL
+ ktime_t time_period_start;
+#endif
+
+ /*Temperature*/
+ IMG_UINT32 temperature;
+ IMG_UINT32 temperature_time;
+
+ /*Timer*/
+ spinlock_t timer_lock;
+ struct hrtimer timer;
+ IMG_BOOL timer_active;
+
+ /*To calculate utilization for x sec */
+ IMG_INT freq_level;
+ IMG_INT freq;
+ IMG_INT time_tick;
+ struct rk_utilis stUtilis;
+ IMG_INT utilisation;
+ IMG_UINT32 time_busy;
+ IMG_UINT32 time_idle;
+ IMG_BOOL dvfs_enabled;
+#if RK33_USE_CL_COUNT_UTILS
+ IMG_UINT32 abs_load[4];
+#endif
+
+#if RK33_SYSFS_FILE_SUPPORT
+#if RK33_DVFS_FREQ_LIMIT
+ IMG_INT up_level;
+ IMG_INT down_level;
+#endif //end of RK33_DVFS_FREQ_LIMIT
+ IMG_INT debug_level;
+ IMG_UINT fps_gap;
+ IMG_INT fix_freq;
+#endif //end of RK33_SYSFS_FILE_SUPPORT
+
+#endif //end of RK33_DVFS_SUPPORT
+};
+
+IMG_VOID RgxRkInit(IMG_VOID);
+IMG_VOID RgxRkUnInit(IMG_VOID);
+IMG_VOID RgxResume(IMG_VOID);
+IMG_VOID RgxSuspend(IMG_VOID);
+
+IMG_BOOL rk33_dvfs_init(IMG_VOID);
+IMG_VOID rk33_dvfs_term(IMG_VOID);
+
+IMG_BOOL rk33_set_device_node(IMG_HANDLE hDevCookie);
+IMG_BOOL rk33_clear_device_node(IMG_VOID);
+
+
+PVRSRV_ERROR IonInit(void *pvPrivateData);
+IMG_VOID IonDeinit(IMG_VOID);
+PVRSRV_ERROR RkPrePowerState(PVRSRV_DEV_POWER_STATE eNewPowerState, PVRSRV_DEV_POWER_STATE eCurrentPowerState, IMG_BOOL bForced);
+PVRSRV_ERROR RkPostPowerState(PVRSRV_DEV_POWER_STATE eNewPowerState, PVRSRV_DEV_POWER_STATE eCurrentPowerState, IMG_BOOL bForced);
+#endif /* __SUNXI_INIT__ */
diff --git a/drivers/gpu/rogue/system/rk3368/sysconfig.c b/drivers/gpu/rogue/system/rk3368/sysconfig.c
new file mode 100755
index 000000000000..3817f6756826
--- /dev/null
+++ b/drivers/gpu/rogue/system/rk3368/sysconfig.c
@@ -0,0 +1,242 @@
+/*************************************************************************/ /*!
+@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 "sysconfig.h"
+#include "physheap.h"
+#if defined(SUPPORT_ION)
+#include "ion_support.h"
+#endif
+#include "rk_init.h"
+
+static RGX_TIMING_INFORMATION gsRGXTimingInfo;
+static RGX_DATA gsRGXData;
+static PVRSRV_DEVICE_CONFIG gsDevices[1];
+static PVRSRV_SYSTEM_CONFIG gsSysConfig;
+
+static PHYS_HEAP_FUNCTIONS gsPhysHeapFuncs;
+#if defined(TDMETACODE)
+static PHYS_HEAP_CONFIG gsPhysHeapConfig[3];
+#else
+static PHYS_HEAP_CONFIG gsPhysHeapConfig[1];
+#endif
+
+/*
+ CPU to Device physcial address translation
+*/
+static
+IMG_VOID UMAPhysHeapCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
+ IMG_DEV_PHYADDR *psDevPAddr,
+ IMG_CPU_PHYADDR *psCpuPAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(hPrivData);
+
+ psDevPAddr->uiAddr = psCpuPAddr->uiAddr;
+}
+
+/*
+ Device to CPU physcial address translation
+*/
+static
+IMG_VOID UMAPhysHeapDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
+ IMG_CPU_PHYADDR *psCpuPAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(hPrivData);
+
+ psCpuPAddr->uiAddr = psDevPAddr->uiAddr;
+}
+
+/*
+ SysCreateConfigData
+*/
+PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig)
+{
+ /* Rk Init */
+ RgxRkInit();
+
+ /*
+ * Setup information about physical memory heap(s) we have
+ */
+ gsPhysHeapFuncs.pfnCpuPAddrToDevPAddr = UMAPhysHeapCpuPAddrToDevPAddr;
+ gsPhysHeapFuncs.pfnDevPAddrToCpuPAddr = UMAPhysHeapDevPAddrToCpuPAddr;
+
+ gsPhysHeapConfig[0].ui32PhysHeapID = 0;
+ gsPhysHeapConfig[0].pszPDumpMemspaceName = "SYSMEM";
+ gsPhysHeapConfig[0].eType = PHYS_HEAP_TYPE_UMA;
+ gsPhysHeapConfig[0].psMemFuncs = &gsPhysHeapFuncs;
+ gsPhysHeapConfig[0].hPrivData = IMG_NULL;
+
+#if defined(TDMETACODE)
+ gsPhysHeapConfig[1].ui32PhysHeapID = 1;
+ gsPhysHeapConfig[1].pszPDumpMemspaceName = "TDMETACODEMEM";
+ gsPhysHeapConfig[1].eType = PHYS_HEAP_TYPE_UMA;
+ gsPhysHeapConfig[1].psMemFuncs = &gsPhysHeapFuncs;
+ gsPhysHeapConfig[1].hPrivData = IMG_NULL;
+
+ gsPhysHeapConfig[2].ui32PhysHeapID = 2;
+ gsPhysHeapConfig[2].pszPDumpMemspaceName = "TDSECUREBUFMEM";
+ gsPhysHeapConfig[2].eType = PHYS_HEAP_TYPE_UMA;
+ gsPhysHeapConfig[2].psMemFuncs = &gsPhysHeapFuncs;
+ gsPhysHeapConfig[2].hPrivData = IMG_NULL;
+#endif
+
+ gsSysConfig.pasPhysHeaps = &(gsPhysHeapConfig[0]);
+ gsSysConfig.ui32PhysHeapCount = IMG_ARR_NUM_ELEMS(gsPhysHeapConfig);
+
+ gsSysConfig.pui32BIFTilingHeapConfigs = gauiBIFTilingHeapXStrides;
+ gsSysConfig.ui32BIFTilingHeapCount = IMG_ARR_NUM_ELEMS(gauiBIFTilingHeapXStrides);
+
+ /*
+ * Setup RGX specific timing data
+ */
+ gsRGXTimingInfo.ui32CoreClockSpeed = RGX_RK_CORE_CLOCK_SPEED;
+ gsRGXTimingInfo.bEnableActivePM = IMG_TRUE;
+ gsRGXTimingInfo.bEnableRDPowIsland = IMG_FALSE;
+ gsRGXTimingInfo.ui32ActivePMLatencyms = SYS_RGX_ACTIVE_POWER_LATENCY_MS;
+
+ /*
+ *Setup RGX specific data
+ */
+ gsRGXData.psRGXTimingInfo = &gsRGXTimingInfo;
+#if defined(TDMETACODE)
+ gsRGXData.bHasTDMetaCodePhysHeap = IMG_TRUE;
+ gsRGXData.uiTDMetaCodePhysHeapID = 1;
+
+ gsRGXData.bHasTDSecureBufPhysHeap = IMG_TRUE;
+ gsRGXData.uiTDSecureBufPhysHeapID = 2;
+#endif
+
+ /*
+ * Setup RGX device
+ */
+ gsDevices[0].eDeviceType = PVRSRV_DEVICE_TYPE_RGX;
+ gsDevices[0].pszName = "RGX";
+
+ /* Device setup information */
+ gsDevices[0].sRegsCpuPBase.uiAddr = RK_GPU_PBASE;
+ gsDevices[0].ui32RegsSize = RK_GPU_SIZE;
+ gsDevices[0].ui32IRQ = RK_IRQ_GPU;
+
+ /* Device's physical heap IDs */
+ gsDevices[0].aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] = 0;
+ gsDevices[0].aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL] = 0;
+
+ /* No power management on RK system */
+ gsDevices[0].pfnPrePowerState = RkPrePowerState;
+ gsDevices[0].pfnPostPowerState = RkPostPowerState;
+
+ /* No clock frequency either */
+ gsDevices[0].pfnClockFreqGet = IMG_NULL;
+
+ /* No interrupt handled either */
+ gsDevices[0].pfnInterruptHandled = IMG_NULL;
+
+ gsDevices[0].pfnCheckMemAllocSize = SysCheckMemAllocSize;
+
+ gsDevices[0].hDevData = &gsRGXData;
+
+ /*
+ * Setup system config
+ */
+ gsSysConfig.pszSystemName = RGX_RK_SYSTEM_NAME;
+ gsSysConfig.uiDeviceCount = sizeof(gsDevices)/sizeof(gsDevices[0]);
+ gsSysConfig.pasDevices = &gsDevices[0];
+
+ /* No power management on no HW system */
+ gsSysConfig.pfnSysPrePowerState = IMG_NULL;
+ gsSysConfig.pfnSysPostPowerState = IMG_NULL;
+
+ /* no cache snooping */
+ gsSysConfig.eCacheSnoopingMode = PVRSRV_SYSTEM_SNOOP_NONE;
+
+ /* Setup other system specific stuff */
+#if defined(SUPPORT_ION)
+ IonInit(NULL);
+#endif
+
+ *ppsSysConfig = &gsSysConfig;
+
+ return PVRSRV_OK;
+}
+
+/*
+ SysDestroyConfigData
+*/
+IMG_VOID SysDestroyConfigData(PVRSRV_SYSTEM_CONFIG *psSysConfig)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysConfig);
+
+ /* Rk UnInit */
+ RgxRkUnInit();
+
+#if defined(SUPPORT_ION)
+ IonDeinit();
+#endif
+}
+
+PVRSRV_ERROR SysAcquireSystemData(IMG_HANDLE hSysData)
+{
+ PVR_UNREFERENCED_PARAMETER(hSysData);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+PVRSRV_ERROR SysReleaseSystemData(IMG_HANDLE hSysData)
+{
+ PVR_UNREFERENCED_PARAMETER(hSysData);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+PVRSRV_ERROR SysDebugInfo(PVRSRV_SYSTEM_CONFIG *psSysConfig, DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysConfig);
+ PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
+ return PVRSRV_OK;
+}
+
+/******************************************************************************
+ End of file (sysconfig.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/system/rk3368/sysconfig.h b/drivers/gpu/rogue/system/rk3368/sysconfig.h
new file mode 100755
index 000000000000..ef11fbc7ee93
--- /dev/null
+++ b/drivers/gpu/rogue/system/rk3368/sysconfig.h
@@ -0,0 +1,72 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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 "rgxdevice.h"
+
+#if !defined(__SYSCCONFIG_H__)
+#define __SYSCCONFIG_H__
+
+//zxl:rk special data
+#define RGX_RK_CORE_CLOCK_SPEED (100*1000*1000)
+#define RGX_RK_SYSTEM_NAME "RGX RK"
+#define RK_GPU_PBASE 0xffa30000
+#define RK_GPU_SIZE 0x10000
+#define RK_IRQ_GPU 40
+
+#define SYS_RGX_ACTIVE_POWER_LATENCY_MS (100)
+
+/* default BIF tiling heap x-stride configurations. */
+static IMG_UINT32 gauiBIFTilingHeapXStrides[RGXFWIF_NUM_BIF_TILING_CONFIGS] =
+{
+ 0, /* BIF tiling heap 1 x-stride */
+ 1, /* BIF tiling heap 2 x-stride */
+ 2, /* BIF tiling heap 3 x-stride */
+ 3 /* BIF tiling heap 4 x-stride */
+};
+
+/*****************************************************************************
+ * system specific data structures
+ *****************************************************************************/
+
+#endif /* __SYSCCONFIG_H__ */
diff --git a/drivers/gpu/rogue/system/rk3368/sysinfo.h b/drivers/gpu/rogue/system/rk3368/sysinfo.h
new file mode 100644
index 000000000000..b7efa09f28cf
--- /dev/null
+++ b/drivers/gpu/rogue/system/rk3368/sysinfo.h
@@ -0,0 +1,71 @@
+/*************************************************************************/ /*!
+@File
+@Title System Description Header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description This header provides system-specific declarations and macros
+@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(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+/*!< System specific poll/timeout details */
+#define MAX_HW_TIME_US (500000)
+#define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT (10000)
+#define DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT (3600000)
+#define WAIT_TRY_COUNT (10000)
+
+#define SYS_DEVICE_COUNT 3 /* RGX, DISPLAY (external), BUFFER (external) */
+
+#if defined(TDMETACODE)
+/* 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 SYS_PHYS_HEAP_COUNT 3
+#else
+#define SYS_PHYS_HEAP_COUNT 1
+#endif
+
+#if defined(__linux__)
+#define SYS_RGX_DEV_NAME "rgxnohw"
+#endif
+
+#endif /* !defined(__SYSINFO_H__) */
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/Kbuild.mk b/drivers/gpu/rogue/tools/services/debug/dbgdriv/Kbuild.mk
new file mode 100644
index 000000000000..95ccf09c9e24
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/Kbuild.mk
@@ -0,0 +1,50 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+ccflags-y += \
+ -I$(TOP)/tools/services/debug/dbgdriv/common \
+ -I$(TOP)/tools/services/debug/include
+
+dbgdrv-y += \
+ tools/services/debug/dbgdriv/common/dbgdriv.o \
+ tools/services/debug/dbgdriv/common/ioctl.o \
+ tools/services/debug/dbgdriv/common/handle.o \
+ tools/services/debug/dbgdriv/linux/main.o \
+ tools/services/debug/dbgdriv/linux/hostfunc.o
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/Linux.mk b/drivers/gpu/rogue/tools/services/debug/dbgdriv/Linux.mk
new file mode 100644
index 000000000000..e0508796b020
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/Linux.mk
@@ -0,0 +1,45 @@
+########################################################################### ###
+#@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.
+### ###########################################################################
+
+modules := dbgdrv
+
+dbgdrv_type := kernel_module
+dbgdrv_target := dbgdrv.ko
+dbgdrv_makefile := $(THIS_DIR)/Kbuild.mk
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv.c b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv.c
new file mode 100644
index 000000000000..72b4c9b495d8
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv.c
@@ -0,0 +1,1573 @@
+/*************************************************************************/ /*!
+@File
+@Title Debug Driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description 32 Bit kernel mode debug driver
+@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(UNDER_CE)
+#include <windows.h>
+#include <ceddk.h>
+
+#else
+#if defined(_WIN32)
+#pragma warning(disable:4201)
+#pragma warning(disable:4214)
+#pragma warning(disable:4115)
+#pragma warning(disable:4514)
+
+
+#include <ntddk.h>
+#include <windef.h>
+#include <winerror.h>
+#endif /* _WIN32 */
+#endif /* UNDER_CE */
+
+#ifdef LINUX
+#include <linux/string.h>
+#endif
+
+#if defined (__QNXNTO__)
+#include <string.h>
+#endif
+
+#include "img_types.h"
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "dbgdrvif_srv5.h"
+#include "dbgdriv.h"
+#include "hostfunc.h"
+
+#ifdef _WIN32
+#pragma warning(default:4214)
+#pragma warning(default:4115)
+#endif /* _WIN32 */
+
+
+/******************************************************************************
+ Types
+******************************************************************************/
+
+#define DBG_STREAM_NAME_MAX 30
+
+/*
+ Per-buffer control structure.
+*/
+typedef struct _DBG_STREAM_
+{
+ struct _DBG_STREAM_* psNext;
+ struct _DBG_STREAM_* psInitStream;
+ struct _DBG_STREAM_* psDeinitStream;
+ IMG_UINT32 ui32Flags; /*!< flags (see DEBUG_FLAGS) */
+ IMG_PVOID pvBase;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32RPtr;
+ IMG_UINT32 ui32WPtr;
+
+ IMG_UINT32 ui32Marker; /*!< Size marker for file splitting */
+
+ IMG_UINT32 ui32InitPhaseWOff; /*!< snapshot offset for init phase end for follow-on pdump */
+
+ IMG_CHAR szName[DBG_STREAM_NAME_MAX]; /* Give this a size, some compilers don't like [] */
+} DBG_STREAM;
+
+/* Check 4xDBG_STREAM will fit in one page */
+BLD_ASSERT(sizeof(DBG_STREAM)<<2<HOST_PAGESIZE,dbgdriv_c)
+
+/******************************************************************************
+ Global variables
+******************************************************************************/
+
+static PDBG_STREAM g_psStreamList = 0;
+
+IMG_VOID * g_pvAPIMutex=IMG_NULL;
+
+static IMG_UINT32 g_PDumpCurrentFrameNo = 0;
+
+DBGKM_SERVICE_TABLE g_sDBGKMServices =
+{
+ sizeof (DBGKM_SERVICE_TABLE),
+ ExtDBGDrivCreateStream,
+ ExtDBGDrivDestroyStream,
+ ExtDBGDrivWrite2,
+ ExtDBGDrivSetMarker,
+ ExtDBGDrivWaitForEvent,
+ ExtDBGDrivGetCtrlState,
+ ExtDBGDrivSetFrame
+};
+
+
+/***************************************************************************
+ Forward declarations
+***************************************************************************/
+
+IMG_BOOL IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *pszName, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Pages, IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit);
+IMG_VOID IMG_CALLCONV DBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit);
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize);
+IMG_VOID IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(void);
+IMG_VOID IMG_CALLCONV DBGDrivSetFrame(IMG_UINT32 ui32Frame);
+IMG_VOID DestroyAllStreams(IMG_VOID);
+
+/* Static function declarations */
+static IMG_UINT32 SpaceInStream(PDBG_STREAM psStream);
+static IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize);
+static IMG_VOID InvalidateAllStreams(IMG_VOID);
+
+
+/*****************************************************************************
+ Code
+*****************************************************************************/
+
+/*!
+ @name ExtDBGDrivCreateStream
+ */
+IMG_BOOL IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR *pszName, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit)
+{
+ IMG_BOOL pvRet;
+
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet=DBGDrivCreateStream(pszName, ui32Flags, ui32Size, phInit, phMain, phDeinit);
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+/*!
+ @name ExtDBGDrivDestroyStream
+ */
+IMG_VOID IMG_CALLCONV ExtDBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit)
+{
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivDestroyStream(hInit, hMain, hDeinit);
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+/*!
+ @name ExtDBGDrivFindStream
+ */
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+ IMG_VOID * pvRet;
+
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet=DBGDrivFindStream(pszName, bResetStream);
+ if (pvRet == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ExtDBGDrivFindStream: Stream not found"));
+ }
+
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+/*!
+ @name ExtDBGDrivRead
+ */
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Ret;
+
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivRead(psStream, ui32BufID, ui32OutBuffSize, pui8OutBuf);
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+/*!
+ @name ExtDBGDrivWrite2
+ */
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
+{
+ IMG_UINT32 ui32Ret;
+
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize);
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+/*!
+ @name ExtDBGDrivSetMarker
+ */
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetMarker(psStream, ui32Marker);
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+/*!
+ @name ExtDBGDrivGetMarker
+ */
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Marker;
+
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Marker = DBGDrivGetMarker(psStream);
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Marker;
+}
+
+/*!
+ @name ExtDBGDrivWaitForEvent
+ */
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ DBGDrivWaitForEvent(eEvent);
+#else /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
+ PVR_UNREFERENCED_PARAMETER(eEvent); /* PRQA S 3358 */
+#endif /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
+}
+
+
+/*!
+ @name ExtDBGDrivGetCtrlState
+ */
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID)
+{
+ IMG_UINT32 ui32State = 0;
+
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32State = DBGDrivGetCtrlState(psStream, ui32StateID);
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32State;
+}
+
+/*!
+ @name ExtDBGDrivGetFrame
+ */
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(void)
+{
+ IMG_UINT32 ui32Frame = 0;
+
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Frame = DBGDrivGetFrame();
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Frame;
+}
+
+/*!
+ @name ExtDBGDrivGetCtrlState
+ */
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetFrame(IMG_UINT32 ui32Frame)
+{
+ /* Aquire API Mutex */
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetFrame(ui32Frame);
+
+ /* Release API Mutex */
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+
+
+/*!****************************************************************************
+ @name AtoI
+ @brief Returns the integer value of a decimal string
+ @param szIn - String with hexadecimal value
+ @return IMG_UINT32 integer value, 0 if string is null or not valid
+ Based on Max`s one, now copes with (only) hex ui32ords, upper or lower case a-f.
+*****************************************************************************/
+IMG_UINT32 AtoI(IMG_CHAR *szIn)
+{
+ IMG_INT iLen = 0;
+ IMG_UINT32 ui32Value = 0;
+ IMG_UINT32 ui32Digit=1;
+ IMG_UINT32 ui32Base=10;
+ IMG_INT iPos;
+ IMG_CHAR bc;
+
+ //get len of string
+ while (szIn[iLen] > 0)
+ {
+ iLen ++;
+ }
+
+ //nothing to do
+ if (iLen == 0)
+ {
+ return (0);
+ }
+
+ /* See if we have an 'x' or 'X' before the number to make it a hex number */
+ iPos=0;
+ while (szIn[iPos] == '0')
+ {
+ iPos++;
+ }
+ if (szIn[iPos] == '\0')
+ {
+ return 0;
+ }
+ if (szIn[iPos] == 'x' || szIn[iPos] == 'X')
+ {
+ ui32Base=16;
+ szIn[iPos]='0';
+ }
+
+ //go through string from right (least significant) to left
+ for (iPos = iLen - 1; iPos >= 0; iPos --)
+ {
+ bc = szIn[iPos];
+
+ if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16) //handle lower case a-f
+ {
+ bc -= 'a' - 0xa;
+ }
+ else
+ if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16) //handle upper case A-F
+ {
+ bc -= 'A' - 0xa;
+ }
+ else
+ if ((bc >= '0') && (bc <= '9')) //if char out of range, return 0
+ {
+ bc -= '0';
+ }
+ else
+ return (0);
+
+ ui32Value += (IMG_UINT32)bc * ui32Digit;
+
+ ui32Digit = ui32Digit * ui32Base;
+ }
+ return (ui32Value);
+}
+
+
+/*!****************************************************************************
+ @name StreamValid
+ @brief Validates supplied debug buffer.
+ @param psStream - debug stream
+ @return true if valid
+*****************************************************************************/
+static IMG_BOOL StreamValid(PDBG_STREAM psStream)
+{
+ PDBG_STREAM psThis;
+
+ psThis = g_psStreamList;
+
+ while (psThis)
+ {
+ if (psStream && ((psThis == psStream) ||
+ (psThis->psInitStream == psStream) ||
+ (psThis->psDeinitStream == psStream)) )
+ {
+ return(IMG_TRUE);
+ }
+ else
+ {
+ psThis = psThis->psNext;
+ }
+ }
+
+ return(IMG_FALSE);
+}
+
+
+/*!****************************************************************************
+ @name StreamValidForRead
+ @brief Validates supplied debug buffer for read op.
+ @param psStream - debug stream
+ @return true if readable
+*****************************************************************************/
+static IMG_BOOL StreamValidForRead(PDBG_STREAM psStream)
+{
+ if( StreamValid(psStream) &&
+ ((psStream->ui32Flags & DEBUG_FLAGS_WRITEONLY) == 0) )
+ {
+ return(IMG_TRUE);
+ }
+
+ return(IMG_FALSE);
+}
+
+/*!****************************************************************************
+ @name StreamValidForWrite
+ @brief Validates supplied debug buffer for write op.
+ @param psStream - debug stream
+ @return true if writable
+*****************************************************************************/
+static IMG_BOOL StreamValidForWrite(PDBG_STREAM psStream)
+{
+ if( StreamValid(psStream) &&
+ ((psStream->ui32Flags & DEBUG_FLAGS_READONLY) == 0) )
+ {
+ return(IMG_TRUE);
+ }
+
+ return(IMG_FALSE);
+}
+
+/*!****************************************************************************
+ @name Write
+ @brief Copies data from a buffer into selected stream. Stream size is fixed.
+ @param psStream - stream for output
+ @param pui8Data - input buffer
+ @param ui32InBuffSize - size of input
+ @return none
+*****************************************************************************/
+static IMG_VOID Write(PDBG_STREAM psStream,IMG_PUINT8 pui8Data,IMG_UINT32 ui32InBuffSize)
+{
+ /*
+ Split copy into two bits as necessary (if we're allowed to wrap).
+ */
+ if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) == 0)
+ {
+ PVR_ASSERT( (psStream->ui32WPtr + ui32InBuffSize) < psStream->ui32Size );
+ }
+
+ if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
+ {
+ /* Yes we need two bits, calculate their sizes */
+ IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
+ IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
+
+ /* Copy first block to current location */
+ HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
+ (IMG_PVOID) pui8Data,
+ ui32B1);
+
+ /* Copy second block to start of buffer */
+ HostMemCopy(psStream->pvBase,
+ (IMG_PVOID)(pui8Data + ui32B1),
+ ui32B2);
+
+ /* Set pointer to be the new end point */
+ psStream->ui32WPtr = ui32B2;
+ }
+ else
+ { /* Can fit block in single chunk */
+ HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
+ (IMG_PVOID) pui8Data,
+ ui32InBuffSize);
+
+ psStream->ui32WPtr += ui32InBuffSize;
+
+ if (psStream->ui32WPtr == psStream->ui32Size)
+ {
+ psStream->ui32WPtr = 0;
+ }
+ }
+}
+
+
+/*!****************************************************************************
+ @name WriteExpandingBuffer
+ @brief Copies data from a buffer into selected stream. Stream size may be expandable.
+ @param psStream - stream for output
+ @param pui8InBuf - input buffer
+ @param ui32InBuffSize - size of input
+ @return bytes copied
+*****************************************************************************/
+static IMG_UINT32 WriteExpandingBuffer(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
+{
+ IMG_UINT ui32Space;
+
+ /*
+ How much space have we got in the buffer ?
+ */
+ ui32Space = SpaceInStream(psStream);
+
+ /*
+ Check if we can expand the buffer
+ */
+ if (psStream->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
+ {
+ /*
+ Don't do anything if we've got less that 32 ui8tes of space and
+ we're not allowing expansion of buffer space...
+ */
+ if (ui32Space < 32)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %p is full and isn't expandable", psStream));
+ return(0);
+ }
+ }
+ else
+ {
+ if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4)))
+ {
+ IMG_UINT32 ui32NewBufSize;
+
+ /*
+ Find new buffer size, double the current size or increase by 1MB
+ */
+ ui32NewBufSize = MIN(psStream->ui32Size<<1,psStream->ui32Size+(1<<20));
+ ui32NewBufSize = MIN(ui32NewBufSize, (16<<20));
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanding buffer size = %x, new size = %x",
+ psStream->ui32Size, ui32NewBufSize));
+
+ if (ui32InBuffSize > psStream->ui32Size)
+ {
+ ui32NewBufSize += ui32InBuffSize;
+ PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %p is expanding by size of input buffer %u", psStream, ui32NewBufSize));
+ }
+
+ /*
+ Attempt to expand the buffer
+ */
+ if ((ui32NewBufSize < psStream->ui32Size) ||
+ !ExpandStreamBuffer(psStream,ui32NewBufSize))
+ {
+ if (ui32Space < 32)
+ {
+ if((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
+ {
+ return(0);
+ }
+ else
+ {
+ /* out of memory */
+ PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: Unable to expand %p. Out of memory.", psStream));
+ InvalidateAllStreams();
+ return (0xFFFFFFFFUL);
+ }
+ }
+ }
+
+ /*
+ Recalc the space in the buffer
+ */
+ ui32Space = SpaceInStream(psStream);
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanded buffer, free space = %x",
+ ui32Space));
+ }
+ }
+
+ /*
+ Only copy what we can..
+ */
+ if (ui32Space <= (ui32InBuffSize + 4))
+ {
+ ui32InBuffSize = ui32Space - 4;
+ }
+
+ /*
+ Write the stuff...
+ */
+ Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32InBuffSize)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+ return(ui32InBuffSize);
+}
+
+/*****************************************************************************
+******************************************************************************
+******************************************************************************
+ THE ACTUAL FUNCTIONS
+******************************************************************************
+******************************************************************************
+*****************************************************************************/
+
+static IMG_VOID DBGDrivSetStreamName(PDBG_STREAM psStream,
+ IMG_CHAR* pszBase,
+ IMG_CHAR* pszExt)
+{
+ IMG_CHAR* pCh = psStream->szName;
+ IMG_CHAR* pChEnd = psStream->szName+DBG_STREAM_NAME_MAX-8;
+ IMG_CHAR* pSrcCh;
+ IMG_CHAR* pSrcChEnd;
+
+ for (pSrcCh = pszBase, pSrcChEnd = pszBase+strlen(pszBase);
+ (pSrcCh < pSrcChEnd) && (pCh < pChEnd) ;
+ pSrcCh++, pCh++)
+ {
+ *pCh = *pSrcCh;
+ }
+
+ for (pSrcCh = pszExt, pSrcChEnd = pszExt+strlen(pszExt);
+ (pSrcCh < pSrcChEnd) && (pCh < pChEnd) ;
+ pSrcCh++, pCh++)
+ {
+ *pCh = *pSrcCh;
+ }
+
+ *pCh = '\0';
+}
+
+/*!****************************************************************************
+ @name DBGDrivCreateStream
+ @brief Creates a pdump/debug stream
+ @param pszName - stream name
+ @param ui32Flags - output flags, text stream bit is set for pdumping
+ @param ui32Size - size of stream buffer in pages
+ @return none
+*****************************************************************************/
+IMG_BOOL IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *pszName,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_HANDLE* phInit,
+ IMG_HANDLE* phMain,
+ IMG_HANDLE* phDeinit)
+{
+ IMG_BOOL bUseNonPagedMem4Buffers = ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0);
+ PDBG_STREAM psStream = IMG_NULL;
+ PDBG_STREAM psInitStream = IMG_NULL;
+ PDBG_STREAM psStreamDeinit = IMG_NULL;
+ IMG_VOID* pvBase = IMG_NULL;
+
+ /*
+ If we already have a buffer using this name just return
+ its handle.
+ */
+ psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
+ if (psStream)
+ {
+ *phInit = psStream->psInitStream;
+ *phMain = psStream;
+ *phDeinit = psStream->psDeinitStream;
+ return IMG_TRUE;
+ }
+
+ /*
+ Allocate memory for control structures
+ */
+ psStream = HostNonPageablePageAlloc(1);
+ if (!psStream)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc control structs\n\r"));
+ goto errCleanup;
+ }
+ psInitStream = psStream+1;
+ psStreamDeinit = psStream+2;
+
+
+ /* Allocate memory for Main buffer */
+ psStream->pvBase = IMG_NULL;
+ if (bUseNonPagedMem4Buffers)
+ {
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ }
+ else
+ {
+ pvBase = HostPageablePageAlloc(ui32Size);
+ }
+
+ if (!pvBase)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc Stream buffer\n\r"));
+ goto errCleanup;
+ }
+
+ /*
+ Setup debug buffer state.
+ */
+ psStream->psNext = 0;
+ psStream->pvBase = pvBase;
+ psStream->ui32Flags = ui32Flags | DEBUG_FLAGS_CIRCULAR;
+ psStream->ui32Size = ui32Size * HOST_PAGESIZE;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = 0;
+ psStream->ui32Marker = 0;
+ psStream->ui32InitPhaseWOff = 0;
+ DBGDrivSetStreamName(psStream, pszName, "");
+ PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Created stream with deinit name (%s)\n\r", psStream->szName));
+
+ /* Allocate memory for Init buffer */
+ psInitStream->pvBase = IMG_NULL;
+ if (bUseNonPagedMem4Buffers)
+ {
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ }
+ else
+ {
+ pvBase = HostPageablePageAlloc(ui32Size);
+ }
+
+ if (!pvBase)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc InitStream buffer\n\r"));
+ goto errCleanup;
+ }
+
+ /* Initialise the stream for the Init phase */
+ psInitStream->psNext = psInitStream->psInitStream = psInitStream->psDeinitStream = IMG_NULL;
+ psInitStream->ui32Flags = ui32Flags;
+ psInitStream->pvBase = pvBase;
+ psInitStream->ui32Size = ui32Size * HOST_PAGESIZE;
+ psInitStream->ui32RPtr = 0;
+ psInitStream->ui32WPtr = 0;
+ psInitStream->ui32Marker = 0;
+ psInitStream->ui32InitPhaseWOff = 0;
+ DBGDrivSetStreamName(psInitStream, pszName, "_Init");
+ PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Created stream with init name (%s)\n\r", psInitStream->szName));
+ psStream->psInitStream = psInitStream;
+
+ /* Allocate memory for Deinit buffer */
+ psStreamDeinit->pvBase = IMG_NULL;
+ if (bUseNonPagedMem4Buffers)
+ {
+ pvBase = HostNonPageablePageAlloc(1);
+ }
+ else
+ {
+ pvBase = HostPageablePageAlloc(1);
+ }
+
+ if (!pvBase)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc DeinitStream buffer\n\r"));
+ goto errCleanup;
+ }
+
+ /* Initialise the stream for the Deinit phase */
+ psStreamDeinit->psNext = psStreamDeinit->psInitStream = psStreamDeinit->psDeinitStream = IMG_NULL;
+ psStreamDeinit->pvBase = pvBase;
+ psStreamDeinit->ui32Flags = ui32Flags;
+ psStreamDeinit->ui32Size = HOST_PAGESIZE;
+ psStreamDeinit->ui32RPtr = 0;
+ psStreamDeinit->ui32WPtr = 0;
+ psStreamDeinit->ui32Marker = 0;
+ psStreamDeinit->ui32InitPhaseWOff = 0;
+ DBGDrivSetStreamName(psStreamDeinit, pszName, "_Deinit");
+ PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Created stream with deinit name (%s)\n\r", psStreamDeinit->szName));
+
+ psStream->psDeinitStream = psStreamDeinit;
+
+ /*
+ Insert into list.
+ */
+ psStream->psNext = g_psStreamList;
+ g_psStreamList = psStream;
+
+ AddSIDEntry(psStream);
+
+ *phInit = psStream->psInitStream;
+ *phMain = psStream;
+ *phDeinit = psStream->psDeinitStream;
+
+ return IMG_TRUE;
+
+errCleanup:
+ if (bUseNonPagedMem4Buffers)
+ {
+ if (psStream) HostNonPageablePageFree(psStream->pvBase);
+ if (psInitStream) HostNonPageablePageFree(psInitStream->pvBase);
+ if (psStreamDeinit) HostNonPageablePageFree(psStreamDeinit->pvBase);
+ }
+ else
+ {
+ if (psStream) HostPageablePageFree(psStream->pvBase);
+ if (psInitStream) HostPageablePageFree(psInitStream->pvBase);
+ if (psStreamDeinit) HostPageablePageFree(psStreamDeinit->pvBase);
+ }
+ HostNonPageablePageFree(psStream);
+#if !defined(__KLOCWORK__) /* klocworks would report a possible memory leak */
+ psStream = psInitStream = psStreamDeinit = IMG_NULL;
+#endif
+ return IMG_FALSE;
+}
+
+/*!****************************************************************************
+ @name DBGDrivDestroyStream
+ @brief Delete a stream and free its memory
+ @param psStream - stream to be removed
+ @return none
+*****************************************************************************/
+IMG_VOID IMG_CALLCONV DBGDrivDestroyStream(IMG_HANDLE hInit,IMG_HANDLE hMain, IMG_HANDLE hDeinit)
+{
+ PDBG_STREAM psStreamInit = (PDBG_STREAM) hInit;
+ PDBG_STREAM psStream = (PDBG_STREAM) hMain;
+ PDBG_STREAM psStreamDeinit = (PDBG_STREAM) hDeinit;
+ PDBG_STREAM psStreamThis;
+ PDBG_STREAM psStreamPrev;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
+
+ /*
+ Validate buffer.
+ */
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ RemoveSIDEntry(psStream);
+
+ /*
+ Remove from linked list.
+ */
+ psStreamThis = g_psStreamList;
+ psStreamPrev = 0;
+
+ while (psStreamThis)
+ {
+ if (psStreamThis == psStream)
+ {
+ if (psStreamPrev)
+ {
+ psStreamPrev->psNext = psStreamThis->psNext;
+ }
+ else
+ {
+ g_psStreamList = psStreamThis->psNext;
+ }
+
+ psStreamThis = 0;
+ }
+ else
+ {
+ psStreamPrev = psStreamThis;
+ psStreamThis = psStreamThis->psNext;
+ }
+ }
+
+ /*
+ And free its memory.
+ */
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree(psStream->pvBase);
+ HostNonPageablePageFree(psStreamInit->pvBase);
+ HostNonPageablePageFree(psStreamDeinit->pvBase);
+ }
+ else
+ {
+ HostPageablePageFree(psStream->pvBase);
+ HostPageablePageFree(psStreamInit->pvBase);
+ HostPageablePageFree(psStreamDeinit->pvBase);
+ }
+
+ /* Free the shared page used for the three stream tuple */
+ HostNonPageablePageFree(psStream);
+ psStream = psStreamInit = psStreamDeinit = IMG_NULL;
+
+ if (g_psStreamList == 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Stream list now empty" ));
+ }
+
+ return;
+}
+
+/*!****************************************************************************
+ @name DBGDrivFindStream
+ @brief Finds/resets a named stream
+ @param pszName - stream name
+ @param bResetStream - whether to reset the stream, e.g. to end pdump init phase
+ @return none
+*****************************************************************************/
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+ PDBG_STREAM psStream;
+ PDBG_STREAM psThis;
+ IMG_UINT32 ui32Off;
+ IMG_BOOL bAreSame;
+
+ psStream = 0;
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "PDump client connecting to %s %s",
+ pszName,
+ (bResetStream == IMG_TRUE) ? "with reset" : "no reset"));
+
+ /*
+ Scan buffer names for supplied one.
+ */
+ for (psThis = g_psStreamList; psThis != IMG_NULL; psThis = psThis->psNext)
+ {
+ bAreSame = IMG_TRUE;
+ ui32Off = 0;
+
+ if (strlen(psThis->szName) == strlen(pszName))
+ {
+ while ((ui32Off < DBG_STREAM_NAME_MAX) && (psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && bAreSame)
+ {
+ if (psThis->szName[ui32Off] != pszName[ui32Off])
+ {
+ bAreSame = IMG_FALSE;
+ }
+
+ ui32Off++;
+ }
+ }
+ else
+ {
+ bAreSame = IMG_FALSE;
+ }
+
+ if (bAreSame)
+ {
+ psStream = psThis;
+ break;
+ }
+ }
+
+ if(psStream)
+ {
+ psStream->psInitStream->ui32RPtr = 0;
+ psStream->psDeinitStream->ui32RPtr = 0;
+ psStream->ui32RPtr = 0;
+ if (bResetStream)
+ {
+ /* This will erase any data written to the main stream
+ * before the client starts. */
+ psStream->ui32WPtr = 0;
+ }
+ psStream->ui32Marker = psStream->psInitStream->ui32Marker = 0;
+
+
+ /* mark init stream to prevent further reading by pdump client */
+ /* Check for possible race condition */
+ psStream->psInitStream->ui32InitPhaseWOff = psStream->psInitStream->ui32WPtr;
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Set %s client marker bo %x",
+ psStream->szName,
+ psStream->psInitStream->ui32InitPhaseWOff));
+ }
+
+ return((IMG_VOID *) psStream);
+}
+
+static IMG_VOID IMG_CALLCONV DBGDrivInvalidateStream(PDBG_STREAM psStream)
+{
+ IMG_CHAR pszErrorMsg[] = "**OUTOFMEM\n";
+ IMG_UINT32 ui32Space;
+ IMG_UINT32 ui32Off = 0;
+ IMG_UINT32 ui32WPtr = psStream->ui32WPtr;
+ IMG_PUINT8 pui8Buffer = (IMG_UINT8 *) psStream->pvBase;
+
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: An error occurred for stream %s", psStream->szName ));
+
+ /*
+ Validate buffer.
+ */
+ /*
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+*/
+ /* Write what we can of the error message */
+ ui32Space = SpaceInStream(psStream);
+
+ /* Make sure there's space for termination character */
+ if(ui32Space > 0)
+ {
+ ui32Space--;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: Buffer full."));
+ }
+
+ while((pszErrorMsg[ui32Off] != 0) && (ui32Off < ui32Space))
+ {
+ pui8Buffer[ui32WPtr] = (IMG_UINT8)pszErrorMsg[ui32Off];
+ ui32Off++;
+ ui32WPtr++;
+ }
+ pui8Buffer[ui32WPtr++] = '\0';
+ psStream->ui32WPtr = ui32WPtr;
+
+ /* Buffer will accept no more params from Services/client driver */
+ psStream->ui32Flags |= DEBUG_FLAGS_READONLY;
+}
+
+/*!****************************************************************************
+ @name InvalidateAllStreams
+ @brief invalidate all streams in list
+ @return none
+*****************************************************************************/
+static IMG_VOID InvalidateAllStreams(IMG_VOID)
+{
+ PDBG_STREAM psStream = g_psStreamList;
+ while (psStream != IMG_NULL)
+ {
+ DBGDrivInvalidateStream(psStream);
+ psStream = psStream->psNext;
+ }
+ return;
+}
+
+/*!****************************************************************************
+ @name DBGDrivWrite2
+ @brief Copies data from a buffer into selected (expandable) stream.
+ @param psStream - stream for output
+ @param pui8InBuf - input buffer
+ @param ui32InBuffSize - size of input
+ @return bytes copied, 0 if recoverable error, -1 if unrecoverable error
+*****************************************************************************/
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
+{
+
+ /*
+ Validate buffer.
+ */
+ if (!StreamValidForWrite(psStream))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite2: stream not valid"));
+ return(0xFFFFFFFFUL);
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv(exp) %d b for %s: Roff = %x, WOff = %x",
+ ui32InBuffSize,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr));
+
+ return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
+}
+
+/*!****************************************************************************
+ @name DBGDrivRead
+ @brief Read from debug driver buffers
+ @param psMainStream - stream
+ @param ui32BufID - on of the DEBUG_READ_BUFID flags to indicate which buffer
+ @param ui32OutBuffSize - available space in client buffer
+ @param pui8OutBuf - output buffer
+ @return bytes read, 0 if failure occurred
+*****************************************************************************/
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psMainStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Data;
+ DBG_STREAM *psStream;
+
+ /*
+ Validate buffer.
+ */
+ if (!StreamValidForRead(psMainStream))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivRead: buffer %p is invalid", psMainStream));
+ return(0);
+ }
+
+ if(ui32BufID == DEBUG_READ_BUFID_INIT)
+ {
+ psStream = psMainStream->psInitStream;
+ }
+ else if (ui32BufID == DEBUG_READ_BUFID_DEINIT)
+ {
+ psStream = psMainStream->psDeinitStream;
+ }
+ else
+ {
+ psStream = psMainStream;
+ }
+
+ /* Don't read beyond the init phase marker point */
+ if (psStream->ui32RPtr == psStream->ui32WPtr ||
+ ((psStream->ui32InitPhaseWOff > 0) &&
+ (psStream->ui32RPtr >= psStream->ui32InitPhaseWOff)) )
+ {
+ return(0);
+ }
+
+ /*
+ Get amount of data in buffer.
+ */
+ if (psStream->ui32RPtr <= psStream->ui32WPtr)
+ {
+ ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
+ }
+ else
+ {
+ ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
+ }
+
+ /*
+ Don't read beyond the init phase marker point
+ */
+ if ((psStream->ui32InitPhaseWOff > 0) &&
+ (psStream->ui32InitPhaseWOff < psStream->ui32WPtr))
+ {
+ ui32Data = psStream->ui32InitPhaseWOff - psStream->ui32RPtr;
+ }
+
+ /*
+ Only transfer what target buffer can handle.
+ */
+ if (ui32Data > ui32OutBuffSize)
+ {
+ ui32Data = ui32OutBuffSize;
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Send %x b from %s: Roff = %x, WOff = %x",
+ ui32Data,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr));
+
+ /*
+ Split copy into two bits or one depending on W/R position.
+ */
+ if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size)
+ { /* Calc block 1 and block 2 sizes */
+ IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
+ IMG_UINT32 ui32B2 = ui32Data - ui32B1;
+
+ /* Copy up to end of circular buffer */
+ HostMemCopy((IMG_VOID *) pui8OutBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ ui32B1);
+
+ /* Copy from start of circular buffer */
+ HostMemCopy((IMG_VOID *)(pui8OutBuf + ui32B1),
+ psStream->pvBase,
+ ui32B2);
+
+ /* Update read pointer now that we've copied the data out */
+ psStream->ui32RPtr = ui32B2;
+ }
+ else
+ { /* Copy data from wherever */
+ HostMemCopy((IMG_VOID *) pui8OutBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ ui32Data);
+
+ /* Update read pointer now that we've copied the data out */
+ psStream->ui32RPtr += ui32Data;
+
+ /* Check for wrapping */
+ if ((psStream->ui32RPtr != psStream->ui32WPtr) &&
+ (psStream->ui32RPtr >= psStream->ui32Size))
+ {
+ psStream->ui32RPtr = 0;
+ }
+ }
+
+ return(ui32Data);
+}
+
+/*!****************************************************************************
+ @name DBGDrivSetMarker
+ @brief Sets the marker in the stream to split output files
+ @param psStream, ui32Marker
+ @return nothing
+*****************************************************************************/
+IMG_VOID IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+ /*
+ Validate buffer
+ */
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ /* Called by PDump client to reset the marker to zero after a file split */
+ if ((ui32Marker == 0) && (psStream->ui32Marker == 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivSetMarker: Client resetting marker that is already zero!"));
+ }
+ /* Called by pvrsrvkm to set the marker to signal a file split is required */
+ if ((ui32Marker != 0) && (psStream->ui32Marker != 0))
+ {
+ /* In this case a previous split request is still outstanding. The
+ * client has not yet actioned and acknowledged the previous
+ * marker. This may be an error if the client does not catch-up and
+ * the stream's written data is allowed to pass the max file
+ * size again. If this happens the PDump is invalid as the offsets
+ * from the script file will be incorrect.
+ */
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivSetMarker: Server setting marker that is already set!"));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "DBGDrivSetMarker: Setting stream split marker to %d (was %d)", ui32Marker, psStream->ui32Marker));
+ }
+
+ psStream->ui32Marker = ui32Marker;
+}
+
+/*!****************************************************************************
+ @name DBGDrivGetMarker
+ @brief Gets the marker in the stream to split output files
+ @param psStream - stream
+ @return marker offset
+*****************************************************************************/
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream)
+{
+ /*
+ Validate buffer
+ */
+ if (!StreamValid(psStream))
+ {
+ return 0;
+ }
+
+ return psStream->ui32Marker;
+}
+
+/*!****************************************************************************
+ @name DBGDrivGetServiceTable
+ @brief get jump table for Services driver
+ @return pointer to jump table
+*****************************************************************************/
+IMG_PVOID IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID)
+{
+ return((IMG_PVOID)&g_sDBGKMServices);
+}
+
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+/*!****************************************************************************
+ @name DBGDrivWaitForEvent
+ @brief waits for an event
+ @param eEvent - debug driver event
+ @return IMG_VOID
+*****************************************************************************/
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+ HostWaitForEvent(eEvent);
+}
+#endif
+
+/* Use PVR_DPF() to avoid state messages in release build */
+#if defined(PVR_DISABLE_LOGGING) || !defined(DEBUG)
+#define PVR_LOG(...)
+#else
+
+extern IMG_VOID PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR* pszFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR* pszFormat,
+ ... );
+/* Reproduce the PVR_LOG macro here but direct it to DPF */
+#define PVR_LOG(...) PVRSRVDebugPrintf( DBGPRIV_CALLTRACE, __FILE__, __LINE__ , __VA_ARGS__);
+
+#endif
+
+
+/*!****************************************************************************
+ @name DBGDrivGetCtrlState
+ @brief Gets a state value from the debug driver or stream
+ @param psStream - stream
+ @param ui32StateID - state ID
+ @return Nothing
+*****************************************************************************/
+IMG_UINT32 IMG_CALLCONV DBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID)
+{
+ /* Validate buffer */
+ if (!StreamValid(psStream))
+ {
+ return (0xFFFFFFFF);
+ }
+
+ /* Retrieve the state asked for */
+ switch (ui32StateID)
+ {
+ case DBG_GET_STATE_FLAG_IS_READONLY:
+ return ((psStream->ui32Flags & DEBUG_FLAGS_READONLY) != 0);
+ break;
+
+ case 0xFE: /* Dump the current stream state */
+ PVR_LOG("------ PDUMP DBGDriv: psStream( %p ) ( -- %s -- ) ui32Flags( %x )",
+ psStream, psStream->szName, psStream->ui32Flags);
+ PVR_LOG("------ PDUMP DBGDriv: psStream->pvBase( %p ) psStream->ui32Size( %u )",
+ psStream->pvBase, psStream->ui32Size);
+ PVR_LOG("------ PDUMP DBGDriv: psStream->ui32RPtr( %u ) psStream->ui32WPtr( %u )",
+ psStream->ui32RPtr, psStream->ui32WPtr);
+ PVR_LOG("------ PDUMP DBGDriv: psStream->ui32Marker( %u ) psStream->ui32InitPhaseWOff( %u )",
+ psStream->ui32Marker, psStream->ui32InitPhaseWOff);
+ if (psStream->psInitStream)
+ {
+ PVR_LOG("-------- PDUMP DBGDriv: psInitStream( %p ) ( -- %s -- ) ui32Flags( %x )",
+ psStream->psInitStream, psStream->psInitStream->szName, psStream->ui32Flags);
+ PVR_LOG("-------- PDUMP DBGDriv: psInitStream->pvBase( %p ) psInitStream->ui32Size( %u )",
+ psStream->psInitStream->pvBase, psStream->psInitStream->ui32Size);
+ PVR_LOG("-------- PDUMP DBGDriv: psInitStream->ui32RPtr( %u ) psInitStream->ui32WPtr( %u )",
+ psStream->psInitStream->ui32RPtr, psStream->psInitStream->ui32WPtr);
+ PVR_LOG("-------- PDUMP DBGDriv: psInitStream->ui32Marker( %u ) psInitStream->ui32InitPhaseWOff( %u ) ",
+ psStream->psInitStream->ui32Marker, psStream->psInitStream->ui32InitPhaseWOff);
+ }
+
+ break;
+
+ case 0xFF: /* Dump driver state not in a stream */
+ {
+ PVR_LOG("------ PDUMP DBGDriv: g_psStreamList( head %p ) g_pvAPIMutex( %p ) g_PDumpCurrentFrameNo( %u )", g_psStreamList, g_pvAPIMutex, g_PDumpCurrentFrameNo);
+ }
+ break;
+
+ default:
+ PVR_ASSERT(0);
+ }
+
+ return (0xFFFFFFFF);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(void)
+{
+ return g_PDumpCurrentFrameNo;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivSetFrame(IMG_UINT32 ui32Frame)
+{
+ g_PDumpCurrentFrameNo = ui32Frame;
+}
+
+
+/*!****************************************************************************
+ @name ExpandStreamBuffer
+ @brief allocates a new buffer when the current one is full
+ @param psStream - stream
+ @param ui32NewSize - new size
+ @return IMG_TRUE - if allocation succeeded, IMG_FALSE - if not
+*****************************************************************************/
+static IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
+{
+ IMG_VOID * pvNewBuf;
+ IMG_UINT32 ui32NewSizeInPages;
+ IMG_UINT32 ui32NewWOffset;
+ IMG_UINT32 ui32NewROffset;
+ IMG_UINT32 ui32SpaceInOldBuf;
+
+ /*
+ First check new size is bigger than existing size
+ */
+ if (psStream->ui32Size >= ui32NewSize)
+ {
+ return IMG_FALSE;
+ }
+
+ /*
+ Calc space in old buffer
+ */
+ ui32SpaceInOldBuf = SpaceInStream(psStream);
+
+ /*
+ Allocate new buffer
+ */
+ ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
+ }
+ else
+ {
+ pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
+ }
+
+ if (pvNewBuf == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
+ {
+ /*
+ Copy over old buffer to new one, we place data at start of buffer
+ even if Read offset is not at start of buffer
+ */
+ if (psStream->ui32RPtr <= psStream->ui32WPtr)
+ {
+ /*
+ No wrapping of data so copy data to start of new buffer
+ */
+ HostMemCopy(pvNewBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ psStream->ui32WPtr - psStream->ui32RPtr);
+ }
+ else
+ {
+ IMG_UINT32 ui32FirstCopySize;
+
+ /*
+ The data has wrapped around the buffer, copy beginning of buffer first
+ */
+ ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
+
+ HostMemCopy(pvNewBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ ui32FirstCopySize);
+
+ /*
+ Now second half
+ */
+ HostMemCopy((IMG_VOID *)((IMG_UINTPTR_T)pvNewBuf + ui32FirstCopySize),
+ (IMG_VOID *)(IMG_PBYTE)psStream->pvBase,
+ psStream->ui32WPtr);
+ }
+ ui32NewROffset = 0;
+ }
+ else
+ {
+ /* Copy everything in the old buffer to the new one */
+ HostMemCopy(pvNewBuf, psStream->pvBase, psStream->ui32WPtr);
+ ui32NewROffset = psStream->ui32RPtr;
+ }
+
+ /*
+ New Write offset is at end of data
+ */
+ ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
+
+ /*
+ Free old buffer
+ */
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree(psStream->pvBase);
+ }
+ else
+ {
+ HostPageablePageFree(psStream->pvBase);
+ }
+
+ /*
+ Now set new params up
+ */
+ psStream->pvBase = pvNewBuf;
+ psStream->ui32RPtr = ui32NewROffset;
+ psStream->ui32WPtr = ui32NewWOffset;
+ psStream->ui32Size = ui32NewSizeInPages * 4096;
+
+ return IMG_TRUE;
+}
+
+/*!****************************************************************************
+ @name SpaceInStream
+ @brief remaining space in stream
+ @param psStream - stream
+ @return bytes remaining
+*****************************************************************************/
+static IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Space;
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_CIRCULAR) != 0)
+ {
+ /* Allow overwriting the buffer which was already read */
+ if (psStream->ui32RPtr > psStream->ui32WPtr)
+ {
+ ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
+ }
+ else
+ {
+ ui32Space = psStream->ui32RPtr + (psStream->ui32Size - psStream->ui32WPtr);
+ }
+ }
+ else
+ {
+ /* Don't overwrite anything */
+ ui32Space = psStream->ui32Size - psStream->ui32WPtr;
+ }
+
+ return ui32Space;
+}
+
+
+/*!****************************************************************************
+ @name DestroyAllStreams
+ @brief delete all streams in list
+ @return none
+*****************************************************************************/
+IMG_VOID DestroyAllStreams(IMG_VOID)
+{
+ PDBG_STREAM psStream = g_psStreamList;
+ PDBG_STREAM psStreamToFree;
+
+ while (psStream != IMG_NULL)
+ {
+ psStreamToFree = psStream;
+ psStream = psStream->psNext;
+ DBGDrivDestroyStream(psStreamToFree->psInitStream, psStreamToFree, psStreamToFree->psDeinitStream);
+ }
+ g_psStreamList = IMG_NULL;
+ return;
+}
+
+/******************************************************************************
+ End of file (DBGDRIV.C)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv.h b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv.h
new file mode 100644
index 000000000000..6649e5cd48dc
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv.h
@@ -0,0 +1,114 @@
+/*************************************************************************/ /*!
+@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 _DBGDRIV_
+#define _DBGDRIV_
+
+/*****************************************************************************
+ The odd constant or two
+*****************************************************************************/
+
+#define DBGDRIV_VERSION 0x100
+#define MAX_PROCESSES 2
+#define BLOCK_USED 0x01
+#define BLOCK_LOCKED 0x02
+#define DBGDRIV_MONOBASE 0x000B0000
+
+
+extern IMG_VOID * g_pvAPIMutex;
+
+/*****************************************************************************
+ Internal debug driver core functions
+*****************************************************************************/
+/* Called by WDDM debug driver win7/hostfunc.c */
+IMG_BOOL IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *pszName, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Pages,
+ IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit);
+
+/* Called by Linux debug driver main.c to allow the API mutex lock to be used
+ * to protect the common IOCTL read buffer while avoiding deadlock in the Ext
+ * layer
+ */
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psStream, IMG_UINT32 ui32BufID,
+ IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
+
+/* Used in ioctl.c in DBGDIOCDrivGetServiceTable() which is called in WDDM PDump files */
+IMG_PVOID IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID);
+
+/* Used in WDDM version of debug driver win7/main.c */
+IMG_VOID DestroyAllStreams(IMG_VOID);
+
+/*****************************************************************************
+ Function prototypes
+*****************************************************************************/
+IMG_UINT32 AtoI(IMG_CHAR *szIn);
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest,IMG_UINT8 ui8Value,IMG_UINT32 ui32Size);
+IMG_VOID HostMemCopy(IMG_VOID *pvDest,IMG_VOID *pvSrc,IMG_UINT32 ui32Size);
+
+/*****************************************************************************
+ Secure handle Function prototypes
+*****************************************************************************/
+IMG_SID PStream2SID(PDBG_STREAM psStream);
+PDBG_STREAM SID2PStream(IMG_SID hStream);
+IMG_BOOL AddSIDEntry(PDBG_STREAM psStream);
+IMG_BOOL RemoveSIDEntry(PDBG_STREAM psStream);
+
+/*****************************************************************************
+ Declarations for IOCTL Service table and KM table entry points
+*****************************************************************************/
+IMG_BOOL IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR *pszName, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_HANDLE* phInit, IMG_HANDLE* phMain, IMG_HANDLE* phDeinit);
+IMG_VOID IMG_CALLCONV ExtDBGDrivDestroyStream(IMG_HANDLE hInit, IMG_HANDLE hMain, IMG_HANDLE hDeinit);
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_UINT32 ui32BufID, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 *pui8OutBuf);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetCtrlState(PDBG_STREAM psStream, IMG_UINT32 ui32StateID);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(void);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetFrame(IMG_UINT32 ui32Frame);
+
+#endif
+
+/*****************************************************************************
+ End of file (DBGDRIV.H)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv_ioctl.h b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv_ioctl.h
new file mode 100644
index 000000000000..bce7b968f43b
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/dbgdriv_ioctl.h
@@ -0,0 +1,58 @@
+/*************************************************************************/ /*!
+@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 _DBGDRIV_IOCTL_H_
+#define _DBGDRIV_IOCTL_H_
+
+#include "dbgdrvif_srv5.h"
+
+
+/* Share this debug driver global with the OS layer so that IOCTL calls
+ * coming from the OS enter the common table of entry points.
+ */
+extern IMG_UINT32 (*g_DBGDrivProc[DEBUG_SERVICE_MAX_API])(IMG_VOID *, IMG_VOID *, IMG_BOOL);
+
+
+#endif /* _DBGDRIV_IOCTL_H_ */
+
+/*****************************************************************************
+ End of file
+ *****************************************************************************/
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/handle.c b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/handle.c
new file mode 100644
index 000000000000..af54eee41300
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/handle.c
@@ -0,0 +1,141 @@
+/*************************************************************************/ /*!
+@File
+@Title Resource Handle Manager
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource handle management
+@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 "dbgdrvif_srv5.h"
+#include "dbgdriv.h"
+
+/* max number of streams held in SID info table */
+#define MAX_SID_ENTRIES 8
+
+typedef struct _SID_INFO
+{
+ PDBG_STREAM psStream;
+} SID_INFO, *PSID_INFO;
+
+static SID_INFO gaSID_Xlat_Table[MAX_SID_ENTRIES];
+
+IMG_SID PStream2SID(PDBG_STREAM psStream)
+{
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ IMG_INT32 iIdx;
+
+ for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+ {
+ if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+ {
+ /* idx is one based */
+ return (IMG_SID)iIdx+1;
+ }
+ }
+ }
+
+ return (IMG_SID)0;
+}
+
+
+PDBG_STREAM SID2PStream(IMG_SID hStream)
+{
+ /* changed to zero based */
+ IMG_INT32 iIdx = (IMG_INT32)hStream-1;
+
+ if (iIdx >= 0 && iIdx < MAX_SID_ENTRIES)
+ {
+ return gaSID_Xlat_Table[iIdx].psStream;
+ }
+ else
+ {
+ return (PDBG_STREAM)IMG_NULL;
+ }
+}
+
+
+IMG_BOOL AddSIDEntry(PDBG_STREAM psStream)
+{
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ IMG_INT32 iIdx;
+
+ for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+ {
+ if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+ {
+ /* already created */
+ return IMG_TRUE;
+ }
+
+ if (gaSID_Xlat_Table[iIdx].psStream == (PDBG_STREAM)IMG_NULL)
+ {
+ /* free entry */
+ gaSID_Xlat_Table[iIdx].psStream = psStream;
+ return IMG_TRUE;
+ }
+ }
+ }
+
+ return IMG_FALSE;
+}
+
+IMG_BOOL RemoveSIDEntry(PDBG_STREAM psStream)
+{
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ IMG_INT32 iIdx;
+
+ for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+ {
+ if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+ {
+ gaSID_Xlat_Table[iIdx].psStream = (PDBG_STREAM)IMG_NULL;
+ return IMG_TRUE;
+ }
+ }
+ }
+
+ return IMG_FALSE;
+}
+
+
+/******************************************************************************
+ End of file (handle.c)
+******************************************************************************/
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/hostfunc.h b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/hostfunc.h
new file mode 100644
index 000000000000..ed801772662a
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/hostfunc.h
@@ -0,0 +1,82 @@
+/*************************************************************************/ /*!
+@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 _HOSTFUNC_
+#define _HOSTFUNC_
+
+/*****************************************************************************
+ Defines
+*****************************************************************************/
+#define HOST_PAGESIZE (4096)
+#define DBG_MEMORY_INITIALIZER (0xe2)
+
+/*****************************************************************************
+ Function prototypes
+*****************************************************************************/
+IMG_UINT32 HostReadRegistryDWORDFromString(IMG_CHAR *pcKey, IMG_CHAR *pcValueName, IMG_UINT32 *pui32Data);
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase);
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase);
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID * *ppvMdl);
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess);
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID);
+
+IMG_VOID * HostCreateMutex(IMG_VOID);
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex);
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex);
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_INT32 HostCreateEventObjects(IMG_VOID);
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent);
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent);
+IMG_VOID HostDestroyEventObjects(IMG_VOID);
+#endif /*defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
+
+#endif
+
+/*****************************************************************************
+ End of file (HOSTFUNC.H)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/ioctl.c b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/ioctl.c
new file mode 100644
index 000000000000..76ee319b8cb6
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/common/ioctl.c
@@ -0,0 +1,335 @@
+/*************************************************************************/ /*!
+@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.
+*/ /**************************************************************************/
+#if defined(UNDER_CE)
+#include <windows.h>
+#include <ceddk.h>
+#else
+
+#if defined(_WIN32)
+#pragma warning(disable:4201)
+#pragma warning(disable:4214)
+#pragma warning(disable:4115)
+#pragma warning(disable:4514)
+
+#include <ntddk.h>
+#include <windef.h>
+
+#endif /* _WIN32 */
+#endif /* UNDER_CE */
+
+#ifdef LINUX
+#include <asm/uaccess.h>
+#include "pvr_uaccess.h"
+#endif /* LINUX */
+
+#include "img_types.h"
+#include "dbgdrvif_srv5.h"
+#include "dbgdriv.h"
+#include "dbgdriv_ioctl.h"
+#include "hostfunc.h"
+
+#ifdef _WIN32
+#pragma warning(default:4214)
+#pragma warning(default:4115)
+#endif /* _WIN32 */
+
+/*****************************************************************************
+ Code
+*****************************************************************************/
+
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivGetServiceTable
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
+static IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer, IMG_BOOL bCompat)
+{
+ IMG_PVOID * ppvOut;
+
+ PVR_UNREFERENCED_PARAMETER(pvInBuffer);
+ PVR_UNREFERENCED_PARAMETER(bCompat);
+ ppvOut = (IMG_PVOID *) pvOutBuffer;
+
+ *ppvOut = DBGDrivGetServiceTable();
+
+ return(IMG_TRUE);
+}
+
+#if defined(__QNXNTO__)
+/*****************************************************************************
+ FUNCTION : DBGIODrivCreateStream
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
+static IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer, IMG_BOOL bCompat)
+{
+ PDBG_IN_CREATESTREAM psIn;
+ PDBG_OUT_CREATESTREAM psOut;
+
+ PVR_UNREFERENCED_PARAMETER(bCompat);
+
+ psIn = (PDBG_IN_CREATESTREAM) pvInBuffer;
+ psOut = (PDBG_OUT_CREATESTREAM) pvOutBuffer;
+
+ return (ExtDBGDrivCreateStream(psIn->u.pszName, DEBUG_FLAGS_NO_BUF_EXPANDSION, psIn->ui32Pages, &psOut->phInit, &psOut->phMain, &psOut->phDeinit));
+}
+#endif
+
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivGetStream
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
+static IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer, IMG_BOOL bCompat)
+{
+ PDBG_IN_FINDSTREAM psParams;
+ IMG_SID * phStream;
+
+ psParams = (PDBG_IN_FINDSTREAM)pvInBuffer;
+ phStream = (IMG_SID *)pvOutBuffer;
+
+ *phStream = PStream2SID(ExtDBGDrivFindStream(WIDEPTR_GET_PTR(psParams->pszName, bCompat), psParams->bResetStream));
+
+ return(IMG_TRUE);
+}
+
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivRead
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
+static IMG_UINT32 DBGDIOCDrivRead(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer, IMG_BOOL bCompat)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_READ psInParams;
+ PDBG_STREAM psStream;
+ IMG_UINT8 *pui8ReadBuffer;
+
+ psInParams = (PDBG_IN_READ) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+ pui8ReadBuffer = WIDEPTR_GET_PTR(psInParams->pui8OutBuffer, bCompat);
+
+ psStream = SID2PStream(psInParams->hStream);
+
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+#ifdef UNDER_WDDM
+ IMG_UINT8 *pui8ClientBuffer;
+ /* WDDM DbgDriv operates at DISPATCH level so it cannot write directly
+ * to pdump.exe's userspace buffer
+ */
+
+ pui8ReadBuffer = HostNonPageablePageAlloc(
+ (psInParams->ui32OutBufferSize + HOST_PAGESIZE - 1) / HOST_PAGESIZE);
+ if (!pui8ReadBuffer)
+ {
+ return(IMG_FALSE);
+ }
+ pui8ClientBuffer = WIDEPTR_GET_PTR(psInParams->pui8OutBuffer, bCompat);
+#endif
+ *pui32BytesCopied = ExtDBGDrivRead(psStream,
+ psInParams->ui32BufID,
+ psInParams->ui32OutBufferSize,
+ pui8ReadBuffer);
+#ifdef UNDER_WDDM
+ if(*pui32BytesCopied > 0)
+ {
+ HostMemCopy(pui8ClientBuffer, pui8ReadBuffer, *pui32BytesCopied);
+ }
+
+ HostNonPageablePageFree(pui8ReadBuffer);
+#endif
+ return(IMG_TRUE);
+ }
+ else
+ {
+ /* invalid SID */
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivSetMarker
+
+ PURPOSE : Sets the marker in the stream to split output files
+
+ PARAMETERS : pvInBuffer, pvOutBuffer
+
+ RETURNS : success
+*****************************************************************************/
+static IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer, IMG_BOOL bCompat)
+{
+ PDBG_IN_SETMARKER psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETMARKER) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+ PVR_UNREFERENCED_PARAMETER(bCompat);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetMarker(psStream, psParams->ui32Marker);
+ return(IMG_TRUE);
+ }
+ else
+ {
+ /* invalid SID */
+ return(IMG_FALSE);
+ }
+}
+
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivGetMarker
+
+ PURPOSE : Gets the marker in the stream to split output files
+
+ PARAMETERS : pvInBuffer, pvOutBuffer
+
+ RETURNS : success
+*****************************************************************************/
+static IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer, IMG_BOOL bCompat)
+{
+ PDBG_STREAM psStream;
+ IMG_UINT32 *pui32Current;
+
+ PVR_UNREFERENCED_PARAMETER(bCompat);
+
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32Current = ExtDBGDrivGetMarker(psStream);
+ return(IMG_TRUE);
+ }
+ else
+ {
+ /* invalid SID */
+ *pui32Current = 0;
+ return(IMG_FALSE);
+ }
+}
+
+
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivWaitForEvent
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
+static IMG_UINT32 DBGDIOCDrivWaitForEvent(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer, IMG_BOOL bCompat)
+{
+ DBG_EVENT eEvent = (DBG_EVENT)(*(IMG_UINT32 *)pvInBuffer);
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+ PVR_UNREFERENCED_PARAMETER(bCompat);
+
+ ExtDBGDrivWaitForEvent(eEvent);
+
+ return(IMG_TRUE);
+}
+
+
+/*****************************************************************************
+ FUNCTION : DBGDIOCDrivGetFrame
+
+ PURPOSE : Gets the marker in the stream to split output files
+
+ PARAMETERS : pvInBuffer, pvOutBuffer
+
+ RETURNS : success
+*****************************************************************************/
+static IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer, IMG_BOOL bCompat)
+{
+ IMG_UINT32 *pui32Current;
+
+ PVR_UNREFERENCED_PARAMETER(pvInBuffer);
+ PVR_UNREFERENCED_PARAMETER(bCompat);
+
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+ *pui32Current = ExtDBGDrivGetFrame();
+
+ return(IMG_TRUE);
+}
+
+/*
+ ioctl interface jump table.
+ Accessed from the UM debug driver client and from WDDM KMD server
+*/
+IMG_UINT32 (*g_DBGDrivProc[DEBUG_SERVICE_MAX_API])(IMG_VOID *, IMG_VOID *, IMG_BOOL) =
+{
+ DBGDIOCDrivGetServiceTable, /* WDDM only for KMD to retrieve address from DBGDRV, Not used by umdbgdrvlnx */
+ DBGDIOCDrivGetStream,
+ DBGDIOCDrivRead,
+ DBGDIOCDrivSetMarker,
+ DBGDIOCDrivGetMarker,
+ DBGDIOCDrivWaitForEvent,
+ DBGDIOCDrivGetFrame,
+#if defined(__QNXNTO__)
+ DBGDIOCDrivCreateStream
+#endif
+};
+
+/*****************************************************************************
+ End of file (IOCTL.C)
+*****************************************************************************/
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/linux/hostfunc.c b/drivers/gpu/rogue/tools/services/debug/dbgdriv/linux/hostfunc.c
new file mode 100644
index 000000000000..578d77b4f258
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/linux/hostfunc.c
@@ -0,0 +1,382 @@
+/*************************************************************************/ /*!
+@File
+@Title Debug driver 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/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/hardirq.h>
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#endif /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
+
+#include "img_types.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif_srv5.h"
+#include "hostfunc.h"
+#include "dbgdriv.h"
+
+#if defined(PVRSRV_NEED_PVR_DPF) && !defined(SUPPORT_DRM)
+IMG_UINT32 gPVRDebugLevel = (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING |
+ DBGPRIV_CALLTRACE); /* Added call trace level to support PVR_LOGging of state in debug driver */
+
+#define PVR_STRING_TERMINATOR '\0'
+#define PVR_IS_FILE_SEPARATOR(character) ( ((character) == '\\') || ((character) == '/') )
+
+/******************************************************************************/
+
+
+/*----------------------------------------------------------------------------
+<function>
+ FUNCTION : PVRSRVDebugPrintf
+ PURPOSE : To output a debug message to the user
+ PARAMETERS : In : uDebugLevel - The current debug level
+ In : pszFile - The source file generating the message
+ In : uLine - The line of the source file
+ In : pszFormat - The message format string
+ In : ... - Zero or more arguments for use by the format string
+ RETURNS : None
+</function>
+------------------------------------------------------------------------------*/
+void PVRSRVDebugPrintf (
+ IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR* pszFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR* pszFormat,
+ ...
+ )
+{
+ IMG_BOOL bTrace;
+ IMG_CHAR *pszLeafName;
+
+ pszLeafName = (char *)strrchr (pszFileName, '/');
+
+ if (pszLeafName)
+ {
+ pszFileName = pszLeafName;
+ }
+
+ bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
+
+ if (gPVRDebugLevel & ui32DebugLevel)
+ {
+ va_list vaArgs;
+ static char szBuffer[512];
+
+ va_start (vaArgs, pszFormat);
+
+ /* Add in the level of warning */
+ if (bTrace == IMG_FALSE)
+ {
+ switch(ui32DebugLevel)
+ {
+ case DBGPRIV_FATAL:
+ {
+ strcpy (szBuffer, "PVR_K:(Fatal): ");
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ strcpy (szBuffer, "PVR_K:(Error): ");
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ strcpy (szBuffer, "PVR_K:(Warning): ");
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ strcpy (szBuffer, "PVR_K:(Message): ");
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ strcpy (szBuffer, "PVR_K:(Verbose): ");
+ break;
+ }
+ default:
+ {
+ strcpy (szBuffer, "PVR_K:()");
+ break;
+ }
+ }
+ }
+ else
+ {
+ strcpy (szBuffer, "PVR_K: ");
+ }
+
+ vsprintf (&szBuffer[strlen(szBuffer)], pszFormat, vaArgs);
+
+ /*
+ * Metrics and Traces don't need a location
+ */
+ if (bTrace == IMG_FALSE)
+ {
+ sprintf (&szBuffer[strlen(szBuffer)], " [%d, %s]", (int)ui32Line, pszFileName);
+ }
+
+ printk(KERN_INFO "%s\n", szBuffer);
+
+ va_end (vaArgs);
+ }
+}
+#endif /* defined(PVRSRV_NEED_PVR_DPF) && !defined(SUPPORT_DRM) */
+
+/*!
+******************************************************************************
+
+ @Function HostMemSet
+
+ @Description Function that does the same as the C memset() functions
+
+ @Modified *pvDest : pointer to start of buffer to be set
+
+ @Input ui8Value: value to set each byte to
+
+ @Input ui32Size : number of bytes to set
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID HostMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+ memset(pvDest, (int) ui8Value, (size_t) ui32Size);
+}
+
+/*!
+******************************************************************************
+
+ @Function HostMemCopy
+
+ @Description Copies memory around
+
+ @Input pvDst - pointer to dst
+ @Output pvSrc - pointer to src
+ @Input ui32Size - bytes to copy
+
+ @Return none
+
+******************************************************************************/
+IMG_VOID HostMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+ unsigned char *src,*dst;
+ int i;
+
+ src=(unsigned char *)pvSrc;
+ dst=(unsigned char *)pvDst;
+ for(i=0;i<ui32Size;i++)
+ {
+ dst[i]=src[i];
+ }
+#else
+ memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+IMG_UINT32 HostReadRegistryDWORDFromString(char *pcKey, char *pcValueName, IMG_UINT32 *pui32Data)
+{
+ /* XXX Not yet implemented */
+ return 0;
+}
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);/*, GFP_KERNEL);*/
+}
+
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase)
+{
+ vfree(pvBase);
+}
+
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);/*, GFP_KERNEL);*/
+}
+
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase)
+{
+ vfree(pvBase);
+}
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID **ppvMdl)
+{
+ /* XXX Not yet implemented */
+ return IMG_NULL;
+}
+
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess)
+{
+ /* XXX Not yet implemented */
+}
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID)
+{
+ /* XXX Not yet implemented */
+}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+typedef struct mutex MUTEX;
+#define INIT_MUTEX(m) mutex_init(m)
+#define DOWN_TRYLOCK(m) (!mutex_trylock(m))
+#define DOWN(m) mutex_lock(m)
+#define UP(m) mutex_unlock(m)
+#else
+typedef struct semaphore MUTEX;
+#define INIT_MUTEX(m) init_MUTEX(m)
+#define DOWN_TRYLOCK(m) down_trylock(m)
+#define DOWN(m) down(m)
+#define UP(m) up(m)
+#endif
+
+IMG_VOID *HostCreateMutex(IMG_VOID)
+{
+ MUTEX *psMutex;
+
+ psMutex = kmalloc(sizeof(*psMutex), GFP_KERNEL);
+ if (psMutex)
+ {
+ INIT_MUTEX(psMutex);
+ }
+
+ return psMutex;
+}
+
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex)
+{
+ BUG_ON(in_interrupt());
+
+#if defined(PVR_DEBUG_DBGDRV_DETECT_HOST_MUTEX_COLLISIONS)
+ if (DOWN_TRYLOCK((MUTEX *)pvMutex))
+ {
+ printk(KERN_INFO "HostAquireMutex: Waiting for mutex\n");
+ DOWN((MUTEX *)pvMutex);
+ }
+#else
+ DOWN((MUTEX *)pvMutex);
+#endif
+}
+
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex)
+{
+ UP((MUTEX *)pvMutex);
+}
+
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex)
+{
+ if (pvMutex)
+ {
+ kfree(pvMutex);
+ }
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+#define EVENT_WAIT_TIMEOUT_MS 500
+#define EVENT_WAIT_TIMEOUT_JIFFIES (EVENT_WAIT_TIMEOUT_MS * HZ / 1000)
+
+static int iStreamData;
+static wait_queue_head_t sStreamDataEvent;
+
+IMG_INT32 HostCreateEventObjects(IMG_VOID)
+{
+ init_waitqueue_head(&sStreamDataEvent);
+
+ return 0;
+}
+
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent)
+{
+ switch(eEvent)
+ {
+ case DBG_EVENT_STREAM_DATA:
+ /*
+ * More than one process may be woken up.
+ * Any process that wakes up should consume
+ * all the data from the streams.
+ */
+ wait_event_interruptible_timeout(sStreamDataEvent, iStreamData != 0, EVENT_WAIT_TIMEOUT_JIFFIES);
+ iStreamData = 0;
+ break;
+ default:
+ /*
+ * For unknown events, enter an interruptible sleep.
+ */
+ msleep_interruptible(EVENT_WAIT_TIMEOUT_MS);
+ break;
+ }
+}
+
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent)
+{
+ switch(eEvent)
+ {
+ case DBG_EVENT_STREAM_DATA:
+ iStreamData = 1;
+ wake_up_interruptible(&sStreamDataEvent);
+ break;
+ default:
+ break;
+ }
+}
+
+IMG_VOID HostDestroyEventObjects(IMG_VOID)
+{
+}
+#endif /* defined(SUPPORT_DBGDRV_EVENT_OBJECTS) */
diff --git a/drivers/gpu/rogue/tools/services/debug/dbgdriv/linux/main.c b/drivers/gpu/rogue/tools/services/debug/dbgdriv/linux/main.c
new file mode 100644
index 000000000000..58c337a3cf74
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/dbgdriv/linux/main.c
@@ -0,0 +1,358 @@
+/*************************************************************************/ /*!
+@File
+@Title Debug driver main 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/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+
+#if defined(LDM_PLATFORM) && !defined(SUPPORT_DRM)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(LDM_PCI) && !defined(SUPPORT_DRM)
+#include <linux/pci.h>
+#endif
+
+#include <asm/uaccess.h>
+
+#if defined(SUPPORT_DRM)
+#include <drm/drmP.h>
+#endif
+
+#include "img_types.h"
+#include "linuxsrv.h"
+#include "dbgdriv_ioctl.h"
+#include "dbgdrvif_srv5.h"
+#include "dbgdriv.h"
+#include "hostfunc.h"
+#include "pvr_debug.h"
+#include "pvrmodule.h"
+#include "pvr_uaccess.h"
+
+#if defined(SUPPORT_DRM)
+
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#else /* defined(SUPPORT_DRM) */
+
+#define DRVNAME "dbgdrv"
+MODULE_SUPPORTED_DEVICE(DRVNAME);
+
+static struct class *psDbgDrvClass;
+
+static int AssignedMajorNumber = 0;
+
+long dbgdrv_ioctl(struct file *, unsigned int, unsigned long);
+long dbgdrv_ioctl_compat(struct file *, unsigned int, unsigned long);
+
+static int dbgdrv_open(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_release(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_mmap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+ return 0;
+}
+
+static struct file_operations dbgdrv_fops =
+{
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = dbgdrv_ioctl,
+ .compat_ioctl = dbgdrv_ioctl_compat,
+ .open = dbgdrv_open,
+ .release = dbgdrv_release,
+ .mmap = dbgdrv_mmap,
+};
+
+#endif /* defined(SUPPORT_DRM) */
+
+/* Outward temp buffer used by IOCTL handler allocated once and grows as needed.
+ * This optimisation means the debug driver performs less vmallocs/vfrees
+ * reducing the chance of kernel vmalloc space exhaustion.
+ * but is not multi-threaded optimised as it now uses a mutex to protect this
+ * shared buffer serialising buffer reads. However the PDump client is not
+ * multi-threaded at the moment.
+ */
+static IMG_CHAR* g_outTmpBuf = IMG_NULL;
+static IMG_UINT32 g_outTmpBufSize = 64*PAGE_SIZE;
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table)
+{
+ extern DBGKM_SERVICE_TABLE g_sDBGKMServices;
+
+ *fn_table = &g_sDBGKMServices;
+}
+
+#if defined(SUPPORT_DRM)
+void dbgdrv_cleanup(void)
+#else
+void cleanup_module(void)
+#endif
+{
+ if (g_outTmpBuf)
+ {
+ vfree(g_outTmpBuf);
+ g_outTmpBuf = IMG_NULL;
+ }
+
+#if !defined(SUPPORT_DRM)
+ device_destroy(psDbgDrvClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psDbgDrvClass);
+ unregister_chrdev(AssignedMajorNumber, DRVNAME);
+#endif /* !defined(SUPPORT_DRM) */
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ HostDestroyEventObjects();
+#endif
+ HostDestroyMutex(g_pvAPIMutex);
+ return;
+}
+
+#if defined(SUPPORT_DRM)
+IMG_INT dbgdrv_init(void)
+#else
+int init_module(void)
+#endif
+{
+#if !defined(SUPPORT_DRM)
+ struct device *psDev;
+#endif
+
+#if !defined(SUPPORT_DRM)
+ int err = -EBUSY;
+#endif
+
+ /* Init API mutex */
+ if ((g_pvAPIMutex=HostCreateMutex()) == IMG_NULL)
+ {
+ return -ENOMEM;
+ }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ /*
+ * The current implementation of HostCreateEventObjects on Linux
+ * can never fail, so there is no need to check for error.
+ */
+ (void) HostCreateEventObjects();
+#endif
+
+#if !defined(SUPPORT_DRM)
+ AssignedMajorNumber =
+ register_chrdev(AssignedMajorNumber, DRVNAME, &dbgdrv_fops);
+
+ if (AssignedMajorNumber <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR," unable to get major\n"));
+ goto ErrDestroyEventObjects;
+ }
+
+ /*
+ * This code (using GPL symbols) facilitates automatic device
+ * node creation on platforms with udev (or similar).
+ */
+ psDbgDrvClass = class_create(THIS_MODULE, DRVNAME);
+ if (IS_ERR(psDbgDrvClass))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: unable to create class (%ld)",
+ __func__, PTR_ERR(psDbgDrvClass)));
+ goto ErrUnregisterCharDev;
+ }
+
+ psDev = device_create(psDbgDrvClass, NULL, MKDEV(AssignedMajorNumber, 0), NULL, DRVNAME);
+ if (IS_ERR(psDev))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: unable to create device (%ld)",
+ __func__, PTR_ERR(psDev)));
+ goto ErrDestroyClass;
+ }
+#endif /* !defined(SUPPORT_DRM) */
+
+ return 0;
+
+#if !defined(SUPPORT_DRM)
+ErrDestroyEventObjects:
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ HostDestroyEventObjects();
+#endif
+ErrUnregisterCharDev:
+ unregister_chrdev(AssignedMajorNumber, DRVNAME);
+ErrDestroyClass:
+ class_destroy(psDbgDrvClass);
+ return err;
+#endif /* !defined(SUPPORT_DRM) */
+}
+
+static IMG_INT dbgdrv_ioctl_work(IMG_VOID *arg, IMG_BOOL bCompat)
+{
+ IOCTL_PACKAGE *pIP = (IOCTL_PACKAGE *) arg;
+ char *buffer, *in, *out;
+ unsigned int cmd;
+ IMG_VOID *pBufferIn, *pBufferOut;
+
+ if ((pIP->ui32InBufferSize > (PAGE_SIZE >> 1) ) || (pIP->ui32OutBufferSize > (PAGE_SIZE >> 1)))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Sizes of the buffers are too large, cannot do ioctl\n"));
+ return -1;
+ }
+
+ buffer = (char *) HostPageablePageAlloc(1);
+ if (!buffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to allocate buffer, cannot do ioctl\n"));
+ return -EFAULT;
+ }
+
+ in = buffer;
+ out = buffer + (PAGE_SIZE >>1);
+
+ pBufferIn = WIDEPTR_GET_PTR(pIP->pInBuffer, bCompat);
+ pBufferOut = WIDEPTR_GET_PTR(pIP->pOutBuffer, bCompat);
+
+ if (pvr_copy_from_user(in, pBufferIn, pIP->ui32InBufferSize) != 0)
+ {
+ goto init_failed;
+ }
+
+ /* Extra -1 because ioctls start at DEBUG_SERVICE_IOCTL_BASE + 1 */
+ cmd = MAKEIOCTLINDEX(pIP->ui32Cmd) - DEBUG_SERVICE_IOCTL_BASE - 1;
+
+ if (pIP->ui32Cmd == DEBUG_SERVICE_READ)
+ {
+ IMG_UINT32 *pui32BytesCopied = (IMG_UINT32 *)out;
+ DBG_OUT_READ *psReadOutParams = (DBG_OUT_READ *)out;
+ DBG_IN_READ *psReadInParams = (DBG_IN_READ *)in;
+ IMG_VOID *pvOutBuffer;
+ PDBG_STREAM psStream;
+
+ psStream = SID2PStream(psReadInParams->hStream);
+ if (!psStream)
+ {
+ goto init_failed;
+ }
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ if ((g_outTmpBuf == IMG_NULL) || (psReadInParams->ui32OutBufferSize > g_outTmpBufSize))
+ {
+ if (psReadInParams->ui32OutBufferSize > g_outTmpBufSize)
+ {
+ g_outTmpBufSize = psReadInParams->ui32OutBufferSize;
+ }
+ g_outTmpBuf = vmalloc(g_outTmpBufSize);
+ if (!g_outTmpBuf)
+ {
+ HostReleaseMutex(g_pvAPIMutex);
+ goto init_failed;
+ }
+ }
+
+ psReadOutParams->ui32DataRead = DBGDrivRead(psStream,
+ psReadInParams->ui32BufID,
+ psReadInParams->ui32OutBufferSize,
+ g_outTmpBuf);
+ psReadOutParams->ui32SplitMarker = DBGDrivGetMarker(psStream);
+
+ pvOutBuffer = WIDEPTR_GET_PTR(psReadInParams->pui8OutBuffer, bCompat);
+
+ if (pvr_copy_to_user(pvOutBuffer,
+ g_outTmpBuf,
+ *pui32BytesCopied) != 0)
+ {
+ HostReleaseMutex(g_pvAPIMutex);
+ goto init_failed;
+ }
+
+ HostReleaseMutex(g_pvAPIMutex);
+ }
+ else
+ {
+ (g_DBGDrivProc[cmd])(in, out, bCompat);
+ }
+
+ if (copy_to_user(pBufferOut, out, pIP->ui32OutBufferSize) != 0)
+ {
+ goto init_failed;
+ }
+
+ HostPageablePageFree((IMG_VOID *)buffer);
+ return 0;
+
+init_failed:
+ HostPageablePageFree((IMG_VOID *)buffer);
+ return -EFAULT;
+}
+
+#if defined(SUPPORT_DRM)
+int dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+long dbgdrv_ioctl(struct file *file, unsigned int ioctlCmd, unsigned long arg)
+#endif
+{
+ return dbgdrv_ioctl_work((IMG_VOID *) arg, IMG_FALSE);
+}
+
+#if defined(SUPPORT_DRM)
+int dbgdrv_ioctl_compat(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+long dbgdrv_ioctl_compat(struct file *file, unsigned int ioctlCmd, unsigned long arg)
+#endif
+{
+ return dbgdrv_ioctl_work((IMG_VOID *) arg, IMG_TRUE);
+}
+
+
+
+EXPORT_SYMBOL(DBGDrvGetServiceTable);
diff --git a/drivers/gpu/rogue/tools/services/debug/include/linuxsrv.h b/drivers/gpu/rogue/tools/services/debug/include/linuxsrv.h
new file mode 100644
index 000000000000..488294789959
--- /dev/null
+++ b/drivers/gpu/rogue/tools/services/debug/include/linuxsrv.h
@@ -0,0 +1,69 @@
+/*************************************************************************/ /*!
+@File
+@Title Module defs for pvr core drivers
+@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 _LINUXSRV_H__
+#define _LINUXSRV_H__
+
+#include "dbgdrvif_srv5.h"
+
+typedef struct tagIOCTL_PACKAGE
+{
+ IMG_UINT32 ui32Cmd; // ioctl command
+ IMG_UINT32 ui32Size; // needs to be correctly set
+ DBG_WIDEPTR pInBuffer; // input data buffer
+ IMG_UINT32 ui32InBufferSize; // size of input data buffer
+ DBG_WIDEPTR pOutBuffer; // output data buffer
+ IMG_UINT32 ui32OutBufferSize; // size of output data buffer
+#if defined(SUPPORT_DRM)
+ IMG_UINT32 ui32PtrSize;
+#endif
+} IOCTL_PACKAGE;
+
+IMG_UINT32 DeviceIoControl(IMG_UINT32 hDevice,
+ IMG_UINT32 ui32ControlCode,
+ IMG_VOID *pInBuffer,
+ IMG_UINT32 ui32InBufferSize,
+ IMG_VOID *pOutBuffer,
+ IMG_UINT32 ui32OutBufferSize,
+ IMG_UINT32 *pui32BytesReturned);
+
+#endif /* _LINUXSRV_H__*/