aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShow Liu <show.liu@linaro.org>2013-12-25 14:14:27 +0800
committerShow Liu <show.liu@linaro.org>2014-04-28 11:37:14 +0800
commit2fdaee08fcbc16be5e6cd984017deffd10533b2f (patch)
tree373571b0de6134a89ab0924685e355fd1e91afcc
parent87b98c1fa196a2d41af2987165b53a921322f3d0 (diff)
downloadlinaro-lsk-2fdaee08fcbc16be5e6cd984017deffd10533b2f.tar.gz
Added Mali T6xx GPU driver
-rw-r--r--drivers/gpu/Makefile2
-rwxr-xr-xdrivers/gpu/arm/Kbuild16
-rwxr-xr-xdrivers/gpu/arm/Kconfig18
-rwxr-xr-xdrivers/gpu/arm/sconscript17
-rwxr-xr-xdrivers/gpu/arm/t6xx/Kbuild16
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/Kbuild17
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/Kconfig170
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/Makefile93
-rw-r--r--drivers/gpu/arm/t6xx/kbase/Module.symvers0
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/docs/Doxyfile125
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/docs/policy_operation_diagram.dot110
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/docs/policy_overview.dot61
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/mali_base_hwconfig.h467
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/mali_base_kernel.h1553
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/mali_base_kernel_sync.h45
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/mali_kbase_config.h856
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/mali_kbase_debug.h226
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/mali_uk.h140
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd.h479
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_compilers.h601
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_pack_pop.h25
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_pack_push.h25
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types.h31
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types_gcc.h90
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types_rvct.h190
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/malisw/mali_malisw.h236
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/malisw/mali_stdtypes.h213
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/platform_dummy/mali_ukk_os.h52
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/sconscript16
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/Kbuild196
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/Makefile35
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/Makefile.kbase16
-rw-r--r--drivers/gpu/arm/t6xx/kbase/src/Module.symvers43
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase.h435
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_10969_workaround.c182
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_10969_workaround.h23
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_8401_workaround.c422
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_8401_workaround.h31
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cache_policy.c39
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cache_policy.h45
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_config.c607
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_context.c227
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cpuprops.c94
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cpuprops.h54
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_debug.c63
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_defs.h787
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_device.c691
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_event.c174
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gator.h31
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops.c314
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops.h52
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops_types.h101
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_hw.c84
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_hw.h39
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_instr.c616
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jd.c1438
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jm.c1274
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jm.h202
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js.c2122
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js.h927
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js_affinity.c407
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js_affinity.h154
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js_ctx_attr.c307
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js_ctx_attr.h156
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js_defs.h474
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js_policy.h765
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js_policy_cfs.c1436
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js_policy_cfs.h165
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_mem.c2034
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_mem.h580
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_mem_alloc.c234
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_mem_alloc.h31
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_mem_lowlevel.c53
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_mem_lowlevel.h109
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_mmu.c1572
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm.c441
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm.h830
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_always_on.c60
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_always_on.h66
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_ca.c173
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_ca.h170
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_ca_fixed.c62
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_ca_fixed.h37
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_coarse_demand.c66
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_coarse_demand.h58
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_demand.c68
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_demand.h55
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_driver.c911
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_metrics.c264
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_metrics_dummy.c37
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_policy.c792
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_pm_policy.h270
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_security.c76
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_security.h50
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_softjobs.c430
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_trace_defs.h226
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_trace_timeline.c227
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_trace_timeline.h366
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_trace_timeline_defs.h130
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_uku.h339
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_utility.c30
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_utility.h35
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_midg_regmap.h468
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/common/mali_timeline.h367
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_kbase_config_linux.c44
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_kbase_config_linux.h41
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_kbase_core_linux.c2921
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_kbase_linux.h79
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_kbase_mem_linux.c724
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_kbase_mem_linux.h60
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_kbase_sync.c190
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_kbase_sync.h81
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_kbase_sync_user.c153
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/linux/mali_linux_trace.h124
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/mali_base_mem_priv.h50
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/mali_base_vendor_specific_func.h24
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/platform/Kbuild20
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/platform/Kconfig23
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/platform/vexpress/Kbuild17
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/platform/vexpress/mali_kbase_config_vexpress.c384
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/platform/vexpress/mali_kbase_cpu_vexpress.c178
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/platform/vexpress/mali_kbase_cpu_vexpress.h26
-rwxr-xr-xdrivers/gpu/arm/t6xx/kbase/src/sconscript103
-rwxr-xr-xdrivers/gpu/arm/t6xx/sconscript16
-rw-r--r--drivers/video/Kconfig42
125 files changed, 38114 insertions, 21 deletions
diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index d8a22c2a579..a759007a95a 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -1,2 +1,2 @@
-obj-y += drm/ vga/
+obj-y += drm/ vga/ arm/
obj-$(CONFIG_TEGRA_HOST1X) += host1x/
diff --git a/drivers/gpu/arm/Kbuild b/drivers/gpu/arm/Kbuild
new file mode 100755
index 00000000000..3351e745f6d
--- /dev/null
+++ b/drivers/gpu/arm/Kbuild
@@ -0,0 +1,16 @@
+#
+# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+obj-$(CONFIG_MALI_T6XX) += t6xx/
diff --git a/drivers/gpu/arm/Kconfig b/drivers/gpu/arm/Kconfig
new file mode 100755
index 00000000000..a36e79d0a15
--- /dev/null
+++ b/drivers/gpu/arm/Kconfig
@@ -0,0 +1,18 @@
+#
+# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+menu "ARM GPU Configuration"
+source "drivers/gpu/arm/t6xx/kbase/Kconfig"
+endmenu
diff --git a/drivers/gpu/arm/sconscript b/drivers/gpu/arm/sconscript
new file mode 100755
index 00000000000..1d5a71ef616
--- /dev/null
+++ b/drivers/gpu/arm/sconscript
@@ -0,0 +1,17 @@
+#
+# (C) COPYRIGHT 2010-2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+
+SConscript('t6xx/sconscript')
diff --git a/drivers/gpu/arm/t6xx/Kbuild b/drivers/gpu/arm/t6xx/Kbuild
new file mode 100755
index 00000000000..2aa0d48beef
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/Kbuild
@@ -0,0 +1,16 @@
+#
+# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+obj-$(CONFIG_MALI_T6XX) += kbase/
diff --git a/drivers/gpu/arm/t6xx/kbase/Kbuild b/drivers/gpu/arm/t6xx/kbase/Kbuild
new file mode 100755
index 00000000000..738aed36ed4
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/Kbuild
@@ -0,0 +1,17 @@
+#
+# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+obj-y += src/
+
diff --git a/drivers/gpu/arm/t6xx/kbase/Kconfig b/drivers/gpu/arm/t6xx/kbase/Kconfig
new file mode 100755
index 00000000000..a40b3547a56
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/Kconfig
@@ -0,0 +1,170 @@
+#
+# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+menuconfig MALI_T6XX
+ tristate "Mali-T6XX support"
+ default n
+ help
+ Enable this option to build support for the ARM Mali-T6XX GPU.
+
+ To compile this driver as a module, choose M here:
+ this will generate a single module, called mali_kbase.
+
+config MALI_GATOR_SUPPORT
+ bool "Streamline Debug support"
+ depends on MALI_T6XX
+ default n
+ help
+ Adds diagnostic support for use with the ARM Streamline Performance Analyzer.
+ You will need the Gator device driver already loaded before loading this driver when enabling
+ Streamline debug support.
+
+config MALI_T6XX_DVFS
+ bool "Enable DVFS"
+ depends on MALI_T6XX
+ default n
+ help
+ Choose this option to enable DVFS on MALI T6XX DDK.
+
+config MALI_T6XX_RT_PM
+ bool "Enable Runtime power management"
+ depends on MALI_T6XX
+ depends on PM_RUNTIME
+ default n
+ help
+ Choose this option to enable runtime power management on MALI T6XX DDK.
+
+config MALI_T6XX_ENABLE_TRACE
+ bool "Enable kbase tracing"
+ depends on MALI_T6XX
+ default n
+ help
+ Enables tracing in kbase. Trace log available through
+ the "mali_trace" debugfs file, when the CONFIG_DEBUG_FS is enabled
+
+config MALI_T6XX_DEBUG_SYS
+ bool "Enable sysfs for mali t6xx"
+ depends on MALI_T6XX && SYSFS
+ default n
+ help
+ Enables sysfs for mali t6xx device. Set/Monitor Mali T6xx Device
+
+# MALI_EXPERT configuration options
+
+menuconfig MALI_EXPERT
+ depends on MALI_T6XX
+ bool "Enable Expert Settings"
+ default n
+ help
+ Enabling this option and modifying the default settings may produce a driver with performance or
+ other limitations.
+
+config MALI_DEBUG_SHADER_SPLIT_FS
+ bool "Allow mapping of shader cores via sysfs"
+ depends on MALI_T6XX && MALI_T6XX_DEBUG_SYS && MALI_EXPERT
+ default n
+ help
+ Select this option to provide a sysfs entry for runtime configuration of shader
+ core affinity masks.
+
+config MALI_PLATFORM_FAKE
+ bool "Enable fake platform device support"
+ depends on MALI_T6XX && MALI_EXPERT
+ default n
+ help
+ When you start to work with the Mali-T600 Series device driver the platform-specific code of
+ the Linux kernel for your platform may not be complete. In this situation the kernel device driver
+ supports creating the platform device outside of the Linux platform-specific code.
+ Enable this option if would like to use a platform device configuration from within the device driver.
+
+choice
+ prompt "Platform configuration"
+ depends on MALI_T6XX && (MALI_PLATFORM_FAKE && MALI_EXPERT)
+ default MALI_PLATFORM_VEXPRESS
+ help
+ Select the SOC platform that contains a Mali-T6XX
+
+config MALI_PLATFORM_VEXPRESS
+ depends on ARCH_VEXPRESS && (ARCH_VEXPRESS_CA9X4 || ARCH_VEXPRESS_CA15X4)
+ bool "Versatile Express"
+config MALI_PLATFORM_GOLDFISH
+ depends on ARCH_GOLDFISH
+ bool "Android Goldfish virtual CPU"
+config MALI_PLATFORM_PBX
+ depends on ARCH_REALVIEW && REALVIEW_EB_A9MP && MACH_REALVIEW_PBX
+ bool "Realview PBX-A9"
+config MALI_PLATFORM_THIRDPARTY
+ bool "Third Party Platform"
+endchoice
+
+config MALI_PLATFORM_THIRDPARTY_NAME
+ depends on MALI_T6XX && MALI_PLATFORM_THIRDPARTY && (MALI_PLATFORM_FAKE && MALI_EXPERT)
+ string "Third party platform name"
+ help
+ Enter the name of a third party platform that is supported. The third part configuration
+ file must be in kbase/src/linux/config/tpip/mali_kbase_config_xxx.c where xxx is the name
+ specified here.
+
+config MALI_DEBUG
+ bool "Debug build"
+ depends on MALI_T6XX && MALI_EXPERT
+ default n
+ help
+ Select this option for increased checking and reporting of errors.
+
+config MALI_NO_MALI
+ bool "No Mali"
+ depends on MALI_T6XX && MALI_EXPERT
+ default n
+ help
+ This can be used to test the driver in a simulated environment
+ whereby the hardware is not physically present. If the hardware is physically
+ present it will not be used. This can be used to test the majority of the
+ driver without needing actual hardware or for software benchmarking.
+ All calls to the simulated hardware will complete immediately as if the hardware
+ completed the task.
+
+config MALI_ERROR_INJECT
+ bool "Error injection"
+ depends on MALI_T6XX && MALI_EXPERT && MALI_NO_MALI
+ default n
+ help
+ Enables insertion of errors to test module failure and recovery mechanisms.
+
+config MALI_TRACE_TIMELINE
+ bool "Timeline tracing"
+ depends on MALI_T6XX && MALI_EXPERT
+ default n
+ help
+ Enables timeline tracing through the kernel tracepoint system.
+
+config MALI_SYSTEM_TRACE
+ bool "Enable system event tracing support"
+ depends on MALI_T6XX && MALI_EXPERT
+ default n
+ help
+ Choose this option to enable system trace events for each
+ kbase event. This is typically used for debugging but has
+ minimal overhead when not in use. Enable only if you know what
+ you are doing.
+
+config MALI_GPU_TRACEPOINTS
+ bool "Enable GPU tracepoints"
+ depends on MALI_T6XX && ANDROID
+ select GPU_TRACEPOINTS
+ help
+ Enables GPU tracepoints using Android trace event definitions.
+
+source "drivers/gpu/arm/t6xx/kbase/src/platform/Kconfig"
diff --git a/drivers/gpu/arm/t6xx/kbase/Makefile b/drivers/gpu/arm/t6xx/kbase/Makefile
new file mode 100755
index 00000000000..3a28e435d97
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/Makefile
@@ -0,0 +1,93 @@
+#
+# (C) COPYRIGHT 2011-2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+# Defaults
+export PLATFORM?=dummy
+export MALI_ANDROID?=0
+export MALI_UNIT_TEST?=0
+export MALI_KERNEL_TEST_API?=0
+export MALI_MOCK_TEST?=0
+export MALI_INSTRUMENTATION_LEVEL?=0
+export MALI_CUSTOMER_RELEASE?=1
+export MALI_COVERAGE?=0
+export CONFIG_MALI_NO_MALI?=n
+export CONFIG_UMP?=m
+export CONFIG_MALI_DEBUG?=y
+export CONFIG_MALI_ERROR_INJECT?=n
+export CONFIG_MALI_PLATFORM_FAKE?=y
+export CONFIG_MALI_PLATFORM_VEXPRESS?=y
+export CONFIG_MALI_GATOR_SUPPORT?=y
+export CONFIG_MALI_T6XX?=m
+export CONFIG_KDS?=m
+export CONFIG_MALI_DEBUG_SHADER_SPLIT_FS?=n
+export CONFIG_MALI_TRACE_TIMELINE?=n
+
+ifeq ($(CONFIG_MALI_NO_MALI),y)
+ SCONS_CFLAGS+=-DCONFIG_MALI_NO_MALI
+endif
+ifeq ($(CONFIG_UMP),m)
+ SCONS_CFLAGS+=-DCONFIG_UMP
+endif
+ifeq ($(CONFIG_MALI_DEBUG),y)
+ SCONS_CFLAGS+=-DCONFIG_MALI_DEBUG
+endif
+ifeq ($(CONFIG_MALI_DEBUG_SHADER_SPLIT_FS),y)
+ SCONS_CFLAGS+=-DCONFIG_MALI_DEBUG_SHADER_SPLIT_FS
+endif
+ifeq ($(CONFIG_MALI_ERROR_INJECT),y)
+ SCONS_CFLAGS+=-DCONFIG_MALI_ERROR_INJECT
+endif
+ifeq ($(CONFIG_MALI_PLATFORM_FAKE),y)
+ SCONS_CFLAGS+=-DCONFIG_MALI_PLATFORM_FAKE
+endif
+ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS),y)
+ SCONS_CFLAGS+=-DCONFIG_MALI_PLATFORM_VEXPRESS
+endif
+ifeq ($(CONFIG_MALI_GATOR_SUPPORT),y)
+ SCONS_CFLAGS+=-DCONFIG_MALI_GATOR_SUPPORT
+endif
+ifeq ($(CONFIG_KDS),m)
+ SCONS_CFLAGS+=-DCONFIG_KDS
+endif
+ifeq ($(CONFIG_MALI_TRACE_TIMELINE),y)
+ SCONS_CFLAGS+=-DCONFIG_MALI_TRACE_TIMELINE
+endif
+export SCONS_CFLAGS
+
+KDIR ?= /lib/modules/$(shell uname -r)/build
+
+# MROOT defines root of kernel device driver components
+# This makefile may reside in container directory of the kernel device driver components or within the
+# 'kbase' kernel driver component itself, so we set MROOT accordingly.
+#
+ifeq ($(wildcard $(PWD)/kbase/src/Makefile),)
+MROOT=$(PWD)/../../../../../..
+else
+MROOT=$(PWD)
+endif
+
+KBASE_PATH=$(MROOT)/kernel/drivers/gpu/arm/t6xx/kbase
+UMP_PATH=$(MROOT)/kernel/drivers/base/ump
+KDS_PATH=$(MROOT)/kernel/drivers/base/kds
+
+all:
+ $(MAKE) -C $(KDS_PATH)
+ $(MAKE) -C $(UMP_PATH)/src
+ $(MAKE) -C $(KBASE_PATH)/src
+
+clean:
+ $(MAKE) -C $(KDS_PATH) clean
+ $(MAKE) -C $(UMP_PATH)/src clean
+ $(MAKE) -C $(KBASE_PATH)/src clean
diff --git a/drivers/gpu/arm/t6xx/kbase/Module.symvers b/drivers/gpu/arm/t6xx/kbase/Module.symvers
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/Module.symvers
diff --git a/drivers/gpu/arm/t6xx/kbase/docs/Doxyfile b/drivers/gpu/arm/t6xx/kbase/docs/Doxyfile
new file mode 100755
index 00000000000..8102b7eea25
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/docs/Doxyfile
@@ -0,0 +1,125 @@
+#
+# (C) COPYRIGHT 2011-2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+##############################################################################
+
+# This file contains per-module Doxygen configuration. Please do not add
+# extra settings to this file without consulting all stakeholders, as they
+# may cause override project-wide settings.
+#
+# Additionally, when defining aliases, macros, sections etc, use the module
+# name as a prefix e.g. gles_my_alias.
+
+##############################################################################
+
+@INCLUDE = ../../bldsys/Doxyfile_common
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT += ../../kernel/drivers/gpu/arm/t6xx/kbase/src/common/ ../../kernel/drivers/gpu/arm/t6xx/kbase/mali_base_kernel.h ../../kernel/drivers/gpu/arm/t6xx/kbase/src/mali_base_mem_priv.h ../../kernel/drivers/gpu/arm/t6xx/kbase/mali_kbase_config.h
+
+##############################################################################
+# Everything below here is optional, and in most cases not required
+##############################################################################
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES +=
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS +=
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS +=
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE +=
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS +=
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS +=
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH +=
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH +=
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH +=
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED +=
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED +=
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS += ../../kernel/drivers/gpu/arm/t6xx/kbase/docs
+
diff --git a/drivers/gpu/arm/t6xx/kbase/docs/policy_operation_diagram.dot b/drivers/gpu/arm/t6xx/kbase/docs/policy_operation_diagram.dot
new file mode 100755
index 00000000000..17e13e53e64
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/docs/policy_operation_diagram.dot
@@ -0,0 +1,110 @@
+/*
+ *
+ * (C) COPYRIGHT 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+digraph policy_objects_diagram {
+ rankdir=LR;
+ size="12,8";
+ compound=true;
+
+ node [ shape = box ];
+
+ subgraph cluster_policy_queues {
+ low_queue [ shape=record label = "LowP | {<ql>ctx_lo | ... | <qm>ctx_i | ... | <qr>ctx_hi}" ];
+ queues_middle_sep [ label="" shape=plaintext width=0 height=0 ];
+
+ rt_queue [ shape=record label = "RT | {<ql>ctx_lo | ... | <qm>ctx_j | ... | <qr>ctx_hi}" ];
+
+ label = "Policy's Queue(s)";
+ }
+
+ call_enqueue [ shape=plaintext label="enqueue_ctx()" ];
+
+ {
+ rank=same;
+ ordering=out;
+ call_dequeue [ shape=plaintext label="dequeue_head_ctx()\n+ runpool_add_ctx()" ];
+ call_ctxfinish [ shape=plaintext label="runpool_remove_ctx()" ];
+
+ call_ctxdone [ shape=plaintext label="don't requeue;\n/* ctx has no more jobs */" ];
+ }
+
+ subgraph cluster_runpool {
+
+ as0 [ width=2 height = 0.25 label="AS0: Job_1, ..., Job_n" ];
+ as1 [ width=2 height = 0.25 label="AS1: Job_1, ..., Job_m" ];
+ as2 [ width=2 height = 0.25 label="AS2: Job_1, ..., Job_p" ];
+ as3 [ width=2 height = 0.25 label="AS3: Job_1, ..., Job_q" ];
+
+ label = "Policy's Run Pool";
+ }
+
+ {
+ rank=same;
+ call_jdequeue [ shape=plaintext label="dequeue_job()" ];
+ sstop_dotfixup [ shape=plaintext label="" width=0 height=0 ];
+ }
+
+ {
+ rank=same;
+ ordering=out;
+ sstop [ shape=ellipse label="SS-Timer expires" ]
+ jobslots [ shape=record label="Jobslots: | <0>js[0] | <1>js[1] | <2>js[2]" ];
+
+ irq [ label="IRQ" shape=ellipse ];
+
+ job_finish [ shape=plaintext label="don't requeue;\n/* job done */" ];
+ }
+
+ hstop [ shape=ellipse label="HS-Timer expires" ]
+
+ /*
+ * Edges
+ */
+
+ call_enqueue -> queues_middle_sep [ lhead=cluster_policy_queues ];
+
+ low_queue:qr -> call_dequeue:w;
+ rt_queue:qr -> call_dequeue:w;
+
+ call_dequeue -> as1 [lhead=cluster_runpool];
+
+ as1->call_jdequeue [ltail=cluster_runpool];
+ call_jdequeue->jobslots:0;
+ call_jdequeue->sstop_dotfixup [ arrowhead=none];
+ sstop_dotfixup->sstop [label="Spawn SS-Timer"];
+ sstop->jobslots [label="SoftStop"];
+ sstop->hstop [label="Spawn HS-Timer"];
+ hstop->jobslots:ne [label="HardStop"];
+
+
+ as3->call_ctxfinish:ne [ ltail=cluster_runpool ];
+ call_ctxfinish:sw->rt_queue:qm [ lhead=cluster_policy_queues label="enqueue_ctx()\n/* ctx still has jobs */" ];
+
+ call_ctxfinish->call_ctxdone [constraint=false];
+
+ call_ctxdone->call_enqueue [weight=0.1 labeldistance=20.0 labelangle=0.0 taillabel="Job submitted to the ctx" style=dotted constraint=false];
+
+
+ {
+ jobslots->irq [constraint=false];
+
+ irq->job_finish [constraint=false];
+ }
+
+ irq->as2 [lhead=cluster_runpool label="requeue_job()\n/* timeslice expired */" ];
+
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/docs/policy_overview.dot b/drivers/gpu/arm/t6xx/kbase/docs/policy_overview.dot
new file mode 100755
index 00000000000..d22d58122c7
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/docs/policy_overview.dot
@@ -0,0 +1,61 @@
+/*
+ *
+ * (C) COPYRIGHT 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+digraph policy_objects_diagram {
+ rankdir=LR
+ size="6,6"
+ compound=true;
+
+ node [ shape = box ];
+
+ call_enqueue [ shape=plaintext label="enqueue ctx" ];
+
+
+ policy_queue [ label="Policy's Queue" ];
+
+ {
+ rank=same;
+ runpool [ label="Policy's Run Pool" ];
+
+ ctx_finish [ label="ctx finished" ];
+ }
+
+ {
+ rank=same;
+ jobslots [ shape=record label="Jobslots: | <0>js[0] | <1>js[1] | <2>js[2]" ];
+
+ job_finish [ label="Job finished" ];
+ }
+
+
+
+ /*
+ * Edges
+ */
+
+ call_enqueue -> policy_queue;
+
+ policy_queue->runpool [label="dequeue ctx" weight=0.1];
+ runpool->policy_queue [label="requeue ctx" weight=0.1];
+
+ runpool->ctx_finish [ style=dotted ];
+
+ runpool->jobslots [label="dequeue job" weight=0.1];
+ jobslots->runpool [label="requeue job" weight=0.1];
+
+ jobslots->job_finish [ style=dotted ];
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/mali_base_hwconfig.h b/drivers/gpu/arm/t6xx/kbase/mali_base_hwconfig.h
new file mode 100755
index 00000000000..1efa54020f6
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/mali_base_hwconfig.h
@@ -0,0 +1,467 @@
+/*
+ *
+ * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file
+ * Software workarounds configuration for Hardware issues.
+ */
+
+#ifndef _BASE_HWCONFIG_H_
+#define _BASE_HWCONFIG_H_
+
+#include <malisw/mali_malisw.h>
+
+/**
+ * List of all workarounds.
+ *
+ */
+
+typedef enum base_hw_issue {
+
+ /* The current version of the model doesn't support Soft-Stop */
+ BASE_HW_ISSUE_5736,
+
+ /* Need way to guarantee that all previously-translated memory accesses are commited */
+ BASE_HW_ISSUE_6367,
+
+ /* Unaligned load stores crossing 128 bit boundaries will fail */
+ BASE_HW_ISSUE_6402,
+
+ /* On job complete with non-done the cache is not flushed */
+ BASE_HW_ISSUE_6787,
+
+ /* WLS allocation does not respect the Instances field in the Thread Storage Descriptor */
+ BASE_HW_ISSUE_7027,
+
+ /* The clamp integer coordinate flag bit of the sampler descriptor is reserved */
+ BASE_HW_ISSUE_7144,
+
+ /* CRC computation can only happen when the bits per pixel is less than or equal to 32 */
+ BASE_HW_ISSUE_7393,
+
+ /* Write of PRFCNT_CONFIG_MODE_MANUAL to PRFCNT_CONFIG causes a instrumentation dump if
+ PRFCNT_TILER_EN is enabled */
+ BASE_HW_ISSUE_8186,
+
+ /* TIB: Reports faults from a vtile which has not yet been allocated */
+ BASE_HW_ISSUE_8245,
+
+ /* WLMA memory goes wrong when run on shader cores other than core 0. */
+ BASE_HW_ISSUE_8250,
+
+ /* Hierz doesn't work when stenciling is enabled */
+ BASE_HW_ISSUE_8260,
+
+ /* Livelock in L0 icache */
+ BASE_HW_ISSUE_8280,
+
+ /* uTLB deadlock could occur when writing to an invalid page at the same time as
+ * access to a valid page in the same uTLB cache line ( == 4 PTEs == 16K block of mapping) */
+ BASE_HW_ISSUE_8316,
+
+ /* TLS base address mismatch, must stay below 1MB TLS */
+ BASE_HW_ISSUE_8381,
+
+ /* HT: TERMINATE for RUN command ignored if previous LOAD_DESCRIPTOR is still executing */
+ BASE_HW_ISSUE_8394,
+
+ /* CSE : Sends a TERMINATED response for a task that should not be terminated */
+ /* (Note that PRLAM-8379 also uses this workaround) */
+ BASE_HW_ISSUE_8401,
+
+ /* Repeatedly Soft-stopping a job chain consisting of (Vertex Shader, Cache Flush, Tiler)
+ * jobs causes 0x58 error on tiler job. */
+ BASE_HW_ISSUE_8408,
+
+ /* Disable the Pause Buffer in the LS pipe. */
+ BASE_HW_ISSUE_8443,
+
+ /* Stencil test enable 1->0 sticks */
+ BASE_HW_ISSUE_8456,
+
+ /* Tiler heap issue using FBOs or multiple processes using the tiler simultaneously */
+ /* (Note that PRLAM-9049 also uses this work-around) */
+ BASE_HW_ISSUE_8564,
+
+ /* Livelock issue using atomic instructions (particularly when using atomic_cmpxchg as a spinlock) */
+ BASE_HW_ISSUE_8791,
+
+ /* Fused jobs are not supported (for various reasons) */
+ /* Jobs with relaxed dependencies do not support soft-stop */
+ /* (Note that PRLAM-8803, PRLAM-8393, PRLAM-8559, PRLAM-8601 & PRLAM-8607 all use this work-around) */
+ BASE_HW_ISSUE_8803,
+
+ /* Blend shader output is wrong for certain formats */
+ BASE_HW_ISSUE_8833,
+
+ /* Occlusion queries can create false 0 result in boolean and counter modes */
+ BASE_HW_ISSUE_8879,
+
+ /* Output has half intensity with blend shaders enabled on 8xMSAA. */
+ BASE_HW_ISSUE_8896,
+
+ /* 8xMSAA does not work with CRC */
+ BASE_HW_ISSUE_8975,
+
+ /* Boolean occlusion queries don't work properly due to sdc issue. */
+ BASE_HW_ISSUE_8986,
+
+ /* Change in RMUs in use causes problems related with the core's SDC */
+ BASE_HW_ISSUE_8987,
+
+ /* Occlusion query result is not updated if color writes are disabled. */
+ BASE_HW_ISSUE_9010,
+
+ /* Problem with number of work registers in the RSD if set to 0 */
+ BASE_HW_ISSUE_9275,
+
+ /* Incorrect coverage mask for 8xMSAA */
+ BASE_HW_ISSUE_9423,
+
+ /* Compute endpoint has a 4-deep queue of tasks, meaning a soft stop won't complete until all 4 tasks have completed */
+ BASE_HW_ISSUE_9435,
+
+ /* HT: Tiler returns TERMINATED for command that hasn't been terminated */
+ BASE_HW_ISSUE_9510,
+
+ /* Occasionally the GPU will issue multiple page faults for the same address before the MMU page table has been read by the GPU */
+ BASE_HW_ISSUE_9630,
+
+ /* Must clear the 64 byte private state of the tiler information */
+ BASE_HW_ISSUE_10127,
+
+ /* RA DCD load request to SDC returns invalid load ignore causing colour buffer mismatch */
+ BASE_HW_ISSUE_10327,
+
+ /* Occlusion query result may be updated prematurely when fragment shader alters coverage */
+ BASE_HW_ISSUE_10410,
+
+ /* MAG / MIN filter selection happens after image descriptor clamps were applied */
+ BASE_HW_ISSUE_10472,
+
+ /* GPU interprets sampler and image descriptor pointer array sizes as one bigger than they are defined in midg structures */
+ BASE_HW_ISSUE_10487,
+
+ /* LD_SPECIAL instruction reads incorrect RAW tile buffer value when internal tib format is R10G10B10A2 */
+ BASE_HW_ISSUE_10632,
+
+ /* MMU TLB invalidation hazards */
+ BASE_HW_ISSUE_10649,
+
+ /* Missing cache flush in multi core-group configuration */
+ BASE_HW_ISSUE_10676,
+
+ /* Indexed format 95 cannot be used with a component swizzle of "set to 1" when sampled as integer texture */
+ BASE_HW_ISSUE_10682,
+
+ /* sometimes HW doesn't invalidate cached VPDs when it has to */
+ BASE_HW_ISSUE_10684,
+
+ /* Soft-stopping fragment jobs might fail with TILE_RANGE_FAULT */
+ BASE_HW_ISSUE_10817,
+
+ /* Intermittent missing interrupt on job completion */
+ BASE_HW_ISSUE_10883,
+
+ /* Depth bounds incorrectly normalized in hierz depth bounds test */
+ BASE_HW_ISSUE_10931,
+
+ /* Soft-stopped fragment shader job can restart with out-of-bound restart index */
+ BASE_HW_ISSUE_10969,
+
+ /* The BASE_HW_ISSUE_END value must be the last issue listed in this enumeration
+ * and must be the last value in each array that contains the list of workarounds
+ * for a particular HW version.
+ */
+ BASE_HW_ISSUE_END
+} base_hw_issue;
+
+/**
+ * Workarounds configuration for each HW revision
+ */
+/* Mali T60x r0p0-15dev0 - 2011-W39-stable-9 */
+static const base_hw_issue base_hw_issues_t60x_r0p0_15dev0[] = {
+ BASE_HW_ISSUE_6367,
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_6787,
+ BASE_HW_ISSUE_7027,
+ BASE_HW_ISSUE_7144,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8186,
+ BASE_HW_ISSUE_8245,
+ BASE_HW_ISSUE_8250,
+ BASE_HW_ISSUE_8260,
+ BASE_HW_ISSUE_8280,
+ BASE_HW_ISSUE_8316,
+ BASE_HW_ISSUE_8381,
+ BASE_HW_ISSUE_8394,
+ BASE_HW_ISSUE_8401,
+ BASE_HW_ISSUE_8408,
+ BASE_HW_ISSUE_8443,
+ BASE_HW_ISSUE_8456,
+ BASE_HW_ISSUE_8564,
+ BASE_HW_ISSUE_8791,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_8833,
+ BASE_HW_ISSUE_8896,
+ BASE_HW_ISSUE_8975,
+ BASE_HW_ISSUE_8986,
+ BASE_HW_ISSUE_8987,
+ BASE_HW_ISSUE_9010,
+ BASE_HW_ISSUE_9275,
+ BASE_HW_ISSUE_9423,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_9510,
+ BASE_HW_ISSUE_9630,
+ BASE_HW_ISSUE_10410,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10487,
+ BASE_HW_ISSUE_10632,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10676,
+ BASE_HW_ISSUE_10682,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ BASE_HW_ISSUE_10969,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T60x r0p0-00rel0 - 2011-W46-stable-13c */
+static const base_hw_issue base_hw_issues_t60x_r0p0_eac[] = {
+ BASE_HW_ISSUE_6367,
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_6787,
+ BASE_HW_ISSUE_7027,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8408,
+ BASE_HW_ISSUE_8564,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_8975,
+ BASE_HW_ISSUE_9010,
+ BASE_HW_ISSUE_9275,
+ BASE_HW_ISSUE_9423,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_9510,
+ BASE_HW_ISSUE_10410,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10487,
+ BASE_HW_ISSUE_10632,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10676,
+ BASE_HW_ISSUE_10682,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ BASE_HW_ISSUE_10969,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T60x r0p1 */
+static const base_hw_issue base_hw_issues_t60x_r0p1[] = {
+ BASE_HW_ISSUE_6367,
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_6787,
+ BASE_HW_ISSUE_7027,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8408,
+ BASE_HW_ISSUE_8564,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_8975,
+ BASE_HW_ISSUE_9010,
+ BASE_HW_ISSUE_9275,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_9510,
+ BASE_HW_ISSUE_10410,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10487,
+ BASE_HW_ISSUE_10632,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10676,
+ BASE_HW_ISSUE_10682,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T65x r0p1 */
+static const base_hw_issue base_hw_issues_t65x_r0p1[] = {
+ BASE_HW_ISSUE_6367,
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_6787,
+ BASE_HW_ISSUE_7027,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8408,
+ BASE_HW_ISSUE_8564,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_9010,
+ BASE_HW_ISSUE_9275,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_9510,
+ BASE_HW_ISSUE_10410,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10487,
+ BASE_HW_ISSUE_10632,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10676,
+ BASE_HW_ISSUE_10682,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T62x r0p0 */
+static const base_hw_issue base_hw_issues_t62x_r0p0[] = {
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_10127,
+ BASE_HW_ISSUE_10327,
+ BASE_HW_ISSUE_10410,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10487,
+ BASE_HW_ISSUE_10632,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10676,
+ BASE_HW_ISSUE_10682,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10817,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T67x r0p0 */
+static const base_hw_issue base_hw_issues_t67x_r0p0[] = {
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_10127,
+ BASE_HW_ISSUE_10327,
+ BASE_HW_ISSUE_10410,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10487,
+ BASE_HW_ISSUE_10632,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10676,
+ BASE_HW_ISSUE_10682,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10817,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T62x r0p1 */
+static const base_hw_issue base_hw_issues_t62x_r0p1[] = {
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_10127,
+ BASE_HW_ISSUE_10327,
+ BASE_HW_ISSUE_10410,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10487,
+ BASE_HW_ISSUE_10632,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10676,
+ BASE_HW_ISSUE_10682,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10817,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T67x r0p1 */
+static const base_hw_issue base_hw_issues_t67x_r0p1[] = {
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_10127,
+ BASE_HW_ISSUE_10327,
+ BASE_HW_ISSUE_10410,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10487,
+ BASE_HW_ISSUE_10632,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10676,
+ BASE_HW_ISSUE_10682,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10817,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T62x r1p0 */
+static const base_hw_issue base_hw_issues_t62x_r1p0[] = {
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T67x r1p0 */
+static const base_hw_issue base_hw_issues_t67x_r1p0[] = {
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_7393,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_10472,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10684,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+/* Mali T75x r0p0 */
+static const base_hw_issue base_hw_issues_t75x_r0p0[] = {
+ BASE_HW_ISSUE_6402,
+ BASE_HW_ISSUE_8803,
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_10649,
+ BASE_HW_ISSUE_10883,
+ BASE_HW_ISSUE_10931,
+ /* List of hardware issues must end with BASE_HW_ISSUE_END */
+ BASE_HW_ISSUE_END
+};
+
+#endif /* _BASE_HWCONFIG_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/mali_base_kernel.h b/drivers/gpu/arm/t6xx/kbase/mali_base_kernel.h
new file mode 100755
index 00000000000..200fde00a57
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/mali_base_kernel.h
@@ -0,0 +1,1553 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file
+ * Base structures shared with the kernel.
+ */
+
+#ifndef _BASE_KERNEL_H_
+#define _BASE_KERNEL_H_
+
+/* For now we support the legacy API as well as the new API */
+#define BASE_LEGACY_JD_API 1
+
+typedef mali_addr64 base_mem_handle;
+
+#include <kbase/src/mali_base_mem_priv.h>
+
+/*
+ * Dependency stuff, keep it private for now. May want to expose it if
+ * we decide to make the number of semaphores a configurable
+ * option.
+ */
+#define BASE_JD_ATOM_COUNT 256
+
+#define BASEP_JD_SEM_PER_WORD_LOG2 5
+#define BASEP_JD_SEM_PER_WORD (1 << BASEP_JD_SEM_PER_WORD_LOG2)
+#define BASEP_JD_SEM_WORD_NR(x) ((x) >> BASEP_JD_SEM_PER_WORD_LOG2)
+#define BASEP_JD_SEM_MASK_IN_WORD(x) (1 << ((x) & (BASEP_JD_SEM_PER_WORD - 1)))
+#define BASEP_JD_SEM_ARRAY_SIZE BASEP_JD_SEM_WORD_NR(BASE_JD_ATOM_COUNT)
+
+#if BASE_LEGACY_JD_API
+/* Size of the ring buffer */
+#define BASEP_JCTX_RB_NRPAGES 4
+#endif /* BASE_LEGACY_JD_API */
+
+#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 3
+
+#define BASE_MAX_COHERENT_GROUPS 16
+
+#if defined CDBG_ASSERT
+#define LOCAL_ASSERT CDBG_ASSERT
+#elif defined KBASE_DEBUG_ASSERT
+#define LOCAL_ASSERT KBASE_DEBUG_ASSERT
+#else
+#error assert macro not defined!
+#endif
+
+#if defined PAGE_MASK
+#define LOCAL_PAGE_LSB ~PAGE_MASK
+#else
+#include <osu/mali_osu.h>
+
+#if defined OSU_CONFIG_CPU_PAGE_SIZE_LOG2
+#define LOCAL_PAGE_LSB ((1ul << OSU_CONFIG_CPU_PAGE_SIZE_LOG2) - 1)
+#else
+#error Failed to find page size
+#endif
+#endif
+
+/** 32/64-bit neutral way to represent pointers */
+typedef union kbase_pointer {
+ void *value; /**< client should store their pointers here */
+ u32 compat_value; /**< 64-bit kernels should fetch value here when handling 32-bit clients */
+ u64 sizer; /**< Force 64-bit storage for all clients regardless */
+} kbase_pointer;
+
+/**
+ * @addtogroup base_user_api User-side Base APIs
+ * @{
+ */
+
+/**
+ * @addtogroup base_user_api_memory User-side Base Memory APIs
+ * @{
+ */
+
+/**
+ * @brief Memory allocation, access/hint flags
+ *
+ * A combination of MEM_PROT/MEM_HINT flags must be passed to each allocator
+ * in order to determine the best cache policy. Some combinations are
+ * of course invalid (eg @c MEM_PROT_CPU_WR | @c MEM_HINT_CPU_RD),
+ * which defines a @a write-only region on the CPU side, which is
+ * heavily read by the CPU...
+ * Other flags are only meaningful to a particular allocator.
+ * More flags can be added to this list, as long as they don't clash
+ * (see ::BASE_MEM_FLAGS_NR_BITS for the number of the first free bit).
+ */
+typedef u32 base_mem_alloc_flags;
+
+/**
+ * @brief Memory allocation, access/hint flags
+ *
+ * See ::base_mem_alloc_flags.
+ *
+ */
+enum {
+ BASE_MEM_PROT_CPU_RD = (1U << 0), /**< Read access CPU side */
+ BASE_MEM_PROT_CPU_WR = (1U << 1), /**< Write access CPU side */
+ BASE_MEM_PROT_GPU_RD = (1U << 2), /**< Read access GPU side */
+ BASE_MEM_PROT_GPU_WR = (1U << 3), /**< Write access GPU side */
+ BASE_MEM_PROT_GPU_EX = (1U << 4), /**< Execute allowed on the GPU side */
+
+ /* Note that the HINT flags are obsolete now. If you want the memory
+ * to be cached on the CPU please use the BASE_MEM_CACHED_CPU flag
+ */
+ BASE_MEM_HINT_CPU_RD = (1U << 5), /**< Heavily read CPU side - OBSOLETE */
+ BASE_MEM_HINT_CPU_WR = (1U << 6), /**< Heavily written CPU side - OBSOLETE */
+ BASE_MEM_HINT_GPU_RD = (1U << 7), /**< Heavily read GPU side - OBSOLETE */
+ BASE_MEM_HINT_GPU_WR = (1U << 8), /**< Heavily written GPU side - OBSOLETE */
+
+ BASEP_MEM_GROWABLE = (1U << 9), /**< Growable memory. This is a private flag that is set automatically. Not valid for PMEM. */
+ BASE_MEM_GROW_ON_GPF = (1U << 10), /**< Grow backing store on GPU Page Fault */
+
+ BASE_MEM_COHERENT_SYSTEM = (1U << 11), /**< Page coherence Outer shareable */
+ BASE_MEM_COHERENT_LOCAL = (1U << 12), /**< Page coherence Inner shareable */
+ BASE_MEM_CACHED_CPU = (1U << 13) /**< Should be cached on the CPU */
+};
+
+/**
+ * @brief Memory types supported by @a base_tmem_import
+ *
+ * Each type defines what the supported handle type is.
+ *
+ * If any new type is added here ARM must be contacted
+ * to allocate a numeric value for it.
+ * Do not just add a new type without synchronizing with ARM
+ * as future releases from ARM might include other new types
+ * which could clash with your custom types.
+ */
+typedef enum base_tmem_import_type {
+ BASE_TMEM_IMPORT_TYPE_INVALID = 0,
+ /** UMP import. Handle type is ump_secure_id. */
+ BASE_TMEM_IMPORT_TYPE_UMP = 1,
+ /** UMM import. Handle type is a file descriptor (int) */
+ BASE_TMEM_IMPORT_TYPE_UMM = 2
+} base_tmem_import_type;
+
+/**
+ * @brief Number of bits used as flags for base memory management
+ *
+ * Must be kept in sync with the ::base_mem_alloc_flags flags
+ */
+#define BASE_MEM_FLAGS_NR_BITS 14
+
+/**
+ * @brief Result codes of changing the size of the backing store allocated to a tmem region
+ */
+typedef enum base_backing_threshold_status {
+ BASE_BACKING_THRESHOLD_OK = 0, /**< Resize successful */
+ BASE_BACKING_THRESHOLD_ERROR_NOT_GROWABLE = -1, /**< Not a growable tmem object */
+ BASE_BACKING_THRESHOLD_ERROR_OOM = -2, /**< Increase failed due to an out-of-memory condition */
+ BASE_BACKING_THRESHOLD_ERROR_MAPPED = -3, /**< Resize attempted on buffer while it was mapped, which is not permitted */
+ BASE_BACKING_THRESHOLD_ERROR_INVALID_ARGUMENTS = -4 /**< Invalid arguments (not tmem, illegal size request, etc.) */
+} base_backing_threshold_status;
+
+/**
+ * @addtogroup base_user_api_memory_defered User-side Base Defered Memory Coherency APIs
+ * @{
+ */
+
+/**
+ * @brief a basic memory operation (sync-set).
+ *
+ * The content of this structure is private, and should only be used
+ * by the accessors.
+ */
+typedef struct base_syncset {
+ basep_syncset basep_sset;
+} base_syncset;
+
+/** @} end group base_user_api_memory_defered */
+
+/**
+ * Handle to represent imported memory object.
+ * Simple opague handle to imported memory, can't be used
+ * with anything but base_external_resource_init to bind to an atom.
+ */
+typedef struct base_import_handle {
+ struct {
+ mali_addr64 handle;
+ } basep;
+} base_import_handle;
+
+/** @} end group base_user_api_memory */
+
+/**
+ * @addtogroup base_user_api_job_dispatch User-side Base Job Dispatcher APIs
+ * @{
+ */
+
+typedef int platform_fence_type;
+#define INVALID_PLATFORM_FENCE ((platform_fence_type)-1)
+
+/**
+ * Base stream handle.
+ *
+ * References an underlying base stream object.
+ */
+typedef struct base_stream {
+ struct {
+ int fd;
+ } basep;
+} base_stream;
+
+/**
+ * Base fence handle.
+ *
+ * References an underlying base fence object.
+ */
+typedef struct base_fence {
+ struct {
+ int fd;
+ int stream_fd;
+ } basep;
+} base_fence;
+
+#if BASE_LEGACY_JD_API
+/**
+ * @brief A pre- or post- dual dependency.
+ *
+ * This structure is used to express either
+ * @li a single or dual pre-dependency (a job depending on one or two
+ * other jobs),
+ * @li a single or dual post-dependency (a job resolving a dependency
+ * for one or two other jobs).
+ *
+ * The dependency itself is specified as a u8, where 0 indicates no
+ * dependency. A single dependency is expressed by having one of the
+ * dependencies set to 0.
+ */
+typedef struct base_jd_dep {
+ u8 dep[2]; /**< pre/post dependencies */
+} base_jd_dep;
+#endif /* BASE_LEGACY_JD_API */
+
+/**
+ * @brief Per-job data
+ *
+ * This structure is used to store per-job data, and is completly unused
+ * by the Base driver. It can be used to store things such as callback
+ * function pointer, data to handle job completion. It is guaranteed to be
+ * untouched by the Base driver.
+ */
+typedef struct base_jd_udata {
+ u64 blob[2]; /**< per-job data array */
+} base_jd_udata;
+
+/**
+ * @brief Job chain hardware requirements.
+ *
+ * A job chain must specify what GPU features it needs to allow the
+ * driver to schedule the job correctly. By not specifying the
+ * correct settings can/will cause an early job termination. Multiple
+ * values can be ORed together to specify multiple requirements.
+ * Special case is ::BASE_JD_REQ_DEP, which is used to express complex
+ * dependencies, and that doesn't execute anything on the hardware.
+ */
+typedef u16 base_jd_core_req;
+
+/* Requirements that come from the HW */
+#define BASE_JD_REQ_DEP 0 /**< No requirement, dependency only */
+#define BASE_JD_REQ_FS (1U << 0) /**< Requires fragment shaders */
+/**
+ * Requires compute shaders
+ * This covers any of the following Midgard Job types:
+ * - Vertex Shader Job
+ * - Geometry Shader Job
+ * - An actual Compute Shader Job
+ *
+ * Compare this with @ref BASE_JD_REQ_ONLY_COMPUTE, which specifies that the
+ * job is specifically just the "Compute Shader" job type, and not the "Vertex
+ * Shader" nor the "Geometry Shader" job type.
+ */
+#define BASE_JD_REQ_CS (1U << 1)
+#define BASE_JD_REQ_T (1U << 2) /**< Requires tiling */
+#define BASE_JD_REQ_CF (1U << 3) /**< Requires cache flushes */
+#define BASE_JD_REQ_V (1U << 4) /**< Requires value writeback */
+
+/* SW-only requirements - the HW does not expose these as part of the job slot capabilities */
+/**
+ * SW Only requirement: the job chain requires a coherent core group. We don't
+ * mind which coherent core group is used.
+ */
+#define BASE_JD_REQ_COHERENT_GROUP (1U << 6)
+
+/**
+ * SW Only requirement: The performance counters should be enabled only when
+ * they are needed, to reduce power consumption.
+ */
+
+#define BASE_JD_REQ_PERMON (1U << 7)
+
+/**
+ * SW Only requirement: External resources are referenced by this atom.
+ * When external resources are referenced no syncsets can be bundled with the atom
+ * but should instead be part of a NULL jobs inserted into the dependency tree.
+ * The first pre_dep object must be configured for the external resouces to use,
+ * the second pre_dep object can be used to create other dependencies.
+ */
+#define BASE_JD_REQ_EXTERNAL_RESOURCES (1U << 8)
+
+/**
+ * SW Only requirement: Software defined job. Jobs with this bit set will not be submitted
+ * to the hardware but will cause some action to happen within the driver
+ */
+#define BASE_JD_REQ_SOFT_JOB (1U << 9)
+
+#define BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME (BASE_JD_REQ_SOFT_JOB | 0x1)
+#define BASE_JD_REQ_SOFT_FENCE_TRIGGER (BASE_JD_REQ_SOFT_JOB | 0x2)
+#define BASE_JD_REQ_SOFT_FENCE_WAIT (BASE_JD_REQ_SOFT_JOB | 0x3)
+
+/**
+ * HW Requirement: Requires Compute shaders (but not Vertex or Geometry Shaders)
+ *
+ * This indicates that the Job Chain contains Midgard Jobs of the 'Compute Shaders' type.
+ *
+ * In contrast to @ref BASE_JD_REQ_CS, this does \b not indicate that the Job
+ * Chain contains 'Geometry Shader' or 'Vertex Shader' jobs.
+ *
+ * @note This is a more flexible variant of the @ref BASE_CONTEXT_HINT_ONLY_COMPUTE flag,
+ * allowing specific jobs to be marked as 'Only Compute' instead of the entire context
+ */
+#define BASE_JD_REQ_ONLY_COMPUTE (1U << 10)
+
+/**
+ * HW Requirement: Use the base_jd_atom::device_nr field to specify a
+ * particular core group
+ *
+ * If both BASE_JD_REQ_COHERENT_GROUP and this flag are set, this flag takes priority
+ *
+ * This is only guaranteed to work for BASE_JD_REQ_ONLY_COMPUTE atoms.
+ *
+ * If the core availability policy is keeping the required core group turned off, then
+ * the job will fail with a BASE_JD_EVENT_PM_EVENT error code.
+ */
+#define BASE_JD_REQ_SPECIFIC_COHERENT_GROUP (1U << 11)
+
+/**
+ * SW Flag: If this bit is set then the successful completion of this atom
+ * will not cause an event to be sent to userspace
+ */
+#define BASE_JD_REQ_EVENT_ONLY_ON_FAILURE (1U << 12)
+
+/**
+* These requirement bits are currently unused in base_jd_core_req (currently a u16)
+*/
+
+#define BASEP_JD_REQ_RESERVED_BIT5 (1U << 5)
+#define BASEP_JD_REQ_RESERVED_BIT13 (1U << 13)
+#define BASEP_JD_REQ_RESERVED_BIT14 (1U << 14)
+#define BASEP_JD_REQ_RESERVED_BIT15 (1U << 15)
+
+/**
+* Mask of all the currently unused requirement bits in base_jd_core_req.
+*/
+
+#define BASEP_JD_REQ_RESERVED (BASEP_JD_REQ_RESERVED_BIT5 | BASEP_JD_REQ_RESERVED_BIT13 |\
+ BASEP_JD_REQ_RESERVED_BIT14 | BASEP_JD_REQ_RESERVED_BIT15)
+
+/**
+ * Mask of all bits in base_jd_core_req that control the type of the atom.
+ *
+ * This allows dependency only atoms to have flags set
+ */
+#define BASEP_JD_REQ_ATOM_TYPE (~(BASEP_JD_REQ_RESERVED | BASE_JD_REQ_EVENT_ONLY_ON_FAILURE |\
+ BASE_JD_REQ_EXTERNAL_RESOURCES))
+
+#if BASE_LEGACY_JD_API
+/**
+ * @brief A single job chain, with pre/post dependendencies and mem ops
+ *
+ * This structure is used to describe a single job-chain to be submitted
+ * as part of a bag.
+ * It contains all the necessary information for Base to take care of this
+ * job-chain, including core requirements, priority, syncsets and
+ * dependencies.
+ */
+typedef struct base_jd_atom {
+ mali_addr64 jc; /**< job-chain GPU address */
+ base_jd_udata udata; /**< user data */
+ base_jd_dep pre_dep; /**< pre-dependencies */
+ base_jd_dep post_dep; /**< post-dependencies */
+ base_jd_core_req core_req; /**< core requirements */
+ u16 nr_syncsets; /**< nr of syncsets following the atom */
+ u16 nr_extres; /**< nr of external resources following the atom */
+
+ /** @brief Relative priority.
+ *
+ * A positive value requests a lower priority, whilst a negative value
+ * requests a higher priority. Only privileged processes may request a
+ * higher priority. For unprivileged processes, a negative priority will
+ * be interpreted as zero.
+ */
+ s8 prio;
+
+ /**
+ * @brief Device number to use, depending on @ref base_jd_core_req flags set.
+ *
+ * When BASE_JD_REQ_SPECIFIC_COHERENT_GROUP is set, a 'device' is one of
+ * the coherent core groups, and so this targets a particular coherent
+ * core-group. They are numbered from 0 to (mali_base_gpu_coherent_group_info::num_groups - 1),
+ * and the cores targeted by this device_nr will usually be those specified by
+ * (mali_base_gpu_coherent_group_info::group[device_nr].core_mask).
+ * Further, two atoms from different processes using the same \a device_nr
+ * at the same time will always target the same coherent core-group.
+ *
+ * There are exceptions to when the device_nr is ignored:
+ * - when any process in the system uses a BASE_JD_REQ_CS or
+ * BASE_JD_REQ_ONLY_COMPUTE atom that can run on all cores across all
+ * coherency groups (i.e. also does \b not have the
+ * BASE_JD_REQ_COHERENT_GROUP or BASE_JD_REQ_SPECIFIC_COHERENT_GROUP flags
+ * set). In this case, such atoms would block device_nr==1 being used due
+ * to restrictions on affinity, perhaps indefinitely. To ensure progress is
+ * made, the atoms targeted for device_nr 1 will instead be redirected to
+ * device_nr 0
+ * - During certain HW workarounds, such as BASE_HW_ISSUE_8987, where
+ * BASE_JD_REQ_ONLY_COMPUTE atoms must not use the same cores as other
+ * atoms. In this case, all atoms are targeted to device_nr == min( num_groups, 1 )
+ *
+ * Note that the 'device' number for a coherent coregroup cannot exceed
+ * (BASE_MAX_COHERENT_GROUPS - 1).
+ */
+ u8 device_nr;
+} base_jd_atom;
+#endif /* BASE_LEGACY_JD_API */
+
+typedef u8 base_atom_id; /**< Type big enough to store an atom number in */
+
+typedef struct base_jd_atom_v2 {
+ mali_addr64 jc; /**< job-chain GPU address */
+ base_jd_core_req core_req; /**< core requirements */
+ base_jd_udata udata; /**< user data */
+ kbase_pointer extres_list; /**< list of external resources */
+ u16 nr_extres; /**< nr of external resources */
+ base_atom_id pre_dep[2]; /**< pre-dependencies */
+ base_atom_id atom_number; /**< unique number to identify the atom */
+ s8 prio; /**< priority - smaller is higher priority */
+ u8 device_nr; /**< coregroup when BASE_JD_REQ_SPECIFIC_COHERENT_GROUP specified */
+} base_jd_atom_v2;
+
+#if BASE_LEGACY_JD_API
+/* Structure definition works around the fact that C89 doesn't allow arrays of size 0 */
+typedef struct basep_jd_atom_ss {
+ base_jd_atom atom;
+ base_syncset syncsets[1];
+} basep_jd_atom_ss;
+#endif /* BASE_LEGACY_JD_API */
+
+typedef enum base_external_resource_access {
+ BASE_EXT_RES_ACCESS_SHARED,
+ BASE_EXT_RES_ACCESS_EXCLUSIVE
+} base_external_resource_access;
+
+typedef struct base_external_resource {
+ u64 ext_resource;
+} base_external_resource;
+
+#if BASE_LEGACY_JD_API
+/* Structure definition works around the fact that C89 doesn't allow arrays of size 0 */
+typedef struct basep_jd_atom_ext_res {
+ base_jd_atom atom;
+ base_external_resource resources[1];
+} basep_jd_atom_ext_res;
+
+static INLINE size_t base_jd_atom_size_ex(u32 syncset_count, u32 external_res_count)
+{
+ int size;
+
+ LOCAL_ASSERT(0 == syncset_count || 0 == external_res_count);
+
+ size = syncset_count ? offsetof(basep_jd_atom_ss, syncsets[0]) + (sizeof(base_syncset) * syncset_count) : external_res_count ? offsetof(basep_jd_atom_ext_res, resources[0]) + (sizeof(base_external_resource) * external_res_count) : sizeof(base_jd_atom);
+
+ /* Atom minimum size set to 64 bytes to ensure that the maximum
+ * number of atoms in the ring buffer is limited to 256 */
+ return MAX(64, size);
+}
+
+/**
+ * @brief Atom size evaluator
+ *
+ * This function returns the size in bytes of a ::base_jd_atom
+ * containing @a n syncsets. It must be used to compute the size of a
+ * bag before allocation.
+ *
+ * @param nr the number of syncsets for this atom
+ * @return the atom size in bytes
+ */
+static INLINE size_t base_jd_atom_size(u32 nr)
+{
+ return base_jd_atom_size_ex(nr, 0);
+}
+
+/**
+ * @brief Atom syncset accessor
+ *
+ * This function returns a pointer to the nth syncset allocated
+ * together with an atom.
+ *
+ * @param[in] atom The allocated atom
+ * @param n The number of the syncset to be returned
+ * @return a pointer to the nth syncset.
+ */
+static INLINE base_syncset *base_jd_get_atom_syncset(base_jd_atom *atom, u16 n)
+{
+ LOCAL_ASSERT(atom != NULL);
+ LOCAL_ASSERT(0 == (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES));
+ LOCAL_ASSERT(n <= atom->nr_syncsets);
+ return &((basep_jd_atom_ss *) atom)->syncsets[n];
+}
+#endif /* BASE_LEGACY_JD_API */
+
+/**
+ * @brief Soft-atom fence trigger setup.
+ *
+ * Sets up an atom to be a SW-only atom signaling a fence
+ * when it reaches the run state.
+ *
+ * Using the existing base dependency system the fence can
+ * be set to trigger when a GPU job has finished.
+ *
+ * The base fence object must not be terminated until the atom
+ * has been submitted to @a base_jd_submit_bag and @a base_jd_submit_bag has returned.
+ *
+ * @a fence must be a valid fence set up with @a base_fence_init.
+ * Calling this function with a uninitialized fence results in undefined behavior.
+ *
+ * @param[out] atom A pre-allocated atom to configure as a fence trigger SW atom
+ * @param[in] fence The base fence object to trigger.
+ */
+static INLINE void base_jd_fence_trigger_setup(base_jd_atom * const atom, base_fence *fence)
+{
+ LOCAL_ASSERT(atom);
+ LOCAL_ASSERT(fence);
+ LOCAL_ASSERT(fence->basep.fd == INVALID_PLATFORM_FENCE);
+ LOCAL_ASSERT(fence->basep.stream_fd >= 0);
+ atom->jc = (uintptr_t) fence;
+ atom->core_req = BASE_JD_REQ_SOFT_FENCE_TRIGGER;
+}
+
+static INLINE void base_jd_fence_trigger_setup_v2(base_jd_atom_v2 *atom, base_fence *fence)
+{
+ LOCAL_ASSERT(atom);
+ LOCAL_ASSERT(fence);
+ LOCAL_ASSERT(fence->basep.fd == INVALID_PLATFORM_FENCE);
+ LOCAL_ASSERT(fence->basep.stream_fd >= 0);
+ atom->jc = (uintptr_t) fence;
+ atom->core_req = BASE_JD_REQ_SOFT_FENCE_TRIGGER;
+}
+
+/**
+ * @brief Soft-atom fence wait setup.
+ *
+ * Sets up an atom to be a SW-only atom waiting on a fence.
+ * When the fence becomes triggered the atom becomes runnable
+ * and completes immediately.
+ *
+ * Using the existing base dependency system the fence can
+ * be set to block a GPU job until it has been triggered.
+ *
+ * The base fence object must not be terminated until the atom
+ * has been submitted to @a base_jd_submit_bag and @a base_jd_submit_bag has returned.
+ *
+ * @a fence must be a valid fence set up with @a base_fence_init or @a base_fence_import.
+ * Calling this function with a uninitialized fence results in undefined behavior.
+ *
+ * @param[out] atom A pre-allocated atom to configure as a fence wait SW atom
+ * @param[in] fence The base fence object to wait on
+ */
+static INLINE void base_jd_fence_wait_setup(base_jd_atom * const atom, base_fence *fence)
+{
+ LOCAL_ASSERT(atom);
+ LOCAL_ASSERT(fence);
+ LOCAL_ASSERT(fence->basep.fd >= 0);
+ atom->jc = (uintptr_t) fence;
+ atom->core_req = BASE_JD_REQ_SOFT_FENCE_WAIT;
+}
+
+static INLINE void base_jd_fence_wait_setup_v2(base_jd_atom_v2 *atom, base_fence *fence)
+{
+ LOCAL_ASSERT(atom);
+ LOCAL_ASSERT(fence);
+ LOCAL_ASSERT(fence->basep.fd >= 0);
+ atom->jc = (uintptr_t) fence;
+ atom->core_req = BASE_JD_REQ_SOFT_FENCE_WAIT;
+}
+
+#if BASE_LEGACY_JD_API
+/**
+ * @brief Atom external resource accessor
+ *
+ * This functions returns a pointer to the nth external resource tracked by the atom.
+ *
+ * @param[in] atom The allocated atom
+ * @param n The number of the external resource to return a pointer to
+ * @return a pointer to the nth external resource
+ */
+static INLINE base_external_resource * base_jd_get_external_resource(base_jd_atom *atom, u16 n)
+{
+ LOCAL_ASSERT(atom != NULL);
+ LOCAL_ASSERT(BASE_JD_REQ_EXTERNAL_RESOURCES == (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES));
+ LOCAL_ASSERT(n <= atom->nr_extres);
+ return &((basep_jd_atom_ext_res *) atom)->resources[n];
+}
+#endif /* BASE_LEGACY_JD_API */
+
+/**
+ * @brief External resource info initialization.
+ *
+ * Sets up a external resource object to reference
+ * a memory allocation and the type of access requested.
+ *
+ * @param[in] res The resource object to initialize
+ * @param handle The handle to the imported memory object
+ * @param access The type of access requested
+ */
+static INLINE void base_external_resource_init(base_external_resource * res, base_import_handle handle, base_external_resource_access access)
+{
+ mali_addr64 address;
+ address = handle.basep.handle;
+
+ LOCAL_ASSERT(res != NULL);
+ LOCAL_ASSERT(0 == (address & LOCAL_PAGE_LSB));
+ LOCAL_ASSERT(access == BASE_EXT_RES_ACCESS_SHARED || access == BASE_EXT_RES_ACCESS_EXCLUSIVE);
+
+ res->ext_resource = address | (access & LOCAL_PAGE_LSB);
+}
+
+#if BASE_LEGACY_JD_API
+/**
+ * @brief Next atom accessor
+ *
+ * This function returns a pointer to the next allocated atom. It
+ * relies on the fact that the current atom has been correctly
+ * initialized (relies on the base_jd_atom::nr_syncsets field).
+ *
+ * @param[in] atom The allocated atom
+ * @return a pointer to the next atom.
+ */
+static INLINE base_jd_atom *base_jd_get_next_atom(base_jd_atom *atom)
+{
+ LOCAL_ASSERT(atom != NULL);
+ return (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) ? (base_jd_atom *) base_jd_get_external_resource(atom, atom->nr_extres) : (base_jd_atom *) base_jd_get_atom_syncset(atom, atom->nr_syncsets);
+}
+#endif /* BASE_LEGACY_JD_API */
+
+/**
+ * @brief Job chain event code bits
+ * Defines the bits used to create ::base_jd_event_code
+ */
+enum {
+ BASE_JD_SW_EVENT_KERNEL = (1u << 15), /**< Kernel side event */
+ BASE_JD_SW_EVENT = (1u << 14), /**< SW defined event */
+ BASE_JD_SW_EVENT_SUCCESS = (1u << 13), /**< Event idicates success (SW events only) */
+ BASE_JD_SW_EVENT_JOB = (0u << 11), /**< Job related event */
+ BASE_JD_SW_EVENT_BAG = (1u << 11), /**< Bag related event */
+ BASE_JD_SW_EVENT_INFO = (2u << 11), /**< Misc/info event */
+ BASE_JD_SW_EVENT_RESERVED = (3u << 11), /**< Reserved event type */
+ BASE_JD_SW_EVENT_TYPE_MASK = (3u << 11) /**< Mask to extract the type from an event code */
+};
+
+/**
+ * @brief Job chain event codes
+ *
+ * HW and low-level SW events are represented by event codes.
+ * The status of jobs which succeeded are also represented by
+ * an event code (see ::BASE_JD_EVENT_DONE).
+ * Events are usually reported as part of a ::base_jd_event.
+ *
+ * The event codes are encoded in the following way:
+ * @li 10:0 - subtype
+ * @li 12:11 - type
+ * @li 13 - SW success (only valid if the SW bit is set)
+ * @li 14 - SW event (HW event if not set)
+ * @li 15 - Kernel event (should never be seen in userspace)
+ *
+ * Events are split up into ranges as follows:
+ * - BASE_JD_EVENT_RANGE_\<description\>_START
+ * - BASE_JD_EVENT_RANGE_\<description\>_END
+ *
+ * \a code is in \<description\>'s range when:
+ * - <tt>BASE_JD_EVENT_RANGE_\<description\>_START <= code < BASE_JD_EVENT_RANGE_\<description\>_END </tt>
+ *
+ * Ranges can be asserted for adjacency by testing that the END of the previous
+ * is equal to the START of the next. This is useful for optimizing some tests
+ * for range.
+ *
+ * A limitation is that the last member of this enum must explicitly be handled
+ * (with an assert-unreachable statement) in switch statements that use
+ * variables of this type. Otherwise, the compiler warns that we have not
+ * handled that enum value.
+ */
+typedef enum base_jd_event_code {
+ /* HW defined exceptions */
+
+ /** Start of HW Non-fault status codes
+ *
+ * @note Obscurely, BASE_JD_EVENT_TERMINATED indicates a real fault,
+ * because the job was hard-stopped
+ */
+ BASE_JD_EVENT_RANGE_HW_NONFAULT_START = 0,
+
+ /* non-fatal exceptions */
+ BASE_JD_EVENT_NOT_STARTED = 0x00, /**< Can't be seen by userspace, treated as 'previous job done' */
+ BASE_JD_EVENT_DONE = 0x01,
+ BASE_JD_EVENT_STOPPED = 0x03, /**< Can't be seen by userspace, becomes TERMINATED, DONE or JOB_CANCELLED */
+ BASE_JD_EVENT_TERMINATED = 0x04, /**< This is actually a fault status code - the job was hard stopped */
+ BASE_JD_EVENT_ACTIVE = 0x08, /**< Can't be seen by userspace, jobs only returned on complete/fail/cancel */
+
+ /** End of HW Non-fault status codes
+ *
+ * @note Obscurely, BASE_JD_EVENT_TERMINATED indicates a real fault,
+ * because the job was hard-stopped
+ */
+ BASE_JD_EVENT_RANGE_HW_NONFAULT_END = 0x40,
+
+ /** Start of HW fault and SW Error status codes */
+ BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_START = 0x40,
+
+ /* job exceptions */
+ BASE_JD_EVENT_JOB_CONFIG_FAULT = 0x40,
+ BASE_JD_EVENT_JOB_POWER_FAULT = 0x41,
+ BASE_JD_EVENT_JOB_READ_FAULT = 0x42,
+ BASE_JD_EVENT_JOB_WRITE_FAULT = 0x43,
+ BASE_JD_EVENT_JOB_AFFINITY_FAULT = 0x44,
+ BASE_JD_EVENT_JOB_BUS_FAULT = 0x48,
+ BASE_JD_EVENT_INSTR_INVALID_PC = 0x50,
+ BASE_JD_EVENT_INSTR_INVALID_ENC = 0x51,
+ BASE_JD_EVENT_INSTR_TYPE_MISMATCH = 0x52,
+ BASE_JD_EVENT_INSTR_OPERAND_FAULT = 0x53,
+ BASE_JD_EVENT_INSTR_TLS_FAULT = 0x54,
+ BASE_JD_EVENT_INSTR_BARRIER_FAULT = 0x55,
+ BASE_JD_EVENT_INSTR_ALIGN_FAULT = 0x56,
+ BASE_JD_EVENT_DATA_INVALID_FAULT = 0x58,
+ BASE_JD_EVENT_TILE_RANGE_FAULT = 0x59,
+ BASE_JD_EVENT_STATE_FAULT = 0x5A,
+ BASE_JD_EVENT_OUT_OF_MEMORY = 0x60,
+ BASE_JD_EVENT_UNKNOWN = 0x7F,
+
+ /* GPU exceptions */
+ BASE_JD_EVENT_DELAYED_BUS_FAULT = 0x80,
+ BASE_JD_EVENT_SHAREABILITY_FAULT = 0x88,
+
+ /* MMU exceptions */
+ BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL1 = 0xC1,
+ BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL2 = 0xC2,
+ BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL3 = 0xC3,
+ BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL4 = 0xC4,
+ BASE_JD_EVENT_PERMISSION_FAULT = 0xC8,
+ BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL1 = 0xD1,
+ BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL2 = 0xD2,
+ BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL3 = 0xD3,
+ BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL4 = 0xD4,
+ BASE_JD_EVENT_ACCESS_FLAG = 0xD8,
+
+ /* SW defined exceptions */
+ BASE_JD_EVENT_MEM_GROWTH_FAILED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x000,
+ BASE_JD_EVENT_TIMED_OUT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x001,
+ BASE_JD_EVENT_JOB_CANCELLED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x002,
+ BASE_JD_EVENT_JOB_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x003,
+ BASE_JD_EVENT_PM_EVENT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x004,
+
+ BASE_JD_EVENT_BAG_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_BAG | 0x003,
+
+ /** End of HW fault and SW Error status codes */
+ BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_RESERVED | 0x3FF,
+
+ /** Start of SW Success status codes */
+ BASE_JD_EVENT_RANGE_SW_SUCCESS_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | 0x000,
+
+ BASE_JD_EVENT_PROGRESS_REPORT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_JOB | 0x000,
+ BASE_JD_EVENT_BAG_DONE = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_BAG | 0x000,
+ BASE_JD_EVENT_DRV_TERMINATED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_INFO | 0x000,
+
+ /** End of SW Success status codes */
+ BASE_JD_EVENT_RANGE_SW_SUCCESS_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_RESERVED | 0x3FF,
+
+ /** Start of Kernel-only status codes. Such codes are never returned to user-space */
+ BASE_JD_EVENT_RANGE_KERNEL_ONLY_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | 0x000,
+ BASE_JD_EVENT_REMOVED_FROM_NEXT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | BASE_JD_SW_EVENT_JOB | 0x000,
+
+ /** End of Kernel-only status codes. */
+ BASE_JD_EVENT_RANGE_KERNEL_ONLY_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | BASE_JD_SW_EVENT_RESERVED | 0x3FF
+} base_jd_event_code;
+
+/**
+ * @brief Event reporting structure
+ *
+ * This structure is used by the kernel driver to report information
+ * about GPU events. The can either be HW-specific events or low-level
+ * SW events, such as job-chain completion.
+ *
+ * The event code contains an event type field which can be extracted
+ * by ANDing with ::BASE_JD_SW_EVENT_TYPE_MASK.
+ *
+ * Based on the event type base_jd_event::data holds:
+ * @li ::BASE_JD_SW_EVENT_JOB : the offset in the ring-buffer for the completed
+ * job-chain
+ * @li ::BASE_JD_SW_EVENT_BAG : The address of the ::base_jd_bag that has
+ * been completed (ie all contained job-chains have been completed).
+ * @li ::BASE_JD_SW_EVENT_INFO : base_jd_event::data not used
+ */
+#if BASE_LEGACY_JD_API
+typedef struct base_jd_event {
+ base_jd_event_code event_code; /**< event code */
+ void *data; /**< event specific data */
+} base_jd_event;
+#endif
+
+typedef struct base_jd_event_v2 {
+ base_jd_event_code event_code; /**< event code */
+ base_atom_id atom_number; /**< the atom number that has completed */
+ base_jd_udata udata; /**< user data */
+} base_jd_event_v2;
+
+/**
+ * Padding required to ensure that the @ref basep_dump_cpu_gpu_counters structure fills
+ * a full cache line.
+ */
+
+#define BASE_CPU_GPU_CACHE_LINE_PADDING (36)
+
+
+/**
+ * @brief Structure for BASE_JD_REQ_SOFT_DUMP_CPU_GPU_COUNTERS jobs.
+ *
+ * This structure is stored into the memory pointed to by the @c jc field of @ref base_jd_atom.
+ *
+ * This structure must be padded to ensure that it will occupy whole cache lines. This is to avoid
+ * cases where access to pages containing the structure is shared between cached and un-cached
+ * memory regions, which would cause memory corruption. Here we set the structure size to be 64 bytes
+ * which is the cache line for ARM A15 processors.
+ */
+
+typedef struct base_dump_cpu_gpu_counters {
+ u64 system_time;
+ u64 cycle_counter;
+ u64 sec;
+ u32 usec;
+ u8 padding[BASE_CPU_GPU_CACHE_LINE_PADDING];
+} base_dump_cpu_gpu_counters;
+
+
+
+/** @} end group base_user_api_job_dispatch */
+
+#ifdef __KERNEL__
+/*
+ * The following typedefs should be removed when a midg types header is added.
+ * See MIDCOM-1657 for details.
+ */
+typedef u32 midg_product_id;
+typedef u32 midg_cache_features;
+typedef u32 midg_tiler_features;
+typedef u32 midg_mem_features;
+typedef u32 midg_mmu_features;
+typedef u32 midg_js_features;
+typedef u32 midg_as_present;
+typedef u32 midg_js_present;
+
+#define MIDG_MAX_JOB_SLOTS 16
+
+#else
+#include <midg/mali_midg.h>
+#endif
+
+/**
+ * @page page_base_user_api_gpuprops User-side Base GPU Property Query API
+ *
+ * The User-side Base GPU Property Query API encapsulates two
+ * sub-modules:
+ *
+ * - @ref base_user_api_gpuprops_dyn "Dynamic GPU Properties"
+ * - @ref base_plat_config_gpuprops "Base Platform Config GPU Properties"
+ *
+ * There is a related third module outside of Base, which is owned by the MIDG
+ * module:
+ * - @ref midg_gpuprops_static "Midgard Compile-time GPU Properties"
+ *
+ * Base only deals with properties that vary between different Midgard
+ * implementations - the Dynamic GPU properties and the Platform Config
+ * properties.
+ *
+ * For properties that are constant for the Midgard Architecture, refer to the
+ * MIDG module. However, we will discuss their relevance here <b>just to
+ * provide background information.</b>
+ *
+ * @section sec_base_user_api_gpuprops_about About the GPU Properties in Base and MIDG modules
+ *
+ * The compile-time properties (Platform Config, Midgard Compile-time
+ * properties) are exposed as pre-processor macros.
+ *
+ * Complementing the compile-time properties are the Dynamic GPU
+ * Properties, which act as a conduit for the Midgard Configuration
+ * Discovery.
+ *
+ * In general, the dynamic properties are present to verify that the platform
+ * has been configured correctly with the right set of Platform Config
+ * Compile-time Properties.
+ *
+ * As a consistant guide across the entire DDK, the choice for dynamic or
+ * compile-time should consider the following, in order:
+ * -# Can the code be written so that it doesn't need to know the
+ * implementation limits at all?
+ * -# If you need the limits, get the information from the Dynamic Property
+ * lookup. This should be done once as you fetch the context, and then cached
+ * as part of the context data structure, so it's cheap to access.
+ * -# If there's a clear and arguable inefficiency in using Dynamic Properties,
+ * then use a Compile-Time Property (Platform Config, or Midgard Compile-time
+ * property). Examples of where this might be sensible follow:
+ * - Part of a critical inner-loop
+ * - Frequent re-use throughout the driver, causing significant extra load
+ * instructions or control flow that would be worthwhile optimizing out.
+ *
+ * We cannot provide an exhaustive set of examples, neither can we provide a
+ * rule for every possible situation. Use common sense, and think about: what
+ * the rest of the driver will be doing; how the compiler might represent the
+ * value if it is a compile-time constant; whether an OEM shipping multiple
+ * devices would benefit much more from a single DDK binary, instead of
+ * insignificant micro-optimizations.
+ *
+ * @section sec_base_user_api_gpuprops_dyn Dynamic GPU Properties
+ *
+ * Dynamic GPU properties are presented in two sets:
+ * -# the commonly used properties in @ref base_gpu_props, which have been
+ * unpacked from GPU register bitfields.
+ * -# The full set of raw, unprocessed properties in @ref midg_raw_gpu_props
+ * (also a member of @ref base_gpu_props). All of these are presented in
+ * the packed form, as presented by the GPU registers themselves.
+ *
+ * @usecase The raw properties in @ref midg_raw_gpu_props are necessary to
+ * allow a user of the Mali Tools (e.g. PAT) to determine "Why is this device
+ * behaving differently?". In this case, all information about the
+ * configuration is potentially useful, but it <b>does not need to be processed
+ * by the driver</b>. Instead, the raw registers can be processed by the Mali
+ * Tools software on the host PC.
+ *
+ * The properties returned extend the Midgard Configuration Discovery
+ * registers. For example, GPU clock speed is not specified in the Midgard
+ * Architecture, but is <b>necessary for OpenCL's clGetDeviceInfo() function</b>.
+ *
+ * The GPU properties are obtained by a call to
+ * _mali_base_get_gpu_props(). This simply returns a pointer to a const
+ * base_gpu_props structure. It is constant for the life of a base
+ * context. Multiple calls to _mali_base_get_gpu_props() to a base context
+ * return the same pointer to a constant structure. This avoids cache pollution
+ * of the common data.
+ *
+ * This pointer must not be freed, because it does not point to the start of a
+ * region allocated by the memory allocator; instead, just close the @ref
+ * base_context.
+ *
+ *
+ * @section sec_base_user_api_gpuprops_config Platform Config Compile-time Properties
+ *
+ * The Platform Config File sets up gpu properties that are specific to a
+ * certain platform. Properties that are 'Implementation Defined' in the
+ * Midgard Architecture spec are placed here.
+ *
+ * @note Reference configurations are provided for Midgard Implementations, such as
+ * the Mali-T600 family. The customer need not repeat this information, and can select one of
+ * these reference configurations. For example, VA_BITS, PA_BITS and the
+ * maximum number of samples per pixel might vary between Midgard Implementations, but
+ * \b not for platforms using the Mali-T604. This information is placed in
+ * the reference configuration files.
+ *
+ * The System Integrator creates the following structure:
+ * - platform_XYZ
+ * - platform_XYZ/plat
+ * - platform_XYZ/plat/plat_config.h
+ *
+ * They then edit plat_config.h, using the example plat_config.h files as a
+ * guide.
+ *
+ * At the very least, the customer must set @ref CONFIG_GPU_CORE_TYPE, and will
+ * receive a helpful \#error message if they do not do this correctly. This
+ * selects the Reference Configuration for the Midgard Implementation. The rationale
+ * behind this decision (against asking the customer to write \#include
+ * <gpus/mali_t600.h> in their plat_config.h) is as follows:
+ * - This mechanism 'looks' like a regular config file (such as Linux's
+ * .config)
+ * - It is difficult to get wrong in a way that will produce strange build
+ * errors:
+ * - They need not know where the mali_t600.h, other_midg_gpu.h etc. files are stored - and
+ * so they won't accidentally pick another file with 'mali_t600' in its name
+ * - When the build doesn't work, the System Integrator may think the DDK is
+ * doesn't work, and attempt to fix it themselves:
+ * - For the @ref CONFIG_GPU_CORE_TYPE mechanism, the only way to get past the
+ * error is to set @ref CONFIG_GPU_CORE_TYPE, and this is what the \#error tells
+ * you.
+ * - For a \#include mechanism, checks must still be made elsewhere, which the
+ * System Integrator may try working around by setting \#defines (such as
+ * VA_BITS) themselves in their plat_config.h. In the worst case, they may
+ * set the prevention-mechanism \#define of
+ * "A_CORRECT_MIDGARD_CORE_WAS_CHOSEN".
+ * - In this case, they would believe they are on the right track, because
+ * the build progresses with their fix, but with errors elsewhere.
+ *
+ * However, there is nothing to prevent the customer using \#include to organize
+ * their own configurations files hierarchically.
+ *
+ * The mechanism for the header file processing is as follows:
+ *
+ * @dot
+ digraph plat_config_mechanism {
+ rankdir=BT
+ size="6,6"
+
+ "mali_base.h";
+ "midg/midg.h";
+
+ node [ shape=box ];
+ {
+ rank = same; ordering = out;
+
+ "midg/midg_gpu_props.h";
+ "base/midg_gpus/mali_t600.h";
+ "base/midg_gpus/other_midg_gpu.h";
+ }
+ { rank = same; "plat/plat_config.h"; }
+ {
+ rank = same;
+ "midg/midg.h" [ shape=box ];
+ gpu_chooser [ label="" style="invisible" width=0 height=0 fixedsize=true ];
+ select_gpu [ label="Mali-T600 | Other\n(select_gpu.h)" shape=polygon,sides=4,distortion=0.25 width=3.3 height=0.99 fixedsize=true ] ;
+ }
+ node [ shape=box ];
+ { rank = same; "plat/plat_config.h"; }
+ { rank = same; "mali_base.h"; }
+
+ "mali_base.h" -> "midg/midg.h" -> "midg/midg_gpu_props.h";
+ "mali_base.h" -> "plat/plat_config.h" ;
+ "mali_base.h" -> select_gpu ;
+
+ "plat/plat_config.h" -> gpu_chooser [style="dotted,bold" dir=none weight=4] ;
+ gpu_chooser -> select_gpu [style="dotted,bold"] ;
+
+ select_gpu -> "base/midg_gpus/mali_t600.h" ;
+ select_gpu -> "base/midg_gpus/other_midg_gpu.h" ;
+ }
+ @enddot
+ *
+ *
+ * @section sec_base_user_api_gpuprops_kernel Kernel Operation
+ *
+ * During Base Context Create time, user-side makes a single kernel call:
+ * - A call to fill user memory with GPU information structures
+ *
+ * The kernel-side will fill the provided the entire processed @ref base_gpu_props
+ * structure, because this information is required in both
+ * user and kernel side; it does not make sense to decode it twice.
+ *
+ * Coherency groups must be derived from the bitmasks, but this can be done
+ * kernel side, and just once at kernel startup: Coherency groups must already
+ * be known kernel-side, to support chains that specify a 'Only Coherent Group'
+ * SW requirement, or 'Only Coherent Group with Tiler' SW requirement.
+ *
+ * @section sec_base_user_api_gpuprops_cocalc Coherency Group calculation
+ * Creation of the coherent group data is done at device-driver startup, and so
+ * is one-time. This will most likely involve a loop with CLZ, shifting, and
+ * bit clearing on the L2_PRESENT or L3_PRESENT masks, depending on whether the
+ * system is L2 or L2+L3 Coherent. The number of shader cores is done by a
+ * population count, since faulty cores may be disabled during production,
+ * producing a non-contiguous mask.
+ *
+ * The memory requirements for this algoirthm can be determined either by a u64
+ * population count on the L2/L3_PRESENT masks (a LUT helper already is
+ * requried for the above), or simple assumption that there can be no more than
+ * 16 coherent groups, since core groups are typically 4 cores.
+ */
+
+/**
+ * @addtogroup base_user_api_gpuprops User-side Base GPU Property Query APIs
+ * @{
+ */
+
+/**
+ * @addtogroup base_user_api_gpuprops_dyn Dynamic HW Properties
+ * @{
+ */
+
+#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 3
+
+#define BASE_MAX_COHERENT_GROUPS 16
+
+struct mali_base_gpu_core_props {
+ /**
+ * Product specific value.
+ */
+ midg_product_id product_id;
+
+ /**
+ * Status of the GPU release.
+ * No defined values, but starts at 0 and increases by one for each release
+ * status (alpha, beta, EAC, etc.).
+ * 4 bit values (0-15).
+ */
+ u16 version_status;
+
+ /**
+ * Minor release number of the GPU. "P" part of an "RnPn" release number.
+ * 8 bit values (0-255).
+ */
+ u16 minor_revision;
+
+ /**
+ * Major release number of the GPU. "R" part of an "RnPn" release number.
+ * 4 bit values (0-15).
+ */
+ u16 major_revision;
+
+ u16 padding;
+
+ /**
+ * @usecase GPU clock speed is not specified in the Midgard Architecture, but is
+ * <b>necessary for OpenCL's clGetDeviceInfo() function</b>.
+ */
+ u32 gpu_speed_mhz;
+
+ /**
+ * @usecase GPU clock max/min speed is required for computing best/worst case
+ * in tasks as job scheduling ant irq_throttling. (It is not specified in the
+ * Midgard Architecture).
+ */
+ u32 gpu_freq_khz_max;
+ u32 gpu_freq_khz_min;
+
+ /**
+ * Size of the shader program counter, in bits.
+ */
+ u32 log2_program_counter_size;
+
+ /**
+ * TEXTURE_FEATURES_x registers, as exposed by the GPU. This is a
+ * bitpattern where a set bit indicates that the format is supported.
+ *
+ * Before using a texture format, it is recommended that the corresponding
+ * bit be checked.
+ */
+ u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS];
+
+ /**
+ * Theoretical maximum memory available to the GPU. It is unlikely that a
+ * client will be able to allocate all of this memory for their own
+ * purposes, but this at least provides an upper bound on the memory
+ * available to the GPU.
+ *
+ * This is required for OpenCL's clGetDeviceInfo() call when
+ * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL GPU devices. The
+ * client will not be expecting to allocate anywhere near this value.
+ */
+ u64 gpu_available_memory_size;
+};
+
+/**
+ *
+ * More information is possible - but associativity and bus width are not
+ * required by upper-level apis.
+ */
+struct mali_base_gpu_l2_cache_props {
+ u8 log2_line_size;
+ u8 log2_cache_size;
+ u8 num_l2_slices; /* Number of L2C slices. 1 or higher */
+ u8 padding[5];
+};
+
+struct mali_base_gpu_l3_cache_props {
+ u8 log2_line_size;
+ u8 log2_cache_size;
+ u8 padding[6];
+};
+
+struct mali_base_gpu_tiler_props {
+ u32 bin_size_bytes; /* Max is 4*2^15 */
+ u32 max_active_levels; /* Max is 2^15 */
+};
+
+/**
+ * GPU threading system details. If a value is 0 the information is not available on
+ * the implementation of the GPU.
+ */
+struct mali_base_gpu_thread_props {
+ u16 max_registers; /* Total size [1..65535] of the register file available per core. */
+ u8 max_task_queue; /* Max. tasks [1..255] which may be sent to a core before it becomes blocked. */
+ u8 max_thread_group_split; /* Max. allowed value [1..15] of the Thread Group Split field. */
+ u8 impl_tech; /* 1 = Silicon, 2 = FPGA, 3 = SW Model/Emulation */
+ u8 padding[3];
+};
+
+/**
+ * @brief descriptor for a coherent group
+ *
+ * \c core_mask exposes all cores in that coherent group, and \c num_cores
+ * provides a cached population-count for that mask.
+ *
+ * @note Whilst all cores are exposed in the mask, not all may be available to
+ * the application, depending on the Kernel Job Scheduler policy. Therefore,
+ * the application should not further restrict the core mask itself, as it may
+ * result in an empty core mask. However, it can guarentee that there will be
+ * at least one core available for each core group exposed .
+ *
+ * @usecase Chains marked at certain user-side priorities (e.g. the Long-running
+ * (batch) priority ) can be prevented from running on entire core groups by the
+ * Kernel Chain Scheduler policy.
+ *
+ * @note if u64s must be 8-byte aligned, then this structure has 32-bits of wastage.
+ */
+struct mali_base_gpu_coherent_group {
+ u64 core_mask; /**< Core restriction mask required for the group */
+ u16 num_cores; /**< Number of cores in the group */
+ u16 padding[3];
+};
+
+/**
+ * @brief Coherency group information
+ *
+ * Note that the sizes of the members could be reduced. However, the \c group
+ * member might be 8-byte aligned to ensure the u64 core_mask is 8-byte
+ * aligned, thus leading to wastage if the other members sizes were reduced.
+ *
+ * The groups are sorted by core mask. The core masks are non-repeating and do
+ * not intersect.
+ */
+struct mali_base_gpu_coherent_group_info {
+ u32 num_groups;
+
+ /**
+ * Number of core groups (coherent or not) in the GPU. Equivalent to the number of L2 Caches.
+ *
+ * The GPU Counter dumping writes 2048 bytes per core group, regardless of
+ * whether the core groups are coherent or not. Hence this member is needed
+ * to calculate how much memory is required for dumping.
+ *
+ * @note Do not use it to work out how many valid elements are in the
+ * group[] member. Use num_groups instead.
+ */
+ u32 num_core_groups;
+
+ /**
+ * Coherency features of the memory, accessed by @ref midg_mem_features
+ * methods
+ */
+ midg_mem_features coherency;
+
+ u32 padding;
+
+ /**
+ * Descriptors of coherent groups
+ */
+ struct mali_base_gpu_coherent_group group[BASE_MAX_COHERENT_GROUPS];
+};
+
+/**
+ * A complete description of the GPU's Hardware Configuration Discovery
+ * registers.
+ *
+ * The information is presented inefficiently for access. For frequent access,
+ * the values should be better expressed in an unpacked form in the
+ * base_gpu_props structure.
+ *
+ * @usecase The raw properties in @ref midg_raw_gpu_props are necessary to
+ * allow a user of the Mali Tools (e.g. PAT) to determine "Why is this device
+ * behaving differently?". In this case, all information about the
+ * configuration is potentially useful, but it <b>does not need to be processed
+ * by the driver</b>. Instead, the raw registers can be processed by the Mali
+ * Tools software on the host PC.
+ *
+ */
+struct midg_raw_gpu_props {
+ u64 shader_present;
+ u64 tiler_present;
+ u64 l2_present;
+ u64 l3_present;
+
+ midg_cache_features l2_features;
+ midg_cache_features l3_features;
+ midg_mem_features mem_features;
+ midg_mmu_features mmu_features;
+
+ midg_as_present as_present;
+
+ u32 js_present;
+ midg_js_features js_features[MIDG_MAX_JOB_SLOTS];
+ midg_tiler_features tiler_features;
+ u32 texture_features[3];
+
+ u32 gpu_id;
+
+ u32 thread_max_threads;
+ u32 thread_max_workgroup_size;
+ u32 thread_max_barrier_size;
+ u32 thread_features;
+
+ u32 padding;
+};
+
+/**
+ * Return structure for _mali_base_get_gpu_props().
+ *
+ */
+typedef struct mali_base_gpu_props {
+ struct mali_base_gpu_core_props core_props;
+ struct mali_base_gpu_l2_cache_props l2_props;
+ struct mali_base_gpu_l3_cache_props l3_props;
+ struct mali_base_gpu_tiler_props tiler_props;
+ struct mali_base_gpu_thread_props thread_props;
+
+ /** This member is large, likely to be 128 bytes */
+ struct midg_raw_gpu_props raw_props;
+
+ /** This must be last member of the structure */
+ struct mali_base_gpu_coherent_group_info coherency_info;
+} base_gpu_props;
+
+/** @} end group base_user_api_gpuprops_dyn */
+
+/** @} end group base_user_api_gpuprops */
+
+/**
+ * @addtogroup base_user_api_core User-side Base core APIs
+ * @{
+ */
+
+/**
+ * \enum base_context_create_flags
+ *
+ * Flags to pass to ::base_context_init.
+ * Flags can be ORed together to enable multiple things.
+ *
+ * These share the same space as @ref basep_context_private_flags, and so must
+ * not collide with them.
+ */
+enum base_context_create_flags {
+ /** No flags set */
+ BASE_CONTEXT_CREATE_FLAG_NONE = 0,
+
+ /** Base context is embedded in a cctx object (flag used for CINSTR software counter macros) */
+ BASE_CONTEXT_CCTX_EMBEDDED = (1u << 0),
+
+ /** Base context is a 'System Monitor' context for Hardware counters.
+ *
+ * One important side effect of this is that job submission is disabled. */
+ BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED = (1u << 1),
+
+ /** Base context flag indicating a 'hint' that this context uses Compute
+ * Jobs only.
+ *
+ * Specifially, this means that it only sends atoms that <b>do not</b>
+ * contain the following @ref base_jd_core_req :
+ * - BASE_JD_REQ_FS
+ * - BASE_JD_REQ_T
+ *
+ * Violation of these requirements will cause the Job-Chains to be rejected.
+ *
+ * In addition, it is inadvisable for the atom's Job-Chains to contain Jobs
+ * of the following @ref midg_job_type (whilst it may work now, it may not
+ * work in future) :
+ * - @ref MIDG_JOB_VERTEX
+ * - @ref MIDG_JOB_GEOMETRY
+ *
+ * @note An alternative to using this is to specify the BASE_JD_REQ_ONLY_COMPUTE
+ * requirement in atoms.
+ */
+ BASE_CONTEXT_HINT_ONLY_COMPUTE = (1u << 2)
+};
+
+/**
+ * Bitpattern describing the ::base_context_create_flags that can be passed to base_context_init()
+ */
+#define BASE_CONTEXT_CREATE_ALLOWED_FLAGS \
+ (((u32)BASE_CONTEXT_CCTX_EMBEDDED) | \
+ ((u32)BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) | \
+ ((u32)BASE_CONTEXT_HINT_ONLY_COMPUTE))
+
+/**
+ * Bitpattern describing the ::base_context_create_flags that can be passed to the kernel
+ */
+#define BASE_CONTEXT_CREATE_KERNEL_FLAGS \
+ (((u32)BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) | \
+ ((u32)BASE_CONTEXT_HINT_ONLY_COMPUTE))
+
+/**
+ * Private flags used on the base context
+ *
+ * These start at bit 31, and run down to zero.
+ *
+ * They share the same space as @ref base_context_create_flags, and so must
+ * not collide with them.
+ */
+enum basep_context_private_flags {
+ /** Private flag tracking whether job descriptor dumping is disabled */
+ BASEP_CONTEXT_FLAG_JOB_DUMP_DISABLED = (1 << 31)
+};
+
+/** @} end group base_user_api_core */
+
+/** @} end group base_user_api */
+
+/**
+ * @addtogroup base_plat_config_gpuprops Base Platform Config GPU Properties
+ * @{
+ *
+ * C Pre-processor macros are exposed here to do with Platform
+ * Config.
+ *
+ * These include:
+ * - GPU Properties that are constant on a particular Midgard Family
+ * Implementation e.g. Maximum samples per pixel on Mali-T600.
+ * - General platform config for the GPU, such as the GPU major and minor
+ * revison.
+ */
+
+/** @} end group base_plat_config_gpuprops */
+
+/**
+ * @addtogroup base_api Base APIs
+ * @{
+ */
+/**
+ * @addtogroup basecpuprops Base CPU Properties
+ * @{
+ */
+
+/**
+ * @brief CPU Property Flag for base_cpu_props::cpu_flags, indicating a
+ * Little Endian System. If not set in base_cpu_props::cpu_flags, then the
+ * system is Big Endian.
+ *
+ * The compile-time equivalent is @ref OSU_CONFIG_CPU_LITTLE_ENDIAN.
+ */
+#define BASE_CPU_PROPERTY_FLAG_LITTLE_ENDIAN F_BIT_0
+
+
+/**
+ * @brief Platform dynamic CPU ID properties structure
+ */
+typedef struct base_cpu_id_props
+{
+ /**
+ * CPU ID
+ */
+ u32 id;
+
+ /**
+ * CPU Part number
+ */
+ u16 part;
+
+ /**
+ * ASCII code of implementer trademark
+ */
+ u8 implementer;
+
+ /**
+ * CPU Variant
+ */
+ u8 variant;
+
+ /**
+ * CPU Architecture
+ */
+ u8 arch;
+
+ /**
+ * CPU revision
+ */
+ u8 rev;
+
+ u16 padding;
+}base_cpu_id_props;
+
+
+/** @brief Platform Dynamic CPU properties structure */
+typedef struct base_cpu_props {
+ u32 nr_cores; /**< Number of CPU cores */
+
+ /**
+ * CPU page size as a Logarithm to Base 2. The compile-time
+ * equivalent is @ref OSU_CONFIG_CPU_PAGE_SIZE_LOG2
+ */
+ u32 cpu_page_size_log2;
+
+ /**
+ * CPU L1 Data cache line size as a Logarithm to Base 2. The compile-time
+ * equivalent is @ref OSU_CONFIG_CPU_L1_DCACHE_LINE_SIZE_LOG2.
+ */
+ u32 cpu_l1_dcache_line_size_log2;
+
+ /**
+ * CPU L1 Data cache size, in bytes. The compile-time equivalient is
+ * @ref OSU_CONFIG_CPU_L1_DCACHE_SIZE.
+ *
+ * This CPU Property is mainly provided to implement OpenCL's
+ * clGetDeviceInfo(), which allows the CL_DEVICE_GLOBAL_MEM_CACHE_SIZE
+ * hint to be queried.
+ */
+ u32 cpu_l1_dcache_size;
+
+ /**
+ * CPU Property Flags bitpattern.
+ *
+ * This is a combination of bits as specified by the macros prefixed with
+ * 'BASE_CPU_PROPERTY_FLAG_'.
+ */
+ u32 cpu_flags;
+
+ /**
+ * Maximum clock speed in MHz.
+ * @usecase 'Maximum' CPU Clock Speed information is required by OpenCL's
+ * clGetDeviceInfo() function for the CL_DEVICE_MAX_CLOCK_FREQUENCY hint.
+ */
+ u32 max_cpu_clock_speed_mhz;
+
+ /**
+ * @brief Total memory, in bytes.
+ *
+ * This is the theoretical maximum memory available to the CPU. It is
+ * unlikely that a client will be able to allocate all of this memory for
+ * their own purposes, but this at least provides an upper bound on the
+ * memory available to the CPU.
+ *
+ * This is required for OpenCL's clGetDeviceInfo() call when
+ * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL CPU devices.
+ */
+ u64 available_memory_size;
+
+ /**
+ * CPU ID detailed info
+ */
+ base_cpu_id_props cpu_id;
+
+ u32 padding;
+} base_cpu_props;
+/** @} end group basecpuprops */
+
+/** @} end group base_api */
+
+#endif /* _BASE_KERNEL_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/mali_base_kernel_sync.h b/drivers/gpu/arm/t6xx/kbase/mali_base_kernel_sync.h
new file mode 100755
index 00000000000..879872a60af
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/mali_base_kernel_sync.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file
+ * Base cross-proccess sync API.
+ */
+
+#ifndef _BASE_KERNEL_SYNC_H_
+#define _BASE_KERNEL_SYNC_H_
+
+#include <linux/ioctl.h>
+
+#define STREAM_IOC_MAGIC '~'
+
+/* Fence insert.
+ *
+ * Inserts a fence on the stream operated on.
+ * Fence can be waited via a base fence wait soft-job
+ * or triggered via a base fence trigger soft-job.
+ *
+ * Fences must be cleaned up with close when no longer needed.
+ *
+ * No input/output arguments.
+ * Returns
+ * >=0 fd
+ * <0 error code
+ */
+#define STREAM_IOC_FENCE_INSERT _IO(STREAM_IOC_MAGIC, 0)
+
+#endif /* _BASE_KERNEL_SYNC_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/mali_kbase_config.h b/drivers/gpu/arm/t6xx/kbase/mali_kbase_config.h
new file mode 100755
index 00000000000..c83e769ef04
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/mali_kbase_config.h
@@ -0,0 +1,856 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_config.h
+ * Configuration API and Attributes for KBase
+ */
+
+#ifndef _KBASE_CONFIG_H_
+#define _KBASE_CONFIG_H_
+
+#include <malisw/mali_stdtypes.h>
+
+/**
+ * @addtogroup base_api
+ * @{
+ */
+
+/**
+ * @addtogroup base_kbase_api
+ * @{
+ */
+
+/**
+ * @addtogroup kbase_config Configuration API and Attributes
+ * @{
+ */
+
+#if MALI_CUSTOMER_RELEASE == 0
+/* This flag is set for internal builds so we can run tests without credentials. */
+#define KBASE_HWCNT_DUMP_BYPASS_ROOT 1
+#else
+#define KBASE_HWCNT_DUMP_BYPASS_ROOT 0
+#endif
+
+#include <linux/rbtree.h>
+
+/**
+ * Relative memory performance indicators. Enum elements should always be defined in slowest to fastest order.
+ */
+typedef enum kbase_memory_performance {
+ KBASE_MEM_PERF_SLOW,
+ KBASE_MEM_PERF_NORMAL,
+ KBASE_MEM_PERF_FAST,
+
+ KBASE_MEM_PERF_MAX_VALUE = KBASE_MEM_PERF_FAST
+} kbase_memory_performance;
+
+/**
+ * Device wide configuration
+ */
+enum {
+ /**
+ * Invalid attribute ID (reserve 0).
+ *
+ * Attached value: Ignored
+ * Default value: NA
+ * */
+ KBASE_CONFIG_ATTR_INVALID,
+
+ /**
+ * Memory resource object.
+ * Multiple resources can be listed.
+ * The resources will be used in the order listed
+ * in the configuration attribute list if they have no other
+ * preferred order based on the memory resource property list
+ * (see ::kbase_memory_attribute).
+ *
+ * Attached value: Pointer to a kbase_memory_resource object.
+ * Default value: No resources
+ * */
+
+ KBASE_CONFIG_ATTR_MEMORY_RESOURCE,
+ /**
+ * Maximum of memory which can be allocated from the OS
+ * to be used by the GPU (shared memory).
+ * This must be greater than 0 as the GPU page tables
+ * are currently stored in a shared memory allocation.
+ *
+ * Attached value: number in bytes
+ * Default value: Limited by available memory
+ */
+ KBASE_CONFIG_ATTR_MEMORY_OS_SHARED_MAX,
+
+ /**
+ * Relative performance for the GPU to access
+ * OS shared memory.
+ *
+ * Attached value: ::kbase_memory_performance member
+ * Default value: ::KBASE_MEM_PERF_NORMAL
+ */
+ KBASE_CONFIG_ATTR_MEMORY_OS_SHARED_PERF_GPU,
+
+ /**
+ * Limit (in bytes) the amount of memory a single process
+ * can allocate across all memory banks (including OS shared memory)
+ * for use by the GPU.
+ *
+ * Attached value: number in bytes
+ * Default value: Limited by available memory
+ */
+ KBASE_CONFIG_ATTR_MEMORY_PER_PROCESS_LIMIT,
+
+ /**
+ * UMP device mapping.
+ * Which UMP device this GPU should be mapped to.
+ *
+ * Attached value: UMP_DEVICE_<device>_SHIFT
+ * Default value: UMP_DEVICE_W_SHIFT
+ */
+ KBASE_CONFIG_ATTR_UMP_DEVICE,
+
+ /**
+ * Maximum frequency GPU will be clocked at. Given in kHz.
+ * This must be specified as there is no default value.
+ *
+ * Attached value: number in kHz
+ * Default value: NA
+ */
+ KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX,
+
+ /**
+ * Minimum frequency GPU will be clocked at. Given in kHz.
+ * This must be specified as there is no default value.
+ *
+ * Attached value: number in kHz
+ * Default value: NA
+ */
+ KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MIN,
+
+ /**
+ * Irq throttle. It is the minimum desired time in between two
+ * consecutive gpu interrupts (given in 'us'). The irq throttle
+ * gpu register will be configured after this, taking into
+ * account the configured max frequency.
+ *
+ * Attached value: number in micro seconds
+ * Default value: see DEFAULT_IRQ_THROTTLE_TIME_US
+ */
+ KBASE_CONFIG_ATTR_GPU_IRQ_THROTTLE_TIME_US,
+
+ /*** Begin Job Scheduling Configs ***/
+ /**
+ * Job Scheduler scheduling tick granuality. This is in nanoseconds to
+ * allow HR timer support.
+ *
+ * On each scheduling tick, the scheduler may decide to:
+ * -# soft stop a job (the job will be re-run later, and other jobs will
+ * be able to run on the GPU now). This effectively controls the
+ * 'timeslice' given to a job.
+ * -# hard stop a job (to kill a job if it has spent too long on the GPU
+ * and didn't soft-stop).
+ *
+ * The numbers of ticks for these events are controlled by:
+ * - @ref KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS
+ * - @ref KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS
+ * - @ref KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS
+ *
+ * A soft-stopped job will later be resumed, allowing it to use more GPU
+ * time <em>in total</em> than that defined by any of the above. However,
+ * the scheduling policy attempts to limit the amount of \em uninterrupted
+ * time spent on the GPU using the above values (that is, the 'timeslice'
+ * of a job)
+ *
+ * This value is supported by the following scheduling policies:
+ * - The Completely Fair Share (CFS) policy
+ *
+ * Attached value: unsigned 32-bit kbasep_js_device_data::scheduling_tick_ns.
+ * The value might be rounded down to lower precision. Must be non-zero
+ * after rounding.<br>
+ * Default value: @ref DEFAULT_JS_SCHEDULING_TICK_NS
+ *
+ * @note this value is allowed to be greater than
+ * @ref KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS. This allows jobs to run on (much)
+ * longer than the job-timeslice, but once this happens, the context gets
+ * scheduled in (much) less frequently than others that stay within the
+ * ctx-timeslice.
+ */
+ KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS,
+
+ /**
+ * Job Scheduler minimum number of scheduling ticks before jobs are soft-stopped.
+ *
+ * This defines the amount of time a job is allowed to stay on the GPU,
+ * before it is soft-stopped to allow other jobs to run.
+ *
+ * That is, this defines the 'timeslice' of the job. It is separate from the
+ * timeslice of the context that contains the job (see
+ * @ref KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS).
+ *
+ * This value is supported by the following scheduling policies:
+ * - The Completely Fair Share (CFS) policy
+ *
+ * Attached value: unsigned 32-bit kbasep_js_device_data::soft_stop_ticks<br>
+ * Default value: @ref DEFAULT_JS_SOFT_STOP_TICKS
+ *
+ * @note a value of zero means "the quickest time to soft-stop a job",
+ * which is somewhere between instant and one tick later.
+ *
+ * @note this value is allowed to be greater than
+ * @ref KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS or
+ * @ref KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS. This effectively disables
+ * soft-stop, and just uses hard-stop instead. In this case, this value
+ * should be much greater than any of the hard stop values (to avoid
+ * soft-stop-after-hard-stop)
+ *
+ * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS
+ */
+ KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS,
+
+ /**
+ * Job Scheduler minimum number of scheduling ticks before jobs are hard-stopped.
+ *
+ * This defines the amount of time a job is allowed to spend on the GPU before it
+ * is killed. Such jobs won't be resumed if killed.
+ *
+ * This value is supported by the following scheduling policies:
+ * - The Completely Fair Share (CFS) policy
+ *
+ * Attached value: unsigned 32-bit kbasep_js_device_data::hard_stop_ticks_ss<br>
+ * Default value: @ref DEFAULT_JS_HARD_STOP_TICKS_SS
+ *
+ * @note a value of zero means "the quickest time to hard-stop a job",
+ * which is somewhere between instant and one tick later.
+ *
+ * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS
+ */
+ KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS,
+
+ /**
+ * Job Scheduler minimum number of scheduling ticks before jobs are hard-stopped
+ * when dumping.
+ *
+ * This defines the amount of time a job is allowed to spend on the GPU before it
+ * is killed. Such jobs won't be resumed if killed.
+ *
+ * This value is supported by the following scheduling policies:
+ * - The Completely Fair Share (CFS) policy
+ *
+ * Attached value: unsigned 32-bit kbasep_js_device_data::hard_stop_ticks_nss<br>
+ * Default value: @ref DEFAULT_JS_HARD_STOP_TICKS_NSS
+ *
+ * @note a value of zero means "the quickest time to hard-stop a job",
+ * which is somewhere between instant and one tick later.
+ *
+ * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS
+ */
+ KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS,
+
+ /**
+ * Job Scheduler timeslice that a context is scheduled in for, in nanoseconds.
+ *
+ * When a context has used up this amount of time across its jobs, it is
+ * scheduled out to let another run.
+ *
+ * @note the resolution is nanoseconds (ns) here, because that's the format
+ * often used by the OS.
+ *
+ * This value controls affects the actual time defined by the following
+ * config values:
+ * - @ref KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_INIT_SLICES
+ * - @ref KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_MIN_SLICES
+ *
+ * This value is supported by the following scheduling policies:
+ * - The Completely Fair Share (CFS) policy
+ *
+ * Attached value: unsigned 32-bit kbasep_js_device_data::ctx_timeslice_ns.
+ * The value might be rounded down to lower precision.<br>
+ * Default value: @ref DEFAULT_JS_CTX_TIMESLICE_NS
+ *
+ * @note a value of zero models a "Round Robin" scheduling policy, and
+ * disables @ref KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_INIT_SLICES
+ * (initially causing LIFO scheduling) and
+ * @ref KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_MIN_SLICES (allowing
+ * not-run-often contexts to get scheduled in quickly, but to only use
+ * a single timeslice when they get scheduled in).
+ */
+ KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS,
+
+ /**
+ * Job Scheduler initial runtime of a context for the CFS Policy, in time-slices.
+ *
+ * This value is relative to that of the least-run context, and defines
+ * where in the CFS queue a new context is added. A value of 1 means 'after
+ * the least-run context has used its timeslice'. Therefore, when all
+ * contexts consistently use the same amount of time, a value of 1 models a
+ * FIFO. A value of 0 would model a LIFO.
+ *
+ * The value is represented in "numbers of time slices". Multiply this
+ * value by that defined in @ref KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS to get
+ * the time value for this in nanoseconds.
+ *
+ * Attached value: unsigned 32-bit kbasep_js_device_data::cfs_ctx_runtime_init_slices<br>
+ * Default value: @ref DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES
+ */
+ KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_INIT_SLICES,
+
+ /**
+ * Job Scheduler minimum runtime value of a context for CFS, in time_slices
+ * relative to that of the least-run context.
+ *
+ * This is a measure of how much preferrential treatment is given to a
+ * context that is not run very often.
+ *
+ * Specficially, this value defines how many timeslices such a context is
+ * (initially) allowed to use at once. Such contexts (e.g. 'interactive'
+ * processes) will appear near the front of the CFS queue, and can initially
+ * use more time than contexts that run continuously (e.g. 'batch'
+ * processes).
+ *
+ * This limit \b prevents a "stored-up timeslices" DoS attack, where a ctx
+ * not run for a long time attacks the system by using a very large initial
+ * number of timeslices when it finally does run.
+ *
+ * Attached value: unsigned 32-bit kbasep_js_device_data::cfs_ctx_runtime_min_slices<br>
+ * Default value: @ref DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES
+ *
+ * @note A value of zero allows not-run-often contexts to get scheduled in
+ * quickly, but to only use a single timeslice when they get scheduled in.
+ */
+ KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_MIN_SLICES,
+
+ /**
+ * Job Scheduler minimum number of scheduling ticks before jobs cause the GPU to be
+ * reset.
+ *
+ * This defines the amount of time a job is allowed to spend on the GPU before it
+ * is assumed that the GPU has hung and needs to be reset. The assumes that the job
+ * has been hard-stopped already and so the presence of a job that has remained on
+ * the GPU for so long indicates that the GPU has in some way hung.
+ *
+ * This value is supported by the following scheduling policies:
+ * - The Completely Fair Share (CFS) policy
+ *
+ * Attached value: unsigned 32-bit kbasep_js_device_data::gpu_reset_ticks_nss<br>
+ * Default value: @ref DEFAULT_JS_RESET_TICKS_SS
+ *
+ * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS
+ */
+ KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS,
+
+ /**
+ * Job Scheduler minimum number of scheduling ticks before jobs cause the GPU to be
+ * reset when dumping.
+ *
+ * This defines the amount of time a job is allowed to spend on the GPU before it
+ * is assumed that the GPU has hung and needs to be reset. The assumes that the job
+ * has been hard-stopped already and so the presence of a job that has remained on
+ * the GPU for so long indicates that the GPU has in some way hung.
+ *
+ * This value is supported by the following scheduling policies:
+ * - The Completely Fair Share (CFS) policy
+ *
+ * Attached value: unsigned 32-bit kbasep_js_device_data::gpu_reset_ticks_nss<br>
+ * Default value: @ref DEFAULT_JS_RESET_TICKS_NSS
+ *
+ * @see KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS
+ */
+ KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS,
+
+ /**
+ * Number of milliseconds given for other jobs on the GPU to be
+ * soft-stopped when the GPU needs to be reset.
+ *
+ * Attached value: number in milliseconds
+ * Default value: @ref DEFAULT_JS_RESET_TIMEOUT_MS
+ */
+ KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS,
+ /*** End Job Scheduling Configs ***/
+
+ /** Power management configuration
+ *
+ * Attached value: pointer to @ref kbase_pm_callback_conf
+ * Default value: See @ref kbase_pm_callback_conf
+ */
+ KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS,
+
+ /**
+ * Boolean indicating whether the driver is configured to be secure at
+ * a potential loss of performance.
+ *
+ * This currently affects only r0p0-15dev0 HW and earlier.
+ *
+ * On r0p0-15dev0 HW and earlier, there are tradeoffs between security and
+ * performance:
+ *
+ * - When this is set to MALI_TRUE, the driver remains fully secure,
+ * but potentially loses performance compared with setting this to
+ * MALI_FALSE.
+ * - When set to MALI_FALSE, the driver is open to certain security
+ * attacks.
+ *
+ * From r0p0-00rel0 and onwards, there is no security loss by setting
+ * this to MALI_FALSE, and no performance loss by setting it to
+ * MALI_TRUE.
+ *
+ * Attached value: mali_bool value
+ * Default value: @ref DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE
+ */
+ KBASE_CONFIG_ATTR_SECURE_BUT_LOSS_OF_PERFORMANCE,
+
+ /**
+ * A pointer to a function that calculates the CPU clock
+ * speed of the platform in MHz - see
+ * @ref kbase_cpuprops_clock_speed_function for the function
+ * prototype.
+ *
+ * Attached value: A @ref kbase_cpuprops_clock_speed_function.
+ * Default Value: Pointer to @ref DEFAULT_CPU_SPEED_FUNC -
+ * returns a clock speed of 100 MHz.
+ */
+ KBASE_CONFIG_ATTR_CPU_SPEED_FUNC,
+
+ /**
+ * A pointer to a function that calculates the GPU clock
+ * speed of the platform in MHz - see
+ * @ref kbase_gpuprops_clock_speed_function for the function
+ * prototype.
+ *
+ * Attached value: A @ref kbase_gpuprops_clock_speed_function.
+ * Default Value: NULL (in which case the driver assumes a current
+ * GPU frequency specified by KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX)
+ */
+ KBASE_CONFIG_ATTR_GPU_SPEED_FUNC,
+
+ /**
+ * Platform specific configuration functions
+ *
+ * Attached value: pointer to @ref kbase_platform_funcs_conf
+ * Default value: See @ref kbase_platform_funcs_conf
+ */
+ KBASE_CONFIG_ATTR_PLATFORM_FUNCS,
+
+ /**
+ * Limit ARID width on the AXI bus.
+ *
+ * Attached value: u32 register value
+ * KBASE_AID_32 - use the full 32 IDs (5 ID bits)
+ * KBASE_AID_16 - use 16 IDs (4 ID bits)
+ * KBASE_AID_8 - use 8 IDs (3 ID bits)
+ * KBASE_AID_4 - use 4 IDs (2 ID bits)
+ * Default value: KBASE_AID_32 (no limit). Note hardware implementation
+ * may limit to a lower value.
+ */
+ KBASE_CONFIG_ATTR_ARID_LIMIT,
+
+ /**
+ * Limit AWID width on the AXI bus.
+ *
+ * Attached value: u32 register value
+ * KBASE_AID_32 - use the full 32 IDs (5 ID bits)
+ * KBASE_AID_16 - use 16 IDs (4 ID bits)
+ * KBASE_AID_8 - use 8 IDs (3 ID bits)
+ * KBASE_AID_4 - use 4 IDs (2 ID bits)
+ * Default value: KBASE_AID_32 (no limit). Note hardware implementation
+ * may limit to a lower value.
+ */
+ KBASE_CONFIG_ATTR_AWID_LIMIT,
+
+ /**
+ * Enable alternative hardware counter capture for the Mali shader cores.
+ *
+ * Attached value: mali_bool value
+ * Default value: @ref MALI_FALSE
+ */
+ KBASE_CONFIG_ATTR_ALTERNATIVE_HWC,
+
+ /**
+ * Rate at which dvfs data should be collected.
+ *
+ * Attached value: u32 value
+ * Default value: 500 Milliseconds
+ */
+ KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ,
+
+ /**
+ * Power Management poweroff tick granuality. This is in nanoseconds to
+ * allow HR timer support.
+ *
+ * On each scheduling tick, the power manager core may decide to:
+ * -# Power off one or more shader cores
+ * -# Power off the entire GPU
+ *
+ * Attached value: number in nanoseconds
+ * Default value: @ref DEFAULT_PM_GPU_POWEROFF_TICK_NS,
+ */
+ KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS,
+
+ /**
+ * Power Manager number of ticks before shader cores are powered off
+ *
+ * Attached value: unsigned 32-bit kbasep_pm_device_data::poweroff_shader_ticks<br>
+ * Default value: @ref DEFAULT_PM_POWEROFF_TICK_SHADER
+ *
+ * @see KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS
+ */
+ KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER,
+
+ /**
+ * Power Manager number of ticks before GPU is powered off
+ *
+ * Attached value: unsigned 32-bit kbasep_pm_device_data::poweroff_gpu_ticks<br>
+ * Default value: @ref DEFAULT_PM_POWEROFF_TICK_GPU
+ *
+ * @see KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS
+ */
+ KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU,
+
+ /**
+ * End of attribute list indicator.
+ * The configuration loader will stop processing any more elements
+ * when it encounters this attribute.
+ *
+ * Default value: NA
+ */
+ KBASE_CONFIG_ATTR_END = 0x1FFFUL
+};
+
+enum {
+ /**
+ * Invalid attribute ID (reserve 0).
+ *
+ * Attached value: Ignored
+ * Default value: NA
+ */
+ KBASE_MEM_ATTR_INVALID,
+
+ /**
+ * Relative performance for the CPU to access
+ * the memory resource.
+ *
+ * Attached value: ::kbase_memory_performance member
+ * Default value: ::KBASE_MEM_PERF_NORMAL
+ */
+ KBASE_MEM_ATTR_PERF_CPU,
+
+ /**
+ * Relative performance for the GPU to access
+ * the memory resource.
+ *
+ * Attached value: ::kbase_memory_performance member
+ * Default value: ::KBASE_MEM_PERF_NORMAL
+ */
+ KBASE_MEM_ATTR_PERF_GPU,
+
+ /**
+ * End of attribute list indicator.
+ * The memory resource loader will stop processing any more
+ * elements when it encounters this attribute.
+ *
+ * Attached value: Ignored
+ * Default value: NA
+ */
+ KBASE_MEM_ATTR_END = 0x1FFFUL
+};
+
+enum {
+ /**
+ * Use unrestricted Address ID width on the AXI bus.
+ */
+ KBASE_AID_32 = 0x0,
+
+ /**
+ * Restrict GPU to a half of maximum Address ID count.
+ * This will reduce performance, but reduce bus load due to GPU.
+ */
+ KBASE_AID_16 = 0x3,
+
+ /**
+ * Restrict GPU to a quarter of maximum Address ID count.
+ * This will reduce performance, but reduce bus load due to GPU.
+ */
+ KBASE_AID_8 = 0x2,
+
+ /**
+ * Restrict GPU to an eighth of maximum Address ID count.
+ * This will reduce performance, but reduce bus load due to GPU.
+ */
+ KBASE_AID_4 = 0x1
+};
+
+/*
+ * @brief specifies a single attribute
+ *
+ * Attribute is identified by attr field. Data is either integer or a pointer to attribute-specific structure.
+ */
+typedef struct kbase_attribute {
+ int id;
+ uintptr_t data;
+} kbase_attribute;
+
+/*
+ * @brief Specifies dedicated memory bank
+ *
+ * Specifies base, size and attributes of a memory bank
+ */
+typedef struct kbase_memory_resource {
+ u64 base;
+ u64 size;
+ struct kbase_attribute *attributes;
+ const char *name;
+} kbase_memory_resource;
+
+/* Forward declaration of kbase_device */
+struct kbase_device;
+
+/*
+ * @brief Specifies the functions for platform specific initialization and termination
+ *
+ * By default no functions are required. No additional platform specific control is necessary.
+ */
+typedef struct kbase_platform_funcs_conf {
+ /**
+ * Function pointer for platform specific initialization or NULL if no initialization function is required.
+ * This function will be called \em before any other callbacks listed in the kbase_attribute struct (such as
+ * Power Management callbacks).
+ * The platform specific private pointer kbase_device::platform_context can be accessed (and possibly initialized) in here.
+ */
+ mali_bool(*platform_init_func) (struct kbase_device *kbdev);
+ /**
+ * Function pointer for platform specific termination or NULL if no termination function is required.
+ * This function will be called \em after any other callbacks listed in the kbase_attribute struct (such as
+ * Power Management callbacks).
+ * The platform specific private pointer kbase_device::platform_context can be accessed (and possibly terminated) in here.
+ */
+ void (*platform_term_func) (struct kbase_device *kbdev);
+
+} kbase_platform_funcs_conf;
+
+/*
+ * @brief Specifies the callbacks for power management
+ *
+ * By default no callbacks will be made and the GPU must not be powered off.
+ */
+typedef struct kbase_pm_callback_conf {
+ /** Callback for when the GPU is idle and the power to it can be switched off.
+ *
+ * The system integrator can decide whether to either do nothing, just switch off
+ * the clocks to the GPU, or to completely power down the GPU.
+ * The platform specific private pointer kbase_device::platform_context can be accessed and modified in here. It is the
+ * platform \em callbacks responsiblity to initialize and terminate this pointer if used (see @ref kbase_platform_funcs_conf).
+ */
+ void (*power_off_callback) (struct kbase_device *kbdev);
+
+ /** Callback for when the GPU is about to become active and power must be supplied.
+ *
+ * This function must not return until the GPU is powered and clocked sufficiently for register access to
+ * succeed. The return value specifies whether the GPU was powered down since the call to power_off_callback.
+ * If the GPU state has been lost then this function must return 1, otherwise it should return 0.
+ * The platform specific private pointer kbase_device::platform_context can be accessed and modified in here. It is the
+ * platform \em callbacks responsiblity to initialize and terminate this pointer if used (see @ref kbase_platform_funcs_conf).
+ *
+ * The return value of the first call to this function is ignored.
+ *
+ * @return 1 if the GPU state may have been lost, 0 otherwise.
+ */
+ int (*power_on_callback) (struct kbase_device *kbdev);
+
+ /** Callback for handling runtime power management initialization.
+ *
+ * The runtime power management callbacks @ref power_runtime_off_callback and @ref power_runtime_on_callback
+ * will become active from calls made to the OS from within this function.
+ * The runtime calls can be triggered by calls from @ref power_off_callback and @ref power_on_callback.
+ * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature.
+ *
+ * @return MALI_ERROR_NONE on success, else mali_error erro code.
+ */
+ mali_error(*power_runtime_init_callback) (struct kbase_device *kbdev);
+
+ /** Callback for handling runtime power management termination.
+ *
+ * The runtime power management callbacks @ref power_runtime_off_callback and @ref power_runtime_on_callback
+ * should no longer be called by the OS on completion of this function.
+ * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature.
+ */
+ void (*power_runtime_term_callback) (struct kbase_device *kbdev);
+
+ /** Callback for runtime power-off power management callback
+ *
+ * For linux this callback will be called by the kernel runtime_suspend callback.
+ * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature.
+ *
+ * @return 0 on success, else OS error code.
+ */
+ void (*power_runtime_off_callback) (struct kbase_device *kbdev);
+
+ /** Callback for runtime power-on power management callback
+ *
+ * For linux this callback will be called by the kernel runtime_resume callback.
+ * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature.
+ */
+ int (*power_runtime_on_callback) (struct kbase_device *kbdev);
+
+} kbase_pm_callback_conf;
+
+/**
+ * Type of the function pointer for KBASE_CONFIG_ATTR_CPU_SPEED_FUNC.
+ *
+ * @param clock_speed [out] Once called this will contain the current CPU clock speed in MHz.
+ * This is mainly used to implement OpenCL's clGetDeviceInfo().
+ *
+ * @return 0 on success, 1 on error.
+ */
+typedef int (*kbase_cpuprops_clock_speed_function) (u32 *clock_speed);
+
+/**
+ * Type of the function pointer for KBASE_CONFIG_ATTR_GPU_SPEED_FUNC.
+ *
+ * @param clock_speed [out] Once called this will contain the current GPU clock speed in MHz.
+ * If the system timer is not available then this function is required
+ * for the OpenCL queue profiling to return correct timing information.
+ *
+ * @return 0 on success, 1 on error. When an error is returned the caller assumes a current
+ * GPU speed as specified by KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX.
+ */
+typedef int (*kbase_gpuprops_clock_speed_function) (u32 *clock_speed);
+
+#ifdef CONFIG_MALI_PLATFORM_FAKE
+/*
+ * @brief Specifies start and end of I/O memory region.
+ */
+typedef struct kbase_io_memory_region {
+ u64 start;
+ u64 end;
+} kbase_io_memory_region;
+
+/*
+ * @brief Specifies I/O related resources like IRQs and memory region for I/O operations.
+ */
+typedef struct kbase_io_resources {
+ u32 job_irq_number;
+ u32 mmu_irq_number;
+ u32 gpu_irq_number;
+ kbase_io_memory_region io_memory_region;
+} kbase_io_resources;
+
+typedef struct kbase_platform_config {
+ const kbase_attribute *attributes;
+ const kbase_io_resources *io_resources;
+ u32 midgard_type;
+} kbase_platform_config;
+
+#endif /* CONFIG_MALI_PLATFORM_FAKE */
+/**
+ * @brief Return character string associated with the given midgard type.
+ *
+ * @param[in] midgard_type - ID of midgard type
+ *
+ * @return Pointer to NULL-terminated character array associated with the given midgard type
+ */
+const char *kbasep_midgard_type_to_string(u32 midgard_type);
+
+/**
+ * @brief Gets the count of attributes in array
+ *
+ * Function gets the count of attributes in array. Note that end of list indicator is also included.
+ *
+ * @param[in] attributes Array of attributes
+ *
+ * @return Number of attributes in the array including end of list indicator.
+ */
+int kbasep_get_config_attribute_count(const kbase_attribute *attributes);
+
+/**
+ * @brief Gets the next config attribute with the specified ID from the array of attributes.
+ *
+ * Function gets the next attribute with specified attribute id within specified array. If no such attribute is found,
+ * NULL is returned.
+ *
+ * @param[in] attributes Array of attributes in which lookup is performed
+ * @param[in] attribute_id ID of attribute
+ *
+ * @return Pointer to the first attribute matching id or NULL if none is found.
+ */
+const kbase_attribute *kbasep_get_next_attribute(const kbase_attribute *attributes, int attribute_id);
+
+/**
+ * @brief Gets the value of a single config attribute.
+ *
+ * Function gets the value of attribute specified as parameter. If no such attribute is found in the array of
+ * attributes, default value is used.
+ *
+ * @param[in] kbdev Kbase device pointer
+ * @param[in] attributes Array of attributes in which lookup is performed
+ * @param[in] attribute_id ID of attribute
+ *
+ * @return Value of attribute with the given id
+ */
+uintptr_t kbasep_get_config_value(struct kbase_device *kbdev, const kbase_attribute *attributes, int attribute_id);
+
+/**
+ * @brief Validates configuration attributes
+ *
+ * Function checks validity of given configuration attributes. It will fail on any attribute with unknown id, attribute
+ * with invalid value or attribute list that is not correctly terminated. It will also fail if
+ * KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MIN or KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX are not specified.
+ *
+ * @param[in] kbdev Kbase device pointer
+ * @param[in] attributes Array of attributes to validate
+ *
+ * @return MALI_TRUE if no errors have been found in the config. MALI_FALSE otherwise.
+ */
+mali_bool kbasep_validate_configuration_attributes(struct kbase_device *kbdev, const kbase_attribute *attributes);
+
+#ifdef CONFIG_MALI_PLATFORM_FAKE
+/**
+ * @brief Gets the pointer to platform config.
+ *
+ * @return Pointer to the platform config
+ */
+kbase_platform_config *kbase_get_platform_config(void);
+#endif /* CONFIG_MALI_PLATFORM_FAKE */
+
+/**
+ * @brief Platform specific call to initialize hardware
+ *
+ * Function calls a platform defined routine if specified in the configuration attributes.
+ * The routine can initialize any hardware and context state that is required for the GPU block to function.
+ *
+ * @param[in] kbdev Kbase device pointer
+ *
+ * @return MALI_TRUE if no errors have been found in the config. MALI_FALSE otherwise.
+ */
+mali_bool kbasep_platform_device_init(struct kbase_device *kbdev);
+
+/**
+ * @brief Platform specific call to terminate hardware
+ *
+ * Function calls a platform defined routine if specified in the configuration attributes.
+ * The routine can destroy any platform specific context state and shut down any hardware functionality that are
+ * outside of the Power Management callbacks.
+ *
+ * @param[in] kbdev Kbase device pointer
+ *
+ */
+void kbasep_platform_device_term(struct kbase_device *kbdev);
+
+ /** @} *//* end group kbase_config */
+ /** @} *//* end group base_kbase_api */
+ /** @} *//* end group base_api */
+
+#endif /* _KBASE_CONFIG_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/mali_kbase_debug.h b/drivers/gpu/arm/t6xx/kbase/mali_kbase_debug.h
new file mode 100755
index 00000000000..40e930488b9
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/mali_kbase_debug.h
@@ -0,0 +1,226 @@
+/*
+ *
+ * (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _KBASE_DEBUG_H
+#define _KBASE_DEBUG_H
+
+#include <linux/bug.h>
+
+/** @brief If equals to 0, a trace containing the file, line, and function will be displayed before each message. */
+#define KBASE_DEBUG_SKIP_TRACE 0
+
+/** @brief If different from 0, the trace will only contain the file and line. */
+#define KBASE_DEBUG_SKIP_FUNCTION_NAME 0
+
+/** @brief Disable the asserts tests if set to 1. Default is to disable the asserts in release. */
+#ifndef KBASE_DEBUG_DISABLE_ASSERTS
+#ifdef CONFIG_MALI_DEBUG
+#define KBASE_DEBUG_DISABLE_ASSERTS 0
+#else
+#define KBASE_DEBUG_DISABLE_ASSERTS 1
+#endif
+#endif /* KBASE_DEBUG_DISABLE_ASSERTS */
+
+typedef enum {
+ KBASE_UNKNOWN = 0, /**< @brief Unknown module */
+ KBASE_MMU, /**< @brief ID of Base MMU */
+ KBASE_JD, /**< @brief ID of Base Job Dispatch */
+ KBASE_JM, /**< @brief ID of Base Job Manager */
+ KBASE_CORE, /**< @brief ID of Base Core */
+ KBASE_MEM, /**< @brief ID of Base Memory */
+ KBASE_EVENT, /**< @brief ID of Base Event */
+ KBASE_CTX, /**< @brief ID of Base Context */
+ KBASE_PM, /**< @brief ID of Base Power Management */
+ KBASE_MODULES_ALL /**< @brief Select all the modules at once / Also gives the number of modules in the enum */
+} kbase_module;
+
+/** Function type that is called on an KBASE_DEBUG_ASSERT() or KBASE_DEBUG_ASSERT_MSG() */
+typedef void (kbase_debug_assert_hook) (void *);
+
+typedef struct kbasep_debug_assert_cb {
+ kbase_debug_assert_hook *func;
+ void *param;
+} kbasep_debug_assert_cb;
+
+/**
+ * @def KBASEP_DEBUG_PRINT_TRACE
+ * @brief Private macro containing the format of the trace to display before every message
+ * @sa KBASE_DEBUG_SKIP_TRACE, KBASE_DEBUG_SKIP_FUNCTION_NAME
+ */
+#if KBASE_DEBUG_SKIP_TRACE == 0
+#define KBASEP_DEBUG_PRINT_TRACE \
+ "In file: " __FILE__ " line: " CSTD_STR2(__LINE__)
+#if KBASE_DEBUG_SKIP_FUNCTION_NAME == 0
+#define KBASEP_DEBUG_PRINT_FUNCTION CSTD_FUNC
+#else
+#define KBASEP_DEBUG_PRINT_FUNCTION ""
+#endif
+#else
+#define KBASEP_DEBUG_PRINT_TRACE ""
+#endif
+
+/**
+ * @def KBASEP_DEBUG_ASSERT_OUT(trace, function, ...)
+ * @brief (Private) system printing function associated to the @see KBASE_DEBUG_ASSERT_MSG event.
+ * @param trace location in the code from where the message is printed
+ * @param function function from where the message is printed
+ * @param ... Format string followed by format arguments.
+ * @note function parameter cannot be concatenated with other strings
+ */
+/* Select the correct system output function*/
+#ifdef CONFIG_MALI_DEBUG
+#define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...)\
+ do { \
+ printk(KERN_ERR "Mali<ASSERT>: %s function:%s ", trace, function);\
+ printk(KERN_ERR __VA_ARGS__);\
+ printk(KERN_ERR "\n");\
+ } while (MALI_FALSE)
+#else
+#define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) CSTD_NOP()
+#endif
+
+#ifdef CONFIG_MALI_DEBUG
+#define KBASE_CALL_ASSERT_HOOK() kbasep_debug_assert_call_hook();
+#else
+#define KBASE_CALL_ASSERT_HOOK() CSTD_NOP();
+#endif
+
+/**
+ * @def KBASE_DEBUG_ASSERT(expr)
+ * @brief Calls @see KBASE_PRINT_ASSERT and prints the expression @a expr if @a expr is false
+ *
+ * @note This macro does nothing if the flag @see KBASE_DEBUG_DISABLE_ASSERTS is set to 1
+ *
+ * @param expr Boolean expression
+ */
+#define KBASE_DEBUG_ASSERT(expr) \
+ KBASE_DEBUG_ASSERT_MSG(expr, #expr)
+
+#if KBASE_DEBUG_DISABLE_ASSERTS
+#define KBASE_DEBUG_ASSERT_MSG(expr, ...) CSTD_NOP()
+#else
+ /**
+ * @def KBASE_DEBUG_ASSERT_MSG(expr, ...)
+ * @brief Calls @see KBASEP_DEBUG_ASSERT_OUT and prints the given message if @a expr is false
+ *
+ * @note This macro does nothing if the flag @see KBASE_DEBUG_DISABLE_ASSERTS is set to 1
+ *
+ * @param expr Boolean expression
+ * @param ... Message to display when @a expr is false, as a format string followed by format arguments.
+ */
+#define KBASE_DEBUG_ASSERT_MSG(expr, ...) \
+ do { \
+ if (MALI_FALSE == (expr)) { \
+ KBASEP_DEBUG_ASSERT_OUT(KBASEP_DEBUG_PRINT_TRACE, KBASEP_DEBUG_PRINT_FUNCTION, __VA_ARGS__);\
+ KBASE_CALL_ASSERT_HOOK();\
+ BUG();\
+ } \
+ } while (MALI_FALSE)
+#endif /* KBASE_DEBUG_DISABLE_ASSERTS */
+
+/**
+ * @def KBASEP_DEBUG_WARN_OUT(module, trace, ...)
+ * @brief (Private) system printing function associated to the @see KBASE_DEBUG_PRINT_WARN event.
+ * @param module module ID
+ * @param trace location in the code from where the message is printed
+ * @param function function from where the message is printed
+ * @param ... Format string followed by format arguments.
+ * @note function parameter cannot be concatenated with other strings
+ */
+#ifdef CONFIG_MALI_DEBUG
+#define KBASE_DEBUG_PRINT_WARN(module, ...)\
+ do {\
+ printk(KERN_WARNING "Mali<WARN, %s>: %s function:%s ", kbasep_debug_module_to_str(module), KBASEP_DEBUG_PRINT_TRACE, KBASEP_DEBUG_PRINT_FUNCTION);\
+ printk(KERN_WARNING __VA_ARGS__);\
+ printk(KERN_WARNING "\n");\
+ } while (MALI_FALSE)
+#else
+#define KBASE_DEBUG_PRINT_WARN(module, ...) CSTD_NOP()
+#endif
+
+#define KBASE_DEBUG_PRINT_ERROR(module, ...)\
+ do {\
+ printk(KERN_ERR "Mali<ERROR, %s>: %s function:%s ", kbasep_debug_module_to_str(module), KBASEP_DEBUG_PRINT_TRACE, KBASEP_DEBUG_PRINT_FUNCTION);\
+ printk(KERN_ERR __VA_ARGS__);\
+ printk(KERN_ERR "\n");\
+ } while (MALI_FALSE)
+
+/*If this is not disabled then Android boot times out*/
+#define KBASE_DEBUG_PRINT_INFO(module, ...) CSTD_NOP()
+
+#define KBASE_DEBUG_PRINT_RAW(module, ...)\
+ do {\
+ printk(__VA_ARGS__);\
+ printk("\n");\
+ } while (MALI_FALSE)
+
+#define KBASE_DEBUG_PRINT_RAW_LEVEL(level, module, ...)\
+ do {\
+ printk(level __VA_ARGS__);\
+ printk(level "\n");\
+ } while (MALI_FALSE)
+
+#define KBASE_DEBUG_PRINT(module, ...) KBASE_DEBUG_PRINT_RAW(module, __VA_ARGS__)
+
+/**
+ * @def KBASE_DEBUG_CODE( X )
+ * @brief Executes the code inside the macro only in debug mode
+ *
+ * @param X Code to compile only in debug mode.
+ */
+#ifdef CONFIG_MALI_DEBUG
+#define KBASE_DEBUG_CODE(X) X
+#else
+#define KBASE_DEBUG_CODE(X) CSTD_NOP()
+#endif /* CONFIG_MALI_DEBUG */
+
+/**
+ * @brief Register a function to call on ASSERT
+ *
+ * Such functions will \b only be called during Debug mode, and for debugging
+ * features \b only. Do not rely on them to be called in general use.
+ *
+ * To disable the hook, supply NULL to \a func.
+ *
+ * @note This function is not thread-safe, and should only be used to
+ * register/deregister once in the module's lifetime.
+ *
+ * @param[in] func the function to call when an assert is triggered.
+ * @param[in] param the parameter to pass to \a func when calling it
+ */
+void kbase_debug_assert_register_hook(kbase_debug_assert_hook *func, void *param);
+
+/**
+ * @brief Call a debug assert hook previously registered with kbase_debug_assert_register_hook()
+ *
+ * @note This function is not thread-safe with respect to multiple threads
+ * registering functions and parameters with
+ * kbase_debug_assert_register_hook(). Otherwise, thread safety is the
+ * responsibility of the registered hook.
+ */
+void kbasep_debug_assert_call_hook(void);
+
+/**
+ * @brief Convert a module id into a module name.
+ *
+ * @param module ID of the module to convert
+ * @note module names are stored in : @see kbasep_str_modules.
+ * @return the name of the given module ID as a string of characters.
+ */
+const char *kbasep_debug_module_to_str(const kbase_module module);
+
+#endif /* _KBASE_DEBUG_H */
diff --git a/drivers/gpu/arm/t6xx/kbase/mali_uk.h b/drivers/gpu/arm/t6xx/kbase/mali_uk.h
new file mode 100755
index 00000000000..4f90273fe8b
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/mali_uk.h
@@ -0,0 +1,140 @@
+/*
+ *
+ * (C) COPYRIGHT 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_uk.h
+ * Types and definitions that are common across OSs for both the user
+ * and kernel side of the User-Kernel interface.
+ */
+
+#ifndef _UK_H_
+#define _UK_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <malisw/mali_stdtypes.h>
+
+/**
+ * @addtogroup base_api
+ * @{
+ */
+
+/**
+ * @defgroup uk_api User-Kernel Interface API
+ *
+ * The User-Kernel Interface abstracts the communication mechanism between the user and kernel-side code of device
+ * drivers developed as part of the Midgard DDK. Currently that includes the Base driver and the UMP driver.
+ *
+ * It exposes an OS independent API to user-side code (UKU) which routes functions calls to an OS-independent
+ * kernel-side API (UKK) via an OS-specific communication mechanism.
+ *
+ * This API is internal to the Midgard DDK and is not exposed to any applications.
+ *
+ * @{
+ */
+
+/**
+ * These are identifiers for kernel-side drivers implementing a UK interface, aka UKK clients. The
+ * UK module maps this to an OS specific device name, e.g. "gpu_base" -> "GPU0:". Specify this
+ * identifier to select a UKK client to the uku_open() function.
+ *
+ * When a new UKK client driver is created a new identifier needs to be added to the uk_client_id
+ * enumeration and the uku_open() implemenation for the various OS ports need to be updated to
+ * provide a mapping of the identifier to the OS specific device name.
+ *
+ */
+ typedef enum uk_client_id {
+ /**
+ * Value used to identify the Base driver UK client.
+ */
+ UK_CLIENT_MALI_T600_BASE,
+
+ /** The number of uk clients supported. This must be the last member of the enum */
+ UK_CLIENT_COUNT
+ } uk_client_id;
+
+/**
+ * Each function callable through the UK interface has a unique number.
+ * Functions provided by UK clients start from number UK_FUNC_ID.
+ * Numbers below UK_FUNC_ID are used for internal UK functions.
+ */
+ typedef enum uk_func {
+ UKP_FUNC_ID_CHECK_VERSION, /**< UKK Core internal function */
+ /**
+ * Each UK client numbers the functions they provide starting from
+ * number UK_FUNC_ID. This number is then eventually assigned to the
+ * id field of the uk_header structure when preparing to make a
+ * UK call. See your UK client for a list of their function numbers.
+ */
+ UK_FUNC_ID = 512
+ } uk_func;
+
+/**
+ * Arguments for a UK call are stored in a structure. This structure consists
+ * of a fixed size header and a payload. The header carries a 32-bit number
+ * identifying the UK function to be called (see uk_func). When the UKK client
+ * receives this header and executed the requested UK function, it will use
+ * the same header to store the result of the function in the form of a
+ * mali_error return code. The size of this structure is such that the
+ * first member of the payload following the header can be accessed efficiently
+ * on a 32 and 64-bit kernel and the structure has the same size regardless
+ * of a 32 or 64-bit kernel. The uk_kernel_size_type type should be defined
+ * accordingly in the OS specific mali_uk_os.h header file.
+ */
+ typedef union uk_header {
+ /**
+ * 32-bit number identifying the UK function to be called.
+ * Also see uk_func.
+ */
+ u32 id;
+ /**
+ * The mali_error return code returned by the called UK function.
+ * See the specification of the particular UK function you are
+ * calling for the meaning of the error codes returned. All
+ * UK functions return MALI_ERROR_NONE on success.
+ */
+ u32 ret;
+ /*
+ * Used to ensure 64-bit alignment of this union. Do not remove.
+ * This field is used for padding and does not need to be initialized.
+ */
+ u64 sizer;
+ } uk_header;
+
+/**
+ * This structure carries a 16-bit major and minor number and is sent along with an internal UK call
+ * used during uku_open to identify the versions of the UK module in use by the user-side and kernel-side.
+ */
+ typedef struct uku_version_check_args {
+ uk_header header;
+ /**< UK call header */
+ u16 major;
+ /**< This field carries the user-side major version on input and the kernel-side major version on output */
+ u16 minor;
+ /**< This field carries the user-side minor version on input and the kernel-side minor version on output. */
+ } uku_version_check_args;
+
+/** @} end group uk_api */
+
+ /** @} *//* end group base_api */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _UK_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd.h b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd.h
new file mode 100755
index 00000000000..faf3c3261eb
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd.h
@@ -0,0 +1,479 @@
+/*
+ *
+ * (C) COPYRIGHT 2007-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @addtogroup malisw
+ * @{
+ */
+
+/* ============================================================================
+ Description
+============================================================================ */
+/**
+ * @defgroup arm_cstd_coding_standard ARM C standard types and constants
+ * The common files are a set of standard headers which are used by all parts
+ * of this development, describing types, and generic constants.
+ *
+ * Files in group:
+ * - arm_cstd.h
+ * - arm_cstd_compilers.h
+ * - arm_cstd_types.h
+ * - arm_cstd_types_rvct.h
+ * - arm_cstd_types_gcc.h
+ * - arm_cstd_types_msvc.h
+ * - arm_cstd_pack_push.h
+ * - arm_cstd_pack_pop.h
+ */
+
+/**
+ * @addtogroup arm_cstd_coding_standard
+ * @{
+ */
+
+#ifndef _ARM_CSTD_
+#define _ARM_CSTD_
+
+/* ============================================================================
+ Import standard C99 types
+============================================================================ */
+#include "arm_cstd_compilers.h"
+#include "arm_cstd_types.h"
+
+/* ============================================================================
+ Min and Max Values
+============================================================================ */
+#if !defined(INT8_MAX)
+ #define INT8_MAX ((int8_t) 0x7F)
+#endif
+#if !defined(INT8_MIN)
+ #define INT8_MIN (-INT8_MAX - 1)
+#endif
+
+#if !defined(INT16_MAX)
+ #define INT16_MAX ((int16_t)0x7FFF)
+#endif
+#if !defined(INT16_MIN)
+ #define INT16_MIN (-INT16_MAX - 1)
+#endif
+
+#if !defined(INT32_MAX)
+ #define INT32_MAX ((int32_t)0x7FFFFFFF)
+#endif
+#if !defined(INT32_MIN)
+ #define INT32_MIN (-INT32_MAX - 1)
+#endif
+
+#if !defined(INT64_MAX)
+ #define INT64_MAX ((int64_t)0x7FFFFFFFFFFFFFFFLL)
+#endif
+#if !defined(INT64_MIN)
+ #define INT64_MIN (-INT64_MAX - 1)
+#endif
+
+#if !defined(UINT8_MAX)
+ #define UINT8_MAX ((uint8_t) 0xFF)
+#endif
+
+#if !defined(UINT16_MAX)
+ #define UINT16_MAX ((uint16_t)0xFFFF)
+#endif
+
+#if !defined(UINT32_MAX)
+ #define UINT32_MAX ((uint32_t)0xFFFFFFFF)
+#endif
+
+#if !defined(UINT64_MAX)
+ #define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFFULL)
+#endif
+
+/* fallbacks if limits.h wasn't available */
+#if !defined(UCHAR_MAX)
+ #define UCHAR_MAX ((unsigned char)~0U)
+#endif
+
+#if !defined(SCHAR_MAX)
+ #define SCHAR_MAX ((signed char)(UCHAR_MAX >> 1))
+#endif
+#if !defined(SCHAR_MIN)
+ #define SCHAR_MIN ((signed char)(-SCHAR_MAX - 1))
+#endif
+
+#if !defined(USHRT_MAX)
+ #define USHRT_MAX ((unsigned short)~0U)
+#endif
+
+#if !defined(SHRT_MAX)
+ #define SHRT_MAX ((signed short)(USHRT_MAX >> 1))
+#endif
+#if !defined(SHRT_MIN)
+ #define SHRT_MIN ((signed short)(-SHRT_MAX - 1))
+#endif
+
+#if !defined(UINT_MAX)
+ #define UINT_MAX ((unsigned int)~0U)
+#endif
+
+#if !defined(INT_MAX)
+ #define INT_MAX ((signed int)(UINT_MAX >> 1))
+#endif
+#if !defined(INT_MIN)
+ #define INT_MIN ((signed int)(-INT_MAX - 1))
+#endif
+
+#if !defined(ULONG_MAX)
+ #define ULONG_MAX ((unsigned long)~0UL)
+#endif
+
+#if !defined(LONG_MAX)
+ #define LONG_MAX ((signed long)(ULONG_MAX >> 1))
+#endif
+#if !defined(LONG_MIN)
+ #define LONG_MIN ((signed long)(-LONG_MAX - 1))
+#endif
+
+#if !defined(ULLONG_MAX)
+ #define ULLONG_MAX ((unsigned long long)~0ULL)
+#endif
+
+#if !defined(LLONG_MAX)
+ #define LLONG_MAX ((signed long long)(ULLONG_MAX >> 1))
+#endif
+#if !defined(LLONG_MIN)
+ #define LLONG_MIN ((signed long long)(-LLONG_MAX - 1))
+#endif
+
+#if !defined(SIZE_MAX)
+ #if 1 == CSTD_CPU_32BIT
+ #define SIZE_MAX UINT32_MAX
+ #elif 1 == CSTD_CPU_64BIT
+ #define SIZE_MAX UINT64_MAX
+ #endif
+#endif
+
+/* ============================================================================
+ Keywords
+============================================================================ */
+/* Portable keywords. */
+
+#if !defined(CONST)
+/**
+ * @hideinitializer
+ * Variable is a C @c const, which can be made non-const for testing purposes.
+ */
+ #define CONST const
+#endif
+
+#if !defined(STATIC)
+/**
+ * @hideinitializer
+ * Variable is a C @c static, which can be made non-static for testing
+ * purposes.
+ */
+ #define STATIC static
+#endif
+
+/**
+ * Specifies a function as being exported outside of a logical module.
+ */
+#define PUBLIC
+
+/**
+ * @def PROTECTED
+ * Specifies a a function which is internal to an logical module, but which
+ * should not be used outside of that module. This cannot be enforced by the
+ * compiler, as a module is typically more than one translation unit.
+ */
+#define PROTECTED
+
+/**
+ * Specifies a function as being internal to a translation unit. Private
+ * functions would typically be declared as STATIC, unless they are being
+ * exported for unit test purposes.
+ */
+#define PRIVATE STATIC
+
+/**
+ * Specify an assertion value which is evaluated at compile time. Recommended
+ * usage is specification of a @c static @c INLINE function containing all of
+ * the assertions thus:
+ *
+ * @code
+ * static INLINE [module]_compile_time_assertions( void )
+ * {
+ * COMPILE_TIME_ASSERT( sizeof(uintptr_t) == sizeof(intptr_t) );
+ * }
+ * @endcode
+ *
+ * @note Use @c static not @c STATIC. We never want to turn off this @c static
+ * specification for testing purposes.
+ */
+#define CSTD_COMPILE_TIME_ASSERT( expr ) \
+ do { switch(0){case 0: case (expr):;} } while( FALSE )
+
+/**
+ * @hideinitializer
+ * @deprecated Prefered form is @c CSTD_UNUSED
+ * Function-like macro for suppressing unused variable warnings. Where possible
+ * such variables should be removed; this macro is present for cases where we
+ * much support API backwards compatibility.
+ */
+#define UNUSED( x ) ((void)(x))
+
+/**
+ * @hideinitializer
+ * Function-like macro for suppressing unused variable warnings. Where possible
+ * such variables should be removed; this macro is present for cases where we
+ * much support API backwards compatibility.
+ */
+#define CSTD_UNUSED( x ) ((void)(x))
+
+/**
+ * @hideinitializer
+ * Function-like macro for use where "no behavior" is desired. This is useful
+ * when compile time macros turn a function-like macro in to a no-op, but
+ * where having no statement is otherwise invalid.
+ */
+#define CSTD_NOP( ... ) ((void)#__VA_ARGS__)
+
+/**
+ * @hideinitializer
+ * Function-like macro for converting a pointer in to a u64 for storing into
+ * an external data structure. This is commonly used when pairing a 32-bit
+ * CPU with a 64-bit peripheral, such as a Midgard GPU. C's type promotion
+ * is complex and a straight cast does not work reliably as pointers are
+ * often considered as signed.
+ */
+#define CSTD_PTR_TO_U64( x ) ((uint64_t)((uintptr_t)(x)))
+
+/**
+ * @hideinitializer
+ * Function-like macro for stringizing a single level macro.
+ * @code
+ * #define MY_MACRO 32
+ * CSTD_STR1( MY_MACRO )
+ * > "MY_MACRO"
+ * @endcode
+ */
+#define CSTD_STR1( x ) #x
+
+/**
+ * @hideinitializer
+ * Function-like macro for stringizing a macro's value. This should not be used
+ * if the macro is defined in a way which may have no value; use the
+ * alternative @c CSTD_STR2N macro should be used instead.
+ * @code
+ * #define MY_MACRO 32
+ * CSTD_STR2( MY_MACRO )
+ * > "32"
+ * @endcode
+ */
+#define CSTD_STR2( x ) CSTD_STR1( x )
+
+/**
+ * @hideinitializer
+ * Utility function for stripping the first character off a string.
+ */
+static INLINE char* arm_cstd_strstrip( char * string )
+{
+ return ++string;
+}
+
+/**
+ * @hideinitializer
+ * Function-like macro for stringizing a single level macro where the macro
+ * itself may not have a value. Parameter @c a should be set to any single
+ * character which is then stripped by the macro via an inline function. This
+ * should only be used via the @c CSTD_STR2N macro; for printing a single
+ * macro only the @c CSTD_STR1 macro is a better alternative.
+ *
+ * This macro requires run-time code to handle the case where the macro has
+ * no value (you can't concat empty strings in the preprocessor).
+ */
+#define CSTD_STR1N( a, x ) arm_cstd_strstrip( CSTD_STR1( a##x ) )
+
+/**
+ * @hideinitializer
+ * Function-like macro for stringizing a two level macro where the macro itself
+ * may not have a value.
+ * @code
+ * #define MY_MACRO 32
+ * CSTD_STR2N( MY_MACRO )
+ * > "32"
+ *
+ * #define MY_MACRO 32
+ * CSTD_STR2N( MY_MACRO )
+ * > "32"
+ * @endcode
+ */
+#define CSTD_STR2N( x ) CSTD_STR1N( _, x )
+
+/* ============================================================================
+ Validate portability constructs
+============================================================================ */
+static INLINE void arm_cstd_compile_time_assertions( void )
+{
+ CSTD_COMPILE_TIME_ASSERT( sizeof(uint8_t) == 1 );
+ CSTD_COMPILE_TIME_ASSERT( sizeof(int8_t) == 1 );
+ CSTD_COMPILE_TIME_ASSERT( sizeof(uint16_t) == 2 );
+ CSTD_COMPILE_TIME_ASSERT( sizeof(int16_t) == 2 );
+ CSTD_COMPILE_TIME_ASSERT( sizeof(uint32_t) == 4 );
+ CSTD_COMPILE_TIME_ASSERT( sizeof(int32_t) == 4 );
+ CSTD_COMPILE_TIME_ASSERT( sizeof(uint64_t) == 8 );
+ CSTD_COMPILE_TIME_ASSERT( sizeof(int64_t) == 8 );
+ CSTD_COMPILE_TIME_ASSERT( sizeof(intptr_t) == sizeof(uintptr_t) );
+
+ CSTD_COMPILE_TIME_ASSERT( 1 == TRUE );
+ CSTD_COMPILE_TIME_ASSERT( 0 == FALSE );
+
+#if 1 == CSTD_CPU_32BIT
+ CSTD_COMPILE_TIME_ASSERT( sizeof(uintptr_t) == 4 );
+#elif 1 == CSTD_CPU_64BIT
+ CSTD_COMPILE_TIME_ASSERT( sizeof(uintptr_t) == 8 );
+#endif
+
+}
+
+/* ============================================================================
+ Useful function-like macro
+============================================================================ */
+/**
+ * @brief Return the lesser of two values.
+ * As a macro it may evaluate its arguments more than once.
+ * @see CSTD_MAX
+ */
+#define CSTD_MIN( x, y ) ((x) < (y) ? (x) : (y))
+
+/**
+ * @brief Return the greater of two values.
+ * As a macro it may evaluate its arguments more than once.
+ * If called on the same two arguments as CSTD_MIN it is guaranteed to return
+ * the one that CSTD_MIN didn't return. This is significant for types where not
+ * all values are comparable e.g. NaNs in floating-point types. But if you want
+ * to retrieve the min and max of two values, consider using a conditional swap
+ * instead.
+ */
+#define CSTD_MAX( x, y ) ((x) < (y) ? (y) : (x))
+
+/**
+ * @brief Clamp value @c x to within @c min and @c max inclusive.
+ */
+#define CSTD_CLAMP( x, min, max ) ((x)<(min) ? (min):((x)>(max) ? (max):(x)))
+
+/**
+ * Flag a cast as a reinterpretation, usually of a pointer type.
+ */
+#define CSTD_REINTERPRET_CAST(type) (type)
+
+/**
+ * Flag a cast as casting away const, usually of a pointer type.
+ */
+#define CSTD_CONST_CAST(type) (type)
+
+/**
+ * Flag a cast as a (potentially complex) value conversion, usually of a
+ * numerical type.
+ */
+#define CSTD_STATIC_CAST(type) (type)
+
+/* ============================================================================
+ Useful bit constants
+============================================================================ */
+/**
+ * @cond arm_cstd_utilities
+ */
+
+/* Common bit constant values, useful in embedded programming. */
+#define F_BIT_0 ((uint32_t)0x00000001)
+#define F_BIT_1 ((uint32_t)0x00000002)
+#define F_BIT_2 ((uint32_t)0x00000004)
+#define F_BIT_3 ((uint32_t)0x00000008)
+#define F_BIT_4 ((uint32_t)0x00000010)
+#define F_BIT_5 ((uint32_t)0x00000020)
+#define F_BIT_6 ((uint32_t)0x00000040)
+#define F_BIT_7 ((uint32_t)0x00000080)
+#define F_BIT_8 ((uint32_t)0x00000100)
+#define F_BIT_9 ((uint32_t)0x00000200)
+#define F_BIT_10 ((uint32_t)0x00000400)
+#define F_BIT_11 ((uint32_t)0x00000800)
+#define F_BIT_12 ((uint32_t)0x00001000)
+#define F_BIT_13 ((uint32_t)0x00002000)
+#define F_BIT_14 ((uint32_t)0x00004000)
+#define F_BIT_15 ((uint32_t)0x00008000)
+#define F_BIT_16 ((uint32_t)0x00010000)
+#define F_BIT_17 ((uint32_t)0x00020000)
+#define F_BIT_18 ((uint32_t)0x00040000)
+#define F_BIT_19 ((uint32_t)0x00080000)
+#define F_BIT_20 ((uint32_t)0x00100000)
+#define F_BIT_21 ((uint32_t)0x00200000)
+#define F_BIT_22 ((uint32_t)0x00400000)
+#define F_BIT_23 ((uint32_t)0x00800000)
+#define F_BIT_24 ((uint32_t)0x01000000)
+#define F_BIT_25 ((uint32_t)0x02000000)
+#define F_BIT_26 ((uint32_t)0x04000000)
+#define F_BIT_27 ((uint32_t)0x08000000)
+#define F_BIT_28 ((uint32_t)0x10000000)
+#define F_BIT_29 ((uint32_t)0x20000000)
+#define F_BIT_30 ((uint32_t)0x40000000)
+#define F_BIT_31 ((uint32_t)0x80000000)
+
+/* Common 2^n size values, useful in embedded programming. */
+#define C_SIZE_1B ((uint32_t)0x00000001)
+#define C_SIZE_2B ((uint32_t)0x00000002)
+#define C_SIZE_4B ((uint32_t)0x00000004)
+#define C_SIZE_8B ((uint32_t)0x00000008)
+#define C_SIZE_16B ((uint32_t)0x00000010)
+#define C_SIZE_32B ((uint32_t)0x00000020)
+#define C_SIZE_64B ((uint32_t)0x00000040)
+#define C_SIZE_128B ((uint32_t)0x00000080)
+#define C_SIZE_256B ((uint32_t)0x00000100)
+#define C_SIZE_512B ((uint32_t)0x00000200)
+#define C_SIZE_1KB ((uint32_t)0x00000400)
+#define C_SIZE_2KB ((uint32_t)0x00000800)
+#define C_SIZE_4KB ((uint32_t)0x00001000)
+#define C_SIZE_8KB ((uint32_t)0x00002000)
+#define C_SIZE_16KB ((uint32_t)0x00004000)
+#define C_SIZE_32KB ((uint32_t)0x00008000)
+#define C_SIZE_64KB ((uint32_t)0x00010000)
+#define C_SIZE_128KB ((uint32_t)0x00020000)
+#define C_SIZE_256KB ((uint32_t)0x00040000)
+#define C_SIZE_512KB ((uint32_t)0x00080000)
+#define C_SIZE_1MB ((uint32_t)0x00100000)
+#define C_SIZE_2MB ((uint32_t)0x00200000)
+#define C_SIZE_4MB ((uint32_t)0x00400000)
+#define C_SIZE_8MB ((uint32_t)0x00800000)
+#define C_SIZE_16MB ((uint32_t)0x01000000)
+#define C_SIZE_32MB ((uint32_t)0x02000000)
+#define C_SIZE_64MB ((uint32_t)0x04000000)
+#define C_SIZE_128MB ((uint32_t)0x08000000)
+#define C_SIZE_256MB ((uint32_t)0x10000000)
+#define C_SIZE_512MB ((uint32_t)0x20000000)
+#define C_SIZE_1GB ((uint32_t)0x40000000)
+#define C_SIZE_2GB ((uint32_t)0x80000000)
+
+/**
+ * @endcond
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* End (_ARM_CSTD_) */
diff --git a/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_compilers.h b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_compilers.h
new file mode 100755
index 00000000000..1a99115a525
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_compilers.h
@@ -0,0 +1,601 @@
+/*
+ *
+ * (C) COPYRIGHT 2005-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _ARM_CSTD_COMPILERS_H_
+#define _ARM_CSTD_COMPILERS_H_
+
+/* ============================================================================
+ Document default definitions - assuming nothing set at this point.
+============================================================================ */
+/**
+ * @addtogroup arm_cstd_coding_standard
+ * @{
+ */
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if toolchain is Microsoft Visual Studio, 0
+ * otherwise.
+ */
+#define CSTD_TOOLCHAIN_MSVC 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if toolchain is the GNU Compiler Collection, 0
+ * otherwise.
+ */
+#define CSTD_TOOLCHAIN_GCC 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if toolchain is ARM RealView Compiler Tools, 0
+ * otherwise. Note - if running RVCT in GCC mode this define will be set to 0;
+ * @c CSTD_TOOLCHAIN_GCC and @c CSTD_TOOLCHAIN_RVCT_GCC_MODE will both be
+ * defined as 1.
+ */
+#define CSTD_TOOLCHAIN_RVCT 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if toolchain is ARM RealView Compiler Tools running
+ * in GCC mode, 0 otherwise.
+ */
+#define CSTD_TOOLCHAIN_RVCT_GCC_MODE 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if processor is an x86 32-bit machine, 0 otherwise.
+ */
+#define CSTD_CPU_X86_32 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if processor is an x86-64 (AMD64) machine, 0
+ * otherwise.
+ */
+#define CSTD_CPU_X86_64 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if processor is an ARM machine, 0 otherwise.
+ */
+#define CSTD_CPU_ARM 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if processor is a MIPS machine, 0 otherwise.
+ */
+#define CSTD_CPU_MIPS 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if CPU is 32-bit, 0 otherwise.
+ */
+#define CSTD_CPU_32BIT 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if CPU is 64-bit, 0 otherwise.
+ */
+#define CSTD_CPU_64BIT 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if processor configured as big-endian, 0 if it
+ * is little-endian.
+ */
+#define CSTD_CPU_BIG_ENDIAN 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a version of Windows, 0 if
+ * it is not.
+ */
+#define CSTD_OS_WINDOWS 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a 32-bit version of Windows,
+ * 0 if it is not.
+ */
+#define CSTD_OS_WIN32 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a 64-bit version of Windows,
+ * 0 if it is not.
+ */
+#define CSTD_OS_WIN64 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is Linux, 0 if it is not.
+ */
+#define CSTD_OS_LINUX 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if we are compiling Linux kernel code, 0 otherwise.
+ */
+#define CSTD_OS_LINUX_KERNEL 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a 32-bit version of Linux,
+ * 0 if it is not.
+ */
+#define CSTD_OS_LINUX32 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a 64-bit version of Linux,
+ * 0 if it is not.
+ */
+#define CSTD_OS_LINUX64 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is Android, 0 if it is not.
+ */
+#define CSTD_OS_ANDROID 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if we are compiling Android kernel code, 0 otherwise.
+ */
+#define CSTD_OS_ANDROID_KERNEL 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a 32-bit version of Android,
+ * 0 if it is not.
+ */
+#define CSTD_OS_ANDROID32 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a 64-bit version of Android,
+ * 0 if it is not.
+ */
+#define CSTD_OS_ANDROID64 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a version of Apple OS,
+ * 0 if it is not.
+ */
+#define CSTD_OS_APPLEOS 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a 32-bit version of Apple OS,
+ * 0 if it is not.
+ */
+#define CSTD_OS_APPLEOS32 0
+
+/**
+ * @hideinitializer
+ * Defined with value of 1 if operating system is a 64-bit version of Apple OS,
+ * 0 if it is not.
+ */
+#define CSTD_OS_APPLEOS64 0
+
+/**
+ * @def CSTD_OS_SYMBIAN
+ * @hideinitializer
+ * Defined with value of 1 if operating system is Symbian, 0 if it is not.
+ */
+#define CSTD_OS_SYMBIAN 0
+
+/**
+ * @def CSTD_OS_NONE
+ * @hideinitializer
+ * Defined with value of 1 if there is no operating system (bare metal), 0
+ * otherwise
+ */
+#define CSTD_OS_NONE 0
+
+/* ============================================================================
+ Determine the compiler in use
+============================================================================ */
+
+/* Default empty definitions of compiler-specific option enable/disable. This will be overridden
+ * if applicable by preprocessor defines below. */
+#define CSTD_PUSH_WARNING_GCC_WADDRESS
+#define CSTD_POP_WARNING_GCC_WADDRESS
+
+#if defined(_MSC_VER)
+ #undef CSTD_TOOLCHAIN_MSVC
+ #define CSTD_TOOLCHAIN_MSVC 1
+
+#elif defined(__GNUC__)
+ #undef CSTD_TOOLCHAIN_GCC
+ #define CSTD_TOOLCHAIN_GCC 1
+
+ /* Detect RVCT pretending to be GCC. */
+ #if defined(__ARMCC_VERSION)
+ #undef CSTD_TOOLCHAIN_RVCT_GCC_MODE
+ #define CSTD_TOOLCHAIN_RVCT_GCC_MODE 1
+ #endif
+
+ #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && MALI_GCC_WORKAROUND_MIDCOM_4598 == 0)
+ /* As a workaround to MIDCOM-4598 (GCC internal defect), these pragmas are not compiled if the GCC version
+ * is within a certain range, or if a #define is enabled by the build system. For more, see a comment
+ * in the build system also referring to the MIDCOM issue mentioned, where the environment is updated
+ * for the GNU toolchain. */
+ #undef CSTD_PUSH_WARNING_GCC_WADDRESS
+ #define CSTD_PUSH_WARNING_GCC_WADDRESS \
+ do\
+ {\
+ _Pragma("GCC diagnostic push")\
+ _Pragma("GCC diagnostic ignored \"-Waddress\"")\
+ }while(MALI_FALSE)
+
+ #undef CSTD_POP_WARNING_GCC_WADDRESS
+ #define CSTD_POP_WARNING_GCC_WADDRESS \
+ do\
+ {\
+ _Pragma("GCC diagnostic pop")\
+ }while(MALI_FALSE)
+ #endif
+
+#elif defined(__ARMCC_VERSION)
+ #undef CSTD_TOOLCHAIN_RVCT
+ #define CSTD_TOOLCHAIN_RVCT 1
+
+#else
+ #warning "Unsupported or unknown toolchain"
+
+#endif
+
+/* ============================================================================
+ Determine the processor
+============================================================================ */
+#if 1 == CSTD_TOOLCHAIN_MSVC
+ #if defined(_M_IX86)
+ #undef CSTD_CPU_X86_32
+ #define CSTD_CPU_X86_32 1
+
+ #elif defined(_M_X64) || defined(_M_AMD64)
+ #undef CSTD_CPU_X86_64
+ #define CSTD_CPU_X86_64 1
+
+ #elif defined(_M_ARM)
+ #undef CSTD_CPU_ARM
+ #define CSTD_CPU_ARM 1
+
+ #elif defined(_M_MIPS)
+ #undef CSTD_CPU_MIPS
+ #define CSTD_CPU_MIPS 1
+
+ #else
+ #warning "Unsupported or unknown host CPU for MSVC tools"
+
+ #endif
+
+#elif 1 == CSTD_TOOLCHAIN_GCC
+ #if defined(__amd64__)
+ #undef CSTD_CPU_X86_64
+ #define CSTD_CPU_X86_64 1
+
+ #elif defined(__i386__)
+ #undef CSTD_CPU_X86_32
+ #define CSTD_CPU_X86_32 1
+
+ #elif defined(__arm__)
+ #undef CSTD_CPU_ARM
+ #define CSTD_CPU_ARM 1
+
+ #elif defined(__mips__)
+ #undef CSTD_CPU_MIPS
+ #define CSTD_CPU_MIPS 1
+
+ #else
+ #warning "Unsupported or unknown host CPU for GCC tools"
+
+ #endif
+
+#elif 1 == CSTD_TOOLCHAIN_RVCT
+ #undef CSTD_CPU_ARM
+ #define CSTD_CPU_ARM 1
+
+#else
+ #warning "Unsupported or unknown toolchain"
+
+#endif
+
+/* ============================================================================
+ Determine the Processor Endianness
+============================================================================ */
+
+#if ((1 == CSTD_CPU_X86_32) || (1 == CSTD_CPU_X86_64))
+ /* Note: x86 and x86-64 are always little endian, so leave at default. */
+
+#elif 1 == CSTD_TOOLCHAIN_RVCT
+ #if defined(__BIG_ENDIAN)
+ #undef CSTD_ENDIAN_BIG
+ #define CSTD_ENDIAN_BIG 1
+ #endif
+
+#elif ((1 == CSTD_TOOLCHAIN_GCC) && (1 == CSTD_CPU_ARM))
+ #if defined(__ARMEB__)
+ #undef CSTD_ENDIAN_BIG
+ #define CSTD_ENDIAN_BIG 1
+ #endif
+
+#elif ((1 == CSTD_TOOLCHAIN_GCC) && (1 == CSTD_CPU_MIPS))
+ #if defined(__MIPSEB__)
+ #undef CSTD_ENDIAN_BIG
+ #define CSTD_ENDIAN_BIG 1
+ #endif
+
+#elif 1 == CSTD_TOOLCHAIN_MSVC
+ /* Note: Microsoft only support little endian, so leave at default. */
+
+#else
+ #warning "Unsupported or unknown CPU"
+
+#endif
+
+/* ============================================================================
+ Determine the operating system and addressing width
+============================================================================ */
+#if 1 == CSTD_TOOLCHAIN_MSVC
+ #if defined(_WIN32) && !defined(_WIN64)
+ #undef CSTD_OS_WINDOWS
+ #define CSTD_OS_WINDOWS 1
+ #undef CSTD_OS_WIN32
+ #define CSTD_OS_WIN32 1
+ #undef CSTD_CPU_32BIT
+ #define CSTD_CPU_32BIT 1
+
+ #elif defined(_WIN32) && defined(_WIN64)
+ #undef CSTD_OS_WINDOWS
+ #define CSTD_OS_WINDOWS 1
+ #undef CSTD_OS_WIN64
+ #define CSTD_OS_WIN64 1
+ #undef CSTD_CPU_64BIT
+ #define CSTD_CPU_64BIT 1
+
+ #else
+ #warning "Unsupported or unknown host OS for MSVC tools"
+
+ #endif
+
+#elif 1 == CSTD_TOOLCHAIN_GCC
+ #if defined(_WIN32) && defined(_WIN64)
+ #undef CSTD_OS_WINDOWS
+ #define CSTD_OS_WINDOWS 1
+ #undef CSTD_OS_WIN64
+ #define CSTD_OS_WIN64 1
+ #undef CSTD_CPU_64BIT
+ #define CSTD_CPU_64BIT 1
+
+ #elif defined(_WIN32) && !defined(_WIN64)
+ #undef CSTD_OS_WINDOWS
+ #define CSTD_OS_WINDOWS 1
+ #undef CSTD_OS_WIN32
+ #define CSTD_OS_WIN32 1
+ #undef CSTD_CPU_32BIT
+ #define CSTD_CPU_32BIT 1
+
+ #elif defined(ANDROID)
+ #undef CSTD_OS_ANDROID
+ #define CSTD_OS_ANDROID 1
+
+ #if defined(__KERNEL__)
+ #undef CSTD_OS_ANDROID_KERNEL
+ #define CSTD_OS_ANDROID_KERNEL 1
+ #endif
+
+ #if defined(__LP64__) || defined(_LP64)
+ #undef CSTD_OS_ANDROID64
+ #define CSTD_OS_ANDROID64 1
+ #undef CSTD_CPU_64BIT
+ #define CSTD_CPU_64BIT 1
+ #else
+ #undef CSTD_OS_ANDROID32
+ #define CSTD_OS_ANDROID32 1
+ #undef CSTD_CPU_32BIT
+ #define CSTD_CPU_32BIT 1
+ #endif
+
+ #elif defined(__KERNEL__) || defined(__linux)
+ #undef CSTD_OS_LINUX
+ #define CSTD_OS_LINUX 1
+
+ #if defined(__KERNEL__)
+ #undef CSTD_OS_LINUX_KERNEL
+ #define CSTD_OS_LINUX_KERNEL 1
+ #endif
+
+ #if defined(__LP64__) || defined(_LP64)
+ #undef CSTD_OS_LINUX64
+ #define CSTD_OS_LINUX64 1
+ #undef CSTD_CPU_64BIT
+ #define CSTD_CPU_64BIT 1
+ #else
+ #undef CSTD_OS_LINUX32
+ #define CSTD_OS_LINUX32 1
+ #undef CSTD_CPU_32BIT
+ #define CSTD_CPU_32BIT 1
+ #endif
+
+ #elif defined(__APPLE__)
+ #undef CSTD_OS_APPLEOS
+ #define CSTD_OS_APPLEOS 1
+
+ #if defined(__LP64__) || defined(_LP64)
+ #undef CSTD_OS_APPLEOS64
+ #define CSTD_OS_APPLEOS64 1
+ #undef CSTD_CPU_64BIT
+ #define CSTD_CPU_64BIT 1
+ #else
+ #undef CSTD_OS_APPLEOS32
+ #define CSTD_OS_APPLEOS32 1
+ #undef CSTD_CPU_32BIT
+ #define CSTD_CPU_32BIT 1
+ #endif
+
+ #elif defined(__SYMBIAN32__)
+ #undef CSTD_OS_SYMBIAN
+ #define CSTD_OS_SYMBIAN 1
+ #undef CSTD_CPU_32BIT
+ #define CSTD_CPU_32BIT 1
+
+ #else
+ #undef CSTD_OS_NONE
+ #define CSTD_OS_NONE 1
+ #undef CSTD_CPU_32BIT
+ #define CSTD_CPU_32BIT 1
+
+#endif
+
+#elif 1 == CSTD_TOOLCHAIN_RVCT
+
+ #if defined(ANDROID)
+ #undef CSTD_OS_ANDROID
+ #undef CSTD_OS_ANDROID32
+ #define CSTD_OS_ANDROID 1
+ #define CSTD_OS_ANDROID32 1
+
+ #elif defined(__linux)
+ #undef CSTD_OS_LINUX
+ #undef CSTD_OS_LINUX32
+ #define CSTD_OS_LINUX 1
+ #define CSTD_OS_LINUX32 1
+
+ #elif defined(__SYMBIAN32__)
+ #undef CSTD_OS_SYMBIAN
+ #define CSTD_OS_SYMBIAN 1
+
+ #else
+ #undef CSTD_OS_NONE
+ #define CSTD_OS_NONE 1
+
+#endif
+
+#else
+ #warning "Unsupported or unknown host OS"
+
+#endif
+
+/* ============================================================================
+ Determine the correct linker symbol Import and Export Macros
+============================================================================ */
+/**
+ * @defgroup arm_cstd_linkage_specifiers Linkage Specifiers
+ * @{
+ *
+ * This set of macros contain system-dependent linkage specifiers which
+ * determine the visibility of symbols across DLL boundaries. A header for a
+ * particular DLL should define a set of local macros derived from these,
+ * and should not use these macros to decorate functions directly as there may
+ * be multiple DLLs being used.
+ *
+ * These DLL library local macros should be (with appropriate library prefix)
+ * <tt>[MY_LIBRARY]_API</tt>, <tt>[MY_LIBRARY]_IMPL</tt>, and
+ * <tt>[MY_LIBRARY]_LOCAL</tt>.
+ *
+ * - <tt>[MY_LIBRARY]_API</tt> should be use to decorate the function
+ * declarations in the header. It should be defined as either
+ * @c CSTD_LINK_IMPORT or @c CSTD_LINK_EXPORT, depending whether the
+ * current situation is a compile of the DLL itself (use export) or a
+ * compile of an external user of the DLL (use import).
+ * - <tt>[MY_LIBRARY]_IMPL</tt> should be defined as @c CSTD_LINK_IMPL
+ * and should be used to decorate the definition of functions in the C
+ * file.
+ * - <tt>[MY_LIBRARY]_LOCAL</tt> should be used to decorate function
+ * declarations which are exported across translation units within the
+ * DLL, but which are not exported outside of the DLL boundary.
+ *
+ * Functions which are @c static in either a C file or in a header file do not
+ * need any form of linkage decoration, and should therefore have no linkage
+ * macro applied to them.
+ */
+
+/**
+ * @def CSTD_LINK_IMPORT
+ * Specifies a function as being imported to a translation unit across a DLL
+ * boundary.
+ */
+
+/**
+ * @def CSTD_LINK_EXPORT
+ * Specifies a function as being exported across a DLL boundary by a
+ * translation unit.
+ */
+
+/**
+ * @def CSTD_LINK_IMPL
+ * Specifies a function which will be exported across a DLL boundary as
+ * being implemented by a translation unit.
+ */
+
+/**
+ * @def CSTD_LINK_LOCAL
+ * Specifies a function which is internal to a DLL, and which should not be
+ * exported outside of it.
+ */
+
+/**
+ * @}
+ */
+
+#if 1 == CSTD_OS_LINUX
+ #define CSTD_LINK_IMPORT __attribute__((visibility("default")))
+ #define CSTD_LINK_EXPORT __attribute__((visibility("default")))
+ #define CSTD_LINK_IMPL __attribute__((visibility("default")))
+ #define CSTD_LINK_LOCAL __attribute__((visibility("hidden")))
+
+#elif 1 == CSTD_OS_WINDOWS
+ #define CSTD_LINK_IMPORT __declspec(dllimport)
+ #define CSTD_LINK_EXPORT __declspec(dllexport)
+ #define CSTD_LINK_IMPL __declspec(dllexport)
+ #define CSTD_LINK_LOCAL
+
+#elif 1 == CSTD_OS_SYMBIAN
+ #define CSTD_LINK_IMPORT IMPORT_C
+ #define CSTD_LINK_EXPORT IMPORT_C
+ #define CSTD_LINK_IMPL EXPORT_C
+ #define CSTD_LINK_LOCAL
+
+#elif 1 == CSTD_OS_APPLEOS
+ #define CSTD_LINK_IMPORT __attribute__((visibility("default")))
+ #define CSTD_LINK_EXPORT __attribute__((visibility("default")))
+ #define CSTD_LINK_IMPL __attribute__((visibility("default")))
+ #define CSTD_LINK_LOCAL __attribute__((visibility("hidden")))
+
+#elif 1 == CSTD_OS_ANDROID
+ #define CSTD_LINK_IMPORT __attribute__((visibility("default")))
+ #define CSTD_LINK_EXPORT __attribute__((visibility("default")))
+ #define CSTD_LINK_IMPL __attribute__((visibility("default")))
+ #define CSTD_LINK_LOCAL __attribute__((visibility("hidden")))
+
+#else /* CSTD_OS_NONE */
+ #define CSTD_LINK_IMPORT
+ #define CSTD_LINK_EXPORT
+ #define CSTD_LINK_IMPL
+ #define CSTD_LINK_LOCAL
+
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* End (_ARM_CSTD_COMPILERS_H_) */
diff --git a/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_pack_pop.h b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_pack_pop.h
new file mode 100755
index 00000000000..334c391171b
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_pack_pop.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * (C) COPYRIGHT 2009-2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _ARM_CSTD_PACK_POP_H_
+#define _ARM_CSTD_PACK_POP_H_
+
+#if 1 == CSTD_TOOLCHAIN_MSVC
+ #include <poppack.h>
+#endif
+
+#endif /* End (_ARM_CSTD_PACK_POP_H_) */
diff --git a/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_pack_push.h b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_pack_push.h
new file mode 100755
index 00000000000..d507ad88c37
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_pack_push.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * (C) COPYRIGHT 2009-2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _ARM_CSTD_PACK_PUSH_H_
+#define _ARM_CSTD_PACK_PUSH_H_
+
+#if 1 == CSTD_TOOLCHAIN_MSVC
+ #include <pshpack1.h>
+#endif
+
+#endif /* End (_ARM_CSTD_PACK_PUSH_H_) */
diff --git a/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types.h b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types.h
new file mode 100755
index 00000000000..1728fd523a6
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * (C) COPYRIGHT 2009-2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _ARM_CSTD_TYPES_H_
+#define _ARM_CSTD_TYPES_H_
+
+#if 1 == CSTD_TOOLCHAIN_MSVC
+ #include "arm_cstd_types_msvc.h"
+#elif 1 == CSTD_TOOLCHAIN_GCC
+ #include "arm_cstd_types_gcc.h"
+#elif 1 == CSTD_TOOLCHAIN_RVCT
+ #include "arm_cstd_types_rvct.h"
+#else
+ #error "Toolchain not recognized"
+#endif
+
+#endif /* End (_ARM_CSTD_TYPES_H_) */
diff --git a/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types_gcc.h b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types_gcc.h
new file mode 100755
index 00000000000..1a3190af8f7
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types_gcc.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * (C) COPYRIGHT 2009-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _ARM_CSTD_TYPES_GCC_H_
+#define _ARM_CSTD_TYPES_GCC_H_
+
+/* ============================================================================
+ Type definitions
+============================================================================ */
+/* All modern versions of GCC support stdint outside of C99 Mode. */
+/* However, Linux kernel limits what headers are available! */
+#if 1 == CSTD_OS_LINUX_KERNEL
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/stddef.h>
+ #include <linux/version.h>
+
+ /* Fix up any types which CSTD provdes but which Linux is missing. */
+ /* Note Linux assumes pointers are "long", so this is safe. */
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+ typedef unsigned long uintptr_t;
+ #endif
+ typedef long intptr_t;
+
+#else
+ #include <stdint.h>
+ #include <stddef.h>
+ #include <limits.h>
+#endif
+
+typedef uint32_t bool_t;
+
+#if !defined(TRUE)
+ #define TRUE ((bool_t)1)
+#endif
+
+#if !defined(FALSE)
+ #define FALSE ((bool_t)0)
+#endif
+
+/* ============================================================================
+ Keywords
+============================================================================ */
+/* Doxygen documentation for these is in the RVCT header. */
+#define ASM __asm__
+
+#define INLINE __inline__
+
+#define FORCE_INLINE __attribute__((__always_inline__)) __inline__
+
+#define NEVER_INLINE __attribute__((__noinline__))
+
+#define PURE __attribute__((__pure__))
+
+#define PACKED __attribute__((__packed__))
+
+/* GCC does not support pointers to UNALIGNED data, so we do not define it to
+ * force a compile error if this macro is used. */
+
+#define RESTRICT __restrict__
+
+/* RVCT in GCC mode does not support the CHECK_RESULT attribute. */
+#if 0 == CSTD_TOOLCHAIN_RVCT_GCC_MODE
+ #define CHECK_RESULT __attribute__((__warn_unused_result__))
+#else
+ #define CHECK_RESULT
+#endif
+
+/* RVCT in GCC mode does not support the __func__ name outside of C99. */
+#if (0 == CSTD_TOOLCHAIN_RVCT_GCC_MODE)
+ #define CSTD_FUNC __func__
+#else
+ #define CSTD_FUNC __FUNCTION__
+#endif
+
+#endif /* End (_ARM_CSTD_TYPES_GCC_H_) */
diff --git a/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types_rvct.h b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types_rvct.h
new file mode 100755
index 00000000000..e9f97effb01
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/malisw/arm_cstd/arm_cstd_types_rvct.h
@@ -0,0 +1,190 @@
+/*
+ *
+ * (C) COPYRIGHT 2009-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _ARM_CSTD_TYPES_RVCT_H_
+#define _ARM_CSTD_TYPES_RVCT_H_
+
+/* ============================================================================
+ Type definitions
+============================================================================ */
+#include <stddef.h>
+#include <limits.h>
+
+#if 199901L <= __STDC_VERSION__
+ #include <inttypes.h>
+#else
+ typedef unsigned char uint8_t;
+ typedef signed char int8_t;
+ typedef unsigned short uint16_t;
+ typedef signed short int16_t;
+ typedef unsigned int uint32_t;
+ typedef signed int int32_t;
+ typedef unsigned __int64 uint64_t;
+ typedef signed __int64 int64_t;
+ typedef ptrdiff_t intptr_t;
+ typedef size_t uintptr_t;
+#endif
+
+typedef uint32_t bool_t;
+
+#if !defined(TRUE)
+ #define TRUE ((bool_t)1)
+#endif
+
+#if !defined(FALSE)
+ #define FALSE ((bool_t)0)
+#endif
+
+/* ============================================================================
+ Keywords
+============================================================================ */
+/**
+ * @addtogroup arm_cstd_coding_standard
+ * @{
+ */
+
+/**
+ * @def ASM
+ * @hideinitializer
+ * Mark an assembler block. Such blocks are often compiler specific, so often
+ * need to be surrounded in appropriate @c ifdef and @c endif blocks
+ * using the relevant @c CSTD_TOOLCHAIN macro.
+ */
+#define ASM __asm
+
+/**
+ * @def INLINE
+ * @hideinitializer
+ * Mark a definition as something which should be inlined. This is not always
+ * possible on a given compiler, and may be disabled at lower optimization
+ * levels.
+ */
+#define INLINE __inline
+
+/**
+ * @def FORCE_INLINE
+ * @hideinitializer
+ * Mark a definition as something which should be inlined. This provides a much
+ * stronger hint to the compiler than @c INLINE, and if supported should always
+ * result in an inlined function being emitted. If not supported this falls
+ * back to using the @c INLINE definition.
+ */
+#define FORCE_INLINE __forceinline
+
+/**
+ * @def NEVER_INLINE
+ * @hideinitializer
+ * Mark a definition as something which should not be inlined. This provides a
+ * stronger hint to the compiler than the function should not be inlined,
+ * bypassing any heuristic rules the compiler normally applies. If not
+ * supported by a toolchain this falls back to being an empty macro.
+ */
+#define NEVER_INLINE __declspec(noinline)
+
+/**
+ * @def PURE
+ * @hideinitializer
+ * Denotes that a function's return is only dependent on its inputs, enabling
+ * more efficient optimizations. Falls back to an empty macro if not supported.
+ */
+#define PURE __pure
+
+/**
+ * @def PACKED
+ * @hideinitializer
+ * Denotes that a structure should be stored in a packed form. This macro must
+ * be used in conjunction with the @c arm_cstd_pack_* headers for portability:
+ *
+ * @code
+ * #include <cstd/arm_cstd_pack_push.h>
+ *
+ * struct PACKED myStruct {
+ * ...
+ * };
+ *
+ * #include <cstd/arm_cstd_pack_pop.h>
+ * PACKED
+ * @endcode
+ */
+#define PACKED __packed
+
+/**
+ * @def UNALIGNED
+ * @hideinitializer
+ * Denotes that a pointer points to a buffer with lower alignment than the
+ * natural alignment required by the C standard. This should only be used
+ * in extreme cases, as the emitted code is normally more efficient if memory
+ * is aligned.
+ *
+ * @warning This is \b NON-PORTABLE. The GNU tools are anti-unaligned pointers
+ * and have no support for such a construction.
+ */
+#define UNALIGNED __packed
+
+/**
+ * @def RESTRICT
+ * @hideinitializer
+ * Denotes that a pointer does not overlap with any other points currently in
+ * scope, increasing the range of optimizations which can be performed by the
+ * compiler.
+ *
+ * @warning Specification of @c RESTRICT is a contract between the programmer
+ * and the compiler. If you place @c RESTICT on buffers which do actually
+ * overlap the behavior is undefined, and likely to vary at different
+ * optimization levels.!
+ */
+#define RESTRICT __restrict
+
+/**
+ * @def CHECK_RESULT
+ * @hideinitializer
+ * Function attribute which causes a warning to be emitted if the compiler's
+ * return value is not used by the caller. Compiles to an empty macro if
+ * there is no supported mechanism for this check in the underlying compiler.
+ *
+ * @note At the time of writing this is only supported by GCC. RVCT does not
+ * support this attribute, even in GCC mode, so engineers are encouraged to
+ * compile their code using GCC even if primarily working with another
+ * compiler.
+ *
+ * @code
+ * CHECK_RESULT int my_func( void );
+ * @endcode
+ */
+#define CHECK_RESULT
+
+/**
+ * @def CSTD_FUNC
+ * Specify the @c CSTD_FUNC macro, a portable construct containing the name of
+ * the current function. On most compilers it is illegal to use this macro
+ * outside of a function scope. If not supported by the compiler we define
+ * @c CSTD_FUNC as an empty string.
+ *
+ * @warning Due to the implementation of this on most modern compilers this
+ * expands to a magically defined "static const" variable, not a constant
+ * string. This makes injecting @c CSTD_FUNC directly in to compile-time
+ * strings impossible, so if you want to make the function name part of a
+ * larger string you must use a printf-like function with a @c @%s template
+ * which is populated with @c CSTD_FUNC
+ */
+#define CSTD_FUNC __FUNCTION__
+
+/**
+ * @}
+ */
+
+#endif /* End (_ARM_CSTD_TYPES_RVCT_H_) */
diff --git a/drivers/gpu/arm/t6xx/kbase/malisw/mali_malisw.h b/drivers/gpu/arm/t6xx/kbase/malisw/mali_malisw.h
new file mode 100755
index 00000000000..53ddcbb86a8
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/malisw/mali_malisw.h
@@ -0,0 +1,236 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _MALISW_H_
+#define _MALISW_H_
+
+/**
+ * @file mali_malisw.h
+ * Driver-wide include for common macros and types.
+ */
+
+/**
+ * @defgroup malisw Mali software definitions and types
+ * @{
+ */
+
+#include <stddef.h>
+
+#include "mali_stdtypes.h"
+
+/** @brief Gets the container object when given a pointer to a member of an object. */
+#define CONTAINER_OF(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type,member)))
+
+/** @brief Gets the number of elements of type s in a fixed length array of s */
+#define NELEMS(s) (sizeof(s)/sizeof((s)[0]))
+
+/**
+ * @brief The lesser of two values.
+ * May evaluate its arguments more than once.
+ * @see CSTD_MIN
+ */
+#define MIN(x,y) CSTD_MIN(x,y)
+
+/**
+ * @brief The greater of two values.
+ * May evaluate its arguments more than once.
+ * @see CSTD_MAX
+ */
+#define MAX(x,y) CSTD_MAX(x,y)
+
+/**
+ * @brief Clamp value x to within min and max inclusive
+ * May evaluate its arguments more than once.
+ * @see CSTD_CLAMP
+ */
+#define CLAMP( x, min, max ) CSTD_CLAMP( x, min, max )
+
+/**
+ * @brief Convert a pointer into a u64 for storing in a data structure.
+ * This is commonly used when pairing a 32-bit CPU with a 64-bit peripheral,
+ * such as a Midgard GPU. C's type promotion is complex and a straight cast
+ * does not work reliably as pointers are often considered as signed.
+ */
+#define PTR_TO_U64( x ) CSTD_PTR_TO_U64( x )
+
+/**
+ * @name Mali library linkage specifiers
+ * These directly map to the cstd versions described in detail here: @ref arm_cstd_linkage_specifiers
+ * @{
+ */
+#define MALI_IMPORT CSTD_LINK_IMPORT
+#define MALI_EXPORT CSTD_LINK_EXPORT
+#define MALI_IMPL CSTD_LINK_IMPL
+#define MALI_LOCAL CSTD_LINK_LOCAL
+
+/** @brief Decorate exported function prototypes.
+ *
+ * The file containing the implementation of the function should define this to be MALI_EXPORT before including
+ * malisw/mali_malisw.h.
+ */
+#ifndef MALI_API
+#define MALI_API MALI_IMPORT
+#endif
+/** @} */
+
+/** @name Testable static functions
+ * @{
+ *
+ * These macros can be used to allow functions to be static in release builds but exported from a shared library in unit
+ * test builds, allowing them to be tested or used to assist testing.
+ *
+ * Example mali_foo_bar.c containing the function to test:
+ *
+ * @code
+ * #define MALI_API MALI_EXPORT
+ *
+ * #include <malisw/mali_malisw.h>
+ * #include "mali_foo_testable_statics.h"
+ *
+ * MALI_TESTABLE_STATIC_IMPL void my_func()
+ * {
+ * //Implementation
+ * }
+ * @endcode
+ *
+ * Example mali_foo_testable_statics.h:
+ *
+ * @code
+ * #if 1 == MALI_UNIT_TEST
+ * #include <malisw/mali_malisw.h>
+ *
+ * MALI_TESTABLE_STATIC_API void my_func();
+ *
+ * #endif
+ * @endcode
+ *
+ * Example mali_foo_tests.c:
+ *
+ * @code
+ * #include <foo/src/mali_foo_testable_statics.h>
+ *
+ * void my_test_func()
+ * {
+ * my_func();
+ * }
+ * @endcode
+ */
+
+/** @brief Decorate testable static function implementations.
+ *
+ * A header file containing a MALI_TESTABLE_STATIC_API-decorated prototype for each static function will be required
+ * when MALI_UNIT_TEST == 1 in order to link the function from the test.
+ */
+#if 1 == MALI_UNIT_TEST
+#define MALI_TESTABLE_STATIC_IMPL MALI_IMPL
+#else
+#define MALI_TESTABLE_STATIC_IMPL static
+#endif
+
+/** @brief Decorate testable static function prototypes.
+ *
+ * @note Prototypes should @em only be declared when MALI_UNIT_TEST == 1
+ */
+#define MALI_TESTABLE_STATIC_API MALI_API
+/** @} */
+
+/** @name Testable local functions
+ * @{
+ *
+ * These macros can be used to allow functions to be local to a shared library in release builds but be exported in unit
+ * test builds, allowing them to be tested or used to assist testing.
+ *
+ * Example mali_foo_bar.c containing the function to test:
+ *
+ * @code
+ * #define MALI_API MALI_EXPORT
+ *
+ * #include <malisw/mali_malisw.h>
+ * #include "mali_foo_bar.h"
+ *
+ * MALI_TESTABLE_LOCAL_IMPL void my_func()
+ * {
+ * //Implementation
+ * }
+ * @endcode
+ *
+ * Example mali_foo_bar.h:
+ *
+ * @code
+ * #include <malisw/mali_malisw.h>
+ *
+ * MALI_TESTABLE_LOCAL_API void my_func();
+ *
+ * @endcode
+ *
+ * Example mali_foo_tests.c:
+ *
+ * @code
+ * #include <foo/src/mali_foo_bar.h>
+ *
+ * void my_test_func()
+ * {
+ * my_func();
+ * }
+ * @endcode
+ */
+
+/** @brief Decorate testable local function implementations.
+ *
+ * This can be used to have a function normally local to the shared library except in debug builds where it will be
+ * exported.
+ */
+#ifdef CONFIG_MALI_DEBUG
+#define MALI_TESTABLE_LOCAL_IMPL MALI_IMPL
+#else
+#define MALI_TESTABLE_LOCAL_IMPL MALI_LOCAL
+#endif /* CONFIG_MALI_DEBUG */
+
+/** @brief Decorate testable local function prototypes.
+ *
+ * This can be used to have a function normally local to the shared library except in debug builds where it will be
+ * exported.
+ */
+#ifdef CONFIG_MALI_DEBUG
+#define MALI_TESTABLE_LOCAL_API MALI_API
+#else
+#define MALI_TESTABLE_LOCAL_API MALI_LOCAL
+#endif /* CONFIG_MALI_DEBUG */
+/** @} */
+
+/**
+ * Flag a cast as a reinterpretation, usually of a pointer type.
+ * @see CSTD_REINTERPRET_CAST
+ */
+#define REINTERPRET_CAST(type) CSTD_REINTERPRET_CAST(type)
+
+/**
+ * Flag a cast as casting away const, usually of a pointer type.
+ * @see CSTD_CONST_CAST
+ */
+#define CONST_CAST(type) (type) CSTD_CONST_CAST(type)
+
+/**
+ * Flag a cast as a (potentially complex) value conversion, usually of a numerical type.
+ * @see CSTD_STATIC_CAST
+ */
+#define STATIC_CAST(type) (type) CSTD_STATIC_CAST(type)
+
+
+/** @} */
+
+#endif /* _MALISW_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/malisw/mali_stdtypes.h b/drivers/gpu/arm/t6xx/kbase/malisw/mali_stdtypes.h
new file mode 100755
index 00000000000..6459a580430
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/malisw/mali_stdtypes.h
@@ -0,0 +1,213 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _MALISW_STDTYPES_H_
+#define _MALISW_STDTYPES_H_
+
+/**
+ * @file mali_stdtypes.h
+ * This file defines the standard types used by the Mali codebase.
+ */
+
+/**
+ * @addtogroup malisw
+ * @{
+ */
+
+/**
+ * @defgroup malisw_stdtypes Mali software standard types
+ *
+ * Basic driver-wide types.
+ */
+
+/**
+ * @addtogroup malisw_stdtypes
+ * @{
+ */
+
+#include "arm_cstd/arm_cstd.h"
+
+/**
+ * @name Scalar types.
+ * These are the scalar types used within the mali driver.
+ * @{
+ */
+/* Note: if compiling the Linux kernel then avoid redefining these. */
+#if 0 == CSTD_OS_LINUX_KERNEL
+ typedef uint64_t u64;
+ typedef uint32_t u32;
+ typedef uint16_t u16;
+ typedef uint8_t u8;
+
+ typedef int64_t s64;
+ typedef int32_t s32;
+ typedef int16_t s16;
+ typedef int8_t s8;
+#endif
+
+typedef double f64;
+typedef float f32;
+typedef u16 f16;
+
+typedef u32 mali_fixed16_16;
+/* @} */
+
+/**
+ * @name Boolean types.
+ * The intended use is for bool8 to be used when storing boolean values in
+ * structures, casting to mali_bool to be used in code sections.
+ * @{
+ */
+typedef bool_t mali_bool;
+typedef u8 mali_bool8;
+
+#define MALI_FALSE FALSE
+#define MALI_TRUE TRUE
+/* @} */
+
+/**
+ * @name Integer bounding values
+ * Maximum and minimum values for integer types
+ * @{
+ */
+#define U64_MAX UINT64_MAX
+#define U32_MAX UINT32_MAX
+#define U16_MAX UINT16_MAX
+#define U8_MAX UINT8_MAX
+
+#define S64_MAX INT64_MAX
+#define S64_MIN INT64_MIN
+#define S32_MAX INT32_MAX
+#define S32_MIN INT32_MIN
+#define S16_MAX INT16_MAX
+#define S16_MIN INT16_MIN
+#define S8_MAX INT8_MAX
+#define S8_MIN INT8_MIN
+/* @} */
+
+/**
+ * @name GPU address types
+ * Types for integers which hold a GPU pointer or GPU pointer offsets.
+ * @{
+ */
+typedef u64 mali_addr64;
+typedef u32 mali_addr32;
+typedef u64 mali_size64;
+typedef s64 mali_offset64;
+/* 32 bit offsets and sizes are always for native types and so use ptrdiff_t and size_t respectively */
+/* @} */
+
+/**
+ * @name Mali error types
+ * @brief The common error type for the mali drivers
+ * The mali_error type, all driver error handling should be of this type unless
+ * it must deal with a specific APIs error type.
+ * @{
+ */
+typedef enum
+{
+ /**
+ * @brief Common Mali errors for the entire driver
+ * MALI_ERROR_NONE is guaranteed to be 0.
+ * @{
+ */
+ MALI_ERROR_NONE = 0,
+ MALI_ERROR_OUT_OF_GPU_MEMORY,
+ MALI_ERROR_OUT_OF_MEMORY,
+ MALI_ERROR_FUNCTION_FAILED,
+ /* @} */
+ /**
+ * @brief Mali errors for Client APIs to pass to EGL when creating EGLImages
+ * These errors must only be returned to EGL from one of the Client APIs as part of the
+ * (clientapi)_egl_image_interface.h
+ * @{
+ */
+ MALI_ERROR_EGLP_BAD_ACCESS,
+ MALI_ERROR_EGLP_BAD_PARAMETER,
+ /* @} */
+ /**
+ * @brief Mali errors for the MCL module.
+ * These errors must only be used within the private components of the OpenCL implementation that report
+ * directly to API functions for cases where errors cannot be detected in the entrypoints file. They must
+ * not be passed between driver components.
+ * These are errors in the mali error space specifically for the MCL module, hence the MCLP prefix.
+ * @{
+ */
+ MALI_ERROR_MCLP_DEVICE_NOT_FOUND,
+ MALI_ERROR_MCLP_DEVICE_NOT_AVAILABLE,
+ MALI_ERROR_MCLP_COMPILER_NOT_AVAILABLE,
+ MALI_ERROR_MCLP_MEM_OBJECT_ALLOCATION_FAILURE,
+ MALI_ERROR_MCLP_PROFILING_INFO_NOT_AVAILABLE,
+ MALI_ERROR_MCLP_MEM_COPY_OVERLAP,
+ MALI_ERROR_MCLP_IMAGE_FORMAT_MISMATCH,
+ MALI_ERROR_MCLP_IMAGE_FORMAT_NOT_SUPPORTED,
+ MALI_ERROR_MCLP_BUILD_PROGRAM_FAILURE,
+ MALI_ERROR_MCLP_MAP_FAILURE,
+ MALI_ERROR_MCLP_MISALIGNED_SUB_BUFFER_OFFSET,
+ MALI_ERROR_MCLP_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST,
+ MALI_ERROR_MCLP_INVALID_VALUE,
+ MALI_ERROR_MCLP_INVALID_DEVICE_TYPE,
+ MALI_ERROR_MCLP_INVALID_PLATFORM,
+ MALI_ERROR_MCLP_INVALID_DEVICE,
+ MALI_ERROR_MCLP_INVALID_CONTEXT,
+ MALI_ERROR_MCLP_INVALID_QUEUE_PROPERTIES,
+ MALI_ERROR_MCLP_INVALID_COMMAND_QUEUE,
+ MALI_ERROR_MCLP_INVALID_HOST_PTR,
+ MALI_ERROR_MCLP_INVALID_MEM_OBJECT,
+ MALI_ERROR_MCLP_INVALID_IMAGE_FORMAT_DESCRIPTOR,
+ MALI_ERROR_MCLP_INVALID_IMAGE_SIZE,
+ MALI_ERROR_MCLP_INVALID_SAMPLER,
+ MALI_ERROR_MCLP_INVALID_BINARY,
+ MALI_ERROR_MCLP_INVALID_BUILD_OPTIONS,
+ MALI_ERROR_MCLP_INVALID_PROGRAM,
+ MALI_ERROR_MCLP_INVALID_PROGRAM_EXECUTABLE,
+ MALI_ERROR_MCLP_INVALID_KERNEL_NAME,
+ MALI_ERROR_MCLP_INVALID_KERNEL_DEFINITION,
+ MALI_ERROR_MCLP_INVALID_KERNEL,
+ MALI_ERROR_MCLP_INVALID_ARG_INDEX,
+ MALI_ERROR_MCLP_INVALID_ARG_VALUE,
+ MALI_ERROR_MCLP_INVALID_ARG_SIZE,
+ MALI_ERROR_MCLP_INVALID_KERNEL_ARGS,
+ MALI_ERROR_MCLP_INVALID_WORK_DIMENSION,
+ MALI_ERROR_MCLP_INVALID_WORK_GROUP_SIZE,
+ MALI_ERROR_MCLP_INVALID_WORK_ITEM_SIZE,
+ MALI_ERROR_MCLP_INVALID_GLOBAL_OFFSET,
+ MALI_ERROR_MCLP_INVALID_EVENT_WAIT_LIST,
+ MALI_ERROR_MCLP_INVALID_EVENT,
+ MALI_ERROR_MCLP_INVALID_OPERATION,
+ MALI_ERROR_MCLP_INVALID_GL_OBJECT,
+ MALI_ERROR_MCLP_INVALID_BUFFER_SIZE,
+ MALI_ERROR_MCLP_INVALID_MIP_LEVEL,
+ MALI_ERROR_MCLP_INVALID_GLOBAL_WORK_SIZE,
+ /* @} */
+ /**
+ * @brief Mali errors for the BASE module
+ * These errors must only be used within the private components of the Base implementation. They will not
+ * passed to other modules by the base driver.
+ * These are errors in the mali error space specifically for the BASE module, hence the BASEP prefix.
+ * @{
+ */
+ MALI_ERROR_BASEP_INVALID_FUNCTION
+ /* @} */
+} mali_error;
+/* @} */
+
+/* @} */
+
+/* @} */
+
+#endif /* _MALISW_STDTYPES_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/platform_dummy/mali_ukk_os.h b/drivers/gpu/arm/t6xx/kbase/platform_dummy/mali_ukk_os.h
new file mode 100755
index 00000000000..a046f8e685b
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/platform_dummy/mali_ukk_os.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * (C) COPYRIGHT 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_ukk_os.h
+ * Types and definitions that are common for Linux OSs for the kernel side of the
+ * User-Kernel interface.
+ */
+
+#ifndef _UKK_OS_H_ /* Linux version */
+#define _UKK_OS_H_
+
+#include <linux/fs.h>
+
+/**
+ * @addtogroup uk_api User-Kernel Interface API
+ * @{
+ */
+
+/**
+ * @addtogroup uk_api_kernel UKK (Kernel side)
+ * @{
+ */
+
+/**
+ * Internal OS specific data structure associated with each UKK session. Part
+ * of a ukk_session object.
+ */
+typedef struct ukkp_session
+{
+ int dummy; /**< No internal OS specific data at this time */
+} ukkp_session;
+
+/** @} end group uk_api_kernel */
+
+/** @} end group uk_api */
+
+#endif /* _UKK_OS_H__ */
diff --git a/drivers/gpu/arm/t6xx/kbase/sconscript b/drivers/gpu/arm/t6xx/kbase/sconscript
new file mode 100755
index 00000000000..50d449f2bb9
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/sconscript
@@ -0,0 +1,16 @@
+#
+# (C) COPYRIGHT 2010-2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+SConscript('src/sconscript')
diff --git a/drivers/gpu/arm/t6xx/kbase/src/Kbuild b/drivers/gpu/arm/t6xx/kbase/src/Kbuild
new file mode 100755
index 00000000000..c2b81153c9b
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/Kbuild
@@ -0,0 +1,196 @@
+#
+# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+# Driver version string which is returned to userspace via an ioctl
+MALI_RELEASE_NAME ?= "r3p0-02rel0"
+
+# Paths required for build
+KBASE_PATH = $(src)/../..
+KBASE_SRC_PATH = $(src)/..
+KBASE_PLATFORM_PATH = $(KBASE_SRC_PATH)/platform_dummy
+UMP_PATH = $(src)/../../../../../base
+
+ifeq ($(CONFIG_MALI_ERROR_INJECTION),y)
+MALI_ERROR_INJECT_ON = 1
+endif
+
+# Set up defaults if not defined by build system
+MALI_CUSTOMER_RELEASE ?= 1
+MALI_UNIT_TEST ?= 0
+MALI_KERNEL_TEST_API ?= 0
+MALI_ERROR_INJECT_ON ?= 0
+MALI_MOCK_TEST ?= 0
+MALI_COVERAGE ?= 0
+MALI_INSTRUMENTATION_LEVEL ?= 0
+# This workaround is for what seems to be a compiler bug we observed in
+# GCC 4.7 on AOSP 4.3. The bug caused an intermittent failure compiling
+# the "_Pragma" syntax, where an error message is returned:
+#
+# "internal compiler error: unspellable token PRAGMA"
+#
+# This regression has thus far only been seen on the GCC 4.7 compiler bundled
+# with AOSP 4.3.0. So this makefile, intended for in-tree kernel builds
+# which are not known to be used with AOSP, is hardcoded to disable the
+# workaround, i.e. set the define to 0.
+MALI_GCC_WORKAROUND_MIDCOM_4598 ?= 0
+
+# Set up our defines, which will be passed to gcc
+DEFINES = \
+ -DMALI_CUSTOMER_RELEASE=$(MALI_CUSTOMER_RELEASE) \
+ -DMALI_KERNEL_TEST_API=$(MALI_KERNEL_TEST_API) \
+ -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \
+ -DMALI_ERROR_INJECT_ON=$(MALI_ERROR_INJECT_ON) \
+ -DMALI_MOCK_TEST=$(MALI_MOCK_TEST) \
+ -DMALI_COVERAGE=$(MALI_COVERAGE) \
+ -DMALI_INSTRUMENTATION_LEVEL=$(MALI_INSTRUMENTATION_LEVEL) \
+ -DMALI_RELEASE_NAME=\"$(MALI_RELEASE_NAME)\" \
+ -DMALI_GCC_WORKAROUND_MIDCOM_4598=$(MALI_GCC_WORKAROUND_MIDCOM_4598)
+
+ifeq ($(KBUILD_EXTMOD),)
+# in-tree
+DEFINES +=-DMALI_KBASE_THIRDPARTY_PATH=../../$(src)/platform/$(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)
+else
+# out-of-tree
+DEFINES +=-DMALI_KBASE_THIRDPARTY_PATH=$(src)/platform/$(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME)
+endif
+
+# Use our defines when compiling
+ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(src)/linux -I$(KBASE_SRC_PATH) -I$(KBASE_PLATFORM_PATH) -I$(UMP_PATH)
+subdir-ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(src)/linux -I$(KBASE_SRC_PATH) -I$(KBASE_PLATFORM_PATH) -I$(OSK_PATH) -I$(UMP_PATH)
+
+SRC := \
+ common/mali_kbase_device.c \
+ common/mali_kbase_cache_policy.c \
+ common/mali_kbase_mem.c \
+ common/mali_kbase_mmu.c \
+ common/mali_kbase_jd.c \
+ common/mali_kbase_jm.c \
+ common/mali_kbase_cpuprops.c \
+ common/mali_kbase_gpuprops.c \
+ common/mali_kbase_js.c \
+ common/mali_kbase_js_affinity.c \
+ common/mali_kbase_js_ctx_attr.c \
+ common/mali_kbase_pm.c \
+ common/mali_kbase_event.c \
+ common/mali_kbase_context.c \
+ common/mali_kbase_pm.c \
+ common/mali_kbase_pm_driver.c \
+ common/mali_kbase_pm_metrics.c \
+ common/mali_kbase_pm_ca.c \
+ common/mali_kbase_pm_ca_fixed.c \
+ common/mali_kbase_pm_always_on.c \
+ common/mali_kbase_pm_coarse_demand.c \
+ common/mali_kbase_pm_demand.c \
+ common/mali_kbase_pm_policy.c \
+ common/mali_kbase_config.c \
+ common/mali_kbase_security.c \
+ common/mali_kbase_instr.c \
+ common/mali_kbase_softjobs.c \
+ common/mali_kbase_8401_workaround.c \
+ common/mali_kbase_10969_workaround.c \
+ common/mali_kbase_hw.c \
+ common/mali_kbase_utility.c \
+ common/mali_kbase_mem_lowlevel.c \
+ common/mali_kbase_debug.c \
+ common/mali_kbase_trace_timeline.c \
+ linux/mali_kbase_mem_linux.c \
+ linux/mali_kbase_core_linux.c \
+ linux/mali_kbase_config_linux.c \
+ linux/mali_kbase_sync.c \
+ linux/mali_kbase_sync_user.c \
+
+ifeq ($(MALI_CUSTOMER_RELEASE),0)
+SRC += \
+ common/mali_kbase_pm_ca_random.c \
+ common/mali_kbase_pm_demand_always_powered.c \
+ common/mali_kbase_pm_fast_start.c
+endif
+
+# Job Scheduler Policy: Completely Fair Scheduler
+SRC += common/mali_kbase_js_policy_cfs.c
+
+ifeq ($(CONFIG_MACH_MANTA),y)
+ SRC += common/mali_kbase_mem_alloc_carveout.c
+else
+ SRC += common/mali_kbase_mem_alloc.c
+endif
+
+# ensure GPL version of malisw gets pulled in
+ccflags-y += -I$(KBASE_PATH)
+
+ifeq ($(CONFIG_MALI_NO_MALI),y)
+ # Dummy model
+ SRC += common/mali_kbase_model_dummy.c
+ SRC += linux/mali_kbase_model_linux.c
+ # HW error simulation
+ SRC += common/mali_kbase_model_error_generator.c
+endif
+
+ifeq ($(MALI_MOCK_TEST),1)
+ # Test functionality
+ SRC += ../tests/internal/src/mock/mali_kbase_pm_driver_mock.c
+endif
+
+# in-tree/out-of-tree logic needs to be slightly different to determine if a file is present
+ifeq ($(KBUILD_EXTMOD),)
+# in-tree
+MALI_METRICS_PATH = $(srctree)/drivers/gpu/arm/t6xx/kbase/src/linux
+else
+# out-of-tree
+MALI_METRICS_PATH = $(KBUILD_EXTMOD)/linux
+endif
+
+# Use vsync metrics example using PL111 driver, if available
+ifeq ($(wildcard $(MALI_METRICS_PATH)/mali_kbase_pm_metrics_linux.c),)
+ SRC += common/mali_kbase_pm_metrics_dummy.c
+else
+ SRC += linux/mali_kbase_pm_metrics_linux.c
+endif
+
+ifeq ($(CONFIG_MALI_PLATFORM_VEXPRESS),y)
+ SRC += platform/vexpress/mali_kbase_config_vexpress.c \
+ platform/vexpress/mali_kbase_cpu_vexpress.c
+endif
+
+ifeq ($(CONFIG_MALI_PLATFORM_GOLDFISH),y)
+ SRC += platform/goldfish/mali_kbase_config_goldfish.c
+endif
+
+ifeq ($(CONFIG_MALI_PLATFORM_PBX),y)
+ SRC += platform/pbx/mali_kbase_config_pbx.c
+endif
+
+ifeq ($(CONFIG_MALI_PLATFORM_PANDA),y)
+ SRC += platform/panda/mali_kbase_config_panda.c
+endif
+
+ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y)
+ifeq ($(CONFIG_MALI_T6XX),m)
+# remove begin and end quotes from the Kconfig string type
+ platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME))
+ MALI_PLATFORM_THIRDPARTY_DIR := platform/$(platform_name)
+ include $(src)/platform/$(platform_name)/Kbuild
+else ifeq ($(CONFIG_MALI_T6XX),y)
+ obj-$(CONFIG_MALI_T6XX) += platform/
+endif
+endif
+
+# Tell the Linux build system from which .o file to create the kernel module
+obj-$(CONFIG_MALI_T6XX) += mali_kbase.o
+
+# Tell the Linux build system to enable building of our .c files
+mali_kbase-y := $(SRC:.c=.o)
+
+
diff --git a/drivers/gpu/arm/t6xx/kbase/src/Makefile b/drivers/gpu/arm/t6xx/kbase/src/Makefile
new file mode 100755
index 00000000000..f214d82d168
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/Makefile
@@ -0,0 +1,35 @@
+#
+# (C) COPYRIGHT 2010-2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+
+KDIR ?= /lib/modules/$(shell uname -r)/build
+
+UMP_PATH_RELATIVE = $(CURDIR)/../../../../../base/ump
+KBASE_PATH_RELATIVE = $(CURDIR)/../../kbase
+KDS_PATH_RELATIVE = $(CURDIR)/../../../../../..
+EXTRA_SYMBOLS = $(UMP_PATH_RELATIVE)/src/Module.symvers
+
+ifeq ($(MALI_UNIT_TEST), 1)
+ EXTRA_SYMBOLS += $(KBASE_PATH_RELATIVE)/tests/internal/src/kernel_assert_module/linux/Module.symvers
+endif
+
+# GPL driver supports KDS
+EXTRA_SYMBOLS += $(KDS_PATH_RELATIVE)/drivers/base/kds/Module.symvers
+
+# we get the symbols from modules using KBUILD_EXTRA_SYMBOLS to prevent warnings about unknown functions
+all:
+ $(MAKE) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../../../../include $(SCONS_CFLAGS)" $(SCONS_CONFIGS) KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules
+
+clean:
+ $(MAKE) -C $(KDIR) M=$(CURDIR) clean
diff --git a/drivers/gpu/arm/t6xx/kbase/src/Makefile.kbase b/drivers/gpu/arm/t6xx/kbase/src/Makefile.kbase
new file mode 100755
index 00000000000..1a1ca17e1c7
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/Makefile.kbase
@@ -0,0 +1,16 @@
+#
+# (C) COPYRIGHT 2010 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the
+# GNU General Public License version 2 as published by the Free Software
+# Foundation, and any use by you of this program is subject to the terms
+# of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained
+# from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#
+
+EXTRA_CFLAGS += -I$(ROOT) -I$(KBASE_PATH)/.. -I$(OSK_PATH)/src/linux/include -I$(KBASE_PATH)/platform_$(PLATFORM)
+
diff --git a/drivers/gpu/arm/t6xx/kbase/src/Module.symvers b/drivers/gpu/arm/t6xx/kbase/src/Module.symvers
new file mode 100644
index 00000000000..11459ae7d34
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/Module.symvers
@@ -0,0 +1,43 @@
+0x00000000 ump_dd_handle_create_from_secure_id /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kds_waitall /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/kds/kds EXPORT_SYMBOL
+0x00000000 kds_resource_set_release_sync /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/kds/kds EXPORT_SYMBOL
+0x00000000 ump_import_module_unregister /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kds_resource_term /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/kds/kds EXPORT_SYMBOL
+0x00000000 kbase_destroy_context /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 kbase_instr_hwcnt_dump_complete /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 ump_dd_create_from_phys_blocks_64 /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 ump_dd_reference_release /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kds_async_waitall /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/kds/kds EXPORT_SYMBOL
+0x00000000 ump_dd_phys_blocks_get_64 /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 ump_dd_handle_create_from_phys_blocks /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kbase_create_context /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 kbase_va_free /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 kbase_instr_hwcnt_disable /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 kds_callback_init /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/kds/kds EXPORT_SYMBOL
+0x00000000 ump_import_module_register /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 ump_dd_allocate_64 /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kbase_va_alloc /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 ump_dd_release /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kbase_instr_hwcnt_dump_irq /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 ump_dd_secure_id_get /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kbasep_debug_module_to_str /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 kbase_instr_hwcnt_dump /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 ump_dd_phys_block_count_get /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kbase_instr_hwcnt_enable /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 kbase_find_device /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 ump_dd_kds_resource_get /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kbasep_debug_assert_call_hook /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 kds_callback_term /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/kds/kds EXPORT_SYMBOL
+0x00000000 ump_dd_phys_blocks_get /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 ump_dd_reference_add /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 ump_dd_size_get /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 ump_dd_retain /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 ump_dd_phys_block_get /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 ump_dd_size_get_64 /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kbase_instr_hwcnt_clear /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 ump_dd_from_secure_id /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 ump_dd_allocation_flags_get /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/ump/src/ump EXPORT_SYMBOL
+0x00000000 kds_resource_init /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/kds/kds EXPORT_SYMBOL
+0x00000000 kbase_context_set_create_flags /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 kbase_release_device /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/gpu/arm/t6xx/kbase/src/mali_kbase EXPORT_SYMBOL
+0x00000000 kds_resource_set_release /home/show/workspace/arndale/mali/TX011-SW-99002-r3p0-02rel0/driver/product/kernel/drivers/base/kds/kds EXPORT_SYMBOL
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase.h
new file mode 100755
index 00000000000..8044a93cda2
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase.h
@@ -0,0 +1,435 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _KBASE_H_
+#define _KBASE_H_
+
+#include <malisw/mali_malisw.h>
+
+#include <kbase/mali_kbase_debug.h>
+
+#include <asm/page.h>
+
+#include <linux/atomic.h>
+#include <linux/highmem.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/mm_types.h>
+#include <linux/mutex.h>
+#include <linux/rwsem.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <kbase/mali_base_kernel.h>
+#include <kbase/src/common/mali_kbase_uku.h>
+#include <kbase/src/linux/mali_kbase_linux.h>
+
+#include "mali_kbase_pm.h"
+#include "mali_kbase_mem_lowlevel.h"
+#include "mali_kbase_defs.h"
+#include "mali_kbase_trace_timeline.h"
+#include "mali_kbase_js.h"
+#include "mali_kbase_mem.h"
+#include "mali_kbase_security.h"
+#include "mali_kbase_utility.h"
+
+#include "mali_kbase_cpuprops.h"
+#include "mali_kbase_gpuprops.h"
+#ifdef CONFIG_GPU_TRACEPOINTS
+#include <trace/events/gpu.h>
+#endif
+/**
+ * @page page_base_kernel_main Kernel-side Base (KBase) APIs
+ *
+ * The Kernel-side Base (KBase) APIs are divided up as follows:
+ * - @subpage page_kbase_js_policy
+ */
+
+/**
+ * @defgroup base_kbase_api Kernel-side Base (KBase) APIs
+ */
+
+kbase_device *kbase_device_alloc(void);
+/* note: configuration attributes member of kbdev needs to have been setup before calling kbase_device_init */
+mali_error kbase_device_init(kbase_device * const kbdev);
+void kbase_device_term(kbase_device *kbdev);
+void kbase_device_free(kbase_device *kbdev);
+int kbase_device_has_feature(kbase_device *kbdev, u32 feature);
+kbase_midgard_type kbase_device_get_type(kbase_device *kbdev);
+struct kbase_device *kbase_find_device(int minor); /* Only needed for gator integration */
+
+/**
+ * Ensure that all IRQ handlers have completed execution
+ *
+ * @param kbdev The kbase device
+ */
+void kbase_synchronize_irqs(kbase_device *kbdev);
+
+kbase_context *kbase_create_context(kbase_device *kbdev);
+void kbase_destroy_context(kbase_context *kctx);
+mali_error kbase_context_set_create_flags(kbase_context *kctx, u32 flags);
+
+mali_error kbase_instr_hwcnt_setup(kbase_context *kctx, kbase_uk_hwcnt_setup *setup);
+mali_error kbase_instr_hwcnt_enable(kbase_context *kctx, kbase_uk_hwcnt_setup *setup);
+mali_error kbase_instr_hwcnt_disable(kbase_context *kctx);
+mali_error kbase_instr_hwcnt_clear(kbase_context *kctx);
+mali_error kbase_instr_hwcnt_dump(kbase_context *kctx);
+mali_error kbase_instr_hwcnt_dump_irq(kbase_context *kctx);
+mali_bool kbase_instr_hwcnt_dump_complete(kbase_context *kctx, mali_bool * const success);
+void kbase_instr_hwcnt_suspend(kbase_device *kbdev);
+void kbase_instr_hwcnt_resume(kbase_device *kbdev);
+
+void kbasep_cache_clean_worker(struct work_struct *data);
+void kbase_clean_caches_done(kbase_device *kbdev);
+
+/**
+ * The GPU has completed performance count sampling successfully.
+ */
+void kbase_instr_hwcnt_sample_done(kbase_device *kbdev);
+
+mali_error kbase_create_os_context(kbase_os_context * const osctx);
+void kbase_destroy_os_context(kbase_os_context *osctx);
+
+mali_error kbase_jd_init(kbase_context *kctx);
+void kbase_jd_exit(kbase_context *kctx);
+mali_error kbase_jd_submit(kbase_context *kctx, const kbase_uk_job_submit *user_bag);
+void kbase_jd_done(kbase_jd_atom *katom, int slot_nr, ktime_t *end_timestamp,
+ kbasep_js_atom_done_code done_code);
+void kbase_jd_cancel(kbase_device *kbdev, kbase_jd_atom *katom);
+void kbase_jd_zap_context(kbase_context *kctx);
+mali_bool jd_done_nolock(kbase_jd_atom *katom);
+void kbase_jd_free_external_resources(kbase_jd_atom *katom);
+
+mali_error kbase_job_slot_init(kbase_device *kbdev);
+void kbase_job_slot_halt(kbase_device *kbdev);
+void kbase_job_slot_term(kbase_device *kbdev);
+void kbase_job_done(kbase_device *kbdev, u32 done);
+void kbase_job_zap_context(kbase_context *kctx);
+
+void kbase_job_slot_softstop(kbase_device *kbdev, int js, kbase_jd_atom *target_katom);
+void kbase_job_slot_hardstop(kbase_context *kctx, int js, kbase_jd_atom *target_katom);
+
+void kbase_event_post(kbase_context *ctx, kbase_jd_atom *event);
+int kbase_event_dequeue(kbase_context *ctx, base_jd_event_v2 *uevent);
+int kbase_event_pending(kbase_context *ctx);
+mali_error kbase_event_init(kbase_context *kctx);
+void kbase_event_close(kbase_context *kctx);
+void kbase_event_cleanup(kbase_context *kctx);
+void kbase_event_wakeup(kbase_context *kctx);
+
+int kbase_process_soft_job(kbase_jd_atom *katom);
+mali_error kbase_prepare_soft_job(kbase_jd_atom *katom);
+void kbase_finish_soft_job(kbase_jd_atom *katom);
+void kbase_cancel_soft_job(kbase_jd_atom *katom);
+void kbase_resume_suspended_soft_jobs(kbase_device *kbdev);
+
+/* api used internally for register access. Contains validation and tracing */
+void kbase_reg_write(kbase_device *kbdev, u16 offset, u32 value, kbase_context *kctx);
+u32 kbase_reg_read(kbase_device *kbdev, u16 offset, kbase_context *kctx);
+void kbase_device_trace_register_access(kbase_context *kctx, kbase_reg_access_type type, u16 reg_offset, u32 reg_value);
+void kbase_device_trace_buffer_install(kbase_context *kctx, u32 *tb, size_t size);
+void kbase_device_trace_buffer_uninstall(kbase_context *kctx);
+
+/* api to be ported per OS, only need to do the raw register access */
+void kbase_os_reg_write(kbase_device *kbdev, u16 offset, u32 value);
+u32 kbase_os_reg_read(kbase_device *kbdev, u16 offset);
+
+/** Report a GPU fault.
+ *
+ * This function is called from the interrupt handler when a GPU fault occurs.
+ * It reports the details of the fault using KBASE_DEBUG_PRINT_WARN.
+ *
+ * @param kbdev The kbase device that the GPU fault occurred from.
+ * @param multiple Zero if only GPU_FAULT was raised, non-zero if MULTIPLE_GPU_FAULTS was also set
+ */
+void kbase_report_gpu_fault(kbase_device *kbdev, int multiple);
+
+/** Kill all jobs that are currently running from a context
+ *
+ * This is used in response to a page fault to remove all jobs from the faulting context from the hardware.
+ *
+ * @param kctx The context to kill jobs from
+ */
+void kbase_job_kill_jobs_from_context(kbase_context *kctx);
+
+/**
+ * GPU interrupt handler
+ *
+ * This function is called from the interrupt handler when a GPU irq is to be handled.
+ *
+ * @param kbdev The kbase device to handle an IRQ for
+ * @param val The value of the GPU IRQ status register which triggered the call
+ */
+void kbase_gpu_interrupt(kbase_device *kbdev, u32 val);
+
+/**
+ * Prepare for resetting the GPU.
+ * This function just soft-stops all the slots to ensure that as many jobs as possible are saved.
+ *
+ * The function returns a boolean which should be interpreted as follows:
+ * - MALI_TRUE - Prepared for reset, kbase_reset_gpu should be called.
+ * - MALI_FALSE - Another thread is performing a reset, kbase_reset_gpu should not be called.
+ *
+ * @return See description
+ */
+mali_bool kbase_prepare_to_reset_gpu(kbase_device *kbdev);
+
+/**
+ * Pre-locked version of @a kbase_prepare_to_reset_gpu.
+ *
+ * Identical to @a kbase_prepare_to_reset_gpu, except that the
+ * kbasep_js_device_data::runpool_irq::lock is externally locked.
+ *
+ * @see kbase_prepare_to_reset_gpu
+ */
+mali_bool kbase_prepare_to_reset_gpu_locked(kbase_device *kbdev);
+
+/** Reset the GPU
+ *
+ * This function should be called after kbase_prepare_to_reset_gpu iff it returns MALI_TRUE.
+ * It should never be called without a corresponding call to kbase_prepare_to_reset_gpu.
+ *
+ * After this function is called (or not called if kbase_prepare_to_reset_gpu returned MALI_FALSE),
+ * the caller should wait for kbdev->reset_waitq to be signalled to know when the reset has completed.
+ */
+void kbase_reset_gpu(kbase_device *kbdev);
+
+/**
+ * Pre-locked version of @a kbase_reset_gpu.
+ *
+ * Identical to @a kbase_reset_gpu, except that the
+ * kbasep_js_device_data::runpool_irq::lock is externally locked.
+ *
+ * @see kbase_reset_gpu
+ */
+void kbase_reset_gpu_locked(kbase_device *kbdev);
+
+/** Returns the name associated with a Mali exception code
+ *
+ * @param[in] exception_code exception code
+ * @return name associated with the exception code
+ */
+const char *kbase_exception_name(u32 exception_code);
+
+/**
+ * Check whether a system suspend is in progress, or has already been suspended
+ *
+ * The caller should ensure that either kbdev->pm.active_count_lock is held, or
+ * a dmb was executed recently (to ensure the value is most
+ * up-to-date). However, without a lock the value could change afterwards.
+ *
+ * @return MALI_FALSE if a suspend is not in progress
+ * @return !=MALI_FALSE otherwise
+ */
+static INLINE mali_bool kbase_pm_is_suspending(struct kbase_device *kbdev) {
+ return kbdev->pm.suspending;
+}
+
+/**
+ * Return the atom's ID, as was originally supplied by userspace in
+ * base_jd_atom_v2::atom_number
+ */
+static INLINE int kbase_jd_atom_id(kbase_context *kctx, kbase_jd_atom *katom)
+{
+ int result;
+ KBASE_DEBUG_ASSERT(kctx);
+ KBASE_DEBUG_ASSERT(katom);
+ KBASE_DEBUG_ASSERT(katom->kctx == kctx);
+
+ result = katom - &kctx->jctx.atoms[0];
+ KBASE_DEBUG_ASSERT(result >= 0 && result <= BASE_JD_ATOM_COUNT);
+ return result;
+}
+
+#if KBASE_TRACE_ENABLE != 0
+/** Add trace values about a job-slot
+ *
+ * @note Any functions called through this macro will still be evaluated in
+ * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
+ * functions called to get the parameters supplied to this macro must:
+ * - be static or static inline
+ * - must just return 0 and have no other statements present in the body.
+ */
+#define KBASE_TRACE_ADD_SLOT(kbdev, code, ctx, katom, gpu_addr, jobslot) \
+ kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
+ KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, 0)
+
+/** Add trace values about a job-slot, with info
+ *
+ * @note Any functions called through this macro will still be evaluated in
+ * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
+ * functions called to get the parameters supplied to this macro must:
+ * - be static or static inline
+ * - must just return 0 and have no other statements present in the body.
+ */
+#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val) \
+ kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
+ KBASE_TRACE_FLAG_JOBSLOT, 0, jobslot, info_val)
+
+/** Add trace values about a ctx refcount
+ *
+ * @note Any functions called through this macro will still be evaluated in
+ * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
+ * functions called to get the parameters supplied to this macro must:
+ * - be static or static inline
+ * - must just return 0 and have no other statements present in the body.
+ */
+#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount) \
+ kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
+ KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, 0)
+/** Add trace values about a ctx refcount, and info
+ *
+ * @note Any functions called through this macro will still be evaluated in
+ * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
+ * functions called to get the parameters supplied to this macro must:
+ * - be static or static inline
+ * - must just return 0 and have no other statements present in the body.
+ */
+#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val) \
+ kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
+ KBASE_TRACE_FLAG_REFCOUNT, refcount, 0, info_val)
+
+/** Add trace values (no slot or refcount)
+ *
+ * @note Any functions called through this macro will still be evaluated in
+ * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when KBASE_TRACE_ENABLE == 0 any
+ * functions called to get the parameters supplied to this macro must:
+ * - be static or static inline
+ * - must just return 0 and have no other statements present in the body.
+ */
+#define KBASE_TRACE_ADD(kbdev, code, ctx, katom, gpu_addr, info_val) \
+ kbasep_trace_add(kbdev, KBASE_TRACE_CODE(code), ctx, katom, gpu_addr, \
+ 0, 0, 0, info_val)
+
+/** Clear the trace */
+#define KBASE_TRACE_CLEAR(kbdev) \
+ kbasep_trace_clear(kbdev)
+
+/** Dump the slot trace */
+#define KBASE_TRACE_DUMP(kbdev) \
+ kbasep_trace_dump(kbdev)
+
+/** PRIVATE - do not use directly. Use KBASE_TRACE_ADD() instead */
+void kbasep_trace_add(kbase_device *kbdev, kbase_trace_code code, void *ctx, kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, u32 info_val);
+/** PRIVATE - do not use directly. Use KBASE_TRACE_CLEAR() instead */
+void kbasep_trace_clear(kbase_device *kbdev);
+#else
+#ifdef CONFIG_MALI_SYSTEM_TRACE
+/* Dispatch kbase trace events as system trace events */
+#include <kbase/src/linux/mali_linux_kbase_trace.h>
+#define KBASE_TRACE_ADD_SLOT( kbdev, code, ctx, katom, gpu_addr, jobslot )\
+ trace_mali_##code(jobslot, 0)
+
+#define KBASE_TRACE_ADD_SLOT_INFO( kbdev, code, ctx, katom, gpu_addr, jobslot, info_val )\
+ trace_mali_##code(jobslot, info_val)
+
+#define KBASE_TRACE_ADD_REFCOUNT( kbdev, code, ctx, katom, gpu_addr, refcount )\
+ trace_mali_##code(refcount, 0)
+
+#define KBASE_TRACE_ADD_REFCOUNT_INFO( kbdev, code, ctx, katom, gpu_addr, refcount, info_val )\
+ trace_mali_##code(refcount, info_val)
+
+#define KBASE_TRACE_ADD( kbdev, code, ctx, katom, gpu_addr, info_val )\
+ trace_mali_##code(gpu_addr, info_val)
+
+#define KBASE_TRACE_CLEAR( kbdev )\
+ do{\
+ CSTD_UNUSED(kbdev);\
+ CSTD_NOP(0);\
+ }while(0)
+#define KBASE_TRACE_DUMP( kbdev )\
+ do{\
+ CSTD_UNUSED(kbdev);\
+ CSTD_NOP(0);\
+ }while(0)
+
+#else /* CONFIG_MALI_SYSTEM_TRACE */
+#define KBASE_TRACE_ADD_SLOT( kbdev, code, ctx, katom, gpu_addr, jobslot )\
+ do{\
+ CSTD_UNUSED(kbdev);\
+ CSTD_NOP(code);\
+ CSTD_UNUSED(ctx);\
+ CSTD_UNUSED(katom);\
+ CSTD_UNUSED(gpu_addr);\
+ CSTD_UNUSED(jobslot);\
+ } while (0)
+
+#define KBASE_TRACE_ADD_SLOT_INFO(kbdev, code, ctx, katom, gpu_addr, jobslot, info_val)\
+ do {\
+ CSTD_UNUSED(kbdev);\
+ CSTD_NOP(code);\
+ CSTD_UNUSED(ctx);\
+ CSTD_UNUSED(katom);\
+ CSTD_UNUSED(gpu_addr);\
+ CSTD_UNUSED(jobslot);\
+ CSTD_UNUSED(info_val);\
+ CSTD_NOP(0);\
+ } while (0)
+
+#define KBASE_TRACE_ADD_REFCOUNT(kbdev, code, ctx, katom, gpu_addr, refcount)\
+ do {\
+ CSTD_UNUSED(kbdev);\
+ CSTD_NOP(code);\
+ CSTD_UNUSED(ctx);\
+ CSTD_UNUSED(katom);\
+ CSTD_UNUSED(gpu_addr);\
+ CSTD_UNUSED(refcount);\
+ CSTD_NOP(0);\
+ } while (0)
+
+#define KBASE_TRACE_ADD_REFCOUNT_INFO(kbdev, code, ctx, katom, gpu_addr, refcount, info_val)\
+ do {\
+ CSTD_UNUSED(kbdev);\
+ CSTD_NOP(code);\
+ CSTD_UNUSED(ctx);\
+ CSTD_UNUSED(katom);\
+ CSTD_UNUSED(gpu_addr);\
+ CSTD_UNUSED(info_val);\
+ CSTD_NOP(0);\
+ } while (0)
+
+#define KBASE_TRACE_ADD(kbdev, code, subcode, ctx, katom, val)\
+ do {\
+ CSTD_UNUSED(kbdev);\
+ CSTD_NOP(code);\
+ CSTD_UNUSED(subcode);\
+ CSTD_UNUSED(ctx);\
+ CSTD_UNUSED(katom);\
+ CSTD_UNUSED(val);\
+ CSTD_NOP(0);\
+ }while(0)
+
+#define KBASE_TRACE_CLEAR( kbdev )\
+ do{\
+ CSTD_UNUSED(kbdev);\
+ CSTD_NOP(0);\
+ }while(0)
+#define KBASE_TRACE_DUMP( kbdev )\
+ do{\
+ CSTD_UNUSED(kbdev);\
+ CSTD_NOP(0);\
+ }while(0)
+#endif /* CONFIG_MALI_SYSTEM_TRACE */
+#endif
+/** PRIVATE - do not use directly. Use KBASE_TRACE_DUMP() instead */
+void kbasep_trace_dump(kbase_device *kbdev);
+#endif
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_10969_workaround.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_10969_workaround.c
new file mode 100755
index 00000000000..f14f3be17e7
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_10969_workaround.c
@@ -0,0 +1,182 @@
+/*
+ *
+ * (C) COPYRIGHT 2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#include <kbase/src/common/mali_kbase.h>
+
+/* This function is used to solve an HW issue with single iterator GPUs.
+ * If a fragment job is soft-stopped on the edge of its bounding box, can happen that the
+ * restart index is out of bounds and the rerun causes a tile range fault. If this happens
+ * we try to clamp the restart index to a correct value and rerun the job.
+ */
+/* Mask of X and Y coordinates for the coordinates words in the descriptors*/
+#define X_COORDINATE_MASK 0x00000FFF
+#define Y_COORDINATE_MASK 0x0FFF0000
+/* Max number of words needed from the fragment shader job descriptor */
+#define JOB_HEADER_SIZE_IN_WORDS 10
+#define JOB_HEADER_SIZE (JOB_HEADER_SIZE_IN_WORDS*sizeof(u32))
+
+/* Word 0: Status Word */
+#define JOB_DESC_STATUS_WORD 0
+/* Word 1: Restart Index */
+#define JOB_DESC_RESTART_INDEX_WORD 1
+/* Word 2: Fault address low word */
+#define JOB_DESC_FAULT_ADDR_LOW_WORD 2
+/* Word 8: Minimum Tile Coordinates */
+#define FRAG_JOB_DESC_MIN_TILE_COORD_WORD 8
+/* Word 9: Maximum Tile Coordinates */
+#define FRAG_JOB_DESC_MAX_TILE_COORD_WORD 9
+
+int kbasep_10969_workaround_clamp_coordinates(kbase_jd_atom *katom)
+{
+ u32 clamped = 0;
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD,"Called TILE_RANGE_FAULT workaround clamping function. \n");
+ if (katom->core_req & BASE_JD_REQ_FS){
+ kbase_va_region * region = kbase_region_tracker_find_region_enclosing_address(katom->kctx, katom->jc );
+
+ if (region){
+ phys_addr_t * page_array = kbase_get_phy_pages(region);
+
+ if (page_array){
+ u64 page_index = (katom->jc >> PAGE_SHIFT) - region->start_pfn;
+ u32 offset = katom->jc & (~PAGE_MASK);
+ u32 * page_1 = NULL;
+ u32 * page_2 = NULL;
+ u32 job_header[JOB_HEADER_SIZE_IN_WORDS];
+ void* dst = job_header;
+
+ /* we need the first 10 words of the fragment shader job descriptor. We need to check
+ * that the offset + 10 words is less that the page size otherwise we need to load the next
+ * page. page_size_overflow will be equal to 0 in case the whole descriptor is within the page
+ * >0 otherwise.
+ */
+ u32 copy_size = MIN(PAGE_SIZE - offset, JOB_HEADER_SIZE);
+
+ page_1 = kmap_atomic(pfn_to_page(PFN_DOWN(page_array[page_index])));
+ if (!page_1){
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD, "Restart Index clamping function not able to map page 1 \n");
+ goto exit;
+ }
+ /* page_1 is a u32 pointer, offset is expressed in bytes */
+ page_1 += offset>>2;
+ kbase_sync_to_cpu(page_array[page_index] + offset, page_1, copy_size);
+ memcpy(dst, page_1, copy_size);
+
+ /* The data needed overflows page the dimension, need to map the subsequent page */
+ if (copy_size < JOB_HEADER_SIZE){
+ page_2 = kmap_atomic(pfn_to_page(PFN_DOWN(page_array[page_index + 1])));
+ if (!page_2){
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD, "Restart Index clamping function not able to map page 2 \n");
+ kunmap_atomic(page_1);
+ goto exit;
+ }
+ kbase_sync_to_cpu(page_array[page_index + 1], page_2, JOB_HEADER_SIZE - copy_size);
+ memcpy(dst + copy_size, page_2, JOB_HEADER_SIZE - copy_size);
+ }
+
+ /* We managed to correctly map one or two pages (in case of overflow ) */
+ {
+ u32 minX,minY,maxX,maxY;
+ u32 restartX,restartY;
+
+ /* Get Bounding Box data and restart index from fault address low word*/
+ minX = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & X_COORDINATE_MASK;
+ minY = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & Y_COORDINATE_MASK;
+ maxX = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & X_COORDINATE_MASK;
+ maxY = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & Y_COORDINATE_MASK;
+ restartX = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & X_COORDINATE_MASK;
+ restartY = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & Y_COORDINATE_MASK;
+
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD, "Before Clamping: \n" \
+ "Jobstatus: %08x \n" \
+ "restartIdx: %08x \n" \
+ "Fault_addr_low: %08x \n" \
+ "minCoordsX: %08x minCoordsY: %08x \n" \
+ "maxCoordsX: %08x maxCoordsY: %08x \n",
+ job_header[JOB_DESC_STATUS_WORD],
+ job_header[JOB_DESC_RESTART_INDEX_WORD],
+ job_header[JOB_DESC_FAULT_ADDR_LOW_WORD],
+ minX,minY,
+ maxX,maxY );
+
+ /* Set the restart index to the one which generated the fault*/
+ job_header[JOB_DESC_RESTART_INDEX_WORD] = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD];
+
+ if (restartX < minX){
+ job_header[JOB_DESC_RESTART_INDEX_WORD] = (minX) | restartY;
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD,
+ "Clamping restart X index to minimum. %08x clamped to %08x \n",
+ restartX, minX );
+ clamped = 1;
+ }
+ if (restartY < minY){
+ job_header[JOB_DESC_RESTART_INDEX_WORD] = (minY) | restartX;
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD,
+ "Clamping restart Y index to minimum. %08x clamped to %08x \n",
+ restartY, minY );
+ clamped = 1;
+ }
+ if (restartX > maxX){
+ job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxX) | restartY;
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD,
+ "Clamping restart X index to maximum. %08x clamped to %08x \n",
+ restartX, maxX );
+ clamped = 1;
+ }
+ if (restartY > maxY){
+ job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxY) | restartX;
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD,"Clamping restart Y index to maximum. %08x clamped to %08x \n",
+ restartY, maxY );
+ clamped = 1;
+ }
+
+ if (clamped){
+ /* Reset the fault address low word and set the job status to STOPPED */
+ job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] = 0x0;
+ job_header[JOB_DESC_STATUS_WORD] = BASE_JD_EVENT_STOPPED;
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD, "After Clamping: \n" \
+ "Jobstatus: %08x \n" \
+ "restartIdx: %08x \n" \
+ "Fault_addr_low: %08x \n" \
+ "minCoordsX: %08x minCoordsY: %08x \n" \
+ "maxCoordsX: %08x maxCoordsY: %08x \n",
+ job_header[JOB_DESC_STATUS_WORD],
+ job_header[JOB_DESC_RESTART_INDEX_WORD],
+ job_header[JOB_DESC_FAULT_ADDR_LOW_WORD],
+ minX,minY,
+ maxX,maxY );
+
+ /* Flush CPU cache to update memory for future GPU reads*/
+ memcpy(page_1, dst, copy_size);
+ kbase_sync_to_memory(page_array[page_index] + offset, page_1, copy_size);
+
+ if (copy_size < JOB_HEADER_SIZE){
+ memcpy(page_2, dst + copy_size, JOB_HEADER_SIZE - copy_size);
+ kbase_sync_to_memory(page_array[page_index + 1], page_2, JOB_HEADER_SIZE - copy_size);
+ }
+
+ }
+ }
+ if (copy_size < JOB_HEADER_SIZE)
+ kunmap_atomic(page_2);
+
+ kunmap_atomic(page_1);
+ }
+ }
+ }
+exit:
+ return clamped;
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_10969_workaround.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_10969_workaround.h
new file mode 100755
index 00000000000..0fd32eacbb8
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_10969_workaround.h
@@ -0,0 +1,23 @@
+/*
+ *
+ * (C) COPYRIGHT 2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _KBASE_10969_WORKAROUND_
+#define _KBASE_10969_WORKAROUND_
+
+int kbasep_10969_workaround_clamp_coordinates( kbase_jd_atom * katom );
+
+#endif /* _KBASE_10969_WORKAROUND_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_8401_workaround.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_8401_workaround.c
new file mode 100755
index 00000000000..bf42e41668b
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_8401_workaround.c
@@ -0,0 +1,422 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_8401_workaround.c
+ * Functions related to working around BASE_HW_ISSUE_8401
+ */
+
+#include <kbase/src/common/mali_kbase.h>
+#include <kbase/src/common/mali_kbase_defs.h>
+#include <kbase/src/common/mali_kbase_jm.h>
+#include <kbase/src/common/mali_kbase_8401_workaround.h>
+
+#define WORKAROUND_PAGE_OFFSET (2)
+#define URT_POINTER_INDEX (20)
+#define RMU_POINTER_INDEX (23)
+#define RSD_POINTER_INDEX (24)
+#define TSD_POINTER_INDEX (31)
+
+static const u32 compute_job_32bit_header[] = {
+ /* Job Descriptor Header */
+
+ /* Job Status */
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ /* Flags and Indices */
+ /* job_type = compute shader job */
+ 0x00000008, 0x00000000,
+ /* Pointer to next job */
+ 0x00000000,
+ /* Reserved */
+ 0x00000000,
+ /* Job Dimension Data */
+ 0x0000000f, 0x21040842,
+ /* Task Split */
+ 0x08000000,
+ /* Reserved */
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+
+ /* Draw Call Descriptor - 32 bit (Must be aligned to a 64-byte boundry) */
+
+ /* Flags */
+ 0x00000004,
+ /* Primary Attribute Offset */
+ 0x00000000,
+ /* Primitive Index Base Value */
+ 0x00000000,
+
+ /* Pointer To Vertex Position Array (64-byte alignment) */
+ 0x00000000,
+ /* Pointer To Uniform Remapping Table (8-byte alignment) */
+ 0,
+ /* Pointer To Image Descriptor Pointer Table */
+ 0x00000000,
+ /* Pointer To Sampler Array */
+ 0x00000000,
+ /* Pointer To Register-Mapped Uniform Data Area (16-byte alignment) */
+ 0,
+ /* Pointer To Renderer State Descriptor (64-byte alignment) */
+ 0,
+ /* Pointer To Primary Attribute Buffer Array */
+ 0x00000000,
+ /* Pointer To Primary Attribute Array */
+ 0x00000000,
+ /* Pointer To Secondary Attribute Buffer Array */
+ 0x00000000,
+ /* Pointer To Secondary Attribute Array */
+ 0x00000000,
+ /* Pointer To Viewport Descriptor */
+ 0x00000000,
+ /* Pointer To Occlusion Query Result */
+ 0x00000000,
+ /* Pointer To Thread Storage (64 byte alignment) */
+ 0,
+};
+
+static const u32 compute_job_32bit_urt[] = {
+ /* Uniform Remapping Table Entry */
+ 0, 0,
+};
+
+static const u32 compute_job_32bit_rmu[] = {
+ /* Register Mapped Uniform Data Area (16 byte aligned), an array of 128-bit
+ * register values.
+ *
+ * NOTE: this is also used as the URT pointer, so the first 16-byte entry
+ * must be all zeros.
+ *
+ * For BASE_HW_ISSUE_8987, we place 16 RMUs here, because this should only
+ * be run concurrently with other GLES jobs (i.e. FS jobs from slot 0).
+ */
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+static const u32 compute_job_32bit_rsd[] = {
+ /* Renderer State Descriptor */
+
+ /* Shader program inital PC (low) */
+ 0x00000001,
+ /* Shader program initial PC (high) */
+ 0x00000000,
+ /* Image descriptor array sizes */
+ 0x00000000,
+ /* Attribute array sizes */
+ 0x00000000,
+ /* Uniform array size and Shader Flags */
+ /* Flags set: R, D, SE, Reg Uniforms==16, FPM==OpenCL */
+ 0x42003800,
+ /* Depth bias */
+ 0x00000000,
+ /* Depth slope bias */
+ 0x00000000,
+ /* Depth bias clamp */
+ 0x00000000,
+ /* Multisample Write Mask and Flags */
+ 0x00000000,
+ /* Stencil Write Masks and Alpha parameters */
+ 0x00000000,
+ /* Stencil tests - forward facing */
+ 0x00000000,
+ /* Stencel tests - back facing */
+ 0x00000000,
+ /* Alpha Test Reference Value */
+ 0x00000000,
+ /* Thread Balancing Information */
+ 0x00000000,
+ /* Blend Parameters or Pointer (low) */
+ 0x00000000,
+ /* Blend Parameters or Pointer (high) */
+ 0x00000000,
+};
+
+static const u32 compute_job_32bit_tsd[] = {
+ /* Thread Storage Descriptor */
+
+ /* Thread Local Storage Sizes */
+ 0x00000000,
+ /* Workgroup Local Memory Area Flags */
+ 0x0000001f,
+ /* Pointer to Local Storage Area */
+ 0x00021000, 0x00000001,
+ /* Pointer to Workgroup Local Storage Area */
+ 0x00000000, 0x00000000,
+ /* Pointer to Shader Exception Handler */
+ 0x00000000, 0x00000000
+};
+
+static kbase_jd_atom dummy_job_atom[KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT];
+
+/**
+ * Initialize the compute job sturcture.
+ */
+
+static void kbasep_8401_workaround_update_job_pointers(u32 *dummy_compute_job, int page_nr)
+{
+ u32 base_address = (page_nr + WORKAROUND_PAGE_OFFSET) * PAGE_SIZE;
+ u8 *dummy_job = (u8 *) dummy_compute_job;
+ u8 *dummy_job_urt;
+ u8 *dummy_job_rmu;
+ u8 *dummy_job_rsd;
+ u8 *dummy_job_tsd;
+
+ KBASE_DEBUG_ASSERT(dummy_compute_job);
+
+ /* determin where each job section goes taking alignment restrictions into consideration */
+ dummy_job_urt = (u8 *) ((((uintptr_t) dummy_job + sizeof(compute_job_32bit_header)) + 7) & ~7);
+ dummy_job_rmu = (u8 *) ((((uintptr_t) dummy_job_urt + sizeof(compute_job_32bit_urt)) + 15) & ~15);
+ dummy_job_rsd = (u8 *) ((((uintptr_t) dummy_job_rmu + sizeof(compute_job_32bit_rmu)) + 63) & ~63);
+ dummy_job_tsd = (u8 *) ((((uintptr_t) dummy_job_rsd + sizeof(compute_job_32bit_rsd)) + 63) & ~63);
+
+ /* Make sure the job fits within a single page */
+ KBASE_DEBUG_ASSERT(PAGE_SIZE > ((dummy_job_tsd + sizeof(compute_job_32bit_tsd)) - dummy_job));
+
+ /* Copy the job sections to the allocated memory */
+ memcpy(dummy_job, compute_job_32bit_header, sizeof(compute_job_32bit_header));
+ memcpy(dummy_job_urt, compute_job_32bit_urt, sizeof(compute_job_32bit_urt));
+ memcpy(dummy_job_rmu, compute_job_32bit_rmu, sizeof(compute_job_32bit_rmu));
+ memcpy(dummy_job_rsd, compute_job_32bit_rsd, sizeof(compute_job_32bit_rsd));
+ memcpy(dummy_job_tsd, compute_job_32bit_tsd, sizeof(compute_job_32bit_tsd));
+
+ /* Update header pointers */
+ *(dummy_compute_job + URT_POINTER_INDEX) = (dummy_job_urt - dummy_job) + base_address;
+ *(dummy_compute_job + RMU_POINTER_INDEX) = (dummy_job_rmu - dummy_job) + base_address;
+ *(dummy_compute_job + RSD_POINTER_INDEX) = (dummy_job_rsd - dummy_job) + base_address;
+ *(dummy_compute_job + TSD_POINTER_INDEX) = (dummy_job_tsd - dummy_job) + base_address;
+ /* Update URT pointer */
+ *((u32 *) dummy_job_urt + 0) = (((dummy_job_rmu - dummy_job) + base_address) << 8) & 0xffffff00;
+ *((u32 *) dummy_job_urt + 1) = (((dummy_job_rmu - dummy_job) + base_address) >> 24) & 0xff;
+}
+
+/**
+ * Initialize the memory for 8401 workaround.
+ */
+
+mali_error kbasep_8401_workaround_init(kbase_device * const kbdev)
+{
+ kbasep_js_device_data *js_devdata;
+ kbase_context *workaround_kctx;
+ int i;
+ u16 as_present_mask;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+ KBASE_DEBUG_ASSERT(kbdev->workaround_kctx == NULL);
+
+ js_devdata = &kbdev->js_data;
+
+ /* For this workaround we reserve one address space to allow us to
+ * submit a special job independent of other contexts */
+ --(kbdev->nr_hw_address_spaces);
+
+ /* Only update nr_user_address_spaces if it was unchanged - to ensure
+ * HW workarounds that have modified this will still work */
+ if (kbdev->nr_user_address_spaces == (kbdev->nr_hw_address_spaces + 1))
+ --(kbdev->nr_user_address_spaces);
+
+ KBASE_DEBUG_ASSERT(kbdev->nr_user_address_spaces <= kbdev->nr_hw_address_spaces);
+
+ /* Recalculate the free address spaces bit-pattern */
+ as_present_mask = (1U << kbdev->nr_hw_address_spaces) - 1;
+ js_devdata->as_free &= as_present_mask;
+
+ workaround_kctx = kbase_create_context(kbdev);
+ if (!workaround_kctx)
+ return MALI_ERROR_FUNCTION_FAILED;
+
+ /* Allocate the pages required to contain the job */
+ if (MALI_ERROR_NONE != kbase_mem_allocator_alloc(&workaround_kctx->osalloc, KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT, kbdev->workaround_compute_job_pa, 0))
+ goto no_pages;
+
+ /* Get virtual address of mapped memory and write a compute job for each page */
+ for (i = 0; i < KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT; i++) {
+ kbdev->workaround_compute_job_va[i] = kmap(pfn_to_page(PFN_DOWN(kbdev->workaround_compute_job_pa[i])));
+ if (NULL == kbdev->workaround_compute_job_va[i])
+ goto page_free;
+
+ /* Generate the compute job data */
+ kbasep_8401_workaround_update_job_pointers((u32 *) kbdev->workaround_compute_job_va[i], i);
+ }
+
+ /* Insert pages to the gpu mmu. */
+ kbase_gpu_vm_lock(workaround_kctx);
+
+ kbase_mmu_insert_pages(workaround_kctx,
+ /* vpfn = page number */
+ (u64) WORKAROUND_PAGE_OFFSET,
+ /* physical address */
+ kbdev->workaround_compute_job_pa,
+ /* number of pages */
+ KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT,
+ /* flags */
+ KBASE_REG_GPU_RD | KBASE_REG_CPU_RD | KBASE_REG_CPU_WR | KBASE_REG_GPU_WR);
+
+ kbase_gpu_vm_unlock(workaround_kctx);
+
+ kbdev->workaround_kctx = workaround_kctx;
+ return MALI_ERROR_NONE;
+ page_free:
+ while (i--)
+ kunmap(pfn_to_page(PFN_DOWN(kbdev->workaround_compute_job_pa[i])));
+
+ kbase_mem_allocator_free(&workaround_kctx->osalloc, KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT, kbdev->workaround_compute_job_pa, MALI_TRUE);
+ no_pages:
+ kbase_destroy_context(workaround_kctx);
+
+ return MALI_ERROR_FUNCTION_FAILED;
+}
+
+/**
+ * Free up the memory used by 8401 workaround.
+ **/
+
+void kbasep_8401_workaround_term(kbase_device *kbdev)
+{
+ kbasep_js_device_data *js_devdata;
+ int i;
+ u16 restored_as;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+ KBASE_DEBUG_ASSERT(kbdev->workaround_kctx);
+
+ js_devdata = &kbdev->js_data;
+
+ for (i = 0; i < KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT; i++)
+ kunmap(pfn_to_page(PFN_DOWN(kbdev->workaround_compute_job_pa[i])));
+
+ kbase_mem_allocator_free(&kbdev->workaround_kctx->osalloc, KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT, kbdev->workaround_compute_job_pa, MALI_TRUE);
+
+ kbase_destroy_context(kbdev->workaround_kctx);
+ kbdev->workaround_kctx = NULL;
+
+ /* Free up the workaround address space */
+ kbdev->nr_hw_address_spaces++;
+
+ if (kbdev->nr_user_address_spaces == (kbdev->nr_hw_address_spaces - 1)) {
+ /* Only update nr_user_address_spaces if it was unchanged - to ensure
+ * HW workarounds that have modified this will still work */
+ ++(kbdev->nr_user_address_spaces);
+ }
+ KBASE_DEBUG_ASSERT(kbdev->nr_user_address_spaces <= kbdev->nr_hw_address_spaces);
+
+ /* Recalculate the free address spaces bit-pattern */
+ restored_as = (1U << kbdev->nr_hw_address_spaces);
+ js_devdata->as_free |= restored_as;
+}
+
+/**
+ * Submit the 8401 workaround job.
+ *
+ * Important for BASE_HW_ISSUE_8987: This job always uses 16 RMUs
+ * - Therefore, on slot[1] it will always use the same number of RMUs as another
+ * GLES job.
+ * - On slot[2], no other job (GLES or otherwise) will be running on the
+ * cores, by virtue of it being slot[2]. Therefore, any value of RMUs is
+ * acceptable.
+ */
+void kbasep_8401_submit_dummy_job(kbase_device *kbdev, int js)
+{
+ u32 cfg;
+ mali_addr64 jc;
+ u32 pgd_high;
+
+ /* While this workaround is active we reserve the last address space just for submitting the dummy jobs */
+ int as = kbdev->nr_hw_address_spaces;
+
+ /* Don't issue compute jobs on job slot 0 */
+ KBASE_DEBUG_ASSERT(js != 0);
+ KBASE_DEBUG_ASSERT(js < KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT);
+
+ /* Job chain GPU address */
+ jc = (js + WORKAROUND_PAGE_OFFSET) * PAGE_SIZE; /* GPU phys address (see kbase_mmu_insert_pages call in kbasep_8401_workaround_init */
+
+ /* Clear the job status words which may contain values from a previous job completion */
+ memset(kbdev->workaround_compute_job_va[js], 0, 4 * sizeof(u32));
+
+ /* Get the affinity of the previous job */
+ dummy_job_atom[js].affinity = ((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_LO), NULL)) | (((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_HI), NULL)) << 32);
+
+ /* Don't submit a compute job if the affinity was previously zero (i.e. no jobs have run yet on this slot) */
+ if (!dummy_job_atom[js].affinity)
+ return;
+
+ /* Ensure that our page tables are programmed into the MMU */
+ kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_TRANSTAB_LO), (kbdev->workaround_kctx->pgd & ASn_TRANSTAB_ADDR_SPACE_MASK) | ASn_TRANSTAB_READ_INNER | ASn_TRANSTAB_ADRMODE_TABLE, NULL);
+
+ /* Need to use a conditional expression to avoid "right shift count >= width of type"
+ * error when using an if statement - although the size_of condition is evaluated at compile
+ * time the unused branch is not removed until after it is type-checked and the error
+ * produced.
+ */
+ pgd_high = sizeof(kbdev->workaround_kctx->pgd) > 4 ? (kbdev->workaround_kctx->pgd >> 32) : 0;
+ kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_TRANSTAB_HI), pgd_high, NULL);
+
+ kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_MEMATTR_LO), ASn_MEMATTR_IMPL_DEF_CACHE_POLICY, NULL);
+ kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_MEMATTR_HI), ASn_MEMATTR_IMPL_DEF_CACHE_POLICY, NULL);
+ kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_COMMAND), ASn_COMMAND_UPDATE, NULL);
+
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_LO), jc & 0xFFFFFFFF, NULL);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_HI), jc >> 32, NULL);
+
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_NEXT_LO), dummy_job_atom[js].affinity & 0xFFFFFFFF, NULL);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_NEXT_HI), dummy_job_atom[js].affinity >> 32, NULL);
+
+ /* start MMU, medium priority, cache clean/flush on end, clean/flush on start */
+ cfg = as | JSn_CONFIG_END_FLUSH_CLEAN_INVALIDATE | JSn_CONFIG_START_MMU | JSn_CONFIG_START_FLUSH_CLEAN_INVALIDATE | JSn_CONFIG_THREAD_PRI(8);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_CONFIG_NEXT), cfg, NULL);
+
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_SUBMIT, NULL, 0, jc, js);
+
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), JSn_COMMAND_START, NULL);
+ /* Report that the job has been submitted */
+ kbasep_jm_enqueue_submit_slot(&kbdev->jm_slots[js], &dummy_job_atom[js]);
+}
+
+/**
+ * Check if the katom given is a dummy compute job.
+ */
+mali_bool kbasep_8401_is_workaround_job(kbase_jd_atom *katom)
+{
+ int i;
+
+ /* Note: we don't check the first dummy_job_atom as slot 0 is never used for the workaround */
+ for (i = 1; i < KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT; i++) {
+ if (katom == &dummy_job_atom[i]) {
+ /* This is a dummy job */
+ return MALI_TRUE;
+ }
+ }
+
+ /* This is a real job */
+ return MALI_FALSE;
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_8401_workaround.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_8401_workaround.h
new file mode 100755
index 00000000000..49e673587f1
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_8401_workaround.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_8401_workaround.h
+ * Functions related to working around BASE_HW_ISSUE_8401
+ */
+
+#ifndef _KBASE_8401_WORKAROUND_H_
+#define _KBASE_8401_WORKAROUND_H_
+
+mali_error kbasep_8401_workaround_init(kbase_device * const kbdev);
+void kbasep_8401_workaround_term(kbase_device *kbdev);
+void kbasep_8401_submit_dummy_job(kbase_device *kbdev, int js);
+mali_bool kbasep_8401_is_workaround_job(kbase_jd_atom *katom);
+
+#endif /* _KBASE_8401_WORKAROUND_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cache_policy.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cache_policy.c
new file mode 100755
index 00000000000..202ca420e9a
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cache_policy.c
@@ -0,0 +1,39 @@
+/*
+ *
+ * (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_cache_policy.h
+ * Cache Policy API.
+ */
+
+#include "mali_kbase_cache_policy.h"
+
+/*
+ * The output flags should be a combination of the following values:
+ * KBASE_REG_CPU_CACHED: CPU cache should be enabled
+ */
+u32 kbase_cache_enabled(u32 flags, u32 nr_pages)
+{
+ u32 cache_flags = 0;
+
+ CSTD_UNUSED(nr_pages);
+
+ if (flags & BASE_MEM_CACHED_CPU)
+ cache_flags |= KBASE_REG_CPU_CACHED;
+
+ return cache_flags;
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cache_policy.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cache_policy.h
new file mode 100755
index 00000000000..615105b8723
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cache_policy.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_cache_policy.h
+ * Cache Policy API.
+ */
+
+#ifndef _KBASE_CACHE_POLICY_H_
+#define _KBASE_CACHE_POLICY_H_
+
+#include <malisw/mali_malisw.h>
+#include "mali_kbase.h"
+#include <kbase/mali_base_kernel.h>
+
+/**
+ * @brief Choose the cache policy for a specific region
+ *
+ * Tells whether the CPU and GPU caches should be enabled or not for a specific region.
+ * This function can be modified to customize the cache policy depending on the flags
+ * and size of the region.
+ *
+ * @param[in] flags flags describing attributes of the region
+ * @param[in] nr_pages total number of pages (backed or not) for the region
+ *
+ * @return a combination of KBASE_REG_CPU_CACHED and KBASE_REG_GPU_CACHED depending
+ * on the cache policy
+ */
+u32 kbase_cache_enabled(u32 flags, u32 nr_pages);
+
+#endif /* _KBASE_CACHE_POLICY_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_config.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_config.c
new file mode 100755
index 00000000000..5ae5ad908b7
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_config.c
@@ -0,0 +1,607 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#include <kbase/src/common/mali_kbase.h>
+#include <kbase/src/common/mali_kbase_defs.h>
+#include <kbase/src/common/mali_kbase_cpuprops.h>
+#ifdef CONFIG_UMP
+#include <linux/ump-common.h>
+#endif /* CONFIG_UMP */
+
+/* Specifies how many attributes are permitted in the config (excluding terminating attribute).
+ * This is used in validation function so we can detect if configuration is properly terminated. This value can be
+ * changed if we need to introduce more attributes or many memory regions need to be defined */
+#define ATTRIBUTE_COUNT_MAX 32
+
+/* right now we allow only 2 memory attributes (excluding termination attribute) */
+#define MEMORY_ATTRIBUTE_COUNT_MAX 2
+
+/* Limits for gpu frequency configuration parameters. These will use for config validation. */
+#define MAX_GPU_ALLOWED_FREQ_KHZ 1000000
+#define MIN_GPU_ALLOWED_FREQ_KHZ 1
+
+/* Default irq throttle time. This is the default desired minimum time in between two consecutive
+ * interrupts from the gpu. The irq throttle gpu register is set after this value. */
+#define DEFAULT_IRQ_THROTTLE_TIME_US 20
+
+/*** Begin Scheduling defaults ***/
+
+/**
+ * Default scheduling tick granuality, in nanoseconds
+ */
+#define DEFAULT_JS_SCHEDULING_TICK_NS 100000000u /* 100ms */
+
+/**
+ * Default minimum number of scheduling ticks before jobs are soft-stopped.
+ *
+ * This defines the time-slice for a job (which may be different from that of a context)
+ */
+#define DEFAULT_JS_SOFT_STOP_TICKS 1 /* Between 0.1 and 0.2s before soft-stop */
+
+/**
+ * Default minimum number of scheduling ticks before jobs are hard-stopped
+ */
+#define DEFAULT_JS_HARD_STOP_TICKS_SS_HW_ISSUE_8408 12 /* 1.2s before hard-stop, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) */
+#define DEFAULT_JS_HARD_STOP_TICKS_SS 2 /* Between 0.2 and 0.3s before hard-stop */
+
+/**
+ * Default minimum number of scheduling ticks before jobs are hard-stopped
+ * during dumping
+ */
+#define DEFAULT_JS_HARD_STOP_TICKS_NSS 600 /* 60s @ 100ms tick */
+
+/**
+ * Default minimum number of scheduling ticks before the GPU is reset
+ * to clear a "stuck" job
+ */
+#define DEFAULT_JS_RESET_TICKS_SS_HW_ISSUE_8408 18 /* 1.8s before resetting GPU, for a certain GLES2 test at 128x128 (bound by combined vertex+tiler job) */
+#define DEFAULT_JS_RESET_TICKS_SS 3 /* 0.3-0.4s before GPU is reset */
+
+/**
+ * Default minimum number of scheduling ticks before the GPU is reset
+ * to clear a "stuck" job during dumping.
+ */
+#define DEFAULT_JS_RESET_TICKS_NSS 601 /* 60.1s @ 100ms tick */
+
+/**
+ * Number of milliseconds given for other jobs on the GPU to be
+ * soft-stopped when the GPU needs to be reset.
+ */
+#define DEFAULT_JS_RESET_TIMEOUT_MS 3000
+
+/**
+ * Default timeslice that a context is scheduled in for, in nanoseconds.
+ *
+ * When a context has used up this amount of time across its jobs, it is
+ * scheduled out to let another run.
+ *
+ * @note the resolution is nanoseconds (ns) here, because that's the format
+ * often used by the OS.
+ */
+#define DEFAULT_JS_CTX_TIMESLICE_NS 50000000 /* 0.05s - at 20fps a ctx does at least 1 frame before being scheduled out. At 40fps, 2 frames, etc */
+
+/**
+ * Default initial runtime of a context for CFS, in ticks.
+ *
+ * This value is relative to that of the least-run context, and defines where
+ * in the CFS queue a new context is added.
+ */
+#define DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES 1
+
+/**
+ * Default minimum runtime value of a context for CFS, in ticks.
+ *
+ * This value is relative to that of the least-run context. This prevents
+ * "stored-up timeslices" DoS attacks.
+ */
+#define DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES 2
+
+/**
+ * Default setting for whether to prefer security or performance.
+ *
+ * Currently affects only r0p0-15dev0 HW and earlier.
+ */
+#define DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE MALI_FALSE
+
+/**
+ * Default setting for read Address ID limiting on AXI.
+ */
+#define DEFAULT_ARID_LIMIT KBASE_AID_32
+
+/**
+ * Default setting for write Address ID limiting on AXI.
+ */
+#define DEFAULT_AWID_LIMIT KBASE_AID_32
+
+/**
+ * Default setting for using alternative hardware counters.
+ */
+#define DEFAULT_ALTERNATIVE_HWC MALI_FALSE
+
+/*** End Scheduling defaults ***/
+
+/*** Begin Power Manager defaults */
+
+#define DEFAULT_PM_DVFS_FREQ 500 /* Milliseconds */
+
+/**
+ * Default poweroff tick granuality, in nanoseconds
+ */
+#define DEFAULT_PM_GPU_POWEROFF_TICK_NS 400000 /* 400us */
+
+/**
+ * Default number of poweroff ticks before shader cores are powered off
+ */
+#define DEFAULT_PM_POWEROFF_TICK_SHADER 2 /* 400-800us */
+
+/**
+ * Default number of poweroff ticks before GPU is powered off
+ */
+#define DEFAULT_PM_POWEROFF_TICK_GPU 2 /* 400-800us */
+
+/*** End Power Manager defaults ***/
+
+/**
+ * Default value for KBASE_CONFIG_ATTR_CPU_SPEED_FUNC.
+ * Points to @ref kbase_cpuprops_get_default_clock_speed.
+ */
+#define DEFAULT_CPU_SPEED_FUNC ((uintptr_t)kbase_cpuprops_get_default_clock_speed)
+
+int kbasep_get_config_attribute_count(const kbase_attribute *attributes)
+{
+ int count = 1;
+
+ KBASE_DEBUG_ASSERT(attributes != NULL);
+
+ while (attributes->id != KBASE_CONFIG_ATTR_END) {
+ attributes++;
+ count++;
+ }
+
+ return count;
+}
+
+const kbase_attribute *kbasep_get_next_attribute(const kbase_attribute *attributes, int attribute_id)
+{
+ KBASE_DEBUG_ASSERT(attributes != NULL);
+
+ while (attributes->id != KBASE_CONFIG_ATTR_END) {
+ if (attributes->id == attribute_id)
+ return attributes;
+
+ attributes++;
+ }
+ return NULL;
+}
+
+KBASE_EXPORT_TEST_API(kbasep_get_next_attribute)
+
+uintptr_t kbasep_get_config_value(struct kbase_device *kbdev, const kbase_attribute *attributes, int attribute_id)
+{
+ const kbase_attribute *attr;
+
+ KBASE_DEBUG_ASSERT(attributes != NULL);
+
+ attr = kbasep_get_next_attribute(attributes, attribute_id);
+ if (attr != NULL)
+ return attr->data;
+
+ /* default values */
+ switch (attribute_id) {
+ case KBASE_CONFIG_ATTR_MEMORY_PER_PROCESS_LIMIT:
+ return (uintptr_t) -1;
+#ifdef CONFIG_UMP
+ case KBASE_CONFIG_ATTR_UMP_DEVICE:
+ return UMP_DEVICE_W_SHIFT;
+#endif /* CONFIG_UMP */
+ case KBASE_CONFIG_ATTR_MEMORY_OS_SHARED_MAX:
+ return (uintptr_t) -1;
+ case KBASE_CONFIG_ATTR_MEMORY_OS_SHARED_PERF_GPU:
+ return KBASE_MEM_PERF_NORMAL;
+ case KBASE_CONFIG_ATTR_GPU_IRQ_THROTTLE_TIME_US:
+ return DEFAULT_IRQ_THROTTLE_TIME_US;
+ /* Begin scheduling defaults */
+ case KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS:
+ return DEFAULT_JS_SCHEDULING_TICK_NS;
+ case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS:
+ return DEFAULT_JS_SOFT_STOP_TICKS;
+ case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS:
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408))
+ return DEFAULT_JS_HARD_STOP_TICKS_SS_HW_ISSUE_8408;
+ else
+ return DEFAULT_JS_HARD_STOP_TICKS_SS;
+ case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS:
+ return DEFAULT_JS_HARD_STOP_TICKS_NSS;
+ case KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS:
+ return DEFAULT_JS_CTX_TIMESLICE_NS;
+ case KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_INIT_SLICES:
+ return DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES;
+ case KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_MIN_SLICES:
+ return DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES;
+ case KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS:
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408))
+ return DEFAULT_JS_RESET_TICKS_SS_HW_ISSUE_8408;
+ else
+ return DEFAULT_JS_RESET_TICKS_SS;
+ case KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS:
+ return DEFAULT_JS_RESET_TICKS_NSS;
+ case KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS:
+ return DEFAULT_JS_RESET_TIMEOUT_MS;
+ /* End scheduling defaults */
+ case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS:
+ return 0;
+ case KBASE_CONFIG_ATTR_PLATFORM_FUNCS:
+ return 0;
+ case KBASE_CONFIG_ATTR_SECURE_BUT_LOSS_OF_PERFORMANCE:
+ return DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE;
+ case KBASE_CONFIG_ATTR_CPU_SPEED_FUNC:
+ return DEFAULT_CPU_SPEED_FUNC;
+ case KBASE_CONFIG_ATTR_GPU_SPEED_FUNC:
+ return 0;
+ case KBASE_CONFIG_ATTR_ARID_LIMIT:
+ return DEFAULT_ARID_LIMIT;
+ case KBASE_CONFIG_ATTR_AWID_LIMIT:
+ return DEFAULT_AWID_LIMIT;
+ case KBASE_CONFIG_ATTR_ALTERNATIVE_HWC:
+ return DEFAULT_ALTERNATIVE_HWC;
+ case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ:
+ return DEFAULT_PM_DVFS_FREQ;
+ case KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS:
+ return DEFAULT_PM_GPU_POWEROFF_TICK_NS;
+ case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER:
+ return DEFAULT_PM_POWEROFF_TICK_SHADER;
+ case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU:
+ return DEFAULT_PM_POWEROFF_TICK_GPU;
+
+ default:
+ KBASE_DEBUG_PRINT_ERROR(KBASE_CORE, "kbasep_get_config_value. Cannot get value of attribute with id=%d and no default value defined", attribute_id);
+ return 0;
+ }
+}
+
+KBASE_EXPORT_TEST_API(kbasep_get_config_value)
+
+mali_bool kbasep_platform_device_init(kbase_device *kbdev)
+{
+ kbase_platform_funcs_conf *platform_funcs;
+
+ platform_funcs = (kbase_platform_funcs_conf *) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PLATFORM_FUNCS);
+ if (platform_funcs) {
+ if (platform_funcs->platform_init_func)
+ return platform_funcs->platform_init_func(kbdev);
+ }
+ return MALI_TRUE;
+}
+
+void kbasep_platform_device_term(kbase_device *kbdev)
+{
+ kbase_platform_funcs_conf *platform_funcs;
+
+ platform_funcs = (kbase_platform_funcs_conf *) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PLATFORM_FUNCS);
+ if (platform_funcs) {
+ if (platform_funcs->platform_term_func)
+ platform_funcs->platform_term_func(kbdev);
+ }
+}
+
+#ifdef CONFIG_UMP
+static mali_bool kbasep_validate_ump_device(int ump_device)
+{
+ mali_bool valid;
+
+ switch (ump_device) {
+ case UMP_DEVICE_W_SHIFT:
+ case UMP_DEVICE_X_SHIFT:
+ case UMP_DEVICE_Y_SHIFT:
+ case UMP_DEVICE_Z_SHIFT:
+ valid = MALI_TRUE;
+ break;
+ default:
+ valid = MALI_FALSE;
+ break;
+ }
+ return valid;
+}
+#endif /* CONFIG_UMP */
+
+static mali_bool kbasep_validate_memory_performance(kbase_memory_performance performance)
+{
+ return performance <= KBASE_MEM_PERF_MAX_VALUE;
+}
+
+static mali_bool kbasep_validate_memory_resource(const kbase_memory_resource *memory_resource)
+{
+ KBASE_DEBUG_ASSERT(memory_resource != NULL);
+
+ if (memory_resource->name == NULL) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Unnamed memory region found");
+ return MALI_FALSE;
+ }
+
+ if (memory_resource->base & ((1 << PAGE_SHIFT) - 1)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Base address of \"%s\" memory region is not page aligned", memory_resource->name);
+ return MALI_FALSE;
+ }
+
+ if (memory_resource->size & ((1 << PAGE_SHIFT) - 1)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Size of \"%s\" memory region is not a multiple of page size", memory_resource->name);
+ return MALI_FALSE;
+ }
+
+ if (memory_resource->attributes != NULL) { /* we allow NULL attribute list */
+ int i;
+
+ for (i = 0; memory_resource->attributes[i].id != KBASE_MEM_ATTR_END; i++) {
+ if (i >= MEMORY_ATTRIBUTE_COUNT_MAX) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "More than MEMORY_ATTRIBUTE_COUNT_MAX=%d configuration attributes defined. Is memory attribute list properly terminated?", MEMORY_ATTRIBUTE_COUNT_MAX);
+ return MALI_FALSE;
+ }
+ switch (memory_resource->attributes[i].id) {
+ case KBASE_MEM_ATTR_PERF_CPU:
+ if (MALI_TRUE != kbasep_validate_memory_performance((kbase_memory_performance) memory_resource->attributes[i].data)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "CPU performance of \"%s\" region is invalid: %d", memory_resource->name, (kbase_memory_performance) memory_resource->attributes[i].data);
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_MEM_ATTR_PERF_GPU:
+ if (MALI_TRUE != kbasep_validate_memory_performance((kbase_memory_performance) memory_resource->attributes[i].data)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "GPU performance of \"%s\" region is invalid: %d", memory_resource->name, (kbase_memory_performance) memory_resource->attributes[i].data);
+ return MALI_FALSE;
+ }
+ break;
+ default:
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid memory attribute found in \"%s\" memory region: %d", memory_resource->name, memory_resource->attributes[i].id);
+ return MALI_FALSE;
+ }
+ }
+ }
+
+ return MALI_TRUE;
+}
+
+static mali_bool kbasep_validate_gpu_clock_freq(kbase_device *kbdev, const kbase_attribute *attributes)
+{
+ uintptr_t freq_min = kbasep_get_config_value(kbdev, attributes, KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MIN);
+ uintptr_t freq_max = kbasep_get_config_value(kbdev, attributes, KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX);
+
+ if ((freq_min > MAX_GPU_ALLOWED_FREQ_KHZ) || (freq_min < MIN_GPU_ALLOWED_FREQ_KHZ) || (freq_max > MAX_GPU_ALLOWED_FREQ_KHZ) || (freq_max < MIN_GPU_ALLOWED_FREQ_KHZ) || (freq_min > freq_max)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid GPU frequencies found in configuration: min=%ldkHz, max=%ldkHz.", freq_min, freq_max);
+ return MALI_FALSE;
+ }
+
+ return MALI_TRUE;
+}
+
+static mali_bool kbasep_validate_pm_callback(const kbase_pm_callback_conf *callbacks)
+{
+ if (callbacks == NULL) {
+ /* Having no callbacks is valid */
+ return MALI_TRUE;
+ }
+
+ if ((callbacks->power_off_callback != NULL && callbacks->power_on_callback == NULL) || (callbacks->power_off_callback == NULL && callbacks->power_on_callback != NULL)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid power management callbacks: Only one of power_off_callback and power_on_callback was specified");
+ return MALI_FALSE;
+ }
+ return MALI_TRUE;
+}
+
+static mali_bool kbasep_validate_cpu_speed_func(kbase_cpuprops_clock_speed_function fcn)
+{
+ return fcn != NULL;
+}
+
+mali_bool kbasep_validate_configuration_attributes(kbase_device *kbdev, const kbase_attribute *attributes)
+{
+ int i;
+ mali_bool had_gpu_freq_min = MALI_FALSE, had_gpu_freq_max = MALI_FALSE;
+
+ KBASE_DEBUG_ASSERT(attributes);
+
+ for (i = 0; attributes[i].id != KBASE_CONFIG_ATTR_END; i++) {
+ if (i >= ATTRIBUTE_COUNT_MAX) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "More than ATTRIBUTE_COUNT_MAX=%d configuration attributes defined. Is attribute list properly terminated?", ATTRIBUTE_COUNT_MAX);
+ return MALI_FALSE;
+ }
+
+ switch (attributes[i].id) {
+ case KBASE_CONFIG_ATTR_MEMORY_RESOURCE:
+ if (MALI_FALSE == kbasep_validate_memory_resource((kbase_memory_resource *) attributes[i].data)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid memory region found in configuration");
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_MEMORY_OS_SHARED_MAX:
+ /* Some shared memory is required for GPU page tables, see MIDBASE-1534 */
+ if (0 == attributes[i].data) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Maximum OS Shared Memory Maximum is set to 0 which is not supported");
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_MEMORY_OS_SHARED_PERF_GPU:
+ if (MALI_FALSE == kbasep_validate_memory_performance((kbase_memory_performance) attributes[i].data)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Shared OS memory GPU performance attribute has invalid value: %d", (kbase_memory_performance) attributes[i].data);
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_MEMORY_PER_PROCESS_LIMIT:
+ /* any value is allowed */
+ break;
+#ifdef CONFIG_UMP
+ case KBASE_CONFIG_ATTR_UMP_DEVICE:
+ if (MALI_FALSE == kbasep_validate_ump_device(attributes[i].data)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Unknown UMP device found in configuration: %d", (int)attributes[i].data);
+ return MALI_FALSE;
+ }
+ break;
+#endif /* CONFIG_UMP */
+
+ case KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MIN:
+ had_gpu_freq_min = MALI_TRUE;
+ if (MALI_FALSE == kbasep_validate_gpu_clock_freq(kbdev, attributes)) {
+ /* Warning message handled by kbasep_validate_gpu_clock_freq() */
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX:
+ had_gpu_freq_max = MALI_TRUE;
+ if (MALI_FALSE == kbasep_validate_gpu_clock_freq(kbdev, attributes)) {
+ /* Warning message handled by kbasep_validate_gpu_clock_freq() */
+ return MALI_FALSE;
+ }
+ break;
+
+ /* Only non-zero unsigned 32-bit values accepted */
+ case KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS:
+#if CSTD_CPU_64BIT
+ if (attributes[i].data == 0u || (u64) attributes[i].data > (u64) U32_MAX)
+#else
+ if (attributes[i].data == 0u)
+#endif
+ {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid Job Scheduling Configuration attribute for " "KBASE_CONFIG_ATTR_JS_SCHEDULING_TICKS_NS: %d", (int)attributes[i].data);
+ return MALI_FALSE;
+ }
+ break;
+
+ /* All these Job Scheduling attributes are FALLTHROUGH: only unsigned 32-bit values accepted */
+ case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS:
+ case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS:
+ case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS:
+ case KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS:
+ case KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS:
+ case KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS:
+ case KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS:
+ case KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_INIT_SLICES:
+ case KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_MIN_SLICES:
+#if CSTD_CPU_64BIT
+ if ((u64) attributes[i].data > (u64) U32_MAX) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Job Scheduling Configuration attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data);
+ return MALI_FALSE;
+ }
+#endif
+ break;
+
+ case KBASE_CONFIG_ATTR_GPU_IRQ_THROTTLE_TIME_US:
+#if CSTD_CPU_64BIT
+ if ((u64) attributes[i].data > (u64) U32_MAX) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "IRQ throttle time attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data);
+ return MALI_FALSE;
+ }
+#endif
+ break;
+
+ case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS:
+ if (MALI_FALSE == kbasep_validate_pm_callback((kbase_pm_callback_conf *) attributes[i].data)) {
+ /* Warning message handled by kbasep_validate_pm_callback() */
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_SECURE_BUT_LOSS_OF_PERFORMANCE:
+ if (attributes[i].data != MALI_TRUE && attributes[i].data != MALI_FALSE) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Value for KBASE_CONFIG_ATTR_SECURE_BUT_LOSS_OF_PERFORMANCE was not " "MALI_TRUE or MALI_FALSE: %u", (unsigned int)attributes[i].data);
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_CPU_SPEED_FUNC:
+ if (MALI_FALSE == kbasep_validate_cpu_speed_func((kbase_cpuprops_clock_speed_function) attributes[i].data)) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid function pointer in KBASE_CONFIG_ATTR_CPU_SPEED_FUNC");
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_GPU_SPEED_FUNC:
+ if (0 == attributes[i].data) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid function pointer in KBASE_CONFIG_ATTR_GPU_SPEED_FUNC");
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_PLATFORM_FUNCS:
+ /* any value is allowed */
+ break;
+
+ case KBASE_CONFIG_ATTR_AWID_LIMIT:
+ case KBASE_CONFIG_ATTR_ARID_LIMIT:
+ if ((u32) attributes[i].data > 0x3) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid AWID or ARID limit");
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_ALTERNATIVE_HWC:
+ if (attributes[i].data != MALI_TRUE && attributes[i].data != MALI_FALSE) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Value for KBASE_CONFIG_ATTR_ALTERNATIVE_HWC was not " "MALI_TRUE or MALI_FALSE: %u", (unsigned int)attributes[i].data);
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ:
+#if CSTD_CPU_64BIT
+ if ((u64) attributes[i].data > (u64) U32_MAX) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "PM DVFS interval exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data);
+ return MALI_FALSE;
+ }
+#endif
+ break;
+
+ case KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS:
+#if CSTD_CPU_64BIT
+ if (attributes[i].data == 0u || (u64) attributes[i].data > (u64) U32_MAX) {
+#else
+ if (attributes[i].data == 0u) {
+#endif
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid Power Manager Configuration attribute for " "KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: %d", (int)attributes[i].data);
+ return MALI_FALSE;
+ }
+ break;
+
+ case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER:
+ case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU:
+#if CSTD_CPU_64BIT
+ if ((u64) attributes[i].data > (u64) U32_MAX) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Power Manager Configuration attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data);
+ return MALI_FALSE;
+ }
+#endif
+ break;
+
+ default:
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Invalid attribute found in configuration: %d", attributes[i].id);
+ return MALI_FALSE;
+ }
+ }
+
+ if (!had_gpu_freq_min) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Configuration does not include mandatory attribute KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MIN");
+ return MALI_FALSE;
+ }
+
+ if (!had_gpu_freq_max) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Configuration does not include mandatory attribute KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX");
+ return MALI_FALSE;
+ }
+
+ return MALI_TRUE;
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_context.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_context.c
new file mode 100755
index 00000000000..05867d83756
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_context.c
@@ -0,0 +1,227 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_context.c
+ * Base kernel context APIs
+ */
+
+#include <kbase/src/common/mali_kbase.h>
+#include <kbase/src/common/mali_midg_regmap.h>
+
+#define MEMPOOL_PAGES 16384
+
+/**
+ * @brief Create a kernel base context.
+ *
+ * Allocate and init a kernel base context. Calls
+ * kbase_create_os_context() to setup OS specific structures.
+ */
+kbase_context *kbase_create_context(kbase_device *kbdev)
+{
+ kbase_context *kctx;
+ mali_error mali_err;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ /* zero-inited as lot of code assume it's zero'ed out on create */
+ kctx = vzalloc(sizeof(*kctx));
+
+ if (!kctx)
+ goto out;
+
+ kctx->kbdev = kbdev;
+ kctx->as_nr = KBASEP_AS_NR_INVALID;
+#ifdef CONFIG_MALI_TRACE_TIMELINE
+ kctx->timeline.owner_tgid = task_tgid_nr(current);
+#endif
+ atomic_set(&kctx->setup_complete, 0);
+ atomic_set(&kctx->setup_in_progress, 0);
+ kctx->keep_gpu_powered = MALI_FALSE;
+ spin_lock_init(&kctx->mm_update_lock);
+ kctx->process_mm = NULL;
+ atomic_set(&kctx->nonmapped_pages, 0);
+
+ if (MALI_ERROR_NONE != kbase_mem_allocator_init(&kctx->osalloc, MEMPOOL_PAGES))
+ goto free_kctx;
+
+ kctx->pgd_allocator = &kctx->osalloc;
+ if (kbase_mem_usage_init(&kctx->usage, kctx->kbdev->memdev.per_process_memory_limit >> PAGE_SHIFT))
+ goto free_allocator;
+
+
+ if (kbase_jd_init(kctx))
+ goto free_memctx;
+
+ mali_err = kbasep_js_kctx_init(kctx);
+ if (MALI_ERROR_NONE != mali_err)
+ goto free_jd; /* safe to call kbasep_js_kctx_term in this case */
+
+ mali_err = kbase_event_init(kctx);
+ if (MALI_ERROR_NONE != mali_err)
+ goto free_jd;
+
+ mutex_init(&kctx->reg_lock);
+
+ INIT_LIST_HEAD(&kctx->waiting_soft_jobs);
+#ifdef CONFIG_KDS
+ INIT_LIST_HEAD(&kctx->waiting_kds_resource);
+#endif
+
+ mali_err = kbase_mmu_init(kctx);
+ if (MALI_ERROR_NONE != mali_err)
+ goto free_event;
+
+ kctx->pgd = kbase_mmu_alloc_pgd(kctx);
+ if (!kctx->pgd)
+ goto free_mmu;
+
+ if (kbase_create_os_context(&kctx->osctx))
+ goto free_pgd;
+
+ /* Make sure page 0 is not used... */
+ if (kbase_region_tracker_init(kctx))
+ goto free_osctx;
+#ifdef CONFIG_GPU_TRACEPOINTS
+ atomic_set(&kctx->jctx.work_id, 0);
+#endif
+#ifdef CONFIG_MALI_TRACE_TIMELINE
+ atomic_set(&kctx->timeline.jd_atoms_in_flight, 0);
+#endif
+
+ return kctx;
+
+ free_osctx:
+ kbase_destroy_os_context(&kctx->osctx);
+ free_pgd:
+ kbase_mmu_free_pgd(kctx);
+ free_mmu:
+ kbase_mmu_term(kctx);
+ free_event:
+ kbase_event_cleanup(kctx);
+ free_jd:
+ /* Safe to call this one even when didn't initialize (assuming kctx was sufficiently zeroed) */
+ kbasep_js_kctx_term(kctx);
+ kbase_jd_exit(kctx);
+ free_memctx:
+ kbase_mem_usage_term(&kctx->usage);
+ free_allocator:
+ kbase_mem_allocator_term(&kctx->osalloc);
+ free_kctx:
+ vfree(kctx);
+ out:
+ return NULL;
+
+}
+KBASE_EXPORT_SYMBOL(kbase_create_context)
+
+/**
+ * @brief Destroy a kernel base context.
+ *
+ * Destroy a kernel base context. Calls kbase_destroy_os_context() to
+ * free OS specific structures. Will release all outstanding regions.
+ */
+void kbase_destroy_context(kbase_context *kctx)
+{
+ kbase_device *kbdev;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+
+ KBASE_TRACE_ADD(kbdev, CORE_CTX_DESTROY, kctx, NULL, 0u, 0u);
+
+ /* Ensure the core is powered up for the destroy process */
+ /* A suspend won't happen here, because we're in a syscall from a userspace
+ * thread. */
+ kbase_pm_context_active(kbdev);
+
+ if (kbdev->hwcnt.kctx == kctx) {
+ /* disable the use of the hw counters if the app didn't use the API correctly or crashed */
+ KBASE_TRACE_ADD(kbdev, CORE_CTX_HWINSTR_TERM, kctx, NULL, 0u, 0u);
+ KBASE_DEBUG_PRINT_WARN(KBASE_CTX, "The privileged process asking for instrumentation forgot to disable it " "before exiting. Will end instrumentation for them");
+ kbase_instr_hwcnt_disable(kctx);
+ }
+
+ kbase_jd_zap_context(kctx);
+ kbase_event_cleanup(kctx);
+
+ kbase_gpu_vm_lock(kctx);
+
+ /* MMU is disabled as part of scheduling out the context */
+ kbase_mmu_free_pgd(kctx);
+ kbase_region_tracker_term(kctx);
+ kbase_destroy_os_context(&kctx->osctx);
+ kbase_gpu_vm_unlock(kctx);
+
+ /* Safe to call this one even when didn't initialize (assuming kctx was sufficiently zeroed) */
+ kbasep_js_kctx_term(kctx);
+
+ kbase_jd_exit(kctx);
+
+ kbase_pm_context_idle(kbdev);
+
+ kbase_mmu_term(kctx);
+
+ kbase_mem_usage_term(&kctx->usage);
+
+ if (kctx->keep_gpu_powered) {
+ atomic_dec(&kbdev->keep_gpu_powered_count);
+ kbase_pm_context_idle(kbdev);
+ }
+
+ kbase_mem_allocator_term(&kctx->osalloc);
+ WARN_ON(atomic_read(&kctx->nonmapped_pages) != 0);
+ vfree(kctx);
+}
+KBASE_EXPORT_SYMBOL(kbase_destroy_context)
+
+/**
+ * Set creation flags on a context
+ */
+mali_error kbase_context_set_create_flags(kbase_context *kctx, u32 flags)
+{
+ mali_error err = MALI_ERROR_NONE;
+ kbasep_js_kctx_info *js_kctx_info;
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ /* Validate flags */
+ if (flags != (flags & BASE_CONTEXT_CREATE_KERNEL_FLAGS)) {
+ err = MALI_ERROR_FUNCTION_FAILED;
+ goto out;
+ }
+
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+
+ /* Translate the flags */
+ if ((flags & BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) == 0)
+ js_kctx_info->ctx.flags &= ~((u32) KBASE_CTX_FLAG_SUBMIT_DISABLED);
+
+ if ((flags & BASE_CONTEXT_HINT_ONLY_COMPUTE) != 0)
+ js_kctx_info->ctx.flags |= (u32) KBASE_CTX_FLAG_HINT_ONLY_COMPUTE;
+
+ /* Latch the initial attributes into the Job Scheduler */
+ kbasep_js_ctx_attr_set_initial_attrs(kctx->kbdev, kctx);
+
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+ out:
+ return err;
+}
+KBASE_EXPORT_SYMBOL(kbase_context_set_create_flags)
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cpuprops.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cpuprops.c
new file mode 100755
index 00000000000..81c1afa367f
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cpuprops.c
@@ -0,0 +1,94 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_cpuprops.c
+ * Base kernel property query APIs
+ */
+
+#include "mali_kbase.h"
+#include "mali_kbase_cpuprops.h"
+#include "mali_kbase_uku.h"
+#include <kbase/mali_kbase_config.h>
+#include <linux/cache.h>
+#include <asm/cputype.h>
+
+#define L1_DCACHE_LINE_SIZE_LOG2 L1_CACHE_SHIFT
+
+/**
+ * @brief Macros used to extract cpu id info
+ * @see Doc's for Main ID register
+ */
+#define KBASE_CPUPROPS_ID_GET_REV(cpuid) ( (cpuid) & 0x0F ) /* [3:0] Revision */
+#define KBASE_CPUPROPS_ID_GET_PART_NR(cpuid)( ((cpuid) >> 4) & 0xFFF ) /* [15:4] Part number */
+#define KBASE_CPUPROPS_ID_GET_ARCH(cpuid) ( ((cpuid) >> 16) & 0x0F ) /* [19:16] Architecture */
+#define KBASE_CPUPROPS_ID_GET_VARIANT(cpuid)( ((cpuid) >> 20) & 0x0F ) /* [23:20] Variant */
+#define KBASE_CPUPROPS_ID_GET_CODE(cpuid) ( ((cpuid) >> 24) & 0xFF ) /* [31:23] ASCII code of implementer trademark */
+
+/*Below value sourced from OSK*/
+#define L1_DCACHE_SIZE ((u32)0x00008000)
+
+
+/**
+ * @brief Retrieves detailed CPU info from given cpu_val ( ID reg )
+ *
+ * @param kbase_props CPU props to be filled-in with cpu id info
+ * @param cpu_val CPU ID info
+ *
+ */
+static void kbasep_cpuprops_uk_get_cpu_id_info(kbase_uk_cpuprops * const kbase_props, u32 cpu_val)
+{
+ kbase_props->props.cpu_id.id = cpu_val;
+
+ kbase_props->props.cpu_id.rev = KBASE_CPUPROPS_ID_GET_REV(cpu_val);
+ kbase_props->props.cpu_id.part = KBASE_CPUPROPS_ID_GET_PART_NR(cpu_val);
+ kbase_props->props.cpu_id.arch = KBASE_CPUPROPS_ID_GET_ARCH(cpu_val);
+ kbase_props->props.cpu_id.variant = KBASE_CPUPROPS_ID_GET_VARIANT(cpu_val);
+ kbase_props->props.cpu_id.implementer = KBASE_CPUPROPS_ID_GET_CODE(cpu_val);
+
+}
+
+int kbase_cpuprops_get_default_clock_speed(u32 * const clock_speed)
+{
+ KBASE_DEBUG_ASSERT(NULL != clock_speed);
+
+ *clock_speed = 100;
+ return 0;
+}
+
+mali_error kbase_cpuprops_uk_get_props(kbase_context *kctx, kbase_uk_cpuprops * const kbase_props)
+{
+ int result;
+ kbase_cpuprops_clock_speed_function kbase_cpuprops_uk_get_clock_speed;
+
+ kbase_props->props.cpu_l1_dcache_line_size_log2 = L1_DCACHE_LINE_SIZE_LOG2;
+ kbase_props->props.cpu_l1_dcache_size = L1_DCACHE_SIZE;
+ kbase_props->props.cpu_flags = BASE_CPU_PROPERTY_FLAG_LITTLE_ENDIAN;
+
+ kbase_props->props.nr_cores = NR_CPUS;
+ kbase_props->props.cpu_page_size_log2 = PAGE_SHIFT;
+ kbase_props->props.available_memory_size = totalram_pages << PAGE_SHIFT;
+
+ kbasep_cpuprops_uk_get_cpu_id_info(kbase_props, read_cpuid_id());
+
+ kbase_cpuprops_uk_get_clock_speed = (kbase_cpuprops_clock_speed_function) kbasep_get_config_value(kctx->kbdev, kctx->kbdev->config_attributes, KBASE_CONFIG_ATTR_CPU_SPEED_FUNC);
+ result = kbase_cpuprops_uk_get_clock_speed(&kbase_props->props.max_cpu_clock_speed_mhz);
+ if (result != 0)
+ return MALI_ERROR_FUNCTION_FAILED;
+
+ return MALI_ERROR_NONE;
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cpuprops.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cpuprops.h
new file mode 100755
index 00000000000..b0a36b3ea54
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_cpuprops.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_cpuprops.h
+ * Base kernel property query APIs
+ */
+
+#ifndef _KBASE_CPUPROPS_H_
+#define _KBASE_CPUPROPS_H_
+
+#include <malisw/mali_malisw.h>
+
+/* Forward declarations */
+struct kbase_uk_cpuprops;
+
+/**
+ * @brief Default implementation of @ref KBASE_CONFIG_ATTR_CPU_SPEED_FUNC.
+ *
+ * This function sets clock_speed to 100, so will be an underestimate for
+ * any real system.
+ *
+ * See @ref kbase_cpuprops_clock_speed_function for details on the parameters
+ * and return value.
+ */
+int kbase_cpuprops_get_default_clock_speed(u32 * const clock_speed);
+
+/**
+ * @brief Provides CPU properties data.
+ *
+ * Fill the kbase_uk_cpuprops with values from CPU configuration.
+ *
+ * @param kctx The kbase context
+ * @param kbase_props A copy of the kbase_uk_cpuprops structure from userspace
+ *
+ * @return MALI_ERROR_NONE on success. Any other value indicates failure.
+ */
+mali_error kbase_cpuprops_uk_get_props(kbase_context *kctx, struct kbase_uk_cpuprops * const kbase_props);
+
+#endif /*_KBASE_CPUPROPS_H_*/
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_debug.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_debug.c
new file mode 100755
index 00000000000..aaa904c3672
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_debug.c
@@ -0,0 +1,63 @@
+/*
+ *
+ * (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#include <kbase/src/common/mali_kbase.h>
+
+kbasep_debug_assert_cb kbasep_debug_assert_registered_cb = {
+ NULL,
+ NULL
+};
+
+void kbase_debug_assert_register_hook(kbase_debug_assert_hook *func, void *param)
+{
+ kbasep_debug_assert_registered_cb.func = func;
+ kbasep_debug_assert_registered_cb.param = param;
+}
+
+void kbasep_debug_assert_call_hook(void)
+{
+ if (kbasep_debug_assert_registered_cb.func != NULL)
+ kbasep_debug_assert_registered_cb.func(kbasep_debug_assert_registered_cb.param);
+}
+KBASE_EXPORT_SYMBOL(kbasep_debug_assert_call_hook);
+
+/**
+ * @brief Contains the module names (modules in the same order as for the kbase_module enumeration)
+ * @sa kbasep_module_to_str
+ */
+static const char *CONST kbasep_str_modules[] = {
+ "UNKNOWN", /**< Unknown module */
+ "BASE_MMU", /**< Base MMU */
+ "BASE_JD", /**< Base Job Dispatch */
+ "BASE_JM", /**< Base Job Manager */
+ "BASE_CORE", /**< Base Core */
+ "BASE_MEM", /**< Base Memory */
+ "BASE_EVENT", /**< Base Event */
+ "BASE_CTX", /**< Base Context */
+ "BASE_PM" /**< Base Power Management */
+};
+
+#define MODULE_STRING_ARRAY_SIZE (sizeof(kbasep_str_modules)/sizeof(kbasep_str_modules[0]))
+
+const char *kbasep_debug_module_to_str(const kbase_module module)
+{
+ if (MODULE_STRING_ARRAY_SIZE <= module)
+ return "";
+
+ return kbasep_str_modules[module];
+}
+KBASE_EXPORT_SYMBOL(kbasep_debug_module_to_str);
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_defs.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_defs.h
new file mode 100755
index 00000000000..67ad3608bb4
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_defs.h
@@ -0,0 +1,787 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_defs.h
+ *
+ * Defintions (types, defines, etcs) common to Kbase. They are placed here to
+ * allow the hierarchy of header files to work.
+ */
+
+#ifndef _KBASE_DEFS_H_
+#define _KBASE_DEFS_H_
+
+#include <kbase/mali_kbase_config.h>
+#include <kbase/mali_base_hwconfig.h>
+#include <kbase/src/common/mali_kbase_mem_lowlevel.h>
+#include <kbase/src/common/mali_kbase_mem_alloc.h>
+
+
+#include <linux/atomic.h>
+#include <linux/mempool.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_KDS
+#include <linux/kds.h>
+#endif /* CONFIG_KDS */
+
+#ifdef CONFIG_SYNC
+#include <linux/sync.h>
+#endif /* CONFIG_SYNC */
+
+/** Enable SW tracing when set */
+#ifdef CONFIG_MALI_T6XX_ENABLE_TRACE
+#define KBASE_TRACE_ENABLE 1
+#endif
+
+#ifndef KBASE_TRACE_ENABLE
+#ifdef CONFIG_MALI_DEBUG
+#define KBASE_TRACE_ENABLE 1
+#else
+#define KBASE_TRACE_ENABLE 0
+#endif /* CONFIG_MALI_DEBUG */
+#endif /* KBASE_TRACE_ENABLE */
+
+/** Dump Job slot trace on error (only active if KBASE_TRACE_ENABLE != 0) */
+#define KBASE_TRACE_DUMP_ON_JOB_SLOT_ERROR 1
+
+/**
+ * Number of milliseconds before resetting the GPU when a job cannot be "zapped" from the hardware.
+ * Note that the time is actually ZAP_TIMEOUT+SOFT_STOP_RESET_TIMEOUT between the context zap starting and the GPU
+ * actually being reset to give other contexts time for their jobs to be soft-stopped and removed from the hardware
+ * before resetting.
+ */
+#define ZAP_TIMEOUT 1000
+
+/** Number of milliseconds before we time out on a GPU soft/hard reset */
+#define RESET_TIMEOUT 500
+
+/**
+ * Prevent soft-stops from occuring in scheduling situations
+ *
+ * This is not due to HW issues, but when scheduling is desired to be more predictable.
+ *
+ * Therefore, soft stop may still be disabled due to HW issues.
+ *
+ * @note Soft stop will still be used for non-scheduling purposes e.g. when terminating a context.
+ *
+ * @note if not in use, define this value to 0 instead of \#undef'ing it
+ */
+#define KBASE_DISABLE_SCHEDULING_SOFT_STOPS 0
+
+/**
+ * Prevent hard-stops from occuring in scheduling situations
+ *
+ * This is not due to HW issues, but when scheduling is desired to be more predictable.
+ *
+ * @note Hard stop will still be used for non-scheduling purposes e.g. when terminating a context.
+ *
+ * @note if not in use, define this value to 0 instead of \#undef'ing it
+ */
+#define KBASE_DISABLE_SCHEDULING_HARD_STOPS 0
+
+/* Forward declarations+defintions */
+typedef struct kbase_context kbase_context;
+typedef struct kbase_jd_atom kbasep_jd_atom;
+typedef struct kbase_device kbase_device;
+
+/**
+ * The maximum number of Job Slots to support in the Hardware.
+ *
+ * You can optimize this down if your target devices will only ever support a
+ * small number of job slots.
+ */
+#define BASE_JM_MAX_NR_SLOTS 16
+
+/**
+ * The maximum number of Address Spaces to support in the Hardware.
+ *
+ * You can optimize this down if your target devices will only ever support a
+ * small number of Address Spaces
+ */
+#define BASE_MAX_NR_AS 16
+
+/* mmu */
+#define ENTRY_IS_ATE 1ULL
+#define ENTRY_IS_INVAL 2ULL
+#define ENTRY_IS_PTE 3ULL
+
+#define MIDGARD_MMU_VA_BITS 48
+
+#define ENTRY_ATTR_BITS (7ULL << 2) /* bits 4:2 */
+#define ENTRY_RD_BIT (1ULL << 6)
+#define ENTRY_WR_BIT (1ULL << 7)
+#define ENTRY_SHARE_BITS (3ULL << 8) /* bits 9:8 */
+#define ENTRY_ACCESS_BIT (1ULL << 10)
+#define ENTRY_NX_BIT (1ULL << 54)
+
+#define ENTRY_FLAGS_MASK (ENTRY_ATTR_BITS | ENTRY_RD_BIT | ENTRY_WR_BIT | ENTRY_SHARE_BITS | ENTRY_ACCESS_BIT | ENTRY_NX_BIT)
+
+#if MIDGARD_MMU_VA_BITS > 39
+#define MIDGARD_MMU_TOPLEVEL 0
+#else
+#define MIDGARD_MMU_TOPLEVEL 1
+#endif
+
+#define GROWABLE_FLAGS_REQUIRED (KBASE_REG_PF_GROW | KBASE_REG_ZONE_TMEM)
+#define GROWABLE_FLAGS_MASK (GROWABLE_FLAGS_REQUIRED | KBASE_REG_FREE)
+
+/** setting in kbase_context::as_nr that indicates it's invalid */
+#define KBASEP_AS_NR_INVALID (-1)
+
+#define KBASE_LOCK_REGION_MAX_SIZE (63)
+#define KBASE_LOCK_REGION_MIN_SIZE (11)
+
+#define KBASE_TRACE_SIZE_LOG2 8 /* 256 entries */
+#define KBASE_TRACE_SIZE (1 << KBASE_TRACE_SIZE_LOG2)
+#define KBASE_TRACE_MASK ((1 << KBASE_TRACE_SIZE_LOG2)-1)
+
+#include "mali_kbase_js_defs.h"
+
+/**
+ * @brief States to model state machine processed by kbasep_js_job_check_ref_cores(), which
+ * handles retaining cores for power management and affinity management.
+ *
+ * The state @ref KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY prevents an attack
+ * where lots of atoms could be submitted before powerup, and each has an
+ * affinity chosen that causes other atoms to have an affinity
+ * violation. Whilst the affinity was not causing violations at the time it
+ * was chosen, it could cause violations thereafter. For example, 1000 jobs
+ * could have had their affinity chosen during the powerup time, so any of
+ * those 1000 jobs could cause an affinity violation later on.
+ *
+ * The attack would otherwise occur because other atoms/contexts have to wait for:
+ * -# the currently running atoms (which are causing the violation) to
+ * finish
+ * -# and, the atoms that had their affinity chosen during powerup to
+ * finish. These are run preferrentially because they don't cause a
+ * violation, but instead continue to cause the violation in others.
+ * -# or, the attacker is scheduled out (which might not happen for just 2
+ * contexts)
+ *
+ * By re-choosing the affinity (which is designed to avoid violations at the
+ * time it's chosen), we break condition (2) of the wait, which minimizes the
+ * problem to just waiting for current jobs to finish (which can be bounded if
+ * the Job Scheduling Policy has a timer).
+ */
+typedef enum {
+ /** Starting state: No affinity chosen, and cores must be requested. kbase_jd_atom::affinity==0 */
+ KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED,
+ /** Cores requested, but waiting for them to be powered. Requested cores given by kbase_jd_atom::affinity */
+ KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES,
+ /** Cores given by kbase_jd_atom::affinity are powered, but affinity might be out-of-date, so must recheck */
+ KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY,
+ /** Cores given by kbase_jd_atom::affinity are powered, and affinity is up-to-date, but must check for violations */
+ KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS,
+ /** Cores are powered, kbase_jd_atom::affinity up-to-date, no affinity violations: atom can be submitted to HW */
+ KBASE_ATOM_COREREF_STATE_READY
+} kbase_atom_coreref_state;
+
+typedef enum {
+ /** Atom is not used */
+ KBASE_JD_ATOM_STATE_UNUSED,
+ /** Atom is queued in JD */
+ KBASE_JD_ATOM_STATE_QUEUED,
+ /** Atom has been given to JS (is runnable/running) */
+ KBASE_JD_ATOM_STATE_IN_JS,
+ /** Atom has been completed, but not yet handed back to userspace */
+ KBASE_JD_ATOM_STATE_COMPLETED
+} kbase_jd_atom_state;
+
+/** Atom has been previously soft-stoppped */
+#define KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED (1<<1)
+/** Atom has been previously retried to execute */
+#define KBASE_KATOM_FLAGS_RERUN (1<<2)
+
+typedef struct kbase_jd_atom kbase_jd_atom;
+
+struct kbase_jd_atom {
+ struct work_struct work;
+ ktime_t start_timestamp;
+
+ base_jd_udata udata;
+ kbase_context *kctx;
+
+ struct list_head dep_head[2];
+ struct list_head dep_item[2];
+ struct kbase_jd_atom *dep_atom[2];
+
+ u16 nr_extres;
+ struct base_external_resource *extres;
+
+ u32 device_nr;
+ u64 affinity;
+ u64 jc;
+ kbase_atom_coreref_state coreref_state;
+#ifdef CONFIG_KDS
+ struct list_head node;
+ struct kds_resource_set *kds_rset;
+ mali_bool kds_dep_satisfied;
+#endif /* CONFIG_KDS */
+#ifdef CONFIG_SYNC
+ struct sync_fence *fence;
+ struct sync_fence_waiter sync_waiter;
+#endif /* CONFIG_SYNC */
+
+ /* Note: refer to kbasep_js_atom_retained_state, which will take a copy of some of the following members */
+ base_jd_event_code event_code;
+ base_jd_core_req core_req; /**< core requirements */
+ /** Job Slot to retry submitting to if submission from IRQ handler failed
+ *
+ * NOTE: see if this can be unified into the another member e.g. the event */
+ int retry_submit_on_slot;
+
+ kbasep_js_policy_job_info sched_info;
+ /* atom priority scaled to nice range with +20 offset 0..39 */
+ int nice_prio;
+
+ int poking; /* BASE_HW_ISSUE_8316 */
+
+ wait_queue_head_t completed;
+ kbase_jd_atom_state status;
+#ifdef CONFIG_GPU_TRACEPOINTS
+ int work_id;
+#endif
+ /* Assigned after atom is completed. Used to check whether PRLAM-10676 workaround should be applied */
+ int slot_nr;
+
+ u32 atom_flags;
+};
+
+/*
+ * Theory of operations:
+ *
+ * Atom objects are statically allocated within the context structure.
+ *
+ * Each atom is the head of two lists, one for the "left" set of dependencies, one for the "right" set.
+ */
+
+#define KBASE_JD_DEP_QUEUE_SIZE 256
+
+typedef struct kbase_jd_context {
+ struct mutex lock;
+ kbasep_js_kctx_info sched_info;
+ kbase_jd_atom atoms[BASE_JD_ATOM_COUNT];
+
+ /** Tracks all job-dispatch jobs. This includes those not tracked by
+ * the scheduler: 'not ready to run' and 'dependency-only' jobs. */
+ u32 job_nr;
+
+ /** Waitq that reflects whether there are no jobs (including SW-only
+ * dependency jobs). This is set when no jobs are present on the ctx,
+ * and clear when there are jobs.
+ *
+ * @note: Job Dispatcher knows about more jobs than the Job Scheduler:
+ * the Job Scheduler is unaware of jobs that are blocked on dependencies,
+ * and SW-only dependency jobs.
+ *
+ * This waitq can be waited upon to find out when the context jobs are all
+ * done/cancelled (including those that might've been blocked on
+ * dependencies) - and so, whether it can be terminated. However, it should
+ * only be terminated once it is neither present in the policy-queue (see
+ * kbasep_js_policy_try_evict_ctx() ) nor the run-pool (see
+ * kbasep_js_kctx_info::ctx::is_scheduled).
+ *
+ * Since the waitq is only set under kbase_jd_context::lock,
+ * the waiter should also briefly obtain and drop kbase_jd_context::lock to
+ * guarentee that the setter has completed its work on the kbase_context
+ *
+ * This must be updated atomically with:
+ * - kbase_jd_context::job_nr */
+ wait_queue_head_t zero_jobs_wait;
+
+ /** Job Done workqueue. */
+ struct workqueue_struct *job_done_wq;
+
+ spinlock_t tb_lock;
+ u32 *tb;
+ size_t tb_wrap_offset;
+
+#ifdef CONFIG_KDS
+ struct kds_callback kds_cb;
+#endif /* CONFIG_KDS */
+#ifdef CONFIG_GPU_TRACEPOINTS
+ atomic_t work_id;
+#endif
+} kbase_jd_context;
+
+typedef struct kbase_jm_slot {
+ /* The number of slots must be a power of two */
+#define BASE_JM_SUBMIT_SLOTS 16
+#define BASE_JM_SUBMIT_SLOTS_MASK (BASE_JM_SUBMIT_SLOTS - 1)
+
+ struct kbase_jd_atom *submitted[BASE_JM_SUBMIT_SLOTS];
+
+ kbase_context *last_context;
+
+ u8 submitted_head;
+ u8 submitted_nr;
+
+} kbase_jm_slot;
+
+typedef enum kbase_midgard_type {
+ KBASE_MALI_T601,
+ KBASE_MALI_T604,
+ KBASE_MALI_T608,
+ KBASE_MALI_COUNT
+} kbase_midgard_type;
+
+typedef struct kbase_device_info {
+ kbase_midgard_type dev_type;
+ u32 features;
+} kbase_device_info;
+
+/** Poking state for BASE_HW_ISSUE_8316 */
+enum {
+ KBASE_AS_POKE_STATE_IN_FLIGHT = 1<<0,
+ KBASE_AS_POKE_STATE_KILLING_POKE = 1<<1
+};
+
+/** Poking state for BASE_HW_ISSUE_8316 */
+typedef u32 kbase_as_poke_state;
+
+/**
+ * Important: Our code makes assumptions that a kbase_as structure is always at
+ * kbase_device->as[number]. This is used to recover the containing
+ * kbase_device from a kbase_as structure.
+ *
+ * Therefore, kbase_as structures must not be allocated anywhere else.
+ */
+typedef struct kbase_as {
+ int number;
+
+ struct workqueue_struct *pf_wq;
+ struct work_struct work_pagefault;
+ struct work_struct work_busfault;
+ mali_addr64 fault_addr;
+ struct mutex transaction_mutex;
+
+ /* BASE_HW_ISSUE_8316 */
+ struct workqueue_struct *poke_wq;
+ struct work_struct poke_work;
+ /** Protected by kbasep_js_device_data::runpool_irq::lock */
+ int poke_refcount;
+ /** Protected by kbasep_js_device_data::runpool_irq::lock */
+ kbase_as_poke_state poke_state;
+ struct hrtimer poke_timer;
+} kbase_as;
+
+/* tracking of memory usage */
+typedef struct kbasep_mem_usage {
+ u32 max_pages;
+ atomic_t cur_pages;
+} kbasep_mem_usage;
+
+
+/**
+ * Instrumentation State Machine States
+ */
+typedef enum {
+ /** State where instrumentation is not active */
+ KBASE_INSTR_STATE_DISABLED = 0,
+ /** State machine is active and ready for a command. */
+ KBASE_INSTR_STATE_IDLE,
+ /** Hardware is currently dumping a frame. */
+ KBASE_INSTR_STATE_DUMPING,
+ /** We've requested a clean to occur on a workqueue */
+ KBASE_INSTR_STATE_REQUEST_CLEAN,
+ /** Hardware is currently cleaning and invalidating caches. */
+ KBASE_INSTR_STATE_CLEANING,
+ /** Cache clean completed, and either a) a dump is complete, or
+ * b) instrumentation can now be setup. */
+ KBASE_INSTR_STATE_CLEANED,
+ /** kbasep_reset_timeout_worker() has started (but not compelted) a
+ * reset. This generally indicates the current action should be aborted, and
+ * kbasep_reset_timeout_worker() will handle the cleanup */
+ KBASE_INSTR_STATE_RESETTING,
+ /** An error has occured during DUMPING (page fault). */
+ KBASE_INSTR_STATE_FAULT
+} kbase_instr_state;
+
+typedef struct kbasep_mem_device {
+#ifdef CONFIG_UMP
+ u32 ump_device_id; /* Which UMP device this GPU should be mapped to.
+ Read-only, copied from platform configuration on startup. */
+#endif /* CONFIG_UMP */
+
+ u32 per_process_memory_limit; /* How much memory (in bytes) a single process can access.
+ Read-only, copied from platform configuration on startup. */
+ kbasep_mem_usage usage; /* Tracks usage of OS shared memory. Initialized with platform
+ configuration data, updated when OS memory is allocated/freed. */
+
+} kbasep_mem_device;
+
+
+
+#define KBASE_TRACE_CODE(X) KBASE_TRACE_CODE_ ## X
+
+typedef enum {
+ /* IMPORTANT: USE OF SPECIAL #INCLUDE OF NON-STANDARD HEADER FILE
+ * THIS MUST BE USED AT THE START OF THE ENUM */
+#define KBASE_TRACE_CODE_MAKE_CODE(X) KBASE_TRACE_CODE(X)
+#include "mali_kbase_trace_defs.h"
+#undef KBASE_TRACE_CODE_MAKE_CODE
+ /* Comma on its own, to extend the list */
+ ,
+ /* Must be the last in the enum */
+ KBASE_TRACE_CODE_COUNT
+} kbase_trace_code;
+
+#define KBASE_TRACE_FLAG_REFCOUNT (((u8)1) << 0)
+#define KBASE_TRACE_FLAG_JOBSLOT (((u8)1) << 1)
+
+typedef struct kbase_trace {
+ struct timespec timestamp;
+ u32 thread_id;
+ u32 cpu;
+ void *ctx;
+ mali_bool katom;
+ int atom_number;
+ u64 atom_udata[2];
+ u64 gpu_addr;
+ u32 info_val;
+ u8 code;
+ u8 jobslot;
+ u8 refcount;
+ u8 flags;
+} kbase_trace;
+
+/** Event IDs for the power management framework.
+ *
+ * Any of these events might be missed, so they should not be relied upon to
+ * find the precise state of the GPU at a particular time in the
+ * trace. Overall, we should get a high percentage of these events for
+ * statisical purposes, and so a few missing should not be a problem */
+typedef enum kbase_timeline_pm_event {
+ /* helper for tests */
+ KBASEP_TIMELINE_PM_EVENT_FIRST,
+
+ /** Event reserved for backwards compatibility with 'init' events */
+ KBASE_TIMELINE_PM_EVENT_RESERVED_0 = KBASEP_TIMELINE_PM_EVENT_FIRST,
+
+ /** The power state of the device has changed.
+ *
+ * Specifically, the device has reached a desired or available state.
+ */
+ KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED,
+
+ /** The GPU is becoming active.
+ *
+ * This event is sent when the first context is about to use the GPU.
+ */
+ KBASE_TIMELINE_PM_EVENT_GPU_ACTIVE,
+
+ /** The GPU is becoming idle.
+ *
+ * This event is sent when the last context has finished using the GPU.
+ */
+ KBASE_TIMELINE_PM_EVENT_GPU_IDLE,
+
+ /** Event reserved for backwards compatibility with 'policy_change'
+ * events */
+ KBASE_TIMELINE_PM_EVENT_RESERVED_4,
+
+ /** Event reserved for backwards compatibility with 'system_suspend'
+ * events */
+ KBASE_TIMELINE_PM_EVENT_RESERVED_5,
+
+ /** Event reserved for backwards compatibility with 'system_resume'
+ * events */
+ KBASE_TIMELINE_PM_EVENT_RESERVED_6,
+
+ /** The job scheduler is requesting to power up/down cores.
+ *
+ * This event is sent when:
+ * - powered down cores are needed to complete a job
+ * - powered up cores are not needed anymore
+ */
+ KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE,
+
+ KBASEP_TIMELINE_PM_EVENT_LAST = KBASE_TIMELINE_PM_EVENT_CHANGE_GPU_STATE,
+} kbase_timeline_pm_event;
+
+#ifdef CONFIG_MALI_TRACE_TIMELINE
+typedef struct kbase_trace_kctx_timeline {
+ atomic_t jd_atoms_in_flight;
+ u32 owner_tgid;
+} kbase_trace_kctx_timeline;
+
+typedef struct kbase_trace_kbdev_timeline {
+ /** DebugFS entry */
+ struct dentry *dentry;
+
+ /* Note: strictly speaking, not needed, because it's in sync with
+ * kbase_device::jm_slots[]::submitted_nr
+ *
+ * But it's kept as an example of how to add global timeline tracking
+ * information
+ *
+ * The caller must hold kbasep_js_device_data::runpool_irq::lock when
+ * accessing this */
+ u8 slot_atoms_submitted[BASE_JM_SUBMIT_SLOTS];
+
+ /* Last UID for each PM event */
+ atomic_t pm_event_uid[KBASEP_TIMELINE_PM_EVENT_LAST+1];
+ /* Counter for generating PM event UIDs */
+ atomic_t pm_event_uid_counter;
+ /*
+ * L2 transition state - MALI_TRUE indicates that the transition is ongoing
+ * Expected to be protected by pm.power_change_lock */
+ mali_bool l2_transitioning;
+} kbase_trace_kbdev_timeline;
+#endif /* CONFIG_MALI_TRACE_TIMELINE */
+
+
+typedef struct kbasep_kctx_list_element {
+ struct list_head link;
+ kbase_context *kctx;
+} kbasep_kctx_list_element;
+
+struct kbase_device {
+ /** jm_slots is protected by kbasep_js_device_data::runpool_irq::lock */
+ kbase_jm_slot jm_slots[BASE_JM_MAX_NR_SLOTS];
+ s8 slot_submit_count_irq[BASE_JM_MAX_NR_SLOTS];
+ kbase_os_device osdev;
+ kbase_pm_device_data pm;
+ kbasep_js_device_data js_data;
+ kbasep_mem_device memdev;
+
+ kbase_as as[BASE_MAX_NR_AS];
+
+ spinlock_t mmu_mask_change;
+
+ kbase_gpu_props gpu_props;
+
+ /** List of SW workarounds for HW issues */
+ unsigned long hw_issues_mask[(BASE_HW_ISSUE_END + BITS_PER_LONG - 1) / BITS_PER_LONG];
+
+ /* Cached present bitmaps - these are the same as the corresponding hardware registers */
+ u64 shader_present_bitmap;
+ u64 tiler_present_bitmap;
+ u64 l2_present_bitmap;
+ u64 l3_present_bitmap;
+
+ /* Bitmaps of cores that are currently in use (running jobs).
+ * These should be kept up to date by the job scheduler.
+ *
+ * pm.power_change_lock should be held when accessing these members.
+ *
+ * kbase_pm_check_transitions_nolock() should be called when bits are
+ * cleared to update the power management system and allow transitions to
+ * occur. */
+ u64 shader_inuse_bitmap;
+
+ /* Refcount for cores in use */
+ u32 shader_inuse_cnt[64];
+
+ /* Bitmaps of cores the JS needs for jobs ready to run */
+ u64 shader_needed_bitmap;
+
+ /* Refcount for cores needed */
+ u32 shader_needed_cnt[64];
+
+ u32 tiler_inuse_cnt;
+
+ u32 tiler_needed_cnt;
+
+ /* Refcount for tracking users of the l2 cache, e.g. when using hardware counter instrumentation. */
+ u32 l2_users_count;
+
+ /* Bitmaps of cores that are currently available (powered up and the power policy is happy for jobs to be
+ * submitted to these cores. These are updated by the power management code. The job scheduler should avoid
+ * submitting new jobs to any cores that are not marked as available.
+ *
+ * pm.power_change_lock should be held when accessing these members.
+ */
+ u64 shader_available_bitmap;
+ u64 tiler_available_bitmap;
+ u64 l2_available_bitmap;
+
+ u64 shader_ready_bitmap;
+ u64 shader_transitioning_bitmap;
+
+ s8 nr_hw_address_spaces; /**< Number of address spaces in the GPU (constant after driver initialisation) */
+ s8 nr_user_address_spaces; /**< Number of address spaces available to user contexts */
+
+ /* Structure used for instrumentation and HW counters dumping */
+ struct {
+ /* The lock should be used when accessing any of the following members */
+ spinlock_t lock;
+
+ kbase_context *kctx;
+ u64 addr;
+ wait_queue_head_t wait;
+ int triggered;
+ kbase_instr_state state;
+ wait_queue_head_t cache_clean_wait;
+ struct workqueue_struct *cache_clean_wq;
+ struct work_struct cache_clean_work;
+
+ kbase_context *suspended_kctx;
+ kbase_uk_hwcnt_setup suspended_state;
+ } hwcnt;
+
+ /* Set when we're about to reset the GPU */
+ atomic_t reset_gpu;
+#define KBASE_RESET_GPU_NOT_PENDING 0 /* The GPU reset isn't pending */
+#define KBASE_RESET_GPU_PREPARED 1 /* kbase_prepare_to_reset_gpu has been called */
+#define KBASE_RESET_GPU_COMMITTED 2 /* kbase_reset_gpu has been called - the reset will now definitely happen
+ * within the timeout period */
+#define KBASE_RESET_GPU_HAPPENING 3 /* The GPU reset process is currently occuring (timeout has expired or
+ * kbasep_try_reset_gpu_early was called) */
+
+ /* Work queue and work item for performing the reset in */
+ struct workqueue_struct *reset_workq;
+ struct work_struct reset_work;
+ wait_queue_head_t reset_wait;
+ struct hrtimer reset_timer;
+
+ /*value to be written to the irq_throttle register each time an irq is served */
+ atomic_t irq_throttle_cycles;
+
+ const kbase_attribute *config_attributes;
+
+ /* >> BASE_HW_ISSUE_8401 >> */
+#define KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT 3
+ kbase_context *workaround_kctx;
+ void *workaround_compute_job_va[KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT];
+ phys_addr_t workaround_compute_job_pa[KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT];
+ /* << BASE_HW_ISSUE_8401 << */
+
+#if KBASE_TRACE_ENABLE != 0
+ spinlock_t trace_lock;
+ u16 trace_first_out;
+ u16 trace_next_in;
+ kbase_trace *trace_rbuf;
+#endif
+
+#if MALI_CUSTOMER_RELEASE == 0
+ /* This is used to override the current job scheduler values for
+ * KBASE_CONFIG_ATTR_JS_STOP_STOP_TICKS_SS
+ * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS
+ * KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS
+ * KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS
+ * KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS.
+ *
+ * These values are set via the js_timeouts sysfs file.
+ */
+ u32 js_soft_stop_ticks;
+ u32 js_hard_stop_ticks_ss;
+ u32 js_hard_stop_ticks_nss;
+ u32 js_reset_ticks_ss;
+ u32 js_reset_ticks_nss;
+#endif
+
+ struct mutex cacheclean_lock;
+
+ /* Platform specific private data to be accessed by mali_kbase_config_xxx.c only */
+ void *platform_context;
+
+ /** Count of contexts keeping the GPU powered */
+ atomic_t keep_gpu_powered_count;
+
+ /* List of kbase_contexts created */
+ struct list_head kctx_list;
+ struct mutex kctx_list_lock;
+
+#ifdef CONFIG_MALI_T6XX_RT_PM
+ struct delayed_work runtime_pm_workqueue;
+#endif
+
+#ifdef CONFIG_MALI_TRACE_TIMELINE
+ kbase_trace_kbdev_timeline timeline;
+#endif
+};
+
+struct kbase_context {
+ kbase_device *kbdev;
+ phys_addr_t pgd;
+ struct list_head event_list;
+ struct mutex event_mutex;
+ mali_bool event_closed;
+ struct workqueue_struct *event_workq;
+
+ atomic_t setup_complete;
+ atomic_t setup_in_progress;
+
+ mali_bool keep_gpu_powered;
+
+ u64 *mmu_teardown_pages;
+
+ struct mutex reg_lock; /* To be converted to a rwlock? */
+ struct rb_root reg_rbtree; /* Red-Black tree of GPU regions (live regions) */
+
+ kbase_os_context osctx;
+ kbase_jd_context jctx;
+ kbasep_mem_usage usage;
+ atomic_t nonmapped_pages;
+
+ kbase_mem_allocator osalloc;
+ kbase_mem_allocator * pgd_allocator;
+
+ struct list_head waiting_soft_jobs;
+#ifdef CONFIG_KDS
+ struct list_head waiting_kds_resource;
+#endif
+ /** This is effectively part of the Run Pool, because it only has a valid
+ * setting (!=KBASEP_AS_NR_INVALID) whilst the context is scheduled in
+ *
+ * The kbasep_js_device_data::runpool_irq::lock must be held whilst accessing
+ * this.
+ *
+ * If the context relating to this as_nr is required, you must use
+ * kbasep_js_runpool_retain_ctx() to ensure that the context doesn't disappear
+ * whilst you're using it. Alternatively, just hold the kbasep_js_device_data::runpool_irq::lock
+ * to ensure the context doesn't disappear (but this has restrictions on what other locks
+ * you can take whilst doing this) */
+ int as_nr;
+
+ /* NOTE:
+ *
+ * Flags are in jctx.sched_info.ctx.flags
+ * Mutable flags *must* be accessed under jctx.sched_info.ctx.jsctx_mutex
+ *
+ * All other flags must be added there */
+ spinlock_t mm_update_lock;
+ struct mm_struct * process_mm;
+
+#ifdef CONFIG_MALI_TRACE_TIMELINE
+ kbase_trace_kctx_timeline timeline;
+#endif
+};
+
+typedef enum kbase_reg_access_type {
+ REG_READ,
+ REG_WRITE
+} kbase_reg_access_type;
+
+typedef enum kbase_share_attr_bits {
+ /* (1ULL << 8) bit is reserved */
+ SHARE_BOTH_BITS = (2ULL << 8), /* inner and outer shareable coherency */
+ SHARE_INNER_BITS = (3ULL << 8) /* inner shareable coherency */
+} kbase_share_attr_bits;
+
+/* 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))
+
+/* Maximum number of loops polling the GPU for a cache flush before we assume it must have completed */
+#define KBASE_CLEAN_CACHE_MAX_LOOPS 100000
+/* Maximum number of loops polling the GPU for an AS flush to complete before we assume the GPU has hung */
+#define KBASE_AS_FLUSH_MAX_LOOPS 100000
+
+#endif /* _KBASE_DEFS_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_device.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_device.c
new file mode 100755
index 00000000000..23df622a46b
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_device.c
@@ -0,0 +1,691 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_device.c
+ * Base kernel device APIs
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <kbase/src/common/mali_kbase.h>
+#include <kbase/src/common/mali_kbase_defs.h>
+#include <kbase/src/common/mali_kbase_hw.h>
+
+/* NOTE: Magic - 0x45435254 (TRCE in ASCII).
+ * Supports tracing feature provided in the base module.
+ * Please keep it in sync with the value of base module.
+ */
+#define TRACE_BUFFER_HEADER_SPECIAL 0x45435254
+
+#ifdef CONFIG_MALI_PLATFORM_VEXPRESS
+#ifdef CONFIG_MALI_PLATFORM_FAKE
+extern kbase_attribute config_attributes_hw_issue_8408[];
+#endif /* CONFIG_MALI_PLATFORM_FAKE */
+#endif /* CONFIG_MALI_PLATFORM_VEXPRESS */
+
+#if KBASE_TRACE_ENABLE != 0
+STATIC CONST char *kbasep_trace_code_string[] = {
+ /* IMPORTANT: USE OF SPECIAL #INCLUDE OF NON-STANDARD HEADER FILE
+ * THIS MUST BE USED AT THE START OF THE ARRAY */
+#define KBASE_TRACE_CODE_MAKE_CODE(X) # X
+#include "mali_kbase_trace_defs.h"
+#undef KBASE_TRACE_CODE_MAKE_CODE
+};
+#endif
+
+#define DEBUG_MESSAGE_SIZE 256
+
+STATIC mali_error kbasep_trace_init(kbase_device *kbdev);
+STATIC void kbasep_trace_term(kbase_device *kbdev);
+STATIC void kbasep_trace_hook_wrapper(void *param);
+#if KBASE_TRACE_ENABLE != 0
+STATIC void kbasep_trace_debugfs_init(kbase_device *kbdev);
+#endif
+
+void kbasep_as_do_poke(struct work_struct *work);
+enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *data);
+void kbasep_reset_timeout_worker(struct work_struct *data);
+
+kbase_device *kbase_device_alloc(void)
+{
+ return kzalloc(sizeof(kbase_device), GFP_KERNEL);
+}
+
+mali_error kbase_device_init(kbase_device * const kbdev)
+{
+ int i; /* i used after the for loop, don't reuse ! */
+
+ spin_lock_init(&kbdev->mmu_mask_change);
+
+ /* Initialize platform specific context */
+ if (MALI_FALSE == kbasep_platform_device_init(kbdev))
+ goto fail;
+
+ /* Ensure we can access the GPU registers */
+ kbase_pm_register_access_enable(kbdev);
+
+ /* Find out GPU properties based on the GPU feature registers */
+ kbase_gpuprops_set(kbdev);
+
+ /* Get the list of workarounds for issues on the current HW (identified by the GPU_ID register) */
+ if (MALI_ERROR_NONE != kbase_hw_set_issues_mask(kbdev)) {
+ kbase_pm_register_access_disable(kbdev);
+ goto free_platform;
+ }
+
+ kbdev->nr_hw_address_spaces = kbdev->gpu_props.num_address_spaces;
+
+ /* We're done accessing the GPU registers for now. */
+ kbase_pm_register_access_disable(kbdev);
+
+ for (i = 0; i < kbdev->nr_hw_address_spaces; i++) {
+ const char format[] = "mali_mmu%d";
+ char name[sizeof(format)];
+ const char poke_format[] = "mali_mmu%d_poker"; /* BASE_HW_ISSUE_8316 */
+ char poke_name[sizeof(poke_format)]; /* BASE_HW_ISSUE_8316 */
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) {
+ if (0 > snprintf(poke_name, sizeof(poke_name), poke_format, i))
+ goto free_workqs;
+ }
+
+ if (0 > snprintf(name, sizeof(name), format, i))
+ goto free_workqs;
+
+ kbdev->as[i].number = i;
+ kbdev->as[i].fault_addr = 0ULL;
+
+ kbdev->as[i].pf_wq = alloc_workqueue(name, 0, 1);
+ if (NULL == kbdev->as[i].pf_wq)
+ goto free_workqs;
+
+ mutex_init(&kbdev->as[i].transaction_mutex);
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) {
+ struct hrtimer *poking_timer = &kbdev->as[i].poke_timer;
+
+ kbdev->as[i].poke_wq = alloc_workqueue(poke_name, 0, 1);
+ if (NULL == kbdev->as[i].poke_wq) {
+ destroy_workqueue(kbdev->as[i].pf_wq);
+ goto free_workqs;
+ }
+ KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&kbdev->as[i].poke_work));
+ INIT_WORK(&kbdev->as[i].poke_work, kbasep_as_do_poke);
+
+ hrtimer_init(poking_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+
+ poking_timer->function = kbasep_as_poke_timer_callback;
+
+ kbdev->as[i].poke_refcount = 0;
+ kbdev->as[i].poke_state = 0u;
+ }
+ }
+ /* don't change i after this point */
+
+ spin_lock_init(&kbdev->hwcnt.lock);
+
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_DISABLED;
+ init_waitqueue_head(&kbdev->reset_wait);
+ init_waitqueue_head(&kbdev->hwcnt.wait);
+ init_waitqueue_head(&kbdev->hwcnt.cache_clean_wait);
+ INIT_WORK(&kbdev->hwcnt.cache_clean_work, kbasep_cache_clean_worker);
+ kbdev->hwcnt.triggered = 0;
+
+ kbdev->hwcnt.cache_clean_wq = alloc_workqueue("Mali cache cleaning workqueue",
+ 0, 1);
+ if (NULL == kbdev->hwcnt.cache_clean_wq)
+ goto free_workqs;
+
+ kbdev->reset_workq = alloc_workqueue("Mali reset workqueue", 0, 1);
+ if (NULL == kbdev->reset_workq)
+ goto free_cache_clean_workq;
+
+ KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&kbdev->reset_work));
+ INIT_WORK(&kbdev->reset_work, kbasep_reset_timeout_worker);
+
+ hrtimer_init(&kbdev->reset_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ kbdev->reset_timer.function = kbasep_reset_timer_callback;
+
+ if (kbasep_trace_init(kbdev) != MALI_ERROR_NONE)
+ goto free_reset_workq;
+
+ mutex_init(&kbdev->cacheclean_lock);
+ atomic_set(&kbdev->keep_gpu_powered_count, 0);
+
+#ifdef CONFIG_MALI_TRACE_TIMELINE
+ for (i = 0; i < BASE_JM_SUBMIT_SLOTS; ++i)
+ kbdev->timeline.slot_atoms_submitted[i] = 0;
+
+ for (i = 0; i <= KBASEP_TIMELINE_PM_EVENT_LAST; ++i)
+ atomic_set(&kbdev->timeline.pm_event_uid[i], 0);
+#endif /* CONFIG_MALI_TRACE_TIMELINE */
+
+ kbase_debug_assert_register_hook(&kbasep_trace_hook_wrapper, kbdev);
+
+#ifdef CONFIG_MALI_PLATFORM_VEXPRESS
+#ifdef CONFIG_MALI_PLATFORM_FAKE
+ /* BASE_HW_ISSUE_8408 requires a configuration with different timeouts for
+ * the vexpress platform */
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408))
+ kbdev->config_attributes = config_attributes_hw_issue_8408;
+#endif /* CONFIG_MALI_PLATFORM_FAKE */
+#endif /* CONFIG_MALI_PLATFORM_VEXPRESS */
+
+ return MALI_ERROR_NONE;
+
+ free_reset_workq:
+ destroy_workqueue(kbdev->reset_workq);
+ free_cache_clean_workq:
+ destroy_workqueue(kbdev->hwcnt.cache_clean_wq);
+ free_workqs:
+ while (i > 0) {
+ i--;
+ destroy_workqueue(kbdev->as[i].pf_wq);
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316))
+ destroy_workqueue(kbdev->as[i].poke_wq);
+ }
+ free_platform:
+ kbasep_platform_device_term(kbdev);
+ fail:
+ return MALI_ERROR_FUNCTION_FAILED;
+}
+
+void kbase_device_term(kbase_device *kbdev)
+{
+ int i;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+
+#if KBASE_TRACE_ENABLE != 0
+ kbase_debug_assert_register_hook(NULL, NULL);
+#endif
+
+ kbasep_trace_term(kbdev);
+
+ destroy_workqueue(kbdev->reset_workq);
+ destroy_workqueue(kbdev->hwcnt.cache_clean_wq);
+
+ for (i = 0; i < kbdev->nr_hw_address_spaces; i++) {
+ destroy_workqueue(kbdev->as[i].pf_wq);
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316))
+ destroy_workqueue(kbdev->as[i].poke_wq);
+ }
+
+ kbasep_platform_device_term(kbdev);
+}
+
+void kbase_device_free(kbase_device *kbdev)
+{
+ kfree(kbdev);
+}
+
+void kbase_device_trace_buffer_install(kbase_context *kctx, u32 *tb, size_t size)
+{
+ unsigned long flags;
+ KBASE_DEBUG_ASSERT(kctx);
+ KBASE_DEBUG_ASSERT(tb);
+
+ /* set up the header */
+ /* magic number in the first 4 bytes */
+ tb[0] = TRACE_BUFFER_HEADER_SPECIAL;
+ /* Store (write offset = 0, wrap counter = 0, transaction active = no)
+ * write offset 0 means never written.
+ * Offsets 1 to (wrap_offset - 1) used to store values when trace started
+ */
+ tb[1] = 0;
+
+ /* install trace buffer */
+ spin_lock_irqsave(&kctx->jctx.tb_lock, flags);
+ kctx->jctx.tb_wrap_offset = size / 8;
+ kctx->jctx.tb = tb;
+ spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags);
+}
+
+void kbase_device_trace_buffer_uninstall(kbase_context *kctx)
+{
+ unsigned long flags;
+ KBASE_DEBUG_ASSERT(kctx);
+ spin_lock_irqsave(&kctx->jctx.tb_lock, flags);
+ kctx->jctx.tb = NULL;
+ kctx->jctx.tb_wrap_offset = 0;
+ spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags);
+}
+
+void kbase_device_trace_register_access(kbase_context *kctx, kbase_reg_access_type type, u16 reg_offset, u32 reg_value)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&kctx->jctx.tb_lock, flags);
+ if (kctx->jctx.tb) {
+ u16 wrap_count;
+ u16 write_offset;
+ u32 *tb = kctx->jctx.tb;
+ u32 header_word;
+
+ header_word = tb[1];
+ KBASE_DEBUG_ASSERT(0 == (header_word & 0x1));
+
+ wrap_count = (header_word >> 1) & 0x7FFF;
+ write_offset = (header_word >> 16) & 0xFFFF;
+
+ /* mark as transaction in progress */
+ tb[1] |= 0x1;
+ mb();
+
+ /* calculate new offset */
+ write_offset++;
+ if (write_offset == kctx->jctx.tb_wrap_offset) {
+ /* wrap */
+ write_offset = 1;
+ wrap_count++;
+ wrap_count &= 0x7FFF; /* 15bit wrap counter */
+ }
+
+ /* store the trace entry at the selected offset */
+ tb[write_offset * 2 + 0] = (reg_offset & ~0x3) | ((type == REG_WRITE) ? 0x1 : 0x0);
+ tb[write_offset * 2 + 1] = reg_value;
+ mb();
+
+ /* new header word */
+ header_word = (write_offset << 16) | (wrap_count << 1) | 0x0; /* transaction complete */
+ tb[1] = header_word;
+ }
+ spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags);
+}
+
+void kbase_reg_write(kbase_device *kbdev, u16 offset, u32 value, kbase_context *kctx)
+{
+ KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered);
+ KBASE_DEBUG_ASSERT(kctx == NULL || kctx->as_nr != KBASEP_AS_NR_INVALID);
+ KBASE_DEBUG_PRINT_INFO(KBASE_CORE, "w: reg %04x val %08x", offset, value);
+ kbase_os_reg_write(kbdev, offset, value);
+ if (kctx && kctx->jctx.tb)
+ kbase_device_trace_register_access(kctx, REG_WRITE, offset, value);
+}
+
+KBASE_EXPORT_TEST_API(kbase_reg_write)
+
+u32 kbase_reg_read(kbase_device *kbdev, u16 offset, kbase_context *kctx)
+{
+ u32 val;
+ KBASE_DEBUG_ASSERT(kbdev->pm.gpu_powered);
+ KBASE_DEBUG_ASSERT(kctx == NULL || kctx->as_nr != KBASEP_AS_NR_INVALID);
+ val = kbase_os_reg_read(kbdev, offset);
+ KBASE_DEBUG_PRINT_INFO(KBASE_CORE, "r: reg %04x val %08x", offset, val);
+ if (kctx && kctx->jctx.tb)
+ kbase_device_trace_register_access(kctx, REG_READ, offset, val);
+ return val;
+}
+
+KBASE_EXPORT_TEST_API(kbase_reg_read)
+
+void kbase_report_gpu_fault(kbase_device *kbdev, int multiple)
+{
+ u32 status;
+ u64 address;
+
+ status = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS), NULL);
+ address = (u64) kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTADDRESS_HI), NULL) << 32;
+ address |= kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTADDRESS_LO), NULL);
+
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "GPU Fault 0x%08x (%s) at 0x%016llx", status, kbase_exception_name(status), address);
+ if (multiple)
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "There were multiple GPU faults - some have not been reported\n");
+}
+
+void kbase_gpu_interrupt(kbase_device *kbdev, u32 val)
+{
+ KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, NULL, 0u, val);
+ if (val & GPU_FAULT)
+ kbase_report_gpu_fault(kbdev, val & MULTIPLE_GPU_FAULTS);
+
+ if (val & RESET_COMPLETED)
+ kbase_pm_reset_done(kbdev);
+
+ if (val & PRFCNT_SAMPLE_COMPLETED)
+ kbase_instr_hwcnt_sample_done(kbdev);
+
+ if (val & CLEAN_CACHES_COMPLETED)
+ kbase_clean_caches_done(kbdev);
+
+ KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, NULL, 0u, val);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), val, NULL);
+
+ /* kbase_pm_check_transitions must be called after the IRQ has been cleared. This is because it might trigger
+ * further power transitions and we don't want to miss the interrupt raised to notify us that these further
+ * transitions have finished.
+ */
+ if (val & POWER_CHANGED_ALL) {
+ mali_bool cores_are_available;
+ unsigned long flags;
+
+ KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_START);
+ spin_lock_irqsave(&kbdev->pm.power_change_lock, flags);
+ cores_are_available = kbase_pm_check_transitions_nolock(kbdev);
+ spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags);
+ KBASE_TIMELINE_PM_CHECKTRANS(kbdev, SW_FLOW_PM_CHECKTRANS_GPU_INTERRUPT_END);
+
+ if (cores_are_available) {
+ /* Fast-path Job Scheduling on PM IRQ */
+ int js;
+ /* Log timelining information that a change in state has completed */
+ kbase_timeline_pm_handle_event(kbdev, KBASE_TIMELINE_PM_EVENT_GPU_STATE_CHANGED);
+
+ spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, flags);
+ /* A simplified check to ensure the last context hasn't exited
+ * after dropping the PM lock whilst doing a PM IRQ: any bits set
+ * in 'submit_allowed' indicate that we have a context in the
+ * runpool (which can't leave whilst we hold this lock). It is
+ * sometimes zero even when we have a context in the runpool, but
+ * that's no problem because we'll be unable to submit jobs
+ * anyway */
+ if (kbdev->js_data.runpool_irq.submit_allowed)
+ for (js = 0; js < kbdev->gpu_props.num_job_slots; ++js) {
+ mali_bool needs_retry;
+ s8 submitted_count = 0;
+ needs_retry = kbasep_js_try_run_next_job_on_slot_irq_nolock(kbdev, js, &submitted_count);
+ /* Don't need to retry outside of IRQ context - this can
+ * only happen if we submitted too many in one IRQ, such
+ * that they were completing faster than we could
+ * submit. In this case, a job IRQ will fire to cause more
+ * work to be submitted in some way */
+ CSTD_UNUSED(needs_retry);
+ }
+ spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, flags);
+ }
+ }
+ KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_DONE, NULL, NULL, 0u, val);
+}
+
+/*
+ * Device trace functions
+ */
+#if KBASE_TRACE_ENABLE != 0
+
+STATIC mali_error kbasep_trace_init(kbase_device *kbdev)
+{
+ void *rbuf;
+
+ rbuf = kmalloc(sizeof(kbase_trace) * KBASE_TRACE_SIZE, GFP_KERNEL);
+
+ if (!rbuf)
+ return MALI_ERROR_FUNCTION_FAILED;
+
+ kbdev->trace_rbuf = rbuf;
+ spin_lock_init(&kbdev->trace_lock);
+ kbasep_trace_debugfs_init(kbdev);
+ return MALI_ERROR_NONE;
+}
+
+STATIC void kbasep_trace_term(kbase_device *kbdev)
+{
+ kfree(kbdev->trace_rbuf);
+}
+
+void kbasep_trace_format_msg(kbase_trace *trace_msg, char *buffer, int len)
+{
+ s32 written = 0;
+
+ /* Initial part of message */
+ written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d.%.6d,%d,%d,%s,%p,", (int)trace_msg->timestamp.tv_sec, (int)(trace_msg->timestamp.tv_nsec / 1000), trace_msg->thread_id, trace_msg->cpu, kbasep_trace_code_string[trace_msg->code], trace_msg->ctx), 0);
+
+ if (trace_msg->katom != MALI_FALSE) {
+ written += MAX(snprintf(buffer + written, MAX(len - written, 0), "atom %d (ud: 0x%llx 0x%llx)", trace_msg->atom_number, trace_msg->atom_udata[0], trace_msg->atom_udata[1]), 0);
+ }
+
+ written += MAX(snprintf(buffer + written, MAX(len - written, 0), ",%.8llx,", trace_msg->gpu_addr), 0);
+
+ /* NOTE: Could add function callbacks to handle different message types */
+ /* Jobslot present */
+ if ((trace_msg->flags & KBASE_TRACE_FLAG_JOBSLOT) != MALI_FALSE)
+ written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->jobslot), 0);
+
+ written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0);
+
+ /* Refcount present */
+ if ((trace_msg->flags & KBASE_TRACE_FLAG_REFCOUNT) != MALI_FALSE)
+ written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->refcount), 0);
+
+ written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0);
+
+ /* Rest of message */
+ written += MAX(snprintf(buffer + written, MAX(len - written, 0), "0x%.8x", trace_msg->info_val), 0);
+
+}
+
+void kbasep_trace_dump_msg(kbase_trace *trace_msg)
+{
+ char buffer[DEBUG_MESSAGE_SIZE];
+
+ kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE);
+ KBASE_DEBUG_PRINT(KBASE_CORE, "%s", buffer);
+}
+
+void kbasep_trace_add(kbase_device *kbdev, kbase_trace_code code, void *ctx, kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, u32 info_val)
+{
+ unsigned long irqflags;
+ kbase_trace *trace_msg;
+
+ spin_lock_irqsave(&kbdev->trace_lock, irqflags);
+
+ trace_msg = &kbdev->trace_rbuf[kbdev->trace_next_in];
+
+ /* Fill the message */
+ trace_msg->thread_id = task_pid_nr(current);
+ trace_msg->cpu = task_cpu(current);
+
+ getnstimeofday(&trace_msg->timestamp);
+
+ trace_msg->code = code;
+ trace_msg->ctx = ctx;
+
+ if (NULL == katom) {
+ trace_msg->katom = MALI_FALSE;
+ } else {
+ trace_msg->katom = MALI_TRUE;
+ trace_msg->atom_number = kbase_jd_atom_id(katom->kctx, katom);
+ trace_msg->atom_udata[0] = katom->udata.blob[0];
+ trace_msg->atom_udata[1] = katom->udata.blob[1];
+ }
+
+ trace_msg->gpu_addr = gpu_addr;
+ trace_msg->jobslot = jobslot;
+ trace_msg->refcount = MIN((unsigned int)refcount, 0xFF);
+ trace_msg->info_val = info_val;
+ trace_msg->flags = flags;
+
+ /* Update the ringbuffer indices */
+ kbdev->trace_next_in = (kbdev->trace_next_in + 1) & KBASE_TRACE_MASK;
+ if (kbdev->trace_next_in == kbdev->trace_first_out)
+ kbdev->trace_first_out = (kbdev->trace_first_out + 1) & KBASE_TRACE_MASK;
+
+ /* Done */
+
+ spin_unlock_irqrestore(&kbdev->trace_lock, irqflags);
+}
+
+void kbasep_trace_clear(kbase_device *kbdev)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&kbdev->trace_lock, flags);
+ kbdev->trace_first_out = kbdev->trace_next_in;
+ spin_unlock_irqrestore(&kbdev->trace_lock, flags);
+}
+
+void kbasep_trace_dump(kbase_device *kbdev)
+{
+ unsigned long flags;
+ u32 start;
+ u32 end;
+
+ KBASE_DEBUG_PRINT(KBASE_CORE, "Dumping trace:\nsecs,nthread,cpu,code,ctx,katom,gpu_addr,jobslot,refcount,info_val");
+ spin_lock_irqsave(&kbdev->trace_lock, flags);
+ start = kbdev->trace_first_out;
+ end = kbdev->trace_next_in;
+
+ while (start != end) {
+ kbase_trace *trace_msg = &kbdev->trace_rbuf[start];
+ kbasep_trace_dump_msg(trace_msg);
+
+ start = (start + 1) & KBASE_TRACE_MASK;
+ }
+ KBASE_DEBUG_PRINT(KBASE_CORE, "TRACE_END");
+
+ spin_unlock_irqrestore(&kbdev->trace_lock, flags);
+
+ KBASE_TRACE_CLEAR(kbdev);
+}
+
+STATIC void kbasep_trace_hook_wrapper(void *param)
+{
+ kbase_device *kbdev = (kbase_device *) param;
+ kbasep_trace_dump(kbdev);
+}
+
+#ifdef CONFIG_DEBUG_FS
+struct trace_seq_state {
+ kbase_trace trace_buf[KBASE_TRACE_SIZE];
+ u32 start;
+ u32 end;
+};
+
+void *kbasep_trace_seq_start(struct seq_file *s, loff_t *pos)
+{
+ struct trace_seq_state *state = s->private;
+ int i;
+
+ i = (state->start + *pos) & KBASE_TRACE_MASK;
+ if (i >= state-> end)
+ return NULL;
+
+ return state;
+}
+
+void kbasep_trace_seq_stop(struct seq_file *s, void *data)
+{
+}
+
+void *kbasep_trace_seq_next(struct seq_file *s, void *data, loff_t *pos)
+{
+ struct trace_seq_state *state = s->private;
+ int i;
+
+ (*pos)++;
+
+ i = (state->start + *pos) & KBASE_TRACE_MASK;
+ if (i >= state->end)
+ return NULL;
+
+ return &state->trace_buf[i];
+}
+
+int kbasep_trace_seq_show(struct seq_file *s, void *data)
+{
+ kbase_trace *trace_msg = data;
+ char buffer[DEBUG_MESSAGE_SIZE];
+
+ kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE);
+ seq_printf(s, "%s\n", buffer);
+ return 0;
+}
+
+static const struct seq_operations kbasep_trace_seq_ops = {
+ .start = kbasep_trace_seq_start,
+ .next = kbasep_trace_seq_next,
+ .stop = kbasep_trace_seq_stop,
+ .show = kbasep_trace_seq_show,
+};
+
+static int kbasep_trace_debugfs_open(struct inode *inode, struct file *file)
+{
+ kbase_device *kbdev = inode->i_private;
+ unsigned long flags;
+
+ struct trace_seq_state *state;
+
+ state = __seq_open_private(file, &kbasep_trace_seq_ops, sizeof(*state));
+ if (!state)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&kbdev->trace_lock, flags);
+ state->start = kbdev->trace_first_out;
+ state->end = kbdev->trace_next_in;
+ memcpy(state->trace_buf, kbdev->trace_rbuf, sizeof(state->trace_buf));
+ spin_unlock_irqrestore(&kbdev->trace_lock, flags);
+
+ return 0;
+}
+
+static const struct file_operations kbasep_trace_debugfs_fops = {
+ .open = kbasep_trace_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+STATIC void kbasep_trace_debugfs_init(kbase_device *kbdev)
+{
+ debugfs_create_file("mali_trace", S_IRUGO, NULL, kbdev, &kbasep_trace_debugfs_fops);
+}
+#else
+STATIC void kbasep_trace_debugfs_init(kbase_device *kbdev)
+{
+
+}
+#endif /* CONFIG_DEBUG_FS */
+
+#else /* KBASE_TRACE_ENABLE != 0 */
+STATIC mali_error kbasep_trace_init(kbase_device *kbdev)
+{
+ CSTD_UNUSED(kbdev);
+ return MALI_ERROR_NONE;
+}
+
+STATIC void kbasep_trace_term(kbase_device *kbdev)
+{
+ CSTD_UNUSED(kbdev);
+}
+
+STATIC void kbasep_trace_hook_wrapper(void *param)
+{
+ CSTD_UNUSED(param);
+}
+
+void kbasep_trace_add(kbase_device *kbdev, kbase_trace_code code, void *ctx, kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, u32 info_val)
+{
+ CSTD_UNUSED(kbdev);
+ CSTD_UNUSED(code);
+ CSTD_UNUSED(ctx);
+ CSTD_UNUSED(katom);
+ CSTD_UNUSED(gpu_addr);
+ CSTD_UNUSED(flags);
+ CSTD_UNUSED(refcount);
+ CSTD_UNUSED(jobslot);
+ CSTD_UNUSED(info_val);
+}
+
+void kbasep_trace_clear(kbase_device *kbdev)
+{
+ CSTD_UNUSED(kbdev);
+}
+
+void kbasep_trace_dump(kbase_device *kbdev)
+{
+ CSTD_UNUSED(kbdev);
+}
+#endif /* KBASE_TRACE_ENABLE != 0 */
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_event.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_event.c
new file mode 100755
index 00000000000..7f6834cc138
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_event.c
@@ -0,0 +1,174 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#include <kbase/src/common/mali_kbase.h>
+
+#define beenthere(f, a...) pr_debug("%s:" f, __func__, ##a)
+
+STATIC base_jd_udata kbase_event_process(kbase_context *kctx, kbase_jd_atom *katom)
+{
+ base_jd_udata data;
+
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ KBASE_DEBUG_ASSERT(katom != NULL);
+ KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED);
+
+ data = katom->udata;
+
+ KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_sub_return(1, &kctx->timeline.jd_atoms_in_flight));
+
+ katom->status = KBASE_JD_ATOM_STATE_UNUSED;
+
+ wake_up(&katom->completed);
+
+ return data;
+}
+
+int kbase_event_pending(kbase_context *ctx)
+{
+ int ret;
+
+ KBASE_DEBUG_ASSERT(ctx);
+
+ mutex_lock(&ctx->event_mutex);
+ ret = (!list_empty(&ctx->event_list)) || (MALI_TRUE == ctx->event_closed);
+ mutex_unlock(&ctx->event_mutex);
+
+ return ret;
+}
+
+KBASE_EXPORT_TEST_API(kbase_event_pending)
+
+int kbase_event_dequeue(kbase_context *ctx, base_jd_event_v2 *uevent)
+{
+ kbase_jd_atom *atom;
+
+ KBASE_DEBUG_ASSERT(ctx);
+
+ mutex_lock(&ctx->event_mutex);
+
+ if (list_empty(&ctx->event_list)) {
+ if (ctx->event_closed) {
+ /* generate the BASE_JD_EVENT_DRV_TERMINATED message on the fly */
+ mutex_unlock(&ctx->event_mutex);
+ uevent->event_code = BASE_JD_EVENT_DRV_TERMINATED;
+ memset(&uevent->udata, 0, sizeof(uevent->udata));
+ beenthere("event system closed, returning BASE_JD_EVENT_DRV_TERMINATED(0x%X)\n", BASE_JD_EVENT_DRV_TERMINATED);
+ return 0;
+ } else {
+ mutex_unlock(&ctx->event_mutex);
+ return -1;
+ }
+ }
+
+ /* normal event processing */
+ atom = list_entry(ctx->event_list.next, kbase_jd_atom, dep_item[0]);
+ list_del(ctx->event_list.next);
+
+ mutex_unlock(&ctx->event_mutex);
+
+ beenthere("event dequeuing %p\n", (void *)atom);
+ uevent->event_code = atom->event_code;
+ uevent->atom_number = (atom - ctx->jctx.atoms);
+ uevent->udata = kbase_event_process(ctx, atom);
+
+ return 0;
+}
+
+KBASE_EXPORT_TEST_API(kbase_event_dequeue)
+
+static void kbase_event_post_worker(struct work_struct *data)
+{
+ kbase_jd_atom *atom = CONTAINER_OF(data, kbase_jd_atom, work);
+ kbase_context *ctx = atom->kctx;
+
+ if (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES)
+ kbase_jd_free_external_resources(atom);
+
+ if (atom->core_req & BASE_JD_REQ_EVENT_ONLY_ON_FAILURE) {
+ if (atom->event_code == BASE_JD_EVENT_DONE) {
+ /* Don't report the event */
+ kbase_event_process(ctx, atom);
+ return;
+ }
+ }
+
+ mutex_lock(&ctx->event_mutex);
+ list_add_tail(&atom->dep_item[0], &ctx->event_list);
+ mutex_unlock(&ctx->event_mutex);
+
+ kbase_event_wakeup(ctx);
+}
+
+void kbase_event_post(kbase_context *ctx, kbase_jd_atom *atom)
+{
+ KBASE_DEBUG_ASSERT(ctx);
+ KBASE_DEBUG_ASSERT(ctx->event_workq);
+ KBASE_DEBUG_ASSERT(atom);
+
+ INIT_WORK(&atom->work, kbase_event_post_worker);
+ queue_work(ctx->event_workq, &atom->work);
+}
+
+KBASE_EXPORT_TEST_API(kbase_event_post)
+
+void kbase_event_close(kbase_context *kctx)
+{
+ mutex_lock(&kctx->event_mutex);
+ kctx->event_closed = MALI_TRUE;
+ mutex_unlock(&kctx->event_mutex);
+ kbase_event_wakeup(kctx);
+}
+
+mali_error kbase_event_init(kbase_context *kctx)
+{
+ KBASE_DEBUG_ASSERT(kctx);
+
+ INIT_LIST_HEAD(&kctx->event_list);
+ mutex_init(&kctx->event_mutex);
+ kctx->event_closed = MALI_FALSE;
+ kctx->event_workq = alloc_workqueue("kbase_event", WQ_MEM_RECLAIM, 1);
+
+ if (NULL == kctx->event_workq)
+ return MALI_ERROR_FUNCTION_FAILED;
+
+ return MALI_ERROR_NONE;
+}
+
+KBASE_EXPORT_TEST_API(kbase_event_init)
+
+void kbase_event_cleanup(kbase_context *kctx)
+{
+ KBASE_DEBUG_ASSERT(kctx);
+ KBASE_DEBUG_ASSERT(kctx->event_workq);
+
+ flush_workqueue(kctx->event_workq);
+ destroy_workqueue(kctx->event_workq);
+
+ /* We use kbase_event_dequeue to remove the remaining events as that
+ * deals with all the cleanup needed for the atoms.
+ *
+ * Note: use of kctx->event_list without a lock is safe because this must be the last
+ * thread using it (because we're about to terminate the lock)
+ */
+ while (!list_empty(&kctx->event_list)) {
+ base_jd_event_v2 event;
+ kbase_event_dequeue(kctx, &event);
+ }
+}
+
+KBASE_EXPORT_TEST_API(kbase_event_cleanup)
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gator.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gator.h
new file mode 100755
index 00000000000..3820bcf07d9
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gator.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifdef CONFIG_MALI_GATOR_SUPPORT
+#define GATOR_MAKE_EVENT(type, number) (((type) << 24) | ((number) << 16))
+#define GATOR_JOB_SLOT_START 1
+#define GATOR_JOB_SLOT_STOP 2
+#define GATOR_JOB_SLOT_SOFT_STOPPED 3
+void kbase_trace_mali_job_slots_event(u32 event, const kbase_context *kctx);
+void kbase_trace_mali_pm_status(u32 event, u64 value);
+void kbase_trace_mali_pm_power_off(u32 event, u64 value);
+void kbase_trace_mali_pm_power_on(u32 event, u64 value);
+void kbase_trace_mali_page_fault_insert_pages(int event, u32 value);
+void kbase_trace_mali_mmu_as_in_use(int event);
+void kbase_trace_mali_mmu_as_released(int event);
+void kbase_trace_mali_total_alloc_pages_change(long long int event);
+#endif
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops.c
new file mode 100755
index 00000000000..93ceee8c850
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops.c
@@ -0,0 +1,314 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_gpuprops.c
+ * Base kernel property query APIs
+ */
+
+#include <kbase/src/common/mali_kbase.h>
+#include <kbase/src/common/mali_midg_regmap.h>
+#include <kbase/src/common/mali_kbase_gpuprops.h>
+
+/**
+ * @brief Extracts bits from a 32-bit bitfield.
+ * @hideinitializer
+ *
+ * @param[in] value The value from which to extract bits.
+ * @param[in] offset The first bit to extract (0 being the LSB).
+ * @param[in] size The number of bits to extract.
+ * @return Bits [@a offset, @a offset + @a size) from @a value.
+ *
+ * @pre offset + size <= 32.
+ */
+/* from mali_cdsb.h */
+#define KBASE_UBFX32(value, offset, size) \
+ (((u32)(value) >> (u32)(offset)) & (u32)((1ULL << (u32)(size)) - 1))
+
+mali_error kbase_gpuprops_uk_get_props(kbase_context *kctx, kbase_uk_gpuprops * const kbase_props)
+{
+ kbase_gpuprops_clock_speed_function get_gpu_speed_mhz;
+ u32 gpu_speed_mhz;
+ int rc = 1;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+ KBASE_DEBUG_ASSERT(NULL != kbase_props);
+
+ /* Current GPU speed is requested from the system integrator via the KBASE_CONFIG_ATTR_GPU_SPEED_FUNC function.
+ * If that function fails, or the function is not provided by the system integrator, we report the maximum
+ * GPU speed as specified by KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX.
+ */
+ get_gpu_speed_mhz = (kbase_gpuprops_clock_speed_function) kbasep_get_config_value(kctx->kbdev, kctx->kbdev->config_attributes, KBASE_CONFIG_ATTR_GPU_SPEED_FUNC);
+ if (get_gpu_speed_mhz != NULL) {
+ rc = get_gpu_speed_mhz(&gpu_speed_mhz);
+#ifdef CONFIG_MALI_DEBUG
+ /* Issue a warning message when the reported GPU speed falls outside the min/max range */
+ if (rc == 0) {
+ u32 gpu_speed_khz = gpu_speed_mhz * 1000;
+ if (gpu_speed_khz < kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_min || gpu_speed_khz > kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max)
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "GPU Speed is outside of min/max range (got %lu Khz, min %lu Khz, max %lu Khz)\n", (unsigned long)gpu_speed_khz, (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_min, (unsigned long)kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max);
+ }
+#endif /* CONFIG_MALI_DEBUG */
+ }
+ if (rc != 0)
+ gpu_speed_mhz = kctx->kbdev->gpu_props.props.core_props.gpu_freq_khz_max / 1000;
+
+ kctx->kbdev->gpu_props.props.core_props.gpu_speed_mhz = gpu_speed_mhz;
+
+ memcpy(&kbase_props->props, &kctx->kbdev->gpu_props.props, sizeof(kbase_props->props));
+
+ return MALI_ERROR_NONE;
+}
+
+STATIC void kbase_gpuprops_dump_registers(kbase_device *kbdev, kbase_gpuprops_regdump *regdump)
+{
+ int i;
+
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+ KBASE_DEBUG_ASSERT(NULL != regdump);
+
+ /* Fill regdump with the content of the relevant registers */
+ regdump->gpu_id = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID));
+
+ regdump->l2_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_FEATURES));
+ regdump->l3_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_FEATURES));
+ regdump->tiler_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_FEATURES));
+ regdump->mem_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(MEM_FEATURES));
+ regdump->mmu_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(MMU_FEATURES));
+ regdump->as_present = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(AS_PRESENT));
+ regdump->js_present = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(JS_PRESENT));
+
+ for (i = 0; i < MIDG_MAX_JOB_SLOTS; i++)
+ regdump->js_features[i] = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(JS_FEATURES_REG(i)));
+
+ for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++)
+ regdump->texture_features[i] = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TEXTURE_FEATURES_REG(i)));
+
+ regdump->thread_max_threads = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_MAX_THREADS));
+ regdump->thread_max_workgroup_size = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_MAX_WORKGROUP_SIZE));
+ regdump->thread_max_barrier_size = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_MAX_BARRIER_SIZE));
+ regdump->thread_features = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(THREAD_FEATURES));
+
+ regdump->shader_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(SHADER_PRESENT_LO));
+ regdump->shader_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(SHADER_PRESENT_HI));
+
+ regdump->tiler_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_PRESENT_LO));
+ regdump->tiler_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(TILER_PRESENT_HI));
+
+ regdump->l2_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_PRESENT_LO));
+ regdump->l2_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L2_PRESENT_HI));
+
+ regdump->l3_present_lo = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_PRESENT_LO));
+ regdump->l3_present_hi = kbase_os_reg_read(kbdev, GPU_CONTROL_REG(L3_PRESENT_HI));
+}
+
+STATIC void kbase_gpuprops_construct_coherent_groups(base_gpu_props * const props)
+{
+ struct mali_base_gpu_coherent_group *current_group;
+ u64 group_present;
+ u64 group_mask;
+ u64 first_set, first_set_prev;
+ u32 num_groups = 0;
+
+ KBASE_DEBUG_ASSERT(NULL != props);
+
+ props->coherency_info.coherency = props->raw_props.mem_features;
+ props->coherency_info.num_core_groups = hweight64(props->raw_props.l2_present);
+
+ if (props->coherency_info.coherency & GROUPS_L3_COHERENT) {
+ /* Group is l3 coherent */
+ group_present = props->raw_props.l3_present;
+ } else if (props->coherency_info.coherency & GROUPS_L2_COHERENT) {
+ /* Group is l2 coherent */
+ group_present = props->raw_props.l2_present;
+ } else {
+ /* Group is l1 coherent */
+ group_present = props->raw_props.shader_present;
+ }
+
+ /*
+ * The coherent group mask can be computed from the l2/l3 present
+ * register.
+ *
+ * For the coherent group n:
+ * group_mask[n] = (first_set[n] - 1) & ~(first_set[n-1] - 1)
+ * where first_set is group_present with only its nth set-bit kept
+ * (i.e. the position from where a new group starts).
+ *
+ * For instance if the groups are l2 coherent and l2_present=0x0..01111:
+ * The first mask is:
+ * group_mask[1] = (first_set[1] - 1) & ~(first_set[0] - 1)
+ * = (0x0..010 - 1) & ~(0x0..01 - 1)
+ * = 0x0..00f
+ * The second mask is:
+ * group_mask[2] = (first_set[2] - 1) & ~(first_set[1] - 1)
+ * = (0x0..100 - 1) & ~(0x0..010 - 1)
+ * = 0x0..0f0
+ * And so on until all the bits from group_present have been cleared
+ * (i.e. there is no group left).
+ */
+
+ current_group = props->coherency_info.group;
+ first_set = group_present & ~(group_present - 1);
+
+ while (group_present != 0 && num_groups < BASE_MAX_COHERENT_GROUPS) {
+ group_present -= first_set; /* Clear the current group bit */
+ first_set_prev = first_set;
+
+ first_set = group_present & ~(group_present - 1);
+ group_mask = (first_set - 1) & ~(first_set_prev - 1);
+
+ /* Populate the coherent_group structure for each group */
+ current_group->core_mask = group_mask & props->raw_props.shader_present;
+ current_group->num_cores = hweight64(current_group->core_mask);
+
+ num_groups++;
+ current_group++;
+ }
+
+ if (group_present != 0)
+ KBASE_DEBUG_PRINT_WARN(KBASE_CORE, "Too many coherent groups (keeping only %d groups).\n", BASE_MAX_COHERENT_GROUPS);
+
+ props->coherency_info.num_groups = num_groups;
+}
+
+/**
+ * @brief Get the GPU configuration
+ *
+ * Fill the base_gpu_props structure with values from the GPU configuration registers.
+ * Only the raw properties are filled in this function
+ *
+ * @param gpu_props The base_gpu_props structure
+ * @param kbdev The kbase_device structure for the device
+ */
+static void kbase_gpuprops_get_props(base_gpu_props * const gpu_props, kbase_device *kbdev)
+{
+ kbase_gpuprops_regdump regdump;
+ int i;
+
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+ KBASE_DEBUG_ASSERT(NULL != gpu_props);
+
+ /* Dump relevant registers */
+ kbase_gpuprops_dump_registers(kbdev, &regdump);
+
+ gpu_props->raw_props.gpu_id = regdump.gpu_id;
+ gpu_props->raw_props.tiler_features = regdump.tiler_features;
+ gpu_props->raw_props.mem_features = regdump.mem_features;
+ gpu_props->raw_props.mmu_features = regdump.mmu_features;
+ gpu_props->raw_props.l2_features = regdump.l2_features;
+ gpu_props->raw_props.l3_features = regdump.l3_features;
+
+ gpu_props->raw_props.as_present = regdump.as_present;
+ gpu_props->raw_props.js_present = regdump.js_present;
+ gpu_props->raw_props.shader_present = ((u64) regdump.shader_present_hi << 32) + regdump.shader_present_lo;
+ gpu_props->raw_props.tiler_present = ((u64) regdump.tiler_present_hi << 32) + regdump.tiler_present_lo;
+ gpu_props->raw_props.l2_present = ((u64) regdump.l2_present_hi << 32) + regdump.l2_present_lo;
+ gpu_props->raw_props.l3_present = ((u64) regdump.l3_present_hi << 32) + regdump.l3_present_lo;
+
+ for (i = 0; i < MIDG_MAX_JOB_SLOTS; i++)
+ gpu_props->raw_props.js_features[i] = regdump.js_features[i];
+
+ for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++)
+ gpu_props->raw_props.texture_features[i] = regdump.texture_features[i];
+
+ gpu_props->raw_props.thread_max_barrier_size = regdump.thread_max_barrier_size;
+ gpu_props->raw_props.thread_max_threads = regdump.thread_max_threads;
+ gpu_props->raw_props.thread_max_workgroup_size = regdump.thread_max_workgroup_size;
+ gpu_props->raw_props.thread_features = regdump.thread_features;
+}
+
+/**
+ * @brief Calculate the derived properties
+ *
+ * Fill the base_gpu_props structure with values derived from the GPU configuration registers
+ *
+ * @param gpu_props The base_gpu_props structure
+ * @param kbdev The kbase_device structure for the device
+ */
+static void kbase_gpuprops_calculate_props(base_gpu_props * const gpu_props, kbase_device *kbdev)
+{
+ int i;
+
+ /* Populate the base_gpu_props structure */
+ gpu_props->core_props.version_status = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 0U, 4);
+ gpu_props->core_props.minor_revision = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 4U, 8);
+ gpu_props->core_props.major_revision = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 12U, 4);
+ gpu_props->core_props.product_id = KBASE_UBFX32(gpu_props->raw_props.gpu_id, 16U, 16);
+ gpu_props->core_props.log2_program_counter_size = KBASE_GPU_PC_SIZE_LOG2;
+ gpu_props->core_props.gpu_available_memory_size = totalram_pages << PAGE_SHIFT;
+
+ for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++)
+ gpu_props->core_props.texture_features[i] = gpu_props->raw_props.texture_features[i];
+
+ gpu_props->l2_props.log2_line_size = KBASE_UBFX32(gpu_props->raw_props.l2_features, 0U, 8);
+ gpu_props->l2_props.log2_cache_size = KBASE_UBFX32(gpu_props->raw_props.l2_features, 16U, 8);
+ if (gpu_props->core_props.product_id == GPU_ID_PI_T75X) {
+ gpu_props->l2_props.num_l2_slices = KBASE_UBFX32(gpu_props->raw_props.mem_features, 8U, 4) + 1;
+ } else {
+ gpu_props->l2_props.num_l2_slices = 1;
+ }
+
+ gpu_props->l3_props.log2_line_size = KBASE_UBFX32(gpu_props->raw_props.l3_features, 0U, 8);
+ gpu_props->l3_props.log2_cache_size = KBASE_UBFX32(gpu_props->raw_props.l3_features, 16U, 8);
+
+ gpu_props->tiler_props.bin_size_bytes = 1 << KBASE_UBFX32(gpu_props->raw_props.tiler_features, 0U, 6);
+ gpu_props->tiler_props.max_active_levels = KBASE_UBFX32(gpu_props->raw_props.tiler_features, 8U, 4);
+
+ gpu_props->thread_props.max_registers = KBASE_UBFX32(gpu_props->raw_props.thread_features, 0U, 16);
+ gpu_props->thread_props.max_task_queue = KBASE_UBFX32(gpu_props->raw_props.thread_features, 16U, 8);
+ gpu_props->thread_props.max_thread_group_split = KBASE_UBFX32(gpu_props->raw_props.thread_features, 24U, 6);
+ gpu_props->thread_props.impl_tech = KBASE_UBFX32(gpu_props->raw_props.thread_features, 30U, 2);
+
+ /* Initialize the coherent_group structure for each group */
+ kbase_gpuprops_construct_coherent_groups(gpu_props);
+}
+
+void kbase_gpuprops_set(kbase_device *kbdev)
+{
+ kbase_gpu_props *gpu_props;
+ struct midg_raw_gpu_props *raw;
+
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+ gpu_props = &kbdev->gpu_props;
+ raw = &gpu_props->props.raw_props;
+
+ /* Initialize the base_gpu_props structure from the hardware */
+ kbase_gpuprops_get_props(&gpu_props->props, kbdev);
+
+ /* Populate the derived properties */
+ kbase_gpuprops_calculate_props(&gpu_props->props, kbdev);
+
+ /* Populate kbase-only fields */
+ gpu_props->l2_props.associativity = KBASE_UBFX32(raw->l2_features, 8U, 8);
+ gpu_props->l2_props.external_bus_width = KBASE_UBFX32(raw->l2_features, 24U, 8);
+
+ gpu_props->l3_props.associativity = KBASE_UBFX32(raw->l3_features, 8U, 8);
+ gpu_props->l3_props.external_bus_width = KBASE_UBFX32(raw->l3_features, 24U, 8);
+
+ gpu_props->mem.core_group = KBASE_UBFX32(raw->mem_features, 0U, 1);
+ gpu_props->mem.supergroup = KBASE_UBFX32(raw->mem_features, 1U, 1);
+
+ gpu_props->mmu.va_bits = KBASE_UBFX32(raw->mmu_features, 0U, 8);
+ gpu_props->mmu.pa_bits = KBASE_UBFX32(raw->mmu_features, 8U, 8);
+
+ gpu_props->num_cores = hweight64(raw->shader_present);
+ gpu_props->num_core_groups = hweight64(raw->l2_present);
+ gpu_props->num_supergroups = hweight64(raw->l3_present);
+ gpu_props->num_address_spaces = hweight32(raw->as_present);
+ gpu_props->num_job_slots = hweight32(raw->js_present);
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops.h
new file mode 100755
index 00000000000..b00168c73c8
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_gpuprops.h
+ * Base kernel property query APIs
+ */
+
+#ifndef _KBASE_GPUPROPS_H_
+#define _KBASE_GPUPROPS_H_
+
+#include "mali_kbase_gpuprops_types.h"
+
+/* Forward definition - see mali_kbase.h */
+struct kbase_device;
+
+/**
+ * @brief Set up Kbase GPU properties.
+ *
+ * Set up Kbase GPU properties with information from the GPU registers
+ *
+ * @param kbdev The kbase_device structure for the device
+ */
+void kbase_gpuprops_set(struct kbase_device *kbdev);
+
+/**
+ * @brief Provide GPU properties to userside through UKU call.
+ *
+ * Fill the kbase_uk_gpuprops with values from GPU configuration registers.
+ *
+ * @param kctx The kbase_context structure
+ * @param kbase_props A copy of the kbase_uk_gpuprops structure from userspace
+ *
+ * @return MALI_ERROR_NONE on success. Any other value indicates failure.
+ */
+mali_error kbase_gpuprops_uk_get_props(kbase_context *kctx, kbase_uk_gpuprops * const kbase_props);
+
+#endif /* _KBASE_GPUPROPS_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops_types.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops_types.h
new file mode 100755
index 00000000000..3f36c63b820
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_gpuprops_types.h
@@ -0,0 +1,101 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_gpuprops_types.h
+ * Base kernel property query APIs
+ */
+
+#ifndef _KBASE_GPUPROPS_TYPES_H_
+#define _KBASE_GPUPROPS_TYPES_H_
+
+#include <kbase/mali_base_kernel.h>
+
+#define KBASE_GPU_SPEED_MHZ 123
+#define KBASE_GPU_PC_SIZE_LOG2 16U
+
+typedef struct kbase_gpuprops_regdump {
+ u32 gpu_id;
+ u32 l2_features;
+ u32 l3_features;
+ u32 tiler_features;
+ u32 mem_features;
+ u32 mmu_features;
+ u32 as_present;
+ u32 js_present;
+
+ u32 js_features[MIDG_MAX_JOB_SLOTS];
+
+ u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS];
+
+ u32 shader_present_lo;
+ u32 shader_present_hi;
+
+ u32 tiler_present_lo;
+ u32 tiler_present_hi;
+
+ u32 l2_present_lo;
+ u32 l2_present_hi;
+
+ u32 l3_present_lo;
+ u32 l3_present_hi;
+
+ u32 thread_max_threads;
+ u32 thread_max_workgroup_size;
+ u32 thread_max_barrier_size;
+ u32 thread_features;
+} kbase_gpuprops_regdump;
+
+typedef struct kbase_gpu_cache_props {
+ u8 associativity;
+ u8 external_bus_width;
+} kbase_gpu_cache_props;
+
+typedef struct kbase_gpu_mem_props {
+ u8 core_group;
+ u8 supergroup;
+} kbase_gpu_mem_props;
+
+typedef struct kbase_gpu_mmu_props {
+ u8 va_bits;
+ u8 pa_bits;
+} kbase_gpu_mmu_props;
+
+typedef struct mali_kbase_gpu_props {
+ /* kernel-only properties */
+ u8 num_cores;
+ u8 num_core_groups;
+ u8 num_supergroups;
+ u8 num_address_spaces;
+ u8 num_job_slots;
+
+ kbase_gpu_cache_props l2_props;
+ kbase_gpu_cache_props l3_props;
+
+ kbase_gpu_mem_props mem;
+ kbase_gpu_mmu_props mmu;
+
+ /**
+ * Implementation specific irq throttle value (us), should be adjusted during integration.
+ */
+ int irq_throttle_time_us;
+
+ /* Properties shared with userspace */
+ base_gpu_props props;
+} kbase_gpu_props;
+
+#endif /* _KBASE_GPUPROPS_TYPES_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_hw.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_hw.c
new file mode 100755
index 00000000000..b9e6a8a4594
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_hw.c
@@ -0,0 +1,84 @@
+/*
+ *
+ * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file
+ * Run-time work-arounds helpers
+ */
+
+#include <kbase/mali_base_hwconfig.h>
+#include <kbase/src/common/mali_midg_regmap.h>
+#include "mali_kbase.h"
+#include "mali_kbase_hw.h"
+
+mali_error kbase_hw_set_issues_mask(kbase_device *kbdev)
+{
+ const base_hw_issue *issues;
+ u32 gpu_id;
+
+ gpu_id = kbdev->gpu_props.props.raw_props.gpu_id;
+
+ switch (gpu_id) {
+ case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_15DEV0):
+ issues = base_hw_issues_t60x_r0p0_15dev0;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 0, GPU_ID_S_EAC):
+ issues = base_hw_issues_t60x_r0p0_eac;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T60X, 0, 1, 0):
+ issues = base_hw_issues_t60x_r0p1;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T65X, 0, 1, 0):
+ issues = base_hw_issues_t65x_r0p1;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T62X, 0, 0, 0):
+ case GPU_ID_MAKE(GPU_ID_PI_T62X, 0, 0, 1):
+ issues = base_hw_issues_t62x_r0p0;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T62X, 0, 1, 0):
+ issues = base_hw_issues_t62x_r0p1;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 0):
+ case GPU_ID_MAKE(GPU_ID_PI_T62X, 1, 0, 1):
+ issues = base_hw_issues_t62x_r1p0;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T67X, 0, 0, 0):
+ case GPU_ID_MAKE(GPU_ID_PI_T67X, 0, 0, 1):
+ issues = base_hw_issues_t67x_r0p0;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T67X, 0, 1, 0):
+ issues = base_hw_issues_t67x_r0p1;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T67X, 1, 0, 0):
+ case GPU_ID_MAKE(GPU_ID_PI_T67X, 1, 0, 1):
+ issues = base_hw_issues_t67x_r1p0;
+ break;
+ case GPU_ID_MAKE(GPU_ID_PI_T75X, 0, 0, 0):
+ issues = base_hw_issues_t75x_r0p0;
+ break;
+ default:
+ KBASE_DEBUG_PRINT_ERROR(KBASE_CORE, "Unknown GPU ID %x", gpu_id);
+ return MALI_ERROR_FUNCTION_FAILED;
+ }
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_CORE, "GPU identified as 0x%04x r%dp%d status %d", (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >> GPU_ID_VERSION_PRODUCT_ID_SHIFT, (gpu_id & GPU_ID_VERSION_MAJOR) >> GPU_ID_VERSION_MAJOR_SHIFT, (gpu_id & GPU_ID_VERSION_MINOR) >> GPU_ID_VERSION_MINOR_SHIFT, (gpu_id & GPU_ID_VERSION_STATUS) >> GPU_ID_VERSION_STATUS_SHIFT);
+
+ for (; *issues != BASE_HW_ISSUE_END; issues++)
+ set_bit(*issues, &kbdev->hw_issues_mask[0]);
+
+ return MALI_ERROR_NONE;
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_hw.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_hw.h
new file mode 100755
index 00000000000..6de1953c298
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_hw.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file
+ * Run-time work-arounds helpers
+ */
+
+#ifndef _KBASE_HW_H_
+#define _KBASE_HW_H_
+
+#include "mali_kbase_defs.h"
+
+/**
+ * @brief Tell whether a work-around should be enabled
+ */
+#define kbase_hw_has_issue(kbdev, issue)\
+ test_bit(issue, &(kbdev)->hw_issues_mask[0])
+
+/**
+ * @brief Set the HW issues mask depending on the GPU ID
+ */
+mali_error kbase_hw_set_issues_mask(kbase_device *kbdev);
+
+#endif /* _KBASE_HW_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_instr.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_instr.c
new file mode 100755
index 00000000000..484482065ae
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_instr.c
@@ -0,0 +1,616 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_instr.c
+ * Base kernel instrumentation APIs.
+ */
+
+#include <kbase/src/common/mali_kbase.h>
+#include <kbase/src/common/mali_midg_regmap.h>
+
+/**
+ * @brief Issue Cache Clean & Invalidate command to hardware
+ */
+static void kbasep_instr_hwcnt_cacheclean(kbase_device *kbdev)
+{
+ unsigned long flags;
+ unsigned long pm_flags;
+ u32 irq_mask;
+
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ /* Wait for any reset to complete */
+ while (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) {
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ wait_event(kbdev->hwcnt.cache_clean_wait,
+ kbdev->hwcnt.state != KBASE_INSTR_STATE_RESETTING);
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ }
+ KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_REQUEST_CLEAN);
+
+ /* Enable interrupt */
+ spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags);
+ irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask | CLEAN_CACHES_COMPLETED, NULL);
+ spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags);
+
+ /* clean&invalidate the caches so we're sure the mmu tables for the dump buffer is valid */
+ KBASE_TRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, NULL, 0u, 0);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CLEAN_INV_CACHES, NULL);
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_CLEANING;
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+}
+
+STATIC mali_error kbase_instr_hwcnt_enable_internal(kbase_device *kbdev, kbase_context *kctx, kbase_uk_hwcnt_setup *setup)
+{
+ unsigned long flags, pm_flags;
+ mali_error err = MALI_ERROR_FUNCTION_FAILED;
+ kbasep_js_device_data *js_devdata;
+ u32 irq_mask;
+ int ret;
+ u64 shader_cores_needed;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+ KBASE_DEBUG_ASSERT(NULL != setup);
+ KBASE_DEBUG_ASSERT(NULL == kbdev->hwcnt.suspended_kctx);
+
+ shader_cores_needed = kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER);
+
+ js_devdata = &kbdev->js_data;
+
+ /* alignment failure */
+ if ((setup->dump_buffer == 0ULL) || (setup->dump_buffer & (2048 - 1)))
+ goto out_err;
+
+ /* Override core availability policy to ensure all cores are available */
+ kbase_pm_ca_instr_enable(kbdev);
+
+ /* Mark the context as active so the GPU is kept turned on */
+ /* A suspend won't happen here, because we're in a syscall from a userspace
+ * thread. */
+ kbase_pm_context_active(kbdev);
+
+ /* Request the cores early on synchronously - we'll release them on any errors
+ * (e.g. instrumentation already active) */
+ kbase_pm_request_cores_sync(kbdev, MALI_TRUE, shader_cores_needed);
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) {
+ /* GPU is being reset */
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0);
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ }
+
+ if (kbdev->hwcnt.state != KBASE_INSTR_STATE_DISABLED) {
+ /* Instrumentation is already enabled */
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ goto out_unrequest_cores;
+ }
+
+ /* Enable interrupt */
+ spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags);
+ irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask | PRFCNT_SAMPLE_COMPLETED, NULL);
+ spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags);
+
+ /* In use, this context is the owner */
+ kbdev->hwcnt.kctx = kctx;
+ /* Remember the dump address so we can reprogram it later */
+ kbdev->hwcnt.addr = setup->dump_buffer;
+ /* Remember all the settings for suspend/resume */
+ if (&kbdev->hwcnt.suspended_state != setup)
+ memcpy(&kbdev->hwcnt.suspended_state, setup, sizeof(kbdev->hwcnt.suspended_state));
+
+ /* Request the clean */
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_REQUEST_CLEAN;
+ kbdev->hwcnt.triggered = 0;
+ /* Clean&invalidate the caches so we're sure the mmu tables for the dump buffer is valid */
+ ret = queue_work(kbdev->hwcnt.cache_clean_wq, &kbdev->hwcnt.cache_clean_work);
+ KBASE_DEBUG_ASSERT(ret);
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+
+ /* Wait for cacheclean to complete */
+ wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0);
+
+ KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE);
+
+ /* Schedule the context in */
+ kbasep_js_schedule_privileged_ctx(kbdev, kctx);
+
+ /* Configure */
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_OFF, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), setup->dump_buffer & 0xFFFFFFFF, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), setup->dump_buffer >> 32, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), setup->jm_bm, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), setup->shader_bm, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_L3_CACHE_EN), setup->l3_cache_bm, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), setup->mmu_l2_bm, kctx);
+ /* Due to PRLAM-8186 we need to disable the Tiler before we enable the HW counter dump. */
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186))
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), 0, kctx);
+ else
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), setup->tiler_bm, kctx);
+
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_MANUAL, kctx);
+
+ /* If HW has PRLAM-8186 we can now re-enable the tiler HW counters dump */
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186))
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), setup->tiler_bm, kctx);
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) {
+ /* GPU is being reset */
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0);
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ }
+
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE;
+ kbdev->hwcnt.triggered = 1;
+ wake_up(&kbdev->hwcnt.wait);
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+
+ err = MALI_ERROR_NONE;
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_CORE, "HW counters dumping set-up for context %p", kctx);
+ return err;
+ out_unrequest_cores:
+ kbase_pm_unrequest_cores(kbdev, MALI_TRUE, shader_cores_needed);
+ kbase_pm_context_idle(kbdev);
+ out_err:
+ return err;
+}
+
+/**
+ * @brief Enable HW counters collection
+ *
+ * Note: will wait for a cache clean to complete
+ */
+mali_error kbase_instr_hwcnt_enable(kbase_context *kctx, kbase_uk_hwcnt_setup *setup)
+{
+ kbase_device *kbdev;
+ mali_bool access_allowed;
+ kbdev = kctx->kbdev;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+ /* Determine if the calling task has access to this capability */
+ access_allowed = kbase_security_has_capability(kctx, KBASE_SEC_INSTR_HW_COUNTERS_COLLECT, KBASE_SEC_FLAG_NOAUDIT);
+ if (MALI_FALSE == access_allowed)
+ return MALI_ERROR_FUNCTION_FAILED;
+
+ return kbase_instr_hwcnt_enable_internal(kbdev, kctx, setup);
+}
+KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_enable)
+
+/**
+ * @brief Disable HW counters collection
+ *
+ * Note: might sleep, waiting for an ongoing dump to complete
+ */
+mali_error kbase_instr_hwcnt_disable(kbase_context *kctx)
+{
+ unsigned long flags, pm_flags;
+ mali_error err = MALI_ERROR_FUNCTION_FAILED;
+ u32 irq_mask;
+ kbase_device *kbdev;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+
+ while (1) {
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_DISABLED) {
+ /* Instrumentation is not enabled */
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ goto out;
+ }
+
+ if (kbdev->hwcnt.kctx != kctx) {
+ /* Instrumentation has been setup for another context */
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ goto out;
+ }
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE)
+ break;
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+
+ /* Ongoing dump/setup - wait for its completion */
+ wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0);
+
+ }
+
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_DISABLED;
+ kbdev->hwcnt.triggered = 0;
+
+ /* Disable interrupt */
+ spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags);
+ irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask & ~PRFCNT_SAMPLE_COMPLETED, NULL);
+ spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags);
+
+ /* Disable the counters */
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), 0, kctx);
+
+ kbdev->hwcnt.kctx = NULL;
+ kbdev->hwcnt.addr = 0ULL;
+
+ kbase_pm_ca_instr_disable(kbdev);
+
+ kbase_pm_unrequest_cores(kbdev, MALI_TRUE, kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER));
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+
+ /* Release the context. This had its own Power Manager Active reference */
+ kbasep_js_release_privileged_ctx(kbdev, kctx);
+
+ /* Also release our Power Manager Active reference */
+ kbase_pm_context_idle(kbdev);
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_CORE, "HW counters dumping disabled for context %p", kctx);
+
+ err = MALI_ERROR_NONE;
+
+ out:
+ return err;
+}
+KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_disable)
+
+/**
+ * @brief Configure HW counters collection
+ */
+mali_error kbase_instr_hwcnt_setup(kbase_context *kctx, kbase_uk_hwcnt_setup *setup)
+{
+ mali_error err = MALI_ERROR_FUNCTION_FAILED;
+ kbase_device *kbdev;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+
+ if (NULL == setup) {
+ /* Bad parameter - abort */
+ goto out;
+ }
+
+ if (setup->dump_buffer != 0ULL) {
+ /* Enable HW counters */
+ err = kbase_instr_hwcnt_enable(kctx, setup);
+ } else {
+ /* Disable HW counters */
+ err = kbase_instr_hwcnt_disable(kctx);
+ }
+
+ out:
+ return err;
+}
+
+/**
+ * @brief Issue Dump command to hardware
+ *
+ * Notes:
+ * - does not sleep
+ */
+mali_error kbase_instr_hwcnt_dump_irq(kbase_context *kctx)
+{
+ unsigned long flags;
+ mali_error err = MALI_ERROR_FUNCTION_FAILED;
+ kbase_device *kbdev;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+
+ if (kbdev->hwcnt.kctx != kctx) {
+ /* The instrumentation has been setup for another context */
+ goto unlock;
+ }
+
+ if (kbdev->hwcnt.state != KBASE_INSTR_STATE_IDLE) {
+ /* HW counters are disabled or another dump is ongoing, or we're resetting */
+ goto unlock;
+ }
+
+ kbdev->hwcnt.triggered = 0;
+
+ /* Mark that we're dumping - the PF handler can signal that we faulted */
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_DUMPING;
+
+ /* Reconfigure the dump address */
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), kbdev->hwcnt.addr & 0xFFFFFFFF, NULL);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), kbdev->hwcnt.addr >> 32, NULL);
+
+ /* Start dumping */
+ KBASE_TRACE_ADD(kbdev, CORE_GPU_PRFCNT_SAMPLE, NULL, NULL, kbdev->hwcnt.addr, 0);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_PRFCNT_SAMPLE, kctx);
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_CORE, "HW counters dumping done for context %p", kctx);
+
+ err = MALI_ERROR_NONE;
+
+ unlock:
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ return err;
+}
+KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_irq)
+
+/**
+ * @brief Tell whether the HW counters dump has completed
+ *
+ * Notes:
+ * - does not sleep
+ * - success will be set to MALI_TRUE if the dump succeeded or
+ * MALI_FALSE on failure
+ */
+mali_bool kbase_instr_hwcnt_dump_complete(kbase_context *kctx, mali_bool * const success)
+{
+ unsigned long flags;
+ mali_bool complete = MALI_FALSE;
+ kbase_device *kbdev;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+ KBASE_DEBUG_ASSERT(NULL != success);
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE) {
+ *success = MALI_TRUE;
+ complete = MALI_TRUE;
+ } else if (kbdev->hwcnt.state == KBASE_INSTR_STATE_FAULT) {
+ *success = MALI_FALSE;
+ complete = MALI_TRUE;
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE;
+ }
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+
+ return complete;
+}
+KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_complete)
+
+/**
+ * @brief Issue Dump command to hardware and wait for completion
+ */
+mali_error kbase_instr_hwcnt_dump(kbase_context *kctx)
+{
+ unsigned long flags;
+ mali_error err = MALI_ERROR_FUNCTION_FAILED;
+ kbase_device *kbdev;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+
+ err = kbase_instr_hwcnt_dump_irq(kctx);
+ if (MALI_ERROR_NONE != err) {
+ /* Can't dump HW counters */
+ goto out;
+ }
+
+ /* Wait for dump & cacheclean to complete */
+ wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0);
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) {
+ /* GPU is being reset */
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0);
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ }
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_FAULT) {
+ err = MALI_ERROR_FUNCTION_FAILED;
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE;
+ } else {
+ /* Dump done */
+ KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_IDLE);
+ err = MALI_ERROR_NONE;
+ }
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ out:
+ return err;
+}
+KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump)
+
+/**
+ * @brief Clear the HW counters
+ */
+mali_error kbase_instr_hwcnt_clear(kbase_context *kctx)
+{
+ unsigned long flags;
+ mali_error err = MALI_ERROR_FUNCTION_FAILED;
+ kbase_device *kbdev;
+
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) {
+ /* GPU is being reset */
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0);
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ }
+
+ /* Check it's the context previously set up and we're not already dumping */
+ if (kbdev->hwcnt.kctx != kctx || kbdev->hwcnt.state != KBASE_INSTR_STATE_IDLE)
+ goto out;
+
+ /* Clear the counters */
+ KBASE_TRACE_ADD(kbdev, CORE_GPU_PRFCNT_CLEAR, NULL, NULL, 0u, 0);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_PRFCNT_CLEAR, kctx);
+
+ err = MALI_ERROR_NONE;
+
+ out:
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ return err;
+}
+KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_clear)
+
+/**
+ * Workqueue for handling cache cleaning
+ */
+void kbasep_cache_clean_worker(struct work_struct *data)
+{
+ kbase_device *kbdev;
+ unsigned long flags;
+
+ kbdev = container_of(data, kbase_device, hwcnt.cache_clean_work);
+
+ mutex_lock(&kbdev->cacheclean_lock);
+ kbasep_instr_hwcnt_cacheclean(kbdev);
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ /* Wait for our condition, and any reset to complete */
+ while (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING
+ || kbdev->hwcnt.state == KBASE_INSTR_STATE_CLEANING) {
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ wait_event(kbdev->hwcnt.cache_clean_wait,
+ (kbdev->hwcnt.state != KBASE_INSTR_STATE_RESETTING
+ && kbdev->hwcnt.state != KBASE_INSTR_STATE_CLEANING));
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ }
+ KBASE_DEBUG_ASSERT(kbdev->hwcnt.state == KBASE_INSTR_STATE_CLEANED);
+
+ /* All finished and idle */
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE;
+ kbdev->hwcnt.triggered = 1;
+ wake_up(&kbdev->hwcnt.wait);
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ mutex_unlock(&kbdev->cacheclean_lock);
+}
+
+/**
+ * @brief Dump complete interrupt received
+ */
+void kbase_instr_hwcnt_sample_done(kbase_device *kbdev)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_FAULT) {
+ kbdev->hwcnt.triggered = 1;
+ wake_up(&kbdev->hwcnt.wait);
+ } else if (kbdev->hwcnt.state == KBASE_INSTR_STATE_DUMPING) {
+ int ret;
+ /* Always clean and invalidate the cache after a successful dump */
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_REQUEST_CLEAN;
+ ret = queue_work(kbdev->hwcnt.cache_clean_wq, &kbdev->hwcnt.cache_clean_work);
+ KBASE_DEBUG_ASSERT(ret);
+ }
+ /* NOTE: In the state KBASE_INSTR_STATE_RESETTING, We're in a reset,
+ * and the instrumentation state hasn't been restored yet -
+ * kbasep_reset_timeout_worker() will do the rest of the work */
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+}
+
+/**
+ * @brief Cache clean interrupt received
+ */
+void kbase_clean_caches_done(kbase_device *kbdev)
+{
+ u32 irq_mask;
+
+ if (kbdev->hwcnt.state != KBASE_INSTR_STATE_DISABLED) {
+ unsigned long flags;
+ unsigned long pm_flags;
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ /* Disable interrupt */
+ spin_lock_irqsave(&kbdev->pm.power_change_lock, pm_flags);
+ irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), NULL);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask & ~CLEAN_CACHES_COMPLETED, NULL);
+ spin_unlock_irqrestore(&kbdev->pm.power_change_lock, pm_flags);
+
+ /* Wakeup... */
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_CLEANING) {
+ /* Only wake if we weren't resetting */
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_CLEANED;
+ wake_up(&kbdev->hwcnt.cache_clean_wait);
+ }
+ /* NOTE: In the state KBASE_INSTR_STATE_RESETTING, We're in a reset,
+ * and the instrumentation state hasn't been restored yet -
+ * kbasep_reset_timeout_worker() will do the rest of the work */
+
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ }
+}
+
+
+/* Disable instrumentation and wait for any existing dump to complete
+ * It's assumed that there's only one privileged context
+ * Safe to do this without lock when doing an OS suspend, because it only
+ * changes in response to user-space IOCTLs */
+void kbase_instr_hwcnt_suspend(kbase_device *kbdev)
+{
+ kbase_context *kctx;
+ KBASE_DEBUG_ASSERT(kbdev);
+ KBASE_DEBUG_ASSERT(!kbdev->hwcnt.suspended_kctx);
+
+ kctx = kbdev->hwcnt.kctx;
+ kbdev->hwcnt.suspended_kctx = kctx;
+
+ /* Relevant state was saved into hwcnt.suspended_state when enabling the
+ * counters */
+
+ if (kctx)
+ {
+ KBASE_DEBUG_ASSERT(kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED);
+ kbase_instr_hwcnt_disable(kctx);
+ }
+}
+
+void kbase_instr_hwcnt_resume(kbase_device *kbdev)
+{
+ kbase_context *kctx;
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ kctx = kbdev->hwcnt.suspended_kctx;
+ kbdev->hwcnt.suspended_kctx = NULL;
+
+ if (kctx)
+ {
+ mali_error err;
+ err = kbase_instr_hwcnt_enable_internal(kbdev, kctx, &kbdev->hwcnt.suspended_state);
+ WARN(err != MALI_ERROR_NONE,
+ "Failed to restore instrumented hardware counters on resume\n");
+ }
+}
+
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jd.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jd.c
new file mode 100755
index 00000000000..f1961d2c511
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jd.c
@@ -0,0 +1,1438 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#if defined(CONFIG_DMA_SHARED_BUFFER)
+#include <linux/dma-buf.h>
+#endif /* defined(CONFIG_DMA_SHARED_BUFFER) */
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+#include <kbase/src/common/mali_kbase.h>
+#include <kbase/src/common/mali_kbase_uku.h>
+#include <kbase/src/common/mali_kbase_js_affinity.h>
+#include <kbase/src/common/mali_kbase_10969_workaround.h>
+#ifdef CONFIG_UMP
+#include <linux/ump.h>
+#endif /* CONFIG_UMP */
+
+#define beenthere(f, a...) KBASE_DEBUG_PRINT_INFO(KBASE_JD, "%s:" f, __func__, ##a)
+
+/*
+ * This is the kernel side of the API. Only entry points are:
+ * - kbase_jd_submit(): Called from userspace to submit a single bag
+ * - kbase_jd_done(): Called from interrupt context to track the
+ * completion of a job.
+ * Callouts:
+ * - to the job manager (enqueue a job)
+ * - to the event subsystem (signals the completion/failure of bag/job-chains).
+ */
+
+static void *get_compat_pointer(const kbase_pointer *p)
+{
+#ifdef CONFIG_COMPAT
+ if (is_compat_task())
+ return (void *)p->compat_value;
+ else
+#endif
+ return p->value;
+}
+
+/* Runs an atom, either by handing to the JS or by immediately running it in the case of soft-jobs
+ *
+ * Returns whether the JS needs a reschedule.
+ *
+ * Note that the caller must also check the atom status and
+ * if it is KBASE_JD_ATOM_STATE_COMPLETED must call jd_done_nolock
+ */
+static int jd_run_atom(kbase_jd_atom *katom)
+{
+ kbase_context *kctx = katom->kctx;
+ KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED);
+
+ if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) == BASE_JD_REQ_DEP) {
+ /* Dependency only atom */
+ katom->status = KBASE_JD_ATOM_STATE_COMPLETED;
+ return 0;
+ } else if (katom->core_req & BASE_JD_REQ_SOFT_JOB) {
+ /* Soft-job */
+ if (kbase_process_soft_job(katom) == 0) {
+ kbase_finish_soft_job(katom);
+ katom->status = KBASE_JD_ATOM_STATE_COMPLETED;
+ } else {
+ /* The job has not completed */
+ list_add_tail(&katom->dep_item[0], &kctx->waiting_soft_jobs);
+ }
+ return 0;
+ }
+ katom->status = KBASE_JD_ATOM_STATE_IN_JS;
+ /* Queue an action about whether we should try scheduling a context */
+ return kbasep_js_add_job(kctx, katom);
+}
+
+#ifdef CONFIG_KDS
+
+/* Add the katom to the kds waiting list.
+ * Atoms must be added to the waiting list after a successful call to kds_async_waitall.
+ * The caller must hold the kbase_jd_context.lock */
+
+static void kbase_jd_kds_waiters_add(kbase_jd_atom *katom)
+{
+ kbase_context *kctx;
+ KBASE_DEBUG_ASSERT(katom);
+
+ kctx = katom->kctx;
+
+ list_add_tail(&katom->node, &kctx->waiting_kds_resource);
+}
+
+/* Remove the katom from the kds waiting list.
+ * Atoms must be removed from the waiting list before a call to kds_resource_set_release_sync.
+ * The supplied katom must first have been added to the list with a call to kbase_jd_kds_waiters_add.
+ * The caller must hold the kbase_jd_context.lock */
+
+static void kbase_jd_kds_waiters_remove(kbase_jd_atom *katom)
+{
+ KBASE_DEBUG_ASSERT(katom);
+ list_del(&katom->node);
+}
+
+static void kds_dep_clear(void *callback_parameter, void *callback_extra_parameter)
+{
+ kbase_jd_atom *katom;
+ kbase_jd_context *ctx;
+ kbase_device *kbdev;
+
+ katom = (kbase_jd_atom *) callback_parameter;
+ KBASE_DEBUG_ASSERT(katom);
+ ctx = &katom->kctx->jctx;
+ kbdev = katom->kctx->kbdev;
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ mutex_lock(&ctx->lock);
+
+ /* KDS resource has already been satisfied (e.g. due to zapping) */
+ if (katom->kds_dep_satisfied)
+ goto out;
+
+ /* This atom's KDS dependency has now been met */
+ katom->kds_dep_satisfied = MALI_TRUE;
+
+ /* Check whether the atom's other dependencies were already met */
+ if (!katom->dep_atom[0] && !katom->dep_atom[1]) {
+ /* katom dep complete, attempt to run it */
+ mali_bool resched = MALI_FALSE;
+ resched = jd_run_atom(katom);
+
+ if (katom->status == KBASE_JD_ATOM_STATE_COMPLETED) {
+ /* The atom has already finished */
+ resched |= jd_done_nolock(katom);
+ }
+
+ if (resched)
+ kbasep_js_try_schedule_head_ctx(kbdev);
+ }
+ out:
+ mutex_unlock(&ctx->lock);
+}
+
+void kbase_cancel_kds_wait_job(kbase_jd_atom *katom)
+{
+ KBASE_DEBUG_ASSERT(katom);
+
+ /* Prevent job_done_nolock from being called twice on an atom when
+ * there is a race between job completion and cancellation */
+
+ if ( katom->status == KBASE_JD_ATOM_STATE_QUEUED ) {
+ /* Wait was cancelled - zap the atom */
+ katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
+ if (jd_done_nolock(katom)) {
+ kbasep_js_try_schedule_head_ctx( katom->kctx->kbdev );
+ }
+ }
+}
+#endif /* CONFIG_KDS */
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+static mali_error kbase_jd_umm_map(kbase_context *kctx, struct kbase_va_region *reg)
+{
+ struct sg_table *st;
+ struct scatterlist *s;
+ int i;
+ phys_addr_t *pa;
+ mali_error err;
+
+ KBASE_DEBUG_ASSERT(NULL == reg->imported_metadata.umm.st);
+ st = dma_buf_map_attachment(reg->imported_metadata.umm.dma_attachment, DMA_BIDIRECTIONAL);
+
+ if (IS_ERR_OR_NULL(st))
+ return MALI_ERROR_FUNCTION_FAILED;
+
+ /* save for later */
+ reg->imported_metadata.umm.st = st;
+
+ pa = kbase_get_phy_pages(reg);
+ KBASE_DEBUG_ASSERT(pa);
+
+ for_each_sg(st->sgl, s, st->nents, i) {
+ int j;
+ size_t pages = PFN_DOWN(sg_dma_len(s));
+
+ for (j = 0; j < pages; j++)
+ *pa++ = sg_dma_address(s) + (j << PAGE_SHIFT);
+ }
+
+ err = kbase_mmu_insert_pages(kctx, reg->start_pfn, kbase_get_phy_pages(reg), reg->nr_alloc_pages, reg->flags | KBASE_REG_GPU_WR | KBASE_REG_GPU_RD);
+
+ if (MALI_ERROR_NONE != err) {
+ dma_buf_unmap_attachment(reg->imported_metadata.umm.dma_attachment, reg->imported_metadata.umm.st, DMA_BIDIRECTIONAL);
+ reg->imported_metadata.umm.st = NULL;
+ }
+
+ return err;
+}
+
+static void kbase_jd_umm_unmap(kbase_context *kctx, struct kbase_va_region *reg)
+{
+ KBASE_DEBUG_ASSERT(kctx);
+ KBASE_DEBUG_ASSERT(reg);
+ KBASE_DEBUG_ASSERT(reg->imported_metadata.umm.dma_attachment);
+ KBASE_DEBUG_ASSERT(reg->imported_metadata.umm.st);
+ kbase_mmu_teardown_pages(kctx, reg->start_pfn, reg->nr_alloc_pages);
+ dma_buf_unmap_attachment(reg->imported_metadata.umm.dma_attachment, reg->imported_metadata.umm.st, DMA_BIDIRECTIONAL);
+ reg->imported_metadata.umm.st = NULL;
+}
+#endif /* CONFIG_DMA_SHARED_BUFFER */
+
+void kbase_jd_free_external_resources(kbase_jd_atom *katom)
+{
+#ifdef CONFIG_KDS
+ if (katom->kds_rset) {
+ kbase_jd_context * jctx = &katom->kctx->jctx;
+
+ /*
+ * As the atom is no longer waiting, remove it from
+ * the waiting list.
+ */
+
+ mutex_lock(&jctx->lock);
+ kbase_jd_kds_waiters_remove( katom );
+ mutex_unlock(&jctx->lock);
+
+ /* Release the kds resource or cancel if zapping */
+ kds_resource_set_release_sync(&katom->kds_rset);
+ }
+#endif /* CONFIG_KDS */
+}
+
+static void kbase_jd_post_external_resources(kbase_jd_atom *katom)
+{
+ KBASE_DEBUG_ASSERT(katom);
+ KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES);
+
+#ifdef CONFIG_KDS
+ /* Prevent the KDS resource from triggering the atom in case of zapping */
+ if (katom->kds_rset)
+ katom->kds_dep_satisfied = MALI_TRUE;
+#endif /* CONFIG_KDS */
+
+#if defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG)
+ /* Lock also used in debug mode just for lock order checking */
+ kbase_gpu_vm_lock(katom->kctx);
+#endif /* defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG) */
+ /* only roll back if extres is non-NULL */
+ if (katom->extres) {
+#ifdef CONFIG_DMA_SHARED_BUFFER
+ u32 res_no;
+ res_no = katom->nr_extres;
+ while (res_no-- > 0) {
+ base_external_resource *res;
+ kbase_va_region *reg;
+
+ res = &katom->extres[res_no];
+ reg = kbase_region_tracker_find_region_enclosing_address(katom->kctx, res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE);
+ /* if reg wasn't found then it has been freed while the job ran */
+ if (reg && reg->imported_type == BASE_TMEM_IMPORT_TYPE_UMM) {
+ /* last job using */
+ if (1 == reg->imported_metadata.umm.current_mapping_usage_count--)
+ kbase_jd_umm_unmap(katom->kctx, reg);
+ }
+ }
+#endif /* CONFIG_DMA_SHARED_BUFFER */
+ kfree(katom->extres);
+ katom->extres = NULL;
+ }
+#if defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG)
+ /* Lock also used in debug mode just for lock order checking */
+ kbase_gpu_vm_unlock(katom->kctx);
+#endif /* defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG) */
+}
+
+#if (defined(CONFIG_KDS) && defined(CONFIG_UMP)) || defined(CONFIG_DMA_SHARED_BUFFER_USES_KDS)
+static void add_kds_resource(struct kds_resource *kds_res, struct kds_resource **kds_resources, u32 *kds_res_count, unsigned long *kds_access_bitmap, mali_bool exclusive)
+{
+ u32 i;
+
+ for (i = 0; i < *kds_res_count; i++) {
+ /* Duplicate resource, ignore */
+ if (kds_resources[i] == kds_res)
+ return;
+ }
+
+ kds_resources[*kds_res_count] = kds_res;
+ if (exclusive)
+ set_bit(*kds_res_count, kds_access_bitmap);
+ (*kds_res_count)++;
+}
+#endif
+
+/*
+ * Set up external resources needed by this job.
+ *
+ * jctx.lock must be held when this is called.
+ */
+
+static mali_error kbase_jd_pre_external_resources(kbase_jd_atom *katom, const base_jd_atom_v2 *user_atom)
+{
+ mali_error err_ret_val = MALI_ERROR_FUNCTION_FAILED;
+ u32 res_no;
+#ifdef CONFIG_KDS
+ u32 kds_res_count = 0;
+ struct kds_resource **kds_resources = NULL;
+ unsigned long *kds_access_bitmap = NULL;
+#endif /* CONFIG_KDS */
+
+ KBASE_DEBUG_ASSERT(katom);
+ KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES);
+
+ /* no resources encoded, early out */
+ if (!katom->nr_extres)
+ return MALI_ERROR_FUNCTION_FAILED;
+
+ katom->extres = kmalloc(sizeof(base_external_resource) * katom->nr_extres, GFP_KERNEL);
+ if (NULL == katom->extres) {
+ err_ret_val = MALI_ERROR_OUT_OF_MEMORY;
+ goto early_err_out;
+ }
+
+ if (copy_from_user(katom->extres, get_compat_pointer(&user_atom->extres_list), sizeof(base_external_resource) * katom->nr_extres) != 0) {
+ err_ret_val = MALI_ERROR_FUNCTION_FAILED;
+ goto early_err_out;
+ }
+#ifdef CONFIG_KDS
+ /* assume we have to wait for all */
+ KBASE_DEBUG_ASSERT(0 != katom->nr_extres);
+ kds_resources = kmalloc(sizeof(struct kds_resource *) * katom->nr_extres, GFP_KERNEL);
+
+ if (NULL == kds_resources) {
+ err_ret_val = MALI_ERROR_OUT_OF_MEMORY;
+ goto early_err_out;
+ }
+
+ KBASE_DEBUG_ASSERT(0 != katom->nr_extres);
+ kds_access_bitmap = kzalloc(sizeof(unsigned long) * ((katom->nr_extres + BITS_PER_LONG - 1) / BITS_PER_LONG), GFP_KERNEL);
+
+ if (NULL == kds_access_bitmap) {
+ err_ret_val = MALI_ERROR_OUT_OF_MEMORY;
+ goto early_err_out;
+ }
+#endif /* CONFIG_KDS */
+
+#if defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG)
+ /* need to keep the GPU VM locked while we set up UMM buffers */
+ /* Lock also used in debug mode just for lock order checking */
+ kbase_gpu_vm_lock(katom->kctx);
+#endif /* defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG) */
+
+ for (res_no = 0; res_no < katom->nr_extres; res_no++) {
+ base_external_resource *res;
+ kbase_va_region *reg;
+
+ res = &katom->extres[res_no];
+ reg = kbase_region_tracker_find_region_enclosing_address(katom->kctx, res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE);
+ /* did we find a matching region object? */
+ if (NULL == reg) {
+ /* roll back */
+ goto failed_loop;
+ }
+
+ /* decide what needs to happen for this resource */
+ switch (reg->imported_type) {
+ case BASE_TMEM_IMPORT_TYPE_UMP:
+ {
+#if defined(CONFIG_KDS) && defined(CONFIG_UMP)
+ struct kds_resource *kds_res;
+ kds_res = ump_dd_kds_resource_get(reg->imported_metadata.ump_handle);
+ if (kds_res)
+ add_kds_resource(kds_res, kds_resources, &kds_res_count, kds_access_bitmap, katom->extres[res_no].ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE);
+#endif /*defined(CONFIG_KDS) && defined(CONFIG_UMP) */
+ break;
+ }
+#ifdef CONFIG_DMA_SHARED_BUFFER
+ case BASE_TMEM_IMPORT_TYPE_UMM:
+ {
+#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS
+ struct kds_resource *kds_res;
+ kds_res = get_dma_buf_kds_resource(reg->imported_metadata.umm.dma_buf);
+ if (kds_res)
+ add_kds_resource(kds_res, kds_resources, &kds_res_count, kds_access_bitmap, katom->extres[res_no].ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE);
+#endif
+ reg->imported_metadata.umm.current_mapping_usage_count++;
+ if (1 == reg->imported_metadata.umm.current_mapping_usage_count) {
+ /* use a local variable to not pollute err_ret_val
+ * with a potential success value as some other gotos depend
+ * on the default error code stored in err_ret_val */
+ mali_error tmp;
+ tmp = kbase_jd_umm_map(katom->kctx, reg);
+ if (MALI_ERROR_NONE != tmp) {
+ /* failed to map this buffer, roll back */
+ err_ret_val = tmp;
+ reg->imported_metadata.umm.current_mapping_usage_count--;
+ goto failed_loop;
+ }
+ }
+ break;
+ }
+#endif
+ default:
+ goto failed_loop;
+ }
+ }
+ /* successfully parsed the extres array */
+#if defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG)
+ /* drop the vm lock before we call into kds */
+ /* Lock also used in debug mode just for lock order checking */
+ kbase_gpu_vm_unlock(katom->kctx);
+#endif /* defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG) */
+
+#ifdef CONFIG_KDS
+ if (kds_res_count) {
+ int wait_failed;
+ /* We have resources to wait for with kds */
+ katom->kds_dep_satisfied = MALI_FALSE;
+
+ wait_failed = kds_async_waitall(&katom->kds_rset,
+ &katom->kctx->jctx.kds_cb,
+ katom,
+ NULL,
+ kds_res_count,
+ kds_access_bitmap,
+ kds_resources);
+ if (wait_failed) {
+ goto failed_kds_setup;
+ } else {
+ kbase_jd_kds_waiters_add( katom );
+ }
+ } else {
+ /* Nothing to wait for, so kds dep met */
+ katom->kds_dep_satisfied = MALI_TRUE;
+ }
+ kfree(kds_resources);
+ kfree(kds_access_bitmap);
+#endif /* CONFIG_KDS */
+
+ /* all done OK */
+ return MALI_ERROR_NONE;
+
+/* error handling section */
+
+#ifdef CONFIG_KDS
+ failed_kds_setup:
+
+#if defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG)
+ /* lock before we unmap */
+ /* Lock also used in debug mode just for lock order checking */
+ kbase_gpu_vm_lock(katom->kctx);
+#endif /* defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG) */
+#endif /* CONFIG_KDS */
+
+ failed_loop:
+#ifdef CONFIG_DMA_SHARED_BUFFER
+ /* undo the loop work */
+ while (res_no-- > 0) {
+ base_external_resource *res;
+ kbase_va_region *reg;
+
+ res = &katom->extres[res_no];
+ reg = kbase_region_tracker_find_region_enclosing_address(katom->kctx, res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE);
+ /* if reg wasn't found then it has been freed when we set up kds */
+ if (reg && reg->imported_type == BASE_TMEM_IMPORT_TYPE_UMM) {
+ reg->imported_metadata.umm.current_mapping_usage_count--;
+ if (0 == reg->imported_metadata.umm.current_mapping_usage_count)
+ kbase_jd_umm_unmap(katom->kctx, reg);
+ }
+ }
+#endif /* CONFIG_DMA_SHARED_BUFFER */
+#if defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG)
+ /* Lock also used in debug mode just for lock order checking */
+ kbase_gpu_vm_unlock(katom->kctx);
+#endif /* defined(CONFIG_DMA_SHARED_BUFFER) || defined(CONFIG_MALI_DEBUG) */
+
+ early_err_out:
+ kfree(katom->extres);
+ katom->extres = NULL;
+#ifdef CONFIG_KDS
+ kfree(kds_resources);
+ kfree(kds_access_bitmap);
+#endif /* CONFIG_KDS */
+ return err_ret_val;
+}
+
+STATIC INLINE void jd_resolve_dep(struct list_head *out_list, kbase_jd_atom *katom, u8 d)
+{
+ u8 other_d = !d;
+
+ while (!list_empty(&katom->dep_head[d])) {
+ kbase_jd_atom *dep_atom = list_entry(katom->dep_head[d].next, kbase_jd_atom, dep_item[d]);
+ list_del(katom->dep_head[d].next);
+
+ dep_atom->dep_atom[d] = NULL;
+
+ if (katom->event_code != BASE_JD_EVENT_DONE) {
+ /* Atom failed, so remove the other dependencies and immediately fail the atom */
+ if (dep_atom->dep_atom[other_d]) {
+ list_del(&dep_atom->dep_item[other_d]);
+ dep_atom->dep_atom[other_d] = NULL;
+ }
+#ifdef CONFIG_KDS
+ if (!dep_atom->kds_dep_satisfied) {
+ /* Just set kds_dep_satisfied to true. If the callback happens after this then it will early out and
+ * do nothing. If the callback doesn't happen then kbase_jd_post_external_resources will clean up
+ */
+ dep_atom->kds_dep_satisfied = MALI_TRUE;
+ }
+#endif
+
+ dep_atom->event_code = katom->event_code;
+ KBASE_DEBUG_ASSERT(dep_atom->status != KBASE_JD_ATOM_STATE_UNUSED);
+ dep_atom->status = KBASE_JD_ATOM_STATE_COMPLETED;
+
+ list_add(&dep_atom->dep_item[0], out_list);
+ } else if (!dep_atom->dep_atom[other_d]) {
+#ifdef CONFIG_KDS
+ if (dep_atom->kds_dep_satisfied)
+#endif
+ list_add(&dep_atom->dep_item[0], out_list);
+ }
+ }
+}
+
+KBASE_EXPORT_TEST_API(jd_resolve_dep)
+
+/*
+ * Perform the necessary handling of an atom that has finished running
+ * on the GPU.
+ *
+ * Note that if this is a soft-job that has had kbase_prepare_soft_job called on it then the caller
+ * is responsible for calling kbase_finish_soft_job *before* calling this function.
+ *
+ * The caller must hold the kbase_jd_context.lock.
+ */
+mali_bool jd_done_nolock(kbase_jd_atom *katom)
+{
+ struct kbase_context *kctx = katom->kctx;
+ kbase_device *kbdev = kctx->kbdev;
+ struct list_head completed_jobs;
+ struct list_head runnable_jobs;
+ mali_bool need_to_try_schedule_context = MALI_FALSE;
+ int i;
+
+ INIT_LIST_HEAD(&completed_jobs);
+ INIT_LIST_HEAD(&runnable_jobs);
+
+ KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED);
+
+ /* This is needed in case an atom is failed due to being invalid, this
+ * can happen *before* the jobs that the atom depends on have completed */
+ for (i = 0; i < 2; i++) {
+ if (katom->dep_atom[i]) {
+ list_del(&katom->dep_item[i]);
+ katom->dep_atom[i] = NULL;
+ }
+ }
+
+ /* With PRLAM-10817 the last tile of a fragment job being soft-stopped can fail with
+ * BASE_JD_EVENT_TILE_RANGE_FAULT.
+ *
+ * So here if the fragment job failed with TILE_RANGE_FAULT and it has been soft-stopped, then we promote the
+ * error code to BASE_JD_EVENT_DONE
+ */
+
+ if ( kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10817) && katom->event_code == BASE_JD_EVENT_TILE_RANGE_FAULT ) {
+ if ( ( katom->core_req & BASE_JD_REQ_FS ) && (katom->atom_flags & KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED) ) {
+ /* Promote the failure to job done */
+ katom->event_code = BASE_JD_EVENT_DONE;
+ katom->atom_flags = katom->atom_flags & (~KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED);
+ }
+ }
+
+ katom->status = KBASE_JD_ATOM_STATE_COMPLETED;
+ list_add_tail(&katom->dep_item[0], &completed_jobs);
+
+ while (!list_empty(&completed_jobs)) {
+ katom = list_entry(completed_jobs.prev, kbase_jd_atom, dep_item[0]);
+ list_del(completed_jobs.prev);
+
+ KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED);
+
+ for (i = 0; i < 2; i++)
+ jd_resolve_dep(&runnable_jobs, katom, i);
+
+ while (!list_empty(&runnable_jobs)) {
+ kbase_jd_atom *node = list_entry(runnable_jobs.prev, kbase_jd_atom, dep_item[0]);
+ list_del(runnable_jobs.prev);
+
+ KBASE_DEBUG_ASSERT(node->status != KBASE_JD_ATOM_STATE_UNUSED);
+
+ if (katom->event_code == BASE_JD_EVENT_DONE) {
+ need_to_try_schedule_context |= jd_run_atom(node);
+ } else {
+ node->event_code = katom->event_code;
+ node->status = KBASE_JD_ATOM_STATE_COMPLETED;
+
+ if (node->core_req & BASE_JD_REQ_SOFT_JOB) {
+ /* If this is a fence wait then remove it from the list of sync waiters. */
+ if ( BASE_JD_REQ_SOFT_FENCE_WAIT == node->core_req )
+ list_del(&node->dep_item[0]);
+
+ kbase_finish_soft_job(node);
+ }
+ }
+
+ if (node->status == KBASE_JD_ATOM_STATE_COMPLETED)
+ list_add_tail(&node->dep_item[0], &completed_jobs);
+ }
+
+ if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES)
+ kbase_jd_post_external_resources(katom);
+
+ kbase_event_post(kctx, katom);
+
+ /* Decrement and check the TOTAL number of jobs. This includes
+ * those not tracked by the scheduler: 'not ready to run' and
+ * 'dependency-only' jobs. */
+ if (--kctx->jctx.job_nr == 0)
+ wake_up(&kctx->jctx.zero_jobs_wait); /* All events are safely queued now, and we can signal any waiter
+ * that we've got no more jobs (so we can be safely terminated) */
+ }
+
+ return need_to_try_schedule_context;
+}
+
+KBASE_EXPORT_TEST_API(jd_done_nolock)
+
+#ifdef CONFIG_GPU_TRACEPOINTS
+enum {
+ CORE_REQ_DEP_ONLY,
+ CORE_REQ_SOFT,
+ CORE_REQ_COMPUTE,
+ CORE_REQ_FRAGMENT,
+ CORE_REQ_VERTEX,
+ CORE_REQ_TILER,
+ CORE_REQ_FRAGMENT_VERTEX,
+ CORE_REQ_FRAGMENT_VERTEX_TILER,
+ CORE_REQ_FRAGMENT_TILER,
+ CORE_REQ_VERTEX_TILER,
+ CORE_REQ_UNKNOWN
+};
+static const char * const core_req_strings[] = {
+ "Dependency Only Job",
+ "Soft Job",
+ "Compute Shader Job",
+ "Fragment Shader Job",
+ "Vertex/Geometry Shader Job",
+ "Tiler Job",
+ "Fragment Shader + Vertex/Geometry Shader Job",
+ "Fragment Shader + Vertex/Geometry Shader Job + Tiler Job",
+ "Fragment Shader + Tiler Job",
+ "Vertex/Geometry Shader Job + Tiler Job",
+ "Unknown Job"
+};
+static const char *kbasep_map_core_reqs_to_string(base_jd_core_req core_req)
+{
+ if (core_req & BASE_JD_REQ_SOFT_JOB)
+ return core_req_strings[CORE_REQ_SOFT];
+ if (core_req & BASE_JD_REQ_ONLY_COMPUTE)
+ return core_req_strings[CORE_REQ_COMPUTE];
+ switch (core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) {
+ case BASE_JD_REQ_DEP:
+ return core_req_strings[CORE_REQ_DEP_ONLY];
+ case BASE_JD_REQ_FS:
+ return core_req_strings[CORE_REQ_FRAGMENT];
+ case BASE_JD_REQ_CS:
+ return core_req_strings[CORE_REQ_VERTEX];
+ case BASE_JD_REQ_T:
+ return core_req_strings[CORE_REQ_TILER];
+ case (BASE_JD_REQ_FS | BASE_JD_REQ_CS):
+ return core_req_strings[CORE_REQ_FRAGMENT_VERTEX];
+ case (BASE_JD_REQ_FS | BASE_JD_REQ_T):
+ return core_req_strings[CORE_REQ_FRAGMENT_TILER];
+ case (BASE_JD_REQ_CS | BASE_JD_REQ_T):
+ return core_req_strings[CORE_REQ_VERTEX_TILER];
+ case (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T):
+ return core_req_strings[CORE_REQ_FRAGMENT_VERTEX_TILER];
+ }
+ return core_req_strings[CORE_REQ_UNKNOWN];
+}
+#endif
+
+static mali_bool jd_submit_atom(kbase_context *kctx, const base_jd_atom_v2 *user_atom)
+{
+ kbase_jd_context *jctx = &kctx->jctx;
+ kbase_jd_atom *katom;
+ base_jd_core_req core_req;
+ base_atom_id atom_number = user_atom->atom_number;
+ int queued = 0;
+ int i;
+ mali_bool ret;
+
+ katom = &jctx->atoms[atom_number];
+
+ mutex_lock(&jctx->lock);
+ while (katom->status != KBASE_JD_ATOM_STATE_UNUSED) {
+ /* Atom number is already in use, wait for the atom to complete */
+ mutex_unlock(&jctx->lock);
+
+ /* This thread will wait for the atom to complete. Due to thread scheduling we are not sure that
+ * the other thread that owns the atom will also schedule the context, so we force the scheduler
+ * to be active and hence eventually schedule this context at some point later.
+ */
+ kbasep_js_try_schedule_head_ctx(kctx->kbdev);
+ if (wait_event_killable(katom->completed, katom->status == KBASE_JD_ATOM_STATE_UNUSED)) {
+ /* We're being killed so the result code doesn't really matter */
+ return MALI_FALSE;
+ }
+ mutex_lock(&jctx->lock);
+ }
+
+ /* Update the TOTAL number of jobs. This includes those not tracked by
+ * the scheduler: 'not ready to run' and 'dependency-only' jobs. */
+ jctx->job_nr++;
+
+ core_req = user_atom->core_req;
+
+ katom->udata = user_atom->udata;
+ katom->kctx = kctx;
+ katom->nr_extres = user_atom->nr_extres;
+ katom->extres = NULL;
+ katom->device_nr = user_atom->device_nr;
+ katom->affinity = 0;
+ katom->jc = user_atom->jc;
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED;
+ katom->core_req = core_req;
+ katom->nice_prio = user_atom->prio;
+ katom->atom_flags = 0;
+
+#ifdef CONFIG_KDS
+ /* Start by assuming that the KDS dependencies are satisfied,
+ * kbase_jd_pre_external_resources will correct this if there are dependencies */
+ katom->kds_dep_satisfied = MALI_TRUE;
+ katom->kds_rset = NULL;
+#endif /* CONFIG_KDS */
+
+ /* Add dependencies */
+ for (i = 0; i < 2; i++) {
+ int dep_atom_number = user_atom->pre_dep[i];
+ katom->dep_atom[i] = NULL;
+ if (dep_atom_number) {
+ kbase_jd_atom *dep_atom = &jctx->atoms[dep_atom_number];
+
+ if (dep_atom->status == KBASE_JD_ATOM_STATE_UNUSED || dep_atom->status == KBASE_JD_ATOM_STATE_COMPLETED) {
+ if (dep_atom->event_code != BASE_JD_EVENT_DONE) {
+ if (i == 1 && katom->dep_atom[0]) {
+ /* Remove the previous dependency */
+ list_del(&katom->dep_item[0]);
+ katom->dep_atom[0] = NULL;
+ }
+ /* Atom has completed, propagate the error code if any */
+ katom->event_code = dep_atom->event_code;
+ katom->status = KBASE_JD_ATOM_STATE_QUEUED;
+ ret = jd_done_nolock(katom);
+ goto out;
+ }
+ } else {
+ /* Atom is in progress, add this atom to the list */
+ list_add_tail(&katom->dep_item[i], &dep_atom->dep_head[i]);
+ katom->dep_atom[i] = dep_atom;
+ queued = 1;
+ }
+ }
+ }
+
+ /* These must occur after the above loop to ensure that an atom that
+ * depends on a previous atom with the same number behaves as expected */
+ katom->event_code = BASE_JD_EVENT_DONE;
+ katom->status = KBASE_JD_ATOM_STATE_QUEUED;
+
+ /* Reject atoms with job chain = NULL, as these cause issues with soft-stop */
+ if (0 == katom->jc && (katom->core_req & BASEP_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP)
+ {
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD, "Rejecting atom with jc = NULL");
+ katom->event_code = BASE_JD_EVENT_JOB_INVALID;
+ ret = jd_done_nolock(katom);
+ goto out;
+ }
+
+ /*
+ * If the priority is increased we need to check the caller has security caps to do this, if
+ * priority is decreased then this is ok as the result will have no negative impact on other
+ * processes running.
+ */
+ if (0 > katom->nice_prio) {
+ mali_bool access_allowed;
+ access_allowed = kbase_security_has_capability(kctx, KBASE_SEC_MODIFY_PRIORITY, KBASE_SEC_FLAG_NOAUDIT);
+ if (!access_allowed) {
+ /* For unprivileged processes - a negative priority is interpreted as zero */
+ katom->nice_prio = 0;
+ }
+ }
+
+ /* Scale priority range to use NICE range */
+ if (katom->nice_prio) {
+ /* Remove sign for calculation */
+ int nice_priority = katom->nice_prio + 128;
+ /* Fixed point maths to scale from ..255 to 0..39 (NICE range with +20 offset) */
+ katom->nice_prio = (((20 << 16) / 128) * nice_priority) >> 16;
+ }
+
+ if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) {
+ /* handle what we need to do to access the external resources */
+ if (MALI_ERROR_NONE != kbase_jd_pre_external_resources(katom, user_atom)) {
+ /* setup failed (no access, bad resource, unknown resource types, etc.) */
+ katom->event_code = BASE_JD_EVENT_JOB_INVALID;
+ ret = jd_done_nolock(katom);
+ goto out;
+ }
+ }
+
+ /* Initialize the jobscheduler policy for this atom. Function will
+ * return error if the atom is malformed.
+ *
+ * Soft-jobs never enter the job scheduler but have their own initialize method.
+ *
+ * If either fail then we immediately complete the atom with an error.
+ */
+ if ((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0) {
+ kbasep_js_policy *js_policy = &(kctx->kbdev->js_data.policy);
+ if (MALI_ERROR_NONE != kbasep_js_policy_init_job(js_policy, kctx, katom)) {
+ katom->event_code = BASE_JD_EVENT_JOB_INVALID;
+ ret = jd_done_nolock(katom);
+ goto out;
+ }
+ } else {
+ /* Soft-job */
+ if (MALI_ERROR_NONE != kbase_prepare_soft_job(katom)) {
+ katom->event_code = BASE_JD_EVENT_JOB_INVALID;
+ ret = jd_done_nolock(katom);
+ goto out;
+ }
+ }
+
+#ifdef CONFIG_GPU_TRACEPOINTS
+ katom->work_id = atomic_inc_return(&jctx->work_id);
+ trace_gpu_job_enqueue((u32)kctx, katom->work_id, kbasep_map_core_reqs_to_string(katom->core_req));
+#endif
+
+ if (queued) {
+ ret = MALI_FALSE;
+ goto out;
+ }
+#ifdef CONFIG_KDS
+ if (!katom->kds_dep_satisfied) {
+ /* Queue atom due to KDS dependency */
+ ret = MALI_FALSE;
+ goto out;
+ }
+#endif /* CONFIG_KDS */
+
+ if (katom->core_req & BASE_JD_REQ_SOFT_JOB) {
+ if (kbase_process_soft_job(katom) == 0) {
+ kbase_finish_soft_job(katom);
+ ret = jd_done_nolock(katom);
+ goto out;
+ }
+ /* The job has not yet completed */
+ list_add_tail(&katom->dep_item[0], &kctx->waiting_soft_jobs);
+ ret = MALI_FALSE;
+ } else if ((katom->core_req & BASEP_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) {
+ katom->status = KBASE_JD_ATOM_STATE_IN_JS;
+ ret = kbasep_js_add_job(kctx, katom);
+ } else {
+ /* This is a pure dependency. Resolve it immediately */
+ ret = jd_done_nolock(katom);
+ }
+
+ out:
+ mutex_unlock(&jctx->lock);
+ return ret;
+}
+
+mali_error kbase_jd_submit(kbase_context *kctx, const kbase_uk_job_submit *submit_data)
+{
+ mali_error err = MALI_ERROR_NONE;
+ int i;
+ mali_bool need_to_try_schedule_context = MALI_FALSE;
+ kbase_device *kbdev;
+ void *user_addr;
+
+ /*
+ * kbase_jd_submit isn't expected to fail and so all errors with the jobs
+ * are reported by immediately falling them (through event system)
+ */
+ kbdev = kctx->kbdev;
+
+ beenthere("%s", "Enter");
+
+ if ((kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) != 0) {
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JD, "Attempt to submit to a context that has SUBMIT_DISABLED set on it");
+ return MALI_ERROR_FUNCTION_FAILED;
+ }
+
+ if (submit_data->stride != sizeof(base_jd_atom_v2)) {
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JD, "Stride passed to job_submit doesn't match kernel");
+ return MALI_ERROR_FUNCTION_FAILED;
+ }
+
+ user_addr = get_compat_pointer(&submit_data->addr);
+
+ KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_add_return(submit_data->nr_atoms, &kctx->timeline.jd_atoms_in_flight));
+
+ for (i = 0; i < submit_data->nr_atoms; i++) {
+ base_jd_atom_v2 user_atom;
+
+ if (copy_from_user(&user_atom, user_addr, sizeof(user_atom)) != 0) {
+ err = MALI_ERROR_FUNCTION_FAILED;
+ KBASE_TIMELINE_ATOMS_IN_FLIGHT(kctx, atomic_sub_return(submit_data->nr_atoms - i, &kctx->timeline.jd_atoms_in_flight));
+ break;
+ }
+
+ user_addr = (void *)((uintptr_t) user_addr + submit_data->stride);
+
+ need_to_try_schedule_context |= jd_submit_atom(kctx, &user_atom);
+ }
+
+ if (need_to_try_schedule_context)
+ kbasep_js_try_schedule_head_ctx(kbdev);
+
+ return err;
+}
+
+KBASE_EXPORT_TEST_API(kbase_jd_submit)
+
+static void kbasep_jd_cacheclean(kbase_device *kbdev)
+{
+ /* Limit the number of loops to avoid a hang if the interrupt is missed */
+ u32 max_loops = KBASE_CLEAN_CACHE_MAX_LOOPS;
+
+ mutex_lock(&kbdev->cacheclean_lock);
+
+ /* use GPU_COMMAND completion solution */
+ /* clean & invalidate the caches */
+ KBASE_TRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, NULL, 0u, 0);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CLEAN_INV_CACHES, NULL);
+
+ /* wait for cache flush to complete before continuing */
+ while (--max_loops && (kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL) & CLEAN_CACHES_COMPLETED) == 0)
+ ;
+
+ /* clear the CLEAN_CACHES_COMPLETED irq */
+ KBASE_TRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, NULL, 0u, CLEAN_CACHES_COMPLETED);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), CLEAN_CACHES_COMPLETED, NULL);
+ KBASE_DEBUG_ASSERT_MSG(kbdev->hwcnt.state != KBASE_INSTR_STATE_CLEANING,
+ "Instrumentation code was cleaning caches, but Job Management code cleared their IRQ - Instrumentation code will now hang.");
+
+ mutex_unlock(&kbdev->cacheclean_lock);
+}
+
+/**
+ * This function:
+ * - requeues the job from the runpool (if it was soft-stopped/removed from NEXT registers)
+ * - removes it from the system if it finished/failed/was cancelled.
+ * - resolves dependencies to add dependent jobs to the context, potentially starting them if necessary (which may add more references to the context)
+ * - releases the reference to the context from the no-longer-running job.
+ * - Handles retrying submission outside of IRQ context if it failed from within IRQ context.
+ */
+static void jd_done_worker(struct work_struct *data)
+{
+ kbase_jd_atom *katom = container_of(data, kbase_jd_atom, work);
+ kbase_jd_context *jctx;
+ kbase_context *kctx;
+ kbasep_js_kctx_info *js_kctx_info;
+ kbasep_js_policy *js_policy;
+ kbase_device *kbdev;
+ kbasep_js_device_data *js_devdata;
+ u64 cache_jc = katom->jc;
+ kbasep_js_atom_retained_state katom_retained_state;
+
+ /* Soft jobs should never reach this function */
+ KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0);
+
+ kctx = katom->kctx;
+ jctx = &kctx->jctx;
+ kbdev = kctx->kbdev;
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ js_devdata = &kbdev->js_data;
+ js_policy = &kbdev->js_data.policy;
+
+ KBASE_TRACE_ADD(kbdev, JD_DONE_WORKER, kctx, katom, katom->jc, 0);
+ /*
+ * Begin transaction on JD context and JS context
+ */
+ mutex_lock(&jctx->lock);
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+
+ /* This worker only gets called on contexts that are scheduled *in*. This is
+ * because it only happens in response to an IRQ from a job that was
+ * running.
+ */
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE);
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6787) && katom->event_code != BASE_JD_EVENT_DONE && !(katom->event_code & BASE_JD_SW_EVENT))
+ kbasep_jd_cacheclean(kbdev); /* cache flush when jobs complete with non-done codes */
+ else if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10676)) {
+ if (kbdev->gpu_props.num_core_groups > 1 &&
+ !(katom->affinity & kbdev->gpu_props.props.coherency_info.group[0].core_mask) &&
+ (katom->affinity & kbdev->gpu_props.props.coherency_info.group[1].core_mask)) {
+ KBASE_DEBUG_PRINT_INFO(KBASE_JD, "JD: Flushing cache due to PRLAM-10676\n");
+ kbasep_jd_cacheclean(kbdev);
+ }
+ }
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10969) &&
+ (katom->core_req & BASE_JD_REQ_FS) &&
+ katom->event_code == BASE_JD_EVENT_TILE_RANGE_FAULT &&
+ (katom->atom_flags & KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED) &&
+ !(katom->atom_flags & KBASE_KATOM_FLAGS_RERUN)){
+ KBASE_DEBUG_PRINT_INFO(KBASE_JD,
+ " Soft-stopped fragment shader job got a TILE_RANGE_FAULT." \
+ "Possible HW issue, trying SW workaround \n " );
+ if (kbasep_10969_workaround_clamp_coordinates(katom)){
+ /* The job had a TILE_RANGE_FAULT after was soft-stopped.
+ * Due to an HW issue we try to execute the job
+ * again.
+ */
+ KBASE_DEBUG_PRINT_INFO(KBASE_JD, " Clamping has been executed, try to rerun the job \n" );
+ katom->event_code = BASE_JD_EVENT_STOPPED;
+ katom->atom_flags |= KBASE_KATOM_FLAGS_RERUN;
+
+ /* The atom will be requeued, but requeing does not submit more
+ * jobs. If this was the last job, we must also ensure that more
+ * jobs will be run on slot 0 - this is a Fragment job. */
+ kbasep_js_set_job_retry_submit_slot(katom, 0);
+ }
+ }
+
+ /* If job was rejected due to BASE_JD_EVENT_PM_EVENT but was not
+ * specifically targeting core group 1, then re-submit targeting core
+ * group 0 */
+ if (katom->event_code == BASE_JD_EVENT_PM_EVENT && !(katom->core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) {
+ katom->event_code = BASE_JD_EVENT_STOPPED;
+ /* Don't need to worry about any previously set retry-slot - it's
+ * impossible for it to have been set previously, because we guarantee
+ * kbase_jd_done() was called with done_code==0 on this atom */
+ kbasep_js_set_job_retry_submit_slot(katom, 1);
+ }
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316))
+ kbase_as_poking_timer_release_atom(kbdev, kctx, katom);
+
+ /* Release cores this job was using (this might power down unused cores, and
+ * cause extra latency if a job submitted here - such as depenedent jobs -
+ * would use those cores) */
+ kbasep_js_job_check_deref_cores(kbdev, katom);
+
+ /* Retain state before the katom disappears */
+ kbasep_js_atom_retained_state_copy(&katom_retained_state, katom);
+
+ if (!kbasep_js_has_atom_finished(&katom_retained_state)) {
+ unsigned long flags;
+ /* Requeue the atom on soft-stop / removed from NEXT registers */
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "JS: Soft Stopped/Removed from next on Ctx %p; Requeuing", kctx);
+
+ mutex_lock(&js_devdata->runpool_mutex);
+ kbasep_js_clear_job_retry_submit(katom);
+
+ KBASE_TIMELINE_ATOM_READY(kctx, kbase_jd_atom_id(kctx, katom));
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ kbasep_js_policy_enqueue_job(js_policy, katom);
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+
+ /* A STOPPED/REMOVED job must cause a re-submit to happen, in case it
+ * was the last job left. Crucially, work items on work queues can run
+ * out of order e.g. on different CPUs, so being able to submit from
+ * the IRQ handler is not a good indication that we don't need to run
+ * jobs; the submitted job could be processed on the work-queue
+ * *before* the stopped job, even though it was submitted after. */
+ {
+ int tmp;
+ KBASE_DEBUG_ASSERT(kbasep_js_get_atom_retry_submit_slot(&katom_retained_state, &tmp) != MALI_FALSE);
+ CSTD_UNUSED(tmp);
+ }
+
+ mutex_unlock(&js_devdata->runpool_mutex);
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+ } else {
+ /* Remove the job from the system for all other reasons */
+ mali_bool need_to_try_schedule_context;
+
+ kbasep_js_remove_job(kbdev, kctx, katom);
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+ /* jd_done_nolock() requires the jsctx_mutex lock to be dropped */
+
+ need_to_try_schedule_context = jd_done_nolock(katom);
+
+ /* This ctx is already scheduled in, so return value guarenteed FALSE */
+ KBASE_DEBUG_ASSERT(need_to_try_schedule_context == MALI_FALSE);
+ }
+ /* katom may have been freed now, do not use! */
+
+ /*
+ * Transaction complete
+ */
+ mutex_unlock(&jctx->lock);
+
+ /* Job is now no longer running, so can now safely release the context
+ * reference, and handle any actions that were logged against the atom's retained state */
+ kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &katom_retained_state);
+
+ KBASE_TRACE_ADD(kbdev, JD_DONE_WORKER_END, kctx, NULL, cache_jc, 0);
+}
+
+/**
+ * Work queue job cancel function
+ * Only called as part of 'Zapping' a context (which occurs on termination)
+ * Operates serially with the jd_done_worker() on the work queue.
+ *
+ * This can only be called on contexts that aren't scheduled.
+ *
+ * @note We don't need to release most of the resources that would occur on
+ * kbase_jd_done() or jd_done_worker(), because the atoms here must not be
+ * running (by virtue of only being called on contexts that aren't
+ * scheduled). The only resources that are an exception to this are:
+ * - those held by kbasep_js_job_check_ref_cores(), because these resources are
+ * held for non-running atoms as well as running atoms.
+ */
+static void jd_cancel_worker(struct work_struct *data)
+{
+ kbase_jd_atom *katom = container_of(data, kbase_jd_atom, work);
+ kbase_jd_context *jctx;
+ kbase_context *kctx;
+ kbasep_js_kctx_info *js_kctx_info;
+ mali_bool need_to_try_schedule_context;
+ kbase_device *kbdev;
+
+ /* Soft jobs should never reach this function */
+ KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0);
+
+ kctx = katom->kctx;
+ kbdev = kctx->kbdev;
+ jctx = &kctx->jctx;
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ KBASE_TRACE_ADD(kbdev, JD_CANCEL_WORKER, kctx, katom, katom->jc, 0);
+
+ /* This only gets called on contexts that are scheduled out. Hence, we must
+ * make sure we don't de-ref the number of running jobs (there aren't
+ * any), nor must we try to schedule out the context (it's already
+ * scheduled out).
+ */
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE);
+
+ /* Release cores this job was using (this might power down unused cores) */
+ kbasep_js_job_check_deref_cores(kctx->kbdev, katom);
+
+ /* Scheduler: Remove the job from the system */
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+ kbasep_js_remove_cancelled_job(kbdev, kctx, katom);
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+
+ mutex_lock(&jctx->lock);
+
+ need_to_try_schedule_context = jd_done_nolock(katom);
+ /* Because we're zapping, we're not adding any more jobs to this ctx, so no need to
+ * schedule the context. There's also no need for the jsctx_mutex to have been taken
+ * around this too. */
+ KBASE_DEBUG_ASSERT(need_to_try_schedule_context == MALI_FALSE);
+
+ /* katom may have been freed now, do not use! */
+ mutex_unlock(&jctx->lock);
+
+}
+
+/**
+ * @brief Complete a job that has been removed from the Hardware
+ *
+ * This must be used whenever a job has been removed from the Hardware, e.g.:
+ * - An IRQ indicates that the job finished (for both error and 'done' codes)
+ * - The job was evicted from the JSn_HEAD_NEXT registers during a Soft/Hard stop.
+ *
+ * Some work is carried out immediately, and the rest is deferred onto a workqueue
+ *
+ * This can be called safely from atomic context.
+ *
+ * The caller must hold kbasep_js_device_data::runpool_irq::lock
+ *
+ */
+void kbase_jd_done(kbase_jd_atom *katom, int slot_nr, ktime_t *end_timestamp,
+ kbasep_js_atom_done_code done_code)
+{
+ kbase_context *kctx;
+ kbase_device *kbdev;
+ KBASE_DEBUG_ASSERT(katom);
+ kctx = katom->kctx;
+ KBASE_DEBUG_ASSERT(kctx);
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ if (done_code & KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT)
+ katom->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT;
+
+ kbase_timeline_job_slot_done(kbdev, kctx, katom, slot_nr, done_code);
+
+ KBASE_TRACE_ADD(kbdev, JD_DONE, kctx, katom, katom->jc, 0);
+
+ kbasep_js_job_done_slot_irq(katom, slot_nr, end_timestamp, done_code);
+
+ katom->slot_nr = slot_nr;
+
+ KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work));
+ INIT_WORK(&katom->work, jd_done_worker);
+ queue_work(kctx->jctx.job_done_wq, &katom->work);
+}
+
+KBASE_EXPORT_TEST_API(kbase_jd_done)
+
+void kbase_jd_cancel(kbase_device *kbdev, kbase_jd_atom *katom)
+{
+ kbase_context *kctx;
+ kbasep_js_kctx_info *js_kctx_info;
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+ KBASE_DEBUG_ASSERT(NULL != katom);
+ kctx = katom->kctx;
+ KBASE_DEBUG_ASSERT(NULL != kctx);
+
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ KBASE_TRACE_ADD(kbdev, JD_CANCEL, kctx, katom, katom->jc, 0);
+
+ /* This should only be done from a context that is not scheduled */
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE);
+
+ katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
+
+ KBASE_DEBUG_ASSERT(0 == object_is_on_stack(&katom->work));
+ INIT_WORK(&katom->work, jd_cancel_worker);
+ queue_work(kctx->jctx.job_done_wq, &katom->work);
+}
+
+typedef struct zap_reset_data {
+ /* The stages are:
+ * 1. The timer has never been called
+ * 2. The zap has timed out, all slots are soft-stopped - the GPU reset will happen.
+ * The GPU has been reset when kbdev->reset_waitq is signalled
+ *
+ * (-1 - The timer has been cancelled)
+ */
+ int stage;
+ kbase_device *kbdev;
+ struct hrtimer timer;
+ spinlock_t lock;
+} zap_reset_data;
+
+static enum hrtimer_restart zap_timeout_callback(struct hrtimer *timer)
+{
+ zap_reset_data *reset_data = container_of(timer, zap_reset_data, timer);
+ kbase_device *kbdev = reset_data->kbdev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&reset_data->lock, flags);
+
+ if (reset_data->stage == -1)
+ goto out;
+
+ if (kbase_prepare_to_reset_gpu(kbdev)) {
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JD, "Issueing GPU soft-reset because jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n", ZAP_TIMEOUT);
+ kbase_reset_gpu(kbdev);
+ }
+
+ reset_data->stage = 2;
+
+ out:
+ spin_unlock_irqrestore(&reset_data->lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
+void kbase_jd_zap_context(kbase_context *kctx)
+{
+ kbase_jd_atom *katom;
+ struct list_head *entry;
+ kbase_device *kbdev;
+ zap_reset_data reset_data;
+ unsigned long flags;
+
+ KBASE_DEBUG_ASSERT(kctx);
+
+ kbdev = kctx->kbdev;
+
+ KBASE_TRACE_ADD(kbdev, JD_ZAP_CONTEXT, kctx, NULL, 0u, 0u);
+ kbase_job_zap_context(kctx);
+
+ mutex_lock(&kctx->jctx.lock);
+
+ /*
+ * While holding the kbase_jd_context lock clean up jobs which are known to kbase but are
+ * queued outside the job scheduler.
+ */
+
+ list_for_each(entry, &kctx->waiting_soft_jobs) {
+ katom = list_entry(entry, kbase_jd_atom, dep_item[0]);
+
+ kbase_cancel_soft_job(katom);
+ }
+
+#ifdef CONFIG_KDS
+
+ /* For each job waiting on a kds resource, cancel the wait and force the job to
+ * complete early, this is done so that we don't leave jobs outstanding waiting
+ * on kds resources which may never be released when contexts are zapped, resulting
+ * in a hang.
+ *
+ * Note that we can safely iterate over the list as the kbase_jd_context lock is held,
+ * this prevents items being removed when calling job_done_nolock in kbase_cancel_kds_wait_job.
+ */
+
+ list_for_each( entry, &kctx->waiting_kds_resource) {
+ katom = list_entry(entry, kbase_jd_atom, node);
+
+ kbase_cancel_kds_wait_job(katom);
+ }
+#endif
+
+ mutex_unlock(&kctx->jctx.lock);
+
+ hrtimer_init_on_stack(&reset_data.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ reset_data.timer.function = zap_timeout_callback;
+
+ spin_lock_init(&reset_data.lock);
+
+ reset_data.kbdev = kbdev;
+ reset_data.stage = 1;
+
+ hrtimer_start(&reset_data.timer, HR_TIMER_DELAY_MSEC(ZAP_TIMEOUT), HRTIMER_MODE_REL);
+
+ /* Wait for all jobs to finish, and for the context to be not-scheduled
+ * (due to kbase_job_zap_context(), we also guarentee it's not in the JS
+ * policy queue either */
+ wait_event(kctx->jctx.zero_jobs_wait, kctx->jctx.job_nr == 0);
+ wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, kctx->jctx.sched_info.ctx.is_scheduled == MALI_FALSE);
+
+ spin_lock_irqsave(&reset_data.lock, flags);
+ if (reset_data.stage == 1) {
+ /* The timer hasn't run yet - so cancel it */
+ reset_data.stage = -1;
+ }
+ spin_unlock_irqrestore(&reset_data.lock, flags);
+
+ hrtimer_cancel(&reset_data.timer);
+
+ if (reset_data.stage == 2) {
+ /* The reset has already started.
+ * Wait for the reset to complete
+ */
+ wait_event(kbdev->reset_wait, atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_NOT_PENDING);
+ }
+ destroy_hrtimer_on_stack(&reset_data.timer);
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "Zap: Finished Context %p", kctx);
+
+ /* Ensure that the signallers of the waitqs have finished */
+ mutex_lock(&kctx->jctx.lock);
+ mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex);
+ mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex);
+ mutex_unlock(&kctx->jctx.lock);
+}
+
+KBASE_EXPORT_TEST_API(kbase_jd_zap_context)
+
+mali_error kbase_jd_init(kbase_context *kctx)
+{
+ int i;
+ mali_error mali_err = MALI_ERROR_NONE;
+#ifdef CONFIG_KDS
+ int err;
+#endif /* CONFIG_KDS */
+
+ KBASE_DEBUG_ASSERT(kctx);
+
+ kctx->jctx.job_done_wq = alloc_workqueue("mali_jd", 0, 1);
+ if (NULL == kctx->jctx.job_done_wq) {
+ mali_err = MALI_ERROR_OUT_OF_MEMORY;
+ goto out1;
+ }
+
+ for (i = 0; i < BASE_JD_ATOM_COUNT; i++) {
+ init_waitqueue_head(&kctx->jctx.atoms[i].completed);
+
+ INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[0]);
+ INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[1]);
+
+ /* Catch userspace attempting to use an atom which doesn't exist as a pre-dependency */
+ kctx->jctx.atoms[i].event_code = BASE_JD_EVENT_JOB_INVALID;
+ kctx->jctx.atoms[i].status = KBASE_JD_ATOM_STATE_UNUSED;
+ }
+
+ mutex_init(&kctx->jctx.lock);
+
+ init_waitqueue_head(&kctx->jctx.zero_jobs_wait);
+
+ spin_lock_init(&kctx->jctx.tb_lock);
+
+#ifdef CONFIG_KDS
+ err = kds_callback_init(&kctx->jctx.kds_cb, 0, kds_dep_clear);
+ if (0 != err) {
+ mali_err = MALI_ERROR_FUNCTION_FAILED;
+ goto out2;
+ }
+#endif /* CONFIG_KDS */
+
+ kctx->jctx.job_nr = 0;
+
+ return MALI_ERROR_NONE;
+
+#ifdef CONFIG_KDS
+ out2:
+ destroy_workqueue(kctx->jctx.job_done_wq);
+#endif /* CONFIG_KDS */
+ out1:
+ return mali_err;
+}
+
+KBASE_EXPORT_TEST_API(kbase_jd_init)
+
+void kbase_jd_exit(kbase_context *kctx)
+{
+ KBASE_DEBUG_ASSERT(kctx);
+
+#ifdef CONFIG_KDS
+ kds_callback_term(&kctx->jctx.kds_cb);
+#endif /* CONFIG_KDS */
+ /* Work queue is emptied by this */
+ destroy_workqueue(kctx->jctx.job_done_wq);
+}
+
+KBASE_EXPORT_TEST_API(kbase_jd_exit)
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jm.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jm.c
new file mode 100755
index 00000000000..f162e4142a3
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jm.c
@@ -0,0 +1,1274 @@
+/*
+ *
+ * (C) COPYRIGHT 2010-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_jm.c
+ * Base kernel job manager APIs
+ */
+
+#include <kbase/src/common/mali_kbase.h>
+#include <kbase/src/common/mali_midg_regmap.h>
+#include <kbase/src/common/mali_kbase_gator.h>
+#include <kbase/src/common/mali_kbase_js_affinity.h>
+#include <kbase/src/common/mali_kbase_8401_workaround.h>
+#include <kbase/src/common/mali_kbase_hw.h>
+
+#include "mali_kbase_jm.h"
+
+#define beenthere(f, a...) KBASE_DEBUG_PRINT_INFO(KBASE_JM, "%s:" f, __func__, ##a)
+
+#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS
+u64 mali_js0_affinity_mask = 0xFFFFFFFFFFFFFFFFULL;
+u64 mali_js1_affinity_mask = 0xFFFFFFFFFFFFFFFFULL;
+u64 mali_js2_affinity_mask = 0xFFFFFFFFFFFFFFFFULL;
+#endif
+
+
+static void kbasep_try_reset_gpu_early(kbase_device *kbdev);
+
+#ifdef CONFIG_GPU_TRACEPOINTS
+static char *kbasep_make_job_slot_string(int js, char *js_string)
+{
+ sprintf(js_string, "job_slot_%i", js);
+ return js_string;
+}
+#endif
+
+static void kbase_job_hw_submit(kbase_device *kbdev, kbase_jd_atom *katom, int js)
+{
+ kbase_context *kctx;
+ u32 cfg;
+ u64 jc_head = katom->jc;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+ KBASE_DEBUG_ASSERT(katom);
+
+ kctx = katom->kctx;
+
+ /* Command register must be available */
+ KBASE_DEBUG_ASSERT(kbasep_jm_is_js_free(kbdev, js, kctx));
+ /* Affinity is not violating */
+ kbase_js_debug_log_current_affinities(kbdev);
+ KBASE_DEBUG_ASSERT(!kbase_js_affinity_would_violate(kbdev, js, katom->affinity));
+
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_LO), jc_head & 0xFFFFFFFF, kctx);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_HI), jc_head >> 32, kctx);
+
+#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS
+ {
+ u64 mask;
+ u32 value;
+
+ if( 0 == js )
+ {
+ mask = mali_js0_affinity_mask;
+ }
+ else if( 1 == js )
+ {
+ mask = mali_js1_affinity_mask;
+ }
+ else
+ {
+ mask = mali_js2_affinity_mask;
+ }
+
+ value = katom->affinity & (mask & 0xFFFFFFFF);
+
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_NEXT_LO), value, kctx);
+
+ value = (katom->affinity >> 32) & ((mask>>32) & 0xFFFFFFFF);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_NEXT_HI), value, kctx);
+ }
+#else
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_NEXT_LO), katom->affinity & 0xFFFFFFFF, kctx);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_NEXT_HI), katom->affinity >> 32, kctx);
+#endif
+
+ /* start MMU, medium priority, cache clean/flush on end, clean/flush on start */
+ cfg = kctx->as_nr | JSn_CONFIG_END_FLUSH_CLEAN_INVALIDATE | JSn_CONFIG_START_MMU | JSn_CONFIG_START_FLUSH_CLEAN_INVALIDATE | JSn_CONFIG_THREAD_PRI(8);
+
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_CONFIG_NEXT), cfg, kctx);
+
+ /* Write an approximate start timestamp.
+ * It's approximate because there might be a job in the HEAD register. In
+ * such cases, we'll try to make a better approximation in the IRQ handler
+ * (up to the KBASE_JS_IRQ_THROTTLE_TIME_US). */
+ katom->start_timestamp = ktime_get();
+
+ /* GO ! */
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "JS: Submitting atom %p from ctx %p to js[%d] with head=0x%llx, affinity=0x%llx", katom, kctx, js, jc_head, katom->affinity);
+
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_SUBMIT, kctx, katom, jc_head, js, (u32) katom->affinity);
+
+#ifdef CONFIG_MALI_GATOR_SUPPORT
+ kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_START, js), kctx);
+#endif /* CONFIG_MALI_GATOR_SUPPORT */
+#ifdef CONFIG_GPU_TRACEPOINTS
+ if (kbasep_jm_nr_jobs_submitted(&kbdev->jm_slots[js]) == 1)
+ {
+ /* If this is the only job on the slot, trace it as starting */
+ char js_string[16];
+ trace_gpu_sched_switch(kbasep_make_job_slot_string(js, js_string), ktime_to_ns(katom->start_timestamp), (u32)katom->kctx, 0, katom->work_id);
+ kbdev->jm_slots[js].last_context = katom->kctx;
+ }
+#endif
+ kbase_timeline_job_slot_submit(kbdev, kctx, katom, js);
+
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), JSn_COMMAND_START, katom->kctx);
+}
+
+void kbase_job_submit_nolock(kbase_device *kbdev, kbase_jd_atom *katom, int js)
+{
+ kbase_jm_slot *jm_slots;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ jm_slots = kbdev->jm_slots;
+
+ /*
+ * We can have:
+ * - one job already done (pending interrupt),
+ * - one running,
+ * - one ready to be run.
+ * Hence a maximum of 3 inflight jobs. We have a 4 job
+ * queue, which I hope will be enough...
+ */
+ kbasep_jm_enqueue_submit_slot(&jm_slots[js], katom);
+ kbase_job_hw_submit(kbdev, katom, js);
+}
+
+void kbase_job_done_slot(kbase_device *kbdev, int s, u32 completion_code, u64 job_tail, ktime_t *end_timestamp)
+{
+ kbase_jm_slot *slot;
+ kbase_jd_atom *katom;
+ mali_addr64 jc_head;
+ kbase_context *kctx;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ if (completion_code != BASE_JD_EVENT_DONE && completion_code != BASE_JD_EVENT_STOPPED)
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JM, "t6xx: GPU fault 0x%02lx from job slot %d\n", (unsigned long)completion_code, s);
+
+ /* IMPORTANT: this function must only contain work necessary to complete a
+ * job from a Real IRQ (and not 'fake' completion, e.g. from
+ * Soft-stop). For general work that must happen no matter how the job was
+ * removed from the hardware, place it in kbase_jd_done() */
+
+ slot = &kbdev->jm_slots[s];
+ katom = kbasep_jm_dequeue_submit_slot(slot);
+
+ /* If the katom completed is because it's a dummy job for HW workarounds, then take no further action */
+ if (kbasep_jm_is_dummy_workaround_job(kbdev, katom)) {
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_JOB_DONE, NULL, NULL, 0, s, completion_code);
+ return;
+ }
+
+ jc_head = katom->jc;
+ kctx = katom->kctx;
+
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_JOB_DONE, kctx, katom, jc_head, s, completion_code);
+
+ if (completion_code != BASE_JD_EVENT_DONE && completion_code != BASE_JD_EVENT_STOPPED) {
+
+#if KBASE_TRACE_DUMP_ON_JOB_SLOT_ERROR != 0
+ KBASE_TRACE_DUMP(kbdev);
+#endif
+ }
+ if (job_tail != 0) {
+ mali_bool was_updated = (job_tail != jc_head);
+ /* Some of the job has been executed, so we update the job chain address to where we should resume from */
+ katom->jc = job_tail;
+ if (was_updated)
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_UPDATE_HEAD, kctx, katom, job_tail, s);
+ }
+
+ /* Only update the event code for jobs that weren't cancelled */
+ if (katom->event_code != BASE_JD_EVENT_JOB_CANCELLED)
+ katom->event_code = (base_jd_event_code) completion_code;
+
+ kbase_device_trace_register_access(kctx, REG_WRITE, JOB_CONTROL_REG(JOB_IRQ_CLEAR), 1 << s);
+
+ /* Complete the job, and start new ones
+ *
+ * Also defer remaining work onto the workqueue:
+ * - Re-queue Soft-stopped jobs
+ * - For any other jobs, queue the job back into the dependency system
+ * - Schedule out the parent context if necessary, and schedule a new one in.
+ */
+#ifdef CONFIG_GPU_TRACEPOINTS
+ if (kbasep_jm_nr_jobs_submitted(slot) != 0) {
+ kbase_jd_atom *katom;
+ char js_string[16];
+ katom = kbasep_jm_peek_idx_submit_slot(slot, 0); /* The atom in the HEAD */
+ trace_gpu_sched_switch(kbasep_make_job_slot_string(s, js_string), ktime_to_ns(*end_timestamp), (u32)katom->kctx, 0, katom->work_id);
+ slot->last_context = katom->kctx;
+ } else {
+ char js_string[16];
+ trace_gpu_sched_switch(kbasep_make_job_slot_string(s, js_string), ktime_to_ns(ktime_get()), 0, 0, 0);
+ slot->last_context = 0;
+ }
+#endif
+ kbase_jd_done(katom, s, end_timestamp, KBASE_JS_ATOM_DONE_START_NEW_ATOMS);
+}
+
+/**
+ * Update the start_timestamp of the job currently in the HEAD, based on the
+ * fact that we got an IRQ for the previous set of completed jobs.
+ *
+ * The estimate also takes into account the KBASE_JS_IRQ_THROTTLE_TIME_US and
+ * the time the job was submitted, to work out the best estimate (which might
+ * still result in an over-estimate to the calculated time spent)
+ */
+STATIC void kbasep_job_slot_update_head_start_timestamp(kbase_device *kbdev, kbase_jm_slot *slot, ktime_t end_timestamp)
+{
+ KBASE_DEBUG_ASSERT(slot);
+
+ if (kbasep_jm_nr_jobs_submitted(slot) > 0) {
+ kbase_jd_atom *katom;
+ ktime_t new_timestamp;
+ ktime_t timestamp_diff;
+ katom = kbasep_jm_peek_idx_submit_slot(slot, 0); /* The atom in the HEAD */
+
+ KBASE_DEBUG_ASSERT(katom != NULL);
+
+ if (kbasep_jm_is_dummy_workaround_job(kbdev, katom) != MALI_FALSE) {
+ /* Don't access the members of HW workaround 'dummy' jobs */
+ return;
+ }
+
+ /* Account for any IRQ Throttle time - makes an overestimate of the time spent by the job */
+ new_timestamp = ktime_sub_ns(end_timestamp, KBASE_JS_IRQ_THROTTLE_TIME_US * 1000);
+ timestamp_diff = ktime_sub(new_timestamp, katom->start_timestamp);
+ if (ktime_to_ns(timestamp_diff) >= 0) {
+ /* Only update the timestamp if it's a better estimate than what's currently stored.
+ * This is because our estimate that accounts for the throttle time may be too much
+ * of an overestimate */
+ katom->start_timestamp = new_timestamp;
+ }
+ }
+}
+
+void kbase_job_done(kbase_device *kbdev, u32 done)
+{
+ unsigned long flags;
+ int i;
+ u32 count = 0;
+ ktime_t end_timestamp = ktime_get();
+ kbasep_js_device_data *js_devdata;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+ js_devdata = &kbdev->js_data;
+
+ KBASE_TRACE_ADD(kbdev, JM_IRQ, NULL, NULL, 0, done);
+
+ memset(&kbdev->slot_submit_count_irq[0], 0, sizeof(kbdev->slot_submit_count_irq));
+
+ /* write irq throttle register, this will prevent irqs from occurring until
+ * the given number of gpu clock cycles have passed */
+ {
+ int irq_throttle_cycles = atomic_read(&kbdev->irq_throttle_cycles);
+ kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_THROTTLE), irq_throttle_cycles, NULL);
+ }
+
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+
+ while (done) {
+ kbase_jm_slot *slot;
+ u32 failed = done >> 16;
+
+ /* treat failed slots as finished slots */
+ u32 finished = (done & 0xFFFF) | failed;
+
+ /* Note: This is inherently unfair, as we always check
+ * for lower numbered interrupts before the higher
+ * numbered ones.*/
+ i = ffs(finished) - 1;
+ KBASE_DEBUG_ASSERT(i >= 0);
+
+ slot = &kbdev->jm_slots[i];
+
+ do {
+ int nr_done;
+ u32 active;
+ u32 completion_code = BASE_JD_EVENT_DONE; /* assume OK */
+ u64 job_tail = 0;
+
+ if (failed & (1u << i)) {
+ /* read out the job slot status code if the job slot reported failure */
+ completion_code = kbase_reg_read(kbdev, JOB_SLOT_REG(i, JSn_STATUS), NULL);
+
+ switch (completion_code) {
+ case BASE_JD_EVENT_STOPPED:
+#ifdef CONFIG_MALI_GATOR_SUPPORT
+ kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_SOFT_STOPPED, i), NULL);
+#endif /* CONFIG_MALI_GATOR_SUPPORT */
+ /* Soft-stopped job - read the value of JS<n>_TAIL so that the job chain can be resumed */
+ job_tail = (u64) kbase_reg_read(kbdev, JOB_SLOT_REG(i, JSn_TAIL_LO), NULL) | ((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(i, JSn_TAIL_HI), NULL) << 32);
+ break;
+ case BASE_JD_EVENT_NOT_STARTED:
+ /* PRLAM-10673 can cause a TERMINATED job to come back as NOT_STARTED, but the error interrupt helps us detect it */
+ completion_code = BASE_JD_EVENT_TERMINATED;
+ /* fall throught */
+ default:
+ KBASE_DEBUG_PRINT_WARN(KBASE_JD, "error detected from slot %d, job status 0x%08x (%s)", i, completion_code, kbase_exception_name(completion_code));
+ }
+ }
+
+ kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), done & ((1 << i) | (1 << (i + 16))), NULL);
+ active = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_JS_STATE), NULL);
+
+ if (((active >> i) & 1) == 0 && (((done >> (i + 16)) & 1) == 0)) {
+ /* There is a potential race we must work around:
+ *
+ * 1. A job slot has a job in both current and next registers
+ * 2. The job in current completes successfully, the IRQ handler reads RAWSTAT
+ * and calls this function with the relevant bit set in "done"
+ * 3. The job in the next registers becomes the current job on the GPU
+ * 4. Sometime before the JOB_IRQ_CLEAR line above the job on the GPU _fails_
+ * 5. The IRQ_CLEAR clears the done bit but not the failed bit. This atomically sets
+ * JOB_IRQ_JS_STATE. However since both jobs have now completed the relevant bits
+ * for the slot are set to 0.
+ *
+ * If we now did nothing then we'd incorrectly assume that _both_ jobs had completed
+ * successfully (since we haven't yet observed the fail bit being set in RAWSTAT).
+ *
+ * So at this point if there are no active jobs left we check to see if RAWSTAT has a failure
+ * bit set for the job slot. If it does we know that there has been a new failure that we
+ * didn't previously know about, so we make sure that we record this in active (but we wait
+ * for the next loop to deal with it).
+ *
+ * If we were handling a job failure (i.e. done has the relevant high bit set) then we know that
+ * the value read back from JOB_IRQ_JS_STATE is the correct number of remaining jobs because
+ * the failed job will have prevented any futher jobs from starting execution.
+ */
+ u32 rawstat = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL);
+
+ if ((rawstat >> (i + 16)) & 1) {
+ /* There is a failed job that we've missed - add it back to active */
+ active |= (1u << i);
+ }
+ }
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "Job ended with status 0x%08X\n", completion_code);
+
+ nr_done = kbasep_jm_nr_jobs_submitted(slot);
+ nr_done -= (active >> i) & 1;
+ nr_done -= (active >> (i + 16)) & 1;
+
+ if (nr_done <= 0) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_JM, "Spurious interrupt on slot %d", i);
+ goto spurious;
+ }
+
+ count += nr_done;
+
+ while (nr_done) {
+ if (nr_done == 1) {
+ kbase_job_done_slot(kbdev, i, completion_code, job_tail, &end_timestamp);
+ } else {
+ /* More than one job has completed. Since this is not the last job being reported this time it
+ * must have passed. This is because the hardware will not allow further jobs in a job slot to
+ * complete until the faile job is cleared from the IRQ status.
+ */
+ kbase_job_done_slot(kbdev, i, BASE_JD_EVENT_DONE, 0, &end_timestamp);
+ }
+ nr_done--;
+ }
+
+ spurious:
+ done = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL);
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10883)) {
+ /* Workaround for missing interrupt caused by PRLAM-10883 */
+ if (((active >> i) & 1) && (0 == kbase_reg_read(kbdev, JOB_SLOT_REG(i, JSn_STATUS), NULL))) {
+ /* Force job slot to be processed again */
+ done |= (1u << i);
+ }
+ }
+
+ failed = done >> 16;
+ finished = (done & 0xFFFF) | failed;
+ } while (finished & (1 << i));
+
+ kbasep_job_slot_update_head_start_timestamp(kbdev, slot, end_timestamp);
+ }
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+
+ if (atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_COMMITTED) {
+ /* If we're trying to reset the GPU then we might be able to do it early
+ * (without waiting for a timeout) because some jobs have completed
+ */
+ kbasep_try_reset_gpu_early(kbdev);
+ }
+
+ KBASE_TRACE_ADD(kbdev, JM_IRQ_END, NULL, NULL, 0, count);
+}
+KBASE_EXPORT_TEST_API(kbase_job_done)
+
+static mali_bool kbasep_soft_stop_allowed(kbase_device *kbdev, u16 core_reqs)
+{
+ mali_bool soft_stops_allowed = MALI_TRUE;
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) {
+ if ((core_reqs & BASE_JD_REQ_T) != 0)
+ soft_stops_allowed = MALI_FALSE;
+ }
+ return soft_stops_allowed;
+}
+
+static mali_bool kbasep_hard_stop_allowed(kbase_device *kbdev, u16 core_reqs)
+{
+ mali_bool hard_stops_allowed = MALI_TRUE;
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8394)) {
+ if ((core_reqs & BASE_JD_REQ_T) != 0)
+ hard_stops_allowed = MALI_FALSE;
+ }
+ return hard_stops_allowed;
+}
+
+static void kbasep_job_slot_soft_or_hard_stop_do_action(kbase_device *kbdev, int js, u32 action, u16 core_reqs, kbase_jd_atom * target_katom )
+{
+ kbase_context *kctx = target_katom->kctx;
+#if KBASE_TRACE_ENABLE
+ u32 status_reg_before;
+ u64 job_in_head_before;
+ u32 status_reg_after;
+
+ /* Check the head pointer */
+ job_in_head_before = ((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_HEAD_LO), NULL))
+ | (((u64) kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_HEAD_HI), NULL)) << 32);
+ status_reg_before = kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_STATUS), NULL);
+#endif
+
+ if (action == JSn_COMMAND_SOFT_STOP) {
+ mali_bool soft_stop_allowed = kbasep_soft_stop_allowed(kbdev, core_reqs);
+ if (!soft_stop_allowed) {
+#ifdef CONFIG_MALI_DEBUG
+ KBASE_DEBUG_PRINT(KBASE_JM, "Attempt made to soft-stop a job that cannot be soft-stopped. core_reqs = 0x%X", (unsigned int)core_reqs);
+#endif /* CONFIG_MALI_DEBUG */
+ return;
+ }
+
+ /* We are about to issue a soft stop, so mark the atom as having been soft stopped */
+ target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_SOFT_STOPPPED;
+ }
+
+ if (action == JSn_COMMAND_HARD_STOP) {
+ mali_bool hard_stop_allowed = kbasep_hard_stop_allowed(kbdev, core_reqs);
+ if (!hard_stop_allowed) {
+ /* Jobs can be hard-stopped for the following reasons:
+ * * CFS decides the job has been running too long (and soft-stop has not occurred).
+ * In this case the GPU will be reset by CFS if the job remains on the GPU.
+ *
+ * * The context is destroyed, kbase_jd_zap_context will attempt to hard-stop the job. However
+ * it also has a watchdog which will cause the GPU to be reset if the job remains on the GPU.
+ *
+ * * An (unhandled) MMU fault occurred. As long as BASE_HW_ISSUE_8245 is defined then
+ * the GPU will be reset.
+ *
+ * All three cases result in the GPU being reset if the hard-stop fails,
+ * so it is safe to just return and ignore the hard-stop request.
+ */
+ KBASE_DEBUG_PRINT_WARN(KBASE_JM, "Attempt made to hard-stop a job that cannot be hard-stopped. core_reqs = 0x%X", (unsigned int)core_reqs);
+ return;
+ }
+ }
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316) && action == JSn_COMMAND_SOFT_STOP) {
+ int i;
+ kbase_jm_slot *slot;
+ slot = &kbdev->jm_slots[js];
+
+ for (i = 0; i < kbasep_jm_nr_jobs_submitted(slot); i++) {
+ kbase_jd_atom *katom;
+
+ katom = kbasep_jm_peek_idx_submit_slot(slot, i);
+
+ KBASE_DEBUG_ASSERT(katom);
+
+ if (kbasep_jm_is_dummy_workaround_job(kbdev, katom) != MALI_FALSE) {
+ /* Don't access the members of HW workaround 'dummy' jobs
+ *
+ * This assumes that such jobs can't cause HW_ISSUE_8316, and could only be blocked
+ * by other jobs causing HW_ISSUE_8316 (which will get poked/or eventually get killed) */
+ continue;
+ }
+
+ /* For HW_ISSUE_8316, only 'bad' jobs attacking the system can
+ * cause this issue: normally, all memory should be allocated in
+ * multiples of 4 pages, and growable memory should be changed size
+ * in multiples of 4 pages.
+ *
+ * Whilst such 'bad' jobs can be cleared by a GPU reset, the
+ * locking up of a uTLB entry caused by the bad job could also
+ * stall other ASs, meaning that other ASs' jobs don't complete in
+ * the 'grace' period before the reset. We don't want to lose other
+ * ASs' jobs when they would normally complete fine, so we must
+ * 'poke' the MMU regularly to help other ASs complete */
+ kbase_as_poking_timer_retain_atom(kbdev, katom->kctx, katom);
+ }
+ }
+
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_COMMAND), action, kctx);
+
+
+
+#if KBASE_TRACE_ENABLE
+ status_reg_after = kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_STATUS), NULL);
+ if (status_reg_after == BASE_JD_EVENT_ACTIVE) {
+ kbase_jm_slot *slot;
+ kbase_jd_atom *head;
+ kbase_context *head_kctx;
+
+ slot = &kbdev->jm_slots[js];
+ head = kbasep_jm_peek_idx_submit_slot(slot, slot->submitted_nr - 1);
+ head_kctx = head->kctx;
+
+ /* We don't need to check kbasep_jm_is_dummy_workaround_job( head ) here:
+ * - Members are not indirected through
+ * - The members will all be zero anyway
+ */
+ if (status_reg_before == BASE_JD_EVENT_ACTIVE)
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, head_kctx, head, job_in_head_before, js);
+ else
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, 0, js);
+
+ if (action == JSn_COMMAND_SOFT_STOP)
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP, head_kctx, head, head->jc, js);
+ else
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP, head_kctx, head, head->jc, js);
+ } else {
+ if (status_reg_before == BASE_JD_EVENT_ACTIVE)
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, job_in_head_before, js);
+ else
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, 0, js);
+
+ if (action == JSn_COMMAND_SOFT_STOP)
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_SOFTSTOP, NULL, NULL, 0, js);
+ else
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_HARDSTOP, NULL, NULL, 0, js);
+ }
+#endif
+}
+
+/* Helper macros used by kbasep_job_slot_soft_or_hard_stop */
+#define JM_SLOT_MAX_JOB_SUBMIT_REGS 2
+#define JM_JOB_IS_CURRENT_JOB_INDEX(n) (1 == n) /* Index of the last job to process */
+#define JM_JOB_IS_NEXT_JOB_INDEX(n) (2 == n) /* Index of the prior to last job to process */
+
+/** Soft or hard-stop a slot
+ *
+ * This function safely ensures that the correct job is either hard or soft-stopped.
+ * It deals with evicting jobs from the next registers where appropriate.
+ *
+ * This does not attempt to stop or evict jobs that are 'dummy' jobs for HW workarounds.
+ *
+ * @param kbdev The kbase device
+ * @param kctx The context to soft/hard-stop job(s) from (or NULL is all jobs should be targeted)
+ * @param js The slot that the job(s) are on
+ * @param target_katom The atom that should be targeted (or NULL if all jobs from the context should be targeted)
+ * @param action The action to perform, either JSn_COMMAND_HARD_STOP or JSn_COMMAND_SOFT_STOP
+ */
+static void kbasep_job_slot_soft_or_hard_stop(kbase_device *kbdev, kbase_context *kctx, int js, kbase_jd_atom *target_katom, u32 action)
+{
+ kbase_jd_atom *katom;
+ u8 i;
+ u8 jobs_submitted;
+ kbase_jm_slot *slot;
+ u16 core_reqs;
+ kbasep_js_device_data *js_devdata;
+
+ KBASE_DEBUG_ASSERT(action == JSn_COMMAND_HARD_STOP || action == JSn_COMMAND_SOFT_STOP);
+ KBASE_DEBUG_ASSERT(kbdev);
+ js_devdata = &kbdev->js_data;
+
+ slot = &kbdev->jm_slots[js];
+ KBASE_DEBUG_ASSERT(slot);
+ lockdep_assert_held(&js_devdata->runpool_irq.lock);
+
+ jobs_submitted = kbasep_jm_nr_jobs_submitted(slot);
+
+ KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 1);
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JM_SLOT_SOFT_OR_HARD_STOP, kctx, NULL, 0u, js, jobs_submitted);
+
+ if (jobs_submitted > JM_SLOT_MAX_JOB_SUBMIT_REGS)
+ i = jobs_submitted - JM_SLOT_MAX_JOB_SUBMIT_REGS;
+ else
+ i = 0;
+
+ /* Loop through all jobs that have been submitted to the slot and haven't completed */
+ for (; i < jobs_submitted; i++) {
+ katom = kbasep_jm_peek_idx_submit_slot(slot, i);
+
+ if (kctx && katom->kctx != kctx)
+ continue;
+
+ if (target_katom && katom != target_katom)
+ continue;
+
+ if (kbasep_jm_is_dummy_workaround_job(kbdev, katom))
+ continue;
+
+ core_reqs = katom->core_req;
+
+ if (JM_JOB_IS_CURRENT_JOB_INDEX(jobs_submitted - i)) {
+ /* The last job in the slot, check if there is a job in the next register */
+ if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), NULL) == 0) {
+ kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, js, action, core_reqs, katom);
+ } else {
+ /* The job is in the next registers */
+ beenthere("clearing job from next registers on slot %d", js);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), JSn_COMMAND_NOP, NULL);
+
+ /* Check to see if we did remove a job from the next registers */
+ if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_LO), NULL) != 0 || kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_HI), NULL) != 0) {
+ /* The job was successfully cleared from the next registers, requeue it */
+ kbase_jd_atom *dequeued_katom = kbasep_jm_dequeue_tail_submit_slot(slot);
+ KBASE_DEBUG_ASSERT(dequeued_katom == katom);
+ jobs_submitted--;
+
+ /* Set the next registers to NULL */
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_LO), 0, NULL);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_HI), 0, NULL);
+
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_SLOT_EVICT, dequeued_katom->kctx, dequeued_katom, dequeued_katom->jc, js);
+
+ /* Complete the job, indicate it took no time, but don't submit any more at this point */
+ kbase_jd_done(dequeued_katom, js, NULL, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT);
+ } else {
+ /* The job transitioned into the current registers before we managed to evict it,
+ * in this case we fall back to soft/hard-stopping the job */
+ beenthere("missed job in next register, soft/hard-stopping slot %d", js);
+ kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, js, action, core_reqs, katom);
+ }
+ }
+ } else if (JM_JOB_IS_NEXT_JOB_INDEX(jobs_submitted - i)) {
+ /* There's a job after this one, check to see if that job is in the next registers */
+ if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), NULL) != 0) {
+ kbase_jd_atom *check_next_atom;
+ /* It is - we should remove that job and soft/hard-stop the slot */
+
+ /* Only proceed when the next jobs isn't a HW workaround 'dummy' job
+ *
+ * This can't be an ASSERT due to MMU fault code:
+ * - This first hard-stops the job that caused the fault
+ * - Under HW Issue 8401, this inserts a dummy workaround job into NEXT
+ * - Under HW Issue 8245, it will then reset the GPU
+ * - This causes a Soft-stop to occur on all slots
+ * - By the time of the soft-stop, we may (depending on timing) still have:
+ * - The original job in HEAD, if it's not finished the hard-stop
+ * - The dummy workaround job in NEXT
+ *
+ * Other cases could be coded in future that cause back-to-back Soft/Hard
+ * stops with dummy workaround jobs in place, e.g. MMU handler code and Job
+ * Scheduler watchdog timer running in parallel.
+ *
+ * Note, the index i+1 is valid to peek from: i == jobs_submitted-2, therefore
+ * i+1 == jobs_submitted-1 */
+ check_next_atom = kbasep_jm_peek_idx_submit_slot(slot, i + 1);
+ if (kbasep_jm_is_dummy_workaround_job(kbdev, check_next_atom) != MALI_FALSE)
+ continue;
+
+ beenthere("clearing job from next registers on slot %d", js);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), JSn_COMMAND_NOP, NULL);
+
+ /* Check to see if we did remove a job from the next registers */
+ if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_LO), NULL) != 0 || kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_HI), NULL) != 0) {
+ /* We did remove a job from the next registers, requeue it */
+ kbase_jd_atom *dequeued_katom = kbasep_jm_dequeue_tail_submit_slot(slot);
+ KBASE_DEBUG_ASSERT(dequeued_katom != NULL);
+ jobs_submitted--;
+
+ /* Set the next registers to NULL */
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_LO), 0, NULL);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_HI), 0, NULL);
+
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_SLOT_EVICT, dequeued_katom->kctx, dequeued_katom, dequeued_katom->jc, js);
+
+ /* Complete the job, indicate it took no time, but don't submit any more at this point */
+ kbase_jd_done(dequeued_katom, js, NULL, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT);
+ } else {
+ /* We missed the job, that means the job we're interested in left the hardware before
+ * we managed to do anything, so we can proceed to the next job */
+ continue;
+ }
+
+ /* Next is now free, so we can soft/hard-stop the slot */
+ beenthere("soft/hard-stopped slot %d (there was a job in next which was successfully cleared)\n", js);
+ kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, js, action, core_reqs, katom);
+ }
+ /* If there was no job in the next registers, then the job we were
+ * interested in has finished, so we need not take any action
+ */
+ }
+ }
+
+ KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 0);
+}
+
+void kbase_job_kill_jobs_from_context(kbase_context *kctx)
+{
+ unsigned long flags;
+ kbase_device *kbdev;
+ kbasep_js_device_data *js_devdata;
+ int i;
+
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ js_devdata = &kbdev->js_data;
+
+ /* Cancel any remaining running jobs for this kctx */
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ for (i = 0; i < kbdev->gpu_props.num_job_slots; i++)
+ kbase_job_slot_hardstop(kctx, i, NULL);
+
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+}
+
+void kbase_job_zap_context(kbase_context *kctx)
+{
+ kbase_device *kbdev;
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_kctx_info *js_kctx_info;
+ int i;
+ mali_bool evict_success;
+
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ js_devdata = &kbdev->js_data;
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ /*
+ * Critical assumption: No more submission is possible outside of the
+ * workqueue. This is because the OS *must* prevent U/K calls (IOCTLs)
+ * whilst the kbase_context is terminating.
+ */
+
+ /* First, atomically do the following:
+ * - mark the context as dying
+ * - try to evict it from the policy queue */
+
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+ js_kctx_info->ctx.is_dying = MALI_TRUE;
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "Zap: Try Evict Ctx %p", kctx);
+ mutex_lock(&js_devdata->queue_mutex);
+ evict_success = kbasep_js_policy_try_evict_ctx(&js_devdata->policy, kctx);
+ mutex_unlock(&js_devdata->queue_mutex);
+
+ /*
+ * At this point we know:
+ * - If eviction succeeded, it was in the policy queue, but now no longer is
+ * - We must cancel the jobs here. No Power Manager active reference to
+ * release.
+ * - This happens asynchronously - kbase_jd_zap_context() will wait for
+ * those jobs to be killed.
+ * - If eviction failed, then it wasn't in the policy queue. It is one of
+ * the following:
+ * - a. it didn't have any jobs, and so is not in the Policy Queue or the
+ * Run Pool (not scheduled)
+ * - Hence, no more work required to cancel jobs. No Power Manager active
+ * reference to release.
+ * - b. it was in the middle of a scheduling transaction (and thus must
+ * have at least 1 job). This can happen from a syscall or a kernel thread.
+ * We still hold the jsctx_mutex, and so the thread must be waiting inside
+ * kbasep_js_try_schedule_head_ctx(), before checking whether the runpool
+ * is full. That thread will continue after we drop the mutex, and will
+ * notice the context is dying. It will rollback the transaction, killing
+ * all jobs at the same time. kbase_jd_zap_context() will wait for those
+ * jobs to be killed.
+ * - Hence, no more work required to cancel jobs, or to release the Power
+ * Manager active reference.
+ * - c. it is scheduled, and may or may not be running jobs
+ * - We must cause it to leave the runpool by stopping it from submitting
+ * any more jobs. When it finally does leave,
+ * kbasep_js_runpool_requeue_or_kill_ctx() will kill all remaining jobs
+ * (because it is dying), release the Power Manager active reference, and
+ * will not requeue the context in the policy queue. kbase_jd_zap_context()
+ * will wait for those jobs to be killed.
+ * - Hence, work required just to make it leave the runpool. Cancelling
+ * jobs and releasing the Power manager active reference will be handled
+ * when it leaves the runpool.
+ */
+
+ if (evict_success != MALI_FALSE || js_kctx_info->ctx.is_scheduled == MALI_FALSE) {
+ /* The following events require us to kill off remaining jobs and
+ * update PM book-keeping:
+ * - we evicted it correctly (it must have jobs to be in the Policy Queue)
+ *
+ * These events need no action, but take this path anyway:
+ * - Case a: it didn't have any jobs, and was never in the Queue
+ * - Case b: scheduling transaction will be partially rolled-back (this
+ * already cancels the jobs)
+ */
+
+ KBASE_TRACE_ADD(kbdev, JM_ZAP_NON_SCHEDULED, kctx, NULL, 0u, js_kctx_info->ctx.is_scheduled);
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "Zap: Ctx %p evict_success=%d, scheduled=%d", kctx, evict_success, js_kctx_info->ctx.is_scheduled);
+
+ if (evict_success != MALI_FALSE) {
+ /* Only cancel jobs when we evicted from the policy queue. No Power
+ * Manager active reference was held.
+ *
+ * Having is_dying set ensures that this kills, and doesn't requeue */
+ kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_FALSE);
+ }
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+ } else {
+ unsigned long flags;
+ mali_bool was_retained;
+ /* Case c: didn't evict, but it is scheduled - it's in the Run Pool */
+ KBASE_TRACE_ADD(kbdev, JM_ZAP_SCHEDULED, kctx, NULL, 0u, js_kctx_info->ctx.is_scheduled);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "Zap: Ctx %p is in RunPool", kctx);
+
+ /* Disable the ctx from submitting any more jobs */
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ kbasep_js_clear_submit_allowed(js_devdata, kctx);
+
+ /* Retain and (later) release the context whilst it is is now disallowed from submitting
+ * jobs - ensures that someone somewhere will be removing the context later on */
+ was_retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx);
+
+ /* Since it's scheduled and we have the jsctx_mutex, it must be retained successfully */
+ KBASE_DEBUG_ASSERT(was_retained != MALI_FALSE);
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "Zap: Ctx %p Kill Any Running jobs", kctx);
+ /* Cancel any remaining running jobs for this kctx - if any. Submit is disallowed
+ * which takes effect immediately, so no more new jobs will appear after we do this. */
+ for (i = 0; i < kbdev->gpu_props.num_job_slots; i++)
+ kbase_job_slot_hardstop(kctx, i, NULL);
+
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "Zap: Ctx %p Release (may or may not schedule out immediately)", kctx);
+ kbasep_js_runpool_release_ctx(kbdev, kctx);
+ }
+ KBASE_TRACE_ADD(kbdev, JM_ZAP_DONE, kctx, NULL, 0u, 0u);
+
+ /* After this, you must wait on both the kbase_jd_context::zero_jobs_wait
+ * and the kbasep_js_kctx_info::ctx::is_scheduled_waitq - to wait for the
+ * jobs to be destroyed, and the context to be de-scheduled (if it was on
+ * the runpool).
+ *
+ * kbase_jd_zap_context() will do this. */
+}
+KBASE_EXPORT_TEST_API(kbase_job_zap_context)
+
+mali_error kbase_job_slot_init(kbase_device *kbdev)
+{
+ int i;
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ for (i = 0; i < kbdev->gpu_props.num_job_slots; i++)
+ kbasep_jm_init_submit_slot(&kbdev->jm_slots[i]);
+
+ return MALI_ERROR_NONE;
+}
+KBASE_EXPORT_TEST_API(kbase_job_slot_init)
+
+void kbase_job_slot_halt(kbase_device *kbdev)
+{
+ CSTD_UNUSED(kbdev);
+}
+
+void kbase_job_slot_term(kbase_device *kbdev)
+{
+ KBASE_DEBUG_ASSERT(kbdev);
+}
+KBASE_EXPORT_TEST_API(kbase_job_slot_term)
+
+/**
+ * Soft-stop the specified job slot
+ *
+ * The job slot lock must be held when calling this function.
+ * The job slot must not already be in the process of being soft-stopped.
+ *
+ * Where possible any job in the next register is evicted before the soft-stop.
+ *
+ * @param kbdev The kbase device
+ * @param js The job slot to soft-stop
+ * @param target_katom The job that should be soft-stopped (or NULL for any job)
+ */
+void kbase_job_slot_softstop(kbase_device *kbdev, int js, kbase_jd_atom *target_katom)
+{
+ kbasep_job_slot_soft_or_hard_stop(kbdev, NULL, js, target_katom, JSn_COMMAND_SOFT_STOP);
+}
+
+/**
+ * Hard-stop the specified job slot
+ *
+ * The job slot lock must be held when calling this function.
+ *
+ * @param kctx The kbase context that contains the job(s) that should be hard-stopped
+ * @param js The job slot to hard-stop
+ * @param target_katom The job that should be hard-stopped (or NULL for all jobs from the context)
+ */
+void kbase_job_slot_hardstop(kbase_context *kctx, int js, kbase_jd_atom *target_katom)
+{
+ kbase_device *kbdev = kctx->kbdev;
+ kbasep_job_slot_soft_or_hard_stop(kbdev, kctx, js, target_katom, JSn_COMMAND_HARD_STOP);
+
+ if (kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_8401) || kbase_hw_has_issue(kctx->kbdev, BASE_HW_ISSUE_9510)) {
+ /* The workaround for HW issue 8401 has an issue, so instead of hard-stopping
+ * just reset the GPU. This will ensure that the jobs leave the GPU.
+ */
+ if (kbase_prepare_to_reset_gpu_locked(kbdev)) {
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JD, "Issueing GPU soft-reset instead of hard stopping job due to a hardware issue");
+ kbase_reset_gpu_locked(kbdev);
+ }
+ }
+}
+
+void kbasep_reset_timeout_worker(struct work_struct *data)
+{
+ unsigned long flags;
+ kbase_device *kbdev;
+ int i;
+ ktime_t end_timestamp = ktime_get();
+ kbasep_js_device_data *js_devdata;
+ kbase_uk_hwcnt_setup hwcnt_setup = { {0} };
+ kbase_instr_state bckp_state;
+
+ KBASE_DEBUG_ASSERT(data);
+
+ kbdev = container_of(data, kbase_device, reset_work);
+
+ KBASE_DEBUG_ASSERT(kbdev);
+ js_devdata = &kbdev->js_data;
+
+ KBASE_TRACE_ADD(kbdev, JM_BEGIN_RESET_WORKER, NULL, NULL, 0u, 0);
+
+ /* Make sure the timer has completed - this cannot be done from interrupt context,
+ * so this cannot be done within kbasep_try_reset_gpu_early. */
+ hrtimer_cancel(&kbdev->reset_timer);
+
+ if (kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) {
+ /* This would re-activate the GPU. Since it's already idle, there's no
+ * need to reset it */
+ atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_NOT_PENDING);
+ wake_up(&kbdev->reset_wait);
+ return;
+ }
+
+ mutex_lock(&kbdev->pm.lock);
+ /* We hold the pm lock, so there ought to be a current policy */
+ KBASE_DEBUG_ASSERT(kbdev->pm.pm_current_policy);
+
+ /* All slot have been soft-stopped and we've waited SOFT_STOP_RESET_TIMEOUT for the slots to clear, at this point
+ * we assume that anything that is still left on the GPU is stuck there and we'll kill it when we reset the GPU */
+
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JD, "Resetting GPU (allowing up to %d ms)", RESET_TIMEOUT);
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+
+ if (kbdev->hwcnt.state == KBASE_INSTR_STATE_RESETTING) { /*the same interrupt handler preempted itself */
+ /* GPU is being reset */
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ wait_event(kbdev->hwcnt.wait, kbdev->hwcnt.triggered != 0);
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ }
+ /* Save the HW counters setup */
+ if (kbdev->hwcnt.kctx != NULL) {
+ kbase_context *kctx = kbdev->hwcnt.kctx;
+ hwcnt_setup.dump_buffer = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), kctx) & 0xffffffff;
+ hwcnt_setup.dump_buffer |= (mali_addr64) kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), kctx) << 32;
+ hwcnt_setup.jm_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), kctx);
+ hwcnt_setup.shader_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), kctx);
+ hwcnt_setup.tiler_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), kctx);
+ hwcnt_setup.l3_cache_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_L3_CACHE_EN), kctx);
+ hwcnt_setup.mmu_l2_bm = kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), kctx);
+ }
+ bckp_state = kbdev->hwcnt.state;
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_RESETTING;
+ kbdev->hwcnt.triggered = 0;
+ /* Disable IRQ to avoid IRQ handlers to kick in after releaseing the spinlock;
+ * this also clears any outstanding interrupts */
+ kbase_pm_disable_interrupts(kbdev);
+ /* Ensure that any IRQ handlers have finished */
+ kbase_synchronize_irqs(kbdev);
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+
+ /* Reset the GPU */
+ kbase_pm_init_hw(kbdev, MALI_TRUE);
+ /* IRQs were re-enabled by kbase_pm_init_hw, and GPU is still powered */
+
+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
+ /* Restore the HW counters setup */
+ if (kbdev->hwcnt.kctx != NULL) {
+ kbase_context *kctx = kbdev->hwcnt.kctx;
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_OFF, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), hwcnt_setup.dump_buffer & 0xFFFFFFFF, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), hwcnt_setup.dump_buffer >> 32, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), hwcnt_setup.jm_bm, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), hwcnt_setup.shader_bm, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_L3_CACHE_EN), hwcnt_setup.l3_cache_bm, kctx);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), hwcnt_setup.mmu_l2_bm, kctx);
+
+ /* Due to PRLAM-8186 we need to disable the Tiler before we enable the HW counter dump. */
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186))
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), 0, kctx);
+ else
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), hwcnt_setup.tiler_bm, kctx);
+
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), (kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT) | PRFCNT_CONFIG_MODE_MANUAL, kctx);
+
+ /* If HW has PRLAM-8186 we can now re-enable the tiler HW counters dump */
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186))
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), hwcnt_setup.tiler_bm, kctx);
+ }
+ kbdev->hwcnt.state = bckp_state;
+ switch(kbdev->hwcnt.state) {
+ /* Cases for waking kbasep_cache_clean_worker worker */
+ case KBASE_INSTR_STATE_CLEANED:
+ /* Cache-clean IRQ occurred, but we reset:
+ * Wakeup incase the waiter saw RESETTING */
+ case KBASE_INSTR_STATE_REQUEST_CLEAN:
+ /* After a clean was requested, but before the regs were written:
+ * Wakeup incase the waiter saw RESETTING */
+ wake_up(&kbdev->hwcnt.cache_clean_wait);
+ break;
+ case KBASE_INSTR_STATE_CLEANING:
+ /* Either:
+ * 1) We've not got the Cache-clean IRQ yet: it was lost, or:
+ * 2) We got it whilst resetting: it was voluntarily lost
+ *
+ * So, move to the next state and wakeup: */
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_CLEANED;
+ wake_up(&kbdev->hwcnt.cache_clean_wait);
+ break;
+
+ /* Cases for waking anyone else */
+ case KBASE_INSTR_STATE_DUMPING:
+ /* If dumping, abort the dump, because we may've lost the IRQ */
+ kbdev->hwcnt.state = KBASE_INSTR_STATE_IDLE;
+ kbdev->hwcnt.triggered = 1;
+ wake_up(&kbdev->hwcnt.wait);
+ break;
+ case KBASE_INSTR_STATE_DISABLED:
+ case KBASE_INSTR_STATE_IDLE:
+ case KBASE_INSTR_STATE_FAULT:
+ /* Every other reason: wakeup in that state */
+ kbdev->hwcnt.triggered = 1;
+ wake_up(&kbdev->hwcnt.wait);
+ break;
+
+ /* Unhandled cases */
+ case KBASE_INSTR_STATE_RESETTING:
+ default:
+ BUG();
+ break;
+ }
+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+
+ /* Complete any jobs that were still on the GPU */
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) {
+ int nr_done;
+ kbase_jm_slot *slot = &kbdev->jm_slots[i];
+
+ nr_done = kbasep_jm_nr_jobs_submitted(slot);
+ while (nr_done) {
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JD, "Job stuck in slot %d on the GPU was cancelled", i);
+ kbase_job_done_slot(kbdev, i, BASE_JD_EVENT_JOB_CANCELLED, 0, &end_timestamp);
+ nr_done--;
+ }
+ }
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+
+ mutex_lock(&js_devdata->runpool_mutex);
+
+ /* Reprogram the GPU's MMU */
+ for (i = 0; i < BASE_MAX_NR_AS; i++) {
+ if (js_devdata->runpool_irq.per_as_data[i].kctx) {
+ kbase_as *as = &kbdev->as[i];
+ mutex_lock(&as->transaction_mutex);
+ kbase_mmu_update(js_devdata->runpool_irq.per_as_data[i].kctx);
+ mutex_unlock(&as->transaction_mutex);
+ }
+ }
+
+ atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_NOT_PENDING);
+ wake_up(&kbdev->reset_wait);
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JD, "Reset complete");
+
+ /* Find out what cores are required now */
+ kbase_pm_update_cores_state(kbdev);
+
+ /* Synchronously request and wait for those cores, because if
+ * instrumentation is enabled it would need them immediately. */
+ kbase_pm_check_transitions_sync(kbdev);
+
+ /* Try submitting some jobs to restart processing */
+ if (js_devdata->nr_user_contexts_running > 0) {
+ KBASE_TRACE_ADD(kbdev, JM_SUBMIT_AFTER_RESET, NULL, NULL, 0u, 0);
+
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ kbasep_js_try_run_next_job_nolock(kbdev);
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ }
+ mutex_unlock(&js_devdata->runpool_mutex);
+ mutex_unlock(&kbdev->pm.lock);
+
+ kbase_pm_context_idle(kbdev);
+ KBASE_TRACE_ADD(kbdev, JM_END_RESET_WORKER, NULL, NULL, 0u, 0);
+}
+
+enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *timer)
+{
+ kbase_device *kbdev = container_of(timer, kbase_device, reset_timer);
+
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ /* Reset still pending? */
+ if (atomic_cmpxchg(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) == KBASE_RESET_GPU_COMMITTED)
+ queue_work(kbdev->reset_workq, &kbdev->reset_work);
+
+ return HRTIMER_NORESTART;
+}
+
+/*
+ * If all jobs are evicted from the GPU then we can reset the GPU
+ * immediately instead of waiting for the timeout to elapse
+ */
+
+static void kbasep_try_reset_gpu_early_locked(kbase_device *kbdev)
+{
+ int i;
+ int pending_jobs = 0;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ /* Count the number of jobs */
+ for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) {
+ kbase_jm_slot *slot = &kbdev->jm_slots[i];
+ pending_jobs += kbasep_jm_nr_jobs_submitted(slot);
+ }
+
+ if (pending_jobs > 0) {
+ /* There are still jobs on the GPU - wait */
+ return;
+ }
+
+ /* Check that the reset has been committed to (i.e. kbase_reset_gpu has been called), and that no other
+ * thread beat this thread to starting the reset */
+ if (atomic_cmpxchg(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) != KBASE_RESET_GPU_COMMITTED) {
+ /* Reset has already occurred */
+ return;
+ }
+ queue_work(kbdev->reset_workq, &kbdev->reset_work);
+}
+
+static void kbasep_try_reset_gpu_early(kbase_device *kbdev)
+{
+ unsigned long flags;
+ kbasep_js_device_data *js_devdata;
+
+ js_devdata = &kbdev->js_data;
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ kbasep_try_reset_gpu_early_locked(kbdev);
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+}
+
+/*
+ * Prepare for resetting the GPU.
+ * This function just soft-stops all the slots to ensure that as many jobs as possible are saved.
+ *
+ * The function returns a boolean which should be interpreted as follows:
+ * - MALI_TRUE - Prepared for reset, kbase_reset_gpu should be called.
+ * - MALI_FALSE - Another thread is performing a reset, kbase_reset_gpu should not be called.
+ *
+ * @return See description
+ */
+mali_bool kbase_prepare_to_reset_gpu_locked(kbase_device *kbdev)
+{
+ int i;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ if (atomic_cmpxchg(&kbdev->reset_gpu, KBASE_RESET_GPU_NOT_PENDING, KBASE_RESET_GPU_PREPARED) != KBASE_RESET_GPU_NOT_PENDING) {
+ /* Some other thread is already resetting the GPU */
+ return MALI_FALSE;
+ }
+
+ for (i = 0; i < kbdev->gpu_props.num_job_slots; i++)
+ kbase_job_slot_softstop(kbdev, i, NULL);
+
+ return MALI_TRUE;
+}
+
+mali_bool kbase_prepare_to_reset_gpu(kbase_device *kbdev)
+{
+ unsigned long flags;
+ mali_bool ret;
+ kbasep_js_device_data *js_devdata;
+
+ js_devdata = &kbdev->js_data;
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ ret = kbase_prepare_to_reset_gpu_locked(kbdev);
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+
+ return ret;
+}
+KBASE_EXPORT_TEST_API(kbase_prepare_to_reset_gpu)
+
+/*
+ * This function should be called after kbase_prepare_to_reset_gpu iff it returns MALI_TRUE.
+ * It should never be called without a corresponding call to kbase_prepare_to_reset_gpu.
+ *
+ * After this function is called (or not called if kbase_prepare_to_reset_gpu returned MALI_FALSE),
+ * the caller should wait for kbdev->reset_waitq to be signalled to know when the reset has completed.
+ */
+void kbase_reset_gpu(kbase_device *kbdev)
+{
+ u32 timeout_ms;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ /* Note this is an assert/atomic_set because it is a software issue for a race to be occuring here */
+ KBASE_DEBUG_ASSERT(atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_PREPARED);
+ atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED);
+
+ timeout_ms = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS);
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JD, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", timeout_ms);
+ hrtimer_start(&kbdev->reset_timer, HR_TIMER_DELAY_MSEC(timeout_ms), HRTIMER_MODE_REL);
+
+ /* Try resetting early */
+ kbasep_try_reset_gpu_early(kbdev);
+}
+KBASE_EXPORT_TEST_API(kbase_reset_gpu)
+
+void kbase_reset_gpu_locked(kbase_device *kbdev)
+{
+ u32 timeout_ms;
+
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ /* Note this is an assert/atomic_set because it is a software issue for a race to be occuring here */
+ KBASE_DEBUG_ASSERT(atomic_read(&kbdev->reset_gpu) == KBASE_RESET_GPU_PREPARED);
+ atomic_set(&kbdev->reset_gpu, KBASE_RESET_GPU_COMMITTED);
+
+ timeout_ms = kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS);
+ KBASE_DEBUG_PRINT_ERROR(KBASE_JD, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", timeout_ms);
+ hrtimer_start(&kbdev->reset_timer, HR_TIMER_DELAY_MSEC(timeout_ms), HRTIMER_MODE_REL);
+
+ /* Try resetting early */
+ kbasep_try_reset_gpu_early_locked(kbdev);
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jm.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jm.h
new file mode 100755
index 00000000000..6bd70865984
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_jm.h
@@ -0,0 +1,202 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_jm.h
+ * Job Manager Low-level APIs.
+ */
+
+#ifndef _KBASE_JM_H_
+#define _KBASE_JM_H_
+
+#include <kbase/src/common/mali_kbase_8401_workaround.h>
+#include <kbase/src/common/mali_kbase_hw.h>
+#include <linux/atomic.h>
+
+/**
+ * @addtogroup base_api
+ * @{
+ */
+
+/**
+ * @addtogroup base_kbase_api
+ * @{
+ */
+
+/**
+ * @addtogroup kbase_jm Job Manager Low-level APIs
+ * @{
+ *
+ */
+
+static INLINE int kbasep_jm_is_js_free(kbase_device *kbdev, int js, kbase_context *kctx)
+{
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(0 <= js && js < kbdev->gpu_props.num_job_slots);
+
+ return !kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), kctx);
+}
+
+/**
+ * This checks that:
+ * - there is enough space in the GPU's buffers (JSn_NEXT and JSn_HEAD registers) to accomodate the job.
+ * - there is enough space to track the job in a our Submit Slots. Note that we have to maintain space to
+ * requeue one job in case the next registers on the hardware need to be cleared.
+ */
+static INLINE mali_bool kbasep_jm_is_submit_slots_free(kbase_device *kbdev, int js, kbase_context *kctx)
+{
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(0 <= js && js < kbdev->gpu_props.num_job_slots);
+
+ if (atomic_read(&kbdev->reset_gpu) != KBASE_RESET_GPU_NOT_PENDING) {
+ /* The GPU is being reset - so prevent submission */
+ return MALI_FALSE;
+ }
+
+ return (mali_bool) (kbasep_jm_is_js_free(kbdev, js, kctx)
+ && kbdev->jm_slots[js].submitted_nr < (BASE_JM_SUBMIT_SLOTS - 2));
+}
+
+/**
+ * Initialize a submit slot
+ */
+static INLINE void kbasep_jm_init_submit_slot(kbase_jm_slot *slot)
+{
+ slot->submitted_nr = 0;
+ slot->submitted_head = 0;
+}
+
+/**
+ * Find the atom at the idx'th element in the queue without removing it, starting at the head with idx==0.
+ */
+static INLINE kbase_jd_atom *kbasep_jm_peek_idx_submit_slot(kbase_jm_slot *slot, u8 idx)
+{
+ u8 pos;
+ kbase_jd_atom *katom;
+
+ KBASE_DEBUG_ASSERT(idx < BASE_JM_SUBMIT_SLOTS);
+
+ pos = (slot->submitted_head + idx) & BASE_JM_SUBMIT_SLOTS_MASK;
+ katom = slot->submitted[pos];
+
+ return katom;
+}
+
+/**
+ * Pop front of the submitted
+ */
+static INLINE kbase_jd_atom *kbasep_jm_dequeue_submit_slot(kbase_jm_slot *slot)
+{
+ u8 pos;
+ kbase_jd_atom *katom;
+
+ pos = slot->submitted_head & BASE_JM_SUBMIT_SLOTS_MASK;
+ katom = slot->submitted[pos];
+ slot->submitted[pos] = NULL; /* Just to catch bugs... */
+ KBASE_DEBUG_ASSERT(katom);
+
+ /* rotate the buffers */
+ slot->submitted_head = (slot->submitted_head + 1) & BASE_JM_SUBMIT_SLOTS_MASK;
+ slot->submitted_nr--;
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "katom %p new head %u", (void *)katom, (unsigned int)slot->submitted_head);
+
+ return katom;
+}
+
+/* Pop back of the submitted queue (unsubmit a job)
+ */
+static INLINE kbase_jd_atom *kbasep_jm_dequeue_tail_submit_slot(kbase_jm_slot *slot)
+{
+ u8 pos;
+
+ slot->submitted_nr--;
+
+ pos = (slot->submitted_head + slot->submitted_nr) & BASE_JM_SUBMIT_SLOTS_MASK;
+
+ return slot->submitted[pos];
+}
+
+static INLINE u8 kbasep_jm_nr_jobs_submitted(kbase_jm_slot *slot)
+{
+ return slot->submitted_nr;
+}
+
+/**
+ * Push back of the submitted
+ */
+static INLINE void kbasep_jm_enqueue_submit_slot(kbase_jm_slot *slot, kbase_jd_atom *katom)
+{
+ u8 nr;
+ u8 pos;
+ nr = slot->submitted_nr++;
+ KBASE_DEBUG_ASSERT(nr < BASE_JM_SUBMIT_SLOTS);
+
+ pos = (slot->submitted_head + nr) & BASE_JM_SUBMIT_SLOTS_MASK;
+ slot->submitted[pos] = katom;
+}
+
+/**
+ * @brief Query whether a job peeked/dequeued from the submit slots is a
+ * 'dummy' job that is used for hardware workaround purposes.
+ *
+ * Any time a job is peeked/dequeued from the submit slots, this should be
+ * queried on that job.
+ *
+ * If a \a atom is indicated as being a dummy job, then you <b>must not attempt
+ * to use \a atom</b>. This is because its members will not necessarily be
+ * initialized, and so could lead to a fault if they were used.
+ *
+ * @param[in] kbdev kbase device pointer
+ * @param[in] atom The atom to query
+ *
+ * @return MALI_TRUE if \a atom is for a dummy job, in which case you must not
+ * attempt to use it.
+ * @return MALI_FALSE otherwise, and \a atom is safe to use.
+ */
+static INLINE mali_bool kbasep_jm_is_dummy_workaround_job(kbase_device *kbdev, kbase_jd_atom *atom)
+{
+ /* Query the set of workaround jobs here */
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8401)) {
+ if (kbasep_8401_is_workaround_job(atom) != MALI_FALSE)
+ return MALI_TRUE;
+ }
+
+ /* This job is not a workaround job, so it will be processed as normal */
+ return MALI_FALSE;
+}
+
+/**
+ * @brief Submit a job to a certain job-slot
+ *
+ * The caller must check kbasep_jm_is_submit_slots_free() != MALI_FALSE before calling this.
+ *
+ * The following locking conditions are made on the caller:
+ * - it must hold the kbasep_js_device_data::runpoool_irq::lock
+ */
+void kbase_job_submit_nolock(kbase_device *kbdev, kbase_jd_atom *katom, int js);
+
+/**
+ * @brief Complete the head job on a particular job-slot
+ */
+void kbase_job_done_slot(kbase_device *kbdev, int s, u32 completion_code, u64 job_tail, ktime_t *end_timestamp);
+
+ /** @} *//* end group kbase_jm */
+ /** @} *//* end group base_kbase_api */
+ /** @} *//* end group base_api */
+
+#endif /* _KBASE_JM_H_ */
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js.c b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js.c
new file mode 100755
index 00000000000..66bf4c170be
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js.c
@@ -0,0 +1,2122 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/*
+ * Job Scheduler Implementation
+ */
+#include <kbase/src/common/mali_kbase.h>
+#include <kbase/src/common/mali_kbase_js.h>
+#include <kbase/src/common/mali_kbase_js_affinity.h>
+#include <kbase/src/common/mali_kbase_gator.h>
+#include <kbase/src/common/mali_kbase_hw.h>
+
+#include "mali_kbase_jm.h"
+#include <kbase/src/common/mali_kbase_defs.h>
+
+/*
+ * Private types
+ */
+
+/** Bitpattern indicating the result of releasing a context */
+enum {
+ /** The context was descheduled - caller should try scheduling in a new one
+ * to keep the runpool full */
+ KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED = (1u << 0),
+};
+
+typedef u32 kbasep_js_release_result;
+
+/*
+ * Private function prototypes
+ */
+STATIC INLINE void kbasep_js_deref_permon_check_and_disable_cycle_counter(kbase_device *kbdev, kbase_jd_atom *katom);
+
+STATIC INLINE void kbasep_js_ref_permon_check_and_enable_cycle_counter(kbase_device *kbdev, kbase_jd_atom *katom);
+
+STATIC kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(kbase_device *kbdev, kbase_context *kctx, kbasep_js_atom_retained_state *katom_retained_state);
+
+/** Helper for trace subcodes */
+#if KBASE_TRACE_ENABLE != 0
+STATIC int kbasep_js_trace_get_refcnt(kbase_device *kbdev, kbase_context *kctx)
+{
+ unsigned long flags;
+ kbasep_js_device_data *js_devdata;
+ int as_nr;
+ int refcnt = 0;
+
+ js_devdata = &kbdev->js_data;
+
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ as_nr = kctx->as_nr;
+ if (as_nr != KBASEP_AS_NR_INVALID) {
+ kbasep_js_per_as_data *js_per_as_data;
+ js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr];
+
+ refcnt = js_per_as_data->as_busy_refcount;
+ }
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+
+ return refcnt;
+}
+#else /* KBASE_TRACE_ENABLE != 0 */
+STATIC int kbasep_js_trace_get_refcnt(kbase_device *kbdev, kbase_context *kctx)
+{
+ CSTD_UNUSED(kbdev);
+ CSTD_UNUSED(kctx);
+ return 0;
+}
+#endif /* KBASE_TRACE_ENABLE != 0 */
+
+/*
+ * Private types
+ */
+enum {
+ JS_DEVDATA_INIT_NONE = 0,
+ JS_DEVDATA_INIT_CONSTANTS = (1 << 0),
+ JS_DEVDATA_INIT_POLICY = (1 << 1),
+ JS_DEVDATA_INIT_ALL = ((1 << 2) - 1)
+};
+
+enum {
+ JS_KCTX_INIT_NONE = 0,
+ JS_KCTX_INIT_CONSTANTS = (1 << 0),
+ JS_KCTX_INIT_POLICY = (1 << 1),
+ JS_KCTX_INIT_ALL = ((1 << 2) - 1)
+};
+
+/*
+ * Private functions
+ */
+
+/**
+ * Check if the job had performance monitoring enabled and decrement the count. If no jobs require
+ * performance monitoring, then the cycle counters will be disabled in the GPU.
+ *
+ * No locks need to be held - locking is handled further down
+ *
+ * This function does not sleep.
+ */
+
+STATIC INLINE void kbasep_js_deref_permon_check_and_disable_cycle_counter(kbase_device *kbdev, kbase_jd_atom *katom)
+{
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(katom != NULL);
+
+ if (katom->core_req & BASE_JD_REQ_PERMON)
+ kbase_pm_release_gpu_cycle_counter(kbdev);
+}
+
+/**
+ * Check if the job has performance monitoring enabled and keep a count of it. If at least one
+ * job requires performance monitoring, then the cycle counters will be enabled in the GPU.
+ *
+ * No locks need to be held - locking is handled further down
+ *
+ * This function does not sleep.
+ */
+
+STATIC INLINE void kbasep_js_ref_permon_check_and_enable_cycle_counter(kbase_device *kbdev, kbase_jd_atom *katom)
+{
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(katom != NULL);
+
+ if (katom->core_req & BASE_JD_REQ_PERMON)
+ kbase_pm_request_gpu_cycle_counter(kbdev);
+}
+
+/*
+ * The following locking conditions are made on the caller:
+ * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex.
+ * - The caller must hold the kbasep_js_device_data::runpool_mutex
+ */
+STATIC INLINE void runpool_inc_context_count(kbase_device *kbdev, kbase_context *kctx)
+{
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_kctx_info *js_kctx_info;
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+
+ js_devdata = &kbdev->js_data;
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex));
+ BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex));
+
+ /* Track total contexts */
+ ++(js_devdata->nr_all_contexts_running);
+
+ if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) == 0) {
+ /* Track contexts that can submit jobs */
+ ++(js_devdata->nr_user_contexts_running);
+ }
+}
+
+/*
+ * The following locking conditions are made on the caller:
+ * - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex.
+ * - The caller must hold the kbasep_js_device_data::runpool_mutex
+ */
+STATIC INLINE void runpool_dec_context_count(kbase_device *kbdev, kbase_context *kctx)
+{
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_kctx_info *js_kctx_info;
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+
+ js_devdata = &kbdev->js_data;
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ BUG_ON(!mutex_is_locked(&js_kctx_info->ctx.jsctx_mutex));
+ BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex));
+
+ /* Track total contexts */
+ --(js_devdata->nr_all_contexts_running);
+
+ if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) == 0) {
+ /* Track contexts that can submit jobs */
+ --(js_devdata->nr_user_contexts_running);
+ }
+}
+
+/**
+ * @brief check whether the runpool is full for a specified context
+ *
+ * If kctx == NULL, then this makes the least restrictive check on the
+ * runpool. A specific context that is supplied immediately after could fail
+ * the check, even under the same conditions.
+ *
+ * Therefore, once a context is obtained you \b must re-check it with this
+ * function, since the return value could change to MALI_FALSE.
+ *
+ * The following locking conditions are made on the caller:
+ * - In all cases, the caller must hold kbasep_js_device_data::runpool_mutex
+ * - When kctx != NULL the caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex.
+ * - When kctx == NULL, then the caller need not hold any jsctx_mutex locks (but it doesn't do any harm to do so).
+ */
+STATIC mali_bool check_is_runpool_full(kbase_device *kbdev, kbase_context *kctx)
+{
+ kbasep_js_device_data *js_devdata;
+ mali_bool is_runpool_full;
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ js_devdata = &kbdev->js_data;
+ BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex));
+
+ /* Regardless of whether a context is submitting or not, can't have more than there
+ * are HW address spaces */
+ is_runpool_full = (mali_bool) (js_devdata->nr_all_contexts_running >= kbdev->nr_hw_address_spaces);
+
+ if (kctx != NULL && (kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_SUBMIT_DISABLED) == 0) {
+ BUG_ON(!mutex_is_locked(&kctx->jctx.sched_info.ctx.jsctx_mutex));
+ /* Contexts that submit might use less of the address spaces available, due to HW
+ * workarounds. In which case, the runpool is also full when the number of
+ * submitting contexts exceeds the number of submittable address spaces.
+ *
+ * Both checks must be made: can have nr_user_address_spaces == nr_hw_address spaces,
+ * and at the same time can have nr_user_contexts_running < nr_all_contexts_running. */
+ is_runpool_full |= (mali_bool) (js_devdata->nr_user_contexts_running >= kbdev->nr_user_address_spaces);
+ }
+
+ return is_runpool_full;
+}
+
+STATIC base_jd_core_req core_reqs_from_jsn_features(u16 features) /* JS<n>_FEATURE register value */
+{
+ base_jd_core_req core_req = 0u;
+
+ if ((features & JSn_FEATURE_SET_VALUE_JOB) != 0)
+ core_req |= BASE_JD_REQ_V;
+
+ if ((features & JSn_FEATURE_CACHE_FLUSH_JOB) != 0)
+ core_req |= BASE_JD_REQ_CF;
+
+ if ((features & JSn_FEATURE_COMPUTE_JOB) != 0)
+ core_req |= BASE_JD_REQ_CS;
+
+ if ((features & JSn_FEATURE_TILER_JOB) != 0)
+ core_req |= BASE_JD_REQ_T;
+
+ if ((features & JSn_FEATURE_FRAGMENT_JOB) != 0)
+ core_req |= BASE_JD_REQ_FS;
+
+ return core_req;
+}
+
+/**
+ * Picks and reserves an address space.
+ *
+ * When this function returns, the address space returned is reserved and
+ * cannot be picked for another context until it is released.
+ *
+ * The caller must ensure there \b is a free address space before calling this.
+ *
+ * The following locking conditions are made on the caller:
+ * - it must hold kbasep_js_device_data::runpool_mutex
+ *
+ * @return a non-NULL pointer to a kbase_as that is not in use by any other context
+ */
+STATIC kbase_as *pick_free_addr_space(kbase_device *kbdev)
+{
+ kbasep_js_device_data *js_devdata;
+ kbase_as *current_as;
+ long ffs_result;
+ js_devdata = &kbdev->js_data;
+
+ lockdep_assert_held(&js_devdata->runpool_mutex);
+
+ /* Find the free address space */
+ ffs_result = ffs(js_devdata->as_free) - 1;
+
+ /* ASSERT that we should've found a free one */
+ KBASE_DEBUG_ASSERT(0 <= ffs_result && ffs_result < kbdev->nr_hw_address_spaces);
+ /* Ensure no-one else picks this one */
+ js_devdata->as_free &= ~((u16) (1u << ffs_result));
+
+ current_as = &kbdev->as[ffs_result];
+
+ return current_as;
+}
+
+/**
+ * Release an address space, making it available for being picked again.
+ *
+ * The following locking conditions are made on the caller:
+ * - it must hold kbasep_js_device_data::runpool_mutex
+ */
+STATIC INLINE void release_addr_space(kbase_device *kbdev, int kctx_as_nr)
+{
+ kbasep_js_device_data *js_devdata;
+ u16 as_bit = (1u << kctx_as_nr);
+
+ js_devdata = &kbdev->js_data;
+ lockdep_assert_held(&js_devdata->runpool_mutex);
+
+ /* The address space must not already be free */
+ KBASE_DEBUG_ASSERT(!(js_devdata->as_free & as_bit));
+
+ js_devdata->as_free |= as_bit;
+}
+
+/**
+ * Assign an Address Space (AS) to a context, and add the context to the Policy.
+ *
+ * This includes:
+ * - setting up the global runpool_irq structure and the context on the AS
+ * - Activating the MMU on the AS
+ * - Allowing jobs to be submitted on the AS
+ *
+ * Locking conditions:
+ * - Caller must hold the kbasep_js_kctx_info::jsctx_mutex
+ * - Caller must hold the kbasep_js_device_data::runpool_mutex
+ * - Caller must hold AS transaction mutex
+ * - Caller must hold Runpool IRQ lock
+ */
+STATIC void assign_and_activate_kctx_addr_space(kbase_device *kbdev, kbase_context *kctx, kbase_as *current_as)
+{
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_per_as_data *js_per_as_data;
+ int as_nr;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ KBASE_DEBUG_ASSERT(current_as != NULL);
+
+ js_devdata = &kbdev->js_data;
+ as_nr = current_as->number;
+
+ lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex);
+ lockdep_assert_held(&js_devdata->runpool_mutex);
+ lockdep_assert_held(&current_as->transaction_mutex);
+ lockdep_assert_held(&js_devdata->runpool_irq.lock);
+
+ js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr];
+
+ /* Attribute handling */
+ kbasep_js_ctx_attr_runpool_retain_ctx(kbdev, kctx);
+
+ /* Assign addr space */
+ kctx->as_nr = as_nr;
+#ifdef CONFIG_MALI_GATOR_SUPPORT
+ kbase_trace_mali_mmu_as_in_use(kctx->as_nr);
+#endif /* CONFIG_MALI_GATOR_SUPPORT */
+ /* Activate this address space on the MMU */
+ kbase_mmu_update(kctx);
+
+ /* Allow it to run jobs */
+ kbasep_js_set_submit_allowed(js_devdata, kctx);
+
+ /* Book-keeping */
+ js_per_as_data->kctx = kctx;
+ js_per_as_data->as_busy_refcount = 0;
+
+ /* Lastly, add the context to the policy's runpool - this really allows it to run jobs */
+ kbasep_js_policy_runpool_add_ctx(&js_devdata->policy, kctx);
+
+}
+
+void kbasep_js_try_run_next_job_nolock(kbase_device *kbdev)
+{
+ kbasep_js_device_data *js_devdata;
+ int js;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ js_devdata = &kbdev->js_data;
+ lockdep_assert_held(&js_devdata->runpool_mutex);
+ lockdep_assert_held(&js_devdata->runpool_irq.lock);
+
+ /* It's cheap and simple to retest this here - otherwise we burden the
+ * caller with it. In some cases, we do this higher up to optimize out the
+ * spinlock. */
+ if (js_devdata->nr_user_contexts_running == 0)
+ return; /* No contexts present - the GPU might be powered off, so just return */
+
+ for (js = 0; js < kbdev->gpu_props.num_job_slots; ++js)
+ kbasep_js_try_run_next_job_on_slot_nolock(kbdev, js);
+}
+
+/** Hold the kbasep_js_device_data::runpool_irq::lock for this */
+mali_bool kbasep_js_runpool_retain_ctx_nolock(kbase_device *kbdev, kbase_context *kctx)
+{
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_per_as_data *js_per_as_data;
+ mali_bool result = MALI_FALSE;
+ int as_nr;
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ js_devdata = &kbdev->js_data;
+
+ as_nr = kctx->as_nr;
+ if (as_nr != KBASEP_AS_NR_INVALID) {
+ int new_refcnt;
+
+ KBASE_DEBUG_ASSERT(as_nr >= 0);
+ js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr];
+
+ KBASE_DEBUG_ASSERT(js_per_as_data->kctx != NULL);
+
+ new_refcnt = ++(js_per_as_data->as_busy_refcount);
+ KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RETAIN_CTX_NOLOCK, kctx, NULL, 0u, new_refcnt);
+ result = MALI_TRUE;
+ }
+
+ return result;
+}
+
+/*
+ * Functions private to KBase ('Protected' functions)
+ */
+void kbase_js_try_run_jobs(kbase_device *kbdev)
+{
+ kbasep_js_device_data *js_devdata;
+ unsigned long flags;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ js_devdata = &kbdev->js_data;
+
+ mutex_lock(&js_devdata->runpool_mutex);
+ if (js_devdata->nr_user_contexts_running != 0) {
+ /* Only try running jobs when we have contexts present, otherwise the GPU might be powered off. */
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+
+ kbasep_js_try_run_next_job_nolock(kbdev);
+
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ }
+ mutex_unlock(&js_devdata->runpool_mutex);
+}
+
+void kbase_js_try_run_jobs_on_slot(kbase_device *kbdev, int js)
+{
+ unsigned long flags;
+ kbasep_js_device_data *js_devdata;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ js_devdata = &kbdev->js_data;
+
+ mutex_lock(&js_devdata->runpool_mutex);
+ if (js_devdata->nr_user_contexts_running != 0) {
+ /* Only try running jobs when we have contexts present, otherwise the GPU might be powered off. */
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+
+ kbasep_js_try_run_next_job_on_slot_nolock(kbdev, js);
+
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ }
+ mutex_unlock(&js_devdata->runpool_mutex);
+}
+
+mali_error kbasep_js_devdata_init(kbase_device * const kbdev)
+{
+ kbasep_js_device_data *js_devdata;
+ mali_error err;
+ int i;
+ u16 as_present;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ js_devdata = &kbdev->js_data;
+
+ KBASE_DEBUG_ASSERT(js_devdata->init_status == JS_DEVDATA_INIT_NONE);
+
+ /* These two must be recalculated if nr_hw_address_spaces changes (e.g. for HW workarounds) */
+ as_present = (1U << kbdev->nr_hw_address_spaces) - 1;
+ kbdev->nr_user_address_spaces = kbdev->nr_hw_address_spaces;
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8987)) {
+ mali_bool use_workaround_for_security;
+ use_workaround_for_security = (mali_bool) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_SECURE_BUT_LOSS_OF_PERFORMANCE);
+ if (use_workaround_for_security != MALI_FALSE) {
+ KBASE_DEBUG_PRINT(KBASE_JM, "GPU has HW ISSUE 8987, and driver configured for security workaround: 1 address space only");
+ kbdev->nr_user_address_spaces = 1;
+ }
+ }
+#ifdef CONFIG_MALI_DEBUG
+ /* Soft-stop will be disabled on a single context by default unless softstop_always is set */
+ js_devdata->softstop_always = MALI_FALSE;
+#endif /* CONFIG_MALI_DEBUG */
+ js_devdata->nr_all_contexts_running = 0;
+ js_devdata->nr_user_contexts_running = 0;
+ js_devdata->as_free = as_present; /* All ASs initially free */
+ js_devdata->runpool_irq.submit_allowed = 0u; /* No ctx allowed to submit */
+ memset(js_devdata->runpool_irq.ctx_attr_ref_count, 0, sizeof(js_devdata->runpool_irq.ctx_attr_ref_count));
+ memset(js_devdata->runpool_irq.slot_affinities, 0, sizeof(js_devdata->runpool_irq.slot_affinities));
+ js_devdata->runpool_irq.slots_blocked_on_affinity = 0u;
+ memset(js_devdata->runpool_irq.slot_affinity_refcount, 0, sizeof(js_devdata->runpool_irq.slot_affinity_refcount));
+ INIT_LIST_HEAD(&js_devdata->suspended_soft_jobs_list);
+
+ /* Config attributes */
+ js_devdata->scheduling_tick_ns = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS);
+ js_devdata->soft_stop_ticks = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS);
+ js_devdata->hard_stop_ticks_ss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS);
+ js_devdata->hard_stop_ticks_nss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS);
+ js_devdata->gpu_reset_ticks_ss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS);
+ js_devdata->gpu_reset_ticks_nss = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS);
+ js_devdata->ctx_timeslice_ns = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS);
+ js_devdata->cfs_ctx_runtime_init_slices = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_INIT_SLICES);
+ js_devdata->cfs_ctx_runtime_min_slices = (u32) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_MIN_SLICES);
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "JS Config Attribs: ");
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "\tjs_devdata->scheduling_tick_ns:%u", js_devdata->scheduling_tick_ns);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "\tjs_devdata->soft_stop_ticks:%u", js_devdata->soft_stop_ticks);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "\tjs_devdata->hard_stop_ticks_ss:%u", js_devdata->hard_stop_ticks_ss);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "\tjs_devdata->hard_stop_ticks_nss:%u", js_devdata->hard_stop_ticks_nss);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "\tjs_devdata->gpu_reset_ticks_ss:%u", js_devdata->gpu_reset_ticks_ss);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "\tjs_devdata->gpu_reset_ticks_nss:%u", js_devdata->gpu_reset_ticks_nss);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "\tjs_devdata->ctx_timeslice_ns:%u", js_devdata->ctx_timeslice_ns);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "\tjs_devdata->cfs_ctx_runtime_init_slices:%u", js_devdata->cfs_ctx_runtime_init_slices);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "\tjs_devdata->cfs_ctx_runtime_min_slices:%u", js_devdata->cfs_ctx_runtime_min_slices);
+
+#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS != 0
+ KBASE_DEBUG_PRINT(KBASE_JM, "Job Scheduling Policy Soft-stops disabled, ignoring value for soft_stop_ticks==%u at %uns per tick. Other soft-stops may still occur.", js_devdata->soft_stop_ticks, js_devdata->scheduling_tick_ns);
+#endif
+#if KBASE_DISABLE_SCHEDULING_HARD_STOPS != 0
+ KBASE_DEBUG_PRINT(KBASE_JM, "Job Scheduling Policy Hard-stops disabled, ignoring values for hard_stop_ticks_ss==%d and hard_stop_ticks_nss==%u at %uns per tick. Other hard-stops may still occur.", js_devdata->hard_stop_ticks_ss, js_devdata->hard_stop_ticks_nss, js_devdata->scheduling_tick_ns);
+#endif
+#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS != 0 && KBASE_DISABLE_SCHEDULING_HARD_STOPS != 0
+ KBASE_DEBUG_PRINT(KBASE_JM, "Note: The JS policy's tick timer (if coded) will still be run, but do nothing.");
+#endif
+
+ /* setup the number of irq throttle cycles base on given time */
+ {
+ int irq_throttle_time_us = kbdev->gpu_props.irq_throttle_time_us;
+ int irq_throttle_cycles = kbasep_js_convert_us_to_gpu_ticks_max_freq(kbdev, irq_throttle_time_us);
+ atomic_set(&kbdev->irq_throttle_cycles, irq_throttle_cycles);
+ }
+
+ /* Clear the AS data, including setting NULL pointers */
+ memset(&js_devdata->runpool_irq.per_as_data[0], 0, sizeof(js_devdata->runpool_irq.per_as_data));
+
+ for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i)
+ js_devdata->js_reqs[i] = core_reqs_from_jsn_features(kbdev->gpu_props.props.raw_props.js_features[i]);
+
+ js_devdata->init_status |= JS_DEVDATA_INIT_CONSTANTS;
+
+ /* On error, we could continue on: providing none of the below resources
+ * rely on the ones above */
+
+ mutex_init(&js_devdata->runpool_mutex);
+ mutex_init(&js_devdata->queue_mutex);
+ spin_lock_init(&js_devdata->runpool_irq.lock);
+
+ err = kbasep_js_policy_init(kbdev);
+ if (err == MALI_ERROR_NONE)
+ js_devdata->init_status |= JS_DEVDATA_INIT_POLICY;
+
+ /* On error, do no cleanup; this will be handled by the caller(s), since
+ * we've designed this resource to be safe to terminate on init-fail */
+ if (js_devdata->init_status != JS_DEVDATA_INIT_ALL)
+ return MALI_ERROR_FUNCTION_FAILED;
+
+ return MALI_ERROR_NONE;
+}
+
+void kbasep_js_devdata_halt(kbase_device *kbdev)
+{
+ CSTD_UNUSED(kbdev);
+}
+
+void kbasep_js_devdata_term(kbase_device *kbdev)
+{
+ kbasep_js_device_data *js_devdata;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ js_devdata = &kbdev->js_data;
+
+ if ((js_devdata->init_status & JS_DEVDATA_INIT_CONSTANTS)) {
+ s8 zero_ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT] = { 0, };
+ /* The caller must de-register all contexts before calling this */
+ KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running == 0);
+ KBASE_DEBUG_ASSERT(memcmp(js_devdata->runpool_irq.ctx_attr_ref_count, zero_ctx_attr_ref_count, sizeof(js_devdata->runpool_irq.ctx_attr_ref_count)) == 0);
+ CSTD_UNUSED(zero_ctx_attr_ref_count);
+ }
+ if ((js_devdata->init_status & JS_DEVDATA_INIT_POLICY))
+ kbasep_js_policy_term(&js_devdata->policy);
+
+ js_devdata->init_status = JS_DEVDATA_INIT_NONE;
+}
+
+mali_error kbasep_js_kctx_init(kbase_context * const kctx)
+{
+ kbase_device *kbdev;
+ kbasep_js_kctx_info *js_kctx_info;
+ mali_error err;
+
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ js_kctx_info = &kctx->jctx.sched_info;
+ KBASE_DEBUG_ASSERT(js_kctx_info->init_status == JS_KCTX_INIT_NONE);
+
+ js_kctx_info->ctx.nr_jobs = 0;
+ js_kctx_info->ctx.is_scheduled = MALI_FALSE;
+ js_kctx_info->ctx.is_dying = MALI_FALSE;
+ memset(js_kctx_info->ctx.ctx_attr_ref_count, 0, sizeof(js_kctx_info->ctx.ctx_attr_ref_count));
+
+ /* Initially, the context is disabled from submission until the create flags are set */
+ js_kctx_info->ctx.flags = KBASE_CTX_FLAG_SUBMIT_DISABLED;
+
+ js_kctx_info->init_status |= JS_KCTX_INIT_CONSTANTS;
+
+ /* On error, we could continue on: providing none of the below resources
+ * rely on the ones above */
+ mutex_init(&js_kctx_info->ctx.jsctx_mutex);
+
+ init_waitqueue_head(&js_kctx_info->ctx.is_scheduled_wait);
+
+ err = kbasep_js_policy_init_ctx(kbdev, kctx);
+ if (err == MALI_ERROR_NONE)
+ js_kctx_info->init_status |= JS_KCTX_INIT_POLICY;
+
+ /* On error, do no cleanup; this will be handled by the caller(s), since
+ * we've designed this resource to be safe to terminate on init-fail */
+ if (js_kctx_info->init_status != JS_KCTX_INIT_ALL)
+ return MALI_ERROR_FUNCTION_FAILED;
+
+ return MALI_ERROR_NONE;
+}
+
+void kbasep_js_kctx_term(kbase_context *kctx)
+{
+ kbase_device *kbdev;
+ kbasep_js_kctx_info *js_kctx_info;
+ kbasep_js_policy *js_policy;
+
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+
+ kbdev = kctx->kbdev;
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ js_policy = &kbdev->js_data.policy;
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ if ((js_kctx_info->init_status & JS_KCTX_INIT_CONSTANTS)) {
+ /* The caller must de-register all jobs before calling this */
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE);
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs == 0);
+ }
+
+ if ((js_kctx_info->init_status & JS_KCTX_INIT_POLICY))
+ kbasep_js_policy_term_ctx(js_policy, kctx);
+
+ js_kctx_info->init_status = JS_KCTX_INIT_NONE;
+}
+
+/* Evict jobs from the NEXT registers
+ *
+ * The caller must hold:
+ * - kbasep_js_kctx_info::ctx::jsctx_mutex
+ * - kbasep_js_device_data::runpool_mutex
+ */
+STATIC void kbasep_js_runpool_evict_next_jobs(kbase_device *kbdev, kbase_context *kctx)
+{
+ unsigned long flags;
+ int js;
+ kbasep_js_device_data *js_devdata;
+
+ js_devdata = &kbdev->js_data;
+
+ BUG_ON(!mutex_is_locked(&kctx->jctx.sched_info.ctx.jsctx_mutex));
+ BUG_ON(!mutex_is_locked(&js_devdata->runpool_mutex));
+
+ /* Prevent contexts in the runpool from submitting jobs */
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+
+ /* There's no need to prevent contexts in the runpool from submitting jobs,
+ * because we complete this operation by the time we release the
+ * runpool_irq.lock */
+
+ /* Evict jobs from the NEXT registers */
+ for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) {
+ kbase_jm_slot *slot;
+ kbase_jd_atom *tail;
+
+ if (!kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), NULL)) {
+ /* No job in the NEXT register */
+ continue;
+ }
+
+ slot = &kbdev->jm_slots[js];
+ tail = kbasep_jm_peek_idx_submit_slot(slot, slot->submitted_nr - 1);
+
+ KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 1);
+ /* Clearing job from next registers */
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), JSn_COMMAND_NOP, NULL);
+
+ /* Check to see if we did remove a job from the next registers */
+ if (kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_LO), NULL) != 0 || kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_HI), NULL) != 0) {
+ /* The job was successfully cleared from the next registers, requeue it */
+ kbase_jd_atom *dequeued_katom = kbasep_jm_dequeue_tail_submit_slot(slot);
+ KBASE_DEBUG_ASSERT(dequeued_katom == tail);
+
+ /* Set the next registers to NULL */
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_LO), 0, NULL);
+ kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_HI), 0, NULL);
+
+ KBASE_TRACE_ADD_SLOT(kbdev, JM_SLOT_EVICT, dequeued_katom->kctx, dequeued_katom, dequeued_katom->jc, js);
+
+ /* Complete the job, indicate that it took no time, and don't start
+ * new atoms */
+ kbase_jd_done(dequeued_katom, js, NULL, KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT);
+ }
+ KBASE_TIMELINE_TRY_SOFT_STOP(kctx, js, 0);
+ }
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+}
+
+/**
+ * Fast start a higher priority job
+ * If the runpool is full, the lower priority contexts with no running jobs
+ * will be evicted from the runpool
+ *
+ * If \a kctx_new is NULL, the first context with no running jobs will be evicted
+ *
+ * The following locking conditions are made on the caller:
+ * - The caller must \b not hold \a kctx_new's
+ * kbasep_js_kctx_info::ctx::jsctx_mutex, or that mutex of any ctx in the
+ * runpool. This is because \a kctx_new's jsctx_mutex and one of the other
+ * scheduled ctx's jsctx_mutex will be obtained internally.
+ * - it must \em not hold kbasep_js_device_data::runpool_irq::lock (as this will be
+ * obtained internally)
+ * - it must \em not hold kbasep_js_device_data::runpool_mutex (as this will be
+ * obtained internally)
+ * - it must \em not hold kbasep_jd_device_data::queue_mutex (again, it's used
+ * internally).
+ */
+STATIC void kbasep_js_runpool_attempt_fast_start_ctx(kbase_device *kbdev, kbase_context *kctx_new)
+{
+ unsigned long flags;
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_kctx_info *js_kctx_new;
+ kbasep_js_policy *js_policy;
+ kbasep_js_per_as_data *js_per_as_data;
+ int evict_as_nr;
+ kbasep_js_atom_retained_state katom_retained_state;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ js_devdata = &kbdev->js_data;
+ js_policy = &kbdev->js_data.policy;
+
+ if (kctx_new != NULL) {
+ js_kctx_new = &kctx_new->jctx.sched_info;
+ mutex_lock(&js_kctx_new->ctx.jsctx_mutex);
+ } else {
+ js_kctx_new = NULL;
+ CSTD_UNUSED(js_kctx_new);
+ }
+
+ /* Setup a dummy katom_retained_state */
+ kbasep_js_atom_retained_state_init_invalid(&katom_retained_state);
+
+ mutex_lock(&js_devdata->runpool_mutex);
+
+ /* If the runpool is full and it's not dying, attempt to fast start our context */
+ if (check_is_runpool_full(kbdev, kctx_new) != MALI_FALSE
+ && !js_kctx_new->ctx.is_dying) {
+ /* No free address spaces - attempt to evict non-running lower priority context */
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ for (evict_as_nr = 0; evict_as_nr < kbdev->nr_hw_address_spaces; evict_as_nr++) {
+ kbase_context *kctx_evict;
+ js_per_as_data = &js_devdata->runpool_irq.per_as_data[evict_as_nr];
+ kctx_evict = js_per_as_data->kctx;
+
+ /* Look for the AS which is not currently running */
+ if (0 == js_per_as_data->as_busy_refcount && kctx_evict != NULL) {
+ /* Now compare the scheduled priority we are considering evicting with the new ctx priority
+ * and take into consideration if the scheduled priority is a realtime policy or not.
+ * Note that the lower the number, the higher the priority
+ */
+ if ((kctx_new == NULL) || kbasep_js_policy_ctx_has_priority(js_policy, kctx_evict, kctx_new)) {
+ mali_bool retain_result;
+ kbasep_js_release_result release_result;
+ KBASE_TRACE_ADD(kbdev, JS_FAST_START_EVICTS_CTX, kctx_evict, NULL, 0u, (u32) kctx_new);
+
+ /* Retain the ctx to work on it - this shouldn't be able to fail */
+ retain_result = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx_evict);
+ KBASE_DEBUG_ASSERT(retain_result != MALI_FALSE);
+ CSTD_UNUSED(retain_result);
+
+ /* This will cause the context to be scheduled out on the next runpool_release_ctx(),
+ * and also stop its refcount increasing */
+ kbasep_js_clear_submit_allowed(js_devdata, kctx_evict);
+
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ mutex_unlock(&js_devdata->runpool_mutex);
+ if (kctx_new != NULL)
+ mutex_unlock(&js_kctx_new->ctx.jsctx_mutex);
+
+ /* Stop working on the target context, start working on the kctx_evict context */
+
+ mutex_lock(&kctx_evict->jctx.sched_info.ctx.jsctx_mutex);
+ mutex_lock(&js_devdata->runpool_mutex);
+ release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx_evict, &katom_retained_state);
+ mutex_unlock(&js_devdata->runpool_mutex);
+ /* Only requeue if actually descheduled, which is more robust in case
+ * something else retains it (e.g. two high priority contexts racing
+ * to evict the same lower priority context) */
+ if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u)
+ kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx_evict, MALI_TRUE);
+
+ mutex_unlock(&kctx_evict->jctx.sched_info.ctx.jsctx_mutex);
+
+ /* release_result isn't propogated further:
+ * - the caller will be scheduling in a context anyway
+ * - which will also cause new jobs to run */
+
+ /* ctx fast start has taken place */
+ return;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ }
+
+ /* ctx fast start has not taken place */
+ mutex_unlock(&js_devdata->runpool_mutex);
+ if (kctx_new != NULL)
+ mutex_unlock(&js_kctx_new->ctx.jsctx_mutex);
+}
+
+mali_bool kbasep_js_add_job(kbase_context *kctx, kbase_jd_atom *atom)
+{
+ unsigned long flags;
+ kbasep_js_kctx_info *js_kctx_info;
+ kbase_device *kbdev;
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_policy *js_policy;
+
+ mali_bool policy_queue_updated = MALI_FALSE;
+
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ KBASE_DEBUG_ASSERT(atom != NULL);
+ lockdep_assert_held(&kctx->jctx.lock);
+
+ kbdev = kctx->kbdev;
+ js_devdata = &kbdev->js_data;
+ js_policy = &kbdev->js_data.policy;
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ KBASE_TIMELINE_ATOM_READY(kctx, kbase_jd_atom_id(kctx, atom));
+
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+ /* Policy-specific initialization of atoms (which cannot fail). Anything that
+ * could've failed must've been done at kbasep_jd_policy_init_job() time. */
+ kbasep_js_policy_register_job(js_policy, kctx, atom);
+
+ /*
+ * Begin Runpool transaction
+ */
+ mutex_lock(&js_devdata->runpool_mutex);
+ KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_ADD_JOB, kctx, atom, atom->jc, kbasep_js_trace_get_refcnt(kbdev, kctx));
+
+ /* Refcount ctx.nr_jobs */
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs < U32_MAX);
+ ++(js_kctx_info->ctx.nr_jobs);
+
+ /* Setup any scheduling information */
+ kbasep_js_clear_job_retry_submit(atom);
+
+ /* Lock for state available during IRQ */
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+
+ /* Context Attribute Refcounting */
+ kbasep_js_ctx_attr_ctx_retain_atom(kbdev, kctx, atom);
+
+ /* Enqueue the job in the policy, causing it to be scheduled if the
+ * parent context gets scheduled */
+ kbasep_js_policy_enqueue_job(js_policy, atom);
+
+ if (js_kctx_info->ctx.is_scheduled != MALI_FALSE) {
+ /* Handle an already running context - try to run the new job, in case it
+ * matches requirements that aren't matched by any other job in the Run
+ * Pool */
+ kbasep_js_try_run_next_job_nolock(kbdev);
+ }
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ mutex_unlock(&js_devdata->runpool_mutex);
+ /* End runpool transaction */
+
+ if (js_kctx_info->ctx.is_scheduled == MALI_FALSE) {
+ if (js_kctx_info->ctx.is_dying) {
+ /* A job got added while/after kbase_job_zap_context() was called
+ * on a non-scheduled context (e.g. KDS dependency resolved). Kill
+ * that job by killing the context. */
+ kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_FALSE);
+ } else if (js_kctx_info->ctx.nr_jobs == 1) {
+ /* Handle Refcount going from 0 to 1: schedule the context on the Policy Queue */
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE);
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "JS: Enqueue Context %p", kctx);
+
+ mutex_lock(&js_devdata->queue_mutex);
+ kbasep_js_policy_enqueue_ctx(js_policy, kctx);
+ mutex_unlock(&js_devdata->queue_mutex);
+
+ /* Policy Queue was updated - caller must try to schedule the head context
+ * We also try to encourage a fast-start from here. */
+ policy_queue_updated = MALI_TRUE;
+ }
+ }
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+
+ /* If the runpool is full and this job has a higher priority than the
+ * non-running job in the runpool - evict it so this higher priority job
+ * starts faster. Fast-starting requires the jsctx_mutex to be dropped,
+ * because it works on multiple ctxs
+ *
+ * Note: If the context is being killed with kbase_job_zap_context(), then
+ * kctx can't disappear after the jsctx_mutex was dropped. This is because
+ * the caller holds kctx->jctx.lock */
+ if (policy_queue_updated)
+ kbasep_js_runpool_attempt_fast_start_ctx(kbdev, kctx);
+
+ return policy_queue_updated;
+}
+
+void kbasep_js_remove_job(kbase_device *kbdev, kbase_context *kctx, kbase_jd_atom *atom)
+{
+ kbasep_js_kctx_info *js_kctx_info;
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_policy *js_policy;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ KBASE_DEBUG_ASSERT(atom != NULL);
+
+ js_devdata = &kbdev->js_data;
+ js_policy = &kbdev->js_data.policy;
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_REMOVE_JOB, kctx, atom, atom->jc, kbasep_js_trace_get_refcnt(kbdev, kctx));
+
+ /* De-refcount ctx.nr_jobs */
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs > 0);
+ --(js_kctx_info->ctx.nr_jobs);
+
+ /* De-register the job from the system */
+ kbasep_js_policy_deregister_job(js_policy, kctx, atom);
+}
+
+void kbasep_js_remove_cancelled_job(kbase_device *kbdev, kbase_context *kctx, kbase_jd_atom *katom)
+{
+ unsigned long flags;
+ kbasep_js_atom_retained_state katom_retained_state;
+ kbasep_js_device_data *js_devdata;
+ mali_bool attr_state_changed;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ KBASE_DEBUG_ASSERT(katom != NULL);
+
+ js_devdata = &kbdev->js_data;
+
+ kbasep_js_atom_retained_state_copy(&katom_retained_state, katom);
+ kbasep_js_remove_job(kbdev, kctx, katom);
+
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+
+ /* The atom has 'finished' (will not be re-run), so no need to call
+ * kbasep_js_has_atom_finished().
+ *
+ * This is because it returns MALI_FALSE for soft-stopped atoms, but we
+ * want to override that, because we're cancelling an atom regardless of
+ * whether it was soft-stopped or not */
+ attr_state_changed = kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, &katom_retained_state);
+
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+
+ if (attr_state_changed != MALI_FALSE) {
+ /* A change in runpool ctx attributes might mean we can run more jobs
+ * than before. */
+ kbase_js_try_run_jobs(kbdev);
+ }
+}
+
+mali_bool kbasep_js_runpool_retain_ctx(kbase_device *kbdev, kbase_context *kctx)
+{
+ unsigned long flags;
+ kbasep_js_device_data *js_devdata;
+ mali_bool result;
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ js_devdata = &kbdev->js_data;
+
+ /* KBASE_TRACE_ADD_REFCOUNT( kbdev, JS_RETAIN_CTX, kctx, NULL, 0,
+ kbasep_js_trace_get_refcnt(kbdev, kctx)); */
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ result = kbasep_js_runpool_retain_ctx_nolock(kbdev, kctx);
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+
+ return result;
+}
+
+kbase_context *kbasep_js_runpool_lookup_ctx(kbase_device *kbdev, int as_nr)
+{
+ unsigned long flags;
+ kbasep_js_device_data *js_devdata;
+ kbase_context *found_kctx = NULL;
+ kbasep_js_per_as_data *js_per_as_data;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(0 <= as_nr && as_nr < BASE_MAX_NR_AS);
+ js_devdata = &kbdev->js_data;
+ js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr];
+
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+
+ found_kctx = js_per_as_data->kctx;
+
+ if (found_kctx != NULL)
+ ++(js_per_as_data->as_busy_refcount);
+
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+
+ return found_kctx;
+}
+
+/**
+ * @brief Try running more jobs after releasing a context and/or atom
+ *
+ * This collates a set of actions that must happen whilst
+ * kbasep_js_device_data::runpool_irq::lock is held.
+ *
+ * This includes running more jobs when:
+ * - The previously released kctx caused a ctx attribute change
+ * - The released atom caused a ctx attribute change
+ * - Slots were previously blocked due to affinity restrictions
+ * - Submission during IRQ handling failed
+ */
+STATIC void kbasep_js_run_jobs_after_ctx_and_atom_release(kbase_device *kbdev, kbase_context *kctx, kbasep_js_atom_retained_state *katom_retained_state, mali_bool runpool_ctx_attr_change)
+{
+ kbasep_js_device_data *js_devdata;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ KBASE_DEBUG_ASSERT(katom_retained_state != NULL);
+ js_devdata = &kbdev->js_data;
+
+ lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex);
+ lockdep_assert_held(&js_devdata->runpool_mutex);
+ lockdep_assert_held(&js_devdata->runpool_irq.lock);
+
+ if (js_devdata->nr_user_contexts_running != 0) {
+ mali_bool retry_submit;
+ int retry_jobslot;
+
+ retry_submit = kbasep_js_get_atom_retry_submit_slot(katom_retained_state, &retry_jobslot);
+
+ if (runpool_ctx_attr_change != MALI_FALSE) {
+ /* A change in runpool ctx attributes might mean we can run more jobs
+ * than before */
+ kbasep_js_try_run_next_job_nolock(kbdev);
+
+ /* A retry submit on all slots has now happened, so don't need to do it again */
+ retry_submit = MALI_FALSE;
+ }
+
+ /* Submit on any slots that might've had atoms blocked by the affinity of
+ * a completed atom.
+ *
+ * If no atom has recently completed, then this is harmelss */
+ kbase_js_affinity_submit_to_blocked_slots(kbdev);
+
+ /* If the IRQ handler failed to get a job from the policy, try again from
+ * outside the IRQ handler
+ * NOTE: We may've already cleared retry_submit from submitting above */
+ if (retry_submit != MALI_FALSE) {
+ KBASE_TRACE_ADD_SLOT(kbdev, JD_DONE_TRY_RUN_NEXT_JOB, kctx, NULL, 0u, retry_jobslot);
+ kbasep_js_try_run_next_job_on_slot_nolock(kbdev, retry_jobslot);
+ }
+ }
+}
+
+/**
+ * Internal function to release the reference on a ctx and an atom's "retained
+ * state", only taking the runpool and as transaction mutexes
+ *
+ * This also starts more jobs running in the case of an ctx-attribute state change
+ *
+ * This does none of the followup actions for scheduling:
+ * - It does not schedule in a new context
+ * - It does not requeue or handle dying contexts
+ *
+ * For those tasks, just call kbasep_js_runpool_release_ctx() instead
+ *
+ * Requires:
+ * - Context is scheduled in, and kctx->as_nr matches kctx_as_nr
+ * - Context has a non-zero refcount
+ * - Caller holds js_kctx_info->ctx.jsctx_mutex
+ * - Caller holds js_devdata->runpool_mutex
+ */
+STATIC kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(kbase_device *kbdev, kbase_context *kctx, kbasep_js_atom_retained_state *katom_retained_state)
+{
+ unsigned long flags;
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_kctx_info *js_kctx_info;
+ kbasep_js_policy *js_policy;
+ kbasep_js_per_as_data *js_per_as_data;
+
+ kbasep_js_release_result release_result = 0u;
+ mali_bool runpool_ctx_attr_change = MALI_FALSE;
+ int kctx_as_nr;
+ kbase_as *current_as;
+ int new_ref_count;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ js_kctx_info = &kctx->jctx.sched_info;
+ js_devdata = &kbdev->js_data;
+ js_policy = &kbdev->js_data.policy;
+
+ /* Ensure context really is scheduled in */
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled != MALI_FALSE);
+
+ /* kctx->as_nr and js_per_as_data are only read from here. The caller's
+ * js_ctx_mutex provides a barrier that ensures they are up-to-date.
+ *
+ * They will not change whilst we're reading them, because the refcount
+ * is non-zero (and we ASSERT on that last fact).
+ */
+ kctx_as_nr = kctx->as_nr;
+ KBASE_DEBUG_ASSERT(kctx_as_nr != KBASEP_AS_NR_INVALID);
+ js_per_as_data = &js_devdata->runpool_irq.per_as_data[kctx_as_nr];
+ KBASE_DEBUG_ASSERT(js_per_as_data->as_busy_refcount > 0);
+
+ /*
+ * Transaction begins on AS and runpool_irq
+ *
+ * Assert about out calling contract
+ */
+ current_as = &kbdev->as[kctx_as_nr];
+ mutex_lock(&current_as->transaction_mutex);
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+ KBASE_DEBUG_ASSERT(kctx_as_nr == kctx->as_nr);
+ KBASE_DEBUG_ASSERT(js_per_as_data->as_busy_refcount > 0);
+
+ /* Update refcount */
+ new_ref_count = --(js_per_as_data->as_busy_refcount);
+
+ /* Release the atom if it finished (i.e. wasn't soft-stopped) */
+ if (kbasep_js_has_atom_finished(katom_retained_state) != MALI_FALSE)
+ runpool_ctx_attr_change |= kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, katom_retained_state);
+
+ KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_RELEASE_CTX, kctx, NULL, 0u, new_ref_count);
+
+ if (new_ref_count == 1 && kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED
+ && !kbase_pm_is_suspending(kbdev) ) {
+ /* Context is kept scheduled into an address space even when there are no jobs, in this case we have
+ * to handle the situation where all jobs have been evicted from the GPU and submission is disabled.
+ *
+ * At this point we re-enable submission to allow further jobs to be executed
+ */
+ kbasep_js_set_submit_allowed(js_devdata, kctx);
+ }
+
+ /* Make a set of checks to see if the context should be scheduled out */
+ if (new_ref_count == 0 && (kctx->jctx.sched_info.ctx.nr_jobs == 0 || kbasep_js_is_submit_allowed(js_devdata, kctx) == MALI_FALSE)) {
+ /* Last reference, and we've been told to remove this context from the Run Pool */
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "JS: RunPool Remove Context %p because as_busy_refcount=%d, jobs=%d, allowed=%d", kctx, new_ref_count, js_kctx_info->ctx.nr_jobs, kbasep_js_is_submit_allowed(js_devdata, kctx));
+
+ kbasep_js_policy_runpool_remove_ctx(js_policy, kctx);
+
+ /* Stop any more refcounts occuring on the context */
+ js_per_as_data->kctx = NULL;
+
+ /* Ensure we prevent the context from submitting any new jobs
+ * e.g. from kbasep_js_try_run_next_job_on_slot_irq_nolock() */
+ kbasep_js_clear_submit_allowed(js_devdata, kctx);
+
+ /* Disable the MMU on the affected address space, and indicate it's invalid */
+ kbase_mmu_disable(kctx);
+
+#ifdef CONFIG_MALI_GATOR_SUPPORT
+ kbase_trace_mali_mmu_as_released(kctx->as_nr);
+#endif /* CONFIG_MALI_GATOR_SUPPORT */
+
+ kctx->as_nr = KBASEP_AS_NR_INVALID;
+
+ /* Ctx Attribute handling
+ *
+ * Releasing atoms attributes must either happen before this, or after
+ * 'is_scheduled' is changed, otherwise we double-decount the attributes*/
+ runpool_ctx_attr_change |= kbasep_js_ctx_attr_runpool_release_ctx(kbdev, kctx);
+
+ /* Early update of context count, to optimize the
+ * kbasep_js_run_jobs_after_ctx_and_atom_release() call */
+ runpool_dec_context_count(kbdev, kctx);
+
+ /* Releasing the context and katom retained state can allow more jobs to run */
+ kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, kctx, katom_retained_state, runpool_ctx_attr_change);
+
+ /*
+ * Transaction ends on AS and runpool_irq:
+ *
+ * By this point, the AS-related data is now clear and ready for re-use.
+ *
+ * Since releases only occur once for each previous successful retain, and no more
+ * retains are allowed on this context, no other thread will be operating in this
+ * code whilst we are
+ */
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ mutex_unlock(&current_as->transaction_mutex);
+
+ /* Free up the address space */
+ release_addr_space(kbdev, kctx_as_nr);
+ /* Note: Don't reuse kctx_as_nr now */
+
+ /* Synchronize with any policy timers */
+ kbasep_js_policy_runpool_timers_sync(js_policy);
+
+ /* update book-keeping info */
+ js_kctx_info->ctx.is_scheduled = MALI_FALSE;
+ /* Signal any waiter that the context is not scheduled, so is safe for
+ * termination - once the jsctx_mutex is also dropped, and jobs have
+ * finished. */
+ wake_up(&js_kctx_info->ctx.is_scheduled_wait);
+
+ /* Queue an action to occur after we've dropped the lock */
+ release_result |= KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED;
+
+ } else {
+ kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, kctx, katom_retained_state, runpool_ctx_attr_change);
+
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ mutex_unlock(&current_as->transaction_mutex);
+ }
+
+ return release_result;
+}
+
+void kbasep_js_runpool_requeue_or_kill_ctx(kbase_device *kbdev, kbase_context *kctx, mali_bool has_pm_ref)
+{
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_policy *js_policy;
+ kbasep_js_kctx_info *js_kctx_info;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ js_kctx_info = &kctx->jctx.sched_info;
+ js_policy = &kbdev->js_data.policy;
+ js_devdata = &kbdev->js_data;
+
+ /* This is called if and only if you've you've detached the context from
+ * the Runpool or the Policy Queue, and not added it back to the Runpool */
+ KBASE_DEBUG_ASSERT(js_kctx_info->ctx.is_scheduled == MALI_FALSE);
+
+ if (js_kctx_info->ctx.is_dying != MALI_FALSE) {
+ /* Dying: don't requeue, but kill all jobs on the context. This happens
+ * asynchronously */
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "JS: ** Killing Context %p on RunPool Remove **", kctx);
+ kbasep_js_policy_foreach_ctx_job(js_policy, kctx, &kbase_jd_cancel, MALI_TRUE);
+ } else if (js_kctx_info->ctx.nr_jobs > 0) {
+ /* Not dying, has jobs: de-ref core counts from each job before addding
+ * back to the queue */
+ kbasep_js_policy_foreach_ctx_job(js_policy, kctx, &kbasep_js_job_check_deref_cores, MALI_FALSE);
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "JS: Requeue Context %p", kctx);
+ mutex_lock(&js_devdata->queue_mutex);
+ kbasep_js_policy_enqueue_ctx(js_policy, kctx);
+ mutex_unlock(&js_devdata->queue_mutex);
+ } else {
+ /* Not dying, no jobs: don't add back to the queue */
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "JS: Idling Context %p (not requeued)", kctx);
+ }
+
+ if (has_pm_ref) {
+ /* In all cases where we had a pm active refcount, release it */
+ kbase_pm_context_idle(kbdev);
+ }
+}
+
+void kbasep_js_runpool_release_ctx_and_katom_retained_state(kbase_device *kbdev, kbase_context *kctx, kbasep_js_atom_retained_state *katom_retained_state)
+{
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_kctx_info *js_kctx_info;
+ kbasep_js_release_result release_result;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ js_kctx_info = &kctx->jctx.sched_info;
+ js_devdata = &kbdev->js_data;
+
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+ mutex_lock(&js_devdata->runpool_mutex);
+ release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, katom_retained_state);
+
+ /* Drop the runpool mutex to allow requeing kctx */
+ mutex_unlock(&js_devdata->runpool_mutex);
+ if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u)
+ kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_TRUE);
+
+ /* Drop the jsctx_mutex to allow scheduling in a new context */
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+ if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) {
+ /* We've freed up an address space, so let's try to schedule in another
+ * context
+ *
+ * Note: if there's a context to schedule in, then it also tries to run
+ * another job, in case the new context has jobs satisfying requirements
+ * that no other context/job in the runpool does */
+ kbasep_js_try_schedule_head_ctx(kbdev);
+ }
+}
+
+void kbasep_js_runpool_release_ctx(kbase_device *kbdev, kbase_context *kctx)
+{
+ kbasep_js_atom_retained_state katom_retained_state;
+
+ kbasep_js_atom_retained_state_init_invalid(&katom_retained_state);
+
+ kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &katom_retained_state);
+}
+
+/** Variant of kbasep_js_runpool_release_ctx() that doesn't call into
+ * kbasep_js_try_schedule_head_ctx() */
+STATIC void kbasep_js_runpool_release_ctx_no_schedule(kbase_device *kbdev, kbase_context *kctx)
+{
+ kbasep_js_device_data *js_devdata;
+ kbasep_js_kctx_info *js_kctx_info;
+ kbasep_js_release_result release_result;
+ kbasep_js_atom_retained_state katom_retained_state_struct;
+ kbasep_js_atom_retained_state *katom_retained_state = &katom_retained_state_struct;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ js_kctx_info = &kctx->jctx.sched_info;
+ js_devdata = &kbdev->js_data;
+ kbasep_js_atom_retained_state_init_invalid(katom_retained_state);
+
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+ mutex_lock(&js_devdata->runpool_mutex);
+ release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, katom_retained_state);
+
+ /* Drop the runpool mutex to allow requeing kctx */
+ mutex_unlock(&js_devdata->runpool_mutex);
+ if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u)
+ kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, MALI_TRUE);
+
+ /* Drop the jsctx_mutex to allow scheduling in a new context */
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+
+ /* NOTE: could return release_result if the caller would like to know
+ * whether it should schedule a new context, but currently no callers do */
+}
+
+
+/**
+ * @brief Handle retaining cores for power management and affinity management,
+ * ensuring that cores are powered up and won't violate affinity restrictions.
+ *
+ * This function enters at the following @ref kbase_atom_coreref_state states:
+ *
+ * - NO_CORES_REQUESTED,
+ * - WAITING_FOR_REQUESTED_CORES,
+ * - RECHECK_AFFINITY,
+ *
+ * The transitions are as folows:
+ * - NO_CORES_REQUESTED -> WAITING_FOR_REQUESTED_CORES
+ * - WAITING_FOR_REQUESTED_CORES -> ( WAITING_FOR_REQUESTED_CORES or RECHECK_AFFINITY )
+ * - RECHECK_AFFINITY -> ( WAITING_FOR_REQUESTED_CORES or CHECK_AFFINITY_VIOLATIONS )
+ * - CHECK_AFFINITY_VIOLATIONS -> ( RECHECK_AFFINITY or READY )
+ *
+ * The caller must hold:
+ * - kbasep_js_device_data::runpool_irq::lock
+ *
+ * @return MALI_FALSE when the function makes a transition to the same or lower state, indicating
+ * that the cores are not ready.
+ * @return MALI_TRUE once READY state is reached, indicating that the cores are 'ready' and won't
+ * violate affinity restrictions.
+ *
+ */
+STATIC mali_bool kbasep_js_job_check_ref_cores(kbase_device *kbdev, int js, kbase_jd_atom *katom)
+{
+ /* The most recently checked affinity. Having this at this scope allows us
+ * to guarantee that we've checked the affinity in this function call. */
+ u64 recently_chosen_affinity = 0;
+ mali_bool chosen_affinity = MALI_FALSE;
+ mali_bool retry;
+
+ do {
+ retry = MALI_FALSE;
+
+ /* NOTE: The following uses a number of FALLTHROUGHs to optimize the
+ * calls to this function. Ending of the function is indicated by BREAK OUT */
+ switch (katom->coreref_state) {
+ /* State when job is first attempted to be run */
+ case KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED:
+ KBASE_DEBUG_ASSERT(katom->affinity == 0);
+
+ /* Compute affinity */
+ if (MALI_FALSE == kbase_js_choose_affinity(&recently_chosen_affinity, kbdev, katom, js)) {
+ /* No cores are currently available */
+ /* *** BREAK OUT: No state transition *** */
+ break;
+ }
+
+ chosen_affinity = MALI_TRUE;
+
+ /* Request the cores */
+ kbase_pm_request_cores(kbdev, katom->core_req & BASE_JD_REQ_T, recently_chosen_affinity);
+
+ katom->affinity = recently_chosen_affinity;
+
+ /* Proceed to next state */
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES;
+
+ /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
+
+ case KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES:
+ {
+ kbase_pm_cores_ready cores_ready;
+ KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T));
+
+ cores_ready = kbase_pm_register_inuse_cores(kbdev, katom->core_req & BASE_JD_REQ_T, katom->affinity);
+ if (cores_ready == KBASE_NEW_AFFINITY) {
+ /* Affinity no longer valid - return to previous state */
+ kbasep_js_job_check_deref_cores(kbdev, katom);
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_INUSE_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity);
+ /* *** BREAK OUT: Return to previous state, retry *** */
+ retry = MALI_TRUE;
+ break;
+ }
+ if (cores_ready == KBASE_CORES_NOT_READY) {
+ /* Stay in this state and return, to retry at this state later */
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_INUSE_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity);
+ /* *** BREAK OUT: No state transition *** */
+ break;
+ }
+ /* Proceed to next state */
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY;
+ }
+
+ /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
+
+ case KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY:
+ KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T));
+
+ /* Optimize out choosing the affinity twice in the same function call */
+ if (chosen_affinity == MALI_FALSE) {
+ /* See if the affinity changed since a previous call. */
+ if (MALI_FALSE == kbase_js_choose_affinity(&recently_chosen_affinity, kbdev, katom, js)) {
+ /* No cores are currently available */
+ kbasep_js_job_check_deref_cores(kbdev, katom);
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REQUEST_ON_RECHECK_FAILED, katom->kctx, katom, katom->jc, js, (u32) recently_chosen_affinity);
+ /* *** BREAK OUT: Transition to lower state *** */
+ break;
+ }
+ chosen_affinity = MALI_TRUE;
+ }
+
+ /* Now see if this requires a different set of cores */
+ if (recently_chosen_affinity != katom->affinity) {
+ kbase_pm_cores_ready cores_ready;
+
+ kbase_pm_request_cores(kbdev, katom->core_req & BASE_JD_REQ_T, recently_chosen_affinity);
+
+ /* Register new cores whilst we still hold the old ones, to minimize power transitions */
+ cores_ready = kbase_pm_register_inuse_cores(kbdev, katom->core_req & BASE_JD_REQ_T, recently_chosen_affinity);
+ kbasep_js_job_check_deref_cores(kbdev, katom);
+
+ /* Fixup the state that was reduced by deref_cores: */
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY;
+ katom->affinity = recently_chosen_affinity;
+ if (cores_ready == KBASE_NEW_AFFINITY) {
+ /* Affinity no longer valid - return to previous state */
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES;
+ kbasep_js_job_check_deref_cores(kbdev, katom);
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_INUSE_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity);
+ /* *** BREAK OUT: Return to previous state, retry *** */
+ retry = MALI_TRUE;
+ break;
+ }
+ /* Now might be waiting for powerup again, with a new affinity */
+ if (cores_ready == KBASE_CORES_NOT_READY) {
+ /* Return to previous state */
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES;
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_REGISTER_ON_RECHECK_FAILED, katom->kctx, katom, katom->jc, js, (u32) katom->affinity);
+ /* *** BREAK OUT: Transition to lower state *** */
+ break;
+ }
+ }
+ /* Proceed to next state */
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS;
+
+ /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
+ case KBASE_ATOM_COREREF_STATE_CHECK_AFFINITY_VIOLATIONS:
+ KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T));
+ KBASE_DEBUG_ASSERT(katom->affinity == recently_chosen_affinity);
+
+ /* Note: this is where the caller must've taken the runpool_irq.lock */
+
+ /* Check for affinity violations - if there are any, then we just ask
+ * the caller to requeue and try again later */
+ if (kbase_js_affinity_would_violate(kbdev, js, katom->affinity) != MALI_FALSE) {
+ /* Cause a re-attempt to submit from this slot on the next job complete */
+ kbase_js_affinity_slot_blocked_an_atom(kbdev, js);
+ /* Return to previous state */
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY;
+ /* *** BREAK OUT: Transition to lower state *** */
+ KBASE_TRACE_ADD_SLOT_INFO(kbdev, JS_CORE_REF_AFFINITY_WOULD_VIOLATE, katom->kctx, katom, katom->jc, js, (u32) katom->affinity);
+ break;
+ }
+
+ /* No affinity violations would result, so the cores are ready */
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_READY;
+ /* *** BREAK OUT: Cores Ready *** */
+ break;
+
+ default:
+ KBASE_DEBUG_ASSERT_MSG(MALI_FALSE, "Unhandled kbase_atom_coreref_state %d", katom->coreref_state);
+ break;
+ }
+ } while (retry != MALI_FALSE);
+
+ return (katom->coreref_state == KBASE_ATOM_COREREF_STATE_READY);
+}
+
+void kbasep_js_job_check_deref_cores(kbase_device *kbdev, struct kbase_jd_atom *katom)
+{
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(katom != NULL);
+
+ switch (katom->coreref_state) {
+ case KBASE_ATOM_COREREF_STATE_READY:
+ /* State where atom was submitted to the HW - just proceed to power-down */
+ KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T));
+
+ /* *** FALLTHROUGH *** */
+
+ case KBASE_ATOM_COREREF_STATE_RECHECK_AFFINITY:
+ /* State where cores were registered */
+ KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T));
+ kbase_pm_release_cores(kbdev, katom->core_req & BASE_JD_REQ_T, katom->affinity);
+
+ /* Note: We do not clear the state for kbase_js_affinity_slot_blocked_an_atom().
+ * That is handled after finishing the job. This might be slightly
+ * suboptimal for some corner cases, but is otherwise not a problem
+ * (and resolves itself after the next job completes). */
+
+ break;
+
+ case KBASE_ATOM_COREREF_STATE_WAITING_FOR_REQUESTED_CORES:
+ /* State where cores were requested, but not registered */
+ KBASE_DEBUG_ASSERT(katom->affinity != 0 || (katom->core_req & BASE_JD_REQ_T));
+ kbase_pm_unrequest_cores(kbdev, katom->core_req & BASE_JD_REQ_T, katom->affinity);
+ break;
+
+ case KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED:
+ /* Initial state - nothing required */
+ KBASE_DEBUG_ASSERT(katom->affinity == 0);
+ break;
+
+ default:
+ KBASE_DEBUG_ASSERT_MSG(MALI_FALSE, "Unhandled coreref_state: %d", katom->coreref_state);
+ break;
+ }
+
+ katom->affinity = 0;
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED;
+}
+
+/*
+ * Note: this function is quite similar to kbasep_js_try_run_next_job_on_slot()
+ */
+mali_bool kbasep_js_try_run_next_job_on_slot_irq_nolock(kbase_device *kbdev, int js, s8 *submit_count)
+{
+ kbasep_js_device_data *js_devdata;
+ mali_bool cores_ready;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ js_devdata = &kbdev->js_data;
+
+ /* The caller of this function may not be aware of Ctx Attribute state changes so we
+ * must recheck if the given slot is still valid. Otherwise do not try to run.
+ */
+ if (kbase_js_can_run_job_on_slot_no_lock(kbdev, js)) {
+ /* Keep submitting while there's space to run a job on this job-slot,
+ * and there are jobs to get that match its requirements (see 'break'
+ * statement below) */
+ while (*submit_count < KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ && kbasep_jm_is_submit_slots_free(kbdev, js, NULL) != MALI_FALSE) {
+ kbase_jd_atom *dequeued_atom;
+ mali_bool has_job = MALI_FALSE;
+
+ /* Dequeue a job that matches the requirements */
+ has_job = kbasep_js_policy_dequeue_job(kbdev, js, &dequeued_atom);
+
+ if (has_job != MALI_FALSE) {
+ /* NOTE: since the runpool_irq lock is currently held and acts across
+ * all address spaces, any context whose busy refcount has reached
+ * zero won't yet be scheduled out whilst we're trying to run jobs
+ * from it */
+ kbase_context *parent_ctx = dequeued_atom->kctx;
+ mali_bool retain_success;
+
+ /* Retain/power up the cores it needs, check if cores are ready */
+ cores_ready = kbasep_js_job_check_ref_cores(kbdev, js, dequeued_atom);
+
+ if (cores_ready != MALI_TRUE && dequeued_atom->event_code != BASE_JD_EVENT_PM_EVENT) {
+ /* The job can't be submitted until the cores are ready, requeue the job */
+ kbasep_js_policy_enqueue_job(&kbdev->js_data.policy, dequeued_atom);
+ break;
+ }
+
+ /* ASSERT that the Policy picked a job from an allowed context */
+ KBASE_DEBUG_ASSERT(kbasep_js_is_submit_allowed(js_devdata, parent_ctx));
+
+ /* Retain the context to stop it from being scheduled out
+ * This is released when the job finishes */
+ retain_success = kbasep_js_runpool_retain_ctx_nolock(kbdev, parent_ctx);
+ KBASE_DEBUG_ASSERT(retain_success != MALI_FALSE);
+ CSTD_UNUSED(retain_success);
+
+ /* Retain the affinity on the slot */
+ kbase_js_affinity_retain_slot_cores(kbdev, js, dequeued_atom->affinity);
+
+ /* Check if this job needs the cycle counter enabled before submission */
+ kbasep_js_ref_permon_check_and_enable_cycle_counter(kbdev, dequeued_atom);
+
+ if (dequeued_atom->event_code == BASE_JD_EVENT_PM_EVENT) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_PM, "Rejecting atom due to BASE_JD_EVENT_PM_EVENT\n");
+ /* The job has failed due to the specified core group being unavailable */
+ kbase_jd_done(dequeued_atom, js, NULL, 0);
+ } else {
+ /* Submit the job */
+ kbase_job_submit_nolock(kbdev, dequeued_atom, js);
+
+ ++(*submit_count);
+ }
+ } else {
+ /* No more jobs - stop submitting for this slot */
+ break;
+ }
+ }
+ }
+
+ /* Indicate whether a retry in submission should be tried on a different
+ * dequeue function. These are the reasons why it *must* happen:
+ * - the KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ threshold was reached
+ * and new scheduling must be performed outside of IRQ mode.
+ *
+ * Failure to indicate this correctly could stop further jobs being processed.
+ *
+ * However, we do not _need_ to indicate a retry for the following:
+ * - kbasep_js_policy_dequeue_job() couldn't get a job. In which case,
+ * there's no point re-trying outside of IRQ, because the result will be
+ * the same until job dependencies are resolved, or user-space provides
+ * more jobs. In both those cases, we try to run jobs anyway, so
+ * processing does not stop.
+ * - kbasep_jm_is_submit_slots_free() was MALI_FALSE, indicating jobs were
+ * already running. When those jobs complete, that will still cause events
+ * that cause us to resume job submission.
+ * - kbase_js_can_run_job_on_slot_no_lock() was MALI_FALSE - this is for
+ * Ctx Attribute handling. That _can_ change outside of IRQ context, but
+ * is handled explicitly by kbasep_js_runpool_release_ctx_and_katom_retained_state().
+ */
+ return (mali_bool) (*submit_count >= KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ);
+}
+
+void kbasep_js_try_run_next_job_on_slot_nolock(kbase_device *kbdev, int js)
+{
+ kbasep_js_device_data *js_devdata;
+ mali_bool has_job;
+ mali_bool cores_ready;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ js_devdata = &kbdev->js_data;
+
+ KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running > 0);
+
+ /* Keep submitting while there's space to run a job on this job-slot,
+ * and there are jobs to get that match its requirements (see 'break'
+ * statement below) */
+ if (kbasep_jm_is_submit_slots_free(kbdev, js, NULL) != MALI_FALSE) {
+ /* The caller of this function may not be aware of Ctx Attribute state changes so we
+ * must recheck if the given slot is still valid. Otherwise do not try to run.
+ */
+ if (kbase_js_can_run_job_on_slot_no_lock(kbdev, js)) {
+ do {
+ kbase_jd_atom *dequeued_atom;
+
+ /* Dequeue a job that matches the requirements */
+ has_job = kbasep_js_policy_dequeue_job(kbdev, js, &dequeued_atom);
+
+ if (has_job != MALI_FALSE) {
+ /* NOTE: since the runpool_irq lock is currently held and acts across
+ * all address spaces, any context whose busy refcount has reached
+ * zero won't yet be scheduled out whilst we're trying to run jobs
+ * from it */
+ kbase_context *parent_ctx = dequeued_atom->kctx;
+ mali_bool retain_success;
+
+ /* Retain/power up the cores it needs, check if cores are ready */
+ cores_ready = kbasep_js_job_check_ref_cores(kbdev, js, dequeued_atom);
+
+ if (cores_ready != MALI_TRUE && dequeued_atom->event_code != BASE_JD_EVENT_PM_EVENT) {
+ /* The job can't be submitted until the cores are ready, requeue the job */
+ kbasep_js_policy_enqueue_job(&kbdev->js_data.policy, dequeued_atom);
+ break;
+ }
+ /* ASSERT that the Policy picked a job from an allowed context */
+ KBASE_DEBUG_ASSERT(kbasep_js_is_submit_allowed(js_devdata, parent_ctx));
+
+ /* Retain the context to stop it from being scheduled out
+ * This is released when the job finishes */
+ retain_success = kbasep_js_runpool_retain_ctx_nolock(kbdev, parent_ctx);
+ KBASE_DEBUG_ASSERT(retain_success != MALI_FALSE);
+ CSTD_UNUSED(retain_success);
+
+ /* Retain the affinity on the slot */
+ kbase_js_affinity_retain_slot_cores(kbdev, js, dequeued_atom->affinity);
+
+ /* Check if this job needs the cycle counter enabled before submission */
+ kbasep_js_ref_permon_check_and_enable_cycle_counter(kbdev, dequeued_atom);
+
+ if (dequeued_atom->event_code == BASE_JD_EVENT_PM_EVENT) {
+ KBASE_DEBUG_PRINT_WARN(KBASE_PM, "Rejecting atom due to BASE_JD_EVENT_PM_EVENT\n");
+ /* The job has failed due to the specified core group being unavailable */
+ kbase_jd_done(dequeued_atom, js, NULL, 0);
+ } else {
+ /* Submit the job */
+ kbase_job_submit_nolock(kbdev, dequeued_atom, js);
+ }
+ }
+
+ } while (kbasep_jm_is_submit_slots_free(kbdev, js, NULL) != MALI_FALSE && has_job != MALI_FALSE);
+ }
+ }
+}
+
+void kbasep_js_try_schedule_head_ctx(kbase_device *kbdev)
+{
+ kbasep_js_device_data *js_devdata;
+ mali_bool has_kctx;
+ kbase_context *head_kctx;
+ kbasep_js_kctx_info *js_kctx_info;
+ mali_bool is_runpool_full;
+ kbase_as *new_address_space;
+ unsigned long flags;
+ mali_bool head_kctx_suspended = MALI_FALSE;
+ int pm_active_err;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+
+ js_devdata = &kbdev->js_data;
+
+ /* We *don't* make a speculative check on whether we can fit a context in the
+ * runpool, because most of our use-cases assume 2 or fewer contexts, and
+ * so we will usually have enough address spaces free.
+ *
+ * In any case, the check will be done later on once we have a context */
+
+ /* Grab the context off head of queue - if there is one */
+ mutex_lock(&js_devdata->queue_mutex);
+ has_kctx = kbasep_js_policy_dequeue_head_ctx(&js_devdata->policy, &head_kctx);
+ mutex_unlock(&js_devdata->queue_mutex);
+
+ if (has_kctx == MALI_FALSE) {
+ /* No ctxs to run - nothing to do */
+ return;
+ }
+ js_kctx_info = &head_kctx->jctx.sched_info;
+
+ KBASE_DEBUG_PRINT_INFO(KBASE_JM, "JS: Dequeue Context %p", head_kctx);
+
+ pm_active_err = kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE);
+
+ /*
+ * Atomic transaction on the Context and Run Pool begins
+ */
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+ mutex_lock(&js_devdata->runpool_mutex);
+
+ /* Check to see if we shouldn't add the context to run Run Pool:
+ * - it can't take the specified context, and so is 'full'. This may be
+ * 'full' even when there are addres spaces available, since some contexts
+ * are allowed in whereas others may not due to HW workarounds
+ * - A suspend is taking place
+ * - The context is dying due to kbase_job_zap_context() */
+ is_runpool_full = check_is_runpool_full(kbdev, head_kctx);
+ if (is_runpool_full || pm_active_err || js_kctx_info->ctx.is_dying) {
+ /* Roll back the transaction so far and return */
+ mutex_unlock(&js_devdata->runpool_mutex);
+
+ /* Note: If a Power Management active reference was taken, it's released by
+ * this: */
+ kbasep_js_runpool_requeue_or_kill_ctx(kbdev, head_kctx, !pm_active_err);
+
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+ return;
+ }
+
+ /* From the point on, the Power Management active reference is released
+ * only if kbasep_js_runpool_release_ctx() causes the context to be removed
+ * from the runpool */
+
+ KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_TRY_SCHEDULE_HEAD_CTX, head_kctx, NULL, 0u, kbasep_js_trace_get_refcnt(kbdev, head_kctx));
+
+#if MALI_CUSTOMER_RELEASE == 0
+ if (js_devdata->nr_user_contexts_running == 0) {
+ /* Only when there are no other contexts submitting jobs:
+ * Latch in run-time job scheduler timeouts that were set through js_timeouts sysfs file */
+ if (kbdev->js_soft_stop_ticks != 0)
+ js_devdata->soft_stop_ticks = kbdev->js_soft_stop_ticks;
+
+ if (kbdev->js_hard_stop_ticks_ss != 0)
+ js_devdata->hard_stop_ticks_ss = kbdev->js_hard_stop_ticks_ss;
+
+ if (kbdev->js_hard_stop_ticks_nss != 0)
+ js_devdata->hard_stop_ticks_nss = kbdev->js_hard_stop_ticks_nss;
+
+ if (kbdev->js_reset_ticks_ss != 0)
+ js_devdata->gpu_reset_ticks_ss = kbdev->js_reset_ticks_ss;
+
+ if (kbdev->js_reset_ticks_nss != 0)
+ js_devdata->gpu_reset_ticks_nss = kbdev->js_reset_ticks_nss;
+ }
+#endif
+
+ runpool_inc_context_count(kbdev, head_kctx);
+ /* Cause any future waiter-on-termination to wait until the context is
+ * descheduled */
+ js_kctx_info->ctx.is_scheduled = MALI_TRUE;
+ wake_up(&js_kctx_info->ctx.is_scheduled_wait);
+
+ /* Pick the free address space (guaranteed free by check_is_runpool_full() ) */
+ new_address_space = pick_free_addr_space(kbdev);
+
+ /* Lock the address space whilst working on it */
+ mutex_lock(&new_address_space->transaction_mutex);
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+
+ /* Do all the necessaries to assign the address space (inc. update book-keeping info)
+ * Add the context to the Run Pool, and allow it to run jobs */
+ assign_and_activate_kctx_addr_space(kbdev, head_kctx, new_address_space);
+
+ /* NOTE: If Linux allows, then we can drop the new_address_space->transaction mutex here */
+
+ if ((js_kctx_info->ctx.flags & KBASE_CTX_FLAG_PRIVILEGED) != 0) {
+ /* We need to retain it to keep the corresponding address space */
+ kbasep_js_runpool_retain_ctx_nolock(kbdev, head_kctx);
+ }
+
+ /* Re-check for suspending: a suspend could've occurred after we
+ * pm_context_active'd, and all the contexts could've been removed from the
+ * runpool before we took this lock. In this case, we don't want to allow
+ * this context to run jobs, we just want it out immediately.
+ *
+ * The DMB required to read the suspend flag was issued recently as part of
+ * the runpool_irq locking. If a suspend occurs *after* that lock was taken
+ * (i.e. this condition doesn't execute), then the kbasep_js_suspend() code
+ * will cleanup this context instead (by virtue of it being called strictly
+ * after the suspend flag is set, and will wait for this lock to drop) */
+ if (kbase_pm_is_suspending(kbdev)) {
+ /* Cause it to leave at some later point */
+ mali_bool retained;
+ retained = kbasep_js_runpool_retain_ctx_nolock(kbdev, head_kctx);
+ KBASE_DEBUG_ASSERT(retained);
+ kbasep_js_clear_submit_allowed(js_devdata, head_kctx);
+ head_kctx_suspended = MALI_TRUE;
+ }
+
+ /* Try to run the next job, in case this context has jobs that match the
+ * job slot requirements, but none of the other currently running contexts
+ * do */
+ kbasep_js_try_run_next_job_nolock(kbdev);
+
+ /* Transaction complete */
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+ mutex_unlock(&new_address_space->transaction_mutex);
+ mutex_unlock(&js_devdata->runpool_mutex);
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+ /* Note: after this point, the context could potentially get scheduled out immediately */
+
+ if (head_kctx_suspended) {
+ /* Finishing forcing out the context due to a suspend. Use a variant of
+ * kbasep_js_runpool_release_ctx() that doesn't schedule a new context,
+ * to prevent a risk of recursion back into this function */
+ kbasep_js_runpool_release_ctx_no_schedule(kbdev, head_kctx);
+ }
+ return;
+}
+
+void kbasep_js_schedule_privileged_ctx(kbase_device *kbdev, kbase_context *kctx)
+{
+ kbasep_js_kctx_info *js_kctx_info;
+ kbasep_js_device_data *js_devdata;
+ mali_bool is_scheduled;
+
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+
+ js_devdata = &kbdev->js_data;
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ /* This must never be attempted whilst suspending - i.e. it should only
+ * happen in response to a syscall from a user-space thread */
+ BUG_ON(kbase_pm_is_suspending(kbdev));
+
+ kbase_pm_request_l2_caches(kbdev);
+
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+ /* Mark the context as privileged */
+ js_kctx_info->ctx.flags |= KBASE_CTX_FLAG_PRIVILEGED;
+
+ is_scheduled = js_kctx_info->ctx.is_scheduled;
+ if (is_scheduled == MALI_FALSE) {
+ mali_bool is_runpool_full;
+
+ /* Add the context to the runpool */
+ mutex_lock(&js_devdata->queue_mutex);
+ kbasep_js_policy_enqueue_ctx(&js_devdata->policy, kctx);
+ mutex_unlock(&js_devdata->queue_mutex);
+
+ mutex_lock(&js_devdata->runpool_mutex);
+ {
+ is_runpool_full = check_is_runpool_full(kbdev, kctx);
+ if (is_runpool_full != MALI_FALSE) {
+ /* Evict jobs from the NEXT registers to free an AS asap */
+ kbasep_js_runpool_evict_next_jobs(kbdev, kctx);
+ }
+ }
+ mutex_unlock(&js_devdata->runpool_mutex);
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+ /* Fast-starting requires the jsctx_mutex to be dropped, because it works on multiple ctxs */
+
+ if (is_runpool_full != MALI_FALSE) {
+ /* Evict non-running contexts from the runpool */
+ kbasep_js_runpool_attempt_fast_start_ctx(kbdev, NULL);
+ }
+ /* Try to schedule the context in */
+ kbasep_js_try_schedule_head_ctx(kbdev);
+
+ /* Wait for the context to be scheduled in */
+ wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, kctx->jctx.sched_info.ctx.is_scheduled == MALI_TRUE);
+ } else {
+ /* Already scheduled in - We need to retain it to keep the corresponding address space */
+ kbasep_js_runpool_retain_ctx(kbdev, kctx);
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+
+ }
+}
+
+void kbasep_js_release_privileged_ctx(kbase_device *kbdev, kbase_context *kctx)
+{
+ kbasep_js_kctx_info *js_kctx_info;
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ js_kctx_info = &kctx->jctx.sched_info;
+
+ /* We don't need to use the address space anymore */
+ mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
+ js_kctx_info->ctx.flags &= (~KBASE_CTX_FLAG_PRIVILEGED);
+ mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
+
+ kbase_pm_release_l2_caches(kbdev);
+
+ /* Release the context - it will be scheduled out if there is no pending job */
+ kbasep_js_runpool_release_ctx(kbdev, kctx);
+}
+
+void kbasep_js_job_done_slot_irq(kbase_jd_atom *katom, int slot_nr,
+ ktime_t *end_timestamp,
+ kbasep_js_atom_done_code done_code)
+{
+ kbase_device *kbdev;
+ kbasep_js_policy *js_policy;
+ kbasep_js_device_data *js_devdata;
+ mali_bool submit_retry_needed = MALI_TRUE; /* If we don't start jobs here, start them from the workqueue */
+ ktime_t tick_diff;
+ u64 microseconds_spent = 0u;
+ kbase_context *parent_ctx;
+
+ KBASE_DEBUG_ASSERT(katom);
+ parent_ctx = katom->kctx;
+ KBASE_DEBUG_ASSERT(parent_ctx);
+ kbdev = parent_ctx->kbdev;
+ KBASE_DEBUG_ASSERT(kbdev);
+
+ js_devdata = &kbdev->js_data;
+ js_policy = &kbdev->js_data.policy;
+
+ lockdep_assert_held(&js_devdata->runpool_irq.lock);
+
+ /*
+ * Release resources before submitting new jobs (bounds the refcount of
+ * the resource to BASE_JM_SUBMIT_SLOTS)
+ */
+#ifdef CONFIG_MALI_GATOR_SUPPORT
+ kbase_trace_mali_job_slots_event(GATOR_MAKE_EVENT(GATOR_JOB_SLOT_STOP, slot_nr), NULL);
+#endif /* CONFIG_MALI_GATOR_SUPPORT */
+
+ /* Check if submitted jobs no longer require the cycle counter to be enabled */
+ kbasep_js_deref_permon_check_and_disable_cycle_counter(kbdev, katom);
+
+ /* Release the affinity from the slot - must happen before next submission to this slot */
+ kbase_js_affinity_release_slot_cores(kbdev, slot_nr, katom->affinity);
+ kbase_js_debug_log_current_affinities(kbdev);
+ /* Calculate the job's time used */
+ if (end_timestamp != NULL) {
+ /* Only calculating it for jobs that really run on the HW (e.g. removed
+ * from next jobs never actually ran, so really did take zero time) */
+ tick_diff = ktime_sub(*end_timestamp, katom->start_timestamp);
+
+ microseconds_spent = ktime_to_ns(tick_diff);
+ do_div(microseconds_spent, 1000);
+
+ /* Round up time spent to the minimum timer resolution */
+ if (microseconds_spent < KBASEP_JS_TICK_RESOLUTION_US)
+ microseconds_spent = KBASEP_JS_TICK_RESOLUTION_US;
+ }
+
+ /* Log the result of the job (completion status, and time spent). */
+ kbasep_js_policy_log_job_result(js_policy, katom, microseconds_spent);
+ /* Determine whether the parent context's timeslice is up */
+ if (kbasep_js_policy_should_remove_ctx(js_policy, parent_ctx) != MALI_FALSE)
+ kbasep_js_clear_submit_allowed(js_devdata, parent_ctx);
+
+ if (done_code & KBASE_JS_ATOM_DONE_START_NEW_ATOMS) {
+ /* Submit a new job (if there is one) to help keep the GPU's HEAD and NEXT registers full */
+ KBASE_TRACE_ADD_SLOT(kbdev, JS_JOB_DONE_TRY_RUN_NEXT_JOB, parent_ctx, katom, katom->jc, slot_nr);
+
+ submit_retry_needed = kbasep_js_try_run_next_job_on_slot_irq_nolock(kbdev, slot_nr, &kbdev->slot_submit_count_irq[slot_nr]);
+ }
+
+ if (submit_retry_needed != MALI_FALSE || katom->event_code == BASE_JD_EVENT_STOPPED) {
+ /* The extra condition on STOPPED jobs is needed because they may be
+ * the only job present, but they won't get re-run until the JD work
+ * queue activates. Crucially, work queues can run items out of order
+ * e.g. on different CPUs, so being able to submit from the IRQ handler
+ * is not a good indication that we don't need to run jobs; the
+ * submitted job could be processed on the work-queue *before* the
+ * stopped job, even though it was submitted after.
+ *
+ * Therefore, we must try to run it, otherwise it might not get run at
+ * all after this. */
+
+ KBASE_TRACE_ADD_SLOT(kbdev, JS_JOB_DONE_RETRY_NEEDED, parent_ctx, katom, katom->jc, slot_nr);
+ kbasep_js_set_job_retry_submit_slot(katom, slot_nr);
+ }
+}
+
+void kbasep_js_suspend(kbase_device *kbdev)
+{
+ unsigned long flags;
+ kbasep_js_device_data *js_devdata;
+ int i;
+ u16 retained = 0u;
+ int nr_privileged_ctx = 0;
+ KBASE_DEBUG_ASSERT(kbdev);
+ KBASE_DEBUG_ASSERT(kbase_pm_is_suspending(kbdev));
+ js_devdata = &kbdev->js_data;
+
+ spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
+
+ /* Prevent all contexts from submitting */
+ js_devdata->runpool_irq.submit_allowed = 0;
+
+ /* Retain each of the contexts, so we can cause it to leave even if it had
+ * no refcount to begin with */
+ for (i = BASE_MAX_NR_AS - 1; i >= 0; --i) {
+ kbasep_js_per_as_data *js_per_as_data = &js_devdata->runpool_irq.per_as_data[i];
+ kbase_context *kctx = js_per_as_data->kctx;
+ retained = retained << 1;
+
+ if (kctx) {
+ ++(js_per_as_data->as_busy_refcount);
+ retained |= 1u;
+ /* We can only cope with up to 1 privileged context - the
+ * instrumented context. It'll be suspended by disabling
+ * instrumentation */
+ if (kctx->jctx.sched_info.ctx.flags & KBASE_CTX_FLAG_PRIVILEGED)
+ KBASE_DEBUG_ASSERT(++nr_privileged_ctx == 1);
+ }
+ }
+ CSTD_UNUSED(nr_privileged_ctx);
+ spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
+
+ /* De-ref the previous retain to ensure each context gets pulled out
+ * sometime later. */
+ for (i = 0;
+ i < BASE_MAX_NR_AS;
+ ++i, retained = retained >> 1) {
+ kbasep_js_per_as_data *js_per_as_data = &js_devdata->runpool_irq.per_as_data[i];
+ kbase_context *kctx = js_per_as_data->kctx;
+
+ if (retained & 1u)
+ kbasep_js_runpool_release_ctx(kbdev,kctx);
+ }
+
+ /* Caller must wait for all Power Manager active references to be dropped */
+}
+
+void kbasep_js_resume(kbase_device *kbdev)
+{
+ kbasep_js_device_data *js_devdata;
+ int i;
+ KBASE_DEBUG_ASSERT(kbdev);
+ js_devdata = &kbdev->js_data;
+
+ KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev));
+
+ /* Schedule in as many contexts as address spaces. This also starts atoms. */
+ for (i = 0 ; i < kbdev->nr_hw_address_spaces; ++i)
+ {
+ kbasep_js_try_schedule_head_ctx(kbdev);
+ }
+ /* JS Resume complete */
+}
diff --git a/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js.h b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js.h
new file mode 100755
index 00000000000..20abb90d58a
--- /dev/null
+++ b/drivers/gpu/arm/t6xx/kbase/src/common/mali_kbase_js.h
@@ -0,0 +1,927 @@
+/*
+ *
+ * (C) COPYRIGHT 2011-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+/**
+ * @file mali_kbase_js.h
+ * Job Scheduler APIs.
+ */
+
+#ifndef _KBASE_JS_H_
+#define _KBASE_JS_H_
+
+#include <malisw/mali_malisw.h>
+
+#include "mali_kbase_js_defs.h"
+#include "mali_kbase_js_policy.h"
+#include "mali_kbase_defs.h"
+
+#include "mali_kbase_js_ctx_attr.h"
+
+/**
+ * @addtogroup base_api
+ * @{
+ */
+
+/**
+ * @addtogroup base_kbase_api
+ * @{
+ */
+
+/**
+ * @addtogroup kbase_js Job Scheduler Internal APIs
+ * @{
+ *
+ * These APIs are Internal to KBase and are available for use by the
+ * @ref kbase_js_policy "Job Scheduler Policy APIs"
+ */
+
+/**
+ * @brief Initialize the Job Scheduler
+ *
+ * The kbasep_js_device_data sub-structure of \a kbdev must be zero
+ * initialized before passing to the kbasep_js_devdata_init() function. This is
+ * to give efficient error path code.
+ */
+mali_error kbasep_js_devdata_init(kbase_device * const kbdev);
+
+/**
+ * @brief Halt the Job Scheduler.
+ *
+ * It is safe to call this on \a kbdev even if it the kbasep_js_device_data
+ * sub-structure was never initialized/failed initialization, to give efficient
+ * error-path code.
+ *
+ * For this to work, the kbasep_js_device_data sub-structure of \a kbdev must
+ * be zero initialized before passing to the kbasep_js_devdata_init()
+ * function. This is to give efficient error path