+++ /dev/null
-From 39f791b03c5e534884f13ecfb9f86306fe7324dd Mon Sep 17 00:00:00 2001
-From: binqi zhang <binqi.zhang@amlogic.com>
-Date: Thu, 12 Aug 2021 16:34:29 +0800
-Subject: [PATCH] update r32p1 gpu driver
-
-Change-Id: Ic8672b57c42e98ed97c65b48925280fbb38de0ee
----
- .../ABI/testing/sysfs-device-mali | 293 +
- .../devicetree/bindings/arm/mali-midgard.txt | 19 +-
- .../bindings/arm/memory_group_manager.txt | 7 +-
- .../bindings/arm/priority_control_manager.txt | 48 +
- .../arm/protected_memory_allocator.txt | 7 +-
- .../devicetree/bindings/power/mali-opp.txt | 9 +-
- .../Documentation/dma-buf-test-exporter.txt | 10 +-
- dvalin/kernel/Mconfig | 31 +-
- dvalin/kernel/build.bp | 65 +-
- dvalin/kernel/drivers/base/arm/Kbuild | 34 +
- dvalin/kernel/drivers/base/arm/Kconfig | 64 +
- dvalin/kernel/drivers/base/arm/Makefile | 98 +
- dvalin/kernel/drivers/base/arm/Mconfig | 64 +
- .../base/{ => arm}/dma_buf_lock/src/Kbuild | 9 +-
- .../base/{ => arm}/dma_buf_lock/src/Makefile | 17 +-
- .../{ => arm}/dma_buf_lock/src/dma_buf_lock.c | 132 +-
- .../{ => arm}/dma_buf_lock/src/dma_buf_lock.h | 7 +-
- .../base/arm/dma_buf_test_exporter/Kbuild | 23 +
- .../base/arm/dma_buf_test_exporter/build.bp | 36 +
- .../dma-buf-test-exporter.c | 106 +-
- .../memory_group_manager}/Kbuild | 11 +-
- .../base/arm/memory_group_manager/build.bp | 36 +
- .../memory_group_manager.c | 14 +-
- .../arm/protected_memory_allocator/Kbuild | 23 +
- .../arm/protected_memory_allocator/build.bp | 36 +
- .../protected_memory_allocator.c | 551 ++
- .../base/dma_buf_test_exporter/Kconfig | 26 -
- .../base/dma_buf_test_exporter/Makefile | 36 -
- .../base/dma_buf_test_exporter/build.bp | 26 -
- .../base/memory_group_manager/Makefile | 35 -
- .../base/memory_group_manager/build.bp | 22 -
- .../base/protected_memory_allocator/Makefile | 35 -
- .../base/protected_memory_allocator/build.bp | 26 -
- .../protected_memory_allocator.c | 308 -
- dvalin/kernel/drivers/gpu/arm/Kbuild | 8 +-
- dvalin/kernel/drivers/gpu/arm/Kconfig | 8 +-
- .../Kbuild => gpu/arm/Makefile} | 9 +-
- dvalin/kernel/drivers/gpu/arm/midgard/Kbuild | 367 +-
- dvalin/kernel/drivers/gpu/arm/midgard/Kconfig | 357 +-
- .../kernel/drivers/gpu/arm/midgard/Makefile | 201 +-
- dvalin/kernel/drivers/gpu/arm/midgard/Mconfig | 288 +-
- .../drivers/gpu/arm/midgard/arbiter/Kbuild | 11 +-
- .../arm/midgard/arbiter/mali_kbase_arbif.c | 209 +-
- .../arm/midgard/arbiter/mali_kbase_arbif.h | 44 +-
- .../midgard/arbiter/mali_kbase_arbiter_defs.h | 34 +-
- .../arbiter/mali_kbase_arbiter_interface.h | 70 +-
- .../midgard/arbiter/mali_kbase_arbiter_pm.c | 614 +-
- .../midgard/arbiter/mali_kbase_arbiter_pm.h | 87 +-
- .../gpu/arm/midgard/backend/gpu/Kbuild | 70 +-
- .../backend/gpu/mali_kbase_backend_config.h | 7 +-
- .../gpu/mali_kbase_cache_policy_backend.c | 9 +-
- .../gpu/mali_kbase_cache_policy_backend.h | 10 +-
- .../gpu/mali_kbase_clk_rate_trace_mgr.c | 325 ++
- .../gpu/mali_kbase_clk_rate_trace_mgr.h | 154 +
- .../gpu/mali_kbase_debug_job_fault_backend.c | 11 +-
- .../midgard/backend/gpu/mali_kbase_devfreq.c | 207 +-
- .../midgard/backend/gpu/mali_kbase_devfreq.h | 23 +-
- .../backend/gpu/mali_kbase_device_hw.c | 388 --
- .../backend/gpu/mali_kbase_device_internal.h | 127 -
- .../backend/gpu/mali_kbase_gpuprops_backend.c | 75 +-
- .../backend/gpu/mali_kbase_instr_backend.c | 130 +-
- .../backend/gpu/mali_kbase_instr_defs.h | 18 +-
- .../backend/gpu/mali_kbase_instr_internal.h | 9 +-
- .../backend/gpu/mali_kbase_irq_internal.h | 7 +-
- .../backend/gpu/mali_kbase_irq_linux.c | 37 +-
- .../midgard/backend/gpu/mali_kbase_jm_as.c | 14 +-
- .../midgard/backend/gpu/mali_kbase_jm_defs.h | 20 +-
- .../midgard/backend/gpu/mali_kbase_jm_hw.c | 236 +-
- .../backend/gpu/mali_kbase_jm_internal.h | 17 +-
- .../midgard/backend/gpu/mali_kbase_jm_rb.c | 145 +-
- .../midgard/backend/gpu/mali_kbase_jm_rb.h | 8 +-
- .../backend/gpu/mali_kbase_js_backend.c | 61 +-
- .../backend/gpu/mali_kbase_js_internal.h | 8 +-
- .../backend/gpu/mali_kbase_l2_mmu_config.c | 47 +-
- .../backend/gpu/mali_kbase_l2_mmu_config.h | 25 +-
- .../backend/gpu/mali_kbase_pm_always_on.c | 13 +-
- .../backend/gpu/mali_kbase_pm_always_on.h | 9 +-
- .../backend/gpu/mali_kbase_pm_backend.c | 243 +-
- .../midgard/backend/gpu/mali_kbase_pm_ca.c | 44 +-
- .../midgard/backend/gpu/mali_kbase_pm_ca.h | 7 +-
- .../backend/gpu/mali_kbase_pm_ca_devfreq.h | 7 +-
- .../backend/gpu/mali_kbase_pm_coarse_demand.c | 13 +-
- .../backend/gpu/mali_kbase_pm_coarse_demand.h | 9 +-
- .../midgard/backend/gpu/mali_kbase_pm_defs.h | 244 +-
- .../backend/gpu/mali_kbase_pm_driver.c | 907 ++-
- .../backend/gpu/mali_kbase_pm_internal.h | 143 +-
- .../backend/gpu/mali_kbase_pm_l2_states.h | 20 +-
- .../backend/gpu/mali_kbase_pm_mcu_states.h | 63 +
- .../backend/gpu/mali_kbase_pm_metrics.c | 271 +-
- .../backend/gpu/mali_kbase_pm_policy.c | 204 +-
- .../backend/gpu/mali_kbase_pm_policy.h | 7 +-
- .../backend/gpu/mali_kbase_pm_shader_states.h | 44 +-
- .../arm/midgard/backend/gpu/mali_kbase_time.c | 57 +-
- .../kernel/drivers/gpu/arm/midgard/build.bp | 203 +-
- .../arm/midgard/context/Kbuild} | 19 +-
- .../context/backend/mali_kbase_context_csf.c | 201 +
- .../context/backend/mali_kbase_context_jm.c | 138 +-
- .../arm/midgard/context/mali_kbase_context.c | 205 +-
- .../arm/midgard/context/mali_kbase_context.h | 35 +-
- .../context/mali_kbase_context_internal.h | 18 +-
- .../kernel/drivers/gpu/arm/midgard/csf/Kbuild | 47 +
- .../ipa_control/Kbuild} | 11 +-
- .../ipa_control/mali_kbase_csf_ipa_control.c | 925 +++
- .../ipa_control/mali_kbase_csf_ipa_control.h | 244 +
- .../gpu/arm/midgard/csf/mali_kbase_csf.c | 3069 ++++++++++
- .../gpu/arm/midgard/csf/mali_kbase_csf.h | 564 ++
- .../csf/mali_kbase_csf_cpu_queue_debugfs.c | 191 +
- .../csf/mali_kbase_csf_cpu_queue_debugfs.h | 90 +
- .../midgard/csf/mali_kbase_csf_csg_debugfs.c | 591 ++
- .../midgard/csf/mali_kbase_csf_csg_debugfs.h | 47 +
- .../gpu/arm/midgard/csf/mali_kbase_csf_defs.h | 1254 ++++
- .../arm/midgard/csf/mali_kbase_csf_firmware.c | 2337 ++++++++
- .../arm/midgard/csf/mali_kbase_csf_firmware.h | 811 +++
- .../midgard/csf/mali_kbase_csf_firmware_cfg.c | 327 ++
- .../midgard/csf/mali_kbase_csf_firmware_cfg.h | 74 +
- .../csf/mali_kbase_csf_firmware_no_mali.c | 1389 +++++
- .../csf/mali_kbase_csf_heap_context_alloc.c | 195 +
- .../csf/mali_kbase_csf_heap_context_alloc.h | 75 +
- .../gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c | 2258 ++++++++
- .../gpu/arm/midgard/csf/mali_kbase_csf_kcpu.h | 356 ++
- .../midgard/csf/mali_kbase_csf_kcpu_debugfs.c | 197 +
- .../midgard/csf/mali_kbase_csf_kcpu_debugfs.h | 37 +
- .../csf/mali_kbase_csf_protected_memory.c | 119 +
- .../csf/mali_kbase_csf_protected_memory.h | 71 +
- .../midgard/csf/mali_kbase_csf_reset_gpu.c | 629 ++
- .../midgard/csf/mali_kbase_csf_scheduler.c | 5063 +++++++++++++++++
- .../midgard/csf/mali_kbase_csf_scheduler.h | 494 ++
- .../midgard/csf/mali_kbase_csf_tiler_heap.c | 611 ++
- .../midgard/csf/mali_kbase_csf_tiler_heap.h | 115 +
- .../csf/mali_kbase_csf_tiler_heap_debugfs.c | 106 +
- .../csf/mali_kbase_csf_tiler_heap_debugfs.h | 37 +
- .../csf/mali_kbase_csf_tiler_heap_def.h | 114 +
- .../arm/midgard/csf/mali_kbase_csf_timeout.c | 178 +
- .../arm/midgard/csf/mali_kbase_csf_timeout.h | 66 +
- .../midgard/csf/mali_kbase_csf_tl_reader.c | 534 ++
- .../midgard/csf/mali_kbase_csf_tl_reader.h | 185 +
- .../midgard/csf/mali_kbase_csf_trace_buffer.c | 688 +++
- .../midgard/csf/mali_kbase_csf_trace_buffer.h | 182 +
- .../drivers/gpu/arm/midgard/debug/Kbuild | 27 +
- .../mali_kbase_debug_ktrace_codes_csf.h | 278 +
- .../mali_kbase_debug_ktrace_codes_jm.h | 10 +-
- .../backend/mali_kbase_debug_ktrace_csf.c | 193 +
- .../backend/mali_kbase_debug_ktrace_csf.h | 203 +
- .../mali_kbase_debug_ktrace_defs_csf.h | 116 +
- .../backend/mali_kbase_debug_ktrace_defs_jm.h | 100 +-
- .../backend/mali_kbase_debug_ktrace_jm.c | 50 +-
- .../backend/mali_kbase_debug_ktrace_jm.h | 118 +-
- .../mali_kbase_debug_linux_ktrace_csf.h | 241 +
- .../mali_kbase_debug_linux_ktrace_jm.h | 52 +-
- .../midgard/debug/mali_kbase_debug_ktrace.c | 55 +-
- .../midgard/debug/mali_kbase_debug_ktrace.h | 20 +-
- .../debug/mali_kbase_debug_ktrace_codes.h | 24 +-
- .../debug/mali_kbase_debug_ktrace_defs.h | 83 +-
- .../debug/mali_kbase_debug_ktrace_internal.h | 7 +-
- .../debug/mali_kbase_debug_linux_ktrace.h | 40 +-
- .../{tests/kutf/Makefile => device/Kbuild} | 30 +-
- .../device/backend/mali_kbase_device_csf.c | 464 ++
- .../device/backend/mali_kbase_device_hw_csf.c | 163 +
- .../device/backend/mali_kbase_device_hw_jm.c | 98 +
- .../device/backend/mali_kbase_device_jm.c | 181 +-
- .../arm/midgard/device/mali_kbase_device.c | 233 +-
- .../arm/midgard/device/mali_kbase_device.h | 126 +-
- .../arm/midgard/device/mali_kbase_device_hw.c | 182 +
- .../device/mali_kbase_device_internal.h | 24 +-
- .../{tests/kutf/Kconfig => gpu/Kbuild} | 19 +-
- .../gpu/backend/mali_kbase_gpu_fault_csf.c | 104 +
- .../gpu/backend/mali_kbase_gpu_fault_jm.c | 13 +-
- .../gpu/arm/midgard/gpu/mali_kbase_gpu.c | 8 +-
- .../arm/midgard/gpu/mali_kbase_gpu_fault.h | 23 +-
- .../arm/midgard/gpu/mali_kbase_gpu_regmap.h | 416 +-
- .../kernel/drivers/gpu/arm/midgard/ipa/Kbuild | 25 +-
- .../mali_kbase_ipa_counter_common_csf.c | 457 ++
- .../mali_kbase_ipa_counter_common_csf.h | 159 +
- .../mali_kbase_ipa_counter_common_jm.c} | 20 +-
- .../mali_kbase_ipa_counter_common_jm.h} | 40 +-
- .../ipa/backend/mali_kbase_ipa_counter_csf.c | 171 +
- .../mali_kbase_ipa_counter_jm.c} | 113 +-
- .../gpu/arm/midgard/ipa/mali_kbase_ipa.c | 287 +-
- .../gpu/arm/midgard/ipa/mali_kbase_ipa.h | 90 +-
- .../arm/midgard/ipa/mali_kbase_ipa_debugfs.c | 12 +-
- .../arm/midgard/ipa/mali_kbase_ipa_debugfs.h | 12 +-
- .../arm/midgard/ipa/mali_kbase_ipa_simple.c | 53 +-
- .../arm/midgard/ipa/mali_kbase_ipa_simple.h | 7 +-
- .../gpu/arm/midgard/jm/mali_kbase_jm_defs.h | 76 +-
- .../gpu/arm/midgard/jm/mali_kbase_jm_js.h | 89 +-
- .../gpu/arm/midgard/jm/mali_kbase_js_defs.h | 411 +-
- .../arm/midgard/mali_base_hwconfig_features.h | 62 +-
- .../arm/midgard/mali_base_hwconfig_issues.h | 62 +-
- .../drivers/gpu/arm/midgard/mali_kbase.h | 165 +-
- .../arm/midgard/mali_kbase_as_fault_debugfs.c | 11 +-
- .../arm/midgard/mali_kbase_as_fault_debugfs.h | 9 +-
- .../drivers/gpu/arm/midgard/mali_kbase_bits.h | 16 +-
- .../gpu/arm/midgard/mali_kbase_cache_policy.c | 12 +-
- .../gpu/arm/midgard/mali_kbase_cache_policy.h | 11 +-
- .../drivers/gpu/arm/midgard/mali_kbase_caps.h | 61 +
- .../gpu/arm/midgard/mali_kbase_ccswe.c | 100 +
- .../gpu/arm/midgard/mali_kbase_ccswe.h | 96 +
- .../gpu/arm/midgard/mali_kbase_config.c | 68 +-
- .../gpu/arm/midgard/mali_kbase_config.h | 294 +-
- .../arm/midgard/mali_kbase_config_defaults.h | 26 +-
- .../gpu/arm/midgard/mali_kbase_core_linux.c | 1969 +++++--
- .../arm/midgard/mali_kbase_cs_experimental.h | 20 +-
- .../gpu/arm/midgard/mali_kbase_ctx_sched.c | 84 +-
- .../gpu/arm/midgard/mali_kbase_ctx_sched.h | 44 +-
- .../gpu/arm/midgard/mali_kbase_debug.c | 9 +-
- .../gpu/arm/midgard/mali_kbase_debug.h | 79 +-
- .../arm/midgard/mali_kbase_debug_job_fault.c | 36 +-
- .../arm/midgard/mali_kbase_debug_job_fault.h | 10 +-
- .../arm/midgard/mali_kbase_debug_mem_view.c | 26 +-
- .../arm/midgard/mali_kbase_debug_mem_view.h | 7 +-
- .../arm/midgard/mali_kbase_debugfs_helper.c | 104 +-
- .../arm/midgard/mali_kbase_debugfs_helper.h | 53 +-
- .../drivers/gpu/arm/midgard/mali_kbase_defs.h | 573 +-
- .../arm/midgard/mali_kbase_disjoint_events.c | 7 +-
- .../gpu/arm/midgard/mali_kbase_dma_fence.c | 59 +-
- .../gpu/arm/midgard/mali_kbase_dma_fence.h | 26 +-
- .../gpu/arm/midgard/mali_kbase_dummy_job_wa.c | 15 +-
- .../gpu/arm/midgard/mali_kbase_dummy_job_wa.h | 36 +-
- .../gpu/arm/midgard/mali_kbase_dvfs_debugfs.c | 98 +
- .../gpu/arm/midgard/mali_kbase_dvfs_debugfs.h | 35 +
- .../gpu/arm/midgard/mali_kbase_event.c | 30 +-
- .../gpu/arm/midgard/mali_kbase_fence.c | 73 +-
- .../gpu/arm/midgard/mali_kbase_fence.h | 17 +-
- .../gpu/arm/midgard/mali_kbase_fence_defs.h | 15 +-
- .../gpu/arm/midgard/mali_kbase_fence_ops.c | 83 +
- .../gpu/arm/midgard/mali_kbase_gator.h | 7 +-
- .../midgard/mali_kbase_gpu_memory_debugfs.c | 22 +-
- .../midgard/mali_kbase_gpu_memory_debugfs.h | 26 +-
- .../gpu/arm/midgard/mali_kbase_gpuprops.c | 315 +-
- .../gpu/arm/midgard/mali_kbase_gpuprops.h | 67 +-
- .../arm/midgard/mali_kbase_gpuprops_types.h | 89 +-
- .../drivers/gpu/arm/midgard/mali_kbase_gwt.c | 11 +-
- .../drivers/gpu/arm/midgard/mali_kbase_gwt.h | 9 +-
- .../drivers/gpu/arm/midgard/mali_kbase_hw.c | 230 +-
- .../drivers/gpu/arm/midgard/mali_kbase_hw.h | 23 +-
- .../arm/midgard/mali_kbase_hwaccess_backend.h | 8 +-
- .../arm/midgard/mali_kbase_hwaccess_defs.h | 15 +-
- .../midgard/mali_kbase_hwaccess_gpuprops.h | 39 +-
- .../arm/midgard/mali_kbase_hwaccess_instr.h | 22 +-
- .../gpu/arm/midgard/mali_kbase_hwaccess_jm.h | 12 +-
- .../gpu/arm/midgard/mali_kbase_hwaccess_pm.h | 75 +-
- .../arm/midgard/mali_kbase_hwaccess_time.h | 30 +-
- .../gpu/arm/midgard/mali_kbase_hwcnt.c | 103 +-
- .../midgard/mali_kbase_hwcnt_accumulator.h | 7 +-
- .../arm/midgard/mali_kbase_hwcnt_backend.h | 102 +-
- .../midgard/mali_kbase_hwcnt_backend_csf.c | 1864 ++++++
- .../midgard/mali_kbase_hwcnt_backend_csf.h | 162 +
- .../midgard/mali_kbase_hwcnt_backend_csf_if.h | 311 +
- .../mali_kbase_hwcnt_backend_csf_if_fw.c | 787 +++
- .../mali_kbase_hwcnt_backend_csf_if_fw.h | 50 +
- .../midgard/mali_kbase_hwcnt_backend_gpu.c | 510 --
- .../arm/midgard/mali_kbase_hwcnt_backend_jm.c | 793 +++
- ...nd_gpu.h => mali_kbase_hwcnt_backend_jm.h} | 23 +-
- .../arm/midgard/mali_kbase_hwcnt_context.h | 46 +-
- .../gpu/arm/midgard/mali_kbase_hwcnt_gpu.c | 760 +--
- .../gpu/arm/midgard/mali_kbase_hwcnt_gpu.h | 314 +-
- .../gpu/arm/midgard/mali_kbase_hwcnt_legacy.c | 11 +-
- .../gpu/arm/midgard/mali_kbase_hwcnt_legacy.h | 7 +-
- .../gpu/arm/midgard/mali_kbase_hwcnt_types.c | 129 +-
- .../gpu/arm/midgard/mali_kbase_hwcnt_types.h | 125 +-
- .../midgard/mali_kbase_hwcnt_virtualizer.c | 26 +-
- .../midgard/mali_kbase_hwcnt_virtualizer.h | 23 +-
- .../drivers/gpu/arm/midgard/mali_kbase_jd.c | 331 +-
- .../gpu/arm/midgard/mali_kbase_jd_debugfs.c | 56 +-
- .../gpu/arm/midgard/mali_kbase_jd_debugfs.h | 12 +-
- .../drivers/gpu/arm/midgard/mali_kbase_jm.c | 16 +-
- .../drivers/gpu/arm/midgard/mali_kbase_jm.h | 12 +-
- .../drivers/gpu/arm/midgard/mali_kbase_js.c | 422 +-
- .../drivers/gpu/arm/midgard/mali_kbase_js.h | 12 +-
- .../gpu/arm/midgard/mali_kbase_js_ctx_attr.c | 39 +-
- .../gpu/arm/midgard/mali_kbase_js_ctx_attr.h | 47 +-
- .../gpu/arm/midgard/mali_kbase_kinstr_jm.c | 894 +++
- .../gpu/arm/midgard/mali_kbase_kinstr_jm.h | 275 +
- .../gpu/arm/midgard/mali_kbase_linux.h | 12 +-
- .../drivers/gpu/arm/midgard/mali_kbase_mem.c | 1160 ++--
- .../drivers/gpu/arm/midgard/mali_kbase_mem.h | 518 +-
- .../gpu/arm/midgard/mali_kbase_mem_linux.c | 683 ++-
- .../gpu/arm/midgard/mali_kbase_mem_linux.h | 36 +-
- .../gpu/arm/midgard/mali_kbase_mem_lowlevel.h | 13 +-
- .../gpu/arm/midgard/mali_kbase_mem_pool.c | 44 +-
- .../arm/midgard/mali_kbase_mem_pool_debugfs.c | 7 +-
- .../arm/midgard/mali_kbase_mem_pool_debugfs.h | 7 +-
- .../arm/midgard/mali_kbase_mem_pool_group.c | 7 +-
- .../arm/midgard/mali_kbase_mem_pool_group.h | 7 +-
- .../midgard/mali_kbase_mem_profile_debugfs.c | 26 +-
- .../midgard/mali_kbase_mem_profile_debugfs.h | 23 +-
- .../mali_kbase_mem_profile_debugfs_buf_size.h | 8 +-
- .../arm/midgard/mali_kbase_mipe_gen_header.h | 40 +-
- .../gpu/arm/midgard/mali_kbase_mipe_proto.h | 7 +-
- .../gpu/arm/midgard/mali_kbase_native_mgm.c | 7 +-
- .../gpu/arm/midgard/mali_kbase_native_mgm.h | 9 +-
- .../arm/midgard/mali_kbase_platform_fake.c | 15 +-
- .../drivers/gpu/arm/midgard/mali_kbase_pm.c | 55 +-
- .../drivers/gpu/arm/midgard/mali_kbase_pm.h | 34 +-
- .../midgard/mali_kbase_regs_history_debugfs.c | 138 +-
- .../midgard/mali_kbase_regs_history_debugfs.h | 40 +-
- .../gpu/arm/midgard/mali_kbase_reset_gpu.h | 162 +-
- .../drivers/gpu/arm/midgard/mali_kbase_smc.c | 9 +-
- .../drivers/gpu/arm/midgard/mali_kbase_smc.h | 11 +-
- .../gpu/arm/midgard/mali_kbase_softjobs.c | 167 +-
- .../gpu/arm/midgard/mali_kbase_strings.c | 10 +-
- .../gpu/arm/midgard/mali_kbase_strings.h | 7 +-
- .../drivers/gpu/arm/midgard/mali_kbase_sync.h | 28 +-
- .../gpu/arm/midgard/mali_kbase_sync_android.c | 67 +-
- .../gpu/arm/midgard/mali_kbase_sync_common.c | 11 +-
- .../gpu/arm/midgard/mali_kbase_sync_file.c | 36 +-
- .../arm/midgard/mali_kbase_trace_gpu_mem.c | 221 +
- .../arm/midgard/mali_kbase_trace_gpu_mem.h | 100 +
- .../gpu/arm/midgard/mali_kbase_utility.h | 11 +-
- .../gpu/arm/midgard/mali_kbase_vinstr.c | 311 +-
- .../gpu/arm/midgard/mali_kbase_vinstr.h | 7 +-
- .../gpu/arm/midgard/mali_linux_trace.h | 47 +-
- .../drivers/gpu/arm/midgard/mali_malisw.h | 60 +-
- ...gpu.h => mali_power_gpu_frequency_trace.c} | 21 +-
- .../midgard/mali_power_gpu_frequency_trace.h | 68 +
- .../Kconfig => gpu/arm/midgard/mmu/Kbuild} | 22 +-
- .../midgard/mmu/backend/mali_kbase_mmu_csf.c | 565 ++
- .../midgard/mmu/backend/mali_kbase_mmu_jm.c | 90 +-
- .../gpu/arm/midgard/mmu/mali_kbase_mmu.c | 220 +-
- .../gpu/arm/midgard/mmu/mali_kbase_mmu.h | 45 +-
- .../gpu/arm/midgard/mmu/mali_kbase_mmu_hw.h | 12 +-
- .../midgard/mmu/mali_kbase_mmu_hw_direct.c | 67 +-
- .../arm/midgard/mmu/mali_kbase_mmu_internal.h | 49 +-
- .../midgard/mmu/mali_kbase_mmu_mode_aarch64.c | 25 +-
- .../midgard/mmu/mali_kbase_mmu_mode_lpae.c | 215 -
- .../drivers/gpu/arm/midgard/platform/Kconfig | 10 +-
- .../arm/midgard/platform/devicetree/Kbuild | 7 +-
- .../midgard/platform/devicetree/Kbuild.rej | 17 +
- .../devicetree/mali_kbase_clk_rate_trace.c | 105 +
- .../devicetree/mali_kbase_config_devicetree.c | 39 +-
- .../devicetree/mali_kbase_config_platform.c | 43 +
- .../devicetree/mali_kbase_config_platform.h | 54 +-
- .../mali_kbase_config_platform.h.rej | 42 +
- .../devicetree/mali_kbase_runtime_pm.c | 26 +-
- .../gpu/arm/midgard/platform/vexpress/Kbuild | 11 +-
- .../vexpress/mali_kbase_config_platform.h | 7 +-
- .../vexpress/mali_kbase_config_vexpress.c | 22 +-
- .../midgard/platform/vexpress_1xv7_a57/Kbuild | 11 +-
- .../mali_kbase_config_platform.h | 7 +-
- .../mali_kbase_config_vexpress.c | 20 +-
- .../platform/vexpress_6xvirtex7_10mhz/Kbuild | 13 +-
- .../mali_kbase_config_platform.h | 7 +-
- .../mali_kbase_config_vexpress.c | 22 +-
- .../gpu/arm/midgard/protected_mode_switcher.h | 31 +-
- .../drivers/gpu/arm/midgard/tests/Kbuild | 17 +-
- .../drivers/gpu/arm/midgard/tests/Kconfig | 46 +-
- .../drivers/gpu/arm/midgard/tests/Mconfig | 81 +-
- .../drivers/gpu/arm/midgard/tests/build.bp | 40 +
- .../midgard/tests/include/kutf/kutf_helpers.h | 15 +-
- .../tests/include/kutf/kutf_helpers_user.h | 25 +-
- .../arm/midgard/tests/include/kutf/kutf_mem.h | 7 +-
- .../tests/include/kutf/kutf_resultset.h | 7 +-
- .../midgard/tests/include/kutf/kutf_suite.h | 29 +-
- .../midgard/tests/include/kutf/kutf_utils.h | 7 +-
- .../drivers/gpu/arm/midgard/tests/kutf/Kbuild | 21 +-
- .../gpu/arm/midgard/tests/kutf/build.bp | 24 +-
- .../gpu/arm/midgard/tests/kutf/kutf_helpers.c | 13 +-
- .../midgard/tests/kutf/kutf_helpers_user.c | 28 +-
- .../gpu/arm/midgard/tests/kutf/kutf_mem.c | 7 +-
- .../arm/midgard/tests/kutf/kutf_resultset.c | 7 +-
- .../gpu/arm/midgard/tests/kutf/kutf_suite.c | 23 +-
- .../gpu/arm/midgard/tests/kutf/kutf_utils.c | 7 +-
- .../mali_kutf_clk_rate_trace/kernel/Kbuild | 25 +
- .../mali_kutf_clk_rate_trace/kernel/build.bp | 43 +
- .../kernel/mali_kutf_clk_rate_trace_test.c | 957 ++++
- .../mali_kutf_clk_rate_trace_test.h | 151 +
- .../midgard/tests/mali_kutf_irq_test/Kbuild | 13 +-
- .../midgard/tests/mali_kutf_irq_test/Kconfig | 29 -
- .../midgard/tests/mali_kutf_irq_test/Makefile | 51 -
- .../midgard/tests/mali_kutf_irq_test/build.bp | 21 +-
- .../mali_kutf_irq_test_main.c | 15 +-
- .../arm/midgard/thirdparty}/Kbuild | 9 +-
- .../arm/midgard/thirdparty/mali_kbase_mmap.c | 77 +-
- .../kernel/drivers/gpu/arm/midgard/tl/Kbuild | 32 +
- .../tl/backend/mali_kbase_timeline_csf.c | 171 +
- .../tl/backend/mali_kbase_timeline_jm.c | 23 +-
- .../gpu/arm/midgard/tl/mali_kbase_timeline.c | 142 +-
- .../gpu/arm/midgard/tl/mali_kbase_timeline.h | 57 +-
- .../arm/midgard/tl/mali_kbase_timeline_io.c | 177 +-
- .../arm/midgard/tl/mali_kbase_timeline_priv.h | 26 +-
- .../arm/midgard/tl/mali_kbase_tl_serialize.h | 7 +-
- .../gpu/arm/midgard/tl/mali_kbase_tlstream.c | 43 +-
- .../gpu/arm/midgard/tl/mali_kbase_tlstream.h | 22 +-
- .../arm/midgard/tl/mali_kbase_tracepoints.c | 585 +-
- .../arm/midgard/tl/mali_kbase_tracepoints.h | 1159 +++-
- .../include/linux/dma-buf-test-exporter.h | 8 +-
- .../include/linux/memory_group_manager.h | 7 +-
- .../include/linux/priority_control_manager.h | 77 +
- .../linux/protected_memory_allocator.h | 7 +-
- .../include/linux/protected_mode_switcher.h | 7 +-
- .../arm/midgard/csf/mali_base_csf_kernel.h | 765 +++
- .../csf/mali_gpu_csf_control_registers.h | 32 +
- .../arm/midgard/csf/mali_gpu_csf_registers.h | 1488 +++++
- .../arm/midgard/csf/mali_kbase_csf_ioctl.h | 433 ++
- .../gpu/backend/mali_kbase_gpu_regmap_csf.h | 335 ++
- .../gpu/backend/mali_kbase_gpu_regmap_jm.h | 47 +-
- .../midgard/gpu/mali_kbase_gpu_coherency.h | 13 +-
- .../gpu/arm/midgard/gpu/mali_kbase_gpu_id.h | 64 +-
- .../arm/midgard/gpu/mali_kbase_gpu_regmap.h | 434 ++
- .../gpu/arm/midgard/jm/mali_base_jm_kernel.h | 285 +-
- .../gpu/arm/midgard/jm/mali_kbase_jm_ioctl.h | 107 +-
- .../uapi}/gpu/arm/midgard/mali_base_kernel.h | 461 +-
- .../gpu/arm/midgard/mali_base_mem_priv.h | 23 +-
- .../gpu/arm/midgard/mali_kbase_hwcnt_reader.h | 76 +-
- .../uapi}/gpu/arm/midgard/mali_kbase_ioctl.h | 212 +-
- .../arm/midgard/mali_kbase_kinstr_jm_reader.h | 69 +
- .../uapi}/gpu/arm/midgard/mali_uk.h | 46 +-
- 407 files changed, 58537 insertions(+), 10409 deletions(-)
- create mode 100644 dvalin/kernel/Documentation/ABI/testing/sysfs-device-mali
- create mode 100644 dvalin/kernel/Documentation/devicetree/bindings/arm/priority_control_manager.txt
- create mode 100644 dvalin/kernel/drivers/base/arm/Kbuild
- create mode 100644 dvalin/kernel/drivers/base/arm/Kconfig
- create mode 100644 dvalin/kernel/drivers/base/arm/Makefile
- create mode 100644 dvalin/kernel/drivers/base/arm/Mconfig
- rename dvalin/kernel/drivers/base/{ => arm}/dma_buf_lock/src/Kbuild (78%)
- rename dvalin/kernel/drivers/base/{ => arm}/dma_buf_lock/src/Makefile (71%)
- rename dvalin/kernel/drivers/base/{ => arm}/dma_buf_lock/src/dma_buf_lock.c (90%)
- rename dvalin/kernel/drivers/base/{ => arm}/dma_buf_lock/src/dma_buf_lock.h (88%)
- create mode 100644 dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/Kbuild
- create mode 100644 dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/build.bp
- rename dvalin/kernel/drivers/base/{ => arm}/dma_buf_test_exporter/dma-buf-test-exporter.c (89%)
- rename dvalin/kernel/drivers/base/{dma_buf_test_exporter => arm/memory_group_manager}/Kbuild (74%)
- create mode 100644 dvalin/kernel/drivers/base/arm/memory_group_manager/build.bp
- rename dvalin/kernel/drivers/base/{ => arm}/memory_group_manager/memory_group_manager.c (98%)
- create mode 100644 dvalin/kernel/drivers/base/arm/protected_memory_allocator/Kbuild
- create mode 100644 dvalin/kernel/drivers/base/arm/protected_memory_allocator/build.bp
- create mode 100644 dvalin/kernel/drivers/base/arm/protected_memory_allocator/protected_memory_allocator.c
- delete mode 100644 dvalin/kernel/drivers/base/dma_buf_test_exporter/Kconfig
- delete mode 100644 dvalin/kernel/drivers/base/dma_buf_test_exporter/Makefile
- delete mode 100644 dvalin/kernel/drivers/base/dma_buf_test_exporter/build.bp
- delete mode 100644 dvalin/kernel/drivers/base/memory_group_manager/Makefile
- delete mode 100644 dvalin/kernel/drivers/base/memory_group_manager/build.bp
- delete mode 100644 dvalin/kernel/drivers/base/protected_memory_allocator/Makefile
- delete mode 100644 dvalin/kernel/drivers/base/protected_memory_allocator/build.bp
- delete mode 100644 dvalin/kernel/drivers/base/protected_memory_allocator/protected_memory_allocator.c
- rename dvalin/kernel/drivers/{base/protected_memory_allocator/Kbuild => gpu/arm/Makefile} (77%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_clk_rate_trace_mgr.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_clk_rate_trace_mgr.h
- delete mode 100755 dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_device_hw.c
- delete mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_device_internal.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_mcu_states.h
- rename dvalin/kernel/drivers/{base/memory_group_manager/Kconfig => gpu/arm/midgard/context/Kbuild} (63%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/context/backend/mali_kbase_context_csf.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/Kbuild
- rename dvalin/kernel/drivers/gpu/arm/midgard/{Makefile.kbase => csf/ipa_control/Kbuild} (75%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/mali_kbase_csf_ipa_control.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/mali_kbase_csf_ipa_control.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_cpu_queue_debugfs.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_cpu_queue_debugfs.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_csg_debugfs.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_csg_debugfs.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_defs.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_cfg.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_cfg.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_no_mali.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_heap_context_alloc.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_heap_context_alloc.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu_debugfs.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu_debugfs.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_protected_memory.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_protected_memory.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_reset_gpu.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_scheduler.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_scheduler.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_debugfs.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_debugfs.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_def.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_timeout.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_timeout.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tl_reader.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tl_reader.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_trace_buffer.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_trace_buffer.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/debug/Kbuild
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_codes_csf.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_csf.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_csf.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_defs_csf.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_linux_ktrace_csf.h
- rename dvalin/kernel/drivers/gpu/arm/midgard/{tests/kutf/Makefile => device/Kbuild} (56%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_csf.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_hw_csf.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_hw_jm.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device_hw.c
- rename dvalin/kernel/drivers/gpu/arm/midgard/{tests/kutf/Kconfig => gpu/Kbuild} (65%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_fault_csf.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_csf.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_csf.h
- rename dvalin/kernel/drivers/gpu/arm/midgard/ipa/{mali_kbase_ipa_vinstr_common.c => backend/mali_kbase_ipa_counter_common_jm.c} (95%)
- rename dvalin/kernel/drivers/gpu/arm/midgard/ipa/{mali_kbase_ipa_vinstr_common.h => backend/mali_kbase_ipa_counter_common_jm.h} (85%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_csf.c
- rename dvalin/kernel/drivers/gpu/arm/midgard/ipa/{mali_kbase_ipa_vinstr_g7x.c => backend/mali_kbase_ipa_counter_jm.c} (83%)
- mode change 100644 => 100755 dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_caps.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ccswe.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ccswe.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dvfs_debugfs.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dvfs_debugfs.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence_ops.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if_fw.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if_fw.h
- delete mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_gpu.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_jm.c
- rename dvalin/kernel/drivers/gpu/arm/midgard/{mali_kbase_hwcnt_backend_gpu.h => mali_kbase_hwcnt_backend_jm.h} (75%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_kinstr_jm.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_kinstr_jm.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_trace_gpu_mem.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_trace_gpu_mem.h
- rename dvalin/kernel/drivers/gpu/arm/midgard/{gpu/mali_kbase_gpu.h => mali_power_gpu_frequency_trace.c} (67%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mali_power_gpu_frequency_trace.h
- rename dvalin/kernel/drivers/{base/protected_memory_allocator/Kconfig => gpu/arm/midgard/mmu/Kbuild} (61%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mmu/backend/mali_kbase_mmu_csf.c
- delete mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_mode_lpae.c
- mode change 100644 => 100755 dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/Kbuild
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/Kbuild.rej
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_clk_rate_trace.c
- mode change 100644 => 100755 dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_devicetree.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.c
- mode change 100644 => 100755 dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h.rej
- mode change 100644 => 100755 dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_runtime_pm.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/tests/build.bp
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/Kbuild
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/build.bp
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/mali_kutf_clk_rate_trace_test.h
- delete mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kconfig
- delete mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Makefile
- rename dvalin/kernel/drivers/{base/memory_group_manager => gpu/arm/midgard/thirdparty}/Kbuild (82%)
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/tl/Kbuild
- create mode 100644 dvalin/kernel/drivers/gpu/arm/midgard/tl/backend/mali_kbase_timeline_csf.c
- create mode 100644 dvalin/kernel/include/linux/priority_control_manager.h
- create mode 100644 dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_base_csf_kernel.h
- create mode 100644 dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_gpu_csf_control_registers.h
- create mode 100644 dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_gpu_csf_registers.h
- create mode 100644 dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_kbase_csf_ioctl.h
- create mode 100644 dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_csf.h
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_jm.h (89%)
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/gpu/mali_kbase_gpu_coherency.h (75%)
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/gpu/mali_kbase_gpu_id.h (74%)
- create mode 100644 dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_regmap.h
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/jm/mali_base_jm_kernel.h (75%)
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/jm/mali_kbase_jm_ioctl.h (57%)
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/mali_base_kernel.h (72%)
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/mali_base_mem_priv.h (80%)
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/mali_kbase_hwcnt_reader.h (52%)
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/mali_kbase_ioctl.h (83%)
- create mode 100644 dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_kinstr_jm_reader.h
- rename dvalin/kernel/{drivers => include/uapi}/gpu/arm/midgard/mali_uk.h (69%)
-
-diff --git a/dvalin/kernel/Documentation/ABI/testing/sysfs-device-mali b/dvalin/kernel/Documentation/ABI/testing/sysfs-device-mali
-new file mode 100644
-index 0000000..99f8ae5
---- /dev/null
-+++ b/dvalin/kernel/Documentation/ABI/testing/sysfs-device-mali
-@@ -0,0 +1,293 @@
-+/*
-+ *
-+ * (C) COPYRIGHT 2020 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.
-+ *
-+ */
-+
-+What: /sys/class/misc/mali%u/device/core_mask
-+Description:
-+ This attribute is used to restrict the number of shader cores
-+ available in this instance, is useful for debugging purposes.
-+ Reading this attribute provides us mask of all cores available.
-+ Writing to it will set the current core mask. Doesn't
-+ allow disabling all the cores present in this instance.
-+
-+What: /sys/class/misc/mali%u/device/debug_command
-+Description:
-+ This attribute is used to issue debug commands that supported
-+ by the driver. On reading it provides the list of debug commands
-+ that are supported, and writing back one of those commands will
-+ enable that debug option.
-+
-+What: /sys/class/misc/mali%u/device/dvfs_period
-+Description:
-+ This is used to set the DVFS sampling period to be used by the
-+ driver, On reading it provides the current DVFS sampling period,
-+ on writing a value we set the DVFS sampling period.
-+
-+What: /sys/class/misc/mali%u/device/dummy_job_wa_info
-+Description:
-+ This attribute is available only with platform device that
-+ supports a Job Manager based GPU that requires a GPU workaround
-+ to execute the dummy fragment job on all shader cores to
-+ workaround a hang issue.
-+
-+ Its a readonly attribute and on reading gives details on the
-+ options used with the dummy workaround.
-+
-+What: /sys/class/misc/mali%u/device/fw_timeout
-+Description:
-+ This attribute is available only with mali platform
-+ device-driver that supports a CSF GPU. This attribute is
-+ used to set the duration value in milliseconds for the
-+ waiting timeout used for a GPU status change request being
-+ acknowledged by the FW.
-+
-+What: /sys/class/misc/mali%u/device/gpuinfo
-+Description:
-+ This attribute provides description of the present Mali GPU.
-+ Its a read only attribute provides details like GPU family, the
-+ number of cores, the hardware version and the raw product id.
-+
-+What: /sys/class/misc/mali%u/device/idle_hysteresis_time
-+Description:
-+ This attribute is available only with mali platform
-+ device-driver that supports a CSF GPU. This attribute is
-+ used to set the duration value in milliseconds for the
-+ configuring hysteresis field for determining GPU idle detection.
-+
-+What: /sys/class/misc/mali%u/device/js_ctx_scheduling_mode
-+Description:
-+ This attribute is available only with platform device that
-+ supports a Job Manager based GPU. This attribute is used to set
-+ context scheduling priority for a job slot.
-+
-+ On Reading it provides the currently set job slot context
-+ priority.
-+
-+ Writing 0 to this attribute sets it to the mode were
-+ higher priority atoms will be scheduled first, regardless of
-+ the context they belong to. Newly-runnable higher priority atoms
-+ can preempt lower priority atoms currently running on the GPU,
-+ even if they belong to a different context.
-+
-+ Writing 1 to this attribute set it to the mode were the
-+ highest-priority atom will be chosen from each context in turn
-+ using a round-robin algorithm, so priority only has an effect
-+ within the context an atom belongs to. Newly-runnable higher
-+ priority atoms can preempt the lower priority atoms currently
-+ running on the GPU, but only if they belong to the same context.
-+
-+What: /sys/class/misc/mali%u/device/js_scheduling_period
-+Description:
-+ This attribute is available only with platform device that
-+ supports a Job Manager based GPU. Used to set the job scheduler
-+ tick period in nano-seconds. The Job Scheduler determines the
-+ jobs that are run on the GPU, and for how long, Job Scheduler
-+ makes decisions at a regular time interval determined by value
-+ in js_scheduling_period.
-+
-+What: /sys/class/misc/mali%u/device/js_softstop_always
-+Description:
-+ This attribute is available only with platform device that
-+ supports a Job Manager based GPU. Soft-stops are disabled when
-+ only a single context is present, this attribute is used to
-+ enable soft-stop when only a single context is present can be
-+ used for debug and unit-testing purposes.
-+
-+What: /sys/class/misc/mali%u/device/js_timeouts
-+Description:
-+ This attribute is available only with platform device that
-+ supports a Job Manager based GPU. It used to set the soft stop
-+ and hard stop times for the job scheduler.
-+
-+ Writing value 0 causes no change, or -1 to restore the
-+ default timeout.
-+
-+ The format used to set js_timeouts is
-+ "<soft_stop_ms> <soft_stop_ms_cl> <hard_stop_ms_ss>
-+ <hard_stop_ms_cl> <hard_stop_ms_dumping> <reset_ms_ss>
-+ <reset_ms_cl> <reset_ms_dumping>"
-+
-+
-+What: /sys/class/misc/mali%u/device/lp_mem_pool_max_size
-+Description:
-+ This attribute is used to set the maximum number of large pages
-+ memory pools that the driver can contain. Large pages are of
-+ size 2MB. On read it displays all the max size of all memory
-+ pools and can be used to modify each individual pools as well.
-+
-+What: /sys/class/misc/mali%u/device/lp_mem_pool_size
-+Description:
-+ This attribute is used to set the number of large memory pages
-+ which should be populated, changing this value may cause
-+ existing pages to be removed from the pool, or new pages to be
-+ created and then added to the pool. On read it will provide
-+ pool size for all available pools and we can modify individual
-+ pool.
-+
-+What: /sys/class/misc/mali%u/device/mem_pool_max_size
-+Description:
-+ This attribute is used to set the maximum number of small pages
-+ for memory pools that the driver can contain. Here small pages
-+ are of size 4KB. On read it will display the max size for all
-+ available pools and allows us to set max size of
-+ individual pools.
-+
-+What: /sys/class/misc/mali%u/device/mem_pool_size
-+Description:
-+ This attribute is used to set the number of small memory pages
-+ which should be populated, changing this value may cause
-+ existing pages to be removed from the pool, or new pages to
-+ be created and then added to the pool. On read it will provide
-+ pool size for all available pools and we can modify individual
-+ pool.
-+
-+What: /sys/class/misc/mali%u/device/device/mempool/ctx_default_max_size
-+Description:
-+ This attribute is used to set maximum memory pool size for
-+ all the memory pool so that the maximum amount of free memory
-+ that each pool can hold is identical.
-+
-+What: /sys/class/misc/mali%u/device/device/mempool/lp_max_size
-+Description:
-+ This attribute is used to set the maximum number of large pages
-+ for all memory pools that the driver can contain.
-+ Large pages are of size 2MB.
-+
-+What: /sys/class/misc/mali%u/device/device/mempool/max_size
-+Description:
-+ This attribute is used to set the maximum number of small pages
-+ for all the memory pools that the driver can contain.
-+ Here small pages are of size 4KB.
-+
-+What: /sys/class/misc/mali%u/device/pm_poweroff
-+Description:
-+ This attribute contains the current values, represented as the
-+ following space-separated integers:
-+ • PM_GPU_POWEROFF_TICK_NS.
-+ • PM_POWEROFF_TICK_SHADER.
-+ • PM_POWEROFF_TICK_GPU.
-+
-+ Example:
-+ echo 100000 4 4 > /sys/class/misc/mali0/device/pm_poweroff
-+
-+ Sets the following new values: 100,000ns tick, four ticks
-+ for shader power down, and four ticks for GPU power down.
-+
-+What: /sys/class/misc/mali%u/device/power_policy
-+Description:
-+ This attribute is used to find the current power policy been
-+ used, reading will list the power policies available and
-+ enclosed in square bracket is the current one been selected.
-+
-+ Example:
-+ cat /sys/class/misc/mali0/device/power_policy
-+ [demand] coarse_demand always_on
-+
-+ To switch to a different policy at runtime write the valid entry
-+ name back to the attribute.
-+
-+ Example:
-+ echo "coarse_demand" > /sys/class/misc/mali0/device/power_policy
-+
-+What: /sys/class/misc/mali%u/device/progress_timeout
-+Description:
-+ This attribute is available only with mali platform
-+ device-driver that supports a CSF GPU. This attribute
-+ is used to set the progress timeout value and read the current
-+ progress timeout value.
-+
-+ Progress timeout value is the maximum number of GPU cycles
-+ without forward progress to allow to elapse before terminating a
-+ GPU command queue group.
-+
-+What: /sys/class/misc/mali%u/device/reset_timeout
-+Description:
-+ This attribute is used to set the number of milliseconds to
-+ wait for the soft stop to complete for the GPU jobs before
-+ proceeding with the GPU reset.
-+
-+What: /sys/class/misc/mali%u/device/soft_job_timeout
-+Description:
-+ This attribute is available only with platform device that
-+ supports a Job Manager based GPU. It used to set the timeout
-+ value for waiting for any soft event to complete.
-+
-+What: /sys/class/misc/mali%u/device/scheduling/serialize_jobs
-+Description:
-+ This attribute is available only with platform device that
-+ supports a Job Manager based GPU.
-+
-+ Various options available under this are:
-+ • none - for disabling serialization.
-+ • intra-slot - Serialize atoms within a slot, only one
-+ atom per job slot.
-+ • inter-slot - Serialize atoms between slots, only one
-+ job slot running at any time.
-+ • full - it a combination of both inter and intra slot,
-+ so only one atom and one job slot running
-+ at any time.
-+ • full-reset - full serialization and Reset the GPU after
-+ each atom completion
-+
-+ These options are useful for debugging and investigating
-+ failures and gpu hangs to narrow down atoms that could cause
-+ troubles.
-+
-+What: /sys/class/misc/mali%u/device/firmware_config/Compute iterator count/*
-+Description:
-+ This attribute is available only with mali platform
-+ device-driver that supports a CSF GPU. Its a read-only attribute
-+ which indicates the maximum number of Compute iterators
-+ supported by the GPU.
-+
-+What: /sys/class/misc/mali%u/device/firmware_config/CSHWIF count/*
-+Description:
-+ This attribute is available only with mali platform
-+ device-driver that supports a CSF GPU. Its a read-only
-+ attribute which indicates the maximum number of CSHWIFs
-+ supported by the GPU.
-+
-+What: /sys/class/misc/mali%u/device/firmware_config/Fragment iterator count/*
-+Description:
-+ This attribute is available only with mali platform
-+ device-driver that supports a CSF GPU. Its a read-only
-+ attribute which indicates the maximum number of
-+ Fragment iterators supported by the GPU.
-+
-+What: /sys/class/misc/mali%u/device/firmware_config/Scoreboard set count/*
-+Description:
-+ This attribute is available only with mali platform
-+ device-driver that supports a CSF GPU. Its a read-only
-+ attribute which indicates the maximum number of
-+ Scoreboard set supported by the GPU.
-+
-+What: /sys/class/misc/mali%u/device/firmware_config/Tiler iterator count/*
-+Description:
-+ This attribute is available only with mali platform
-+ device-driver that supports a CSF GPU. Its a read-only
-+ attribute which indicates the maximum number of Tiler iterators
-+ supported by the GPU.
-+
-+What: /sys/class/misc/mali%u/device/firmware_config/Log verbosity/*
-+Description:
-+ This attribute is available only with mali platform
-+ device-driver that supports a CSF GPU.
-+
-+ Used to enable firmware logs, logging levels valid values
-+ are indicated using 'min and 'max' attribute values
-+ values that are read-only.
-+
-+ Log level can be set using the 'cur' read, write attribute,
-+ we can use a valid log level value from min and max range values
-+ and set a valid desired log level for firmware logs.
-diff --git a/dvalin/kernel/Documentation/devicetree/bindings/arm/mali-midgard.txt b/dvalin/kernel/Documentation/devicetree/bindings/arm/mali-midgard.txt
-index dd8f733..a74d569 100644
---- a/dvalin/kernel/Documentation/devicetree/bindings/arm/mali-midgard.txt
-+++ b/dvalin/kernel/Documentation/devicetree/bindings/arm/mali-midgard.txt
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2013-2020 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2013-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,8 +16,6 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- * ARM Mali Midgard / Bifrost devices
-@@ -46,12 +45,12 @@ Documentation/devicetree/bindings/regulator/regulator.txt for details.
- This is optional.
- - operating-points-v2 : Refer to Documentation/devicetree/bindings/power/mali-opp.txt
- for details.
--- quirks_jm : Used to write to the JM_CONFIG register or equivalent.
-+- quirks_gpu : Used to write to the JM_CONFIG or CSF_CONFIG register.
- Should be used with care. Options passed here are used to override
- certain default behavior. Note: This will override 'idvs-group-size'
- field in devicetree and module param 'corestack_driver_control',
-- therefore if 'quirks_jm' is used then 'idvs-group-size' and
-- 'corestack_driver_control' value should be incorporated into 'quirks_jm'.
-+ therefore if 'quirks_gpu' is used then 'idvs-group-size' and
-+ 'corestack_driver_control' value should be incorporated into 'quirks_gpu'.
- - quirks_sc : Used to write to the SHADER_CONFIG register.
- Should be used with care. Options passed here are used to override
- certain default behavior.
-@@ -64,8 +63,8 @@ for details.
- - power_model : Sets the power model parameters. Defined power models include:
- "mali-simple-power-model", "mali-g51-power-model", "mali-g52-power-model",
- "mali-g52_r1-power-model", "mali-g71-power-model", "mali-g72-power-model",
-- "mali-g76-power-model", "mali-g77-power-model", "mali-tnax-power-model"
-- and "mali-tbex-power-model".
-+ "mali-g76-power-model", "mali-g77-power-model", "mali-tnax-power-model",
-+ "mali-tbex-power-model" and "mali-tbax-power-model".
- - mali-simple-power-model: this model derives the GPU power usage based
- on the GPU voltage scaled by the system temperature. Note: it was
- designed for the Juno platform, and may not be suitable for others.
-@@ -98,6 +97,8 @@ for details.
- are used at different points so care should be taken to configure
- both power models in the device tree (specifically dynamic-coefficient,
- static-coefficient and scale) to best match the platform.
-+- power_policy : Sets the GPU power policy at probe time. Available options are
-+ "coarse_demand" and "always_on". If not set, then "coarse_demand" is used.
- - system-coherency : Sets the coherency protocol to be used for coherent
- accesses made from the GPU.
- If not set then no coherency is used.
-diff --git a/dvalin/kernel/Documentation/devicetree/bindings/arm/memory_group_manager.txt b/dvalin/kernel/Documentation/devicetree/bindings/arm/memory_group_manager.txt
-index fda8f00..634973f 100644
---- a/dvalin/kernel/Documentation/devicetree/bindings/arm/memory_group_manager.txt
-+++ b/dvalin/kernel/Documentation/devicetree/bindings/arm/memory_group_manager.txt
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2019-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,8 +16,6 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- * Arm memory group manager for Mali GPU device drivers
-diff --git a/dvalin/kernel/Documentation/devicetree/bindings/arm/priority_control_manager.txt b/dvalin/kernel/Documentation/devicetree/bindings/arm/priority_control_manager.txt
-new file mode 100644
-index 0000000..c7dd14f
---- /dev/null
-+++ b/dvalin/kernel/Documentation/devicetree/bindings/arm/priority_control_manager.txt
-@@ -0,0 +1,48 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2020-2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+* Arm priority control manager for Mali GPU device drivers
-+
-+Required properties:
-+
-+- compatible: Must be "arm,priority-control-manager"
-+
-+An example node:
-+
-+ gpu_priority_control_manager: priority-control-manager {
-+ compatible = "arm,priority-control-manager";
-+ };
-+
-+It must be referenced by the GPU as well, see priority-control-manager:
-+
-+ gpu: gpu@0x6e000000 {
-+ compatible = "arm,mali-midgard";
-+ reg = <0x0 0x6e000000 0x0 0x200000>;
-+ interrupts = <0 168 4>, <0 168 4>, <0 168 4>;
-+ interrupt-names = "JOB", "MMU", "GPU";
-+ clocks = <&scpi_dvfs 2>;
-+ clock-names = "clk_mali";
-+ system-coherency = <31>;
-+ priority-control-manager = <&gpu_priority_control_manager>;
-+ operating-points = <
-+ /* KHz uV */
-+ 50000 820000
-+ >;
-+ };
-diff --git a/dvalin/kernel/Documentation/devicetree/bindings/arm/protected_memory_allocator.txt b/dvalin/kernel/Documentation/devicetree/bindings/arm/protected_memory_allocator.txt
-index f054348..89a3cc7 100644
---- a/dvalin/kernel/Documentation/devicetree/bindings/arm/protected_memory_allocator.txt
-+++ b/dvalin/kernel/Documentation/devicetree/bindings/arm/protected_memory_allocator.txt
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2019-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,8 +16,6 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- * Arm protected memory allocator for Mali GPU device drivers
-diff --git a/dvalin/kernel/Documentation/devicetree/bindings/power/mali-opp.txt b/dvalin/kernel/Documentation/devicetree/bindings/power/mali-opp.txt
-index 49ed773..b9c0743 100644
---- a/dvalin/kernel/Documentation/devicetree/bindings/power/mali-opp.txt
-+++ b/dvalin/kernel/Documentation/devicetree/bindings/power/mali-opp.txt
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2017, 2019 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2017, 2019-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,8 +16,6 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- * ARM Mali Midgard OPP
-@@ -54,7 +53,7 @@ Optional properties:
-
- - opp-core-count: Number of cores to use for this OPP. If this is present then
- the driver will build a core mask using the available core mask provided by
-- the GPU hardware.
-+ the GPU hardware. An opp-core-count value of 0 is not permitted.
-
- If neither this nor opp-core-mask are present then all shader cores will be
- used for this OPP.
-diff --git a/dvalin/kernel/Documentation/dma-buf-test-exporter.txt b/dvalin/kernel/Documentation/dma-buf-test-exporter.txt
-index 8d8cbc9..b01020c 100644
---- a/dvalin/kernel/Documentation/dma-buf-test-exporter.txt
-+++ b/dvalin/kernel/Documentation/dma-buf-test-exporter.txt
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2013, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,10 +16,7 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
--#
--
-
- =====================
- dma-buf-test-exporter
-@@ -42,5 +40,3 @@ It supports being compiled as a module both in-tree and out-of-tree.
-
- See include/linux/dma-buf-test-exporter.h for the ioctl interface.
- See Documentation/dma-buf-sharing.txt for details on dma_buf.
--
--
-diff --git a/dvalin/kernel/Mconfig b/dvalin/kernel/Mconfig
-index e451591..217715c 100644
---- a/dvalin/kernel/Mconfig
-+++ b/dvalin/kernel/Mconfig
-@@ -1,27 +1,26 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--#
--# (C) COPYRIGHT 2017-2020 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2017-2021 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.
-+# of such GNU license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
- #
--# 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.
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
- #
- #
-
--source "kernel/drivers/gpu/arm/midgard/Mconfig"
--source "kernel/drivers/gpu/arm/midgard/arbitration/Mconfig"
-+menu "Kernel menu"
-
--config DMA_BUF_SYNC_IOCTL_SUPPORTED
-- bool "Kernel DMA buffers support DMA_BUF_IOCTL_SYNC"
-- depends on BACKEND_KERNEL
-- default y
-+source "kernel/drivers/base/arm/Mconfig"
-+source "kernel/drivers/gpu/arm/midgard/Mconfig"
-
--config BUILD_CSF_ONLY_MODULE
-- bool "Build CSF GPU specific kernel modules"
-- depends on BUILD_KERNEL_MODULES && GPU_HAS_CSF
-- default y
-+endmenu
-diff --git a/dvalin/kernel/build.bp b/dvalin/kernel/build.bp
-index 2bc725f..c97da2c 100644
---- a/dvalin/kernel/build.bp
-+++ b/dvalin/kernel/build.bp
-@@ -1,15 +1,21 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2016-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2016-2021 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.
-+ * of such GNU license.
- *
-- * 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 program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
- *
- */
-
-@@ -25,6 +31,7 @@ bob_install_group {
-
- bob_defaults {
- name: "kernel_defaults",
-+ build_by_default: false,
- enabled: false,
- exclude_srcs: [
- "**/*.mod.c",
-@@ -33,6 +40,7 @@ bob_defaults {
- "include",
- ],
- build_kernel_modules: {
-+ build_by_default: true,
- enabled: true,
- kernel_dir: "{{.kernel_dir}}",
- kernel_cross_compile: "{{.kernel_compiler}}",
-@@ -42,6 +50,8 @@ bob_defaults {
- kernel_ld: "{{.kernel_ld}}",
- },
- install_group: "IG_kernel_modules",
-+ add_to_alias: ["kernel"],
-+ owner: "{{.android_module_owner}}",
- cflags: [
- "-Wall",
- ],
-@@ -54,49 +64,12 @@ bob_defaults {
- "optional",
- ],
- },
-- kbuild_options: [
-- // Start of CS experimental features definitions.
-- // If there is nothing below, definition should be added as follows:
-- // "MALI_EXPERIMENTAL_FEATURE={{.experimental_feature}}"
-- // experimental_feature above comes from Mconfig in
-- // <ddk_root>/product/base/
-- // However, in Mconfig, experimental_feature should be looked up (for
-- // similar explanation to this one) as ALLCAPS, i.e.
-- // EXPERIMENTAL_FEATURE.
-- //
-- // IMPORTANT: MALI_CS_EXPERIMENTAL should NEVER be defined below as it
-- // is an umbrella feature that would be open for inappropriate use
-- // (catch-all for experimental CS code without separating it into
-- // different features).
-- "MALI_JIT_PRESSURE_LIMIT={{.jit_pressure_limit}}",
-- "MALI_INCREMENTAL_RENDERING={{.incremental_rendering}}",
-- ],
--}
--
--bob_defaults {
-- name: "kutf_includes",
-- local_include_dirs: [
-- "drivers/gpu/arm/midgard/tests/include",
-- ],
--}
--
--bob_defaults {
-- name: "kernel_test_includes",
-- defaults: ["kutf_includes"],
-- local_include_dirs: [
-- "drivers/gpu/arm",
-- "drivers/gpu/arm/midgard",
-- "drivers/gpu/arm/midgard/backend/gpu",
-- "drivers/gpu/arm/midgard/debug",
-- "drivers/gpu/arm/midgard/debug/backend",
-- ],
- }
-
-+// Alias for all kernel modules. `kernel_defaults` uses `add_to_alias` to
-+// ensure any modules using that are included in this alias; any
-+// bob_kernel_modules not using those defaults must explicitly use
-+// `add_to_alias` or be listed here.
- bob_alias {
- name: "kernel",
-- srcs: [
-- "dma-buf-test-exporter",
-- "memory_group_manager",
-- "mali_kbase",
-- ],
- }
-diff --git a/dvalin/kernel/drivers/base/arm/Kbuild b/dvalin/kernel/drivers/base/arm/Kbuild
-new file mode 100644
-index 0000000..b0fbf93
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/Kbuild
-@@ -0,0 +1,34 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+#
-+# ccflags
-+#
-+ccflags-y += -I$(src)/../../../include
-+
-+subdir-ccflags-y += $(ccflags-y)
-+
-+#
-+# Kernel modules
-+#
-+obj-$(CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER) += dma_buf_test_exporter/
-+obj-$(CONFIG_MALI_MEMORY_GROUP_MANAGER) += memory_group_manager/
-+obj-$(CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR) += protected_memory_allocator/
-+
-diff --git a/dvalin/kernel/drivers/base/arm/Kconfig b/dvalin/kernel/drivers/base/arm/Kconfig
-new file mode 100644
-index 0000000..75d5434
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/Kconfig
-@@ -0,0 +1,64 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+menuconfig MALI_BASE_MODULES
-+ bool "Mali Base extra modules"
-+ default n
-+ help
-+ Enable this option to build support for a Arm Mali base modules.
-+ Those modules provide extra features or debug interfaces and,
-+ are optional for the use of the Mali GPU modules.
-+
-+config DMA_SHARED_BUFFER_TEST_EXPORTER
-+ bool "Build dma-buf framework test exporter module"
-+ depends on MALI_BASE_MODULES && DMA_SHARED_BUFFER
-+ default y
-+ help
-+ This option will build the dma-buf framework test exporter module.
-+ Usable to help test importers.
-+
-+ Modules:
-+ - dma-buf-test-exporter.ko
-+
-+config MALI_MEMORY_GROUP_MANAGER
-+ bool "Build Mali Memory Group Manager module"
-+ depends on MALI_BASE_MODULES
-+ default y
-+ help
-+ This option will build the memory group manager module.
-+ This is an example implementation for allocation and release of pages
-+ for memory pools managed by Mali GPU device drivers.
-+
-+ Modules:
-+ - memory_group_manager.ko
-+
-+config MALI_PROTECTED_MEMORY_ALLOCATOR
-+ bool "Build Mali Protected Memory Allocator module"
-+ depends on MALI_BASE_MODULES && MALI_CSF_SUPPORT
-+ default y
-+ help
-+ This option will build the protected memory allocator module.
-+ This is an example implementation for allocation and release of pages
-+ of secure memory intended to be used by the firmware
-+ of Mali GPU device drivers.
-+
-+ Modules:
-+ - protected_memory_allocator.ko
-+
-diff --git a/dvalin/kernel/drivers/base/arm/Makefile b/dvalin/kernel/drivers/base/arm/Makefile
-new file mode 100644
-index 0000000..0bd6ab5
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/Makefile
-@@ -0,0 +1,98 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+#
-+# Paths
-+#
-+KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
-+KDIR ?= $(KERNEL_SRC)
-+
-+ifeq ($(KDIR),)
-+ $(error Must specify KDIR to point to the kernel to target))
-+endif
-+
-+vars :=
-+#
-+# Default configuration values
-+#
-+CONFIG_MALI_BASE_MODULES ?= n
-+
-+ifeq ($(CONFIG_MALI_BASE_MODULES),y)
-+ CONFIG_MALI_CSF_SUPPORT ?= n
-+
-+ ifneq ($(CONFIG_DMA_SHARED_BUFFER),n)
-+ CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER ?= y
-+ else
-+ # Prevent misuse when CONFIG_DMA_SHARED_BUFFER=n
-+ CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER = n
-+ endif
-+
-+ CONFIG_MALI_MEMORY_GROUP_MANAGER ?= y
-+
-+ ifneq ($(CONFIG_MALI_CSF_SUPPORT), n)
-+ CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR ?= y
-+ endif
-+
-+else
-+ # Prevent misuse when CONFIG_MALI_BASE_MODULES=n
-+ CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER = n
-+ CONFIG_MALI_MEMORY_GROUP_MANAGER = n
-+ CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR = n
-+
-+endif
-+
-+CONFIGS := \
-+ CONFIG_MALI_BASE_MODULES \
-+ CONFIG_MALI_CSF_SUPPORT \
-+ CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER \
-+ CONFIG_MALI_MEMORY_GROUP_MANAGER \
-+ CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR
-+
-+
-+#
-+# MAKE_ARGS to pass the custom CONFIGs on out-of-tree build
-+#
-+# Generate the list of CONFIGs and values.
-+# $(value config) is the name of the CONFIG option.
-+# $(value $(value config)) is its value (y, m).
-+# When the CONFIG is not set to y or m, it defaults to n.
-+MAKE_ARGS := $(foreach config,$(CONFIGS), \
-+ $(if $(filter y m,$(value $(value config))), \
-+ $(value config)=$(value $(value config)), \
-+ $(value config)=n))
-+
-+#
-+# EXTRA_CFLAGS to define the custom CONFIGs on out-of-tree build
-+#
-+# Generate the list of CONFIGs defines with values from CONFIGS.
-+# $(value config) is the name of the CONFIG option.
-+# When set to y or m, the CONFIG gets defined to 1.
-+EXTRA_CFLAGS := $(foreach config,$(CONFIGS), \
-+ $(if $(filter y m,$(value $(value config))), \
-+ -D$(value config)=1))
-+
-+all:
-+ $(MAKE) -C $(KDIR) M=$(CURDIR) $(MAKE_ARGS) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules
-+
-+modules_install:
-+ $(MAKE) -C $(KDIR) M=$(CURDIR) $(MAKE_ARGS) modules_install
-+
-+clean:
-+ $(MAKE) -C $(KDIR) M=$(CURDIR) $(MAKE_ARGS) clean
-diff --git a/dvalin/kernel/drivers/base/arm/Mconfig b/dvalin/kernel/drivers/base/arm/Mconfig
-new file mode 100644
-index 0000000..d21a72e
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/Mconfig
-@@ -0,0 +1,64 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+menuconfig MALI_BASE_MODULES
-+ bool "Mali Base extra modules"
-+ default y if BACKEND_KERNEL
-+ help
-+ Enable this option to build support for a Arm Mali base modules.
-+ Those modules provide extra features or debug interfaces and,
-+ are optional for the use of the Mali GPU modules.
-+
-+config DMA_SHARED_BUFFER_TEST_EXPORTER
-+ bool "Build dma-buf framework test exporter module"
-+ depends on MALI_BASE_MODULES
-+ default y
-+ help
-+ This option will build the dma-buf framework test exporter module.
-+ Usable to help test importers.
-+
-+ Modules:
-+ - dma-buf-test-exporter.ko
-+
-+config MALI_MEMORY_GROUP_MANAGER
-+ bool "Build Mali Memory Group Manager module"
-+ depends on MALI_BASE_MODULES
-+ default y
-+ help
-+ This option will build the memory group manager module.
-+ This is an example implementation for allocation and release of pages
-+ for memory pools managed by Mali GPU device drivers.
-+
-+ Modules:
-+ - memory_group_manager.ko
-+
-+config MALI_PROTECTED_MEMORY_ALLOCATOR
-+ bool "Build Mali Protected Memory Allocator module"
-+ depends on MALI_BASE_MODULES && GPU_HAS_CSF
-+ default y
-+ help
-+ This option will build the protected memory allocator module.
-+ This is an example implementation for allocation and release of pages
-+ of secure memory intended to be used by the firmware
-+ of Mali GPU device drivers.
-+
-+ Modules:
-+ - protected_memory_allocator.ko
-+
-diff --git a/dvalin/kernel/drivers/base/dma_buf_lock/src/Kbuild b/dvalin/kernel/drivers/base/arm/dma_buf_lock/src/Kbuild
-similarity index 78%
-rename from dvalin/kernel/drivers/base/dma_buf_lock/src/Kbuild
-rename to dvalin/kernel/drivers/base/arm/dma_buf_lock/src/Kbuild
-index ddf1bb5..c7ae332 100644
---- a/dvalin/kernel/drivers/base/dma_buf_lock/src/Kbuild
-+++ b/dvalin/kernel/drivers/base/arm/dma_buf_lock/src/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,10 +16,8 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
--ifneq ($(CONFIG_DMA_SHARED_BUFFER),)
-+ifeq ($(CONFIG_DMA_SHARED_BUFFER), y)
- obj-m := dma_buf_lock.o
- endif
-diff --git a/dvalin/kernel/drivers/base/dma_buf_lock/src/Makefile b/dvalin/kernel/drivers/base/arm/dma_buf_lock/src/Makefile
-similarity index 71%
-rename from dvalin/kernel/drivers/base/dma_buf_lock/src/Makefile
-rename to dvalin/kernel/drivers/base/arm/dma_buf_lock/src/Makefile
-index 3b10406..451d2d7 100644
---- a/dvalin/kernel/drivers/base/dma_buf_lock/src/Makefile
-+++ b/dvalin/kernel/drivers/base/arm/dma_buf_lock/src/Makefile
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,8 +16,6 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- # linux build system bootstrap for out-of-tree module
-@@ -24,15 +23,17 @@
- # default to building for the host
- ARCH ?= $(shell uname -m)
-
--ifeq ($(KDIR),)
--$(error Must specify KDIR to point to the kernel to target))
--endif
-+# Handle Android Common Kernel source naming
-+KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
-+KDIR ?= $(KERNEL_SRC)
-
- all: dma_buf_lock
-
- dma_buf_lock:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../../include"
-+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../../../include"
-
- clean:
- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean
-
-+modules_install:
-+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) modules_install
-diff --git a/dvalin/kernel/drivers/base/dma_buf_lock/src/dma_buf_lock.c b/dvalin/kernel/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.c
-similarity index 90%
-rename from dvalin/kernel/drivers/base/dma_buf_lock/src/dma_buf_lock.c
-rename to dvalin/kernel/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.c
-index 529ce71..f5ab1ed 100644
---- a/dvalin/kernel/drivers/base/dma_buf_lock/src/dma_buf_lock.c
-+++ b/dvalin/kernel/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2013, 2017-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2014, 2017-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/version.h>
-@@ -29,7 +28,11 @@
- #include <linux/device.h>
- #include <linux/slab.h>
- #include <linux/atomic.h>
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- #include <linux/reservation.h>
-+#else
-+#include <linux/dma-resv.h>
-+#endif
- #include <linux/dma-buf.h>
- #include <linux/wait.h>
- #include <linux/sched.h>
-@@ -37,7 +40,7 @@
- #include <linux/anon_inodes.h>
- #include <linux/file.h>
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-
- #include <linux/fence.h>
-
-@@ -60,7 +63,7 @@
-
- #include <linux/dma-fence.h>
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
-+#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE)
- #define dma_fence_get_status(a) (dma_fence_is_signaled(a) ? \
- (a)->status ?: 1 \
- : 0)
-@@ -101,7 +104,7 @@ static struct file_operations dma_buf_lock_fops =
-
- typedef struct dma_buf_lock_resource
- {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence fence;
- #else
- struct dma_fence fence;
-@@ -127,7 +130,7 @@ typedef struct dma_buf_lock_resource
- * @node: List head for linking this callback to the lock resource
- */
- struct dma_buf_lock_fence_cb {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence_cb fence_cb;
- struct fence *fence;
- #else
-@@ -151,7 +154,7 @@ static void dma_buf_lock_dounlock(struct kref *ref);
- static DEFINE_SPINLOCK(dma_buf_lock_fence_lock);
-
- static const char *
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- dma_buf_lock_fence_get_driver_name(struct fence *fence)
- #else
- dma_buf_lock_fence_get_driver_name(struct dma_fence *fence)
-@@ -161,7 +164,7 @@ dma_buf_lock_fence_get_driver_name(struct dma_fence *fence)
- }
-
- static const char *
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- dma_buf_lock_fence_get_timeline_name(struct fence *fence)
- #else
- dma_buf_lock_fence_get_timeline_name(struct dma_fence *fence)
-@@ -171,7 +174,7 @@ dma_buf_lock_fence_get_timeline_name(struct dma_fence *fence)
- }
-
- static bool
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- dma_buf_lock_fence_enable_signaling(struct fence *fence)
- #else
- dma_buf_lock_fence_enable_signaling(struct dma_fence *fence)
-@@ -180,7 +183,7 @@ dma_buf_lock_fence_enable_signaling(struct dma_fence *fence)
- return true;
- }
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- const struct fence_ops dma_buf_lock_fence_ops = {
- .wait = fence_default_wait,
- #else
-@@ -235,7 +238,7 @@ dma_buf_lock_fence_work(struct work_struct *pwork)
- }
-
- static void
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- dma_buf_lock_fence_callback(struct fence *fence, struct fence_cb *cb)
- #else
- dma_buf_lock_fence_callback(struct dma_fence *fence, struct dma_fence_cb *cb)
-@@ -256,14 +259,13 @@ dma_buf_lock_fence_callback(struct dma_fence *fence, struct dma_fence_cb *cb)
- atomic_set(&resource->locked, 1);
- wake_up(&resource->wait);
-
-- if (resource->exclusive) {
-+ if (resource->exclusive)
- /* Warn if the work was already queued */
- WARN_ON(!schedule_work(&resource->work));
-- }
- }
- }
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- static int
- dma_buf_lock_fence_add_callback(dma_buf_lock_resource *resource,
- struct fence *fence,
-@@ -317,12 +319,19 @@ dma_buf_lock_fence_add_callback(dma_buf_lock_resource *resource,
- return err;
- }
-
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- static int
- dma_buf_lock_add_fence_reservation_callback(dma_buf_lock_resource *resource,
- struct reservation_object *resv,
- bool exclusive)
-+#else
-+static int
-+dma_buf_lock_add_fence_reservation_callback(dma_buf_lock_resource *resource,
-+ struct dma_resv *resv,
-+ bool exclusive)
-+#endif
- {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *excl_fence = NULL;
- struct fence **shared_fences = NULL;
- #else
-@@ -332,7 +341,12 @@ dma_buf_lock_add_fence_reservation_callback(dma_buf_lock_resource *resource,
- unsigned int shared_count = 0;
- int err, i;
-
-- err = reservation_object_get_fences_rcu(resv,
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
-+ err = reservation_object_get_fences_rcu(
-+#else
-+ err = dma_resv_get_fences_rcu(
-+#endif
-+ resv,
- &excl_fence,
- &shared_count,
- &shared_fences);
-@@ -393,7 +407,11 @@ static int
- dma_buf_lock_acquire_fence_reservation(dma_buf_lock_resource *resource,
- struct ww_acquire_ctx *ctx)
- {
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- struct reservation_object *content_resv = NULL;
-+#else
-+ struct dma_resv *content_resv = NULL;
-+#endif
- unsigned int content_resv_idx = 0;
- unsigned int r;
- int err = 0;
-@@ -472,21 +490,16 @@ static unsigned int dma_buf_lock_handle_poll(struct file *file,
- #if DMA_BUF_LOCK_DEBUG
- printk("dma_buf_lock_handle_poll\n");
- #endif
-- if (1 == atomic_read(&resource->locked))
-- {
-+ if (atomic_read(&resource->locked) == 1) {
- /* Resources have been locked */
- ret = POLLIN | POLLRDNORM;
- if (resource->exclusive)
-- {
- ret |= POLLOUT | POLLWRNORM;
-- }
- }
- else
- {
-- if (!poll_does_not_wait(wait))
-- {
-+ if (!poll_does_not_wait(wait))
- poll_wait(file, &resource->wait, wait);
-- }
- }
- #if DMA_BUF_LOCK_DEBUG
- printk("dma_buf_lock_handle_poll : return %i\n", ret);
-@@ -525,29 +538,19 @@ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request)
- int i;
- int ret;
-
-- if (NULL == request->list_of_dma_buf_fds)
-- {
-+ if (request->list_of_dma_buf_fds == NULL)
- return -EINVAL;
-- }
- if (request->count <= 0)
-- {
- return -EINVAL;
-- }
- if (request->count > DMA_BUF_LOCK_BUF_MAX)
-- {
- return -EINVAL;
-- }
- if (request->exclusive != DMA_BUF_LOCK_NONEXCLUSIVE &&
- request->exclusive != DMA_BUF_LOCK_EXCLUSIVE)
-- {
- return -EINVAL;
-- }
-
- resource = kzalloc(sizeof(dma_buf_lock_resource), GFP_KERNEL);
-- if (NULL == resource)
-- {
-+ if (resource == NULL)
- return -ENOMEM;
-- }
-
- atomic_set(&resource->locked, 0);
- kref_init(&resource->refcount);
-@@ -559,8 +562,7 @@ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request)
- size = request->count * sizeof(int);
- resource->list_of_dma_buf_fds = kmalloc(size, GFP_KERNEL);
-
-- if (NULL == resource->list_of_dma_buf_fds)
-- {
-+ if (resource->list_of_dma_buf_fds == NULL) {
- kfree(resource);
- return -ENOMEM;
- }
-@@ -569,8 +571,7 @@ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request)
- size = sizeof(struct dma_buf *) * request->count;
- resource->dma_bufs = kmalloc(size, GFP_KERNEL);
-
-- if (NULL == resource->dma_bufs)
-- {
-+ if (resource->dma_bufs == NULL) {
- kfree(resource->list_of_dma_buf_fds);
- kfree(resource);
- return -ENOMEM;
-@@ -578,8 +579,9 @@ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request)
-
- /* Copy requested list of dma_buf_fds from user space */
- size = request->count * sizeof(int);
-- if (0 != copy_from_user(resource->list_of_dma_buf_fds, (void __user *)request->list_of_dma_buf_fds, size))
-- {
-+ if (copy_from_user(resource->list_of_dma_buf_fds,
-+ (void __user *)request->list_of_dma_buf_fds,
-+ size) != 0) {
- kfree(resource->list_of_dma_buf_fds);
- kfree(resource->dma_bufs);
- kfree(resource);
-@@ -587,9 +589,7 @@ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request)
- }
- #if DMA_BUF_LOCK_DEBUG
- for (i = 0; i < request->count; i++)
-- {
- printk("dma_buf %i = %X\n", i, resource->list_of_dma_buf_fds[i]);
-- }
- #endif
-
- /* Initialize the fence associated with dma_buf_lock resource */
-@@ -620,8 +620,7 @@ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request)
- }
-
- /*Check the reservation object associated with dma_buf */
-- if (NULL == resource->dma_bufs[i]->resv)
-- {
-+ if (resource->dma_bufs[i]->resv == NULL) {
- mutex_lock(&dma_buf_lock_mutex);
- kref_put(&resource->refcount, dma_buf_lock_dounlock);
- mutex_unlock(&dma_buf_lock_mutex);
-@@ -680,10 +679,18 @@ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request)
- kref_get(&resource->refcount);
-
- for (i = 0; i < request->count; i++) {
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- struct reservation_object *resv = resource->dma_bufs[i]->resv;
--
-+#else
-+ struct dma_resv *resv = resource->dma_bufs[i]->resv;
-+#endif
- if (!test_bit(i, &resource->exclusive)) {
-+
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- ret = reservation_object_reserve_shared(resv);
-+#else
-+ ret = dma_resv_reserve_shared(resv, 0);
-+#endif
- if (ret) {
- #if DMA_BUF_LOCK_DEBUG
- printk(KERN_DEBUG "dma_buf_lock_dolock : Error %d reserving space for shared fence.\n", ret);
-@@ -701,7 +708,11 @@ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request)
- break;
- }
-
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- reservation_object_add_shared_fence(resv, &resource->fence);
-+#else
-+ dma_resv_add_shared_fence(resv, &resource->fence);
-+#endif
- } else {
- ret = dma_buf_lock_add_fence_reservation_callback(resource,
- resv,
-@@ -713,7 +724,11 @@ static int dma_buf_lock_dolock(dma_buf_lock_k_request *request)
- break;
- }
-
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- reservation_object_add_excl_fence(resv, &resource->fence);
-+#else
-+ dma_resv_add_excl_fence(resv, &resource->fence);
-+#endif
- }
- }
-
-@@ -783,27 +798,21 @@ static int __init dma_buf_lock_init(void)
- #endif
- err = alloc_chrdev_region(&dma_buf_lock_dev, 0, 1, dma_buf_lock_dev_name);
-
-- if (0 == err)
-- {
-+ if (err == 0) {
- cdev_init(&dma_buf_lock_cdev, &dma_buf_lock_fops);
-
- err = cdev_add(&dma_buf_lock_cdev, dma_buf_lock_dev, 1);
-
-- if (0 == err)
-- {
-+ if (err == 0) {
- dma_buf_lock_class = class_create(THIS_MODULE, dma_buf_lock_dev_name);
- if (IS_ERR(dma_buf_lock_class))
-- {
- err = PTR_ERR(dma_buf_lock_class);
-- }
- else
- {
- struct device *mdev;
- mdev = device_create(dma_buf_lock_class, NULL, dma_buf_lock_dev, NULL, dma_buf_lock_dev_name);
- if (!IS_ERR(mdev))
-- {
- return 0;
-- }
-
- err = PTR_ERR(mdev);
- class_destroy(dma_buf_lock_class);
-@@ -836,7 +845,7 @@ static void __exit dma_buf_lock_exit(void)
- }
- else
- {
-- dma_buf_lock_resource *resource = list_entry(dma_buf_lock_resource_list.next,
-+ dma_buf_lock_resource *resource = list_entry(dma_buf_lock_resource_list.next,
- dma_buf_lock_resource, link);
- kref_put(&resource->refcount, dma_buf_lock_dounlock);
- mutex_unlock(&dma_buf_lock_mutex);
-@@ -862,26 +871,17 @@ static int dma_buf_lock_ioctl(struct inode *inode, struct file *filp, unsigned i
- int size = _IOC_SIZE(cmd);
-
- if (_IOC_TYPE(cmd) != DMA_BUF_LOCK_IOC_MAGIC)
-- {
- return -ENOTTY;
--
-- }
- if ((_IOC_NR(cmd) < DMA_BUF_LOCK_IOC_MINNR) || (_IOC_NR(cmd) > DMA_BUF_LOCK_IOC_MAXNR))
-- {
- return -ENOTTY;
-- }
-
- switch (cmd)
- {
- case DMA_BUF_LOCK_FUNC_LOCK_ASYNC:
- if (size != sizeof(dma_buf_lock_k_request))
-- {
- return -ENOTTY;
-- }
- if (copy_from_user(&request, (void __user *)arg, size))
-- {
- return -EFAULT;
-- }
- #if DMA_BUF_LOCK_DEBUG
- printk("DMA_BUF_LOCK_FUNC_LOCK_ASYNC - %i\n", request.count);
- #endif
-diff --git a/dvalin/kernel/drivers/base/dma_buf_lock/src/dma_buf_lock.h b/dvalin/kernel/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.h
-similarity index 88%
-rename from dvalin/kernel/drivers/base/dma_buf_lock/src/dma_buf_lock.h
-rename to dvalin/kernel/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.h
-index f2ae575..104af1f 100644
---- a/dvalin/kernel/drivers/base/dma_buf_lock/src/dma_buf_lock.h
-+++ b/dvalin/kernel/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _DMA_BUF_LOCK_H
-diff --git a/dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/Kbuild b/dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/Kbuild
-new file mode 100644
-index 0000000..0e20cb4
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/Kbuild
-@@ -0,0 +1,23 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2012, 2020-2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+ifeq ($(CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER), y)
-+obj-m += dma-buf-test-exporter.o
-+endif
-diff --git a/dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/build.bp b/dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/build.bp
-new file mode 100644
-index 0000000..a49fb81
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/build.bp
-@@ -0,0 +1,36 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2017, 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+bob_kernel_module {
-+ name: "dma-buf-test-exporter",
-+ defaults: [
-+ "kernel_defaults"
-+ ],
-+ srcs: [
-+ "Kbuild",
-+ "dma-buf-test-exporter.c",
-+ ],
-+ enabled: false,
-+ dma_shared_buffer_test_exporter: {
-+ kbuild_options: ["CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER=y"],
-+ enabled: true,
-+ },
-+}
-diff --git a/dvalin/kernel/drivers/base/dma_buf_test_exporter/dma-buf-test-exporter.c b/dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/dma-buf-test-exporter.c
-similarity index 89%
-rename from dvalin/kernel/drivers/base/dma_buf_test_exporter/dma-buf-test-exporter.c
-rename to dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/dma-buf-test-exporter.c
-index 3eb34c0..ccf73cc 100644
---- a/dvalin/kernel/drivers/base/dma_buf_test_exporter/dma-buf-test-exporter.c
-+++ b/dvalin/kernel/drivers/base/arm/dma_buf_test_exporter/dma-buf-test-exporter.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/dma-buf-test-exporter.h>
-@@ -31,18 +30,16 @@
- #include <linux/atomic.h>
- #include <linux/mm.h>
- #include <linux/highmem.h>
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
-+#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE)
- #include <linux/dma-attrs.h>
- #endif
- #include <linux/dma-mapping.h>
--#endif
-
- /* Maximum size allowed in a single DMA_BUF_TE_ALLOC call */
- #define DMA_BUF_TE_ALLOC_MAX_SIZE ((8ull << 30) >> PAGE_SHIFT) /* 8 GB */
-
- /* Since kernel version 5.0 CONFIG_ARCH_NO_SG_CHAIN replaced CONFIG_ARCH_HAS_SG_CHAIN */
--#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
-+#if KERNEL_VERSION(5, 0, 0) > LINUX_VERSION_CODE
- #if (!defined(ARCH_HAS_SG_CHAIN) && !defined(CONFIG_ARCH_HAS_SG_CHAIN))
- #define NO_SG_CHAIN
- #endif
-@@ -77,7 +74,7 @@ struct dma_buf_te_attachment {
-
- static struct miscdevice te_device;
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0))
-+#if (KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE)
- static int dma_buf_te_attach(struct dma_buf *buf, struct device *dev, struct dma_buf_attachment *attachment)
- #else
- static int dma_buf_te_attach(struct dma_buf *buf, struct dma_buf_attachment *attachment)
-@@ -206,30 +203,29 @@ static void dma_buf_te_release(struct dma_buf *buf)
- /* no need for locking */
-
- if (alloc->contiguous) {
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
-+#if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
- dma_free_attrs(te_device.this_device,
- alloc->nr_pages * PAGE_SIZE,
- alloc->contig_cpu_addr,
- alloc->contig_dma_addr,
- DMA_ATTR_WRITE_COMBINE);
--
--#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-+#else
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
- dma_free_attrs(te_device.this_device,
- alloc->nr_pages * PAGE_SIZE,
- alloc->contig_cpu_addr, alloc->contig_dma_addr, &attrs);
--#else
-- dma_free_writecombine(te_device.this_device,
-- alloc->nr_pages * PAGE_SIZE,
-- alloc->contig_cpu_addr, alloc->contig_dma_addr);
- #endif
- } else {
- for (i = 0; i < alloc->nr_pages; i++)
- __free_page(alloc->pages[i]);
- }
-+#if (KERNEL_VERSION(4, 12, 0) <= LINUX_VERSION_CODE)
-+ kvfree(alloc->pages);
-+#else
- kfree(alloc->pages);
-+#endif
- kfree(alloc);
- }
-
-@@ -316,7 +312,7 @@ static void dma_buf_te_mmap_close(struct vm_area_struct *vma)
- mutex_unlock(&dma_buf->lock);
- }
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
- static int dma_buf_te_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
- #elif KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE
- static int dma_buf_te_mmap_fault(struct vm_fault *vmf)
-@@ -328,7 +324,7 @@ static vm_fault_t dma_buf_te_mmap_fault(struct vm_fault *vmf)
- struct dma_buf *dmabuf;
- struct page *pageptr;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
- dmabuf = vma->vm_private_data;
- #else
- dmabuf = vmf->vma->vm_private_data;
-@@ -362,11 +358,7 @@ static int dma_buf_te_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
- if (alloc->fail_mmap)
- return -ENOMEM;
-
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
- vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
--#else
-- vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTEXPAND;
--#endif
- vma->vm_ops = &dma_buf_te_vm_ops;
- vma->vm_private_data = dmabuf;
-
-@@ -378,7 +370,7 @@ static int dma_buf_te_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
- return 0;
- }
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
-+#if KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE
- static void *dma_buf_te_kmap_atomic(struct dma_buf *buf, unsigned long page_num)
- {
- /* IGNORE */
-@@ -419,19 +411,19 @@ static struct dma_buf_ops dma_buf_te_ops = {
- .mmap = dma_buf_te_mmap,
- .begin_cpu_access = dma_buf_te_begin_cpu_access,
- .end_cpu_access = dma_buf_te_end_cpu_access,
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
-+#if KERNEL_VERSION(4, 12, 0) > LINUX_VERSION_CODE
- .kmap = dma_buf_te_kmap,
- .kunmap = dma_buf_te_kunmap,
-
- /* nop handlers for mandatory functions we ignore */
- .kmap_atomic = dma_buf_te_kmap_atomic
- #else
--#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)
-+#if KERNEL_VERSION(5, 6, 0) > LINUX_VERSION_CODE
- .map = dma_buf_te_kmap,
- .unmap = dma_buf_te_kunmap,
- #endif
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
-+#if KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE
- /* nop handlers for mandatory functions we ignore */
- .map_atomic = dma_buf_te_kmap_atomic
- #endif
-@@ -481,7 +473,8 @@ static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf,
- /* Whilst it is possible to allocate larger buffer, we won't be able to
- * map it during actual usage (mmap() still succeeds). We fail here so
- * userspace code can deal with it early than having driver failure
-- * later on. */
-+ * later on.
-+ */
- if (max_nr_pages > SG_MAX_SINGLE_ALLOC)
- max_nr_pages = SG_MAX_SINGLE_ALLOC;
- #endif /* NO_SG_CHAIN */
-@@ -493,7 +486,7 @@ static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf,
- }
-
- alloc = kzalloc(sizeof(struct dma_buf_te_alloc), GFP_KERNEL);
-- if (NULL == alloc) {
-+ if (alloc == NULL) {
- dev_err(te_device.this_device, "%s: couldn't alloc object", __func__);
- goto no_alloc_object;
- }
-@@ -501,7 +494,12 @@ static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf,
- alloc->nr_pages = alloc_req.size;
- alloc->contiguous = contiguous;
-
-+#if (KERNEL_VERSION(4, 12, 0) <= LINUX_VERSION_CODE)
-+ alloc->pages = kvzalloc(sizeof(struct page *) * alloc->nr_pages, GFP_KERNEL);
-+#else
- alloc->pages = kzalloc(sizeof(struct page *) * alloc->nr_pages, GFP_KERNEL);
-+#endif
-+
- if (!alloc->pages) {
- dev_err(te_device.this_device,
- "%s: couldn't alloc %zu page structures",
-@@ -512,14 +510,13 @@ static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf,
- if (contiguous) {
- dma_addr_t dma_aux;
-
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
-+#if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
- alloc->contig_cpu_addr = dma_alloc_attrs(te_device.this_device,
- alloc->nr_pages * PAGE_SIZE,
- &alloc->contig_dma_addr,
- GFP_KERNEL | __GFP_ZERO,
- DMA_ATTR_WRITE_COMBINE);
--
--#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-+#else
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-@@ -527,11 +524,6 @@ static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf,
- alloc->nr_pages * PAGE_SIZE,
- &alloc->contig_dma_addr,
- GFP_KERNEL | __GFP_ZERO, &attrs);
--#else
-- alloc->contig_cpu_addr = dma_alloc_writecombine(te_device.this_device,
-- alloc->nr_pages * PAGE_SIZE,
-- &alloc->contig_dma_addr,
-- GFP_KERNEL | __GFP_ZERO);
- #endif
- if (!alloc->contig_cpu_addr) {
- dev_err(te_device.this_device, "%s: couldn't alloc contiguous buffer %zu pages",
-@@ -546,7 +538,7 @@ static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf,
- } else {
- for (i = 0; i < alloc->nr_pages; i++) {
- alloc->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
-- if (NULL == alloc->pages[i]) {
-+ if (alloc->pages[i] == NULL) {
- dev_err(te_device.this_device, "%s: couldn't alloc page", __func__);
- goto no_page;
- }
-@@ -554,13 +546,10 @@ static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf,
- }
-
- /* alloc ready, let's export it */
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
- {
- struct dma_buf_export_info export_info = {
- .exp_name = "dma_buf_te",
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
- .owner = THIS_MODULE,
--#endif
- .ops = &dma_buf_te_ops,
- .size = alloc->nr_pages << PAGE_SHIFT,
- .flags = O_CLOEXEC | O_RDWR,
-@@ -569,13 +558,6 @@ static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf,
-
- dma_buf = dma_buf_export(&export_info);
- }
--#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
-- dma_buf = dma_buf_export(alloc, &dma_buf_te_ops,
-- alloc->nr_pages << PAGE_SHIFT, O_CLOEXEC|O_RDWR, NULL);
--#else
-- dma_buf = dma_buf_export(alloc, &dma_buf_te_ops,
-- alloc->nr_pages << PAGE_SHIFT, O_CLOEXEC|O_RDWR);
--#endif
-
- if (IS_ERR_OR_NULL(dma_buf)) {
- dev_err(te_device.this_device, "%s: couldn't export dma_buf", __func__);
-@@ -598,32 +580,30 @@ no_export:
- /* i still valid */
- no_page:
- if (contiguous) {
--
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
-+#if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
- dma_free_attrs(te_device.this_device,
- alloc->nr_pages * PAGE_SIZE,
- alloc->contig_cpu_addr,
- alloc->contig_dma_addr,
- DMA_ATTR_WRITE_COMBINE);
--
--#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-+#else
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
- dma_free_attrs(te_device.this_device,
- alloc->nr_pages * PAGE_SIZE,
- alloc->contig_cpu_addr, alloc->contig_dma_addr, &attrs);
--#else
-- dma_free_writecombine(te_device.this_device,
-- alloc->nr_pages * PAGE_SIZE,
-- alloc->contig_cpu_addr, alloc->contig_dma_addr);
- #endif
- } else {
- while (i-- > 0)
- __free_page(alloc->pages[i]);
- }
- free_page_struct:
-+#if (KERNEL_VERSION(4, 12, 0) <= LINUX_VERSION_CODE)
-+ kvfree(alloc->pages);
-+#else
- kfree(alloc->pages);
-+#endif
- free_alloc_object:
- kfree(alloc);
- no_alloc_object:
-@@ -727,17 +707,17 @@ static u32 dma_te_buf_fill(struct dma_buf *dma_buf, unsigned int value)
- }
-
- ret = dma_buf_begin_cpu_access(dma_buf,
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
-- 0, dma_buf->size,
-+#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE
-+ 0, dma_buf->size,
- #endif
-- DMA_BIDIRECTIONAL);
-+ DMA_BIDIRECTIONAL);
- if (ret)
- goto no_cpu_access;
-
- for_each_sg(sgt->sgl, sg, sgt->nents, count) {
- for (i = 0; i < sg_dma_len(sg); i = i + PAGE_SIZE) {
- void *addr = NULL;
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
-+#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE
- addr = dma_buf_te_kmap(dma_buf, i >> PAGE_SHIFT);
- #else
- addr = dma_buf_kmap(dma_buf, i >> PAGE_SHIFT);
-@@ -747,7 +727,7 @@ static u32 dma_te_buf_fill(struct dma_buf *dma_buf, unsigned int value)
- goto no_kmap;
- }
- memset(addr, value, PAGE_SIZE);
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
-+#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE
- dma_buf_te_kunmap(dma_buf, i >> PAGE_SHIFT, addr);
- #else
- dma_buf_kunmap(dma_buf, i >> PAGE_SHIFT, addr);
-@@ -758,10 +738,10 @@ static u32 dma_te_buf_fill(struct dma_buf *dma_buf, unsigned int value)
-
- no_kmap:
- dma_buf_end_cpu_access(dma_buf,
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
-- 0, dma_buf->size,
-+#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE
-+ 0, dma_buf->size,
- #endif
-- DMA_BIDIRECTIONAL);
-+ DMA_BIDIRECTIONAL);
- no_cpu_access:
- dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL);
- no_import:
-diff --git a/dvalin/kernel/drivers/base/dma_buf_test_exporter/Kbuild b/dvalin/kernel/drivers/base/arm/memory_group_manager/Kbuild
-similarity index 74%
-rename from dvalin/kernel/drivers/base/dma_buf_test_exporter/Kbuild
-rename to dvalin/kernel/drivers/base/arm/memory_group_manager/Kbuild
-index c382b79..99ce311 100644
---- a/dvalin/kernel/drivers/base/dma_buf_test_exporter/Kbuild
-+++ b/dvalin/kernel/drivers/base/arm/memory_group_manager/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2019-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,10 +16,8 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
--ifneq ($(CONFIG_DMA_SHARED_BUFFER),)
--obj-$(CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER) += dma-buf-test-exporter.o
-+ifeq ($(CONFIG_MALI_MEMORY_GROUP_MANAGER), y)
-+obj-m := memory_group_manager.o
- endif
-diff --git a/dvalin/kernel/drivers/base/arm/memory_group_manager/build.bp b/dvalin/kernel/drivers/base/arm/memory_group_manager/build.bp
-new file mode 100644
-index 0000000..23db183
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/memory_group_manager/build.bp
-@@ -0,0 +1,36 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+bob_kernel_module {
-+ name: "memory_group_manager",
-+ defaults: [
-+ "kernel_defaults"
-+ ],
-+ srcs: [
-+ "Kbuild",
-+ "memory_group_manager.c",
-+ ],
-+ enabled: false,
-+ mali_memory_group_manager: {
-+ kbuild_options: ["CONFIG_MALI_MEMORY_GROUP_MANAGER=y"],
-+ enabled: true,
-+ },
-+}
-diff --git a/dvalin/kernel/drivers/base/memory_group_manager/memory_group_manager.c b/dvalin/kernel/drivers/base/arm/memory_group_manager/memory_group_manager.c
-similarity index 98%
-rename from dvalin/kernel/drivers/base/memory_group_manager/memory_group_manager.c
-rename to dvalin/kernel/drivers/base/arm/memory_group_manager/memory_group_manager.c
-index 44f848a..a70fe70 100644
---- a/dvalin/kernel/drivers/base/memory_group_manager/memory_group_manager.c
-+++ b/dvalin/kernel/drivers/base/arm/memory_group_manager/memory_group_manager.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/fs.h>
-@@ -26,7 +25,7 @@
- #include <linux/platform_device.h>
- #include <linux/version.h>
- #include <linux/module.h>
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- #include <linux/debugfs.h>
- #endif
- #include <linux/mm.h>
-@@ -92,12 +91,12 @@ struct mgm_group {
- struct mgm_groups {
- struct mgm_group groups[MEMORY_GROUP_MANAGER_NR_GROUPS];
- struct device *dev;
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- struct dentry *mgm_debugfs_root;
- #endif
- };
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-
- static int mgm_size_get(void *data, u64 *val)
- {
-@@ -475,7 +474,6 @@ static struct platform_driver memory_group_manager_driver = {
- .remove = memory_group_manager_remove,
- .driver = {
- .name = "physical-memory-group-manager",
-- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(memory_group_manager_dt_ids),
- /*
- * Prevent the mgm_dev from being unbound and freed, as other's
-diff --git a/dvalin/kernel/drivers/base/arm/protected_memory_allocator/Kbuild b/dvalin/kernel/drivers/base/arm/protected_memory_allocator/Kbuild
-new file mode 100644
-index 0000000..25295a9
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/protected_memory_allocator/Kbuild
-@@ -0,0 +1,23 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2019-2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+ifeq ($(CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR), y)
-+obj-m := protected_memory_allocator.o
-+endif
-diff --git a/dvalin/kernel/drivers/base/arm/protected_memory_allocator/build.bp b/dvalin/kernel/drivers/base/arm/protected_memory_allocator/build.bp
-new file mode 100644
-index 0000000..4c56154
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/protected_memory_allocator/build.bp
-@@ -0,0 +1,36 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+bob_kernel_module {
-+ name: "protected_memory_allocator",
-+ defaults: [
-+ "kernel_defaults"
-+ ],
-+ srcs: [
-+ "Kbuild",
-+ "protected_memory_allocator.c",
-+ ],
-+ enabled: false,
-+ mali_protected_memory_allocator: {
-+ kbuild_options: ["CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR=y"],
-+ enabled: true,
-+ },
-+}
-diff --git a/dvalin/kernel/drivers/base/arm/protected_memory_allocator/protected_memory_allocator.c b/dvalin/kernel/drivers/base/arm/protected_memory_allocator/protected_memory_allocator.c
-new file mode 100644
-index 0000000..6684210
---- /dev/null
-+++ b/dvalin/kernel/drivers/base/arm/protected_memory_allocator/protected_memory_allocator.c
-@@ -0,0 +1,551 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <linux/version.h>
-+#include <linux/of.h>
-+#include <linux/of_reserved_mem.h>
-+#include <linux/platform_device.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/mm.h>
-+#include <linux/io.h>
-+#include <linux/protected_memory_allocator.h>
-+
-+/* Size of a bitfield element in bytes */
-+#define BITFIELD_ELEM_SIZE sizeof(u64)
-+
-+/* We can track whether or not 64 pages are currently allocated in a u64 */
-+#define PAGES_PER_BITFIELD_ELEM (BITFIELD_ELEM_SIZE * BITS_PER_BYTE)
-+
-+/* Order 6 (ie, 64) corresponds to the number of pages held in a bitfield */
-+#define ORDER_OF_PAGES_PER_BITFIELD_ELEM 6
-+
-+/**
-+ * struct simple_pma_device - Simple implementation of a protected memory
-+ * allocator device
-+ *
-+ * @pma_dev: Protected memory allocator device pointer
-+ * @dev: Device pointer
-+ * @alloc_pages_bitfield_arr: Status of all the physical memory pages within the
-+ * protected memory region, one bit per page
-+ * @rmem_base: Base address of the reserved memory region
-+ * @rmem_size: Size of the reserved memory region, in pages
-+ * @num_free_pages: Number of free pages in the memory region
-+ * @rmem_lock: Lock to serialize the allocation and freeing of
-+ * physical pages from the protected memory region
-+ */
-+struct simple_pma_device {
-+ struct protected_memory_allocator_device pma_dev;
-+ struct device *dev;
-+ u64 *allocated_pages_bitfield_arr;
-+ phys_addr_t rmem_base;
-+ size_t rmem_size;
-+ size_t num_free_pages;
-+ spinlock_t rmem_lock;
-+};
-+
-+/**
-+ * Number of elements in array 'allocated_pages_bitfield_arr'. If the number of
-+ * pages required does not divide exactly by PAGES_PER_BITFIELD_ELEM, adds an
-+ * extra page for the remainder.
-+ */
-+#define ALLOC_PAGES_BITFIELD_ARR_SIZE(num_pages) \
-+ ((PAGES_PER_BITFIELD_ELEM * (0 != (num_pages % PAGES_PER_BITFIELD_ELEM)) + \
-+ num_pages) / PAGES_PER_BITFIELD_ELEM)
-+
-+/**
-+ * Allocate a power-of-two number of pages, N, where
-+ * 0 <= N <= ORDER_OF_PAGES_PER_BITFIELD_ELEM - 1. ie, Up to 32 pages. The routine
-+ * fills-in a pma structure and sets the appropriate bits in the allocated-pages
-+ * bitfield array but assumes the caller has already determined that these are
-+ * already clear.
-+ *
-+ * This routine always works within only a single allocated-pages bitfield element.
-+ * It can be thought of as the 'small-granularity' allocator.
-+ */
-+static void small_granularity_alloc(struct simple_pma_device *const epma_dev,
-+ size_t alloc_bitfield_idx, size_t start_bit,
-+ size_t order,
-+ struct protected_memory_allocation *pma)
-+{
-+ size_t i;
-+ size_t page_idx;
-+ u64 *bitfield;
-+ size_t alloc_pages_bitfield_size;
-+
-+ if (WARN_ON(!epma_dev) ||
-+ WARN_ON(!pma))
-+ return;
-+
-+ WARN(epma_dev->rmem_size == 0, "%s: rmem_size is 0", __func__);
-+ alloc_pages_bitfield_size = ALLOC_PAGES_BITFIELD_ARR_SIZE(epma_dev->rmem_size);
-+
-+ WARN(alloc_bitfield_idx >= alloc_pages_bitfield_size,
-+ "%s: idx>bf_size: %zu %zu", __FUNCTION__,
-+ alloc_bitfield_idx, alloc_pages_bitfield_size);
-+
-+ WARN((start_bit + (1 << order)) > PAGES_PER_BITFIELD_ELEM,
-+ "%s: start=%zu order=%zu ppbe=%zu",
-+ __FUNCTION__, start_bit, order, PAGES_PER_BITFIELD_ELEM);
-+
-+ bitfield = &epma_dev->allocated_pages_bitfield_arr[alloc_bitfield_idx];
-+
-+ for (i = 0; i < (1 << order); i++) {
-+ /* Check the pages represented by this bit are actually free */
-+ WARN (*bitfield & (1ULL << (start_bit + i)),
-+ "in %s: page not free: %zu %zu %.16llx %zu\n",
-+ __FUNCTION__, i, order, *bitfield, alloc_pages_bitfield_size);
-+
-+ /* Mark the pages as now allocated */
-+ *bitfield |= (1ULL << (start_bit + i));
-+ }
-+
-+ /* Compute the page index */
-+ page_idx = (alloc_bitfield_idx * PAGES_PER_BITFIELD_ELEM) + start_bit;
-+
-+ /* Fill-in the allocation struct for the caller */
-+ pma->pa = epma_dev->rmem_base + (page_idx << PAGE_SHIFT);
-+ pma->order = order;
-+}
-+
-+/**
-+ * Allocate a power-of-two number of pages, N, where
-+ * N >= ORDER_OF_PAGES_PER_BITFIELD_ELEM. ie, 64 pages or more. The routine fills-in
-+ * a pma structure and sets the appropriate bits in the allocated-pages bitfield array
-+ * but assumes the caller has already determined that these are already clear.
-+ *
-+ * Unlike small_granularity_alloc, this routine can work with multiple 64-page groups,
-+ * ie multiple elements from the allocated-pages bitfield array. However, it always
-+ * works with complete sets of these 64-page groups. It can therefore be thought of
-+ * as the 'large-granularity' allocator.
-+ */
-+static void large_granularity_alloc(struct simple_pma_device *const epma_dev,
-+ size_t start_alloc_bitfield_idx,
-+ size_t order,
-+ struct protected_memory_allocation *pma)
-+{
-+ size_t i;
-+ size_t num_pages_to_alloc = (size_t)1 << order;
-+ size_t num_bitfield_elements_needed = num_pages_to_alloc / PAGES_PER_BITFIELD_ELEM;
-+ size_t start_page_idx = start_alloc_bitfield_idx * PAGES_PER_BITFIELD_ELEM;
-+
-+ if (WARN_ON(!epma_dev) ||
-+ WARN_ON(!pma))
-+ return;
-+
-+ /*
-+ * Are there anough bitfield array elements (groups of 64 pages)
-+ * between the start element and the end of the bitfield array
-+ * to fulfill the request?
-+ */
-+ WARN((start_alloc_bitfield_idx + order) >= ALLOC_PAGES_BITFIELD_ARR_SIZE(epma_dev->rmem_size),
-+ "%s: start=%zu order=%zu ms=%zu",
-+ __FUNCTION__, start_alloc_bitfield_idx, order, epma_dev->rmem_size);
-+
-+ for (i = 0; i < num_bitfield_elements_needed; i++) {
-+ u64 *bitfield = &epma_dev->allocated_pages_bitfield_arr[start_alloc_bitfield_idx + i];
-+
-+ /* We expect all pages that relate to this bitfield element to be free */
-+ WARN((*bitfield != 0),
-+ "in %s: pages not free: i=%zu o=%zu bf=%.16llx\n",
-+ __FUNCTION__, i, order, *bitfield);
-+
-+ /* Mark all the pages for this element as not free */
-+ *bitfield = ~0ULL;
-+ }
-+
-+ /* Fill-in the allocation struct for the caller */
-+ pma->pa = epma_dev->rmem_base + (start_page_idx << PAGE_SHIFT);
-+ pma->order = order;
-+}
-+
-+static struct protected_memory_allocation *simple_pma_alloc_page(
-+ struct protected_memory_allocator_device *pma_dev, unsigned int order)
-+{
-+ struct simple_pma_device *const epma_dev =
-+ container_of(pma_dev, struct simple_pma_device, pma_dev);
-+ struct protected_memory_allocation *pma;
-+ size_t num_pages_to_alloc;
-+
-+ u64 *bitfields = epma_dev->allocated_pages_bitfield_arr;
-+ size_t i;
-+ size_t bit;
-+ size_t count;
-+
-+ dev_dbg(epma_dev->dev, "%s(pma_dev=%px, order=%u\n",
-+ __func__, (void *)pma_dev, order);
-+
-+ /* This is an example function that follows an extremely simple logic
-+ * and is very likely to fail to allocate memory if put under stress.
-+ *
-+ * The simple_pma_device maintains an array of u64s, with one bit used
-+ * to track the status of each page.
-+ *
-+ * In order to create a memory allocation, the allocator looks for an
-+ * adjacent group of cleared bits. This does leave the algorithm open
-+ * to fragmentation issues, but is deemed sufficient for now.
-+ * If successful, the allocator shall mark all the pages as allocated
-+ * and increment the offset accordingly.
-+ *
-+ * Allocations of 64 pages or more (order 6) can be allocated only with
-+ * 64-page alignment, in order to keep the algorithm as simple as
-+ * possible. ie, starting from bit 0 of any 64-bit page-allocation
-+ * bitfield. For this, the large-granularity allocator is utilised.
-+ *
-+ * Allocations of lower-order can only be allocated entirely within the
-+ * same group of 64 pages, with the small-ganularity allocator (ie
-+ * always from the same 64-bit page-allocation bitfield) - again, to
-+ * keep things as simple as possible, but flexible to meet
-+ * current needs.
-+ */
-+
-+ num_pages_to_alloc = (size_t)1 << order;
-+
-+ pma = devm_kzalloc(epma_dev->dev, sizeof(*pma), GFP_KERNEL);
-+ if (!pma) {
-+ dev_err(epma_dev->dev, "Failed to alloc pma struct");
-+ return NULL;
-+ }
-+
-+ spin_lock(&epma_dev->rmem_lock);
-+
-+ if (epma_dev->num_free_pages < num_pages_to_alloc) {
-+ dev_err(epma_dev->dev, "not enough free pages\n");
-+ devm_kfree(epma_dev->dev, pma);
-+ spin_unlock(&epma_dev->rmem_lock);
-+ return NULL;
-+ }
-+
-+ /*
-+ * For order 0-5 (ie, 1 to 32 pages) we always allocate within the same set of 64 pages
-+ * Currently, most allocations will be very small (1 page), so the more likely path
-+ * here is order < ORDER_OF_PAGES_PER_BITFIELD_ELEM.
-+ */
-+ if (likely(order < ORDER_OF_PAGES_PER_BITFIELD_ELEM)) {
-+ size_t alloc_pages_bitmap_size = ALLOC_PAGES_BITFIELD_ARR_SIZE(epma_dev->rmem_size);
-+
-+ for (i = 0; i < alloc_pages_bitmap_size; i++) {
-+ count = 0;
-+
-+ for (bit = 0; bit < PAGES_PER_BITFIELD_ELEM; bit++) {
-+ if (0 == (bitfields[i] & (1ULL << bit))) {
-+ if ((count + 1) >= num_pages_to_alloc) {
-+ /*
-+ * We've found enough free, consecutive pages with which to
-+ * make an allocation
-+ */
-+ small_granularity_alloc(
-+ epma_dev, i,
-+ bit - count, order,
-+ pma);
-+
-+ epma_dev->num_free_pages -=
-+ num_pages_to_alloc;
-+
-+ spin_unlock(
-+ &epma_dev->rmem_lock);
-+ return pma;
-+ }
-+
-+ /* So far so good, but we need more set bits yet */
-+ count++;
-+ } else {
-+ /*
-+ * We found an allocated page, so nothing we've seen so far can be used.
-+ * Keep looking.
-+ */
-+ count = 0;
-+ }
-+ }
-+ }
-+ } else {
-+ /**
-+ * For allocations of order ORDER_OF_PAGES_PER_BITFIELD_ELEM and above (>= 64 pages), we know
-+ * we'll only get allocations for whole groups of 64 pages, which hugely simplifies the task.
-+ */
-+ size_t alloc_pages_bitmap_size = ALLOC_PAGES_BITFIELD_ARR_SIZE(epma_dev->rmem_size);
-+
-+ /* How many 64-bit bitfield elements will be needed for the allocation? */
-+ size_t num_bitfield_elements_needed = num_pages_to_alloc / PAGES_PER_BITFIELD_ELEM;
-+
-+ count = 0;
-+
-+ for (i = 0; i < alloc_pages_bitmap_size; i++) {
-+ /* Are all the pages free for the i'th u64 bitfield element? */
-+ if (bitfields[i] == 0) {
-+ count += PAGES_PER_BITFIELD_ELEM;
-+
-+ if (count >= (1 << order)) {
-+ size_t start_idx = (i + 1) - num_bitfield_elements_needed;
-+
-+ large_granularity_alloc(epma_dev,
-+ start_idx,
-+ order, pma);
-+
-+ epma_dev->num_free_pages -= 1 << order;
-+ spin_unlock(&epma_dev->rmem_lock);
-+ return pma;
-+ }
-+ }
-+ else
-+ {
-+ count = 0;
-+ }
-+ }
-+ }
-+
-+ spin_unlock(&epma_dev->rmem_lock);
-+ devm_kfree(epma_dev->dev, pma);
-+
-+ dev_err(epma_dev->dev, "not enough contiguous pages (need %zu), total free pages left %zu\n",
-+ num_pages_to_alloc, epma_dev->num_free_pages);
-+ return NULL;
-+}
-+
-+static phys_addr_t simple_pma_get_phys_addr(
-+ struct protected_memory_allocator_device *pma_dev,
-+ struct protected_memory_allocation *pma)
-+{
-+ struct simple_pma_device *const epma_dev =
-+ container_of(pma_dev, struct simple_pma_device, pma_dev);
-+
-+ dev_dbg(epma_dev->dev, "%s(pma_dev=%px, pma=%px, pa=%llx\n",
-+ __func__, (void *)pma_dev, (void *)pma,
-+ (unsigned long long)pma->pa);
-+
-+ return pma->pa;
-+}
-+
-+static void simple_pma_free_page(
-+ struct protected_memory_allocator_device *pma_dev,
-+ struct protected_memory_allocation *pma)
-+{
-+ struct simple_pma_device *const epma_dev =
-+ container_of(pma_dev, struct simple_pma_device, pma_dev);
-+ size_t num_pages_in_allocation;
-+ size_t offset;
-+ size_t i;
-+ size_t bitfield_idx;
-+ size_t bitfield_start_bit;
-+ size_t page_num;
-+ u64 *bitfield;
-+ size_t alloc_pages_bitmap_size;
-+ size_t num_bitfield_elems_used_by_alloc;
-+
-+ WARN_ON(pma == NULL);
-+
-+ dev_dbg(epma_dev->dev, "%s(pma_dev=%px, pma=%px, pa=%llx\n",
-+ __func__, (void *)pma_dev, (void *)pma,
-+ (unsigned long long)pma->pa);
-+
-+ WARN_ON(pma->pa < epma_dev->rmem_base);
-+
-+ /* This is an example function that follows an extremely simple logic
-+ * and is vulnerable to abuse.
-+ */
-+ offset = (pma->pa - epma_dev->rmem_base);
-+ num_pages_in_allocation = (size_t)1 << pma->order;
-+
-+ /* The number of bitfield elements used by the allocation */
-+ num_bitfield_elems_used_by_alloc = num_pages_in_allocation / PAGES_PER_BITFIELD_ELEM;
-+
-+ /* The page number of the first page of the allocation, relative to rmem_base */
-+ page_num = offset >> PAGE_SHIFT;
-+
-+ /* Which u64 bitfield refers to this page? */
-+ bitfield_idx = page_num / PAGES_PER_BITFIELD_ELEM;
-+
-+ alloc_pages_bitmap_size = ALLOC_PAGES_BITFIELD_ARR_SIZE(epma_dev->rmem_size);
-+
-+ /* Is the allocation within expected bounds? */
-+ WARN_ON((bitfield_idx + num_bitfield_elems_used_by_alloc) >= alloc_pages_bitmap_size);
-+
-+ spin_lock(&epma_dev->rmem_lock);
-+
-+ if (pma->order < ORDER_OF_PAGES_PER_BITFIELD_ELEM) {
-+ bitfield = &epma_dev->allocated_pages_bitfield_arr[bitfield_idx];
-+
-+ /* Which bit within that u64 bitfield is the lsb covering this allocation? */
-+ bitfield_start_bit = page_num % PAGES_PER_BITFIELD_ELEM;
-+
-+ /* Clear the bits for the pages we're now freeing */
-+ *bitfield &= ~(((1ULL << num_pages_in_allocation) - 1) << bitfield_start_bit);
-+ }
-+ else {
-+ WARN(page_num % PAGES_PER_BITFIELD_ELEM,
-+ "%s: Expecting allocs of order >= %d to be %zu-page aligned\n",
-+ __FUNCTION__, ORDER_OF_PAGES_PER_BITFIELD_ELEM, PAGES_PER_BITFIELD_ELEM);
-+
-+ for (i = 0; i < num_bitfield_elems_used_by_alloc; i++) {
-+ bitfield = &epma_dev->allocated_pages_bitfield_arr[bitfield_idx + i];
-+
-+ /* We expect all bits to be set (all pages allocated) */
-+ WARN((*bitfield != ~0),
-+ "%s: alloc being freed is not fully allocated: of=%zu np=%zu bf=%.16llx\n",
-+ __FUNCTION__, offset, num_pages_in_allocation, *bitfield);
-+
-+ /*
-+ * Now clear all the bits in the bitfield element to mark all the pages
-+ * it refers to as free.
-+ */
-+ *bitfield = 0ULL;
-+ }
-+ }
-+
-+ epma_dev->num_free_pages += num_pages_in_allocation;
-+ spin_unlock(&epma_dev->rmem_lock);
-+ devm_kfree(epma_dev->dev, pma);
-+}
-+
-+static int protected_memory_allocator_probe(struct platform_device *pdev)
-+{
-+ struct simple_pma_device *epma_dev;
-+ struct device_node *np;
-+ phys_addr_t rmem_base;
-+ size_t rmem_size;
-+ size_t alloc_bitmap_pages_arr_size;
-+#if (KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE)
-+ struct reserved_mem *rmem;
-+#endif
-+
-+ np = pdev->dev.of_node;
-+
-+ if (!np) {
-+ dev_err(&pdev->dev, "device node pointer not set\n");
-+ return -ENODEV;
-+ }
-+
-+ np = of_parse_phandle(np, "memory-region", 0);
-+ if (!np) {
-+ dev_err(&pdev->dev, "memory-region node not set\n");
-+ return -ENODEV;
-+ }
-+
-+#if (KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE)
-+ rmem = of_reserved_mem_lookup(np);
-+ if (rmem) {
-+ rmem_base = rmem->base;
-+ rmem_size = rmem->size >> PAGE_SHIFT;
-+ } else
-+#endif
-+ {
-+ of_node_put(np);
-+ dev_err(&pdev->dev, "could not read reserved memory-region\n");
-+ return -ENODEV;
-+ }
-+
-+ of_node_put(np);
-+ epma_dev = devm_kzalloc(&pdev->dev, sizeof(*epma_dev), GFP_KERNEL);
-+ if (!epma_dev)
-+ return -ENOMEM;
-+
-+ epma_dev->pma_dev.ops.pma_alloc_page = simple_pma_alloc_page;
-+ epma_dev->pma_dev.ops.pma_get_phys_addr = simple_pma_get_phys_addr;
-+ epma_dev->pma_dev.ops.pma_free_page = simple_pma_free_page;
-+ epma_dev->pma_dev.owner = THIS_MODULE;
-+ epma_dev->dev = &pdev->dev;
-+ epma_dev->rmem_base = rmem_base;
-+ epma_dev->rmem_size = rmem_size;
-+ epma_dev->num_free_pages = rmem_size;
-+ spin_lock_init(&epma_dev->rmem_lock);
-+
-+ alloc_bitmap_pages_arr_size = ALLOC_PAGES_BITFIELD_ARR_SIZE(epma_dev->rmem_size);
-+
-+ epma_dev->allocated_pages_bitfield_arr = devm_kzalloc(&pdev->dev,
-+ alloc_bitmap_pages_arr_size * BITFIELD_ELEM_SIZE, GFP_KERNEL);
-+
-+ if (!epma_dev->allocated_pages_bitfield_arr) {
-+ dev_err(&pdev->dev, "failed to allocate resources\n");
-+ devm_kfree(&pdev->dev, epma_dev);
-+ return -ENOMEM;
-+ }
-+
-+ if (epma_dev->rmem_size % PAGES_PER_BITFIELD_ELEM) {
-+ size_t extra_pages =
-+ alloc_bitmap_pages_arr_size * PAGES_PER_BITFIELD_ELEM -
-+ epma_dev->rmem_size;
-+ size_t last_bitfield_index = alloc_bitmap_pages_arr_size - 1;
-+
-+ /* Mark the extra pages (that lie outside the reserved range) as
-+ * always in use.
-+ */
-+ epma_dev->allocated_pages_bitfield_arr[last_bitfield_index] =
-+ ((1ULL << extra_pages) - 1) <<
-+ (PAGES_PER_BITFIELD_ELEM - extra_pages);
-+ }
-+
-+ platform_set_drvdata(pdev, &epma_dev->pma_dev);
-+ dev_info(&pdev->dev,
-+ "Protected memory allocator probed successfully\n");
-+ dev_info(&pdev->dev, "Protected memory region: base=%llx num pages=%zu\n",
-+ (unsigned long long)rmem_base, rmem_size);
-+
-+ return 0;
-+}
-+
-+static int protected_memory_allocator_remove(struct platform_device *pdev)
-+{
-+ struct protected_memory_allocator_device *pma_dev =
-+ platform_get_drvdata(pdev);
-+ struct simple_pma_device *epma_dev;
-+ struct device *dev;
-+
-+ if (!pma_dev)
-+ return -EINVAL;
-+
-+ epma_dev = container_of(pma_dev, struct simple_pma_device, pma_dev);
-+ dev = epma_dev->dev;
-+
-+ if (epma_dev->num_free_pages < epma_dev->rmem_size) {
-+ dev_warn(&pdev->dev, "Leaking %zu pages of protected memory\n",
-+ epma_dev->rmem_size - epma_dev->num_free_pages);
-+ }
-+
-+ platform_set_drvdata(pdev, NULL);
-+ devm_kfree(dev, epma_dev->allocated_pages_bitfield_arr);
-+ devm_kfree(dev, epma_dev);
-+
-+ dev_info(&pdev->dev,
-+ "Protected memory allocator removed successfully\n");
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id protected_memory_allocator_dt_ids[] = {
-+ { .compatible = "arm,protected-memory-allocator" },
-+ { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, protected_memory_allocator_dt_ids);
-+
-+static struct platform_driver protected_memory_allocator_driver = {
-+ .probe = protected_memory_allocator_probe,
-+ .remove = protected_memory_allocator_remove,
-+ .driver = {
-+ .name = "simple_protected_memory_allocator",
-+ .of_match_table = of_match_ptr(protected_memory_allocator_dt_ids),
-+ }
-+};
-+
-+module_platform_driver(protected_memory_allocator_driver);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("ARM Ltd.");
-+MODULE_VERSION("1.0");
-diff --git a/dvalin/kernel/drivers/base/dma_buf_test_exporter/Kconfig b/dvalin/kernel/drivers/base/dma_buf_test_exporter/Kconfig
-deleted file mode 100644
-index 66ca1bc..0000000
---- a/dvalin/kernel/drivers/base/dma_buf_test_exporter/Kconfig
-+++ /dev/null
-@@ -1,26 +0,0 @@
--#
--# (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.
--#
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--# GNU General Public License for more details.
--#
--# You should have received a copy of the GNU General Public License
--# along with this program; if not, you can access it online at
--# http://www.gnu.org/licenses/gpl-2.0.html.
--#
--# SPDX-License-Identifier: GPL-2.0
--#
--#
--
--config DMA_SHARED_BUFFER_TEST_EXPORTER
-- tristate "Test exporter for the dma-buf framework"
-- depends on DMA_SHARED_BUFFER
-- help
-- This option enables the test exporter usable to help test importerts.
-diff --git a/dvalin/kernel/drivers/base/dma_buf_test_exporter/Makefile b/dvalin/kernel/drivers/base/dma_buf_test_exporter/Makefile
-deleted file mode 100644
-index 528582c..0000000
---- a/dvalin/kernel/drivers/base/dma_buf_test_exporter/Makefile
-+++ /dev/null
-@@ -1,36 +0,0 @@
--#
--# (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.
--#
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--# GNU General Public License for more details.
--#
--# You should have received a copy of the GNU General Public License
--# along with this program; if not, you can access it online at
--# http://www.gnu.org/licenses/gpl-2.0.html.
--#
--# SPDX-License-Identifier: GPL-2.0
--#
--#
--
--# linux build system bootstrap for out-of-tree module
--
--# default to building for the host
--ARCH ?= $(shell uname -m)
--
--ifeq ($(KDIR),)
--$(error Must specify KDIR to point to the kernel to target))
--endif
--
--all:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER=m
--
--clean:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean
--
-diff --git a/dvalin/kernel/drivers/base/dma_buf_test_exporter/build.bp b/dvalin/kernel/drivers/base/dma_buf_test_exporter/build.bp
-deleted file mode 100644
-index 7b0bd5d..0000000
---- a/dvalin/kernel/drivers/base/dma_buf_test_exporter/build.bp
-+++ /dev/null
-@@ -1,26 +0,0 @@
--/*
-- *
-- * (C) COPYRIGHT 2017, 2020 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.
-- *
-- */
--
--bob_kernel_module {
-- name: "dma-buf-test-exporter",
-- srcs: [
-- "Kbuild",
-- "dma-buf-test-exporter.c",
-- ],
-- kbuild_options: [
-- "CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER=m",
-- ],
-- defaults: ["kernel_defaults"],
--}
-diff --git a/dvalin/kernel/drivers/base/memory_group_manager/Makefile b/dvalin/kernel/drivers/base/memory_group_manager/Makefile
-deleted file mode 100644
-index a5bceae..0000000
---- a/dvalin/kernel/drivers/base/memory_group_manager/Makefile
-+++ /dev/null
-@@ -1,35 +0,0 @@
--#
--# (C) COPYRIGHT 2019 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.
--#
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--# GNU General Public License for more details.
--#
--# You should have received a copy of the GNU General Public License
--# along with this program; if not, you can access it online at
--# http://www.gnu.org/licenses/gpl-2.0.html.
--#
--# SPDX-License-Identifier: GPL-2.0
--#
--#
--
--# linux build system bootstrap for out-of-tree module
--
--# default to building for the host
--ARCH ?= $(shell uname -m)
--
--ifeq ($(KDIR),)
--$(error Must specify KDIR to point to the kernel to target))
--endif
--
--all:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" modules CONFIG_MALI_MEMORY_GROUP_MANAGER=m
--
--clean:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean
-diff --git a/dvalin/kernel/drivers/base/memory_group_manager/build.bp b/dvalin/kernel/drivers/base/memory_group_manager/build.bp
-deleted file mode 100644
-index 04dbfd3..0000000
---- a/dvalin/kernel/drivers/base/memory_group_manager/build.bp
-+++ /dev/null
-@@ -1,22 +0,0 @@
--/*
-- * (C) COPYRIGHT 2019 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.
-- */
--
--bob_kernel_module {
-- name: "memory_group_manager",
-- srcs: [
-- "Kbuild",
-- "memory_group_manager.c",
-- ],
-- kbuild_options: ["CONFIG_MALI_MEMORY_GROUP_MANAGER=m"],
-- defaults: ["kernel_defaults"],
--}
-diff --git a/dvalin/kernel/drivers/base/protected_memory_allocator/Makefile b/dvalin/kernel/drivers/base/protected_memory_allocator/Makefile
-deleted file mode 100644
-index 17b2600..0000000
---- a/dvalin/kernel/drivers/base/protected_memory_allocator/Makefile
-+++ /dev/null
-@@ -1,35 +0,0 @@
--#
--# (C) COPYRIGHT 2019 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.
--#
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--# GNU General Public License for more details.
--#
--# You should have received a copy of the GNU General Public License
--# along with this program; if not, you can access it online at
--# http://www.gnu.org/licenses/gpl-2.0.html.
--#
--# SPDX-License-Identifier: GPL-2.0
--#
--#
--
--# linux build system bootstrap for out-of-tree module
--
--# default to building for the host
--ARCH ?= $(shell uname -m)
--
--ifeq ($(KDIR),)
--$(error Must specify KDIR to point to the kernel to target))
--endif
--
--all:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../include" modules CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR=m
--
--clean:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean
-diff --git a/dvalin/kernel/drivers/base/protected_memory_allocator/build.bp b/dvalin/kernel/drivers/base/protected_memory_allocator/build.bp
-deleted file mode 100644
-index 165b17b..0000000
---- a/dvalin/kernel/drivers/base/protected_memory_allocator/build.bp
-+++ /dev/null
-@@ -1,26 +0,0 @@
--/*
-- * (C) COPYRIGHT 2019 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.
-- */
--
--bob_kernel_module {
-- name: "protected_memory_allocator",
-- srcs: [
-- "Kbuild",
-- "protected_memory_allocator.c",
-- ],
-- kbuild_options: ["CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR=m"],
-- defaults: ["kernel_defaults"],
-- enabled: false,
-- build_csf_only_module: {
-- enabled: true,
-- },
--}
-diff --git a/dvalin/kernel/drivers/base/protected_memory_allocator/protected_memory_allocator.c b/dvalin/kernel/drivers/base/protected_memory_allocator/protected_memory_allocator.c
-deleted file mode 100644
-index bb0b1dd..0000000
---- a/dvalin/kernel/drivers/base/protected_memory_allocator/protected_memory_allocator.c
-+++ /dev/null
-@@ -1,308 +0,0 @@
--/*
-- *
-- * (C) COPYRIGHT 2019-2020 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- */
--
--#include <linux/version.h>
--#include <linux/of.h>
--#include <linux/of_reserved_mem.h>
--#include <linux/platform_device.h>
--#include <linux/module.h>
--#include <linux/slab.h>
--#include <linux/mm.h>
--#include <linux/io.h>
--#include <linux/protected_memory_allocator.h>
--
--/**
-- * struct simple_pma_device - Simple implementation of a protected memory
-- * allocator device
-- *
-- * @pma_dev: Protected memory allocator device pointer
-- * @dev: Device pointer
-- * @alloc_pages: Status of all the physical memory pages within the
-- * protected memory region; true for allocated pages
-- * @rmem_base: Base address of the reserved memory region
-- * @rmem_size: Size of the reserved memory region, in pages
-- * @free_pa_offset: Offset of the lowest physical address within the protected
-- * memory region that is currently associated with a free page
-- * @num_free_pages: Number of free pages in the memory region
-- */
--struct simple_pma_device {
-- struct protected_memory_allocator_device pma_dev;
-- struct device *dev;
-- bool *alloc_pages;
-- phys_addr_t rmem_base;
-- size_t rmem_size;
-- size_t free_pa_offset;
-- size_t num_free_pages;
--};
--
--static struct protected_memory_allocation *simple_pma_alloc_page(
-- struct protected_memory_allocator_device *pma_dev, unsigned int order)
--{
-- struct simple_pma_device *const epma_dev =
-- container_of(pma_dev, struct simple_pma_device, pma_dev);
-- struct protected_memory_allocation *pma;
-- size_t num_pages;
-- size_t i;
--
-- dev_dbg(epma_dev->dev, "%s(pma_dev=%px, order=%u\n",
-- __func__, (void *)pma_dev, order);
--
-- /* This is an example function that follows an extremely simple logic
-- * and is very likely to fail to allocate memory if put under stress.
-- *
-- * The simple_pma_device maintains an array of booleans to track
-- * the status of every page and an offset to the free page to use
-- * for the next allocation. The offset starts from 0 and can only grow,
-- * and be reset when the end of the memory region is reached.
-- *
-- * In order to create a memory allocation, the allocator simply looks
-- * at the offset and verifies whether there are enough free pages
-- * after it to accommodate the allocation request. If successful,
-- * the allocator shall mark all the pages as allocated and increment
-- * the offset accordingly.
-- *
-- * The allocator does not look for any other free pages inside the
-- * memory region, even if plenty of free memory is available.
-- * Free memory pages are counted and the offset is ignored if the
-- * memory region is fully allocated.
-- */
--
-- /* The only candidate for allocation is the sub-region starting
-- * from the free_pa_offset. Verify that enough contiguous pages
-- * are available and that they are all free.
-- */
-- num_pages = (size_t)1 << order;
--
-- if (epma_dev->num_free_pages < num_pages)
-- dev_err(epma_dev->dev, "not enough free pages\n");
--
-- if (epma_dev->free_pa_offset + num_pages > epma_dev->rmem_size) {
-- dev_err(epma_dev->dev, "not enough contiguous pages\n");
-- return NULL;
-- }
--
-- for (i = 0; i < num_pages; i++)
-- if (epma_dev->alloc_pages[epma_dev->free_pa_offset + i])
-- break;
--
-- if (i < num_pages) {
-- dev_err(epma_dev->dev, "free pages are not contiguous\n");
-- return NULL;
-- }
--
-- /* Memory allocation is successful. Mark pages as allocated.
-- * Update the free_pa_offset if free pages are still available:
-- * increment the free_pa_offset accordingly, and then making sure
-- * that it points at the next free page, potentially wrapping over
-- * the end of the memory region.
-- */
-- pma = devm_kzalloc(epma_dev->dev, sizeof(*pma), GFP_KERNEL);
-- if (!pma)
-- return NULL;
--
-- pma->pa = epma_dev->rmem_base + (epma_dev->free_pa_offset << PAGE_SHIFT);
-- pma->order = order;
--
-- for (i = 0; i < num_pages; i++)
-- epma_dev->alloc_pages[epma_dev->free_pa_offset + i] = true;
--
-- epma_dev->num_free_pages -= num_pages;
--
-- if (epma_dev->num_free_pages) {
-- epma_dev->free_pa_offset += num_pages;
-- i = 0;
-- while (epma_dev->alloc_pages[epma_dev->free_pa_offset + i]) {
-- epma_dev->free_pa_offset++;
-- if (epma_dev->free_pa_offset > epma_dev->rmem_size)
-- epma_dev->free_pa_offset = 0;
-- }
-- }
--
-- return pma;
--}
--
--static phys_addr_t simple_pma_get_phys_addr(
-- struct protected_memory_allocator_device *pma_dev,
-- struct protected_memory_allocation *pma)
--{
-- struct simple_pma_device *const epma_dev =
-- container_of(pma_dev, struct simple_pma_device, pma_dev);
--
-- dev_dbg(epma_dev->dev, "%s(pma_dev=%px, pma=%px, pa=%llx\n",
-- __func__, (void *)pma_dev, (void *)pma, pma->pa);
--
-- return pma->pa;
--}
--
--static void simple_pma_free_page(
-- struct protected_memory_allocator_device *pma_dev,
-- struct protected_memory_allocation *pma)
--{
-- struct simple_pma_device *const epma_dev =
-- container_of(pma_dev, struct simple_pma_device, pma_dev);
-- size_t num_pages;
-- size_t offset;
-- size_t i;
--
-- dev_dbg(epma_dev->dev, "%s(pma_dev=%px, pma=%px, pa=%llx\n",
-- __func__, (void *)pma_dev, (void *)pma, pma->pa);
--
-- /* This is an example function that follows an extremely simple logic
-- * and is vulnerable to abuse. For instance, double frees won't be
-- * detected.
-- *
-- * If memory is full, must update the free_pa_offset that is currently
-- * pointing at an allocated page.
-- *
-- * Increase the number of free pages and mark them as free.
-- */
-- offset = (pma->pa - epma_dev->rmem_base) >> PAGE_SHIFT;
-- num_pages = (size_t)1 << pma->order;
--
-- if (epma_dev->num_free_pages == 0)
-- epma_dev->free_pa_offset = offset;
--
-- epma_dev->num_free_pages += num_pages;
-- for (i = 0; i < num_pages; i++)
-- epma_dev->alloc_pages[offset + i] = false;
--
-- devm_kfree(epma_dev->dev, pma);
--}
--
--static int protected_memory_allocator_probe(struct platform_device *pdev)
--{
-- struct simple_pma_device *epma_dev;
-- struct device_node *np;
-- phys_addr_t rmem_base;
-- size_t rmem_size;
--#if (KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE)
-- struct reserved_mem *rmem;
--#endif
--
-- np = pdev->dev.of_node;
--
-- if (!np) {
-- dev_err(&pdev->dev, "device node pointer not set\n");
-- return -ENODEV;
-- }
--
-- np = of_parse_phandle(np, "memory-region", 0);
-- if (!np) {
-- dev_err(&pdev->dev, "memory-region node not set\n");
-- return -ENODEV;
-- }
--
--#if (KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE)
-- rmem = of_reserved_mem_lookup(np);
-- if (rmem) {
-- rmem_base = rmem->base;
-- rmem_size = rmem->size >> PAGE_SHIFT;
-- } else
--#endif
-- {
-- of_node_put(np);
-- dev_err(&pdev->dev, "could not read reserved memory-region\n");
-- return -ENODEV;
-- }
--
-- of_node_put(np);
-- epma_dev = devm_kzalloc(&pdev->dev, sizeof(*epma_dev), GFP_KERNEL);
-- if (!epma_dev)
-- return -ENOMEM;
--
-- epma_dev->pma_dev.ops.pma_alloc_page = simple_pma_alloc_page;
-- epma_dev->pma_dev.ops.pma_get_phys_addr = simple_pma_get_phys_addr;
-- epma_dev->pma_dev.ops.pma_free_page = simple_pma_free_page;
-- epma_dev->pma_dev.owner = THIS_MODULE;
-- epma_dev->dev = &pdev->dev;
-- epma_dev->rmem_base = rmem_base;
-- epma_dev->rmem_size = rmem_size;
-- epma_dev->free_pa_offset = 0;
-- epma_dev->num_free_pages = rmem_size;
--
-- epma_dev->alloc_pages = devm_kzalloc(&pdev->dev,
-- sizeof(bool) * epma_dev->rmem_size, GFP_KERNEL);
--
-- if (!epma_dev->alloc_pages) {
-- dev_err(&pdev->dev, "failed to allocate resources\n");
-- devm_kfree(&pdev->dev, epma_dev);
-- return -ENOMEM;
-- }
--
-- platform_set_drvdata(pdev, &epma_dev->pma_dev);
-- dev_info(&pdev->dev,
-- "Protected memory allocator probed successfully\n");
-- dev_info(&pdev->dev, "Protected memory region: base=%llx num pages=%zu\n",
-- rmem_base, rmem_size);
--
-- return 0;
--}
--
--static int protected_memory_allocator_remove(struct platform_device *pdev)
--{
-- struct protected_memory_allocator_device *pma_dev =
-- platform_get_drvdata(pdev);
-- struct simple_pma_device *epma_dev;
-- struct device *dev;
--
-- if (!pma_dev)
-- return -EINVAL;
--
-- epma_dev = container_of(pma_dev, struct simple_pma_device, pma_dev);
-- dev = epma_dev->dev;
--
-- if (epma_dev->num_free_pages < epma_dev->rmem_size) {
-- dev_warn(&pdev->dev, "Leaking %zu pages of protected memory\n",
-- epma_dev->rmem_size - epma_dev->num_free_pages);
-- }
--
-- platform_set_drvdata(pdev, NULL);
-- devm_kfree(dev, epma_dev->alloc_pages);
-- devm_kfree(dev, epma_dev);
--
-- dev_info(&pdev->dev,
-- "Protected memory allocator removed successfully\n");
--
-- return 0;
--}
--
--static const struct of_device_id protected_memory_allocator_dt_ids[] = {
-- { .compatible = "arm,protected-memory-allocator" },
-- { /* sentinel */ }
--};
--MODULE_DEVICE_TABLE(of, protected_memory_allocator_dt_ids);
--
--static struct platform_driver protected_memory_allocator_driver = {
-- .probe = protected_memory_allocator_probe,
-- .remove = protected_memory_allocator_remove,
-- .driver = {
-- .name = "simple_protected_memory_allocator",
-- .owner = THIS_MODULE,
-- .of_match_table = of_match_ptr(protected_memory_allocator_dt_ids),
-- }
--};
--
--module_platform_driver(protected_memory_allocator_driver);
--
--MODULE_LICENSE("GPL");
--MODULE_AUTHOR("ARM Ltd.");
--MODULE_VERSION("1.0");
-diff --git a/dvalin/kernel/drivers/gpu/arm/Kbuild b/dvalin/kernel/drivers/gpu/arm/Kbuild
-index 1a6fa3c..52ea5fb 100644
---- a/dvalin/kernel/drivers/gpu/arm/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,9 +16,6 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
--#
--
-
- obj-$(CONFIG_MALI_MIDGARD) += midgard/
-diff --git a/dvalin/kernel/drivers/gpu/arm/Kconfig b/dvalin/kernel/drivers/gpu/arm/Kconfig
-index 693b86f..2da8c98 100644
---- a/dvalin/kernel/drivers/gpu/arm/Kconfig
-+++ b/dvalin/kernel/drivers/gpu/arm/Kconfig
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012, 2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,10 +16,7 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
--#
--
-
- menu "ARM GPU Configuration"
- source "drivers/gpu/arm/midgard/Kconfig"
-diff --git a/dvalin/kernel/drivers/base/protected_memory_allocator/Kbuild b/dvalin/kernel/drivers/gpu/arm/Makefile
-similarity index 77%
-rename from dvalin/kernel/drivers/base/protected_memory_allocator/Kbuild
-rename to dvalin/kernel/drivers/gpu/arm/Makefile
-index 241aeb9..ea9ecc7 100644
---- a/dvalin/kernel/drivers/base/protected_memory_allocator/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/Makefile
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,8 +16,6 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
--obj-$(CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR) := protected_memory_allocator.o
-\ No newline at end of file
-+include midgard/Makefile
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/Kbuild
-index fa52548..d3c4ee1 100755
---- a/dvalin/kernel/drivers/gpu/arm/midgard/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012-2020 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,202 +16,240 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
-+
-+# make $(src) as absolute path if it is not already, by prefixing $(srctree)
-+# This is to prevent any build issue due to wrong path.
-+src:=$(if $(patsubst /%,,$(src)),$(srctree)/$(src),$(src))
-+
- #
-+# Prevent misuse when Kernel configurations are not present by default
-+# in out-of-tree builds
-+#
-+ifneq ($(CONFIG_ANDROID),n)
-+ifeq ($(CONFIG_GPU_TRACEPOINTS),n)
-+ $(error CONFIG_GPU_TRACEPOINTS must be set in Kernel configuration)
-+endif
-+endif
-
-+ifeq ($(CONFIG_DMA_SHARED_BUFFER),n)
-+ $(error CONFIG_DMA_SHARED_BUFFER must be set in Kernel configuration)
-+endif
-
--# Driver version string which is returned to userspace via an ioctl
--MALI_RELEASE_NAME ?= "r25p0-01rel0"
-+ifeq ($(CONFIG_PM_DEVFREQ),n)
-+ $(error CONFIG_PM_DEVFREQ must be set in Kernel configuration)
-+endif
-
--# Paths required for build
--# make $(src) as absolute path if it isn't already, by prefixing $(srctree)
--src:=$(if $(patsubst /%,,$(src)),$(srctree)/$(src),$(src))
--KBASE_PATH = $(src)
--KBASE_PLATFORM_PATH = $(KBASE_PATH)/platform_dummy
--UMP_PATH = $(src)/../../../base
-+ifeq ($(CONFIG_DEVFREQ_THERMAL),n)
-+ $(error CONFIG_DEVFREQ_THERMAL must be set in Kernel configuration)
-+endif
-+
-+ifeq ($(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND),n)
-+ $(error CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND must be set in Kernel configuration)
-+endif
-+
-+ifeq ($(CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS), y)
-+ ifneq ($(CONFIG_DEBUG_FS), y)
-+ $(error CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS depends on CONFIG_DEBUG_FS to be set in Kernel configuration)
-+ endif
-+endif
-+
-+ifeq ($(CONFIG_MALI_FENCE_DEBUG), y)
-+ ifneq ($(CONFIG_SYNC), y)
-+ ifneq ($(CONFIG_SYNC_FILE), y)
-+ $(error CONFIG_MALI_FENCE_DEBUG depends on CONFIG_SYNC || CONFIG_SYNC_FILE to be set in Kernel configuration)
-+ endif
-+ endif
-+endif
-
-+#
-+# Configurations
-+#
-+
-+# Driver version string which is returned to userspace via an ioctl
-+MALI_RELEASE_NAME ?= '"r32p1-01bet0"'
- # Set up defaults if not defined by build system
--MALI_CUSTOMER_RELEASE ?= 1
--MALI_USE_CSF ?= 0
--MALI_UNIT_TEST ?= 0
--MALI_KERNEL_TEST_API ?= 0
-+ifeq ($(CONFIG_MALI_DEBUG), y)
-+ MALI_UNIT_TEST = 1
-+ MALI_CUSTOMER_RELEASE ?= 0
-+else
-+ MALI_UNIT_TEST ?= 0
-+ MALI_CUSTOMER_RELEASE ?= 1
-+endif
- MALI_COVERAGE ?= 0
-+
- CONFIG_MALI_PLATFORM_NAME ?= "devicetree"
-+
-+# Kconfig passes in the name with quotes for in-tree builds - remove them.
-+MALI_PLATFORM_DIR := $(shell echo $(CONFIG_MALI_PLATFORM_NAME))
-+
-+ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
-+ MALI_JIT_PRESSURE_LIMIT_BASE = 0
-+ MALI_USE_CSF = 1
-+else
-+ MALI_JIT_PRESSURE_LIMIT_BASE ?= 1
-+ MALI_USE_CSF ?= 0
-+endif
-+
-+ifneq ($(CONFIG_MALI_KUTF), n)
-+ MALI_KERNEL_TEST_API ?= 1
-+else
-+ MALI_KERNEL_TEST_API ?= 0
-+endif
-+
- # Experimental features (corresponding -D definition should be appended to
--# DEFINES below, e.g. for MALI_EXPERIMENTAL_FEATURE,
-+# ccflags-y below, e.g. for MALI_EXPERIMENTAL_FEATURE,
- # -DMALI_EXPERIMENTAL_FEATURE=$(MALI_EXPERIMENTAL_FEATURE) should be appended)
- #
- # Experimental features must default to disabled, e.g.:
- # MALI_EXPERIMENTAL_FEATURE ?= 0
--MALI_JIT_PRESSURE_LIMIT ?= 0
- MALI_INCREMENTAL_RENDERING ?= 0
-
--# Set up our defines, which will be passed to gcc
--DEFINES = \
-- -DMALI_CUSTOMER_RELEASE=$(MALI_CUSTOMER_RELEASE) \
-- -DMALI_USE_CSF=$(MALI_USE_CSF) \
-- -DMALI_KERNEL_TEST_API=$(MALI_KERNEL_TEST_API) \
-- -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \
-- -DMALI_COVERAGE=$(MALI_COVERAGE) \
-- -DMALI_RELEASE_NAME=\"$(MALI_RELEASE_NAME)\" \
-- -DMALI_JIT_PRESSURE_LIMIT=$(MALI_JIT_PRESSURE_LIMIT) \
-- -DMALI_INCREMENTAL_RENDERING=$(MALI_INCREMENTAL_RENDERING)
-+#
-+# ccflags
-+#
-+ccflags-y = \
-+ -DMALI_CUSTOMER_RELEASE=$(MALI_CUSTOMER_RELEASE) \
-+ -DMALI_USE_CSF=$(MALI_USE_CSF) \
-+ -DMALI_KERNEL_TEST_API=$(MALI_KERNEL_TEST_API) \
-+ -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \
-+ -DMALI_COVERAGE=$(MALI_COVERAGE) \
-+ -DMALI_RELEASE_NAME=$(MALI_RELEASE_NAME) \
-+ -DMALI_JIT_PRESSURE_LIMIT_BASE=$(MALI_JIT_PRESSURE_LIMIT_BASE) \
-+ -DMALI_INCREMENTAL_RENDERING=$(MALI_INCREMENTAL_RENDERING) \
-+ -DMALI_KBASE_BUILD \
-+ -DMALI_PLATFORM_DIR=$(MALI_PLATFORM_DIR)
-+
-
- ifeq ($(KBUILD_EXTMOD),)
- # in-tree
--DEFINES +=-DMALI_KBASE_PLATFORM_PATH=../../$(src)/platform/$(CONFIG_MALI_PLATFORM_NAME)
-+ ccflags-y +=-DMALI_KBASE_PLATFORM_PATH=../../$(src)/platform/$(CONFIG_MALI_PLATFORM_NAME)
- else
- # out-of-tree
--DEFINES +=-DMALI_KBASE_PLATFORM_PATH=$(src)/platform/$(CONFIG_MALI_PLATFORM_NAME)
--endif
--
--DEFINES += -I$(srctree)/drivers/staging/android
--#meson graphics start
--ldflags-y += --strip-debug
--#meson graphics end
--
--DEFINES += -DMALI_KBASE_BUILD
--
--# Use our defines when compiling
--ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(KBASE_PLATFORM_PATH) -I$(UMP_PATH) -I$(srctree)/include/linux
--subdir-ccflags-y += $(DEFINES) -I$(KBASE_PATH) -I$(KBASE_PLATFORM_PATH) -I$(UMP_PATH) -I$(srctree)/include/linux
--
--SRC := \
-- context/mali_kbase_context.c \
-- debug/mali_kbase_debug_ktrace.c \
-- device/mali_kbase_device.c \
-- mali_kbase_cache_policy.c \
-- mali_kbase_mem.c \
-- mali_kbase_mem_pool_group.c \
-- mali_kbase_native_mgm.c \
-- mali_kbase_ctx_sched.c \
-- mali_kbase_jm.c \
-- mali_kbase_gpuprops.c \
-- mali_kbase_pm.c \
-- mali_kbase_config.c \
-- mali_kbase_vinstr.c \
-- mali_kbase_hwcnt.c \
-- mali_kbase_hwcnt_backend_gpu.c \
-- mali_kbase_hwcnt_gpu.c \
-- mali_kbase_hwcnt_legacy.c \
-- mali_kbase_hwcnt_types.c \
-- mali_kbase_hwcnt_virtualizer.c \
-- mali_kbase_softjobs.c \
-- mali_kbase_hw.c \
-- mali_kbase_debug.c \
-- mali_kbase_gpu_memory_debugfs.c \
-- mali_kbase_mem_linux.c \
-- mali_kbase_core_linux.c \
-- mali_kbase_mem_profile_debugfs.c \
-- mmu/mali_kbase_mmu.c \
-- mmu/mali_kbase_mmu_hw_direct.c \
-- mmu/mali_kbase_mmu_mode_lpae.c \
-- mmu/mali_kbase_mmu_mode_aarch64.c \
-- mali_kbase_disjoint_events.c \
-- mali_kbase_debug_mem_view.c \
-- mali_kbase_smc.c \
-- mali_kbase_mem_pool.c \
-- mali_kbase_mem_pool_debugfs.c \
-- mali_kbase_debugfs_helper.c \
-- mali_kbase_strings.c \
-- mali_kbase_as_fault_debugfs.c \
-- mali_kbase_regs_history_debugfs.c \
-- thirdparty/mali_kbase_mmap.c \
-- tl/mali_kbase_timeline.c \
-- tl/mali_kbase_timeline_io.c \
-- tl/mali_kbase_tlstream.c \
-- tl/mali_kbase_tracepoints.c \
-- gpu/mali_kbase_gpu.c
--
--ifeq ($(MALI_USE_CSF),1)
-- SRC += \
-- debug/backend/mali_kbase_debug_ktrace_csf.c \
-- device/backend/mali_kbase_device_csf.c \
-- gpu/backend/mali_kbase_gpu_fault_csf.c \
-- tl/backend/mali_kbase_timeline_csf.c \
-- mmu/backend/mali_kbase_mmu_csf.c \
-- context/backend/mali_kbase_context_csf.c
--else
-- SRC += \
-- mali_kbase_dummy_job_wa.c \
-- mali_kbase_debug_job_fault.c \
-- mali_kbase_event.c \
-- mali_kbase_jd.c \
-- mali_kbase_jd_debugfs.c \
-- mali_kbase_js.c \
-- mali_kbase_js_ctx_attr.c \
-- debug/backend/mali_kbase_debug_ktrace_jm.c \
-- device/backend/mali_kbase_device_jm.c \
-- gpu/backend/mali_kbase_gpu_fault_jm.c \
-- tl/backend/mali_kbase_timeline_jm.c \
-- mmu/backend/mali_kbase_mmu_jm.c \
-- context/backend/mali_kbase_context_jm.c
-+ ccflags-y +=-DMALI_KBASE_PLATFORM_PATH=$(src)/platform/$(CONFIG_MALI_PLATFORM_NAME)
- endif
-
--ifeq ($(CONFIG_MALI_CINSTR_GWT),y)
-- SRC += mali_kbase_gwt.c
--endif
-+ccflags-y += \
-+ -I$(srctree)/include/linux \
-+ -I$(srctree)/drivers/staging/android \
-+ -I$(src) \
-+ -I$(src)/platform/$(MALI_PLATFORM_DIR) \
-+ -I$(src)/../../../base \
-+ -I$(src)/../../../../include
-
--ifeq ($(MALI_UNIT_TEST),1)
-- SRC += tl/mali_kbase_timeline_test.c
--endif
-+subdir-ccflags-y += $(ccflags-y)
-
--ifeq ($(MALI_CUSTOMER_RELEASE),0)
-- SRC += mali_kbase_regs_dump_debugfs.c
--endif
-+#
-+# Kernel Modules
-+#
-+obj-$(CONFIG_MALI_MIDGARD) += mali_kbase.o
-+obj-$(CONFIG_MALI_ARBITRATION) += arbitration/
-+obj-$(CONFIG_MALI_KUTF) += tests/
-+
-+mali_kbase-y := \
-+ mali_kbase_cache_policy.o \
-+ mali_kbase_ccswe.o \
-+ mali_kbase_mem.o \
-+ mali_kbase_mem_pool_group.o \
-+ mali_kbase_native_mgm.o \
-+ mali_kbase_ctx_sched.o \
-+ mali_kbase_gpuprops.o \
-+ mali_kbase_pm.o \
-+ mali_kbase_config.o \
-+ mali_kbase_vinstr.o \
-+ mali_kbase_hwcnt.o \
-+ mali_kbase_hwcnt_gpu.o \
-+ mali_kbase_hwcnt_legacy.o \
-+ mali_kbase_hwcnt_types.o \
-+ mali_kbase_hwcnt_virtualizer.o \
-+ mali_kbase_softjobs.o \
-+ mali_kbase_hw.o \
-+ mali_kbase_debug.o \
-+ mali_kbase_gpu_memory_debugfs.o \
-+ mali_kbase_mem_linux.o \
-+ mali_kbase_core_linux.o \
-+ mali_kbase_mem_profile_debugfs.o \
-+ mali_kbase_disjoint_events.o \
-+ mali_kbase_debug_mem_view.o \
-+ mali_kbase_smc.o \
-+ mali_kbase_mem_pool.o \
-+ mali_kbase_mem_pool_debugfs.o \
-+ mali_kbase_debugfs_helper.o \
-+ mali_kbase_strings.o \
-+ mali_kbase_as_fault_debugfs.o \
-+ mali_kbase_regs_history_debugfs.o \
-+ mali_kbase_dvfs_debugfs.o \
-+ mali_power_gpu_frequency_trace.o \
-+ mali_kbase_trace_gpu_mem.o
-+
-+mali_kbase-$(CONFIG_MALI_CINSTR_GWT) += mali_kbase_gwt.o
-
-+mali_kbase-$(CONFIG_SYNC) += \
-+ mali_kbase_sync_android.o \
-+ mali_kbase_sync_common.o
-
--ccflags-y += -I$(KBASE_PATH) -I$(KBASE_PATH)/debug \
-- -I$(KBASE_PATH)/debug/backend
-+mali_kbase-$(CONFIG_SYNC_FILE) += \
-+ mali_kbase_fence_ops.o \
-+ mali_kbase_sync_file.o \
-+ mali_kbase_sync_common.o
-+
-+ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
-+ mali_kbase-y += \
-+ mali_kbase_hwcnt_backend_csf.o \
-+ mali_kbase_hwcnt_backend_csf_if_fw.o
-+else
-+ mali_kbase-y += \
-+ mali_kbase_jm.o \
-+ mali_kbase_hwcnt_backend_jm.o \
-+ mali_kbase_dummy_job_wa.o \
-+ mali_kbase_debug_job_fault.o \
-+ mali_kbase_event.o \
-+ mali_kbase_jd.o \
-+ mali_kbase_jd_debugfs.o \
-+ mali_kbase_js.o \
-+ mali_kbase_js_ctx_attr.o \
-+ mali_kbase_kinstr_jm.o
-+
-+ mali_kbase-$(CONFIG_MALI_DMA_FENCE) += \
-+ mali_kbase_fence_ops.o \
-+ mali_kbase_dma_fence.o \
-+ mali_kbase_fence.o
-+
-+ mali_kbase-$(CONFIG_SYNC_FILE) += \
-+ mali_kbase_fence_ops.o \
-+ mali_kbase_fence.o
-+endif
-
--# Tell the Linux build system from which .o file to create the kernel module
--obj-$(CONFIG_MALI_MIDGARD) += mali_kbase.o
-
--# Tell the Linux build system to enable building of our .c files
--mali_kbase-y := $(SRC:.c=.o)
-+INCLUDE_SUBDIR = \
-+ $(src)/context/Kbuild \
-+ $(src)/debug/Kbuild \
-+ $(src)/device/Kbuild \
-+ $(src)/backend/gpu/Kbuild \
-+ $(src)/mmu/Kbuild \
-+ $(src)/tl/Kbuild \
-+ $(src)/gpu/Kbuild \
-+ $(src)/thirdparty/Kbuild \
-+ $(src)/platform/$(MALI_PLATFORM_DIR)/Kbuild
-
--# Kconfig passes in the name with quotes for in-tree builds - remove them.
--platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_NAME))
--MALI_PLATFORM_DIR := platform/$(platform_name)
--ccflags-y += -I$(src)/$(MALI_PLATFORM_DIR)
--include $(src)/$(MALI_PLATFORM_DIR)/Kbuild
-+ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
-+ INCLUDE_SUBDIR += $(src)/csf/Kbuild
-+endif
-
--ifeq ($(CONFIG_MALI_DEVFREQ),y)
-- ifeq ($(CONFIG_DEVFREQ_THERMAL),y)
-- include $(src)/ipa/Kbuild
-- endif
-+ifeq ($(CONFIG_MALI_ARBITER_SUPPORT),y)
-+ INCLUDE_SUBDIR += $(src)/arbiter/Kbuild
- endif
-
--ifeq ($(MALI_USE_CSF),1)
-- include $(src)/csf/Kbuild
--else
--# empty
-+ifeq ($(CONFIG_MALI_DEVFREQ),y)
-+ ifeq ($(CONFIG_DEVFREQ_THERMAL),y)
-+ INCLUDE_SUBDIR += $(src)/ipa/Kbuild
-+ endif
- endif
-
--ifeq ($(CONFIG_MALI_ARBITER_SUPPORT),y)
-- include $(src)/arbiter/Kbuild
-+ifeq ($(KBUILD_EXTMOD),)
-+# in-tree
-+ -include $(INCLUDE_SUBDIR)
- else
--# empty
-+# out-of-tree
-+ include $(INCLUDE_SUBDIR)
- endif
--
--mali_kbase-$(CONFIG_MALI_DMA_FENCE) += \
-- mali_kbase_dma_fence.o \
-- mali_kbase_fence.o
--mali_kbase-$(CONFIG_SYNC) += \
-- mali_kbase_sync_android.o \
-- mali_kbase_sync_common.o
--mali_kbase-$(CONFIG_SYNC_FILE) += \
-- mali_kbase_sync_file.o \
-- mali_kbase_sync_common.o \
-- mali_kbase_fence.o
--
--include $(src)/backend/gpu/Kbuild
--mali_kbase-y += $(BACKEND:.c=.o)
--
--
--ccflags-y += -I$(src)/backend/gpu
--subdir-ccflags-y += -I$(src)/backend/gpu
--
--# For kutf and mali_kutf_irq_latency_test
--obj-$(CONFIG_MALI_KUTF) += tests/
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/Kconfig b/dvalin/kernel/drivers/gpu/arm/midgard/Kconfig
-index ca59dbb..5541383 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/Kconfig
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/Kconfig
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012-2020 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,15 +16,14 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
--#
--
-
- menuconfig MALI_MIDGARD
- tristate "Mali Midgard series support"
- select GPU_TRACEPOINTS if ANDROID
- select DMA_SHARED_BUFFER
-+ select PM_DEVFREQ
-+ select DEVFREQ_THERMAL
- default n
- help
- Enable this option to build support for a ARM Mali Midgard GPU.
-@@ -31,13 +31,43 @@ menuconfig MALI_MIDGARD
- To compile this driver as a module, choose M here:
- this will generate a single module, called mali_kbase.
-
--config MALI_GATOR_SUPPORT
-- bool "Enable Streamline tracing support"
-+if MALI_MIDGARD
-+
-+config MALI_PLATFORM_NAME
- depends on MALI_MIDGARD
-+ string "Platform name"
-+ default "devicetree"
-+ help
-+ Enter the name of the desired platform configuration directory to
-+ include in the build. 'platform/$(MALI_PLATFORM_NAME)/Makefile' must
-+ exist.
-+
-+config MALI_REAL_HW
-+ depends on MALI_MIDGARD
-+ def_bool !MALI_NO_MALI
-+
-+menu "Platform specific options"
-+source "drivers/gpu/arm/midgard/platform/Kconfig"
-+endmenu
-+
-+config MALI_CSF_SUPPORT
-+ bool "Enable Mali CSF based GPU support"
-+ depends on MALI_MIDGARD=m
-+ default n
-+ help
-+ Enables support for CSF based GPUs.
-+
-+config MALI_DEVFREQ
-+ bool "Enable devfreq support for Mali"
-+ depends on MALI_MIDGARD && PM_DEVFREQ
-+ select DEVFREQ_GOV_SIMPLE_ONDEMAND
- default y
- help
-- Enables kbase tracing used by the Arm Streamline Performance Analyzer.
-- The tracepoints are used to derive GPU activity charts in Streamline.
-+ Support devfreq for Mali.
-+
-+ Using the devfreq framework and, by default, the simple on-demand
-+ governor, the frequency of Mali will be dynamically selected from the
-+ available OPPs.
-
- config MALI_MIDGARD_DVFS
- bool "Enable legacy DVFS"
-@@ -46,28 +76,25 @@ config MALI_MIDGARD_DVFS
- help
- Choose this option to enable legacy DVFS in the Mali Midgard DDK.
-
-+config MALI_GATOR_SUPPORT
-+ bool "Enable Streamline tracing support"
-+ depends on MALI_MIDGARD
-+ default y
-+ help
-+ Enables kbase tracing used by the Arm Streamline Performance Analyzer.
-+ The tracepoints are used to derive GPU activity charts in Streamline.
-+
- config MALI_MIDGARD_ENABLE_TRACE
- bool "Enable kbase tracing"
- depends on MALI_MIDGARD
- default y if MALI_DEBUG
- default n
- help
-- Enables tracing in kbase. Trace log available through
-+ Enables tracing in kbase. Trace log available through
- the "mali_trace" debugfs file, when the CONFIG_DEBUG_FS is enabled
-
--config MALI_DEVFREQ
-- bool "devfreq support for Mali"
-- depends on MALI_MIDGARD && PM_DEVFREQ
-- default y
-- help
-- Support devfreq for Mali.
--
-- Using the devfreq framework and, by default, the simpleondemand
-- governor, the frequency of Mali will be dynamically selected from the
-- available OPPs.
--
- config MALI_DMA_FENCE
-- bool "DMA_BUF fence support for Mali"
-+ bool "Enable DMA_BUF fence support for Mali"
- depends on MALI_MIDGARD
- default n
- help
-@@ -76,18 +103,9 @@ config MALI_DMA_FENCE
- This option should only be enabled if the Linux Kernel has built in
- support for DMA_BUF fences.
-
--config MALI_PLATFORM_NAME
-- depends on MALI_MIDGARD
-- string "Platform name"
-- default "devicetree"
-- help
-- Enter the name of the desired platform configuration directory to
-- include in the build. 'platform/$(MALI_PLATFORM_NAME)/Kbuild' must
-- exist.
--
- config MALI_ARBITER_SUPPORT
- bool "Enable arbiter support for Mali"
-- depends on MALI_MIDGARD
-+ depends on MALI_MIDGARD && !MALI_CSF_SUPPORT
- default n
- help
- Enable support for the arbiter interface in the driver.
-@@ -96,18 +114,64 @@ config MALI_ARBITER_SUPPORT
-
- If unsure, say N.
-
--# MALI_EXPERT configuration options
-+config MALI_DMA_BUF_MAP_ON_DEMAND
-+ bool "Enable map imported dma-bufs on demand"
-+ depends on MALI_MIDGARD
-+ default n
-+ help
-+ This option caused kbase to set up the GPU mapping of imported
-+ dma-buf when needed to run atoms. This is the legacy behavior.
-+
-+ This is intended for testing and the option will get removed in the
-+ future.
-+
-+config MALI_DMA_BUF_LEGACY_COMPAT
-+ bool "Enable legacy compatibility cache flush on dma-buf map"
-+ depends on MALI_MIDGARD && !MALI_DMA_BUF_MAP_ON_DEMAND
-+ default n
-+ help
-+ This option enables compatibility with legacy dma-buf mapping
-+ behavior, then the dma-buf is mapped on import, by adding cache
-+ maintenance where MALI_DMA_BUF_MAP_ON_DEMAND would do the mapping,
-+ including a cache flush.
-+
-+ This option might work-around issues related to missing cache
-+ flushes in other drivers. This only has an effect for clients using
-+ UK 11.18 or older. For later UK versions it is not possible.
-
- menuconfig MALI_EXPERT
- depends on MALI_MIDGARD
- bool "Enable Expert Settings"
- default n
- help
-- Enabling this option and modifying the default settings may produce a driver with performance or
-- other limitations.
-+ Enabling this option and modifying the default settings may produce
-+ a driver with performance or other limitations.
-+
-+if MALI_EXPERT
-+
-+config MALI_2MB_ALLOC
-+ bool "Attempt to allocate 2MB pages"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-+ default n
-+ help
-+ Rather than allocating all GPU memory page-by-page, attempt to
-+ allocate 2MB pages from the kernel. This reduces TLB pressure and
-+ helps to prevent memory fragmentation.
-+
-+ If in doubt, say N
-+
-+config MALI_MEMORY_FULLY_BACKED
-+ bool "Enable memory fully physically-backed"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-+ default n
-+ help
-+ This option enables full physical backing of all virtual
-+ memory allocations in the kernel. Notice that this build
-+ option only affects allocations of grow-on-GPU-page-fault
-+ memory.
-
- config MALI_CORESTACK
-- bool "Support controlling power to the GPU core stack"
-+ bool "Enable support of GPU core stack power control"
- depends on MALI_MIDGARD && MALI_EXPERT
- default n
- help
-@@ -119,15 +183,48 @@ config MALI_CORESTACK
-
- If unsure, say N.
-
-+comment "Platform options"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-+
-+config MALI_NO_MALI
-+ bool "Enable No Mali"
-+ depends on MALI_MIDGARD && 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 "Enable No Mali error injection"
-+ depends on MALI_MIDGARD && MALI_EXPERT && MALI_NO_MALI
-+ default n
-+ help
-+ Enables insertion of errors to test module failure and recovery mechanisms.
-+
-+config MALI_GEM5_BUILD
-+ bool "Enable build of Mali kernel driver for GEM5"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-+ default n
-+ help
-+ This option is to do a Mali GEM5 build.
-+ If unsure, say N.
-+
-+comment "Debug options"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-+
- config MALI_DEBUG
-- bool "Debug build"
-+ bool "Enable debug build"
- depends on MALI_MIDGARD && MALI_EXPERT
- default n
- help
- Select this option for increased checking and reporting of errors.
-
- config MALI_FENCE_DEBUG
-- bool "Debug sync fence usage"
-+ bool "Enable debug sync fence usage"
- depends on MALI_MIDGARD && MALI_EXPERT && (SYNC || SYNC_FILE)
- default y if MALI_DEBUG
- help
-@@ -143,28 +240,6 @@ config MALI_FENCE_DEBUG
- The timeout can be changed at runtime through the js_soft_timeout
- device attribute, where the timeout is specified in milliseconds.
-
--config MALI_NO_MALI
-- bool "No Mali"
-- depends on MALI_MIDGARD && 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_REAL_HW
-- def_bool !MALI_NO_MALI
--
--config MALI_ERROR_INJECT
-- bool "Error injection"
-- depends on MALI_MIDGARD && MALI_EXPERT && MALI_NO_MALI
-- default n
-- help
-- Enables insertion of errors to test module failure and recovery mechanisms.
--
- config MALI_SYSTEM_TRACE
- bool "Enable system event tracing support"
- depends on MALI_MIDGARD && MALI_EXPERT
-@@ -176,63 +251,93 @@ config MALI_SYSTEM_TRACE
- minimal overhead when not in use. Enable only if you know what
- you are doing.
-
--config MALI_2MB_ALLOC
-- bool "Attempt to allocate 2MB pages"
-+comment "Instrumentation options"
- depends on MALI_MIDGARD && MALI_EXPERT
-- default n
-- help
-- Rather than allocating all GPU memory page-by-page, attempt to
-- allocate 2MB pages from the kernel. This reduces TLB pressure and
-- helps to prevent memory fragmentation.
-
-- If in doubt, say N
-+choice
-+ prompt "Select Performance counters set"
-+ default MALI_PRFCNT_SET_PRIMARY
-+ depends on MALI_MIDGARD && MALI_EXPERT
-
--config MALI_PWRSOFT_765
-- bool "PWRSOFT-765 ticket"
-+config MALI_PRFCNT_SET_PRIMARY
-+ bool "Primary"
- depends on MALI_MIDGARD && MALI_EXPERT
-- default n
- help
-- PWRSOFT-765 fixes devfreq cooling devices issues. The fix was merged
-- in kernel v4.10, however if backported into the kernel then this
-- option must be manually selected.
-+ Select this option to use primary set of performance counters.
-
-- If using kernel >= v4.10 then say N, otherwise if devfreq cooling
-- changes have been backported say Y to avoid compilation errors.
-+config MALI_PRFCNT_SET_SECONDARY
-+ bool "Secondary"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-+ help
-+ Select this option to use secondary set of performance counters. Kernel
-+ features that depend on an access to the primary set of counters may
-+ become unavailable. Enabling this option will prevent power management
-+ from working optimally and may cause instrumentation tools to return
-+ bogus results.
-
--config MALI_MEMORY_FULLY_BACKED
-- bool "Memory fully physically-backed"
-+ If unsure, use MALI_PRFCNT_SET_PRIMARY.
-+
-+config MALI_PRFCNT_SET_TERTIARY
-+ bool "Tertiary"
- depends on MALI_MIDGARD && MALI_EXPERT
-+ help
-+ Select this option to use tertiary set of performance counters. Kernel
-+ features that depend on an access to the primary set of counters may
-+ become unavailable. Enabling this option will prevent power management
-+ from working optimally and may cause instrumentation tools to return
-+ bogus results.
-+
-+ If unsure, use MALI_PRFCNT_SET_PRIMARY.
-+
-+endchoice
-+
-+config MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
-+ bool "Enable runtime selection of performance counters set via debugfs"
-+ depends on MALI_MIDGARD && MALI_EXPERT && DEBUG_FS
- default n
- help
-- This option enables full physical backing of all virtual
-- memory allocations in the kernel. Notice that this build
-- option only affects allocations of grow-on-GPU-page-fault
-- memory.
-+ Select this option to make the secondary set of performance counters
-+ available at runtime via debugfs. Kernel features that depend on an
-+ access to the primary set of counters may become unavailable.
-
--config MALI_DMA_BUF_MAP_ON_DEMAND
-- bool "Map imported dma-bufs on demand"
-- depends on MALI_MIDGARD
-+ If no runtime debugfs option is set, the build time counter set
-+ choice will be used.
-+
-+ This feature is unsupported and unstable, and may break at any time.
-+ Enabling this option will prevent power management from working
-+ optimally and may cause instrumentation tools to return bogus results.
-+
-+ No validation is done on the debugfs input. Invalid input could cause
-+ performance counter errors. Valid inputs are the values accepted by
-+ the SET_SELECT bits of the PRFCNT_CONFIG register as defined in the
-+ architecture specification.
-+
-+ If unsure, say N.
-+
-+config MALI_JOB_DUMP
-+ bool "Enable system level support needed for job dumping"
-+ depends on MALI_MIDGARD && MALI_EXPERT
- default n
- help
-- This option caused kbase to set up the GPU mapping of imported
-- dma-buf when needed to run atoms. This is the legacy behaviour.
-+ Choose this option to enable system level support needed for
-+ job dumping. This is typically used for instrumentation but has
-+ minimal overhead when not in use. Enable only if you know what
-+ you are doing.
-
-- This is intended for testing and the option will get removed in the
-- future.
-+comment "Workarounds"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-
--config MALI_DMA_BUF_LEGACY_COMPAT
-- bool "Enable legacy compatibility cache flush on dma-buf map"
-- depends on MALI_MIDGARD && !MALI_DMA_BUF_MAP_ON_DEMAND
-+config MALI_PWRSOFT_765
-+ bool "Enable workaround for PWRSOFT-765"
-+ depends on MALI_MIDGARD && MALI_EXPERT
- default n
- help
-- This option enables compatibility with legacy dma-buf mapping
-- behavior, then the dma-buf is mapped on import, by adding cache
-- maintenance where MALI_DMA_BUF_MAP_ON_DEMAND would do the mapping,
-- including a cache flush.
-+ PWRSOFT-765 fixes devfreq cooling devices issues. The fix was merged
-+ in kernel v4.10, however if backported into the kernel then this
-+ option must be manually selected.
-
-- This option might work-around issues related to missing cache
-- flushes in other drivers. This only has an effect for clients using
-- UK 11.18 or older. For later UK versions it is not possible.
-+ If using kernel >= v4.10 then say N, otherwise if devfreq cooling
-+ changes have been backported say Y to avoid compilation errors.
-
- config MALI_HW_ERRATA_1485982_NOT_AFFECTED
- bool "Disable workaround for BASE_HW_ISSUE_GPU2017_1336"
-@@ -252,58 +357,22 @@ config MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE
- default n
- help
- This option uses an alternative workaround for GPU2017-1336. Lowering
-- the GPU clock to a, platform specific, known good frequeuncy before
-+ the GPU clock to a, platform specific, known good frequency before
- powering down the L2 cache. The clock can be specified in the device
- tree using the property, opp-mali-errata-1485982. Otherwise the
- slowest clock will be selected.
-
--config MALI_GEM5_BUILD
-- bool "Enable build of Mali kernel driver for GEM5"
-- depends on MALI_MIDGARD
-- default n
-- help
-- This option is to do a Mali GEM5 build.
-- If unsure, say N.
--
--# Instrumentation options.
-+endif
-
--config MALI_JOB_DUMP
-- bool "Enable system level support needed for job dumping"
-- depends on MALI_MIDGARD && MALI_EXPERT
-- default n
-- help
-- Choose this option to enable system level support needed for
-- job dumping. This is typically used for instrumentation but has
-- minimal overhead when not in use. Enable only if you know what
-- you are doing.
--
--config MALI_PRFCNT_SET_SECONDARY
-- bool "Use secondary set of performance counters"
-- depends on MALI_MIDGARD && MALI_EXPERT
-- default n
-- help
-- Select this option to use secondary set of performance counters. Kernel
-- features that depend on an access to the primary set of counters may
-- become unavailable. Enabling this option will prevent power management
-- from working optimally and may cause instrumentation tools to return
-- bogus results.
--
-- If unsure, say N.
--
--config MALI_PRFCNT_SET_SECONDARY_VIA_DEBUG_FS
-- bool "Use secondary set of performance counters"
-- depends on MALI_MIDGARD && MALI_EXPERT && !MALI_PRFCNT_SET_SECONDARY && DEBUG_FS
-+config MALI_ARBITRATION
-+ bool "Enable Virtualization reference code"
-+ depends on MALI_MIDGARD
- default n
- help
-- Select this option to make the secondary set of performance counters
-- available at runtime via debugfs. Kernel features that depend on an
-- access to the primary set of counters may become unavailable.
--
-- This feature is unsupported and unstable, and may break at any time.
-- Enabling this option will prevent power management from working
-- optimally and may cause instrumentation tools to return bogus results.
--
-+ Enables the build of several reference modules used in the reference
-+ virtualization setup for Mali
- If unsure, say N.
-
--source "drivers/gpu/arm/midgard/platform/Kconfig"
- source "drivers/gpu/arm/midgard/tests/Kconfig"
-+
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/Makefile b/dvalin/kernel/drivers/gpu/arm/midgard/Makefile
-index 53a1209..4384e80 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/Makefile
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/Makefile
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2010-2019 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2010-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,24 +16,200 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
-+
-+KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
-+KDIR ?= $(KERNEL_SRC)
-+
-+ifeq ($(KDIR),)
-+ $(error Must specify KDIR to point to the kernel to target))
-+endif
-+
-+#
-+# Default configuration values
-+#
-+# Dependency resolution is done through statements as Kconfig
-+# is not supported for out-of-tree builds.
- #
-
-+CONFIG_MALI_MIDGARD ?= m
-+ifeq ($(CONFIG_MALI_MIDGARD),m)
-+ CONFIG_MALI_GATOR_SUPPORT ?= y
-+ CONFIG_MALI_ARBITRATION ?= n
-+ CONFIG_MALI_PARTITION_MANAGER ?= n
-+
-+ ifneq ($(CONFIG_MALI_NO_MALI),y)
-+ # Prevent misuse when CONFIG_MALI_NO_MALI=y
-+ CONFIG_MALI_REAL_HW ?= y
-+ endif
-+
-+ ifeq ($(CONFIG_MALI_MIDGARD_DVFS),y)
-+ # Prevent misuse when CONFIG_MALI_MIDGARD_DVFS=y
-+ CONFIG_MALI_DEVFREQ ?= n
-+ else
-+ CONFIG_MALI_DEVFREQ ?= y
-+ endif
-+
-+ ifeq ($(CONFIG_MALI_DMA_BUF_MAP_ON_DEMAND), y)
-+ # Prevent misuse when CONFIG_MALI_DMA_BUF_MAP_ON_DEMAND=y
-+ CONFIG_MALI_DMA_BUF_LEGACY_COMPAT = n
-+ endif
-+
-+ ifeq ($(CONFIG_BSP_HAS_HYPERVISOR),y)
-+ ifneq ($(CONFIG_MALI_ARBITRATION), n)
-+ CONFIG_MALI_XEN ?= m
-+ endif
-+ endif
-+
-+ #
-+ # Expert/Debug/Test released configurations
-+ #
-+ ifeq ($(CONFIG_MALI_EXPERT), y)
-+ ifeq ($(CONFIG_MALI_NO_MALI), y)
-+ CONFIG_MALI_REAL_HW = n
-+ else
-+ # Prevent misuse when CONFIG_MALI_NO_MALI=n
-+ CONFIG_MALI_REAL_HW = y
-+ CONFIG_MALI_ERROR_INJECT = n
-+ endif
-+
-+ ifeq ($(CONFIG_MALI_HW_ERRATA_1485982_NOT_AFFECTED), y)
-+ # Prevent misuse when CONFIG_MALI_HW_ERRATA_1485982_NOT_AFFECTED=y
-+ CONFIG_MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE = n
-+ endif
-
--KDIR ?= /lib/modules/$(shell uname -r)/build
-+ ifeq ($(CONFIG_MALI_DEBUG), y)
-+ CONFIG_MALI_MIDGARD_ENABLE_TRACE ?= y
-+ CONFIG_MALI_SYSTEM_TRACE ?= y
-
--BUSLOG_PATH_RELATIVE = $(CURDIR)/../../../..
--KBASE_PATH_RELATIVE = $(CURDIR)
-+ ifeq ($(CONFIG_SYNC), y)
-+ CONFIG_MALI_FENCE_DEBUG ?= y
-+ else
-+ ifeq ($(CONFIG_SYNC_FILE), y)
-+ CONFIG_MALI_FENCE_DEBUG ?= y
-+ else
-+ CONFIG_MALI_FENCE_DEBUG = n
-+ endif
-+ endif
-+ else
-+ # Prevent misuse when CONFIG_MALI_DEBUG=n
-+ CONFIG_MALI_MIDGARD_ENABLE_TRACE = n
-+ CONFIG_MALI_SYSTEM_TRACE = n
-+ CONFIG_MALI_FENCE_DEBUG = n
-+ endif
-+ else
-+ # Prevent misuse when CONFIG_MALI_EXPERT=n
-+ CONFIG_MALI_CORESTACK = n
-+ CONFIG_MALI_2MB_ALLOC = n
-+ CONFIG_MALI_PWRSOFT_765 = n
-+ CONFIG_MALI_MEMORY_FULLY_BACKED = n
-+ CONFIG_MALI_JOB_DUMP = n
-+ CONFIG_MALI_NO_MALI = n
-+ CONFIG_MALI_REAL_HW = y
-+ CONFIG_MALI_ERROR_INJECT = n
-+ CONFIG_MALI_HW_ERRATA_1485982_NOT_AFFECTED = n
-+ CONFIG_MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE = n
-+ CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS = n
-+ CONFIG_MALI_DEBUG = n
-+ CONFIG_MALI_MIDGARD_ENABLE_TRACE = n
-+ CONFIG_MALI_SYSTEM_TRACE = n
-+ CONFIG_MALI_FENCE_DEBUG = n
-+ endif
-
--ifeq ($(CONFIG_MALI_BUSLOG),y)
--#Add bus logger symbols
--EXTRA_SYMBOLS += $(BUSLOG_PATH_RELATIVE)/drivers/base/bus_logger/Module.symvers
-+ ifeq ($(CONFIG_MALI_DEBUG), y)
-+ CONFIG_MALI_KUTF ?= y
-+ ifeq ($(CONFIG_MALI_KUTF), y)
-+ CONFIG_MALI_KUTF_IRQ_TEST ?= y
-+ CONFIG_MALI_KUTF_CLK_RATE_TRACE ?= y
-+ else
-+ # Prevent misuse when CONFIG_MALI_KUTF=n
-+ CONFIG_MALI_KUTF_IRQ_TEST = n
-+ CONFIG_MALI_KUTF_CLK_RATE_TRACE = n
-+ endif
-+ else
-+ # Prevent misuse when CONFIG_MALI_DEBUG=n
-+ CONFIG_MALI_KUTF = n
-+ CONFIG_MALI_KUTF_IRQ_TEST = n
-+ CONFIG_MALI_KUTF_CLK_RATE_TRACE = n
-+ endif
-+else
-+ # Prevent misuse when CONFIG_MALI_MIDGARD=n
-+ CONFIG_MALI_ARBITRATION = n
-+ CONFIG_MALI_KUTF = n
-+ CONFIG_MALI_KUTF_IRQ_TEST = n
-+ CONFIG_MALI_KUTF_CLK_RATE_TRACE = n
- endif
-
--# we get the symbols from modules using KBUILD_EXTRA_SYMBOLS to prevent warnings about unknown functions
-+# All Mali CONFIG should be listed here
-+CONFIGS := \
-+ CONFIG_MALI_MIDGARD \
-+ CONFIG_MALI_CSF_SUPPORT \
-+ CONFIG_MALI_GATOR_SUPPORT \
-+ CONFIG_MALI_DMA_FENCE \
-+ CONFIG_MALI_ARBITER_SUPPORT \
-+ CONFIG_MALI_ARBITRATION \
-+ CONFIG_MALI_PARTITION_MANAGER \
-+ CONFIG_MALI_REAL_HW \
-+ CONFIG_MALI_GEM5_BUILD \
-+ CONFIG_MALI_DEVFREQ \
-+ CONFIG_MALI_MIDGARD_DVFS \
-+ CONFIG_MALI_DMA_BUF_MAP_ON_DEMAND \
-+ CONFIG_MALI_DMA_BUF_LEGACY_COMPAT \
-+ CONFIG_MALI_EXPERT \
-+ CONFIG_MALI_CORESTACK \
-+ CONFIG_MALI_2MB_ALLOC \
-+ CONFIG_MALI_PWRSOFT_765 \
-+ CONFIG_MALI_MEMORY_FULLY_BACKED \
-+ CONFIG_MALI_JOB_DUMP \
-+ CONFIG_MALI_NO_MALI \
-+ CONFIG_MALI_ERROR_INJECT \
-+ CONFIG_MALI_HW_ERRATA_1485982_NOT_AFFECTED \
-+ CONFIG_MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE \
-+ CONFIG_MALI_PRFCNT_SET_PRIMARY \
-+ CONFIG_MALI_PRFCNT_SET_SECONDARY \
-+ CONFIG_MALI_PRFCNT_SET_TERTIARY \
-+ CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS \
-+ CONFIG_MALI_DEBUG \
-+ CONFIG_MALI_MIDGARD_ENABLE_TRACE \
-+ CONFIG_MALI_SYSTEM_TRACE \
-+ CONFIG_MALI_FENCE_DEBUG \
-+ CONFIG_MALI_KUTF \
-+ CONFIG_MALI_KUTF_IRQ_TEST \
-+ CONFIG_MALI_KUTF_CLK_RATE_TRACE \
-+ CONFIG_MALI_XEN
-+
-+
-+#
-+# MAKE_ARGS to pass the custom CONFIGs on out-of-tree build
-+#
-+# Generate the list of CONFIGs and values.
-+# $(value config) is the name of the CONFIG option.
-+# $(value $(value config)) is its value (y, m).
-+# When the CONFIG is not set to y or m, it defaults to n.
-+MAKE_ARGS := $(foreach config,$(CONFIGS), \
-+ $(if $(filter y m,$(value $(value config))), \
-+ $(value config)=$(value $(value config)), \
-+ $(value config)=n))
-+
-+#
-+# EXTRA_CFLAGS to define the custom CONFIGs on out-of-tree build
-+#
-+# Generate the list of CONFIGs defines with values from CONFIGS.
-+# $(value config) is the name of the CONFIG option.
-+# When set to y or m, the CONFIG gets defined to 1.
-+EXTRA_CFLAGS := $(foreach config,$(CONFIGS), \
-+ $(if $(filter y m,$(value $(value config))), \
-+ -D$(value config)=1))
-+
-+#
-+# KBUILD_EXTRA_SYMBOLS to prevent warnings about unknown functions
-+#
-+
- all:
-- $(MAKE) -C $(KDIR) M=$(CURDIR) EXTRA_CFLAGS="-I$(CURDIR)/../../../../include -I$(CURDIR)/../../../../tests/include $(SCONS_CFLAGS)" $(SCONS_CONFIGS) KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules
-+ $(MAKE) -C $(KDIR) M=$(CURDIR) $(MAKE_ARGS) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules
-+
-+modules_install:
-+ $(MAKE) -C $(KDIR) M=$(CURDIR) $(MAKE_ARGS) modules_install
-
- clean:
-- $(MAKE) -C $(KDIR) M=$(CURDIR) clean
-+ $(MAKE) -C $(KDIR) M=$(CURDIR) $(MAKE_ARGS) clean
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/Mconfig b/dvalin/kernel/drivers/gpu/arm/midgard/Mconfig
-index b137793..d71a113 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/Mconfig
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/Mconfig
-@@ -1,17 +1,22 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012-2020 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2021 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.
-+# of such GNU license.
- #
--# 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 program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
- #
- #
--
-
- menuconfig MALI_MIDGARD
- bool "Mali Midgard series support"
-@@ -22,13 +27,44 @@ menuconfig MALI_MIDGARD
- To compile this driver as a module, choose M here:
- this will generate a single module, called mali_kbase.
-
--config MALI_GATOR_SUPPORT
-- bool "Enable Streamline tracing support"
-- depends on MALI_MIDGARD && !BACKEND_USER
-+config MALI_PLATFORM_NAME
-+ depends on MALI_MIDGARD
-+ string "Platform name"
-+ default "hisilicon" if PLATFORM_HIKEY960
-+ default "hisilicon" if PLATFORM_HIKEY970
-+ default "devicetree"
-+ help
-+ Enter the name of the desired platform configuration directory to
-+ include in the build. 'platform/$(MALI_PLATFORM_NAME)/Makefile' must
-+ exist.
-+
-+ When PLATFORM_CUSTOM is set, this needs to be set manually to
-+ pick up the desired platform files.
-+
-+config MALI_REAL_HW
-+ bool
-+ depends on MALI_MIDGARD
- default y
-+ default n if NO_MALI
-+
-+config MALI_CSF_SUPPORT
-+ bool "Enable Mali CSF based GPU support"
-+ depends on MALI_MIDGARD
-+ default y if GPU_HAS_CSF
- help
-- Enables kbase tracing used by the Arm Streamline Performance Analyzer.
-- The tracepoints are used to derive GPU activity charts in Streamline.
-+ Enables support for CSF based GPUs.
-+
-+config MALI_DEVFREQ
-+ bool "Enable devfreq support for Mali"
-+ depends on MALI_MIDGARD
-+ default y if PLATFORM_JUNO
-+ default y if PLATFORM_CUSTOM
-+ help
-+ Support devfreq for Mali.
-+
-+ Using the devfreq framework and, by default, the simple on-demand
-+ governor, the frequency of Mali will be dynamically selected from the
-+ available OPPs.
-
- config MALI_MIDGARD_DVFS
- bool "Enable legacy DVFS"
-@@ -37,29 +73,25 @@ config MALI_MIDGARD_DVFS
- help
- Choose this option to enable legacy DVFS in the Mali Midgard DDK.
-
-+config MALI_GATOR_SUPPORT
-+ bool "Enable Streamline tracing support"
-+ depends on MALI_MIDGARD && !BACKEND_USER
-+ default y
-+ help
-+ Enables kbase tracing used by the Arm Streamline Performance Analyzer.
-+ The tracepoints are used to derive GPU activity charts in Streamline.
-+
- config MALI_MIDGARD_ENABLE_TRACE
- bool "Enable kbase tracing"
- depends on MALI_MIDGARD
- default y if MALI_DEBUG
- default n
- help
-- Enables tracing in kbase. Trace log available through
-+ Enables tracing in kbase. Trace log available through
- the "mali_trace" debugfs file, when the CONFIG_DEBUG_FS is enabled
-
--config MALI_DEVFREQ
-- bool "devfreq support for Mali"
-- depends on MALI_MIDGARD
-- default y if PLATFORM_JUNO
-- default y if PLATFORM_CUSTOM
-- help
-- Support devfreq for Mali.
--
-- Using the devfreq framework and, by default, the simpleondemand
-- governor, the frequency of Mali will be dynamically selected from the
-- available OPPs.
--
- config MALI_DMA_FENCE
-- bool "DMA_BUF fence support for Mali"
-+ bool "Enable DMA_BUF fence support for Mali"
- depends on MALI_MIDGARD
- default n
- help
-@@ -68,23 +100,9 @@ config MALI_DMA_FENCE
- This option should only be enabled if the Linux Kernel has built in
- support for DMA_BUF fences.
-
--config MALI_PLATFORM_NAME
-- depends on MALI_MIDGARD
-- string "Platform name"
-- default "hisilicon" if PLATFORM_HIKEY960
-- default "hisilicon" if PLATFORM_HIKEY970
-- default "devicetree"
-- help
-- Enter the name of the desired platform configuration directory to
-- include in the build. 'platform/$(MALI_PLATFORM_NAME)/Kbuild' must
-- exist.
--
-- When PLATFORM_CUSTOM is set, this needs to be set manually to
-- pick up the desired platform files.
--
- config MALI_ARBITER_SUPPORT
- bool "Enable arbiter support for Mali"
-- depends on MALI_MIDGARD
-+ depends on MALI_MIDGARD && !MALI_CSF_SUPPORT
- default n
- help
- Enable support for the arbiter interface in the driver.
-@@ -93,62 +111,89 @@ config MALI_ARBITER_SUPPORT
-
- If unsure, say N.
-
--# MALI_EXPERT configuration options
-+config DMA_BUF_SYNC_IOCTL_SUPPORTED
-+ bool "Enable Kernel DMA buffers support DMA_BUF_IOCTL_SYNC"
-+ depends on MALI_MIDGARD && BACKEND_KERNEL
-+ default y
-+
-+config MALI_DMA_BUF_MAP_ON_DEMAND
-+ bool "Enable map imported dma-bufs on demand"
-+ depends on MALI_MIDGARD
-+ default n
-+ default y if !DMA_BUF_SYNC_IOCTL_SUPPORTED
-+ help
-+ This option caused kbase to set up the GPU mapping of imported
-+ dma-buf when needed to run atoms. This is the legacy behavior.
-+
-+ This is intended for testing and the option will get removed in the
-+ future.
-+
-+config MALI_DMA_BUF_LEGACY_COMPAT
-+ bool "Enable legacy compatibility cache flush on dma-buf map"
-+ depends on MALI_MIDGARD && !MALI_DMA_BUF_MAP_ON_DEMAND
-+ default n
-+ help
-+ This option enables compatibility with legacy dma-buf mapping
-+ behavior, then the dma-buf is mapped on import, by adding cache
-+ maintenance where MALI_DMA_BUF_MAP_ON_DEMAND would do the mapping,
-+ including a cache flush.
-+
-+ This option might work-around issues related to missing cache
-+ flushes in other drivers. This only has an effect for clients using
-+ UK 11.18 or older. For later UK versions it is not possible.
-
- menuconfig MALI_EXPERT
- depends on MALI_MIDGARD
- bool "Enable Expert Settings"
- default y
- help
-- Enabling this option and modifying the default settings may produce a driver with performance or
-- other limitations.
-+ Enabling this option and modifying the default settings may produce
-+ a driver with performance or other limitations.
-
--config MALI_CORESTACK
-- bool "Support controlling power to the GPU core stack"
-+config MALI_2MB_ALLOC
-+ bool "Attempt to allocate 2MB pages"
- depends on MALI_MIDGARD && MALI_EXPERT
- default n
- help
-- Enabling this feature on supported GPUs will let the driver powering
-- on/off the GPU core stack independently without involving the Power
-- Domain Controller. This should only be enabled on platforms which
-- integration of the PDC to the Mali GPU is known to be problematic.
-- This feature is currently only supported on t-Six and t-HEx GPUs.
-+ Rather than allocating all GPU memory page-by-page, attempt to
-+ allocate 2MB pages from the kernel. This reduces TLB pressure and
-+ helps to prevent memory fragmentation.
-
-- If unsure, say N.
-+ If in doubt, say N
-
--config MALI_DEBUG
-- bool "Debug build"
-+config MALI_MEMORY_FULLY_BACKED
-+ bool "Enable memory fully physically-backed"
- depends on MALI_MIDGARD && MALI_EXPERT
-- default y if DEBUG
- default n
- help
-- Select this option for increased checking and reporting of errors.
-+ This option enables full physical backing of all virtual
-+ memory allocations in the kernel. Notice that this build
-+ option only affects allocations of grow-on-GPU-page-fault
-+ memory.
-
--config MALI_FENCE_DEBUG
-- bool "Debug sync fence usage"
-+config MALI_CORESTACK
-+ bool "Enable support of GPU core stack power control"
- depends on MALI_MIDGARD && MALI_EXPERT
-- default y if MALI_DEBUG
-+ default n
- help
-- Select this option to enable additional checking and reporting on the
-- use of sync fences in the Mali driver.
--
-- This will add a 3s timeout to all sync fence waits in the Mali
-- driver, so that when work for Mali has been waiting on a sync fence
-- for a long time a debug message will be printed, detailing what fence
-- is causing the block, and which dependent Mali atoms are blocked as a
-- result of this.
-+ Enabling this feature on supported GPUs will let the driver powering
-+ on/off the GPU core stack independently without involving the Power
-+ Domain Controller. This should only be enabled on platforms which
-+ integration of the PDC to the Mali GPU is known to be problematic.
-+ This feature is currently only supported on t-Six and t-HEx GPUs.
-
-- The timeout can be changed at runtime through the js_soft_timeout
-- device attribute, where the timeout is specified in milliseconds.
-+ If unsure, say N.
-
- choice
- prompt "Error injection level"
-+ depends on MALI_MIDGARD && MALI_EXPERT
- default MALI_ERROR_INJECT_NONE
- help
- Enables insertion of errors to test module failure and recovery mechanisms.
-
- config MALI_ERROR_INJECT_NONE
- bool "disabled"
-+ depends on MALI_MIDGARD && MALI_EXPERT
- help
- Error injection is disabled.
-
-@@ -168,14 +213,49 @@ endchoice
-
- config MALI_ERROR_INJECT_ON
- string
-+ depends on MALI_MIDGARD && MALI_EXPERT
- default "0" if MALI_ERROR_INJECT_NONE
- default "1" if MALI_ERROR_INJECT_TRACK_LIST
- default "2" if MALI_ERROR_INJECT_RANDOM
-
- config MALI_ERROR_INJECT
- bool
-+ depends on MALI_MIDGARD && MALI_EXPERT
- default y if !MALI_ERROR_INJECT_NONE
-
-+config MALI_GEM5_BUILD
-+ bool "Enable build of Mali kernel driver for GEM5"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-+ default n
-+ help
-+ This option is to do a Mali GEM5 build.
-+ If unsure, say N.
-+
-+config MALI_DEBUG
-+ bool "Enable debug build"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-+ default y if DEBUG
-+ default n
-+ help
-+ Select this option for increased checking and reporting of errors.
-+
-+config MALI_FENCE_DEBUG
-+ bool "Enable debug sync fence usage"
-+ depends on MALI_MIDGARD && MALI_EXPERT
-+ default y if MALI_DEBUG
-+ help
-+ Select this option to enable additional checking and reporting on the
-+ use of sync fences in the Mali driver.
-+
-+ This will add a 3s timeout to all sync fence waits in the Mali
-+ driver, so that when work for Mali has been waiting on a sync fence
-+ for a long time a debug message will be printed, detailing what fence
-+ is causing the block, and which dependent Mali atoms are blocked as a
-+ result of this.
-+
-+ The timeout can be changed at runtime through the js_soft_timeout
-+ device attribute, where the timeout is specified in milliseconds.
-+
- config MALI_SYSTEM_TRACE
- bool "Enable system event tracing support"
- depends on MALI_MIDGARD && MALI_EXPERT
-@@ -187,56 +267,35 @@ config MALI_SYSTEM_TRACE
- minimal overhead when not in use. Enable only if you know what
- you are doing.
-
--config MALI_2MB_ALLOC
-- bool "Attempt to allocate 2MB pages"
-- depends on MALI_MIDGARD && MALI_EXPERT
-- default n
-- help
-- Rather than allocating all GPU memory page-by-page, attempt to
-- allocate 2MB pages from the kernel. This reduces TLB pressure and
-- helps to prevent memory fragmentation.
-+# Instrumentation options.
-
-- If in doubt, say N
-+# config MALI_PRFCNT_SET_PRIMARY exists in the Kernel Kconfig but is configured using CINSTR_PRIMARY_HWC in Mconfig.
-+# config MALI_PRFCNT_SET_SECONDARY exists in the Kernel Kconfig but is configured using CINSTR_SECONDARY_HWC in Mconfig.
-+# config MALI_PRFCNT_SET_TERTIARY exists in the Kernel Kconfig but is configured using CINSTR_TERTIARY_HWC in Mconfig.
-+# config MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS exists in the Kernel Kconfig but is configured using CINSTR_HWC_SET_SELECT_VIA_DEBUG_FS in Mconfig.
-
--config MALI_PWRSOFT_765
-- bool "PWRSOFT-765 ticket"
-+config MALI_JOB_DUMP
-+ bool "Enable system level support needed for job dumping"
- depends on MALI_MIDGARD && MALI_EXPERT
- default n
- help
-- PWRSOFT-765 fixes devfreq cooling devices issues. However, they are
-- not merged in mainline kernel yet. So this define helps to guard those
-- parts of the code.
--
--config MALI_MEMORY_FULLY_BACKED
-- bool "Memory fully physically-backed"
-- default n
-- help
-- This option enables full backing of all virtual memory allocations
-- for the kernel. This only affects grow-on-GPU-page-fault memory.
-+ Choose this option to enable system level support needed for
-+ job dumping. This is typically used for instrumentation but has
-+ minimal overhead when not in use. Enable only if you know what
-+ you are doing.
-
--config MALI_DMA_BUF_MAP_ON_DEMAND
-- bool "Map imported dma-bufs on demand"
-- depends on MALI_MIDGARD
-+config MALI_PWRSOFT_765
-+ bool "Enable workaround for PWRSOFT-765"
-+ depends on MALI_MIDGARD && MALI_EXPERT
- default n
-- default y if !DMA_BUF_SYNC_IOCTL_SUPPORTED
- help
-- This option caused kbase to set up the GPU mapping of imported
-- dma-buf when needed to run atoms. This is the legacy behaviour.
-+ PWRSOFT-765 fixes devfreq cooling devices issues. The fix was merged
-+ in kernel v4.10, however if backported into the kernel then this
-+ option must be manually selected.
-
--config MALI_DMA_BUF_LEGACY_COMPAT
-- bool "Enable legacy compatibility cache flush on dma-buf map"
-- depends on MALI_MIDGARD && !MALI_DMA_BUF_MAP_ON_DEMAND
-- default n
-- help
-- This option enables compatibility with legacy dma-buf mapping
-- behavior, then the dma-buf is mapped on import, by adding cache
-- maintenance where MALI_DMA_BUF_MAP_ON_DEMAND would do the mapping,
-- including a cache flush.
-+ If using kernel >= v4.10 then say N, otherwise if devfreq cooling
-+ changes have been backported say Y to avoid compilation errors.
-
--config MALI_REAL_HW
-- bool
-- default y
-- default n if NO_MALI
-
- config MALI_HW_ERRATA_1485982_NOT_AFFECTED
- bool "Disable workaround for BASE_HW_ISSUE_GPU2017_1336"
-@@ -262,17 +321,6 @@ config MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE
- tree using the property, opp-mali-errata-1485982. Otherwise the
- slowest clock will be selected.
-
--config MALI_GEM5_BUILD
-- bool "Enable build of Mali kernel driver for GEM5"
-- depends on MALI_MIDGARD
-- default n
-- help
-- This option is to do a Mali GEM5 build.
-- If unsure, say N.
--
--# Instrumentation options.
--
--# config MALI_JOB_DUMP exists in the Kernel Kconfig but is configured using CINSTR_JOB_DUMP in Mconfig.
--# config MALI_PRFCNT_SET_SECONDARY exists in the Kernel Kconfig but is configured using CINSTR_SECONDARY_HWC in Mconfig.
-
-+source "kernel/drivers/gpu/arm/midgard/arbitration/Mconfig"
- source "kernel/drivers/gpu/arm/midgard/tests/Mconfig"
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/Kbuild
-index 98e47be..5203281 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2019-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,10 +16,8 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- mali_kbase-y += \
-- arbiter/mali_kbase_arbif.o \
-- arbiter/mali_kbase_arbiter_pm.o
-+ arbiter/mali_kbase_arbif.o \
-+ arbiter/mali_kbase_arbiter_pm.o
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbif.c b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbif.c
-index d193cb9..64e11ce 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbif.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbif.c
-@@ -1,13 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
--
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -18,13 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-- * @file mali_kbase_arbif.c
-- * Mali arbiter interface APIs to share GPU between Virtual Machines
-+ * DOC: Mali arbiter interface APIs to share GPU between Virtual Machines
- */
-
- #include <mali_kbase.h>
-@@ -34,32 +30,155 @@
- #include <linux/of_platform.h>
- #include "mali_kbase_arbiter_interface.h"
-
-+/* Arbiter interface version against which was implemented this module */
-+#define MALI_REQUIRED_KBASE_ARBITER_INTERFACE_VERSION 5
-+#if MALI_REQUIRED_KBASE_ARBITER_INTERFACE_VERSION != \
-+ MALI_KBASE_ARBITER_INTERFACE_VERSION
-+#error "Unsupported Mali Arbiter interface version."
-+#endif
-+
-+static void on_max_config(struct device *dev, uint32_t max_l2_slices,
-+ uint32_t max_core_mask)
-+{
-+ struct kbase_device *kbdev;
-+
-+ if (!dev) {
-+ pr_err("%s(): dev is NULL", __func__);
-+ return;
-+ }
-+
-+ kbdev = dev_get_drvdata(dev);
-+ if (!kbdev) {
-+ dev_err(dev, "%s(): kbdev is NULL", __func__);
-+ return;
-+ }
-+
-+ if (!max_l2_slices || !max_core_mask) {
-+ dev_dbg(dev,
-+ "%s(): max_config ignored as one of the fields is zero",
-+ __func__);
-+ return;
-+ }
-+
-+ /* set the max config info in the kbase device */
-+ kbase_arbiter_set_max_config(kbdev, max_l2_slices, max_core_mask);
-+}
-+
-+/**
-+ * on_update_freq() - Updates GPU clock frequency
-+ * @dev: arbiter interface device handle
-+ * @freq: GPU clock frequency value reported from arbiter
-+ *
-+ * call back function to update GPU clock frequency with
-+ * new value from arbiter
-+ */
-+static void on_update_freq(struct device *dev, uint32_t freq)
-+{
-+ struct kbase_device *kbdev;
-+
-+ if (!dev) {
-+ pr_err("%s(): dev is NULL", __func__);
-+ return;
-+ }
-+
-+ kbdev = dev_get_drvdata(dev);
-+ if (!kbdev) {
-+ dev_err(dev, "%s(): kbdev is NULL", __func__);
-+ return;
-+ }
-+
-+ kbase_arbiter_pm_update_gpu_freq(&kbdev->arb.arb_freq, freq);
-+}
-+
-+/**
-+ * on_gpu_stop() - sends KBASE_VM_GPU_STOP_EVT event on VM stop
-+ * @dev: arbiter interface device handle
-+ *
-+ * call back function to signal a GPU STOP event from arbiter interface
-+ */
- static void on_gpu_stop(struct device *dev)
- {
-- struct kbase_device *kbdev = dev_get_drvdata(dev);
-+ struct kbase_device *kbdev;
-+
-+ if (!dev) {
-+ pr_err("%s(): dev is NULL", __func__);
-+ return;
-+ }
-
-- KBASE_TLSTREAM_TL_EVENT_ARB_STOP_REQUESTED(kbdev, kbdev);
-+ kbdev = dev_get_drvdata(dev);
-+ if (!kbdev) {
-+ dev_err(dev, "%s(): kbdev is NULL", __func__);
-+ return;
-+ }
-+
-+ KBASE_TLSTREAM_TL_ARBITER_STOP_REQUESTED(kbdev, kbdev);
- kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_STOP_EVT);
- }
-
-+/**
-+ * on_gpu_granted() - sends KBASE_VM_GPU_GRANTED_EVT event on GPU granted
-+ * @dev: arbiter interface device handle
-+ *
-+ * call back function to signal a GPU GRANT event from arbiter interface
-+ */
- static void on_gpu_granted(struct device *dev)
- {
-- struct kbase_device *kbdev = dev_get_drvdata(dev);
-+ struct kbase_device *kbdev;
-+
-+ if (!dev) {
-+ pr_err("%s(): dev is NULL", __func__);
-+ return;
-+ }
-+
-+ kbdev = dev_get_drvdata(dev);
-+ if (!kbdev) {
-+ dev_err(dev, "%s(): kbdev is NULL", __func__);
-+ return;
-+ }
-
-- KBASE_TLSTREAM_TL_EVENT_ARB_GRANTED(kbdev, kbdev);
-+ KBASE_TLSTREAM_TL_ARBITER_GRANTED(kbdev, kbdev);
- kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_GRANTED_EVT);
- }
-
-+/**
-+ * on_gpu_lost() - sends KBASE_VM_GPU_LOST_EVT event on GPU granted
-+ * @dev: arbiter interface device handle
-+ *
-+ * call back function to signal a GPU LOST event from arbiter interface
-+ */
- static void on_gpu_lost(struct device *dev)
- {
-- struct kbase_device *kbdev = dev_get_drvdata(dev);
-+ struct kbase_device *kbdev;
-+
-+ if (!dev) {
-+ pr_err("%s(): dev is NULL", __func__);
-+ return;
-+ }
-+
-+ kbdev = dev_get_drvdata(dev);
-+ if (!kbdev) {
-+ dev_err(dev, "%s(): kbdev is NULL", __func__);
-+ return;
-+ }
-
- kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_LOST_EVT);
- }
-
-+/**
-+ * kbase_arbif_init() - Kbase Arbiter interface initialisation.
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Initialise Kbase Arbiter interface and assign callback functions.
-+ *
-+ * Return:
-+ * * 0 - the interface was initialized or was not specified
-+ * * in the device tree.
-+ * * -EFAULT - the interface was specified but failed to initialize.
-+ * * -EPROBE_DEFER - module dependencies are not yet available.
-+ */
- int kbase_arbif_init(struct kbase_device *kbdev)
- {
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- struct arbiter_if_arb_vm_ops ops;
- struct arbiter_if_dev *arb_if;
- struct device_node *arbiter_if_node;
-@@ -100,17 +219,26 @@ int kbase_arbif_init(struct kbase_device *kbdev)
- ops.arb_vm_gpu_stop = on_gpu_stop;
- ops.arb_vm_gpu_granted = on_gpu_granted;
- ops.arb_vm_gpu_lost = on_gpu_lost;
-+ ops.arb_vm_max_config = on_max_config;
-+ ops.arb_vm_update_freq = on_update_freq;
-+
-+ kbdev->arb.arb_freq.arb_freq = 0;
-+ kbdev->arb.arb_freq.freq_updated = false;
-+ mutex_init(&kbdev->arb.arb_freq.arb_freq_lock);
-
- /* register kbase arbiter_if callbacks */
- if (arb_if->vm_ops.vm_arb_register_dev) {
- err = arb_if->vm_ops.vm_arb_register_dev(arb_if,
- kbdev->dev, &ops);
- if (err) {
-- dev_err(kbdev->dev, "Arbiter registration failed.\n");
-+ dev_err(&pdev->dev, "Failed to register with arbiter\n");
- module_put(pdev->dev.driver->owner);
-+ if (err != -EPROBE_DEFER)
-+ err = -EFAULT;
- return err;
- }
- }
-+
- #else /* CONFIG_OF */
- dev_dbg(kbdev->dev, "No arbiter without Device Tree support\n");
- kbdev->arb.arb_dev = NULL;
-@@ -119,6 +247,12 @@ int kbase_arbif_init(struct kbase_device *kbdev)
- return 0;
- }
-
-+/**
-+ * kbase_arbif_destroy() - De-init Kbase arbiter interface
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * De-initialise Kbase arbiter interface
-+ */
- void kbase_arbif_destroy(struct kbase_device *kbdev)
- {
- struct arbiter_if_dev *arb_if = kbdev->arb.arb_if;
-@@ -133,27 +267,64 @@ void kbase_arbif_destroy(struct kbase_device *kbdev)
- kbdev->arb.arb_dev = NULL;
- }
-
-+/**
-+ * kbase_arbif_get_max_config() - Request max config info
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * call back function from arb interface to arbiter requesting max config info
-+ */
-+void kbase_arbif_get_max_config(struct kbase_device *kbdev)
-+{
-+ struct arbiter_if_dev *arb_if = kbdev->arb.arb_if;
-+
-+ if (arb_if && arb_if->vm_ops.vm_arb_get_max_config) {
-+ dev_dbg(kbdev->dev, "%s\n", __func__);
-+ arb_if->vm_ops.vm_arb_get_max_config(arb_if);
-+ }
-+}
-+
-+/**
-+ * kbase_arbif_gpu_request() - Request GPU from
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * call back function from arb interface to arbiter requesting GPU for VM
-+ */
- void kbase_arbif_gpu_request(struct kbase_device *kbdev)
- {
- struct arbiter_if_dev *arb_if = kbdev->arb.arb_if;
-
- if (arb_if && arb_if->vm_ops.vm_arb_gpu_request) {
- dev_dbg(kbdev->dev, "%s\n", __func__);
-+ KBASE_TLSTREAM_TL_ARBITER_REQUESTED(kbdev, kbdev);
- arb_if->vm_ops.vm_arb_gpu_request(arb_if);
- }
- }
-
-+/**
-+ * kbase_arbif_gpu_stopped() - send GPU stopped message to the arbiter
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ * @gpu_required: GPU request flag
-+ *
-+ */
- void kbase_arbif_gpu_stopped(struct kbase_device *kbdev, u8 gpu_required)
- {
- struct arbiter_if_dev *arb_if = kbdev->arb.arb_if;
-
- if (arb_if && arb_if->vm_ops.vm_arb_gpu_stopped) {
- dev_dbg(kbdev->dev, "%s\n", __func__);
-- KBASE_TLSTREAM_TL_EVENT_ARB_STOPPED(kbdev, kbdev);
-+ KBASE_TLSTREAM_TL_ARBITER_STOPPED(kbdev, kbdev);
-+ if (gpu_required)
-+ KBASE_TLSTREAM_TL_ARBITER_REQUESTED(kbdev, kbdev);
- arb_if->vm_ops.vm_arb_gpu_stopped(arb_if, gpu_required);
- }
- }
-
-+/**
-+ * kbase_arbif_gpu_active() - Sends a GPU_ACTIVE message to the Arbiter
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Informs the arbiter VM is active
-+ */
- void kbase_arbif_gpu_active(struct kbase_device *kbdev)
- {
- struct arbiter_if_dev *arb_if = kbdev->arb.arb_if;
-@@ -164,6 +335,12 @@ void kbase_arbif_gpu_active(struct kbase_device *kbdev)
- }
- }
-
-+/**
-+ * kbase_arbif_gpu_idle() - Inform the arbiter that the VM has gone idle
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Informs the arbiter VM is idle
-+ */
- void kbase_arbif_gpu_idle(struct kbase_device *kbdev)
- {
- struct arbiter_if_dev *arb_if = kbdev->arb.arb_if;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbif.h b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbif.h
-index e7e9de7..701ffd4 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbif.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbif.h
-@@ -1,28 +1,7 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--
--/*
-- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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
-@@ -38,12 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- *
- */
-
- /**
-- * @file
-- * Mali arbiter interface APIs to share GPU between Virtual Machines
-+ * DOC: Mali arbiter interface APIs to share GPU between Virtual Machines
- */
-
- #ifndef _MALI_KBASE_ARBIF_H_
-@@ -80,8 +57,11 @@ enum kbase_arbif_evt {
- * Initialize the arbiter interface and also determines
- * if Arbiter functionality is required.
- *
-- * Return: 0 if the Arbiter interface was successfully initialized or the
-- * Arbiter was not required.
-+ * Return:
-+ * * 0 - the interface was initialized or was not specified
-+ * * in the device tree.
-+ * * -EFAULT - the interface was specified but failed to initialize.
-+ * * -EPROBE_DEFER - module dependencies are not yet available.
- */
- int kbase_arbif_init(struct kbase_device *kbdev);
-
-@@ -94,6 +74,14 @@ int kbase_arbif_init(struct kbase_device *kbdev);
- */
- void kbase_arbif_destroy(struct kbase_device *kbdev);
-
-+/**
-+ * kbase_arbif_get_max_config() - Request max config info
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * call back function from arb interface to arbiter requesting max config info
-+ */
-+void kbase_arbif_get_max_config(struct kbase_device *kbdev);
-+
- /**
- * kbase_arbif_gpu_request() - Send GPU request message to the arbiter
- * @kbdev: The kbase device structure for the device (must be a valid pointer)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_defs.h
-index 1f53cbf..570a82a 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_defs.h
-@@ -1,28 +1,7 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--
--/*
-- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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
-@@ -38,7 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- *
- */
-
- /**
-@@ -66,7 +44,8 @@
- * @vm_resume_work: Work item for vm_arb_wq to resume current work on GPU
- * @vm_arb_starting: Work queue resume in progress
- * @vm_arb_stopping: Work queue suspend in progress
-- * @vm_arb_users_waiting: Count of users waiting for GPU
-+ * @interrupts_installed: Flag set when interrupts are installed
-+ * @vm_request_timer: Timer to monitor GPU request
- */
- struct kbase_arbiter_vm_state {
- struct kbase_device *kbdev;
-@@ -78,7 +57,8 @@ struct kbase_arbiter_vm_state {
- struct work_struct vm_resume_work;
- bool vm_arb_starting;
- bool vm_arb_stopping;
-- int vm_arb_users_waiting;
-+ bool interrupts_installed;
-+ struct hrtimer vm_request_timer;
- };
-
- /**
-@@ -86,10 +66,12 @@ struct kbase_arbiter_vm_state {
- * allocated from the probe method of Mali driver
- * @arb_if: Pointer to the arbiter interface device
- * @arb_dev: Pointer to the arbiter device
-+ * @arb_freq: GPU clock frequency retrieved from arbiter.
- */
- struct kbase_arbiter_device {
- struct arbiter_if_dev *arb_if;
- struct device *arb_dev;
-+ struct kbase_arbiter_freq arb_freq;
- };
-
- #endif /* _MALI_KBASE_ARBITER_DEFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_interface.h b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_interface.h
-index 5d5d8a7..c0137f7 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_interface.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_interface.h
-@@ -1,28 +1,7 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--
--/*
-- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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
-@@ -38,7 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- *
- */
-
- /**
-@@ -50,7 +28,7 @@
- #define _MALI_KBASE_ARBITER_INTERFACE_H_
-
- /**
-- * @brief Mali arbiter interface version
-+ * Mali arbiter interface version
- *
- * This specifies the current version of the configuration interface. Whenever
- * the arbiter interface changes, so that integration effort is required, the
-@@ -61,8 +39,15 @@
- * 1 - Added the Mali arbiter configuration interface.
- * 2 - Strip out reference code from header
- * 3 - Removed DVFS utilization interface (DVFS moved to arbiter side)
-+ * 4 - Added max_config support
-+ * 5 - Added GPU clock frequency reporting support from arbiter
- */
--#define MALI_KBASE_ARBITER_INTERFACE_VERSION 3
-+#define MALI_KBASE_ARBITER_INTERFACE_VERSION 5
-+
-+/**
-+ * NO_FREQ is used in case platform doesn't support reporting frequency
-+ */
-+#define NO_FREQ 0
-
- struct arbiter_if_dev;
-
-@@ -108,6 +93,27 @@ struct arbiter_if_arb_vm_ops {
- * If successful, will respond with a vm_arb_gpu_stopped message.
- */
- void (*arb_vm_gpu_lost)(struct device *dev);
-+
-+ /**
-+ * arb_vm_max_config() - Send max config info to the VM
-+ * @dev: The arbif kernel module device.
-+ * @max_l2_slices: The maximum number of L2 slices.
-+ * @max_core_mask: The largest core mask.
-+ *
-+ * Informs KBase the maximum resources that can be allocated to the
-+ * partition in use.
-+ */
-+ void (*arb_vm_max_config)(struct device *dev, uint32_t max_l2_slices,
-+ uint32_t max_core_mask);
-+
-+ /**
-+ * arb_vm_update_freq() - GPU clock frequency has been updated
-+ * @dev: The arbif kernel module device.
-+ * @freq: GPU clock frequency value reported from arbiter
-+ *
-+ * Informs KBase that the GPU clock frequency has been updated.
-+ */
-+ void (*arb_vm_update_freq)(struct device *dev, uint32_t freq);
- };
-
- /**
-@@ -126,6 +132,11 @@ struct arbiter_if_vm_arb_ops {
- * @dev: The device structure to supply in the callbacks.
- * @ops: The callbacks that the device driver supports
- * (none are optional).
-+ *
-+ * Return:
-+ * * 0 - successful.
-+ * * -EINVAL - invalid argument.
-+ * * -EPROBE_DEFER - module dependencies are not yet available.
- */
- int (*vm_arb_register_dev)(struct arbiter_if_dev *arbif_dev,
- struct device *dev, struct arbiter_if_arb_vm_ops *ops);
-@@ -136,6 +147,13 @@ struct arbiter_if_vm_arb_ops {
- */
- void (*vm_arb_unregister_dev)(struct arbiter_if_dev *arbif_dev);
-
-+ /**
-+ * vm_arb_gpu_get_max_config() - Request the max config from the
-+ * Arbiter.
-+ * @arbif_dev: The arbiter interface we want to issue the request.
-+ */
-+ void (*vm_arb_get_max_config)(struct arbiter_if_dev *arbif_dev);
-+
- /**
- * vm_arb_gpu_request() - Ask the arbiter interface for GPU access.
- * @arbif_dev: The arbiter interface we want to issue the request.
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_pm.c b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_pm.c
-index 6c35e16..5c75686 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_pm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_pm.c
-@@ -1,13 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
--
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -18,27 +17,49 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-- * @file mali_kbase_arbiter_pm.c
-+ * @file
- * Mali arbiter power manager state machine and APIs
- */
-
- #include <mali_kbase.h>
- #include <mali_kbase_pm.h>
- #include <mali_kbase_hwaccess_jm.h>
--#include <mali_kbase_irq_internal.h>
-+#include <backend/gpu/mali_kbase_irq_internal.h>
- #include <mali_kbase_hwcnt_context.h>
--#include <mali_kbase_pm_internal.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
- #include <tl/mali_kbase_tracepoints.h>
-+#include <mali_kbase_gpuprops.h>
-+
-+/* A dmesg warning will occur if the GPU is not granted
-+ * after the following time (in milliseconds) has ellapsed.
-+ */
-+#define GPU_REQUEST_TIMEOUT 1000
-+#define KHZ_TO_HZ 1000
-+
-+#define MAX_L2_SLICES_MASK 0xFF
-+
-+/* Maximum time in ms, before deferring probe incase
-+ * GPU_GRANTED message is not received
-+ */
-+static int gpu_req_timeout = 1;
-+module_param(gpu_req_timeout, int, 0644);
-+MODULE_PARM_DESC(gpu_req_timeout,
-+ "On a virtualized platform, if the GPU is not granted within this time(ms) kbase will defer the probe");
-
- static void kbase_arbiter_pm_vm_wait_gpu_assignment(struct kbase_device *kbdev);
- static inline bool kbase_arbiter_pm_vm_gpu_assigned_lockheld(
- struct kbase_device *kbdev);
-
-+/**
-+ * kbase_arbiter_pm_vm_state_str() - Helper function to get string
-+ * for kbase VM state.(debug)
-+ * @state: kbase VM state
-+ *
-+ * Return: string representation of Kbase_vm_state
-+ */
- static inline const char *kbase_arbiter_pm_vm_state_str(
- enum kbase_vm_state state)
- {
-@@ -73,6 +94,13 @@ static inline const char *kbase_arbiter_pm_vm_state_str(
- }
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_event_str() - Helper function to get string
-+ * for kbase VM event.(debug)
-+ * @evt: kbase VM state
-+ *
-+ * Return: String representation of Kbase_arbif_event
-+ */
- static inline const char *kbase_arbiter_pm_vm_event_str(
- enum kbase_arbif_evt evt)
- {
-@@ -99,6 +127,13 @@ static inline const char *kbase_arbiter_pm_vm_event_str(
- }
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_set_state() - Sets new kbase_arbiter_vm_state
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ * @new_state: kbase VM new state
-+ *
-+ * This function sets the new state for the VM
-+ */
- static void kbase_arbiter_pm_vm_set_state(struct kbase_device *kbdev,
- enum kbase_vm_state new_state)
- {
-@@ -107,11 +142,22 @@ static void kbase_arbiter_pm_vm_set_state(struct kbase_device *kbdev,
- dev_dbg(kbdev->dev, "VM set_state %s -> %s",
- kbase_arbiter_pm_vm_state_str(arb_vm_state->vm_state),
- kbase_arbiter_pm_vm_state_str(new_state));
-+
- lockdep_assert_held(&arb_vm_state->vm_state_lock);
- arb_vm_state->vm_state = new_state;
-+ if (new_state != KBASE_VM_STATE_INITIALIZING_WITH_GPU &&
-+ new_state != KBASE_VM_STATE_INITIALIZING)
-+ KBASE_KTRACE_ADD(kbdev, ARB_VM_STATE, NULL, new_state);
- wake_up(&arb_vm_state->vm_state_wait);
- }
-
-+/**
-+ * kbase_arbiter_pm_suspend_wq() - suspend work queue of the driver.
-+ * @data: work queue
-+ *
-+ * Suspends work queue of the driver, when VM is in SUSPEND_PENDING or
-+ * STOPPING_IDLE or STOPPING_ACTIVE state
-+ */
- static void kbase_arbiter_pm_suspend_wq(struct work_struct *data)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = container_of(data,
-@@ -136,6 +182,13 @@ static void kbase_arbiter_pm_suspend_wq(struct work_struct *data)
- dev_dbg(kbdev->dev, "<%s\n", __func__);
- }
-
-+/**
-+ * kbase_arbiter_pm_resume_wq() -Kbase resume work queue.
-+ * @data: work item
-+ *
-+ * Resume work queue of the driver when VM is in STARTING state,
-+ * else if its in STOPPING_ACTIVE will request a stop event.
-+ */
- static void kbase_arbiter_pm_resume_wq(struct work_struct *data)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = container_of(data,
-@@ -157,9 +210,74 @@ static void kbase_arbiter_pm_resume_wq(struct work_struct *data)
- }
- arb_vm_state->vm_arb_starting = false;
- mutex_unlock(&arb_vm_state->vm_state_lock);
-+ KBASE_TLSTREAM_TL_ARBITER_STARTED(kbdev, kbdev);
- dev_dbg(kbdev->dev, "<%s\n", __func__);
- }
-
-+/**
-+ * request_timer_callback() - Issue warning on request timer expiration
-+ * @timer: Request hr timer data
-+ *
-+ * Called when the Arbiter takes too long to grant the GPU after a
-+ * request has been made. Issues a warning in dmesg.
-+ *
-+ * Return: Always returns HRTIMER_NORESTART
-+ */
-+static enum hrtimer_restart request_timer_callback(struct hrtimer *timer)
-+{
-+ struct kbase_arbiter_vm_state *arb_vm_state = container_of(timer,
-+ struct kbase_arbiter_vm_state, vm_request_timer);
-+
-+ KBASE_DEBUG_ASSERT(arb_vm_state);
-+ KBASE_DEBUG_ASSERT(arb_vm_state->kbdev);
-+
-+ dev_warn(arb_vm_state->kbdev->dev,
-+ "Still waiting for GPU to be granted from Arbiter after %d ms\n",
-+ GPU_REQUEST_TIMEOUT);
-+ return HRTIMER_NORESTART;
-+}
-+
-+/**
-+ * start_request_timer() - Start a timer after requesting GPU
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Start a timer to track when kbase is waiting for the GPU from the
-+ * Arbiter. If the timer expires before GPU is granted, a warning in
-+ * dmesg will be issued.
-+ */
-+static void start_request_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-+
-+ hrtimer_start(&arb_vm_state->vm_request_timer,
-+ HR_TIMER_DELAY_MSEC(GPU_REQUEST_TIMEOUT),
-+ HRTIMER_MODE_REL);
-+}
-+
-+/**
-+ * cancel_request_timer() - Stop the request timer
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Stops the request timer once GPU has been granted. Safe to call
-+ * even if timer is no longer running.
-+ */
-+static void cancel_request_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-+
-+ hrtimer_cancel(&arb_vm_state->vm_request_timer);
-+}
-+
-+/**
-+ * kbase_arbiter_pm_early_init() - Initialize arbiter for VM
-+ * Paravirtualized use.
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Initialize the arbiter and other required resources during the runtime
-+ * and request the GPU for the VM for the first time.
-+ *
-+ * Return: 0 if success, or a Linux error code
-+ */
- int kbase_arbiter_pm_early_init(struct kbase_device *kbdev)
- {
- int err;
-@@ -179,29 +297,49 @@ int kbase_arbiter_pm_early_init(struct kbase_device *kbdev)
- WQ_HIGHPRI);
- if (!arb_vm_state->vm_arb_wq) {
- dev_err(kbdev->dev, "Failed to allocate vm_arb workqueue\n");
-+ kfree(arb_vm_state);
- return -ENOMEM;
- }
- INIT_WORK(&arb_vm_state->vm_suspend_work, kbase_arbiter_pm_suspend_wq);
- INIT_WORK(&arb_vm_state->vm_resume_work, kbase_arbiter_pm_resume_wq);
- arb_vm_state->vm_arb_starting = false;
-- arb_vm_state->vm_arb_users_waiting = 0;
-+ atomic_set(&kbdev->pm.gpu_users_waiting, 0);
-+ hrtimer_init(&arb_vm_state->vm_request_timer, CLOCK_MONOTONIC,
-+ HRTIMER_MODE_REL);
-+ arb_vm_state->vm_request_timer.function =
-+ request_timer_callback;
- kbdev->pm.arb_vm_state = arb_vm_state;
-
- err = kbase_arbif_init(kbdev);
- if (err) {
-+ dev_err(kbdev->dev, "Failed to initialise arbif module\n");
- goto arbif_init_fail;
- }
-+
- if (kbdev->arb.arb_if) {
- kbase_arbif_gpu_request(kbdev);
- dev_dbg(kbdev->dev, "Waiting for initial GPU assignment...\n");
-- wait_event(arb_vm_state->vm_state_wait,
-+ err = wait_event_timeout(arb_vm_state->vm_state_wait,
- arb_vm_state->vm_state ==
-- KBASE_VM_STATE_INITIALIZING_WITH_GPU);
-+ KBASE_VM_STATE_INITIALIZING_WITH_GPU,
-+ msecs_to_jiffies(gpu_req_timeout));
-+
-+ if (!err) {
-+ dev_dbg(kbdev->dev,
-+ "Kbase probe Deferred after waiting %d ms to receive GPU_GRANT\n",
-+ gpu_req_timeout);
-+ err = -EPROBE_DEFER;
-+ goto arbif_eprobe_defer;
-+ }
-+
- dev_dbg(kbdev->dev,
- "Waiting for initial GPU assignment - done\n");
- }
- return 0;
-
-+arbif_eprobe_defer:
-+ kbase_arbiter_pm_early_term(kbdev);
-+ return err;
- arbif_init_fail:
- destroy_workqueue(arb_vm_state->vm_arb_wq);
- kfree(arb_vm_state);
-@@ -209,35 +347,72 @@ arbif_init_fail:
- return err;
- }
-
-+/**
-+ * kbase_arbiter_pm_early_term() - Shutdown arbiter and free resources
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Clean up all the resources
-+ */
- void kbase_arbiter_pm_early_term(struct kbase_device *kbdev)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-
-+ cancel_request_timer(kbdev);
- mutex_lock(&arb_vm_state->vm_state_lock);
-- if (arb_vm_state->vm_state > KBASE_VM_STATE_STOPPED_GPU_REQUESTED)
-+ if (arb_vm_state->vm_state > KBASE_VM_STATE_STOPPED_GPU_REQUESTED) {
-+ kbase_pm_set_gpu_lost(kbdev, false);
- kbase_arbif_gpu_stopped(kbdev, false);
--
-+ }
- mutex_unlock(&arb_vm_state->vm_state_lock);
-- kbase_arbif_destroy(kbdev);
- destroy_workqueue(arb_vm_state->vm_arb_wq);
-+ kbase_arbif_destroy(kbdev);
- arb_vm_state->vm_arb_wq = NULL;
- kfree(kbdev->pm.arb_vm_state);
- kbdev->pm.arb_vm_state = NULL;
- }
-
-+/**
-+ * kbase_arbiter_pm_release_interrupts() - Release the GPU interrupts
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Releases interrupts and set the interrupt flag to false
-+ */
- void kbase_arbiter_pm_release_interrupts(struct kbase_device *kbdev)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-
- mutex_lock(&arb_vm_state->vm_state_lock);
-- if (!kbdev->arb.arb_if ||
-- arb_vm_state->vm_state >
-- KBASE_VM_STATE_STOPPED_GPU_REQUESTED)
-+ if (arb_vm_state->interrupts_installed == true) {
-+ arb_vm_state->interrupts_installed = false;
- kbase_release_interrupts(kbdev);
-+ }
-+ mutex_unlock(&arb_vm_state->vm_state_lock);
-+}
-
-+/**
-+ * kbase_arbiter_pm_install_interrupts() - Install the GPU interrupts
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Install interrupts and set the interrupt_install flag to true.
-+ */
-+int kbase_arbiter_pm_install_interrupts(struct kbase_device *kbdev)
-+{
-+ struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-+ int err;
-+
-+ mutex_lock(&arb_vm_state->vm_state_lock);
-+ arb_vm_state->interrupts_installed = true;
-+ err = kbase_install_interrupts(kbdev);
- mutex_unlock(&arb_vm_state->vm_state_lock);
-+ return err;
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_stopped() - Handle stop state for the VM
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Handles a stop state for the VM
-+ */
- void kbase_arbiter_pm_vm_stopped(struct kbase_device *kbdev)
- {
- bool request_gpu = false;
-@@ -245,14 +420,19 @@ void kbase_arbiter_pm_vm_stopped(struct kbase_device *kbdev)
-
- lockdep_assert_held(&arb_vm_state->vm_state_lock);
-
-- if (arb_vm_state->vm_arb_users_waiting > 0 &&
-+ if (atomic_read(&kbdev->pm.gpu_users_waiting) > 0 &&
- arb_vm_state->vm_state == KBASE_VM_STATE_STOPPING_IDLE)
- kbase_arbiter_pm_vm_set_state(kbdev,
- KBASE_VM_STATE_STOPPING_ACTIVE);
-
- dev_dbg(kbdev->dev, "%s %s\n", __func__,
- kbase_arbiter_pm_vm_state_str(arb_vm_state->vm_state));
-- kbase_release_interrupts(kbdev);
-+
-+ if (arb_vm_state->interrupts_installed) {
-+ arb_vm_state->interrupts_installed = false;
-+ kbase_release_interrupts(kbdev);
-+ }
-+
- switch (arb_vm_state->vm_state) {
- case KBASE_VM_STATE_STOPPING_ACTIVE:
- request_gpu = true;
-@@ -271,14 +451,95 @@ void kbase_arbiter_pm_vm_stopped(struct kbase_device *kbdev)
- break;
- }
-
-+ kbase_pm_set_gpu_lost(kbdev, false);
- kbase_arbif_gpu_stopped(kbdev, request_gpu);
-+ if (request_gpu)
-+ start_request_timer(kbdev);
-+}
-+
-+void kbase_arbiter_set_max_config(struct kbase_device *kbdev,
-+ uint32_t max_l2_slices,
-+ uint32_t max_core_mask)
-+{
-+ struct kbase_arbiter_vm_state *arb_vm_state;
-+ struct max_config_props max_config;
-+
-+ if (!kbdev)
-+ return;
-+
-+ /* Mask the max_l2_slices as it is stored as 8 bits into kbase */
-+ max_config.l2_slices = max_l2_slices & MAX_L2_SLICES_MASK;
-+ max_config.core_mask = max_core_mask;
-+ arb_vm_state = kbdev->pm.arb_vm_state;
-+
-+ mutex_lock(&arb_vm_state->vm_state_lock);
-+ /* Just set the max_props in kbase during initialization. */
-+ if (arb_vm_state->vm_state == KBASE_VM_STATE_INITIALIZING)
-+ kbase_gpuprops_set_max_config(kbdev, &max_config);
-+ else
-+ dev_dbg(kbdev->dev, "Unexpected max_config on VM state %s",
-+ kbase_arbiter_pm_vm_state_str(arb_vm_state->vm_state));
-+
-+ mutex_unlock(&arb_vm_state->vm_state_lock);
-+}
-+
-+int kbase_arbiter_pm_gpu_assigned(struct kbase_device *kbdev)
-+{
-+ struct kbase_arbiter_vm_state *arb_vm_state;
-+ int result = -EINVAL;
-+
-+ if (!kbdev)
-+ return result;
-+
-+ /* First check the GPU_LOST state */
-+ kbase_pm_lock(kbdev);
-+ if (kbase_pm_is_gpu_lost(kbdev)) {
-+ kbase_pm_unlock(kbdev);
-+ return 0;
-+ }
-+ kbase_pm_unlock(kbdev);
-+
-+ /* Then the arbitration state machine */
-+ arb_vm_state = kbdev->pm.arb_vm_state;
-+
-+ mutex_lock(&arb_vm_state->vm_state_lock);
-+ switch (arb_vm_state->vm_state) {
-+ case KBASE_VM_STATE_INITIALIZING:
-+ case KBASE_VM_STATE_SUSPENDED:
-+ case KBASE_VM_STATE_STOPPED:
-+ case KBASE_VM_STATE_STOPPED_GPU_REQUESTED:
-+ case KBASE_VM_STATE_SUSPEND_WAIT_FOR_GRANT:
-+ result = 0;
-+ break;
-+ default:
-+ result = 1;
-+ break;
-+ }
-+ mutex_unlock(&arb_vm_state->vm_state_lock);
-+
-+ return result;
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_gpu_start() - Handles the start state of the VM
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Handles the start state of the VM
-+ */
- static void kbase_arbiter_pm_vm_gpu_start(struct kbase_device *kbdev)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-+ bool freq_updated = false;
-
- lockdep_assert_held(&arb_vm_state->vm_state_lock);
-+ mutex_lock(&kbdev->arb.arb_freq.arb_freq_lock);
-+ if (kbdev->arb.arb_freq.freq_updated) {
-+ kbdev->arb.arb_freq.freq_updated = false;
-+ freq_updated = true;
-+ }
-+ mutex_unlock(&kbdev->arb.arb_freq.arb_freq_lock);
-+
-+ cancel_request_timer(kbdev);
- switch (arb_vm_state->vm_state) {
- case KBASE_VM_STATE_INITIALIZING:
- kbase_arbiter_pm_vm_set_state(kbdev,
-@@ -286,22 +547,43 @@ static void kbase_arbiter_pm_vm_gpu_start(struct kbase_device *kbdev)
- break;
- case KBASE_VM_STATE_STOPPED_GPU_REQUESTED:
- kbase_arbiter_pm_vm_set_state(kbdev, KBASE_VM_STATE_STARTING);
-+ arb_vm_state->interrupts_installed = true;
- kbase_install_interrupts(kbdev);
-+ /*
-+ * GPU GRANTED received while in stop can be a result of a
-+ * repartitioning.
-+ */
-+ kbase_gpuprops_req_curr_config_update(kbdev);
-+ /* curr_config will be updated while resuming the PM. */
- queue_work(arb_vm_state->vm_arb_wq,
- &arb_vm_state->vm_resume_work);
- break;
- case KBASE_VM_STATE_SUSPEND_WAIT_FOR_GRANT:
-+ kbase_pm_set_gpu_lost(kbdev, false);
- kbase_arbif_gpu_stopped(kbdev, false);
- kbase_arbiter_pm_vm_set_state(kbdev, KBASE_VM_STATE_SUSPENDED);
- break;
- default:
-- dev_warn(kbdev->dev,
-- "GPU_GRANTED when not expected - state %s\n",
-- kbase_arbiter_pm_vm_state_str(arb_vm_state->vm_state));
-+ /*
-+ * GPU_GRANTED can be received when there is a frequency update
-+ * Only show a warning if received in an unexpected state
-+ * without a frequency update
-+ */
-+ if (!freq_updated)
-+ dev_warn(kbdev->dev,
-+ "GPU_GRANTED when not expected - state %s\n",
-+ kbase_arbiter_pm_vm_state_str(
-+ arb_vm_state->vm_state));
- break;
- }
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_gpu_stop() - Handles the stop state of the VM
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Handles the start state of the VM
-+ */
- static void kbase_arbiter_pm_vm_gpu_stop(struct kbase_device *kbdev)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-@@ -344,9 +626,16 @@ static void kbase_arbiter_pm_vm_gpu_stop(struct kbase_device *kbdev)
- }
- }
-
-+/**
-+ * kbase_gpu_lost() - Kbase signals GPU is lost on a lost event signal
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * On GPU lost event signals GPU_LOST to the aribiter
-+ */
- static void kbase_gpu_lost(struct kbase_device *kbdev)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-+ bool handle_gpu_lost = false;
-
- lockdep_assert_held(&arb_vm_state->vm_state_lock);
-
-@@ -357,33 +646,47 @@ static void kbase_gpu_lost(struct kbase_device *kbdev)
- dev_warn(kbdev->dev, "GPU lost in state %s",
- kbase_arbiter_pm_vm_state_str(arb_vm_state->vm_state));
- kbase_arbiter_pm_vm_gpu_stop(kbdev);
-- mutex_unlock(&arb_vm_state->vm_state_lock);
-- kbase_pm_handle_gpu_lost(kbdev);
-- mutex_lock(&arb_vm_state->vm_state_lock);
-+ handle_gpu_lost = true;
- break;
- case KBASE_VM_STATE_STOPPING_IDLE:
- case KBASE_VM_STATE_STOPPING_ACTIVE:
- case KBASE_VM_STATE_SUSPEND_PENDING:
-- dev_info(kbdev->dev, "GPU lost while stopping");
-- mutex_unlock(&arb_vm_state->vm_state_lock);
-- kbase_pm_handle_gpu_lost(kbdev);
-- mutex_lock(&arb_vm_state->vm_state_lock);
-+ dev_dbg(kbdev->dev, "GPU lost while stopping");
-+ handle_gpu_lost = true;
- break;
- case KBASE_VM_STATE_SUSPENDED:
- case KBASE_VM_STATE_STOPPED:
- case KBASE_VM_STATE_STOPPED_GPU_REQUESTED:
-- dev_info(kbdev->dev, "GPU lost while already stopped");
-+ dev_dbg(kbdev->dev, "GPU lost while already stopped");
- break;
- case KBASE_VM_STATE_SUSPEND_WAIT_FOR_GRANT:
-- dev_info(kbdev->dev, "GPU lost while waiting to suspend");
-+ dev_dbg(kbdev->dev, "GPU lost while waiting to suspend");
- kbase_arbiter_pm_vm_set_state(kbdev, KBASE_VM_STATE_SUSPENDED);
- break;
- default:
- break;
- }
--
-+ if (handle_gpu_lost) {
-+ /* Releasing the VM state lock here is safe because
-+ * we are guaranteed to be in either STOPPING_IDLE,
-+ * STOPPING_ACTIVE or SUSPEND_PENDING at this point.
-+ * The only transitions that are valid from here are to
-+ * STOPPED, STOPPED_GPU_REQUESTED or SUSPENDED which can
-+ * only happen at the completion of the GPU lost handling.
-+ */
-+ mutex_unlock(&arb_vm_state->vm_state_lock);
-+ kbase_pm_handle_gpu_lost(kbdev);
-+ mutex_lock(&arb_vm_state->vm_state_lock);
-+ }
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_os_suspend_ready_state() - checks if VM is ready
-+ * to be moved to suspended state.
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Return: True if its ready to be suspended else False.
-+ */
- static inline bool kbase_arbiter_pm_vm_os_suspend_ready_state(
- struct kbase_device *kbdev)
- {
-@@ -398,6 +701,14 @@ static inline bool kbase_arbiter_pm_vm_os_suspend_ready_state(
- }
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_os_prepare_suspend() - Prepare OS to be in suspend state
-+ * until it receives the grant message from arbiter
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Prepares OS to be in suspend state until it receives GRANT message
-+ * from Arbiter asynchronously.
-+ */
- static void kbase_arbiter_pm_vm_os_prepare_suspend(struct kbase_device *kbdev)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-@@ -463,6 +774,14 @@ static void kbase_arbiter_pm_vm_os_prepare_suspend(struct kbase_device *kbdev)
- }
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_os_resume() - Resume OS function once it receives
-+ * a grant message from arbiter
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Resume OS function once it receives GRANT message
-+ * from Arbiter asynchronously.
-+ */
- static void kbase_arbiter_pm_vm_os_resume(struct kbase_device *kbdev)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-@@ -475,6 +794,7 @@ static void kbase_arbiter_pm_vm_os_resume(struct kbase_device *kbdev)
- kbase_arbiter_pm_vm_set_state(kbdev,
- KBASE_VM_STATE_STOPPED_GPU_REQUESTED);
- kbase_arbif_gpu_request(kbdev);
-+ start_request_timer(kbdev);
-
- /* Release lock and block resume OS function until we have
- * asynchronously received the GRANT message from the Arbiter and
-@@ -486,6 +806,14 @@ static void kbase_arbiter_pm_vm_os_resume(struct kbase_device *kbdev)
- mutex_lock(&arb_vm_state->vm_state_lock);
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_event() - Dispatch VM event to the state machine.
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ * @evt: VM event
-+ *
-+ * The state machine function. Receives events and transitions states
-+ * according the event received and the current state
-+ */
- void kbase_arbiter_pm_vm_event(struct kbase_device *kbdev,
- enum kbase_arbif_evt evt)
- {
-@@ -497,7 +825,9 @@ void kbase_arbiter_pm_vm_event(struct kbase_device *kbdev,
- mutex_lock(&arb_vm_state->vm_state_lock);
- dev_dbg(kbdev->dev, "%s %s\n", __func__,
- kbase_arbiter_pm_vm_event_str(evt));
--
-+ if (arb_vm_state->vm_state != KBASE_VM_STATE_INITIALIZING_WITH_GPU &&
-+ arb_vm_state->vm_state != KBASE_VM_STATE_INITIALIZING)
-+ KBASE_KTRACE_ADD(kbdev, ARB_VM_EVT, NULL, evt);
- switch (evt) {
- case KBASE_VM_GPU_GRANTED_EVT:
- kbase_arbiter_pm_vm_gpu_start(kbdev);
-@@ -506,7 +836,7 @@ void kbase_arbiter_pm_vm_event(struct kbase_device *kbdev,
- kbase_arbiter_pm_vm_gpu_stop(kbdev);
- break;
- case KBASE_VM_GPU_LOST_EVT:
-- dev_info(kbdev->dev, "KBASE_ARBIF_GPU_LOST_EVT!");
-+ dev_dbg(kbdev->dev, "KBASE_ARBIF_GPU_LOST_EVT!");
- kbase_gpu_lost(kbdev);
- break;
- case KBASE_VM_OS_SUSPEND_EVENT:
-@@ -530,8 +860,6 @@ void kbase_arbiter_pm_vm_event(struct kbase_device *kbdev,
- case KBASE_VM_REF_EVENT:
- switch (arb_vm_state->vm_state) {
- case KBASE_VM_STATE_STARTING:
-- KBASE_TLSTREAM_TL_EVENT_ARB_STARTED(kbdev, kbdev);
-- /* FALL THROUGH */
- case KBASE_VM_STATE_IDLE:
- kbase_arbiter_pm_vm_set_state(kbdev,
- KBASE_VM_STATE_ACTIVE);
-@@ -547,15 +875,21 @@ void kbase_arbiter_pm_vm_event(struct kbase_device *kbdev,
- break;
-
- case KBASE_VM_GPU_INITIALIZED_EVT:
-- lockdep_assert_held(&kbdev->pm.lock);
-- if (kbdev->pm.active_count > 0) {
-- kbase_arbiter_pm_vm_set_state(kbdev,
-- KBASE_VM_STATE_ACTIVE);
-- kbase_arbif_gpu_active(kbdev);
-- } else {
-- kbase_arbiter_pm_vm_set_state(kbdev,
-- KBASE_VM_STATE_IDLE);
-- kbase_arbif_gpu_idle(kbdev);
-+ switch (arb_vm_state->vm_state) {
-+ case KBASE_VM_STATE_INITIALIZING_WITH_GPU:
-+ lockdep_assert_held(&kbdev->pm.lock);
-+ if (kbdev->pm.active_count > 0) {
-+ kbase_arbiter_pm_vm_set_state(kbdev,
-+ KBASE_VM_STATE_ACTIVE);
-+ kbase_arbif_gpu_active(kbdev);
-+ } else {
-+ kbase_arbiter_pm_vm_set_state(kbdev,
-+ KBASE_VM_STATE_IDLE);
-+ kbase_arbif_gpu_idle(kbdev);
-+ }
-+ break;
-+ default:
-+ break;
- }
- break;
-
-@@ -566,6 +900,14 @@ void kbase_arbiter_pm_vm_event(struct kbase_device *kbdev,
- mutex_unlock(&arb_vm_state->vm_state_lock);
- }
-
-+KBASE_EXPORT_TEST_API(kbase_arbiter_pm_vm_event);
-+
-+/**
-+ * kbase_arbiter_pm_vm_wait_gpu_assignment() - VM wait for a GPU assignment.
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * VM waits for a GPU assignment.
-+ */
- static void kbase_arbiter_pm_vm_wait_gpu_assignment(struct kbase_device *kbdev)
- {
- struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-@@ -577,6 +919,12 @@ static void kbase_arbiter_pm_vm_wait_gpu_assignment(struct kbase_device *kbdev)
- dev_dbg(kbdev->dev, "Waiting for GPU assignment - done\n");
- }
-
-+/**
-+ * kbase_arbiter_pm_vm_gpu_assigned_lockheld() - Check if VM holds VM state lock
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Checks if the virtual machine holds VM state lock.
-+ */
- static inline bool kbase_arbiter_pm_vm_gpu_assigned_lockheld(
- struct kbase_device *kbdev)
- {
-@@ -587,11 +935,25 @@ static inline bool kbase_arbiter_pm_vm_gpu_assigned_lockheld(
- arb_vm_state->vm_state == KBASE_VM_STATE_ACTIVE);
- }
-
-+/**
-+ * kbase_arbiter_pm_ctx_active_handle_suspend() - Handle suspend operation for
-+ * arbitration mode
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ * @suspend_handler: The handler code for how to handle a suspend
-+ * that might occur
-+ *
-+ * This function handles a suspend event from the driver,
-+ * communicating with the arbiter and waiting synchronously for the GPU
-+ * to be granted again depending on the VM state.
-+ *
-+ * Return: 0 on success else 1 suspend handler isn not possible.
-+ */
- int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev,
- enum kbase_pm_suspend_handler suspend_handler)
- {
- struct kbasep_js_device_data *js_devdata = &kbdev->js_data;
- struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-+ int res = 0;
-
- if (kbdev->arb.arb_if) {
- mutex_lock(&arb_vm_state->vm_state_lock);
-@@ -606,30 +968,41 @@ int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev,
- kbase_arbiter_pm_vm_set_state(kbdev,
- KBASE_VM_STATE_STOPPED_GPU_REQUESTED);
- kbase_arbif_gpu_request(kbdev);
-+ start_request_timer(kbdev);
- } else if (arb_vm_state->vm_state ==
- KBASE_VM_STATE_INITIALIZING_WITH_GPU)
- break;
-
- if (suspend_handler !=
- KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE) {
-- if (suspend_handler ==
-- KBASE_PM_SUSPEND_HANDLER_VM_GPU_GRANTED
-- ||
-- kbdev->pm.active_count > 0)
-- break;
-
-- mutex_unlock(&arb_vm_state->vm_state_lock);
-- mutex_unlock(&kbdev->pm.lock);
-- mutex_unlock(&js_devdata->runpool_mutex);
-- return 1;
-- }
-+ /* In case of GPU lost, even if
-+ * active_count > 0, we no longer have GPU
-+ * access
-+ */
-+ if (kbase_pm_is_gpu_lost(kbdev))
-+ res = 1;
-
-- if (arb_vm_state->vm_state ==
-- KBASE_VM_STATE_INITIALIZING_WITH_GPU)
-+ switch (suspend_handler) {
-+ case KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE:
-+ res = 1;
-+ break;
-+ case KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE:
-+ if (kbdev->pm.active_count == 0)
-+ res = 1;
-+ break;
-+ case KBASE_PM_SUSPEND_HANDLER_VM_GPU_GRANTED:
-+ break;
-+ default:
-+ WARN(1, "Unknown suspend_handler\n");
-+ res = 1;
-+ break;
-+ }
- break;
-+ }
-
- /* Need to synchronously wait for GPU assignment */
-- arb_vm_state->vm_arb_users_waiting++;
-+ atomic_inc(&kbdev->pm.gpu_users_waiting);
- mutex_unlock(&arb_vm_state->vm_state_lock);
- mutex_unlock(&kbdev->pm.lock);
- mutex_unlock(&js_devdata->runpool_mutex);
-@@ -637,9 +1010,128 @@ int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev,
- mutex_lock(&js_devdata->runpool_mutex);
- mutex_lock(&kbdev->pm.lock);
- mutex_lock(&arb_vm_state->vm_state_lock);
-- arb_vm_state->vm_arb_users_waiting--;
-+ atomic_dec(&kbdev->pm.gpu_users_waiting);
- }
- mutex_unlock(&arb_vm_state->vm_state_lock);
- }
-- return 0;
-+ return res;
-+}
-+
-+/**
-+ * kbase_arbiter_pm_update_gpu_freq() - Updates GPU clock frequency received
-+ * from arbiter.
-+ * @arb_freq - Pointer to struchture holding GPU clock frequenecy data
-+ * @freq - New frequency value in KHz
-+ */
-+void kbase_arbiter_pm_update_gpu_freq(struct kbase_arbiter_freq *arb_freq,
-+ uint32_t freq)
-+{
-+ struct kbase_gpu_clk_notifier_data ndata;
-+
-+ mutex_lock(&arb_freq->arb_freq_lock);
-+ if (arb_freq->arb_freq != freq) {
-+ ndata.new_rate = freq * KHZ_TO_HZ;
-+ ndata.old_rate = arb_freq->arb_freq * KHZ_TO_HZ;
-+ ndata.gpu_clk_handle = arb_freq;
-+ arb_freq->arb_freq = freq;
-+ arb_freq->freq_updated = true;
-+ if (arb_freq->nb)
-+ arb_freq->nb->notifier_call(arb_freq->nb,
-+ POST_RATE_CHANGE, &ndata);
-+ }
-+
-+ mutex_unlock(&arb_freq->arb_freq_lock);
-+}
-+
-+/**
-+ * enumerate_arb_gpu_clk() - Enumerate a GPU clock on the given index
-+ * @kbdev - kbase_device pointer
-+ * @index - GPU clock index
-+ *
-+ * Returns pointer to structure holding GPU clock frequency data reported from
-+ * arbiter, only index 0 is valid.
-+ */
-+static void *enumerate_arb_gpu_clk(struct kbase_device *kbdev,
-+ unsigned int index)
-+{
-+ if (index == 0)
-+ return &kbdev->arb.arb_freq;
-+ return NULL;
-+}
-+
-+/**
-+ * get_arb_gpu_clk_rate() - Get the current rate of GPU clock frequency value
-+ * @kbdev - kbase_device pointer
-+ * @index - GPU clock index
-+ *
-+ * Returns the GPU clock frequency value saved when gpu is granted from arbiter
-+ */
-+static unsigned long get_arb_gpu_clk_rate(struct kbase_device *kbdev,
-+ void *gpu_clk_handle)
-+{
-+ uint32_t freq;
-+ struct kbase_arbiter_freq *arb_dev_freq =
-+ (struct kbase_arbiter_freq *) gpu_clk_handle;
-+
-+ mutex_lock(&arb_dev_freq->arb_freq_lock);
-+ /* Convert from KHz to Hz */
-+ freq = arb_dev_freq->arb_freq * KHZ_TO_HZ;
-+ mutex_unlock(&arb_dev_freq->arb_freq_lock);
-+ return freq;
-+}
-+
-+/**
-+ * arb_gpu_clk_notifier_register() - Register a clock rate change notifier.
-+ * @kbdev - kbase_device pointer
-+ * @gpu_clk_handle - Handle unique to the enumerated GPU clock
-+ * @nb - notifier block containing the callback function pointer
-+ *
-+ * Returns 0 on success, negative error code otherwise.
-+ *
-+ * This function registers a callback function that is invoked whenever the
-+ * frequency of the clock corresponding to @gpu_clk_handle changes.
-+ */
-+static int arb_gpu_clk_notifier_register(struct kbase_device *kbdev,
-+ void *gpu_clk_handle, struct notifier_block *nb)
-+{
-+ int ret = 0;
-+ struct kbase_arbiter_freq *arb_dev_freq =
-+ (struct kbase_arbiter_freq *)gpu_clk_handle;
-+
-+ if (!arb_dev_freq->nb)
-+ arb_dev_freq->nb = nb;
-+ else
-+ ret = -EBUSY;
-+
-+ return ret;
-+}
-+
-+/**
-+ * gpu_clk_notifier_unregister() - Unregister clock rate change notifier
-+ * @kbdev - kbase_device pointer
-+ * @gpu_clk_handle - Handle unique to the enumerated GPU clock
-+ * @nb - notifier block containing the callback function pointer
-+ *
-+ * This function pointer is used to unregister a callback function that
-+ * was previously registered to get notified of a frequency change of the
-+ * clock corresponding to @gpu_clk_handle.
-+ */
-+static void arb_gpu_clk_notifier_unregister(struct kbase_device *kbdev,
-+ void *gpu_clk_handle, struct notifier_block *nb)
-+{
-+ struct kbase_arbiter_freq *arb_dev_freq =
-+ (struct kbase_arbiter_freq *)gpu_clk_handle;
-+ if (arb_dev_freq->nb == nb) {
-+ arb_dev_freq->nb = NULL;
-+ } else {
-+ dev_err(kbdev->dev, "%s - notifier did not match\n",
-+ __func__);
-+ }
- }
-+
-+struct kbase_clk_rate_trace_op_conf arb_clk_rate_trace_ops = {
-+ .get_gpu_clk_rate = get_arb_gpu_clk_rate,
-+ .enumerate_gpu_clk = enumerate_arb_gpu_clk,
-+ .gpu_clk_notifier_register = arb_gpu_clk_notifier_register,
-+ .gpu_clk_notifier_unregister = arb_gpu_clk_notifier_unregister
-+};
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_pm.h b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_pm.h
-index 3c49eb1..1f570bb 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_pm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/arbiter/mali_kbase_arbiter_pm.h
-@@ -1,28 +1,7 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--
--/*
-- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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
-@@ -38,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-@@ -116,10 +93,18 @@ void kbase_arbiter_pm_early_term(struct kbase_device *kbdev);
- * kbase_arbiter_pm_release_interrupts() - Release the GPU interrupts
- * @kbdev: The kbase device structure for the device (must be a valid pointer)
- *
-- * Releases interrupts if needed (GPU is available) otherwise does nothing
-+ * Releases interrupts and set the interrupt flag to false
- */
- void kbase_arbiter_pm_release_interrupts(struct kbase_device *kbdev);
-
-+/**
-+ * kbase_arbiter_pm_install_interrupts() - Install the GPU interrupts
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Install interrupts and set the interrupt_install flag to true.
-+ */
-+int kbase_arbiter_pm_install_interrupts(struct kbase_device *kbdev);
-+
- /**
- * kbase_arbiter_pm_vm_event() - Dispatch VM event to the state machine
- * @kbdev: The kbase device structure for the device (must be a valid pointer)
-@@ -156,4 +141,54 @@ int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev,
- */
- void kbase_arbiter_pm_vm_stopped(struct kbase_device *kbdev);
-
-+/**
-+ * kbase_arbiter_set_max_config() - Set the max config data in kbase device.
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer).
-+ * @max_l2_slices: The maximum number of L2 slices.
-+ * @max_core_mask: The largest core mask.
-+ *
-+ * This function handles a stop event for the VM.
-+ * It will update the VM state and forward the stop event to the driver.
-+ */
-+void kbase_arbiter_set_max_config(struct kbase_device *kbdev,
-+ uint32_t max_l2_slices,
-+ uint32_t max_core_mask);
-+
-+/**
-+ * kbase_arbiter_pm_gpu_assigned() - Determine if this VM has access to the GPU
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Return: 0 if the VM does not have access, 1 if it does, and a negative number
-+ * if an error occurred
-+ */
-+int kbase_arbiter_pm_gpu_assigned(struct kbase_device *kbdev);
-+
-+extern struct kbase_clk_rate_trace_op_conf arb_clk_rate_trace_ops;
-+
-+/**
-+ * struct kbase_arbiter_freq - Holding the GPU clock frequency data retrieved
-+ * from arbiter
-+ * @arb_freq: GPU clock frequency value
-+ * @arb_freq_lock: Mutex protecting access to arbfreq value
-+ * @nb: Notifier block to receive rate change callbacks
-+ * @freq_updated: Flag to indicate whether a frequency changed has just been
-+ * communicated to avoid "GPU_GRANTED when not expected" warning
-+ */
-+struct kbase_arbiter_freq {
-+ uint32_t arb_freq;
-+ struct mutex arb_freq_lock;
-+ struct notifier_block *nb;
-+ bool freq_updated;
-+};
-+
-+/**
-+ * kbase_arbiter_pm_update_gpu_freq() - Update GPU frequency
-+ * @arb_freq: Pointer to GPU clock frequency data
-+ * @freq: The new frequency
-+ *
-+ * Updates the GPU frequency and triggers any notifications
-+ */
-+void kbase_arbiter_pm_update_gpu_freq(struct kbase_arbiter_freq *arb_freq,
-+ uint32_t freq);
-+
- #endif /*_MALI_KBASE_ARBITER_PM_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/Kbuild
-index 2449e80..5dbcff3 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2014-2019 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2014-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,51 +16,34 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
--BACKEND += \
-- backend/gpu/mali_kbase_cache_policy_backend.c \
-- backend/gpu/mali_kbase_device_hw.c \
-- backend/gpu/mali_kbase_gpuprops_backend.c \
-- backend/gpu/mali_kbase_irq_linux.c \
-- backend/gpu/mali_kbase_instr_backend.c \
-- backend/gpu/mali_kbase_js_backend.c \
-- backend/gpu/mali_kbase_pm_backend.c \
-- backend/gpu/mali_kbase_pm_driver.c \
-- backend/gpu/mali_kbase_pm_metrics.c \
-- backend/gpu/mali_kbase_pm_ca.c \
-- backend/gpu/mali_kbase_pm_always_on.c \
-- backend/gpu/mali_kbase_pm_coarse_demand.c \
-- backend/gpu/mali_kbase_pm_policy.c \
-- backend/gpu/mali_kbase_time.c \
-- backend/gpu/mali_kbase_l2_mmu_config.c
-+mali_kbase-y += \
-+ backend/gpu/mali_kbase_cache_policy_backend.o \
-+ backend/gpu/mali_kbase_gpuprops_backend.o \
-+ backend/gpu/mali_kbase_irq_linux.o \
-+ backend/gpu/mali_kbase_js_backend.o \
-+ backend/gpu/mali_kbase_pm_backend.o \
-+ backend/gpu/mali_kbase_pm_driver.o \
-+ backend/gpu/mali_kbase_pm_metrics.o \
-+ backend/gpu/mali_kbase_pm_ca.o \
-+ backend/gpu/mali_kbase_pm_always_on.o \
-+ backend/gpu/mali_kbase_pm_coarse_demand.o \
-+ backend/gpu/mali_kbase_pm_policy.o \
-+ backend/gpu/mali_kbase_time.o \
-+ backend/gpu/mali_kbase_l2_mmu_config.o \
-+ backend/gpu/mali_kbase_clk_rate_trace_mgr.o
-
--ifeq ($(MALI_USE_CSF),1)
--# empty
--else
-- BACKEND += \
-- backend/gpu/mali_kbase_jm_as.c \
-- backend/gpu/mali_kbase_debug_job_fault_backend.c \
-- backend/gpu/mali_kbase_jm_hw.c \
-- backend/gpu/mali_kbase_jm_rb.c
-+ifeq ($(MALI_USE_CSF),0)
-+ mali_kbase-y += \
-+ backend/gpu/mali_kbase_instr_backend.o \
-+ backend/gpu/mali_kbase_jm_as.o \
-+ backend/gpu/mali_kbase_debug_job_fault_backend.o \
-+ backend/gpu/mali_kbase_jm_hw.o \
-+ backend/gpu/mali_kbase_jm_rb.o
- endif
-
--ifeq ($(MALI_CUSTOMER_RELEASE),0)
--BACKEND += \
-- backend/gpu/mali_kbase_pm_always_on_demand.c
--endif
-
--ifeq ($(CONFIG_MALI_DEVFREQ),y)
--BACKEND += \
-- backend/gpu/mali_kbase_devfreq.c
--endif
-+mali_kbase-$(CONFIG_MALI_DEVFREQ) += \
-+ backend/gpu/mali_kbase_devfreq.o
-
--ifeq ($(CONFIG_MALI_NO_MALI),y)
-- # Dummy model
-- BACKEND += backend/gpu/mali_kbase_model_dummy.c
-- BACKEND += backend/gpu/mali_kbase_model_linux.c
-- # HW error simulation
-- BACKEND += backend/gpu/mali_kbase_model_error_generator.c
--endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_backend_config.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_backend_config.h
-index 4a61f96..6924fdb 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_backend_config.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_backend_config.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_cache_policy_backend.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_cache_policy_backend.c
-index 7378bfd..e542ccf 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_cache_policy_backend.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_cache_policy_backend.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2015-2016,2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2016, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "backend/gpu/mali_kbase_cache_policy_backend.h"
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
-
- void kbase_cache_set_coherency_mode(struct kbase_device *kbdev,
- u32 mode)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_cache_policy_backend.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_cache_policy_backend.h
-index f78ada7..278125a 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_cache_policy_backend.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_cache_policy_backend.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2015-2016 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2016, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,16 +17,13 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- #ifndef _KBASE_CACHE_POLICY_BACKEND_H_
- #define _KBASE_CACHE_POLICY_BACKEND_H_
-
- #include "mali_kbase.h"
--#include "mali_base_kernel.h"
-+#include <uapi/gpu/arm/midgard/mali_base_kernel.h>
-
- /**
- * kbase_cache_set_coherency_mode() - Sets the system coherency mode
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_clk_rate_trace_mgr.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_clk_rate_trace_mgr.c
-new file mode 100644
-index 0000000..6ad0f58
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_clk_rate_trace_mgr.c
-@@ -0,0 +1,325 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * Implementation of the GPU clock rate trace manager.
-+ */
-+
-+#include <mali_kbase.h>
-+#include <mali_kbase_config_defaults.h>
-+#include <linux/clk.h>
-+#include <asm/div64.h>
-+#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
-+
-+#ifdef CONFIG_TRACE_POWER_GPU_FREQUENCY
-+#include <trace/events/power_gpu_frequency.h>
-+#else
-+#include "mali_power_gpu_frequency_trace.h"
-+#endif
-+
-+#ifndef CLK_RATE_TRACE_OPS
-+#define CLK_RATE_TRACE_OPS (NULL)
-+#endif
-+
-+/**
-+ * get_clk_rate_trace_callbacks() - Returns pointer to clk trace ops.
-+ * @kbdev: Pointer to kbase device, used to check if arbitration is enabled
-+ * when compiled with arbiter support.
-+ * Return: Pointer to clk trace ops if supported or NULL.
-+ */
-+static struct kbase_clk_rate_trace_op_conf *
-+get_clk_rate_trace_callbacks(struct kbase_device *kbdev __maybe_unused)
-+{
-+ /* base case */
-+ struct kbase_clk_rate_trace_op_conf *callbacks =
-+ (struct kbase_clk_rate_trace_op_conf *)CLK_RATE_TRACE_OPS;
-+#if defined(CONFIG_MALI_ARBITER_SUPPORT) && defined(CONFIG_OF)
-+ const void *arbiter_if_node;
-+
-+ if (WARN_ON(!kbdev) || WARN_ON(!kbdev->dev))
-+ return callbacks;
-+
-+ arbiter_if_node =
-+ of_get_property(kbdev->dev->of_node, "arbiter_if", NULL);
-+ /* Arbitration enabled, override the callback pointer.*/
-+ if (arbiter_if_node)
-+ callbacks = &arb_clk_rate_trace_ops;
-+ else
-+ dev_dbg(kbdev->dev,
-+ "Arbitration supported but disabled by platform. Leaving clk rate callbacks as default.\n");
-+
-+#endif
-+
-+ return callbacks;
-+}
-+
-+static int gpu_clk_rate_change_notifier(struct notifier_block *nb,
-+ unsigned long event, void *data)
-+{
-+ struct kbase_gpu_clk_notifier_data *ndata = data;
-+ struct kbase_clk_data *clk_data =
-+ container_of(nb, struct kbase_clk_data, clk_rate_change_nb);
-+ struct kbase_clk_rate_trace_manager *clk_rtm = clk_data->clk_rtm;
-+ unsigned long flags;
-+
-+ if (WARN_ON_ONCE(clk_data->gpu_clk_handle != ndata->gpu_clk_handle))
-+ return NOTIFY_BAD;
-+
-+ spin_lock_irqsave(&clk_rtm->lock, flags);
-+ if (event == POST_RATE_CHANGE) {
-+ if (!clk_rtm->gpu_idle &&
-+ (clk_data->clock_val != ndata->new_rate)) {
-+ kbase_clk_rate_trace_manager_notify_all(
-+ clk_rtm, clk_data->index, ndata->new_rate);
-+ }
-+
-+ clk_data->clock_val = ndata->new_rate;
-+ }
-+ spin_unlock_irqrestore(&clk_rtm->lock, flags);
-+
-+ return NOTIFY_DONE;
-+}
-+
-+static int gpu_clk_data_init(struct kbase_device *kbdev,
-+ void *gpu_clk_handle, unsigned int index)
-+{
-+ struct kbase_clk_rate_trace_op_conf *callbacks;
-+ struct kbase_clk_data *clk_data;
-+ struct kbase_clk_rate_trace_manager *clk_rtm = &kbdev->pm.clk_rtm;
-+ int ret = 0;
-+
-+ callbacks = get_clk_rate_trace_callbacks(kbdev);
-+
-+ if (WARN_ON(!callbacks) ||
-+ WARN_ON(!gpu_clk_handle) ||
-+ WARN_ON(index >= BASE_MAX_NR_CLOCKS_REGULATORS))
-+ return -EINVAL;
-+
-+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
-+ if (!clk_data) {
-+ dev_err(kbdev->dev, "Failed to allocate data for clock enumerated at index %u", index);
-+ return -ENOMEM;
-+ }
-+
-+ clk_data->index = (u8)index;
-+ clk_data->gpu_clk_handle = gpu_clk_handle;
-+ /* Store the initial value of clock */
-+ clk_data->clock_val =
-+ callbacks->get_gpu_clk_rate(kbdev, gpu_clk_handle);
-+
-+ {
-+ /* At the initialization time, GPU is powered off. */
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&clk_rtm->lock, flags);
-+ kbase_clk_rate_trace_manager_notify_all(
-+ clk_rtm, clk_data->index, 0);
-+ spin_unlock_irqrestore(&clk_rtm->lock, flags);
-+ }
-+
-+ clk_data->clk_rtm = clk_rtm;
-+ clk_rtm->clks[index] = clk_data;
-+
-+ clk_data->clk_rate_change_nb.notifier_call =
-+ gpu_clk_rate_change_notifier;
-+
-+ if (callbacks->gpu_clk_notifier_register)
-+ ret = callbacks->gpu_clk_notifier_register(kbdev,
-+ gpu_clk_handle, &clk_data->clk_rate_change_nb);
-+ if (ret) {
-+ dev_err(kbdev->dev, "Failed to register notifier for clock enumerated at index %u", index);
-+ kfree(clk_data);
-+ }
-+
-+ return ret;
-+}
-+
-+int kbase_clk_rate_trace_manager_init(struct kbase_device *kbdev)
-+{
-+ struct kbase_clk_rate_trace_op_conf *callbacks;
-+ struct kbase_clk_rate_trace_manager *clk_rtm = &kbdev->pm.clk_rtm;
-+ unsigned int i;
-+ int ret = 0;
-+
-+ callbacks = get_clk_rate_trace_callbacks(kbdev);
-+
-+ spin_lock_init(&clk_rtm->lock);
-+ INIT_LIST_HEAD(&clk_rtm->listeners);
-+
-+ /* Return early if no callbacks provided for clock rate tracing */
-+ if (!callbacks) {
-+ WRITE_ONCE(clk_rtm->clk_rate_trace_ops, NULL);
-+ return 0;
-+ }
-+
-+ clk_rtm->gpu_idle = true;
-+
-+ for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
-+ void *gpu_clk_handle =
-+ callbacks->enumerate_gpu_clk(kbdev, i);
-+
-+ if (!gpu_clk_handle)
-+ break;
-+
-+ ret = gpu_clk_data_init(kbdev, gpu_clk_handle, i);
-+ if (ret)
-+ goto error;
-+ }
-+
-+ /* Activate clock rate trace manager if at least one GPU clock was
-+ * enumerated.
-+ */
-+ if (i) {
-+ WRITE_ONCE(clk_rtm->clk_rate_trace_ops, callbacks);
-+ } else {
-+ dev_info(kbdev->dev, "No clock(s) available for rate tracing");
-+ WRITE_ONCE(clk_rtm->clk_rate_trace_ops, NULL);
-+ }
-+
-+ return 0;
-+
-+error:
-+ while (i--) {
-+ clk_rtm->clk_rate_trace_ops->gpu_clk_notifier_unregister(
-+ kbdev, clk_rtm->clks[i]->gpu_clk_handle,
-+ &clk_rtm->clks[i]->clk_rate_change_nb);
-+ kfree(clk_rtm->clks[i]);
-+ }
-+
-+ return ret;
-+}
-+
-+void kbase_clk_rate_trace_manager_term(struct kbase_device *kbdev)
-+{
-+ struct kbase_clk_rate_trace_manager *clk_rtm = &kbdev->pm.clk_rtm;
-+ unsigned int i;
-+
-+ WARN_ON(!list_empty(&clk_rtm->listeners));
-+
-+ if (!clk_rtm->clk_rate_trace_ops)
-+ return;
-+
-+ for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
-+ if (!clk_rtm->clks[i])
-+ break;
-+
-+ if (clk_rtm->clk_rate_trace_ops->gpu_clk_notifier_unregister)
-+ clk_rtm->clk_rate_trace_ops->gpu_clk_notifier_unregister
-+ (kbdev, clk_rtm->clks[i]->gpu_clk_handle,
-+ &clk_rtm->clks[i]->clk_rate_change_nb);
-+ kfree(clk_rtm->clks[i]);
-+ }
-+
-+ WRITE_ONCE(clk_rtm->clk_rate_trace_ops, NULL);
-+}
-+
-+void kbase_clk_rate_trace_manager_gpu_active(struct kbase_device *kbdev)
-+{
-+ struct kbase_clk_rate_trace_manager *clk_rtm = &kbdev->pm.clk_rtm;
-+ unsigned int i;
-+ unsigned long flags;
-+
-+ if (!clk_rtm->clk_rate_trace_ops)
-+ return;
-+
-+ spin_lock_irqsave(&clk_rtm->lock, flags);
-+
-+ for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
-+ struct kbase_clk_data *clk_data = clk_rtm->clks[i];
-+
-+ if (!clk_data)
-+ break;
-+
-+ if (unlikely(!clk_data->clock_val))
-+ continue;
-+
-+ kbase_clk_rate_trace_manager_notify_all(
-+ clk_rtm, clk_data->index, clk_data->clock_val);
-+ }
-+
-+ clk_rtm->gpu_idle = false;
-+ spin_unlock_irqrestore(&clk_rtm->lock, flags);
-+}
-+
-+void kbase_clk_rate_trace_manager_gpu_idle(struct kbase_device *kbdev)
-+{
-+ struct kbase_clk_rate_trace_manager *clk_rtm = &kbdev->pm.clk_rtm;
-+ unsigned int i;
-+ unsigned long flags;
-+
-+ if (!clk_rtm->clk_rate_trace_ops)
-+ return;
-+
-+ spin_lock_irqsave(&clk_rtm->lock, flags);
-+
-+ for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
-+ struct kbase_clk_data *clk_data = clk_rtm->clks[i];
-+
-+ if (!clk_data)
-+ break;
-+
-+ if (unlikely(!clk_data->clock_val))
-+ continue;
-+
-+ kbase_clk_rate_trace_manager_notify_all(
-+ clk_rtm, clk_data->index, 0);
-+ }
-+
-+ clk_rtm->gpu_idle = true;
-+ spin_unlock_irqrestore(&clk_rtm->lock, flags);
-+}
-+
-+void kbase_clk_rate_trace_manager_notify_all(
-+ struct kbase_clk_rate_trace_manager *clk_rtm,
-+ u32 clk_index,
-+ unsigned long new_rate)
-+{
-+ struct kbase_clk_rate_listener *pos;
-+ struct kbase_device *kbdev;
-+
-+ lockdep_assert_held(&clk_rtm->lock);
-+
-+ kbdev = container_of(clk_rtm, struct kbase_device, pm.clk_rtm);
-+
-+ dev_dbg(kbdev->dev, "%s - GPU clock %u rate changed to %lu, pid: %d",
-+ __func__, clk_index, new_rate, current->pid);
-+
-+ /* Raise standard `power/gpu_frequency` ftrace event */
-+ {
-+ unsigned long new_rate_khz = new_rate;
-+
-+#if BITS_PER_LONG == 64
-+ do_div(new_rate_khz, 1000);
-+#elif BITS_PER_LONG == 32
-+ new_rate_khz /= 1000;
-+#else
-+#error "unsigned long division is not supported for this architecture"
-+#endif
-+
-+ trace_gpu_frequency(new_rate_khz, clk_index);
-+ }
-+
-+ /* Notify the listeners. */
-+ list_for_each_entry(pos, &clk_rtm->listeners, node) {
-+ pos->notify(pos, clk_index, new_rate);
-+ }
-+}
-+KBASE_EXPORT_TEST_API(kbase_clk_rate_trace_manager_notify_all);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_clk_rate_trace_mgr.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_clk_rate_trace_mgr.h
-new file mode 100644
-index 0000000..f7ec9d1
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_clk_rate_trace_mgr.h
-@@ -0,0 +1,154 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CLK_RATE_TRACE_MGR_
-+#define _KBASE_CLK_RATE_TRACE_MGR_
-+
-+/* The index of top clock domain in kbase_clk_rate_trace_manager:clks. */
-+#define KBASE_CLOCK_DOMAIN_TOP (0)
-+
-+/* The index of shader-cores clock domain in
-+ * kbase_clk_rate_trace_manager:clks.
-+ */
-+#define KBASE_CLOCK_DOMAIN_SHADER_CORES (1)
-+
-+/**
-+ * struct kbase_clk_data - Data stored per enumerated GPU clock.
-+ *
-+ * @clk_rtm: Pointer to clock rate trace manager object.
-+ * @gpu_clk_handle: Handle unique to the enumerated GPU clock.
-+ * @plat_private: Private data for the platform to store into
-+ * @clk_rate_change_nb: notifier block containing the pointer to callback
-+ * function that is invoked whenever the rate of
-+ * enumerated GPU clock changes.
-+ * @clock_val: Current rate of the enumerated GPU clock.
-+ * @index: Index at which the GPU clock was enumerated.
-+ */
-+struct kbase_clk_data {
-+ struct kbase_clk_rate_trace_manager *clk_rtm;
-+ void *gpu_clk_handle;
-+ void *plat_private;
-+ struct notifier_block clk_rate_change_nb;
-+ unsigned long clock_val;
-+ u8 index;
-+};
-+
-+/**
-+ * kbase_clk_rate_trace_manager_init - Initialize GPU clock rate trace manager.
-+ *
-+ * @kbdev: Device pointer
-+ *
-+ * Return: 0 if success, or an error code on failure.
-+ */
-+int kbase_clk_rate_trace_manager_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_clk_rate_trace_manager_term - Terminate GPU clock rate trace manager.
-+ *
-+ * @kbdev: Device pointer
-+ */
-+void kbase_clk_rate_trace_manager_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_clk_rate_trace_manager_gpu_active - Inform GPU clock rate trace
-+ * manager of GPU becoming active.
-+ *
-+ * @kbdev: Device pointer
-+ */
-+void kbase_clk_rate_trace_manager_gpu_active(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_clk_rate_trace_manager_gpu_idle - Inform GPU clock rate trace
-+ * manager of GPU becoming idle.
-+ * @kbdev: Device pointer
-+ */
-+void kbase_clk_rate_trace_manager_gpu_idle(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_clk_rate_trace_manager_subscribe_no_lock() - Add freq change listener.
-+ *
-+ * @clk_rtm: Clock rate manager instance.
-+ * @listener: Listener handle
-+ *
-+ * kbase_clk_rate_trace_manager:lock must be held by the caller.
-+ */
-+static inline void kbase_clk_rate_trace_manager_subscribe_no_lock(
-+ struct kbase_clk_rate_trace_manager *clk_rtm,
-+ struct kbase_clk_rate_listener *listener)
-+{
-+ lockdep_assert_held(&clk_rtm->lock);
-+ list_add(&listener->node, &clk_rtm->listeners);
-+}
-+
-+/**
-+ * kbase_clk_rate_trace_manager_subscribe() - Add freq change listener.
-+ *
-+ * @clk_rtm: Clock rate manager instance.
-+ * @listener: Listener handle
-+ */
-+static inline void kbase_clk_rate_trace_manager_subscribe(
-+ struct kbase_clk_rate_trace_manager *clk_rtm,
-+ struct kbase_clk_rate_listener *listener)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&clk_rtm->lock, flags);
-+ kbase_clk_rate_trace_manager_subscribe_no_lock(
-+ clk_rtm, listener);
-+ spin_unlock_irqrestore(&clk_rtm->lock, flags);
-+}
-+
-+/**
-+ * kbase_clk_rate_trace_manager_unsubscribe() - Remove freq change listener.
-+ *
-+ * @clk_rtm: Clock rate manager instance.
-+ * @listener: Listener handle
-+ */
-+static inline void kbase_clk_rate_trace_manager_unsubscribe(
-+ struct kbase_clk_rate_trace_manager *clk_rtm,
-+ struct kbase_clk_rate_listener *listener)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&clk_rtm->lock, flags);
-+ list_del(&listener->node);
-+ spin_unlock_irqrestore(&clk_rtm->lock, flags);
-+}
-+
-+/**
-+ * kbase_clk_rate_trace_manager_notify_all() - Notify all clock \
-+ * rate listeners.
-+ *
-+ * @clk_rtm: Clock rate manager instance.
-+ * @clock_index: Clock index.
-+ * @new_rate: New clock frequency(Hz)
-+ *
-+ * kbase_clk_rate_trace_manager:lock must be locked.
-+ * This function is exported to be used by clock rate trace test
-+ * portal.
-+ */
-+void kbase_clk_rate_trace_manager_notify_all(
-+ struct kbase_clk_rate_trace_manager *clk_rtm,
-+ u32 clock_index,
-+ unsigned long new_rate);
-+
-+#endif /* _KBASE_CLK_RATE_TRACE_MGR_ */
-+
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_debug_job_fault_backend.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_debug_job_fault_backend.c
-index b05844e..e121b41 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_debug_job_fault_backend.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_debug_job_fault_backend.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2015,2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2015, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,13 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include "mali_kbase_debug_job_fault.h"
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-
- /*GPU_CONTROL_REG(r)*/
- static int gpu_control_reg_snapshot[] = {
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c
-index 2806f05..8c31499 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
-@@ -27,40 +26,53 @@
- #include <linux/of.h>
- #include <linux/clk.h>
- #include <linux/devfreq.h>
--#ifdef CONFIG_DEVFREQ_THERMAL
-+#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
- #include <linux/devfreq_cooling.h>
- #endif
-
- #include <linux/version.h>
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
- #include <linux/pm_opp.h>
--#else /* Linux >= 3.13 */
--/* In 3.13 the OPP include header file, types, and functions were all
-- * renamed. Use the old filename for the include, and define the new names to
-- * the old, when an old kernel is detected.
-- */
--#include <linux/opp.h>
--#define dev_pm_opp opp
--#define dev_pm_opp_get_voltage opp_get_voltage
--#define dev_pm_opp_get_opp_count opp_get_opp_count
--#define dev_pm_opp_find_freq_ceil opp_find_freq_ceil
--#define dev_pm_opp_find_freq_floor opp_find_freq_floor
--#endif /* Linux >= 3.13 */
-
- /**
-- * opp_translate - Translate nominal OPP frequency from devicetree into real
-- * frequency and core mask
-- * @kbdev: Device pointer
-- * @freq: Nominal frequency
-- * @core_mask: Pointer to u64 to store core mask to
-- * @freqs: Pointer to array of frequencies
-- * @volts: Pointer to array of voltages
-+ * get_voltage() - Get the voltage value corresponding to the nominal frequency
-+ * used by devfreq.
-+ * @kbdev: Device pointer
-+ * @freq: Nominal frequency in Hz passed by devfreq.
-+ *
-+ * This function will be called only when the opp table which is compatible with
-+ * "operating-points-v2-mali", is not present in the devicetree for GPU device.
- *
-- * This function will only perform translation if an operating-points-v2-mali
-- * table is present in devicetree. If one is not present then it will return an
-- * untranslated frequency and all cores enabled.
-+ * Return: Voltage value in milli volts, 0 in case of error.
- */
--static void opp_translate(struct kbase_device *kbdev, unsigned long freq,
-+static unsigned long get_voltage(struct kbase_device *kbdev, unsigned long freq)
-+{
-+ struct dev_pm_opp *opp;
-+ unsigned long voltage = 0;
-+
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
-+ rcu_read_lock();
-+#endif
-+
-+ opp = dev_pm_opp_find_freq_exact(kbdev->dev, freq, true);
-+
-+ if (IS_ERR_OR_NULL(opp))
-+ dev_err(kbdev->dev, "Failed to get opp (%ld)\n", PTR_ERR(opp));
-+ else {
-+ voltage = dev_pm_opp_get_voltage(opp);
-+#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE
-+ dev_pm_opp_put(opp);
-+#endif
-+ }
-+
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
-+ rcu_read_unlock();
-+#endif
-+
-+ /* Return the voltage in milli volts */
-+ return voltage / 1000;
-+}
-+
-+void kbase_devfreq_opp_translate(struct kbase_device *kbdev, unsigned long freq,
- u64 *core_mask, unsigned long *freqs, unsigned long *volts)
- {
- unsigned int i;
-@@ -82,12 +94,17 @@ static void opp_translate(struct kbase_device *kbdev, unsigned long freq,
- }
-
- /* If failed to find OPP, return all cores enabled
-- * and nominal frequency
-+ * and nominal frequency and the corresponding voltage.
- */
- if (i == kbdev->num_opps) {
-+ unsigned long voltage = get_voltage(kbdev, freq);
-+
- *core_mask = kbdev->gpu_props.props.raw_props.shader_present;
-- for (i = 0; i < kbdev->nr_clocks; i++)
-+
-+ for (i = 0; i < kbdev->nr_clocks; i++) {
- freqs[i] = freq;
-+ volts[i] = voltage;
-+ }
- }
- }
-
-@@ -104,18 +121,18 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
-
- nominal_freq = *target_freq;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
- rcu_read_lock();
- #endif
- opp = devfreq_recommended_opp(dev, &nominal_freq, flags);
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
- rcu_read_unlock();
- #endif
- if (IS_ERR_OR_NULL(opp)) {
- dev_err(dev, "Failed to get opp (%ld)\n", PTR_ERR(opp));
- return PTR_ERR(opp);
- }
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE
- dev_pm_opp_put(opp);
- #endif
-
-@@ -127,9 +144,10 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
- return 0;
- }
-
-- opp_translate(kbdev, nominal_freq, &core_mask, freqs, volts);
-+ kbase_devfreq_opp_translate(kbdev, nominal_freq, &core_mask,
-+ freqs, volts);
-
--#ifdef CONFIG_REGULATOR
-+#if IS_ENABLED(CONFIG_REGULATOR)
- /* Regulators and clocks work in pairs: every clock has a regulator,
- * and we never expect to have more regulators than clocks.
- *
-@@ -177,7 +195,7 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
- }
- }
-
--#ifdef CONFIG_REGULATOR
-+#if IS_ENABLED(CONFIG_REGULATOR)
- for (i = 0; i < kbdev->nr_clocks; i++) {
- if (kbdev->regulators[i] &&
- kbdev->current_voltages[i] != volts[i] &&
-@@ -238,6 +256,10 @@ kbase_devfreq_status(struct device *dev, struct devfreq_dev_status *stat)
- stat->current_frequency = kbdev->current_nominal_freq;
- stat->private_data = NULL;
-
-+#if MALI_USE_CSF && defined CONFIG_DEVFREQ_THERMAL
-+ kbase_ipa_reset_data(kbdev);
-+#endif
-+
- return 0;
- }
-
-@@ -249,11 +271,11 @@ static int kbase_devfreq_init_freq_table(struct kbase_device *kbdev,
- unsigned long freq;
- struct dev_pm_opp *opp;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
- rcu_read_lock();
- #endif
- count = dev_pm_opp_get_opp_count(kbdev->dev);
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
- rcu_read_unlock();
- #endif
- if (count < 0)
-@@ -264,20 +286,20 @@ static int kbase_devfreq_init_freq_table(struct kbase_device *kbdev,
- if (!dp->freq_table)
- return -ENOMEM;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
- rcu_read_lock();
- #endif
- for (i = 0, freq = ULONG_MAX; i < count; i++, freq--) {
- opp = dev_pm_opp_find_freq_floor(kbdev->dev, &freq);
- if (IS_ERR(opp))
- break;
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE
- dev_pm_opp_put(opp);
--#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) */
-+#endif /* KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE */
-
- dp->freq_table[i] = freq;
- }
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
-+#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE
- rcu_read_unlock();
- #endif
-
-@@ -309,18 +331,21 @@ static void kbase_devfreq_term_freq_table(struct kbase_device *kbdev)
- struct devfreq_dev_profile *dp = &kbdev->devfreq_profile;
-
- kfree(dp->freq_table);
-+ dp->freq_table = NULL;
- }
-
- static void kbase_devfreq_term_core_mask_table(struct kbase_device *kbdev)
- {
- kfree(kbdev->devfreq_table);
-+ kbdev->devfreq_table = NULL;
- }
-
- static void kbase_devfreq_exit(struct device *dev)
- {
- struct kbase_device *kbdev = dev_get_drvdata(dev);
-
-- kbase_devfreq_term_freq_table(kbdev);
-+ if (kbdev)
-+ kbase_devfreq_term_freq_table(kbdev);
- }
-
- static void kbasep_devfreq_read_suspend_clock(struct kbase_device *kbdev,
-@@ -359,7 +384,7 @@ static void kbasep_devfreq_read_suspend_clock(struct kbase_device *kbdev,
-
- static int kbase_devfreq_init_core_mask_table(struct kbase_device *kbdev)
- {
--#if KERNEL_VERSION(3, 18, 0) > LINUX_VERSION_CODE || !defined(CONFIG_OF)
-+#ifndef CONFIG_OF
- /* OPP table initialization requires at least the capability to get
- * regulators and clocks from the device tree, as well as parsing
- * arrays of unsigned integer values.
-@@ -392,7 +417,7 @@ static int kbase_devfreq_init_core_mask_table(struct kbase_device *kbdev)
- u64 core_mask, opp_freq,
- real_freqs[BASE_MAX_NR_CLOCKS_REGULATORS];
- int err;
--#ifdef CONFIG_REGULATOR
-+#if IS_ENABLED(CONFIG_REGULATOR)
- u32 opp_volts[BASE_MAX_NR_CLOCKS_REGULATORS];
- #endif
-
-@@ -420,7 +445,7 @@ static int kbase_devfreq_init_core_mask_table(struct kbase_device *kbdev)
- err);
- continue;
- }
--#ifdef CONFIG_REGULATOR
-+#if IS_ENABLED(CONFIG_REGULATOR)
- err = of_property_read_u32_array(node,
- "opp-microvolt", opp_volts, kbdev->nr_regulators);
- if (err < 0) {
-@@ -474,7 +499,7 @@ static int kbase_devfreq_init_core_mask_table(struct kbase_device *kbdev)
- kbdev->devfreq_table[i].real_freqs[j] =
- real_freqs[j];
- }
--#ifdef CONFIG_REGULATOR
-+#if IS_ENABLED(CONFIG_REGULATOR)
- if (kbdev->nr_regulators > 0) {
- int j;
-
-@@ -493,11 +518,9 @@ static int kbase_devfreq_init_core_mask_table(struct kbase_device *kbdev)
- kbdev->num_opps = i;
-
- return 0;
--#endif /* KERNEL_VERSION(3, 18, 0) > LINUX_VERSION_CODE */
-+#endif /* CONFIG_OF */
- }
-
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
--
- static const char *kbase_devfreq_req_type_name(enum kbase_devfreq_work_type type)
- {
- const char *p;
-@@ -554,27 +577,26 @@ static void kbase_devfreq_suspend_resume_worker(struct work_struct *work)
- }
- }
-
--#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */
--
- void kbase_devfreq_enqueue_work(struct kbase_device *kbdev,
- enum kbase_devfreq_work_type work_type)
- {
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
- unsigned long flags;
-
- WARN_ON(work_type == DEVFREQ_WORK_NONE);
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-- kbdev->devfreq_queue.req_type = work_type;
-- queue_work(kbdev->devfreq_queue.workq, &kbdev->devfreq_queue.work);
-+ /* Skip enqueuing a work if workqueue has already been terminated. */
-+ if (likely(kbdev->devfreq_queue.workq)) {
-+ kbdev->devfreq_queue.req_type = work_type;
-+ queue_work(kbdev->devfreq_queue.workq,
-+ &kbdev->devfreq_queue.work);
-+ }
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
- dev_dbg(kbdev->dev, "Enqueuing devfreq req: %s\n",
- kbase_devfreq_req_type_name(work_type));
--#endif
- }
-
- static int kbase_devfreq_work_init(struct kbase_device *kbdev)
- {
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
- kbdev->devfreq_queue.req_type = DEVFREQ_WORK_NONE;
- kbdev->devfreq_queue.acted_type = DEVFREQ_WORK_RESUME;
-
-@@ -584,17 +606,23 @@ static int kbase_devfreq_work_init(struct kbase_device *kbdev)
-
- INIT_WORK(&kbdev->devfreq_queue.work,
- kbase_devfreq_suspend_resume_worker);
--#endif
- return 0;
- }
-
- static void kbase_devfreq_work_term(struct kbase_device *kbdev)
- {
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
-- destroy_workqueue(kbdev->devfreq_queue.workq);
--#endif
-+ unsigned long flags;
-+ struct workqueue_struct *workq;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ workq = kbdev->devfreq_queue.workq;
-+ kbdev->devfreq_queue.workq = NULL;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ destroy_workqueue(workq);
- }
-
-+
- int kbase_devfreq_init(struct kbase_device *kbdev)
- {
- struct devfreq_dev_profile *dp;
-@@ -631,19 +659,11 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
- /* Record the maximum frequency possible */
- kbdev->gpu_props.props.core_props.gpu_freq_khz_max =
- dp->freq_table[0] / 1000;
-- };
--
-- err = kbase_devfreq_init_core_mask_table(kbdev);
-- if (err) {
-- kbase_devfreq_term_freq_table(kbdev);
-- return err;
- }
-
-- /* Initialise devfreq suspend/resume workqueue */
-- err = kbase_devfreq_work_init(kbdev);
-+ err = kbase_devfreq_init_core_mask_table(kbdev);
- if (err) {
- kbase_devfreq_term_freq_table(kbdev);
-- dev_err(kbdev->dev, "Devfreq initialization failed");
- return err;
- }
-
-@@ -651,13 +671,27 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
- "simple_ondemand", NULL);
- if (IS_ERR(kbdev->devfreq)) {
- err = PTR_ERR(kbdev->devfreq);
-- kbase_devfreq_work_term(kbdev);
-+ kbdev->devfreq = NULL;
-+ kbase_devfreq_term_core_mask_table(kbdev);
- kbase_devfreq_term_freq_table(kbdev);
-+ dev_err(kbdev->dev, "Fail to add devfreq device(%d)\n", err);
-+ return err;
-+ }
-+
-+ /* Initialize devfreq suspend/resume workqueue */
-+ err = kbase_devfreq_work_init(kbdev);
-+ if (err) {
-+ if (devfreq_remove_device(kbdev->devfreq))
-+ dev_err(kbdev->dev, "Fail to rm devfreq\n");
-+ kbdev->devfreq = NULL;
-+ kbase_devfreq_term_core_mask_table(kbdev);
-+ dev_err(kbdev->dev, "Fail to init devfreq workqueue\n");
- return err;
- }
-
- /* devfreq_add_device only copies a few of kbdev->dev's fields, so
-- * set drvdata explicitly so IPA models can access kbdev. */
-+ * set drvdata explicitly so IPA models can access kbdev.
-+ */
- dev_set_drvdata(&kbdev->devfreq->dev, kbdev);
-
- err = devfreq_register_opp_notifier(kbdev->dev, kbdev->devfreq);
-@@ -667,11 +701,11 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
- goto opp_notifier_failed;
- }
-
--#ifdef CONFIG_DEVFREQ_THERMAL
-+#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
- err = kbase_ipa_init(kbdev);
- if (err) {
- dev_err(kbdev->dev, "IPA initialization failed\n");
-- goto cooling_failed;
-+ goto ipa_init_failed;
- }
-
- kbdev->devfreq_cooling = of_devfreq_cooling_register_power(
-@@ -683,23 +717,28 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
- dev_err(kbdev->dev,
- "Failed to register cooling device (%d)\n",
- err);
-- goto cooling_failed;
-+ goto cooling_reg_failed;
- }
- #endif
-
- return 0;
-
--#ifdef CONFIG_DEVFREQ_THERMAL
--cooling_failed:
-+#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
-+cooling_reg_failed:
-+ kbase_ipa_term(kbdev);
-+ipa_init_failed:
- devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq);
- #endif /* CONFIG_DEVFREQ_THERMAL */
-+
- opp_notifier_failed:
-+ kbase_devfreq_work_term(kbdev);
-+
- if (devfreq_remove_device(kbdev->devfreq))
- dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err);
-- else
-- kbdev->devfreq = NULL;
-
-- kbase_devfreq_work_term(kbdev);
-+ kbdev->devfreq = NULL;
-+
-+ kbase_devfreq_term_core_mask_table(kbdev);
-
- return err;
- }
-@@ -710,7 +749,7 @@ void kbase_devfreq_term(struct kbase_device *kbdev)
-
- dev_dbg(kbdev->dev, "Term Mali devfreq\n");
-
--#ifdef CONFIG_DEVFREQ_THERMAL
-+#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
- if (kbdev->devfreq_cooling)
- devfreq_cooling_unregister(kbdev->devfreq_cooling);
-
-@@ -719,6 +758,8 @@ void kbase_devfreq_term(struct kbase_device *kbdev)
-
- devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq);
-
-+ kbase_devfreq_work_term(kbdev);
-+
- err = devfreq_remove_device(kbdev->devfreq);
- if (err)
- dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err);
-@@ -726,6 +767,4 @@ void kbase_devfreq_term(struct kbase_device *kbdev)
- kbdev->devfreq = NULL;
-
- kbase_devfreq_term_core_mask_table(kbdev);
--
-- kbase_devfreq_work_term(kbdev);
- }
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.h
-index 8c976b2..901827e 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _BASE_DEVFREQ_H_
-@@ -43,4 +42,20 @@ void kbase_devfreq_force_freq(struct kbase_device *kbdev, unsigned long freq);
- void kbase_devfreq_enqueue_work(struct kbase_device *kbdev,
- enum kbase_devfreq_work_type work_type);
-
-+/**
-+ * kbase_devfreq_opp_translate - Translate nominal OPP frequency from devicetree
-+ * into real frequency & voltage pair, along with
-+ * core mask
-+ * @kbdev: Device pointer
-+ * @freq: Nominal frequency
-+ * @core_mask: Pointer to u64 to store core mask to
-+ * @freqs: Pointer to array of frequencies
-+ * @volts: Pointer to array of voltages
-+ *
-+ * This function will only perform translation if an operating-points-v2-mali
-+ * table is present in devicetree. If one is not present then it will return an
-+ * untranslated frequency (and corresponding voltage) and all cores enabled.
-+ */
-+void kbase_devfreq_opp_translate(struct kbase_device *kbdev, unsigned long freq,
-+ u64 *core_mask, unsigned long *freqs, unsigned long *volts);
- #endif /* _BASE_DEVFREQ_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_device_hw.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_device_hw.c
-deleted file mode 100755
-index 5943e4e..0000000
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_device_hw.c
-+++ /dev/null
-@@ -1,388 +0,0 @@
--/*
-- *
-- * (C) COPYRIGHT 2014-2016, 2018-2020 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- */
--
--
--/*
-- *
-- */
--#include <mali_kbase.h>
--#include <gpu/mali_kbase_gpu_fault.h>
--#include <backend/gpu/mali_kbase_instr_internal.h>
--#include <backend/gpu/mali_kbase_pm_internal.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
--#include <mali_kbase_reset_gpu.h>
--#include <mmu/mali_kbase_mmu.h>
--
--#if !defined(CONFIG_MALI_NO_MALI)
--
--#ifdef CONFIG_DEBUG_FS
--
--int kbase_io_history_resize(struct kbase_io_history *h, u16 new_size)
--{
-- struct kbase_io_access *old_buf;
-- struct kbase_io_access *new_buf;
-- unsigned long flags;
--
-- if (!new_size)
-- goto out_err; /* The new size must not be 0 */
--
-- new_buf = vmalloc(new_size * sizeof(*h->buf));
-- if (!new_buf)
-- goto out_err;
--
-- spin_lock_irqsave(&h->lock, flags);
--
-- old_buf = h->buf;
--
-- /* Note: we won't bother with copying the old data over. The dumping
-- * logic wouldn't work properly as it relies on 'count' both as a
-- * counter and as an index to the buffer which would have changed with
-- * the new array. This is a corner case that we don't need to support.
-- */
-- h->count = 0;
-- h->size = new_size;
-- h->buf = new_buf;
--
-- spin_unlock_irqrestore(&h->lock, flags);
--
-- vfree(old_buf);
--
-- return 0;
--
--out_err:
-- return -1;
--}
--
--
--int kbase_io_history_init(struct kbase_io_history *h, u16 n)
--{
-- h->enabled = false;
-- spin_lock_init(&h->lock);
-- h->count = 0;
-- h->size = 0;
-- h->buf = NULL;
-- if (kbase_io_history_resize(h, n))
-- return -1;
--
-- return 0;
--}
--
--
--void kbase_io_history_term(struct kbase_io_history *h)
--{
-- vfree(h->buf);
-- h->buf = NULL;
--}
--
--
--/* kbase_io_history_add - add new entry to the register access history
-- *
-- * @h: Pointer to the history data structure
-- * @addr: Register address
-- * @value: The value that is either read from or written to the register
-- * @write: 1 if it's a register write, 0 if it's a read
-- */
--static void kbase_io_history_add(struct kbase_io_history *h,
-- void __iomem const *addr, u32 value, u8 write)
--{
-- struct kbase_io_access *io;
-- unsigned long flags;
--
-- spin_lock_irqsave(&h->lock, flags);
--
-- io = &h->buf[h->count % h->size];
-- io->addr = (uintptr_t)addr | write;
-- io->value = value;
-- ++h->count;
-- /* If count overflows, move the index by the buffer size so the entire
-- * buffer will still be dumped later */
-- if (unlikely(!h->count))
-- h->count = h->size;
--
-- spin_unlock_irqrestore(&h->lock, flags);
--}
--
--
--void kbase_io_history_dump(struct kbase_device *kbdev)
--{
-- struct kbase_io_history *const h = &kbdev->io_history;
-- u16 i;
-- size_t iters;
-- unsigned long flags;
--
-- if (!unlikely(h->enabled))
-- return;
--
-- spin_lock_irqsave(&h->lock, flags);
--
-- dev_err(kbdev->dev, "Register IO History:");
-- iters = (h->size > h->count) ? h->count : h->size;
-- dev_err(kbdev->dev, "Last %zu register accesses of %zu total:\n", iters,
-- h->count);
-- for (i = 0; i < iters; ++i) {
-- struct kbase_io_access *io =
-- &h->buf[(h->count - iters + i) % h->size];
-- char const access = (io->addr & 1) ? 'w' : 'r';
--
-- dev_err(kbdev->dev, "%6i: %c: reg 0x%016lx val %08x\n", i,
-- access, (unsigned long)(io->addr & ~0x1), io->value);
-- }
--
-- spin_unlock_irqrestore(&h->lock, flags);
--}
--
--
--#endif /* CONFIG_DEBUG_FS */
--
--
--void kbase_reg_write(struct kbase_device *kbdev, u32 offset, u32 value)
--{
-- KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered);
-- KBASE_DEBUG_ASSERT(kbdev->dev != NULL);
--
-- writel(value, kbdev->reg + offset);
--
--#ifdef CONFIG_DEBUG_FS
-- if (unlikely(kbdev->io_history.enabled))
-- kbase_io_history_add(&kbdev->io_history, kbdev->reg + offset,
-- value, 1);
--#endif /* CONFIG_DEBUG_FS */
-- dev_dbg(kbdev->dev, "w: reg %08x val %08x", offset, value);
--}
--
--KBASE_EXPORT_TEST_API(kbase_reg_write);
--
--u32 kbase_reg_read(struct kbase_device *kbdev, u32 offset)
--{
-- u32 val;
-- KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered);
-- KBASE_DEBUG_ASSERT(kbdev->dev != NULL);
--
-- val = readl(kbdev->reg + offset);
--
--#ifdef CONFIG_DEBUG_FS
-- if (unlikely(kbdev->io_history.enabled))
-- kbase_io_history_add(&kbdev->io_history, kbdev->reg + offset,
-- val, 0);
--#endif /* CONFIG_DEBUG_FS */
-- dev_dbg(kbdev->dev, "r: reg %08x val %08x", offset, val);
--
-- return val;
--}
--
--KBASE_EXPORT_TEST_API(kbase_reg_read);
--
--bool kbase_is_gpu_lost(struct kbase_device *kbdev)
--{
-- u32 val;
--
-- val = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID));
--
-- return val == 0;
--}
--#endif /* !defined(CONFIG_MALI_NO_MALI) */
--
--/**
-- * kbase_report_gpu_fault - Report a GPU fault.
-- * @kbdev: Kbase device pointer
-- * @multiple: Zero if only GPU_FAULT was raised, non-zero if MULTIPLE_GPU_FAULTS
-- * was also set
-- *
-- * This function is called from the interrupt handler when a GPU fault occurs.
-- * It reports the details of the fault using dev_warn().
-- */
--static void kbase_report_gpu_fault(struct kbase_device *kbdev, int multiple)
--{
-- u32 status = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS));
-- u64 address = (u64) kbase_reg_read(kbdev,
-- GPU_CONTROL_REG(GPU_FAULTADDRESS_HI)) << 32;
--
-- address |= kbase_reg_read(kbdev,
-- GPU_CONTROL_REG(GPU_FAULTADDRESS_LO));
--
-- meson_gpu_fault ++;
-- dev_warn(kbdev->dev, "GPU Fault 0x%08x (%s) at 0x%016llx",
-- status,
-- kbase_gpu_exception_name(status & 0xFF),
-- address);
-- if (multiple)
-- dev_warn(kbdev->dev, "There were multiple GPU faults - some have not been reported\n");
--}
--
--static bool kbase_gpu_fault_interrupt(struct kbase_device *kbdev, int multiple)
--{
-- kbase_report_gpu_fault(kbdev, multiple);
-- return false;
--}
--
--void kbase_gpu_start_cache_clean_nolock(struct kbase_device *kbdev)
--{
-- u32 irq_mask;
--
-- lockdep_assert_held(&kbdev->hwaccess_lock);
--
-- if (kbdev->cache_clean_in_progress) {
-- /* If this is called while another clean is in progress, we
-- * can't rely on the current one to flush any new changes in
-- * the cache. Instead, trigger another cache clean immediately
-- * after this one finishes.
-- */
-- kbdev->cache_clean_queued = true;
-- return;
-- }
--
-- /* Enable interrupt */
-- irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK));
-- kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK),
-- irq_mask | CLEAN_CACHES_COMPLETED);
--
-- KBASE_KTRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, 0);
-- kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-- GPU_COMMAND_CLEAN_INV_CACHES);
--
-- kbdev->cache_clean_in_progress = true;
--}
--
--void kbase_gpu_start_cache_clean(struct kbase_device *kbdev)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-- kbase_gpu_start_cache_clean_nolock(kbdev);
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
--}
--
--void kbase_gpu_cache_clean_wait_complete(struct kbase_device *kbdev)
--{
-- lockdep_assert_held(&kbdev->hwaccess_lock);
--
-- kbdev->cache_clean_queued = false;
-- kbdev->cache_clean_in_progress = false;
-- wake_up(&kbdev->cache_clean_wait);
--}
--
--static void kbase_clean_caches_done(struct kbase_device *kbdev)
--{
-- u32 irq_mask;
-- unsigned long flags;
--
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
--
-- if (kbdev->cache_clean_queued) {
-- kbdev->cache_clean_queued = false;
--
-- KBASE_KTRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, 0);
-- kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-- GPU_COMMAND_CLEAN_INV_CACHES);
-- } else {
-- /* Disable interrupt */
-- irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK));
-- kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK),
-- irq_mask & ~CLEAN_CACHES_COMPLETED);
--
-- kbase_gpu_cache_clean_wait_complete(kbdev);
-- }
--
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
--}
--
--static inline bool get_cache_clean_flag(struct kbase_device *kbdev)
--{
-- bool cache_clean_in_progress;
-- unsigned long flags;
--
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-- cache_clean_in_progress = kbdev->cache_clean_in_progress;
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
--
-- return cache_clean_in_progress;
--}
--
--void kbase_gpu_wait_cache_clean(struct kbase_device *kbdev)
--{
-- while (get_cache_clean_flag(kbdev)) {
-- wait_event_interruptible(kbdev->cache_clean_wait,
-- !kbdev->cache_clean_in_progress);
-- }
--}
--
--int kbase_gpu_wait_cache_clean_timeout(struct kbase_device *kbdev,
-- unsigned int wait_timeout_ms)
--{
-- long remaining = msecs_to_jiffies(wait_timeout_ms);
--
-- while (remaining && get_cache_clean_flag(kbdev)) {
-- remaining = wait_event_timeout(kbdev->cache_clean_wait,
-- !kbdev->cache_clean_in_progress,
-- remaining);
-- }
--
-- return (remaining ? 0 : -ETIMEDOUT);
--}
--
--void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val)
--{
-- bool clear_gpu_fault = false;
--
-- KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, val);
-- if (val & GPU_FAULT)
-- clear_gpu_fault = kbase_gpu_fault_interrupt(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);
--
-- KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, val);
-- kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), val);
--
-- /* kbase_pm_check_transitions (called by kbase_pm_power_changed) 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. The same applies to kbase_clean_caches_done() - if another
-- * clean was queued, it might trigger another clean, which might
-- * generate another interrupt which shouldn't be missed.
-- */
--
-- if (val & CLEAN_CACHES_COMPLETED)
-- kbase_clean_caches_done(kbdev);
--
-- if (val & POWER_CHANGED_ALL) {
-- kbase_pm_power_changed(kbdev);
-- } else if (val & CLEAN_CACHES_COMPLETED) {
-- /* If cache line evict messages can be lost when shader cores
-- * power down then we need to flush the L2 cache before powering
-- * down cores. When the flush completes, the shaders' state
-- * machine needs to be re-invoked to proceed with powering down
-- * cores.
-- */
-- if (kbdev->pm.backend.l2_always_on ||
-- kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_921))
-- kbase_pm_power_changed(kbdev);
-- }
--
--
-- KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_DONE, NULL, val);
--}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_device_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_device_internal.h
-deleted file mode 100644
-index 2e1d011..0000000
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_device_internal.h
-+++ /dev/null
-@@ -1,127 +0,0 @@
--/*
-- *
-- * (C) COPYRIGHT 2014,2019-2020 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- */
--
--
--
--/*
-- * Backend-specific HW access device APIs
-- */
--
--#ifndef _KBASE_DEVICE_INTERNAL_H_
--#define _KBASE_DEVICE_INTERNAL_H_
--
--/**
-- * kbase_reg_write - write to GPU register
-- * @kbdev: Kbase device pointer
-- * @offset: Offset of register
-- * @value: Value to write
-- *
-- * Caller must ensure the GPU is powered (@kbdev->pm.gpu_powered != false).
-- */
--void kbase_reg_write(struct kbase_device *kbdev, u32 offset, u32 value);
--
--/**
-- * kbase_reg_read - read from GPU register
-- * @kbdev: Kbase device pointer
-- * @offset: Offset of register
-- *
-- * Caller must ensure the GPU is powered (@kbdev->pm.gpu_powered != false).
-- *
-- * Return: Value in desired register
-- */
--u32 kbase_reg_read(struct kbase_device *kbdev, u32 offset);
--
--/**
-- * kbase_is_gpu_lost() - Has the GPU been lost.
-- * @kbdev: Kbase device pointer
-- *
-- * This function will return true if the GPU has been lost.
-- * When this happens register reads will be zero. A zero GPU_ID is
-- * invalid so this is used to detect GPU_LOST
-- *
-- * Return: True if GPU LOST
-- */
--bool kbase_is_gpu_lost(struct kbase_device *kbdev);
--
--/**
-- * kbase_gpu_start_cache_clean - Start a cache clean
-- * @kbdev: Kbase device
-- *
-- * Issue a cache clean and invalidate command to hardware. This function will
-- * take hwaccess_lock.
-- */
--void kbase_gpu_start_cache_clean(struct kbase_device *kbdev);
--
--/**
-- * kbase_gpu_start_cache_clean_nolock - Start a cache clean
-- * @kbdev: Kbase device
-- *
-- * Issue a cache clean and invalidate command to hardware. hwaccess_lock
-- * must be held by the caller.
-- */
--void kbase_gpu_start_cache_clean_nolock(struct kbase_device *kbdev);
--
--/**
-- * kbase_gpu_wait_cache_clean - Wait for cache cleaning to finish
-- * @kbdev: Kbase device
-- *
-- * This function will take hwaccess_lock, and may sleep.
-- */
--void kbase_gpu_wait_cache_clean(struct kbase_device *kbdev);
--
--/**
-- * kbase_gpu_wait_cache_clean_timeout - Wait for certain time for cache
-- * cleaning to finish
-- * @kbdev: Kbase device
-- * @wait_timeout_ms: Time, in milli seconds, to wait for cache clean to complete.
-- *
-- * This function will take hwaccess_lock, and may sleep. This is supposed to be
-- * called from paths (like GPU reset) where an indefinite wait for the completion
-- * of cache clean operation can cause deadlock, as the operation may never
-- * complete.
-- *
-- * Return: 0 if successful or a negative error code on failure.
-- */
--int kbase_gpu_wait_cache_clean_timeout(struct kbase_device *kbdev,
-- unsigned int wait_timeout_ms);
--
--/**
-- * kbase_gpu_cache_clean_wait_complete - Called after the cache cleaning is
-- * finished. Would also be called after
-- * the GPU reset.
-- * @kbdev: Kbase device
-- *
-- * Caller must hold the hwaccess_lock.
-- */
--void kbase_gpu_cache_clean_wait_complete(struct kbase_device *kbdev);
--
--/**
-- * kbase_gpu_interrupt - GPU interrupt handler
-- * @kbdev: Kbase device pointer
-- * @val: The value of the GPU IRQ status register which triggered the call
-- *
-- * This function is called from the interrupt handler when a GPU irq is to be
-- * handled.
-- */
--void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val);
--
--#endif /* _KBASE_DEVICE_INTERNAL_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_gpuprops_backend.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_gpuprops_backend.c
-index 352afa1..11088db 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_gpuprops_backend.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_gpuprops_backend.c
-@@ -1,12 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -17,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -26,7 +24,7 @@
- */
-
- #include <mali_kbase.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include <backend/gpu/mali_kbase_pm_internal.h>
- #include <mali_kbase_hwaccess_gpuprops.h>
-
-@@ -41,8 +39,19 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev,
-
- registers.l2_features = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(L2_FEATURES));
-+ registers.core_features = 0;
-+#if !MALI_USE_CSF
-+ /* TGOx */
- registers.core_features = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(CORE_FEATURES));
-+#else /* !MALI_USE_CSF */
-+ if (((registers.gpu_id & GPU_ID2_PRODUCT_MODEL) ==
-+ GPU_ID2_PRODUCT_TGRX) ||
-+ ((registers.gpu_id & GPU_ID2_PRODUCT_MODEL) ==
-+ GPU_ID2_PRODUCT_TVAX))
-+ registers.core_features =
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(CORE_FEATURES));
-+#endif /* MALI_USE_CSF */
- registers.tiler_features = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(TILER_FEATURES));
- registers.mem_features = kbase_reg_read(kbdev,
-@@ -51,12 +60,20 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev,
- GPU_CONTROL_REG(MMU_FEATURES));
- registers.as_present = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(AS_PRESENT));
-+#if !MALI_USE_CSF
- registers.js_present = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(JS_PRESENT));
-+#else /* !MALI_USE_CSF */
-+ registers.js_present = 0;
-+#endif /* !MALI_USE_CSF */
-
- for (i = 0; i < GPU_MAX_JOB_SLOTS; i++)
-+#if !MALI_USE_CSF
- registers.js_features[i] = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(JS_FEATURES_REG(i)));
-+#else /* !MALI_USE_CSF */
-+ registers.js_features[i] = 0;
-+#endif /* !MALI_USE_CSF */
-
- for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++)
- registers.texture_features[i] = kbase_reg_read(kbdev,
-@@ -93,13 +110,49 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev,
- registers.stack_present_hi = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(STACK_PRESENT_HI));
-
-- if (!kbase_is_gpu_lost(kbdev)) {
-+ if (registers.gpu_id >= GPU_ID2_PRODUCT_MAKE(11, 8, 5, 2)) {
-+ registers.gpu_features_lo = kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(GPU_FEATURES_LO));
-+ registers.gpu_features_hi = kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(GPU_FEATURES_HI));
-+ } else {
-+ registers.gpu_features_lo = 0;
-+ registers.gpu_features_hi = 0;
-+ }
-+
-+ if (!kbase_is_gpu_removed(kbdev)) {
- *regdump = registers;
- return 0;
- } else
- return -EIO;
- }
-
-+int kbase_backend_gpuprops_get_curr_config(struct kbase_device *kbdev,
-+ struct kbase_current_config_regdump *curr_config_regdump)
-+{
-+ if (WARN_ON(!kbdev) || WARN_ON(!curr_config_regdump))
-+ return -EINVAL;
-+
-+ curr_config_regdump->mem_features = kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(MEM_FEATURES));
-+
-+ curr_config_regdump->shader_present_lo = kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(SHADER_PRESENT_LO));
-+ curr_config_regdump->shader_present_hi = kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(SHADER_PRESENT_HI));
-+
-+ curr_config_regdump->l2_present_lo = kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(L2_PRESENT_LO));
-+ curr_config_regdump->l2_present_hi = kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(L2_PRESENT_HI));
-+
-+ if (WARN_ON(kbase_is_gpu_removed(kbdev)))
-+ return -EIO;
-+
-+ return 0;
-+
-+}
-+
- int kbase_backend_gpuprops_get_features(struct kbase_device *kbdev,
- struct kbase_gpuprops_regdump *regdump)
- {
-@@ -112,7 +165,7 @@ int kbase_backend_gpuprops_get_features(struct kbase_device *kbdev,
- coherency_features = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(COHERENCY_FEATURES));
-
-- if (kbase_is_gpu_lost(kbdev))
-+ if (kbase_is_gpu_removed(kbdev))
- return -EIO;
-
- regdump->coherency_features = coherency_features;
-@@ -135,11 +188,15 @@ int kbase_backend_gpuprops_get_l2_features(struct kbase_device *kbdev,
- if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_L2_CONFIG)) {
- u32 l2_features = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(L2_FEATURES));
-+ u32 l2_config =
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_CONFIG));
-+
-
-- if (kbase_is_gpu_lost(kbdev))
-+ if (kbase_is_gpu_removed(kbdev))
- return -EIO;
-
- regdump->l2_features = l2_features;
-+ regdump->l2_config = l2_config;
- }
-
- return 0;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_backend.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_backend.c
-index 8b320c7..d7edf30 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_backend.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_backend.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * GPU backend instrumentation APIs.
- */
-@@ -29,7 +26,7 @@
- #include <mali_kbase.h>
- #include <gpu/mali_kbase_gpu_regmap.h>
- #include <mali_kbase_hwaccess_instr.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include <backend/gpu/mali_kbase_instr_internal.h>
-
-
-@@ -71,12 +68,12 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
-
- /* Configure */
- prfcnt_config = kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT;
--#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY_VIA_DEBUG_FS
-- if (kbdev->hwcnt.backend.use_secondary_override)
-+#ifdef CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
-+ prfcnt_config |= kbdev->hwcnt.backend.override_counter_set
-+ << PRFCNT_CONFIG_SETSELECT_SHIFT;
- #else
-- if (enable->use_secondary)
-+ prfcnt_config |= enable->counter_set << PRFCNT_CONFIG_SETSELECT_SHIFT;
- #endif
-- prfcnt_config |= 1 << PRFCNT_CONFIG_SETSELECT_SHIFT;
-
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG),
- prfcnt_config | PRFCNT_CONFIG_MODE_OFF);
-@@ -87,7 +84,7 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
- enable->dump_buffer >> 32);
-
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN),
-- enable->jm_bm);
-+ enable->fe_bm);
-
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN),
- enable->shader_bm);
-@@ -110,7 +107,7 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
-
- err = 0;
-
-- dev_dbg(kbdev->dev, "HW counters dumping set-up for context %p", kctx);
-+ dev_dbg(kbdev->dev, "HW counters dumping set-up for context %pK", kctx);
- return err;
- out_err:
- return err;
-@@ -170,11 +167,10 @@ int kbase_instr_hwcnt_disable_internal(struct kbase_context *kctx)
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags);
-
-- dev_dbg(kbdev->dev, "HW counters dumping disabled for context %p",
-+ dev_dbg(kbdev->dev, "HW counters dumping disabled for context %pK",
- kctx);
-
- err = 0;
--
- out:
- return err;
- }
-@@ -194,7 +190,8 @@ int kbase_instr_hwcnt_request_dump(struct kbase_context *kctx)
-
- if (kbdev->hwcnt.backend.state != KBASE_INSTR_STATE_IDLE) {
- /* HW counters are disabled or another dump is ongoing, or we're
-- * resetting */
-+ * resetting
-+ */
- goto unlock;
- }
-
-@@ -204,7 +201,6 @@ int kbase_instr_hwcnt_request_dump(struct kbase_context *kctx)
- */
- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DUMPING;
-
--
- /* Reconfigure the dump address */
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO),
- kbdev->hwcnt.addr & 0xFFFFFFFF);
-@@ -218,14 +214,13 @@ int kbase_instr_hwcnt_request_dump(struct kbase_context *kctx)
- kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
- GPU_COMMAND_PRFCNT_SAMPLE);
-
-- dev_dbg(kbdev->dev, "HW counters dumping done for context %p", kctx);
-+ dev_dbg(kbdev->dev, "HW counters dumping done for context %pK", kctx);
-
- err = 0;
-
- unlock:
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
-
--
- return err;
- }
- KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_request_dump);
-@@ -254,40 +249,6 @@ bool kbase_instr_hwcnt_dump_complete(struct kbase_context *kctx,
- }
- KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_complete);
-
--void kbasep_cache_clean_worker(struct work_struct *data)
--{
-- struct kbase_device *kbdev;
-- unsigned long flags, pm_flags;
--
-- kbdev = container_of(data, struct kbase_device,
-- hwcnt.backend.cache_clean_work);
--
-- spin_lock_irqsave(&kbdev->hwaccess_lock, pm_flags);
-- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
--
-- /* Clean and invalidate the caches so we're sure the mmu tables for the
-- * dump buffer is valid.
-- */
-- KBASE_DEBUG_ASSERT(kbdev->hwcnt.backend.state ==
-- KBASE_INSTR_STATE_REQUEST_CLEAN);
-- kbase_gpu_start_cache_clean_nolock(kbdev);
-- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags);
--
-- kbase_gpu_wait_cache_clean(kbdev);
--
-- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
-- KBASE_DEBUG_ASSERT(kbdev->hwcnt.backend.state ==
-- KBASE_INSTR_STATE_REQUEST_CLEAN);
-- /* All finished and idle */
-- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE;
-- kbdev->hwcnt.backend.triggered = 1;
-- wake_up(&kbdev->hwcnt.backend.wait);
--
-- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
--}
--
--
- void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev)
- {
- unsigned long flags;
-@@ -298,20 +259,10 @@ void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev)
- kbdev->hwcnt.backend.triggered = 1;
- wake_up(&kbdev->hwcnt.backend.wait);
- } else if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_DUMPING) {
-- if (kbdev->mmu_mode->flags & KBASE_MMU_MODE_HAS_NON_CACHEABLE) {
-- /* All finished and idle */
-- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE;
-- kbdev->hwcnt.backend.triggered = 1;
-- wake_up(&kbdev->hwcnt.backend.wait);
-- } else {
-- int ret;
-- /* Always clean and invalidate the cache after a successful dump
-- */
-- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_REQUEST_CLEAN;
-- ret = queue_work(kbdev->hwcnt.backend.cache_clean_wq,
-- &kbdev->hwcnt.backend.cache_clean_work);
-- KBASE_DEBUG_ASSERT(ret);
-- }
-+ /* All finished and idle */
-+ kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE;
-+ kbdev->hwcnt.backend.triggered = 1;
-+ wake_up(&kbdev->hwcnt.backend.wait);
- }
-
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
-@@ -353,7 +304,8 @@ int kbase_instr_hwcnt_clear(struct kbase_context *kctx)
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
-
- /* Check it's the context previously set up and we're not already
-- * dumping */
-+ * dumping
-+ */
- if (kbdev->hwcnt.kctx != kctx || kbdev->hwcnt.backend.state !=
- KBASE_INSTR_STATE_IDLE)
- goto out;
-@@ -373,39 +325,45 @@ KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_clear);
-
- int kbase_instr_backend_init(struct kbase_device *kbdev)
- {
-- int ret = 0;
-+ spin_lock_init(&kbdev->hwcnt.lock);
-
- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DISABLED;
-
- init_waitqueue_head(&kbdev->hwcnt.backend.wait);
-- INIT_WORK(&kbdev->hwcnt.backend.cache_clean_work,
-- kbasep_cache_clean_worker);
--
-
- kbdev->hwcnt.backend.triggered = 0;
-
--#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY_VIA_DEBUG_FS
-- kbdev->hwcnt.backend.use_secondary_override = false;
-+#ifdef CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
-+/* Use the build time option for the override default. */
-+#if defined(CONFIG_MALI_PRFCNT_SET_SECONDARY)
-+ kbdev->hwcnt.backend.override_counter_set = KBASE_HWCNT_SET_SECONDARY;
-+#elif defined(CONFIG_MALI_PRFCNT_SET_TERTIARY)
-+ kbdev->hwcnt.backend.override_counter_set = KBASE_HWCNT_SET_TERTIARY;
-+#else
-+ /* Default to primary */
-+ kbdev->hwcnt.backend.override_counter_set = KBASE_HWCNT_SET_PRIMARY;
- #endif
--
-- kbdev->hwcnt.backend.cache_clean_wq =
-- alloc_workqueue("Mali cache cleaning workqueue", 0, 1);
-- if (NULL == kbdev->hwcnt.backend.cache_clean_wq)
-- ret = -EINVAL;
--
-- return ret;
-+#endif
-+ return 0;
- }
-
- void kbase_instr_backend_term(struct kbase_device *kbdev)
- {
-- destroy_workqueue(kbdev->hwcnt.backend.cache_clean_wq);
-+ CSTD_UNUSED(kbdev);
- }
-
--#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY_VIA_DEBUG_FS
-+#ifdef CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
- void kbase_instr_backend_debugfs_init(struct kbase_device *kbdev)
- {
-- debugfs_create_bool("hwcnt_use_secondary", S_IRUGO | S_IWUSR,
-- kbdev->mali_debugfs_directory,
-- &kbdev->hwcnt.backend.use_secondary_override);
-+ /* No validation is done on the debugfs input. Invalid input could cause
-+ * performance counter errors. This is acceptable since this is a debug
-+ * only feature and users should know what they are doing.
-+ *
-+ * Valid inputs are the values accepted bythe SET_SELECT bits of the
-+ * PRFCNT_CONFIG register as defined in the architecture specification.
-+ */
-+ debugfs_create_u8("hwcnt_set_select", S_IRUGO | S_IWUSR,
-+ kbdev->mali_debugfs_directory,
-+ (u8 *)&kbdev->hwcnt.backend.override_counter_set);
- }
- #endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_defs.h
-index 9930968..e356348 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_defs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2016, 2018, 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -27,6 +26,8 @@
- #ifndef _KBASE_INSTR_DEFS_H_
- #define _KBASE_INSTR_DEFS_H_
-
-+#include <mali_kbase_hwcnt_gpu.h>
-+
- /*
- * Instrumentation State Machine States
- */
-@@ -37,8 +38,6 @@ enum kbase_instr_state {
- 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,
- /* An error has occured during DUMPING (page fault). */
- KBASE_INSTR_STATE_FAULT
- };
-@@ -47,14 +46,11 @@ enum kbase_instr_state {
- struct kbase_instr_backend {
- wait_queue_head_t wait;
- int triggered;
--#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY_VIA_DEBUG_FS
-- bool use_secondary_override;
-+#ifdef CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
-+ enum kbase_hwcnt_physical_set override_counter_set;
- #endif
-
- enum kbase_instr_state state;
-- struct workqueue_struct *cache_clean_wq;
-- struct work_struct cache_clean_work;
- };
-
- #endif /* _KBASE_INSTR_DEFS_H_ */
--
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_internal.h
-index 2254b9f..332cc69 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_internal.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_instr_internal.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Backend-specific HW access instrumentation APIs
- */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_irq_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_irq_internal.h
-index ca3c048..2671ce5 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_irq_internal.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_irq_internal.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2015, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_irq_linux.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_irq_linux.c
-index 8696c6a..a29f7ef 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_irq_linux.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_irq_linux.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2016,2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,17 +17,15 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include <backend/gpu/mali_kbase_irq_internal.h>
-
- #include <linux/interrupt.h>
-
--#if !defined(CONFIG_MALI_NO_MALI)
-+#if !IS_ENABLED(CONFIG_MALI_NO_MALI)
-
- /* GPU IRQ Tags */
- #define JOB_IRQ_TAG 0
-@@ -72,7 +71,12 @@ static irqreturn_t kbase_job_irq_handler(int irq, void *data)
-
- dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val);
-
-+#if MALI_USE_CSF
-+ /* call the csf interrupt handler */
-+ kbase_csf_interrupt(kbdev, val);
-+#else
- kbase_job_done(kbdev, val);
-+#endif
-
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
-@@ -210,24 +214,25 @@ int kbase_set_custom_irq_handler(struct kbase_device *kbdev,
- int result = 0;
- irq_handler_t requested_irq_handler = NULL;
-
-- KBASE_DEBUG_ASSERT((JOB_IRQ_HANDLER <= irq_type) &&
-- (GPU_IRQ_HANDLER >= irq_type));
-+ KBASE_DEBUG_ASSERT((irq_type >= JOB_IRQ_HANDLER) &&
-+ (irq_type <= GPU_IRQ_HANDLER));
-
- /* Release previous handler */
- if (kbdev->irqs[irq_type].irq)
- free_irq(kbdev->irqs[irq_type].irq, kbase_tag(kbdev, irq_type));
-
-- requested_irq_handler = (NULL != custom_handler) ? custom_handler :
-- kbase_handler_table[irq_type];
-+ requested_irq_handler = (custom_handler != NULL) ?
-+ custom_handler :
-+ kbase_handler_table[irq_type];
-
-- if (0 != request_irq(kbdev->irqs[irq_type].irq,
-- requested_irq_handler,
-+ if (request_irq(kbdev->irqs[irq_type].irq, requested_irq_handler,
- kbdev->irqs[irq_type].flags | IRQF_SHARED,
-- dev_name(kbdev->dev), kbase_tag(kbdev, irq_type))) {
-+ dev_name(kbdev->dev),
-+ kbase_tag(kbdev, irq_type)) != 0) {
- result = -EINVAL;
- dev_err(kbdev->dev, "Can't request interrupt %d (index %d)\n",
- kbdev->irqs[irq_type].irq, irq_type);
--#ifdef CONFIG_SPARSE_IRQ
-+#if IS_ENABLED(CONFIG_SPARSE_IRQ)
- dev_err(kbdev->dev, "You have CONFIG_SPARSE_IRQ support enabled - is the interrupt number correct for this configuration?\n");
- #endif /* CONFIG_SPARSE_IRQ */
- }
-@@ -456,7 +461,7 @@ int kbase_install_interrupts(struct kbase_device *kbdev)
- if (err) {
- dev_err(kbdev->dev, "Can't request interrupt %d (index %d)\n",
- kbdev->irqs[i].irq, i);
--#ifdef CONFIG_SPARSE_IRQ
-+#if IS_ENABLED(CONFIG_SPARSE_IRQ)
- dev_err(kbdev->dev, "You have CONFIG_SPARSE_IRQ support enabled - is the interrupt number correct for this configuration?\n");
- #endif /* CONFIG_SPARSE_IRQ */
- goto release;
-@@ -496,4 +501,4 @@ void kbase_synchronize_irqs(struct kbase_device *kbdev)
-
- KBASE_EXPORT_TEST_API(kbase_synchronize_irqs);
-
--#endif /* !defined(CONFIG_MALI_NO_MALI) */
-+#endif /* !IS_ENABLED(CONFIG_MALI_NO_MALI) */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_as.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_as.c
-index bb4f548..888aa59 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_as.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_as.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * Register backend context / address space management
- */
-@@ -58,8 +56,10 @@ static void assign_and_activate_kctx_addr_space(struct kbase_device *kbdev,
- lockdep_assert_held(&js_devdata->runpool_mutex);
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
-+#if !MALI_USE_CSF
- /* Attribute handling */
- kbasep_js_ctx_attr_runpool_retain_ctx(kbdev, kctx);
-+#endif
-
- /* Allow it to run jobs */
- kbasep_js_set_submit_allowed(js_devdata, kctx);
-@@ -188,8 +188,8 @@ int kbase_backend_find_and_release_free_address_space(
- }
-
- /* Context was retained while locks were dropped,
-- * continue looking for free AS */
--
-+ * continue looking for free AS
-+ */
- mutex_unlock(&js_devdata->runpool_mutex);
- mutex_unlock(&as_js_kctx_info->ctx.jsctx_mutex);
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_defs.h
-index 7cda61a..e29ace7 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_defs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2016, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * Register-based HW access backend specific definitions
- */
-@@ -78,11 +76,12 @@ struct slot_rb {
- * The hwaccess_lock (a spinlock) must be held when accessing this structure
- */
- struct kbase_backend_data {
-+#if !MALI_USE_CSF
- struct slot_rb slot_rb[BASE_JM_MAX_NR_SLOTS];
--
- struct hrtimer scheduling_timer;
-
- bool timer_running;
-+#endif
- bool suspend_timer;
-
- atomic_t reset_gpu;
-@@ -92,13 +91,16 @@ struct kbase_backend_data {
- /* kbase_prepare_to_reset_gpu has been called */
- #define KBASE_RESET_GPU_PREPARED 1
- /* kbase_reset_gpu has been called - the reset will now definitely happen
-- * within the timeout period */
-+ * within the timeout period
-+ */
- #define KBASE_RESET_GPU_COMMITTED 2
- /* The GPU reset process is currently occuring (timeout has expired or
-- * kbasep_try_reset_gpu_early was called) */
-+ * kbasep_try_reset_gpu_early was called)
-+ */
- #define KBASE_RESET_GPU_HAPPENING 3
- /* Reset the GPU silently, used when resetting the GPU as part of normal
-- * behavior (e.g. when exiting protected mode). */
-+ * behavior (e.g. when exiting protected mode).
-+ */
- #define KBASE_RESET_GPU_SILENT 4
- struct workqueue_struct *reset_workq;
- struct work_struct reset_work;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_hw.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_hw.c
-index fa6bc83..ae0377f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_hw.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_hw.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -33,16 +32,20 @@
- #include <mali_kbase_hwaccess_jm.h>
- #include <mali_kbase_reset_gpu.h>
- #include <mali_kbase_ctx_sched.h>
-+#include <mali_kbase_kinstr_jm.h>
- #include <mali_kbase_hwcnt_context.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include <backend/gpu/mali_kbase_irq_internal.h>
- #include <backend/gpu/mali_kbase_jm_internal.h>
-+#include <mali_kbase_regs_history_debugfs.h>
-
- static void kbasep_try_reset_gpu_early_locked(struct kbase_device *kbdev);
-+static u64 kbasep_apply_limited_core_mask(const struct kbase_device *kbdev,
-+ const u64 affinity, const u64 limited_core_mask);
-
- static u64 kbase_job_write_affinity(struct kbase_device *kbdev,
- base_jd_core_req core_req,
-- int js)
-+ int js, const u64 limited_core_mask)
- {
- u64 affinity;
-
-@@ -71,14 +74,21 @@ static u64 kbase_job_write_affinity(struct kbase_device *kbdev,
- */
- if (js == 2 && num_core_groups > 1)
- affinity &= coherency_info->group[1].core_mask;
-- else
-+ else if (num_core_groups > 1)
- affinity &= coherency_info->group[0].core_mask;
-+ else
-+ affinity &= kbdev->gpu_props.curr_config.shader_present;
- } else {
- /* Use all cores */
- affinity = kbdev->pm.backend.shaders_avail &
- kbdev->pm.debug_core_mask[js];
- }
-
-+ if (core_req & BASE_JD_REQ_LIMITED_CORE_MASK) {
-+ /* Limiting affinity due to BASE_JD_REQ_LIMITED_CORE_MASK by applying the limited core mask. */
-+ affinity = kbasep_apply_limited_core_mask(kbdev, affinity, limited_core_mask);
-+ }
-+
- if (unlikely(!affinity)) {
- #ifdef CONFIG_MALI_DEBUG
- u64 shaders_ready =
-@@ -88,6 +98,16 @@ static u64 kbase_job_write_affinity(struct kbase_device *kbdev,
- #endif
-
- affinity = kbdev->pm.backend.shaders_avail;
-+
-+ if (core_req & BASE_JD_REQ_LIMITED_CORE_MASK) {
-+ /* Limiting affinity again to make sure it only enables shader cores with backed TLS memory. */
-+ affinity = kbasep_apply_limited_core_mask(kbdev, affinity, limited_core_mask);
-+
-+#ifdef CONFIG_MALI_DEBUG
-+ /* affinity should never be 0 */
-+ WARN_ON(!affinity);
-+#endif
-+ }
- }
-
- kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_AFFINITY_NEXT_LO),
-@@ -168,7 +188,7 @@ static u64 select_job_chain(struct kbase_jd_atom *katom)
- }
-
- dev_dbg(kctx->kbdev->dev,
-- "Selected job chain 0x%llx for end atom %p in state %d\n",
-+ "Selected job chain 0x%llx for end atom %pK in state %d\n",
- jc, (void *)katom, (int)rp->state);
-
- katom->jc = jc;
-@@ -192,7 +212,7 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
- /* Command register must be available */
- KBASE_DEBUG_ASSERT(kbasep_jm_is_js_free(kbdev, js, kctx));
-
-- dev_dbg(kctx->kbdev->dev, "Write JS_HEAD_NEXT 0x%llx for atom %p\n",
-+ dev_dbg(kctx->kbdev->dev, "Write JS_HEAD_NEXT 0x%llx for atom %pK\n",
- jc_head, (void *)katom);
-
- kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_LO),
-@@ -200,10 +220,12 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
- kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_HEAD_NEXT_HI),
- jc_head >> 32);
-
-- affinity = kbase_job_write_affinity(kbdev, katom->core_req, js);
-+ affinity = kbase_job_write_affinity(kbdev, katom->core_req, js,
-+ kctx->limited_core_mask);
-
- /* start MMU, medium priority, cache clean/flush on end, clean/flush on
-- * start */
-+ * start
-+ */
- cfg = kctx->as_nr;
-
- if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_REDUCTION) &&
-@@ -255,7 +277,7 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
- katom->start_timestamp = ktime_get();
-
- /* GO ! */
-- dev_dbg(kbdev->dev, "JS: Submitting atom %p from ctx %p to js[%d] with head=0x%llx",
-+ dev_dbg(kbdev->dev, "JS: Submitting atom %pK from ctx %pK to js[%d] with head=0x%llx",
- katom, kctx, js, jc_head);
-
- KBASE_KTRACE_ADD_JM_SLOT_INFO(kbdev, JM_SUBMIT, kctx, katom, jc_head, js,
-@@ -277,7 +299,8 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
- katom,
- &kbdev->gpu_props.props.raw_props.js_features[js],
- "ctx_nr,atom_nr");
--#ifdef CONFIG_GPU_TRACEPOINTS
-+ kbase_kinstr_jm_atom_hw_submit(katom);
-+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
- if (!kbase_backend_nr_atoms_submitted(kbdev, js)) {
- /* If this is the only job on the slot, trace it as starting */
- char js_string[16];
-@@ -328,7 +351,8 @@ static void kbasep_job_slot_update_head_start_timestamp(
- /* 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 */
-+ * too much of an overestimate
-+ */
- katom->start_timestamp = end_timestamp;
- }
- }
-@@ -371,9 +395,9 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done)
- /* 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.*/
-+ /* 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);
-
-@@ -385,7 +409,8 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done)
-
- if (failed & (1u << i)) {
- /* read out the job slot status code if the job
-- * slot reported failure */
-+ * slot reported failure
-+ */
- completion_code = kbase_reg_read(kbdev,
- JOB_SLOT_REG(i, JS_STATUS));
-
-@@ -399,7 +424,8 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done)
-
- /* Soft-stopped job - read the value of
- * JS<n>_TAIL so that the job chain can
-- * be resumed */
-+ * be resumed
-+ */
- job_tail = (u64)kbase_reg_read(kbdev,
- JOB_SLOT_REG(i, JS_TAIL_LO)) |
- ((u64)kbase_reg_read(kbdev,
-@@ -408,21 +434,26 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done)
- } else if (completion_code ==
- 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 */
-+ * job to come back as NOT_STARTED,
-+ * but the error interrupt helps us
-+ * detect it
-+ */
- completion_code =
- BASE_JD_EVENT_TERMINATED;
- }
-
- kbase_gpu_irq_evict(kbdev, i, completion_code);
-
-- /* Some jobs that encounter a BUS FAULT may result in corrupted
-- * state causing future jobs to hang. Reset GPU before
-- * allowing any other jobs on the slot to continue. */
-+ /* Some jobs that encounter a BUS FAULT may
-+ * result in corrupted state causing future
-+ * jobs to hang. Reset GPU before allowing
-+ * any other jobs on the slot to continue.
-+ */
- if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_3076)) {
- if (completion_code == BASE_JD_EVENT_JOB_BUS_FAULT) {
-- if (kbase_prepare_to_reset_gpu_locked(kbdev))
-+ if (kbase_prepare_to_reset_gpu_locked(
-+ kbdev,
-+ RESET_FLAGS_NONE))
- kbase_reset_gpu_locked(kbdev);
- }
- }
-@@ -480,7 +511,8 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done)
-
- if ((rawstat >> (i + 16)) & 1) {
- /* There is a failed job that we've
-- * missed - add it back to active */
-+ * missed - add it back to active
-+ */
- active |= (1u << i);
- }
- }
-@@ -582,7 +614,8 @@ void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev,
- }
-
- /* We are about to issue a soft stop, so mark the atom as having
-- * been soft stopped */
-+ * been soft stopped
-+ */
- target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_SOFT_STOPPED;
-
- /* Mark the point where we issue the soft-stop command */
-@@ -692,12 +725,40 @@ void kbase_backend_jm_kill_running_jobs_from_kctx(struct kbase_context *kctx)
- kbase_job_slot_hardstop(kctx, i, NULL);
- }
-
-+/**
-+ * kbase_is_existing_atom_submitted_later_than_ready
-+ * @ready: sequence number of the ready atom
-+ * @existing: sequence number of the existing atom
-+ *
-+ * Returns true if the existing atom has been submitted later than the
-+ * ready atom. It is used to understand if an atom that is ready has been
-+ * submitted earlier than the currently running atom, so that the currently
-+ * running atom should be preempted to allow the ready atom to run.
-+ */
-+static inline bool kbase_is_existing_atom_submitted_later_than_ready(u64 ready, u64 existing)
-+{
-+ /* No seq_nr set? */
-+ if (!ready || !existing)
-+ return false;
-+
-+ /* Efficiently handle the unlikely case of wrapping.
-+ * The following code assumes that the delta between the sequence number
-+ * of the two atoms is less than INT64_MAX.
-+ * In the extremely unlikely case where the delta is higher, the comparison
-+ * defaults for no preemption.
-+ * The code also assumes that the conversion from unsigned to signed types
-+ * works because the signed integers are 2's complement.
-+ */
-+ return (s64)(ready - existing) < 0;
-+}
-+
- void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx,
- struct kbase_jd_atom *target_katom)
- {
- struct kbase_device *kbdev;
- int js = target_katom->slot_nr;
- int priority = target_katom->sched_priority;
-+ int seq_nr = target_katom->seq_nr;
- int i;
- bool stop_sent = false;
-
-@@ -719,7 +780,8 @@ void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx,
- (katom->kctx != kctx))
- continue;
-
-- if (katom->sched_priority > priority) {
-+ if ((katom->sched_priority > priority) ||
-+ (katom->kctx == kctx && kbase_is_existing_atom_submitted_later_than_ready(seq_nr, katom->seq_nr))) {
- if (!stop_sent)
- KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITIZED(
- kbdev,
-@@ -749,7 +811,7 @@ static int softstop_start_rp_nolock(
-
- if (!(katom->core_req & BASE_JD_REQ_START_RENDERPASS)) {
- dev_dbg(kctx->kbdev->dev,
-- "Atom %p on job slot is not start RP\n", (void *)katom);
-+ "Atom %pK on job slot is not start RP\n", (void *)katom);
- return -EPERM;
- }
-
-@@ -762,13 +824,13 @@ static int softstop_start_rp_nolock(
- rp->state != KBASE_JD_RP_RETRY))
- return -EINVAL;
-
-- dev_dbg(kctx->kbdev->dev, "OOM in state %d with region %p\n",
-+ dev_dbg(kctx->kbdev->dev, "OOM in state %d with region %pK\n",
- (int)rp->state, (void *)reg);
-
- if (WARN_ON(katom != rp->start_katom))
- return -EINVAL;
-
-- dev_dbg(kctx->kbdev->dev, "Adding region %p to list %p\n",
-+ dev_dbg(kctx->kbdev->dev, "Adding region %pK to list %pK\n",
- (void *)reg, (void *)&rp->oom_reg_list);
- list_move_tail(®->link, &rp->oom_reg_list);
- dev_dbg(kctx->kbdev->dev, "Added region to list\n");
-@@ -813,9 +875,9 @@ void kbase_jm_wait_for_zero_jobs(struct kbase_context *kctx)
- if (timeout != 0)
- goto exit;
-
-- if (kbase_prepare_to_reset_gpu(kbdev)) {
-+ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE)) {
- dev_err(kbdev->dev,
-- "Issueing GPU soft-reset because jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n",
-+ "Issuing 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);
- }
-@@ -823,7 +885,7 @@ void kbase_jm_wait_for_zero_jobs(struct kbase_context *kctx)
- /* Wait for the reset to complete */
- kbase_reset_gpu_wait(kbdev);
- exit:
-- dev_dbg(kbdev->dev, "Zap: Finished Context %p", kctx);
-+ dev_dbg(kbdev->dev, "Zap: Finished Context %pK", kctx);
-
- /* Ensure that the signallers of the waitqs have finished */
- mutex_lock(&kctx->jctx.lock);
-@@ -884,7 +946,7 @@ KBASE_EXPORT_TEST_API(kbase_job_slot_term);
- void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, int js,
- struct kbase_jd_atom *target_katom, u32 sw_flags)
- {
-- dev_dbg(kbdev->dev, "Soft-stop atom %p with flags 0x%x (s:%d)\n",
-+ dev_dbg(kbdev->dev, "Soft-stop atom %pK with flags 0x%x (s:%d)\n",
- target_katom, sw_flags, js);
-
- KBASE_DEBUG_ASSERT(!(sw_flags & JS_COMMAND_MASK));
-@@ -988,6 +1050,33 @@ void kbase_job_check_leave_disjoint(struct kbase_device *kbdev,
- }
- }
-
-+int kbase_reset_gpu_prevent_and_wait(struct kbase_device *kbdev)
-+{
-+ WARN(true, "%s Not implemented for JM GPUs", __func__);
-+ return -EINVAL;
-+}
-+
-+int kbase_reset_gpu_try_prevent(struct kbase_device *kbdev)
-+{
-+ WARN(true, "%s Not implemented for JM GPUs", __func__);
-+ return -EINVAL;
-+}
-+
-+void kbase_reset_gpu_allow(struct kbase_device *kbdev)
-+{
-+ WARN(true, "%s Not implemented for JM GPUs", __func__);
-+}
-+
-+void kbase_reset_gpu_assert_prevented(struct kbase_device *kbdev)
-+{
-+ WARN(true, "%s Not implemented for JM GPUs", __func__);
-+}
-+
-+void kbase_reset_gpu_assert_failed_or_prevented(struct kbase_device *kbdev)
-+{
-+ WARN(true, "%s Not implemented for JM GPUs", __func__);
-+}
-+
- static void kbase_debug_dump_registers(struct kbase_device *kbdev)
- {
- int i;
-@@ -1054,13 +1143,15 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
-
- /* Make sure the timer has completed - this cannot be done from
- * interrupt context, so this cannot be done within
-- * kbasep_try_reset_gpu_early. */
-+ * kbasep_try_reset_gpu_early.
-+ */
- hrtimer_cancel(&kbdev->hwaccess.backend.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 */
-+ * there's no need to reset it
-+ */
- atomic_set(&kbdev->hwaccess.backend.reset_gpu,
- KBASE_RESET_GPU_NOT_PENDING);
- kbase_disjoint_state_down(kbdev);
-@@ -1081,14 +1172,16 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
- kbdev->irq_reset_flush = true;
-
- /* Disable IRQ to avoid IRQ handlers to kick in after releasing the
-- * spinlock; this also clears any outstanding interrupts */
-+ * spinlock; this also clears any outstanding interrupts
-+ */
- kbase_pm_disable_interrupts_nolock(kbdev);
-
- spin_unlock(&kbdev->mmu_mask_change);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
- /* Ensure that any IRQ handlers have finished
-- * Must be done without any locks IRQ handlers will take */
-+ * Must be done without any locks IRQ handlers will take
-+ */
- kbase_synchronize_irqs(kbdev);
-
- /* Flush out any in-flight work items */
-@@ -1099,7 +1192,8 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
-
- if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TMIX_8463)) {
- /* Ensure that L2 is not transitioning when we send the reset
-- * command */
-+ * command
-+ */
- while (--max_loops && kbase_pm_get_trans_cores(kbdev,
- KBASE_PM_CORE_L2))
- ;
-@@ -1114,14 +1208,16 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
- /* 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 */
-+ * we'll kill it when we reset the GPU
-+ */
-
- if (!silent)
- dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)",
- RESET_TIMEOUT);
-
- /* Output the state of some interesting registers to help in the
-- * debugging of GPU resets */
-+ * debugging of GPU resets
-+ */
- if (!silent)
- kbase_debug_dump_registers(kbdev);
-
-@@ -1160,7 +1256,8 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
- kbase_pm_update_cores_state(kbdev);
-
- /* Synchronously request and wait for those cores, because if
-- * instrumentation is enabled it would need them immediately. */
-+ * instrumentation is enabled it would need them immediately.
-+ */
- kbase_pm_wait_for_desired_state(kbdev);
-
- mutex_unlock(&kbdev->pm.lock);
-@@ -1237,7 +1334,8 @@ static void kbasep_try_reset_gpu_early_locked(struct kbase_device *kbdev)
-
- /* 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 */
-+ * the reset
-+ */
- if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu,
- KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) !=
- KBASE_RESET_GPU_COMMITTED) {
-@@ -1261,6 +1359,7 @@ static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev)
- /**
- * kbase_prepare_to_reset_gpu_locked - Prepare for resetting the GPU
- * @kbdev: kbase device
-+ * @flags: Bitfield indicating impact of reset (see flag defines)
- *
- * This function just soft-stops all the slots to ensure that as many jobs as
- * possible are saved.
-@@ -1271,12 +1370,23 @@ static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev)
- * false - Another thread is performing a reset, kbase_reset_gpu should
- * not be called.
- */
--bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev)
-+bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev,
-+ unsigned int flags)
- {
- int i;
-
-+ CSTD_UNUSED(flags);
- KBASE_DEBUG_ASSERT(kbdev);
-
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ if (kbase_pm_is_gpu_lost(kbdev)) {
-+ /* GPU access has been removed, reset will be done by
-+ * Arbiter instead
-+ */
-+ return false;
-+ }
-+#endif
-+
- if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu,
- KBASE_RESET_GPU_NOT_PENDING,
- KBASE_RESET_GPU_PREPARED) !=
-@@ -1293,14 +1403,14 @@ bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev)
- return true;
- }
-
--bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev)
-+bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev, unsigned int flags)
- {
-- unsigned long flags;
-+ unsigned long lock_flags;
- bool ret;
-
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-- ret = kbase_prepare_to_reset_gpu_locked(kbdev);
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, lock_flags);
-+ ret = kbase_prepare_to_reset_gpu_locked(kbdev, flags);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, lock_flags);
-
- return ret;
- }
-@@ -1321,7 +1431,8 @@ void kbase_reset_gpu(struct kbase_device *kbdev)
- KBASE_DEBUG_ASSERT(kbdev);
-
- /* Note this is an assert/atomic_set because it is a software issue for
-- * a race to be occuring here */
-+ * a race to be occurring here
-+ */
- KBASE_DEBUG_ASSERT(atomic_read(&kbdev->hwaccess.backend.reset_gpu) ==
- KBASE_RESET_GPU_PREPARED);
- atomic_set(&kbdev->hwaccess.backend.reset_gpu,
-@@ -1344,7 +1455,8 @@ void kbase_reset_gpu_locked(struct kbase_device *kbdev)
- KBASE_DEBUG_ASSERT(kbdev);
-
- /* Note this is an assert/atomic_set because it is a software issue for
-- * a race to be occuring here */
-+ * a race to be occurring here
-+ */
- KBASE_DEBUG_ASSERT(atomic_read(&kbdev->hwaccess.backend.reset_gpu) ==
- KBASE_RESET_GPU_PREPARED);
- atomic_set(&kbdev->hwaccess.backend.reset_gpu,
-@@ -1419,3 +1531,21 @@ void kbase_reset_gpu_term(struct kbase_device *kbdev)
- {
- destroy_workqueue(kbdev->hwaccess.backend.reset_workq);
- }
-+
-+static u64 kbasep_apply_limited_core_mask(const struct kbase_device *kbdev,
-+ const u64 affinity, const u64 limited_core_mask)
-+{
-+ const u64 result = affinity & limited_core_mask;
-+
-+#ifdef CONFIG_MALI_DEBUG
-+ dev_dbg(kbdev->dev,
-+ "Limiting affinity due to BASE_JD_REQ_LIMITED_CORE_MASK from 0x%lx to 0x%lx (mask is 0x%lx)\n",
-+ (unsigned long int)affinity,
-+ (unsigned long int)result,
-+ (unsigned long int)limited_core_mask);
-+#else
-+ CSTD_UNUSED(kbdev);
-+#endif
-+
-+ return result;
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_internal.h
-index 1419b59..1039e85 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_internal.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_internal.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2016, 2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Job Manager backend-specific low-level APIs.
- */
-@@ -34,7 +31,7 @@
- #include <linux/atomic.h>
-
- #include <backend/gpu/mali_kbase_jm_rb.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
-
- /**
- * kbase_job_submit_nolock() - Submit a job to a certain job-slot
-@@ -62,7 +59,7 @@ void kbase_job_submit_nolock(struct kbase_device *kbdev,
- void kbase_job_done_slot(struct kbase_device *kbdev, int s, u32 completion_code,
- u64 job_tail, ktime_t *end_timestamp);
-
--#ifdef CONFIG_GPU_TRACEPOINTS
-+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
- static inline char *kbasep_make_job_slot_string(int js, char *js_string,
- size_t js_size)
- {
-@@ -71,11 +68,13 @@ static inline char *kbasep_make_job_slot_string(int js, char *js_string,
- }
- #endif
-
-+#if !MALI_USE_CSF
- static inline int kbasep_jm_is_js_free(struct kbase_device *kbdev, int js,
- struct kbase_context *kctx)
- {
- return !kbase_reg_read(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT));
- }
-+#endif
-
-
- /**
-@@ -94,6 +93,7 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
- struct kbase_jd_atom *katom,
- int js);
-
-+#if !MALI_USE_CSF
- /**
- * kbasep_job_slot_soft_or_hard_stop_do_action() - Perform a soft or hard stop
- * on the specified atom
-@@ -112,6 +112,7 @@ void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev,
- u32 action,
- base_jd_core_req core_reqs,
- struct kbase_jd_atom *target_katom);
-+#endif /* !MALI_USE_CSF */
-
- /**
- * kbase_backend_soft_hard_stop_slot() - Soft or hard stop jobs on a given job
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_rb.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_rb.c
-index 4e4ed05..8ee897f 100755
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_rb.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_rb.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * Register-based HW access backend specific APIs
- */
-@@ -33,16 +31,19 @@
- #include <tl/mali_kbase_tracepoints.h>
- #include <mali_kbase_hwcnt_context.h>
- #include <mali_kbase_reset_gpu.h>
-+#include <mali_kbase_kinstr_jm.h>
- #include <backend/gpu/mali_kbase_cache_policy_backend.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include <backend/gpu/mali_kbase_jm_internal.h>
- #include <backend/gpu/mali_kbase_pm_internal.h>
-
- /* Return whether the specified ringbuffer is empty. HW access lock must be
-- * held */
-+ * held
-+ */
- #define SLOT_RB_EMPTY(rb) (rb->write_idx == rb->read_idx)
- /* Return number of atoms currently in the specified ringbuffer. HW access lock
-- * must be held */
-+ * must be held
-+ */
- #define SLOT_RB_ENTRIES(rb) (int)(s8)(rb->write_idx - rb->read_idx)
-
- static void kbase_gpu_release_atom(struct kbase_device *kbdev,
-@@ -253,6 +254,8 @@ static bool kbase_gpu_check_secure_atoms(struct kbase_device *kbdev,
-
- int kbase_backend_slot_free(struct kbase_device *kbdev, int js)
- {
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
- if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) !=
- KBASE_RESET_GPU_NOT_PENDING) {
- /* The GPU is being reset - so prevent submission */
-@@ -278,15 +281,19 @@ static void kbase_gpu_release_atom(struct kbase_device *kbdev,
- break;
-
- case KBASE_ATOM_GPU_RB_SUBMITTED:
-+ kbase_kinstr_jm_atom_hw_release(katom);
- /* Inform power management at start/finish of atom so it can
- * update its GPU utilisation metrics. Mark atom as not
-- * submitted beforehand. */
-+ * submitted beforehand.
-+ */
- katom->gpu_rb_state = KBASE_ATOM_GPU_RB_READY;
- kbase_pm_metrics_update(kbdev, end_timestamp);
-
-+ /* Inform platform at start/finish of atom */
-+ kbasep_platform_event_atom_complete(katom);
-+
- if (katom->core_req & BASE_JD_REQ_PERMON)
- kbase_pm_release_gpu_cycle_counter_nolock(kbdev);
-- /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */
-
- KBASE_TLSTREAM_TL_NRET_ATOM_LPU(kbdev, katom,
- &kbdev->gpu_props.props.raw_props.js_features
-@@ -296,6 +303,8 @@ static void kbase_gpu_release_atom(struct kbase_device *kbdev,
- &kbdev->gpu_props.props.raw_props.js_features
- [katom->slot_nr]);
-
-+ /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */
-+
- case KBASE_ATOM_GPU_RB_READY:
- /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */
-
-@@ -540,7 +549,8 @@ static int kbase_jm_enter_protected_mode(struct kbase_device *kbdev,
- KBASE_TLSTREAM_AUX_PROTECTED_ENTER_START(kbdev, kbdev);
- /* The checks in KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV
- * should ensure that we are not already transitiong, and that
-- * there are no atoms currently on the GPU. */
-+ * there are no atoms currently on the GPU.
-+ */
- WARN_ON(kbdev->protected_mode_transition);
- WARN_ON(kbase_gpu_atoms_submitted_any(kbdev));
- /* If hwcnt is disabled, it means we didn't clean up correctly
-@@ -566,19 +576,15 @@ static int kbase_jm_enter_protected_mode(struct kbase_device *kbdev,
-
- /* We couldn't disable atomically, so kick off a worker */
- if (!kbdev->protected_mode_hwcnt_disabled) {
--#if KERNEL_VERSION(3, 16, 0) > LINUX_VERSION_CODE
-- queue_work(system_wq,
-- &kbdev->protected_mode_hwcnt_disable_work);
--#else
-- queue_work(system_highpri_wq,
-+ kbase_hwcnt_context_queue_work(
-+ kbdev->hwcnt_gpu_ctx,
- &kbdev->protected_mode_hwcnt_disable_work);
--#endif
- return -EAGAIN;
- }
-
-- /* Once reaching this point GPU must be
-- * switched to protected mode or hwcnt
-- * re-enabled. */
-+ /* Once reaching this point GPU must be switched to protected
-+ * mode or hwcnt re-enabled.
-+ */
-
- if (kbase_pm_protected_entry_override_enable(kbdev))
- return -EAGAIN;
-@@ -618,7 +624,7 @@ static int kbase_jm_enter_protected_mode(struct kbase_device *kbdev,
- KBASE_PM_CORE_L2) ||
- kbase_pm_get_trans_cores(kbdev,
- KBASE_PM_CORE_L2) ||
-- kbase_is_gpu_lost(kbdev)) {
-+ kbase_is_gpu_removed(kbdev)) {
- /*
- * The L2 is still powered, wait for all
- * the users to finish with it before doing
-@@ -718,7 +724,8 @@ static int kbase_jm_exit_protected_mode(struct kbase_device *kbdev,
- KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_START(kbdev, kbdev);
- /* The checks in KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV
- * should ensure that we are not already transitiong, and that
-- * there are no atoms currently on the GPU. */
-+ * there are no atoms currently on the GPU.
-+ */
- WARN_ON(kbdev->protected_mode_transition);
- WARN_ON(kbase_gpu_atoms_submitted_any(kbdev));
-
-@@ -764,8 +771,8 @@ static int kbase_jm_exit_protected_mode(struct kbase_device *kbdev,
- katom[idx]->event_code = BASE_JD_EVENT_JOB_INVALID;
- kbase_gpu_mark_atom_for_return(kbdev, katom[idx]);
- /* Only return if head atom or previous atom
-- * already removed - as atoms must be returned
-- * in order */
-+ * already removed - as atoms must be returned in order
-+ */
- if (idx == 0 || katom[0]->gpu_rb_state ==
- KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) {
- kbase_gpu_dequeue_atom(kbdev, js, NULL);
-@@ -811,7 +818,8 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
-- if (kbase_reset_gpu_is_active(kbdev) || kbase_is_gpu_lost(kbdev))
-+ if (kbase_reset_gpu_is_active(kbdev) ||
-+ kbase_is_gpu_removed(kbdev))
- #else
- if (kbase_reset_gpu_is_active(kbdev))
- #endif
-@@ -843,7 +851,7 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
- break;
-
- katom[idx]->gpu_rb_state =
-- KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV;
-+ KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV;
-
- /* ***TRANSITION TO HIGHER STATE*** */
- /* fallthrough */
-@@ -907,12 +915,14 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
- kbase_gpu_mark_atom_for_return(kbdev,
- katom[idx]);
- /* Set EVENT_DONE so this atom will be
-- completed, not unpulled. */
-+ * completed, not unpulled.
-+ */
- katom[idx]->event_code =
- BASE_JD_EVENT_DONE;
- /* Only return if head atom or previous
- * atom already removed - as atoms must
-- * be returned in order. */
-+ * be returned in order.
-+ */
- if (idx == 0 || katom[0]->gpu_rb_state ==
- KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) {
- kbase_gpu_dequeue_atom(kbdev, js, NULL);
-@@ -943,7 +953,8 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
-
- if (idx == 1) {
- /* Only submit if head atom or previous
-- * atom already submitted */
-+ * atom already submitted
-+ */
- if ((katom[0]->gpu_rb_state !=
- KBASE_ATOM_GPU_RB_SUBMITTED &&
- katom[0]->gpu_rb_state !=
-@@ -959,7 +970,8 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
- }
-
- /* If inter-slot serialization in use then don't
-- * submit atom if any other slots are in use */
-+ * submit atom if any other slots are in use
-+ */
- if ((kbdev->serialize_jobs &
- KBASE_SERIALIZE_INTER_SLOT) &&
- other_slots_busy(kbdev, js))
-@@ -971,31 +983,37 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
- break;
- #endif
- /* Check if this job needs the cycle counter
-- * enabled before submission */
-+ * enabled before submission
-+ */
- if (katom[idx]->core_req & BASE_JD_REQ_PERMON)
- kbase_pm_request_gpu_cycle_counter_l2_is_on(
- kbdev);
-
- kbase_job_hw_submit(kbdev, katom[idx], js);
- katom[idx]->gpu_rb_state =
-- KBASE_ATOM_GPU_RB_SUBMITTED;
-+ KBASE_ATOM_GPU_RB_SUBMITTED;
-+
-+ /* ***TRANSITION TO HIGHER STATE*** */
-+ /* fallthrough */
-+ case KBASE_ATOM_GPU_RB_SUBMITTED:
-
- /* Inform power management at start/finish of
- * atom so it can update its GPU utilisation
-- * metrics. */
-+ * metrics.
-+ */
- kbase_pm_metrics_update(kbdev,
- &katom[idx]->start_timestamp);
-
-- /* ***TRANSITION TO HIGHER STATE*** */
-- /* fallthrough */
-- case KBASE_ATOM_GPU_RB_SUBMITTED:
-- /* Atom submitted to HW, nothing else to do */
-+ /* Inform platform at start/finish of atom */
-+ kbasep_platform_event_atom_submit(katom[idx]);
-+
- break;
-
- case KBASE_ATOM_GPU_RB_RETURN_TO_JS:
- /* Only return if head atom or previous atom
- * already removed - as atoms must be returned
-- * in order */
-+ * in order
-+ */
- if (idx == 0 || katom[0]->gpu_rb_state ==
- KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) {
- kbase_gpu_dequeue_atom(kbdev, js, NULL);
-@@ -1013,7 +1031,7 @@ void kbase_backend_run_atom(struct kbase_device *kbdev,
- struct kbase_jd_atom *katom)
- {
- lockdep_assert_held(&kbdev->hwaccess_lock);
-- dev_dbg(kbdev->dev, "Backend running atom %p\n", (void *)katom);
-+ dev_dbg(kbdev->dev, "Backend running atom %pK\n", (void *)katom);
-
- kbase_gpu_enqueue_atom(kbdev, katom);
- kbase_backend_slot_update(kbdev);
-@@ -1074,7 +1092,7 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js,
- struct kbase_context *kctx = katom->kctx;
-
- dev_dbg(kbdev->dev,
-- "Atom %p completed on hw with code 0x%x and job_tail 0x%llx (s:%d)\n",
-+ "Atom %pK completed on hw with code 0x%x and job_tail 0x%llx (s:%d)\n",
- (void *)katom, completion_code, job_tail, js);
-
- lockdep_assert_held(&kbdev->hwaccess_lock);
-@@ -1098,7 +1116,8 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js,
- * BASE_JD_REQ_SKIP_CACHE_END is set, the GPU cache is not
- * flushed. To prevent future evictions causing possible memory
- * corruption we need to flush the cache manually before any
-- * affected memory gets reused. */
-+ * affected memory gets reused.
-+ */
- katom->need_cache_flush_cores_retained = true;
- }
-
-@@ -1181,7 +1200,8 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js,
- katom_idx1->gpu_rb_state !=
- KBASE_ATOM_GPU_RB_SUBMITTED) {
- /* Can not dequeue this atom yet - will be
-- * dequeued when atom at idx0 completes */
-+ * dequeued when atom at idx0 completes
-+ */
- katom_idx1->event_code = BASE_JD_EVENT_STOPPED;
- kbase_gpu_mark_atom_for_return(kbdev,
- katom_idx1);
-@@ -1194,7 +1214,7 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js,
- if (job_tail != 0 && job_tail != katom->jc) {
- /* Some of the job has been executed */
- dev_dbg(kbdev->dev,
-- "Update job chain address of atom %p to resume from 0x%llx\n",
-+ "Update job chain address of atom %pK to resume from 0x%llx\n",
- (void *)katom, job_tail);
-
- katom->jc = job_tail;
-@@ -1214,7 +1234,7 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js,
- * - Schedule out the parent context if necessary, and schedule a new
- * one in.
- */
--#ifdef CONFIG_GPU_TRACEPOINTS
-+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
- {
- /* The atom in the HEAD */
- struct kbase_jd_atom *next_katom = kbase_gpu_inspect(kbdev, js,
-@@ -1255,7 +1275,7 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js,
-
- if (katom) {
- dev_dbg(kbdev->dev,
-- "Cross-slot dependency %p has become runnable.\n",
-+ "Cross-slot dependency %pK has become runnable.\n",
- (void *)katom);
-
- /* Check if there are lower priority jobs to soft stop */
-@@ -1268,7 +1288,8 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js,
- kbase_pm_update_state(kbdev);
-
- /* Job completion may have unblocked other atoms. Try to update all job
-- * slots */
-+ * slots
-+ */
- kbase_backend_slot_update(kbdev);
- }
-
-@@ -1319,7 +1340,8 @@ void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp)
- katom->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK;
- /* As the atom was not removed, increment the
- * index so that we read the correct atom in the
-- * next iteration. */
-+ * next iteration.
-+ */
- atom_idx++;
- continue;
- }
-@@ -1422,7 +1444,8 @@ bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev,
- katom_idx0_valid = (katom_idx0 == katom);
- /* If idx0 is to be removed and idx1 is on the same context,
- * then idx1 must also be removed otherwise the atoms might be
-- * returned out of order */
-+ * returned out of order
-+ */
- if (katom_idx1)
- katom_idx1_valid = (katom_idx1 == katom) ||
- (katom_idx0_valid &&
-@@ -1469,7 +1492,8 @@ bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev,
- if (kbase_reg_read(kbdev, JOB_SLOT_REG(js,
- JS_COMMAND_NEXT)) == 0) {
- /* idx0 has already completed - stop
-- * idx1 if needed*/
-+ * idx1 if needed
-+ */
- if (katom_idx1_valid) {
- kbase_gpu_stop_atom(kbdev, js,
- katom_idx1,
-@@ -1478,7 +1502,8 @@ bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev,
- }
- } else {
- /* idx1 is in NEXT registers - attempt
-- * to remove */
-+ * to remove
-+ */
- kbase_reg_write(kbdev,
- JOB_SLOT_REG(js,
- JS_COMMAND_NEXT),
-@@ -1493,7 +1518,8 @@ bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev,
- JS_HEAD_NEXT_HI))
- != 0) {
- /* idx1 removed successfully,
-- * will be handled in IRQ */
-+ * will be handled in IRQ
-+ */
- kbase_gpu_remove_atom(kbdev,
- katom_idx1,
- action, true);
-@@ -1507,7 +1533,8 @@ bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev,
- ret = true;
- } else if (katom_idx1_valid) {
- /* idx0 has already completed,
-- * stop idx1 if needed */
-+ * stop idx1 if needed
-+ */
- kbase_gpu_stop_atom(kbdev, js,
- katom_idx1,
- action);
-@@ -1526,7 +1553,8 @@ bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev,
- * flow was also interrupted, and this function
- * might not enter disjoint state e.g. if we
- * don't actually do a hard stop on the head
-- * atom */
-+ * atom
-+ */
- kbase_gpu_stop_atom(kbdev, js, katom_idx0,
- action);
- ret = true;
-@@ -1554,7 +1582,8 @@ bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev,
- ret = true;
- } else {
- /* idx1 is in NEXT registers - attempt to
-- * remove */
-+ * remove
-+ */
- kbase_reg_write(kbdev, JOB_SLOT_REG(js,
- JS_COMMAND_NEXT),
- JS_COMMAND_NOP);
-@@ -1564,13 +1593,15 @@ bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev,
- kbase_reg_read(kbdev, JOB_SLOT_REG(js,
- JS_HEAD_NEXT_HI)) != 0) {
- /* idx1 removed successfully, will be
-- * handled in IRQ once idx0 completes */
-+ * handled in IRQ once idx0 completes
-+ */
- kbase_gpu_remove_atom(kbdev, katom_idx1,
- action,
- false);
- } else {
- /* idx0 has already completed - stop
-- * idx1 */
-+ * idx1
-+ */
- kbase_gpu_stop_atom(kbdev, js,
- katom_idx1,
- action);
-@@ -1644,7 +1675,7 @@ void kbase_gpu_dump_slots(struct kbase_device *kbdev)
-
- if (katom)
- dev_info(kbdev->dev,
-- " js%d idx%d : katom=%p gpu_rb_state=%d\n",
-+ " js%d idx%d : katom=%pK gpu_rb_state=%d\n",
- js, idx, katom, katom->gpu_rb_state);
- else
- dev_info(kbdev->dev, " js%d idx%d : empty\n",
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_rb.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_rb.h
-index c3b9f2d..d3ff203 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_rb.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_jm_rb.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * Register-based HW access backend specific APIs
- */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_js_backend.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_js_backend.c
-index fcc0437..02d7cdb 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_js_backend.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_js_backend.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * Register-based HW access backend specific job scheduler APIs
- */
-@@ -31,13 +29,14 @@
- #include <backend/gpu/mali_kbase_jm_internal.h>
- #include <backend/gpu/mali_kbase_js_internal.h>
-
-+#if !MALI_USE_CSF
- /*
- * Hold the runpool_mutex for this
- */
- static inline bool timer_callback_should_run(struct kbase_device *kbdev)
- {
- struct kbase_backend_data *backend = &kbdev->hwaccess.backend;
-- s8 nr_running_ctxs;
-+ int nr_running_ctxs;
-
- lockdep_assert_held(&kbdev->js_data.runpool_mutex);
-
-@@ -47,7 +46,8 @@ static inline bool timer_callback_should_run(struct kbase_device *kbdev)
-
- /* nr_contexts_pullable is updated with the runpool_mutex. However, the
- * locking in the caller gives us a barrier that ensures
-- * nr_contexts_pullable is up-to-date for reading */
-+ * nr_contexts_pullable is up-to-date for reading
-+ */
- nr_running_ctxs = atomic_read(&kbdev->js_data.nr_contexts_runnable);
-
- #ifdef CONFIG_MALI_DEBUG
-@@ -69,10 +69,10 @@ static inline bool timer_callback_should_run(struct kbase_device *kbdev)
- * don't check KBASEP_JS_CTX_ATTR_NON_COMPUTE).
- */
- {
-- s8 nr_compute_ctxs =
-+ int nr_compute_ctxs =
- kbasep_js_ctx_attr_count_on_runpool(kbdev,
- KBASEP_JS_CTX_ATTR_COMPUTE);
-- s8 nr_noncompute_ctxs = nr_running_ctxs -
-+ int nr_noncompute_ctxs = nr_running_ctxs -
- nr_compute_ctxs;
-
- return (bool) (nr_compute_ctxs >= 2 ||
-@@ -113,7 +113,8 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer)
-
- if (atom != NULL) {
- /* The current version of the model doesn't support
-- * Soft-Stop */
-+ * Soft-Stop
-+ */
- if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_5736)) {
- u32 ticks = atom->ticks++;
-
-@@ -141,7 +142,8 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer)
- * new soft_stop timeout. This ensures that
- * atoms do not miss any of the timeouts due to
- * races between this worker and the thread
-- * changing the timeouts. */
-+ * changing the timeouts.
-+ */
- if (backend->timeouts_updated &&
- ticks > soft_stop_ticks)
- ticks = atom->ticks = soft_stop_ticks;
-@@ -171,10 +173,11 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer)
- *
- * Similarly, if it's about to be
- * decreased, the last job from another
-- * context has already finished, so it's
-- * not too bad that we observe the older
-- * value and register a disjoint event
-- * when we try soft-stopping */
-+ * context has already finished, so
-+ * it's not too bad that we observe the
-+ * older value and register a disjoint
-+ * event when we try soft-stopping
-+ */
- if (js_devdata->nr_user_contexts_running
- >= disjoint_threshold)
- softstop_flags |=
-@@ -252,9 +255,9 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer)
- }
- }
- if (reset_needed) {
-- dev_err(kbdev->dev, "JS: Job has been on the GPU for too long (JS_RESET_TICKS_SS/DUMPING timeout hit). Issueing GPU soft-reset to resolve.");
-+ dev_err(kbdev->dev, "JS: Job has been on the GPU for too long (JS_RESET_TICKS_SS/DUMPING timeout hit). Issuing GPU soft-reset to resolve.");
-
-- if (kbase_prepare_to_reset_gpu_locked(kbdev))
-+ if (kbase_prepare_to_reset_gpu_locked(kbdev, RESET_FLAGS_NONE))
- kbase_reset_gpu_locked(kbdev);
- }
- /* the timer is re-issued if there is contexts in the run-pool */
-@@ -270,9 +273,11 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer)
-
- return HRTIMER_NORESTART;
- }
-+#endif /* !MALI_USE_CSF */
-
- void kbase_backend_ctx_count_changed(struct kbase_device *kbdev)
- {
-+#if !MALI_USE_CSF
- struct kbasep_js_device_data *js_devdata = &kbdev->js_data;
- struct kbase_backend_data *backend = &kbdev->hwaccess.backend;
- unsigned long flags;
-@@ -284,11 +289,12 @@ void kbase_backend_ctx_count_changed(struct kbase_device *kbdev)
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- backend->timer_running = false;
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-- /* From now on, return value of timer_callback_should_run() will
-- * also cause the timer to not requeue itself. Its return value
-- * cannot change, because it depends on variables updated with
-- * the runpool_mutex held, which the caller of this must also
-- * hold */
-+ /* From now on, return value of timer_callback_should_run()
-+ * will also cause the timer to not requeue itself. Its return
-+ * value cannot change, because it depends on variables updated
-+ * with the runpool_mutex held, which the caller of this must
-+ * also hold
-+ */
- hrtimer_cancel(&backend->scheduling_timer);
- }
-
-@@ -303,25 +309,36 @@ void kbase_backend_ctx_count_changed(struct kbase_device *kbdev)
-
- KBASE_KTRACE_ADD_JM(kbdev, JS_POLICY_TIMER_START, NULL, NULL, 0u, 0u);
- }
-+#else /* !MALI_USE_CSF */
-+ CSTD_UNUSED(kbdev);
-+#endif /* !MALI_USE_CSF */
- }
-
- int kbase_backend_timer_init(struct kbase_device *kbdev)
- {
-+#if !MALI_USE_CSF
- struct kbase_backend_data *backend = &kbdev->hwaccess.backend;
-
- hrtimer_init(&backend->scheduling_timer, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL);
- backend->scheduling_timer.function = timer_callback;
- backend->timer_running = false;
-+#else /* !MALI_USE_CSF */
-+ CSTD_UNUSED(kbdev);
-+#endif /* !MALI_USE_CSF */
-
- return 0;
- }
-
- void kbase_backend_timer_term(struct kbase_device *kbdev)
- {
-+#if !MALI_USE_CSF
- struct kbase_backend_data *backend = &kbdev->hwaccess.backend;
-
- hrtimer_cancel(&backend->scheduling_timer);
-+#else /* !MALI_USE_CSF */
-+ CSTD_UNUSED(kbdev);
-+#endif /* !MALI_USE_CSF */
- }
-
- void kbase_backend_timer_suspend(struct kbase_device *kbdev)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_js_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_js_internal.h
-index 6576e55..5284288 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_js_internal.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_js_internal.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2015, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * Register-based HW access backend specific job scheduler APIs
- */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_l2_mmu_config.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_l2_mmu_config.c
-index e67d12b..7131546 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_l2_mmu_config.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_l2_mmu_config.c
-@@ -1,12 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -17,14 +17,12 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
- #include <mali_kbase_bits.h>
- #include <mali_kbase_config_defaults.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include "mali_kbase_l2_mmu_config.h"
-
- /**
-@@ -56,23 +54,34 @@ struct l2_mmu_config_limit {
- /*
- * Zero represents no limit
- *
-- * For LBEX TBEX TTRX and TNAX:
-+ * For LBEX TBEX TBAX TTRX and TNAX:
- * The value represents the number of outstanding reads (6 bits) or writes (5 bits)
- *
- * For all other GPUS it is a fraction see: mali_kbase_config_defaults.h
- */
- static const struct l2_mmu_config_limit limits[] = {
-- /* GPU read write */
-- {GPU_ID2_PRODUCT_LBEX, {0, GENMASK(10, 5), 5}, {0, GENMASK(16, 12), 12} },
-- {GPU_ID2_PRODUCT_TBEX, {0, GENMASK(10, 5), 5}, {0, GENMASK(16, 12), 12} },
-- {GPU_ID2_PRODUCT_TTRX, {0, GENMASK(12, 7), 7}, {0, GENMASK(17, 13), 13} },
-- {GPU_ID2_PRODUCT_TNAX, {0, GENMASK(12, 7), 7}, {0, GENMASK(17, 13), 13} },
-- {GPU_ID2_PRODUCT_TGOX,
-- {KBASE_3BIT_AID_32, GENMASK(14, 12), 12},
-- {KBASE_3BIT_AID_32, GENMASK(17, 15), 15} },
-- {GPU_ID2_PRODUCT_TNOX,
-- {KBASE_3BIT_AID_32, GENMASK(14, 12), 12},
-- {KBASE_3BIT_AID_32, GENMASK(17, 15), 15} },
-+ /* GPU, read, write */
-+ {GPU_ID2_PRODUCT_LBEX,
-+ {0, GENMASK(10, 5), 5},
-+ {0, GENMASK(16, 12), 12} },
-+ {GPU_ID2_PRODUCT_TBEX,
-+ {0, GENMASK(10, 5), 5},
-+ {0, GENMASK(16, 12), 12} },
-+ {GPU_ID2_PRODUCT_TBAX,
-+ {0, GENMASK(10, 5), 5},
-+ {0, GENMASK(16, 12), 12} },
-+ {GPU_ID2_PRODUCT_TTRX,
-+ {0, GENMASK(12, 7), 7},
-+ {0, GENMASK(17, 13), 13} },
-+ {GPU_ID2_PRODUCT_TNAX,
-+ {0, GENMASK(12, 7), 7},
-+ {0, GENMASK(17, 13), 13} },
-+ {GPU_ID2_PRODUCT_TGOX,
-+ {KBASE_3BIT_AID_32, GENMASK(14, 12), 12},
-+ {KBASE_3BIT_AID_32, GENMASK(17, 15), 15} },
-+ {GPU_ID2_PRODUCT_TNOX,
-+ {KBASE_3BIT_AID_32, GENMASK(14, 12), 12},
-+ {KBASE_3BIT_AID_32, GENMASK(17, 15), 15} },
- };
-
- int kbase_set_mmu_quirks(struct kbase_device *kbdev)
-@@ -100,7 +109,7 @@ int kbase_set_mmu_quirks(struct kbase_device *kbdev)
-
- mmu_config = kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG));
-
-- if (kbase_is_gpu_lost(kbdev))
-+ if (kbase_is_gpu_removed(kbdev))
- return -EIO;
-
- mmu_config &= ~(limit.read.mask | limit.write.mask);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_l2_mmu_config.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_l2_mmu_config.h
-index 0c779ac..07014ad 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_l2_mmu_config.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_l2_mmu_config.h
-@@ -1,31 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * (C) COPYRIGHT 2019-2020 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_always_on.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_always_on.c
-index e33fe0b..077c234 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_always_on.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_always_on.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2015, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2015, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * "Always on" power management policy
- */
-@@ -61,7 +58,11 @@ const struct kbase_pm_policy kbase_pm_always_on_policy_ops = {
- always_on_term, /* term */
- always_on_shaders_needed, /* shaders_needed */
- always_on_get_core_active, /* get_core_active */
-+ NULL, /* handle_event */
- KBASE_PM_POLICY_ID_ALWAYS_ON, /* id */
-+#if MALI_USE_CSF
-+ ALWAYS_ON_PM_SCHED_FLAGS, /* pm_sched_flags */
-+#endif
- };
-
- KBASE_EXPORT_TEST_API(kbase_pm_always_on_policy_ops);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_always_on.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_always_on.h
-index e7927cf..98d35da 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_always_on.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_always_on.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2015,2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2015, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * "Always on" power management policy
- */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_backend.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_backend.c
-index 576c9f2..cc791df 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_backend.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_backend.c
-@@ -1,11 +1,12 @@
-- /*
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * GPU backend implementation of base kernel power management APIs
- */
-@@ -30,14 +28,16 @@
- #include <mali_kbase_config_defaults.h>
-
- #include <mali_kbase_pm.h>
-+#if !MALI_USE_CSF
- #include <mali_kbase_hwaccess_jm.h>
- #include <backend/gpu/mali_kbase_js_internal.h>
- #include <backend/gpu/mali_kbase_jm_internal.h>
-+#endif /* !MALI_USE_CSF */
- #include <mali_kbase_hwcnt_context.h>
- #include <backend/gpu/mali_kbase_pm_internal.h>
- #include <backend/gpu/mali_kbase_devfreq.h>
- #include <mali_kbase_dummy_job_wa.h>
--#include <mali_kbase_irq_internal.h>
-+#include <backend/gpu/mali_kbase_irq_internal.h>
-
- static void kbase_pm_gpu_poweroff_wait_wq(struct work_struct *data);
- static void kbase_pm_hwcnt_disable_worker(struct work_struct *data);
-@@ -106,6 +106,11 @@ void kbase_pm_register_access_enable(struct kbase_device *kbdev)
- if (callbacks)
- callbacks->power_on_callback(kbdev);
-
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ if (WARN_ON(kbase_pm_is_gpu_lost(kbdev)))
-+ dev_err(kbdev->dev, "Attempting to power on while GPU lost\n");
-+#endif
-+
- kbdev->pm.backend.gpu_powered = true;
- }
-
-@@ -139,24 +144,35 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev)
-
- kbdev->pm.backend.ca_cores_enabled = ~0ull;
- kbdev->pm.backend.gpu_powered = false;
-+ kbdev->pm.backend.gpu_ready = false;
- kbdev->pm.suspending = false;
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
-- kbdev->pm.gpu_lost = false;
-+ kbase_pm_set_gpu_lost(kbdev, false);
- #endif
- #ifdef CONFIG_MALI_DEBUG
- kbdev->pm.backend.driver_ready_for_irqs = false;
- #endif /* CONFIG_MALI_DEBUG */
- init_waitqueue_head(&kbdev->pm.backend.gpu_in_desired_state_wait);
-
-+#if !MALI_USE_CSF
- /* Initialise the metrics subsystem */
- ret = kbasep_pm_metrics_init(kbdev);
- if (ret)
- return ret;
-+#else
-+ mutex_init(&kbdev->pm.backend.policy_change_lock);
-+ kbdev->pm.backend.policy_change_clamp_state_to_off = false;
-+ /* Due to dependency on kbase_ipa_control, the metrics subsystem can't
-+ * be initialized here.
-+ */
-+ CSTD_UNUSED(ret);
-+#endif
-
- init_waitqueue_head(&kbdev->pm.backend.reset_done_wait);
- kbdev->pm.backend.reset_done = false;
-
- init_waitqueue_head(&kbdev->pm.zero_active_count_wait);
-+ init_waitqueue_head(&kbdev->pm.resume_wait);
- kbdev->pm.active_count = 0;
-
- spin_lock_init(&kbdev->pm.backend.gpu_cycle_counter_requests_lock);
-@@ -213,7 +229,9 @@ pm_state_machine_fail:
- kbase_pm_policy_term(kbdev);
- kbase_pm_ca_term(kbdev);
- workq_fail:
-+#if !MALI_USE_CSF
- kbasep_pm_metrics_term(kbdev);
-+#endif
- return -EINVAL;
- }
-
-@@ -222,7 +240,8 @@ void kbase_pm_do_poweron(struct kbase_device *kbdev, bool is_resume)
- lockdep_assert_held(&kbdev->pm.lock);
-
- /* Turn clocks and interrupts on - no-op if we haven't done a previous
-- * kbase_pm_clock_off() */
-+ * kbase_pm_clock_off()
-+ */
- kbase_pm_clock_on(kbdev, is_resume);
-
- if (!is_resume) {
-@@ -240,7 +259,8 @@ void kbase_pm_do_poweron(struct kbase_device *kbdev, bool is_resume)
- kbase_pm_update_cores_state(kbdev);
-
- /* NOTE: We don't wait to reach the desired state, since running atoms
-- * will wait for that state to be reached anyway */
-+ * will wait for that state to be reached anyway
-+ */
- }
-
- static void kbase_pm_gpu_poweroff_wait_wq(struct work_struct *data)
-@@ -251,13 +271,20 @@ static void kbase_pm_gpu_poweroff_wait_wq(struct work_struct *data)
- struct kbase_pm_backend_data *backend = &pm->backend;
- unsigned long flags;
-
-+#if !MALI_USE_CSF
- /* Wait for power transitions to complete. We do this with no locks held
- * so that we don't deadlock with any pending workqueues.
- */
- kbase_pm_wait_for_desired_state(kbdev);
-+#endif
-
- kbase_pm_lock(kbdev);
-
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ if (kbase_pm_is_gpu_lost(kbdev))
-+ backend->poweron_required = false;
-+#endif
-+
- if (!backend->poweron_required) {
- unsigned long flags;
-
-@@ -278,6 +305,14 @@ static void kbase_pm_gpu_poweroff_wait_wq(struct work_struct *data)
- kbase_flush_mmu_wqs(kbdev);
- kbase_pm_lock(kbdev);
-
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ /* poweron_required may have changed while pm lock
-+ * was released.
-+ */
-+ if (kbase_pm_is_gpu_lost(kbdev))
-+ backend->poweron_required = false;
-+#endif
-+
- /* Turn off clock now that fault have been handled. We
- * dropped locks so poweron_required may have changed -
- * power back on if this is the case (effectively only
-@@ -296,9 +331,14 @@ static void kbase_pm_gpu_poweroff_wait_wq(struct work_struct *data)
- if (backend->poweron_required) {
- backend->poweron_required = false;
- kbdev->pm.backend.l2_desired = true;
-+#if MALI_USE_CSF
-+ kbdev->pm.backend.mcu_desired = true;
-+#endif
- kbase_pm_update_state(kbdev);
- kbase_pm_update_cores_state_nolock(kbdev);
-+#if !MALI_USE_CSF
- kbase_backend_slot_update(kbdev);
-+#endif /* !MALI_USE_CSF */
- }
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
-@@ -451,12 +491,22 @@ static void kbase_pm_hwcnt_disable_worker(struct work_struct *data)
- */
- backend->hwcnt_disabled = true;
- kbase_pm_update_state(kbdev);
-+#if !MALI_USE_CSF
- kbase_backend_slot_update(kbdev);
-+#endif /* !MALI_USE_CSF */
- } else {
- /* PM state was updated while we were doing the disable,
- * so we need to undo the disable we just performed.
- */
-+#if MALI_USE_CSF
-+ unsigned long lock_flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &lock_flags);
-+#endif
- kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx);
-+#if MALI_USE_CSF
-+ kbase_csf_scheduler_spin_unlock(kbdev, lock_flags);
-+#endif
- }
-
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-@@ -476,8 +526,12 @@ void kbase_pm_do_poweroff(struct kbase_device *kbdev)
- if (kbdev->pm.backend.poweroff_wait_in_progress)
- goto unlock_hwaccess;
-
-+#if MALI_USE_CSF
-+ kbdev->pm.backend.mcu_desired = false;
-+#else
- /* Force all cores off */
- kbdev->pm.backend.shaders_desired = false;
-+#endif
- kbdev->pm.backend.l2_desired = false;
-
- kbdev->pm.backend.poweroff_wait_in_progress = true;
-@@ -528,20 +582,35 @@ int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev,
- KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev));
-
- /* Power up the GPU, don't enable IRQs as we are not ready to receive
-- * them. */
-+ * them
-+ */
- ret = kbase_pm_init_hw(kbdev, flags);
- if (ret) {
- kbase_pm_unlock(kbdev);
- return ret;
- }
--
-+#if MALI_USE_CSF
-+ kbdev->pm.debug_core_mask =
-+ kbdev->gpu_props.props.raw_props.shader_present;
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags);
-+ /* Set the initial value for 'shaders_avail'. It would be later
-+ * modified only from the MCU state machine, when the shader core
-+ * allocation enable mask request has completed. So its value would
-+ * indicate the mask of cores that are currently being used by FW for
-+ * the allocation of endpoints requested by CSGs.
-+ */
-+ kbdev->pm.backend.shaders_avail = kbase_pm_ca_get_core_mask(kbdev);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags);
-+#else
- kbdev->pm.debug_core_mask_all = kbdev->pm.debug_core_mask[0] =
- kbdev->pm.debug_core_mask[1] =
- kbdev->pm.debug_core_mask[2] =
- kbdev->gpu_props.props.raw_props.shader_present;
-+#endif
-
- /* Pretend the GPU is active to prevent a power policy turning the GPU
-- * cores off */
-+ * cores off
-+ */
- kbdev->pm.active_count = 1;
-
- spin_lock_irqsave(&kbdev->pm.backend.gpu_cycle_counter_requests_lock,
-@@ -553,13 +622,27 @@ int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev,
- irq_flags);
-
- /* We are ready to receive IRQ's now as power policy is set up, so
-- * enable them now. */
-+ * enable them now.
-+ */
- #ifdef CONFIG_MALI_DEBUG
- kbdev->pm.backend.driver_ready_for_irqs = true;
- #endif
- kbase_pm_enable_interrupts(kbdev);
-
-+ WARN_ON(!kbdev->pm.backend.gpu_powered);
-+ /* GPU has been powered up (by kbase_pm_init_hw) and interrupts have
-+ * been enabled, so GPU is ready for use and PM state machine can be
-+ * exercised from this point onwards.
-+ */
-+ kbdev->pm.backend.gpu_ready = true;
-+
- /* Turn on the GPU and any cores needed by the policy */
-+#if MALI_USE_CSF
-+ /* Turn on the L2 caches, needed for firmware boot */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags);
-+ kbdev->pm.backend.l2_desired = true;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags);
-+#endif
- kbase_pm_do_poweron(kbdev, false);
- kbase_pm_unlock(kbdev);
-
-@@ -573,6 +656,8 @@ void kbase_hwaccess_pm_halt(struct kbase_device *kbdev)
- mutex_lock(&kbdev->pm.lock);
- kbase_pm_do_poweroff(kbdev);
- mutex_unlock(&kbdev->pm.lock);
-+
-+ kbase_pm_wait_for_poweroff_complete(kbdev);
- }
-
- KBASE_EXPORT_TEST_API(kbase_hwaccess_pm_halt);
-@@ -587,10 +672,15 @@ void kbase_hwaccess_pm_term(struct kbase_device *kbdev)
-
- if (kbdev->pm.backend.hwcnt_disabled) {
- unsigned long flags;
--
-+#if MALI_USE_CSF
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+#else
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+#endif
- }
-
- /* Free any resources the policy allocated */
-@@ -598,8 +688,16 @@ void kbase_hwaccess_pm_term(struct kbase_device *kbdev)
- kbase_pm_policy_term(kbdev);
- kbase_pm_ca_term(kbdev);
-
-+#if !MALI_USE_CSF
- /* Shut down the metrics subsystem */
- kbasep_pm_metrics_term(kbdev);
-+#else
-+ if (WARN_ON(mutex_is_locked(&kbdev->pm.backend.policy_change_lock))) {
-+ mutex_lock(&kbdev->pm.backend.policy_change_lock);
-+ mutex_unlock(&kbdev->pm.backend.policy_change_lock);
-+ }
-+ mutex_destroy(&kbdev->pm.backend.policy_change_lock);
-+#endif
-
- destroy_workqueue(kbdev->pm.backend.gpu_poweroff_wait_wq);
- }
-@@ -611,11 +709,24 @@ void kbase_pm_power_changed(struct kbase_device *kbdev)
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbase_pm_update_state(kbdev);
-
-+#if !MALI_USE_CSF
- kbase_backend_slot_update(kbdev);
-+#endif /* !MALI_USE_CSF */
-
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
- }
-
-+#if MALI_USE_CSF
-+void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev, u64 new_core_mask)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+ lockdep_assert_held(&kbdev->pm.lock);
-+
-+ kbdev->pm.debug_core_mask = new_core_mask;
-+ kbase_pm_update_dynamic_cores_onoff(kbdev);
-+}
-+KBASE_EXPORT_TEST_API(kbase_pm_set_debug_core_mask);
-+#else
- void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev,
- u64 new_core_mask_js0, u64 new_core_mask_js1,
- u64 new_core_mask_js2)
-@@ -636,6 +747,7 @@ void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev,
-
- kbase_pm_update_dynamic_cores_onoff(kbdev);
- }
-+#endif /* MALI_USE_CSF */
-
- void kbase_hwaccess_pm_gpu_active(struct kbase_device *kbdev)
- {
-@@ -651,12 +763,15 @@ void kbase_hwaccess_pm_suspend(struct kbase_device *kbdev)
- {
- /* Force power off the GPU and all cores (regardless of policy), only
- * after the PM active count reaches zero (otherwise, we risk turning it
-- * off prematurely) */
-+ * off prematurely)
-+ */
- kbase_pm_lock(kbdev);
-
- kbase_pm_do_poweroff(kbdev);
-
-+#if !MALI_USE_CSF
- kbase_backend_timer_suspend(kbdev);
-+#endif /* !MALI_USE_CSF */
-
- kbase_pm_unlock(kbdev);
-
-@@ -672,12 +787,19 @@ void kbase_hwaccess_pm_resume(struct kbase_device *kbdev)
-
- kbdev->pm.suspending = false;
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
-- kbdev->pm.gpu_lost = false;
-+ if (kbase_pm_is_gpu_lost(kbdev)) {
-+ dev_dbg(kbdev->dev, "%s: GPU lost in progress\n", __func__);
-+ kbase_pm_unlock(kbdev);
-+ return;
-+ }
- #endif
- kbase_pm_do_poweron(kbdev, true);
-
-+#if !MALI_USE_CSF
- kbase_backend_timer_resume(kbdev);
-+#endif /* !MALI_USE_CSF */
-
-+ wake_up_all(&kbdev->pm.resume_wait);
- kbase_pm_unlock(kbdev);
- }
-
-@@ -685,63 +807,50 @@ void kbase_hwaccess_pm_resume(struct kbase_device *kbdev)
- void kbase_pm_handle_gpu_lost(struct kbase_device *kbdev)
- {
- unsigned long flags;
-- struct kbase_pm_backend_data *backend = &kbdev->pm.backend;
- ktime_t end_timestamp = ktime_get();
-+ struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
-
-- /* Full GPU reset will have been done by hypervisor, so cancel */
-- atomic_set(&kbdev->hwaccess.backend.reset_gpu,
-- KBASE_RESET_GPU_NOT_PENDING);
-- hrtimer_cancel(&kbdev->hwaccess.backend.reset_timer);
--
-- /* GPU is no longer mapped to VM. So no interrupts will be received
-- * and Mali registers have been replaced by dummy RAM
-- */
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-- spin_lock(&kbdev->mmu_mask_change);
-- kbdev->irq_reset_flush = true;
-- spin_unlock(&kbdev->mmu_mask_change);
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-- kbase_synchronize_irqs(kbdev);
-- kbase_flush_mmu_wqs(kbdev);
-- kbdev->irq_reset_flush = false;
-+ if (!kbdev->arb.arb_if)
-+ return;
-
-- /* Clear all jobs running on the GPU */
- mutex_lock(&kbdev->pm.lock);
-- kbdev->pm.gpu_lost = true;
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-- kbdev->protected_mode = false;
-- if (!kbdev->pm.backend.protected_entry_transition_override)
-- kbase_backend_reset(kbdev, &end_timestamp);
-- kbase_pm_metrics_update(kbdev, NULL);
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ mutex_lock(&arb_vm_state->vm_state_lock);
-+ if (kbdev->pm.backend.gpu_powered &&
-+ !kbase_pm_is_gpu_lost(kbdev)) {
-+ kbase_pm_set_gpu_lost(kbdev, true);
-+
-+ /* GPU is no longer mapped to VM. So no interrupts will
-+ * be received and Mali registers have been replaced by
-+ * dummy RAM
-+ */
-+ WARN(!kbase_is_gpu_removed(kbdev),
-+ "GPU is still available after GPU lost event\n");
-
-- /* Cancel any pending HWC dumps */
-- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
-- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE;
-- kbdev->hwcnt.backend.triggered = 1;
-- wake_up(&kbdev->hwcnt.backend.wait);
-- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
-+ /* Full GPU reset will have been done by hypervisor, so
-+ * cancel
-+ */
-+ atomic_set(&kbdev->hwaccess.backend.reset_gpu,
-+ KBASE_RESET_GPU_NOT_PENDING);
-+ hrtimer_cancel(&kbdev->hwaccess.backend.reset_timer);
-+ kbase_synchronize_irqs(kbdev);
-
-- /* Wait for all threads keeping GPU active to complete */
-- mutex_unlock(&kbdev->pm.lock);
-- wait_event(kbdev->pm.zero_active_count_wait,
-- kbdev->pm.active_count == 0);
-- mutex_lock(&kbdev->pm.lock);
-+ /* Clear all jobs running on the GPU */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->protected_mode = false;
-+ kbase_backend_reset(kbdev, &end_timestamp);
-+ kbase_pm_metrics_update(kbdev, NULL);
-+ kbase_pm_update_state(kbdev);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
-- /* Update state to GPU off */
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-- kbdev->pm.backend.shaders_desired = false;
-- kbdev->pm.backend.l2_desired = false;
-- backend->l2_state = KBASE_L2_OFF;
-- backend->shaders_state = KBASE_SHADERS_OFF_CORESTACK_OFF;
-- kbdev->pm.backend.gpu_powered = false;
-- backend->poweroff_wait_in_progress = false;
-- KBASE_KTRACE_ADD(kbdev, PM_WAKE_WAITERS, NULL, 0);
-- wake_up(&kbdev->pm.backend.gpu_in_desired_state_wait);
-- kbase_gpu_cache_clean_wait_complete(kbdev);
-- backend->poweroff_wait_in_progress = false;
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-- wake_up(&kbdev->pm.backend.poweroff_wait);
-+ /* Cancel any pending HWC dumps */
-+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
-+ kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE;
-+ kbdev->hwcnt.backend.triggered = 1;
-+ wake_up(&kbdev->hwcnt.backend.wait);
-+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
-+ }
-+ mutex_unlock(&arb_vm_state->vm_state_lock);
- mutex_unlock(&kbdev->pm.lock);
- }
-+
- #endif /* CONFIG_MALI_ARBITER_SUPPORT */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca.c
-index e7eef26..efc620f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2013-2018, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2013-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -27,9 +26,6 @@
- #include <mali_kbase.h>
- #include <mali_kbase_pm.h>
- #include <backend/gpu/mali_kbase_pm_internal.h>
--#ifdef CONFIG_MALI_NO_MALI
--#include <backend/gpu/mali_kbase_model_dummy.h>
--#endif
- #include <mali_kbase_dummy_job_wa.h>
-
- int kbase_pm_ca_init(struct kbase_device *kbdev)
-@@ -59,6 +55,14 @@ void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask)
-
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-
-+#if MALI_USE_CSF
-+ if (!(core_mask & kbdev->pm.debug_core_mask)) {
-+ dev_err(kbdev->dev,
-+ "OPP core mask 0x%llX does not intersect with debug mask 0x%llX\n",
-+ core_mask, kbdev->pm.debug_core_mask);
-+ goto unlock;
-+ }
-+#else
- if (!(core_mask & kbdev->pm.debug_core_mask_all)) {
- dev_err(kbdev->dev, "OPP core mask 0x%llX does not intersect with debug mask 0x%llX\n",
- core_mask, kbdev->pm.debug_core_mask_all);
-@@ -69,6 +73,7 @@ void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask)
- dev_err(kbdev->dev, "Dynamic core scaling not supported as dummy job WA is enabled");
- goto unlock;
- }
-+#endif /* MALI_USE_CSF */
-
- pm_backend->ca_cores_enabled = core_mask;
-
-@@ -80,21 +85,32 @@ unlock:
- dev_dbg(kbdev->dev, "Devfreq policy : new core mask=%llX\n",
- pm_backend->ca_cores_enabled);
- }
-+KBASE_EXPORT_TEST_API(kbase_devfreq_set_core_mask);
- #endif
-
- u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev)
- {
--#ifdef CONFIG_MALI_DEVFREQ
-- struct kbase_pm_backend_data *pm_backend = &kbdev->pm.backend;
-+#if MALI_USE_CSF
-+ u64 debug_core_mask = kbdev->pm.debug_core_mask;
-+#else
-+ u64 debug_core_mask = kbdev->pm.debug_core_mask_all;
- #endif
-
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
- #ifdef CONFIG_MALI_DEVFREQ
-- return pm_backend->ca_cores_enabled & kbdev->pm.debug_core_mask_all;
-+ /*
-+ * Although in the init we let the pm_backend->ca_cores_enabled to be
-+ * the max config (it uses the base_gpu_props), at this function we need
-+ * to limit it to be a subgroup of the curr config, otherwise the
-+ * shaders state machine on the PM does not evolve.
-+ */
-+ return kbdev->gpu_props.curr_config.shader_present &
-+ kbdev->pm.backend.ca_cores_enabled &
-+ debug_core_mask;
- #else
-- return kbdev->gpu_props.props.raw_props.shader_present &
-- kbdev->pm.debug_core_mask_all;
-+ return kbdev->gpu_props.curr_config.shader_present &
-+ debug_core_mask;
- #endif
- }
-
-@@ -104,8 +120,8 @@ u64 kbase_pm_ca_get_instr_core_mask(struct kbase_device *kbdev)
- {
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
--#ifdef CONFIG_MALI_NO_MALI
-- return (((1ull) << KBASE_DUMMY_MODEL_MAX_SHADER_CORES) - 1);
-+#if MALI_USE_CSF
-+ return kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER);
- #else
- return kbdev->pm.backend.pm_shaders_core_mask;
- #endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca.h
-index 5423e96..8d169c3 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca_devfreq.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca_devfreq.h
-index f67ec65..41f3c14 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca_devfreq.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_ca_devfreq.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_coarse_demand.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_coarse_demand.c
-index 9eef44a..f40b753 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_coarse_demand.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_coarse_demand.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2016, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * "Coarse Demand" power management policy
- */
-@@ -60,7 +57,11 @@ const struct kbase_pm_policy kbase_pm_coarse_demand_policy_ops = {
- coarse_demand_term, /* term */
- coarse_demand_shaders_needed, /* shaders_needed */
- coarse_demand_get_core_active, /* get_core_active */
-+ NULL, /* handle_event */
- KBASE_PM_POLICY_ID_COARSE_DEMAND, /* id */
-+#if MALI_USE_CSF
-+ COARSE_ON_DEMAND_PM_SCHED_FLAGS, /* pm_sched_flags */
-+#endif
- };
-
- KBASE_EXPORT_TEST_API(kbase_pm_coarse_demand_policy_ops);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_coarse_demand.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_coarse_demand.h
-index 304e5d7..5e3f17e 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_coarse_demand.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_coarse_demand.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2015,2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2015, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * "Coarse Demand" power management policy
- */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_defs.h
-index f4bcf3e..1a0572b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_defs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -29,9 +28,6 @@
-
- #include "mali_kbase_pm_always_on.h"
- #include "mali_kbase_pm_coarse_demand.h"
--#if !MALI_CUSTOMER_RELEASE
--#include "mali_kbase_pm_always_on_demand.h"
--#endif
-
- /* Forward definition - see mali_kbase.h */
- struct kbase_device;
-@@ -62,24 +58,9 @@ enum kbase_pm_core_type {
- KBASE_PM_CORE_STACK = STACK_PRESENT_LO
- };
-
--/**
-+/*
- * enum kbase_l2_core_state - The states used for the L2 cache & tiler power
- * state machine.
-- *
-- * @KBASE_L2_OFF: The L2 cache and tiler are off
-- * @KBASE_L2_PEND_ON: The L2 cache and tiler are powering on
-- * @KBASE_L2_RESTORE_CLOCKS: The GPU clock is restored. Conditionally used.
-- * @KBASE_L2_ON_HWCNT_ENABLE: The L2 cache and tiler are on, and hwcnt is being
-- * enabled
-- * @KBASE_L2_ON: The L2 cache and tiler are on, and hwcnt is enabled
-- * @KBASE_L2_ON_HWCNT_DISABLE: The L2 cache and tiler are on, and hwcnt is being
-- * disabled
-- * @KBASE_L2_SLOW_DOWN_CLOCKS: The GPU clock is set to appropriate or lowest
-- * clock. Conditionally used.
-- * @KBASE_L2_POWER_DOWN: The L2 cache and tiler are about to be powered off
-- * @KBASE_L2_PEND_OFF: The L2 cache and tiler are powering off
-- * @KBASE_L2_RESET_WAIT: The GPU is resetting, L2 cache and tiler power state
-- * are unknown
- */
- enum kbase_l2_core_state {
- #define KBASEP_L2_STATE(n) KBASE_L2_ ## n,
-@@ -87,45 +68,19 @@ enum kbase_l2_core_state {
- #undef KBASEP_L2_STATE
- };
-
--/**
-+#if MALI_USE_CSF
-+/*
-+ * enum kbase_mcu_state - The states used for the MCU state machine.
-+ */
-+enum kbase_mcu_state {
-+#define KBASEP_MCU_STATE(n) KBASE_MCU_ ## n,
-+#include "mali_kbase_pm_mcu_states.h"
-+#undef KBASEP_MCU_STATE
-+};
-+#endif
-+
-+/*
- * enum kbase_shader_core_state - The states used for the shaders' state machine.
-- *
-- * @KBASE_SHADERS_OFF_CORESTACK_OFF: The shaders and core stacks are off
-- * @KBASE_SHADERS_OFF_CORESTACK_PEND_ON: The shaders are off, core stacks have
-- * been requested to power on and hwcnt
-- * is being disabled
-- * @KBASE_SHADERS_PEND_ON_CORESTACK_ON: Core stacks are on, shaders have been
-- * requested to power on. Or after doing
-- * partial shader on/off, checking whether
-- * it's the desired state.
-- * @KBASE_SHADERS_ON_CORESTACK_ON: The shaders and core stacks are on, and hwcnt
-- * already enabled.
-- * @KBASE_SHADERS_ON_CORESTACK_ON_RECHECK: The shaders and core stacks
-- * are on, hwcnt disabled, and checks
-- * to powering down or re-enabling
-- * hwcnt.
-- * @KBASE_SHADERS_WAIT_OFF_CORESTACK_ON: The shaders have been requested to
-- * power off, but they remain on for the
-- * duration of the hysteresis timer
-- * @KBASE_SHADERS_WAIT_GPU_IDLE: The shaders partial poweroff needs to reach
-- * a state where jobs on the GPU are finished
-- * including jobs currently running and in the
-- * GPU queue because of GPU2017-861
-- * @KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON: The hysteresis timer has expired
-- * @KBASE_SHADERS_L2_FLUSHING_CORESTACK_ON: The core stacks are on and the
-- * level 2 cache is being flushed.
-- * @KBASE_SHADERS_READY_OFF_CORESTACK_ON: The core stacks are on and the shaders
-- * are ready to be powered off.
-- * @KBASE_SHADERS_PEND_OFF_CORESTACK_ON: The core stacks are on, and the shaders
-- * have been requested to power off
-- * @KBASE_SHADERS_OFF_CORESTACK_PEND_OFF: The shaders are off, and the core stacks
-- * have been requested to power off
-- * @KBASE_SHADERS_OFF_CORESTACK_OFF_TIMER_PEND_OFF: Shaders and corestacks are
-- * off, but the tick timer
-- * cancellation is still
-- * pending.
-- * @KBASE_SHADERS_RESET_WAIT: The GPU is resetting, shader and core stack power
-- * states are unknown
- */
- enum kbase_shader_core_state {
- #define KBASEP_SHADER_STATE(n) KBASE_SHADERS_ ## n,
-@@ -137,28 +92,40 @@ enum kbase_shader_core_state {
- * struct kbasep_pm_metrics - Metrics data collected for use by the power
- * management framework.
- *
-- * @time_busy: number of ns the GPU was busy executing jobs since the
-- * @time_period_start timestamp.
-- * @time_idle: number of ns since time_period_start the GPU was not executing
-- * jobs since the @time_period_start timestamp.
-- * @busy_cl: number of ns the GPU was busy executing CL jobs. Note that
-- * if two CL jobs were active for 400ns, this value would be updated
-- * with 800.
-- * @busy_gl: number of ns the GPU was busy executing GL jobs. Note that
-- * if two GL jobs were active for 400ns, this value would be updated
-- * with 800.
-+ * @time_busy: the amount of time the GPU was busy executing jobs since the
-+ * @time_period_start timestamp, in units of 256ns. This also includes
-+ * time_in_protm, the time spent in protected mode, since it's assumed
-+ * the GPU was busy 100% during this period.
-+ * @time_idle: the amount of time the GPU was not executing jobs since the
-+ * time_period_start timestamp, measured in units of 256ns.
-+ * @time_in_protm: The amount of time the GPU has spent in protected mode since
-+ * the time_period_start timestamp, measured in units of 256ns.
-+ * @busy_cl: the amount of time the GPU was busy executing CL jobs. Note that
-+ * if two CL jobs were active for 256ns, this value would be updated
-+ * with 2 (2x256ns).
-+ * @busy_gl: the amount of time the GPU was busy executing GL jobs. Note that
-+ * if two GL jobs were active for 256ns, this value would be updated
-+ * with 2 (2x256ns).
- */
- struct kbasep_pm_metrics {
- u32 time_busy;
- u32 time_idle;
-+#if MALI_USE_CSF
-+ u32 time_in_protm;
-+#else
- u32 busy_cl[2];
- u32 busy_gl;
-+#endif
- };
-
- /**
- * struct kbasep_pm_metrics_state - State required to collect the metrics in
- * struct kbasep_pm_metrics
- * @time_period_start: time at which busy/idle measurements started
-+ * @ipa_control_client: Handle returned on registering DVFS as a
-+ * kbase_ipa_control client
-+ * @skip_gpu_active_sanity_check: Decide whether to skip GPU_ACTIVE sanity
-+ * check in DVFS utilisation calculation
- * @gpu_active: true when the GPU is executing jobs. false when
- * not. Updated when the job scheduler informs us a job in submitted
- * or removed from a GPU slot.
-@@ -170,6 +137,7 @@ struct kbasep_pm_metrics {
- * @values: The current values of the power management metrics. The
- * kbase_pm_get_dvfs_metrics() function is used to compare these
- * current values with the saved values from a previous invocation.
-+ * @initialized: tracks whether metrics_state has been initialized or not.
- * @timer: timer to regularly make DVFS decisions based on the power
- * management metrics.
- * @timer_active: boolean indicating @timer is running
-@@ -178,9 +146,14 @@ struct kbasep_pm_metrics {
- */
- struct kbasep_pm_metrics_state {
- ktime_t time_period_start;
-+#if MALI_USE_CSF
-+ void *ipa_control_client;
-+ bool skip_gpu_active_sanity_check;
-+#else
- bool gpu_active;
- u32 active_cl_ctx[2];
- u32 active_gl_ctx[3];
-+#endif
- spinlock_t lock;
-
- void *platform_data;
-@@ -189,6 +162,7 @@ struct kbasep_pm_metrics_state {
- struct kbasep_pm_metrics values;
-
- #ifdef CONFIG_MALI_MIDGARD_DVFS
-+ bool initialized;
- struct hrtimer timer;
- bool timer_active;
- struct kbasep_pm_metrics dvfs_last;
-@@ -202,8 +176,12 @@ struct kbasep_pm_metrics_state {
- * @work: Work item which cancels the timer
- * @timer: Timer for powering off the shader cores
- * @configured_interval: Period of GPU poweroff timer
-- * @configured_ticks: User-configured number of ticks to wait after the shader
-- * power down request is received before turning off the cores
-+ * @default_ticks: User-configured number of ticks to wait after the shader
-+ * power down request is received before turning off the cores
-+ * @configured_ticks: Power-policy configured number of ticks to wait after the
-+ * shader power down request is received before turning off
-+ * the cores. For simple power policies, this is equivalent
-+ * to @default_ticks.
- * @remaining_ticks: Number of remaining timer ticks until shaders are powered off
- * @cancel_queued: True if the cancellation work item has been queued. This is
- * required to ensure that it is not queued twice, e.g. after
-@@ -217,6 +195,7 @@ struct kbasep_pm_tick_timer_state {
- struct hrtimer timer;
-
- ktime_t configured_interval;
-+ unsigned int default_ticks;
- unsigned int configured_ticks;
- unsigned int remaining_ticks;
-
-@@ -227,9 +206,6 @@ struct kbasep_pm_tick_timer_state {
- union kbase_pm_policy_data {
- struct kbasep_pm_policy_always_on always_on;
- struct kbasep_pm_policy_coarse_demand coarse_demand;
--#if !MALI_CUSTOMER_RELEASE
-- struct kbasep_pm_policy_always_on_demand always_on_demand;
--#endif
- };
-
- /**
-@@ -240,7 +216,8 @@ union kbase_pm_policy_data {
- *
- * @pm_current_policy: The policy that is currently actively controlling the
- * power state.
-- * @pm_policy_data: Private data for current PM policy
-+ * @pm_policy_data: Private data for current PM policy. This is automatically
-+ * zeroed when a policy change occurs.
- * @reset_done: Flag when a reset is complete
- * @reset_done_wait: Wait queue to wait for changes to @reset_done
- * @gpu_cycle_counter_requests: The reference count of active gpu cycle counter
-@@ -254,6 +231,11 @@ union kbase_pm_policy_data {
- * variable should be protected by: both the hwaccess_lock
- * spinlock and the pm.lock mutex for writes; or at least
- * one of either lock for reads.
-+ * @gpu_ready: Indicates whether the GPU is in a state in which it is
-+ * safe to perform PM changes. When false, the PM state
-+ * machine needs to wait before making changes to the GPU
-+ * power policy, DevFreq or core_mask, so as to avoid these
-+ * changing while implicit GPU resets are ongoing.
- * @pm_shaders_core_mask: Shader PM state synchronised shaders core mask. It
- * holds the cores enabled in a hardware counters dump,
- * and may differ from @shaders_avail when under different
-@@ -294,6 +276,8 @@ union kbase_pm_policy_data {
- * @callback_soft_reset: Optional callback to software reset the GPU. See
- * &struct kbase_pm_callback_conf
- * @ca_cores_enabled: Cores that are currently available
-+ * @mcu_state: The current state of the micro-control unit, only applicable
-+ * to GPUs that have such a component
- * @l2_state: The current state of the L2 cache state machine. See
- * &enum kbase_l2_core_state
- * @l2_desired: True if the L2 cache should be powered on by the L2 cache state
-@@ -303,10 +287,10 @@ union kbase_pm_policy_data {
- * @shaders_avail: This is updated by the state machine when it is in a state
- * where it can write to the SHADER_PWRON or PWROFF registers
- * to have the same set of available cores as specified by
-- * @shaders_desired_mask. So it would eventually have the same
-- * value as @shaders_desired_mask and would precisely indicate
-- * the cores that are currently available. This is internal to
-- * shader state machine and should *not* be modified elsewhere.
-+ * @shaders_desired_mask. So would precisely indicate the cores
-+ * that are currently available. This is internal to shader
-+ * state machine of JM GPUs and should *not* be modified
-+ * elsewhere.
- * @shaders_desired_mask: This is updated by the state machine when it is in
- * a state where it can handle changes to the core
- * availability (either by DVFS or sysfs). This is
-@@ -318,6 +302,16 @@ union kbase_pm_policy_data {
- * cores may be different, but there should be transitions in
- * progress that will eventually achieve this state (assuming
- * that the policy doesn't change its mind in the mean time).
-+ * @mcu_desired: True if the micro-control unit should be powered on
-+ * @policy_change_clamp_state_to_off: Signaling the backend is in PM policy
-+ * change transition, needs the mcu/L2 to be brought back to the
-+ * off state and remain in that state until the flag is cleared.
-+ * @csf_pm_sched_flags: CSF Dynamic PM control flags in accordance to the
-+ * current active PM policy. This field is updated whenever a
-+ * new policy is activated.
-+ * @policy_change_lock: Used to serialize the policy change calls. In CSF case,
-+ * the change of policy may involve the scheduler to
-+ * suspend running CSGs and then reconfigure the MCU.
- * @in_reset: True if a GPU is resetting and normal power manager operation is
- * suspended
- * @partial_shaderoff: True if we want to partial power off shader cores,
-@@ -373,6 +367,7 @@ struct kbase_pm_backend_data {
- wait_queue_head_t gpu_in_desired_state_wait;
-
- bool gpu_powered;
-+ bool gpu_ready;
-
- u64 pm_shaders_core_mask;
-
-@@ -406,10 +401,19 @@ struct kbase_pm_backend_data {
-
- u64 ca_cores_enabled;
-
-+#if MALI_USE_CSF
-+ enum kbase_mcu_state mcu_state;
-+#endif
- enum kbase_l2_core_state l2_state;
- enum kbase_shader_core_state shaders_state;
- u64 shaders_avail;
- u64 shaders_desired_mask;
-+#if MALI_USE_CSF
-+ bool mcu_desired;
-+ bool policy_change_clamp_state_to_off;
-+ unsigned int csf_pm_sched_flags;
-+ struct mutex policy_change_lock;
-+#endif
- bool l2_desired;
- bool l2_always_on;
- bool shaders_desired;
-@@ -433,6 +437,23 @@ struct kbase_pm_backend_data {
- struct work_struct gpu_clock_control_work;
- };
-
-+#if MALI_USE_CSF
-+/* CSF PM flag, signaling that the MCU CORE should be kept on */
-+#define CSF_DYNAMIC_PM_CORE_KEEP_ON (1 << 0)
-+/* CSF PM flag, signaling no scheduler suspension on idle groups */
-+#define CSF_DYNAMIC_PM_SCHED_IGNORE_IDLE (1 << 1)
-+/* CSF PM flag, signaling no scheduler suspension on no runnable groups */
-+#define CSF_DYNAMIC_PM_SCHED_NO_SUSPEND (1 << 2)
-+
-+/* The following flags corresponds to existing defined PM policies */
-+#define ALWAYS_ON_PM_SCHED_FLAGS (CSF_DYNAMIC_PM_CORE_KEEP_ON | \
-+ CSF_DYNAMIC_PM_SCHED_IGNORE_IDLE | \
-+ CSF_DYNAMIC_PM_SCHED_NO_SUSPEND)
-+#define COARSE_ON_DEMAND_PM_SCHED_FLAGS (0)
-+#if !MALI_CUSTOMER_RELEASE
-+#define ALWAYS_ON_DEMAND_PM_SCHED_FLAGS (CSF_DYNAMIC_PM_SCHED_IGNORE_IDLE)
-+#endif
-+#endif
-
- /* List of policy IDs */
- enum kbase_pm_policy_id {
-@@ -443,6 +464,33 @@ enum kbase_pm_policy_id {
- KBASE_PM_POLICY_ID_ALWAYS_ON
- };
-
-+/**
-+ * enum kbase_pm_policy_event - PM Policy event ID
-+ */
-+enum kbase_pm_policy_event {
-+ /**
-+ * @KBASE_PM_POLICY_EVENT_IDLE: Indicates that the GPU power state
-+ * model has determined that the GPU has gone idle.
-+ */
-+ KBASE_PM_POLICY_EVENT_IDLE,
-+ /**
-+ * @KBASE_PM_POLICY_EVENT_POWER_ON: Indicates that the GPU state model
-+ * is preparing to power on the GPU.
-+ */
-+ KBASE_PM_POLICY_EVENT_POWER_ON,
-+ /**
-+ * @KBASE_PM_POLICY_EVENT_TIMER_HIT: Indicates that the GPU became
-+ * active while the Shader Tick Timer was holding the GPU in a powered
-+ * on state.
-+ */
-+ KBASE_PM_POLICY_EVENT_TIMER_HIT,
-+ /**
-+ * @KBASE_PM_POLICY_EVENT_TIMER_MISS: Indicates that the GPU did not
-+ * become active before the Shader Tick Timer timeout occurred.
-+ */
-+ KBASE_PM_POLICY_EVENT_TIMER_MISS,
-+};
-+
- /**
- * struct kbase_pm_policy - Power policy structure.
- *
-@@ -455,15 +503,22 @@ enum kbase_pm_policy_id {
- * @shaders_needed: Function called to find out if shader cores are needed
- * @get_core_active: Function called to get the current overall GPU power
- * state
-+ * @handle_event: Function called when a PM policy event occurs. Should be
-+ * set to NULL if the power policy doesn't require any
-+ * event notifications.
- * @id: Field indicating an ID for this policy. This is not
- * necessarily the same as its index in the list returned
- * by kbase_pm_list_policies().
- * It is used purely for debugging.
-+ * @pm_sched_flags: Policy associated with CSF PM scheduling operational flags.
-+ * Pre-defined required flags exist for each of the
-+ * ARM released policies, such as 'always_on', 'coarse_demand'
-+ * and etc.
- */
- struct kbase_pm_policy {
- char *name;
-
-- /**
-+ /*
- * Function called when the policy is selected
- *
- * This should initialize the kbdev->pm.pm_policy_data structure. It
-@@ -477,7 +532,7 @@ struct kbase_pm_policy {
- */
- void (*init)(struct kbase_device *kbdev);
-
-- /**
-+ /*
- * Function called when the policy is unselected.
- *
- * @kbdev: The kbase device structure for the device (must be a
-@@ -485,7 +540,7 @@ struct kbase_pm_policy {
- */
- void (*term)(struct kbase_device *kbdev);
-
-- /**
-+ /*
- * Function called to find out if shader cores are needed
- *
- * This needs to at least satisfy kbdev->pm.backend.shaders_desired,
-@@ -498,7 +553,7 @@ struct kbase_pm_policy {
- */
- bool (*shaders_needed)(struct kbase_device *kbdev);
-
-- /**
-+ /*
- * Function called to get the current overall GPU power state
- *
- * This function must meet or exceed the requirements for power
-@@ -511,7 +566,26 @@ struct kbase_pm_policy {
- */
- bool (*get_core_active)(struct kbase_device *kbdev);
-
-+ /**
-+ * Function called when a power event occurs
-+ *
-+ * @kbdev: The kbase device structure for the device (must be a
-+ * valid pointer)
-+ * @event: The id of the power event that has occurred
-+ */
-+ void (*handle_event)(struct kbase_device *kbdev,
-+ enum kbase_pm_policy_event event);
-+
- enum kbase_pm_policy_id id;
-+
-+#if MALI_USE_CSF
-+ /* Policy associated with CSF PM scheduling operational flags.
-+ * There are pre-defined required flags exist for each of the
-+ * ARM released policies, such as 'always_on', 'coarse_demand'
-+ * and etc.
-+ */
-+ unsigned int pm_sched_flags;
-+#endif
- };
-
- #endif /* _KBASE_PM_HWACCESS_DEFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_driver.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_driver.c
-index 6b821f7..bcada93 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_driver.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_driver.c
-@@ -1,12 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -17,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -32,12 +30,18 @@
- #include <mali_kbase_pm.h>
- #include <mali_kbase_config_defaults.h>
- #include <mali_kbase_smc.h>
-+
-+#if MALI_USE_CSF
-+#include <csf/ipa_control/mali_kbase_csf_ipa_control.h>
-+#else
- #include <mali_kbase_hwaccess_jm.h>
-+#endif /* !MALI_USE_CSF */
-+
- #include <mali_kbase_reset_gpu.h>
- #include <mali_kbase_ctx_sched.h>
- #include <mali_kbase_hwcnt_context.h>
- #include <backend/gpu/mali_kbase_cache_policy_backend.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include <backend/gpu/mali_kbase_irq_internal.h>
- #include <backend/gpu/mali_kbase_pm_internal.h>
- #include <backend/gpu/mali_kbase_l2_mmu_config.h>
-@@ -45,6 +49,9 @@
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- #include <arbiter/mali_kbase_arbiter_pm.h>
- #endif /* CONFIG_MALI_ARBITER_SUPPORT */
-+#if MALI_USE_CSF
-+#include <csf/ipa_control/mali_kbase_csf_ipa_control.h>
-+#endif
-
- #include <linux/of.h>
-
-@@ -89,6 +96,28 @@ static u64 kbase_pm_get_state(
- enum kbase_pm_core_type core_type,
- enum kbasep_pm_action action);
-
-+#if MALI_USE_CSF
-+bool kbase_pm_is_mcu_desired(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ if (unlikely(!kbdev->csf.firmware_inited))
-+ return false;
-+
-+ if (kbdev->csf.scheduler.pm_active_count)
-+ return true;
-+
-+ /* MCU is supposed to be ON, only when scheduler.pm_active_count is
-+ * non zero. But for always_on policy, the MCU needs to be kept on,
-+ * unless policy changing transition needs it off.
-+ */
-+
-+ return (kbdev->pm.backend.mcu_desired &&
-+ kbase_pm_no_mcu_core_pwroff(kbdev) &&
-+ !kbdev->pm.backend.policy_change_clamp_state_to_off);
-+}
-+#endif
-+
- bool kbase_pm_is_l2_desired(struct kbase_device *kbdev)
- {
- if (kbdev->pm.backend.protected_entry_transition_override)
-@@ -102,6 +131,11 @@ bool kbase_pm_is_l2_desired(struct kbase_device *kbdev)
- !kbdev->pm.backend.shaders_desired)
- return false;
-
-+#if MALI_USE_CSF
-+ if (kbdev->pm.backend.policy_change_clamp_state_to_off)
-+ return false;
-+#endif
-+
- return kbdev->pm.backend.l2_desired;
- }
-
-@@ -210,7 +244,7 @@ static u32 core_type_to_reg(enum kbase_pm_core_type core_type,
- return (u32)core_type + (u32)action;
- }
-
--#ifdef CONFIG_ARM64
-+#if IS_ENABLED(CONFIG_ARM64)
- static void mali_cci_flush_l2(struct kbase_device *kbdev)
- {
- const u32 mask = CLEAN_CACHES_COMPLETED | RESET_COMPLETED;
-@@ -233,7 +267,8 @@ static void mali_cci_flush_l2(struct kbase_device *kbdev)
- GPU_CONTROL_REG(GPU_IRQ_RAWSTAT));
-
- /* Wait for cache flush to complete before continuing, exit on
-- * gpu resets or loop expiry. */
-+ * gpu resets or loop expiry.
-+ */
- while (((raw & mask) == 0) && --loops) {
- raw = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(GPU_IRQ_RAWSTAT));
-@@ -372,9 +407,9 @@ u64 kbase_pm_get_present_cores(struct kbase_device *kbdev,
-
- switch (type) {
- case KBASE_PM_CORE_L2:
-- return kbdev->gpu_props.props.raw_props.l2_present;
-+ return kbdev->gpu_props.curr_config.l2_present;
- case KBASE_PM_CORE_SHADER:
-- return kbdev->gpu_props.props.raw_props.shader_present;
-+ return kbdev->gpu_props.curr_config.shader_present;
- case KBASE_PM_CORE_TILER:
- return kbdev->gpu_props.props.raw_props.tiler_present;
- case KBASE_PM_CORE_STACK:
-@@ -468,14 +503,10 @@ static void kbase_pm_trigger_hwcnt_disable(struct kbase_device *kbdev)
- */
- if (kbase_hwcnt_context_disable_atomic(kbdev->hwcnt_gpu_ctx)) {
- backend->hwcnt_disabled = true;
-+
- } else {
--#if KERNEL_VERSION(3, 16, 0) > LINUX_VERSION_CODE
-- queue_work(system_wq,
-- &backend->hwcnt_disable_work);
--#else
-- queue_work(system_highpri_wq,
-- &backend->hwcnt_disable_work);
--#endif
-+ kbase_hwcnt_context_queue_work(kbdev->hwcnt_gpu_ctx,
-+ &backend->hwcnt_disable_work);
- }
- }
-
-@@ -493,7 +524,8 @@ static void kbase_pm_l2_config_override(struct kbase_device *kbdev)
- * Skip if size and hash are not given explicitly,
- * which means default values are used.
- */
-- if ((kbdev->l2_size_override == 0) && (kbdev->l2_hash_override == 0))
-+ if ((kbdev->l2_size_override == 0) && (kbdev->l2_hash_override == 0) &&
-+ (!kbdev->l2_hash_values_override))
- return;
-
- val = kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_CONFIG));
-@@ -504,13 +536,25 @@ static void kbase_pm_l2_config_override(struct kbase_device *kbdev)
- }
-
- if (kbdev->l2_hash_override) {
-+ WARN_ON(kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_ASN_HASH));
- val &= ~L2_CONFIG_HASH_MASK;
- val |= (kbdev->l2_hash_override << L2_CONFIG_HASH_SHIFT);
-+ } else if (kbdev->l2_hash_values_override) {
-+ int i;
-+
-+ WARN_ON(!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_ASN_HASH));
-+ val &= ~L2_CONFIG_ASN_HASH_ENABLE_MASK;
-+ val |= (0x1 << L2_CONFIG_ASN_HASH_ENABLE_SHIFT);
-+
-+ for (i = 0; i < ASN_HASH_COUNT; i++) {
-+ dev_dbg(kbdev->dev, "Program 0x%x to ASN_HASH[%d]\n",
-+ kbdev->l2_hash_values[i], i);
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(ASN_HASH(i)),
-+ kbdev->l2_hash_values[i]);
-+ }
- }
-
- dev_dbg(kbdev->dev, "Program 0x%x to L2_CONFIG\n", val);
--
-- /* Write L2_CONFIG to override */
- kbase_reg_write(kbdev, GPU_CONTROL_REG(L2_CONFIG), val);
- }
-
-@@ -523,6 +567,278 @@ static void kbase_pm_control_gpu_clock(struct kbase_device *kbdev)
- queue_work(system_wq, &backend->gpu_clock_control_work);
- }
-
-+#if MALI_USE_CSF
-+static const char *kbase_mcu_state_to_string(enum kbase_mcu_state state)
-+{
-+ const char *const strings[] = {
-+#define KBASEP_MCU_STATE(n) #n,
-+#include "mali_kbase_pm_mcu_states.h"
-+#undef KBASEP_MCU_STATE
-+ };
-+ if (WARN_ON((size_t)state >= ARRAY_SIZE(strings)))
-+ return "Bad MCU state";
-+ else
-+ return strings[state];
-+}
-+
-+static inline bool kbase_pm_handle_mcu_core_attr_update(struct kbase_device *kbdev)
-+{
-+ struct kbase_pm_backend_data *backend = &kbdev->pm.backend;
-+ bool timer_update;
-+ bool core_mask_update;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ WARN_ON(backend->mcu_state != KBASE_MCU_ON);
-+
-+ /* This function is only for cases where the MCU managing Cores, if
-+ * the firmware mode is with host control, do nothing here.
-+ */
-+ if (unlikely(kbdev->csf.firmware_hctl_core_pwr))
-+ return false;
-+
-+ core_mask_update =
-+ backend->shaders_avail != backend->shaders_desired_mask;
-+
-+ timer_update = kbdev->csf.mcu_core_pwroff_dur_count !=
-+ kbdev->csf.mcu_core_pwroff_reg_shadow;
-+
-+ if (core_mask_update || timer_update)
-+ kbase_csf_firmware_update_core_attr(kbdev, timer_update,
-+ core_mask_update, backend->shaders_desired_mask);
-+
-+ return (core_mask_update || timer_update);
-+}
-+
-+static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
-+{
-+ struct kbase_pm_backend_data *backend = &kbdev->pm.backend;
-+ enum kbase_mcu_state prev_state;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ /*
-+ * Initial load of firmare should have been done to
-+ * exercise the MCU state machine.
-+ */
-+ if (unlikely(!kbdev->csf.firmware_inited)) {
-+ WARN_ON(backend->mcu_state != KBASE_MCU_OFF);
-+ return -EIO;
-+ }
-+
-+ do {
-+ u64 shaders_trans = kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_SHADER);
-+ u64 shaders_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER);
-+
-+ /* mask off ready from trans in case transitions finished
-+ * between the register reads
-+ */
-+ shaders_trans &= ~shaders_ready;
-+
-+ prev_state = backend->mcu_state;
-+
-+ switch (backend->mcu_state) {
-+ case KBASE_MCU_OFF:
-+ if (kbase_pm_is_mcu_desired(kbdev) &&
-+ !backend->policy_change_clamp_state_to_off &&
-+ backend->l2_state == KBASE_L2_ON) {
-+ kbase_csf_firmware_trigger_reload(kbdev);
-+ backend->mcu_state = KBASE_MCU_PEND_ON_RELOAD;
-+ }
-+ break;
-+
-+ case KBASE_MCU_PEND_ON_RELOAD:
-+ if (kbdev->csf.firmware_reloaded) {
-+ backend->shaders_desired_mask =
-+ kbase_pm_ca_get_core_mask(kbdev);
-+ kbase_csf_firmware_global_reinit(kbdev,
-+ backend->shaders_desired_mask);
-+ backend->mcu_state =
-+ KBASE_MCU_ON_GLB_REINIT_PEND;
-+ }
-+ break;
-+
-+ case KBASE_MCU_ON_GLB_REINIT_PEND:
-+ if (kbase_csf_firmware_global_reinit_complete(kbdev)) {
-+ backend->shaders_avail =
-+ backend->shaders_desired_mask;
-+ backend->pm_shaders_core_mask = 0;
-+ if (kbdev->csf.firmware_hctl_core_pwr) {
-+ kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER,
-+ backend->shaders_avail, ACTION_PWRON);
-+ backend->mcu_state =
-+ KBASE_MCU_HCTL_SHADERS_PEND_ON;
-+ } else
-+ backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE;
-+ }
-+ break;
-+
-+ case KBASE_MCU_HCTL_SHADERS_PEND_ON:
-+ if (!shaders_trans &&
-+ shaders_ready == backend->shaders_avail) {
-+ /* Cores now stable, notify MCU the stable mask */
-+ kbase_csf_firmware_update_core_attr(kbdev,
-+ false, true, shaders_ready);
-+
-+ backend->pm_shaders_core_mask = shaders_ready;
-+ backend->mcu_state =
-+ KBASE_MCU_HCTL_CORES_NOTIFY_PEND;
-+ }
-+ break;
-+
-+ case KBASE_MCU_HCTL_CORES_NOTIFY_PEND:
-+ /* Wait for the acknowledgement */
-+ if (kbase_csf_firmware_core_attr_updated(kbdev))
-+ backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE;
-+ break;
-+
-+ case KBASE_MCU_ON_HWCNT_ENABLE:
-+ backend->hwcnt_desired = true;
-+ if (backend->hwcnt_disabled) {
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ kbase_hwcnt_context_enable(
-+ kbdev->hwcnt_gpu_ctx);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+ backend->hwcnt_disabled = false;
-+ }
-+ backend->mcu_state = KBASE_MCU_ON;
-+ break;
-+
-+ case KBASE_MCU_ON:
-+ backend->shaders_desired_mask = kbase_pm_ca_get_core_mask(kbdev);
-+
-+ if (!kbase_pm_is_mcu_desired(kbdev))
-+ backend->mcu_state = KBASE_MCU_ON_HWCNT_DISABLE;
-+ else if (kbdev->csf.firmware_hctl_core_pwr) {
-+ /* Host control add additional Cores to be active */
-+ if (backend->shaders_desired_mask & ~shaders_ready) {
-+ backend->hwcnt_desired = false;
-+ if (!backend->hwcnt_disabled)
-+ kbase_pm_trigger_hwcnt_disable(kbdev);
-+ backend->mcu_state =
-+ KBASE_MCU_HCTL_MCU_ON_RECHECK;
-+ }
-+ } else if (kbase_pm_handle_mcu_core_attr_update(kbdev))
-+ kbdev->pm.backend.mcu_state =
-+ KBASE_MCU_ON_CORE_ATTR_UPDATE_PEND;
-+ break;
-+
-+ case KBASE_MCU_HCTL_MCU_ON_RECHECK:
-+ backend->shaders_desired_mask = kbase_pm_ca_get_core_mask(kbdev);
-+
-+ if (!backend->hwcnt_disabled) {
-+ /* Wait for being disabled */
-+ ;
-+ } else if (!kbase_pm_is_mcu_desired(kbdev)) {
-+ /* Converging to MCU powering down flow */
-+ backend->mcu_state = KBASE_MCU_ON_HWCNT_DISABLE;
-+ } else if (backend->shaders_desired_mask & ~shaders_ready) {
-+ /* set cores ready but not available to
-+ * meet SHADERS_PEND_ON check pass
-+ */
-+ backend->shaders_avail =
-+ (backend->shaders_desired_mask | shaders_ready);
-+
-+ kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER,
-+ backend->shaders_avail & ~shaders_ready,
-+ ACTION_PWRON);
-+ backend->mcu_state =
-+ KBASE_MCU_HCTL_SHADERS_PEND_ON;
-+ } else {
-+ backend->mcu_state =
-+ KBASE_MCU_HCTL_SHADERS_PEND_ON;
-+ }
-+ break;
-+
-+ case KBASE_MCU_ON_CORE_ATTR_UPDATE_PEND:
-+ if (kbase_csf_firmware_core_attr_updated(kbdev)) {
-+ backend->shaders_avail =
-+ backend->shaders_desired_mask;
-+ backend->mcu_state = KBASE_MCU_ON;
-+ }
-+ break;
-+
-+ case KBASE_MCU_ON_HWCNT_DISABLE:
-+ if (kbase_pm_is_mcu_desired(kbdev)) {
-+ backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE;
-+ break;
-+ }
-+
-+ backend->hwcnt_desired = false;
-+ if (!backend->hwcnt_disabled)
-+ kbase_pm_trigger_hwcnt_disable(kbdev);
-+
-+ if (backend->hwcnt_disabled)
-+ backend->mcu_state = KBASE_MCU_ON_HALT;
-+ break;
-+
-+ case KBASE_MCU_ON_HALT:
-+ if (!kbase_pm_is_mcu_desired(kbdev)) {
-+ kbase_csf_firmware_trigger_mcu_halt(kbdev);
-+ backend->mcu_state = KBASE_MCU_ON_PEND_HALT;
-+ } else
-+ backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE;
-+ break;
-+
-+ case KBASE_MCU_ON_PEND_HALT:
-+ if (kbase_csf_firmware_mcu_halted(kbdev)) {
-+ if (kbdev->csf.firmware_hctl_core_pwr)
-+ backend->mcu_state =
-+ KBASE_MCU_HCTL_SHADERS_READY_OFF;
-+ else
-+ backend->mcu_state = KBASE_MCU_POWER_DOWN;
-+ }
-+ break;
-+
-+ case KBASE_MCU_HCTL_SHADERS_READY_OFF:
-+ kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER,
-+ shaders_ready, ACTION_PWROFF);
-+ backend->mcu_state =
-+ KBASE_MCU_HCTL_SHADERS_PEND_OFF;
-+ break;
-+
-+ case KBASE_MCU_HCTL_SHADERS_PEND_OFF:
-+ if (!shaders_trans && !shaders_ready) {
-+ backend->pm_shaders_core_mask = 0;
-+ backend->mcu_state = KBASE_MCU_POWER_DOWN;
-+ }
-+ break;
-+
-+ case KBASE_MCU_POWER_DOWN:
-+ kbase_csf_firmware_disable_mcu(kbdev);
-+ backend->mcu_state = KBASE_MCU_PEND_OFF;
-+ break;
-+
-+ case KBASE_MCU_PEND_OFF:
-+ /* wait synchronously for the MCU to get disabled */
-+ kbase_csf_firmware_disable_mcu_wait(kbdev);
-+ backend->mcu_state = KBASE_MCU_OFF;
-+ break;
-+
-+ case KBASE_MCU_RESET_WAIT:
-+ /* Reset complete */
-+ if (!backend->in_reset)
-+ backend->mcu_state = KBASE_MCU_OFF;
-+ break;
-+
-+ default:
-+ WARN(1, "Invalid state in mcu_state: %d",
-+ backend->mcu_state);
-+ }
-+
-+ if (backend->mcu_state != prev_state)
-+ dev_dbg(kbdev->dev, "MCU state transition: %s to %s\n",
-+ kbase_mcu_state_to_string(prev_state),
-+ kbase_mcu_state_to_string(backend->mcu_state));
-+
-+ } while (backend->mcu_state != prev_state);
-+
-+ return 0;
-+}
-+#endif
-+
- static const char *kbase_l2_core_state_to_string(enum kbase_l2_core_state state)
- {
- const char *const strings[] = {
-@@ -539,8 +855,10 @@ static const char *kbase_l2_core_state_to_string(enum kbase_l2_core_state state)
- static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
- {
- struct kbase_pm_backend_data *backend = &kbdev->pm.backend;
-- u64 l2_present = kbdev->gpu_props.props.raw_props.l2_present;
-+ u64 l2_present = kbdev->gpu_props.curr_config.l2_present;
-+#if !MALI_USE_CSF
- u64 tiler_present = kbdev->gpu_props.props.raw_props.tiler_present;
-+#endif
- enum kbase_l2_core_state prev_state;
-
- lockdep_assert_held(&kbdev->hwaccess_lock);
-@@ -551,35 +869,49 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
- KBASE_PM_CORE_L2);
- u64 l2_ready = kbase_pm_get_ready_cores(kbdev,
- KBASE_PM_CORE_L2);
-+
-+#if !MALI_USE_CSF
- u64 tiler_trans = kbase_pm_get_trans_cores(kbdev,
- KBASE_PM_CORE_TILER);
- u64 tiler_ready = kbase_pm_get_ready_cores(kbdev,
- KBASE_PM_CORE_TILER);
-+#endif
-
- /*
- * kbase_pm_get_ready_cores and kbase_pm_get_trans_cores
- * are vulnerable to corruption if gpu is lost
- */
-- if (kbase_is_gpu_lost(kbdev))
-- return -EIO;
-+ if (kbase_is_gpu_removed(kbdev)
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ || kbase_pm_is_gpu_lost(kbdev)) {
-+#else
-+ ) {
-+#endif
-+ backend->shaders_state =
-+ KBASE_SHADERS_OFF_CORESTACK_OFF;
-+ backend->l2_state = KBASE_L2_OFF;
-+ dev_dbg(kbdev->dev, "GPU lost has occurred - L2 off\n");
-+ break;
-+ }
-
- /* mask off ready from trans in case transitions finished
- * between the register reads
- */
- l2_trans &= ~l2_ready;
-+#if !MALI_USE_CSF
- tiler_trans &= ~tiler_ready;
--
-+#endif
- prev_state = backend->l2_state;
-
- switch (backend->l2_state) {
- case KBASE_L2_OFF:
- if (kbase_pm_is_l2_desired(kbdev)) {
- /*
-- * Set the desired config for L2 before powering
-- * it on
-+ * Set the desired config for L2 before
-+ * powering it on
- */
- kbase_pm_l2_config_override(kbdev);
--
-+#if !MALI_USE_CSF
- /* L2 is required, power on. Powering on the
- * tiler will also power the first L2 cache.
- */
-@@ -593,14 +925,30 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
- kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2,
- l2_present & ~1,
- ACTION_PWRON);
-+#else
-+ /* With CSF firmware, Host driver doesn't need to
-+ * handle power management with both shader and tiler cores.
-+ * The CSF firmware will power up the cores appropriately.
-+ * So only power the l2 cache explicitly.
-+ */
-+ kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2,
-+ l2_present, ACTION_PWRON);
-+#endif
- backend->l2_state = KBASE_L2_PEND_ON;
- }
- break;
-
- case KBASE_L2_PEND_ON:
-+#if !MALI_USE_CSF
- if (!l2_trans && l2_ready == l2_present && !tiler_trans
- && tiler_ready == tiler_present) {
-- KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, tiler_ready);
-+ KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL,
-+ tiler_ready);
-+#else
-+ if (!l2_trans && l2_ready == l2_present) {
-+ KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_L2, NULL,
-+ l2_ready);
-+#endif
- /*
- * Ensure snoops are enabled after L2 is powered
- * up. Note that kbase keeps track of the snoop
-@@ -658,22 +1006,30 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
- break;
-
- case KBASE_L2_ON_HWCNT_ENABLE:
-+#if !MALI_USE_CSF
- backend->hwcnt_desired = true;
- if (backend->hwcnt_disabled) {
- kbase_hwcnt_context_enable(
- kbdev->hwcnt_gpu_ctx);
- backend->hwcnt_disabled = false;
- }
-+#endif
- backend->l2_state = KBASE_L2_ON;
- break;
-
- case KBASE_L2_ON:
- if (!kbase_pm_is_l2_desired(kbdev)) {
-+#if !MALI_USE_CSF
- /* Do not power off L2 until the shaders and
- * core stacks are off.
- */
- if (backend->shaders_state != KBASE_SHADERS_OFF_CORESTACK_OFF)
- break;
-+#else
-+ /* Do not power off L2 until the MCU has been stopped */
-+ if (backend->mcu_state != KBASE_MCU_OFF)
-+ break;
-+#endif
-
- /* We need to make sure hardware counters are
- * disabled before powering down the L2, to
-@@ -690,6 +1046,7 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
- break;
-
- case KBASE_L2_ON_HWCNT_DISABLE:
-+#if !MALI_USE_CSF
- /* If the L2 became desired while we were waiting on the
- * worker to do the actual hwcnt disable (which might
- * happen if some work was submitted immediately after
-@@ -719,6 +1076,7 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
- if (!backend->hwcnt_disabled) {
- kbase_pm_trigger_hwcnt_disable(kbdev);
- }
-+#endif
-
- if (backend->hwcnt_disabled) {
- if (kbdev->pm.backend.gpu_clock_slow_down_wa)
-@@ -769,9 +1127,11 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
- */
- kbase_gpu_start_cache_clean_nolock(
- kbdev);
--
-+#if !MALI_USE_CSF
- KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, 0u);
--
-+#else
-+ KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_L2, NULL, 0u);
-+#endif
- backend->l2_state = KBASE_L2_PEND_OFF;
- break;
-
-@@ -877,6 +1237,7 @@ static void shader_poweroff_timer_queue_cancel(struct kbase_device *kbdev)
- }
- }
-
-+#if !MALI_USE_CSF
- static const char *kbase_shader_core_state_to_string(
- enum kbase_shader_core_state state)
- {
-@@ -898,7 +1259,6 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
- &kbdev->pm.backend.shader_tick_timer;
- enum kbase_shader_core_state prev_state;
- u64 stacks_avail = 0;
-- int err = 0;
-
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
-@@ -924,8 +1284,15 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
- * kbase_pm_get_ready_cores and kbase_pm_get_trans_cores
- * are vulnerable to corruption if gpu is lost
- */
-- if (kbase_is_gpu_lost(kbdev)) {
-- err = -EIO;
-+ if (kbase_is_gpu_removed(kbdev)
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ || kbase_pm_is_gpu_lost(kbdev)) {
-+#else
-+ ) {
-+#endif
-+ backend->shaders_state =
-+ KBASE_SHADERS_OFF_CORESTACK_OFF;
-+ dev_dbg(kbdev->dev, "GPU lost has occurred - shaders off\n");
- break;
- }
-
-@@ -976,6 +1343,12 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
- kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER,
- backend->shaders_avail, ACTION_PWRON);
-
-+ if (backend->pm_current_policy &&
-+ backend->pm_current_policy->handle_event)
-+ backend->pm_current_policy->handle_event(
-+ kbdev,
-+ KBASE_PM_POLICY_EVENT_POWER_ON);
-+
- backend->shaders_state = KBASE_SHADERS_PEND_ON_CORESTACK_ON;
- }
- break;
-@@ -986,8 +1359,18 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
- backend->pm_shaders_core_mask = shaders_ready;
- backend->hwcnt_desired = true;
- if (backend->hwcnt_disabled) {
-+#if MALI_USE_CSF
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev,
-+ &flags);
-+#endif
- kbase_hwcnt_context_enable(
- kbdev->hwcnt_gpu_ctx);
-+#if MALI_USE_CSF
-+ kbase_csf_scheduler_spin_unlock(kbdev,
-+ flags);
-+#endif
- backend->hwcnt_disabled = false;
- }
-
-@@ -1018,6 +1401,12 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
- /* Wait for being disabled */
- ;
- } else if (!backend->shaders_desired) {
-+ if (backend->pm_current_policy &&
-+ backend->pm_current_policy->handle_event)
-+ backend->pm_current_policy->handle_event(
-+ kbdev,
-+ KBASE_PM_POLICY_EVENT_IDLE);
-+
- if (kbdev->pm.backend.protected_transition_override ||
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- kbase_pm_is_suspending(kbdev) ||
-@@ -1078,9 +1467,21 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
- }
-
- if (backend->shaders_desired) {
-+ if (backend->pm_current_policy &&
-+ backend->pm_current_policy->handle_event)
-+ backend->pm_current_policy->handle_event(
-+ kbdev,
-+ KBASE_PM_POLICY_EVENT_TIMER_HIT);
-+
- stt->remaining_ticks = 0;
- backend->shaders_state = KBASE_SHADERS_ON_CORESTACK_ON_RECHECK;
- } else if (stt->remaining_ticks == 0) {
-+ if (backend->pm_current_policy &&
-+ backend->pm_current_policy->handle_event)
-+ backend->pm_current_policy->handle_event(
-+ kbdev,
-+ KBASE_PM_POLICY_EVENT_TIMER_MISS);
-+
- backend->shaders_state = KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON;
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- } else if (kbase_pm_is_suspending(kbdev) ||
-@@ -1167,8 +1568,18 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
- backend->pm_shaders_core_mask = 0;
- backend->hwcnt_desired = true;
- if (backend->hwcnt_disabled) {
-+#if MALI_USE_CSF
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev,
-+ &flags);
-+#endif
- kbase_hwcnt_context_enable(
- kbdev->hwcnt_gpu_ctx);
-+#if MALI_USE_CSF
-+ kbase_csf_scheduler_spin_unlock(kbdev,
-+ flags);
-+#endif
- backend->hwcnt_disabled = false;
- }
- backend->shaders_state = KBASE_SHADERS_OFF_CORESTACK_OFF_TIMER_PEND_OFF;
-@@ -1195,8 +1606,9 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
-
- } while (backend->shaders_state != prev_state);
-
-- return err;
-+ return 0;
- }
-+#endif
-
- static bool kbase_pm_is_in_desired_state_nolock(struct kbase_device *kbdev)
- {
-@@ -1211,12 +1623,21 @@ static bool kbase_pm_is_in_desired_state_nolock(struct kbase_device *kbdev)
- kbdev->pm.backend.l2_state != KBASE_L2_OFF)
- in_desired_state = false;
-
-+#if !MALI_USE_CSF
- if (kbdev->pm.backend.shaders_desired &&
- kbdev->pm.backend.shaders_state != KBASE_SHADERS_ON_CORESTACK_ON)
- in_desired_state = false;
- else if (!kbdev->pm.backend.shaders_desired &&
- kbdev->pm.backend.shaders_state != KBASE_SHADERS_OFF_CORESTACK_OFF)
- in_desired_state = false;
-+#else
-+ if (kbase_pm_is_mcu_desired(kbdev) &&
-+ kbdev->pm.backend.mcu_state != KBASE_MCU_ON)
-+ in_desired_state = false;
-+ else if (!kbase_pm_is_mcu_desired(kbdev) &&
-+ kbdev->pm.backend.mcu_state != KBASE_MCU_OFF)
-+ in_desired_state = false;
-+#endif
-
- return in_desired_state;
- }
-@@ -1280,17 +1701,22 @@ static void kbase_pm_trace_power_state(struct kbase_device *kbdev)
-
- void kbase_pm_update_state(struct kbase_device *kbdev)
- {
-+#if !MALI_USE_CSF
- enum kbase_shader_core_state prev_shaders_state =
- kbdev->pm.backend.shaders_state;
-+#else
-+ enum kbase_mcu_state prev_mcu_state = kbdev->pm.backend.mcu_state;
-+#endif
-
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
-- if (!kbdev->pm.backend.gpu_powered)
-- return; /* Do nothing if the GPU is off */
-+ if (!kbdev->pm.backend.gpu_ready)
-+ return; /* Do nothing if the GPU is not ready */
-
- if (kbase_pm_l2_update_state(kbdev))
- return;
-
-+#if !MALI_USE_CSF
- if (kbase_pm_shaders_update_state(kbdev))
- return;
-
-@@ -1304,9 +1730,20 @@ void kbase_pm_update_state(struct kbase_device *kbdev)
- if (kbase_pm_l2_update_state(kbdev))
- return;
- }
-+#else
-+ if (kbase_pm_mcu_update_state(kbdev))
-+ return;
-+
-+ if (prev_mcu_state != KBASE_MCU_OFF &&
-+ kbdev->pm.backend.mcu_state == KBASE_MCU_OFF) {
-+ if (kbase_pm_l2_update_state(kbdev))
-+ return;
-+ }
-+#endif
-
- if (kbase_pm_is_in_desired_state_nolock(kbdev)) {
-- KBASE_KTRACE_ADD(kbdev, PM_DESIRED_REACHED, NULL, kbdev->pm.backend.shaders_avail);
-+ KBASE_KTRACE_ADD(kbdev, PM_DESIRED_REACHED, NULL,
-+ kbdev->pm.backend.shaders_avail);
-
- kbase_pm_trace_power_state(kbdev);
-
-@@ -1363,7 +1800,8 @@ int kbase_pm_state_machine_init(struct kbase_device *kbdev)
- hrtimer_init(&stt->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- stt->timer.function = shader_tick_timer_callback;
- stt->configured_interval = HR_TIMER_DELAY_NSEC(DEFAULT_PM_GPU_POWEROFF_TICK_NS);
-- stt->configured_ticks = DEFAULT_PM_POWEROFF_TICK_SHADER;
-+ stt->default_ticks = DEFAULT_PM_POWEROFF_TICK_SHADER;
-+ stt->configured_ticks = stt->default_ticks;
-
- return 0;
- }
-@@ -1382,7 +1820,19 @@ void kbase_pm_reset_start_locked(struct kbase_device *kbdev)
-
- backend->in_reset = true;
- backend->l2_state = KBASE_L2_RESET_WAIT;
-+#if !MALI_USE_CSF
- backend->shaders_state = KBASE_SHADERS_RESET_WAIT;
-+#else
-+ /* MCU state machine is exercised only after the initial load/boot
-+ * of the firmware.
-+ */
-+ if (likely(kbdev->csf.firmware_inited)) {
-+ backend->mcu_state = KBASE_MCU_RESET_WAIT;
-+ kbdev->csf.firmware_reload_needed = true;
-+ } else {
-+ WARN_ON(backend->mcu_state != KBASE_MCU_OFF);
-+ }
-+#endif
-
- /* We're in a reset, so hwcnt will have been synchronously disabled by
- * this function's caller as part of the reset process. We therefore
-@@ -1422,15 +1872,28 @@ void kbase_pm_reset_complete(struct kbase_device *kbdev)
-
- /* Timeout for kbase_pm_wait_for_desired_state when wait_event_killable has
- * aborted due to a fatal signal. If the time spent waiting has exceeded this
-- * threshold then there is most likely a hardware issue. */
--#define PM_TIMEOUT (5*HZ) /* 5s */
-+ * threshold then there is most likely a hardware issue.
-+ */
-+#define PM_TIMEOUT_MS (5000) /* 5s */
-
- static void kbase_pm_timed_out(struct kbase_device *kbdev)
- {
-+ unsigned long flags;
-+
- dev_err(kbdev->dev, "Power transition timed out unexpectedly\n");
-+#if !MALI_USE_CSF
-+ CSTD_UNUSED(flags);
- dev_err(kbdev->dev, "Desired state :\n");
- dev_err(kbdev->dev, "\tShader=%016llx\n",
- kbdev->pm.backend.shaders_desired ? kbdev->pm.backend.shaders_avail : 0);
-+#else
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ dev_err(kbdev->dev, "\tMCU desired = %d\n",
-+ kbase_pm_is_mcu_desired(kbdev));
-+ dev_err(kbdev->dev, "\tMCU sw state = %d\n",
-+ kbdev->pm.backend.mcu_state);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+#endif
- dev_err(kbdev->dev, "Current state :\n");
- dev_err(kbdev->dev, "\tShader=%08x%08x\n",
- kbase_reg_read(kbdev,
-@@ -1447,6 +1910,10 @@ static void kbase_pm_timed_out(struct kbase_device *kbdev)
- GPU_CONTROL_REG(L2_READY_HI)),
- kbase_reg_read(kbdev,
- GPU_CONTROL_REG(L2_READY_LO)));
-+#if MALI_USE_CSF
-+ dev_err(kbdev->dev, "\tMCU status = %d\n",
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(MCU_STATUS)));
-+#endif
- dev_err(kbdev->dev, "Cores transitioning :\n");
- dev_err(kbdev->dev, "\tShader=%08x%08x\n",
- kbase_reg_read(kbdev, GPU_CONTROL_REG(
-@@ -1465,49 +1932,87 @@ static void kbase_pm_timed_out(struct kbase_device *kbdev)
- L2_PWRTRANS_LO)));
-
- dev_err(kbdev->dev, "Sending reset to GPU - all running jobs will be lost\n");
-- if (kbase_prepare_to_reset_gpu(kbdev))
-+ if (kbase_prepare_to_reset_gpu(kbdev,
-+ RESET_FLAGS_HWC_UNRECOVERABLE_ERROR))
- kbase_reset_gpu(kbdev);
- }
-
--void kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev)
-+int kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev)
- {
- unsigned long flags;
- unsigned long timeout;
-- int err;
-+ long remaining;
-+ int err = 0;
-
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbase_pm_update_state(kbdev);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
-- timeout = jiffies + PM_TIMEOUT;
-+#if MALI_USE_CSF
-+ timeout = kbase_csf_timeout_in_jiffies(PM_TIMEOUT_MS);
-+#else
-+ timeout = msecs_to_jiffies(PM_TIMEOUT_MS);
-+#endif
-
- /* Wait for cores */
-- err = wait_event_killable(kbdev->pm.backend.gpu_in_desired_state_wait,
-- kbase_pm_is_in_desired_state_with_l2_powered(kbdev));
-+#if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE
-+ remaining = wait_event_killable_timeout(
-+#else
-+ remaining = wait_event_timeout(
-+#endif
-+ kbdev->pm.backend.gpu_in_desired_state_wait,
-+ kbase_pm_is_in_desired_state_with_l2_powered(kbdev), timeout);
-
-- if (err < 0 && time_after(jiffies, timeout))
-+ if (!remaining) {
- kbase_pm_timed_out(kbdev);
-+ err = -ETIMEDOUT;
-+ } else if (remaining < 0) {
-+ dev_info(
-+ kbdev->dev,
-+ "Wait for desired PM state with L2 powered got interrupted");
-+ err = (int)remaining;
-+ }
-+
-+ return err;
- }
-
--void kbase_pm_wait_for_desired_state(struct kbase_device *kbdev)
-+int kbase_pm_wait_for_desired_state(struct kbase_device *kbdev)
- {
- unsigned long flags;
-- unsigned long timeout;
-- int err;
-+ long remaining;
-+#if MALI_USE_CSF
-+ long timeout = kbase_csf_timeout_in_jiffies(PM_TIMEOUT_MS);
-+#else
-+ long timeout = msecs_to_jiffies(PM_TIMEOUT_MS);
-+#endif
-+ int err = 0;
-
- /* Let the state machine latch the most recent desired state. */
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbase_pm_update_state(kbdev);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
-- timeout = jiffies + PM_TIMEOUT;
--
- /* Wait for cores */
-- err = wait_event_killable(kbdev->pm.backend.gpu_in_desired_state_wait,
-- kbase_pm_is_in_desired_state(kbdev));
-+#if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE
-+ remaining = wait_event_killable_timeout(
-+ kbdev->pm.backend.gpu_in_desired_state_wait,
-+ kbase_pm_is_in_desired_state(kbdev), timeout);
-+#else
-+ remaining = wait_event_timeout(
-+ kbdev->pm.backend.gpu_in_desired_state_wait,
-+ kbase_pm_is_in_desired_state(kbdev), timeout);
-+#endif
-
-- if (err < 0 && time_after(jiffies, timeout))
-+ if (!remaining) {
- kbase_pm_timed_out(kbdev);
-+ err = -ETIMEDOUT;
-+ } else if (remaining < 0) {
-+ dev_info(kbdev->dev,
-+ "Wait for desired PM state got interrupted");
-+ err = (int)remaining;
-+ }
-+
-+ return err;
- }
- KBASE_EXPORT_TEST_API(kbase_pm_wait_for_desired_state);
-
-@@ -1515,7 +2020,7 @@ void kbase_pm_enable_interrupts(struct kbase_device *kbdev)
- {
- unsigned long flags;
-
-- KBASE_DEBUG_ASSERT(NULL != kbdev);
-+ KBASE_DEBUG_ASSERT(kbdev != NULL);
- /*
- * Clear all interrupts,
- * and unmask them all.
-@@ -1529,14 +2034,19 @@ void kbase_pm_enable_interrupts(struct kbase_device *kbdev)
- kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK), 0xFFFFFFFF);
-
- kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), 0xFFFFFFFF);
-+#if MALI_USE_CSF
-+ /* Enable only the Page fault bits part */
-+ kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0xFFFF);
-+#else
- kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0xFFFFFFFF);
-+#endif
- }
-
- KBASE_EXPORT_TEST_API(kbase_pm_enable_interrupts);
-
- void kbase_pm_disable_interrupts_nolock(struct kbase_device *kbdev)
- {
-- KBASE_DEBUG_ASSERT(NULL != kbdev);
-+ KBASE_DEBUG_ASSERT(kbdev != NULL);
- /*
- * Mask all interrupts,
- * and clear them all.
-@@ -1563,6 +2073,23 @@ void kbase_pm_disable_interrupts(struct kbase_device *kbdev)
-
- KBASE_EXPORT_TEST_API(kbase_pm_disable_interrupts);
-
-+#if MALI_USE_CSF
-+static void update_user_reg_page_mapping(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->pm.lock);
-+
-+ if (kbdev->csf.mali_file_inode) {
-+ /* This would zap the pte corresponding to the mapping of User
-+ * register page for all the Kbase contexts.
-+ */
-+ unmap_mapping_range(kbdev->csf.mali_file_inode->i_mapping,
-+ BASEP_MEM_CSF_USER_REG_PAGE_HANDLE,
-+ PAGE_SIZE, 1);
-+ }
-+}
-+#endif
-+
-+
- /*
- * pmu layout:
- * 0x0000: PMU TAG (RO) (0xCAFECAFE)
-@@ -1574,10 +2101,20 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume)
- bool reset_required = is_resume;
- unsigned long flags;
-
-- KBASE_DEBUG_ASSERT(NULL != kbdev);
-+ KBASE_DEBUG_ASSERT(kbdev != NULL);
-+#if !MALI_USE_CSF
- lockdep_assert_held(&kbdev->js_data.runpool_mutex);
-+#endif /* !MALI_USE_CSF */
- lockdep_assert_held(&kbdev->pm.lock);
-
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ if (WARN_ON(kbase_pm_is_gpu_lost(kbdev))) {
-+ dev_err(kbdev->dev,
-+ "%s: Cannot power up while GPU lost", __func__);
-+ return;
-+ }
-+#endif
-+
- if (kbdev->pm.backend.gpu_powered) {
- /* Already turned on */
- if (kbdev->poweroff_pending)
-@@ -1602,11 +2139,40 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume)
- kbdev->pm.backend.gpu_powered = true;
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
-+#if MALI_USE_CSF
-+ /* GPU has been turned on, can switch to actual register page */
-+ update_user_reg_page_mapping(kbdev);
-+#endif
-+
- if (reset_required) {
- /* GPU state was lost, reset GPU to ensure it is in a
-- * consistent state */
-+ * consistent state
-+ */
- kbase_pm_init_hw(kbdev, PM_ENABLE_IRQS);
- }
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ else {
-+ if (kbdev->arb.arb_if) {
-+ struct kbase_arbiter_vm_state *arb_vm_state =
-+ kbdev->pm.arb_vm_state;
-+
-+ /* In the case that the GPU has just been granted by
-+ * the Arbiter, a reset will have already been done.
-+ * However, it is still necessary to initialize the GPU.
-+ */
-+ if (arb_vm_state->vm_arb_starting)
-+ kbase_pm_init_hw(kbdev, PM_ENABLE_IRQS |
-+ PM_NO_RESET);
-+ }
-+ }
-+ /*
-+ * This point means that the GPU trasitioned to ON. So there is a chance
-+ * that a repartitioning occurred. In this case the current config
-+ * should be read again.
-+ */
-+ kbase_gpuprops_get_curr_config_props(kbdev,
-+ &kbdev->gpu_props.curr_config);
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
-
- mutex_lock(&kbdev->mmu_hw_mutex);
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-@@ -1628,7 +2194,19 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume)
-
- /* Turn on the L2 caches */
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->pm.backend.gpu_ready = true;
- kbdev->pm.backend.l2_desired = true;
-+#if MALI_USE_CSF
-+ if (reset_required) {
-+ /* GPU reset was done after the power on, so send the post
-+ * reset event instead. This is okay as GPU power off event
-+ * is same as pre GPU reset event.
-+ */
-+ kbase_ipa_control_handle_gpu_reset_post(kbdev);
-+ } else {
-+ kbase_ipa_control_handle_gpu_power_on(kbdev);
-+ }
-+#endif
- kbase_pm_update_state(kbdev);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
- }
-@@ -1639,7 +2217,7 @@ bool kbase_pm_clock_off(struct kbase_device *kbdev)
- {
- unsigned long flags;
-
-- KBASE_DEBUG_ASSERT(NULL != kbdev);
-+ KBASE_DEBUG_ASSERT(kbdev != NULL);
- lockdep_assert_held(&kbdev->pm.lock);
-
- /* ASSERT that the cores should now be unavailable. No lock needed. */
-@@ -1663,16 +2241,38 @@ bool kbase_pm_clock_off(struct kbase_device *kbdev)
-
- if (atomic_read(&kbdev->faults_pending)) {
- /* Page/bus faults are still being processed. The GPU can not
-- * be powered off until they have completed */
-+ * be powered off until they have completed
-+ */
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
- return false;
- }
-
- kbase_pm_cache_snoop_disable(kbdev);
-+#if MALI_USE_CSF
-+ kbase_ipa_control_handle_gpu_power_off(kbdev);
-+#endif
-+
-+ kbdev->pm.backend.gpu_ready = false;
-
- /* The GPU power may be turned off from this point */
- kbdev->pm.backend.gpu_powered = false;
-+
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ if (kbase_pm_is_gpu_lost(kbdev)) {
-+ /* Ensure we unblock any threads that are stuck waiting
-+ * for the GPU
-+ */
-+ kbase_gpu_cache_clean_wait_complete(kbdev);
-+ }
-+#endif
-+
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+#if MALI_USE_CSF
-+ /* GPU is about to be turned off, switch to dummy page */
-+ update_user_reg_page_mapping(kbdev);
-+#endif
-+
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_IDLE_EVENT);
- #endif /* CONFIG_MALI_ARBITER_SUPPORT */
-@@ -1720,19 +2320,23 @@ static enum hrtimer_restart kbasep_reset_timeout(struct hrtimer *timer)
- struct kbasep_reset_timeout_data *rtdata =
- container_of(timer, struct kbasep_reset_timeout_data, timer);
-
-- rtdata->timed_out = 1;
-+ rtdata->timed_out = true;
-
- /* Set the wait queue to wake up kbase_pm_init_hw even though the reset
-- * hasn't completed */
-+ * hasn't completed
-+ */
- kbase_pm_reset_done(rtdata->kbdev);
-
- return HRTIMER_NORESTART;
- }
-
--static int kbase_set_jm_quirks(struct kbase_device *kbdev, const u32 prod_id)
-+static int kbase_set_gpu_quirks(struct kbase_device *kbdev, const u32 prod_id)
- {
-- u32 hw_quirks_jm = kbase_reg_read(kbdev,
-- GPU_CONTROL_REG(JM_CONFIG));
-+#if MALI_USE_CSF
-+ kbdev->hw_quirks_gpu =
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(CSF_CONFIG));
-+#else
-+ u32 hw_quirks_gpu = kbase_reg_read(kbdev, GPU_CONTROL_REG(JM_CONFIG));
-
- if (GPU_ID2_MODEL_MATCH_VALUE(prod_id) == GPU_ID2_PRODUCT_TMIX) {
- /* Only for tMIx */
-@@ -1746,38 +2350,38 @@ static int kbase_set_jm_quirks(struct kbase_device *kbdev, const u32 prod_id)
- */
- if (coherency_features ==
- COHERENCY_FEATURE_BIT(COHERENCY_ACE)) {
-- hw_quirks_jm |= (COHERENCY_ACE_LITE |
-- COHERENCY_ACE) <<
-- JM_FORCE_COHERENCY_FEATURES_SHIFT;
-+ hw_quirks_gpu |= (COHERENCY_ACE_LITE | COHERENCY_ACE)
-+ << JM_FORCE_COHERENCY_FEATURES_SHIFT;
- }
- }
-
-- if (kbase_is_gpu_lost(kbdev))
-+ if (kbase_is_gpu_removed(kbdev))
- return -EIO;
-
-- kbdev->hw_quirks_jm = hw_quirks_jm;
-+ kbdev->hw_quirks_gpu = hw_quirks_gpu;
-
-+#endif /* !MALI_USE_CSF */
- if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_IDVS_GROUP_SIZE)) {
- int default_idvs_group_size = 0xF;
-- u32 tmp;
-+ u32 group_size = 0;
-
-- if (of_property_read_u32(kbdev->dev->of_node,
-- "idvs-group-size", &tmp))
-- tmp = default_idvs_group_size;
-+ if (of_property_read_u32(kbdev->dev->of_node, "idvs-group-size",
-+ &group_size))
-+ group_size = default_idvs_group_size;
-
-- if (tmp > IDVS_GROUP_MAX_SIZE) {
-+ if (group_size > IDVS_GROUP_MAX_SIZE) {
- dev_err(kbdev->dev,
- "idvs-group-size of %d is too large. Maximum value is %d",
-- tmp, IDVS_GROUP_MAX_SIZE);
-- tmp = default_idvs_group_size;
-+ group_size, IDVS_GROUP_MAX_SIZE);
-+ group_size = default_idvs_group_size;
- }
-
-- kbdev->hw_quirks_jm |= tmp << IDVS_GROUP_SIZE_SHIFT;
-+ kbdev->hw_quirks_gpu |= group_size << IDVS_GROUP_SIZE_SHIFT;
- }
-
- #define MANUAL_POWER_CONTROL ((u32)(1 << 8))
- if (corestack_driver_control)
-- kbdev->hw_quirks_jm |= MANUAL_POWER_CONTROL;
-+ kbdev->hw_quirks_gpu |= MANUAL_POWER_CONTROL;
-
- return 0;
- }
-@@ -1787,7 +2391,7 @@ static int kbase_set_sc_quirks(struct kbase_device *kbdev, const u32 prod_id)
- u32 hw_quirks_sc = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(SHADER_CONFIG));
-
-- if (kbase_is_gpu_lost(kbdev))
-+ if (kbase_is_gpu_removed(kbdev))
- return -EIO;
-
- if (prod_id < 0x750 || prod_id == 0x6956) /* T60x, T62x, T72x */
-@@ -1811,7 +2415,7 @@ static int kbase_set_tiler_quirks(struct kbase_device *kbdev)
- u32 hw_quirks_tiler = kbase_reg_read(kbdev,
- GPU_CONTROL_REG(TILER_CONFIG));
-
-- if (kbase_is_gpu_lost(kbdev))
-+ if (kbase_is_gpu_removed(kbdev))
- return -EIO;
-
- /* Set tiler clock gate override if required */
-@@ -1831,18 +2435,17 @@ static int kbase_pm_hw_issues_detect(struct kbase_device *kbdev)
- GPU_ID_VERSION_PRODUCT_ID_SHIFT;
- int error = 0;
-
-- kbdev->hw_quirks_jm = 0;
-+ kbdev->hw_quirks_gpu = 0;
- kbdev->hw_quirks_sc = 0;
- kbdev->hw_quirks_tiler = 0;
- kbdev->hw_quirks_mmu = 0;
-
-- if (!of_property_read_u32(np, "quirks_jm",
-- &kbdev->hw_quirks_jm)) {
-+ if (!of_property_read_u32(np, "quirks_gpu", &kbdev->hw_quirks_gpu)) {
- dev_info(kbdev->dev,
-- "Found quirks_jm = [0x%x] in Devicetree\n",
-- kbdev->hw_quirks_jm);
-+ "Found quirks_gpu = [0x%x] in Devicetree\n",
-+ kbdev->hw_quirks_gpu);
- } else {
-- error = kbase_set_jm_quirks(kbdev, prod_id);
-+ error = kbase_set_gpu_quirks(kbdev, prod_id);
- if (error)
- return error;
- }
-@@ -1891,15 +2494,20 @@ static void kbase_pm_hw_issues_apply(struct kbase_device *kbdev)
-
- kbase_reg_write(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG),
- kbdev->hw_quirks_mmu);
-+#if MALI_USE_CSF
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(CSF_CONFIG),
-+ kbdev->hw_quirks_gpu);
-+#else
- kbase_reg_write(kbdev, GPU_CONTROL_REG(JM_CONFIG),
-- kbdev->hw_quirks_jm);
-+ kbdev->hw_quirks_gpu);
-+#endif
- }
-
- void kbase_pm_cache_snoop_enable(struct kbase_device *kbdev)
- {
- if ((kbdev->current_gpu_coherency_mode == COHERENCY_ACE) &&
- !kbdev->cci_snoop_enabled) {
--#ifdef CONFIG_ARM64
-+#if IS_ENABLED(CONFIG_ARM64)
- if (kbdev->snoop_enable_smc != 0)
- kbase_invoke_smc_fid(kbdev->snoop_enable_smc, 0, 0, 0);
- #endif /* CONFIG_ARM64 */
-@@ -1911,7 +2519,7 @@ void kbase_pm_cache_snoop_enable(struct kbase_device *kbdev)
- void kbase_pm_cache_snoop_disable(struct kbase_device *kbdev)
- {
- if (kbdev->cci_snoop_enabled) {
--#ifdef CONFIG_ARM64
-+#if IS_ENABLED(CONFIG_ARM64)
- if (kbdev->snoop_disable_smc != 0) {
- mali_cci_flush_l2(kbdev);
- kbase_invoke_smc_fid(kbdev->snoop_disable_smc, 0, 0, 0);
-@@ -1922,6 +2530,7 @@ void kbase_pm_cache_snoop_disable(struct kbase_device *kbdev)
- }
- }
-
-+#if !MALI_USE_CSF
- static void reenable_protected_mode_hwcnt(struct kbase_device *kbdev)
- {
- unsigned long irq_flags;
-@@ -1934,6 +2543,7 @@ static void reenable_protected_mode_hwcnt(struct kbase_device *kbdev)
- }
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags);
- }
-+#endif
-
- static int kbase_pm_do_reset(struct kbase_device *kbdev)
- {
-@@ -1960,7 +2570,7 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev)
-
- /* Initialize a structure for tracking the status of the reset */
- rtdata.kbdev = kbdev;
-- rtdata.timed_out = 0;
-+ rtdata.timed_out = false;
-
- /* Create a timer to use as a timeout on the reset */
- hrtimer_init_on_stack(&rtdata.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-@@ -1972,7 +2582,7 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev)
- /* Wait for the RESET_COMPLETED interrupt to be raised */
- kbase_pm_wait_for_reset(kbdev);
-
-- if (rtdata.timed_out == 0) {
-+ if (!rtdata.timed_out) {
- /* GPU has been reset */
- hrtimer_cancel(&rtdata.timer);
- destroy_hrtimer_on_stack(&rtdata.timer);
-@@ -1980,46 +2590,60 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev)
- }
-
- /* No interrupt has been received - check if the RAWSTAT register says
-- * the reset has completed */
-+ * the reset has completed
-+ */
- if ((kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT)) &
-- RESET_COMPLETED)
-- || kbase_is_gpu_lost(kbdev)) {
-+ RESET_COMPLETED)) {
- /* The interrupt is set in the RAWSTAT; this suggests that the
-- * interrupts are not getting to the CPU */
-+ * interrupts are not getting to the CPU
-+ */
- dev_err(kbdev->dev, "Reset interrupt didn't reach CPU. Check interrupt assignments.\n");
- /* If interrupts aren't working we can't continue. */
- destroy_hrtimer_on_stack(&rtdata.timer);
- return -EINVAL;
- }
-
-+ if (kbase_is_gpu_removed(kbdev)) {
-+ dev_dbg(kbdev->dev, "GPU has been removed, reset no longer needed.\n");
-+ destroy_hrtimer_on_stack(&rtdata.timer);
-+ return -EINVAL;
-+ }
-+
- /* The GPU doesn't seem to be responding to the reset so try a hard
-- * reset */
-- dev_err(kbdev->dev, "Failed to soft-reset GPU (timed out after %d ms), now attempting a hard reset\n",
-- RESET_TIMEOUT);
-- KBASE_KTRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, 0);
-- kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-- GPU_COMMAND_HARD_RESET);
-+ * reset, but only when NOT in arbitration mode.
-+ */
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ if (!kbdev->arb.arb_if) {
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
-+ dev_err(kbdev->dev, "Failed to soft-reset GPU (timed out after %d ms), now attempting a hard reset\n",
-+ RESET_TIMEOUT);
-+ KBASE_KTRACE_ADD(kbdev, CORE_GPU_HARD_RESET, NULL, 0);
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-+ GPU_COMMAND_HARD_RESET);
-
-- /* Restart the timer to wait for the hard reset to complete */
-- rtdata.timed_out = 0;
-+ /* Restart the timer to wait for the hard reset to complete */
-+ rtdata.timed_out = false;
-
-- hrtimer_start(&rtdata.timer, HR_TIMER_DELAY_MSEC(RESET_TIMEOUT),
-- HRTIMER_MODE_REL);
-+ hrtimer_start(&rtdata.timer, HR_TIMER_DELAY_MSEC(RESET_TIMEOUT),
-+ HRTIMER_MODE_REL);
-
-- /* Wait for the RESET_COMPLETED interrupt to be raised */
-- kbase_pm_wait_for_reset(kbdev);
-+ /* Wait for the RESET_COMPLETED interrupt to be raised */
-+ kbase_pm_wait_for_reset(kbdev);
-
-- if (rtdata.timed_out == 0) {
-- /* GPU has been reset */
-- hrtimer_cancel(&rtdata.timer);
-- destroy_hrtimer_on_stack(&rtdata.timer);
-- return 0;
-- }
-+ if (!rtdata.timed_out) {
-+ /* GPU has been reset */
-+ hrtimer_cancel(&rtdata.timer);
-+ destroy_hrtimer_on_stack(&rtdata.timer);
-+ return 0;
-+ }
-
-- destroy_hrtimer_on_stack(&rtdata.timer);
-+ destroy_hrtimer_on_stack(&rtdata.timer);
-
-- dev_err(kbdev->dev, "Failed to hard-reset the GPU (timed out after %d ms)\n",
-- RESET_TIMEOUT);
-+ dev_err(kbdev->dev, "Failed to hard-reset the GPU (timed out after %d ms)\n",
-+ RESET_TIMEOUT);
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ }
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
-
- return -EINVAL;
- }
-@@ -2041,9 +2665,9 @@ int kbase_pm_protected_mode_disable(struct kbase_device *const kbdev)
- int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
- {
- unsigned long irq_flags;
-- int err;
-+ int err = 0;
-
-- KBASE_DEBUG_ASSERT(NULL != kbdev);
-+ KBASE_DEBUG_ASSERT(kbdev != NULL);
- lockdep_assert_held(&kbdev->pm.lock);
-
- /* Ensure the clock is on before attempting to access the hardware */
-@@ -2055,7 +2679,8 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
- }
-
- /* Ensure interrupts are off to begin with, this also clears any
-- * outstanding interrupts */
-+ * outstanding interrupts
-+ */
- kbase_pm_disable_interrupts(kbdev);
- /* Ensure cache snoops are disabled before reset. */
- kbase_pm_cache_snoop_disable(kbdev);
-@@ -2069,10 +2694,24 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags);
-
- /* Soft reset the GPU */
-- err = kbdev->protected_ops->protected_mode_disable(
-- kbdev->protected_dev);
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ if (!(flags & PM_NO_RESET))
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
-+ err = kbdev->protected_ops->protected_mode_disable(
-+ kbdev->protected_dev);
-
- spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags);
-+#if MALI_USE_CSF
-+ if (kbdev->protected_mode) {
-+ unsigned long flags;
-+
-+ kbase_ipa_control_protm_exited(kbdev);
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ kbase_hwcnt_backend_csf_protm_exited(&kbdev->hwcnt_gpu_iface);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+ }
-+#endif
- kbdev->protected_mode = false;
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags);
-
-@@ -2093,7 +2732,8 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
- GPU_STATUS_PROTECTED_MODE_ACTIVE);
-
- /* If cycle counter was in use re-enable it, enable_irqs will only be
-- * false when called from kbase_pm_powerup */
-+ * false when called from kbase_pm_powerup
-+ */
- if (kbdev->pm.backend.gpu_cycle_counter_requests &&
- (flags & PM_ENABLE_IRQS)) {
- kbase_pm_enable_interrupts(kbdev);
-@@ -2116,12 +2756,14 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
- kbase_pm_enable_interrupts(kbdev);
-
- exit:
-+#if !MALI_USE_CSF
- if (!kbdev->pm.backend.protected_entry_transition_override) {
- /* Re-enable GPU hardware counters if we're resetting from
- * protected mode.
- */
- reenable_protected_mode_hwcnt(kbdev);
- }
-+#endif
-
- return err;
- }
-@@ -2148,12 +2790,21 @@ kbase_pm_request_gpu_cycle_counter_do_request(struct kbase_device *kbdev)
-
- spin_lock_irqsave(&kbdev->pm.backend.gpu_cycle_counter_requests_lock,
- flags);
--
- ++kbdev->pm.backend.gpu_cycle_counter_requests;
-
-- if (1 == kbdev->pm.backend.gpu_cycle_counter_requests)
-+ if (kbdev->pm.backend.gpu_cycle_counter_requests == 1)
- kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
- GPU_COMMAND_CYCLE_COUNT_START);
-+ else {
-+ /* This might happen after GPU reset.
-+ * Then counter needs to be kicked.
-+ */
-+ if (!(kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS)) &
-+ GPU_STATUS_CYCLE_COUNT_ACTIVE)) {
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-+ GPU_COMMAND_CYCLE_COUNT_START);
-+ }
-+ }
-
- spin_unlock_irqrestore(
- &kbdev->pm.backend.gpu_cycle_counter_requests_lock,
-@@ -2169,6 +2820,8 @@ void kbase_pm_request_gpu_cycle_counter(struct kbase_device *kbdev)
- KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_cycle_counter_requests <
- INT_MAX);
-
-+ kbase_pm_wait_for_l2_powered(kbdev);
-+
- kbase_pm_request_gpu_cycle_counter_do_request(kbdev);
- }
-
-@@ -2203,7 +2856,7 @@ void kbase_pm_release_gpu_cycle_counter_nolock(struct kbase_device *kbdev)
-
- --kbdev->pm.backend.gpu_cycle_counter_requests;
-
-- if (0 == kbdev->pm.backend.gpu_cycle_counter_requests)
-+ if (kbdev->pm.backend.gpu_cycle_counter_requests == 0)
- kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
- GPU_COMMAND_CYCLE_COUNT_STOP);
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_internal.h
-index 95f10e0..70d009e 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_internal.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_internal.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Power management API definitions used internally by GPU backend
- */
-@@ -31,7 +28,7 @@
-
- #include <mali_kbase_hwaccess_pm.h>
-
--#include "mali_kbase_pm_ca.h"
-+#include "backend/gpu/mali_kbase_pm_ca.h"
- #include "mali_kbase_pm_policy.h"
-
-
-@@ -205,6 +202,30 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags);
- */
- void kbase_pm_reset_done(struct kbase_device *kbdev);
-
-+#if MALI_USE_CSF
-+/**
-+ * kbase_pm_wait_for_desired_state - Wait for the desired power state to be
-+ * reached
-+ *
-+ * Wait for the L2 and MCU state machines to reach the states corresponding
-+ * to the values of 'kbase_pm_is_l2_desired' and 'kbase_pm_is_mcu_desired'.
-+ *
-+ * The usual use-case for this is to ensure that all parts of GPU have been
-+ * powered up after performing a GPU Reset.
-+ *
-+ * Unlike kbase_pm_update_state(), the caller must not hold hwaccess_lock,
-+ * because this function will take that lock itself.
-+ *
-+ * NOTE: This may not wait until the correct state is reached if there is a
-+ * power off in progress and kbase_pm_context_active() was called instead of
-+ * kbase_csf_scheduler_pm_active().
-+ *
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Return: 0 on success, error code on error
-+ */
-+int kbase_pm_wait_for_desired_state(struct kbase_device *kbdev);
-+#else
- /**
- * kbase_pm_wait_for_desired_state - Wait for the desired power state to be
- * reached
-@@ -224,15 +245,17 @@ void kbase_pm_reset_done(struct kbase_device *kbdev);
- * kbase_pm_wait_for_poweroff_complete()
- *
- * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Return: 0 on success, error code on error
- */
--void kbase_pm_wait_for_desired_state(struct kbase_device *kbdev);
-+int kbase_pm_wait_for_desired_state(struct kbase_device *kbdev);
-+#endif
-
- /**
- * kbase_pm_wait_for_l2_powered - Wait for the L2 cache to be powered on
- *
-- * Wait for the L2 to be powered on, and for the L2 and shader state machines to
-- * stabilise by reaching the states corresponding to the values of 'l2_desired'
-- * and 'shaders_desired'.
-+ * Wait for the L2 to be powered on, and for the L2 and the state machines of
-+ * its dependent stack components to stabilise.
- *
- * kbdev->pm.active_count must be non-zero when calling this function.
- *
-@@ -240,8 +263,10 @@ void kbase_pm_wait_for_desired_state(struct kbase_device *kbdev);
- * because this function will take that lock itself.
- *
- * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
-+ * Return: 0 on success, error code on error
- */
--void kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev);
-+int kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev);
-
- /**
- * kbase_pm_update_dynamic_cores_onoff - Update the L2 and shader power state
-@@ -467,7 +492,8 @@ void kbase_pm_register_access_enable(struct kbase_device *kbdev);
- void kbase_pm_register_access_disable(struct kbase_device *kbdev);
-
- /* NOTE: kbase_pm_is_suspending is in mali_kbase.h, because it is an inline
-- * function */
-+ * function
-+ */
-
- /**
- * kbase_pm_metrics_is_active - Check if the power management metrics
-@@ -511,8 +537,22 @@ void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev,
-
- #ifdef CONFIG_MALI_MIDGARD_DVFS
-
-+#if MALI_USE_CSF
-+/**
-+ * kbase_platform_dvfs_event - Report utilisation to DVFS code for CSF GPU
-+ *
-+ * Function provided by platform specific code when DVFS is enabled to allow
-+ * the power management metrics system to report utilisation.
-+ *
-+ * @kbdev: The kbase device structure for the device (must be a
-+ * valid pointer)
-+ * @utilisation: The current calculated utilisation by the metrics system.
-+ * Return: Returns 0 on failure and non zero on success.
-+ */
-+int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation);
-+#else
- /**
-- * kbase_platform_dvfs_event - Report utilisation to DVFS code
-+ * kbase_platform_dvfs_event - Report utilisation to DVFS code for JM GPU
- *
- * Function provided by platform specific code when DVFS is enabled to allow
- * the power management metrics system to report utilisation.
-@@ -525,11 +565,12 @@ void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev,
- * group.
- * Return: Returns 0 on failure and non zero on success.
- */
--
- int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation,
-- u32 util_gl_share, u32 util_cl_share[2]);
-+ u32 util_gl_share, u32 util_cl_share[2]);
- #endif
-
-+#endif /* CONFIG_MALI_MIDGARD_DVFS */
-+
- void kbase_pm_power_changed(struct kbase_device *kbdev);
-
- /**
-@@ -683,6 +724,72 @@ extern bool corestack_driver_control;
- */
- bool kbase_pm_is_l2_desired(struct kbase_device *kbdev);
-
-+#if MALI_USE_CSF
-+/**
-+ * kbase_pm_is_mcu_desired - Check whether MCU is desired
-+ *
-+ * @kbdev: Device pointer
-+ *
-+ * This shall be called to check whether MCU needs to be enabled.
-+ *
-+ * Return: true if MCU needs to be enabled.
-+ */
-+bool kbase_pm_is_mcu_desired(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_pm_idle_groups_sched_suspendable - Check whether the scheduler can be
-+ * suspended to low power state when all
-+ * the CSGs are idle
-+ *
-+ * @kbdev: Device pointer
-+ *
-+ * Return: true if allowed to enter the suspended state.
-+ */
-+static inline
-+bool kbase_pm_idle_groups_sched_suspendable(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ return !(kbdev->pm.backend.csf_pm_sched_flags &
-+ CSF_DYNAMIC_PM_SCHED_IGNORE_IDLE);
-+}
-+
-+/**
-+ * kbase_pm_no_runnables_sched_suspendable - Check whether the scheduler can be
-+ * suspended to low power state when
-+ * there are no runnable CSGs.
-+ *
-+ * @kbdev: Device pointer
-+ *
-+ * Return: true if allowed to enter the suspended state.
-+ */
-+static inline
-+bool kbase_pm_no_runnables_sched_suspendable(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ return !(kbdev->pm.backend.csf_pm_sched_flags &
-+ CSF_DYNAMIC_PM_SCHED_NO_SUSPEND);
-+}
-+
-+/**
-+ * kbase_pm_no_mcu_core_pwroff - Check whether the PM is required to keep the
-+ * MCU core powered in accordance to the active
-+ * power management policy
-+ *
-+ * @kbdev: Device pointer
-+ *
-+ * Return: true if the MCU is to retain powered.
-+ */
-+static inline bool kbase_pm_no_mcu_core_pwroff(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ return kbdev->pm.backend.csf_pm_sched_flags &
-+ CSF_DYNAMIC_PM_CORE_KEEP_ON;
-+}
-+#endif
-+
- /**
- * kbase_pm_lock - Lock all necessary mutexes to perform PM actions
- *
-@@ -692,7 +799,9 @@ bool kbase_pm_is_l2_desired(struct kbase_device *kbdev);
- */
- static inline void kbase_pm_lock(struct kbase_device *kbdev)
- {
-+#if !MALI_USE_CSF
- mutex_lock(&kbdev->js_data.runpool_mutex);
-+#endif /* !MALI_USE_CSF */
- mutex_lock(&kbdev->pm.lock);
- }
-
-@@ -704,7 +813,9 @@ static inline void kbase_pm_lock(struct kbase_device *kbdev)
- static inline void kbase_pm_unlock(struct kbase_device *kbdev)
- {
- mutex_unlock(&kbdev->pm.lock);
-+#if !MALI_USE_CSF
- mutex_unlock(&kbdev->js_data.runpool_mutex);
-+#endif /* !MALI_USE_CSF */
- }
-
- #endif /* _KBASE_BACKEND_PM_INTERNAL_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_l2_states.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_l2_states.h
-index 12cb051..ef72f60 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_l2_states.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_l2_states.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -25,6 +24,19 @@
- * The function-like macro KBASEP_L2_STATE() must be defined before including
- * this header file. This header file can be included multiple times in the
- * same compilation unit with different definitions of KBASEP_L2_STATE().
-+ *
-+ * @OFF: The L2 cache and tiler are off
-+ * @PEND_ON: The L2 cache and tiler are powering on
-+ * @RESTORE_CLOCKS: The GPU clock is restored. Conditionally used.
-+ * @ON_HWCNT_ENABLE: The L2 cache and tiler are on, and hwcnt is being enabled
-+ * @ON: The L2 cache and tiler are on, and hwcnt is enabled
-+ * @ON_HWCNT_DISABLE: The L2 cache and tiler are on, and hwcnt is being disabled
-+ * @SLOW_DOWN_CLOCKS: The GPU clock is set to appropriate or lowest clock.
-+ * Conditionally used.
-+ * @POWER_DOWN: The L2 cache and tiler are about to be powered off
-+ * @PEND_OFF: The L2 cache and tiler are powering off
-+ * @RESET_WAIT: The GPU is resetting, L2 cache and tiler power state are
-+ * unknown
- */
- KBASEP_L2_STATE(OFF)
- KBASEP_L2_STATE(PEND_ON)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_mcu_states.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_mcu_states.h
-new file mode 100644
-index 0000000..4e99928
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_mcu_states.h
-@@ -0,0 +1,63 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * Backend-specific Power Manager MCU state definitions.
-+ * The function-like macro KBASEP_MCU_STATE() must be defined before including
-+ * this header file. This header file can be included multiple times in the
-+ * same compilation unit with different definitions of KBASEP_MCU_STATE().
-+ *
-+ * @OFF: The MCU is powered off.
-+ * @PEND_ON_RELOAD: The warm boot of MCU or cold boot of MCU (with
-+ * firmware reloading) is in progress.
-+ * @ON_GLB_REINIT_PEND: The MCU is enabled and Global configuration
-+ * requests have been sent to the firmware.
-+ * @ON_HWCNT_ENABLE: The Global requests have completed and MCU is now
-+ * ready for use and hwcnt is being enabled.
-+ * @ON: The MCU is active and hwcnt has been enabled.
-+ * @ON_CORE_ATTR_UPDATE_PEND: The MCU is active and mask of enabled shader cores
-+ * is being updated.
-+ * @ON_HWCNT_DISABLE: The MCU is on and hwcnt is being disabled.
-+ * @ON_HALT: The MCU is on and hwcnt has been disabled, MCU
-+ * halt would be triggered.
-+ * @ON_PEND_HALT: MCU halt in progress, confirmation pending.
-+ * @POWER_DOWN: MCU halted operations, pending being disabled.
-+ * @PEND_OFF: MCU is being disabled, pending on powering off.
-+ * @RESET_WAIT: The GPU is resetting, MCU state is unknown.
-+ */
-+KBASEP_MCU_STATE(OFF)
-+KBASEP_MCU_STATE(PEND_ON_RELOAD)
-+KBASEP_MCU_STATE(ON_GLB_REINIT_PEND)
-+KBASEP_MCU_STATE(ON_HWCNT_ENABLE)
-+KBASEP_MCU_STATE(ON)
-+KBASEP_MCU_STATE(ON_CORE_ATTR_UPDATE_PEND)
-+KBASEP_MCU_STATE(ON_HWCNT_DISABLE)
-+KBASEP_MCU_STATE(ON_HALT)
-+KBASEP_MCU_STATE(ON_PEND_HALT)
-+KBASEP_MCU_STATE(POWER_DOWN)
-+KBASEP_MCU_STATE(PEND_OFF)
-+KBASEP_MCU_STATE(RESET_WAIT)
-+/* Additional MCU states with HOST_CONTROL_SHADERS */
-+KBASEP_MCU_STATE(HCTL_SHADERS_PEND_ON)
-+KBASEP_MCU_STATE(HCTL_CORES_NOTIFY_PEND)
-+KBASEP_MCU_STATE(HCTL_MCU_ON_RECHECK)
-+KBASEP_MCU_STATE(HCTL_SHADERS_READY_OFF)
-+KBASEP_MCU_STATE(HCTL_SHADERS_PEND_OFF)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_metrics.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_metrics.c
-index de3babe..69e8dd3 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_metrics.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_metrics.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Metrics for power management
- */
-@@ -29,22 +26,28 @@
- #include <mali_kbase.h>
- #include <mali_kbase_pm.h>
- #include <backend/gpu/mali_kbase_pm_internal.h>
-+
-+#if MALI_USE_CSF
-+#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
-+#include <csf/ipa_control/mali_kbase_csf_ipa_control.h>
-+#else
- #include <backend/gpu/mali_kbase_jm_rb.h>
-+#endif /* !MALI_USE_CSF */
-+
- #include <backend/gpu/mali_kbase_pm_defs.h>
- #include <mali_linux_trace.h>
-
--/* When VSync is being hit aim for utilisation between 70-90% */
--#define KBASE_PM_VSYNC_MIN_UTILISATION 70
--#define KBASE_PM_VSYNC_MAX_UTILISATION 90
--/* Otherwise aim for 10-40% */
--#define KBASE_PM_NO_VSYNC_MIN_UTILISATION 10
--#define KBASE_PM_NO_VSYNC_MAX_UTILISATION 40
--
- /* Shift used for kbasep_pm_metrics_data.time_busy/idle - units of (1 << 8) ns
- * This gives a maximum period between samples of 2^(32+8)/100 ns = slightly
-- * under 11s. Exceeding this will cause overflow */
-+ * under 11s. Exceeding this will cause overflow
-+ */
- #define KBASE_PM_TIME_SHIFT 8
-
-+#if MALI_USE_CSF
-+/* To get the GPU_ACTIVE value in nano seconds unit */
-+#define GPU_ACTIVE_SCALING_FACTOR ((u64)1E9)
-+#endif
-+
- #ifdef CONFIG_MALI_MIDGARD_DVFS
- static enum hrtimer_restart dvfs_callback(struct hrtimer *timer)
- {
-@@ -71,11 +74,45 @@ static enum hrtimer_restart dvfs_callback(struct hrtimer *timer)
-
- int kbasep_pm_metrics_init(struct kbase_device *kbdev)
- {
-- KBASE_DEBUG_ASSERT(kbdev != NULL);
-+#if MALI_USE_CSF
-+ struct kbase_ipa_control_perf_counter perf_counter;
-+ int err;
-
-+ /* One counter group */
-+ const size_t NUM_PERF_COUNTERS = 1;
-+
-+ KBASE_DEBUG_ASSERT(kbdev != NULL);
- kbdev->pm.backend.metrics.kbdev = kbdev;
-+ kbdev->pm.backend.metrics.time_period_start = ktime_get();
-+ kbdev->pm.backend.metrics.values.time_busy = 0;
-+ kbdev->pm.backend.metrics.values.time_idle = 0;
-+ kbdev->pm.backend.metrics.values.time_in_protm = 0;
-+
-+ perf_counter.scaling_factor = GPU_ACTIVE_SCALING_FACTOR;
-
-+ /* Normalize values by GPU frequency */
-+ perf_counter.gpu_norm = true;
-+
-+ /* We need the GPU_ACTIVE counter, which is in the CSHW group */
-+ perf_counter.type = KBASE_IPA_CORE_TYPE_CSHW;
-+
-+ /* We need the GPU_ACTIVE counter */
-+ perf_counter.idx = GPU_ACTIVE_CNT_IDX;
-+
-+ err = kbase_ipa_control_register(
-+ kbdev, &perf_counter, NUM_PERF_COUNTERS,
-+ &kbdev->pm.backend.metrics.ipa_control_client);
-+ if (err) {
-+ dev_err(kbdev->dev,
-+ "Failed to register IPA with kbase_ipa_control: err=%d",
-+ err);
-+ return -1;
-+ }
-+#else
-+ KBASE_DEBUG_ASSERT(kbdev != NULL);
-+ kbdev->pm.backend.metrics.kbdev = kbdev;
- kbdev->pm.backend.metrics.time_period_start = ktime_get();
-+
- kbdev->pm.backend.metrics.gpu_active = false;
- kbdev->pm.backend.metrics.active_cl_ctx[0] = 0;
- kbdev->pm.backend.metrics.active_cl_ctx[1] = 0;
-@@ -89,16 +126,25 @@ int kbasep_pm_metrics_init(struct kbase_device *kbdev)
- kbdev->pm.backend.metrics.values.busy_cl[1] = 0;
- kbdev->pm.backend.metrics.values.busy_gl = 0;
-
-+#endif
- spin_lock_init(&kbdev->pm.backend.metrics.lock);
-
- #ifdef CONFIG_MALI_MIDGARD_DVFS
- hrtimer_init(&kbdev->pm.backend.metrics.timer, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL);
- kbdev->pm.backend.metrics.timer.function = dvfs_callback;
--
-+ kbdev->pm.backend.metrics.initialized = true;
- kbase_pm_metrics_start(kbdev);
- #endif /* CONFIG_MALI_MIDGARD_DVFS */
-
-+#if MALI_USE_CSF
-+ /* The sanity check on the GPU_ACTIVE performance counter
-+ * is skipped for Juno platforms that have timing problems.
-+ */
-+ kbdev->pm.backend.metrics.skip_gpu_active_sanity_check =
-+ of_machine_is_compatible("arm,juno");
-+#endif
-+
- return 0;
- }
- KBASE_EXPORT_TEST_API(kbasep_pm_metrics_init);
-@@ -115,7 +161,13 @@ void kbasep_pm_metrics_term(struct kbase_device *kbdev)
- spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags);
-
- hrtimer_cancel(&kbdev->pm.backend.metrics.timer);
-+ kbdev->pm.backend.metrics.initialized = false;
- #endif /* CONFIG_MALI_MIDGARD_DVFS */
-+
-+#if MALI_USE_CSF
-+ kbase_ipa_control_unregister(
-+ kbdev, kbdev->pm.backend.metrics.ipa_control_client);
-+#endif
- }
-
- KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term);
-@@ -123,8 +175,117 @@ KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term);
- /* caller needs to hold kbdev->pm.backend.metrics.lock before calling this
- * function
- */
-+#if MALI_USE_CSF
-+#if defined(CONFIG_MALI_DEVFREQ) || defined(CONFIG_MALI_MIDGARD_DVFS)
-+static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev)
-+{
-+ int err;
-+ u64 gpu_active_counter;
-+ u64 protected_time;
-+ ktime_t now;
-+
-+ lockdep_assert_held(&kbdev->pm.backend.metrics.lock);
-+
-+ /* Query IPA_CONTROL for the latest GPU-active and protected-time
-+ * info.
-+ */
-+ err = kbase_ipa_control_query(
-+ kbdev, kbdev->pm.backend.metrics.ipa_control_client,
-+ &gpu_active_counter, 1, &protected_time);
-+
-+ /* Read the timestamp after reading the GPU_ACTIVE counter value.
-+ * This ensures the time gap between the 2 reads is consistent for
-+ * a meaningful comparison between the increment of GPU_ACTIVE and
-+ * elapsed time. The lock taken inside kbase_ipa_control_query()
-+ * function can cause lot of variation.
-+ */
-+ now = ktime_get();
-+
-+ if (err) {
-+ dev_err(kbdev->dev,
-+ "Failed to query the increment of GPU_ACTIVE counter: err=%d",
-+ err);
-+ } else {
-+ u64 diff_ns;
-+ s64 diff_ns_signed;
-+ u32 ns_time;
-+ ktime_t diff = ktime_sub(
-+ now, kbdev->pm.backend.metrics.time_period_start);
-+
-+ diff_ns_signed = ktime_to_ns(diff);
-+
-+ if (diff_ns_signed < 0)
-+ return;
-+
-+ diff_ns = (u64)diff_ns_signed;
-+
-+#if !IS_ENABLED(CONFIG_MALI_NO_MALI)
-+ /* The GPU_ACTIVE counter shouldn't clock-up more time than has
-+ * actually elapsed - but still some margin needs to be given
-+ * when doing the comparison. There could be some drift between
-+ * the CPU and GPU clock.
-+ *
-+ * Can do the check only in a real driver build, as an arbitrary
-+ * value for GPU_ACTIVE can be fed into dummy model in no_mali
-+ * configuration which may not correspond to the real elapsed
-+ * time.
-+ */
-+ if (!kbdev->pm.backend.metrics.skip_gpu_active_sanity_check) {
-+ /* Use a margin value that is approximately 1% of the time
-+ * difference.
-+ */
-+ u64 margin_ns = diff_ns >> 6;
-+ if (gpu_active_counter > (diff_ns + margin_ns)) {
-+ dev_info(
-+ kbdev->dev,
-+ "GPU activity takes longer than time interval: %llu ns > %llu ns",
-+ (unsigned long long)gpu_active_counter,
-+ (unsigned long long)diff_ns);
-+ }
-+ }
-+#endif
-+ /* Calculate time difference in units of 256ns */
-+ ns_time = (u32)(diff_ns >> KBASE_PM_TIME_SHIFT);
-+
-+ /* Add protected_time to gpu_active_counter so that time in
-+ * protected mode is included in the apparent GPU active time,
-+ * then convert it from units of 1ns to units of 256ns, to
-+ * match what JM GPUs use. The assumption is made here that the
-+ * GPU is 100% busy while in protected mode, so we should add
-+ * this since the GPU can't (and thus won't) update these
-+ * counters while it's actually in protected mode.
-+ *
-+ * Perform the add after dividing each value down, to reduce
-+ * the chances of overflows.
-+ */
-+ protected_time >>= KBASE_PM_TIME_SHIFT;
-+ gpu_active_counter >>= KBASE_PM_TIME_SHIFT;
-+ gpu_active_counter += protected_time;
-+
-+ /* Ensure the following equations don't go wrong if ns_time is
-+ * slightly larger than gpu_active_counter somehow
-+ */
-+ gpu_active_counter = MIN(gpu_active_counter, ns_time);
-+
-+ kbdev->pm.backend.metrics.values.time_busy +=
-+ gpu_active_counter;
-+
-+ kbdev->pm.backend.metrics.values.time_idle +=
-+ ns_time - gpu_active_counter;
-+
-+ /* Also make time in protected mode available explicitly,
-+ * so users of this data have this info, too.
-+ */
-+ kbdev->pm.backend.metrics.values.time_in_protm +=
-+ protected_time;
-+ }
-+
-+ kbdev->pm.backend.metrics.time_period_start = now;
-+}
-+#endif /* defined(CONFIG_MALI_DEVFREQ) || defined(CONFIG_MALI_MIDGARD_DVFS) */
-+#else
- static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev,
-- ktime_t now)
-+ ktime_t now)
- {
- ktime_t diff;
-
-@@ -149,12 +310,13 @@ static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev,
- if (kbdev->pm.backend.metrics.active_gl_ctx[2])
- kbdev->pm.backend.metrics.values.busy_gl += ns_time;
- } else {
-- kbdev->pm.backend.metrics.values.time_idle += (u32) (ktime_to_ns(diff)
-- >> KBASE_PM_TIME_SHIFT);
-+ kbdev->pm.backend.metrics.values.time_idle +=
-+ (u32)(ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT);
- }
-
- kbdev->pm.backend.metrics.time_period_start = now;
- }
-+#endif /* MALI_USE_CSF */
-
- #if defined(CONFIG_MALI_DEVFREQ) || defined(CONFIG_MALI_MIDGARD_DVFS)
- void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev,
-@@ -165,14 +327,23 @@ void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev,
- unsigned long flags;
-
- spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags);
-+#if MALI_USE_CSF
-+ kbase_pm_get_dvfs_utilisation_calc(kbdev);
-+#else
- kbase_pm_get_dvfs_utilisation_calc(kbdev, ktime_get());
-+#endif
-
- memset(diff, 0, sizeof(*diff));
- diff->time_busy = cur->time_busy - last->time_busy;
- diff->time_idle = cur->time_idle - last->time_idle;
-+
-+#if MALI_USE_CSF
-+ diff->time_in_protm = cur->time_in_protm - last->time_in_protm;
-+#else
- diff->busy_cl[0] = cur->busy_cl[0] - last->busy_cl[0];
- diff->busy_cl[1] = cur->busy_cl[1] - last->busy_cl[1];
- diff->busy_gl = cur->busy_gl - last->busy_gl;
-+#endif
-
- *last = *cur;
-
-@@ -184,26 +355,42 @@ KBASE_EXPORT_TEST_API(kbase_pm_get_dvfs_metrics);
- #ifdef CONFIG_MALI_MIDGARD_DVFS
- void kbase_pm_get_dvfs_action(struct kbase_device *kbdev)
- {
-- int utilisation, util_gl_share;
-- int util_cl_share[2];
-- int busy;
-+ int utilisation;
- struct kbasep_pm_metrics *diff;
-+#if !MALI_USE_CSF
-+ int busy;
-+ int util_gl_share;
-+ int util_cl_share[2];
-+#endif
-
- KBASE_DEBUG_ASSERT(kbdev != NULL);
-
- diff = &kbdev->pm.backend.metrics.dvfs_diff;
-
-- kbase_pm_get_dvfs_metrics(kbdev, &kbdev->pm.backend.metrics.dvfs_last, diff);
-+ kbase_pm_get_dvfs_metrics(kbdev, &kbdev->pm.backend.metrics.dvfs_last,
-+ diff);
-
- utilisation = (100 * diff->time_busy) /
- max(diff->time_busy + diff->time_idle, 1u);
-
-+#if !MALI_USE_CSF
- busy = max(diff->busy_gl + diff->busy_cl[0] + diff->busy_cl[1], 1u);
-+
- util_gl_share = (100 * diff->busy_gl) / busy;
- util_cl_share[0] = (100 * diff->busy_cl[0]) / busy;
- util_cl_share[1] = (100 * diff->busy_cl[1]) / busy;
-
-- kbase_platform_dvfs_event(kbdev, utilisation, util_gl_share, util_cl_share);
-+ kbase_platform_dvfs_event(kbdev, utilisation, util_gl_share,
-+ util_cl_share);
-+#else
-+ /* Note that, at present, we don't pass protected-mode time to the
-+ * platform here. It's unlikely to be useful, however, as the platform
-+ * probably just cares whether the GPU is busy or not; time in
-+ * protected mode is already added to busy-time at this point, though,
-+ * so we should be good.
-+ */
-+ kbase_platform_dvfs_event(kbdev, utilisation);
-+#endif
- }
-
- bool kbase_pm_metrics_is_active(struct kbase_device *kbdev)
-@@ -224,11 +411,20 @@ KBASE_EXPORT_TEST_API(kbase_pm_metrics_is_active);
- void kbase_pm_metrics_start(struct kbase_device *kbdev)
- {
- unsigned long flags;
-+ bool update = true;
-+
-+ if (unlikely(!kbdev->pm.backend.metrics.initialized))
-+ return;
-
- spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags);
-- kbdev->pm.backend.metrics.timer_active = true;
-+ if (!kbdev->pm.backend.metrics.timer_active)
-+ kbdev->pm.backend.metrics.timer_active = true;
-+ else
-+ update = false;
- spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags);
-- hrtimer_start(&kbdev->pm.backend.metrics.timer,
-+
-+ if (update)
-+ hrtimer_start(&kbdev->pm.backend.metrics.timer,
- HR_TIMER_DELAY_MSEC(kbdev->pm.dvfs_period),
- HRTIMER_MODE_REL);
- }
-@@ -236,16 +432,26 @@ void kbase_pm_metrics_start(struct kbase_device *kbdev)
- void kbase_pm_metrics_stop(struct kbase_device *kbdev)
- {
- unsigned long flags;
-+ bool update = true;
-+
-+ if (unlikely(!kbdev->pm.backend.metrics.initialized))
-+ return;
-
- spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags);
-- kbdev->pm.backend.metrics.timer_active = false;
-+ if (kbdev->pm.backend.metrics.timer_active)
-+ kbdev->pm.backend.metrics.timer_active = false;
-+ else
-+ update = false;
- spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags);
-- hrtimer_cancel(&kbdev->pm.backend.metrics.timer);
-+
-+ if (update)
-+ hrtimer_cancel(&kbdev->pm.backend.metrics.timer);
- }
-
-
- #endif /* CONFIG_MALI_MIDGARD_DVFS */
-
-+#if !MALI_USE_CSF
- /**
- * kbase_pm_metrics_active_calc - Update PM active counts based on currently
- * running atoms
-@@ -270,7 +476,8 @@ static void kbase_pm_metrics_active_calc(struct kbase_device *kbdev)
- struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, 0);
-
- /* Head atom may have just completed, so if it isn't running
-- * then try the next atom */
-+ * then try the next atom
-+ */
- if (katom && katom->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED)
- katom = kbase_gpu_inspect(kbdev, js, 1);
-
-@@ -309,10 +516,12 @@ void kbase_pm_metrics_update(struct kbase_device *kbdev, ktime_t *timestamp)
- timestamp = &now;
- }
-
-- /* Track how long CL and/or GL jobs have been busy for */
-+ /* Track how much of time has been spent busy or idle. For JM GPUs,
-+ * this also evaluates how long CL and/or GL jobs have been busy for.
-+ */
- kbase_pm_get_dvfs_utilisation_calc(kbdev, *timestamp);
-
- kbase_pm_metrics_active_calc(kbdev);
--
- spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags);
- }
-+#endif /* !MALI_USE_CSF */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_policy.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_policy.c
-index 17ed21e..cf61ef8 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_policy.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_policy.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -28,27 +27,54 @@
- #include <gpu/mali_kbase_gpu_regmap.h>
- #include <mali_kbase_pm.h>
- #include <backend/gpu/mali_kbase_pm_internal.h>
-+#include <mali_kbase_reset_gpu.h>
-
--static const struct kbase_pm_policy *const all_policy_list[] = {
--#ifdef CONFIG_MALI_NO_MALI
-- &kbase_pm_always_on_policy_ops,
-- &kbase_pm_coarse_demand_policy_ops,
--#if !MALI_CUSTOMER_RELEASE
-- &kbase_pm_always_on_demand_policy_ops,
-+#if MALI_USE_CSF && defined CONFIG_MALI_DEBUG
-+#include <csf/mali_kbase_csf_firmware.h>
- #endif
--#else /* CONFIG_MALI_NO_MALI */
-+
-+#include <linux/of.h>
-+
-+static const struct kbase_pm_policy *const all_policy_list[] = {
- &kbase_pm_coarse_demand_policy_ops,
--#if !MALI_CUSTOMER_RELEASE
-- &kbase_pm_always_on_demand_policy_ops,
--#endif
- &kbase_pm_always_on_policy_ops
--#endif /* CONFIG_MALI_NO_MALI */
- };
-
- void kbase_pm_policy_init(struct kbase_device *kbdev)
- {
-- kbdev->pm.backend.pm_current_policy = all_policy_list[0];
-- kbdev->pm.backend.pm_current_policy->init(kbdev);
-+ const struct kbase_pm_policy *default_policy = all_policy_list[0];
-+ struct device_node *np = kbdev->dev->of_node;
-+ const char *power_policy_name;
-+ unsigned long flags;
-+ int i;
-+
-+ if (of_property_read_string(np, "power_policy", &power_policy_name) == 0) {
-+ for (i = 0; i < ARRAY_SIZE(all_policy_list); i++)
-+ if (sysfs_streq(all_policy_list[i]->name, power_policy_name)) {
-+ default_policy = all_policy_list[i];
-+ break;
-+ }
-+ }
-+
-+#if MALI_USE_CSF && defined(CONFIG_MALI_DEBUG)
-+ /* Use always_on policy if module param fw_debug=1 is
-+ * passed, to aid firmware debugging.
-+ */
-+ if (fw_debug)
-+ default_policy = &kbase_pm_always_on_policy_ops;
-+#endif
-+
-+ default_policy->init(kbdev);
-+
-+#if MALI_USE_CSF
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->pm.backend.pm_current_policy = default_policy;
-+ kbdev->pm.backend.csf_pm_sched_flags = default_policy->pm_sched_flags;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+#else
-+ CSTD_UNUSED(flags);
-+ kbdev->pm.backend.pm_current_policy = default_policy;
-+#endif
- }
-
- void kbase_pm_policy_term(struct kbase_device *kbdev)
-@@ -93,13 +119,17 @@ void kbase_pm_update_active(struct kbase_device *kbdev)
- pm->backend.invoke_poweroff_wait_wq_when_l2_off = false;
- pm->backend.poweroff_wait_in_progress = false;
- pm->backend.l2_desired = true;
-+#if MALI_USE_CSF
-+ pm->backend.mcu_desired = true;
-+#endif
-
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
- kbase_pm_do_poweron(kbdev, false);
- }
- } else {
- /* It is an error for the power policy to power off the GPU
-- * when there are contexts active */
-+ * when there are contexts active
-+ */
- KBASE_DEBUG_ASSERT(pm->active_count == 0);
-
- pm->backend.poweron_required = false;
-@@ -127,6 +157,16 @@ void kbase_pm_update_dynamic_cores_onoff(struct kbase_device *kbdev)
- return;
- if (kbdev->pm.backend.poweroff_wait_in_progress)
- return;
-+
-+#if MALI_USE_CSF
-+ CSTD_UNUSED(shaders_desired);
-+ /* Invoke the MCU state machine to send a request to FW for updating
-+ * the mask of shader cores that can be used for allocation of
-+ * endpoints requested by CSGs.
-+ */
-+ if (kbase_pm_is_mcu_desired(kbdev))
-+ kbase_pm_update_state(kbdev);
-+#else
- /* In protected transition, don't allow outside shader core request
- * affect transition, return directly
- */
-@@ -138,6 +178,7 @@ void kbase_pm_update_dynamic_cores_onoff(struct kbase_device *kbdev)
- if (shaders_desired && kbase_pm_is_l2_desired(kbdev)) {
- kbase_pm_update_state(kbdev);
- }
-+#endif
- }
-
- void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev)
-@@ -153,11 +194,20 @@ void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev)
-
- if (kbdev->pm.backend.protected_transition_override)
- /* We are trying to change in/out of protected mode - force all
-- * cores off so that the L2 powers down */
-+ * cores off so that the L2 powers down
-+ */
- shaders_desired = false;
- else
- shaders_desired = kbdev->pm.backend.pm_current_policy->shaders_needed(kbdev);
-
-+#if MALI_USE_CSF
-+ /* On CSF GPUs, Host driver isn't supposed to do the power management
-+ * for shader cores. CSF firmware will power up the cores appropriately
-+ * and so from Driver's standpoint 'shaders_desired' flag shall always
-+ * remain 0.
-+ */
-+ shaders_desired = false;
-+#endif
- if (kbdev->pm.backend.shaders_desired != shaders_desired) {
- KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_DESIRED, NULL, kbdev->pm.backend.shaders_desired);
-
-@@ -197,20 +247,106 @@ const struct kbase_pm_policy *kbase_pm_get_policy(struct kbase_device *kbdev)
-
- KBASE_EXPORT_TEST_API(kbase_pm_get_policy);
-
-+#if MALI_USE_CSF
-+static int policy_change_wait_for_L2_off(struct kbase_device *kbdev)
-+{
-+#define WAIT_DURATION_MS (3000)
-+ long remaining;
-+ long timeout = kbase_csf_timeout_in_jiffies(WAIT_DURATION_MS);
-+ int err = 0;
-+
-+ /* Wait for L2 becoming off, by which the MCU is also implicitly off
-+ * since the L2 state machine would only start its power-down
-+ * sequence when the MCU is in off state. The L2 off is required
-+ * as the tiler may need to be power cycled for MCU reconfiguration
-+ * for host control of shader cores.
-+ */
-+#if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE
-+ remaining = wait_event_killable_timeout(
-+ kbdev->pm.backend.gpu_in_desired_state_wait,
-+ kbdev->pm.backend.l2_state == KBASE_L2_OFF, timeout);
-+#else
-+ remaining = wait_event_timeout(
-+ kbdev->pm.backend.gpu_in_desired_state_wait,
-+ kbdev->pm.backend.l2_state == KBASE_L2_OFF, timeout);
-+#endif
-+
-+ if (!remaining) {
-+ err = -ETIMEDOUT;
-+ } else if (remaining < 0) {
-+ dev_info(kbdev->dev,
-+ "Wait for L2_off got interrupted");
-+ err = (int)remaining;
-+ }
-+
-+ dev_dbg(kbdev->dev, "%s: err=%d mcu_state=%d, L2_state=%d\n", __func__,
-+ err, kbdev->pm.backend.mcu_state, kbdev->pm.backend.l2_state);
-+
-+ return err;
-+}
-+#endif
-+
- void kbase_pm_set_policy(struct kbase_device *kbdev,
- const struct kbase_pm_policy *new_policy)
- {
- const struct kbase_pm_policy *old_policy;
- unsigned long flags;
-+#if MALI_USE_CSF
-+ unsigned int new_policy_csf_pm_sched_flags;
-+ bool sched_suspend;
-+ bool reset_gpu = false;
-+#endif
-
- KBASE_DEBUG_ASSERT(kbdev != NULL);
- KBASE_DEBUG_ASSERT(new_policy != NULL);
-
- KBASE_KTRACE_ADD(kbdev, PM_SET_POLICY, NULL, new_policy->id);
-
-+#if MALI_USE_CSF
-+ /* Serialize calls on kbase_pm_set_policy() */
-+ mutex_lock(&kbdev->pm.backend.policy_change_lock);
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ /* policy_change_clamp_state_to_off, when needed, is set/cleared in
-+ * this function, a very limited temporal scope for covering the
-+ * change transition.
-+ */
-+ WARN_ON(kbdev->pm.backend.policy_change_clamp_state_to_off);
-+ new_policy_csf_pm_sched_flags = new_policy->pm_sched_flags;
-+
-+ /* Requiring the scheduler PM suspend operation when changes involving
-+ * the always_on policy, reflected by the CSF_DYNAMIC_PM_CORE_KEEP_ON
-+ * flag bit.
-+ */
-+ sched_suspend = kbdev->csf.firmware_inited &&
-+ (CSF_DYNAMIC_PM_CORE_KEEP_ON &
-+ (new_policy_csf_pm_sched_flags |
-+ kbdev->pm.backend.csf_pm_sched_flags));
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ if (sched_suspend)
-+ kbase_csf_scheduler_pm_suspend(kbdev);
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ /* If the current active policy is always_on, one needs to clamp the
-+ * MCU/L2 for reaching off-state
-+ */
-+ if (sched_suspend)
-+ kbdev->pm.backend.policy_change_clamp_state_to_off =
-+ CSF_DYNAMIC_PM_CORE_KEEP_ON & kbdev->pm.backend.csf_pm_sched_flags;
-+
-+ kbase_pm_update_state(kbdev);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ if (sched_suspend)
-+ reset_gpu = policy_change_wait_for_L2_off(kbdev);
-+#endif
-+
- /* During a policy change we pretend the GPU is active */
- /* A suspend won't happen here, because we're in a syscall from a
-- * userspace thread */
-+ * userspace thread
-+ */
- kbase_pm_context_active(kbdev);
-
- kbase_pm_lock(kbdev);
-@@ -225,25 +361,49 @@ void kbase_pm_set_policy(struct kbase_device *kbdev,
- if (old_policy->term)
- old_policy->term(kbdev);
-
-+ memset(&kbdev->pm.backend.pm_policy_data, 0,
-+ sizeof(union kbase_pm_policy_data));
-+
- KBASE_KTRACE_ADD(kbdev, PM_CURRENT_POLICY_INIT, NULL, new_policy->id);
- if (new_policy->init)
- new_policy->init(kbdev);
-
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbdev->pm.backend.pm_current_policy = new_policy;
-+#if MALI_USE_CSF
-+ kbdev->pm.backend.csf_pm_sched_flags = new_policy_csf_pm_sched_flags;
-+ /* New policy in place, release the clamping on mcu/L2 off state */
-+ kbdev->pm.backend.policy_change_clamp_state_to_off = false;
-+ kbase_pm_update_state(kbdev);
-+#endif
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
- /* If any core power state changes were previously attempted, but
- * couldn't be made because the policy was changing (current_policy was
-- * NULL), then re-try them here. */
-+ * NULL), then re-try them here.
-+ */
- kbase_pm_update_active(kbdev);
- kbase_pm_update_cores_state(kbdev);
-
- kbase_pm_unlock(kbdev);
-
- /* Now the policy change is finished, we release our fake context active
-- * reference */
-+ * reference
-+ */
- kbase_pm_context_idle(kbdev);
-+
-+#if MALI_USE_CSF
-+ /* Reverse the suspension done */
-+ if (reset_gpu) {
-+ dev_warn(kbdev->dev, "Resorting to GPU reset for policy change\n");
-+ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
-+ kbase_reset_gpu(kbdev);
-+ kbase_reset_gpu_wait(kbdev);
-+ } else if (sched_suspend)
-+ kbase_csf_scheduler_pm_resume(kbdev);
-+
-+ mutex_unlock(&kbdev->pm.backend.policy_change_lock);
-+#endif
- }
-
- KBASE_EXPORT_TEST_API(kbase_pm_set_policy);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_policy.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_policy.h
-index f103ef0..e811365 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_policy.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_policy.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2015, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2015, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_shader_states.h b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_shader_states.h
-index 2bd9e47..8622ef7 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_shader_states.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_pm_shader_states.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -26,6 +25,41 @@
- * including this header file. This header file can be included multiple
- * times in the same compilation unit with different definitions of
- * KBASEP_SHADER_STATE().
-+ *
-+ * @OFF_CORESTACK_OFF: The shaders and core stacks are off
-+ * @OFF_CORESTACK_PEND_ON: The shaders are off, core stacks have been
-+ * requested to power on and hwcnt is being
-+ * disabled
-+ * @PEND_ON_CORESTACK_ON: Core stacks are on, shaders have been
-+ * requested to power on. Or after doing
-+ * partial shader on/off, checking whether
-+ * it's the desired state.
-+ * @ON_CORESTACK_ON: The shaders and core stacks are on, and
-+ * hwcnt already enabled.
-+ * @ON_CORESTACK_ON_RECHECK: The shaders and core stacks are on, hwcnt
-+ * disabled, and checks to powering down or
-+ * re-enabling hwcnt.
-+ * @WAIT_OFF_CORESTACK_ON: The shaders have been requested to power
-+ * off, but they remain on for the duration
-+ * of the hysteresis timer
-+ * @WAIT_GPU_IDLE: The shaders partial poweroff needs to
-+ * reach a state where jobs on the GPU are
-+ * finished including jobs currently running
-+ * and in the GPU queue because of
-+ * GPU2017-861
-+ * @WAIT_FINISHED_CORESTACK_ON: The hysteresis timer has expired
-+ * @L2_FLUSHING_CORESTACK_ON: The core stacks are on and the level 2
-+ * cache is being flushed.
-+ * @READY_OFF_CORESTACK_ON: The core stacks are on and the shaders are
-+ * ready to be powered off.
-+ * @PEND_OFF_CORESTACK_ON: The core stacks are on, and the shaders
-+ * have been requested to power off
-+ * @OFF_CORESTACK_PEND_OFF: The shaders are off, and the core stacks
-+ * have been requested to power off
-+ * @OFF_CORESTACK_OFF_TIMER_PEND_OFF: Shaders and corestacks are off, but the
-+ * tick timer cancellation is still pending.
-+ * @RESET_WAIT: The GPU is resetting, shader and core
-+ * stack power states are unknown
- */
- KBASEP_SHADER_STATE(OFF_CORESTACK_OFF)
- KBASEP_SHADER_STATE(OFF_CORESTACK_PEND_ON)
-@@ -33,7 +67,9 @@ KBASEP_SHADER_STATE(PEND_ON_CORESTACK_ON)
- KBASEP_SHADER_STATE(ON_CORESTACK_ON)
- KBASEP_SHADER_STATE(ON_CORESTACK_ON_RECHECK)
- KBASEP_SHADER_STATE(WAIT_OFF_CORESTACK_ON)
-+#if !MALI_USE_CSF
- KBASEP_SHADER_STATE(WAIT_GPU_IDLE)
-+#endif /* !MALI_USE_CSF */
- KBASEP_SHADER_STATE(WAIT_FINISHED_CORESTACK_ON)
- KBASEP_SHADER_STATE(L2_FLUSHING_CORESTACK_ON)
- KBASEP_SHADER_STATE(READY_OFF_CORESTACK_ON)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_time.c b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_time.c
-index cb10518..d10e404 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_time.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_time.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2016,2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,22 +17,20 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
- #include <mali_kbase_hwaccess_time.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include <backend/gpu/mali_kbase_pm_internal.h>
-
--void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter,
-- u64 *system_time, struct timespec64 *ts)
-+void kbase_backend_get_gpu_time_norequest(struct kbase_device *kbdev,
-+ u64 *cycle_counter,
-+ u64 *system_time,
-+ struct timespec64 *ts)
- {
- u32 hi1, hi2;
-
-- kbase_pm_request_gpu_cycle_counter(kbdev);
--
- if (cycle_counter) {
- /* Read hi, lo, hi to ensure a coherent u64 */
- do {
-@@ -65,6 +64,46 @@ void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter,
- #else
- ktime_get_raw_ts64(ts);
- #endif
-+}
-+
-+#if !MALI_USE_CSF
-+/**
-+ * timedwait_cycle_count_active() - Timed wait till CYCLE_COUNT_ACTIVE is active
-+ *
-+ * @kbdev: Kbase device
-+ *
-+ * Return: true if CYCLE_COUNT_ACTIVE is active within the timeout.
-+ */
-+static bool timedwait_cycle_count_active(struct kbase_device *kbdev)
-+{
-+ bool success = false;
-+ const unsigned int timeout = 100;
-+ const unsigned long remaining = jiffies + msecs_to_jiffies(timeout);
-
-+ while (time_is_after_jiffies(remaining)) {
-+ if ((kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS)) &
-+ GPU_STATUS_CYCLE_COUNT_ACTIVE)) {
-+ success = true;
-+ break;
-+ }
-+ }
-+ return success;
-+}
-+#endif
-+
-+void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter,
-+ u64 *system_time, struct timespec64 *ts)
-+{
-+#if !MALI_USE_CSF
-+ kbase_pm_request_gpu_cycle_counter(kbdev);
-+ WARN_ONCE(kbdev->pm.backend.l2_state != KBASE_L2_ON,
-+ "L2 not powered up");
-+ WARN_ONCE((!timedwait_cycle_count_active(kbdev)),
-+ "Timed out on CYCLE_COUNT_ACTIVE");
-+#endif
-+ kbase_backend_get_gpu_time_norequest(kbdev, cycle_counter, system_time,
-+ ts);
-+#if !MALI_USE_CSF
- kbase_pm_release_gpu_cycle_counter(kbdev);
-+#endif
- }
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/build.bp b/dvalin/kernel/drivers/gpu/arm/midgard/build.bp
-index 51aeecd..979e06f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/build.bp
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/build.bp
-@@ -1,15 +1,21 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017-2021 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.
-+ * of such GNU license.
- *
-- * 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 program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
- *
- */
-
-@@ -19,11 +25,17 @@
- * both mali_kbase and the test modules. */
- bob_defaults {
- name: "mali_kbase_shared_config_defaults",
-+ defaults: [
-+ "kernel_defaults",
-+ ],
- no_mali: {
-- kbuild_options: ["CONFIG_MALI_NO_MALI=y"],
-+ kbuild_options: [
-+ "CONFIG_MALI_NO_MALI=y",
-+ "CONFIG_MALI_NO_MALI_DEFAULT_GPU={{.gpu}}",
-+ ],
- },
-- mali_real_hw: {
-- kbuild_options: ["CONFIG_MALI_REAL_HW=y"],
-+ gpu_has_csf: {
-+ kbuild_options: ["CONFIG_MALI_CSF_SUPPORT=y"],
- },
- mali_devfreq: {
- kbuild_options: ["CONFIG_MALI_DEVFREQ=y"],
-@@ -31,8 +43,62 @@ bob_defaults {
- mali_midgard_dvfs: {
- kbuild_options: ["CONFIG_MALI_MIDGARD_DVFS=y"],
- },
-+ mali_gator_support: {
-+ kbuild_options: ["CONFIG_MALI_GATOR_SUPPORT=y"],
-+ },
-+ mali_midgard_enable_trace: {
-+ kbuild_options: ["CONFIG_MALI_MIDGARD_ENABLE_TRACE=y"],
-+ },
-+ mali_dma_fence: {
-+ kbuild_options: ["CONFIG_MALI_DMA_FENCE=y"],
-+ },
-+ mali_arbiter_support: {
-+ kbuild_options: ["CONFIG_MALI_ARBITER_SUPPORT=y"],
-+ },
-+ mali_dma_buf_map_on_demand: {
-+ kbuild_options: ["CONFIG_MALI_DMA_BUF_MAP_ON_DEMAND=y"],
-+ },
-+ mali_dma_buf_legacy_compat: {
-+ kbuild_options: ["CONFIG_MALI_DMA_BUF_LEGACY_COMPAT=y"],
-+ },
-+ mali_2mb_alloc: {
-+ kbuild_options: ["CONFIG_MALI_2MB_ALLOC=y"],
-+ },
-+ mali_memory_fully_backed: {
-+ kbuild_options: ["CONFIG_MALI_MEMORY_FULLY_BACKED=y"],
-+ },
-+ mali_corestack: {
-+ kbuild_options: ["CONFIG_MALI_CORESTACK=y"],
-+ },
-+ mali_real_hw: {
-+ kbuild_options: ["CONFIG_MALI_REAL_HW=y"],
-+ },
-+ mali_error_inject_none: {
-+ kbuild_options: ["CONFIG_MALI_ERROR_INJECT_NONE=y"],
-+ },
-+ mali_error_inject_track_list: {
-+ kbuild_options: ["CONFIG_MALI_ERROR_INJECT_TRACK_LIST=y"],
-+ },
-+ mali_error_inject_random: {
-+ kbuild_options: ["CONFIG_MALI_ERROR_INJECT_RANDOM=y"],
-+ },
-+ mali_error_inject: {
-+ kbuild_options: ["CONFIG_MALI_ERROR_INJECT=y"],
-+ },
-+ mali_gem5_build: {
-+ kbuild_options: ["CONFIG_MALI_GEM5_BUILD=y"],
-+ },
- mali_debug: {
-- kbuild_options: ["CONFIG_MALI_DEBUG=y"],
-+ kbuild_options: [
-+ "CONFIG_MALI_DEBUG=y",
-+ "MALI_KERNEL_TEST_API={{.debug}}",
-+ ],
-+ },
-+ mali_fence_debug: {
-+ kbuild_options: ["CONFIG_MALI_FENCE_DEBUG=y"],
-+ },
-+ mali_system_trace: {
-+ kbuild_options: ["CONFIG_MALI_SYSTEM_TRACE=y"],
- },
- buslog: {
- kbuild_options: ["CONFIG_MALI_BUSLOG=y"],
-@@ -43,44 +109,60 @@ bob_defaults {
- cinstr_gwt: {
- kbuild_options: ["CONFIG_MALI_CINSTR_GWT=y"],
- },
-- mali_gator_support: {
-- kbuild_options: ["CONFIG_MALI_GATOR_SUPPORT=y"],
-+ cinstr_primary_hwc: {
-+ kbuild_options: ["CONFIG_MALI_PRFCNT_SET_PRIMARY=y"],
- },
-- mali_midgard_enable_trace: {
-- kbuild_options: ["CONFIG_MALI_MIDGARD_ENABLE_TRACE=y"],
-+ cinstr_secondary_hwc: {
-+ kbuild_options: ["CONFIG_MALI_PRFCNT_SET_SECONDARY=y"],
- },
-- mali_system_trace: {
-- kbuild_options: ["CONFIG_MALI_SYSTEM_TRACE=y"],
-+ cinstr_tertiary_hwc: {
-+ kbuild_options: ["CONFIG_MALI_PRFCNT_SET_TERTIARY=y"],
- },
-- mali_pwrsoft_765: {
-- kbuild_options: ["CONFIG_MALI_PWRSOFT_765=y"],
-+ cinstr_hwc_set_select_via_debug_fs: {
-+ kbuild_options: ["CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS=y"],
- },
-- mali_memory_fully_backed: {
-- kbuild_options: ["CONFIG_MALI_MEMORY_FULLY_BACKED=y"],
-+ mali_job_dump: {
-+ kbuild_options: ["CONFIG_MALI_JOB_DUMP"],
- },
-- mali_dma_buf_map_on_demand: {
-- kbuild_options: ["CONFIG_MALI_DMA_BUF_MAP_ON_DEMAND=y"],
-- },
-- mali_dma_buf_legacy_compat: {
-- kbuild_options: ["CONFIG_MALI_DMA_BUF_LEGACY_COMPAT=y"],
-+ mali_pwrsoft_765: {
-+ kbuild_options: ["CONFIG_MALI_PWRSOFT_765=y"],
- },
-- mali_arbiter_support: {
-- kbuild_options: ["CONFIG_MALI_ARBITER_SUPPORT=y"],
-+ mali_hw_errata_1485982_not_affected: {
-+ kbuild_options: ["CONFIG_MALI_HW_ERRATA_1485982_NOT_AFFECTED=y"],
- },
-- mali_gem5_build: {
-- kbuild_options: ["CONFIG_MALI_GEM5_BUILD=y"],
-+ mali_hw_errata_1485982_use_clock_alternative: {
-+ kbuild_options: ["CONFIG_MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE=y"],
- },
- kbuild_options: [
-- "MALI_UNIT_TEST={{.unit_test_code}}",
-+ "CONFIG_MALI_PLATFORM_NAME={{.mali_platform_name}}",
- "MALI_CUSTOMER_RELEASE={{.release}}",
-+ "MALI_UNIT_TEST={{.unit_test_code}}",
- "MALI_USE_CSF={{.gpu_has_csf}}",
-- "MALI_KERNEL_TEST_API={{.debug}}",
-+ "MALI_JIT_PRESSURE_LIMIT_BASE={{.jit_pressure_limit_base}}",
-+
-+ // Start of CS experimental features definitions.
-+ // If there is nothing below, definition should be added as follows:
-+ // "MALI_EXPERIMENTAL_FEATURE={{.experimental_feature}}"
-+ // experimental_feature above comes from Mconfig in
-+ // <ddk_root>/product/base/
-+ // However, in Mconfig, experimental_feature should be looked up (for
-+ // similar explanation to this one) as ALLCAPS, i.e.
-+ // EXPERIMENTAL_FEATURE.
-+ //
-+ // IMPORTANT: MALI_CS_EXPERIMENTAL should NEVER be defined below as it
-+ // is an umbrella feature that would be open for inappropriate use
-+ // (catch-all for experimental CS code without separating it into
-+ // different features).
-+ "MALI_INCREMENTAL_RENDERING={{.incremental_rendering}}",
-+ "GPU_TIMESTAMP_CORRECTION={{.gpu_timestamp_correction}}",
- ],
-- defaults: ["kernel_defaults"],
- }
-
- bob_kernel_module {
- name: "mali_kbase",
-+ defaults: [
-+ "mali_kbase_shared_config_defaults",
-+ ],
- srcs: [
- "*.c",
- "*.h",
-@@ -90,6 +172,7 @@ bob_kernel_module {
- "backend/gpu/Kbuild",
- "context/*.c",
- "context/*.h",
-+ "context/Kbuild",
- "ipa/*.c",
- "ipa/*.h",
- "ipa/Kbuild",
-@@ -98,52 +181,23 @@ bob_kernel_module {
- "platform/*/*.h",
- "platform/*/Kbuild",
- "thirdparty/*.c",
-+ "thirdparty/Kbuild",
- "debug/*.c",
- "debug/*.h",
-+ "debug/Kbuild",
- "device/*.c",
- "device/*.h",
-+ "device/Kbuild",
- "gpu/*.c",
- "gpu/*.h",
-+ "gpu/Kbuild",
- "tl/*.c",
- "tl/*.h",
-+ "tl/Kbuild",
- "mmu/*.c",
- "mmu/*.h",
-+ "mmu/Kbuild",
- ],
-- kbuild_options: [
-- "CONFIG_MALI_KUTF=n",
-- "CONFIG_MALI_MIDGARD=m",
-- "CONFIG_MALI_NO_MALI_DEFAULT_GPU={{.gpu}}",
-- "CONFIG_MALI_PLATFORM_NAME={{.mali_platform_name}}",
-- ],
-- buslog: {
-- extra_symbols: [
-- "bus_logger",
-- ],
-- },
-- mali_corestack: {
-- kbuild_options: ["CONFIG_MALI_CORESTACK=y"],
-- },
-- mali_error_inject: {
-- kbuild_options: ["CONFIG_MALI_ERROR_INJECT=y"],
-- },
-- mali_error_inject_random: {
-- kbuild_options: ["CONFIG_MALI_ERROR_INJECT_RANDOM=y"],
-- },
-- cinstr_secondary_hwc: {
-- kbuild_options: ["CONFIG_MALI_PRFCNT_SET_SECONDARY=y"],
-- },
-- cinstr_secondary_hwc_via_debug_fs: {
-- kbuild_options: ["CONFIG_MALI_PRFCNT_SET_SECONDARY_VIA_DEBUG_FS=y"],
-- },
-- mali_2mb_alloc: {
-- kbuild_options: ["CONFIG_MALI_2MB_ALLOC=y"],
-- },
-- mali_hw_errata_1485982_not_affected: {
-- kbuild_options: ["CONFIG_MALI_HW_ERRATA_1485982_NOT_AFFECTED=y"],
-- },
-- mali_hw_errata_1485982_use_clock_alternative: {
-- kbuild_options: ["CONFIG_MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE=y"],
-- },
- gpu_has_job_manager: {
- srcs: [
- "context/backend/*_jm.c",
-@@ -155,6 +209,8 @@ bob_kernel_module {
- "jm/*.h",
- "tl/backend/*_jm.c",
- "mmu/backend/*_jm.c",
-+ "ipa/backend/*_jm.c",
-+ "ipa/backend/*_jm.h",
- ],
- },
- gpu_has_csf: {
-@@ -163,6 +219,9 @@ bob_kernel_module {
- "csf/*.c",
- "csf/*.h",
- "csf/Kbuild",
-+ "csf/ipa_control/*.c",
-+ "csf/ipa_control/*.h",
-+ "csf/ipa_control/Kbuild",
- "debug/backend/*_csf.c",
- "debug/backend/*_csf.h",
- "device/backend/*_csf.c",
-@@ -170,6 +229,8 @@ bob_kernel_module {
- "gpu/backend/*_csf.h",
- "tl/backend/*_csf.c",
- "mmu/backend/*_csf.c",
-+ "ipa/backend/*_csf.c",
-+ "ipa/backend/*_csf.h",
- ],
- },
- mali_arbiter_support: {
-@@ -179,5 +240,13 @@ bob_kernel_module {
- "arbiter/Kbuild",
- ],
- },
-- defaults: ["mali_kbase_shared_config_defaults"],
-+ kbuild_options: [
-+ "CONFIG_MALI_MIDGARD=m",
-+ "CONFIG_MALI_KUTF=n",
-+ ],
-+ buslog: {
-+ extra_symbols: [
-+ "bus_logger",
-+ ],
-+ },
- }
-diff --git a/dvalin/kernel/drivers/base/memory_group_manager/Kconfig b/dvalin/kernel/drivers/gpu/arm/midgard/context/Kbuild
-similarity index 63%
-rename from dvalin/kernel/drivers/base/memory_group_manager/Kconfig
-rename to dvalin/kernel/drivers/gpu/arm/midgard/context/Kbuild
-index da464ec..1d9c00a 100644
---- a/dvalin/kernel/drivers/base/memory_group_manager/Kconfig
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/context/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2013, 2016-2017, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,14 +16,12 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
-+mali_kbase-y += context/mali_kbase_context.o
-
--config MALI_MEMORY_GROUP_MANAGER
-- tristate "MALI_MEMORY_GROUP_MANAGER"
-- help
-- This option enables an example implementation of a memory group manager
-- for allocation and release of pages for memory pools managed by Mali GPU
-- device drivers.
-+ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
-+ mali_kbase-y += context/backend/mali_kbase_context_csf.o
-+else
-+ mali_kbase-y += context/backend/mali_kbase_context_jm.o
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/context/backend/mali_kbase_context_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/context/backend/mali_kbase_context_csf.c
-new file mode 100644
-index 0000000..1ce806f
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/context/backend/mali_kbase_context_csf.c
-@@ -0,0 +1,201 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * Base kernel context APIs for CSF GPUs
-+ */
-+
-+#include <context/mali_kbase_context_internal.h>
-+#include <gpu/mali_kbase_gpu_regmap.h>
-+#include <mali_kbase.h>
-+#include <mali_kbase_dma_fence.h>
-+#include <mali_kbase_mem_linux.h>
-+#include <mali_kbase_mem_pool_group.h>
-+#include <mmu/mali_kbase_mmu.h>
-+#include <tl/mali_kbase_timeline.h>
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+#include <csf/mali_kbase_csf_csg_debugfs.h>
-+#include <csf/mali_kbase_csf_kcpu_debugfs.h>
-+#include <csf/mali_kbase_csf_tiler_heap_debugfs.h>
-+#include <csf/mali_kbase_csf_cpu_queue_debugfs.h>
-+#include <mali_kbase_debug_mem_view.h>
-+#include <mali_kbase_mem_pool_debugfs.h>
-+
-+void kbase_context_debugfs_init(struct kbase_context *const kctx)
-+{
-+ kbase_debug_mem_view_init(kctx);
-+ kbase_mem_pool_debugfs_init(kctx->kctx_dentry, kctx);
-+ kbase_jit_debugfs_init(kctx);
-+ kbase_csf_queue_group_debugfs_init(kctx);
-+ kbase_csf_kcpu_debugfs_init(kctx);
-+ kbase_csf_tiler_heap_debugfs_init(kctx);
-+ kbase_csf_cpu_queue_debugfs_init(kctx);
-+}
-+KBASE_EXPORT_SYMBOL(kbase_context_debugfs_init);
-+
-+void kbase_context_debugfs_term(struct kbase_context *const kctx)
-+{
-+ debugfs_remove_recursive(kctx->kctx_dentry);
-+}
-+KBASE_EXPORT_SYMBOL(kbase_context_debugfs_term);
-+#else
-+void kbase_context_debugfs_init(struct kbase_context *const kctx)
-+{
-+ CSTD_UNUSED(kctx);
-+}
-+KBASE_EXPORT_SYMBOL(kbase_context_debugfs_init);
-+
-+void kbase_context_debugfs_term(struct kbase_context *const kctx)
-+{
-+ CSTD_UNUSED(kctx);
-+}
-+KBASE_EXPORT_SYMBOL(kbase_context_debugfs_term);
-+#endif /* CONFIG_DEBUG_FS */
-+
-+static void kbase_context_free(struct kbase_context *kctx)
-+{
-+ kbase_timeline_post_kbase_context_destroy(kctx);
-+
-+ vfree(kctx);
-+}
-+
-+static const struct kbase_context_init context_init[] = {
-+ { NULL, kbase_context_free, NULL },
-+ { kbase_context_common_init, kbase_context_common_term,
-+ "Common context initialization failed" },
-+ { kbase_context_mem_pool_group_init, kbase_context_mem_pool_group_term,
-+ "Memory pool group initialization failed" },
-+ { kbase_mem_evictable_init, kbase_mem_evictable_deinit,
-+ "Memory evictable initialization failed" },
-+ { kbase_context_mmu_init, kbase_context_mmu_term,
-+ "MMU initialization failed" },
-+ { kbase_context_mem_alloc_page, kbase_context_mem_pool_free,
-+ "Memory alloc page failed" },
-+ { kbase_region_tracker_init, kbase_region_tracker_term,
-+ "Region tracker initialization failed" },
-+ { kbase_sticky_resource_init, kbase_context_sticky_resource_term,
-+ "Sticky resource initialization failed" },
-+ { kbase_jit_init, kbase_jit_term, "JIT initialization failed" },
-+ { kbase_csf_ctx_init, kbase_csf_ctx_term,
-+ "CSF context initialization failed" },
-+ { kbase_context_add_to_dev_list, kbase_context_remove_from_dev_list,
-+ "Adding kctx to device failed" },
-+};
-+
-+static void kbase_context_term_partial(
-+ struct kbase_context *kctx,
-+ unsigned int i)
-+{
-+ while (i-- > 0) {
-+ if (context_init[i].term)
-+ context_init[i].term(kctx);
-+ }
-+}
-+
-+struct kbase_context *kbase_create_context(struct kbase_device *kbdev,
-+ bool is_compat,
-+ base_context_create_flags const flags,
-+ unsigned long const api_version,
-+ struct file *const filp)
-+{
-+ struct kbase_context *kctx;
-+ unsigned int i = 0;
-+
-+ if (WARN_ON(!kbdev))
-+ return NULL;
-+
-+ /* Validate flags */
-+ if (WARN_ON(flags != (flags & BASEP_CONTEXT_CREATE_KERNEL_FLAGS)))
-+ return NULL;
-+
-+ /* zero-inited as lot of code assume it's zero'ed out on create */
-+ kctx = vzalloc(sizeof(*kctx));
-+ if (WARN_ON(!kctx))
-+ return NULL;
-+
-+ kctx->kbdev = kbdev;
-+ kctx->api_version = api_version;
-+ kctx->filp = filp;
-+ kctx->create_flags = flags;
-+
-+ if (is_compat)
-+ kbase_ctx_flag_set(kctx, KCTX_COMPAT);
-+#if defined(CONFIG_64BIT)
-+ else
-+ kbase_ctx_flag_set(kctx, KCTX_FORCE_SAME_VA);
-+#endif /* defined(CONFIG_64BIT) */
-+
-+ for (i = 0; i < ARRAY_SIZE(context_init); i++) {
-+ int err = 0;
-+
-+ if (context_init[i].init)
-+ err = context_init[i].init(kctx);
-+
-+ if (err) {
-+ dev_err(kbdev->dev, "%s error = %d\n",
-+ context_init[i].err_mes, err);
-+
-+ /* kctx should be freed by kbase_context_free().
-+ * Otherwise it will result in memory leak.
-+ */
-+ WARN_ON(i == 0);
-+
-+ kbase_context_term_partial(kctx, i);
-+ return NULL;
-+ }
-+ }
-+
-+ return kctx;
-+}
-+KBASE_EXPORT_SYMBOL(kbase_create_context);
-+
-+void kbase_destroy_context(struct kbase_context *kctx)
-+{
-+ struct kbase_device *kbdev;
-+
-+ if (WARN_ON(!kctx))
-+ return;
-+
-+ kbdev = kctx->kbdev;
-+ if (WARN_ON(!kbdev))
-+ return;
-+
-+ /* Context termination could happen whilst the system suspend of
-+ * the GPU device is ongoing or has completed. It has been seen on
-+ * Customer side that a hang could occur if context termination is
-+ * not blocked until the resume of GPU device.
-+ */
-+ while (kbase_pm_context_active_handle_suspend(
-+ kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE)) {
-+ dev_info(kbdev->dev,
-+ "Suspend in progress when destroying context");
-+ wait_event(kbdev->pm.resume_wait,
-+ !kbase_pm_is_suspending(kbdev));
-+ }
-+
-+ kbase_mem_pool_group_mark_dying(&kctx->mem_pools);
-+
-+ kbase_context_term_partial(kctx, ARRAY_SIZE(context_init));
-+
-+ kbase_pm_context_idle(kbdev);
-+}
-+KBASE_EXPORT_SYMBOL(kbase_destroy_context);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/context/backend/mali_kbase_context_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/context/backend/mali_kbase_context_jm.c
-index 2cd2551..8ce81e7 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/context/backend/mali_kbase_context_jm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/context/backend/mali_kbase_context_jm.c
-@@ -1,12 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -17,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -30,13 +28,13 @@
- #include <mali_kbase.h>
- #include <mali_kbase_ctx_sched.h>
- #include <mali_kbase_dma_fence.h>
-+#include <mali_kbase_kinstr_jm.h>
- #include <mali_kbase_mem_linux.h>
- #include <mali_kbase_mem_pool_group.h>
- #include <mmu/mali_kbase_mmu.h>
- #include <tl/mali_kbase_timeline.h>
--#include <tl/mali_kbase_tracepoints.h>
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- #include <mali_kbase_debug_mem_view.h>
- #include <mali_kbase_mem_pool_debugfs.h>
-
-@@ -46,14 +44,12 @@ void kbase_context_debugfs_init(struct kbase_context *const kctx)
- kbase_mem_pool_debugfs_init(kctx->kctx_dentry, kctx);
- kbase_jit_debugfs_init(kctx);
- kbasep_jd_debugfs_ctx_init(kctx);
-- kbase_debug_job_fault_context_init(kctx);
- }
- KBASE_EXPORT_SYMBOL(kbase_context_debugfs_init);
-
- void kbase_context_debugfs_term(struct kbase_context *const kctx)
- {
- debugfs_remove_recursive(kctx->kctx_dentry);
-- kbase_debug_job_fault_context_term(kctx);
- }
- KBASE_EXPORT_SYMBOL(kbase_context_debugfs_term);
- #else
-@@ -70,6 +66,16 @@ void kbase_context_debugfs_term(struct kbase_context *const kctx)
- KBASE_EXPORT_SYMBOL(kbase_context_debugfs_term);
- #endif /* CONFIG_DEBUG_FS */
-
-+static int kbase_context_kbase_kinstr_jm_init(struct kbase_context *kctx)
-+{
-+ return kbase_kinstr_jm_init(&kctx->kinstr_jm);
-+}
-+
-+static void kbase_context_kbase_kinstr_jm_term(struct kbase_context *kctx)
-+{
-+ kbase_kinstr_jm_term(kctx->kinstr_jm);
-+}
-+
- static int kbase_context_kbase_timer_setup(struct kbase_context *kctx)
- {
- kbase_timer_setup(&kctx->soft_job_timeout,
-@@ -98,32 +104,59 @@ static int kbase_context_submit_check(struct kbase_context *kctx)
- return 0;
- }
-
-+static void kbase_context_flush_jobs(struct kbase_context *kctx)
-+{
-+ kbase_jd_zap_context(kctx);
-+ flush_workqueue(kctx->jctx.job_done_wq);
-+}
-+
-+static void kbase_context_free(struct kbase_context *kctx)
-+{
-+ kbase_timeline_post_kbase_context_destroy(kctx);
-+
-+ vfree(kctx);
-+}
-+
- static const struct kbase_context_init context_init[] = {
-- {kbase_context_common_init, kbase_context_common_term, NULL},
-- {kbase_context_mem_pool_group_init, kbase_context_mem_pool_group_term,
-- "Memory pool goup initialization failed"},
-- {kbase_mem_evictable_init, kbase_mem_evictable_deinit,
-- "Memory evictable initialization failed"},
-- {kbasep_js_kctx_init, kbasep_js_kctx_term,
-- "JS kctx initialization failed"},
-- {kbase_jd_init, kbase_jd_exit,
-- "JD initialization failed"},
-- {kbase_event_init, kbase_event_cleanup,
-- "Event initialization failed"},
-- {kbase_dma_fence_init, kbase_dma_fence_term,
-- "DMA fence initialization failed"},
-- {kbase_context_mmu_init, kbase_context_mmu_term,
-- "MMU initialization failed"},
-- {kbase_context_mem_alloc_page, kbase_context_mem_pool_free,
-- "Memory alloc page failed"},
-- {kbase_region_tracker_init, kbase_region_tracker_term,
-- "Region tracker initialization failed"},
-- {kbase_sticky_resource_init, kbase_context_sticky_resource_term,
-- "Sticky resource initialization failed"},
-- {kbase_jit_init, kbase_jit_term,
-- "JIT initialization failed"},
-- {kbase_context_kbase_timer_setup, NULL, NULL},
-- {kbase_context_submit_check, NULL, NULL},
-+ { NULL, kbase_context_free, NULL },
-+ { kbase_context_common_init, kbase_context_common_term,
-+ "Common context initialization failed" },
-+ { kbase_dma_fence_init, kbase_dma_fence_term,
-+ "DMA fence initialization failed" },
-+ { kbase_context_mem_pool_group_init, kbase_context_mem_pool_group_term,
-+ "Memory pool group initialization failed" },
-+ { kbase_mem_evictable_init, kbase_mem_evictable_deinit,
-+ "Memory evictable initialization failed" },
-+ { kbase_context_mmu_init, kbase_context_mmu_term,
-+ "MMU initialization failed" },
-+ { kbase_context_mem_alloc_page, kbase_context_mem_pool_free,
-+ "Memory alloc page failed" },
-+ { kbase_region_tracker_init, kbase_region_tracker_term,
-+ "Region tracker initialization failed" },
-+ { kbase_sticky_resource_init, kbase_context_sticky_resource_term,
-+ "Sticky resource initialization failed" },
-+ { kbase_jit_init, kbase_jit_term, "JIT initialization failed" },
-+ { kbase_context_kbase_kinstr_jm_init,
-+ kbase_context_kbase_kinstr_jm_term,
-+ "JM instrumentation initialization failed" },
-+ { kbase_context_kbase_timer_setup, NULL,
-+ "Timers initialization failed" },
-+ { kbase_event_init, kbase_event_cleanup,
-+ "Event initialization failed" },
-+ { kbasep_js_kctx_init, kbasep_js_kctx_term,
-+ "JS kctx initialization failed" },
-+ { kbase_jd_init, kbase_jd_exit, "JD initialization failed" },
-+ { kbase_context_submit_check, NULL, "Enabling job submission failed" },
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+ { kbase_debug_job_fault_context_init,
-+ kbase_debug_job_fault_context_term,
-+ "Job fault context initialization failed" },
-+#endif
-+ { NULL, kbase_context_flush_jobs, NULL },
-+ { kbase_context_add_to_dev_list, kbase_context_remove_from_dev_list,
-+ "Adding kctx to device failed" },
-+ { kbasep_platform_context_init, kbasep_platform_context_term,
-+ "Platform callback for kctx initialization failed" },
- };
-
- static void kbase_context_term_partial(
-@@ -167,14 +200,23 @@ struct kbase_context *kbase_create_context(struct kbase_device *kbdev,
- #if defined(CONFIG_64BIT)
- else
- kbase_ctx_flag_set(kctx, KCTX_FORCE_SAME_VA);
--#endif /* !defined(CONFIG_64BIT) */
-+#endif /* defined(CONFIG_64BIT) */
-
- for (i = 0; i < ARRAY_SIZE(context_init); i++) {
-- int err = context_init[i].init(kctx);
-+ int err = 0;
-+
-+ if (context_init[i].init)
-+ err = context_init[i].init(kctx);
-
- if (err) {
- dev_err(kbdev->dev, "%s error = %d\n",
- context_init[i].err_mes, err);
-+
-+ /* kctx should be freed by kbase_context_free().
-+ * Otherwise it will result in memory leak.
-+ */
-+ WARN_ON(i == 0);
-+
- kbase_context_term_partial(kctx, i);
- return NULL;
- }
-@@ -195,17 +237,27 @@ void kbase_destroy_context(struct kbase_context *kctx)
- if (WARN_ON(!kbdev))
- return;
-
-- /* 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.
-+ /* Context termination could happen whilst the system suspend of
-+ * the GPU device is ongoing or has completed. It has been seen on
-+ * Customer side that a hang could occur if context termination is
-+ * not blocked until the resume of GPU device.
- */
-- kbase_pm_context_active(kbdev);
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ atomic_inc(&kbdev->pm.gpu_users_waiting);
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
-+ while (kbase_pm_context_active_handle_suspend(
-+ kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE)) {
-+ dev_dbg(kbdev->dev,
-+ "Suspend in progress when destroying context");
-+ wait_event(kbdev->pm.resume_wait,
-+ !kbase_pm_is_suspending(kbdev));
-+ }
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ atomic_dec(&kbdev->pm.gpu_users_waiting);
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
-
- kbase_mem_pool_group_mark_dying(&kctx->mem_pools);
-
-- kbase_jd_zap_context(kctx);
-- flush_workqueue(kctx->jctx.job_done_wq);
--
- kbase_context_term_partial(kctx, ARRAY_SIZE(context_init));
-
- kbase_pm_context_idle(kbdev);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context.c b/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context.c
-index 93fe431..b2e7025 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context.c
-@@ -1,12 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -17,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -28,17 +26,105 @@
- #include <mali_kbase.h>
- #include <gpu/mali_kbase_gpu_regmap.h>
- #include <mali_kbase_mem_linux.h>
--#include <mali_kbase_dma_fence.h>
- #include <mali_kbase_ctx_sched.h>
- #include <mali_kbase_mem_pool_group.h>
--#include <tl/mali_kbase_tracepoints.h>
- #include <tl/mali_kbase_timeline.h>
- #include <mmu/mali_kbase_mmu.h>
- #include <context/mali_kbase_context_internal.h>
-
-+/**
-+ * find_process_node - Used to traverse the process rb_tree to find if
-+ * process exists already in process rb_tree.
-+ *
-+ * @node: Pointer to root node to start search.
-+ * @tgid: Thread group PID to search for.
-+ *
-+ * Return: Pointer to kbase_process if exists otherwise NULL.
-+ */
-+static struct kbase_process *find_process_node(struct rb_node *node, pid_t tgid)
-+{
-+ struct kbase_process *kprcs = NULL;
-+
-+ /* Check if the kctx creation request is from a existing process.*/
-+ while (node) {
-+ struct kbase_process *prcs_node =
-+ rb_entry(node, struct kbase_process, kprcs_node);
-+ if (prcs_node->tgid == tgid) {
-+ kprcs = prcs_node;
-+ break;
-+ }
-+
-+ if (tgid < prcs_node->tgid)
-+ node = node->rb_left;
-+ else
-+ node = node->rb_right;
-+ }
-+
-+ return kprcs;
-+}
-+
-+/**
-+ * kbase_insert_kctx_to_process - Initialise kbase process context.
-+ *
-+ * @kctx: Pointer to kbase context.
-+ *
-+ * Here we initialise per process rb_tree managed by kbase_device.
-+ * We maintain a rb_tree of each unique process that gets created.
-+ * and Each process maintains a list of kbase context.
-+ * This setup is currently used by kernel trace functionality
-+ * to trace and visualise gpu memory consumption.
-+ *
-+ * Return: 0 on success and error number on failure.
-+ */
-+static int kbase_insert_kctx_to_process(struct kbase_context *kctx)
-+{
-+ struct rb_root *const prcs_root = &kctx->kbdev->process_root;
-+ const pid_t tgid = kctx->tgid;
-+ struct kbase_process *kprcs = NULL;
-+
-+ lockdep_assert_held(&kctx->kbdev->kctx_list_lock);
-+
-+ kprcs = find_process_node(prcs_root->rb_node, tgid);
-+
-+ /* if the kctx is from new process then create a new kbase_process
-+ * and add it to the &kbase_device->rb_tree
-+ */
-+ if (!kprcs) {
-+ struct rb_node **new = &prcs_root->rb_node, *parent = NULL;
-+
-+ kprcs = kzalloc(sizeof(*kprcs), GFP_KERNEL);
-+ if (kprcs == NULL)
-+ return -ENOMEM;
-+ kprcs->tgid = tgid;
-+ INIT_LIST_HEAD(&kprcs->kctx_list);
-+ kprcs->dma_buf_root = RB_ROOT;
-+ kprcs->total_gpu_pages = 0;
-+
-+ while (*new) {
-+ struct kbase_process *prcs_node;
-+
-+ parent = *new;
-+ prcs_node = rb_entry(parent, struct kbase_process,
-+ kprcs_node);
-+ if (tgid < prcs_node->tgid)
-+ new = &(*new)->rb_left;
-+ else
-+ new = &(*new)->rb_right;
-+ }
-+ rb_link_node(&kprcs->kprcs_node, parent, new);
-+ rb_insert_color(&kprcs->kprcs_node, prcs_root);
-+ }
-+
-+ kctx->kprcs = kprcs;
-+ list_add(&kctx->kprcs_link, &kprcs->kctx_list);
-+
-+ return 0;
-+}
-+
- int kbase_context_common_init(struct kbase_context *kctx)
- {
- const unsigned long cookies_mask = KBASE_COOKIE_MASK;
-+ int err = 0;
-
- /* creating a context is considered a disjoint event */
- kbase_disjoint_event(kctx->kbdev);
-@@ -66,30 +152,95 @@ int kbase_context_common_init(struct kbase_context *kctx)
-
- init_waitqueue_head(&kctx->event_queue);
- atomic_set(&kctx->event_count, 0);
-+#if !MALI_USE_CSF
- atomic_set(&kctx->event_closed, false);
--
-- bitmap_copy(kctx->cookies, &cookies_mask, BITS_PER_LONG);
--
--#ifdef CONFIG_GPU_TRACEPOINTS
-+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
- atomic_set(&kctx->jctx.work_id, 0);
-+#endif
- #endif
-
-+ bitmap_copy(kctx->cookies, &cookies_mask, BITS_PER_LONG);
-+
- kctx->id = atomic_add_return(1, &(kctx->kbdev->ctx_num)) - 1;
-
- mutex_init(&kctx->legacy_hwcnt_lock);
-
- mutex_lock(&kctx->kbdev->kctx_list_lock);
-- list_add(&kctx->kctx_list_link, &kctx->kbdev->kctx_list);
-
-- KBASE_TLSTREAM_TL_KBASE_NEW_CTX(kctx->kbdev, kctx->id,
-- kctx->kbdev->gpu_props.props.raw_props.gpu_id);
-- KBASE_TLSTREAM_TL_NEW_CTX(kctx->kbdev, kctx, kctx->id,
-- (u32)(kctx->tgid));
-+ err = kbase_insert_kctx_to_process(kctx);
-+ if (err)
-+ dev_err(kctx->kbdev->dev,
-+ "(err:%d) failed to insert kctx to kbase_process\n", err);
-+
- mutex_unlock(&kctx->kbdev->kctx_list_lock);
-
-+ return err;
-+}
-+
-+int kbase_context_add_to_dev_list(struct kbase_context *kctx)
-+{
-+ if (WARN_ON(!kctx))
-+ return -EINVAL;
-+
-+ if (WARN_ON(!kctx->kbdev))
-+ return -EINVAL;
-+
-+ mutex_lock(&kctx->kbdev->kctx_list_lock);
-+ list_add(&kctx->kctx_list_link, &kctx->kbdev->kctx_list);
-+ mutex_unlock(&kctx->kbdev->kctx_list_lock);
-+
-+ kbase_timeline_post_kbase_context_create(kctx);
-+
- return 0;
- }
-
-+void kbase_context_remove_from_dev_list(struct kbase_context *kctx)
-+{
-+ if (WARN_ON(!kctx))
-+ return;
-+
-+ if (WARN_ON(!kctx->kbdev))
-+ return;
-+
-+ kbase_timeline_pre_kbase_context_destroy(kctx);
-+
-+ mutex_lock(&kctx->kbdev->kctx_list_lock);
-+ list_del_init(&kctx->kctx_list_link);
-+ mutex_unlock(&kctx->kbdev->kctx_list_lock);
-+}
-+
-+/**
-+ * kbase_remove_kctx_from_process - remove a terminating context from
-+ * the process list.
-+ *
-+ * @kctx: Pointer to kbase context.
-+ *
-+ * Remove the tracking of context from the list of contexts maintained under
-+ * kbase process and if the list if empty then there no outstanding contexts
-+ * we can remove the process node as well.
-+ */
-+
-+static void kbase_remove_kctx_from_process(struct kbase_context *kctx)
-+{
-+ struct kbase_process *kprcs = kctx->kprcs;
-+
-+ lockdep_assert_held(&kctx->kbdev->kctx_list_lock);
-+ list_del(&kctx->kprcs_link);
-+
-+ /* if there are no outstanding contexts in current process node,
-+ * we can remove it from the process rb_tree.
-+ */
-+ if (list_empty(&kprcs->kctx_list)) {
-+ rb_erase(&kprcs->kprcs_node, &kctx->kbdev->process_root);
-+ /* Add checks, so that the terminating process Should not
-+ * hold any gpu_memory.
-+ */
-+ WARN_ON(kprcs->total_gpu_pages);
-+ WARN_ON(!RB_EMPTY_ROOT(&kprcs->dma_buf_root));
-+ kfree(kprcs);
-+ }
-+}
-+
- void kbase_context_common_term(struct kbase_context *kctx)
- {
- unsigned long flags;
-@@ -109,24 +260,10 @@ void kbase_context_common_term(struct kbase_context *kctx)
- WARN_ON(atomic_read(&kctx->nonmapped_pages) != 0);
-
- mutex_lock(&kctx->kbdev->kctx_list_lock);
--
-- KBASE_TLSTREAM_TL_KBASE_DEL_CTX(kctx->kbdev, kctx->id);
--
-- KBASE_TLSTREAM_TL_DEL_CTX(kctx->kbdev, kctx);
-- list_del(&kctx->kctx_list_link);
-+ kbase_remove_kctx_from_process(kctx);
- mutex_unlock(&kctx->kbdev->kctx_list_lock);
-
- KBASE_KTRACE_ADD(kctx->kbdev, CORE_CTX_DESTROY, kctx, 0u);
--
-- /* Flush the timeline stream, so the user can see the termination
-- * tracepoints being fired.
-- * The "if" statement below is for optimization. It is safe to call
-- * kbase_timeline_streams_flush when timeline is disabled.
-- */
-- if (atomic_read(&kctx->kbdev->timeline_flags) != 0)
-- kbase_timeline_streams_flush(kctx->kbdev->timeline);
--
-- vfree(kctx);
- }
-
- int kbase_context_mem_pool_group_init(struct kbase_context *kctx)
-@@ -144,11 +281,9 @@ void kbase_context_mem_pool_group_term(struct kbase_context *kctx)
-
- int kbase_context_mmu_init(struct kbase_context *kctx)
- {
-- kbase_mmu_init(kctx->kbdev,
-- &kctx->mmu, kctx,
-+ return kbase_mmu_init(
-+ kctx->kbdev, &kctx->mmu, kctx,
- base_context_mmu_group_id_get(kctx->create_flags));
--
-- return 0;
- }
-
- void kbase_context_mmu_term(struct kbase_context *kctx)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context.h b/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context.h
-index e4ed894..a0c51c9 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2017, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,18 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--/*
-- *
-- * (C) COPYRIGHT 2011-2017, 2019 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.
-- *
- */
-
- #ifndef _KBASE_CONTEXT_H_
-@@ -117,25 +106,7 @@ static inline bool kbase_ctx_flag(struct kbase_context *kctx,
- static inline void kbase_ctx_flag_clear(struct kbase_context *kctx,
- enum kbase_context_flags flag)
- {
--#if KERNEL_VERSION(4, 3, 0) > LINUX_VERSION_CODE
-- /*
-- * Earlier kernel versions doesn't have atomic_andnot() or
-- * atomic_and(). atomic_clear_mask() was only available on some
-- * architectures and removed on arm in v3.13 on arm and arm64.
-- *
-- * Use a compare-exchange loop to clear the flag on pre 4.3 kernels,
-- * when atomic_andnot() becomes available.
-- */
-- int old, new;
--
-- do {
-- old = atomic_read(&kctx->flags);
-- new = old & ~flag;
--
-- } while (atomic_cmpxchg(&kctx->flags, old, new) != old);
--#else
- atomic_andnot(flag, &kctx->flags);
--#endif
- }
-
- /**
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context_internal.h
-index 818cdbe..1cde739 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context_internal.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/context/mali_kbase_context_internal.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,16 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * (C) COPYRIGHT 2019 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.
- */
-
- #include <mali_kbase.h>
-@@ -58,3 +49,6 @@ int kbase_context_mem_alloc_page(struct kbase_context *kctx);
- void kbase_context_mem_pool_free(struct kbase_context *kctx);
-
- void kbase_context_sticky_resource_term(struct kbase_context *kctx);
-+
-+int kbase_context_add_to_dev_list(struct kbase_context *kctx);
-+void kbase_context_remove_from_dev_list(struct kbase_context *kctx);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/csf/Kbuild
-new file mode 100644
-index 0000000..765e419
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/Kbuild
-@@ -0,0 +1,47 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2018-2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+mali_kbase-y += \
-+ csf/mali_kbase_csf_firmware_cfg.o \
-+ csf/mali_kbase_csf_trace_buffer.o \
-+ csf/mali_kbase_csf.o \
-+ csf/mali_kbase_csf_scheduler.o \
-+ csf/mali_kbase_csf_kcpu.o \
-+ csf/mali_kbase_csf_tiler_heap.o \
-+ csf/mali_kbase_csf_timeout.o \
-+ csf/mali_kbase_csf_tl_reader.o \
-+ csf/mali_kbase_csf_heap_context_alloc.o \
-+ csf/mali_kbase_csf_reset_gpu.o \
-+ csf/mali_kbase_csf_csg_debugfs.o \
-+ csf/mali_kbase_csf_kcpu_debugfs.o \
-+ csf/mali_kbase_csf_protected_memory.o \
-+ csf/mali_kbase_csf_tiler_heap_debugfs.o \
-+ csf/mali_kbase_csf_cpu_queue_debugfs.o
-+
-+mali_kbase-$(CONFIG_MALI_REAL_HW) += csf/mali_kbase_csf_firmware.o
-+
-+
-+ifeq ($(KBUILD_EXTMOD),)
-+# in-tree
-+ -include $(src)/csf/ipa_control/Kbuild
-+else
-+# out-of-tree
-+ include $(src)/csf/ipa_control/Kbuild
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/Makefile.kbase b/dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/Kbuild
-similarity index 75%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/Makefile.kbase
-rename to dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/Kbuild
-index 6b0f81e..08824b2 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/Makefile.kbase
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2010, 2013, 2018 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,9 +16,7 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
--#
--
--EXTRA_CFLAGS += -I$(ROOT) -I$(KBASE_PATH) -I$(KBASE_PATH)/platform_$(PLATFORM)
-
-+mali_kbase-y += \
-+ csf/ipa_control/mali_kbase_csf_ipa_control.o
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/mali_kbase_csf_ipa_control.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/mali_kbase_csf_ipa_control.c
-new file mode 100644
-index 0000000..e23d681
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/mali_kbase_csf_ipa_control.c
-@@ -0,0 +1,925 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
-+#include "mali_kbase_csf_ipa_control.h"
-+
-+/*
-+ * Status flags from the STATUS register of the IPA Control interface.
-+ */
-+#define STATUS_COMMAND_ACTIVE ((u32)1 << 0)
-+#define STATUS_TIMER_ACTIVE ((u32)1 << 1)
-+#define STATUS_AUTO_ACTIVE ((u32)1 << 2)
-+#define STATUS_PROTECTED_MODE ((u32)1 << 8)
-+#define STATUS_RESET ((u32)1 << 9)
-+#define STATUS_TIMER_ENABLED ((u32)1 << 31)
-+
-+/*
-+ * Commands for the COMMAND register of the IPA Control interface.
-+ */
-+#define COMMAND_NOP ((u32)0)
-+#define COMMAND_APPLY ((u32)1)
-+#define COMMAND_CLEAR ((u32)2)
-+#define COMMAND_SAMPLE ((u32)3)
-+#define COMMAND_PROTECTED_ACK ((u32)4)
-+#define COMMAND_RESET_ACK ((u32)5)
-+
-+/**
-+ * Default value for the TIMER register of the IPA Control interface,
-+ * expressed in milliseconds.
-+ *
-+ * The chosen value is a trade off between two requirements: the IPA Control
-+ * interface should sample counters with a resolution in the order of
-+ * milliseconds, while keeping GPU overhead as limited as possible.
-+ */
-+#define TIMER_DEFAULT_VALUE_MS ((u32)10) /* 10 milliseconds */
-+
-+/**
-+ * Number of timer events per second.
-+ */
-+#define TIMER_EVENTS_PER_SECOND ((u32)1000 / TIMER_DEFAULT_VALUE_MS)
-+
-+/**
-+ * Maximum number of loops polling the GPU before we assume the GPU has hung.
-+ */
-+#define IPA_INACTIVE_MAX_LOOPS ((unsigned int)8000000)
-+
-+/**
-+ * Number of bits used to configure a performance counter in SELECT registers.
-+ */
-+#define IPA_CONTROL_SELECT_BITS_PER_CNT ((u64)8)
-+
-+/**
-+ * Maximum value of a performance counter.
-+ */
-+#define MAX_PRFCNT_VALUE (((u64)1 << 48) - 1)
-+
-+/**
-+ * struct kbase_ipa_control_listener_data - Data for the GPU clock frequency
-+ * listener
-+ *
-+ * @listener: GPU clock frequency listener.
-+ * @kbdev: Pointer to kbase device.
-+ */
-+struct kbase_ipa_control_listener_data {
-+ struct kbase_clk_rate_listener listener;
-+ struct kbase_device *kbdev;
-+};
-+
-+static u32 timer_value(u32 gpu_rate)
-+{
-+ return gpu_rate / TIMER_EVENTS_PER_SECOND;
-+}
-+
-+static int wait_status(struct kbase_device *kbdev, u32 flags)
-+{
-+ unsigned int max_loops = IPA_INACTIVE_MAX_LOOPS;
-+ u32 status = kbase_reg_read(kbdev, IPA_CONTROL_REG(STATUS));
-+
-+ /*
-+ * Wait for the STATUS register to indicate that flags have been
-+ * cleared, in case a transition is pending.
-+ */
-+ while (--max_loops && (status & flags))
-+ status = kbase_reg_read(kbdev, IPA_CONTROL_REG(STATUS));
-+ if (max_loops == 0) {
-+ dev_err(kbdev->dev, "IPA_CONTROL STATUS register stuck");
-+ return -EBUSY;
-+ }
-+
-+ return 0;
-+}
-+
-+static int apply_select_config(struct kbase_device *kbdev, u64 *select)
-+{
-+ int ret;
-+
-+ u32 select_cshw_lo = (u32)(select[KBASE_IPA_CORE_TYPE_CSHW] & U32_MAX);
-+ u32 select_cshw_hi =
-+ (u32)((select[KBASE_IPA_CORE_TYPE_CSHW] >> 32) & U32_MAX);
-+ u32 select_memsys_lo =
-+ (u32)(select[KBASE_IPA_CORE_TYPE_MEMSYS] & U32_MAX);
-+ u32 select_memsys_hi =
-+ (u32)((select[KBASE_IPA_CORE_TYPE_MEMSYS] >> 32) & U32_MAX);
-+ u32 select_tiler_lo =
-+ (u32)(select[KBASE_IPA_CORE_TYPE_TILER] & U32_MAX);
-+ u32 select_tiler_hi =
-+ (u32)((select[KBASE_IPA_CORE_TYPE_TILER] >> 32) & U32_MAX);
-+ u32 select_shader_lo =
-+ (u32)(select[KBASE_IPA_CORE_TYPE_SHADER] & U32_MAX);
-+ u32 select_shader_hi =
-+ (u32)((select[KBASE_IPA_CORE_TYPE_SHADER] >> 32) & U32_MAX);
-+
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_CSHW_LO), select_cshw_lo);
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_CSHW_HI), select_cshw_hi);
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_MEMSYS_LO),
-+ select_memsys_lo);
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_MEMSYS_HI),
-+ select_memsys_hi);
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_TILER_LO),
-+ select_tiler_lo);
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_TILER_HI),
-+ select_tiler_hi);
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_SHADER_LO),
-+ select_shader_lo);
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_SHADER_HI),
-+ select_shader_hi);
-+
-+ ret = wait_status(kbdev, STATUS_COMMAND_ACTIVE);
-+
-+ if (!ret)
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(COMMAND), COMMAND_APPLY);
-+
-+ return ret;
-+}
-+
-+static u64 read_value_cnt(struct kbase_device *kbdev, u8 type, int select_idx)
-+{
-+ u32 value_lo, value_hi;
-+
-+ switch (type) {
-+ case KBASE_IPA_CORE_TYPE_CSHW:
-+ value_lo = kbase_reg_read(
-+ kbdev, IPA_CONTROL_REG(VALUE_CSHW_REG_LO(select_idx)));
-+ value_hi = kbase_reg_read(
-+ kbdev, IPA_CONTROL_REG(VALUE_CSHW_REG_HI(select_idx)));
-+ break;
-+ case KBASE_IPA_CORE_TYPE_MEMSYS:
-+ value_lo = kbase_reg_read(
-+ kbdev,
-+ IPA_CONTROL_REG(VALUE_MEMSYS_REG_LO(select_idx)));
-+ value_hi = kbase_reg_read(
-+ kbdev,
-+ IPA_CONTROL_REG(VALUE_MEMSYS_REG_HI(select_idx)));
-+ break;
-+ case KBASE_IPA_CORE_TYPE_TILER:
-+ value_lo = kbase_reg_read(
-+ kbdev, IPA_CONTROL_REG(VALUE_TILER_REG_LO(select_idx)));
-+ value_hi = kbase_reg_read(
-+ kbdev, IPA_CONTROL_REG(VALUE_TILER_REG_HI(select_idx)));
-+ break;
-+ case KBASE_IPA_CORE_TYPE_SHADER:
-+ value_lo = kbase_reg_read(
-+ kbdev,
-+ IPA_CONTROL_REG(VALUE_SHADER_REG_LO(select_idx)));
-+ value_hi = kbase_reg_read(
-+ kbdev,
-+ IPA_CONTROL_REG(VALUE_SHADER_REG_HI(select_idx)));
-+ break;
-+ default:
-+ WARN(1, "Unknown core type: %u\n", type);
-+ value_lo = value_hi = 0;
-+ break;
-+ }
-+
-+ return (((u64)value_hi << 32) | value_lo);
-+}
-+
-+static void build_select_config(struct kbase_ipa_control *ipa_ctrl,
-+ u64 *select_config)
-+{
-+ size_t i;
-+
-+ for (i = 0; i < KBASE_IPA_CORE_TYPE_NUM; i++) {
-+ size_t j;
-+
-+ select_config[i] = 0ULL;
-+
-+ for (j = 0; j < KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS; j++) {
-+ struct kbase_ipa_control_prfcnt_config *prfcnt_config =
-+ &ipa_ctrl->blocks[i].select[j];
-+
-+ select_config[i] |=
-+ ((u64)prfcnt_config->idx
-+ << (IPA_CONTROL_SELECT_BITS_PER_CNT * j));
-+ }
-+ }
-+}
-+
-+static inline void calc_prfcnt_delta(struct kbase_device *kbdev,
-+ struct kbase_ipa_control_prfcnt *prfcnt,
-+ bool gpu_ready)
-+{
-+ u64 delta_value, raw_value;
-+
-+ if (gpu_ready)
-+ raw_value = read_value_cnt(kbdev, (u8)prfcnt->type,
-+ prfcnt->select_idx);
-+ else
-+ raw_value = prfcnt->latest_raw_value;
-+
-+ if (raw_value < prfcnt->latest_raw_value) {
-+ delta_value = (MAX_PRFCNT_VALUE - prfcnt->latest_raw_value) +
-+ raw_value;
-+ } else {
-+ delta_value = raw_value - prfcnt->latest_raw_value;
-+ }
-+
-+ delta_value *= prfcnt->scaling_factor;
-+
-+ if (!WARN_ON_ONCE(kbdev->csf.ipa_control.cur_gpu_rate == 0))
-+ if (prfcnt->gpu_norm)
-+ delta_value /= kbdev->csf.ipa_control.cur_gpu_rate;
-+
-+ prfcnt->latest_raw_value = raw_value;
-+
-+ /* Accumulate the difference */
-+ prfcnt->accumulated_diff += delta_value;
-+}
-+
-+/**
-+ * kbase_ipa_control_rate_change_notify - GPU frequency change callback
-+ *
-+ * @listener: Clock frequency change listener.
-+ * @clk_index: Index of the clock for which the change has occurred.
-+ * @clk_rate_hz: Clock frequency(Hz).
-+ *
-+ * This callback notifies kbase_ipa_control about GPU frequency changes.
-+ * Only top-level clock changes are meaningful. GPU frequency updates
-+ * affect all performance counters which require GPU normalization
-+ * in every session.
-+ */
-+static void
-+kbase_ipa_control_rate_change_notify(struct kbase_clk_rate_listener *listener,
-+ u32 clk_index, u32 clk_rate_hz)
-+{
-+ if ((clk_index == KBASE_CLOCK_DOMAIN_TOP) && (clk_rate_hz != 0)) {
-+ size_t i;
-+ unsigned long flags;
-+ struct kbase_ipa_control_listener_data *listener_data =
-+ container_of(listener,
-+ struct kbase_ipa_control_listener_data,
-+ listener);
-+ struct kbase_device *kbdev = listener_data->kbdev;
-+ struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+
-+ if (!kbdev->pm.backend.gpu_ready) {
-+ dev_err(kbdev->dev,
-+ "%s: GPU frequency cannot change while GPU is off",
-+ __func__);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ return;
-+ }
-+
-+ /* Interrupts are already disabled and interrupt state is also saved */
-+ spin_lock(&ipa_ctrl->lock);
-+
-+ for (i = 0; i < ipa_ctrl->num_active_sessions; i++) {
-+ size_t j;
-+ struct kbase_ipa_control_session *session = &ipa_ctrl->sessions[i];
-+
-+ for (j = 0; j < session->num_prfcnts; j++) {
-+ struct kbase_ipa_control_prfcnt *prfcnt =
-+ &session->prfcnts[j];
-+
-+ if (prfcnt->gpu_norm)
-+ calc_prfcnt_delta(kbdev, prfcnt, true);
-+ }
-+ }
-+
-+ ipa_ctrl->cur_gpu_rate = clk_rate_hz;
-+
-+ /* Update the timer for automatic sampling if active sessions
-+ * are present. Counters have already been manually sampled.
-+ */
-+ if (ipa_ctrl->num_active_sessions > 0) {
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(TIMER),
-+ timer_value(ipa_ctrl->cur_gpu_rate));
-+ }
-+
-+ spin_unlock(&ipa_ctrl->lock);
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ }
-+}
-+
-+void kbase_ipa_control_init(struct kbase_device *kbdev)
-+{
-+ struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
-+ struct kbase_clk_rate_trace_manager *clk_rtm = &kbdev->pm.clk_rtm;
-+ struct kbase_ipa_control_listener_data *listener_data;
-+ size_t i, j;
-+
-+ for (i = 0; i < KBASE_IPA_CORE_TYPE_NUM; i++) {
-+ for (j = 0; j < KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS; j++) {
-+ ipa_ctrl->blocks[i].select[j].idx = 0;
-+ ipa_ctrl->blocks[i].select[j].refcount = 0;
-+ }
-+ ipa_ctrl->blocks[i].num_available_counters =
-+ KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS;
-+ }
-+
-+ spin_lock_init(&ipa_ctrl->lock);
-+ ipa_ctrl->num_active_sessions = 0;
-+ for (i = 0; i < KBASE_IPA_CONTROL_MAX_SESSIONS; i++) {
-+ ipa_ctrl->sessions[i].active = false;
-+ }
-+
-+ listener_data = kmalloc(sizeof(struct kbase_ipa_control_listener_data),
-+ GFP_KERNEL);
-+ if (listener_data) {
-+ listener_data->listener.notify =
-+ kbase_ipa_control_rate_change_notify;
-+ listener_data->kbdev = kbdev;
-+ ipa_ctrl->rtm_listener_data = listener_data;
-+ }
-+
-+ spin_lock(&clk_rtm->lock);
-+ if (clk_rtm->clks[KBASE_CLOCK_DOMAIN_TOP])
-+ ipa_ctrl->cur_gpu_rate =
-+ clk_rtm->clks[KBASE_CLOCK_DOMAIN_TOP]->clock_val;
-+ if (listener_data)
-+ kbase_clk_rate_trace_manager_subscribe_no_lock(
-+ clk_rtm, &listener_data->listener);
-+ spin_unlock(&clk_rtm->lock);
-+}
-+KBASE_EXPORT_TEST_API(kbase_ipa_control_init);
-+
-+void kbase_ipa_control_term(struct kbase_device *kbdev)
-+{
-+ unsigned long flags;
-+ struct kbase_clk_rate_trace_manager *clk_rtm = &kbdev->pm.clk_rtm;
-+ struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
-+ struct kbase_ipa_control_listener_data *listener_data =
-+ ipa_ctrl->rtm_listener_data;
-+
-+ WARN_ON(ipa_ctrl->num_active_sessions);
-+
-+ if (listener_data)
-+ kbase_clk_rate_trace_manager_unsubscribe(clk_rtm, &listener_data->listener);
-+ kfree(ipa_ctrl->rtm_listener_data);
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ if (kbdev->pm.backend.gpu_powered)
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(TIMER), 0);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+}
-+KBASE_EXPORT_TEST_API(kbase_ipa_control_term);
-+
-+int kbase_ipa_control_register(
-+ struct kbase_device *kbdev,
-+ const struct kbase_ipa_control_perf_counter *perf_counters,
-+ size_t num_counters, void **client)
-+{
-+ int ret = 0;
-+ size_t i, session_idx, req_counters[KBASE_IPA_CORE_TYPE_NUM];
-+ bool already_configured[KBASE_IPA_CONTROL_MAX_COUNTERS];
-+ bool new_config = false;
-+ struct kbase_ipa_control *ipa_ctrl;
-+ struct kbase_ipa_control_session *session = NULL;
-+ unsigned long flags;
-+
-+ if (WARN_ON(kbdev == NULL) || WARN_ON(perf_counters == NULL) ||
-+ WARN_ON(client == NULL) ||
-+ WARN_ON(num_counters > KBASE_IPA_CONTROL_MAX_COUNTERS)) {
-+ dev_err(kbdev->dev, "%s: wrong input arguments", __func__);
-+ return -EINVAL;
-+ }
-+
-+ kbase_pm_context_active(kbdev);
-+
-+ ipa_ctrl = &kbdev->csf.ipa_control;
-+ spin_lock_irqsave(&ipa_ctrl->lock, flags);
-+
-+ if (ipa_ctrl->num_active_sessions == KBASE_IPA_CONTROL_MAX_SESSIONS) {
-+ dev_err(kbdev->dev, "%s: too many sessions", __func__);
-+ ret = -EBUSY;
-+ goto exit;
-+ }
-+
-+ for (i = 0; i < KBASE_IPA_CORE_TYPE_NUM; i++)
-+ req_counters[i] = 0;
-+
-+ /*
-+ * Count how many counters would need to be configured in order to
-+ * satisfy the request. Requested counters which happen to be already
-+ * configured can be skipped.
-+ */
-+ for (i = 0; i < num_counters; i++) {
-+ size_t j;
-+ enum kbase_ipa_core_type type = perf_counters[i].type;
-+ u8 idx = perf_counters[i].idx;
-+
-+ if ((type >= KBASE_IPA_CORE_TYPE_NUM) ||
-+ (idx >= KBASE_IPA_CONTROL_CNT_MAX_IDX)) {
-+ dev_err(kbdev->dev,
-+ "%s: invalid requested type %u and/or index %u",
-+ __func__, type, idx);
-+ ret = -EINVAL;
-+ goto exit;
-+ }
-+
-+ for (j = 0; j < KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS; j++) {
-+ struct kbase_ipa_control_prfcnt_config *prfcnt_config =
-+ &ipa_ctrl->blocks[type].select[j];
-+
-+ if (prfcnt_config->refcount > 0) {
-+ if (prfcnt_config->idx == idx) {
-+ already_configured[i] = true;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (j == KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS) {
-+ already_configured[i] = false;
-+ req_counters[type]++;
-+ new_config = true;
-+ }
-+ }
-+
-+ for (i = 0; i < KBASE_IPA_CORE_TYPE_NUM; i++)
-+ if (req_counters[i] >
-+ ipa_ctrl->blocks[i].num_available_counters) {
-+ dev_err(kbdev->dev,
-+ "%s: more counters (%zu) than available (%zu) have been requested for type %zu",
-+ __func__, req_counters[i],
-+ ipa_ctrl->blocks[i].num_available_counters, i);
-+ ret = -EINVAL;
-+ goto exit;
-+ }
-+
-+ /*
-+ * The request has been validated.
-+ * Firstly, find an available session and then set up the initial state
-+ * of the session and update the configuration of performance counters
-+ * in the internal state of kbase_ipa_control.
-+ */
-+ for (session_idx = 0; session_idx < KBASE_IPA_CONTROL_MAX_SESSIONS;
-+ session_idx++) {
-+ session = &ipa_ctrl->sessions[session_idx];
-+ if (!session->active)
-+ break;
-+ }
-+
-+ if (!session) {
-+ dev_err(kbdev->dev, "%s: wrong or corrupt session state",
-+ __func__);
-+ ret = -EBUSY;
-+ goto exit;
-+ }
-+
-+ for (i = 0; i < num_counters; i++) {
-+ struct kbase_ipa_control_prfcnt_config *prfcnt_config;
-+ size_t j;
-+ u8 type = perf_counters[i].type;
-+ u8 idx = perf_counters[i].idx;
-+
-+ for (j = 0; j < KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS; j++) {
-+ prfcnt_config = &ipa_ctrl->blocks[type].select[j];
-+
-+ if (already_configured[i]) {
-+ if ((prfcnt_config->refcount > 0) &&
-+ (prfcnt_config->idx == idx)) {
-+ break;
-+ }
-+ } else {
-+ if (prfcnt_config->refcount == 0)
-+ break;
-+ }
-+ }
-+
-+ if (WARN_ON((prfcnt_config->refcount > 0 &&
-+ prfcnt_config->idx != idx) ||
-+ (j == KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS))) {
-+ dev_err(kbdev->dev,
-+ "%s: invalid internal state: counter already configured or no counter available to configure",
-+ __func__);
-+ ret = -EBUSY;
-+ goto exit;
-+ }
-+
-+ if (prfcnt_config->refcount == 0) {
-+ prfcnt_config->idx = idx;
-+ ipa_ctrl->blocks[type].num_available_counters--;
-+ }
-+
-+ session->prfcnts[i].accumulated_diff = 0;
-+ session->prfcnts[i].type = type;
-+ session->prfcnts[i].select_idx = j;
-+ session->prfcnts[i].scaling_factor =
-+ perf_counters[i].scaling_factor;
-+ session->prfcnts[i].gpu_norm = perf_counters[i].gpu_norm;
-+
-+ /* Reports to this client for GPU time spent in protected mode
-+ * should begin from the point of registration.
-+ */
-+ session->last_query_time = ktime_get_ns();
-+
-+ /* Initially, no time has been spent in protected mode */
-+ session->protm_time = 0;
-+
-+ prfcnt_config->refcount++;
-+ }
-+
-+ /*
-+ * Apply new configuration, if necessary.
-+ * As a temporary solution, make sure that the GPU is on
-+ * before applying the new configuration.
-+ */
-+ if (new_config) {
-+ u64 select_config[KBASE_IPA_CORE_TYPE_NUM];
-+
-+ build_select_config(ipa_ctrl, select_config);
-+ ret = apply_select_config(kbdev, select_config);
-+ if (ret)
-+ dev_err(kbdev->dev,
-+ "%s: failed to apply SELECT configuration",
-+ __func__);
-+ }
-+
-+ if (!ret) {
-+ /* Accumulator registers don't contain any sample if the timer
-+ * has not been enabled first. Take a sample manually before
-+ * enabling the timer.
-+ */
-+ if (ipa_ctrl->num_active_sessions == 0) {
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(COMMAND),
-+ COMMAND_SAMPLE);
-+ ret = wait_status(kbdev, STATUS_COMMAND_ACTIVE);
-+ if (!ret) {
-+ kbase_reg_write(
-+ kbdev, IPA_CONTROL_REG(TIMER),
-+ timer_value(ipa_ctrl->cur_gpu_rate));
-+ } else {
-+ dev_err(kbdev->dev,
-+ "%s: failed to sample new counters",
-+ __func__);
-+ }
-+ }
-+ }
-+
-+ if (!ret) {
-+ session->num_prfcnts = num_counters;
-+ session->active = true;
-+ ipa_ctrl->num_active_sessions++;
-+ *client = session;
-+
-+ /*
-+ * Read current raw value to initialize the session.
-+ * This is necessary to put the first query in condition
-+ * to generate a correct value by calculating the difference
-+ * from the beginning of the session.
-+ */
-+ for (i = 0; i < session->num_prfcnts; i++) {
-+ struct kbase_ipa_control_prfcnt *prfcnt =
-+ &session->prfcnts[i];
-+ u64 raw_value = read_value_cnt(kbdev, (u8)prfcnt->type,
-+ prfcnt->select_idx);
-+ prfcnt->latest_raw_value = raw_value;
-+ }
-+ }
-+
-+exit:
-+ spin_unlock_irqrestore(&ipa_ctrl->lock, flags);
-+ kbase_pm_context_idle(kbdev);
-+ return ret;
-+}
-+KBASE_EXPORT_TEST_API(kbase_ipa_control_register);
-+
-+int kbase_ipa_control_unregister(struct kbase_device *kbdev, const void *client)
-+{
-+ struct kbase_ipa_control *ipa_ctrl;
-+ struct kbase_ipa_control_session *session;
-+ int ret = 0;
-+ size_t i;
-+ unsigned long flags;
-+ bool new_config = false, valid_session = false;
-+
-+ if (WARN_ON(kbdev == NULL) || WARN_ON(client == NULL)) {
-+ dev_err(kbdev->dev, "%s: wrong input arguments", __func__);
-+ return -EINVAL;
-+ }
-+
-+ kbase_pm_context_active(kbdev);
-+
-+ ipa_ctrl = &kbdev->csf.ipa_control;
-+ session = (struct kbase_ipa_control_session *)client;
-+
-+ spin_lock_irqsave(&ipa_ctrl->lock, flags);
-+
-+ for (i = 0; i < KBASE_IPA_CONTROL_MAX_SESSIONS; i++) {
-+ if (session == &ipa_ctrl->sessions[i]) {
-+ valid_session = true;
-+ break;
-+ }
-+ }
-+
-+ if (!valid_session) {
-+ dev_err(kbdev->dev, "%s: invalid session handle", __func__);
-+ ret = -EINVAL;
-+ goto exit;
-+ }
-+
-+ if (ipa_ctrl->num_active_sessions == 0) {
-+ dev_err(kbdev->dev, "%s: no active sessions found", __func__);
-+ ret = -EINVAL;
-+ goto exit;
-+ }
-+
-+ if (!session->active) {
-+ dev_err(kbdev->dev, "%s: session is already inactive",
-+ __func__);
-+ ret = -EINVAL;
-+ goto exit;
-+ }
-+
-+ for (i = 0; i < session->num_prfcnts; i++) {
-+ struct kbase_ipa_control_prfcnt_config *prfcnt_config;
-+ u8 type = session->prfcnts[i].type;
-+ u8 idx = session->prfcnts[i].select_idx;
-+
-+ prfcnt_config = &ipa_ctrl->blocks[type].select[idx];
-+
-+ if (!WARN_ON(prfcnt_config->refcount == 0)) {
-+ prfcnt_config->refcount--;
-+ if (prfcnt_config->refcount == 0) {
-+ new_config = true;
-+ ipa_ctrl->blocks[type].num_available_counters++;
-+ }
-+ }
-+ }
-+
-+ if (new_config) {
-+ u64 select_config[KBASE_IPA_CORE_TYPE_NUM];
-+
-+ build_select_config(ipa_ctrl, select_config);
-+ ret = apply_select_config(kbdev, select_config);
-+ if (ret)
-+ dev_err(kbdev->dev,
-+ "%s: failed to apply SELECT configuration",
-+ __func__);
-+ }
-+
-+ session->num_prfcnts = 0;
-+ session->active = false;
-+ ipa_ctrl->num_active_sessions--;
-+
-+exit:
-+ spin_unlock_irqrestore(&ipa_ctrl->lock, flags);
-+ kbase_pm_context_idle(kbdev);
-+ return ret;
-+}
-+KBASE_EXPORT_TEST_API(kbase_ipa_control_unregister);
-+
-+int kbase_ipa_control_query(struct kbase_device *kbdev, const void *client,
-+ u64 *values, size_t num_values, u64 *protected_time)
-+{
-+ struct kbase_ipa_control *ipa_ctrl;
-+ struct kbase_ipa_control_session *session;
-+ size_t i;
-+ unsigned long flags;
-+ bool gpu_ready;
-+
-+ if (WARN_ON(kbdev == NULL) || WARN_ON(client == NULL) ||
-+ WARN_ON(values == NULL)) {
-+ dev_err(kbdev->dev, "%s: wrong input arguments", __func__);
-+ return -EINVAL;
-+ }
-+
-+ ipa_ctrl = &kbdev->csf.ipa_control;
-+ session = (struct kbase_ipa_control_session *)client;
-+
-+ if (WARN_ON(num_values < session->num_prfcnts)) {
-+ dev_err(kbdev->dev,
-+ "%s: not enough space (%zu) to return all counter values (%zu)",
-+ __func__, num_values, session->num_prfcnts);
-+ return -EINVAL;
-+ }
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ gpu_ready = kbdev->pm.backend.gpu_ready;
-+
-+ for (i = 0; i < session->num_prfcnts; i++) {
-+ struct kbase_ipa_control_prfcnt *prfcnt = &session->prfcnts[i];
-+
-+ calc_prfcnt_delta(kbdev, prfcnt, gpu_ready);
-+ /* Return all the accumulated difference */
-+ values[i] = prfcnt->accumulated_diff;
-+ prfcnt->accumulated_diff = 0;
-+ }
-+
-+ if (protected_time) {
-+ u64 time_now = ktime_get_ns();
-+
-+ /* This is the amount of protected-mode time spent prior to
-+ * the current protm period.
-+ */
-+ *protected_time = session->protm_time;
-+
-+ if (kbdev->protected_mode) {
-+ *protected_time +=
-+ time_now - MAX(session->last_query_time,
-+ ipa_ctrl->protm_start);
-+ }
-+ session->last_query_time = time_now;
-+ session->protm_time = 0;
-+ }
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ for (i = session->num_prfcnts; i < num_values; i++)
-+ values[i] = 0;
-+
-+ return 0;
-+}
-+KBASE_EXPORT_TEST_API(kbase_ipa_control_query);
-+
-+void kbase_ipa_control_handle_gpu_power_off(struct kbase_device *kbdev)
-+{
-+ struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
-+ size_t session_idx;
-+ int ret;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ /* GPU should still be ready for use when this function gets called */
-+ WARN_ON(!kbdev->pm.backend.gpu_ready);
-+
-+ /* Interrupts are already disabled and interrupt state is also saved */
-+ spin_lock(&ipa_ctrl->lock);
-+
-+ /* First disable the automatic sampling through TIMER */
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(TIMER), 0);
-+ ret = wait_status(kbdev, STATUS_TIMER_ENABLED);
-+ if (ret) {
-+ dev_err(kbdev->dev,
-+ "Wait for disabling of IPA control timer failed: %d",
-+ ret);
-+ }
-+
-+ /* Now issue the manual SAMPLE command */
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(COMMAND), COMMAND_SAMPLE);
-+ ret = wait_status(kbdev, STATUS_COMMAND_ACTIVE);
-+ if (ret) {
-+ dev_err(kbdev->dev,
-+ "Wait for the completion of manual sample failed: %d",
-+ ret);
-+ }
-+
-+ for (session_idx = 0; session_idx < ipa_ctrl->num_active_sessions;
-+ session_idx++) {
-+ struct kbase_ipa_control_session *session =
-+ &ipa_ctrl->sessions[session_idx];
-+ size_t i;
-+
-+ for (i = 0; i < session->num_prfcnts; i++) {
-+ struct kbase_ipa_control_prfcnt *prfcnt =
-+ &session->prfcnts[i];
-+
-+ calc_prfcnt_delta(kbdev, prfcnt, true);
-+ }
-+ }
-+
-+ spin_unlock(&ipa_ctrl->lock);
-+}
-+
-+void kbase_ipa_control_handle_gpu_power_on(struct kbase_device *kbdev)
-+{
-+ struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
-+ int ret;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ /* GPU should have become ready for use when this function gets called */
-+ WARN_ON(!kbdev->pm.backend.gpu_ready);
-+
-+ /* Interrupts are already disabled and interrupt state is also saved */
-+ spin_lock(&ipa_ctrl->lock);
-+
-+ /* Re-issue the APPLY command, this is actually needed only for CSHW */
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(COMMAND), COMMAND_APPLY);
-+ ret = wait_status(kbdev, STATUS_COMMAND_ACTIVE);
-+ if (ret) {
-+ dev_err(kbdev->dev,
-+ "Wait for the completion of apply command failed: %d",
-+ ret);
-+ }
-+
-+ /* Re-enable the timer for periodic sampling */
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(TIMER),
-+ timer_value(ipa_ctrl->cur_gpu_rate));
-+
-+ spin_unlock(&ipa_ctrl->lock);
-+}
-+
-+void kbase_ipa_control_handle_gpu_reset_pre(struct kbase_device *kbdev)
-+{
-+ /* A soft reset is treated as a power down */
-+ kbase_ipa_control_handle_gpu_power_off(kbdev);
-+}
-+KBASE_EXPORT_TEST_API(kbase_ipa_control_handle_gpu_reset_pre);
-+
-+void kbase_ipa_control_handle_gpu_reset_post(struct kbase_device *kbdev)
-+{
-+ struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
-+ int ret;
-+ u32 status;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ /* GPU should have become ready for use when this function gets called */
-+ WARN_ON(!kbdev->pm.backend.gpu_ready);
-+
-+ /* Interrupts are already disabled and interrupt state is also saved */
-+ spin_lock(&ipa_ctrl->lock);
-+
-+ /* Check the status reset bit is set before acknowledging it */
-+ status = kbase_reg_read(kbdev, IPA_CONTROL_REG(STATUS));
-+ if (status & STATUS_RESET) {
-+ /* Acknowledge the reset command */
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(COMMAND), COMMAND_RESET_ACK);
-+ ret = wait_status(kbdev, STATUS_RESET);
-+ if (ret) {
-+ dev_err(kbdev->dev,
-+ "Wait for the reset ack command failed: %d",
-+ ret);
-+ }
-+ }
-+
-+ spin_unlock(&ipa_ctrl->lock);
-+
-+ kbase_ipa_control_handle_gpu_power_on(kbdev);
-+}
-+KBASE_EXPORT_TEST_API(kbase_ipa_control_handle_gpu_reset_post);
-+
-+#if MALI_UNIT_TEST
-+void kbase_ipa_control_rate_change_notify_test(struct kbase_device *kbdev,
-+ u32 clk_index, u32 clk_rate_hz)
-+{
-+ struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
-+ struct kbase_ipa_control_listener_data *listener_data =
-+ ipa_ctrl->rtm_listener_data;
-+
-+ kbase_ipa_control_rate_change_notify(&listener_data->listener,
-+ clk_index, clk_rate_hz);
-+}
-+KBASE_EXPORT_TEST_API(kbase_ipa_control_rate_change_notify_test);
-+#endif
-+
-+void kbase_ipa_control_protm_entered(struct kbase_device *kbdev)
-+{
-+ struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+ ipa_ctrl->protm_start = ktime_get_ns();
-+}
-+
-+void kbase_ipa_control_protm_exited(struct kbase_device *kbdev)
-+{
-+ struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
-+ size_t i;
-+ u64 time_now = ktime_get_ns();
-+ u32 status;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ for (i = 0; i < ipa_ctrl->num_active_sessions; i++) {
-+ struct kbase_ipa_control_session *session =
-+ &ipa_ctrl->sessions[i];
-+ u64 protm_time = time_now - MAX(session->last_query_time,
-+ ipa_ctrl->protm_start);
-+
-+ session->protm_time += protm_time;
-+ }
-+
-+ /* Acknowledge the protected_mode bit in the IPA_CONTROL STATUS
-+ * register
-+ */
-+ status = kbase_reg_read(kbdev, IPA_CONTROL_REG(STATUS));
-+ if (status & STATUS_PROTECTED_MODE) {
-+ int ret;
-+
-+ /* Acknowledge the protm command */
-+ kbase_reg_write(kbdev, IPA_CONTROL_REG(COMMAND),
-+ COMMAND_PROTECTED_ACK);
-+ ret = wait_status(kbdev, STATUS_PROTECTED_MODE);
-+ if (ret) {
-+ dev_err(kbdev->dev,
-+ "Wait for the protm ack command failed: %d",
-+ ret);
-+ }
-+ }
-+}
-+
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/mali_kbase_csf_ipa_control.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/mali_kbase_csf_ipa_control.h
-new file mode 100644
-index 0000000..348a52f
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/ipa_control/mali_kbase_csf_ipa_control.h
-@@ -0,0 +1,244 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_IPA_CONTROL_H_
-+#define _KBASE_CSF_IPA_CONTROL_H_
-+
-+#include <mali_kbase.h>
-+
-+/**
-+ * Maximum index accepted to configure an IPA Control performance counter.
-+ */
-+#define KBASE_IPA_CONTROL_CNT_MAX_IDX ((u8)64 * 3)
-+
-+/**
-+ * struct kbase_ipa_control_perf_counter - Performance counter description
-+ *
-+ * @scaling_factor: Scaling factor by which the counter's value shall be
-+ * multiplied. A scaling factor of 1 corresponds to units
-+ * of 1 second if values are normalised by GPU frequency.
-+ * @gpu_norm: Indicating whether counter values shall be normalized by
-+ * GPU frequency. If true, returned values represent
-+ * an interval of time expressed in seconds (when the scaling
-+ * factor is set to 1).
-+ * @type: Type of counter block for performance counter.
-+ * @idx: Index of the performance counter inside the block.
-+ * It may be dependent on GPU architecture.
-+ * It cannot be greater than KBASE_IPA_CONTROL_CNT_MAX_IDX.
-+ *
-+ * This structure is used by clients of the IPA Control component to describe
-+ * a performance counter that they intend to read. The counter is identified
-+ * by block and index. In addition to that, the client also specifies how
-+ * values shall be represented. Raw values are a number of GPU cycles;
-+ * if normalized, they are divided by GPU frequency and become an interval
-+ * of time expressed in seconds, since the GPU frequency is given in Hz.
-+ * The client may specify a scaling factor to multiply counter values before
-+ * they are divided by frequency, in case the unit of time of 1 second is
-+ * too low in resolution. For instance: a scaling factor of 1000 implies
-+ * that the returned value is a time expressed in milliseconds; a scaling
-+ * factor of 1000 * 1000 implies that the returned value is a time expressed
-+ * in microseconds.
-+ */
-+struct kbase_ipa_control_perf_counter {
-+ u64 scaling_factor;
-+ bool gpu_norm;
-+ enum kbase_ipa_core_type type;
-+ u8 idx;
-+};
-+
-+/**
-+ * kbase_ipa_control_init - Initialize the IPA Control component
-+ *
-+ * @kbdev: Pointer to Kbase device.
-+ */
-+void kbase_ipa_control_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_ipa_control_term - Terminate the IPA Control component
-+ *
-+ * @kbdev: Pointer to Kbase device.
-+ */
-+void kbase_ipa_control_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_ipa_control_register - Register a client to the IPA Control component
-+ *
-+ * @kbdev: Pointer to Kbase device.
-+ * @perf_counters: Array of performance counters the client intends to read.
-+ * For each counter the client specifies block, index,
-+ * scaling factor and whether it must be normalized by GPU
-+ * frequency.
-+ * @num_counters: Number of performance counters. It cannot exceed the total
-+ * number of counters that exist on the IPA Control interface.
-+ * @client: Handle to an opaque structure set by IPA Control if
-+ * the registration is successful. This handle identifies
-+ * a client's session and shall be provided in its future
-+ * queries.
-+ *
-+ * A client needs to subscribe to the IPA Control component by declaring which
-+ * performance counters it intends to read, and specifying a scaling factor
-+ * and whether normalization is requested for each performance counter.
-+ * The function shall configure the IPA Control interface accordingly and start
-+ * a session for the client that made the request. A unique handle is returned
-+ * if registration is successful in order to identify the client's session
-+ * and be used for future queries.
-+ *
-+ * Return: 0 on success, negative -errno on error
-+ */
-+int kbase_ipa_control_register(
-+ struct kbase_device *kbdev,
-+ const struct kbase_ipa_control_perf_counter *perf_counters,
-+ size_t num_counters, void **client);
-+
-+/**
-+ * kbase_ipa_control_unregister - Unregister a client from IPA Control
-+ *
-+ * @kbdev: Pointer to kbase device.
-+ * @client: Handle to an opaque structure that identifies the client session
-+ * to terminate, as returned by kbase_ipa_control_register.
-+ *
-+ * Return: 0 on success, negative -errno on error
-+ */
-+int kbase_ipa_control_unregister(struct kbase_device *kbdev,
-+ const void *client);
-+
-+/**
-+ * kbase_ipa_control_query - Query performance counters
-+ *
-+ * @kbdev: Pointer to kbase device.
-+ * @client: Handle to an opaque structure that identifies the client
-+ * session, as returned by kbase_ipa_control_register.
-+ * @values: Array of values queried from performance counters, whose
-+ * length depends on the number of counters requested at
-+ * the time of registration. Values are scaled and normalized
-+ * and represent the difference since the last query.
-+ * @num_values: Number of entries in the array of values that has been
-+ * passed by the caller. It must be at least equal to the
-+ * number of performance counters the client registered itself
-+ * to read.
-+ * @protected_time: Time spent in protected mode since last query,
-+ * expressed in nanoseconds. This pointer may be NULL if the
-+ * client doesn't want to know about this.
-+ *
-+ * A client that has already opened a session by registering itself to read
-+ * some performance counters may use this function to query the values of
-+ * those counters. The values returned are normalized by GPU frequency if
-+ * requested and then multiplied by the scaling factor provided at the time
-+ * of registration. Values always represent a difference since the last query.
-+ *
-+ * Performance counters are not updated while the GPU operates in protected
-+ * mode. For this reason, returned values may be unreliable if the GPU has
-+ * been in protected mode since the last query. The function returns success
-+ * in that case, but it also gives a measure of how much time has been spent
-+ * in protected mode.
-+ *
-+ * Return: 0 on success, negative -errno on error
-+ */
-+int kbase_ipa_control_query(struct kbase_device *kbdev, const void *client,
-+ u64 *values, size_t num_values,
-+ u64 *protected_time);
-+
-+/**
-+ * kbase_ipa_control_handle_gpu_power_on - Handle the GPU power on event
-+ *
-+ * @kbdev: Pointer to kbase device.
-+ *
-+ * This function is called after GPU has been powered and is ready for use.
-+ * After the GPU power on, IPA Control component needs to ensure that the
-+ * counters start incrementing again.
-+ */
-+void kbase_ipa_control_handle_gpu_power_on(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_ipa_control_handle_gpu_power_off - Handle the GPU power off event
-+ *
-+ * @kbdev: Pointer to kbase device.
-+ *
-+ * This function is called just before the GPU is powered off when it is still
-+ * ready for use.
-+ * IPA Control component needs to be aware of the GPU power off so that it can
-+ * handle the query from Clients appropriately and return meaningful values
-+ * to them.
-+ */
-+void kbase_ipa_control_handle_gpu_power_off(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_ipa_control_handle_gpu_reset_pre - Handle the pre GPU reset event
-+ *
-+ * @kbdev: Pointer to kbase device.
-+ *
-+ * This function is called when the GPU is about to be reset.
-+ */
-+void kbase_ipa_control_handle_gpu_reset_pre(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_ipa_control_handle_gpu_reset_post - Handle the post GPU reset event
-+ *
-+ * @kbdev: Pointer to kbase device.
-+ *
-+ * This function is called after the GPU has been reset.
-+ */
-+void kbase_ipa_control_handle_gpu_reset_post(struct kbase_device *kbdev);
-+
-+#if MALI_UNIT_TEST
-+/**
-+ * kbase_ipa_control_rate_change_notify_test - Notify GPU rate change
-+ * (only for testing)
-+ *
-+ * @kbdev: Pointer to kbase device.
-+ * @clk_index: Index of the clock for which the change has occurred.
-+ * @clk_rate_hz: Clock frequency(Hz).
-+ *
-+ * Notify the IPA Control component about a GPU rate change.
-+ */
-+void kbase_ipa_control_rate_change_notify_test(struct kbase_device *kbdev,
-+ u32 clk_index, u32 clk_rate_hz);
-+#endif /* MALI_UNIT_TEST */
-+
-+/**
-+ * kbase_ipa_control_protm_entered - Tell IPA_CONTROL that protected mode
-+ * has been entered.
-+ *
-+ * @kbdev: Pointer to kbase device.
-+ *
-+ * This function provides a means through which IPA_CONTROL can be informed
-+ * that the GPU has entered protected mode. Since the GPU cannot access
-+ * performance counters while in this mode, this information is useful as
-+ * it implies (a) the values of these registers cannot change, so theres no
-+ * point trying to read them, and (b) IPA_CONTROL has a means through which
-+ * to record the duration of time the GPU is in protected mode, which can
-+ * then be forwarded on to clients, who may wish, for example, to assume
-+ * that the GPU was busy 100% of the time while in this mode.
-+ */
-+void kbase_ipa_control_protm_entered(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_ipa_control_protm_exited - Tell IPA_CONTROL that protected mode
-+ * has been exited.
-+ *
-+ * @kbdev: Pointer to kbase device
-+ *
-+ * This function provides a means through which IPA_CONTROL can be informed
-+ * that the GPU has exited from protected mode.
-+ */
-+void kbase_ipa_control_protm_exited(struct kbase_device *kbdev);
-+
-+#endif /* _KBASE_CSF_IPA_CONTROL_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf.c
-new file mode 100644
-index 0000000..d49e343
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf.c
-@@ -0,0 +1,3069 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <gpu/mali_kbase_gpu_fault.h>
-+#include <mali_kbase_reset_gpu.h>
-+#include "mali_kbase_csf.h"
-+#include "backend/gpu/mali_kbase_pm_internal.h"
-+#include <linux/export.h>
-+#include <linux/priority_control_manager.h>
-+#include <linux/shmem_fs.h>
-+#include <uapi/gpu/arm/midgard/csf/mali_gpu_csf_registers.h>
-+#include "mali_kbase_csf_tiler_heap.h"
-+#include <mmu/mali_kbase_mmu.h>
-+#include "mali_kbase_csf_timeout.h"
-+#include <csf/ipa_control/mali_kbase_csf_ipa_control.h>
-+
-+#define CS_REQ_EXCEPTION_MASK (CS_REQ_FAULT_MASK | CS_REQ_FATAL_MASK)
-+#define CS_ACK_EXCEPTION_MASK (CS_ACK_FAULT_MASK | CS_ACK_FATAL_MASK)
-+#define POWER_DOWN_LATEST_FLUSH_VALUE ((u32)1)
-+
-+/**
-+ * struct kbase_csf_event - CSF event callback.
-+ *
-+ * This structure belongs to the list of events which is part of a Kbase
-+ * context, and describes a callback function with a custom parameter to pass
-+ * to it when a CSF event is signalled.
-+ *
-+ * @link: Link to the rest of the list.
-+ * @kctx: Pointer to the Kbase context this event belongs to.
-+ * @callback: Callback function to call when a CSF event is signalled.
-+ * @param: Parameter to pass to the callback function.
-+ */
-+struct kbase_csf_event {
-+ struct list_head link;
-+ struct kbase_context *kctx;
-+ kbase_csf_event_callback *callback;
-+ void *param;
-+};
-+
-+const u8 kbasep_csf_queue_group_priority_to_relative[BASE_QUEUE_GROUP_PRIORITY_COUNT] = {
-+ KBASE_QUEUE_GROUP_PRIORITY_HIGH,
-+ KBASE_QUEUE_GROUP_PRIORITY_MEDIUM,
-+ KBASE_QUEUE_GROUP_PRIORITY_LOW,
-+ KBASE_QUEUE_GROUP_PRIORITY_REALTIME
-+};
-+const u8 kbasep_csf_relative_to_queue_group_priority[KBASE_QUEUE_GROUP_PRIORITY_COUNT] = {
-+ BASE_QUEUE_GROUP_PRIORITY_REALTIME,
-+ BASE_QUEUE_GROUP_PRIORITY_HIGH,
-+ BASE_QUEUE_GROUP_PRIORITY_MEDIUM,
-+ BASE_QUEUE_GROUP_PRIORITY_LOW
-+};
-+
-+static void put_user_pages_mmap_handle(struct kbase_context *kctx,
-+ struct kbase_queue *queue)
-+{
-+ unsigned long cookie_nr;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ if (queue->handle == BASEP_MEM_INVALID_HANDLE)
-+ return;
-+
-+ cookie_nr =
-+ PFN_DOWN(queue->handle - BASEP_MEM_CSF_USER_IO_PAGES_HANDLE);
-+
-+ if (!WARN_ON(kctx->csf.user_pages_info[cookie_nr] != queue)) {
-+ /* free up cookie */
-+ kctx->csf.user_pages_info[cookie_nr] = NULL;
-+ bitmap_set(kctx->csf.cookies, cookie_nr, 1);
-+ }
-+
-+ queue->handle = BASEP_MEM_INVALID_HANDLE;
-+}
-+
-+/* Reserve a cookie, to be returned as a handle to userspace for creating
-+ * the CPU mapping of the pair of input/output pages and Hw doorbell page.
-+ * Will return 0 in case of success otherwise negative on failure.
-+ */
-+static int get_user_pages_mmap_handle(struct kbase_context *kctx,
-+ struct kbase_queue *queue)
-+{
-+ unsigned long cookie, cookie_nr;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ if (bitmap_empty(kctx->csf.cookies,
-+ KBASE_CSF_NUM_USER_IO_PAGES_HANDLE)) {
-+ dev_err(kctx->kbdev->dev,
-+ "No csf cookies available for allocation!");
-+ return -ENOMEM;
-+ }
-+
-+ /* allocate a cookie */
-+ cookie_nr = find_first_bit(kctx->csf.cookies,
-+ KBASE_CSF_NUM_USER_IO_PAGES_HANDLE);
-+ if (kctx->csf.user_pages_info[cookie_nr]) {
-+ dev_err(kctx->kbdev->dev,
-+ "Inconsistent state of csf cookies!");
-+ return -EINVAL;
-+ }
-+ kctx->csf.user_pages_info[cookie_nr] = queue;
-+ bitmap_clear(kctx->csf.cookies, cookie_nr, 1);
-+
-+ /* relocate to correct base */
-+ cookie = cookie_nr + PFN_DOWN(BASEP_MEM_CSF_USER_IO_PAGES_HANDLE);
-+ cookie <<= PAGE_SHIFT;
-+
-+ queue->handle = (u64)cookie;
-+
-+ return 0;
-+}
-+
-+static void gpu_munmap_user_io_pages(struct kbase_context *kctx,
-+ struct kbase_va_region *reg)
-+{
-+ size_t num_pages = 2;
-+
-+ kbase_mmu_teardown_pages(kctx->kbdev, &kctx->kbdev->csf.mcu_mmu,
-+ reg->start_pfn, num_pages, MCU_AS_NR);
-+
-+ WARN_ON(reg->flags & KBASE_REG_FREE);
-+
-+ mutex_lock(&kctx->kbdev->csf.reg_lock);
-+ kbase_remove_va_region(reg);
-+ mutex_unlock(&kctx->kbdev->csf.reg_lock);
-+}
-+
-+static void init_user_io_pages(struct kbase_queue *queue)
-+{
-+ u32 *input_addr = (u32 *)(queue->user_io_addr);
-+ u32 *output_addr = (u32 *)(queue->user_io_addr + PAGE_SIZE);
-+
-+ input_addr[CS_INSERT_LO/4] = 0;
-+ input_addr[CS_INSERT_HI/4] = 0;
-+
-+ input_addr[CS_EXTRACT_INIT_LO/4] = 0;
-+ input_addr[CS_EXTRACT_INIT_HI/4] = 0;
-+
-+ output_addr[CS_EXTRACT_LO/4] = 0;
-+ output_addr[CS_EXTRACT_HI/4] = 0;
-+
-+ output_addr[CS_ACTIVE/4] = 0;
-+}
-+
-+/* Map the input/output pages in the shared interface segment of MCU firmware
-+ * address space.
-+ */
-+static int gpu_mmap_user_io_pages(struct kbase_device *kbdev,
-+ struct tagged_addr *phys, struct kbase_va_region *reg)
-+{
-+ unsigned long mem_flags = KBASE_REG_GPU_RD;
-+ const size_t num_pages = 2;
-+ int ret;
-+
-+#if ((KERNEL_VERSION(4, 4, 147) >= LINUX_VERSION_CODE) || \
-+ ((KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE) && \
-+ (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE)))
-+ mem_flags |=
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE);
-+#else
-+ if (kbdev->system_coherency == COHERENCY_NONE) {
-+ mem_flags |=
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE);
-+ } else {
-+ mem_flags |= KBASE_REG_SHARE_BOTH |
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_SHARED);
-+ }
-+#endif
-+
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ ret = kbase_add_va_region_rbtree(kbdev, reg, 0, num_pages, 1);
-+ reg->flags &= ~KBASE_REG_FREE;
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ if (ret)
-+ return ret;
-+
-+ /* Map input page */
-+ ret = kbase_mmu_insert_pages(kbdev, &kbdev->csf.mcu_mmu,
-+ reg->start_pfn, &phys[0],
-+ 1, mem_flags, MCU_AS_NR,
-+ KBASE_MEM_GROUP_CSF_IO);
-+ if (ret)
-+ goto bad_insert;
-+
-+ /* Map output page, it needs rw access */
-+ mem_flags |= KBASE_REG_GPU_WR;
-+ ret = kbase_mmu_insert_pages(kbdev, &kbdev->csf.mcu_mmu,
-+ reg->start_pfn + 1, &phys[1],
-+ 1, mem_flags, MCU_AS_NR,
-+ KBASE_MEM_GROUP_CSF_IO);
-+ if (ret)
-+ goto bad_insert_output_page;
-+
-+ return 0;
-+
-+bad_insert_output_page:
-+ kbase_mmu_teardown_pages(kbdev, &kbdev->csf.mcu_mmu,
-+ reg->start_pfn, 1, MCU_AS_NR);
-+bad_insert:
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ kbase_remove_va_region(reg);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ return ret;
-+}
-+
-+static void kernel_unmap_user_io_pages(struct kbase_context *kctx,
-+ struct kbase_queue *queue)
-+{
-+ const size_t num_pages = 2;
-+
-+ kbase_gpu_vm_lock(kctx);
-+
-+ vunmap(queue->user_io_addr);
-+
-+ WARN_ON(num_pages > atomic_read(&kctx->permanent_mapped_pages));
-+ atomic_sub(num_pages, &kctx->permanent_mapped_pages);
-+
-+ kbase_gpu_vm_unlock(kctx);
-+}
-+
-+static int kernel_map_user_io_pages(struct kbase_context *kctx,
-+ struct kbase_queue *queue)
-+{
-+ struct page *page_list[2];
-+ pgprot_t cpu_map_prot;
-+ int ret = 0;
-+ size_t i;
-+
-+ kbase_gpu_vm_lock(kctx);
-+
-+ if (ARRAY_SIZE(page_list) > (KBASE_PERMANENTLY_MAPPED_MEM_LIMIT_PAGES -
-+ atomic_read(&kctx->permanent_mapped_pages))) {
-+ ret = -ENOMEM;
-+ goto unlock;
-+ }
-+
-+ /* The pages are mapped to Userspace also, so use the same mapping
-+ * attributes as used inside the CPU page fault handler.
-+ */
-+#if ((KERNEL_VERSION(4, 4, 147) >= LINUX_VERSION_CODE) || \
-+ ((KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE) && \
-+ (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE)))
-+ cpu_map_prot = pgprot_device(PAGE_KERNEL);
-+#else
-+ if (kctx->kbdev->system_coherency == COHERENCY_NONE)
-+ cpu_map_prot = pgprot_writecombine(PAGE_KERNEL);
-+ else
-+ cpu_map_prot = PAGE_KERNEL;
-+#endif
-+
-+ for (i = 0; i < ARRAY_SIZE(page_list); i++)
-+ page_list[i] = as_page(queue->phys[i]);
-+
-+ queue->user_io_addr = vmap(page_list, ARRAY_SIZE(page_list), VM_MAP, cpu_map_prot);
-+
-+ if (!queue->user_io_addr)
-+ ret = -ENOMEM;
-+ else
-+ atomic_add(ARRAY_SIZE(page_list), &kctx->permanent_mapped_pages);
-+
-+unlock:
-+ kbase_gpu_vm_unlock(kctx);
-+ return ret;
-+}
-+
-+static void term_queue_group(struct kbase_queue_group *group);
-+static void get_queue(struct kbase_queue *queue);
-+static void release_queue(struct kbase_queue *queue);
-+
-+/**
-+ * kbase_csf_free_command_stream_user_pages() - Free the resources allocated
-+ * for a queue at the time of bind.
-+ *
-+ * @kctx: Address of the kbase context within which the queue was created.
-+ * @queue: Pointer to the queue to be unlinked.
-+ *
-+ * This function will free the pair of physical pages allocated for a GPU
-+ * command queue, and also release the hardware doorbell page, that were mapped
-+ * into the process address space to enable direct submission of commands to
-+ * the hardware. Also releases the reference taken on the queue when the mapping
-+ * was created.
-+ *
-+ * This function will be called only when the mapping is being removed and
-+ * so the resources for queue will not get freed up until the mapping is
-+ * removed even though userspace could have terminated the queue.
-+ * Kernel will ensure that the termination of Kbase context would only be
-+ * triggered after the mapping is removed.
-+ *
-+ * If an explicit or implicit unbind was missed by the userspace then the
-+ * mapping will persist. On process exit kernel itself will remove the mapping.
-+ */
-+static void kbase_csf_free_command_stream_user_pages(struct kbase_context *kctx,
-+ struct kbase_queue *queue)
-+{
-+ const size_t num_pages = 2;
-+
-+ gpu_munmap_user_io_pages(kctx, queue->reg);
-+ kernel_unmap_user_io_pages(kctx, queue);
-+
-+ kbase_mem_pool_free_pages(
-+ &kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_IO],
-+ num_pages, queue->phys, true, false);
-+
-+ kfree(queue->reg);
-+ queue->reg = NULL;
-+
-+ /* If the queue has already been terminated by userspace
-+ * then the ref count for queue object will drop to 0 here.
-+ */
-+ release_queue(queue);
-+}
-+
-+int kbase_csf_alloc_command_stream_user_pages(struct kbase_context *kctx,
-+ struct kbase_queue *queue)
-+{
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct kbase_va_region *reg;
-+ const size_t num_pages = 2;
-+ int ret;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ reg = kbase_alloc_free_region(&kctx->kbdev->csf.shared_reg_rbtree, 0,
-+ num_pages, KBASE_REG_ZONE_MCU_SHARED);
-+ if (!reg)
-+ return -ENOMEM;
-+
-+ ret = kbase_mem_pool_alloc_pages(
-+ &kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_IO],
-+ num_pages, queue->phys, false);
-+
-+ if (ret != num_pages)
-+ goto phys_alloc_failed;
-+
-+ ret = kernel_map_user_io_pages(kctx, queue);
-+ if (ret)
-+ goto kernel_map_failed;
-+
-+ init_user_io_pages(queue);
-+
-+ ret = gpu_mmap_user_io_pages(kctx->kbdev, queue->phys, reg);
-+ if (ret)
-+ goto gpu_mmap_failed;
-+
-+ queue->reg = reg;
-+
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ if (kbdev->csf.db_file_offsets >
-+ (U32_MAX - BASEP_QUEUE_NR_MMAP_USER_PAGES + 1))
-+ kbdev->csf.db_file_offsets = 0;
-+
-+ queue->db_file_offset = kbdev->csf.db_file_offsets;
-+ kbdev->csf.db_file_offsets += BASEP_QUEUE_NR_MMAP_USER_PAGES;
-+
-+ WARN(atomic_read(&queue->refcount) != 1, "Incorrect refcounting for queue object\n");
-+ /* This is the second reference taken on the queue object and
-+ * would be dropped only when the IO mapping is removed either
-+ * explicitly by userspace or implicitly by kernel on process exit.
-+ */
-+ get_queue(queue);
-+ queue->bind_state = KBASE_CSF_QUEUE_BOUND;
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ return 0;
-+
-+gpu_mmap_failed:
-+ kernel_unmap_user_io_pages(kctx, queue);
-+
-+kernel_map_failed:
-+ kbase_mem_pool_free_pages(
-+ &kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_IO],
-+ num_pages, queue->phys, false, false);
-+
-+phys_alloc_failed:
-+ kfree(reg);
-+
-+ return -ENOMEM;
-+}
-+
-+static struct kbase_queue_group *find_queue_group(struct kbase_context *kctx,
-+ u8 group_handle)
-+{
-+ uint index = group_handle;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ if (index < MAX_QUEUE_GROUP_NUM && kctx->csf.queue_groups[index]) {
-+ if (WARN_ON(kctx->csf.queue_groups[index]->handle != index))
-+ return NULL;
-+ return kctx->csf.queue_groups[index];
-+ }
-+
-+ return NULL;
-+}
-+
-+int kbase_csf_queue_group_handle_is_valid(struct kbase_context *kctx,
-+ u8 group_handle)
-+{
-+ struct kbase_queue_group *group;
-+
-+ mutex_lock(&kctx->csf.lock);
-+ group = find_queue_group(kctx, group_handle);
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ return group ? 0 : -EINVAL;
-+}
-+
-+static struct kbase_queue *find_queue(struct kbase_context *kctx, u64 base_addr)
-+{
-+ struct kbase_queue *queue;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ list_for_each_entry(queue, &kctx->csf.queue_list, link) {
-+ if (base_addr == queue->base_addr)
-+ return queue;
-+ }
-+
-+ return NULL;
-+}
-+
-+static void get_queue(struct kbase_queue *queue)
-+{
-+ WARN_ON(!atomic_inc_not_zero(&queue->refcount));
-+}
-+
-+static void release_queue(struct kbase_queue *queue)
-+{
-+ lockdep_assert_held(&queue->kctx->csf.lock);
-+
-+ WARN_ON(atomic_read(&queue->refcount) <= 0);
-+
-+ if (atomic_dec_and_test(&queue->refcount)) {
-+ /* The queue can't still be on the per context list. */
-+ WARN_ON(!list_empty(&queue->link));
-+ WARN_ON(queue->group);
-+ kfree(queue);
-+ }
-+}
-+
-+static void oom_event_worker(struct work_struct *data);
-+static void fatal_event_worker(struct work_struct *data);
-+
-+/* Between reg and reg_ex, one and only one must be null */
-+static int csf_queue_register_internal(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_register *reg,
-+ struct kbase_ioctl_cs_queue_register_ex *reg_ex)
-+{
-+ struct kbase_queue *queue;
-+ int ret = 0;
-+ struct kbase_va_region *region;
-+ u64 queue_addr;
-+ size_t queue_size;
-+
-+ /* Only one pointer expected, otherwise coding error */
-+ if ((reg == NULL && reg_ex == NULL) || (reg && reg_ex)) {
-+ dev_err(kctx->kbdev->dev,
-+ "Error, one and only one param-ptr expected!");
-+ return -EINVAL;
-+ }
-+
-+ /* struct kbase_ioctl_cs_queue_register_ex contains a full
-+ * struct kbase_ioctl_cs_queue_register at the start address. So
-+ * the pointer can be safely cast to pointing to a
-+ * kbase_ioctl_cs_queue_register object.
-+ */
-+ if (reg_ex)
-+ reg = (struct kbase_ioctl_cs_queue_register *)reg_ex;
-+
-+ /* Validate the queue priority */
-+ if (reg->priority > BASE_QUEUE_MAX_PRIORITY)
-+ return -EINVAL;
-+
-+ queue_addr = reg->buffer_gpu_addr;
-+ queue_size = reg->buffer_size >> PAGE_SHIFT;
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ /* Check if queue is already registered */
-+ if (find_queue(kctx, queue_addr) != NULL) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ /* Check if the queue address is valid */
-+ kbase_gpu_vm_lock(kctx);
-+ region = kbase_region_tracker_find_region_enclosing_address(kctx,
-+ queue_addr);
-+
-+ if (kbase_is_region_invalid_or_free(region)) {
-+ ret = -ENOENT;
-+ goto out_unlock_vm;
-+ }
-+
-+ if (queue_size > (region->nr_pages -
-+ ((queue_addr >> PAGE_SHIFT) - region->start_pfn))) {
-+ ret = -EINVAL;
-+ goto out_unlock_vm;
-+ }
-+
-+ /* Check address validity on cs_trace buffer etc. Don't care
-+ * if not enabled (i.e. when size is 0).
-+ */
-+ if (reg_ex && reg_ex->ex_buffer_size) {
-+ int buf_pages = (reg_ex->ex_buffer_size +
-+ (1 << PAGE_SHIFT) - 1) >> PAGE_SHIFT;
-+
-+ region = kbase_region_tracker_find_region_enclosing_address(
-+ kctx, reg_ex->ex_buffer_base);
-+ if (kbase_is_region_invalid_or_free(region)) {
-+ ret = -ENOENT;
-+ goto out_unlock_vm;
-+ }
-+
-+ if (buf_pages > (region->nr_pages -
-+ ((reg_ex->ex_buffer_base >> PAGE_SHIFT) -
-+ region->start_pfn))) {
-+ ret = -EINVAL;
-+ goto out_unlock_vm;
-+ }
-+
-+ region = kbase_region_tracker_find_region_enclosing_address(
-+ kctx, reg_ex->ex_offset_var_addr);
-+ if (kbase_is_region_invalid_or_free(region)) {
-+ ret = -ENOENT;
-+ goto out_unlock_vm;
-+ }
-+ }
-+
-+ queue = kzalloc(sizeof(struct kbase_queue), GFP_KERNEL);
-+
-+ if (!queue) {
-+ ret = -ENOMEM;
-+ goto out_unlock_vm;
-+ }
-+
-+ queue->kctx = kctx;
-+ queue->base_addr = queue_addr;
-+ queue->queue_reg = region;
-+ queue->size = (queue_size << PAGE_SHIFT);
-+ queue->csi_index = KBASEP_IF_NR_INVALID;
-+ queue->enabled = false;
-+
-+ queue->priority = reg->priority;
-+ atomic_set(&queue->refcount, 1);
-+
-+ queue->group = NULL;
-+ queue->bind_state = KBASE_CSF_QUEUE_UNBOUND;
-+ queue->handle = BASEP_MEM_INVALID_HANDLE;
-+ queue->doorbell_nr = KBASEP_USER_DB_NR_INVALID;
-+
-+ queue->status_wait = 0;
-+ queue->sync_ptr = 0;
-+ queue->sync_value = 0;
-+
-+ queue->sb_status = 0;
-+ queue->blocked_reason = CS_STATUS_BLOCKED_REASON_REASON_UNBLOCKED;
-+
-+ INIT_LIST_HEAD(&queue->link);
-+ INIT_LIST_HEAD(&queue->error.link);
-+ INIT_WORK(&queue->oom_event_work, oom_event_worker);
-+ INIT_WORK(&queue->fatal_event_work, fatal_event_worker);
-+ list_add(&queue->link, &kctx->csf.queue_list);
-+
-+ region->flags |= KBASE_REG_NO_USER_FREE;
-+
-+ /* Initialize the cs_trace configuration parameters, When buffer_size
-+ * is 0, trace is disabled. Here we only update the fields when
-+ * enabled, otherwise leave them as default zeros.
-+ */
-+ if (reg_ex && reg_ex->ex_buffer_size) {
-+ u32 cfg = CS_INSTR_CONFIG_EVENT_SIZE_SET(
-+ 0, reg_ex->ex_event_size);
-+ cfg = CS_INSTR_CONFIG_EVENT_STATE_SET(
-+ cfg, reg_ex->ex_event_state);
-+
-+ queue->trace_cfg = cfg;
-+ queue->trace_buffer_size = reg_ex->ex_buffer_size;
-+ queue->trace_buffer_base = reg_ex->ex_buffer_base;
-+ queue->trace_offset_ptr = reg_ex->ex_offset_var_addr;
-+ }
-+
-+out_unlock_vm:
-+ kbase_gpu_vm_unlock(kctx);
-+out:
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ return ret;
-+}
-+
-+int kbase_csf_queue_register(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_register *reg)
-+{
-+ return csf_queue_register_internal(kctx, reg, NULL);
-+}
-+
-+int kbase_csf_queue_register_ex(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_register_ex *reg)
-+{
-+ struct kbase_csf_global_iface const *const iface =
-+ &kctx->kbdev->csf.global_iface;
-+ u32 const glb_version = iface->version;
-+ u32 instr = iface->instr_features;
-+ u8 max_size = GLB_INSTR_FEATURES_EVENT_SIZE_MAX_GET(instr);
-+ u32 min_buf_size = (1u << reg->ex_event_size) *
-+ GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_GET(instr);
-+
-+ /* If cs_trace_command not supported, the call fails */
-+ if (glb_version < kbase_csf_interface_version(1, 1, 0))
-+ return -EINVAL;
-+
-+ /* Validate the cs_trace configuration parameters */
-+ if (reg->ex_buffer_size &&
-+ ((reg->ex_event_size > max_size) ||
-+ (reg->ex_buffer_size & (reg->ex_buffer_size - 1)) ||
-+ (reg->ex_buffer_size < min_buf_size)))
-+ return -EINVAL;
-+
-+ return csf_queue_register_internal(kctx, NULL, reg);
-+}
-+
-+static void unbind_queue(struct kbase_context *kctx,
-+ struct kbase_queue *queue);
-+
-+void kbase_csf_queue_terminate(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_terminate *term)
-+{
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct kbase_queue *queue;
-+ int err;
-+ bool reset_prevented = false;
-+
-+ err = kbase_reset_gpu_prevent_and_wait(kbdev);
-+ if (err)
-+ dev_warn(
-+ kbdev->dev,
-+ "Unsuccessful GPU reset detected when terminating queue (buffer_addr=0x%.16llx), attempting to terminate regardless",
-+ term->buffer_gpu_addr);
-+ else
-+ reset_prevented = true;
-+
-+ mutex_lock(&kctx->csf.lock);
-+ queue = find_queue(kctx, term->buffer_gpu_addr);
-+
-+ if (queue) {
-+ unsigned long flags;
-+
-+ /* As the GPU queue has been terminated by the
-+ * user space, undo the actions that were performed when the
-+ * queue was registered i.e. remove the queue from the per
-+ * context list & release the initial reference. The subsequent
-+ * lookups for the queue in find_queue() would fail.
-+ */
-+ list_del_init(&queue->link);
-+
-+ /* Stop the CSI to which queue was bound */
-+ unbind_queue(kctx, queue);
-+
-+ kbase_gpu_vm_lock(kctx);
-+ if (!WARN_ON(!queue->queue_reg)) {
-+ /* After this the Userspace would be able to free the
-+ * memory for GPU queue. In case the Userspace missed
-+ * terminating the queue, the cleanup will happen on
-+ * context termination where teardown of region tracker
-+ * would free up the GPU queue memory.
-+ */
-+ queue->queue_reg->flags &= ~KBASE_REG_NO_USER_FREE;
-+ }
-+ kbase_gpu_vm_unlock(kctx);
-+
-+ spin_lock_irqsave(&kctx->csf.event_lock, flags);
-+ dev_dbg(kctx->kbdev->dev,
-+ "Remove any pending command queue fatal from context %pK\n",
-+ (void *)kctx);
-+ list_del_init(&queue->error.link);
-+ spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
-+
-+ release_queue(queue);
-+ }
-+
-+ mutex_unlock(&kctx->csf.lock);
-+ if (reset_prevented)
-+ kbase_reset_gpu_allow(kbdev);
-+}
-+
-+int kbase_csf_queue_bind(struct kbase_context *kctx, union kbase_ioctl_cs_queue_bind *bind)
-+{
-+ struct kbase_queue *queue;
-+ struct kbase_queue_group *group;
-+ u8 max_streams;
-+ int ret = -EINVAL;
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ group = find_queue_group(kctx, bind->in.group_handle);
-+ queue = find_queue(kctx, bind->in.buffer_gpu_addr);
-+
-+ if (!group || !queue)
-+ goto out;
-+
-+ /* For the time being, all CSGs have the same number of CSs
-+ * so we check CSG 0 for this number
-+ */
-+ max_streams = kctx->kbdev->csf.global_iface.groups[0].stream_num;
-+
-+ if (bind->in.csi_index >= max_streams)
-+ goto out;
-+
-+ if (group->run_state == KBASE_CSF_GROUP_TERMINATED)
-+ goto out;
-+
-+ if (queue->group || group->bound_queues[bind->in.csi_index])
-+ goto out;
-+
-+ ret = get_user_pages_mmap_handle(kctx, queue);
-+ if (ret)
-+ goto out;
-+
-+ bind->out.mmap_handle = queue->handle;
-+ group->bound_queues[bind->in.csi_index] = queue;
-+ queue->group = group;
-+ queue->csi_index = bind->in.csi_index;
-+ queue->bind_state = KBASE_CSF_QUEUE_BIND_IN_PROGRESS;
-+
-+out:
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ return ret;
-+}
-+
-+static struct kbase_queue_group *get_bound_queue_group(
-+ struct kbase_queue *queue)
-+{
-+ struct kbase_context *kctx = queue->kctx;
-+ struct kbase_queue_group *group;
-+
-+ if (queue->bind_state == KBASE_CSF_QUEUE_UNBOUND)
-+ return NULL;
-+
-+ if (!queue->group)
-+ return NULL;
-+
-+ if (queue->csi_index == KBASEP_IF_NR_INVALID) {
-+ dev_warn(kctx->kbdev->dev, "CS interface index is incorrect\n");
-+ return NULL;
-+ }
-+
-+ group = queue->group;
-+
-+ if (group->bound_queues[queue->csi_index] != queue) {
-+ dev_warn(kctx->kbdev->dev, "Incorrect mapping between queues & queue groups\n");
-+ return NULL;
-+ }
-+
-+ return group;
-+}
-+
-+void kbase_csf_ring_csg_doorbell(struct kbase_device *kbdev, int slot)
-+{
-+ if (WARN_ON(slot < 0))
-+ return;
-+
-+ kbase_csf_ring_csg_slots_doorbell(kbdev, (u32) (1 << slot));
-+}
-+
-+void kbase_csf_ring_csg_slots_doorbell(struct kbase_device *kbdev,
-+ u32 slot_bitmap)
-+{
-+ const struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+ const u32 allowed_bitmap =
-+ (u32) ((1U << kbdev->csf.global_iface.group_num) - 1);
-+ u32 value;
-+
-+ if (WARN_ON(slot_bitmap > allowed_bitmap))
-+ return;
-+
-+ value = kbase_csf_firmware_global_output(global_iface, GLB_DB_ACK);
-+ value ^= slot_bitmap;
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_DB_REQ, value,
-+ slot_bitmap);
-+
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+}
-+
-+void kbase_csf_ring_cs_user_doorbell(struct kbase_device *kbdev,
-+ struct kbase_queue *queue)
-+{
-+ mutex_lock(&kbdev->csf.reg_lock);
-+
-+ if (queue->doorbell_nr != KBASEP_USER_DB_NR_INVALID)
-+ kbase_csf_ring_doorbell(kbdev, queue->doorbell_nr);
-+
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+}
-+
-+void kbase_csf_ring_cs_kernel_doorbell(struct kbase_device *kbdev,
-+ int csi_index, int csg_nr,
-+ bool ring_csg_doorbell)
-+{
-+ struct kbase_csf_cmd_stream_group_info *ginfo;
-+ u32 value;
-+
-+ if (WARN_ON(csg_nr < 0) ||
-+ WARN_ON(csg_nr >= kbdev->csf.global_iface.group_num))
-+ return;
-+
-+ ginfo = &kbdev->csf.global_iface.groups[csg_nr];
-+
-+ if (WARN_ON(csi_index < 0) ||
-+ WARN_ON(csi_index >= ginfo->stream_num))
-+ return;
-+
-+ value = kbase_csf_firmware_csg_output(ginfo, CSG_DB_ACK);
-+ value ^= (1 << csi_index);
-+ kbase_csf_firmware_csg_input_mask(ginfo, CSG_DB_REQ, value,
-+ 1 << csi_index);
-+
-+ if (likely(ring_csg_doorbell))
-+ kbase_csf_ring_csg_doorbell(kbdev, csg_nr);
-+}
-+
-+int kbase_csf_queue_kick(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_kick *kick)
-+{
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct kbase_queue_group *group;
-+ struct kbase_queue *queue;
-+ int err = 0;
-+
-+ err = kbase_reset_gpu_prevent_and_wait(kbdev);
-+ if (err) {
-+ dev_warn(
-+ kbdev->dev,
-+ "Unsuccessful GPU reset detected when kicking queue (buffer_addr=0x%.16llx)",
-+ kick->buffer_gpu_addr);
-+ return err;
-+ }
-+
-+ mutex_lock(&kctx->csf.lock);
-+ queue = find_queue(kctx, kick->buffer_gpu_addr);
-+ if (!queue)
-+ err = -EINVAL;
-+
-+ if (!err) {
-+ group = get_bound_queue_group(queue);
-+ if (!group) {
-+ dev_err(kctx->kbdev->dev, "queue not bound\n");
-+ err = -EINVAL;
-+ }
-+ }
-+
-+ if (!err)
-+ err = kbase_csf_scheduler_queue_start(queue);
-+ mutex_unlock(&kctx->csf.lock);
-+ kbase_reset_gpu_allow(kbdev);
-+
-+ return err;
-+}
-+
-+static void unbind_stopped_queue(struct kbase_context *kctx,
-+ struct kbase_queue *queue)
-+{
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ if (queue->bind_state != KBASE_CSF_QUEUE_UNBOUND) {
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kctx->kbdev, &flags);
-+ bitmap_clear(queue->group->protm_pending_bitmap,
-+ queue->csi_index, 1);
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kctx->kbdev, PROTM_PENDING_CLEAR,
-+ queue->group, queue, queue->group->protm_pending_bitmap[0]);
-+ queue->group->bound_queues[queue->csi_index] = NULL;
-+ queue->group = NULL;
-+ kbase_csf_scheduler_spin_unlock(kctx->kbdev, flags);
-+
-+ put_user_pages_mmap_handle(kctx, queue);
-+ queue->bind_state = KBASE_CSF_QUEUE_UNBOUND;
-+ }
-+}
-+/**
-+ * unbind_queue() - Remove the linkage between a GPU command queue and the group
-+ * to which it was bound or being bound.
-+ *
-+ * @kctx: Address of the kbase context within which the queue was created.
-+ * @queue: Pointer to the queue to be unlinked.
-+ *
-+ * This function will also send the stop request to firmware for the CS
-+ * if the group to which the GPU command queue was bound is scheduled.
-+ *
-+ * This function would be called when :-
-+ * - queue is being unbound. This would happen when the IO mapping
-+ * created on bind is removed explicitly by userspace or the process
-+ * is getting exited.
-+ * - queue group is being terminated which still has queues bound
-+ * to it. This could happen on an explicit terminate request from userspace
-+ * or when the kbase context is being terminated.
-+ * - queue is being terminated without completing the bind operation.
-+ * This could happen if either the queue group is terminated
-+ * after the CS_QUEUE_BIND ioctl but before the 2nd part of bind operation
-+ * to create the IO mapping is initiated.
-+ * - There is a failure in executing the 2nd part of bind operation, inside the
-+ * mmap handler, which creates the IO mapping for queue.
-+ */
-+
-+static void unbind_queue(struct kbase_context *kctx, struct kbase_queue *queue)
-+{
-+ kbase_reset_gpu_assert_failed_or_prevented(kctx->kbdev);
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ if (queue->bind_state != KBASE_CSF_QUEUE_UNBOUND) {
-+ if (queue->bind_state == KBASE_CSF_QUEUE_BOUND)
-+ kbase_csf_scheduler_queue_stop(queue);
-+
-+ unbind_stopped_queue(kctx, queue);
-+ }
-+}
-+
-+void kbase_csf_queue_unbind(struct kbase_queue *queue)
-+{
-+ struct kbase_context *kctx = queue->kctx;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ /* As the process itself is exiting, the termination of queue group can
-+ * be done which would be much faster than stopping of individual
-+ * queues. This would ensure a faster exit for the process especially
-+ * in the case where CSI gets stuck.
-+ * The CSI STOP request will wait for the in flight work to drain
-+ * whereas CSG TERM request would result in an immediate abort or
-+ * cancellation of the pending work.
-+ */
-+ if (current->flags & PF_EXITING) {
-+ struct kbase_queue_group *group = get_bound_queue_group(queue);
-+
-+ if (group)
-+ term_queue_group(group);
-+
-+ WARN_ON(queue->bind_state != KBASE_CSF_QUEUE_UNBOUND);
-+ } else {
-+ unbind_queue(kctx, queue);
-+ }
-+
-+ /* Free the resources, if allocated for this queue. */
-+ if (queue->reg)
-+ kbase_csf_free_command_stream_user_pages(kctx, queue);
-+}
-+
-+void kbase_csf_queue_unbind_stopped(struct kbase_queue *queue)
-+{
-+ struct kbase_context *kctx = queue->kctx;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ WARN_ON(queue->bind_state == KBASE_CSF_QUEUE_BOUND);
-+ unbind_stopped_queue(kctx, queue);
-+
-+ /* Free the resources, if allocated for this queue. */
-+ if (queue->reg)
-+ kbase_csf_free_command_stream_user_pages(kctx, queue);
-+}
-+
-+/**
-+ * find_free_group_handle() - Find a free handle for a queue group
-+ *
-+ * @kctx: Address of the kbase context within which the queue group
-+ * is to be created.
-+ *
-+ * Return: a queue group handle on success, or a negative error code on failure.
-+ */
-+static int find_free_group_handle(struct kbase_context *const kctx)
-+{
-+ /* find the available index in the array of CSGs per this context */
-+ int idx, group_handle = -ENOMEM;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ for (idx = 0;
-+ (idx != MAX_QUEUE_GROUP_NUM) && (group_handle < 0);
-+ idx++) {
-+ if (!kctx->csf.queue_groups[idx])
-+ group_handle = idx;
-+ }
-+
-+ return group_handle;
-+}
-+
-+/**
-+ * iface_has_enough_streams() - Check that at least one CSG supports
-+ * a given number of CS
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @cs_min: Minimum number of CSs required.
-+ *
-+ * Return: true if at least one CSG supports the given number
-+ * of CSs (or more); otherwise false.
-+ */
-+static bool iface_has_enough_streams(struct kbase_device *const kbdev,
-+ u32 const cs_min)
-+{
-+ bool has_enough = false;
-+ struct kbase_csf_cmd_stream_group_info *const groups =
-+ kbdev->csf.global_iface.groups;
-+ const u32 group_num = kbdev->csf.global_iface.group_num;
-+ u32 i;
-+
-+ for (i = 0; (i < group_num) && !has_enough; i++) {
-+ if (groups[i].stream_num >= cs_min)
-+ has_enough = true;
-+ }
-+
-+ return has_enough;
-+}
-+
-+/**
-+ * create_normal_suspend_buffer() - Create normal-mode suspend buffer per
-+ * queue group
-+ *
-+ * @kctx: Pointer to kbase context where the queue group is created at
-+ * @s_buf: Pointer to suspend buffer that is attached to queue group
-+ *
-+ * Return: 0 if suspend buffer is successfully allocated and reflected to GPU
-+ * MMU page table. Otherwise -ENOMEM.
-+ */
-+static int create_normal_suspend_buffer(struct kbase_context *const kctx,
-+ struct kbase_normal_suspend_buffer *s_buf)
-+{
-+ struct kbase_va_region *reg = NULL;
-+ const unsigned long mem_flags = KBASE_REG_GPU_RD | KBASE_REG_GPU_WR;
-+ const size_t nr_pages =
-+ PFN_UP(kctx->kbdev->csf.global_iface.groups[0].suspend_size);
-+ int err = 0;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ /* Allocate and initialize Region Object */
-+ reg = kbase_alloc_free_region(&kctx->kbdev->csf.shared_reg_rbtree, 0,
-+ nr_pages, KBASE_REG_ZONE_MCU_SHARED);
-+
-+ if (!reg)
-+ return -ENOMEM;
-+
-+ s_buf->phy = kcalloc(nr_pages, sizeof(*s_buf->phy), GFP_KERNEL);
-+
-+ if (!s_buf->phy) {
-+ err = -ENOMEM;
-+ goto phy_alloc_failed;
-+ }
-+
-+ /* Get physical page for a normal suspend buffer */
-+ err = kbase_mem_pool_alloc_pages(
-+ &kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ nr_pages, &s_buf->phy[0], false);
-+
-+ if (err < 0)
-+ goto phy_pages_alloc_failed;
-+
-+ /* Insert Region Object into rbtree and make virtual address available
-+ * to map it to physical page
-+ */
-+ mutex_lock(&kctx->kbdev->csf.reg_lock);
-+ err = kbase_add_va_region_rbtree(kctx->kbdev, reg, 0, nr_pages, 1);
-+ reg->flags &= ~KBASE_REG_FREE;
-+ mutex_unlock(&kctx->kbdev->csf.reg_lock);
-+
-+ if (err)
-+ goto add_va_region_failed;
-+
-+ /* Update MMU table */
-+ err = kbase_mmu_insert_pages(kctx->kbdev, &kctx->kbdev->csf.mcu_mmu,
-+ reg->start_pfn, &s_buf->phy[0],
-+ nr_pages, mem_flags,
-+ MCU_AS_NR, KBASE_MEM_GROUP_CSF_FW);
-+ if (err)
-+ goto mmu_insert_failed;
-+
-+ s_buf->reg = reg;
-+
-+ return 0;
-+
-+mmu_insert_failed:
-+ mutex_lock(&kctx->kbdev->csf.reg_lock);
-+ WARN_ON(kbase_remove_va_region(reg));
-+ mutex_unlock(&kctx->kbdev->csf.reg_lock);
-+
-+add_va_region_failed:
-+ kbase_mem_pool_free_pages(
-+ &kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], nr_pages,
-+ &s_buf->phy[0], false, false);
-+
-+phy_pages_alloc_failed:
-+ kfree(s_buf->phy);
-+phy_alloc_failed:
-+ kfree(reg);
-+
-+ return err;
-+}
-+
-+/**
-+ * create_protected_suspend_buffer() - Create protected-mode suspend buffer
-+ * per queue group
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @s_buf: Pointer to suspend buffer that is attached to queue group
-+ *
-+ * Return: 0 if suspend buffer is successfully allocated and reflected to GPU
-+ * MMU page table. Otherwise -ENOMEM.
-+ */
-+static int create_protected_suspend_buffer(struct kbase_device *const kbdev,
-+ struct kbase_protected_suspend_buffer *s_buf)
-+{
-+ struct kbase_va_region *reg = NULL;
-+ struct tagged_addr *phys = NULL;
-+ const unsigned long mem_flags = KBASE_REG_GPU_RD | KBASE_REG_GPU_WR;
-+ const size_t nr_pages =
-+ PFN_UP(kbdev->csf.global_iface.groups[0].suspend_size);
-+ int err = 0;
-+
-+ /* Allocate and initialize Region Object */
-+ reg = kbase_alloc_free_region(&kbdev->csf.shared_reg_rbtree, 0,
-+ nr_pages, KBASE_REG_ZONE_MCU_SHARED);
-+
-+ if (!reg)
-+ return -ENOMEM;
-+
-+ phys = kcalloc(nr_pages, sizeof(*phys), GFP_KERNEL);
-+ if (!phys) {
-+ err = -ENOMEM;
-+ goto phy_alloc_failed;
-+ }
-+
-+ s_buf->pma = kbase_csf_protected_memory_alloc(kbdev, phys,
-+ nr_pages);
-+ if (s_buf->pma == NULL) {
-+ err = -ENOMEM;
-+ goto pma_alloc_failed;
-+ }
-+
-+ /* Insert Region Object into rbtree and make virtual address available
-+ * to map it to physical page
-+ */
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ err = kbase_add_va_region_rbtree(kbdev, reg, 0, nr_pages, 1);
-+ reg->flags &= ~KBASE_REG_FREE;
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ if (err)
-+ goto add_va_region_failed;
-+
-+ /* Update MMU table */
-+ err = kbase_mmu_insert_pages(kbdev, &kbdev->csf.mcu_mmu,
-+ reg->start_pfn, phys,
-+ nr_pages, mem_flags, MCU_AS_NR,
-+ KBASE_MEM_GROUP_CSF_FW);
-+ if (err)
-+ goto mmu_insert_failed;
-+
-+ s_buf->reg = reg;
-+ kfree(phys);
-+ return 0;
-+
-+mmu_insert_failed:
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ WARN_ON(kbase_remove_va_region(reg));
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+add_va_region_failed:
-+ kbase_csf_protected_memory_free(kbdev, s_buf->pma, nr_pages);
-+pma_alloc_failed:
-+ kfree(phys);
-+phy_alloc_failed:
-+ kfree(reg);
-+
-+ return err;
-+}
-+
-+static void timer_event_worker(struct work_struct *data);
-+static void protm_event_worker(struct work_struct *data);
-+static void term_normal_suspend_buffer(struct kbase_context *const kctx,
-+ struct kbase_normal_suspend_buffer *s_buf);
-+
-+/**
-+ * create_suspend_buffers - Setup normal and protected mode
-+ * suspend buffers.
-+ *
-+ * @kctx: Address of the kbase context within which the queue group
-+ * is to be created.
-+ * @group: Pointer to GPU command queue group data.
-+ *
-+ * Return: 0 if suspend buffers are successfully allocated. Otherwise -ENOMEM.
-+ */
-+static int create_suspend_buffers(struct kbase_context *const kctx,
-+ struct kbase_queue_group * const group)
-+{
-+ int err = 0;
-+
-+ if (create_normal_suspend_buffer(kctx, &group->normal_suspend_buf)) {
-+ dev_err(kctx->kbdev->dev, "Failed to create normal suspend buffer\n");
-+ return -ENOMEM;
-+ }
-+
-+ if (kctx->kbdev->csf.pma_dev) {
-+ err = create_protected_suspend_buffer(kctx->kbdev,
-+ &group->protected_suspend_buf);
-+ if (err) {
-+ term_normal_suspend_buffer(kctx,
-+ &group->normal_suspend_buf);
-+ dev_err(kctx->kbdev->dev, "Failed to create protected suspend buffer\n");
-+ }
-+ } else {
-+ group->protected_suspend_buf.reg = NULL;
-+ }
-+
-+ return err;
-+}
-+
-+/**
-+ * generate_group_uid() - Makes an ID unique to all kernel base devices
-+ * and contexts, for a queue group and CSG.
-+ *
-+ * Return: A unique ID in the form of an unsigned 32-bit integer
-+ */
-+static u32 generate_group_uid(void)
-+{
-+ /* use first KBase device to store max UID */
-+ struct kbase_device *kbdev = kbase_find_device(-1);
-+ u32 uid = 1;
-+
-+ if (kbdev)
-+ uid = (u32) atomic_inc_return(&kbdev->group_max_uid_in_devices);
-+ else
-+ WARN(1, "NULL kbase device pointer in group UID generation");
-+
-+ return uid;
-+}
-+
-+/**
-+ * create_queue_group() - Create a queue group
-+ *
-+ * @kctx: Address of the kbase context within which the queue group
-+ * is to be created.
-+ * @create: Address of a structure which contains details of the
-+ * queue group which is to be created.
-+ *
-+ * Return: a queue group handle on success, or a negative error code on failure.
-+ */
-+static int create_queue_group(struct kbase_context *const kctx,
-+ union kbase_ioctl_cs_queue_group_create *const create)
-+{
-+ int group_handle = find_free_group_handle(kctx);
-+
-+ if (group_handle < 0) {
-+ dev_err(kctx->kbdev->dev,
-+ "All queue group handles are already in use\n");
-+ } else {
-+ struct kbase_queue_group * const group =
-+ kmalloc(sizeof(struct kbase_queue_group),
-+ GFP_KERNEL);
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ if (!group) {
-+ dev_err(kctx->kbdev->dev, "Failed to allocate a queue\n");
-+ group_handle = -ENOMEM;
-+ } else {
-+ int err = 0;
-+
-+ group->kctx = kctx;
-+ group->handle = group_handle;
-+ group->csg_nr = KBASEP_CSG_NR_INVALID;
-+
-+ group->tiler_mask = create->in.tiler_mask;
-+ group->fragment_mask = create->in.fragment_mask;
-+ group->compute_mask = create->in.compute_mask;
-+
-+ group->tiler_max = create->in.tiler_max;
-+ group->fragment_max = create->in.fragment_max;
-+ group->compute_max = create->in.compute_max;
-+ group->priority = kbase_csf_priority_queue_group_priority_to_relative(
-+ kbase_csf_priority_check(kctx->kbdev, create->in.priority));
-+ group->doorbell_nr = KBASEP_USER_DB_NR_INVALID;
-+ group->faulted = false;
-+
-+ group->group_uid = generate_group_uid();
-+ create->out.group_uid = group->group_uid;
-+
-+ INIT_LIST_HEAD(&group->link);
-+ INIT_LIST_HEAD(&group->link_to_schedule);
-+ INIT_LIST_HEAD(&group->error_fatal.link);
-+ INIT_LIST_HEAD(&group->error_timeout.link);
-+ INIT_LIST_HEAD(&group->error_tiler_oom.link);
-+ INIT_WORK(&group->timer_event_work, timer_event_worker);
-+ INIT_WORK(&group->protm_event_work, protm_event_worker);
-+ bitmap_zero(group->protm_pending_bitmap,
-+ MAX_SUPPORTED_STREAMS_PER_GROUP);
-+
-+ group->run_state = KBASE_CSF_GROUP_INACTIVE;
-+ err = create_suspend_buffers(kctx, group);
-+
-+ if (err < 0) {
-+ kfree(group);
-+ group_handle = err;
-+ } else {
-+ int j;
-+
-+ kctx->csf.queue_groups[group_handle] = group;
-+ for (j = 0; j < MAX_SUPPORTED_STREAMS_PER_GROUP;
-+ j++)
-+ group->bound_queues[j] = NULL;
-+ }
-+ }
-+ }
-+
-+ return group_handle;
-+}
-+
-+int kbase_csf_queue_group_create(struct kbase_context *const kctx,
-+ union kbase_ioctl_cs_queue_group_create *const create)
-+{
-+ int err = 0;
-+ const u32 tiler_count = hweight64(create->in.tiler_mask);
-+ const u32 fragment_count = hweight64(create->in.fragment_mask);
-+ const u32 compute_count = hweight64(create->in.compute_mask);
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ if ((create->in.tiler_max > tiler_count) ||
-+ (create->in.fragment_max > fragment_count) ||
-+ (create->in.compute_max > compute_count)) {
-+ dev_err(kctx->kbdev->dev,
-+ "Invalid maximum number of endpoints for a queue group\n");
-+ err = -EINVAL;
-+ } else if (create->in.priority >= BASE_QUEUE_GROUP_PRIORITY_COUNT) {
-+ dev_err(kctx->kbdev->dev, "Invalid queue group priority %u\n",
-+ (unsigned int)create->in.priority);
-+ err = -EINVAL;
-+ } else if (!iface_has_enough_streams(kctx->kbdev, create->in.cs_min)) {
-+ dev_err(kctx->kbdev->dev,
-+ "No CSG has at least %d CSs\n",
-+ create->in.cs_min);
-+ err = -EINVAL;
-+ } else {
-+ /* For the CSG which satisfies the condition for having
-+ * the needed number of CSs, check whether it also conforms
-+ * with the requirements for at least one of its CSs having
-+ * the iterator of the needed type
-+ * (note: for CSF v1.0 all CSs in a CSG will have access to
-+ * the same iterators)
-+ */
-+ const int group_handle = create_queue_group(kctx, create);
-+
-+ if (group_handle >= 0)
-+ create->out.group_handle = group_handle;
-+ else
-+ err = group_handle;
-+ }
-+
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ return err;
-+}
-+
-+/**
-+ * term_normal_suspend_buffer() - Free normal-mode suspend buffer of queue group
-+ *
-+ * @kctx: Pointer to kbase context where queue group belongs to
-+ * @s_buf: Pointer to queue group suspend buffer to be freed
-+ */
-+static void term_normal_suspend_buffer(struct kbase_context *const kctx,
-+ struct kbase_normal_suspend_buffer *s_buf)
-+{
-+ const size_t nr_pages =
-+ PFN_UP(kctx->kbdev->csf.global_iface.groups[0].suspend_size);
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ WARN_ON(kbase_mmu_teardown_pages(
-+ kctx->kbdev, &kctx->kbdev->csf.mcu_mmu,
-+ s_buf->reg->start_pfn, nr_pages, MCU_AS_NR));
-+
-+ WARN_ON(s_buf->reg->flags & KBASE_REG_FREE);
-+
-+ mutex_lock(&kctx->kbdev->csf.reg_lock);
-+ WARN_ON(kbase_remove_va_region(s_buf->reg));
-+ mutex_unlock(&kctx->kbdev->csf.reg_lock);
-+
-+ kbase_mem_pool_free_pages(
-+ &kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ nr_pages, &s_buf->phy[0], false, false);
-+
-+ kfree(s_buf->phy);
-+ s_buf->phy = NULL;
-+ kfree(s_buf->reg);
-+ s_buf->reg = NULL;
-+}
-+
-+/**
-+ * term_protected_suspend_buffer() - Free normal-mode suspend buffer of
-+ * queue group
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @s_buf: Pointer to queue group suspend buffer to be freed
-+ */
-+static void term_protected_suspend_buffer(struct kbase_device *const kbdev,
-+ struct kbase_protected_suspend_buffer *s_buf)
-+{
-+ const size_t nr_pages =
-+ PFN_UP(kbdev->csf.global_iface.groups[0].suspend_size);
-+
-+ WARN_ON(kbase_mmu_teardown_pages(
-+ kbdev, &kbdev->csf.mcu_mmu,
-+ s_buf->reg->start_pfn, nr_pages, MCU_AS_NR));
-+
-+ WARN_ON(s_buf->reg->flags & KBASE_REG_FREE);
-+
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ WARN_ON(kbase_remove_va_region(s_buf->reg));
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ kbase_csf_protected_memory_free(kbdev, s_buf->pma, nr_pages);
-+ s_buf->pma = NULL;
-+ kfree(s_buf->reg);
-+ s_buf->reg = NULL;
-+}
-+
-+void kbase_csf_term_descheduled_queue_group(struct kbase_queue_group *group)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+
-+ /* Currently each group supports the same number of CS */
-+ u32 max_streams =
-+ kctx->kbdev->csf.global_iface.groups[0].stream_num;
-+ u32 i;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ WARN_ON(group->run_state != KBASE_CSF_GROUP_INACTIVE &&
-+ group->run_state != KBASE_CSF_GROUP_FAULT_EVICTED);
-+
-+ for (i = 0; i < max_streams; i++) {
-+ struct kbase_queue *queue =
-+ group->bound_queues[i];
-+
-+ /* The group is already being evicted from the scheduler */
-+ if (queue)
-+ unbind_stopped_queue(kctx, queue);
-+ }
-+
-+ term_normal_suspend_buffer(kctx, &group->normal_suspend_buf);
-+ if (kctx->kbdev->csf.pma_dev)
-+ term_protected_suspend_buffer(kctx->kbdev,
-+ &group->protected_suspend_buf);
-+
-+ group->run_state = KBASE_CSF_GROUP_TERMINATED;
-+}
-+
-+/**
-+ * term_queue_group - Terminate a GPU command queue group.
-+ *
-+ * @group: Pointer to GPU command queue group data.
-+ *
-+ * Terminates a GPU command queue group. From the userspace perspective the
-+ * group will still exist but it can't bind new queues to it. Userspace can
-+ * still add work in queues bound to the group but it won't be executed. (This
-+ * is because the IO mapping created upon binding such queues is still intact.)
-+ */
-+static void term_queue_group(struct kbase_queue_group *group)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+
-+ kbase_reset_gpu_assert_failed_or_prevented(kctx->kbdev);
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ /* Stop the group and evict it from the scheduler */
-+ kbase_csf_scheduler_group_deschedule(group);
-+
-+ if (group->run_state == KBASE_CSF_GROUP_TERMINATED)
-+ return;
-+
-+ dev_dbg(kctx->kbdev->dev, "group %d terminating", group->handle);
-+
-+ kbase_csf_term_descheduled_queue_group(group);
-+}
-+
-+static void cancel_queue_group_events(struct kbase_queue_group *group)
-+{
-+ cancel_work_sync(&group->timer_event_work);
-+ cancel_work_sync(&group->protm_event_work);
-+}
-+
-+void kbase_csf_queue_group_terminate(struct kbase_context *kctx,
-+ u8 group_handle)
-+{
-+ struct kbase_queue_group *group;
-+ int err;
-+ bool reset_prevented = false;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+
-+ err = kbase_reset_gpu_prevent_and_wait(kbdev);
-+ if (err)
-+ dev_warn(
-+ kbdev->dev,
-+ "Unsuccessful GPU reset detected when terminating group %d, attempting to terminate regardless",
-+ group_handle);
-+ else
-+ reset_prevented = true;
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ group = find_queue_group(kctx, group_handle);
-+
-+ if (group) {
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kctx->csf.event_lock, flags);
-+
-+ dev_dbg(kbdev->dev,
-+ "Remove any pending group fatal error from context %pK\n",
-+ (void *)group->kctx);
-+
-+ list_del_init(&group->error_tiler_oom.link);
-+ list_del_init(&group->error_timeout.link);
-+ list_del_init(&group->error_fatal.link);
-+ spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
-+
-+ term_queue_group(group);
-+ kctx->csf.queue_groups[group_handle] = NULL;
-+ }
-+
-+ mutex_unlock(&kctx->csf.lock);
-+ if (reset_prevented)
-+ kbase_reset_gpu_allow(kbdev);
-+
-+ if (!group)
-+ return;
-+
-+ /* Cancel any pending event callbacks. If one is in progress
-+ * then this thread waits synchronously for it to complete (which
-+ * is why we must unlock the context first). We already ensured
-+ * that no more callbacks can be enqueued by terminating the group.
-+ */
-+ cancel_queue_group_events(group);
-+ kfree(group);
-+}
-+
-+int kbase_csf_queue_group_suspend(struct kbase_context *kctx,
-+ struct kbase_suspend_copy_buffer *sus_buf,
-+ u8 group_handle)
-+{
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ int err;
-+ struct kbase_queue_group *group;
-+
-+ err = kbase_reset_gpu_prevent_and_wait(kbdev);
-+ if (err) {
-+ dev_warn(
-+ kbdev->dev,
-+ "Unsuccessful GPU reset detected when suspending group %d",
-+ group_handle);
-+ return err;
-+ }
-+ mutex_lock(&kctx->csf.lock);
-+
-+ group = find_queue_group(kctx, group_handle);
-+ if (group)
-+ err = kbase_csf_scheduler_group_copy_suspend_buf(group,
-+ sus_buf);
-+ else
-+ err = -EINVAL;
-+
-+ mutex_unlock(&kctx->csf.lock);
-+ kbase_reset_gpu_allow(kbdev);
-+
-+ return err;
-+}
-+
-+/**
-+ * add_error() - Add an error to the list of errors to report to user space
-+ *
-+ * @kctx: Address of a base context associated with a GPU address space.
-+ * @error: Address of the item to be added to the context's pending error list.
-+ * @data: Error data to be returned to userspace.
-+ *
-+ * Does not wake up the event queue blocking a user thread in kbase_poll. This
-+ * is to make it more efficient to add multiple errors.
-+ *
-+ * The added error must not already be on the context's list of errors waiting
-+ * to be reported (e.g. because a previous error concerning the same object has
-+ * not yet been reported).
-+ */
-+static void add_error(struct kbase_context *const kctx,
-+ struct kbase_csf_notification *const error,
-+ struct base_csf_notification const *const data)
-+{
-+ unsigned long flags;
-+
-+ if (WARN_ON(!kctx))
-+ return;
-+
-+ if (WARN_ON(!error))
-+ return;
-+
-+ if (WARN_ON(!data))
-+ return;
-+
-+ spin_lock_irqsave(&kctx->csf.event_lock, flags);
-+
-+ if (!WARN_ON(!list_empty(&error->link))) {
-+ error->data = *data;
-+ list_add_tail(&error->link, &kctx->csf.error_list);
-+ dev_dbg(kctx->kbdev->dev,
-+ "Added error %pK of type %d in context %pK\n",
-+ (void *)error, data->type, (void *)kctx);
-+ }
-+
-+ spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
-+}
-+
-+void kbase_csf_add_group_fatal_error(
-+ struct kbase_queue_group *const group,
-+ struct base_gpu_queue_group_error const *const err_payload)
-+{
-+ struct base_csf_notification error;
-+
-+ if (WARN_ON(!group))
-+ return;
-+
-+ if (WARN_ON(!err_payload))
-+ return;
-+
-+ error = (struct base_csf_notification) {
-+ .type = BASE_CSF_NOTIFICATION_GPU_QUEUE_GROUP_ERROR,
-+ .payload = {
-+ .csg_error = {
-+ .handle = group->handle,
-+ .error = *err_payload
-+ }
-+ }
-+ };
-+
-+ add_error(group->kctx, &group->error_fatal, &error);
-+}
-+
-+void kbase_csf_active_queue_groups_reset(struct kbase_device *kbdev,
-+ struct kbase_context *kctx)
-+{
-+ struct list_head evicted_groups;
-+ struct kbase_queue_group *group;
-+ int i;
-+
-+ INIT_LIST_HEAD(&evicted_groups);
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ kbase_csf_scheduler_evict_ctx_slots(kbdev, kctx, &evicted_groups);
-+ while (!list_empty(&evicted_groups)) {
-+ group = list_first_entry(&evicted_groups,
-+ struct kbase_queue_group, link);
-+
-+ dev_dbg(kbdev->dev, "Context %d_%d active group %d terminated",
-+ kctx->tgid, kctx->id, group->handle);
-+ kbase_csf_term_descheduled_queue_group(group);
-+ list_del_init(&group->link);
-+ }
-+
-+ /* Acting on the queue groups that are pending to be terminated. */
-+ for (i = 0; i < MAX_QUEUE_GROUP_NUM; i++) {
-+ group = kctx->csf.queue_groups[i];
-+ if (group &&
-+ group->run_state == KBASE_CSF_GROUP_FAULT_EVICTED)
-+ kbase_csf_term_descheduled_queue_group(group);
-+ }
-+
-+ mutex_unlock(&kctx->csf.lock);
-+}
-+
-+int kbase_csf_ctx_init(struct kbase_context *kctx)
-+{
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ int err = -ENOMEM;
-+
-+ INIT_LIST_HEAD(&kctx->csf.event_callback_list);
-+ INIT_LIST_HEAD(&kctx->csf.queue_list);
-+ INIT_LIST_HEAD(&kctx->csf.link);
-+ INIT_LIST_HEAD(&kctx->csf.error_list);
-+
-+ spin_lock_init(&kctx->csf.event_lock);
-+ kctx->csf.user_reg_vma = NULL;
-+ mutex_lock(&kbdev->pm.lock);
-+ /* The inode information for /dev/malixx file is not available at the
-+ * time of device probe as the inode is created when the device node
-+ * is created by udevd (through mknod).
-+ */
-+ if (kctx->filp) {
-+ if (!kbdev->csf.mali_file_inode)
-+ kbdev->csf.mali_file_inode = kctx->filp->f_inode;
-+
-+ /* inode is unique for a file */
-+ WARN_ON(kbdev->csf.mali_file_inode != kctx->filp->f_inode);
-+ }
-+ mutex_unlock(&kbdev->pm.lock);
-+
-+ /* Mark all the cookies as 'free' */
-+ bitmap_fill(kctx->csf.cookies, KBASE_CSF_NUM_USER_IO_PAGES_HANDLE);
-+
-+ kctx->csf.wq = alloc_workqueue("mali_kbase_csf_wq",
-+ WQ_UNBOUND, 1);
-+
-+ if (likely(kctx->csf.wq)) {
-+ err = kbase_csf_scheduler_context_init(kctx);
-+
-+ if (likely(!err)) {
-+ err = kbase_csf_kcpu_queue_context_init(kctx);
-+
-+ if (likely(!err)) {
-+ err = kbase_csf_tiler_heap_context_init(kctx);
-+
-+ if (likely(!err))
-+ mutex_init(&kctx->csf.lock);
-+ else
-+ kbase_csf_kcpu_queue_context_term(kctx);
-+ }
-+
-+ if (unlikely(err))
-+ kbase_csf_scheduler_context_term(kctx);
-+ }
-+
-+ if (unlikely(err))
-+ destroy_workqueue(kctx->csf.wq);
-+ }
-+
-+ return err;
-+}
-+
-+void kbase_csf_ctx_handle_fault(struct kbase_context *kctx,
-+ struct kbase_fault *fault)
-+{
-+ int gr;
-+ bool reported = false;
-+ struct base_gpu_queue_group_error err_payload;
-+ int err;
-+ struct kbase_device *kbdev;
-+
-+ if (WARN_ON(!kctx))
-+ return;
-+
-+ if (WARN_ON(!fault))
-+ return;
-+
-+ kbdev = kctx->kbdev;
-+ err = kbase_reset_gpu_try_prevent(kbdev);
-+ /* Regardless of whether reset failed or is currently happening, exit
-+ * early
-+ */
-+ if (err)
-+ return;
-+
-+ err_payload = (struct base_gpu_queue_group_error) {
-+ .error_type = BASE_GPU_QUEUE_GROUP_ERROR_FATAL,
-+ .payload = {
-+ .fatal_group = {
-+ .sideband = fault->addr,
-+ .status = fault->status,
-+ }
-+ }
-+ };
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ for (gr = 0; gr < MAX_QUEUE_GROUP_NUM; gr++) {
-+ struct kbase_queue_group *const group =
-+ kctx->csf.queue_groups[gr];
-+
-+ if (group && group->run_state != KBASE_CSF_GROUP_TERMINATED) {
-+ term_queue_group(group);
-+ kbase_csf_add_group_fatal_error(group, &err_payload);
-+ reported = true;
-+ }
-+ }
-+
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ if (reported)
-+ kbase_event_wakeup(kctx);
-+
-+ kbase_reset_gpu_allow(kbdev);
-+}
-+
-+void kbase_csf_ctx_term(struct kbase_context *kctx)
-+{
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct kbase_as *as = NULL;
-+ unsigned long flags;
-+ u32 i;
-+ int err;
-+ bool reset_prevented = false;
-+
-+ /* As the kbase context is terminating, its debugfs sub-directory would
-+ * have been removed already and so would be the debugfs file created
-+ * for queue groups & kcpu queues, hence no need to explicitly remove
-+ * those debugfs files.
-+ */
-+ kbase_csf_event_wait_remove_all(kctx);
-+
-+ /* Wait for a GPU reset if it is happening, prevent it if not happening */
-+ err = kbase_reset_gpu_prevent_and_wait(kbdev);
-+ if (err)
-+ dev_warn(
-+ kbdev->dev,
-+ "Unsuccessful GPU reset detected when terminating csf context (%d_%d), attempting to terminate regardless",
-+ kctx->tgid, kctx->id);
-+ else
-+ reset_prevented = true;
-+
-+ mutex_lock(&kctx->csf.lock);
-+ /* Iterate through the queue groups that were not terminated by
-+ * userspace and issue the term request to firmware for them.
-+ */
-+ for (i = 0; i < MAX_QUEUE_GROUP_NUM; i++) {
-+ if (kctx->csf.queue_groups[i])
-+ term_queue_group(kctx->csf.queue_groups[i]);
-+ }
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ if (reset_prevented)
-+ kbase_reset_gpu_allow(kbdev);
-+
-+ /* Now that all queue groups have been terminated, there can be no
-+ * more OoM or timer event interrupts but there can be inflight work
-+ * items. Destroying the wq will implicitly flush those work items.
-+ */
-+ destroy_workqueue(kctx->csf.wq);
-+
-+ /* Wait for the firmware error work item to also finish as it could
-+ * be affecting this outgoing context also.
-+ */
-+ flush_work(&kctx->kbdev->csf.fw_error_work);
-+
-+ /* A work item to handle page_fault/bus_fault/gpu_fault could be
-+ * pending for the outgoing context. Flush the workqueue that will
-+ * execute that work item.
-+ */
-+ spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, flags);
-+ if (kctx->as_nr != KBASEP_AS_NR_INVALID)
-+ as = &kctx->kbdev->as[kctx->as_nr];
-+ spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags);
-+ if (as)
-+ flush_workqueue(as->pf_wq);
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ for (i = 0; i < MAX_QUEUE_GROUP_NUM; i++) {
-+ kfree(kctx->csf.queue_groups[i]);
-+ kctx->csf.queue_groups[i] = NULL;
-+ }
-+
-+ /* Iterate through the queues that were not terminated by
-+ * userspace and do the required cleanup for them.
-+ */
-+ while (!list_empty(&kctx->csf.queue_list)) {
-+ struct kbase_queue *queue;
-+
-+ queue = list_first_entry(&kctx->csf.queue_list,
-+ struct kbase_queue, link);
-+
-+ /* The reference held when the IO mapping was created on bind
-+ * would have been dropped otherwise the termination of Kbase
-+ * context itself wouldn't have kicked-in. So there shall be
-+ * only one reference left that was taken when queue was
-+ * registered.
-+ */
-+ if (atomic_read(&queue->refcount) != 1)
-+ dev_warn(kctx->kbdev->dev,
-+ "Releasing queue with incorrect refcounting!\n");
-+ list_del_init(&queue->link);
-+ release_queue(queue);
-+ }
-+
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ kbase_csf_tiler_heap_context_term(kctx);
-+ kbase_csf_kcpu_queue_context_term(kctx);
-+ kbase_csf_scheduler_context_term(kctx);
-+
-+ mutex_destroy(&kctx->csf.lock);
-+}
-+
-+int kbase_csf_event_wait_add(struct kbase_context *kctx,
-+ kbase_csf_event_callback *callback, void *param)
-+{
-+ int err = -ENOMEM;
-+ struct kbase_csf_event *event =
-+ kzalloc(sizeof(struct kbase_csf_event), GFP_KERNEL);
-+
-+ if (event) {
-+ unsigned long flags;
-+
-+ event->kctx = kctx;
-+ event->callback = callback;
-+ event->param = param;
-+
-+ spin_lock_irqsave(&kctx->csf.event_lock, flags);
-+ list_add_tail(&event->link, &kctx->csf.event_callback_list);
-+ dev_dbg(kctx->kbdev->dev,
-+ "Added event handler %pK with param %pK\n", event,
-+ event->param);
-+ spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
-+
-+ err = 0;
-+ }
-+
-+ return err;
-+}
-+
-+void kbase_csf_event_wait_remove(struct kbase_context *kctx,
-+ kbase_csf_event_callback *callback, void *param)
-+{
-+ struct kbase_csf_event *event;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kctx->csf.event_lock, flags);
-+
-+ list_for_each_entry(event, &kctx->csf.event_callback_list, link) {
-+ if ((event->callback == callback) && (event->param == param)) {
-+ list_del(&event->link);
-+ dev_dbg(kctx->kbdev->dev,
-+ "Removed event handler %pK with param %pK\n",
-+ event, event->param);
-+ kfree(event);
-+ break;
-+ }
-+ }
-+ spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
-+}
-+
-+bool kbase_csf_read_error(struct kbase_context *kctx,
-+ struct base_csf_notification *event_data)
-+{
-+ bool got_event = true;
-+ struct kbase_csf_notification *error_data = NULL;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kctx->csf.event_lock, flags);
-+
-+ if (likely(!list_empty(&kctx->csf.error_list))) {
-+ error_data = list_first_entry(&kctx->csf.error_list,
-+ struct kbase_csf_notification, link);
-+ list_del_init(&error_data->link);
-+ *event_data = error_data->data;
-+ dev_dbg(kctx->kbdev->dev, "Dequeued error %pK in context %pK\n",
-+ (void *)error_data, (void *)kctx);
-+ } else {
-+ got_event = false;
-+ }
-+
-+ spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
-+
-+ return got_event;
-+}
-+
-+bool kbase_csf_error_pending(struct kbase_context *kctx)
-+{
-+ bool event_pended = false;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kctx->csf.event_lock, flags);
-+ event_pended = !list_empty(&kctx->csf.error_list);
-+ dev_dbg(kctx->kbdev->dev, "%s error is pending in context %pK\n",
-+ event_pended ? "An" : "No", (void *)kctx);
-+ spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
-+
-+ return event_pended;
-+}
-+
-+void kbase_csf_event_signal(struct kbase_context *kctx, bool notify_gpu)
-+{
-+ struct kbase_csf_event *event, *next_event;
-+ unsigned long flags;
-+
-+ dev_dbg(kctx->kbdev->dev,
-+ "Signal event (%s GPU notify) for context %pK\n",
-+ notify_gpu ? "with" : "without", (void *)kctx);
-+
-+ /* First increment the signal count and wake up event thread.
-+ */
-+ atomic_set(&kctx->event_count, 1);
-+ kbase_event_wakeup(kctx);
-+
-+ /* Signal the CSF firmware. This is to ensure that pending command
-+ * stream synch object wait operations are re-evaluated.
-+ * Write to GLB_DOORBELL would suffice as spec says that all pending
-+ * synch object wait operations are re-evaluated on a write to any
-+ * CS_DOORBELL/GLB_DOORBELL register.
-+ */
-+ if (notify_gpu) {
-+ spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, flags);
-+ if (kctx->kbdev->pm.backend.gpu_powered)
-+ kbase_csf_ring_doorbell(kctx->kbdev, CSF_KERNEL_DOORBELL_NR);
-+ KBASE_KTRACE_ADD(kctx->kbdev, SYNC_UPDATE_EVENT_NOTIFY_GPU, kctx, 0u);
-+ spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags);
-+ }
-+
-+ /* Now invoke the callbacks registered on backend side.
-+ * Allow item removal inside the loop, if requested by the callback.
-+ */
-+ spin_lock_irqsave(&kctx->csf.event_lock, flags);
-+
-+ list_for_each_entry_safe(
-+ event, next_event, &kctx->csf.event_callback_list, link) {
-+ enum kbase_csf_event_callback_action action;
-+
-+ dev_dbg(kctx->kbdev->dev,
-+ "Calling event handler %pK with param %pK\n",
-+ (void *)event, event->param);
-+ action = event->callback(event->param);
-+ if (action == KBASE_CSF_EVENT_CALLBACK_REMOVE) {
-+ list_del(&event->link);
-+ kfree(event);
-+ }
-+ }
-+
-+ spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
-+}
-+
-+void kbase_csf_event_wait_remove_all(struct kbase_context *kctx)
-+{
-+ struct kbase_csf_event *event, *next_event;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kctx->csf.event_lock, flags);
-+
-+ list_for_each_entry_safe(
-+ event, next_event, &kctx->csf.event_callback_list, link) {
-+ list_del(&event->link);
-+ dev_dbg(kctx->kbdev->dev,
-+ "Removed event handler %pK with param %pK\n",
-+ (void *)event, event->param);
-+ kfree(event);
-+ }
-+
-+ spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
-+}
-+
-+/**
-+ * handle_oom_event - Handle the OoM event generated by the firmware for the
-+ * CSI.
-+ *
-+ * This function will handle the OoM event request from the firmware for the
-+ * CS. It will retrieve the address of heap context and heap's
-+ * statistics (like number of render passes in-flight) from the CS's kernel
-+ * kernel output page and pass them to the tiler heap function to allocate a
-+ * new chunk.
-+ * It will also update the CS's kernel input page with the address
-+ * of a new chunk that was allocated.
-+ *
-+ * @kctx: Pointer to the kbase context in which the tiler heap was initialized.
-+ * @stream: Pointer to the structure containing info provided by the firmware
-+ * about the CSI.
-+ *
-+ * Return: 0 if successfully handled the request, otherwise a negative error
-+ * code on failure.
-+ */
-+static int handle_oom_event(struct kbase_context *const kctx,
-+ struct kbase_csf_cmd_stream_info const *const stream)
-+{
-+ u64 gpu_heap_va =
-+ kbase_csf_firmware_cs_output(stream, CS_HEAP_ADDRESS_LO) |
-+ ((u64)kbase_csf_firmware_cs_output(stream, CS_HEAP_ADDRESS_HI) << 32);
-+ const u32 vt_start =
-+ kbase_csf_firmware_cs_output(stream, CS_HEAP_VT_START);
-+ const u32 vt_end =
-+ kbase_csf_firmware_cs_output(stream, CS_HEAP_VT_END);
-+ const u32 frag_end =
-+ kbase_csf_firmware_cs_output(stream, CS_HEAP_FRAG_END);
-+ u32 renderpasses_in_flight;
-+ u32 pending_frag_count;
-+ u64 new_chunk_ptr;
-+ int err;
-+
-+ if ((frag_end > vt_end) || (vt_end >= vt_start)) {
-+ dev_warn(kctx->kbdev->dev, "Invalid Heap statistics provided by firmware: vt_start %d, vt_end %d, frag_end %d\n",
-+ vt_start, vt_end, frag_end);
-+ return -EINVAL;
-+ }
-+
-+ renderpasses_in_flight = vt_start - frag_end;
-+ pending_frag_count = vt_end - frag_end;
-+
-+ err = kbase_csf_tiler_heap_alloc_new_chunk(kctx,
-+ gpu_heap_va, renderpasses_in_flight, pending_frag_count, &new_chunk_ptr);
-+
-+ /* It is okay to acknowledge with a NULL chunk (firmware will then wait
-+ * for the fragment jobs to complete and release chunks)
-+ */
-+ if (err == -EBUSY)
-+ new_chunk_ptr = 0;
-+ else if (err)
-+ return err;
-+
-+ kbase_csf_firmware_cs_input(stream, CS_TILER_HEAP_START_LO,
-+ new_chunk_ptr & 0xFFFFFFFF);
-+ kbase_csf_firmware_cs_input(stream, CS_TILER_HEAP_START_HI,
-+ new_chunk_ptr >> 32);
-+
-+ kbase_csf_firmware_cs_input(stream, CS_TILER_HEAP_END_LO,
-+ new_chunk_ptr & 0xFFFFFFFF);
-+ kbase_csf_firmware_cs_input(stream, CS_TILER_HEAP_END_HI,
-+ new_chunk_ptr >> 32);
-+
-+ return 0;
-+}
-+
-+/**
-+ * report_tiler_oom_error - Report a CSG error due to a tiler heap OOM event
-+ *
-+ * @group: Pointer to the GPU command queue group that encountered the error
-+ */
-+static void report_tiler_oom_error(struct kbase_queue_group *group)
-+{
-+ struct base_csf_notification const
-+ error = { .type = BASE_CSF_NOTIFICATION_GPU_QUEUE_GROUP_ERROR,
-+ .payload = {
-+ .csg_error = {
-+ .handle = group->handle,
-+ .error = {
-+ .error_type =
-+ BASE_GPU_QUEUE_GROUP_ERROR_TILER_HEAP_OOM,
-+ } } } };
-+
-+ add_error(group->kctx, &group->error_tiler_oom, &error);
-+ kbase_event_wakeup(group->kctx);
-+}
-+
-+/**
-+ * kbase_queue_oom_event - Handle tiler out-of-memory for a GPU command queue.
-+ *
-+ * @queue: Pointer to queue for which out-of-memory event was received.
-+ *
-+ * Called with the CSF locked for the affected GPU virtual address space.
-+ * Do not call in interrupt context.
-+ *
-+ * Handles tiler out-of-memory for a GPU command queue and then clears the
-+ * notification to allow the firmware to report out-of-memory again in future.
-+ * If the out-of-memory condition was successfully handled then this function
-+ * rings the relevant doorbell to notify the firmware; otherwise, it terminates
-+ * the GPU command queue group to which the queue is bound. See
-+ * term_queue_group() for details.
-+ */
-+static void kbase_queue_oom_event(struct kbase_queue *const queue)
-+{
-+ struct kbase_context *const kctx = queue->kctx;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ struct kbase_queue_group *group;
-+ int slot_num, err;
-+ struct kbase_csf_cmd_stream_group_info const *ginfo;
-+ struct kbase_csf_cmd_stream_info const *stream;
-+ int csi_index = queue->csi_index;
-+ u32 cs_oom_ack, cs_oom_req;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ group = get_bound_queue_group(queue);
-+ if (!group) {
-+ dev_warn(kctx->kbdev->dev, "queue not bound\n");
-+ return;
-+ }
-+
-+ kbase_csf_scheduler_lock(kbdev);
-+
-+ slot_num = kbase_csf_scheduler_group_get_slot(group);
-+
-+ /* The group could have gone off slot before this work item got
-+ * a chance to execute.
-+ */
-+ if (slot_num < 0)
-+ goto unlock;
-+
-+ /* If the bound group is on slot yet the kctx is marked with disabled
-+ * on address-space fault, the group is pending to be killed. So skip
-+ * the inflight oom operation.
-+ */
-+ if (kbase_ctx_flag(kctx, KCTX_AS_DISABLED_ON_FAULT))
-+ goto unlock;
-+
-+ ginfo = &kbdev->csf.global_iface.groups[slot_num];
-+ stream = &ginfo->streams[csi_index];
-+ cs_oom_ack = kbase_csf_firmware_cs_output(stream, CS_ACK) &
-+ CS_ACK_TILER_OOM_MASK;
-+ cs_oom_req = kbase_csf_firmware_cs_input_read(stream, CS_REQ) &
-+ CS_REQ_TILER_OOM_MASK;
-+
-+ /* The group could have already undergone suspend-resume cycle before
-+ * this work item got a chance to execute. On CSG resume the CS_ACK
-+ * register is set by firmware to reflect the CS_REQ register, which
-+ * implies that all events signaled before suspension are implicitly
-+ * acknowledged.
-+ * A new OoM event is expected to be generated after resume.
-+ */
-+ if (cs_oom_ack == cs_oom_req)
-+ goto unlock;
-+
-+ err = handle_oom_event(kctx, stream);
-+
-+ kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_oom_ack,
-+ CS_REQ_TILER_OOM_MASK);
-+
-+ if (err) {
-+ dev_warn(
-+ kbdev->dev,
-+ "Queue group to be terminated, couldn't handle the OoM event\n");
-+ kbase_csf_scheduler_unlock(kbdev);
-+ term_queue_group(group);
-+ report_tiler_oom_error(group);
-+ return;
-+ }
-+
-+ kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, slot_num, true);
-+unlock:
-+ kbase_csf_scheduler_unlock(kbdev);
-+}
-+
-+/**
-+ * oom_event_worker - Tiler out-of-memory handler called from a workqueue.
-+ *
-+ * @data: Pointer to a work_struct embedded in GPU command queue data.
-+ *
-+ * Handles a tiler out-of-memory condition for a GPU command queue and then
-+ * releases a reference that was added to prevent the queue being destroyed
-+ * while this work item was pending on a workqueue.
-+ */
-+static void oom_event_worker(struct work_struct *data)
-+{
-+ struct kbase_queue *queue =
-+ container_of(data, struct kbase_queue, oom_event_work);
-+ struct kbase_context *kctx = queue->kctx;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+
-+ int err = kbase_reset_gpu_try_prevent(kbdev);
-+ /* Regardless of whether reset failed or is currently happening, exit
-+ * early
-+ */
-+ if (err)
-+ return;
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ kbase_queue_oom_event(queue);
-+ release_queue(queue);
-+
-+ mutex_unlock(&kctx->csf.lock);
-+ kbase_reset_gpu_allow(kbdev);
-+}
-+
-+/**
-+ * report_group_timeout_error - Report the timeout error for the group to userspace.
-+ *
-+ * @group: Pointer to the group for which timeout error occurred
-+ */
-+static void report_group_timeout_error(struct kbase_queue_group *const group)
-+{
-+ struct base_csf_notification const
-+ error = { .type = BASE_CSF_NOTIFICATION_GPU_QUEUE_GROUP_ERROR,
-+ .payload = {
-+ .csg_error = {
-+ .handle = group->handle,
-+ .error = {
-+ .error_type =
-+ BASE_GPU_QUEUE_GROUP_ERROR_TIMEOUT,
-+ } } } };
-+
-+ dev_warn(group->kctx->kbdev->dev,
-+ "Notify the event notification thread, forward progress timeout (%llu cycles)\n",
-+ kbase_csf_timeout_get(group->kctx->kbdev));
-+
-+ add_error(group->kctx, &group->error_timeout, &error);
-+ kbase_event_wakeup(group->kctx);
-+}
-+
-+/**
-+ * timer_event_worker - Handle the progress timeout error for the group
-+ *
-+ * @data: Pointer to a work_struct embedded in GPU command queue group data.
-+ *
-+ * Terminate the CSG and report the error to userspace
-+ */
-+static void timer_event_worker(struct work_struct *data)
-+{
-+ struct kbase_queue_group *const group =
-+ container_of(data, struct kbase_queue_group, timer_event_work);
-+ struct kbase_context *const kctx = group->kctx;
-+ bool reset_prevented = false;
-+ int err = kbase_reset_gpu_prevent_and_wait(kctx->kbdev);
-+
-+ if (err)
-+ dev_warn(
-+ kctx->kbdev->dev,
-+ "Unsuccessful GPU reset detected when terminating group %d on progress timeout, attempting to terminate regardless",
-+ group->handle);
-+ else
-+ reset_prevented = true;
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ term_queue_group(group);
-+ report_group_timeout_error(group);
-+
-+ mutex_unlock(&kctx->csf.lock);
-+ if (reset_prevented)
-+ kbase_reset_gpu_allow(kctx->kbdev);
-+}
-+
-+/**
-+ * handle_progress_timer_event - Progress timer timeout event handler.
-+ *
-+ * @group: Pointer to GPU queue group for which the timeout event is received.
-+ *
-+ * Enqueue a work item to terminate the group and notify the event notification
-+ * thread of progress timeout fault for the GPU command queue group.
-+ */
-+static void handle_progress_timer_event(struct kbase_queue_group *const group)
-+{
-+ queue_work(group->kctx->csf.wq, &group->timer_event_work);
-+}
-+
-+/**
-+ * protm_event_worker - Protected mode switch request event handler
-+ * called from a workqueue.
-+ *
-+ * @data: Pointer to a work_struct embedded in GPU command queue group data.
-+ *
-+ * Request to switch to protected mode.
-+ */
-+static void protm_event_worker(struct work_struct *data)
-+{
-+ struct kbase_queue_group *const group =
-+ container_of(data, struct kbase_queue_group, protm_event_work);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, PROTM_EVENT_WORKER_BEGIN,
-+ group, 0u);
-+ kbase_csf_scheduler_group_protm_enter(group);
-+ KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, PROTM_EVENT_WORKER_END,
-+ group, 0u);
-+}
-+
-+static void report_queue_fatal_error(struct kbase_queue *const queue,
-+ u32 cs_fatal, u64 cs_fatal_info,
-+ u8 group_handle)
-+{
-+ struct base_csf_notification error =
-+ { .type = BASE_CSF_NOTIFICATION_GPU_QUEUE_GROUP_ERROR,
-+ .payload = {
-+ .csg_error = {
-+ .handle = group_handle,
-+ .error = {
-+ .error_type =
-+ BASE_GPU_QUEUE_GROUP_QUEUE_ERROR_FATAL,
-+ .payload = {
-+ .fatal_queue = {
-+ .sideband =
-+ cs_fatal_info,
-+ .status = cs_fatal,
-+ .csi_index =
-+ queue->csi_index,
-+ } } } } } };
-+
-+ add_error(queue->kctx, &queue->error, &error);
-+ kbase_event_wakeup(queue->kctx);
-+}
-+
-+/**
-+ * handle_fault_event - Handler for CS fault.
-+ *
-+ * @queue: Pointer to queue for which fault event was received.
-+ * @stream: Pointer to the structure containing info provided by the
-+ * firmware about the CSI.
-+ *
-+ * Prints meaningful CS fault information.
-+ *
-+ */
-+static void
-+handle_fault_event(struct kbase_queue *const queue,
-+ struct kbase_csf_cmd_stream_info const *const stream)
-+{
-+ const u32 cs_fault = kbase_csf_firmware_cs_output(stream, CS_FAULT);
-+ const u64 cs_fault_info =
-+ kbase_csf_firmware_cs_output(stream, CS_FAULT_INFO_LO) |
-+ ((u64)kbase_csf_firmware_cs_output(stream, CS_FAULT_INFO_HI)
-+ << 32);
-+ const u8 cs_fault_exception_type =
-+ CS_FAULT_EXCEPTION_TYPE_GET(cs_fault);
-+ const u32 cs_fault_exception_data =
-+ CS_FAULT_EXCEPTION_DATA_GET(cs_fault);
-+ const u64 cs_fault_info_exception_data =
-+ CS_FAULT_INFO_EXCEPTION_DATA_GET(cs_fault_info);
-+ struct kbase_device *const kbdev = queue->kctx->kbdev;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+
-+ dev_warn(kbdev->dev,
-+ "Ctx %d_%d Group %d CSG %d CSI: %d\n"
-+ "CS_FAULT.EXCEPTION_TYPE: 0x%x (%s)\n"
-+ "CS_FAULT.EXCEPTION_DATA: 0x%x\n"
-+ "CS_FAULT_INFO.EXCEPTION_DATA: 0x%llx\n",
-+ queue->kctx->tgid, queue->kctx->id, queue->group->handle,
-+ queue->group->csg_nr, queue->csi_index,
-+ cs_fault_exception_type,
-+ kbase_gpu_exception_name(cs_fault_exception_type),
-+ cs_fault_exception_data, cs_fault_info_exception_data);
-+
-+ if (cs_fault_exception_type ==
-+ CS_FAULT_EXCEPTION_TYPE_RESOURCE_EVICTION_TIMEOUT)
-+ report_queue_fatal_error(queue, GPU_EXCEPTION_TYPE_SW_FAULT_2,
-+ 0, queue->group->handle);
-+}
-+
-+/**
-+ * fatal_event_worker - Handle the fatal error for the GPU queue
-+ *
-+ * @data: Pointer to a work_struct embedded in GPU command queue.
-+ *
-+ * Terminate the CSG and report the error to userspace.
-+ */
-+static void fatal_event_worker(struct work_struct *const data)
-+{
-+ struct kbase_queue *const queue =
-+ container_of(data, struct kbase_queue, fatal_event_work);
-+ struct kbase_context *const kctx = queue->kctx;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ struct kbase_queue_group *group;
-+ u8 group_handle;
-+ bool reset_prevented = false;
-+ int err = kbase_reset_gpu_prevent_and_wait(kbdev);
-+
-+ if (err)
-+ dev_warn(
-+ kbdev->dev,
-+ "Unsuccessful GPU reset detected when terminating group to handle fatal event, attempting to terminate regardless");
-+ else
-+ reset_prevented = true;
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ group = get_bound_queue_group(queue);
-+ if (!group) {
-+ dev_warn(kbdev->dev, "queue not bound when handling fatal event");
-+ goto unlock;
-+ }
-+
-+ group_handle = group->handle;
-+ term_queue_group(group);
-+ report_queue_fatal_error(queue, queue->cs_fatal, queue->cs_fatal_info,
-+ group_handle);
-+
-+unlock:
-+ release_queue(queue);
-+ mutex_unlock(&kctx->csf.lock);
-+ if (reset_prevented)
-+ kbase_reset_gpu_allow(kbdev);
-+}
-+
-+/**
-+ * handle_fatal_event - Handler for CS fatal.
-+ *
-+ * @queue: Pointer to queue for which fatal event was received.
-+ * @stream: Pointer to the structure containing info provided by the
-+ * firmware about the CSI.
-+ *
-+ * Prints meaningful CS fatal information.
-+ * Enqueue a work item to terminate the group and report the fatal error
-+ * to user space.
-+ */
-+static void
-+handle_fatal_event(struct kbase_queue *const queue,
-+ struct kbase_csf_cmd_stream_info const *const stream)
-+{
-+ const u32 cs_fatal = kbase_csf_firmware_cs_output(stream, CS_FATAL);
-+ const u64 cs_fatal_info =
-+ kbase_csf_firmware_cs_output(stream, CS_FATAL_INFO_LO) |
-+ ((u64)kbase_csf_firmware_cs_output(stream, CS_FATAL_INFO_HI)
-+ << 32);
-+ const u32 cs_fatal_exception_type =
-+ CS_FATAL_EXCEPTION_TYPE_GET(cs_fatal);
-+ const u32 cs_fatal_exception_data =
-+ CS_FATAL_EXCEPTION_DATA_GET(cs_fatal);
-+ const u64 cs_fatal_info_exception_data =
-+ CS_FATAL_INFO_EXCEPTION_DATA_GET(cs_fatal_info);
-+ struct kbase_device *const kbdev = queue->kctx->kbdev;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+
-+ dev_warn(kbdev->dev,
-+ "Ctx %d_%d Group %d CSG %d CSI: %d\n"
-+ "CS_FATAL.EXCEPTION_TYPE: 0x%x (%s)\n"
-+ "CS_FATAL.EXCEPTION_DATA: 0x%x\n"
-+ "CS_FATAL_INFO.EXCEPTION_DATA: 0x%llx\n",
-+ queue->kctx->tgid, queue->kctx->id, queue->group->handle,
-+ queue->group->csg_nr, queue->csi_index,
-+ cs_fatal_exception_type,
-+ kbase_gpu_exception_name(cs_fatal_exception_type),
-+ cs_fatal_exception_data, cs_fatal_info_exception_data);
-+
-+ if (cs_fatal_exception_type ==
-+ CS_FATAL_EXCEPTION_TYPE_FIRMWARE_INTERNAL_ERROR) {
-+ queue_work(system_wq, &kbdev->csf.fw_error_work);
-+ } else {
-+ get_queue(queue);
-+ queue->cs_fatal = cs_fatal;
-+ queue->cs_fatal_info = cs_fatal_info;
-+ if (!queue_work(queue->kctx->csf.wq, &queue->fatal_event_work))
-+ release_queue(queue);
-+ }
-+}
-+
-+/**
-+ * handle_queue_exception_event - Handler for CS fatal/fault exception events.
-+ *
-+ * @queue: Pointer to queue for which fatal/fault event was received.
-+ * @cs_req: Value of the CS_REQ register from the CS's input page.
-+ * @cs_ack: Value of the CS_ACK register from the CS's output page.
-+ */
-+static void handle_queue_exception_event(struct kbase_queue *const queue,
-+ const u32 cs_req, const u32 cs_ack)
-+{
-+ struct kbase_csf_cmd_stream_group_info const *ginfo;
-+ struct kbase_csf_cmd_stream_info const *stream;
-+ struct kbase_context *const kctx = queue->kctx;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ struct kbase_queue_group *group = queue->group;
-+ int csi_index = queue->csi_index;
-+ int slot_num = group->csg_nr;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+
-+ ginfo = &kbdev->csf.global_iface.groups[slot_num];
-+ stream = &ginfo->streams[csi_index];
-+
-+ if ((cs_ack & CS_ACK_FATAL_MASK) != (cs_req & CS_REQ_FATAL_MASK)) {
-+ handle_fatal_event(queue, stream);
-+ kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_ack,
-+ CS_REQ_FATAL_MASK);
-+ }
-+
-+ if ((cs_ack & CS_ACK_FAULT_MASK) != (cs_req & CS_REQ_FAULT_MASK)) {
-+ handle_fault_event(queue, stream);
-+ kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_ack,
-+ CS_REQ_FAULT_MASK);
-+ kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, slot_num, true);
-+ }
-+}
-+
-+/**
-+ * process_cs_interrupts - Process interrupts for a CS.
-+ *
-+ * @group: Pointer to GPU command queue group data.
-+ * @ginfo: The CSG interface provided by the firmware.
-+ * @irqreq: CSG's IRQ request bitmask (one bit per CS).
-+ * @irqack: CSG's IRQ acknowledge bitmask (one bit per CS).
-+ *
-+ * If the interrupt request bitmask differs from the acknowledge bitmask
-+ * then the firmware is notifying the host of an event concerning those
-+ * CSs indicated by bits whose value differs. The actions required
-+ * are then determined by examining which notification flags differ between
-+ * the request and acknowledge registers for the individual CS(s).
-+ */
-+static void process_cs_interrupts(struct kbase_queue_group *const group,
-+ struct kbase_csf_cmd_stream_group_info const *const ginfo,
-+ u32 const irqreq, u32 const irqack)
-+{
-+ struct kbase_device *const kbdev = group->kctx->kbdev;
-+ u32 remaining = irqreq ^ irqack;
-+ bool protm_pend = false;
-+ const bool group_suspending =
-+ !kbase_csf_scheduler_group_events_enabled(kbdev, group);
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+
-+ while (remaining != 0) {
-+ int const i = ffs(remaining) - 1;
-+ struct kbase_queue *const queue = group->bound_queues[i];
-+
-+ remaining &= ~(1 << i);
-+
-+ /* The queue pointer can be NULL, but if it isn't NULL then it
-+ * cannot disappear since scheduler spinlock is held and before
-+ * freeing a bound queue it has to be first unbound which
-+ * requires scheduler spinlock.
-+ */
-+ if (queue && !WARN_ON(queue->csi_index != i)) {
-+ struct kbase_csf_cmd_stream_info const *const stream =
-+ &ginfo->streams[i];
-+ u32 const cs_req = kbase_csf_firmware_cs_input_read(
-+ stream, CS_REQ);
-+ u32 const cs_ack =
-+ kbase_csf_firmware_cs_output(stream, CS_ACK);
-+ struct workqueue_struct *wq = group->kctx->csf.wq;
-+
-+ if ((cs_req & CS_REQ_EXCEPTION_MASK) ^
-+ (cs_ack & CS_ACK_EXCEPTION_MASK)) {
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_FAULT_INTERRUPT, group, queue, cs_req ^ cs_ack);
-+ handle_queue_exception_event(queue, cs_req, cs_ack);
-+ }
-+
-+ /* PROTM_PEND and TILER_OOM can be safely ignored
-+ * because they will be raised again if the group
-+ * is assigned a CSG slot in future.
-+ */
-+ if (group_suspending) {
-+ u32 const cs_req_remain = cs_req & ~CS_REQ_EXCEPTION_MASK;
-+ u32 const cs_ack_remain = cs_ack & ~CS_ACK_EXCEPTION_MASK;
-+
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_IGNORED_INTERRUPTS_GROUP_SUSPEND,
-+ group, queue, cs_req_remain ^ cs_ack_remain);
-+ continue;
-+ }
-+
-+ if (((cs_req & CS_REQ_TILER_OOM_MASK) ^
-+ (cs_ack & CS_ACK_TILER_OOM_MASK))) {
-+ get_queue(queue);
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_TILER_OOM_INTERRUPT, group, queue,
-+ cs_req ^ cs_ack);
-+ if (WARN_ON(!queue_work(wq, &queue->oom_event_work))) {
-+ /* The work item shall not have been
-+ * already queued, there can be only
-+ * one pending OoM event for a
-+ * queue.
-+ */
-+ release_queue(queue);
-+ }
-+ }
-+
-+ if ((cs_req & CS_REQ_PROTM_PEND_MASK) ^
-+ (cs_ack & CS_ACK_PROTM_PEND_MASK)) {
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_PROTM_PEND_INTERRUPT, group, queue,
-+ cs_req ^ cs_ack);
-+
-+ dev_dbg(kbdev->dev,
-+ "Protected mode entry request for queue on csi %d bound to group-%d on slot %d",
-+ queue->csi_index, group->handle,
-+ group->csg_nr);
-+
-+ bitmap_set(group->protm_pending_bitmap, i, 1);
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, PROTM_PENDING_SET, group, queue,
-+ group->protm_pending_bitmap[0]);
-+ protm_pend = true;
-+ }
-+ }
-+ }
-+
-+ if (protm_pend)
-+ queue_work(group->kctx->csf.wq, &group->protm_event_work);
-+}
-+
-+/**
-+ * process_csg_interrupts - Process interrupts for a CSG.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @csg_nr: CSG number.
-+ *
-+ * Handles interrupts for a CSG and for CSs within it.
-+ *
-+ * If the CSG's request register value differs from its acknowledge register
-+ * then the firmware is notifying the host of an event concerning the whole
-+ * group. The actions required are then determined by examining which
-+ * notification flags differ between those two register values.
-+ *
-+ * See process_cs_interrupts() for details of per-stream interrupt handling.
-+ */
-+static void process_csg_interrupts(struct kbase_device *const kbdev,
-+ int const csg_nr)
-+{
-+ struct kbase_csf_cmd_stream_group_info *ginfo;
-+ struct kbase_queue_group *group = NULL;
-+ u32 req, ack, irqreq, irqack;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+
-+ if (WARN_ON(csg_nr >= kbdev->csf.global_iface.group_num))
-+ return;
-+
-+ KBASE_KTRACE_ADD(kbdev, CSG_INTERRUPT_PROCESS, NULL, csg_nr);
-+
-+ ginfo = &kbdev->csf.global_iface.groups[csg_nr];
-+ req = kbase_csf_firmware_csg_input_read(ginfo, CSG_REQ);
-+ ack = kbase_csf_firmware_csg_output(ginfo, CSG_ACK);
-+ irqreq = kbase_csf_firmware_csg_output(ginfo, CSG_IRQ_REQ);
-+ irqack = kbase_csf_firmware_csg_input_read(ginfo, CSG_IRQ_ACK);
-+
-+ /* There may not be any pending CSG/CS interrupts to process */
-+ if ((req == ack) && (irqreq == irqack))
-+ goto out;
-+
-+ /* Immediately set IRQ_ACK bits to be same as the IRQ_REQ bits before
-+ * examining the CS_ACK & CS_REQ bits. This would ensure that Host
-+ * doesn't misses an interrupt for the CS in the race scenario where
-+ * whilst Host is servicing an interrupt for the CS, firmware sends
-+ * another interrupt for that CS.
-+ */
-+ kbase_csf_firmware_csg_input(ginfo, CSG_IRQ_ACK, irqreq);
-+
-+ group = kbase_csf_scheduler_get_group_on_slot(kbdev, csg_nr);
-+
-+ /* The group pointer can be NULL here if interrupts for the group
-+ * (like SYNC_UPDATE, IDLE notification) were delayed and arrived
-+ * just after the suspension of group completed. However if not NULL
-+ * then the group pointer cannot disappear even if User tries to
-+ * terminate the group whilst this loop is running as scheduler
-+ * spinlock is held and for freeing a group that is resident on a CSG
-+ * slot scheduler spinlock is required.
-+ */
-+ if (!group)
-+ goto out;
-+
-+ if (WARN_ON(kbase_csf_scheduler_group_get_slot_locked(group) != csg_nr))
-+ goto out;
-+
-+ if ((req ^ ack) & CSG_REQ_SYNC_UPDATE_MASK) {
-+ kbase_csf_firmware_csg_input_mask(ginfo,
-+ CSG_REQ, ack, CSG_REQ_SYNC_UPDATE_MASK);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SYNC_UPDATE_INTERRUPT, group, req ^ ack);
-+ kbase_csf_event_signal_cpu_only(group->kctx);
-+ }
-+
-+ if ((req ^ ack) & CSG_REQ_IDLE_MASK) {
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, ack,
-+ CSG_REQ_IDLE_MASK);
-+
-+ set_bit(csg_nr, scheduler->csg_slots_idle_mask);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_SET, group,
-+ scheduler->csg_slots_idle_mask[0]);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_IDLE_INTERRUPT, group, req ^ ack);
-+ dev_dbg(kbdev->dev, "Idle notification received for Group %u on slot %d\n",
-+ group->handle, csg_nr);
-+
-+ /* Check if the scheduling tick can be advanced */
-+ if (kbase_csf_scheduler_all_csgs_idle(kbdev) &&
-+ !scheduler->gpu_idle_fw_timer_enabled) {
-+ kbase_csf_scheduler_advance_tick_nolock(kbdev);
-+ }
-+ }
-+
-+ if ((req ^ ack) & CSG_REQ_PROGRESS_TIMER_EVENT_MASK) {
-+ kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, ack,
-+ CSG_REQ_PROGRESS_TIMER_EVENT_MASK);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_PROGRESS_TIMER_INTERRUPT,
-+ group, req ^ ack);
-+ dev_info(kbdev->dev,
-+ "Timeout notification received for group %u of ctx %d_%d on slot %d\n",
-+ group->handle, group->kctx->tgid, group->kctx->id, csg_nr);
-+
-+ handle_progress_timer_event(group);
-+ }
-+
-+ process_cs_interrupts(group, ginfo, irqreq, irqack);
-+
-+out:
-+ /* group may still be NULL here */
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_INTERRUPT_PROCESS_END, group,
-+ ((u64)req ^ ack) | (((u64)irqreq ^ irqack) << 32));
-+}
-+
-+/**
-+ * process_prfcnt_interrupts - Process performance counter interrupts.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @glb_req: Global request register value.
-+ * @glb_ack: Global acknowledge register value.
-+ *
-+ * Handles interrupts issued by the firmware that relate to the performance
-+ * counters. For example, on completion of a performance counter sample. It is
-+ * expected that the scheduler spinlock is already held on calling this
-+ * function.
-+ */
-+static void process_prfcnt_interrupts(struct kbase_device *kbdev, u32 glb_req,
-+ u32 glb_ack)
-+{
-+ const struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.interrupt_lock);
-+
-+ /* Process PRFCNT_SAMPLE interrupt. */
-+ if (kbdev->csf.hwcnt.request_pending &&
-+ ((glb_req & GLB_REQ_PRFCNT_SAMPLE_MASK) ==
-+ (glb_ack & GLB_REQ_PRFCNT_SAMPLE_MASK))) {
-+ kbdev->csf.hwcnt.request_pending = false;
-+
-+ dev_dbg(kbdev->dev, "PRFCNT_SAMPLE done interrupt received.");
-+
-+ kbase_hwcnt_backend_csf_on_prfcnt_sample(
-+ &kbdev->hwcnt_gpu_iface);
-+ }
-+
-+ /* Process PRFCNT_ENABLE interrupt. */
-+ if (kbdev->csf.hwcnt.enable_pending &&
-+ ((glb_req & GLB_REQ_PRFCNT_ENABLE_MASK) ==
-+ (glb_ack & GLB_REQ_PRFCNT_ENABLE_MASK))) {
-+ kbdev->csf.hwcnt.enable_pending = false;
-+
-+ dev_dbg(kbdev->dev,
-+ "PRFCNT_ENABLE status changed interrupt received.");
-+
-+ if (glb_ack & GLB_REQ_PRFCNT_ENABLE_MASK)
-+ kbase_hwcnt_backend_csf_on_prfcnt_enable(
-+ &kbdev->hwcnt_gpu_iface);
-+ else
-+ kbase_hwcnt_backend_csf_on_prfcnt_disable(
-+ &kbdev->hwcnt_gpu_iface);
-+ }
-+
-+ /* Process PRFCNT_THRESHOLD interrupt. */
-+ if ((glb_req ^ glb_ack) & GLB_REQ_PRFCNT_THRESHOLD_MASK) {
-+ dev_dbg(kbdev->dev, "PRFCNT_THRESHOLD interrupt received.");
-+
-+ kbase_hwcnt_backend_csf_on_prfcnt_threshold(
-+ &kbdev->hwcnt_gpu_iface);
-+
-+ /* Set the GLB_REQ.PRFCNT_THRESHOLD flag back to
-+ * the same value as GLB_ACK.PRFCNT_THRESHOLD
-+ * flag in order to enable reporting of another
-+ * PRFCNT_THRESHOLD event.
-+ */
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_REQ, glb_ack,
-+ GLB_REQ_PRFCNT_THRESHOLD_MASK);
-+ }
-+
-+ /* Process PRFCNT_OVERFLOW interrupt. */
-+ if ((glb_req ^ glb_ack) & GLB_REQ_PRFCNT_OVERFLOW_MASK) {
-+ dev_dbg(kbdev->dev, "PRFCNT_OVERFLOW interrupt received.");
-+
-+ kbase_hwcnt_backend_csf_on_prfcnt_overflow(
-+ &kbdev->hwcnt_gpu_iface);
-+
-+ /* Set the GLB_REQ.PRFCNT_OVERFLOW flag back to
-+ * the same value as GLB_ACK.PRFCNT_OVERFLOW
-+ * flag in order to enable reporting of another
-+ * PRFCNT_OVERFLOW event.
-+ */
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_REQ, glb_ack,
-+ GLB_REQ_PRFCNT_OVERFLOW_MASK);
-+ }
-+}
-+
-+void kbase_csf_interrupt(struct kbase_device *kbdev, u32 val)
-+{
-+ unsigned long flags;
-+ u32 remaining = val;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ KBASE_KTRACE_ADD(kbdev, CSF_INTERRUPT, NULL, val);
-+ kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), val);
-+
-+ if (val & JOB_IRQ_GLOBAL_IF) {
-+ const struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ kbdev->csf.interrupt_received = true;
-+ remaining &= ~JOB_IRQ_GLOBAL_IF;
-+
-+ if (!kbdev->csf.firmware_reloaded)
-+ kbase_csf_firmware_reload_completed(kbdev);
-+ else if (global_iface->output) {
-+ u32 glb_req, glb_ack;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ glb_req = kbase_csf_firmware_global_input_read(
-+ global_iface, GLB_REQ);
-+ glb_ack = kbase_csf_firmware_global_output(
-+ global_iface, GLB_ACK);
-+ KBASE_KTRACE_ADD(kbdev, GLB_REQ_ACQ, NULL, glb_req ^ glb_ack);
-+
-+ if ((glb_req ^ glb_ack) & GLB_REQ_PROTM_EXIT_MASK) {
-+ dev_dbg(kbdev->dev, "Protected mode exit interrupt received");
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_REQ, glb_ack,
-+ GLB_REQ_PROTM_EXIT_MASK);
-+ WARN_ON(!kbase_csf_scheduler_protected_mode_in_use(kbdev));
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_EXIT_PROTM, scheduler->active_protm_grp, 0u);
-+ scheduler->active_protm_grp = NULL;
-+ kbdev->protected_mode = false;
-+ kbase_ipa_control_protm_exited(kbdev);
-+ kbase_hwcnt_backend_csf_protm_exited(
-+ &kbdev->hwcnt_gpu_iface);
-+ }
-+
-+ /* Handle IDLE Hysteresis notification event */
-+ if ((glb_req ^ glb_ack) & GLB_REQ_IDLE_EVENT_MASK) {
-+ int non_idle_offslot_grps;
-+ bool can_suspend_on_idle;
-+ dev_dbg(kbdev->dev, "Idle-hysteresis event flagged");
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_REQ, glb_ack,
-+ GLB_REQ_IDLE_EVENT_MASK);
-+
-+ non_idle_offslot_grps = atomic_read(&scheduler->non_idle_offslot_grps);
-+ can_suspend_on_idle = kbase_pm_idle_groups_sched_suspendable(kbdev);
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_CAN_IDLE, NULL,
-+ ((u64)(u32)non_idle_offslot_grps) | (((u64)can_suspend_on_idle) << 32));
-+
-+ if (!non_idle_offslot_grps) {
-+ if (can_suspend_on_idle)
-+ queue_work(system_highpri_wq,
-+ &scheduler->gpu_idle_work);
-+ } else {
-+ /* Advance the scheduling tick to get
-+ * the non-idle suspended groups loaded
-+ * soon.
-+ */
-+ kbase_csf_scheduler_advance_tick_nolock(
-+ kbdev);
-+ }
-+ }
-+
-+ process_prfcnt_interrupts(kbdev, glb_req, glb_ack);
-+
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ /* Invoke the MCU state machine as a state transition
-+ * might have completed.
-+ */
-+ kbase_pm_update_state(kbdev);
-+ }
-+
-+ if (!remaining) {
-+ wake_up_all(&kbdev->csf.event_wait);
-+ KBASE_KTRACE_ADD(kbdev, CSF_INTERRUPT_END, NULL, val);
-+ return;
-+ }
-+ }
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ while (remaining != 0) {
-+ int const csg_nr = ffs(remaining) - 1;
-+
-+ process_csg_interrupts(kbdev, csg_nr);
-+ remaining &= ~(1 << csg_nr);
-+ }
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ wake_up_all(&kbdev->csf.event_wait);
-+ KBASE_KTRACE_ADD(kbdev, CSF_INTERRUPT_END, NULL, val);
-+}
-+
-+void kbase_csf_doorbell_mapping_term(struct kbase_device *kbdev)
-+{
-+ if (kbdev->csf.db_filp) {
-+ struct page *page = as_page(kbdev->csf.dummy_db_page);
-+
-+ kbase_mem_pool_free(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ page, false);
-+
-+ fput(kbdev->csf.db_filp);
-+ }
-+}
-+
-+int kbase_csf_doorbell_mapping_init(struct kbase_device *kbdev)
-+{
-+ struct tagged_addr phys;
-+ struct file *filp;
-+ int ret;
-+
-+ filp = shmem_file_setup("mali csf", MAX_LFS_FILESIZE, VM_NORESERVE);
-+ if (IS_ERR(filp))
-+ return PTR_ERR(filp);
-+
-+ ret = kbase_mem_pool_alloc_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ 1, &phys, false);
-+
-+ if (ret <= 0) {
-+ fput(filp);
-+ return ret;
-+ }
-+
-+ kbdev->csf.db_filp = filp;
-+ kbdev->csf.dummy_db_page = phys;
-+ kbdev->csf.db_file_offsets = 0;
-+
-+ return 0;
-+}
-+
-+void kbase_csf_free_dummy_user_reg_page(struct kbase_device *kbdev)
-+{
-+ if (as_phys_addr_t(kbdev->csf.dummy_user_reg_page)) {
-+ struct page *page = as_page(kbdev->csf.dummy_user_reg_page);
-+
-+ kbase_mem_pool_free(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], page,
-+ false);
-+ }
-+}
-+
-+int kbase_csf_setup_dummy_user_reg_page(struct kbase_device *kbdev)
-+{
-+ struct tagged_addr phys;
-+ struct page *page;
-+ u32 *addr;
-+ int ret;
-+
-+ kbdev->csf.dummy_user_reg_page = as_tagged(0);
-+
-+ ret = kbase_mem_pool_alloc_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], 1, &phys,
-+ false);
-+
-+ if (ret <= 0)
-+ return ret;
-+
-+ page = as_page(phys);
-+ addr = kmap_atomic(page);
-+
-+ /* Write a special value for the latest flush register inside the
-+ * dummy page
-+ */
-+ addr[LATEST_FLUSH / sizeof(u32)] = POWER_DOWN_LATEST_FLUSH_VALUE;
-+
-+ kbase_sync_single_for_device(kbdev, kbase_dma_addr(page), sizeof(u32),
-+ DMA_BIDIRECTIONAL);
-+ kunmap_atomic(addr);
-+
-+ kbdev->csf.dummy_user_reg_page = phys;
-+
-+ return 0;
-+}
-+
-+u8 kbase_csf_priority_check(struct kbase_device *kbdev, u8 req_priority)
-+{
-+ struct priority_control_manager_device *pcm_device = kbdev->pcm_dev;
-+ u8 out_priority = req_priority;
-+
-+ if (pcm_device) {
-+ req_priority = kbase_csf_priority_queue_group_priority_to_relative(req_priority);
-+ out_priority = pcm_device->ops.pcm_scheduler_priority_check(pcm_device, current, req_priority);
-+ out_priority = kbase_csf_priority_relative_to_queue_group_priority(out_priority);
-+ }
-+
-+ return out_priority;
-+}
-+
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf.h
-new file mode 100644
-index 0000000..e3bd436
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf.h
-@@ -0,0 +1,564 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_H_
-+#define _KBASE_CSF_H_
-+
-+#include "mali_kbase_csf_kcpu.h"
-+#include "mali_kbase_csf_scheduler.h"
-+#include "mali_kbase_csf_firmware.h"
-+#include "mali_kbase_csf_protected_memory.h"
-+
-+/* Indicate invalid CS h/w interface
-+ */
-+#define KBASEP_IF_NR_INVALID ((s8)-1)
-+
-+/* Indicate invalid CSG number for a GPU command queue group
-+ */
-+#define KBASEP_CSG_NR_INVALID ((s8)-1)
-+
-+/* Indicate invalid user doorbell number for a GPU command queue
-+ */
-+#define KBASEP_USER_DB_NR_INVALID ((s8)-1)
-+
-+#define FIRMWARE_PING_INTERVAL_MS (4000) /* 4 seconds */
-+
-+#define FIRMWARE_IDLE_HYSTERESIS_TIME_MS (10) /* Default 10 milliseconds */
-+
-+/**
-+ * enum kbase_csf_event_callback_action - return type for CSF event callbacks.
-+ *
-+ * @KBASE_CSF_EVENT_CALLBACK_FIRST: Never set explicitly.
-+ * It doesn't correspond to any action or type of event callback.
-+ *
-+ * @KBASE_CSF_EVENT_CALLBACK_KEEP: The callback will remain registered.
-+ *
-+ * @KBASE_CSF_EVENT_CALLBACK_REMOVE: The callback will be removed
-+ * immediately upon return.
-+ *
-+ * @KBASE_CSF_EVENT_CALLBACK_LAST: Never set explicitly.
-+ * It doesn't correspond to any action or type of event callback.
-+ */
-+enum kbase_csf_event_callback_action {
-+ KBASE_CSF_EVENT_CALLBACK_FIRST = 0,
-+ KBASE_CSF_EVENT_CALLBACK_KEEP,
-+ KBASE_CSF_EVENT_CALLBACK_REMOVE,
-+ KBASE_CSF_EVENT_CALLBACK_LAST,
-+};
-+
-+/**
-+ * kbase_csf_event_callback_action - type for callback functions to be
-+ * called upon CSF events.
-+ *
-+ * This is the type of callback functions that can be registered
-+ * for CSF events. These function calls shall be triggered by any call
-+ * to kbase_csf_event_signal.
-+ *
-+ * @param: Generic parameter to pass to the callback function.
-+ *
-+ * Return: KBASE_CSF_EVENT_CALLBACK_KEEP if the callback should remain
-+ * registered, or KBASE_CSF_EVENT_CALLBACK_REMOVE if it should be removed.
-+ */
-+typedef enum kbase_csf_event_callback_action kbase_csf_event_callback(void *param);
-+
-+/**
-+ * kbase_csf_event_wait_add - Add a CSF event callback
-+ *
-+ * This function adds an event callback to the list of CSF event callbacks
-+ * belonging to a given Kbase context, to be triggered when a CSF event is
-+ * signalled by kbase_csf_event_signal.
-+ *
-+ * @kctx: The Kbase context the @callback should be registered to.
-+ * @callback: The callback function to register.
-+ * @param: Custom parameter to be passed to the @callback function.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_event_wait_add(struct kbase_context *kctx,
-+ kbase_csf_event_callback *callback, void *param);
-+
-+/**
-+ * kbase_csf_event_wait_remove - Remove a CSF event callback
-+ *
-+ * This function removes an event callback from the list of CSF event callbacks
-+ * belonging to a given Kbase context.
-+ *
-+ * @kctx: The kbase context the @callback should be removed from.
-+ * @callback: The callback function to remove.
-+ * @param: Custom parameter that would have been passed to the @p callback
-+ * function.
-+ */
-+void kbase_csf_event_wait_remove(struct kbase_context *kctx,
-+ kbase_csf_event_callback *callback, void *param);
-+
-+/**
-+ * kbase_csf_event_wait_remove_all - Removes all CSF event callbacks
-+ *
-+ * This function empties the list of CSF event callbacks belonging to a given
-+ * Kbase context.
-+ *
-+ * @kctx: The kbase context for which CSF event callbacks have to be removed.
-+ */
-+void kbase_csf_event_wait_remove_all(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_read_error - Read CS fatal error
-+ *
-+ * This function takes the CS fatal error from context's ordered
-+ * error_list, copies its contents to @event_data.
-+ *
-+ * @kctx: The kbase context to read fatal error from
-+ * @event_data: Caller-provided buffer to copy the fatal error to
-+ *
-+ * Return: true if fatal error is read successfully.
-+ */
-+bool kbase_csf_read_error(struct kbase_context *kctx,
-+ struct base_csf_notification *event_data);
-+
-+/**
-+ * kbase_csf_error_pending - Check whether fatal error is pending
-+ *
-+ * @kctx: The kbase context to check fatal error upon.
-+ *
-+ * Return: true if fatal error is pending.
-+ */
-+bool kbase_csf_error_pending(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_event_signal - Signal a CSF event
-+ *
-+ * This function triggers all the CSF event callbacks that are registered to
-+ * a given Kbase context, and also signals the event handling thread of
-+ * userspace driver waiting for the CSF event.
-+ *
-+ * @kctx: The kbase context whose CSF event callbacks shall be triggered.
-+ * @notify_gpu: Flag to indicate if CSF firmware should be notified of the
-+ * signaling of event that happened on the Driver side, either
-+ * the signal came from userspace or from kcpu queues.
-+ */
-+void kbase_csf_event_signal(struct kbase_context *kctx, bool notify_gpu);
-+
-+static inline void kbase_csf_event_signal_notify_gpu(struct kbase_context *kctx)
-+{
-+ kbase_csf_event_signal(kctx, true);
-+}
-+
-+static inline void kbase_csf_event_signal_cpu_only(struct kbase_context *kctx)
-+{
-+ kbase_csf_event_signal(kctx, false);
-+}
-+
-+/**
-+ * kbase_csf_ctx_init - Initialize the CSF interface for a GPU address space.
-+ *
-+ * @kctx: Pointer to the kbase context which is being initialized.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+int kbase_csf_ctx_init(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_ctx_handle_fault - Terminate queue groups & notify fault upon
-+ * GPU bus fault, MMU page fault or similar.
-+ *
-+ * This function terminates all GPU command queue groups in the context and
-+ * notifies the event notification thread of the fault.
-+ *
-+ * @kctx: Pointer to faulty kbase context.
-+ * @fault: Pointer to the fault.
-+ */
-+void kbase_csf_ctx_handle_fault(struct kbase_context *kctx,
-+ struct kbase_fault *fault);
-+
-+/**
-+ * kbase_csf_ctx_term - Terminate the CSF interface for a GPU address space.
-+ *
-+ * This function terminates any remaining CSGs and CSs which weren't destroyed
-+ * before context termination.
-+ *
-+ * @kctx: Pointer to the kbase context which is being terminated.
-+ */
-+void kbase_csf_ctx_term(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_queue_register - Register a GPU command queue.
-+ *
-+ * @kctx: Pointer to the kbase context within which the
-+ * queue is to be registered.
-+ * @reg: Pointer to the structure which contains details of the
-+ * queue to be registered within the provided
-+ * context.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_queue_register(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_register *reg);
-+
-+/**
-+ * kbase_csf_queue_register_ex - Register a GPU command queue with
-+ * extended format.
-+ *
-+ * @kctx: Pointer to the kbase context within which the
-+ * queue is to be registered.
-+ * @reg: Pointer to the structure which contains details of the
-+ * queue to be registered within the provided
-+ * context, together with the extended parameter fields
-+ * for supporting cs trace command.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_queue_register_ex(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_register_ex *reg);
-+
-+/**
-+ * kbase_csf_queue_terminate - Terminate a GPU command queue.
-+ *
-+ * @kctx: Pointer to the kbase context within which the
-+ * queue is to be terminated.
-+ * @term: Pointer to the structure which identifies which
-+ * queue is to be terminated.
-+ */
-+void kbase_csf_queue_terminate(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_terminate *term);
-+
-+/**
-+ * kbase_csf_alloc_command_stream_user_pages - Allocate resources for a
-+ * GPU command queue.
-+ *
-+ * This function allocates a pair of User mode input/output pages for a
-+ * GPU command queue and maps them in the shared interface segment of MCU
-+ * firmware address space. Also reserves a hardware doorbell page for the queue.
-+ *
-+ * @kctx: Pointer to the kbase context within which the resources
-+ * for the queue are being allocated.
-+ * @queue: Pointer to the queue for which to allocate resources.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_alloc_command_stream_user_pages(struct kbase_context *kctx,
-+ struct kbase_queue *queue);
-+
-+/**
-+ * kbase_csf_queue_bind - Bind a GPU command queue to a queue group.
-+ *
-+ * @kctx: The kbase context.
-+ * @bind: Pointer to the union which specifies a queue group and a
-+ * queue to be bound to that group.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_queue_bind(struct kbase_context *kctx,
-+ union kbase_ioctl_cs_queue_bind *bind);
-+
-+/**
-+ * kbase_csf_queue_unbind - Unbind a GPU command queue from a queue group
-+ * to which it has been bound and free
-+ * resources allocated for this queue if there
-+ * are any.
-+ *
-+ * @queue: Pointer to queue to be unbound.
-+ */
-+void kbase_csf_queue_unbind(struct kbase_queue *queue);
-+
-+/**
-+ * kbase_csf_queue_unbind_stopped - Unbind a GPU command queue in the case
-+ * where it was never started.
-+ * @queue: Pointer to queue to be unbound.
-+ *
-+ * Variant of kbase_csf_queue_unbind() for use on error paths for cleaning up
-+ * queues that failed to fully bind.
-+ */
-+void kbase_csf_queue_unbind_stopped(struct kbase_queue *queue);
-+
-+/**
-+ * kbase_csf_queue_kick - Schedule a GPU command queue on the firmware
-+ *
-+ * @kctx: The kbase context.
-+ * @kick: Pointer to the struct which specifies the queue
-+ * that needs to be scheduled.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_queue_kick(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_kick *kick);
-+
-+/**
-+ * kbase_csf_queue_group_handle_is_valid - Find if the given queue group handle
-+ * is valid.
-+ *
-+ * This function is used to determine if the queue group handle is valid.
-+ *
-+ * @kctx: The kbase context under which the queue group exists.
-+ * @group_handle: Handle for the group which uniquely identifies it within
-+ * the context with which it was created.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_queue_group_handle_is_valid(struct kbase_context *kctx,
-+ u8 group_handle);
-+
-+/**
-+ * kbase_csf_queue_group_create - Create a GPU command queue group.
-+ *
-+ * @kctx: Pointer to the kbase context within which the
-+ * queue group is to be created.
-+ * @create: Pointer to the structure which contains details of the
-+ * queue group which is to be created within the
-+ * provided kbase context.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_queue_group_create(struct kbase_context *kctx,
-+ union kbase_ioctl_cs_queue_group_create *create);
-+
-+/**
-+ * kbase_csf_queue_group_terminate - Terminate a GPU command queue group.
-+ *
-+ * @kctx: Pointer to the kbase context within which the
-+ * queue group is to be terminated.
-+ * @group_handle: Pointer to the structure which identifies the queue
-+ * group which is to be terminated.
-+ */
-+void kbase_csf_queue_group_terminate(struct kbase_context *kctx,
-+ u8 group_handle);
-+
-+/**
-+ * kbase_csf_term_descheduled_queue_group - Terminate a GPU command queue
-+ * group that is not operational
-+ * inside the scheduler.
-+ *
-+ * @group: Pointer to the structure which identifies the queue
-+ * group to be terminated. The function assumes that the caller
-+ * is sure that the given group is not operational inside the
-+ * scheduler. If in doubt, use its alternative:
-+ * @ref kbase_csf_queue_group_terminate().
-+ */
-+void kbase_csf_term_descheduled_queue_group(struct kbase_queue_group *group);
-+
-+/**
-+ * kbase_csf_queue_group_suspend - Suspend a GPU command queue group
-+ *
-+ * This function is used to suspend a queue group and copy the suspend buffer.
-+ *
-+ * @kctx: The kbase context for which the queue group is to be
-+ * suspended.
-+ * @sus_buf: Pointer to the structure which contains details of the
-+ * user buffer and its kernel pinned pages.
-+ * @group_handle: Handle for the group which uniquely identifies it within
-+ * the context within which it was created.
-+ *
-+ * Return: 0 on success or negative value if failed to suspend
-+ * queue group and copy suspend buffer contents.
-+ */
-+int kbase_csf_queue_group_suspend(struct kbase_context *kctx,
-+ struct kbase_suspend_copy_buffer *sus_buf, u8 group_handle);
-+
-+/**
-+ * kbase_csf_add_group_fatal_error - Report a fatal group error to userspace
-+ *
-+ * @group: GPU command queue group.
-+ * @err_payload: Error payload to report.
-+ */
-+void kbase_csf_add_group_fatal_error(
-+ struct kbase_queue_group *const group,
-+ struct base_gpu_queue_group_error const *const err_payload);
-+
-+/**
-+ * kbase_csf_interrupt - Handle interrupts issued by CSF firmware.
-+ *
-+ * @kbdev: The kbase device to handle an IRQ for
-+ * @val: The value of JOB IRQ status register which triggered the interrupt
-+ */
-+void kbase_csf_interrupt(struct kbase_device *kbdev, u32 val);
-+
-+/**
-+ * kbase_csf_doorbell_mapping_init - Initialize the fields that facilitates
-+ * the update of userspace mapping of HW
-+ * doorbell page.
-+ *
-+ * The function creates a file and allocates a dummy page to facilitate the
-+ * update of userspace mapping to point to the dummy page instead of the real
-+ * HW doorbell page after the suspend of queue group.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_doorbell_mapping_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_doorbell_mapping_term - Free the dummy page & close the file used
-+ * to update the userspace mapping of HW doorbell page
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_doorbell_mapping_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_setup_dummy_user_reg_page - Setup the dummy page that is accessed
-+ * instead of the User register page after
-+ * the GPU power down.
-+ *
-+ * The function allocates a dummy page which is used to replace the User
-+ * register page in the userspace mapping after the power down of GPU.
-+ * On the power up of GPU, the mapping is updated to point to the real
-+ * User register page. The mapping is used to allow access to LATEST_FLUSH
-+ * register from userspace.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_setup_dummy_user_reg_page(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_free_dummy_user_reg_page - Free the dummy page that was used
-+ * used to replace the User register page
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_free_dummy_user_reg_page(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_ring_csg_doorbell - ring the doorbell for a CSG interface.
-+ *
-+ * The function kicks a notification on the CSG interface to firmware.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @slot: Index of CSG interface for ringing the door-bell.
-+ */
-+void kbase_csf_ring_csg_doorbell(struct kbase_device *kbdev, int slot);
-+
-+/**
-+ * kbase_csf_ring_csg_slots_doorbell - ring the doorbell for a set of CSG
-+ * interfaces.
-+ *
-+ * The function kicks a notification on a set of CSG interfaces to firmware.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @slot_bitmap: bitmap for the given slots, slot-0 on bit-0, etc.
-+ */
-+void kbase_csf_ring_csg_slots_doorbell(struct kbase_device *kbdev,
-+ u32 slot_bitmap);
-+
-+/**
-+ * kbase_csf_ring_cs_kernel_doorbell - ring the kernel doorbell for a CSI
-+ * assigned to a GPU queue
-+ *
-+ * The function sends a doorbell interrupt notification to the firmware for
-+ * a CSI assigned to a GPU queue.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @csi_index: ID of the CSI assigned to the GPU queue.
-+ * @csg_nr: Index of the CSG slot assigned to the queue
-+ * group to which the GPU queue is bound.
-+ * @ring_csg_doorbell: Flag to indicate if the CSG doorbell needs to be rung
-+ * after updating the CSG_DB_REQ. So if this flag is false
-+ * the doorbell interrupt will not be sent to FW.
-+ * The flag is supposed be false only when the input page
-+ * for bound GPU queues is programmed at the time of
-+ * starting/resuming the group on a CSG slot.
-+ */
-+void kbase_csf_ring_cs_kernel_doorbell(struct kbase_device *kbdev,
-+ int csi_index, int csg_nr,
-+ bool ring_csg_doorbell);
-+
-+/**
-+ * kbase_csf_ring_cs_user_doorbell - ring the user doorbell allocated for a
-+ * queue.
-+ *
-+ * The function kicks a notification to the firmware on the doorbell assigned
-+ * to the queue.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @queue: Pointer to the queue for ringing the door-bell.
-+ */
-+void kbase_csf_ring_cs_user_doorbell(struct kbase_device *kbdev,
-+ struct kbase_queue *queue);
-+
-+/**
-+ * kbase_csf_active_queue_groups_reset - Reset the state of all active GPU
-+ * command queue groups associated with the context.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @kctx: The kbase context.
-+ *
-+ * This function will iterate through all the active/scheduled GPU command
-+ * queue groups associated with the context, deschedule and mark them as
-+ * terminated (which will then lead to unbinding of all the queues bound to
-+ * them) and also no more work would be allowed to execute for them.
-+ *
-+ * This is similar to the action taken in response to an unexpected OoM event.
-+ */
-+void kbase_csf_active_queue_groups_reset(struct kbase_device *kbdev,
-+ struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_priority_check - Check the priority requested
-+ *
-+ * @kbdev: Device pointer
-+ * @req_priority: Requested priority
-+ *
-+ * This will determine whether the requested priority can be satisfied.
-+ *
-+ * Return: The same or lower priority than requested.
-+ */
-+u8 kbase_csf_priority_check(struct kbase_device *kbdev, u8 req_priority);
-+
-+extern const u8 kbasep_csf_queue_group_priority_to_relative[BASE_QUEUE_GROUP_PRIORITY_COUNT];
-+extern const u8 kbasep_csf_relative_to_queue_group_priority[KBASE_QUEUE_GROUP_PRIORITY_COUNT];
-+
-+/**
-+ * kbase_csf_priority_relative_to_queue_group_priority - Convert relative to base priority
-+ *
-+ * @priority: kbase relative priority
-+ *
-+ * This will convert the monotonically increasing realtive priority to the
-+ * fixed base priority list.
-+ *
-+ * Return: base_queue_group_priority priority.
-+ */
-+static inline u8 kbase_csf_priority_relative_to_queue_group_priority(u8 priority)
-+{
-+ if (priority >= KBASE_QUEUE_GROUP_PRIORITY_COUNT)
-+ priority = KBASE_QUEUE_GROUP_PRIORITY_LOW;
-+ return kbasep_csf_relative_to_queue_group_priority[priority];
-+}
-+
-+/**
-+ * kbase_csf_priority_queue_group_priority_to_relative - Convert base priority to relative
-+ *
-+ * @priority: base_queue_group_priority priority
-+ *
-+ * This will convert the fixed base priority list to monotonically increasing realtive priority.
-+ *
-+ * Return: kbase relative priority.
-+ */
-+static inline u8 kbase_csf_priority_queue_group_priority_to_relative(u8 priority)
-+{
-+ /* Apply low priority in case of invalid priority */
-+ if (priority >= BASE_QUEUE_GROUP_PRIORITY_COUNT)
-+ priority = BASE_QUEUE_GROUP_PRIORITY_LOW;
-+ return kbasep_csf_queue_group_priority_to_relative[priority];
-+}
-+
-+
-+#endif /* _KBASE_CSF_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_cpu_queue_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_cpu_queue_debugfs.c
-new file mode 100644
-index 0000000..26637bf
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_cpu_queue_debugfs.c
-@@ -0,0 +1,191 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_csf_cpu_queue_debugfs.h"
-+#include <mali_kbase.h>
-+#include <linux/seq_file.h>
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+
-+bool kbase_csf_cpu_queue_read_dump_req(struct kbase_context *kctx,
-+ struct base_csf_notification *req)
-+{
-+ if (atomic_cmpxchg(&kctx->csf.cpu_queue.dump_req_status,
-+ BASE_CSF_CPU_QUEUE_DUMP_ISSUED,
-+ BASE_CSF_CPU_QUEUE_DUMP_PENDING) !=
-+ BASE_CSF_CPU_QUEUE_DUMP_ISSUED) {
-+ return false;
-+ }
-+
-+ req->type = BASE_CSF_NOTIFICATION_CPU_QUEUE_DUMP;
-+ return true;
-+}
-+
-+/**
-+ * kbasep_csf_cpu_queue_debugfs_show() - Print cpu queue information for per context
-+ *
-+ * @file: The seq_file for printing to
-+ * @data: The debugfs dentry private data, a pointer to kbase_context
-+ *
-+ * Return: Negative error code or 0 on success.
-+ */
-+static int kbasep_csf_cpu_queue_debugfs_show(struct seq_file *file, void *data)
-+{
-+ struct kbase_context *kctx = file->private;
-+
-+ mutex_lock(&kctx->csf.lock);
-+ if (atomic_read(&kctx->csf.cpu_queue.dump_req_status) !=
-+ BASE_CSF_CPU_QUEUE_DUMP_COMPLETE) {
-+ seq_printf(file, "Dump request already started! (try again)\n");
-+ mutex_unlock(&kctx->csf.lock);
-+ return -EBUSY;
-+ }
-+
-+ atomic_set(&kctx->csf.cpu_queue.dump_req_status, BASE_CSF_CPU_QUEUE_DUMP_ISSUED);
-+ init_completion(&kctx->csf.cpu_queue.dump_cmp);
-+ kbase_event_wakeup(kctx);
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ seq_printf(file, "CPU Queues table (version:v%u):\n", MALI_CSF_CPU_QUEUE_DEBUGFS_VERSION);
-+
-+ wait_for_completion_timeout(&kctx->csf.cpu_queue.dump_cmp,
-+ msecs_to_jiffies(3000));
-+
-+ mutex_lock(&kctx->csf.lock);
-+ if (kctx->csf.cpu_queue.buffer) {
-+ WARN_ON(atomic_read(&kctx->csf.cpu_queue.dump_req_status) !=
-+ BASE_CSF_CPU_QUEUE_DUMP_PENDING);
-+
-+ seq_printf(file, "%s\n", kctx->csf.cpu_queue.buffer);
-+
-+ kfree(kctx->csf.cpu_queue.buffer);
-+ kctx->csf.cpu_queue.buffer = NULL;
-+ kctx->csf.cpu_queue.buffer_size = 0;
-+ }
-+ else
-+ seq_printf(file, "Dump error! (time out)\n");
-+
-+ atomic_set(&kctx->csf.cpu_queue.dump_req_status,
-+ BASE_CSF_CPU_QUEUE_DUMP_COMPLETE);
-+
-+ mutex_unlock(&kctx->csf.lock);
-+ return 0;
-+}
-+
-+static int kbasep_csf_cpu_queue_debugfs_open(struct inode *in, struct file *file)
-+{
-+ return single_open(file, kbasep_csf_cpu_queue_debugfs_show, in->i_private);
-+}
-+
-+static const struct file_operations kbasep_csf_cpu_queue_debugfs_fops = {
-+ .open = kbasep_csf_cpu_queue_debugfs_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+void kbase_csf_cpu_queue_debugfs_init(struct kbase_context *kctx)
-+{
-+ struct dentry *file;
-+
-+ if (WARN_ON(!kctx || IS_ERR_OR_NULL(kctx->kctx_dentry)))
-+ return;
-+
-+ file = debugfs_create_file("cpu_queue", 0444, kctx->kctx_dentry,
-+ kctx, &kbasep_csf_cpu_queue_debugfs_fops);
-+
-+ if (IS_ERR_OR_NULL(file)) {
-+ dev_warn(kctx->kbdev->dev,
-+ "Unable to create cpu queue debugfs entry");
-+ }
-+
-+ kctx->csf.cpu_queue.buffer = NULL;
-+ kctx->csf.cpu_queue.buffer_size = 0;
-+ atomic_set(&kctx->csf.cpu_queue.dump_req_status,
-+ BASE_CSF_CPU_QUEUE_DUMP_COMPLETE);
-+}
-+
-+int kbase_csf_cpu_queue_dump(struct kbase_context *kctx,
-+ u64 buffer, size_t buf_size)
-+{
-+ int err = 0;
-+
-+ size_t alloc_size = buf_size;
-+ char *dump_buffer;
-+
-+ if (!buffer || !alloc_size)
-+ goto done;
-+
-+ alloc_size = (alloc_size + PAGE_SIZE) & ~(PAGE_SIZE - 1);
-+ dump_buffer = kzalloc(alloc_size, GFP_KERNEL);
-+ if (ZERO_OR_NULL_PTR(dump_buffer)) {
-+ err = -ENOMEM;
-+ goto done;
-+ }
-+
-+ WARN_ON(kctx->csf.cpu_queue.buffer != NULL);
-+
-+ err = copy_from_user(dump_buffer,
-+ u64_to_user_ptr(buffer),
-+ buf_size);
-+ if (err) {
-+ kfree(dump_buffer);
-+ err = -EFAULT;
-+ goto done;
-+ }
-+
-+ mutex_lock(&kctx->csf.lock);
-+
-+ kfree(kctx->csf.cpu_queue.buffer);
-+
-+ if (atomic_read(&kctx->csf.cpu_queue.dump_req_status) ==
-+ BASE_CSF_CPU_QUEUE_DUMP_PENDING) {
-+ kctx->csf.cpu_queue.buffer = dump_buffer;
-+ kctx->csf.cpu_queue.buffer_size = buf_size;
-+ complete_all(&kctx->csf.cpu_queue.dump_cmp);
-+ } else {
-+ kfree(dump_buffer);
-+ }
-+
-+ mutex_unlock(&kctx->csf.lock);
-+done:
-+ return err;
-+}
-+#else
-+/*
-+ * Stub functions for when debugfs is disabled
-+ */
-+void kbase_csf_cpu_queue_debugfs_init(struct kbase_context *kctx)
-+{
-+}
-+
-+bool kbase_csf_cpu_queue_read_dump_req(struct kbase_context *kctx,
-+ struct base_csf_notification *req)
-+{
-+ return false;
-+}
-+
-+int kbase_csf_cpu_queue_dump(struct kbase_context *kctx,
-+ u64 buffer, size_t buf_size)
-+{
-+ return 0;
-+}
-+#endif /* CONFIG_DEBUG_FS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_cpu_queue_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_cpu_queue_debugfs.h
-new file mode 100644
-index 0000000..435a993
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_cpu_queue_debugfs.h
-@@ -0,0 +1,90 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_CPU_QUEUE_DEBUGFS_H_
-+#define _KBASE_CSF_CPU_QUEUE_DEBUGFS_H_
-+
-+#include <asm/atomic.h>
-+#include <linux/types.h>
-+
-+#include "mali_kbase.h"
-+
-+/* Forward declaration */
-+struct base_csf_notification;
-+
-+#define MALI_CSF_CPU_QUEUE_DEBUGFS_VERSION 0
-+
-+/* CPU queue dump status */
-+/* Dumping is done or no dumping is in progress. */
-+#define BASE_CSF_CPU_QUEUE_DUMP_COMPLETE 0
-+/* Dumping request is pending. */
-+#define BASE_CSF_CPU_QUEUE_DUMP_PENDING 1
-+/* Dumping request is issued to Userspace */
-+#define BASE_CSF_CPU_QUEUE_DUMP_ISSUED 2
-+
-+
-+/**
-+ * kbase_csf_cpu_queue_debugfs_init() - Create a debugfs entry for per context cpu queue(s)
-+ *
-+ * @kctx: The kbase_context for which to create the debugfs entry
-+ */
-+void kbase_csf_cpu_queue_debugfs_init(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_cpu_queue_read_dump_req - Read cpu queue dump request event
-+ *
-+ * @kctx: The kbase_context which cpu queue dumpped belongs to
-+ * @req: Notification with cpu queue dump request.
-+ *
-+ * Return: true if needs CPU queue dump, or false otherwise.
-+ */
-+bool kbase_csf_cpu_queue_read_dump_req(struct kbase_context *kctx,
-+ struct base_csf_notification *req);
-+
-+/**
-+ * kbase_csf_cpu_queue_dump_needed - Check the requirement for cpu queue dump
-+ *
-+ * @kctx: The kbase_context which cpu queue dumpped belongs to
-+ *
-+ * Return: true if it needs cpu queue dump, or false otherwise.
-+ */
-+static inline bool kbase_csf_cpu_queue_dump_needed(struct kbase_context *kctx)
-+{
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+ return (atomic_read(&kctx->csf.cpu_queue.dump_req_status) ==
-+ BASE_CSF_CPU_QUEUE_DUMP_ISSUED);
-+#else
-+ return false;
-+#endif
-+}
-+
-+/**
-+ * kbase_csf_cpu_queue_dump - dump buffer containing cpu queue information to debugfs
-+ *
-+ * @kctx: The kbase_context which cpu queue dumpped belongs to
-+ * @buffer: Buffer containing the cpu queue information.
-+ * @buf_size: Buffer size.
-+ *
-+ * Return: Return 0 for dump successfully, or error code.
-+ */
-+int kbase_csf_cpu_queue_dump(struct kbase_context *kctx,
-+ u64 buffer, size_t buf_size);
-+#endif /* _KBASE_CSF_CPU_QUEUE_DEBUGFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_csg_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_csg_debugfs.c
-new file mode 100644
-index 0000000..14deb98
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_csg_debugfs.c
-@@ -0,0 +1,591 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_csf_csg_debugfs.h"
-+#include <mali_kbase.h>
-+#include <linux/seq_file.h>
-+#include <linux/delay.h>
-+#include <csf/mali_kbase_csf_trace_buffer.h>
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+#include "mali_kbase_csf_tl_reader.h"
-+
-+/**
-+ * blocked_reason_to_string() - Convert blocking reason id to a string
-+ *
-+ * @reason_id: blocked_reason
-+ *
-+ * Return: Suitable string
-+ */
-+static const char *blocked_reason_to_string(u32 reason_id)
-+{
-+ /* possible blocking reasons of a cs */
-+ static const char *const cs_blocked_reason[] = {
-+ [CS_STATUS_BLOCKED_REASON_REASON_UNBLOCKED] = "UNBLOCKED",
-+ [CS_STATUS_BLOCKED_REASON_REASON_WAIT] = "WAIT",
-+ [CS_STATUS_BLOCKED_REASON_REASON_PROGRESS_WAIT] =
-+ "PROGRESS_WAIT",
-+ [CS_STATUS_BLOCKED_REASON_REASON_SYNC_WAIT] = "SYNC_WAIT",
-+ [CS_STATUS_BLOCKED_REASON_REASON_DEFERRED] = "DEFERRED",
-+ [CS_STATUS_BLOCKED_REASON_REASON_RESOURCE] = "RESOURCE",
-+ [CS_STATUS_BLOCKED_REASON_REASON_FLUSH] = "FLUSH"
-+ };
-+
-+ if (WARN_ON(reason_id >= ARRAY_SIZE(cs_blocked_reason)))
-+ return "UNKNOWN_BLOCKED_REASON_ID";
-+
-+ return cs_blocked_reason[reason_id];
-+}
-+
-+static void kbasep_csf_scheduler_dump_active_queue_cs_status_wait(
-+ struct seq_file *file, u32 wait_status, u32 wait_sync_value,
-+ u64 wait_sync_live_value, u64 wait_sync_pointer, u32 sb_status,
-+ u32 blocked_reason)
-+{
-+#define WAITING "Waiting"
-+#define NOT_WAITING "Not waiting"
-+
-+ seq_printf(file, "SB_MASK: %d\n",
-+ CS_STATUS_WAIT_SB_MASK_GET(wait_status));
-+ seq_printf(file, "PROGRESS_WAIT: %s\n",
-+ CS_STATUS_WAIT_PROGRESS_WAIT_GET(wait_status) ?
-+ WAITING : NOT_WAITING);
-+ seq_printf(file, "PROTM_PEND: %s\n",
-+ CS_STATUS_WAIT_PROTM_PEND_GET(wait_status) ?
-+ WAITING : NOT_WAITING);
-+ seq_printf(file, "SYNC_WAIT: %s\n",
-+ CS_STATUS_WAIT_SYNC_WAIT_GET(wait_status) ?
-+ WAITING : NOT_WAITING);
-+ seq_printf(file, "WAIT_CONDITION: %s\n",
-+ CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GET(wait_status) ?
-+ "greater than" : "less or equal");
-+ seq_printf(file, "SYNC_POINTER: 0x%llx\n", wait_sync_pointer);
-+ seq_printf(file, "SYNC_VALUE: %d\n", wait_sync_value);
-+ seq_printf(file, "SYNC_LIVE_VALUE: 0x%016llx\n", wait_sync_live_value);
-+ seq_printf(file, "SB_STATUS: %u\n",
-+ CS_STATUS_SCOREBOARDS_NONZERO_GET(sb_status));
-+ seq_printf(file, "BLOCKED_REASON: %s\n",
-+ blocked_reason_to_string(CS_STATUS_BLOCKED_REASON_REASON_GET(
-+ blocked_reason)));
-+}
-+
-+static void kbasep_csf_scheduler_dump_active_cs_trace(struct seq_file *file,
-+ struct kbase_csf_cmd_stream_info const *const stream)
-+{
-+ u32 val = kbase_csf_firmware_cs_input_read(stream,
-+ CS_INSTR_BUFFER_BASE_LO);
-+ u64 addr = ((u64)kbase_csf_firmware_cs_input_read(stream,
-+ CS_INSTR_BUFFER_BASE_HI) << 32) | val;
-+ val = kbase_csf_firmware_cs_input_read(stream,
-+ CS_INSTR_BUFFER_SIZE);
-+
-+ seq_printf(file, "CS_TRACE_BUF_ADDR: 0x%16llx, SIZE: %u\n", addr, val);
-+
-+ /* Write offset variable address (pointer) */
-+ val = kbase_csf_firmware_cs_input_read(stream,
-+ CS_INSTR_BUFFER_OFFSET_POINTER_LO);
-+ addr = ((u64)kbase_csf_firmware_cs_input_read(stream,
-+ CS_INSTR_BUFFER_OFFSET_POINTER_HI) << 32) | val;
-+ seq_printf(file, "CS_TRACE_BUF_OFFSET_PTR: 0x%16llx\n", addr);
-+
-+ /* EVENT_SIZE and EVENT_STATEs */
-+ val = kbase_csf_firmware_cs_input_read(stream, CS_INSTR_CONFIG);
-+ seq_printf(file, "TRACE_EVENT_SIZE: 0x%x, TRACE_EVENT_STAES 0x%x\n",
-+ CS_INSTR_CONFIG_EVENT_SIZE_GET(val),
-+ CS_INSTR_CONFIG_EVENT_STATE_GET(val));
-+}
-+
-+/**
-+ * kbasep_csf_scheduler_dump_active_queue() - Print GPU command queue
-+ * debug information
-+ *
-+ * @file: seq_file for printing to
-+ * @queue: Address of a GPU command queue to examine
-+ */
-+static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file,
-+ struct kbase_queue *queue)
-+{
-+ u32 *addr;
-+ u64 cs_extract;
-+ u64 cs_insert;
-+ u32 cs_active;
-+ u64 wait_sync_pointer;
-+ u32 wait_status, wait_sync_value;
-+ u32 sb_status;
-+ u32 blocked_reason;
-+ struct kbase_vmap_struct *mapping;
-+ u64 *evt;
-+ u64 wait_sync_live_value;
-+
-+ if (!queue)
-+ return;
-+
-+ if (WARN_ON(queue->csi_index == KBASEP_IF_NR_INVALID ||
-+ !queue->group))
-+ return;
-+
-+ /* Ring the doorbell to have firmware update CS_EXTRACT */
-+ kbase_csf_ring_cs_user_doorbell(queue->kctx->kbdev, queue);
-+ msleep(100);
-+
-+ addr = (u32 *)queue->user_io_addr;
-+ cs_insert = addr[CS_INSERT_LO/4] | ((u64)addr[CS_INSERT_HI/4] << 32);
-+
-+ addr = (u32 *)(queue->user_io_addr + PAGE_SIZE);
-+ cs_extract = addr[CS_EXTRACT_LO/4] | ((u64)addr[CS_EXTRACT_HI/4] << 32);
-+ cs_active = addr[CS_ACTIVE/4];
-+
-+#define KBASEP_CSF_DEBUGFS_CS_HEADER_USER_IO \
-+ "Bind Idx, Ringbuf addr, Prio, Insert offset, Extract offset, Active, Doorbell\n"
-+
-+ seq_printf(file, KBASEP_CSF_DEBUGFS_CS_HEADER_USER_IO "%8d, %16llx, %4u, %16llx, %16llx, %6u, %8d\n",
-+ queue->csi_index, queue->base_addr, queue->priority,
-+ cs_insert, cs_extract, cs_active, queue->doorbell_nr);
-+
-+ /* Print status information for blocked group waiting for sync object. For on-slot queues,
-+ * if cs_trace is enabled, dump the interface's cs_trace configuration.
-+ */
-+ if (kbase_csf_scheduler_group_get_slot(queue->group) < 0) {
-+ if (CS_STATUS_WAIT_SYNC_WAIT_GET(queue->status_wait)) {
-+ wait_status = queue->status_wait;
-+ wait_sync_value = queue->sync_value;
-+ wait_sync_pointer = queue->sync_ptr;
-+ sb_status = queue->sb_status;
-+ blocked_reason = queue->blocked_reason;
-+
-+ evt = (u64 *)kbase_phy_alloc_mapping_get(queue->kctx, wait_sync_pointer, &mapping);
-+ if (evt) {
-+ wait_sync_live_value = evt[0];
-+ kbase_phy_alloc_mapping_put(queue->kctx, mapping);
-+ } else {
-+ wait_sync_live_value = U64_MAX;
-+ }
-+
-+ kbasep_csf_scheduler_dump_active_queue_cs_status_wait(
-+ file, wait_status, wait_sync_value,
-+ wait_sync_live_value, wait_sync_pointer,
-+ sb_status, blocked_reason);
-+ }
-+ } else {
-+ struct kbase_device const *const kbdev =
-+ queue->group->kctx->kbdev;
-+ struct kbase_csf_cmd_stream_group_info const *const ginfo =
-+ &kbdev->csf.global_iface.groups[queue->group->csg_nr];
-+ struct kbase_csf_cmd_stream_info const *const stream =
-+ &ginfo->streams[queue->csi_index];
-+ u64 cmd_ptr;
-+ u32 req_res;
-+
-+ if (WARN_ON(!stream))
-+ return;
-+
-+ cmd_ptr = kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_CMD_PTR_LO);
-+ cmd_ptr |= (u64)kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_CMD_PTR_HI) << 32;
-+ req_res = kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_REQ_RESOURCE);
-+
-+ seq_printf(file, "CMD_PTR: 0x%llx\n", cmd_ptr);
-+ seq_printf(file, "REQ_RESOURCE [COMPUTE]: %d\n",
-+ CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_GET(req_res));
-+ seq_printf(file, "REQ_RESOURCE [FRAGMENT]: %d\n",
-+ CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_GET(req_res));
-+ seq_printf(file, "REQ_RESOURCE [TILER]: %d\n",
-+ CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_GET(req_res));
-+ seq_printf(file, "REQ_RESOURCE [IDVS]: %d\n",
-+ CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_GET(req_res));
-+
-+ wait_status = kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_WAIT);
-+ wait_sync_value = kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_WAIT_SYNC_VALUE);
-+ wait_sync_pointer = kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_WAIT_SYNC_POINTER_LO);
-+ wait_sync_pointer |= (u64)kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_WAIT_SYNC_POINTER_HI) << 32;
-+
-+ sb_status = kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_SCOREBOARDS);
-+ blocked_reason = kbase_csf_firmware_cs_output(
-+ stream, CS_STATUS_BLOCKED_REASON);
-+
-+ evt = (u64 *)kbase_phy_alloc_mapping_get(queue->kctx, wait_sync_pointer, &mapping);
-+ if (evt) {
-+ wait_sync_live_value = evt[0];
-+ kbase_phy_alloc_mapping_put(queue->kctx, mapping);
-+ } else {
-+ wait_sync_live_value = U64_MAX;
-+ }
-+
-+ kbasep_csf_scheduler_dump_active_queue_cs_status_wait(
-+ file, wait_status, wait_sync_value,
-+ wait_sync_live_value, wait_sync_pointer, sb_status,
-+ blocked_reason);
-+ /* Dealing with cs_trace */
-+ if (kbase_csf_scheduler_queue_has_trace(queue))
-+ kbasep_csf_scheduler_dump_active_cs_trace(file, stream);
-+ else
-+ seq_puts(file, "NO CS_TRACE\n");
-+ }
-+
-+ seq_puts(file, "\n");
-+}
-+
-+/* Waiting timeout for STATUS_UPDATE acknowledgment, in milliseconds */
-+#define CSF_STATUS_UPDATE_TO_MS (100)
-+
-+static void kbasep_csf_scheduler_dump_active_group(struct seq_file *file,
-+ struct kbase_queue_group *const group)
-+{
-+ if (kbase_csf_scheduler_group_get_slot(group) >= 0) {
-+ struct kbase_device *const kbdev = group->kctx->kbdev;
-+ unsigned long flags;
-+ u32 ep_c, ep_r;
-+ char exclusive;
-+ struct kbase_csf_cmd_stream_group_info const *const ginfo =
-+ &kbdev->csf.global_iface.groups[group->csg_nr];
-+ long remaining =
-+ kbase_csf_timeout_in_jiffies(CSF_STATUS_UPDATE_TO_MS);
-+ u8 slot_priority =
-+ kbdev->csf.scheduler.csg_slots[group->csg_nr].priority;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ,
-+ ~kbase_csf_firmware_csg_output(ginfo, CSG_ACK),
-+ CSG_REQ_STATUS_UPDATE_MASK);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+ kbase_csf_ring_csg_doorbell(kbdev, group->csg_nr);
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ !((kbase_csf_firmware_csg_input_read(ginfo, CSG_REQ) ^
-+ kbase_csf_firmware_csg_output(ginfo, CSG_ACK)) &
-+ CSG_REQ_STATUS_UPDATE_MASK), remaining);
-+
-+ ep_c = kbase_csf_firmware_csg_output(ginfo,
-+ CSG_STATUS_EP_CURRENT);
-+ ep_r = kbase_csf_firmware_csg_output(ginfo, CSG_STATUS_EP_REQ);
-+
-+ if (CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_GET(ep_r))
-+ exclusive = 'C';
-+ else if (CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_GET(ep_r))
-+ exclusive = 'F';
-+ else
-+ exclusive = '0';
-+
-+ if (!remaining) {
-+ dev_err(kbdev->dev,
-+ "Timed out for STATUS_UPDATE on group %d on slot %d",
-+ group->handle, group->csg_nr);
-+
-+ seq_printf(file, "*** Warn: Timed out for STATUS_UPDATE on slot %d\n",
-+ group->csg_nr);
-+ seq_printf(file, "*** The following group-record is likely stale\n");
-+ }
-+
-+ seq_puts(file, "GroupID, CSG NR, CSG Prio, Run State, Priority, C_EP(Alloc/Req), F_EP(Alloc/Req), T_EP(Alloc/Req), Exclusive\n");
-+ seq_printf(file, "%7d, %6d, %8d, %9d, %8d, %11d/%3d, %11d/%3d, %11d/%3d, %9c\n",
-+ group->handle,
-+ group->csg_nr,
-+ slot_priority,
-+ group->run_state,
-+ group->priority,
-+ CSG_STATUS_EP_CURRENT_COMPUTE_EP_GET(ep_c),
-+ CSG_STATUS_EP_REQ_COMPUTE_EP_GET(ep_r),
-+ CSG_STATUS_EP_CURRENT_FRAGMENT_EP_GET(ep_c),
-+ CSG_STATUS_EP_REQ_FRAGMENT_EP_GET(ep_r),
-+ CSG_STATUS_EP_CURRENT_TILER_EP_GET(ep_c),
-+ CSG_STATUS_EP_REQ_TILER_EP_GET(ep_r),
-+ exclusive);
-+ } else {
-+ seq_puts(file, "GroupID, CSG NR, Run State, Priority\n");
-+ seq_printf(file, "%7d, %6d, %9d, %8d\n",
-+ group->handle,
-+ group->csg_nr,
-+ group->run_state,
-+ group->priority);
-+ }
-+
-+ if (group->run_state != KBASE_CSF_GROUP_TERMINATED) {
-+ unsigned int i;
-+
-+ seq_puts(file, "Bound queues:\n");
-+
-+ for (i = 0; i < MAX_SUPPORTED_STREAMS_PER_GROUP; i++) {
-+ kbasep_csf_scheduler_dump_active_queue(file,
-+ group->bound_queues[i]);
-+ }
-+ }
-+
-+ seq_puts(file, "\n");
-+}
-+
-+/**
-+ * kbasep_csf_queue_group_debugfs_show() - Print per-context GPU command queue
-+ * group debug information
-+ *
-+ * @file: The seq_file for printing to
-+ * @data: The debugfs dentry private data, a pointer to kbase context
-+ *
-+ * Return: Negative error code or 0 on success.
-+ */
-+static int kbasep_csf_queue_group_debugfs_show(struct seq_file *file,
-+ void *data)
-+{
-+ u32 gr;
-+ struct kbase_context *const kctx = file->private;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+
-+ if (WARN_ON(!kctx))
-+ return -EINVAL;
-+
-+ seq_printf(file, "MALI_CSF_CSG_DEBUGFS_VERSION: v%u\n",
-+ MALI_CSF_CSG_DEBUGFS_VERSION);
-+
-+ mutex_lock(&kctx->csf.lock);
-+ kbase_csf_scheduler_lock(kbdev);
-+ for (gr = 0; gr < MAX_QUEUE_GROUP_NUM; gr++) {
-+ struct kbase_queue_group *const group =
-+ kctx->csf.queue_groups[gr];
-+
-+ if (group)
-+ kbasep_csf_scheduler_dump_active_group(file, group);
-+ }
-+ kbase_csf_scheduler_unlock(kbdev);
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ return 0;
-+}
-+
-+/**
-+ * kbasep_csf_scheduler_dump_active_groups() - Print debug info for active
-+ * GPU command queue groups
-+ *
-+ * @file: The seq_file for printing to
-+ * @data: The debugfs dentry private data, a pointer to kbase_device
-+ *
-+ * Return: Negative error code or 0 on success.
-+ */
-+static int kbasep_csf_scheduler_dump_active_groups(struct seq_file *file,
-+ void *data)
-+{
-+ u32 csg_nr;
-+ struct kbase_device *kbdev = file->private;
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+
-+ seq_printf(file, "MALI_CSF_CSG_DEBUGFS_VERSION: v%u\n",
-+ MALI_CSF_CSG_DEBUGFS_VERSION);
-+
-+ kbase_csf_scheduler_lock(kbdev);
-+ for (csg_nr = 0; csg_nr < num_groups; csg_nr++) {
-+ struct kbase_queue_group *const group =
-+ kbdev->csf.scheduler.csg_slots[csg_nr].resident_group;
-+
-+ if (!group)
-+ continue;
-+
-+ seq_printf(file, "\nCtx %d_%d\n", group->kctx->tgid,
-+ group->kctx->id);
-+
-+ kbasep_csf_scheduler_dump_active_group(file, group);
-+ }
-+ kbase_csf_scheduler_unlock(kbdev);
-+
-+ return 0;
-+}
-+
-+static int kbasep_csf_queue_group_debugfs_open(struct inode *in,
-+ struct file *file)
-+{
-+ return single_open(file, kbasep_csf_queue_group_debugfs_show,
-+ in->i_private);
-+}
-+
-+static int kbasep_csf_active_queue_groups_debugfs_open(struct inode *in,
-+ struct file *file)
-+{
-+ return single_open(file, kbasep_csf_scheduler_dump_active_groups,
-+ in->i_private);
-+}
-+
-+static const struct file_operations kbasep_csf_queue_group_debugfs_fops = {
-+ .open = kbasep_csf_queue_group_debugfs_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+void kbase_csf_queue_group_debugfs_init(struct kbase_context *kctx)
-+{
-+ struct dentry *file;
-+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
-+ const mode_t mode = 0444;
-+#else
-+ const mode_t mode = 0400;
-+#endif
-+
-+ if (WARN_ON(!kctx || IS_ERR_OR_NULL(kctx->kctx_dentry)))
-+ return;
-+
-+ file = debugfs_create_file("groups", mode,
-+ kctx->kctx_dentry, kctx, &kbasep_csf_queue_group_debugfs_fops);
-+
-+ if (IS_ERR_OR_NULL(file)) {
-+ dev_warn(kctx->kbdev->dev,
-+ "Unable to create per context queue groups debugfs entry");
-+ }
-+}
-+
-+static const struct file_operations
-+ kbasep_csf_active_queue_groups_debugfs_fops = {
-+ .open = kbasep_csf_active_queue_groups_debugfs_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+static int kbasep_csf_debugfs_scheduling_timer_enabled_get(
-+ void *data, u64 *val)
-+{
-+ struct kbase_device *const kbdev = data;
-+
-+ *val = kbase_csf_scheduler_timer_is_enabled(kbdev);
-+
-+ return 0;
-+}
-+
-+static int kbasep_csf_debugfs_scheduling_timer_enabled_set(
-+ void *data, u64 val)
-+{
-+ struct kbase_device *const kbdev = data;
-+
-+ kbase_csf_scheduler_timer_set_enabled(kbdev, val != 0);
-+
-+ return 0;
-+}
-+
-+static int kbasep_csf_debugfs_scheduling_timer_kick_set(
-+ void *data, u64 val)
-+{
-+ struct kbase_device *const kbdev = data;
-+
-+ kbase_csf_scheduler_kick(kbdev);
-+
-+ return 0;
-+}
-+
-+DEFINE_SIMPLE_ATTRIBUTE(kbasep_csf_debugfs_scheduling_timer_enabled_fops,
-+ &kbasep_csf_debugfs_scheduling_timer_enabled_get,
-+ &kbasep_csf_debugfs_scheduling_timer_enabled_set,
-+ "%llu\n");
-+DEFINE_SIMPLE_ATTRIBUTE(kbasep_csf_debugfs_scheduling_timer_kick_fops,
-+ NULL,
-+ &kbasep_csf_debugfs_scheduling_timer_kick_set,
-+ "%llu\n");
-+
-+/**
-+ * kbase_csf_debugfs_scheduler_suspend_get() - get if the scheduler is suspended.
-+ *
-+ * @data: The debugfs dentry private data, a pointer to kbase_device
-+ * @val: The debugfs output value, boolean: 1 suspended, 0 otherwise
-+ *
-+ * Return: 0
-+ */
-+static int kbase_csf_debugfs_scheduler_suspend_get(
-+ void *data, u64 *val)
-+{
-+ struct kbase_device *kbdev = data;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ kbase_csf_scheduler_lock(kbdev);
-+ *val = (scheduler->state == SCHED_SUSPENDED);
-+ kbase_csf_scheduler_unlock(kbdev);
-+
-+ return 0;
-+}
-+
-+/**
-+ * kbase_csf_debugfs_scheduler_suspend_set() - set the scheduler to suspended.
-+ *
-+ * @data: The debugfs dentry private data, a pointer to kbase_device
-+ * @val: The debugfs input value, boolean: 1 suspend, 0 otherwise
-+ *
-+ * Return: Negative value if already in requested state, 0 otherwise.
-+ */
-+static int kbase_csf_debugfs_scheduler_suspend_set(
-+ void *data, u64 val)
-+{
-+ struct kbase_device *kbdev = data;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ enum kbase_csf_scheduler_state state;
-+
-+ kbase_csf_scheduler_lock(kbdev);
-+ state = scheduler->state;
-+ kbase_csf_scheduler_unlock(kbdev);
-+
-+ if (val && (state != SCHED_SUSPENDED))
-+ kbase_csf_scheduler_pm_suspend(kbdev);
-+ else if (!val && (state == SCHED_SUSPENDED))
-+ kbase_csf_scheduler_pm_resume(kbdev);
-+ else
-+ return -1;
-+
-+ return 0;
-+}
-+
-+DEFINE_SIMPLE_ATTRIBUTE(kbasep_csf_debugfs_scheduler_suspend_fops,
-+ &kbase_csf_debugfs_scheduler_suspend_get,
-+ &kbase_csf_debugfs_scheduler_suspend_set,
-+ "%llu\n");
-+
-+void kbase_csf_debugfs_init(struct kbase_device *kbdev)
-+{
-+ debugfs_create_file("active_groups", 0444,
-+ kbdev->mali_debugfs_directory, kbdev,
-+ &kbasep_csf_active_queue_groups_debugfs_fops);
-+
-+ debugfs_create_file("scheduling_timer_enabled", 0644,
-+ kbdev->mali_debugfs_directory, kbdev,
-+ &kbasep_csf_debugfs_scheduling_timer_enabled_fops);
-+ debugfs_create_file("scheduling_timer_kick", 0200,
-+ kbdev->mali_debugfs_directory, kbdev,
-+ &kbasep_csf_debugfs_scheduling_timer_kick_fops);
-+ debugfs_create_file("scheduler_suspend", 0644,
-+ kbdev->mali_debugfs_directory, kbdev,
-+ &kbasep_csf_debugfs_scheduler_suspend_fops);
-+
-+ kbase_csf_tl_reader_debugfs_init(kbdev);
-+ kbase_csf_firmware_trace_buffer_debugfs_init(kbdev);
-+}
-+
-+#else
-+/*
-+ * Stub functions for when debugfs is disabled
-+ */
-+void kbase_csf_queue_group_debugfs_init(struct kbase_context *kctx)
-+{
-+}
-+
-+void kbase_csf_debugfs_init(struct kbase_device *kbdev)
-+{
-+}
-+
-+#endif /* CONFIG_DEBUG_FS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_csg_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_csg_debugfs.h
-new file mode 100644
-index 0000000..397e657
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_csg_debugfs.h
-@@ -0,0 +1,47 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_CSG_DEBUGFS_H_
-+#define _KBASE_CSF_CSG_DEBUGFS_H_
-+
-+/* Forward declarations */
-+struct kbase_device;
-+struct kbase_context;
-+struct kbase_queue_group;
-+
-+#define MALI_CSF_CSG_DEBUGFS_VERSION 0
-+
-+/**
-+ * kbase_csf_queue_group_debugfs_init() - Add debugfs entry for queue groups
-+ * associated with @kctx.
-+ *
-+ * @kctx: Pointer to kbase_context
-+ */
-+void kbase_csf_queue_group_debugfs_init(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_debugfs_init() - Add a global debugfs entry for queue groups
-+ *
-+ * @kbdev: Pointer to the device
-+ */
-+void kbase_csf_debugfs_init(struct kbase_device *kbdev);
-+
-+#endif /* _KBASE_CSF_CSG_DEBUGFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_defs.h
-new file mode 100644
-index 0000000..53526ce
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_defs.h
-@@ -0,0 +1,1254 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/* Definitions (types, defines, etcs) common to the CSF.
-+ * They are placed here to allow the hierarchy of header files to work.
-+ */
-+
-+#ifndef _KBASE_CSF_DEFS_H_
-+#define _KBASE_CSF_DEFS_H_
-+
-+#include <linux/types.h>
-+#include <linux/wait.h>
-+
-+#include "mali_kbase_csf_firmware.h"
-+
-+/* Maximum number of KCPU command queues to be created per GPU address space.
-+ */
-+#define KBASEP_MAX_KCPU_QUEUES ((size_t)256)
-+
-+/* Maximum number of GPU command queue groups to be created per GPU address
-+ * space.
-+ */
-+#define MAX_QUEUE_GROUP_NUM (256)
-+
-+/* Maximum number of GPU tiler heaps to allow to be created per GPU address
-+ * space.
-+ */
-+#define MAX_TILER_HEAPS (128)
-+
-+#define CSF_FIRMWARE_ENTRY_READ (1ul << 0)
-+#define CSF_FIRMWARE_ENTRY_WRITE (1ul << 1)
-+#define CSF_FIRMWARE_ENTRY_EXECUTE (1ul << 2)
-+#define CSF_FIRMWARE_ENTRY_CACHE_MODE (3ul << 3)
-+#define CSF_FIRMWARE_ENTRY_PROTECTED (1ul << 5)
-+#define CSF_FIRMWARE_ENTRY_SHARED (1ul << 30)
-+#define CSF_FIRMWARE_ENTRY_ZERO (1ul << 31)
-+
-+/**
-+ * enum kbase_csf_bind_state - bind state of the queue
-+ *
-+ * @KBASE_CSF_QUEUE_UNBOUND: Set when the queue is registered or when the link
-+ * between queue and the group to which it was bound or being bound is removed.
-+ * @KBASE_CSF_QUEUE_BIND_IN_PROGRESS: Set when the first part of bind operation
-+ * has completed i.e. CS_QUEUE_BIND ioctl.
-+ * @KBASE_CSF_QUEUE_BOUND: Set when the bind operation has completed i.e. IO
-+ * pages have been mapped in the process address space.
-+ */
-+enum kbase_csf_queue_bind_state {
-+ KBASE_CSF_QUEUE_UNBOUND,
-+ KBASE_CSF_QUEUE_BIND_IN_PROGRESS,
-+ KBASE_CSF_QUEUE_BOUND,
-+};
-+
-+/**
-+ * enum kbase_csf_reset_gpu_state - state of the gpu reset
-+ *
-+ * @KBASE_CSF_RESET_GPU_NOT_PENDING: Set when the GPU reset isn't pending
-+ *
-+ * @KBASE_CSF_RESET_GPU_PREPARED: Set when kbase_prepare_to_reset_gpu() has
-+ * been called. This is just for debugging checks to encourage callers to call
-+ * kbase_prepare_to_reset_gpu() before kbase_reset_gpu().
-+ *
-+ * @KBASE_CSF_RESET_GPU_COMMITTED: Set when the GPU reset process has been
-+ * committed and so will definitely happen, but the procedure to reset the GPU
-+ * has not yet begun. Other threads must finish accessing the HW before we
-+ * reach %KBASE_CSF_RESET_GPU_HAPPENING.
-+ *
-+ * @KBASE_CSF_RESET_GPU_HAPPENING: Set when the GPU reset process is occurring
-+ * (silent or otherwise), and is actively accessing the HW. Any changes to the
-+ * HW in other threads might get lost, overridden, or corrupted.
-+ *
-+ * @KBASE_CSF_RESET_GPU_COMMITTED_SILENT: Set when the GPU reset process has
-+ * been committed but has not started happening. This is used when resetting
-+ * the GPU as part of normal behavior (e.g. when exiting protected mode).
-+ * Other threads must finish accessing the HW before we reach
-+ * %KBASE_CSF_RESET_GPU_HAPPENING.
-+ *
-+ * @KBASE_CSF_RESET_GPU_FAILED: Set when an error is encountered during the
-+ * GPU reset process. No more work could then be executed on GPU, unloading
-+ * the Driver module is the only option.
-+ */
-+enum kbase_csf_reset_gpu_state {
-+ KBASE_CSF_RESET_GPU_NOT_PENDING,
-+ KBASE_CSF_RESET_GPU_PREPARED,
-+ KBASE_CSF_RESET_GPU_COMMITTED,
-+ KBASE_CSF_RESET_GPU_HAPPENING,
-+ KBASE_CSF_RESET_GPU_COMMITTED_SILENT,
-+ KBASE_CSF_RESET_GPU_FAILED,
-+};
-+
-+/**
-+ * enum kbase_csf_group_state - state of the GPU command queue group
-+ *
-+ * @KBASE_CSF_GROUP_INACTIVE: Group is inactive and won't be
-+ * considered by scheduler for running on
-+ * CSG slot.
-+ * @KBASE_CSF_GROUP_RUNNABLE: Group is in the list of runnable groups
-+ * and is subjected to time-slice based
-+ * scheduling. A start request would be
-+ * sent (or already has been sent) if the
-+ * group is assigned the CS
-+ * group slot for the fist time.
-+ * @KBASE_CSF_GROUP_IDLE: Group is currently on a CSG slot
-+ * but all the CSs bound to the group have
-+ * become either idle or waiting on sync
-+ * object.
-+ * Group could be evicted from the slot on
-+ * the next tick if there are no spare
-+ * slots left after scheduling non-idle
-+ * queue groups. If the group is kept on
-+ * slot then it would be moved to the
-+ * RUNNABLE state, also if one of the
-+ * queues bound to the group is kicked it
-+ * would be moved to the RUNNABLE state.
-+ * If the group is evicted from the slot it
-+ * would be moved to either
-+ * KBASE_CSF_GROUP_SUSPENDED_ON_IDLE or
-+ * KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC
-+ * state.
-+ * @KBASE_CSF_GROUP_SUSPENDED: Group was evicted from the CSG slot
-+ * and is not running but is still in the
-+ * list of runnable groups and subjected
-+ * to time-slice based scheduling. A resume
-+ * request would be sent when a CSG slot is
-+ * re-assigned to the group and once the
-+ * resume is complete group would be moved
-+ * back to the RUNNABLE state.
-+ * @KBASE_CSF_GROUP_SUSPENDED_ON_IDLE: Same as KBASE_CSF_GROUP_SUSPENDED except
-+ * that queue group also became idle before
-+ * the suspension. This state helps
-+ * Scheduler avoid scheduling the idle
-+ * groups over the non-idle groups in the
-+ * subsequent ticks. If one of the queues
-+ * bound to the group is kicked it would be
-+ * moved to the SUSPENDED state.
-+ * @KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC: Same as GROUP_SUSPENDED_ON_IDLE
-+ * except that at least one CS
-+ * bound to this group was
-+ * waiting for synchronization object
-+ * before the suspension.
-+ * @KBASE_CSF_GROUP_FAULT_EVICTED: Group is evicted from the scheduler due
-+ * to a fault condition, pending to be
-+ * terminated.
-+ * @KBASE_CSF_GROUP_TERMINATED: Group is no longer schedulable and is
-+ * pending to be deleted by Client, all the
-+ * queues bound to it have been unbound.
-+ */
-+enum kbase_csf_group_state {
-+ KBASE_CSF_GROUP_INACTIVE,
-+ KBASE_CSF_GROUP_RUNNABLE,
-+ KBASE_CSF_GROUP_IDLE,
-+ KBASE_CSF_GROUP_SUSPENDED,
-+ KBASE_CSF_GROUP_SUSPENDED_ON_IDLE,
-+ KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC,
-+ KBASE_CSF_GROUP_FAULT_EVICTED,
-+ KBASE_CSF_GROUP_TERMINATED,
-+};
-+
-+/**
-+ * enum kbase_csf_csg_slot_state - state of the command queue group slots under
-+ * the scheduler control.
-+ *
-+ * @CSG_SLOT_READY: The slot is clean and ready to be programmed with a
-+ * queue group.
-+ * @CSG_SLOT_READY2RUN: The slot has been programmed with a queue group, i.e. a
-+ * start or resume request has been sent to the firmware.
-+ * @CSG_SLOT_RUNNING: The queue group is running on the slot, acknowledgment
-+ * of a start or resume request has been obtained from the
-+ * firmware.
-+ * @CSG_SLOT_DOWN2STOP: The suspend or terminate request for the queue group on
-+ * the slot has been sent to the firmware.
-+ * @CSG_SLOT_STOPPED: The queue group is removed from the slot, acknowledgment
-+ * of suspend or terminate request has been obtained from
-+ * the firmware.
-+ * @CSG_SLOT_READY2RUN_TIMEDOUT: The start or resume request sent on the slot
-+ * for the queue group timed out.
-+ * @CSG_SLOT_DOWN2STOP_TIMEDOUT: The suspend or terminate request for queue
-+ * group on the slot timed out.
-+ */
-+enum kbase_csf_csg_slot_state {
-+ CSG_SLOT_READY,
-+ CSG_SLOT_READY2RUN,
-+ CSG_SLOT_RUNNING,
-+ CSG_SLOT_DOWN2STOP,
-+ CSG_SLOT_STOPPED,
-+ CSG_SLOT_READY2RUN_TIMEDOUT,
-+ CSG_SLOT_DOWN2STOP_TIMEDOUT,
-+};
-+
-+/**
-+ * enum kbase_csf_scheduler_state - state of the scheduler operational phases.
-+ *
-+ * @SCHED_BUSY: The scheduler is busy performing on tick schedule
-+ * operations, the state of CSG slots
-+ * can't be changed.
-+ * @SCHED_INACTIVE: The scheduler is inactive, it is allowed to modify the
-+ * state of CSG slots by in-cycle
-+ * priority scheduling.
-+ * @SCHED_SUSPENDED: The scheduler is in low-power mode with scheduling
-+ * operations suspended and is not holding the power
-+ * management reference. This can happen if the GPU
-+ * becomes idle for a duration exceeding a threshold,
-+ * or due to a system triggered suspend action.
-+ */
-+enum kbase_csf_scheduler_state {
-+ SCHED_BUSY,
-+ SCHED_INACTIVE,
-+ SCHED_SUSPENDED,
-+};
-+
-+/**
-+ * enum kbase_queue_group_priority - Kbase internal relative priority list.
-+ *
-+ * @KBASE_QUEUE_GROUP_PRIORITY_REALTIME: The realtime queue group priority.
-+ * @KBASE_QUEUE_GROUP_PRIORITY_HIGH: The high queue group priority.
-+ * @KBASE_QUEUE_GROUP_PRIORITY_MEDIUM: The medium queue group priority.
-+ * @KBASE_QUEUE_GROUP_PRIORITY_LOW: The low queue group priority.
-+ * @KBASE_QUEUE_GROUP_PRIORITY_COUNT: The number of priority levels.
-+ */
-+enum kbase_queue_group_priority {
-+ KBASE_QUEUE_GROUP_PRIORITY_REALTIME = 0,
-+ KBASE_QUEUE_GROUP_PRIORITY_HIGH,
-+ KBASE_QUEUE_GROUP_PRIORITY_MEDIUM,
-+ KBASE_QUEUE_GROUP_PRIORITY_LOW,
-+ KBASE_QUEUE_GROUP_PRIORITY_COUNT
-+};
-+
-+
-+/**
-+ * struct kbase_csf_notification - Event or error generated as part of command
-+ * queue execution
-+ *
-+ * @data: Event or error data returned to userspace
-+ * @link: Link to the linked list, &struct_kbase_csf_context.error_list.
-+ */
-+struct kbase_csf_notification {
-+ struct base_csf_notification data;
-+ struct list_head link;
-+};
-+
-+/**
-+ * struct kbase_queue - Object representing a GPU command queue.
-+ *
-+ * @kctx: Pointer to the base context with which this GPU command queue
-+ * is associated.
-+ * @reg: Pointer to the region allocated from the shared
-+ * interface segment for mapping the User mode
-+ * input/output pages in MCU firmware address space.
-+ * @phys: Pointer to the physical pages allocated for the
-+ * pair or User mode input/output page
-+ * @user_io_addr: Pointer to the permanent kernel mapping of User mode
-+ * input/output pages. The pages can be accessed through
-+ * the mapping without any cache maintenance.
-+ * @handle: Handle returned with bind ioctl for creating a
-+ * contiguous User mode mapping of input/output pages &
-+ * the hardware doorbell page.
-+ * @doorbell_nr: Index of the hardware doorbell page assigned to the
-+ * queue.
-+ * @db_file_offset: File offset value that is assigned to userspace mapping
-+ * created on bind to access the doorbell page.
-+ * It is in page units.
-+ * @link: Link to the linked list of GPU command queues created per
-+ * GPU address space.
-+ * @refcount: Reference count, stands for the number of times the queue
-+ * has been referenced. The reference is taken when it is
-+ * created, when it is bound to the group and also when the
-+ * @oom_event_work work item is queued
-+ * for it.
-+ * @group: Pointer to the group to which this queue is bound.
-+ * @queue_reg: Pointer to the VA region allocated for CS buffer.
-+ * @oom_event_work: Work item corresponding to the out of memory event for
-+ * chunked tiler heap being used for this queue.
-+ * @base_addr: Base address of the CS buffer.
-+ * @size: Size of the CS buffer.
-+ * @priority: Priority of this queue within the group.
-+ * @bind_state: Bind state of the queue as enum @kbase_csf_queue_bind_state
-+ * @csi_index: The ID of the assigned CS hardware interface.
-+ * @enabled: Indicating whether the CS is running, or not.
-+ * @status_wait: Value of CS_STATUS_WAIT register of the CS will
-+ * be kept when the CS gets blocked by sync wait.
-+ * CS_STATUS_WAIT provides information on conditions queue is
-+ * blocking on. This is set when the group, to which queue is
-+ * bound, is suspended after getting blocked, i.e. in
-+ * KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC state.
-+ * @sync_ptr: Value of CS_STATUS_WAIT_SYNC_POINTER register of the CS
-+ * will be kept when the CS gets blocked by
-+ * sync wait. CS_STATUS_WAIT_SYNC_POINTER contains the address
-+ * of synchronization object being waited on.
-+ * Valid only when @status_wait is set.
-+ * @sync_value: Value of CS_STATUS_WAIT_SYNC_VALUE register of the CS
-+ * will be kept when the CS gets blocked by
-+ * sync wait. CS_STATUS_WAIT_SYNC_VALUE contains the value
-+ * tested against the synchronization object.
-+ * Valid only when @status_wait is set.
-+ * @sb_status: Value indicates which of the scoreboard entries in the queue
-+ * are non-zero
-+ * @blocked_reason: Value shows if the queue is blocked, and if so,
-+ * the reason why it is blocked
-+ * @trace_buffer_base: CS trace buffer base address.
-+ * @trace_offset_ptr: Pointer to the CS trace buffer offset variable.
-+ * @trace_buffer_size: CS trace buffer size for the queue.
-+ * @trace_cfg: CS trace configuration parameters.
-+ * @error: GPU command queue fatal information to pass to user space.
-+ * @fatal_event_work: Work item to handle the CS fatal event reported for this
-+ * queue.
-+ * @cs_fatal_info: Records additional information about the CS fatal event.
-+ * @cs_fatal: Records information about the CS fatal event.
-+ */
-+struct kbase_queue {
-+ struct kbase_context *kctx;
-+ struct kbase_va_region *reg;
-+ struct tagged_addr phys[2];
-+ char *user_io_addr;
-+ u64 handle;
-+ int doorbell_nr;
-+ unsigned long db_file_offset;
-+ struct list_head link;
-+ atomic_t refcount;
-+ struct kbase_queue_group *group;
-+ struct kbase_va_region *queue_reg;
-+ struct work_struct oom_event_work;
-+ u64 base_addr;
-+ u32 size;
-+ u8 priority;
-+ s8 csi_index;
-+ enum kbase_csf_queue_bind_state bind_state;
-+ bool enabled;
-+ u32 status_wait;
-+ u64 sync_ptr;
-+ u32 sync_value;
-+ u32 sb_status;
-+ u32 blocked_reason;
-+ u64 trace_buffer_base;
-+ u64 trace_offset_ptr;
-+ u32 trace_buffer_size;
-+ u32 trace_cfg;
-+ struct kbase_csf_notification error;
-+ struct work_struct fatal_event_work;
-+ u64 cs_fatal_info;
-+ u32 cs_fatal;
-+};
-+
-+/**
-+ * struct kbase_normal_suspend_buffer - Object representing a normal
-+ * suspend buffer for queue group.
-+ * @reg: Memory region allocated for the normal-mode suspend buffer.
-+ * @phy: Array of physical memory pages allocated for the normal-
-+ * mode suspend buffer.
-+ */
-+struct kbase_normal_suspend_buffer {
-+ struct kbase_va_region *reg;
-+ struct tagged_addr *phy;
-+};
-+
-+/**
-+ * struct kbase_protected_suspend_buffer - Object representing a protected
-+ * suspend buffer for queue group.
-+ * @reg: Memory region allocated for the protected-mode suspend buffer.
-+ * @pma: Array of pointer to protected mode allocations containing
-+ * information about memory pages allocated for protected mode
-+ * suspend buffer.
-+ */
-+struct kbase_protected_suspend_buffer {
-+ struct kbase_va_region *reg;
-+ struct protected_memory_allocation **pma;
-+};
-+
-+/**
-+ * struct kbase_queue_group - Object representing a GPU command queue group.
-+ *
-+ * @kctx: Pointer to the kbase context with which this queue group
-+ * is associated.
-+ * @normal_suspend_buf: Object representing the normal suspend buffer.
-+ * Normal-mode suspend buffer that is used for
-+ * group context switch.
-+ * @protected_suspend_buf: Object representing the protected suspend
-+ * buffer. Protected-mode suspend buffer that is
-+ * used for group context switch.
-+ * @handle: Handle which identifies this queue group.
-+ * @csg_nr: Number/index of the CSG to which this queue group is
-+ * mapped; KBASEP_CSG_NR_INVALID indicates that the queue
-+ * group is not scheduled.
-+ * @priority: Priority of the queue group, 0 being the highest,
-+ * BASE_QUEUE_GROUP_PRIORITY_COUNT - 1 being the lowest.
-+ * @tiler_max: Maximum number of tiler endpoints the group is allowed
-+ * to use.
-+ * @fragment_max: Maximum number of fragment endpoints the group is
-+ * allowed to use.
-+ * @compute_max: Maximum number of compute endpoints the group is
-+ * allowed to use.
-+ * @tiler_mask: Mask of tiler endpoints the group is allowed to use.
-+ * @fragment_mask: Mask of fragment endpoints the group is allowed to use.
-+ * @compute_mask: Mask of compute endpoints the group is allowed to use.
-+ * @group_uid: 32-bit wide unsigned identifier for the group, unique
-+ * across all kbase devices and contexts.
-+ * @link: Link to this queue group in the 'runnable_groups' list of
-+ * the corresponding kctx.
-+ * @link_to_schedule: Link to this queue group in the list of prepared groups
-+ * to be scheduled, if the group is runnable/suspended.
-+ * If the group is idle or waiting for CQS, it would be a
-+ * link to the list of idle/blocked groups list.
-+ * @run_state: Current state of the queue group.
-+ * @prepared_seq_num: Indicates the position of queue group in the list of
-+ * prepared groups to be scheduled.
-+ * @scan_seq_num: Scan out sequence number before adjusting for dynamic
-+ * idle conditions. It is used for setting a group's
-+ * onslot priority. It could differ from prepared_seq_number
-+ * when there are idle groups.
-+ * @faulted: Indicates that a GPU fault occurred for the queue group.
-+ * This flag persists until the fault has been queued to be
-+ * reported to userspace.
-+ * @bound_queues: Array of registered queues bound to this queue group.
-+ * @doorbell_nr: Index of the hardware doorbell page assigned to the
-+ * group.
-+ * @protm_event_work: Work item corresponding to the protected mode entry
-+ * event for this queue.
-+ * @protm_pending_bitmap: Bit array to keep a track of CSs that
-+ * have pending protected mode entry requests.
-+ * @error_fatal: An error of type BASE_GPU_QUEUE_GROUP_ERROR_FATAL to be
-+ * returned to userspace if such an error has occurred.
-+ * @error_timeout: An error of type BASE_GPU_QUEUE_GROUP_ERROR_TIMEOUT
-+ * to be returned to userspace if such an error has occurred.
-+ * @error_tiler_oom: An error of type BASE_GPU_QUEUE_GROUP_ERROR_TILER_HEAP_OOM
-+ * to be returned to userspace if such an error has occurred.
-+ * @timer_event_work: Work item to handle the progress timeout fatal event
-+ * for the group.
-+ */
-+struct kbase_queue_group {
-+ struct kbase_context *kctx;
-+ struct kbase_normal_suspend_buffer normal_suspend_buf;
-+ struct kbase_protected_suspend_buffer protected_suspend_buf;
-+ u8 handle;
-+ s8 csg_nr;
-+ u8 priority;
-+
-+ u8 tiler_max;
-+ u8 fragment_max;
-+ u8 compute_max;
-+
-+ u64 tiler_mask;
-+ u64 fragment_mask;
-+ u64 compute_mask;
-+
-+ u32 group_uid;
-+
-+ struct list_head link;
-+ struct list_head link_to_schedule;
-+ enum kbase_csf_group_state run_state;
-+ u32 prepared_seq_num;
-+ u32 scan_seq_num;
-+ bool faulted;
-+
-+ struct kbase_queue *bound_queues[MAX_SUPPORTED_STREAMS_PER_GROUP];
-+
-+ int doorbell_nr;
-+ struct work_struct protm_event_work;
-+ DECLARE_BITMAP(protm_pending_bitmap, MAX_SUPPORTED_STREAMS_PER_GROUP);
-+
-+ struct kbase_csf_notification error_fatal;
-+ struct kbase_csf_notification error_timeout;
-+ struct kbase_csf_notification error_tiler_oom;
-+
-+ struct work_struct timer_event_work;
-+};
-+
-+/**
-+ * struct kbase_csf_kcpu_queue_context - Object representing the kernel CPU
-+ * queues for a GPU address space.
-+ *
-+ * @lock: Lock preventing concurrent access to @array and the @in_use bitmap.
-+ * @array: Array of pointers to kernel CPU command queues.
-+ * @in_use: Bitmap which indicates which kernel CPU command queues are in use.
-+ * @wq: Dedicated workqueue for processing kernel CPU command queues.
-+ * @num_cmds: The number of commands that have been enqueued across
-+ * all the KCPU command queues. This could be used as a
-+ * timestamp to determine the command's enqueueing time.
-+ * @jit_cmds_head: A list of the just-in-time memory commands, both
-+ * allocate & free, in submission order, protected
-+ * by kbase_csf_kcpu_queue_context.lock.
-+ * @jit_blocked_queues: A list of KCPU command queues blocked by a pending
-+ * just-in-time memory allocation command which will be
-+ * reattempted after the impending free of other active
-+ * allocations.
-+ */
-+struct kbase_csf_kcpu_queue_context {
-+ struct mutex lock;
-+ struct kbase_kcpu_command_queue *array[KBASEP_MAX_KCPU_QUEUES];
-+ DECLARE_BITMAP(in_use, KBASEP_MAX_KCPU_QUEUES);
-+ struct workqueue_struct *wq;
-+ u64 num_cmds;
-+
-+ struct list_head jit_cmds_head;
-+ struct list_head jit_blocked_queues;
-+};
-+
-+/**
-+ * struct kbase_csf_cpu_queue_context - Object representing the cpu queue
-+ * information.
-+ *
-+ * @buffer: Buffer containing CPU queue information provided by Userspace.
-+ * @buffer_size: The size of @buffer.
-+ * @dump_req_status: Indicates the current status for CPU queues dump request.
-+ * @dump_cmp: Dumping cpu queue completion event.
-+ */
-+struct kbase_csf_cpu_queue_context {
-+ char *buffer;
-+ size_t buffer_size;
-+ atomic_t dump_req_status;
-+ struct completion dump_cmp;
-+};
-+
-+/**
-+ * struct kbase_csf_heap_context_allocator - Allocator of heap contexts
-+ *
-+ * Heap context structures are allocated by the kernel for use by the firmware.
-+ * The current implementation subdivides a single GPU memory region for use as
-+ * a sparse array.
-+ *
-+ * @kctx: Pointer to the kbase context with which this allocator is
-+ * associated.
-+ * @region: Pointer to a GPU memory region from which heap context structures
-+ * are allocated. NULL if no heap contexts have been allocated.
-+ * @gpu_va: GPU virtual address of the start of the region from which heap
-+ * context structures are allocated. 0 if no heap contexts have been
-+ * allocated.
-+ * @lock: Lock preventing concurrent access to the @in_use bitmap.
-+ * @in_use: Bitmap that indicates which heap context structures are currently
-+ * allocated (in @region).
-+ */
-+struct kbase_csf_heap_context_allocator {
-+ struct kbase_context *kctx;
-+ struct kbase_va_region *region;
-+ u64 gpu_va;
-+ struct mutex lock;
-+ DECLARE_BITMAP(in_use, MAX_TILER_HEAPS);
-+};
-+
-+/**
-+ * struct kbase_csf_tiler_heap_context - Object representing the tiler heaps
-+ * context for a GPU address space.
-+ *
-+ * This contains all of the CSF state relating to chunked tiler heaps for one
-+ * @kbase_context. It is not the same as a heap context structure allocated by
-+ * the kernel for use by the firmware.
-+ *
-+ * @lock: Lock preventing concurrent access to the tiler heaps.
-+ * @list: List of tiler heaps.
-+ * @ctx_alloc: Allocator for heap context structures.
-+ * @nr_of_heaps: Total number of tiler heaps that were added during the
-+ * life time of the context.
-+ */
-+struct kbase_csf_tiler_heap_context {
-+ struct mutex lock;
-+ struct list_head list;
-+ struct kbase_csf_heap_context_allocator ctx_alloc;
-+ u64 nr_of_heaps;
-+};
-+
-+/**
-+ * struct kbase_csf_scheduler_context - Object representing the scheduler's
-+ * context for a GPU address space.
-+ *
-+ * @runnable_groups: Lists of runnable GPU command queue groups in the kctx,
-+ * one per queue group relative-priority level.
-+ * @num_runnable_grps: Total number of runnable groups across all priority
-+ * levels in @runnable_groups.
-+ * @idle_wait_groups: A list of GPU command queue groups in which all enabled
-+ * GPU command queues are idle and at least one of them
-+ * is blocked on a sync wait operation.
-+ * @num_idle_wait_grps: Length of the @idle_wait_groups list.
-+ * @sync_update_wq: Dedicated workqueue to process work items corresponding
-+ * to the sync_update events by sync_set/sync_add
-+ * instruction execution on CSs bound to groups
-+ * of @idle_wait_groups list.
-+ * @sync_update_work: work item to process the sync_update events by
-+ * sync_set / sync_add instruction execution on command
-+ * streams bound to groups of @idle_wait_groups list.
-+ * @ngrp_to_schedule: Number of groups added for the context to the
-+ * 'groups_to_schedule' list of scheduler instance.
-+ */
-+struct kbase_csf_scheduler_context {
-+ struct list_head runnable_groups[KBASE_QUEUE_GROUP_PRIORITY_COUNT];
-+ u32 num_runnable_grps;
-+ struct list_head idle_wait_groups;
-+ u32 num_idle_wait_grps;
-+ struct workqueue_struct *sync_update_wq;
-+ struct work_struct sync_update_work;
-+ u32 ngrp_to_schedule;
-+};
-+
-+/**
-+ * struct kbase_csf_context - Object representing CSF for a GPU address space.
-+ *
-+ * @event_pages_head: A list of pages allocated for the event memory used by
-+ * the synchronization objects. A separate list would help
-+ * in the fast lookup, since the list is expected to be short
-+ * as one page would provide the memory for up to 1K
-+ * synchronization objects.
-+ * KBASE_PERMANENTLY_MAPPED_MEM_LIMIT_PAGES is the upper
-+ * bound on the size of event memory.
-+ * @cookies: Bitmask containing of KBASE_CSF_NUM_USER_IO_PAGES_HANDLE
-+ * bits, used for creating the User mode CPU mapping in a
-+ * deferred manner of a pair of User mode input/output pages
-+ * & a hardware doorbell page.
-+ * The pages are allocated when a GPU command queue is
-+ * bound to a CSG in kbase_csf_queue_bind.
-+ * This helps returning unique handles to Userspace from
-+ * kbase_csf_queue_bind and later retrieving the pointer to
-+ * queue in the mmap handler.
-+ * @user_pages_info: Array containing pointers to queue
-+ * structures, used in conjunction with cookies bitmask for
-+ * providing a mechansim to create a CPU mapping of
-+ * input/output pages & hardware doorbell page.
-+ * @lock: Serializes accesses to all members, except for ones that
-+ * have their own locks.
-+ * @queue_groups: Array of registered GPU command queue groups.
-+ * @queue_list: Linked list of GPU command queues not yet deregistered.
-+ * Note that queues can persist after deregistration if the
-+ * userspace mapping created for them on bind operation
-+ * hasn't been removed.
-+ * @kcpu_queues: Kernel CPU command queues.
-+ * @event_lock: Lock protecting access to @event_callback_list and
-+ * @error_list.
-+ * @event_callback_list: List of callbacks which are registered to serve CSF
-+ * events.
-+ * @tiler_heaps: Chunked tiler memory heaps.
-+ * @wq: Dedicated workqueue to process work items corresponding
-+ * to the OoM events raised for chunked tiler heaps being
-+ * used by GPU command queues, and progress timeout events.
-+ * @link: Link to this csf context in the 'runnable_kctxs' list of
-+ * the scheduler instance
-+ * @user_reg_vma: Pointer to the vma corresponding to the virtual mapping
-+ * of the USER register page. Currently used only for sanity
-+ * checking.
-+ * @sched: Object representing the scheduler's context
-+ * @error_list: List for CS fatal errors in this context.
-+ * Link of fatal error is
-+ * &struct_kbase_csf_notification.link.
-+ * @event_lock needs to be held to access this list.
-+ * @cpu_queue: CPU queue information. Only be available when DEBUG_FS
-+ * is enabled.
-+ */
-+struct kbase_csf_context {
-+ struct list_head event_pages_head;
-+ DECLARE_BITMAP(cookies, KBASE_CSF_NUM_USER_IO_PAGES_HANDLE);
-+ struct kbase_queue *user_pages_info[
-+ KBASE_CSF_NUM_USER_IO_PAGES_HANDLE];
-+ struct mutex lock;
-+ struct kbase_queue_group *queue_groups[MAX_QUEUE_GROUP_NUM];
-+ struct list_head queue_list;
-+ struct kbase_csf_kcpu_queue_context kcpu_queues;
-+ spinlock_t event_lock;
-+ struct list_head event_callback_list;
-+ struct kbase_csf_tiler_heap_context tiler_heaps;
-+ struct workqueue_struct *wq;
-+ struct list_head link;
-+ struct vm_area_struct *user_reg_vma;
-+ struct kbase_csf_scheduler_context sched;
-+ struct list_head error_list;
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+ struct kbase_csf_cpu_queue_context cpu_queue;
-+#endif
-+};
-+
-+/**
-+ * struct kbase_csf_reset_gpu - Object containing the members required for
-+ * GPU reset handling.
-+ * @workq: Workqueue to execute the GPU reset work item @work.
-+ * @work: Work item for performing the GPU reset.
-+ * @wait: Wait queue used to wait for the GPU reset completion.
-+ * @sem: RW Semaphore to ensure no other thread attempts to use the
-+ * GPU whilst a reset is in process. Unlike traditional
-+ * semaphores and wait queues, this allows Linux's lockdep
-+ * mechanism to check for deadlocks involving reset waits.
-+ * @state: Tracks if the GPU reset is in progress or not.
-+ * The state is represented by enum @kbase_csf_reset_gpu_state.
-+ */
-+struct kbase_csf_reset_gpu {
-+ struct workqueue_struct *workq;
-+ struct work_struct work;
-+ wait_queue_head_t wait;
-+ struct rw_semaphore sem;
-+ atomic_t state;
-+};
-+
-+/**
-+ * struct kbase_csf_csg_slot - Object containing members for tracking the state
-+ * of CSG slots.
-+ * @resident_group: pointer to the queue group that is resident on the CSG slot.
-+ * @state: state of the slot as per enum @kbase_csf_csg_slot_state.
-+ * @trigger_jiffies: value of jiffies when change in slot state is recorded.
-+ * @priority: dynamic priority assigned to CSG slot.
-+ */
-+struct kbase_csf_csg_slot {
-+ struct kbase_queue_group *resident_group;
-+ atomic_t state;
-+ unsigned long trigger_jiffies;
-+ u8 priority;
-+};
-+
-+/**
-+ * struct kbase_csf_scheduler - Object representing the scheduler used for
-+ * CSF for an instance of GPU platform device.
-+ * @lock: Lock to serialize the scheduler operations and
-+ * access to the data members.
-+ * @interrupt_lock: Lock to protect members accessed by interrupt
-+ * handler.
-+ * @state: The operational phase the scheduler is in. Primarily
-+ * used for indicating what in-cycle schedule actions
-+ * are allowed.
-+ * @doorbell_inuse_bitmap: Bitmap of hardware doorbell pages keeping track of
-+ * which pages are currently available for assignment
-+ * to clients.
-+ * @csg_inuse_bitmap: Bitmap to keep a track of CSG slots
-+ * that are currently in use.
-+ * @csg_slots: The array for tracking the state of CS
-+ * group slots.
-+ * @runnable_kctxs: List of Kbase contexts that have runnable command
-+ * queue groups.
-+ * @groups_to_schedule: List of runnable queue groups prepared on every
-+ * scheduler tick. The dynamic priority of the CSG
-+ * slot assigned to a group will depend upon the
-+ * position of group in the list.
-+ * @ngrp_to_schedule: Number of groups in the @groups_to_schedule list,
-+ * incremented when a group is added to the list, used
-+ * to record the position of group in the list.
-+ * @num_active_address_spaces: Number of GPU address space slots that would get
-+ * used to program the groups in @groups_to_schedule
-+ * list on all the available CSG
-+ * slots.
-+ * @num_csg_slots_for_tick: Number of CSG slots that can be
-+ * active in the given tick/tock. This depends on the
-+ * value of @num_active_address_spaces.
-+ * @remaining_tick_slots: Tracking the number of remaining available slots
-+ * for @num_csg_slots_for_tick during the scheduling
-+ * operation in a tick/tock.
-+ * @idle_groups_to_schedule: List of runnable queue groups, in which all GPU
-+ * command queues became idle or are waiting for
-+ * synchronization object, prepared on every
-+ * scheduler tick. The groups in this list are
-+ * appended to the tail of @groups_to_schedule list
-+ * after the scan out so that the idle groups aren't
-+ * preferred for scheduling over the non-idle ones.
-+ * @csg_scan_count_for_tick: CSG scanout count for assign the scan_seq_num for
-+ * each scanned out group during scheduling operation
-+ * in a tick/tock.
-+ * @total_runnable_grps: Total number of runnable groups across all KCTXs.
-+ * @csgs_events_enable_mask: Use for temporary masking off asynchronous events
-+ * from firmware (such as OoM events) before a group
-+ * is suspended.
-+ * @csg_slots_idle_mask: Bit array for storing the mask of CS
-+ * group slots for which idle notification was
-+ * received.
-+ * @csg_slots_prio_update: Bit array for tracking slots that have an on-slot
-+ * priority update operation.
-+ * @last_schedule: Time in jiffies recorded when the last "tick" or
-+ * "tock" schedule operation concluded. Used for
-+ * evaluating the exclusion window for in-cycle
-+ * schedule operation.
-+ * @timer_enabled: Whether the CSF scheduler wakes itself up for
-+ * periodic scheduling tasks. If this value is 0
-+ * then it will only perform scheduling under the
-+ * influence of external factors e.g., IRQs, IOCTLs.
-+ * @wq: Dedicated workqueue to execute the @tick_work.
-+ * @tick_timer: High-resolution timer employed to schedule tick
-+ * workqueue items (kernel-provided delayed_work
-+ * items do not use hrtimer and for some reason do
-+ * not provide sufficiently reliable periodicity).
-+ * @tick_work: Work item that performs the "schedule on tick"
-+ * operation to implement timeslice-based scheduling.
-+ * @tock_work: Work item that would perform the schedule on tock
-+ * operation to implement the asynchronous scheduling.
-+ * @ping_work: Work item that would ping the firmware at regular
-+ * intervals, only if there is a single active CSG
-+ * slot, to check if firmware is alive and would
-+ * initiate a reset if the ping request isn't
-+ * acknowledged.
-+ * @top_ctx: Pointer to the Kbase context corresponding to the
-+ * @top_grp.
-+ * @top_grp: Pointer to queue group inside @groups_to_schedule
-+ * list that was assigned the highest slot priority.
-+ * @tock_pending_request: A "tock" request is pending: a group that is not
-+ * currently on the GPU demands to be scheduled.
-+ * @active_protm_grp: Indicates if firmware has been permitted to let GPU
-+ * enter protected mode with the given group. On exit
-+ * from protected mode the pointer is reset to NULL.
-+ * @gpu_idle_fw_timer_enabled: Whether the CSF scheduler has activiated the
-+ * firmware idle hysteresis timer for preparing a
-+ * GPU suspend on idle.
-+ * @gpu_idle_work: Work item for facilitating the scheduler to bring
-+ * the GPU to a low-power mode on becoming idle.
-+ * @non_idle_offslot_grps: Count of off-slot non-idle groups. Reset during
-+ * the scheduler active phase in a tick. It then
-+ * tracks the count of non-idle groups across all the
-+ * other phases.
-+ * @non_idle_scanout_grps: Count on the non-idle groups in the scan-out
-+ * list at the scheduling prepare stage.
-+ * @pm_active_count: Count indicating if the scheduler is owning a power
-+ * management reference count. Reference is taken when
-+ * the count becomes 1 and is dropped when the count
-+ * becomes 0. It is used to enable the power up of MCU
-+ * after GPU and L2 cache have been powered up. So when
-+ * this count is zero, MCU will not be powered up.
-+ * @csg_scheduling_period_ms: Duration of Scheduling tick in milliseconds.
-+ * @tick_timer_active: Indicates whether the @tick_timer is effectively
-+ * active or not, as the callback function of
-+ * @tick_timer will enqueue @tick_work only if this
-+ * flag is true. This is mainly useful for the case
-+ * when scheduling tick needs to be advanced from
-+ * interrupt context, without actually deactivating
-+ * the @tick_timer first and then enqueing @tick_work.
-+ */
-+struct kbase_csf_scheduler {
-+ struct mutex lock;
-+ spinlock_t interrupt_lock;
-+ enum kbase_csf_scheduler_state state;
-+ DECLARE_BITMAP(doorbell_inuse_bitmap, CSF_NUM_DOORBELL);
-+ DECLARE_BITMAP(csg_inuse_bitmap, MAX_SUPPORTED_CSGS);
-+ struct kbase_csf_csg_slot *csg_slots;
-+ struct list_head runnable_kctxs;
-+ struct list_head groups_to_schedule;
-+ u32 ngrp_to_schedule;
-+ u32 num_active_address_spaces;
-+ u32 num_csg_slots_for_tick;
-+ u32 remaining_tick_slots;
-+ struct list_head idle_groups_to_schedule;
-+ u32 csg_scan_count_for_tick;
-+ u32 total_runnable_grps;
-+ DECLARE_BITMAP(csgs_events_enable_mask, MAX_SUPPORTED_CSGS);
-+ DECLARE_BITMAP(csg_slots_idle_mask, MAX_SUPPORTED_CSGS);
-+ DECLARE_BITMAP(csg_slots_prio_update, MAX_SUPPORTED_CSGS);
-+ unsigned long last_schedule;
-+ bool timer_enabled;
-+ struct workqueue_struct *wq;
-+ struct hrtimer tick_timer;
-+ struct work_struct tick_work;
-+ struct delayed_work tock_work;
-+ struct delayed_work ping_work;
-+ struct kbase_context *top_ctx;
-+ struct kbase_queue_group *top_grp;
-+ bool tock_pending_request;
-+ struct kbase_queue_group *active_protm_grp;
-+ bool gpu_idle_fw_timer_enabled;
-+ struct work_struct gpu_idle_work;
-+ atomic_t non_idle_offslot_grps;
-+ u32 non_idle_scanout_grps;
-+ u32 pm_active_count;
-+ unsigned int csg_scheduling_period_ms;
-+ bool tick_timer_active;
-+};
-+
-+/**
-+ * Number of GPU cycles per unit of the global progress timeout.
-+ */
-+#define GLB_PROGRESS_TIMER_TIMEOUT_SCALE ((u64)1024)
-+
-+/**
-+ * Maximum value of the global progress timeout.
-+ */
-+#define GLB_PROGRESS_TIMER_TIMEOUT_MAX \
-+ ((GLB_PROGRESS_TIMER_TIMEOUT_MASK >> \
-+ GLB_PROGRESS_TIMER_TIMEOUT_SHIFT) * \
-+ GLB_PROGRESS_TIMER_TIMEOUT_SCALE)
-+
-+/**
-+ * Default GLB_PWROFF_TIMER_TIMEOUT value in unit of micro-seconds.
-+ */
-+#define DEFAULT_GLB_PWROFF_TIMEOUT_US (800)
-+
-+/**
-+ * In typical operations, the management of the shader core power transitions
-+ * is delegated to the MCU/firmware. However, if the host driver is configured
-+ * to take direct control, one needs to disable the MCU firmware GLB_PWROFF
-+ * timer.
-+ */
-+#define DISABLE_GLB_PWROFF_TIMER (0)
-+
-+/* Index of the GPU_ACTIVE counter within the CSHW counter block */
-+#define GPU_ACTIVE_CNT_IDX (4)
-+
-+/**
-+ * Maximum number of sessions that can be managed by the IPA Control component.
-+ */
-+#if MALI_UNIT_TEST
-+#define KBASE_IPA_CONTROL_MAX_SESSIONS ((size_t)8)
-+#else
-+#define KBASE_IPA_CONTROL_MAX_SESSIONS ((size_t)2)
-+#endif
-+
-+/**
-+ * enum kbase_ipa_core_type - Type of counter block for performance counters
-+ *
-+ * @KBASE_IPA_CORE_TYPE_CSHW: CS Hardware counters.
-+ * @KBASE_IPA_CORE_TYPE_MEMSYS: Memory System counters.
-+ * @KBASE_IPA_CORE_TYPE_TILER: Tiler counters.
-+ * @KBASE_IPA_CORE_TYPE_SHADER: Shader Core counters.
-+ * @KBASE_IPA_CORE_TYPE_NUM: Number of core types.
-+ */
-+enum kbase_ipa_core_type {
-+ KBASE_IPA_CORE_TYPE_CSHW = 0,
-+ KBASE_IPA_CORE_TYPE_MEMSYS,
-+ KBASE_IPA_CORE_TYPE_TILER,
-+ KBASE_IPA_CORE_TYPE_SHADER,
-+ KBASE_IPA_CORE_TYPE_NUM
-+};
-+
-+/**
-+ * Number of configurable counters per type of block on the IPA Control
-+ * interface.
-+ */
-+#define KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS ((size_t)8)
-+
-+/**
-+ * Total number of configurable counters existing on the IPA Control interface.
-+ */
-+#define KBASE_IPA_CONTROL_MAX_COUNTERS \
-+ ((size_t)KBASE_IPA_CORE_TYPE_NUM * KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS)
-+
-+/**
-+ * struct kbase_ipa_control_prfcnt - Session for a single performance counter
-+ *
-+ * @latest_raw_value: Latest raw value read from the counter.
-+ * @scaling_factor: Factor raw value shall be multiplied by.
-+ * @accumulated_diff: Partial sum of scaled and normalized values from
-+ * previous samples. This represent all the values
-+ * that were read before the latest raw value.
-+ * @type: Type of counter block for performance counter.
-+ * @select_idx: Index of the performance counter as configured on
-+ * the IPA Control interface.
-+ * @gpu_norm: Indicating whether values shall be normalized by
-+ * GPU frequency. If true, returned values represent
-+ * an interval of time expressed in seconds (when the
-+ * scaling factor is set to 1).
-+ */
-+struct kbase_ipa_control_prfcnt {
-+ u64 latest_raw_value;
-+ u64 scaling_factor;
-+ u64 accumulated_diff;
-+ enum kbase_ipa_core_type type;
-+ u8 select_idx;
-+ bool gpu_norm;
-+};
-+
-+/**
-+ * struct kbase_ipa_control_session - Session for an IPA Control client
-+ *
-+ * @prfcnts: Sessions for individual performance counters.
-+ * @num_prfcnts: Number of performance counters.
-+ * @active: Indicates whether this slot is in use or not
-+ * @last_query_time: Time of last query, in ns
-+ * @protm_time: Amount of time (in ns) that GPU has been in protected
-+ */
-+struct kbase_ipa_control_session {
-+ struct kbase_ipa_control_prfcnt prfcnts[KBASE_IPA_CONTROL_MAX_COUNTERS];
-+ size_t num_prfcnts;
-+ bool active;
-+ u64 last_query_time;
-+ u64 protm_time;
-+};
-+
-+/**
-+ * struct kbase_ipa_control_prfcnt_config - Performance counter configuration
-+ *
-+ * @idx: Index of the performance counter inside the block, as specified
-+ * in the GPU architecture.
-+ * @refcount: Number of client sessions bound to this counter.
-+ *
-+ * This structure represents one configurable performance counter of
-+ * the IPA Control interface. The entry may be mapped to a specific counter
-+ * by one or more client sessions. The counter is considered to be unused
-+ * if it isn't part of any client session.
-+ */
-+struct kbase_ipa_control_prfcnt_config {
-+ u8 idx;
-+ u8 refcount;
-+};
-+
-+/**
-+ * struct kbase_ipa_control_prfcnt_block - Block of performance counters
-+ *
-+ * @select: Current performance counter configuration.
-+ * @num_available_counters: Number of counters that are not already configured.
-+ *
-+ */
-+struct kbase_ipa_control_prfcnt_block {
-+ struct kbase_ipa_control_prfcnt_config
-+ select[KBASE_IPA_CONTROL_NUM_BLOCK_COUNTERS];
-+ size_t num_available_counters;
-+};
-+
-+/**
-+ * struct kbase_ipa_control - Manager of the IPA Control interface.
-+ *
-+ * @blocks: Current configuration of performance counters
-+ * for the IPA Control interface.
-+ * @sessions: State of client sessions, storing information
-+ * like performance counters the client subscribed to
-+ * and latest value read from each counter.
-+ * @lock: Spinlock to serialize access by concurrent clients.
-+ * @rtm_listener_data: Private data for allocating a GPU frequency change
-+ * listener.
-+ * @num_active_sessions: Number of sessions opened by clients.
-+ * @cur_gpu_rate: Current GPU top-level operating frequency, in Hz.
-+ * @rtm_listener_data: Private data for allocating a GPU frequency change
-+ * listener.
-+ * @protm_start: Time (in ns) at which the GPU entered protected mode
-+ */
-+struct kbase_ipa_control {
-+ struct kbase_ipa_control_prfcnt_block blocks[KBASE_IPA_CORE_TYPE_NUM];
-+ struct kbase_ipa_control_session
-+ sessions[KBASE_IPA_CONTROL_MAX_SESSIONS];
-+ spinlock_t lock;
-+ void *rtm_listener_data;
-+ size_t num_active_sessions;
-+ u32 cur_gpu_rate;
-+ u64 protm_start;
-+};
-+
-+/**
-+ * struct kbase_csf_firmware_interface - Interface in the MCU firmware
-+ *
-+ * @node: Interface objects are on the kbase_device:csf.firmware_interfaces
-+ * list using this list_head to link them
-+ * @phys: Array of the physical (tagged) addresses making up this interface
-+ * @name: NULL-terminated string naming the interface
-+ * @num_pages: Number of entries in @phys and @pma (and length of the interface)
-+ * @virtual: Starting GPU virtual address this interface is mapped at
-+ * @flags: bitmask of CSF_FIRMWARE_ENTRY_* conveying the interface attributes
-+ * @data_start: Offset into firmware image at which the interface data starts
-+ * @data_end: Offset into firmware image at which the interface data ends
-+ * @kernel_map: A kernel mapping of the memory or NULL if not required to be
-+ * mapped in the kernel
-+ * @pma: Array of pointers to protected memory allocations.
-+ */
-+struct kbase_csf_firmware_interface {
-+ struct list_head node;
-+ struct tagged_addr *phys;
-+ char *name;
-+ u32 num_pages;
-+ u32 virtual;
-+ u32 flags;
-+ u32 data_start;
-+ u32 data_end;
-+ void *kernel_map;
-+ struct protected_memory_allocation **pma;
-+};
-+
-+/*
-+ * struct kbase_csf_hwcnt - Object containing members for handling the dump of
-+ * HW counters.
-+ *
-+ * @request_pending: Flag set when HWC requested and used for HWC sample
-+ * done interrupt.
-+ * @enable_pending: Flag set when HWC enable status change and used for
-+ * enable done interrupt.
-+ */
-+struct kbase_csf_hwcnt {
-+ bool request_pending;
-+ bool enable_pending;
-+};
-+
-+/**
-+ * struct kbase_csf_device - Object representing CSF for an instance of GPU
-+ * platform device.
-+ *
-+ * @mcu_mmu: MMU page tables for the MCU firmware
-+ * @firmware_interfaces: List of interfaces defined in the firmware image
-+ * @firmware_config: List of configuration options within the firmware
-+ * image
-+ * @firmware_timeline_metadata: List of timeline meta-data within the firmware
-+ * image
-+ * @fw_cfg_kobj: Pointer to the kobject corresponding to the sysf
-+ * directory that contains a sub-directory for each
-+ * of the configuration option present in the
-+ * firmware image.
-+ * @firmware_trace_buffers: List of trace buffers described in the firmware
-+ * image.
-+ * @shared_interface: Pointer to the interface object containing info for
-+ * the memory area shared between firmware & host.
-+ * @shared_reg_rbtree: RB tree of the memory regions allocated from the
-+ * shared interface segment in MCU firmware address
-+ * space.
-+ * @db_filp: Pointer to a dummy file, that alongwith
-+ * @db_file_offsets, facilitates the use of unqiue
-+ * file offset for the userspace mapping created
-+ * for Hw Doorbell pages. The userspace mapping
-+ * is made to point to this file inside the mmap
-+ * handler.
-+ * @db_file_offsets: Counter that is incremented every time a GPU
-+ * command queue is bound to provide a unique file
-+ * offset range for @db_filp file, so that pte of
-+ * Doorbell page can be zapped through the kernel
-+ * function unmap_mapping_range(). It is incremented
-+ * in page units.
-+ * @dummy_db_page: Address of the dummy page that is mapped in place
-+ * of the real Hw doorbell page for the active GPU
-+ * command queues after they are stopped or after the
-+ * GPU is powered down.
-+ * @dummy_user_reg_page: Address of the dummy page that is mapped in place
-+ * of the real User register page just before the GPU
-+ * is powered down. The User register page is mapped
-+ * in the address space of every process, that created
-+ * a Base context, to enable the access to LATEST_FLUSH
-+ * register from userspace.
-+ * @mali_file_inode: Pointer to the inode corresponding to mali device
-+ * file. This is needed in order to switch to the
-+ * @dummy_user_reg_page on GPU power down.
-+ * All instances of the mali device file will point to
-+ * the same inode.
-+ * @reg_lock: Lock to serialize the MCU firmware related actions
-+ * that affect all contexts such as allocation of
-+ * regions from shared interface area, assignment of
-+ * of hardware doorbell pages, assignment of CSGs,
-+ * sending global requests.
-+ * @event_wait: Wait queue to wait for receiving csf events, i.e.
-+ * the interrupt from CSF firmware, or scheduler state
-+ * changes.
-+ * @interrupt_received: Flag set when the interrupt is received from CSF fw
-+ * @global_iface: The result of parsing the global interface
-+ * structure set up by the firmware, including the
-+ * CSGs, CSs, and their properties
-+ * @scheduler: The CS scheduler instance.
-+ * @reset: Contain members required for GPU reset handling.
-+ * @progress_timeout: Maximum number of GPU clock cycles without forward
-+ * progress to allow, for all tasks running on
-+ * hardware endpoints (e.g. shader cores), before
-+ * terminating a GPU command queue group.
-+ * Must not exceed @GLB_PROGRESS_TIMER_TIMEOUT_MAX.
-+ * @pma_dev: Pointer to protected memory allocator device.
-+ * @firmware_inited: Flag for indicating that the cold-boot stage of
-+ * the MCU has completed.
-+ * @firmware_reloaded: Flag for indicating a firmware reload operation
-+ * in GPU reset has completed.
-+ * @firmware_reload_needed: Flag for indicating that the firmware needs to be
-+ * reloaded as part of the GPU reset action.
-+ * @firmware_hctl_core_pwr: Flag for indicating that the host diver is in
-+ * charge of the shader core's power transitions, and
-+ * the mcu_core_pwroff timeout feature is disabled
-+ * (i.e. configured 0 in the register field). If
-+ * false, the control is delegated to the MCU.
-+ * @firmware_reload_work: Work item for facilitating the procedural actions
-+ * on reloading the firmware.
-+ * @glb_init_request_pending: Flag to indicate that Global requests have been
-+ * sent to the FW after MCU was re-enabled and their
-+ * acknowledgement is pending.
-+ * @fw_error_work: Work item for handling the firmware internal error
-+ * fatal event.
-+ * @ipa_control: IPA Control component manager.
-+ * @mcu_core_pwroff_dur_us: Sysfs attribute for the glb_pwroff timeout input
-+ * in unit of micro-seconds. The firmware does not use
-+ * it directly.
-+ * @mcu_core_pwroff_dur_count: The counterpart of the glb_pwroff timeout input
-+ * in interface required format, ready to be used
-+ * directly in the firmware.
-+ * @mcu_core_pwroff_reg_shadow: The actual value that has been programed into
-+ * the glb_pwoff register. This is separated from
-+ * the @p mcu_core_pwroff_dur_count as an update
-+ * to the latter is asynchronous.
-+ * @gpu_idle_hysteresis_ms: Sysfs attribute for the idle hysteresis time
-+ * window in unit of ms. The firmware does not use it
-+ * directly.
-+ * @gpu_idle_dur_count: The counterpart of the hysteresis time window in
-+ * interface required format, ready to be used
-+ * directly in the firmware.
-+ * @fw_timeout_ms: Timeout value (in milliseconds) used when waiting
-+ * for any request sent to the firmware.
-+ * @hwcnt: Contain members required for handling the dump of
-+ * HW counters.
-+ */
-+struct kbase_csf_device {
-+ struct kbase_mmu_table mcu_mmu;
-+ struct list_head firmware_interfaces;
-+ struct list_head firmware_config;
-+ struct list_head firmware_timeline_metadata;
-+ struct kobject *fw_cfg_kobj;
-+ struct kbase_csf_trace_buffers firmware_trace_buffers;
-+ void *shared_interface;
-+ struct rb_root shared_reg_rbtree;
-+ struct file *db_filp;
-+ u32 db_file_offsets;
-+ struct tagged_addr dummy_db_page;
-+ struct tagged_addr dummy_user_reg_page;
-+ struct inode *mali_file_inode;
-+ struct mutex reg_lock;
-+ wait_queue_head_t event_wait;
-+ bool interrupt_received;
-+ struct kbase_csf_global_iface global_iface;
-+ struct kbase_csf_scheduler scheduler;
-+ struct kbase_csf_reset_gpu reset;
-+ atomic64_t progress_timeout;
-+ struct protected_memory_allocator_device *pma_dev;
-+ bool firmware_inited;
-+ bool firmware_reloaded;
-+ bool firmware_reload_needed;
-+ bool firmware_hctl_core_pwr;
-+ struct work_struct firmware_reload_work;
-+ bool glb_init_request_pending;
-+ struct work_struct fw_error_work;
-+ struct kbase_ipa_control ipa_control;
-+ u32 mcu_core_pwroff_dur_us;
-+ u32 mcu_core_pwroff_dur_count;
-+ u32 mcu_core_pwroff_reg_shadow;
-+ u32 gpu_idle_hysteresis_ms;
-+ u32 gpu_idle_dur_count;
-+ unsigned int fw_timeout_ms;
-+ struct kbase_csf_hwcnt hwcnt;
-+};
-+
-+/**
-+ * struct kbase_as - Object representing an address space of GPU.
-+ * @number: Index at which this address space structure is present
-+ * in an array of address space structures embedded inside
-+ * the &struct kbase_device.
-+ * @pf_wq: Workqueue for processing work items related to
-+ * Page fault, Bus fault and GPU fault handling.
-+ * @work_pagefault: Work item for the Page fault handling.
-+ * @work_busfault: Work item for the Bus fault handling.
-+ * @work_gpufault: Work item for the GPU fault handling.
-+ * @pf_data: Data relating to Page fault.
-+ * @bf_data: Data relating to Bus fault.
-+ * @gf_data: Data relating to GPU fault.
-+ * @current_setup: Stores the MMU configuration for this address space.
-+ */
-+struct kbase_as {
-+ int number;
-+ struct workqueue_struct *pf_wq;
-+ struct work_struct work_pagefault;
-+ struct work_struct work_busfault;
-+ struct work_struct work_gpufault;
-+ struct kbase_fault pf_data;
-+ struct kbase_fault bf_data;
-+ struct kbase_fault gf_data;
-+ struct kbase_mmu_setup current_setup;
-+};
-+
-+#endif /* _KBASE_CSF_DEFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware.c
-new file mode 100644
-index 0000000..1b31122
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware.c
-@@ -0,0 +1,2337 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase.h"
-+#include "mali_kbase_csf_firmware_cfg.h"
-+#include "mali_kbase_csf_trace_buffer.h"
-+#include "mali_kbase_csf_timeout.h"
-+#include "mali_kbase_mem.h"
-+#include "mali_kbase_reset_gpu.h"
-+#include "mali_kbase_ctx_sched.h"
-+#include "mali_kbase_csf_scheduler.h"
-+#include "device/mali_kbase_device.h"
-+#include "backend/gpu/mali_kbase_pm_internal.h"
-+#include "tl/mali_kbase_timeline_priv.h"
-+#include "mali_kbase_csf_tl_reader.h"
-+#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
-+#include <csf/ipa_control/mali_kbase_csf_ipa_control.h>
-+
-+#include <linux/list.h>
-+#include <linux/slab.h>
-+#include <linux/firmware.h>
-+#include <linux/mman.h>
-+#include <linux/string.h>
-+#include <linux/mutex.h>
-+#if (KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE)
-+#include <linux/set_memory.h>
-+#endif
-+#include <mmu/mali_kbase_mmu.h>
-+#include <asm/arch_timer.h>
-+
-+#define MALI_MAX_FIRMWARE_NAME_LEN ((size_t)20)
-+
-+
-+static char fw_name[MALI_MAX_FIRMWARE_NAME_LEN] = "mali_csffw.bin";
-+module_param_string(fw_name, fw_name, sizeof(fw_name), 0644);
-+MODULE_PARM_DESC(fw_name, "firmware image");
-+
-+/* The waiting time for firmware to boot */
-+static unsigned int csf_firmware_boot_timeout_ms = 500;
-+module_param(csf_firmware_boot_timeout_ms, uint, 0444);
-+MODULE_PARM_DESC(csf_firmware_boot_timeout_ms,
-+ "Maximum time to wait for firmware to boot.");
-+
-+#ifdef CONFIG_MALI_DEBUG
-+/* Makes Driver wait indefinitely for an acknowledgment for the different
-+ * requests it sends to firmware. Otherwise the timeouts interfere with the
-+ * use of debugger for source-level debugging of firmware as Driver initiates
-+ * a GPU reset when a request times out, which always happen when a debugger
-+ * is connected.
-+ */
-+bool fw_debug; /* Default value of 0/false */
-+module_param(fw_debug, bool, 0444);
-+MODULE_PARM_DESC(fw_debug,
-+ "Enables effective use of a debugger for debugging firmware code.");
-+#endif
-+
-+#define FIRMWARE_HEADER_MAGIC (0xC3F13A6Eul)
-+#define FIRMWARE_HEADER_VERSION (0ul)
-+#define FIRMWARE_HEADER_LENGTH (0x14ul)
-+
-+#define CSF_FIRMWARE_ENTRY_SUPPORTED_FLAGS \
-+ (CSF_FIRMWARE_ENTRY_READ | \
-+ CSF_FIRMWARE_ENTRY_WRITE | \
-+ CSF_FIRMWARE_ENTRY_EXECUTE | \
-+ CSF_FIRMWARE_ENTRY_PROTECTED | \
-+ CSF_FIRMWARE_ENTRY_SHARED | \
-+ CSF_FIRMWARE_ENTRY_ZERO | \
-+ CSF_FIRMWARE_ENTRY_CACHE_MODE)
-+
-+#define CSF_FIRMWARE_ENTRY_TYPE_INTERFACE (0)
-+#define CSF_FIRMWARE_ENTRY_TYPE_CONFIGURATION (1)
-+#define CSF_FIRMWARE_ENTRY_TYPE_FUTF_TEST (2)
-+#define CSF_FIRMWARE_ENTRY_TYPE_TRACE_BUFFER (3)
-+#define CSF_FIRMWARE_ENTRY_TYPE_TIMELINE_METADATA (4)
-+
-+#define CSF_FIRMWARE_CACHE_MODE_NONE (0ul << 3)
-+#define CSF_FIRMWARE_CACHE_MODE_CACHED (1ul << 3)
-+#define CSF_FIRMWARE_CACHE_MODE_UNCACHED_COHERENT (2ul << 3)
-+#define CSF_FIRMWARE_CACHE_MODE_CACHED_COHERENT (3ul << 3)
-+
-+#define INTERFACE_ENTRY_NAME_OFFSET (0x14)
-+
-+#define TL_METADATA_ENTRY_NAME_OFFSET (0x8)
-+
-+#define CSF_MAX_FW_STOP_LOOPS (100000)
-+
-+#define CSF_GLB_REQ_CFG_MASK \
-+ (GLB_REQ_CFG_ALLOC_EN_MASK | GLB_REQ_CFG_PROGRESS_TIMER_MASK | \
-+ GLB_REQ_CFG_PWROFF_TIMER_MASK)
-+
-+static inline u32 input_page_read(const u32 *const input, const u32 offset)
-+{
-+ WARN_ON(offset % sizeof(u32));
-+
-+ return input[offset / sizeof(u32)];
-+}
-+
-+static inline void input_page_write(u32 *const input, const u32 offset,
-+ const u32 value)
-+{
-+ WARN_ON(offset % sizeof(u32));
-+
-+ input[offset / sizeof(u32)] = value;
-+}
-+
-+static inline void input_page_partial_write(u32 *const input, const u32 offset,
-+ u32 value, u32 mask)
-+{
-+ WARN_ON(offset % sizeof(u32));
-+
-+ input[offset / sizeof(u32)] =
-+ (input_page_read(input, offset) & ~mask) | (value & mask);
-+}
-+
-+static inline u32 output_page_read(const u32 *const output, const u32 offset)
-+{
-+ WARN_ON(offset % sizeof(u32));
-+
-+ return output[offset / sizeof(u32)];
-+}
-+
-+static unsigned int entry_type(u32 header)
-+{
-+ return header & 0xFF;
-+}
-+static unsigned int entry_size(u32 header)
-+{
-+ return (header >> 8) & 0xFF;
-+}
-+static bool entry_update(u32 header)
-+{
-+ return (header >> 30) & 0x1;
-+}
-+static bool entry_optional(u32 header)
-+{
-+ return (header >> 31) & 0x1;
-+}
-+
-+/**
-+ * struct firmware_timeline_metadata -
-+ * Timeline metadata item within the MCU firmware
-+ *
-+ * @node: List head linking all timeline metadata to
-+ * kbase_device:csf.firmware_timeline_metadata.
-+ * @name: NUL-terminated string naming the metadata.
-+ * @data: Metadata content.
-+ * @size: Metadata size.
-+ */
-+struct firmware_timeline_metadata {
-+ struct list_head node;
-+ char *name;
-+ char *data;
-+ size_t size;
-+};
-+
-+/* The shared interface area, used for communicating with firmware, is managed
-+ * like a virtual memory zone. Reserve the virtual space from that zone
-+ * corresponding to shared interface entry parsed from the firmware image.
-+ * The shared_reg_rbtree should have been initialized before calling this
-+ * function.
-+ */
-+static int setup_shared_iface_static_region(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_firmware_interface *interface =
-+ kbdev->csf.shared_interface;
-+ struct kbase_va_region *reg;
-+ int ret = -ENOMEM;
-+
-+ if (!interface)
-+ return -EINVAL;
-+
-+ reg = kbase_alloc_free_region(&kbdev->csf.shared_reg_rbtree, 0,
-+ interface->num_pages, KBASE_REG_ZONE_MCU_SHARED);
-+ if (reg) {
-+ ret = kbase_add_va_region_rbtree(kbdev, reg,
-+ interface->virtual, interface->num_pages, 1);
-+ if (ret)
-+ kfree(reg);
-+ else
-+ reg->flags &= ~KBASE_REG_FREE;
-+ }
-+
-+ return ret;
-+}
-+
-+static int wait_mcu_status_value(struct kbase_device *kbdev, u32 val)
-+{
-+ u32 max_loops = CSF_MAX_FW_STOP_LOOPS;
-+
-+ /* wait for the MCU_STATUS register to reach the given status value */
-+ while (--max_loops &&
-+ (kbase_reg_read(kbdev, GPU_CONTROL_REG(MCU_STATUS)) != val)) {
-+ }
-+
-+ return (max_loops == 0) ? -1 : 0;
-+}
-+
-+void kbase_csf_firmware_disable_mcu_wait(struct kbase_device *kbdev)
-+{
-+ if (wait_mcu_status_value(kbdev, MCU_CNTRL_DISABLE) < 0)
-+ dev_err(kbdev->dev, "MCU failed to get disabled");
-+}
-+
-+static void wait_for_firmware_stop(struct kbase_device *kbdev)
-+{
-+ if (wait_mcu_status_value(kbdev, MCU_CNTRL_DISABLE) < 0) {
-+ /* This error shall go away once MIDJM-2371 is closed */
-+ dev_err(kbdev->dev, "Firmware failed to stop");
-+ }
-+}
-+
-+static void stop_csf_firmware(struct kbase_device *kbdev)
-+{
-+ /* Stop the MCU firmware */
-+ kbase_csf_firmware_disable_mcu(kbdev);
-+
-+ wait_for_firmware_stop(kbdev);
-+}
-+
-+static void wait_for_firmware_boot(struct kbase_device *kbdev)
-+{
-+ const long wait_timeout =
-+ kbase_csf_timeout_in_jiffies(csf_firmware_boot_timeout_ms);
-+ long remaining;
-+
-+ /* Firmware will generate a global interface interrupt once booting
-+ * is complete
-+ */
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ kbdev->csf.interrupt_received == true, wait_timeout);
-+
-+ if (!remaining)
-+ dev_err(kbdev->dev, "Timed out waiting for fw boot completion");
-+
-+ kbdev->csf.interrupt_received = false;
-+}
-+
-+static void boot_csf_firmware(struct kbase_device *kbdev)
-+{
-+ kbase_csf_firmware_enable_mcu(kbdev);
-+
-+ wait_for_firmware_boot(kbdev);
-+}
-+
-+static void wait_ready(struct kbase_device *kbdev)
-+{
-+ u32 max_loops = KBASE_AS_INACTIVE_MAX_LOOPS;
-+ u32 val;
-+
-+ val = kbase_reg_read(kbdev, MMU_AS_REG(MCU_AS_NR, AS_STATUS));
-+
-+ /* Wait for a while for the update command to take effect */
-+ while (--max_loops && (val & AS_STATUS_AS_ACTIVE))
-+ val = kbase_reg_read(kbdev, MMU_AS_REG(MCU_AS_NR, AS_STATUS));
-+
-+ if (max_loops == 0)
-+ dev_err(kbdev->dev, "AS_ACTIVE bit stuck, might be caused by slow/unstable GPU clock or possible faulty FPGA connector\n");
-+}
-+
-+static void unload_mmu_tables(struct kbase_device *kbdev)
-+{
-+ unsigned long irq_flags;
-+
-+ mutex_lock(&kbdev->mmu_hw_mutex);
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags);
-+ if (kbdev->pm.backend.gpu_powered)
-+ kbase_mmu_disable_as(kbdev, MCU_AS_NR);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags);
-+ mutex_unlock(&kbdev->mmu_hw_mutex);
-+}
-+
-+static void load_mmu_tables(struct kbase_device *kbdev)
-+{
-+ unsigned long irq_flags;
-+
-+ mutex_lock(&kbdev->mmu_hw_mutex);
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags);
-+ kbase_mmu_update(kbdev, &kbdev->csf.mcu_mmu, MCU_AS_NR);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags);
-+ mutex_unlock(&kbdev->mmu_hw_mutex);
-+
-+ /* Wait for a while for the update command to take effect */
-+ wait_ready(kbdev);
-+}
-+
-+/**
-+ * convert_mem_flags() - Convert firmware memory flags to GPU region flags
-+ *
-+ * Return: GPU memory region flags
-+ *
-+ * @kbdev: Instance of GPU platform device (used to determine system coherency)
-+ * @flags: Flags of an "interface memory setup" section in a firmware image
-+ * @cm: appropriate cache mode chosen for the "interface memory setup"
-+ * section, which could be different from the cache mode requested by
-+ * firmware.
-+ */
-+static unsigned long convert_mem_flags(const struct kbase_device * const kbdev,
-+ const u32 flags, u32 *cm)
-+{
-+ unsigned long mem_flags = 0;
-+ u32 cache_mode = flags & CSF_FIRMWARE_ENTRY_CACHE_MODE;
-+ bool is_shared = (flags & CSF_FIRMWARE_ENTRY_SHARED) ? true : false;
-+
-+ /* The memory flags control the access permissions for the MCU, the
-+ * shader cores/tiler are not expected to access this memory
-+ */
-+ if (flags & CSF_FIRMWARE_ENTRY_READ)
-+ mem_flags |= KBASE_REG_GPU_RD;
-+
-+ if (flags & CSF_FIRMWARE_ENTRY_WRITE)
-+ mem_flags |= KBASE_REG_GPU_WR;
-+
-+ if ((flags & CSF_FIRMWARE_ENTRY_EXECUTE) == 0)
-+ mem_flags |= KBASE_REG_GPU_NX;
-+
-+ if (flags & CSF_FIRMWARE_ENTRY_PROTECTED)
-+ mem_flags |= KBASE_REG_PROTECTED;
-+
-+ /* Substitute uncached coherent memory for cached coherent memory if
-+ * the system does not support ACE coherency.
-+ */
-+ if ((cache_mode == CSF_FIRMWARE_CACHE_MODE_CACHED_COHERENT) &&
-+ (kbdev->system_coherency != COHERENCY_ACE))
-+ cache_mode = CSF_FIRMWARE_CACHE_MODE_UNCACHED_COHERENT;
-+
-+ /* Substitute uncached incoherent memory for uncached coherent memory
-+ * if the system does not support ACE-Lite coherency.
-+ */
-+ if ((cache_mode == CSF_FIRMWARE_CACHE_MODE_UNCACHED_COHERENT) &&
-+ (kbdev->system_coherency == COHERENCY_NONE))
-+ cache_mode = CSF_FIRMWARE_CACHE_MODE_NONE;
-+
-+ *cm = cache_mode;
-+
-+ switch (cache_mode) {
-+ case CSF_FIRMWARE_CACHE_MODE_NONE:
-+ mem_flags |=
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE);
-+ break;
-+ case CSF_FIRMWARE_CACHE_MODE_CACHED:
-+ mem_flags |=
-+ KBASE_REG_MEMATTR_INDEX(
-+ AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY);
-+ break;
-+ case CSF_FIRMWARE_CACHE_MODE_UNCACHED_COHERENT:
-+ case CSF_FIRMWARE_CACHE_MODE_CACHED_COHERENT:
-+ WARN_ON(!is_shared);
-+ mem_flags |= KBASE_REG_SHARE_BOTH |
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_SHARED);
-+ break;
-+ default:
-+ dev_err(kbdev->dev,
-+ "Firmware contains interface with unsupported cache mode\n");
-+ break;
-+ }
-+ return mem_flags;
-+}
-+
-+static void load_fw_image_section(struct kbase_device *kbdev, const u8 *data,
-+ struct tagged_addr *phys, u32 num_pages, u32 flags,
-+ u32 data_start, u32 data_end)
-+{
-+ u32 data_pos = data_start;
-+ u32 data_len = data_end - data_start;
-+ u32 page_num;
-+ u32 page_limit;
-+
-+ if (flags & CSF_FIRMWARE_ENTRY_ZERO)
-+ page_limit = num_pages;
-+ else
-+ page_limit = (data_len + PAGE_SIZE - 1) / PAGE_SIZE;
-+
-+ for (page_num = 0; page_num < page_limit; ++page_num) {
-+ struct page *const page = as_page(phys[page_num]);
-+ char *const p = kmap_atomic(page);
-+ u32 const copy_len = min_t(u32, PAGE_SIZE, data_len);
-+
-+ if (copy_len > 0) {
-+ memcpy(p, data + data_pos, copy_len);
-+ data_pos += copy_len;
-+ data_len -= copy_len;
-+ }
-+
-+ if (flags & CSF_FIRMWARE_ENTRY_ZERO) {
-+ u32 const zi_len = PAGE_SIZE - copy_len;
-+
-+ memset(p + copy_len, 0, zi_len);
-+ }
-+
-+ kbase_sync_single_for_device(kbdev, kbase_dma_addr(page),
-+ PAGE_SIZE, DMA_TO_DEVICE);
-+ kunmap_atomic(p);
-+ }
-+}
-+
-+static int reload_fw_data_sections(struct kbase_device *kbdev)
-+{
-+ const u32 magic = FIRMWARE_HEADER_MAGIC;
-+ struct kbase_csf_firmware_interface *interface;
-+ const struct firmware *firmware;
-+ int ret = 0;
-+
-+ if (request_firmware(&firmware, fw_name, kbdev->dev) != 0) {
-+ dev_err(kbdev->dev,
-+ "Failed to reload firmware image '%s'\n",
-+ fw_name);
-+ return -ENOENT;
-+ }
-+
-+ /* Do couple of basic sanity checks */
-+ if (firmware->size < FIRMWARE_HEADER_LENGTH) {
-+ dev_err(kbdev->dev, "Firmware image unexpectedly too small\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (memcmp(firmware->data, &magic, sizeof(magic)) != 0) {
-+ dev_err(kbdev->dev, "Incorrect magic value, firmware image could have been corrupted\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ list_for_each_entry(interface, &kbdev->csf.firmware_interfaces, node) {
-+ /* Skip reload of text & read only data sections */
-+ if ((interface->flags & CSF_FIRMWARE_ENTRY_EXECUTE) ||
-+ !(interface->flags & CSF_FIRMWARE_ENTRY_WRITE))
-+ continue;
-+
-+ load_fw_image_section(kbdev, firmware->data, interface->phys,
-+ interface->num_pages, interface->flags,
-+ interface->data_start, interface->data_end);
-+ }
-+
-+ kbase_csf_firmware_reload_trace_buffers_data(kbdev);
-+
-+out:
-+ release_firmware(firmware);
-+ return ret;
-+}
-+
-+/**
-+ * parse_memory_setup_entry() - Process an "interface memory setup" section
-+ *
-+ * Read an "interface memory setup" section from the firmware image and create
-+ * the necessary memory region including the MMU page tables. If successful
-+ * the interface will be added to the kbase_device:csf.firmware_interfaces list.
-+ *
-+ * Return: 0 if successful, negative error code on failure
-+ *
-+ * @kbdev: Kbase device structure
-+ * @fw: The firmware image containing the section
-+ * @entry: Pointer to the start of the section
-+ * @size: Size (in bytes) of the section
-+ */
-+static int parse_memory_setup_entry(struct kbase_device *kbdev,
-+ const struct firmware *fw,
-+ const u32 *entry, unsigned int size)
-+{
-+ int ret = 0;
-+ const u32 flags = entry[0];
-+ const u32 virtual_start = entry[1];
-+ const u32 virtual_end = entry[2];
-+ const u32 data_start = entry[3];
-+ const u32 data_end = entry[4];
-+ u32 num_pages;
-+ char *name;
-+ struct tagged_addr *phys = NULL;
-+ struct kbase_csf_firmware_interface *interface = NULL;
-+ bool allocated_pages = false, protected_mode = false;
-+ unsigned long mem_flags = 0;
-+ u32 cache_mode = 0;
-+ struct protected_memory_allocation **pma = NULL;
-+
-+ if (data_end < data_start) {
-+ dev_err(kbdev->dev, "Firmware corrupt, data_end < data_start (0x%x<0x%x)\n",
-+ data_end, data_start);
-+ return -EINVAL;
-+ }
-+ if (virtual_end < virtual_start) {
-+ dev_err(kbdev->dev, "Firmware corrupt, virtual_end < virtual_start (0x%x<0x%x)\n",
-+ virtual_end, virtual_start);
-+ return -EINVAL;
-+ }
-+ if (data_end > fw->size) {
-+ dev_err(kbdev->dev, "Firmware corrupt, file truncated? data_end=0x%x > fw->size=0x%zx\n",
-+ data_end, fw->size);
-+ return -EINVAL;
-+ }
-+
-+ if ((virtual_start & ~PAGE_MASK) != 0 ||
-+ (virtual_end & ~PAGE_MASK) != 0) {
-+ dev_err(kbdev->dev, "Firmware corrupt: virtual addresses not page aligned: 0x%x-0x%x\n",
-+ virtual_start, virtual_end);
-+ return -EINVAL;
-+ }
-+
-+ if ((flags & CSF_FIRMWARE_ENTRY_SUPPORTED_FLAGS) != flags) {
-+ dev_err(kbdev->dev, "Firmware contains interface with unsupported flags (0x%x)\n",
-+ flags);
-+ return -EINVAL;
-+ }
-+
-+ if (flags & CSF_FIRMWARE_ENTRY_PROTECTED)
-+ protected_mode = true;
-+
-+ if (protected_mode && kbdev->csf.pma_dev == NULL) {
-+ dev_err(kbdev->dev,
-+ "Protected memory allocator not found, Firmware protected mode entry will not be supported");
-+ return 0;
-+ }
-+
-+ num_pages = (virtual_end - virtual_start)
-+ >> PAGE_SHIFT;
-+
-+ phys = kmalloc_array(num_pages, sizeof(*phys), GFP_KERNEL);
-+ if (!phys)
-+ return -ENOMEM;
-+
-+ if (protected_mode) {
-+ pma = kbase_csf_protected_memory_alloc(kbdev, phys, num_pages);
-+
-+ if (pma == NULL) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ } else {
-+ ret = kbase_mem_pool_alloc_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ num_pages, phys, false);
-+ if (ret < 0)
-+ goto out;
-+ }
-+
-+ allocated_pages = true;
-+ load_fw_image_section(kbdev, fw->data, phys, num_pages, flags,
-+ data_start, data_end);
-+
-+ /* Allocate enough memory for the struct kbase_csf_firmware_interface and
-+ * the name of the interface. An extra byte is allocated to place a
-+ * NUL-terminator in. This should already be included according to the
-+ * specification but here we add it anyway to be robust against a
-+ * corrupt firmware image.
-+ */
-+ interface = kmalloc(sizeof(*interface) +
-+ size - INTERFACE_ENTRY_NAME_OFFSET + 1, GFP_KERNEL);
-+ if (!interface) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ name = (void *)(interface + 1);
-+ memcpy(name, entry + (INTERFACE_ENTRY_NAME_OFFSET / sizeof(*entry)),
-+ size - INTERFACE_ENTRY_NAME_OFFSET);
-+ name[size - INTERFACE_ENTRY_NAME_OFFSET] = 0;
-+
-+ interface->name = name;
-+ interface->phys = phys;
-+ interface->num_pages = num_pages;
-+ interface->virtual = virtual_start;
-+ interface->kernel_map = NULL;
-+ interface->flags = flags;
-+ interface->data_start = data_start;
-+ interface->data_end = data_end;
-+ interface->pma = pma;
-+
-+ mem_flags = convert_mem_flags(kbdev, flags, &cache_mode);
-+
-+ if (flags & CSF_FIRMWARE_ENTRY_SHARED) {
-+ struct page **page_list;
-+ u32 i;
-+ pgprot_t cpu_map_prot;
-+ u32 mem_attr_index = KBASE_REG_MEMATTR_VALUE(mem_flags);
-+
-+ /* Since SHARED memory type was used for mapping shared memory
-+ * on GPU side, it can be mapped as cached on CPU side on both
-+ * types of coherent platforms.
-+ */
-+ if ((cache_mode == CSF_FIRMWARE_CACHE_MODE_CACHED_COHERENT) ||
-+ (cache_mode == CSF_FIRMWARE_CACHE_MODE_UNCACHED_COHERENT)) {
-+ WARN_ON(mem_attr_index !=
-+ AS_MEMATTR_INDEX_SHARED);
-+ cpu_map_prot = PAGE_KERNEL;
-+ } else {
-+ WARN_ON(mem_attr_index !=
-+ AS_MEMATTR_INDEX_NON_CACHEABLE);
-+ cpu_map_prot = pgprot_writecombine(PAGE_KERNEL);
-+ }
-+
-+ page_list = kmalloc_array(num_pages, sizeof(*page_list),
-+ GFP_KERNEL);
-+ if (!page_list) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+
-+ for (i = 0; i < num_pages; i++)
-+ page_list[i] = as_page(phys[i]);
-+
-+ interface->kernel_map = vmap(page_list, num_pages, VM_MAP,
-+ cpu_map_prot);
-+
-+ kfree(page_list);
-+
-+ if (!interface->kernel_map) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ }
-+
-+ /* Start location of the shared interface area is fixed and is
-+ * specified in firmware spec, and so there shall only be a
-+ * single entry with that start address.
-+ */
-+ if (virtual_start == (KBASE_REG_ZONE_MCU_SHARED_BASE << PAGE_SHIFT))
-+ kbdev->csf.shared_interface = interface;
-+
-+ list_add(&interface->node, &kbdev->csf.firmware_interfaces);
-+
-+ ret = kbase_mmu_insert_pages_no_flush(kbdev, &kbdev->csf.mcu_mmu,
-+ virtual_start >> PAGE_SHIFT, phys, num_pages, mem_flags,
-+ KBASE_MEM_GROUP_CSF_FW);
-+
-+ if (ret != 0) {
-+ dev_err(kbdev->dev, "Failed to insert firmware pages\n");
-+ /* The interface has been added to the list, so cleanup will
-+ * be handled by firmware unloading
-+ */
-+ }
-+
-+ dev_dbg(kbdev->dev, "Processed section '%s'", name);
-+
-+ return ret;
-+
-+out:
-+ if (allocated_pages) {
-+ if (protected_mode) {
-+ kbase_csf_protected_memory_free(kbdev, pma, num_pages);
-+ } else {
-+ kbase_mem_pool_free_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ num_pages, phys, false, false);
-+ }
-+ }
-+
-+ kfree(phys);
-+ kfree(interface);
-+ return ret;
-+}
-+
-+/**
-+ * parse_timeline_metadata_entry() - Process a "timeline metadata" section
-+ *
-+ * Return: 0 if successful, negative error code on failure
-+ *
-+ * @kbdev: Kbase device structure
-+ * @fw: Firmware image containing the section
-+ * @entry: Pointer to the section
-+ * @size: Size (in bytes) of the section
-+ */
-+static int parse_timeline_metadata_entry(struct kbase_device *kbdev,
-+ const struct firmware *fw, const u32 *entry, unsigned int size)
-+{
-+ const u32 data_start = entry[0];
-+ const u32 data_size = entry[1];
-+ const u32 data_end = data_start + data_size;
-+ const char *name = (char *)&entry[2];
-+ struct firmware_timeline_metadata *metadata;
-+ const unsigned int name_len =
-+ size - TL_METADATA_ENTRY_NAME_OFFSET;
-+ size_t allocation_size = sizeof(*metadata) + name_len + 1 + data_size;
-+
-+ if (data_end > fw->size) {
-+ dev_err(kbdev->dev,
-+ "Firmware corrupt, file truncated? data_end=0x%x > fw->size=0x%zx",
-+ data_end, fw->size);
-+ return -EINVAL;
-+ }
-+
-+ /* Allocate enough space for firmware_timeline_metadata,
-+ * its name and the content.
-+ */
-+ metadata = kmalloc(allocation_size, GFP_KERNEL);
-+ if (!metadata)
-+ return -ENOMEM;
-+
-+ metadata->name = (char *)(metadata + 1);
-+ metadata->data = (char *)(metadata + 1) + name_len + 1;
-+ metadata->size = data_size;
-+
-+ memcpy(metadata->name, name, name_len);
-+ metadata->name[name_len] = 0;
-+
-+ /* Copy metadata's content. */
-+ memcpy(metadata->data, fw->data + data_start, data_size);
-+
-+ list_add(&metadata->node, &kbdev->csf.firmware_timeline_metadata);
-+
-+ dev_dbg(kbdev->dev, "Timeline metadata '%s'", metadata->name);
-+
-+ return 0;
-+}
-+
-+/**
-+ * load_firmware_entry() - Process an entry from a firmware image
-+ *
-+ * Read an entry from a firmware image and do any necessary work (e.g. loading
-+ * the data into page accessible to the MCU).
-+ *
-+ * Unknown entries are ignored if the 'optional' flag is set within the entry,
-+ * otherwise the function will fail with -EINVAL
-+ *
-+ * Return: 0 if successful, negative error code on failure
-+ *
-+ * @kbdev: Kbase device
-+ * @fw: Firmware image containing the entry
-+ * @offset: Byte offset within the image of the entry to load
-+ * @header: Header word of the entry
-+ */
-+static int load_firmware_entry(struct kbase_device *kbdev,
-+ const struct firmware *fw,
-+ u32 offset, u32 header)
-+{
-+ const unsigned int type = entry_type(header);
-+ unsigned int size = entry_size(header);
-+ const bool optional = entry_optional(header);
-+ /* Update is used with configuration and tracebuffer entries to
-+ * initiate a FIRMWARE_CONFIG_UPDATE, instead of triggering a
-+ * silent reset.
-+ */
-+ const bool updatable = entry_update(header);
-+ const u32 *entry = (void *)(fw->data + offset);
-+
-+ if ((offset % sizeof(*entry)) || (size % sizeof(*entry))) {
-+ dev_err(kbdev->dev, "Firmware entry isn't 32 bit aligned, offset=0x%x size=0x%x\n",
-+ offset, size);
-+ return -EINVAL;
-+ }
-+
-+ if (size < sizeof(*entry)) {
-+ dev_err(kbdev->dev, "Size field too small: %u\n", size);
-+ return -EINVAL;
-+ }
-+
-+ /* Remove the header */
-+ entry++;
-+ size -= sizeof(*entry);
-+
-+ switch (type) {
-+ case CSF_FIRMWARE_ENTRY_TYPE_INTERFACE:
-+ /* Interface memory setup */
-+ if (size < INTERFACE_ENTRY_NAME_OFFSET + sizeof(*entry)) {
-+ dev_err(kbdev->dev, "Interface memory setup entry too short (size=%u)\n",
-+ size);
-+ return -EINVAL;
-+ }
-+ return parse_memory_setup_entry(kbdev, fw, entry, size);
-+ case CSF_FIRMWARE_ENTRY_TYPE_CONFIGURATION:
-+ /* Configuration option */
-+ if (size < CONFIGURATION_ENTRY_NAME_OFFSET + sizeof(*entry)) {
-+ dev_err(kbdev->dev, "Configuration option entry too short (size=%u)\n",
-+ size);
-+ return -EINVAL;
-+ }
-+ return kbase_csf_firmware_cfg_option_entry_parse(
-+ kbdev, fw, entry, size, updatable);
-+ case CSF_FIRMWARE_ENTRY_TYPE_FUTF_TEST:
-+#ifndef MALI_KBASE_BUILD
-+ /* FW UTF option */
-+ if (size < 2*sizeof(*entry)) {
-+ dev_err(kbdev->dev, "FW UTF entry too short (size=%u)\n",
-+ size);
-+ return -EINVAL;
-+ }
-+ return mali_kutf_process_fw_utf_entry(kbdev, fw->data,
-+ fw->size, entry);
-+#endif
-+ break;
-+ case CSF_FIRMWARE_ENTRY_TYPE_TRACE_BUFFER:
-+ /* Trace buffer */
-+ if (size < TRACE_BUFFER_ENTRY_NAME_OFFSET + sizeof(*entry)) {
-+ dev_err(kbdev->dev, "Trace Buffer entry too short (size=%u)\n",
-+ size);
-+ return -EINVAL;
-+ }
-+ return kbase_csf_firmware_parse_trace_buffer_entry(
-+ kbdev, entry, size, updatable);
-+ case CSF_FIRMWARE_ENTRY_TYPE_TIMELINE_METADATA:
-+ /* Meta data section */
-+ if (size < TL_METADATA_ENTRY_NAME_OFFSET + sizeof(*entry)) {
-+ dev_err(kbdev->dev, "Timeline metadata entry too short (size=%u)\n",
-+ size);
-+ return -EINVAL;
-+ }
-+ return parse_timeline_metadata_entry(kbdev, fw, entry, size);
-+ }
-+
-+ if (!optional) {
-+ dev_err(kbdev->dev,
-+ "Unsupported non-optional entry type %u in firmware\n",
-+ type);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static void free_global_iface(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *iface = &kbdev->csf.global_iface;
-+
-+ if (iface->groups) {
-+ unsigned int gid;
-+
-+ for (gid = 0; gid < iface->group_num; ++gid)
-+ kfree(iface->groups[gid].streams);
-+
-+ kfree(iface->groups);
-+ iface->groups = NULL;
-+ }
-+}
-+
-+/**
-+ * iface_gpu_va_to_cpu - Convert a GPU VA address within the shared interface
-+ * region to a CPU address, using the existing mapping.
-+ * @kbdev: Device pointer
-+ * @gpu_va: GPU VA to convert
-+ *
-+ * Return: A CPU pointer to the location within the shared interface region, or
-+ * NULL on failure.
-+ */
-+static inline void *iface_gpu_va_to_cpu(struct kbase_device *kbdev, u32 gpu_va)
-+{
-+ struct kbase_csf_firmware_interface *interface =
-+ kbdev->csf.shared_interface;
-+ u8 *kernel_base = interface->kernel_map;
-+
-+ if (gpu_va < interface->virtual ||
-+ gpu_va >= interface->virtual + interface->num_pages * PAGE_SIZE) {
-+ dev_err(kbdev->dev,
-+ "Interface address 0x%x not within %u-page region at 0x%x",
-+ gpu_va, interface->num_pages,
-+ interface->virtual);
-+ return NULL;
-+ }
-+
-+ return (void *)(kernel_base + (gpu_va - interface->virtual));
-+}
-+
-+static int parse_cmd_stream_info(struct kbase_device *kbdev,
-+ struct kbase_csf_cmd_stream_info *sinfo,
-+ u32 *stream_base)
-+{
-+ sinfo->kbdev = kbdev;
-+ sinfo->features = stream_base[STREAM_FEATURES/4];
-+ sinfo->input = iface_gpu_va_to_cpu(kbdev,
-+ stream_base[STREAM_INPUT_VA/4]);
-+ sinfo->output = iface_gpu_va_to_cpu(kbdev,
-+ stream_base[STREAM_OUTPUT_VA/4]);
-+
-+ if (sinfo->input == NULL || sinfo->output == NULL)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static int parse_cmd_stream_group_info(struct kbase_device *kbdev,
-+ struct kbase_csf_cmd_stream_group_info *ginfo,
-+ u32 *group_base, u32 group_stride)
-+{
-+ unsigned int sid;
-+
-+ ginfo->kbdev = kbdev;
-+ ginfo->features = group_base[GROUP_FEATURES/4];
-+ ginfo->input = iface_gpu_va_to_cpu(kbdev,
-+ group_base[GROUP_INPUT_VA/4]);
-+ ginfo->output = iface_gpu_va_to_cpu(kbdev,
-+ group_base[GROUP_OUTPUT_VA/4]);
-+
-+ if (ginfo->input == NULL || ginfo->output == NULL)
-+ return -ENOMEM;
-+
-+ ginfo->suspend_size = group_base[GROUP_SUSPEND_SIZE/4];
-+ ginfo->protm_suspend_size = group_base[GROUP_PROTM_SUSPEND_SIZE/4];
-+ ginfo->stream_num = group_base[GROUP_STREAM_NUM/4];
-+
-+ if (ginfo->stream_num < MIN_SUPPORTED_STREAMS_PER_GROUP ||
-+ ginfo->stream_num > MAX_SUPPORTED_STREAMS_PER_GROUP) {
-+ dev_err(kbdev->dev, "CSG with %u CSs out of range %u-%u",
-+ ginfo->stream_num,
-+ MIN_SUPPORTED_STREAMS_PER_GROUP,
-+ MAX_SUPPORTED_STREAMS_PER_GROUP);
-+ return -EINVAL;
-+ }
-+
-+ ginfo->stream_stride = group_base[GROUP_STREAM_STRIDE/4];
-+
-+ if (ginfo->stream_num * ginfo->stream_stride > group_stride) {
-+ dev_err(kbdev->dev,
-+ "group stride of 0x%x exceeded by %u CSs with stride 0x%x",
-+ group_stride, ginfo->stream_num,
-+ ginfo->stream_stride);
-+ return -EINVAL;
-+ }
-+
-+ ginfo->streams = kmalloc_array(ginfo->stream_num,
-+ sizeof(*ginfo->streams), GFP_KERNEL);
-+
-+ if (!ginfo->streams)
-+ return -ENOMEM;
-+
-+ for (sid = 0; sid < ginfo->stream_num; sid++) {
-+ int err;
-+ u32 *stream_base = group_base + (STREAM_CONTROL_0 +
-+ ginfo->stream_stride * sid) / 4;
-+
-+ err = parse_cmd_stream_info(kbdev, &ginfo->streams[sid],
-+ stream_base);
-+ if (err < 0) {
-+ /* caller will free the memory for CSs array */
-+ return err;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static u32 get_firmware_version(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_firmware_interface *interface =
-+ kbdev->csf.shared_interface;
-+ u32 *shared_info = interface->kernel_map;
-+
-+ return shared_info[GLB_VERSION/4];
-+}
-+
-+static int parse_capabilities(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_firmware_interface *interface =
-+ kbdev->csf.shared_interface;
-+ u32 *shared_info = interface->kernel_map;
-+ struct kbase_csf_global_iface *iface = &kbdev->csf.global_iface;
-+ unsigned int gid;
-+
-+ /* All offsets are in bytes, so divide by 4 for access via a u32 pointer
-+ */
-+
-+ /* The version number of the global interface is expected to be a
-+ * non-zero value. If it's not, the firmware may not have booted.
-+ */
-+ iface->version = get_firmware_version(kbdev);
-+ if (!iface->version) {
-+ dev_err(kbdev->dev, "Version check failed. Firmware may have failed to boot.");
-+ return -EINVAL;
-+ }
-+
-+
-+ iface->kbdev = kbdev;
-+ iface->features = shared_info[GLB_FEATURES/4];
-+ iface->input = iface_gpu_va_to_cpu(kbdev, shared_info[GLB_INPUT_VA/4]);
-+ iface->output = iface_gpu_va_to_cpu(kbdev,
-+ shared_info[GLB_OUTPUT_VA/4]);
-+
-+ if (iface->input == NULL || iface->output == NULL)
-+ return -ENOMEM;
-+
-+ iface->group_num = shared_info[GLB_GROUP_NUM/4];
-+
-+ if (iface->group_num < MIN_SUPPORTED_CSGS ||
-+ iface->group_num > MAX_SUPPORTED_CSGS) {
-+ dev_err(kbdev->dev,
-+ "Interface containing %u CSGs outside of range %u-%u",
-+ iface->group_num, MIN_SUPPORTED_CSGS,
-+ MAX_SUPPORTED_CSGS);
-+ return -EINVAL;
-+ }
-+
-+ iface->group_stride = shared_info[GLB_GROUP_STRIDE/4];
-+ iface->prfcnt_size = shared_info[GLB_PRFCNT_SIZE/4];
-+
-+ if (iface->version >= kbase_csf_interface_version(1, 1, 0)) {
-+ iface->instr_features = shared_info[GLB_INSTR_FEATURES / 4];
-+ } else {
-+ iface->instr_features = 0;
-+ }
-+
-+ if ((GROUP_CONTROL_0 +
-+ (unsigned long)iface->group_num * iface->group_stride) >
-+ (interface->num_pages * PAGE_SIZE)) {
-+ dev_err(kbdev->dev,
-+ "interface size of %u pages exceeded by %u CSGs with stride 0x%x",
-+ interface->num_pages, iface->group_num,
-+ iface->group_stride);
-+ return -EINVAL;
-+ }
-+
-+ WARN_ON(iface->groups);
-+
-+ iface->groups = kcalloc(iface->group_num, sizeof(*iface->groups),
-+ GFP_KERNEL);
-+ if (!iface->groups)
-+ return -ENOMEM;
-+
-+ for (gid = 0; gid < iface->group_num; gid++) {
-+ int err;
-+ u32 *group_base = shared_info + (GROUP_CONTROL_0 +
-+ iface->group_stride * gid) / 4;
-+
-+ err = parse_cmd_stream_group_info(kbdev, &iface->groups[gid],
-+ group_base, iface->group_stride);
-+ if (err < 0) {
-+ free_global_iface(kbdev);
-+ return err;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static inline void access_firmware_memory(struct kbase_device *kbdev,
-+ u32 gpu_addr, u32 *value, const bool read)
-+{
-+ struct kbase_csf_firmware_interface *interface;
-+
-+ list_for_each_entry(interface, &kbdev->csf.firmware_interfaces, node) {
-+ if ((gpu_addr >= interface->virtual) &&
-+ (gpu_addr < interface->virtual + (interface->num_pages << PAGE_SHIFT))) {
-+ u32 offset_bytes = gpu_addr - interface->virtual;
-+ u32 page_num = offset_bytes >> PAGE_SHIFT;
-+ u32 offset_in_page = offset_bytes & ~PAGE_MASK;
-+ struct page *target_page = as_page(
-+ interface->phys[page_num]);
-+ u32 *cpu_addr = kmap_atomic(target_page);
-+
-+ if (read) {
-+ kbase_sync_single_for_device(kbdev,
-+ kbase_dma_addr(target_page) + offset_in_page,
-+ sizeof(u32), DMA_BIDIRECTIONAL);
-+
-+ *value = cpu_addr[offset_in_page >> 2];
-+ } else {
-+ cpu_addr[offset_in_page >> 2] = *value;
-+
-+ kbase_sync_single_for_device(kbdev,
-+ kbase_dma_addr(target_page) + offset_in_page,
-+ sizeof(u32), DMA_BIDIRECTIONAL);
-+ }
-+
-+ kunmap_atomic(cpu_addr);
-+ return;
-+ }
-+ }
-+ dev_warn(kbdev->dev, "Invalid GPU VA %x passed\n", gpu_addr);
-+}
-+
-+void kbase_csf_read_firmware_memory(struct kbase_device *kbdev,
-+ u32 gpu_addr, u32 *value)
-+{
-+ access_firmware_memory(kbdev, gpu_addr, value, true);
-+}
-+
-+void kbase_csf_update_firmware_memory(struct kbase_device *kbdev,
-+ u32 gpu_addr, u32 value)
-+{
-+ access_firmware_memory(kbdev, gpu_addr, &value, false);
-+}
-+
-+void kbase_csf_firmware_cs_input(
-+ const struct kbase_csf_cmd_stream_info *const info, const u32 offset,
-+ const u32 value)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+
-+ dev_dbg(kbdev->dev, "cs input w: reg %08x val %08x\n", offset, value);
-+ input_page_write(info->input, offset, value);
-+}
-+
-+u32 kbase_csf_firmware_cs_input_read(
-+ const struct kbase_csf_cmd_stream_info *const info,
-+ const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+ u32 const val = input_page_read(info->input, offset);
-+
-+ dev_dbg(kbdev->dev, "cs input r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+void kbase_csf_firmware_cs_input_mask(
-+ const struct kbase_csf_cmd_stream_info *const info, const u32 offset,
-+ const u32 value, const u32 mask)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+
-+ dev_dbg(kbdev->dev, "cs input w: reg %08x val %08x mask %08x\n",
-+ offset, value, mask);
-+ input_page_partial_write(info->input, offset, value, mask);
-+}
-+
-+u32 kbase_csf_firmware_cs_output(
-+ const struct kbase_csf_cmd_stream_info *const info, const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+ u32 const val = output_page_read(info->output, offset);
-+
-+ dev_dbg(kbdev->dev, "cs output r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+void kbase_csf_firmware_csg_input(
-+ const struct kbase_csf_cmd_stream_group_info *const info,
-+ const u32 offset, const u32 value)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+
-+ dev_dbg(kbdev->dev, "csg input w: reg %08x val %08x\n",
-+ offset, value);
-+ input_page_write(info->input, offset, value);
-+}
-+
-+u32 kbase_csf_firmware_csg_input_read(
-+ const struct kbase_csf_cmd_stream_group_info *const info,
-+ const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+ u32 const val = input_page_read(info->input, offset);
-+
-+ dev_dbg(kbdev->dev, "csg input r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+void kbase_csf_firmware_csg_input_mask(
-+ const struct kbase_csf_cmd_stream_group_info *const info,
-+ const u32 offset, const u32 value, const u32 mask)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+
-+ dev_dbg(kbdev->dev, "csg input w: reg %08x val %08x mask %08x\n",
-+ offset, value, mask);
-+ input_page_partial_write(info->input, offset, value, mask);
-+}
-+
-+u32 kbase_csf_firmware_csg_output(
-+ const struct kbase_csf_cmd_stream_group_info *const info,
-+ const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+ u32 const val = output_page_read(info->output, offset);
-+
-+ dev_dbg(kbdev->dev, "csg output r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+void kbase_csf_firmware_global_input(
-+ const struct kbase_csf_global_iface *const iface, const u32 offset,
-+ const u32 value)
-+{
-+ const struct kbase_device * const kbdev = iface->kbdev;
-+
-+ dev_dbg(kbdev->dev, "glob input w: reg %08x val %08x\n", offset, value);
-+ input_page_write(iface->input, offset, value);
-+}
-+
-+void kbase_csf_firmware_global_input_mask(
-+ const struct kbase_csf_global_iface *const iface, const u32 offset,
-+ const u32 value, const u32 mask)
-+{
-+ const struct kbase_device * const kbdev = iface->kbdev;
-+
-+ dev_dbg(kbdev->dev, "glob input w: reg %08x val %08x mask %08x\n",
-+ offset, value, mask);
-+ input_page_partial_write(iface->input, offset, value, mask);
-+}
-+
-+u32 kbase_csf_firmware_global_input_read(
-+ const struct kbase_csf_global_iface *const iface, const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = iface->kbdev;
-+ u32 const val = input_page_read(iface->input, offset);
-+
-+ dev_dbg(kbdev->dev, "glob input r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+u32 kbase_csf_firmware_global_output(
-+ const struct kbase_csf_global_iface *const iface, const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = iface->kbdev;
-+ u32 const val = output_page_read(iface->output, offset);
-+
-+ dev_dbg(kbdev->dev, "glob output r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+/**
-+ * handle_internal_firmware_fatal - Handler for CS internal firmware fault.
-+ *
-+ * @kbdev: Pointer to kbase device
-+ *
-+ * Report group fatal error to user space for all GPU command queue groups
-+ * in the device, terminate them and reset GPU.
-+ */
-+static void handle_internal_firmware_fatal(struct kbase_device *const kbdev)
-+{
-+ int as;
-+
-+ for (as = 0; as < kbdev->nr_hw_address_spaces; as++) {
-+ unsigned long flags;
-+ struct kbase_context *kctx;
-+ struct kbase_fault fault;
-+
-+ if (as == MCU_AS_NR)
-+ continue;
-+
-+ /* Only handle the fault for an active address space. Lock is
-+ * taken here to atomically get reference to context in an
-+ * active address space and retain its refcount.
-+ */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kctx = kbase_ctx_sched_as_to_ctx_nolock(kbdev, as);
-+
-+ if (kctx) {
-+ kbase_ctx_sched_retain_ctx_refcount(kctx);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ } else {
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ continue;
-+ }
-+
-+ fault = (struct kbase_fault) {
-+ .status = GPU_EXCEPTION_TYPE_SW_FAULT_1,
-+ };
-+
-+ kbase_csf_ctx_handle_fault(kctx, &fault);
-+ kbase_ctx_sched_release_ctx_lock(kctx);
-+ }
-+
-+ if (kbase_prepare_to_reset_gpu(kbdev,
-+ RESET_FLAGS_HWC_UNRECOVERABLE_ERROR))
-+ kbase_reset_gpu(kbdev);
-+}
-+
-+/**
-+ * firmware_error_worker - Worker function for handling firmware internal error
-+ *
-+ * @data: Pointer to a work_struct embedded in kbase device.
-+ *
-+ * Handle the CS internal firmware error
-+ */
-+static void firmware_error_worker(struct work_struct *const data)
-+{
-+ struct kbase_device *const kbdev =
-+ container_of(data, struct kbase_device, csf.fw_error_work);
-+
-+ handle_internal_firmware_fatal(kbdev);
-+}
-+
-+static bool global_request_complete(struct kbase_device *const kbdev,
-+ u32 const req_mask)
-+{
-+ struct kbase_csf_global_iface *global_iface =
-+ &kbdev->csf.global_iface;
-+ bool complete = false;
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+
-+ if ((kbase_csf_firmware_global_output(global_iface, GLB_ACK) &
-+ req_mask) ==
-+ (kbase_csf_firmware_global_input_read(global_iface, GLB_REQ) &
-+ req_mask))
-+ complete = true;
-+
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ return complete;
-+}
-+
-+static int wait_for_global_request(struct kbase_device *const kbdev,
-+ u32 const req_mask)
-+{
-+ const long wait_timeout =
-+ kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+ long remaining;
-+ int err = 0;
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ global_request_complete(kbdev, req_mask),
-+ wait_timeout);
-+
-+ if (!remaining) {
-+ dev_warn(kbdev->dev, "Timed out waiting for global request %x to complete",
-+ req_mask);
-+ err = -ETIMEDOUT;
-+ }
-+
-+ return err;
-+}
-+
-+static void set_global_request(
-+ const struct kbase_csf_global_iface *const global_iface,
-+ u32 const req_mask)
-+{
-+ u32 glb_req;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(global_iface->kbdev);
-+
-+ glb_req = kbase_csf_firmware_global_output(global_iface, GLB_ACK);
-+ glb_req ^= req_mask;
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ, glb_req,
-+ req_mask);
-+}
-+
-+static void enable_endpoints_global(
-+ const struct kbase_csf_global_iface *const global_iface,
-+ u64 const shader_core_mask)
-+{
-+ kbase_csf_firmware_global_input(global_iface, GLB_ALLOC_EN_LO,
-+ shader_core_mask & U32_MAX);
-+ kbase_csf_firmware_global_input(global_iface, GLB_ALLOC_EN_HI,
-+ shader_core_mask >> 32);
-+
-+ set_global_request(global_iface, GLB_REQ_CFG_ALLOC_EN_MASK);
-+}
-+
-+static void enable_shader_poweroff_timer(struct kbase_device *const kbdev,
-+ const struct kbase_csf_global_iface *const global_iface)
-+{
-+ u32 pwroff_reg;
-+
-+ if (kbdev->csf.firmware_hctl_core_pwr)
-+ pwroff_reg =
-+ GLB_PWROFF_TIMER_TIMER_SOURCE_SET(DISABLE_GLB_PWROFF_TIMER,
-+ GLB_PWROFF_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP);
-+ else
-+ pwroff_reg = kbdev->csf.mcu_core_pwroff_dur_count;
-+
-+ kbase_csf_firmware_global_input(global_iface, GLB_PWROFF_TIMER,
-+ pwroff_reg);
-+ set_global_request(global_iface, GLB_REQ_CFG_PWROFF_TIMER_MASK);
-+
-+ /* Save the programed reg value in its shadow field */
-+ kbdev->csf.mcu_core_pwroff_reg_shadow = pwroff_reg;
-+
-+ dev_dbg(kbdev->dev, "GLB_PWROFF_TIMER set to 0x%.8x\n", pwroff_reg);
-+}
-+
-+static void set_timeout_global(
-+ const struct kbase_csf_global_iface *const global_iface,
-+ u64 const timeout)
-+{
-+ kbase_csf_firmware_global_input(global_iface, GLB_PROGRESS_TIMER,
-+ timeout / GLB_PROGRESS_TIMER_TIMEOUT_SCALE);
-+
-+ set_global_request(global_iface, GLB_REQ_CFG_PROGRESS_TIMER_MASK);
-+}
-+
-+static void global_init(struct kbase_device *const kbdev, u64 core_mask)
-+{
-+ u32 const ack_irq_mask = GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_MASK |
-+ GLB_ACK_IRQ_MASK_PING_MASK |
-+ GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_MASK |
-+ GLB_ACK_IRQ_MASK_PROTM_ENTER_MASK |
-+ GLB_ACK_IRQ_MASK_PROTM_EXIT_MASK |
-+ GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK |
-+ GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_MASK |
-+ GLB_ACK_IRQ_MASK_IDLE_EVENT_MASK;
-+
-+ const struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+
-+ /* Set the coherency mode for protected mode execution */
-+ WARN_ON(kbdev->system_coherency == COHERENCY_ACE);
-+ kbase_csf_firmware_global_input(global_iface, GLB_PROTM_COHERENCY,
-+ kbdev->system_coherency);
-+
-+ /* Update shader core allocation enable mask */
-+ enable_endpoints_global(global_iface, core_mask);
-+ enable_shader_poweroff_timer(kbdev, global_iface);
-+
-+ set_timeout_global(global_iface, kbase_csf_timeout_get(kbdev));
-+
-+ /* Unmask the interrupts */
-+ kbase_csf_firmware_global_input(global_iface,
-+ GLB_ACK_IRQ_MASK, ack_irq_mask);
-+
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+/**
-+ * global_init_on_boot - Sends a global request to control various features.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface
-+ *
-+ * Currently only the request to enable endpoints and timeout for GPU progress
-+ * timer is sent.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+static int global_init_on_boot(struct kbase_device *const kbdev)
-+{
-+ unsigned long flags;
-+ u64 core_mask;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ core_mask = kbase_pm_ca_get_core_mask(kbdev);
-+ kbdev->csf.firmware_hctl_core_pwr =
-+ kbase_pm_no_mcu_core_pwroff(kbdev);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ global_init(kbdev, core_mask);
-+
-+ return wait_for_global_request(kbdev, CSF_GLB_REQ_CFG_MASK);
-+}
-+
-+void kbase_csf_firmware_global_reinit(struct kbase_device *kbdev,
-+ u64 core_mask)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ kbdev->csf.glb_init_request_pending = true;
-+ kbdev->csf.firmware_hctl_core_pwr =
-+ kbase_pm_no_mcu_core_pwroff(kbdev);
-+ global_init(kbdev, core_mask);
-+}
-+
-+bool kbase_csf_firmware_global_reinit_complete(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+ WARN_ON(!kbdev->csf.glb_init_request_pending);
-+
-+ if (global_request_complete(kbdev, CSF_GLB_REQ_CFG_MASK))
-+ kbdev->csf.glb_init_request_pending = false;
-+
-+ return !kbdev->csf.glb_init_request_pending;
-+}
-+
-+void kbase_csf_firmware_update_core_attr(struct kbase_device *kbdev,
-+ bool update_core_pwroff_timer, bool update_core_mask, u64 core_mask)
-+{
-+ unsigned long flags;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ if (update_core_mask)
-+ enable_endpoints_global(&kbdev->csf.global_iface, core_mask);
-+ if (update_core_pwroff_timer)
-+ enable_shader_poweroff_timer(kbdev, &kbdev->csf.global_iface);
-+
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+bool kbase_csf_firmware_core_attr_updated(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ return global_request_complete(kbdev, GLB_REQ_CFG_ALLOC_EN_MASK |
-+ GLB_REQ_CFG_PWROFF_TIMER_MASK);
-+}
-+
-+/**
-+ * kbase_csf_firmware_reload_worker() -
-+ * reload the fw image and re-enable the MCU
-+ * @work: CSF Work item for reloading the firmware.
-+ *
-+ * This helper function will reload the firmware image and re-enable the MCU.
-+ * It is supposed to be called after MCU(GPU) has been reset.
-+ * Unlike the initial boot the firmware binary image is not parsed completely.
-+ * Only the data sections, which were loaded in memory during the initial boot,
-+ * are re-initialized either by zeroing them or copying their data from the
-+ * firmware binary image. The memory allocation for the firmware pages and
-+ * MMU programming is not needed for the reboot, presuming the firmware binary
-+ * file on the filesystem would not change.
-+ */
-+static void kbase_csf_firmware_reload_worker(struct work_struct *work)
-+{
-+ struct kbase_device *kbdev = container_of(work, struct kbase_device,
-+ csf.firmware_reload_work);
-+ int err;
-+
-+ dev_info(kbdev->dev, "reloading firmware");
-+
-+ /* Reload just the data sections from firmware binary image */
-+ err = reload_fw_data_sections(kbdev);
-+ if (err)
-+ return;
-+
-+ kbase_csf_tl_reader_reset(&kbdev->timeline->csf_tl_reader);
-+
-+ /* Reboot the firmware */
-+ kbase_csf_firmware_enable_mcu(kbdev);
-+}
-+
-+void kbase_csf_firmware_trigger_reload(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ kbdev->csf.firmware_reloaded = false;
-+
-+ if (kbdev->csf.firmware_reload_needed) {
-+ kbdev->csf.firmware_reload_needed = false;
-+ queue_work(system_wq, &kbdev->csf.firmware_reload_work);
-+ } else {
-+ kbase_csf_firmware_enable_mcu(kbdev);
-+ }
-+}
-+
-+void kbase_csf_firmware_reload_completed(struct kbase_device *kbdev)
-+{
-+ u32 version;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ if (unlikely(!kbdev->csf.firmware_inited))
-+ return;
-+
-+ /* Check firmware rebooted properly: we do not expect
-+ * the version number to change with a running reboot.
-+ */
-+ version = get_firmware_version(kbdev);
-+
-+ if (version != kbdev->csf.global_iface.version)
-+ dev_err(kbdev->dev, "Version check failed in firmware reboot.");
-+
-+ KBASE_KTRACE_ADD(kbdev, FIRMWARE_REBOOT, NULL, 0u);
-+
-+ /* Tell MCU state machine to transit to next state */
-+ kbdev->csf.firmware_reloaded = true;
-+ kbase_pm_update_state(kbdev);
-+}
-+
-+static u32 convert_dur_to_idle_count(struct kbase_device *kbdev, const u32 dur_ms)
-+{
-+#define HYSTERESIS_VAL_UNIT_SHIFT (10)
-+ /* Get the cntfreq_el0 value, which drives the SYSTEM_TIMESTAMP */
-+ u64 freq = arch_timer_get_cntfrq();
-+ u64 dur_val = dur_ms;
-+ u32 cnt_val_u32, reg_val_u32;
-+ bool src_system_timestamp = freq > 0;
-+
-+ if (!src_system_timestamp) {
-+ /* Get the cycle_counter source alternative */
-+ spin_lock(&kbdev->pm.clk_rtm.lock);
-+ if (kbdev->pm.clk_rtm.clks[0])
-+ freq = kbdev->pm.clk_rtm.clks[0]->clock_val;
-+ else
-+ dev_warn(kbdev->dev, "No GPU clock, unexpected intregration issue!");
-+ spin_unlock(&kbdev->pm.clk_rtm.lock);
-+
-+ dev_info(kbdev->dev, "Can't get the timestamp frequency, "
-+ "use cycle counter format with firmware idle hysteresis!");
-+ }
-+
-+ /* Formula for dur_val = ((dur_ms/1000) * freq_HZ) >> 10) */
-+ dur_val = (dur_val * freq) >> HYSTERESIS_VAL_UNIT_SHIFT;
-+ dur_val = div_u64(dur_val, 1000);
-+
-+ /* Interface limits the value field to S32_MAX */
-+ cnt_val_u32 = (dur_val > S32_MAX) ? S32_MAX : (u32)dur_val;
-+
-+ reg_val_u32 = GLB_IDLE_TIMER_TIMEOUT_SET(0, cnt_val_u32);
-+ /* add the source flag */
-+ if (src_system_timestamp)
-+ reg_val_u32 = GLB_IDLE_TIMER_TIMER_SOURCE_SET(reg_val_u32,
-+ GLB_IDLE_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP);
-+ else
-+ reg_val_u32 = GLB_IDLE_TIMER_TIMER_SOURCE_SET(reg_val_u32,
-+ GLB_IDLE_TIMER_TIMER_SOURCE_GPU_COUNTER);
-+
-+ return reg_val_u32;
-+}
-+
-+u32 kbase_csf_firmware_get_gpu_idle_hysteresis_time(struct kbase_device *kbdev)
-+{
-+ return kbdev->csf.gpu_idle_hysteresis_ms;
-+}
-+
-+u32 kbase_csf_firmware_set_gpu_idle_hysteresis_time(struct kbase_device *kbdev, u32 dur)
-+{
-+ unsigned long flags;
-+ const u32 hysteresis_val = convert_dur_to_idle_count(kbdev, dur);
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ kbdev->csf.gpu_idle_hysteresis_ms = dur;
-+ kbdev->csf.gpu_idle_dur_count = hysteresis_val;
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ dev_dbg(kbdev->dev, "CSF set firmware idle hysteresis count-value: 0x%.8x",
-+ hysteresis_val);
-+
-+ return hysteresis_val;
-+}
-+
-+static u32 convert_dur_to_core_pwroff_count(struct kbase_device *kbdev, const u32 dur_us)
-+{
-+#define PWROFF_VAL_UNIT_SHIFT (10)
-+ /* Get the cntfreq_el0 value, which drives the SYSTEM_TIMESTAMP */
-+ u64 freq = arch_timer_get_cntfrq();
-+ u64 dur_val = dur_us;
-+ u32 cnt_val_u32, reg_val_u32;
-+ bool src_system_timestamp = freq > 0;
-+
-+ if (!src_system_timestamp) {
-+ /* Get the cycle_counter source alternative */
-+ spin_lock(&kbdev->pm.clk_rtm.lock);
-+ if (kbdev->pm.clk_rtm.clks[0])
-+ freq = kbdev->pm.clk_rtm.clks[0]->clock_val;
-+ else
-+ dev_warn(kbdev->dev, "No GPU clock, unexpected integration issue!");
-+ spin_unlock(&kbdev->pm.clk_rtm.lock);
-+
-+ dev_info(kbdev->dev, "Can't get the timestamp frequency, "
-+ "use cycle counter with MCU Core Poweroff timer!");
-+ }
-+
-+ /* Formula for dur_val = ((dur_us/1e6) * freq_HZ) >> 10) */
-+ dur_val = (dur_val * freq) >> HYSTERESIS_VAL_UNIT_SHIFT;
-+ dur_val = div_u64(dur_val, 1000000);
-+
-+ /* Interface limits the value field to S32_MAX */
-+ cnt_val_u32 = (dur_val > S32_MAX) ? S32_MAX : (u32)dur_val;
-+
-+ reg_val_u32 = GLB_PWROFF_TIMER_TIMEOUT_SET(0, cnt_val_u32);
-+ /* add the source flag */
-+ if (src_system_timestamp)
-+ reg_val_u32 = GLB_PWROFF_TIMER_TIMER_SOURCE_SET(reg_val_u32,
-+ GLB_PWROFF_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP);
-+ else
-+ reg_val_u32 = GLB_PWROFF_TIMER_TIMER_SOURCE_SET(reg_val_u32,
-+ GLB_PWROFF_TIMER_TIMER_SOURCE_GPU_COUNTER);
-+
-+ return reg_val_u32;
-+}
-+
-+u32 kbase_csf_firmware_get_mcu_core_pwroff_time(struct kbase_device *kbdev)
-+{
-+ return kbdev->csf.mcu_core_pwroff_dur_us;
-+}
-+
-+u32 kbase_csf_firmware_set_mcu_core_pwroff_time(struct kbase_device *kbdev, u32 dur)
-+{
-+ unsigned long flags;
-+ const u32 pwroff = convert_dur_to_core_pwroff_count(kbdev, dur);
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->csf.mcu_core_pwroff_dur_us = dur;
-+ kbdev->csf.mcu_core_pwroff_dur_count = pwroff;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ dev_dbg(kbdev->dev, "MCU Core Poweroff input update: 0x%.8x", pwroff);
-+
-+ return pwroff;
-+}
-+
-+
-+int kbase_csf_firmware_early_init(struct kbase_device *kbdev)
-+{
-+ init_waitqueue_head(&kbdev->csf.event_wait);
-+ kbdev->csf.interrupt_received = false;
-+ kbdev->csf.fw_timeout_ms = CSF_FIRMWARE_TIMEOUT_MS;
-+
-+ INIT_LIST_HEAD(&kbdev->csf.firmware_interfaces);
-+ INIT_LIST_HEAD(&kbdev->csf.firmware_config);
-+ INIT_LIST_HEAD(&kbdev->csf.firmware_timeline_metadata);
-+ INIT_LIST_HEAD(&kbdev->csf.firmware_trace_buffers.list);
-+ INIT_WORK(&kbdev->csf.firmware_reload_work,
-+ kbase_csf_firmware_reload_worker);
-+ INIT_WORK(&kbdev->csf.fw_error_work, firmware_error_worker);
-+
-+ mutex_init(&kbdev->csf.reg_lock);
-+
-+ return 0;
-+}
-+
-+int kbase_csf_firmware_init(struct kbase_device *kbdev)
-+{
-+ const struct firmware *firmware;
-+ const u32 magic = FIRMWARE_HEADER_MAGIC;
-+ u8 version_major, version_minor;
-+ u32 version_hash;
-+ u32 entry_end_offset;
-+ u32 entry_offset;
-+ int ret;
-+
-+ lockdep_assert_held(&kbdev->fw_load_lock);
-+
-+ if (WARN_ON((kbdev->as_free & MCU_AS_BITMASK) == 0))
-+ return -EINVAL;
-+ kbdev->as_free &= ~MCU_AS_BITMASK;
-+
-+ ret = kbase_mmu_init(kbdev, &kbdev->csf.mcu_mmu, NULL,
-+ BASE_MEM_GROUP_DEFAULT);
-+
-+ if (ret != 0) {
-+ /* Release the address space */
-+ kbdev->as_free |= MCU_AS_BITMASK;
-+ return ret;
-+ }
-+
-+ kbdev->csf.gpu_idle_hysteresis_ms = FIRMWARE_IDLE_HYSTERESIS_TIME_MS;
-+ kbdev->csf.gpu_idle_dur_count = convert_dur_to_idle_count(
-+ kbdev, FIRMWARE_IDLE_HYSTERESIS_TIME_MS);
-+
-+ kbdev->csf.mcu_core_pwroff_dur_us = DEFAULT_GLB_PWROFF_TIMEOUT_US;
-+ kbdev->csf.mcu_core_pwroff_dur_count = convert_dur_to_core_pwroff_count(
-+ kbdev, DEFAULT_GLB_PWROFF_TIMEOUT_US);
-+
-+ ret = kbase_mcu_shared_interface_region_tracker_init(kbdev);
-+ if (ret != 0) {
-+ dev_err(kbdev->dev,
-+ "Failed to setup the rb tree for managing shared interface segment\n");
-+ goto error;
-+ }
-+
-+ if (request_firmware(&firmware, fw_name, kbdev->dev) != 0) {
-+ dev_err(kbdev->dev,
-+ "Failed to load firmware image '%s'\n",
-+ fw_name);
-+ ret = -ENOENT;
-+ goto error;
-+ }
-+
-+ if (firmware->size < FIRMWARE_HEADER_LENGTH) {
-+ dev_err(kbdev->dev, "Firmware too small\n");
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ if (memcmp(firmware->data, &magic, sizeof(magic)) != 0) {
-+ dev_err(kbdev->dev, "Incorrect firmware magic\n");
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ version_minor = firmware->data[4];
-+ version_major = firmware->data[5];
-+
-+ if (version_major != FIRMWARE_HEADER_VERSION) {
-+ dev_err(kbdev->dev,
-+ "Firmware header version %d.%d not understood\n",
-+ version_major, version_minor);
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ memcpy(&version_hash, &firmware->data[8], sizeof(version_hash));
-+
-+ dev_notice(kbdev->dev, "Loading Mali firmware 0x%x", version_hash);
-+
-+ memcpy(&entry_end_offset, &firmware->data[0x10],
-+ sizeof(entry_end_offset));
-+
-+ if (entry_end_offset > firmware->size) {
-+ dev_err(kbdev->dev, "Firmware image is truncated\n");
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ entry_offset = FIRMWARE_HEADER_LENGTH;
-+ while (entry_offset < entry_end_offset) {
-+ u32 header;
-+ unsigned int size;
-+
-+ memcpy(&header, &firmware->data[entry_offset], sizeof(header));
-+
-+ size = entry_size(header);
-+
-+ ret = load_firmware_entry(kbdev, firmware, entry_offset,
-+ header);
-+ if (ret != 0) {
-+ dev_err(kbdev->dev, "Failed to load firmware image\n");
-+ goto error;
-+ }
-+ entry_offset += size;
-+ }
-+
-+ if (!kbdev->csf.shared_interface) {
-+ dev_err(kbdev->dev, "Shared interface region not found\n");
-+ ret = -EINVAL;
-+ goto error;
-+ } else {
-+ ret = setup_shared_iface_static_region(kbdev);
-+ if (ret != 0) {
-+ dev_err(kbdev->dev, "Failed to insert a region for shared iface entry parsed from fw image\n");
-+ goto error;
-+ }
-+ }
-+
-+ ret = kbase_csf_firmware_trace_buffers_init(kbdev);
-+ if (ret != 0) {
-+ dev_err(kbdev->dev, "Failed to initialize trace buffers\n");
-+ goto error;
-+ }
-+
-+ /* Make sure L2 cache is powered up */
-+ kbase_pm_wait_for_l2_powered(kbdev);
-+
-+ /* Load the MMU tables into the selected address space */
-+ load_mmu_tables(kbdev);
-+
-+ boot_csf_firmware(kbdev);
-+
-+ ret = parse_capabilities(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = kbase_csf_doorbell_mapping_init(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = kbase_csf_scheduler_init(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = kbase_csf_setup_dummy_user_reg_page(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = kbase_csf_timeout_init(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = global_init_on_boot(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = kbase_csf_firmware_cfg_init(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+
-+ /* Firmware loaded successfully */
-+ release_firmware(firmware);
-+ KBASE_KTRACE_ADD(kbdev, FIRMWARE_BOOT, NULL,
-+ (((u64)version_hash) << 32) |
-+ (((u64)version_major) << 8) | version_minor);
-+ return 0;
-+
-+error:
-+ kbase_csf_firmware_term(kbdev);
-+ release_firmware(firmware);
-+ return ret;
-+}
-+
-+void kbase_csf_firmware_term(struct kbase_device *kbdev)
-+{
-+ unsigned long flags;
-+ int ret = 0;
-+
-+ cancel_work_sync(&kbdev->csf.fw_error_work);
-+
-+ ret = kbase_reset_gpu_wait(kbdev);
-+
-+ WARN(ret, "failed to wait for GPU reset");
-+
-+ kbase_csf_firmware_cfg_term(kbdev);
-+
-+ kbase_csf_timeout_term(kbdev);
-+
-+ kbase_csf_free_dummy_user_reg_page(kbdev);
-+
-+ kbase_csf_scheduler_term(kbdev);
-+
-+ kbase_csf_doorbell_mapping_term(kbdev);
-+
-+ /* Explicitly trigger the disabling of MCU through the state machine and
-+ * wait for its completion. It may not have been disabled yet due to the
-+ * power policy.
-+ */
-+ kbdev->pm.backend.mcu_desired = false;
-+ kbase_pm_wait_for_desired_state(kbdev);
-+
-+ free_global_iface(kbdev);
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->csf.firmware_inited = false;
-+ if (WARN_ON(kbdev->pm.backend.mcu_state != KBASE_MCU_OFF)) {
-+ kbdev->pm.backend.mcu_state = KBASE_MCU_OFF;
-+ stop_csf_firmware(kbdev);
-+ }
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ unload_mmu_tables(kbdev);
-+
-+ kbase_csf_firmware_trace_buffers_term(kbdev);
-+
-+ while (!list_empty(&kbdev->csf.firmware_interfaces)) {
-+ struct kbase_csf_firmware_interface *interface;
-+
-+ interface =
-+ list_first_entry(&kbdev->csf.firmware_interfaces,
-+ struct kbase_csf_firmware_interface,
-+ node);
-+ list_del(&interface->node);
-+
-+ vunmap(interface->kernel_map);
-+ if (interface->flags & CSF_FIRMWARE_ENTRY_PROTECTED) {
-+ kbase_csf_protected_memory_free(kbdev, interface->pma,
-+ interface->num_pages);
-+ } else {
-+ kbase_mem_pool_free_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ interface->num_pages, interface->phys,
-+ true, false);
-+ }
-+
-+ kfree(interface->phys);
-+ kfree(interface);
-+ }
-+
-+ while (!list_empty(&kbdev->csf.firmware_timeline_metadata)) {
-+ struct firmware_timeline_metadata *metadata;
-+
-+ metadata = list_first_entry(
-+ &kbdev->csf.firmware_timeline_metadata,
-+ struct firmware_timeline_metadata,
-+ node);
-+ list_del(&metadata->node);
-+
-+ kfree(metadata);
-+ }
-+
-+#ifndef MALI_KBASE_BUILD
-+ mali_kutf_fw_utf_entry_cleanup(kbdev);
-+#endif
-+
-+ /* This will also free up the region allocated for the shared interface
-+ * entry parsed from the firmware image.
-+ */
-+ kbase_mcu_shared_interface_region_tracker_term(kbdev);
-+
-+ mutex_destroy(&kbdev->csf.reg_lock);
-+
-+ kbase_mmu_term(kbdev, &kbdev->csf.mcu_mmu);
-+
-+ /* Release the address space */
-+ kbdev->as_free |= MCU_AS_BITMASK;
-+}
-+
-+void kbase_csf_firmware_enable_gpu_idle_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ const u32 glb_req =
-+ kbase_csf_firmware_global_input_read(global_iface, GLB_REQ);
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+
-+ /* The scheduler is assumed to only call the enable when its internal
-+ * state indicates that the idle timer has previously been disabled. So
-+ * on entry the expected field values are:
-+ * 1. GLOBAL_INPUT_BLOCK.GLB_REQ.IDLE_ENABLE: 0
-+ * 2. GLOBAL_OUTPUT_BLOCK.GLB_ACK.IDLE_ENABLE: 0, or, on 1 -> 0
-+ */
-+
-+ if (glb_req & GLB_REQ_IDLE_ENABLE_MASK)
-+ dev_err(kbdev->dev, "Incoherent scheduler state on REQ_IDLE_ENABLE!");
-+
-+ kbase_csf_firmware_global_input(global_iface, GLB_IDLE_TIMER,
-+ kbdev->csf.gpu_idle_dur_count);
-+
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ,
-+ GLB_REQ_REQ_IDLE_ENABLE, GLB_REQ_IDLE_ENABLE_MASK);
-+
-+ dev_dbg(kbdev->dev, "Enabling GPU idle timer with count-value: 0x%.8x",
-+ kbdev->csf.gpu_idle_dur_count);
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+}
-+
-+void kbase_csf_firmware_disable_gpu_idle_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ,
-+ GLB_REQ_REQ_IDLE_DISABLE,
-+ GLB_REQ_IDLE_DISABLE_MASK);
-+ dev_dbg(kbdev->dev, "Sending request to disable gpu idle timer");
-+
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+}
-+
-+void kbase_csf_firmware_ping(struct kbase_device *const kbdev)
-+{
-+ const struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ set_global_request(global_iface, GLB_REQ_PING_MASK);
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+int kbase_csf_firmware_ping_wait(struct kbase_device *const kbdev)
-+{
-+ kbase_csf_firmware_ping(kbdev);
-+ return wait_for_global_request(kbdev, GLB_REQ_PING_MASK);
-+}
-+
-+int kbase_csf_firmware_set_timeout(struct kbase_device *const kbdev,
-+ u64 const timeout)
-+{
-+ const struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+ unsigned long flags;
-+ int err;
-+
-+ /* The 'reg_lock' is also taken and is held till the update is not
-+ * complete, to ensure the update of timeout value by multiple Users
-+ * gets serialized.
-+ */
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ set_timeout_global(global_iface, timeout);
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ err = wait_for_global_request(kbdev, GLB_REQ_CFG_PROGRESS_TIMER_MASK);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ return err;
-+}
-+
-+void kbase_csf_enter_protected_mode(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ unsigned long flags;
-+ int err;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ set_global_request(global_iface, GLB_REQ_PROTM_ENTER_MASK);
-+ dev_dbg(kbdev->dev, "Sending request to enter protected mode");
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ err = wait_for_global_request(kbdev, GLB_REQ_PROTM_ENTER_MASK);
-+
-+ if (!err) {
-+ unsigned long irq_flags;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->protected_mode = true;
-+ kbase_ipa_protection_mode_switch_event(kbdev);
-+ kbase_ipa_control_protm_entered(kbdev);
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &irq_flags);
-+ kbase_hwcnt_backend_csf_protm_entered(&kbdev->hwcnt_gpu_iface);
-+ kbase_csf_scheduler_spin_unlock(kbdev, irq_flags);
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ }
-+}
-+
-+void kbase_csf_firmware_trigger_mcu_halt(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ set_global_request(global_iface, GLB_REQ_HALT_MASK);
-+ dev_dbg(kbdev->dev, "Sending request to HALT MCU");
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+int kbase_csf_trigger_firmware_config_update(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ unsigned long flags;
-+ int err = 0;
-+
-+ /* Ensure GPU is powered-up until we complete config update.*/
-+ kbase_csf_scheduler_pm_active(kbdev);
-+
-+ /* The 'reg_lock' is also taken and is held till the update is
-+ * complete, to ensure the config update gets serialized.
-+ */
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+
-+ set_global_request(global_iface, GLB_REQ_FIRMWARE_CONFIG_UPDATE_MASK);
-+ dev_dbg(kbdev->dev, "Sending request for FIRMWARE_CONFIG_UPDATE");
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ err = wait_for_global_request(kbdev,
-+ GLB_REQ_FIRMWARE_CONFIG_UPDATE_MASK);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ kbase_csf_scheduler_pm_idle(kbdev);
-+ return err;
-+}
-+
-+/**
-+ * copy_grp_and_stm - Copy CS and/or group data
-+ *
-+ * @iface: Global CSF interface provided by the firmware.
-+ * @group_data: Pointer where to store all the group data
-+ * (sequentially).
-+ * @max_group_num: The maximum number of groups to be read. Can be 0, in
-+ * which case group_data is unused.
-+ * @stream_data: Pointer where to store all the CS data
-+ * (sequentially).
-+ * @max_total_stream_num: The maximum number of CSs to be read.
-+ * Can be 0, in which case stream_data is unused.
-+ *
-+ * Return: Total number of CSs, summed across all groups.
-+ */
-+static u32 copy_grp_and_stm(
-+ const struct kbase_csf_global_iface * const iface,
-+ struct basep_cs_group_control * const group_data,
-+ u32 max_group_num,
-+ struct basep_cs_stream_control * const stream_data,
-+ u32 max_total_stream_num)
-+{
-+ u32 i, total_stream_num = 0;
-+
-+ if (WARN_ON((max_group_num > 0) && !group_data))
-+ max_group_num = 0;
-+
-+ if (WARN_ON((max_total_stream_num > 0) && !stream_data))
-+ max_total_stream_num = 0;
-+
-+ for (i = 0; i < iface->group_num; i++) {
-+ u32 j;
-+
-+ if (i < max_group_num) {
-+ group_data[i].features = iface->groups[i].features;
-+ group_data[i].stream_num = iface->groups[i].stream_num;
-+ group_data[i].suspend_size =
-+ iface->groups[i].suspend_size;
-+ }
-+ for (j = 0; j < iface->groups[i].stream_num; j++) {
-+ if (total_stream_num < max_total_stream_num)
-+ stream_data[total_stream_num].features =
-+ iface->groups[i].streams[j].features;
-+ total_stream_num++;
-+ }
-+ }
-+
-+ return total_stream_num;
-+}
-+
-+u32 kbase_csf_firmware_get_glb_iface(
-+ struct kbase_device *kbdev,
-+ struct basep_cs_group_control *const group_data,
-+ u32 const max_group_num,
-+ struct basep_cs_stream_control *const stream_data,
-+ u32 const max_total_stream_num, u32 *const glb_version,
-+ u32 *const features, u32 *const group_num, u32 *const prfcnt_size,
-+ u32 *instr_features)
-+{
-+ const struct kbase_csf_global_iface * const iface =
-+ &kbdev->csf.global_iface;
-+
-+ if (WARN_ON(!glb_version) || WARN_ON(!features) ||
-+ WARN_ON(!group_num) || WARN_ON(!prfcnt_size) ||
-+ WARN_ON(!instr_features))
-+ return 0;
-+
-+ *glb_version = iface->version;
-+ *features = iface->features;
-+ *group_num = iface->group_num;
-+ *prfcnt_size = iface->prfcnt_size;
-+ *instr_features = iface->instr_features;
-+
-+ return copy_grp_and_stm(iface, group_data, max_group_num,
-+ stream_data, max_total_stream_num);
-+}
-+
-+const char *kbase_csf_firmware_get_timeline_metadata(
-+ struct kbase_device *kbdev, const char *name, size_t *size)
-+{
-+ struct firmware_timeline_metadata *metadata;
-+
-+ list_for_each_entry(
-+ metadata, &kbdev->csf.firmware_timeline_metadata, node) {
-+ if (!strcmp(metadata->name, name)) {
-+ *size = metadata->size;
-+ return metadata->data;
-+ }
-+ }
-+
-+ *size = 0;
-+ return NULL;
-+}
-+
-+int kbase_csf_firmware_mcu_shared_mapping_init(
-+ struct kbase_device *kbdev,
-+ unsigned int num_pages,
-+ unsigned long cpu_map_properties,
-+ unsigned long gpu_map_properties,
-+ struct kbase_csf_mapping *csf_mapping)
-+{
-+ struct tagged_addr *phys;
-+ struct kbase_va_region *va_reg;
-+ struct page **page_list;
-+ void *cpu_addr;
-+ int i, ret = 0;
-+ pgprot_t cpu_map_prot = PAGE_KERNEL;
-+ unsigned long gpu_map_prot;
-+
-+ if (cpu_map_properties & PROT_READ)
-+ cpu_map_prot = PAGE_KERNEL_RO;
-+
-+ if (kbdev->system_coherency == COHERENCY_ACE) {
-+ gpu_map_prot =
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_DEFAULT_ACE);
-+ } else {
-+ gpu_map_prot =
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE);
-+ cpu_map_prot = pgprot_writecombine(cpu_map_prot);
-+ };
-+
-+ phys = kmalloc_array(num_pages, sizeof(*phys), GFP_KERNEL);
-+ if (!phys)
-+ goto out;
-+
-+ page_list = kmalloc_array(num_pages, sizeof(*page_list), GFP_KERNEL);
-+ if (!page_list)
-+ goto page_list_alloc_error;
-+
-+ ret = kbase_mem_pool_alloc_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ num_pages, phys, false);
-+ if (ret <= 0)
-+ goto phys_mem_pool_alloc_error;
-+
-+ for (i = 0; i < num_pages; i++)
-+ page_list[i] = as_page(phys[i]);
-+
-+ cpu_addr = vmap(page_list, num_pages, VM_MAP, cpu_map_prot);
-+ if (!cpu_addr)
-+ goto vmap_error;
-+
-+ va_reg = kbase_alloc_free_region(&kbdev->csf.shared_reg_rbtree, 0,
-+ num_pages, KBASE_REG_ZONE_MCU_SHARED);
-+ if (!va_reg)
-+ goto va_region_alloc_error;
-+
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ ret = kbase_add_va_region_rbtree(kbdev, va_reg, 0, num_pages, 1);
-+ va_reg->flags &= ~KBASE_REG_FREE;
-+ if (ret)
-+ goto va_region_add_error;
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ gpu_map_properties &= (KBASE_REG_GPU_RD | KBASE_REG_GPU_WR);
-+ gpu_map_properties |= gpu_map_prot;
-+
-+ ret = kbase_mmu_insert_pages_no_flush(kbdev, &kbdev->csf.mcu_mmu,
-+ va_reg->start_pfn, &phys[0], num_pages,
-+ gpu_map_properties, KBASE_MEM_GROUP_CSF_FW);
-+ if (ret)
-+ goto mmu_insert_pages_error;
-+
-+ kfree(page_list);
-+ csf_mapping->phys = phys;
-+ csf_mapping->cpu_addr = cpu_addr;
-+ csf_mapping->va_reg = va_reg;
-+ csf_mapping->num_pages = num_pages;
-+
-+ return 0;
-+
-+mmu_insert_pages_error:
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ kbase_remove_va_region(va_reg);
-+va_region_add_error:
-+ kbase_free_alloced_region(va_reg);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+va_region_alloc_error:
-+ vunmap(cpu_addr);
-+vmap_error:
-+ kbase_mem_pool_free_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ num_pages, phys, false, false);
-+
-+phys_mem_pool_alloc_error:
-+ kfree(page_list);
-+page_list_alloc_error:
-+ kfree(phys);
-+out:
-+ /* Zero-initialize the mapping to make sure that the termination
-+ * function doesn't try to unmap or free random addresses.
-+ */
-+ csf_mapping->phys = NULL;
-+ csf_mapping->cpu_addr = NULL;
-+ csf_mapping->va_reg = NULL;
-+ csf_mapping->num_pages = 0;
-+
-+ return -ENOMEM;
-+}
-+
-+void kbase_csf_firmware_mcu_shared_mapping_term(
-+ struct kbase_device *kbdev, struct kbase_csf_mapping *csf_mapping)
-+{
-+ if (csf_mapping->va_reg) {
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ kbase_remove_va_region(csf_mapping->va_reg);
-+ kbase_free_alloced_region(csf_mapping->va_reg);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+ }
-+
-+ if (csf_mapping->phys) {
-+ kbase_mem_pool_free_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ csf_mapping->num_pages, csf_mapping->phys, false,
-+ false);
-+ }
-+
-+ vunmap(csf_mapping->cpu_addr);
-+ kfree(csf_mapping->phys);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware.h
-new file mode 100644
-index 0000000..60d7065
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware.h
-@@ -0,0 +1,811 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_FIRMWARE_H_
-+#define _KBASE_CSF_FIRMWARE_H_
-+
-+#include "device/mali_kbase_device.h"
-+#include <uapi/gpu/arm/midgard/csf/mali_gpu_csf_registers.h>
-+
-+/*
-+ * PAGE_KERNEL_RO was only defined on 32bit ARM in 4.19 in:
-+ * Commit a3266bd49c721e2e0a71f352d83713fbd60caadb
-+ * Author: Luis R. Rodriguez <mcgrof@kernel.org>
-+ * Date: Fri Aug 17 15:46:29 2018 -0700
-+ *
-+ * mm: provide a fallback for PAGE_KERNEL_RO for architectures
-+ *
-+ * Some architectures do not define certain PAGE_KERNEL_* flags, this is
-+ * either because:
-+ *
-+ * a) The way to implement some of these flags is *not yet ported*, or
-+ * b) The architecture *has no way* to describe them
-+ *
-+ * [snip]
-+ *
-+ * This can be removed once support of 32bit ARM kernels predating 4.19 is no
-+ * longer required.
-+ */
-+#ifndef PAGE_KERNEL_RO
-+#define PAGE_KERNEL_RO PAGE_KERNEL
-+#endif
-+
-+/* Address space number to claim for the firmware. */
-+#define MCU_AS_NR 0
-+#define MCU_AS_BITMASK (1 << MCU_AS_NR)
-+
-+/* Number of available Doorbells */
-+#define CSF_NUM_DOORBELL ((u8)24)
-+
-+/* Offset to the first HW doorbell page */
-+#define CSF_HW_DOORBELL_PAGE_OFFSET ((u32)0x80000)
-+
-+/* Size of HW Doorbell page, used to calculate the offset to subsequent pages */
-+#define CSF_HW_DOORBELL_PAGE_SIZE ((u32)0x10000)
-+
-+/* Doorbell 0 is used by the driver. */
-+#define CSF_KERNEL_DOORBELL_NR ((u32)0)
-+
-+/* Offset of name inside a trace buffer entry in the firmware image */
-+#define TRACE_BUFFER_ENTRY_NAME_OFFSET (0x1C)
-+
-+/* All implementations of the host interface with major version 0 must comply
-+ * with these restrictions:
-+ */
-+/* GLB_GROUP_NUM: At least 3 CSGs, but no more than 31 */
-+#define MIN_SUPPORTED_CSGS 3
-+#define MAX_SUPPORTED_CSGS 31
-+/* GROUP_STREAM_NUM: At least 8 CSs per CSG, but no more than 32 */
-+#define MIN_SUPPORTED_STREAMS_PER_GROUP 8
-+/* Maximum CSs per csg. */
-+#define MAX_SUPPORTED_STREAMS_PER_GROUP 32
-+
-+/* Waiting timeout for status change acknowledgment, in milliseconds */
-+#define CSF_FIRMWARE_TIMEOUT_MS (3000) /* Relaxed to 3000ms from 800ms due to Android */
-+
-+struct kbase_device;
-+
-+
-+/**
-+ * struct kbase_csf_mapping - Memory mapping for CSF memory.
-+ * @phys: Physical memory allocation used by the mapping.
-+ * @cpu_addr: Starting CPU address for the mapping.
-+ * @va_reg: GPU virtual address region for the mapping.
-+ * @num_pages: Size of the mapping, in memory pages.
-+ */
-+struct kbase_csf_mapping {
-+ struct tagged_addr *phys;
-+ void *cpu_addr;
-+ struct kbase_va_region *va_reg;
-+ unsigned int num_pages;
-+};
-+
-+/**
-+ * struct kbase_csf_trace_buffers - List and state of firmware trace buffers.
-+ * @list: List of trace buffers descriptors.
-+ * @mcu_rw: Metadata for the MCU shared memory mapping used for
-+ * GPU-readable,writable/CPU-writable variables.
-+ * @mcu_write: Metadata for the MCU shared memory mapping used for
-+ * GPU-writable/CPU-readable variables.
-+ */
-+struct kbase_csf_trace_buffers {
-+ struct list_head list;
-+ struct kbase_csf_mapping mcu_rw;
-+ struct kbase_csf_mapping mcu_write;
-+};
-+
-+/**
-+ * struct kbase_csf_cmd_stream_info - CSI provided by the firmware.
-+ *
-+ * @kbdev: Address of the instance of a GPU platform device that implements
-+ * this interface.
-+ * @features: Bit field of CS features (e.g. which types of jobs
-+ * are supported). Bits 7:0 specify the number of work registers(-1).
-+ * Bits 11:8 specify the number of scoreboard entries(-1).
-+ * @input: Address of CSI input page.
-+ * @output: Address of CSI output page.
-+ */
-+struct kbase_csf_cmd_stream_info {
-+ struct kbase_device *kbdev;
-+ u32 features;
-+ void *input;
-+ void *output;
-+};
-+
-+/**
-+ * kbase_csf_firmware_cs_input() - Set a word in a CS's input page
-+ *
-+ * @info: CSI provided by the firmware.
-+ * @offset: Offset of the word to be written, in bytes.
-+ * @value: Value to be written.
-+ */
-+void kbase_csf_firmware_cs_input(
-+ const struct kbase_csf_cmd_stream_info *info, u32 offset, u32 value);
-+
-+/**
-+ * kbase_csf_firmware_cs_input_read() - Read a word in a CS's input page
-+ *
-+ * Return: Value of the word read from the CS's input page.
-+ *
-+ * @info: CSI provided by the firmware.
-+ * @offset: Offset of the word to be read, in bytes.
-+ */
-+u32 kbase_csf_firmware_cs_input_read(
-+ const struct kbase_csf_cmd_stream_info *const info, const u32 offset);
-+
-+/**
-+ * kbase_csf_firmware_cs_input_mask() - Set part of a word in a CS's input page
-+ *
-+ * @info: CSI provided by the firmware.
-+ * @offset: Offset of the word to be modified, in bytes.
-+ * @value: Value to be written.
-+ * @mask: Bitmask with the bits to be modified set.
-+ */
-+void kbase_csf_firmware_cs_input_mask(
-+ const struct kbase_csf_cmd_stream_info *info, u32 offset,
-+ u32 value, u32 mask);
-+
-+/**
-+ * kbase_csf_firmware_cs_output() - Read a word in a CS's output page
-+ *
-+ * Return: Value of the word read from the CS's output page.
-+ *
-+ * @info: CSI provided by the firmware.
-+ * @offset: Offset of the word to be read, in bytes.
-+ */
-+u32 kbase_csf_firmware_cs_output(
-+ const struct kbase_csf_cmd_stream_info *info, u32 offset);
-+/**
-+ * struct kbase_csf_cmd_stream_group_info - CSG interface provided by the
-+ * firmware.
-+ *
-+ * @kbdev: Address of the instance of a GPU platform device that implements
-+ * this interface.
-+ * @features: Bit mask of features. Reserved bits should be 0, and should
-+ * be ignored.
-+ * @input: Address of global interface input page.
-+ * @output: Address of global interface output page.
-+ * @suspend_size: Size in bytes for normal suspend buffer for the CSG
-+ * @protm_suspend_size: Size in bytes for protected mode suspend buffer
-+ * for the CSG.
-+ * @stream_num: Number of CSs in the CSG.
-+ * @stream_stride: Stride in bytes in JASID0 virtual address between
-+ * CS capability structures.
-+ * @streams: Address of an array of CS capability structures.
-+ */
-+struct kbase_csf_cmd_stream_group_info {
-+ struct kbase_device *kbdev;
-+ u32 features;
-+ void *input;
-+ void *output;
-+ u32 suspend_size;
-+ u32 protm_suspend_size;
-+ u32 stream_num;
-+ u32 stream_stride;
-+ struct kbase_csf_cmd_stream_info *streams;
-+};
-+
-+/**
-+ * kbase_csf_firmware_csg_input() - Set a word in a CSG's input page
-+ *
-+ * @info: CSG interface provided by the firmware.
-+ * @offset: Offset of the word to be written, in bytes.
-+ * @value: Value to be written.
-+ */
-+void kbase_csf_firmware_csg_input(
-+ const struct kbase_csf_cmd_stream_group_info *info, u32 offset,
-+ u32 value);
-+
-+/**
-+ * kbase_csf_firmware_csg_input_read() - Read a word in a CSG's input page
-+ *
-+ * Return: Value of the word read from the CSG's input page.
-+ *
-+ * @info: CSG interface provided by the firmware.
-+ * @offset: Offset of the word to be read, in bytes.
-+ */
-+u32 kbase_csf_firmware_csg_input_read(
-+ const struct kbase_csf_cmd_stream_group_info *info, u32 offset);
-+
-+/**
-+ * kbase_csf_firmware_csg_input_mask() - Set part of a word in a CSG's
-+ * input page
-+ *
-+ * @info: CSG interface provided by the firmware.
-+ * @offset: Offset of the word to be modified, in bytes.
-+ * @value: Value to be written.
-+ * @mask: Bitmask with the bits to be modified set.
-+ */
-+void kbase_csf_firmware_csg_input_mask(
-+ const struct kbase_csf_cmd_stream_group_info *info, u32 offset,
-+ u32 value, u32 mask);
-+
-+/**
-+ * kbase_csf_firmware_csg_output()- Read a word in a CSG's output page
-+ *
-+ * Return: Value of the word read from the CSG's output page.
-+ *
-+ * @info: CSG interface provided by the firmware.
-+ * @offset: Offset of the word to be read, in bytes.
-+ */
-+u32 kbase_csf_firmware_csg_output(
-+ const struct kbase_csf_cmd_stream_group_info *info, u32 offset);
-+
-+/**
-+ * struct kbase_csf_global_iface - Global CSF interface
-+ * provided by the firmware.
-+ *
-+ * @kbdev: Address of the instance of a GPU platform device that implements
-+ * this interface.
-+ * @version: Bits 31:16 hold the major version number and 15:0 hold the minor
-+ * version number. A higher minor version is backwards-compatible
-+ * with a lower minor version for the same major version.
-+ * @features: Bit mask of features (e.g. whether certain types of job can
-+ * be suspended). Reserved bits should be 0, and should be ignored.
-+ * @input: Address of global interface input page.
-+ * @output: Address of global interface output page.
-+ * @group_num: Number of CSGs supported.
-+ * @group_stride: Stride in bytes in JASID0 virtual address between
-+ * CSG capability structures.
-+ * @prfcnt_size: Performance counters size.
-+ * @instr_features: Instrumentation features. (csf >= 1.1.0)
-+ * @groups: Address of an array of CSG capability structures.
-+ */
-+struct kbase_csf_global_iface {
-+ struct kbase_device *kbdev;
-+ u32 version;
-+ u32 features;
-+ void *input;
-+ void *output;
-+ u32 group_num;
-+ u32 group_stride;
-+ u32 prfcnt_size;
-+ u32 instr_features;
-+ struct kbase_csf_cmd_stream_group_info *groups;
-+};
-+
-+/**
-+ * kbase_csf_firmware_global_input() - Set a word in the global input page
-+ *
-+ * @iface: CSF interface provided by the firmware.
-+ * @offset: Offset of the word to be written, in bytes.
-+ * @value: Value to be written.
-+ */
-+void kbase_csf_firmware_global_input(
-+ const struct kbase_csf_global_iface *iface, u32 offset, u32 value);
-+
-+/**
-+ * kbase_csf_firmware_global_input_mask() - Set part of a word in the global
-+ * input page
-+ *
-+ * @iface: CSF interface provided by the firmware.
-+ * @offset: Offset of the word to be modified, in bytes.
-+ * @value: Value to be written.
-+ * @mask: Bitmask with the bits to be modified set.
-+ */
-+void kbase_csf_firmware_global_input_mask(
-+ const struct kbase_csf_global_iface *iface, u32 offset,
-+ u32 value, u32 mask);
-+
-+/**
-+ * kbase_csf_firmware_global_input_read() - Read a word in a global input page
-+ *
-+ * Return: Value of the word read from the global input page.
-+ *
-+ * @info: CSG interface provided by the firmware.
-+ * @offset: Offset of the word to be read, in bytes.
-+ */
-+u32 kbase_csf_firmware_global_input_read(
-+ const struct kbase_csf_global_iface *info, u32 offset);
-+
-+/**
-+ * kbase_csf_firmware_global_output() - Read a word in the global output page
-+ *
-+ * Return: Value of the word read from the global output page.
-+ *
-+ * @iface: CSF interface provided by the firmware.
-+ * @offset: Offset of the word to be read, in bytes.
-+ */
-+u32 kbase_csf_firmware_global_output(
-+ const struct kbase_csf_global_iface *iface, u32 offset);
-+
-+/* Calculate the offset to the Hw doorbell page corresponding to the
-+ * doorbell number.
-+ */
-+static u32 csf_doorbell_offset(int doorbell_nr)
-+{
-+ WARN_ON(doorbell_nr >= CSF_NUM_DOORBELL);
-+
-+ return CSF_HW_DOORBELL_PAGE_OFFSET +
-+ (doorbell_nr * CSF_HW_DOORBELL_PAGE_SIZE);
-+}
-+
-+static inline void kbase_csf_ring_doorbell(struct kbase_device *kbdev,
-+ int doorbell_nr)
-+{
-+ WARN_ON(doorbell_nr >= CSF_NUM_DOORBELL);
-+
-+ kbase_reg_write(kbdev, csf_doorbell_offset(doorbell_nr), (u32)1);
-+}
-+
-+/**
-+ * kbase_csf_read_firmware_memory - Read a value in a GPU address
-+ *
-+ * This function read a value in a GPU address that belongs to
-+ * a private firmware memory region. The function assumes that the location
-+ * is not permanently mapped on the CPU address space, therefore it maps it
-+ * and then unmaps it to access it independently.
-+ *
-+ * @kbdev: Device pointer
-+ * @gpu_addr: GPU address to read
-+ * @value: output pointer to which the read value will be written.
-+ */
-+void kbase_csf_read_firmware_memory(struct kbase_device *kbdev,
-+ u32 gpu_addr, u32 *value);
-+
-+/**
-+ * kbase_csf_update_firmware_memory - Write a value in a GPU address
-+ *
-+ * This function writes a given value in a GPU address that belongs to
-+ * a private firmware memory region. The function assumes that the destination
-+ * is not permanently mapped on the CPU address space, therefore it maps it
-+ * and then unmaps it to access it independently.
-+ *
-+ * @kbdev: Device pointer
-+ * @gpu_addr: GPU address to write
-+ * @value: Value to write
-+ */
-+void kbase_csf_update_firmware_memory(struct kbase_device *kbdev,
-+ u32 gpu_addr, u32 value);
-+
-+/**
-+ * kbase_csf_firmware_early_init() - Early initializatin for the firmware.
-+ * @kbdev: Kbase device
-+ *
-+ * Initialize resources related to the firmware. Must be called at kbase probe.
-+ *
-+ * Return: 0 if successful, negative error code on failure
-+ */
-+int kbase_csf_firmware_early_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_init() - Load the firmware for the CSF MCU
-+ * @kbdev: Kbase device
-+ *
-+ * Request the firmware from user space and load it into memory.
-+ *
-+ * Return: 0 if successful, negative error code on failure
-+ */
-+int kbase_csf_firmware_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_term() - Unload the firmware
-+ * @kbdev: Kbase device
-+ *
-+ * Frees the memory allocated by kbase_csf_firmware_init()
-+ */
-+void kbase_csf_firmware_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_ping - Send the ping request to firmware.
-+ *
-+ * The function sends the ping request to firmware.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_firmware_ping(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_ping_wait - Send the ping request to firmware and waits.
-+ *
-+ * The function sends the ping request to firmware and waits to confirm it is
-+ * alive.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_firmware_ping_wait(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_set_timeout - Set a hardware endpoint progress timeout.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @timeout: The maximum number of GPU cycles that is allowed to elapse
-+ * without forward progress before the driver terminates a GPU
-+ * command queue group.
-+ *
-+ * Configures the progress timeout value used by the firmware to decide
-+ * when to report that a task is not making progress on an endpoint.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_firmware_set_timeout(struct kbase_device *kbdev, u64 timeout);
-+
-+/**
-+ * kbase_csf_enter_protected_mode - Send the Global request to firmware to
-+ * enter protected mode and wait for its
-+ * completion.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_enter_protected_mode(struct kbase_device *kbdev);
-+
-+static inline bool kbase_csf_firmware_mcu_halted(struct kbase_device *kbdev)
-+{
-+ return (kbase_reg_read(kbdev, GPU_CONTROL_REG(MCU_STATUS)) ==
-+ MCU_STATUS_HALTED);
-+}
-+
-+/**
-+ * kbase_csf_firmware_trigger_mcu_halt - Send the Global request to firmware to
-+ * halt its operation and bring itself
-+ * into a known internal state for warm
-+ * boot later.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_firmware_trigger_mcu_halt(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_enable_mcu - Send the command to enable MCU
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+static inline void kbase_csf_firmware_enable_mcu(struct kbase_device *kbdev)
-+{
-+ /* Trigger the boot of MCU firmware, Use the AUTO mode as
-+ * otherwise on fast reset, to exit protected mode, MCU will
-+ * not reboot by itself to enter normal mode.
-+ */
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(MCU_CONTROL), MCU_CNTRL_AUTO);
-+}
-+
-+/**
-+ * kbase_csf_firmware_disable_mcu - Send the command to disable MCU
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+static inline void kbase_csf_firmware_disable_mcu(struct kbase_device *kbdev)
-+{
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(MCU_CONTROL), MCU_CNTRL_DISABLE);
-+}
-+
-+/**
-+ * kbase_csf_firmware_disable_mcu_wait - Wait for the MCU to reach disabled
-+ * status.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_firmware_disable_mcu_wait(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_trigger_firmware_reload - Trigger the reboot of MCU firmware, for the
-+ * cold boot case firmware image would be
-+ * reloaded from filesystem into memory.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_firmware_trigger_reload(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_reload_completed - The reboot of MCU firmware has
-+ * completed.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_firmware_reload_completed(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_global_reinit - Send the Global configuration requests
-+ * after the reboot of MCU firmware.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @core_mask: Mask of the enabled shader cores.
-+ */
-+void kbase_csf_firmware_global_reinit(struct kbase_device *kbdev,
-+ u64 core_mask);
-+
-+/**
-+ * kbase_csf_firmware_global_reinit_complete - Check the Global configuration
-+ * requests, sent after the reboot of MCU firmware, have
-+ * completed or not.
-+ *
-+ * Return: true if the Global configuration requests completed otherwise false.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+bool kbase_csf_firmware_global_reinit_complete(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_update_core_attr - Send the Global configuration request
-+ * to update the requested core attribute
-+ * changes.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @update_core_pwroff_timer: If true, signal the firmware needs to update
-+ * the MCU power-off timer value.
-+ * @update_core_mask: If true, need to do the core_mask update with
-+ * the supplied core_mask value.
-+ * @core_mask: New core mask value if update_core_mask is true,
-+ * otherwise unused.
-+ */
-+void kbase_csf_firmware_update_core_attr(struct kbase_device *kbdev,
-+ bool update_core_pwroff_timer, bool update_core_mask, u64 core_mask);
-+
-+/**
-+ * kbase_csf_firmware_core_attr_updated - Check the Global configuration
-+ * request has completed or not, that was sent to update
-+ * the core attributes.
-+ *
-+ * Return: true if the Global configuration request to update the core
-+ * attributes has completed, otherwise false.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+bool kbase_csf_firmware_core_attr_updated(struct kbase_device *kbdev);
-+
-+/**
-+ * Request the global control block of CSF interface capabilities
-+ *
-+ * Return: Total number of CSs, summed across all groups.
-+ *
-+ * @kbdev: Kbase device.
-+ * @group_data: Pointer where to store all the group data
-+ * (sequentially).
-+ * @max_group_num: The maximum number of groups to be read.
-+ * Can be 0, in which case group_data is unused.
-+ * @stream_data: Pointer where to store all the CS data
-+ * (sequentially).
-+ * @max_total_stream_num: The maximum number of CSs to be read.
-+ * Can be 0, in which case stream_data is unused.
-+ * @glb_version: Where to store the global interface version.
-+ * @features: Where to store a bit mask of features (e.g.
-+ * whether certain types of job can be suspended).
-+ * @group_num: Where to store the number of CSGs
-+ * supported.
-+ * @prfcnt_size: Where to store the size of CSF performance counters,
-+ * in bytes. Bits 31:16 hold the size of firmware
-+ * performance counter data and 15:0 hold the size of
-+ * hardware performance counter data.
-+ * @instr_features: Instrumentation features. Bits 7:4 hold the max size
-+ * of events. Bits 3:0 hold the offset update rate.
-+ * (csf >= 1,1,0)
-+ */
-+u32 kbase_csf_firmware_get_glb_iface(
-+ struct kbase_device *kbdev, struct basep_cs_group_control *group_data,
-+ u32 max_group_num, struct basep_cs_stream_control *stream_data,
-+ u32 max_total_stream_num, u32 *glb_version, u32 *features,
-+ u32 *group_num, u32 *prfcnt_size, u32 *instr_features);
-+
-+/**
-+ * Get CSF firmware header timeline metadata content
-+ *
-+ * Return: The firmware timeline metadata content which match @p name.
-+ *
-+ * @kbdev: Kbase device.
-+ * @name: Name of the metadata which metadata content to be returned.
-+ * @size: Metadata size if specified metadata found.
-+ */
-+const char *kbase_csf_firmware_get_timeline_metadata(struct kbase_device *kbdev,
-+ const char *name, size_t *size);
-+
-+/**
-+ * kbase_csf_firmware_mcu_shared_mapping_init -
-+ * Allocate and map MCU shared memory.
-+ *
-+ * This helper function allocates memory and maps it on both the CPU
-+ * and the GPU address spaces. Most of the properties of the mapping
-+ * are implicit and will be automatically determined by the function,
-+ * e.g. whether memory is cacheable.
-+ *
-+ * The client is only expected to specify whether the mapping is readable
-+ * or writable in the CPU and the GPU address spaces; any other flag
-+ * will be ignored by the function.
-+ *
-+ * Return: 0 if success, or an error code on failure.
-+ *
-+ * @kbdev: Kbase device the memory mapping shall belong to.
-+ * @num_pages: Number of memory pages to map.
-+ * @cpu_map_properties: Either PROT_READ or PROT_WRITE.
-+ * @gpu_map_properties: Either KBASE_REG_GPU_RD or KBASE_REG_GPU_WR.
-+ * @csf_mapping: Object where to write metadata for the memory mapping.
-+ */
-+int kbase_csf_firmware_mcu_shared_mapping_init(
-+ struct kbase_device *kbdev,
-+ unsigned int num_pages,
-+ unsigned long cpu_map_properties,
-+ unsigned long gpu_map_properties,
-+ struct kbase_csf_mapping *csf_mapping);
-+
-+/**
-+ * kbase_csf_firmware_mcu_shared_mapping_term - Unmap and free MCU shared memory.
-+ *
-+ * @kbdev: Device pointer.
-+ * @csf_mapping: Metadata of the memory mapping to terminate.
-+ */
-+void kbase_csf_firmware_mcu_shared_mapping_term(
-+ struct kbase_device *kbdev, struct kbase_csf_mapping *csf_mapping);
-+
-+#ifndef MALI_KBASE_BUILD
-+/**
-+ * mali_kutf_process_fw_utf_entry() - Process the "Firmware UTF tests" section
-+ *
-+ * Read "Firmware UTF tests" section from the firmware image and create
-+ * necessary kutf app+suite+tests.
-+ *
-+ * Return: 0 if successful, negative error code on failure. In both cases
-+ * caller will have to invoke mali_kutf_fw_utf_entry_cleanup for the cleanup
-+ *
-+ * @kbdev: Kbase device structure
-+ * @fw_data: Pointer to the start of firmware binary image loaded from disk
-+ * @fw_size: Size (in bytes) of the firmware image
-+ * @entry: Pointer to the start of the section
-+ */
-+int mali_kutf_process_fw_utf_entry(struct kbase_device *kbdev,
-+ const void *fw_data, size_t fw_size, const u32 *entry);
-+
-+/**
-+ * mali_kutf_fw_utf_entry_cleanup() - Remove the Fw UTF tests debugfs entries
-+ *
-+ * Destroy the kutf apps+suites+tests created on parsing "Firmware UTF tests"
-+ * section from the firmware image.
-+ *
-+ * @kbdev: Kbase device structure
-+ */
-+void mali_kutf_fw_utf_entry_cleanup(struct kbase_device *kbdev);
-+#endif
-+
-+#ifdef CONFIG_MALI_DEBUG
-+extern bool fw_debug;
-+#endif
-+
-+static inline long kbase_csf_timeout_in_jiffies(const unsigned int msecs)
-+{
-+#ifdef CONFIG_MALI_DEBUG
-+ return (fw_debug ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(msecs));
-+#else
-+ return msecs_to_jiffies(msecs);
-+#endif
-+}
-+
-+/**
-+ * kbase_csf_firmware_enable_gpu_idle_timer() - Activate the idle hysteresis
-+ * monitoring operation
-+ *
-+ * Program the firmware interface with its configured hysteresis count value
-+ * and enable the firmware to act on it. The Caller is
-+ * assumed to hold the kbdev->csf.scheduler.interrupt_lock.
-+ *
-+ * @kbdev: Kbase device structure
-+ */
-+void kbase_csf_firmware_enable_gpu_idle_timer(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_disable_gpu_idle_timer() - Disable the idle time
-+ * hysteresis monitoring operation
-+ *
-+ * Program the firmware interface to disable the idle hysteresis timer. The
-+ * Caller is assumed to hold the kbdev->csf.scheduler.interrupt_lock.
-+ *
-+ * @kbdev: Kbase device structure
-+ */
-+void kbase_csf_firmware_disable_gpu_idle_timer(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_get_gpu_idle_hysteresis_time - Get the firmware GPU idle
-+ * detection hysteresis duration
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Return: the internally recorded hysteresis (nominal) value.
-+ */
-+u32 kbase_csf_firmware_get_gpu_idle_hysteresis_time(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_set_gpu_idle_hysteresis_time - Set the firmware GPU idle
-+ * detection hysteresis duration
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @dur: The duration value (unit: milliseconds) for the configuring
-+ * hysteresis field for GPU idle detection
-+ *
-+ * The supplied value will be recorded internally without any change. But the
-+ * actual field value will be subject to hysteresis source frequency scaling
-+ * and maximum value limiting. The default source will be SYSTEM_TIMESTAMP
-+ * counter. But in case the platform is not able to supply it, the GPU
-+ * CYCLE_COUNTER source will be used as an alternative. Bit-31 on the
-+ * returned value is the source configuration flag, and it is set to '1'
-+ * when CYCLE_COUNTER alternative source is used.
-+ *
-+ * Return: the actual internally configured hysteresis field value.
-+ */
-+u32 kbase_csf_firmware_set_gpu_idle_hysteresis_time(struct kbase_device *kbdev, u32 dur);
-+
-+/**
-+ * kbase_csf_firmware_get_mcu_core_pwroff_time - Get the MCU core power-off
-+ * time value
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Return: the internally recorded MCU core power-off (nominal) value. The unit
-+ * of the value is in micro-seconds.
-+ */
-+u32 kbase_csf_firmware_get_mcu_core_pwroff_time(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_set_mcu_core_pwroff_time - Set the MCU core power-off
-+ * time value
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @dur: The duration value (unit: micro-seconds) for configuring MCU
-+ * core power-off timer, when the shader cores' power
-+ * transitions are delegated to the MCU (normal operational
-+ * mode)
-+ *
-+ * The supplied value will be recorded internally without any change. But the
-+ * actual field value will be subject to core power-off timer source frequency
-+ * scaling and maximum value limiting. The default source will be
-+ * SYSTEM_TIMESTAMP counter. But in case the platform is not able to supply it,
-+ * the GPU CYCLE_COUNTER source will be used as an alternative. Bit-31 on the
-+ * returned value is the source configuration flag, and it is set to '1'
-+ * when CYCLE_COUNTER alternative source is used.
-+ *
-+ * The configured MCU core power-off timer will only have effect when the host
-+ * driver has delegated the shader cores' power management to MCU.
-+ *
-+ * Return: the actual internal core power-off timer value in register defined
-+ * format.
-+ */
-+u32 kbase_csf_firmware_set_mcu_core_pwroff_time(struct kbase_device *kbdev, u32 dur);
-+
-+/**
-+ * kbase_csf_interface_version - Helper function to build the full firmware
-+ * interface version in a format compatible with
-+ * with GLB_VERSION register
-+ *
-+ * @major: major version of csf interface
-+ * @minor: minor version of csf interface
-+ * @patch: patch version of csf interface
-+ *
-+ * Return: firmware interface version
-+ */
-+static inline u32 kbase_csf_interface_version(u32 major, u32 minor, u32 patch)
-+{
-+ return ((major << GLB_VERSION_MAJOR_SHIFT) |
-+ (minor << GLB_VERSION_MINOR_SHIFT) |
-+ (patch << GLB_VERSION_PATCH_SHIFT));
-+}
-+
-+/**
-+ * kbase_csf_trigger_firmware_config_update - Send a firmware config update.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Any changes done to firmware configuration entry or tracebuffer entry
-+ * requires a GPU silent reset to reflect the configuration changes
-+ * requested, but if Firmware.header.entry.bit(30) is set then we can request a
-+ * FIRMWARE_CONFIG_UPDATE rather than doing a silent reset.
-+ *
-+ * Return: 0 if success, or negative error code on failure.
-+ */
-+int kbase_csf_trigger_firmware_config_update(struct kbase_device *kbdev);
-+#endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_cfg.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_cfg.c
-new file mode 100644
-index 0000000..f00acb1
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_cfg.c
-@@ -0,0 +1,327 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include "mali_kbase_csf_firmware_cfg.h"
-+#include <mali_kbase_reset_gpu.h>
-+
-+#if CONFIG_SYSFS
-+#define CSF_FIRMWARE_CFG_SYSFS_DIR_NAME "firmware_config"
-+
-+/**
-+ * struct firmware_config - Configuration item within the MCU firmware
-+ *
-+ * The firmware may expose configuration options. Each option has a name, the
-+ * address where the option is controlled and the minimum and maximum values
-+ * that the option can take.
-+ *
-+ * @node: List head linking all options to
-+ * kbase_device:csf.firmware_config
-+ * @kbdev: Pointer to the Kbase device
-+ * @kobj: Kobject corresponding to the sysfs sub-directory,
-+ * inside CSF_FIRMWARE_CFG_SYSFS_DIR_NAME directory,
-+ * representing the configuration option @name.
-+ * @kobj_inited: kobject initialization state
-+ * @updatable: Indicates whether config items can be updated with
-+ * FIRMWARE_CONFIG_UPDATE
-+ * @name: NUL-terminated string naming the option
-+ * @address: The address in the firmware image of the configuration option
-+ * @min: The lowest legal value of the configuration option
-+ * @max: The maximum legal value of the configuration option
-+ * @cur_val: The current value of the configuration option
-+ */
-+struct firmware_config {
-+ struct list_head node;
-+ struct kbase_device *kbdev;
-+ struct kobject kobj;
-+ bool kobj_inited;
-+ bool updatable;
-+ char *name;
-+ u32 address;
-+ u32 min;
-+ u32 max;
-+ u32 cur_val;
-+};
-+
-+#define FW_CFG_ATTR(_name, _mode) \
-+ struct attribute fw_cfg_attr_##_name = { \
-+ .name = __stringify(_name), \
-+ .mode = VERIFY_OCTAL_PERMISSIONS(_mode), \
-+ }
-+
-+static FW_CFG_ATTR(min, S_IRUGO);
-+static FW_CFG_ATTR(max, S_IRUGO);
-+static FW_CFG_ATTR(cur, S_IRUGO | S_IWUSR);
-+
-+static void fw_cfg_kobj_release(struct kobject *kobj)
-+{
-+ struct firmware_config *config =
-+ container_of(kobj, struct firmware_config, kobj);
-+
-+ kfree(config);
-+}
-+
-+static ssize_t show_fw_cfg(struct kobject *kobj,
-+ struct attribute *attr, char *buf)
-+{
-+ struct firmware_config *config =
-+ container_of(kobj, struct firmware_config, kobj);
-+ struct kbase_device *kbdev = config->kbdev;
-+ u32 val = 0;
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ if (attr == &fw_cfg_attr_max)
-+ val = config->max;
-+ else if (attr == &fw_cfg_attr_min)
-+ val = config->min;
-+ else if (attr == &fw_cfg_attr_cur) {
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ val = config->cur_val;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ } else {
-+ dev_warn(kbdev->dev,
-+ "Unexpected read from entry %s/%s",
-+ config->name, attr->name);
-+ return -EINVAL;
-+ }
-+
-+ return snprintf(buf, PAGE_SIZE, "%u\n", val);
-+}
-+
-+static ssize_t store_fw_cfg(struct kobject *kobj,
-+ struct attribute *attr,
-+ const char *buf,
-+ size_t count)
-+{
-+ struct firmware_config *config =
-+ container_of(kobj, struct firmware_config, kobj);
-+ struct kbase_device *kbdev = config->kbdev;
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ if (attr == &fw_cfg_attr_cur) {
-+ unsigned long flags;
-+ u32 val;
-+ int ret = kstrtouint(buf, 0, &val);
-+
-+ if (ret) {
-+ dev_err(kbdev->dev,
-+ "Couldn't process %s/%s write operation.\n"
-+ "Use format <value>\n",
-+ config->name, attr->name);
-+ return -EINVAL;
-+ }
-+
-+ if ((val < config->min) || (val > config->max))
-+ return -EINVAL;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ if (config->cur_val == val) {
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ return count;
-+ }
-+
-+ /* If configuration update cannot be performed with
-+ * FIRMWARE_CONFIG_UPDATE then we need to do a
-+ * silent reset before we update the memory.
-+ */
-+ if (!config->updatable) {
-+ /*
-+ * If there is already a GPU reset pending then inform
-+ * the User to retry the write.
-+ */
-+ if (kbase_reset_gpu_silent(kbdev)) {
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock,
-+ flags);
-+ return -EAGAIN;
-+ }
-+ }
-+
-+ /*
-+ * GPU reset request has been placed, now update the
-+ * firmware image. GPU reset will take place only after
-+ * hwaccess_lock is released.
-+ * Update made to firmware image in memory would not
-+ * be lost on GPU reset as configuration entries reside
-+ * in the RONLY section of firmware image, which is not
-+ * reloaded on firmware reboot due to GPU reset.
-+ */
-+ kbase_csf_update_firmware_memory(
-+ kbdev, config->address, val);
-+
-+ config->cur_val = val;
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ /* If we can update the config without firmware reset then
-+ * we need to just trigger FIRMWARE_CONFIG_UPDATE.
-+ */
-+ if (config->updatable) {
-+ ret = kbase_csf_trigger_firmware_config_update(kbdev);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ /* Wait for the config update to take effect */
-+ if (!config->updatable)
-+ kbase_reset_gpu_wait(kbdev);
-+ } else {
-+ dev_warn(kbdev->dev,
-+ "Unexpected write to entry %s/%s",
-+ config->name, attr->name);
-+ return -EINVAL;
-+ }
-+
-+ return count;
-+}
-+
-+static const struct sysfs_ops fw_cfg_ops = {
-+ .show = &show_fw_cfg,
-+ .store = &store_fw_cfg,
-+};
-+
-+static struct attribute *fw_cfg_attrs[] = {
-+ &fw_cfg_attr_min,
-+ &fw_cfg_attr_max,
-+ &fw_cfg_attr_cur,
-+ NULL,
-+};
-+
-+static struct kobj_type fw_cfg_kobj_type = {
-+ .release = &fw_cfg_kobj_release,
-+ .sysfs_ops = &fw_cfg_ops,
-+ .default_attrs = fw_cfg_attrs,
-+};
-+
-+int kbase_csf_firmware_cfg_init(struct kbase_device *kbdev)
-+{
-+ struct firmware_config *config;
-+
-+ kbdev->csf.fw_cfg_kobj = kobject_create_and_add(
-+ CSF_FIRMWARE_CFG_SYSFS_DIR_NAME, &kbdev->dev->kobj);
-+ if (!kbdev->csf.fw_cfg_kobj) {
-+ kobject_put(kbdev->csf.fw_cfg_kobj);
-+ dev_err(kbdev->dev,
-+ "Creation of %s sysfs sub-directory failed\n",
-+ CSF_FIRMWARE_CFG_SYSFS_DIR_NAME);
-+ return -ENOMEM;
-+ }
-+
-+ list_for_each_entry(config, &kbdev->csf.firmware_config, node) {
-+ int err;
-+
-+ kbase_csf_read_firmware_memory(kbdev, config->address,
-+ &config->cur_val);
-+
-+ err = kobject_init_and_add(&config->kobj, &fw_cfg_kobj_type,
-+ kbdev->csf.fw_cfg_kobj, "%s", config->name);
-+ if (err) {
-+ kobject_put(&config->kobj);
-+ dev_err(kbdev->dev,
-+ "Creation of %s sysfs sub-directory failed\n",
-+ config->name);
-+ return err;
-+ }
-+
-+ config->kobj_inited = true;
-+ }
-+
-+ return 0;
-+}
-+
-+void kbase_csf_firmware_cfg_term(struct kbase_device *kbdev)
-+{
-+ while (!list_empty(&kbdev->csf.firmware_config)) {
-+ struct firmware_config *config;
-+
-+ config = list_first_entry(&kbdev->csf.firmware_config,
-+ struct firmware_config, node);
-+ list_del(&config->node);
-+
-+ if (config->kobj_inited) {
-+ kobject_del(&config->kobj);
-+ kobject_put(&config->kobj);
-+ } else
-+ kfree(config);
-+ }
-+
-+ kobject_del(kbdev->csf.fw_cfg_kobj);
-+ kobject_put(kbdev->csf.fw_cfg_kobj);
-+}
-+
-+int kbase_csf_firmware_cfg_option_entry_parse(struct kbase_device *kbdev,
-+ const struct firmware *fw,
-+ const u32 *entry,
-+ unsigned int size, bool updatable)
-+{
-+ const char *name = (char *)&entry[3];
-+ struct firmware_config *config;
-+ const unsigned int name_len = size - CONFIGURATION_ENTRY_NAME_OFFSET;
-+
-+ /* Allocate enough space for struct firmware_config and the
-+ * configuration option name (with NULL termination)
-+ */
-+ config = kzalloc(sizeof(*config) + name_len + 1, GFP_KERNEL);
-+
-+ if (!config)
-+ return -ENOMEM;
-+
-+ config->kbdev = kbdev;
-+ config->updatable = updatable;
-+ config->name = (char *)(config+1);
-+ config->address = entry[0];
-+ config->min = entry[1];
-+ config->max = entry[2];
-+
-+ memcpy(config->name, name, name_len);
-+ config->name[name_len] = 0;
-+
-+ list_add(&config->node, &kbdev->csf.firmware_config);
-+
-+ dev_dbg(kbdev->dev, "Configuration option '%s' at 0x%x range %u-%u",
-+ config->name, config->address,
-+ config->min, config->max);
-+
-+ return 0;
-+}
-+#else
-+int kbase_csf_firmware_cfg_init(struct kbase_device *kbdev)
-+{
-+ return 0;
-+}
-+
-+void kbase_csf_firmware_cfg_term(struct kbase_device *kbdev)
-+{
-+ /* !CONFIG_SYSFS: Nothing to do here */
-+}
-+
-+int kbase_csf_firmware_cfg_option_entry_parse(struct kbase_device *kbdev,
-+ const struct firmware *fw,
-+ const u32 *entry, unsigned int size)
-+{
-+ return 0;
-+}
-+#endif /* CONFIG_SYSFS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_cfg.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_cfg.h
-new file mode 100644
-index 0000000..080c154
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_cfg.h
-@@ -0,0 +1,74 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_FIRMWARE_CFG_H_
-+#define _KBASE_CSF_FIRMWARE_CFG_H_
-+
-+#include <mali_kbase.h>
-+#include "mali_kbase_csf_firmware.h"
-+#include <linux/firmware.h>
-+
-+#define CONFIGURATION_ENTRY_NAME_OFFSET (0xC)
-+
-+/**
-+ * kbase_csf_firmware_cfg_init - Create the sysfs directory for configuration
-+ * options present in firmware image.
-+ *
-+ * This function would create a sysfs directory and populate it with a
-+ * sub-directory, that would contain a file per attribute, for every
-+ * configuration option parsed from firmware image.
-+ *
-+ * @kbdev: Pointer to the Kbase device
-+ *
-+ * Return: The initialization error code.
-+ */
-+int kbase_csf_firmware_cfg_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_cfg_term - Delete the sysfs directory that was created
-+ * for firmware configuration options.
-+ *
-+ * @kbdev: Pointer to the Kbase device
-+ *
-+ */
-+void kbase_csf_firmware_cfg_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_cfg_option_entry_parse() - Process a
-+ * "configuration option" section.
-+ *
-+ * Read a "configuration option" section adding it to the
-+ * kbase_device:csf.firmware_config list.
-+ *
-+ * Return: 0 if successful, negative error code on failure
-+ *
-+ * @kbdev: Kbase device structure
-+ * @fw: Firmware image containing the section
-+ * @entry: Pointer to the section
-+ * @size: Size (in bytes) of the section
-+ * @updatable: Indicates if entry can be updated with FIRMWARE_CONFIG_UPDATE
-+ */
-+int kbase_csf_firmware_cfg_option_entry_parse(struct kbase_device *kbdev,
-+ const struct firmware *fw,
-+ const u32 *entry,
-+ unsigned int size,
-+ bool updatable);
-+#endif /* _KBASE_CSF_FIRMWARE_CFG_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_no_mali.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_no_mali.c
-new file mode 100644
-index 0000000..ae2ad33
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_firmware_no_mali.c
-@@ -0,0 +1,1389 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase.h"
-+#include "mali_kbase_csf_firmware.h"
-+#include "mali_kbase_csf_trace_buffer.h"
-+#include "mali_kbase_csf_timeout.h"
-+#include "mali_kbase_mem.h"
-+#include "mali_kbase_reset_gpu.h"
-+#include "mali_kbase_ctx_sched.h"
-+#include "device/mali_kbase_device.h"
-+#include "backend/gpu/mali_kbase_pm_internal.h"
-+#include "mali_kbase_csf_scheduler.h"
-+#include "mmu/mali_kbase_mmu.h"
-+#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
-+
-+#include <linux/list.h>
-+#include <linux/slab.h>
-+#include <linux/firmware.h>
-+#include <linux/mman.h>
-+#include <linux/string.h>
-+#include <linux/mutex.h>
-+#if (KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE)
-+#include <linux/set_memory.h>
-+#endif
-+#include <asm/arch_timer.h>
-+
-+#ifdef CONFIG_MALI_DEBUG
-+/* Makes Driver wait indefinitely for an acknowledgment for the different
-+ * requests it sends to firmware. Otherwise the timeouts interfere with the
-+ * use of debugger for source-level debugging of firmware as Driver initiates
-+ * a GPU reset when a request times out, which always happen when a debugger
-+ * is connected.
-+ */
-+bool fw_debug; /* Default value of 0/false */
-+module_param(fw_debug, bool, 0444);
-+MODULE_PARM_DESC(fw_debug,
-+ "Enables effective use of a debugger for debugging firmware code.");
-+#endif
-+
-+#define DUMMY_FW_PAGE_SIZE SZ_4K
-+
-+/**
-+ * struct dummy_firmware_csi - Represents a dummy interface for MCU firmware CSs
-+ *
-+ * @cs_kernel_input: CS kernel input memory region
-+ * @cs_kernel_output: CS kernel output memory region
-+ */
-+struct dummy_firmware_csi {
-+ u8 cs_kernel_input[DUMMY_FW_PAGE_SIZE];
-+ u8 cs_kernel_output[DUMMY_FW_PAGE_SIZE];
-+};
-+
-+/**
-+ * struct dummy_firmware_csg - Represents a dummy interface for MCU firmware CSGs
-+ *
-+ * @csg_input: CSG kernel input memory region
-+ * @csg_output: CSG kernel output memory region
-+ * @csi: Dummy firmware CSIs
-+ */
-+struct dummy_firmware_csg {
-+ u8 csg_input[DUMMY_FW_PAGE_SIZE];
-+ u8 csg_output[DUMMY_FW_PAGE_SIZE];
-+ struct dummy_firmware_csi csi[8];
-+} dummy_firmware_csg;
-+
-+/**
-+ * struct dummy_firmware_interface - Represents a dummy interface in the MCU firmware
-+ *
-+ * @global_input: Global input memory region
-+ * @global_output: Global output memory region
-+ * @csg: Dummy firmware CSGs
-+ * @node: Interface objects are on the kbase_device:csf.firmware_interfaces
-+ * list using this list_head to link them
-+ */
-+struct dummy_firmware_interface {
-+ u8 global_input[DUMMY_FW_PAGE_SIZE];
-+ u8 global_output[DUMMY_FW_PAGE_SIZE];
-+ struct dummy_firmware_csg csg[8];
-+ struct list_head node;
-+} dummy_firmware_interface;
-+
-+#define CSF_GLB_REQ_CFG_MASK \
-+ (GLB_REQ_CFG_ALLOC_EN_MASK | GLB_REQ_CFG_PROGRESS_TIMER_MASK | \
-+ GLB_REQ_CFG_PWROFF_TIMER_MASK)
-+
-+static inline u32 input_page_read(const u32 *const input, const u32 offset)
-+{
-+ WARN_ON(offset % sizeof(u32));
-+
-+ return input[offset / sizeof(u32)];
-+}
-+
-+static inline void input_page_write(u32 *const input, const u32 offset,
-+ const u32 value)
-+{
-+ WARN_ON(offset % sizeof(u32));
-+
-+ input[offset / sizeof(u32)] = value;
-+}
-+
-+static inline void input_page_partial_write(u32 *const input, const u32 offset,
-+ u32 value, u32 mask)
-+{
-+ WARN_ON(offset % sizeof(u32));
-+
-+ input[offset / sizeof(u32)] =
-+ (input_page_read(input, offset) & ~mask) | (value & mask);
-+}
-+
-+static inline u32 output_page_read(const u32 *const output, const u32 offset)
-+{
-+ WARN_ON(offset % sizeof(u32));
-+
-+ return output[offset / sizeof(u32)];
-+}
-+
-+static inline void output_page_write(u32 *const output, const u32 offset,
-+ const u32 value)
-+{
-+ WARN_ON(offset % sizeof(u32));
-+
-+ output[offset / sizeof(u32)] = value;
-+}
-+
-+/**
-+ * invent_memory_setup_entry() - Invent an "interface memory setup" section
-+ *
-+ * Invent an "interface memory setup" section similar to one from a firmware
-+ * image. If successful the interface will be added to the
-+ * kbase_device:csf.firmware_interfaces list.
-+ *
-+ * Return: 0 if successful, negative error code on failure
-+ *
-+ * @kbdev: Kbase device structure
-+ */
-+static int invent_memory_setup_entry(struct kbase_device *kbdev)
-+{
-+ struct dummy_firmware_interface *interface = NULL;
-+
-+ /* Allocate enough memory for the struct dummy_firmware_interface.
-+ */
-+ interface = kzalloc(sizeof(*interface), GFP_KERNEL);
-+ if (!interface)
-+ return -ENOMEM;
-+
-+ kbdev->csf.shared_interface = interface;
-+ list_add(&interface->node, &kbdev->csf.firmware_interfaces);
-+
-+ /* NO_MALI: Don't insert any firmware pages */
-+ return 0;
-+}
-+
-+static void free_global_iface(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *iface = &kbdev->csf.global_iface;
-+
-+ if (iface->groups) {
-+ unsigned int gid;
-+
-+ for (gid = 0; gid < iface->group_num; ++gid)
-+ kfree(iface->groups[gid].streams);
-+
-+ kfree(iface->groups);
-+ iface->groups = NULL;
-+ }
-+}
-+
-+static int invent_cmd_stream_group_info(struct kbase_device *kbdev,
-+ struct kbase_csf_cmd_stream_group_info *ginfo,
-+ struct dummy_firmware_csg *csg)
-+{
-+ unsigned int sid;
-+
-+ ginfo->input = csg->csg_input;
-+ ginfo->output = csg->csg_output;
-+
-+ ginfo->kbdev = kbdev;
-+ ginfo->features = 0;
-+ ginfo->suspend_size = 64;
-+ ginfo->protm_suspend_size = 64;
-+ ginfo->stream_num = ARRAY_SIZE(csg->csi);
-+ ginfo->stream_stride = 0;
-+
-+ ginfo->streams = kcalloc(ginfo->stream_num, sizeof(*ginfo->streams), GFP_KERNEL);
-+ if (ginfo->streams == NULL) {
-+ return -ENOMEM;
-+ }
-+
-+ for (sid = 0; sid < ginfo->stream_num; ++sid) {
-+ struct kbase_csf_cmd_stream_info *stream = &ginfo->streams[sid];
-+ struct dummy_firmware_csi *csi = &csg->csi[sid];
-+
-+ stream->input = csi->cs_kernel_input;
-+ stream->output = csi->cs_kernel_output;
-+
-+ stream->kbdev = kbdev;
-+ stream->features =
-+ STREAM_FEATURES_WORK_REGISTERS_SET(0, 80) |
-+ STREAM_FEATURES_SCOREBOARDS_SET(0, 8) |
-+ STREAM_FEATURES_COMPUTE_SET(0, 1) |
-+ STREAM_FEATURES_FRAGMENT_SET(0, 1) |
-+ STREAM_FEATURES_TILER_SET(0, 1);
-+ }
-+
-+ return 0;
-+}
-+
-+static int invent_capabilities(struct kbase_device *kbdev)
-+{
-+ struct dummy_firmware_interface *interface = kbdev->csf.shared_interface;
-+ struct kbase_csf_global_iface *iface = &kbdev->csf.global_iface;
-+ unsigned int gid;
-+
-+ iface->input = interface->global_input;
-+ iface->output = interface->global_output;
-+
-+ iface->version = 1;
-+ iface->kbdev = kbdev;
-+ iface->features = 0;
-+ iface->prfcnt_size = 64;
-+
-+ if (iface->version >= kbase_csf_interface_version(1, 1, 0)) {
-+ /* update rate=1, max event size = 1<<8 = 256 */
-+ iface->instr_features = 0x81;
-+ } else {
-+ iface->instr_features = 0;
-+ }
-+
-+ iface->group_num = ARRAY_SIZE(interface->csg);
-+ iface->group_stride = 0;
-+
-+ iface->groups = kcalloc(iface->group_num, sizeof(*iface->groups), GFP_KERNEL);
-+ if (iface->groups == NULL) {
-+ return -ENOMEM;
-+ }
-+
-+ for (gid = 0; gid < iface->group_num; ++gid) {
-+ int err;
-+
-+ err = invent_cmd_stream_group_info(kbdev, &iface->groups[gid],
-+ &interface->csg[gid]);
-+ if (err < 0) {
-+ free_global_iface(kbdev);
-+ return err;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+void kbase_csf_read_firmware_memory(struct kbase_device *kbdev,
-+ u32 gpu_addr, u32 *value)
-+{
-+ /* NO_MALI: Nothing to do here */
-+}
-+
-+
-+void kbase_csf_update_firmware_memory(struct kbase_device *kbdev,
-+ u32 gpu_addr, u32 value)
-+{
-+ /* NO_MALI: Nothing to do here */
-+}
-+
-+void kbase_csf_firmware_cs_input(
-+ const struct kbase_csf_cmd_stream_info *const info, const u32 offset,
-+ const u32 value)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+
-+ dev_dbg(kbdev->dev, "cs input w: reg %08x val %08x\n", offset, value);
-+ input_page_write(info->input, offset, value);
-+
-+ if (offset == CS_REQ) {
-+ /* NO_MALI: Immediately acknowledge requests */
-+ output_page_write(info->output, CS_ACK, value);
-+ }
-+}
-+
-+u32 kbase_csf_firmware_cs_input_read(
-+ const struct kbase_csf_cmd_stream_info *const info,
-+ const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+ u32 const val = input_page_read(info->input, offset);
-+
-+ dev_dbg(kbdev->dev, "cs input r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+void kbase_csf_firmware_cs_input_mask(
-+ const struct kbase_csf_cmd_stream_info *const info, const u32 offset,
-+ const u32 value, const u32 mask)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+
-+ dev_dbg(kbdev->dev, "cs input w: reg %08x val %08x mask %08x\n",
-+ offset, value, mask);
-+
-+ /* NO_MALI: Go through kbase_csf_firmware_cs_input to capture writes */
-+ kbase_csf_firmware_cs_input(info, offset, (input_page_read(info->input, offset) & ~mask) | (value & mask));
-+}
-+
-+u32 kbase_csf_firmware_cs_output(
-+ const struct kbase_csf_cmd_stream_info *const info, const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+ u32 const val = output_page_read(info->output, offset);
-+
-+ dev_dbg(kbdev->dev, "cs output r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+void kbase_csf_firmware_csg_input(
-+ const struct kbase_csf_cmd_stream_group_info *const info,
-+ const u32 offset, const u32 value)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+
-+ dev_dbg(kbdev->dev, "csg input w: reg %08x val %08x\n",
-+ offset, value);
-+ input_page_write(info->input, offset, value);
-+
-+ if (offset == CSG_REQ) {
-+ /* NO_MALI: Immediately acknowledge requests */
-+ output_page_write(info->output, CSG_ACK, value);
-+ }
-+}
-+
-+u32 kbase_csf_firmware_csg_input_read(
-+ const struct kbase_csf_cmd_stream_group_info *const info,
-+ const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+ u32 const val = input_page_read(info->input, offset);
-+
-+ dev_dbg(kbdev->dev, "csg input r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+void kbase_csf_firmware_csg_input_mask(
-+ const struct kbase_csf_cmd_stream_group_info *const info,
-+ const u32 offset, const u32 value, const u32 mask)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+
-+ dev_dbg(kbdev->dev, "csg input w: reg %08x val %08x mask %08x\n",
-+ offset, value, mask);
-+
-+ /* NO_MALI: Go through kbase_csf_firmware_csg_input to capture writes */
-+ kbase_csf_firmware_csg_input(info, offset, (input_page_read(info->input, offset) & ~mask) | (value & mask));
-+}
-+
-+u32 kbase_csf_firmware_csg_output(
-+ const struct kbase_csf_cmd_stream_group_info *const info,
-+ const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = info->kbdev;
-+ u32 const val = output_page_read(info->output, offset);
-+
-+ dev_dbg(kbdev->dev, "csg output r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+static void
-+csf_firmware_prfcnt_process(const struct kbase_csf_global_iface *const iface,
-+ const u32 glb_req)
-+{
-+ struct kbase_device *kbdev = iface->kbdev;
-+ u32 glb_ack = output_page_read(iface->output, GLB_ACK);
-+ /* If the value of GLB_REQ.PRFCNT_SAMPLE is different from the value of
-+ * GLB_ACK.PRFCNT_SAMPLE, the CSF will sample the performance counters.
-+ */
-+ if ((glb_req ^ glb_ack) & GLB_REQ_PRFCNT_SAMPLE_MASK) {
-+ /* NO_MALI only uses the first buffer in the ring buffer. */
-+ input_page_write(iface->input, GLB_PRFCNT_EXTRACT, 0);
-+ output_page_write(iface->output, GLB_PRFCNT_INSERT, 1);
-+ kbase_reg_write(kbdev, GPU_COMMAND, GPU_COMMAND_PRFCNT_SAMPLE);
-+ }
-+
-+ /* Propagate enable masks to model if request to enable. */
-+ if (glb_req & GLB_REQ_PRFCNT_ENABLE_MASK) {
-+ u32 tiler_en, l2_en, sc_en;
-+
-+ tiler_en = input_page_read(iface->input, GLB_PRFCNT_TILER_EN);
-+ l2_en = input_page_read(iface->input, GLB_PRFCNT_MMU_L2_EN);
-+ sc_en = input_page_read(iface->input, GLB_PRFCNT_SHADER_EN);
-+
-+ /* NO_MALI platform enabled all CSHW counters by default. */
-+ kbase_reg_write(kbdev, PRFCNT_TILER_EN, tiler_en);
-+ kbase_reg_write(kbdev, PRFCNT_MMU_L2_EN, l2_en);
-+ kbase_reg_write(kbdev, PRFCNT_SHADER_EN, sc_en);
-+ }
-+}
-+
-+void kbase_csf_firmware_global_input(
-+ const struct kbase_csf_global_iface *const iface, const u32 offset,
-+ const u32 value)
-+{
-+ const struct kbase_device * const kbdev = iface->kbdev;
-+
-+ dev_dbg(kbdev->dev, "glob input w: reg %08x val %08x\n", offset, value);
-+ input_page_write(iface->input, offset, value);
-+
-+ if (offset == GLB_REQ) {
-+ csf_firmware_prfcnt_process(iface, value);
-+ /* NO_MALI: Immediately acknowledge requests */
-+ output_page_write(iface->output, GLB_ACK, value);
-+ }
-+}
-+
-+void kbase_csf_firmware_global_input_mask(
-+ const struct kbase_csf_global_iface *const iface, const u32 offset,
-+ const u32 value, const u32 mask)
-+{
-+ const struct kbase_device * const kbdev = iface->kbdev;
-+
-+ dev_dbg(kbdev->dev, "glob input w: reg %08x val %08x mask %08x\n",
-+ offset, value, mask);
-+
-+ /* NO_MALI: Go through kbase_csf_firmware_global_input to capture writes */
-+ kbase_csf_firmware_global_input(iface, offset, (input_page_read(iface->input, offset) & ~mask) | (value & mask));
-+}
-+
-+u32 kbase_csf_firmware_global_input_read(
-+ const struct kbase_csf_global_iface *const iface, const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = iface->kbdev;
-+ u32 const val = input_page_read(iface->input, offset);
-+
-+ dev_dbg(kbdev->dev, "glob input r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+u32 kbase_csf_firmware_global_output(
-+ const struct kbase_csf_global_iface *const iface, const u32 offset)
-+{
-+ const struct kbase_device * const kbdev = iface->kbdev;
-+ u32 const val = output_page_read(iface->output, offset);
-+
-+ dev_dbg(kbdev->dev, "glob output r: reg %08x val %08x\n", offset, val);
-+ return val;
-+}
-+
-+/**
-+ * handle_internal_firmware_fatal - Handler for CS internal firmware fault.
-+ *
-+ * @kbdev: Pointer to kbase device
-+ *
-+ * Report group fatal error to user space for all GPU command queue groups
-+ * in the device, terminate them and reset GPU.
-+ */
-+static void handle_internal_firmware_fatal(struct kbase_device *const kbdev)
-+{
-+ int as;
-+
-+ for (as = 0; as < kbdev->nr_hw_address_spaces; as++) {
-+ unsigned long flags;
-+ struct kbase_context *kctx;
-+ struct kbase_fault fault;
-+
-+ if (as == MCU_AS_NR)
-+ continue;
-+
-+ /* Only handle the fault for an active address space. Lock is
-+ * taken here to atomically get reference to context in an
-+ * active address space and retain its refcount.
-+ */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kctx = kbase_ctx_sched_as_to_ctx_nolock(kbdev, as);
-+
-+ if (kctx) {
-+ kbase_ctx_sched_retain_ctx_refcount(kctx);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ } else {
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ continue;
-+ }
-+
-+ fault = (struct kbase_fault) {
-+ .status = GPU_EXCEPTION_TYPE_SW_FAULT_1,
-+ };
-+
-+ kbase_csf_ctx_handle_fault(kctx, &fault);
-+ kbase_ctx_sched_release_ctx_lock(kctx);
-+ }
-+
-+ if (kbase_prepare_to_reset_gpu(kbdev,
-+ RESET_FLAGS_HWC_UNRECOVERABLE_ERROR))
-+ kbase_reset_gpu(kbdev);
-+}
-+
-+/**
-+ * firmware_error_worker - Worker function for handling firmware internal error
-+ *
-+ * @data: Pointer to a work_struct embedded in kbase device.
-+ *
-+ * Handle the CS internal firmware error
-+ */
-+static void firmware_error_worker(struct work_struct *const data)
-+{
-+ struct kbase_device *const kbdev =
-+ container_of(data, struct kbase_device, csf.fw_error_work);
-+
-+ handle_internal_firmware_fatal(kbdev);
-+}
-+
-+static bool global_request_complete(struct kbase_device *const kbdev,
-+ u32 const req_mask)
-+{
-+ struct kbase_csf_global_iface *global_iface =
-+ &kbdev->csf.global_iface;
-+ bool complete = false;
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+
-+ if ((kbase_csf_firmware_global_output(global_iface, GLB_ACK) &
-+ req_mask) ==
-+ (kbase_csf_firmware_global_input_read(global_iface, GLB_REQ) &
-+ req_mask))
-+ complete = true;
-+
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ return complete;
-+}
-+
-+static int wait_for_global_request(struct kbase_device *const kbdev,
-+ u32 const req_mask)
-+{
-+ const long wait_timeout =
-+ kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+ long remaining;
-+ int err = 0;
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ global_request_complete(kbdev, req_mask),
-+ wait_timeout);
-+
-+ if (!remaining) {
-+ dev_warn(kbdev->dev, "Timed out waiting for global request %x to complete",
-+ req_mask);
-+ err = -ETIMEDOUT;
-+ }
-+
-+ return err;
-+}
-+
-+static void set_global_request(
-+ const struct kbase_csf_global_iface *const global_iface,
-+ u32 const req_mask)
-+{
-+ u32 glb_req;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(global_iface->kbdev);
-+
-+ glb_req = kbase_csf_firmware_global_output(global_iface, GLB_ACK);
-+ glb_req ^= req_mask;
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ, glb_req,
-+ req_mask);
-+}
-+
-+static void enable_endpoints_global(
-+ const struct kbase_csf_global_iface *const global_iface,
-+ u64 const shader_core_mask)
-+{
-+ kbase_csf_firmware_global_input(global_iface, GLB_ALLOC_EN_LO,
-+ shader_core_mask & U32_MAX);
-+ kbase_csf_firmware_global_input(global_iface, GLB_ALLOC_EN_HI,
-+ shader_core_mask >> 32);
-+
-+ set_global_request(global_iface, GLB_REQ_CFG_ALLOC_EN_MASK);
-+}
-+
-+static void enable_shader_poweroff_timer(struct kbase_device *const kbdev,
-+ const struct kbase_csf_global_iface *const global_iface)
-+{
-+ u32 pwroff_reg;
-+
-+ if (kbdev->csf.firmware_hctl_core_pwr)
-+ pwroff_reg =
-+ GLB_PWROFF_TIMER_TIMER_SOURCE_SET(DISABLE_GLB_PWROFF_TIMER,
-+ GLB_PWROFF_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP);
-+ else
-+ pwroff_reg = kbdev->csf.mcu_core_pwroff_dur_count;
-+
-+ kbase_csf_firmware_global_input(global_iface, GLB_PWROFF_TIMER,
-+ pwroff_reg);
-+ set_global_request(global_iface, GLB_REQ_CFG_PWROFF_TIMER_MASK);
-+
-+ /* Save the programed reg value in its shadow field */
-+ kbdev->csf.mcu_core_pwroff_reg_shadow = pwroff_reg;
-+}
-+
-+static void set_timeout_global(
-+ const struct kbase_csf_global_iface *const global_iface,
-+ u64 const timeout)
-+{
-+ kbase_csf_firmware_global_input(global_iface, GLB_PROGRESS_TIMER,
-+ timeout / GLB_PROGRESS_TIMER_TIMEOUT_SCALE);
-+
-+ set_global_request(global_iface, GLB_REQ_CFG_PROGRESS_TIMER_MASK);
-+}
-+
-+static void global_init(struct kbase_device *const kbdev, u64 core_mask)
-+{
-+ u32 const ack_irq_mask = GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_MASK |
-+ GLB_ACK_IRQ_MASK_PING_MASK |
-+ GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_MASK |
-+ GLB_ACK_IRQ_MASK_PROTM_ENTER_MASK |
-+ GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK |
-+ GLB_ACK_IRQ_MASK_PROTM_EXIT_MASK |
-+ GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_MASK |
-+ GLB_ACK_IRQ_MASK_IDLE_EVENT_MASK;
-+
-+ const struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+
-+ /* Update shader core allocation enable mask */
-+ enable_endpoints_global(global_iface, core_mask);
-+ enable_shader_poweroff_timer(kbdev, global_iface);
-+
-+ set_timeout_global(global_iface, kbase_csf_timeout_get(kbdev));
-+
-+ /* Unmask the interrupts */
-+ kbase_csf_firmware_global_input(global_iface,
-+ GLB_ACK_IRQ_MASK, ack_irq_mask);
-+
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+/**
-+ * global_init_on_boot - Sends a global request to control various features.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Currently only the request to enable endpoints and cycle counter is sent.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+static int global_init_on_boot(struct kbase_device *const kbdev)
-+{
-+ unsigned long flags;
-+ u64 core_mask;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ core_mask = kbase_pm_ca_get_core_mask(kbdev);
-+ kbdev->csf.firmware_hctl_core_pwr =
-+ kbase_pm_no_mcu_core_pwroff(kbdev);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ global_init(kbdev, core_mask);
-+
-+ return wait_for_global_request(kbdev, CSF_GLB_REQ_CFG_MASK);
-+}
-+
-+void kbase_csf_firmware_global_reinit(struct kbase_device *kbdev,
-+ u64 core_mask)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ kbdev->csf.glb_init_request_pending = true;
-+ kbdev->csf.firmware_hctl_core_pwr =
-+ kbase_pm_no_mcu_core_pwroff(kbdev);
-+ global_init(kbdev, core_mask);
-+}
-+
-+bool kbase_csf_firmware_global_reinit_complete(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+ WARN_ON(!kbdev->csf.glb_init_request_pending);
-+
-+ if (global_request_complete(kbdev, CSF_GLB_REQ_CFG_MASK))
-+ kbdev->csf.glb_init_request_pending = false;
-+
-+ return !kbdev->csf.glb_init_request_pending;
-+}
-+
-+void kbase_csf_firmware_update_core_attr(struct kbase_device *kbdev,
-+ bool update_core_pwroff_timer, bool update_core_mask, u64 core_mask)
-+{
-+ unsigned long flags;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ if (update_core_mask)
-+ enable_endpoints_global(&kbdev->csf.global_iface, core_mask);
-+ if (update_core_pwroff_timer)
-+ enable_shader_poweroff_timer(kbdev, &kbdev->csf.global_iface);
-+
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+bool kbase_csf_firmware_core_attr_updated(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ return global_request_complete(kbdev, GLB_REQ_CFG_ALLOC_EN_MASK |
-+ GLB_REQ_CFG_PWROFF_TIMER_MASK);
-+}
-+
-+static void kbase_csf_firmware_reload_worker(struct work_struct *work)
-+{
-+ struct kbase_device *kbdev = container_of(work, struct kbase_device,
-+ csf.firmware_reload_work);
-+ unsigned long flags;
-+
-+ /* Reboot the firmware */
-+ kbase_csf_firmware_enable_mcu(kbdev);
-+
-+ /* Tell MCU state machine to transit to next state */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->csf.firmware_reloaded = true;
-+ kbase_pm_update_state(kbdev);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+}
-+
-+void kbase_csf_firmware_trigger_reload(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ kbdev->csf.firmware_reloaded = false;
-+
-+ if (kbdev->csf.firmware_reload_needed) {
-+ kbdev->csf.firmware_reload_needed = false;
-+ queue_work(system_wq, &kbdev->csf.firmware_reload_work);
-+ } else {
-+ kbase_csf_firmware_enable_mcu(kbdev);
-+ kbdev->csf.firmware_reloaded = true;
-+ }
-+}
-+
-+void kbase_csf_firmware_reload_completed(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ if (unlikely(!kbdev->csf.firmware_inited))
-+ return;
-+
-+ /* Tell MCU state machine to transit to next state */
-+ kbdev->csf.firmware_reloaded = true;
-+ kbase_pm_update_state(kbdev);
-+}
-+
-+static u32 convert_dur_to_idle_count(struct kbase_device *kbdev, const u32 dur_ms)
-+{
-+#define HYSTERESIS_VAL_UNIT_SHIFT (10)
-+ /* Get the cntfreq_el0 value, which drives the SYSTEM_TIMESTAMP */
-+ u64 freq = arch_timer_get_cntfrq();
-+ u64 dur_val = dur_ms;
-+ u32 cnt_val_u32, reg_val_u32;
-+ bool src_system_timestamp = freq > 0;
-+
-+ if (!src_system_timestamp) {
-+ /* Get the cycle_counter source alternative */
-+ spin_lock(&kbdev->pm.clk_rtm.lock);
-+ if (kbdev->pm.clk_rtm.clks[0])
-+ freq = kbdev->pm.clk_rtm.clks[0]->clock_val;
-+ else
-+ dev_warn(kbdev->dev, "No GPU clock, unexpected intregration issue!");
-+ spin_unlock(&kbdev->pm.clk_rtm.lock);
-+
-+ dev_info(kbdev->dev, "Can't get the timestamp frequency, "
-+ "use cycle counter format with firmware idle hysteresis!");
-+ }
-+
-+ /* Formula for dur_val = ((dur_ms/1000) * freq_HZ) >> 10) */
-+ dur_val = (dur_val * freq) >> HYSTERESIS_VAL_UNIT_SHIFT;
-+ dur_val = div_u64(dur_val, 1000);
-+
-+ /* Interface limits the value field to S32_MAX */
-+ cnt_val_u32 = (dur_val > S32_MAX) ? S32_MAX : (u32)dur_val;
-+
-+ reg_val_u32 = GLB_IDLE_TIMER_TIMEOUT_SET(0, cnt_val_u32);
-+ /* add the source flag */
-+ if (src_system_timestamp)
-+ reg_val_u32 = GLB_IDLE_TIMER_TIMER_SOURCE_SET(reg_val_u32,
-+ GLB_IDLE_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP);
-+ else
-+ reg_val_u32 = GLB_IDLE_TIMER_TIMER_SOURCE_SET(reg_val_u32,
-+ GLB_IDLE_TIMER_TIMER_SOURCE_GPU_COUNTER);
-+
-+ return reg_val_u32;
-+}
-+
-+u32 kbase_csf_firmware_get_gpu_idle_hysteresis_time(struct kbase_device *kbdev)
-+{
-+ return kbdev->csf.gpu_idle_hysteresis_ms;
-+}
-+
-+u32 kbase_csf_firmware_set_gpu_idle_hysteresis_time(struct kbase_device *kbdev, u32 dur)
-+{
-+ unsigned long flags;
-+ const u32 hysteresis_val = convert_dur_to_idle_count(kbdev, dur);
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ kbdev->csf.gpu_idle_hysteresis_ms = dur;
-+ kbdev->csf.gpu_idle_dur_count = hysteresis_val;
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ dev_dbg(kbdev->dev, "CSF set firmware idle hysteresis count-value: 0x%.8x",
-+ hysteresis_val);
-+
-+ return hysteresis_val;
-+}
-+
-+static u32 convert_dur_to_core_pwroff_count(struct kbase_device *kbdev, const u32 dur_us)
-+{
-+#define PWROFF_VAL_UNIT_SHIFT (10)
-+ /* Get the cntfreq_el0 value, which drives the SYSTEM_TIMESTAMP */
-+ u64 freq = arch_timer_get_cntfrq();
-+ u64 dur_val = dur_us;
-+ u32 cnt_val_u32, reg_val_u32;
-+ bool src_system_timestamp = freq > 0;
-+
-+ if (!src_system_timestamp) {
-+ /* Get the cycle_counter source alternative */
-+ spin_lock(&kbdev->pm.clk_rtm.lock);
-+ if (kbdev->pm.clk_rtm.clks[0])
-+ freq = kbdev->pm.clk_rtm.clks[0]->clock_val;
-+ else
-+ dev_warn(kbdev->dev, "No GPU clock, unexpected integration issue!");
-+ spin_unlock(&kbdev->pm.clk_rtm.lock);
-+
-+ dev_info(kbdev->dev, "Can't get the timestamp frequency, "
-+ "use cycle counter with MCU Core Poweroff timer!");
-+ }
-+
-+ /* Formula for dur_val = ((dur_us/1e6) * freq_HZ) >> 10) */
-+ dur_val = (dur_val * freq) >> HYSTERESIS_VAL_UNIT_SHIFT;
-+ dur_val = div_u64(dur_val, 1000000);
-+
-+ /* Interface limits the value field to S32_MAX */
-+ cnt_val_u32 = (dur_val > S32_MAX) ? S32_MAX : (u32)dur_val;
-+
-+ reg_val_u32 = GLB_PWROFF_TIMER_TIMEOUT_SET(0, cnt_val_u32);
-+ /* add the source flag */
-+ if (src_system_timestamp)
-+ reg_val_u32 = GLB_PWROFF_TIMER_TIMER_SOURCE_SET(reg_val_u32,
-+ GLB_PWROFF_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP);
-+ else
-+ reg_val_u32 = GLB_PWROFF_TIMER_TIMER_SOURCE_SET(reg_val_u32,
-+ GLB_PWROFF_TIMER_TIMER_SOURCE_GPU_COUNTER);
-+
-+ return reg_val_u32;
-+}
-+
-+u32 kbase_csf_firmware_get_mcu_core_pwroff_time(struct kbase_device *kbdev)
-+{
-+ return kbdev->csf.mcu_core_pwroff_dur_us;
-+}
-+
-+u32 kbase_csf_firmware_set_mcu_core_pwroff_time(struct kbase_device *kbdev, u32 dur)
-+{
-+ unsigned long flags;
-+ const u32 pwroff = convert_dur_to_core_pwroff_count(kbdev, dur);
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->csf.mcu_core_pwroff_dur_us = dur;
-+ kbdev->csf.mcu_core_pwroff_dur_count = pwroff;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ dev_dbg(kbdev->dev, "MCU Core Poweroff input update: 0x%.8x", pwroff);
-+
-+ return pwroff;
-+}
-+
-+int kbase_csf_firmware_early_init(struct kbase_device *kbdev)
-+{
-+ init_waitqueue_head(&kbdev->csf.event_wait);
-+ kbdev->csf.interrupt_received = false;
-+ kbdev->csf.fw_timeout_ms = CSF_FIRMWARE_TIMEOUT_MS;
-+
-+ INIT_LIST_HEAD(&kbdev->csf.firmware_interfaces);
-+ INIT_LIST_HEAD(&kbdev->csf.firmware_config);
-+ INIT_LIST_HEAD(&kbdev->csf.firmware_trace_buffers.list);
-+ INIT_WORK(&kbdev->csf.firmware_reload_work,
-+ kbase_csf_firmware_reload_worker);
-+ INIT_WORK(&kbdev->csf.fw_error_work, firmware_error_worker);
-+
-+ mutex_init(&kbdev->csf.reg_lock);
-+
-+ return 0;
-+}
-+
-+int kbase_csf_firmware_init(struct kbase_device *kbdev)
-+{
-+ int ret;
-+
-+ lockdep_assert_held(&kbdev->fw_load_lock);
-+
-+ if (WARN_ON((kbdev->as_free & MCU_AS_BITMASK) == 0))
-+ return -EINVAL;
-+ kbdev->as_free &= ~MCU_AS_BITMASK;
-+
-+ ret = kbase_mmu_init(kbdev, &kbdev->csf.mcu_mmu, NULL,
-+ BASE_MEM_GROUP_DEFAULT);
-+
-+ if (ret != 0) {
-+ /* Release the address space */
-+ kbdev->as_free |= MCU_AS_BITMASK;
-+ return ret;
-+ }
-+
-+ kbdev->csf.gpu_idle_hysteresis_ms = FIRMWARE_IDLE_HYSTERESIS_TIME_MS;
-+ kbdev->csf.gpu_idle_dur_count = convert_dur_to_idle_count(
-+ kbdev, FIRMWARE_IDLE_HYSTERESIS_TIME_MS);
-+
-+ ret = kbase_mcu_shared_interface_region_tracker_init(kbdev);
-+ if (ret != 0) {
-+ dev_err(kbdev->dev,
-+ "Failed to setup the rb tree for managing shared interface segment\n");
-+ goto error;
-+ }
-+
-+ ret = invent_memory_setup_entry(kbdev);
-+ if (ret != 0) {
-+ dev_err(kbdev->dev, "Failed to load firmware entry\n");
-+ goto error;
-+ }
-+
-+ /* Make sure L2 cache is powered up */
-+ kbase_pm_wait_for_l2_powered(kbdev);
-+
-+ /* NO_MALI: Don't init trace buffers */
-+
-+ /* NO_MALI: Don't load the MMU tables or boot CSF firmware */
-+
-+ ret = invent_capabilities(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = kbase_csf_doorbell_mapping_init(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = kbase_csf_setup_dummy_user_reg_page(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = kbase_csf_scheduler_init(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = kbase_csf_timeout_init(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ ret = global_init_on_boot(kbdev);
-+ if (ret != 0)
-+ goto error;
-+
-+ return 0;
-+
-+error:
-+ kbase_csf_firmware_term(kbdev);
-+ return ret;
-+}
-+
-+void kbase_csf_firmware_term(struct kbase_device *kbdev)
-+{
-+ cancel_work_sync(&kbdev->csf.fw_error_work);
-+
-+ kbase_csf_timeout_term(kbdev);
-+
-+ /* NO_MALI: Don't stop firmware or unload MMU tables */
-+
-+ kbase_mmu_term(kbdev, &kbdev->csf.mcu_mmu);
-+
-+ kbase_csf_scheduler_term(kbdev);
-+
-+ kbase_csf_free_dummy_user_reg_page(kbdev);
-+
-+ kbase_csf_doorbell_mapping_term(kbdev);
-+
-+ free_global_iface(kbdev);
-+
-+ /* Release the address space */
-+ kbdev->as_free |= MCU_AS_BITMASK;
-+
-+ while (!list_empty(&kbdev->csf.firmware_interfaces)) {
-+ struct dummy_firmware_interface *interface;
-+
-+ interface = list_first_entry(&kbdev->csf.firmware_interfaces,
-+ struct dummy_firmware_interface, node);
-+ list_del(&interface->node);
-+
-+ /* NO_MALI: No cleanup in dummy interface necessary */
-+
-+ kfree(interface);
-+ }
-+
-+ /* NO_MALI: No trace buffers to terminate */
-+
-+#ifndef MALI_KBASE_BUILD
-+ mali_kutf_fw_utf_entry_cleanup(kbdev);
-+#endif
-+
-+ mutex_destroy(&kbdev->csf.reg_lock);
-+
-+ /* This will also free up the region allocated for the shared interface
-+ * entry parsed from the firmware image.
-+ */
-+ kbase_mcu_shared_interface_region_tracker_term(kbdev);
-+}
-+
-+void kbase_csf_firmware_enable_gpu_idle_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ u32 glb_req;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+
-+ /* The scheduler is assumed to only call the enable when its internal
-+ * state indicates that the idle timer has previously been disabled. So
-+ * on entry the expected field values are:
-+ * 1. GLOBAL_INPUT_BLOCK.GLB_REQ.IDLE_ENABLE: 0
-+ * 2. GLOBAL_OUTPUT_BLOCK.GLB_ACK.IDLE_ENABLE: 0, or, on 1 -> 0
-+ */
-+
-+ glb_req = kbase_csf_firmware_global_input_read(global_iface, GLB_REQ);
-+ if (glb_req & GLB_REQ_IDLE_ENABLE_MASK)
-+ dev_err(kbdev->dev, "Incoherent scheduler state on REQ_IDLE_ENABLE!");
-+
-+ kbase_csf_firmware_global_input(global_iface, GLB_IDLE_TIMER,
-+ kbdev->csf.gpu_idle_dur_count);
-+
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ,
-+ GLB_REQ_REQ_IDLE_ENABLE, GLB_REQ_IDLE_ENABLE_MASK);
-+
-+ dev_dbg(kbdev->dev, "Enabling GPU idle timer with count-value: 0x%.8x",
-+ kbdev->csf.gpu_idle_dur_count);
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+}
-+
-+void kbase_csf_firmware_disable_gpu_idle_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ,
-+ GLB_REQ_REQ_IDLE_DISABLE,
-+ GLB_REQ_IDLE_DISABLE_MASK);
-+
-+ dev_dbg(kbdev->dev, "Sending request to disable gpu idle timer");
-+
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+}
-+
-+void kbase_csf_firmware_ping(struct kbase_device *const kbdev)
-+{
-+ const struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ set_global_request(global_iface, GLB_REQ_PING_MASK);
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+int kbase_csf_firmware_ping_wait(struct kbase_device *const kbdev)
-+{
-+ kbase_csf_firmware_ping(kbdev);
-+ return wait_for_global_request(kbdev, GLB_REQ_PING_MASK);
-+}
-+
-+int kbase_csf_firmware_set_timeout(struct kbase_device *const kbdev,
-+ u64 const timeout)
-+{
-+ const struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+ unsigned long flags;
-+ int err;
-+
-+ /* The 'reg_lock' is also taken and is held till the update is not
-+ * complete, to ensure the update of timeout value by multiple Users
-+ * gets serialized.
-+ */
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ set_timeout_global(global_iface, timeout);
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ err = wait_for_global_request(kbdev, GLB_REQ_CFG_PROGRESS_TIMER_MASK);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ return err;
-+}
-+
-+void kbase_csf_enter_protected_mode(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ set_global_request(global_iface, GLB_REQ_PROTM_ENTER_MASK);
-+ dev_dbg(kbdev->dev, "Sending request to enter protected mode");
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ wait_for_global_request(kbdev, GLB_REQ_PROTM_ENTER_MASK);
-+}
-+
-+void kbase_csf_firmware_trigger_mcu_halt(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ unsigned long flags;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ set_global_request(global_iface, GLB_REQ_HALT_MASK);
-+ dev_dbg(kbdev->dev, "Sending request to HALT MCU");
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+int kbase_csf_trigger_firmware_config_update(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ unsigned long flags;
-+ int err = 0;
-+
-+ /* The 'reg_lock' is also taken and is held till the update is
-+ * complete, to ensure the config update gets serialized.
-+ */
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+
-+ set_global_request(global_iface, GLB_REQ_FIRMWARE_CONFIG_UPDATE_MASK);
-+ dev_dbg(kbdev->dev, "Sending request for FIRMWARE_CONFIG_UPDATE");
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ err = wait_for_global_request(kbdev,
-+ GLB_REQ_FIRMWARE_CONFIG_UPDATE_MASK);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+ return err;
-+}
-+
-+/**
-+ * copy_grp_and_stm - Copy CS and/or group data
-+ *
-+ * @iface: Global CSF interface provided by
-+ * the firmware.
-+ * @group_data: Pointer where to store all the group data
-+ * (sequentially).
-+ * @max_group_num: The maximum number of groups to be read. Can be 0, in
-+ * which case group_data is unused.
-+ * @stream_data: Pointer where to store all the stream data
-+ * (sequentially).
-+ * @max_total_stream_num: The maximum number of streams to be read.
-+ * Can be 0, in which case stream_data is unused.
-+ *
-+ * Return: Total number of CSs, summed across all groups.
-+ */
-+static u32 copy_grp_and_stm(
-+ const struct kbase_csf_global_iface * const iface,
-+ struct basep_cs_group_control * const group_data,
-+ u32 max_group_num,
-+ struct basep_cs_stream_control * const stream_data,
-+ u32 max_total_stream_num)
-+{
-+ u32 i, total_stream_num = 0;
-+
-+ if (WARN_ON((max_group_num > 0) && !group_data))
-+ max_group_num = 0;
-+
-+ if (WARN_ON((max_total_stream_num > 0) && !stream_data))
-+ max_total_stream_num = 0;
-+
-+ for (i = 0; i < iface->group_num; i++) {
-+ u32 j;
-+
-+ if (i < max_group_num) {
-+ group_data[i].features = iface->groups[i].features;
-+ group_data[i].stream_num = iface->groups[i].stream_num;
-+ group_data[i].suspend_size =
-+ iface->groups[i].suspend_size;
-+ }
-+ for (j = 0; j < iface->groups[i].stream_num; j++) {
-+ if (total_stream_num < max_total_stream_num)
-+ stream_data[total_stream_num].features =
-+ iface->groups[i].streams[j].features;
-+ total_stream_num++;
-+ }
-+ }
-+
-+ return total_stream_num;
-+}
-+
-+u32 kbase_csf_firmware_get_glb_iface(
-+ struct kbase_device *kbdev,
-+ struct basep_cs_group_control *const group_data,
-+ u32 const max_group_num,
-+ struct basep_cs_stream_control *const stream_data,
-+ u32 const max_total_stream_num, u32 *const glb_version,
-+ u32 *const features, u32 *const group_num, u32 *const prfcnt_size,
-+ u32 *const instr_features)
-+{
-+ const struct kbase_csf_global_iface * const iface =
-+ &kbdev->csf.global_iface;
-+
-+ if (WARN_ON(!glb_version) || WARN_ON(!features) ||
-+ WARN_ON(!group_num) || WARN_ON(!prfcnt_size) ||
-+ WARN_ON(!instr_features))
-+ return 0;
-+
-+ *glb_version = iface->version;
-+ *features = iface->features;
-+ *group_num = iface->group_num;
-+ *prfcnt_size = iface->prfcnt_size;
-+ *instr_features = iface->instr_features;
-+
-+ return copy_grp_and_stm(iface, group_data, max_group_num,
-+ stream_data, max_total_stream_num);
-+}
-+
-+const char *kbase_csf_firmware_get_timeline_metadata(
-+ struct kbase_device *kbdev, const char *name, size_t *size)
-+{
-+ if (WARN_ON(!kbdev) ||
-+ WARN_ON(!name) ||
-+ WARN_ON(!size)) {
-+ return NULL;
-+ }
-+
-+ *size = 0;
-+ return NULL;
-+}
-+
-+void kbase_csf_firmware_disable_mcu_wait(struct kbase_device *kbdev)
-+{
-+ /* NO_MALI: Nothing to do here */
-+}
-+
-+int kbase_csf_firmware_mcu_shared_mapping_init(
-+ struct kbase_device *kbdev,
-+ unsigned int num_pages,
-+ unsigned long cpu_map_properties,
-+ unsigned long gpu_map_properties,
-+ struct kbase_csf_mapping *csf_mapping)
-+{
-+ struct tagged_addr *phys;
-+ struct kbase_va_region *va_reg;
-+ struct page **page_list;
-+ void *cpu_addr;
-+ int i, ret = 0;
-+ pgprot_t cpu_map_prot = PAGE_KERNEL;
-+ unsigned long gpu_map_prot;
-+
-+ if (cpu_map_properties & PROT_READ)
-+ cpu_map_prot = PAGE_KERNEL_RO;
-+
-+ if (kbdev->system_coherency == COHERENCY_ACE) {
-+ gpu_map_prot =
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_DEFAULT_ACE);
-+ } else {
-+ gpu_map_prot =
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE);
-+ cpu_map_prot = pgprot_writecombine(cpu_map_prot);
-+ };
-+
-+ phys = kmalloc_array(num_pages, sizeof(*phys), GFP_KERNEL);
-+ if (!phys)
-+ goto out;
-+
-+ page_list = kmalloc_array(num_pages, sizeof(*page_list), GFP_KERNEL);
-+ if (!page_list)
-+ goto page_list_alloc_error;
-+
-+ ret = kbase_mem_pool_alloc_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ num_pages, phys, false);
-+ if (ret <= 0)
-+ goto phys_mem_pool_alloc_error;
-+
-+ for (i = 0; i < num_pages; i++)
-+ page_list[i] = as_page(phys[i]);
-+
-+ cpu_addr = vmap(page_list, num_pages, VM_MAP, cpu_map_prot);
-+ if (!cpu_addr)
-+ goto vmap_error;
-+
-+ va_reg = kbase_alloc_free_region(&kbdev->csf.shared_reg_rbtree, 0,
-+ num_pages, KBASE_REG_ZONE_MCU_SHARED);
-+ if (!va_reg)
-+ goto va_region_alloc_error;
-+
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ ret = kbase_add_va_region_rbtree(kbdev, va_reg, 0, num_pages, 1);
-+ va_reg->flags &= ~KBASE_REG_FREE;
-+ if (ret)
-+ goto va_region_add_error;
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+
-+ gpu_map_properties &= (KBASE_REG_GPU_RD | KBASE_REG_GPU_WR);
-+ gpu_map_properties |= gpu_map_prot;
-+
-+ ret = kbase_mmu_insert_pages_no_flush(kbdev, &kbdev->csf.mcu_mmu,
-+ va_reg->start_pfn, &phys[0], num_pages,
-+ gpu_map_properties, KBASE_MEM_GROUP_CSF_FW);
-+ if (ret)
-+ goto mmu_insert_pages_error;
-+
-+ kfree(page_list);
-+ csf_mapping->phys = phys;
-+ csf_mapping->cpu_addr = cpu_addr;
-+ csf_mapping->va_reg = va_reg;
-+ csf_mapping->num_pages = num_pages;
-+
-+ return 0;
-+
-+mmu_insert_pages_error:
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ kbase_remove_va_region(va_reg);
-+va_region_add_error:
-+ kbase_free_alloced_region(va_reg);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+va_region_alloc_error:
-+ vunmap(cpu_addr);
-+vmap_error:
-+ kbase_mem_pool_free_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ num_pages, phys, false, false);
-+
-+phys_mem_pool_alloc_error:
-+ kfree(page_list);
-+page_list_alloc_error:
-+ kfree(phys);
-+out:
-+ /* Zero-initialize the mapping to make sure that the termination
-+ * function doesn't try to unmap or free random addresses.
-+ */
-+ csf_mapping->phys = NULL;
-+ csf_mapping->cpu_addr = NULL;
-+ csf_mapping->va_reg = NULL;
-+ csf_mapping->num_pages = 0;
-+
-+ return -ENOMEM;
-+}
-+
-+void kbase_csf_firmware_mcu_shared_mapping_term(
-+ struct kbase_device *kbdev, struct kbase_csf_mapping *csf_mapping)
-+{
-+ if (csf_mapping->va_reg) {
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ kbase_remove_va_region(csf_mapping->va_reg);
-+ kbase_free_alloced_region(csf_mapping->va_reg);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+ }
-+
-+ if (csf_mapping->phys) {
-+ kbase_mem_pool_free_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ csf_mapping->num_pages, csf_mapping->phys, false,
-+ false);
-+ }
-+
-+ vunmap(csf_mapping->cpu_addr);
-+ kfree(csf_mapping->phys);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_heap_context_alloc.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_heap_context_alloc.c
-new file mode 100644
-index 0000000..96746c6
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_heap_context_alloc.c
-@@ -0,0 +1,195 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include "mali_kbase_csf_heap_context_alloc.h"
-+
-+/* Size of one heap context structure, in bytes. */
-+#define HEAP_CTX_SIZE ((size_t)32)
-+
-+/* Total size of the GPU memory region allocated for heap contexts, in bytes. */
-+#define HEAP_CTX_REGION_SIZE (MAX_TILER_HEAPS * HEAP_CTX_SIZE)
-+
-+/**
-+ * sub_alloc - Sub-allocate a heap context from a GPU memory region
-+ *
-+ * @ctx_alloc: Pointer to the heap context allocator.
-+ *
-+ * Return: GPU virtual address of the allocated heap context or 0 on failure.
-+ */
-+static u64 sub_alloc(struct kbase_csf_heap_context_allocator *const ctx_alloc)
-+{
-+ struct kbase_context *const kctx = ctx_alloc->kctx;
-+ int heap_nr = 0;
-+ size_t ctx_offset = 0;
-+ u64 heap_gpu_va = 0;
-+ struct kbase_vmap_struct mapping;
-+ void *ctx_ptr = NULL;
-+
-+ lockdep_assert_held(&ctx_alloc->lock);
-+
-+ heap_nr = find_first_zero_bit(ctx_alloc->in_use,
-+ MAX_TILER_HEAPS);
-+
-+ if (unlikely(heap_nr >= MAX_TILER_HEAPS)) {
-+ dev_err(kctx->kbdev->dev,
-+ "No free tiler heap contexts in the pool\n");
-+ return 0;
-+ }
-+
-+ ctx_offset = heap_nr * HEAP_CTX_SIZE;
-+ heap_gpu_va = ctx_alloc->gpu_va + ctx_offset;
-+ ctx_ptr = kbase_vmap_prot(kctx, heap_gpu_va,
-+ HEAP_CTX_SIZE, KBASE_REG_CPU_WR, &mapping);
-+
-+ if (unlikely(!ctx_ptr)) {
-+ dev_err(kctx->kbdev->dev,
-+ "Failed to map tiler heap context %d (0x%llX)\n",
-+ heap_nr, heap_gpu_va);
-+ return 0;
-+ }
-+
-+ memset(ctx_ptr, 0, HEAP_CTX_SIZE);
-+ kbase_vunmap(ctx_ptr, &mapping);
-+
-+ bitmap_set(ctx_alloc->in_use, heap_nr, 1);
-+
-+ dev_dbg(kctx->kbdev->dev, "Allocated tiler heap context %d (0x%llX)\n",
-+ heap_nr, heap_gpu_va);
-+
-+ return heap_gpu_va;
-+}
-+
-+/**
-+ * sub_free - Free a heap context sub-allocated from a GPU memory region
-+ *
-+ * @ctx_alloc: Pointer to the heap context allocator.
-+ * @heap_gpu_va: The GPU virtual address of a heap context structure to free.
-+ */
-+static void sub_free(struct kbase_csf_heap_context_allocator *const ctx_alloc,
-+ u64 const heap_gpu_va)
-+{
-+ struct kbase_context *const kctx = ctx_alloc->kctx;
-+ u64 ctx_offset = 0;
-+ unsigned int heap_nr = 0;
-+
-+ lockdep_assert_held(&ctx_alloc->lock);
-+
-+ if (WARN_ON(!ctx_alloc->region))
-+ return;
-+
-+ if (WARN_ON(heap_gpu_va < ctx_alloc->gpu_va))
-+ return;
-+
-+ ctx_offset = heap_gpu_va - ctx_alloc->gpu_va;
-+
-+ if (WARN_ON(ctx_offset >= HEAP_CTX_REGION_SIZE) ||
-+ WARN_ON(ctx_offset % HEAP_CTX_SIZE))
-+ return;
-+
-+ heap_nr = ctx_offset / HEAP_CTX_SIZE;
-+ dev_dbg(kctx->kbdev->dev,
-+ "Freed tiler heap context %d (0x%llX)\n", heap_nr, heap_gpu_va);
-+
-+ bitmap_clear(ctx_alloc->in_use, heap_nr, 1);
-+}
-+
-+int kbase_csf_heap_context_allocator_init(
-+ struct kbase_csf_heap_context_allocator *const ctx_alloc,
-+ struct kbase_context *const kctx)
-+{
-+ /* We cannot pre-allocate GPU memory here because the
-+ * custom VA zone may not have been created yet.
-+ */
-+ ctx_alloc->kctx = kctx;
-+ ctx_alloc->region = NULL;
-+ ctx_alloc->gpu_va = 0;
-+
-+ mutex_init(&ctx_alloc->lock);
-+ bitmap_zero(ctx_alloc->in_use, MAX_TILER_HEAPS);
-+
-+ dev_dbg(kctx->kbdev->dev,
-+ "Initialized a tiler heap context allocator\n");
-+
-+ return 0;
-+}
-+
-+void kbase_csf_heap_context_allocator_term(
-+ struct kbase_csf_heap_context_allocator *const ctx_alloc)
-+{
-+ struct kbase_context *const kctx = ctx_alloc->kctx;
-+
-+ dev_dbg(kctx->kbdev->dev,
-+ "Terminating tiler heap context allocator\n");
-+
-+ if (ctx_alloc->region) {
-+ kbase_gpu_vm_lock(kctx);
-+ ctx_alloc->region->flags &= ~KBASE_REG_NO_USER_FREE;
-+ kbase_mem_free_region(kctx, ctx_alloc->region);
-+ kbase_gpu_vm_unlock(kctx);
-+ }
-+
-+ mutex_destroy(&ctx_alloc->lock);
-+}
-+
-+u64 kbase_csf_heap_context_allocator_alloc(
-+ struct kbase_csf_heap_context_allocator *const ctx_alloc)
-+{
-+ struct kbase_context *const kctx = ctx_alloc->kctx;
-+ u64 flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR |
-+ BASE_MEM_PROT_CPU_WR | BASEP_MEM_NO_USER_FREE;
-+ u64 nr_pages = PFN_UP(HEAP_CTX_REGION_SIZE);
-+ u64 heap_gpu_va = 0;
-+
-+#ifdef CONFIG_MALI_VECTOR_DUMP
-+ flags |= BASE_MEM_PROT_CPU_RD;
-+#endif
-+
-+ mutex_lock(&ctx_alloc->lock);
-+
-+ /* If the pool of heap contexts wasn't already allocated then
-+ * allocate it.
-+ */
-+ if (!ctx_alloc->region) {
-+ ctx_alloc->region = kbase_mem_alloc(kctx, nr_pages, nr_pages,
-+ 0, &flags, &ctx_alloc->gpu_va);
-+ }
-+
-+ /* If the pool still isn't allocated then an error occurred. */
-+ if (unlikely(!ctx_alloc->region)) {
-+ dev_err(kctx->kbdev->dev, "Failed to allocate a pool of tiler heap contexts\n");
-+ } else {
-+ heap_gpu_va = sub_alloc(ctx_alloc);
-+ }
-+
-+ mutex_unlock(&ctx_alloc->lock);
-+
-+ return heap_gpu_va;
-+}
-+
-+void kbase_csf_heap_context_allocator_free(
-+ struct kbase_csf_heap_context_allocator *const ctx_alloc,
-+ u64 const heap_gpu_va)
-+{
-+ mutex_lock(&ctx_alloc->lock);
-+ sub_free(ctx_alloc, heap_gpu_va);
-+ mutex_unlock(&ctx_alloc->lock);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_heap_context_alloc.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_heap_context_alloc.h
-new file mode 100644
-index 0000000..993db63
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_heap_context_alloc.h
-@@ -0,0 +1,75 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+
-+#ifndef _KBASE_CSF_HEAP_CONTEXT_ALLOC_H_
-+#define _KBASE_CSF_HEAP_CONTEXT_ALLOC_H_
-+
-+/**
-+ * kbase_csf_heap_context_allocator_init - Initialize an allocator for heap
-+ * contexts
-+ * @ctx_alloc: Pointer to the heap context allocator to initialize.
-+ * @kctx: Pointer to the kbase context.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+int kbase_csf_heap_context_allocator_init(
-+ struct kbase_csf_heap_context_allocator *const ctx_alloc,
-+ struct kbase_context *const kctx);
-+
-+/**
-+ * kbase_csf_heap_context_allocator_term - Terminate an allocator for heap
-+ * contexts
-+ * @ctx_alloc: Pointer to the heap context allocator to terminate.
-+ */
-+void kbase_csf_heap_context_allocator_term(
-+ struct kbase_csf_heap_context_allocator *const ctx_alloc);
-+
-+/**
-+ * kbase_csf_heap_context_allocator_alloc - Allocate a heap context structure
-+ *
-+ * If this function is successful then it returns the address of a
-+ * zero-initialized heap context structure for use by the firmware.
-+ *
-+ * @ctx_alloc: Pointer to the heap context allocator.
-+ *
-+ * Return: GPU virtual address of the allocated heap context or 0 on failure.
-+ */
-+u64 kbase_csf_heap_context_allocator_alloc(
-+ struct kbase_csf_heap_context_allocator *const ctx_alloc);
-+
-+/**
-+ * kbase_csf_heap_context_allocator_free - Free a heap context structure
-+ *
-+ * This function returns a heap context structure to the free pool of unused
-+ * contexts for possible reuse by a future call to
-+ * @kbase_csf_heap_context_allocator_alloc.
-+ *
-+ * @ctx_alloc: Pointer to the heap context allocator.
-+ * @heap_gpu_va: The GPU virtual address of a heap context structure that
-+ * was allocated for the firmware.
-+ */
-+void kbase_csf_heap_context_allocator_free(
-+ struct kbase_csf_heap_context_allocator *const ctx_alloc,
-+ u64 const heap_gpu_va);
-+
-+#endif /* _KBASE_CSF_HEAP_CONTEXT_ALLOC_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c
-new file mode 100644
-index 0000000..4e26a49
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.c
-@@ -0,0 +1,2258 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <tl/mali_kbase_tracepoints.h>
-+#include <mali_kbase_ctx_sched.h>
-+#include "device/mali_kbase_device.h"
-+#include "mali_kbase_csf.h"
-+#include <linux/export.h>
-+
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
-+#include "mali_kbase_fence.h"
-+#include "mali_kbase_sync.h"
-+
-+static DEFINE_SPINLOCK(kbase_csf_fence_lock);
-+#endif
-+
-+static void kcpu_queue_process(struct kbase_kcpu_command_queue *kcpu_queue,
-+ bool ignore_waits);
-+
-+static void kcpu_queue_process_worker(struct work_struct *data);
-+
-+static int kbase_kcpu_map_import_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_import_info *import_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+ struct kbase_va_region *reg;
-+ int ret = 0;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ /* Take the processes mmap lock */
-+ down_read(kbase_mem_get_process_mmap_lock());
-+ kbase_gpu_vm_lock(kctx);
-+
-+ reg = kbase_region_tracker_find_region_enclosing_address(kctx,
-+ import_info->handle);
-+
-+ if (kbase_is_region_invalid_or_free(reg) ||
-+ !kbase_mem_is_imported(reg->gpu_alloc->type)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (reg->gpu_alloc->type == KBASE_MEM_TYPE_IMPORTED_USER_BUF) {
-+ /* Pin the physical pages backing the user buffer while
-+ * we are in the process context and holding the mmap lock.
-+ * The dma mapping & GPU mapping of the pages would be done
-+ * when the MAP_IMPORT operation is executed.
-+ *
-+ * Though the pages would be pinned, no reference is taken
-+ * on the physical pages tracking object. When the last
-+ * reference to the tracking object is dropped the pages
-+ * would be unpinned if they weren't unpinned before.
-+ */
-+ ret = kbase_jd_user_buf_pin_pages(kctx, reg);
-+ if (ret)
-+ goto out;
-+ }
-+
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_MAP_IMPORT;
-+ current_command->info.import.gpu_va = import_info->handle;
-+
-+out:
-+ kbase_gpu_vm_unlock(kctx);
-+ /* Release the processes mmap lock */
-+ up_read(kbase_mem_get_process_mmap_lock());
-+
-+ return ret;
-+}
-+
-+static int kbase_kcpu_unmap_import_prepare_internal(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_import_info *import_info,
-+ struct kbase_kcpu_command *current_command,
-+ enum base_kcpu_command_type type)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+ struct kbase_va_region *reg;
-+ int ret = 0;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ kbase_gpu_vm_lock(kctx);
-+
-+ reg = kbase_region_tracker_find_region_enclosing_address(kctx,
-+ import_info->handle);
-+
-+ if (kbase_is_region_invalid_or_free(reg) ||
-+ !kbase_mem_is_imported(reg->gpu_alloc->type)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (reg->gpu_alloc->type == KBASE_MEM_TYPE_IMPORTED_USER_BUF) {
-+ /* The pages should have been pinned when MAP_IMPORT
-+ * was enqueued previously.
-+ */
-+ if (reg->gpu_alloc->nents !=
-+ reg->gpu_alloc->imported.user_buf.nr_pages) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ }
-+
-+ current_command->type = type;
-+ current_command->info.import.gpu_va = import_info->handle;
-+
-+out:
-+ kbase_gpu_vm_unlock(kctx);
-+
-+ return ret;
-+}
-+
-+static int kbase_kcpu_unmap_import_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_import_info *import_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ return kbase_kcpu_unmap_import_prepare_internal(kcpu_queue,
-+ import_info, current_command,
-+ BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT);
-+}
-+
-+static int kbase_kcpu_unmap_import_force_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_import_info *import_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ return kbase_kcpu_unmap_import_prepare_internal(kcpu_queue,
-+ import_info, current_command,
-+ BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT_FORCE);
-+}
-+
-+/**
-+ * kbase_jit_add_to_pending_alloc_list() - Pend JIT allocation
-+ *
-+ * @queue: The queue containing this JIT allocation
-+ * @cmd: The JIT allocation that is blocking this queue
-+ */
-+static void kbase_jit_add_to_pending_alloc_list(
-+ struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command *cmd)
-+{
-+ struct kbase_context *const kctx = queue->kctx;
-+ struct list_head *target_list_head =
-+ &kctx->csf.kcpu_queues.jit_blocked_queues;
-+ struct kbase_kcpu_command_queue *blocked_queue;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ list_for_each_entry(blocked_queue,
-+ &kctx->csf.kcpu_queues.jit_blocked_queues,
-+ jit_blocked) {
-+ struct kbase_kcpu_command const*const jit_alloc_cmd =
-+ &blocked_queue->commands[blocked_queue->start_offset];
-+
-+ WARN_ON(jit_alloc_cmd->type != BASE_KCPU_COMMAND_TYPE_JIT_ALLOC);
-+ if (cmd->enqueue_ts < jit_alloc_cmd->enqueue_ts) {
-+ target_list_head = &blocked_queue->jit_blocked;
-+ break;
-+ }
-+ }
-+
-+ list_add_tail(&queue->jit_blocked, target_list_head);
-+}
-+
-+/**
-+ * kbase_kcpu_jit_allocate_process() - Process JIT allocation
-+ *
-+ * @queue: The queue containing this JIT allocation
-+ * @cmd: The JIT allocation command
-+ */
-+static int kbase_kcpu_jit_allocate_process(
-+ struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command *cmd)
-+{
-+ struct kbase_context *const kctx = queue->kctx;
-+ struct kbase_kcpu_command_jit_alloc_info *alloc_info =
-+ &cmd->info.jit_alloc;
-+ struct base_jit_alloc_info *info = alloc_info->info;
-+ struct kbase_vmap_struct mapping;
-+ struct kbase_va_region *reg;
-+ u32 count = alloc_info->count;
-+ u64 *ptr, new_addr;
-+ u32 i;
-+ int ret;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ if (alloc_info->blocked) {
-+ list_del(&queue->jit_blocked);
-+ alloc_info->blocked = false;
-+ }
-+
-+ if (WARN_ON(!info))
-+ return -EINVAL;
-+
-+ /* Check if all JIT IDs are not in use */
-+ for (i = 0; i < count; i++, info++) {
-+ /* The JIT ID is still in use so fail the allocation */
-+ if (kctx->jit_alloc[info->id]) {
-+ dev_warn(kctx->kbdev->dev, "JIT ID still in use\n");
-+ return -EINVAL;
-+ }
-+ }
-+
-+ /* Now start the allocation loop */
-+ for (i = 0, info = alloc_info->info; i < count; i++, info++) {
-+ /* Create a JIT allocation */
-+ reg = kbase_jit_allocate(kctx, info, true);
-+ if (!reg) {
-+ bool can_block = false;
-+ struct kbase_kcpu_command const *jit_cmd;
-+
-+ list_for_each_entry(jit_cmd, &kctx->csf.kcpu_queues.jit_cmds_head, info.jit_alloc.node) {
-+ if (jit_cmd == cmd)
-+ break;
-+
-+ if (jit_cmd->type == BASE_KCPU_COMMAND_TYPE_JIT_FREE) {
-+ u8 const*const free_ids = jit_cmd->info.jit_free.ids;
-+
-+ if (free_ids && *free_ids && kctx->jit_alloc[*free_ids]) {
-+ /*
-+ * A JIT free which is active
-+ * and submitted before this
-+ * command.
-+ */
-+ can_block = true;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (!can_block) {
-+ /*
-+ * No prior JIT_FREE command is active. Roll
-+ * back previous allocations and fail.
-+ */
-+ dev_warn_ratelimited(kctx->kbdev->dev, "JIT alloc command failed: %pK\n", cmd);
-+ ret = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ /* There are pending frees for an active allocation
-+ * so we should wait to see whether they free the
-+ * memory. Add to the list of atoms for which JIT
-+ * allocation is pending.
-+ */
-+ kbase_jit_add_to_pending_alloc_list(queue, cmd);
-+ alloc_info->blocked = true;
-+
-+ /* Rollback, the whole set will be re-attempted */
-+ while (i-- > 0) {
-+ info--;
-+ kbase_jit_free(kctx, kctx->jit_alloc[info->id]);
-+ kctx->jit_alloc[info->id] = NULL;
-+ }
-+
-+ return -EAGAIN;
-+ }
-+
-+ /* Bind it to the user provided ID. */
-+ kctx->jit_alloc[info->id] = reg;
-+ }
-+
-+ for (i = 0, info = alloc_info->info; i < count; i++, info++) {
-+ /*
-+ * Write the address of the JIT allocation to the user provided
-+ * GPU allocation.
-+ */
-+ ptr = kbase_vmap(kctx, info->gpu_alloc_addr, sizeof(*ptr),
-+ &mapping);
-+ if (!ptr) {
-+ ret = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ reg = kctx->jit_alloc[info->id];
-+ new_addr = reg->start_pfn << PAGE_SHIFT;
-+ *ptr = new_addr;
-+ kbase_vunmap(kctx, &mapping);
-+ }
-+
-+ return 0;
-+
-+fail:
-+ /* Roll back completely */
-+ for (i = 0, info = alloc_info->info; i < count; i++, info++) {
-+ /* Free the allocations that were successful.
-+ * Mark all the allocations including the failed one and the
-+ * other un-attempted allocations in the set, so we know they
-+ * are in use.
-+ */
-+ if (kctx->jit_alloc[info->id])
-+ kbase_jit_free(kctx, kctx->jit_alloc[info->id]);
-+
-+ kctx->jit_alloc[info->id] = KBASE_RESERVED_REG_JIT_ALLOC;
-+ }
-+
-+ return ret;
-+}
-+
-+static int kbase_kcpu_jit_allocate_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_jit_alloc_info *alloc_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+ void __user *data = u64_to_user_ptr(alloc_info->info);
-+ struct base_jit_alloc_info *info;
-+ u32 count = alloc_info->count;
-+ int ret = 0;
-+ u32 i;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ if (!data || count > kcpu_queue->kctx->jit_max_allocations ||
-+ count > ARRAY_SIZE(kctx->jit_alloc)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ info = kmalloc_array(count, sizeof(*info), GFP_KERNEL);
-+ if (!info) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+
-+ if (copy_from_user(info, data, sizeof(*info) * count) != 0) {
-+ ret = -EINVAL;
-+ goto out_free;
-+ }
-+
-+ for (i = 0; i < count; i++) {
-+ ret = kbasep_jit_alloc_validate(kctx, &info[i]);
-+ if (ret)
-+ goto out_free;
-+ }
-+
-+ /* Search for duplicate JIT ids */
-+ for (i = 0; i < (count - 1); i++) {
-+ u32 j;
-+
-+ for (j = (i + 1); j < count; j++) {
-+ if (info[i].id == info[j].id) {
-+ ret = -EINVAL;
-+ goto out_free;
-+ }
-+ }
-+ }
-+
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_JIT_ALLOC;
-+ list_add_tail(¤t_command->info.jit_alloc.node,
-+ &kctx->csf.kcpu_queues.jit_cmds_head);
-+ current_command->info.jit_alloc.info = info;
-+ current_command->info.jit_alloc.count = count;
-+ current_command->info.jit_alloc.blocked = false;
-+
-+ return 0;
-+out_free:
-+ kfree(info);
-+out:
-+ return ret;
-+}
-+
-+/**
-+ * kbase_kcpu_jit_allocate_finish() - Finish handling the JIT_ALLOC command
-+ *
-+ * @queue: The queue containing this JIT allocation
-+ * @cmd: The JIT allocation command
-+ */
-+static void kbase_kcpu_jit_allocate_finish(
-+ struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command *cmd)
-+{
-+ lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock);
-+
-+ /* Remove this command from the jit_cmds_head list */
-+ list_del(&cmd->info.jit_alloc.node);
-+
-+ /*
-+ * If we get to this point we must have already cleared the blocked
-+ * flag, otherwise it'd be a bug.
-+ */
-+ if (WARN_ON(cmd->info.jit_alloc.blocked)) {
-+ list_del(&queue->jit_blocked);
-+ cmd->info.jit_alloc.blocked = false;
-+ }
-+
-+ kfree(cmd->info.jit_alloc.info);
-+}
-+
-+/**
-+ * kbase_kcpu_jit_retry_pending_allocs() - Retry blocked JIT_ALLOC commands
-+ *
-+ * @kctx: The context containing the blocked JIT_ALLOC commands
-+ */
-+static void kbase_kcpu_jit_retry_pending_allocs(struct kbase_context *kctx)
-+{
-+ struct kbase_kcpu_command_queue *blocked_queue;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ /*
-+ * Reschedule all queues blocked by JIT_ALLOC commands.
-+ * NOTE: This code traverses the list of blocked queues directly. It
-+ * only works as long as the queued works are not executed at the same
-+ * time. This precondition is true since we're holding the
-+ * kbase_csf_kcpu_queue_context.lock .
-+ */
-+ list_for_each_entry(blocked_queue,
-+ &kctx->csf.kcpu_queues.jit_blocked_queues, jit_blocked)
-+ queue_work(kctx->csf.kcpu_queues.wq, &blocked_queue->work);
-+}
-+
-+static int kbase_kcpu_jit_free_process(struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command *const cmd)
-+{
-+ struct kbase_kcpu_command_jit_free_info const *const free_info =
-+ &cmd->info.jit_free;
-+ u8 const *const ids = free_info->ids;
-+ u32 const count = free_info->count;
-+ u32 i;
-+ int rc = 0;
-+ struct kbase_context *kctx = queue->kctx;
-+
-+ if (WARN_ON(!ids))
-+ return -EINVAL;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_FREE_END(
-+ queue->kctx->kbdev, queue);
-+
-+ for (i = 0; i < count; i++) {
-+ u64 pages_used = 0;
-+ int item_err = 0;
-+
-+ if (!kctx->jit_alloc[ids[i]]) {
-+ dev_warn(kctx->kbdev->dev, "invalid JIT free ID\n");
-+ rc = -EINVAL;
-+ item_err = rc;
-+ } else {
-+ struct kbase_va_region *const reg = kctx->jit_alloc[ids[i]];
-+
-+ /*
-+ * If the ID is valid but the allocation request failed, still
-+ * succeed this command but don't try and free the allocation.
-+ */
-+ if (reg != KBASE_RESERVED_REG_JIT_ALLOC) {
-+ pages_used = reg->gpu_alloc->nents;
-+ kbase_jit_free(kctx, reg);
-+ }
-+
-+ kctx->jit_alloc[ids[i]] = NULL;
-+ }
-+
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END(
-+ queue->kctx->kbdev, queue, item_err, pages_used);
-+ }
-+
-+ /* Free the list of ids */
-+ kfree(ids);
-+
-+ /*
-+ * Remove this command from the jit_cmds_head list and retry pending
-+ * allocations.
-+ */
-+ list_del(&cmd->info.jit_free.node);
-+ kbase_kcpu_jit_retry_pending_allocs(kctx);
-+
-+ return rc;
-+}
-+
-+static int kbase_kcpu_jit_free_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_jit_free_info *free_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+ void __user *data = u64_to_user_ptr(free_info->ids);
-+ u8 *ids;
-+ u32 count = free_info->count;
-+ int ret;
-+ u32 i;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ /* Sanity checks */
-+ if (!count || count > ARRAY_SIZE(kctx->jit_alloc)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ /* Copy the information for safe access and future storage */
-+ ids = kmalloc_array(count, sizeof(*ids), GFP_KERNEL);
-+ if (!ids) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+
-+ if (!data) {
-+ ret = -EINVAL;
-+ goto out_free;
-+ }
-+
-+ if (copy_from_user(ids, data, sizeof(*ids) * count)) {
-+ ret = -EINVAL;
-+ goto out_free;
-+ }
-+
-+ for (i = 0; i < count; i++) {
-+ /* Fail the command if ID sent is zero */
-+ if (!ids[i]) {
-+ ret = -EINVAL;
-+ goto out_free;
-+ }
-+ }
-+
-+ /* Search for duplicate JIT ids */
-+ for (i = 0; i < (count - 1); i++) {
-+ u32 j;
-+
-+ for (j = (i + 1); j < count; j++) {
-+ if (ids[i] == ids[j]) {
-+ ret = -EINVAL;
-+ goto out_free;
-+ }
-+ }
-+ }
-+
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_JIT_FREE;
-+ list_add_tail(¤t_command->info.jit_free.node,
-+ &kctx->csf.kcpu_queues.jit_cmds_head);
-+ current_command->info.jit_free.ids = ids;
-+ current_command->info.jit_free.count = count;
-+
-+ return 0;
-+out_free:
-+ kfree(ids);
-+out:
-+ return ret;
-+}
-+
-+static int kbase_csf_queue_group_suspend_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_group_suspend_info *suspend_buf,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+ struct kbase_suspend_copy_buffer *sus_buf = NULL;
-+ u64 addr = suspend_buf->buffer;
-+ u64 page_addr = addr & PAGE_MASK;
-+ u64 end_addr = addr + suspend_buf->size - 1;
-+ u64 last_page_addr = end_addr & PAGE_MASK;
-+ int nr_pages = (last_page_addr - page_addr) / PAGE_SIZE + 1;
-+ int pinned_pages = 0, ret = 0;
-+ struct kbase_va_region *reg;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ if (suspend_buf->size <
-+ kctx->kbdev->csf.global_iface.groups[0].suspend_size)
-+ return -EINVAL;
-+
-+ ret = kbase_csf_queue_group_handle_is_valid(kctx,
-+ suspend_buf->group_handle);
-+ if (ret)
-+ return ret;
-+
-+ sus_buf = kzalloc(sizeof(*sus_buf), GFP_KERNEL);
-+ if (!sus_buf)
-+ return -ENOMEM;
-+
-+ sus_buf->size = suspend_buf->size;
-+ sus_buf->nr_pages = nr_pages;
-+ sus_buf->offset = addr & ~PAGE_MASK;
-+
-+ sus_buf->pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
-+ if (!sus_buf->pages) {
-+ ret = -ENOMEM;
-+ goto out_clean_sus_buf;
-+ }
-+
-+ /* Check if the page_addr is a valid GPU VA from SAME_VA zone,
-+ * otherwise consider it is a CPU VA corresponding to the Host
-+ * memory allocated by userspace.
-+ */
-+ kbase_gpu_vm_lock(kctx);
-+ reg = kbase_region_tracker_find_region_enclosing_address(kctx,
-+ page_addr);
-+
-+ if (kbase_is_region_invalid_or_free(reg)) {
-+ kbase_gpu_vm_unlock(kctx);
-+ pinned_pages = get_user_pages_fast(page_addr, nr_pages, 1,
-+ sus_buf->pages);
-+ kbase_gpu_vm_lock(kctx);
-+
-+ if (pinned_pages < 0) {
-+ ret = pinned_pages;
-+ goto out_clean_pages;
-+ }
-+ if (pinned_pages != nr_pages) {
-+ ret = -EINVAL;
-+ goto out_clean_pages;
-+ }
-+ } else {
-+ struct tagged_addr *page_array;
-+ u64 start, end, i;
-+
-+ if (!(reg->flags & BASE_MEM_SAME_VA) ||
-+ reg->nr_pages < nr_pages ||
-+ kbase_reg_current_backed_size(reg) !=
-+ reg->nr_pages) {
-+ ret = -EINVAL;
-+ goto out_clean_pages;
-+ }
-+
-+ start = PFN_DOWN(page_addr) - reg->start_pfn;
-+ end = start + nr_pages;
-+
-+ if (end > reg->nr_pages) {
-+ ret = -EINVAL;
-+ goto out_clean_pages;
-+ }
-+
-+ sus_buf->cpu_alloc = kbase_mem_phy_alloc_get(reg->cpu_alloc);
-+ kbase_mem_phy_alloc_kernel_mapped(reg->cpu_alloc);
-+ page_array = kbase_get_cpu_phy_pages(reg);
-+ page_array += start;
-+
-+ for (i = 0; i < nr_pages; i++, page_array++)
-+ sus_buf->pages[i] = as_page(*page_array);
-+ }
-+
-+ kbase_gpu_vm_unlock(kctx);
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_GROUP_SUSPEND;
-+ current_command->info.suspend_buf_copy.sus_buf = sus_buf;
-+ current_command->info.suspend_buf_copy.group_handle =
-+ suspend_buf->group_handle;
-+ return ret;
-+
-+out_clean_pages:
-+ kbase_gpu_vm_unlock(kctx);
-+ kfree(sus_buf->pages);
-+out_clean_sus_buf:
-+ kfree(sus_buf);
-+
-+ return ret;
-+}
-+
-+static int kbase_csf_queue_group_suspend_process(struct kbase_context *kctx,
-+ struct kbase_suspend_copy_buffer *sus_buf,
-+ u8 group_handle)
-+{
-+ return kbase_csf_queue_group_suspend(kctx, sus_buf, group_handle);
-+}
-+
-+static enum kbase_csf_event_callback_action event_cqs_callback(void *param)
-+{
-+ struct kbase_kcpu_command_queue *kcpu_queue =
-+ (struct kbase_kcpu_command_queue *)param;
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+
-+ queue_work(kctx->csf.kcpu_queues.wq, &kcpu_queue->work);
-+
-+ return KBASE_CSF_EVENT_CALLBACK_KEEP;
-+}
-+
-+static void cleanup_cqs_wait(struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command_cqs_wait_info *cqs_wait)
-+{
-+ WARN_ON(!cqs_wait->nr_objs);
-+ WARN_ON(!cqs_wait->objs);
-+ WARN_ON(!cqs_wait->signaled);
-+ WARN_ON(!queue->cqs_wait_count);
-+
-+ if (--queue->cqs_wait_count == 0) {
-+ kbase_csf_event_wait_remove(queue->kctx,
-+ event_cqs_callback, queue);
-+ }
-+
-+ kfree(cqs_wait->signaled);
-+ kfree(cqs_wait->objs);
-+ cqs_wait->signaled = NULL;
-+ cqs_wait->objs = NULL;
-+}
-+
-+static int kbase_kcpu_cqs_wait_process(struct kbase_device *kbdev,
-+ struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command_cqs_wait_info *cqs_wait)
-+{
-+ u32 i;
-+
-+ lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock);
-+
-+ if (WARN_ON(!cqs_wait->objs))
-+ return -EINVAL;
-+
-+ /* Skip the CQS waits that have already been signaled when processing */
-+ for (i = find_first_zero_bit(cqs_wait->signaled, cqs_wait->nr_objs); i < cqs_wait->nr_objs; i++) {
-+ if (!test_bit(i, cqs_wait->signaled)) {
-+ struct kbase_vmap_struct *mapping;
-+ bool sig_set;
-+ u32 *evt = (u32 *)kbase_phy_alloc_mapping_get(queue->kctx,
-+ cqs_wait->objs[i].addr, &mapping);
-+
-+ if (!queue->command_started) {
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START(
-+ kbdev, queue);
-+ queue->command_started = true;
-+ KBASE_KTRACE_ADD_CSF_KCPU(kbdev, CQS_WAIT_START,
-+ queue, cqs_wait->nr_objs, 0);
-+ }
-+
-+ if (!evt) {
-+ dev_warn(kbdev->dev,
-+ "Sync memory %llx already freed", cqs_wait->objs[i].addr);
-+ queue->has_error = true;
-+ return -EINVAL;
-+ }
-+
-+ sig_set = evt[BASEP_EVENT_VAL_INDEX] > cqs_wait->objs[i].val;
-+ if (sig_set) {
-+ bool error = false;
-+
-+ bitmap_set(cqs_wait->signaled, i, 1);
-+ if ((cqs_wait->inherit_err_flags & (1U << i)) &&
-+ evt[BASEP_EVENT_ERR_INDEX] > 0) {
-+ queue->has_error = true;
-+ error = true;
-+ }
-+
-+ KBASE_KTRACE_ADD_CSF_KCPU(kbdev, CQS_WAIT_END,
-+ queue, cqs_wait->objs[i].addr,
-+ error);
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END(
-+ kbdev, queue,
-+ evt[BASEP_EVENT_ERR_INDEX]);
-+ queue->command_started = false;
-+ }
-+
-+ kbase_phy_alloc_mapping_put(queue->kctx, mapping);
-+
-+ if (!sig_set)
-+ break;
-+ }
-+ }
-+
-+ /* For the queue to progress further, all cqs objects should get
-+ * signaled.
-+ */
-+ return bitmap_full(cqs_wait->signaled, cqs_wait->nr_objs);
-+}
-+
-+static int kbase_kcpu_cqs_wait_prepare(struct kbase_kcpu_command_queue *queue,
-+ struct base_kcpu_command_cqs_wait_info *cqs_wait_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct base_cqs_wait_info *objs;
-+ unsigned int nr_objs = cqs_wait_info->nr_objs;
-+
-+ lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock);
-+
-+ if (nr_objs > BASEP_KCPU_CQS_MAX_NUM_OBJS)
-+ return -EINVAL;
-+
-+ if (!nr_objs)
-+ return -EINVAL;
-+
-+ objs = kcalloc(nr_objs, sizeof(*objs), GFP_KERNEL);
-+ if (!objs)
-+ return -ENOMEM;
-+
-+ if (copy_from_user(objs, u64_to_user_ptr(cqs_wait_info->objs),
-+ nr_objs * sizeof(*objs))) {
-+ kfree(objs);
-+ return -ENOMEM;
-+ }
-+
-+ if (++queue->cqs_wait_count == 1) {
-+ if (kbase_csf_event_wait_add(queue->kctx,
-+ event_cqs_callback, queue)) {
-+ kfree(objs);
-+ queue->cqs_wait_count--;
-+ return -ENOMEM;
-+ }
-+ }
-+
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_CQS_WAIT;
-+ current_command->info.cqs_wait.nr_objs = nr_objs;
-+ current_command->info.cqs_wait.objs = objs;
-+ current_command->info.cqs_wait.inherit_err_flags =
-+ cqs_wait_info->inherit_err_flags;
-+
-+ current_command->info.cqs_wait.signaled = kcalloc(BITS_TO_LONGS(nr_objs),
-+ sizeof(*current_command->info.cqs_wait.signaled), GFP_KERNEL);
-+ if (!current_command->info.cqs_wait.signaled) {
-+ if (--queue->cqs_wait_count == 0) {
-+ kbase_csf_event_wait_remove(queue->kctx,
-+ event_cqs_callback, queue);
-+ }
-+
-+ kfree(objs);
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+static void kbase_kcpu_cqs_set_process(struct kbase_device *kbdev,
-+ struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command_cqs_set_info *cqs_set)
-+{
-+ unsigned int i;
-+
-+ lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock);
-+
-+ if (WARN_ON(!cqs_set->objs))
-+ return;
-+
-+ for (i = 0; i < cqs_set->nr_objs; i++) {
-+ struct kbase_vmap_struct *mapping;
-+ u32 *evt;
-+
-+ evt = (u32 *)kbase_phy_alloc_mapping_get(
-+ queue->kctx, cqs_set->objs[i].addr, &mapping);
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET(kbdev, queue,
-+ evt ? 0 : 1);
-+
-+ if (!evt) {
-+ dev_warn(kbdev->dev,
-+ "Sync memory %llx already freed", cqs_set->objs[i].addr);
-+ queue->has_error = true;
-+ } else {
-+ evt[BASEP_EVENT_ERR_INDEX] = queue->has_error;
-+ /* Set to signaled */
-+ evt[BASEP_EVENT_VAL_INDEX]++;
-+ kbase_phy_alloc_mapping_put(queue->kctx, mapping);
-+
-+ KBASE_KTRACE_ADD_CSF_KCPU(kbdev, CQS_SET,
-+ queue, cqs_set->objs[i].addr,
-+ evt[BASEP_EVENT_ERR_INDEX]);
-+ }
-+ }
-+
-+ kbase_csf_event_signal_notify_gpu(queue->kctx);
-+
-+ kfree(cqs_set->objs);
-+ cqs_set->objs = NULL;
-+}
-+
-+static int kbase_kcpu_cqs_set_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_cqs_set_info *cqs_set_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+ struct base_cqs_set *objs;
-+ unsigned int nr_objs = cqs_set_info->nr_objs;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ if (nr_objs > BASEP_KCPU_CQS_MAX_NUM_OBJS)
-+ return -EINVAL;
-+
-+ if (!nr_objs)
-+ return -EINVAL;
-+
-+ objs = kcalloc(nr_objs, sizeof(*objs), GFP_KERNEL);
-+ if (!objs)
-+ return -ENOMEM;
-+
-+ if (copy_from_user(objs, u64_to_user_ptr(cqs_set_info->objs),
-+ nr_objs * sizeof(*objs))) {
-+ kfree(objs);
-+ return -ENOMEM;
-+ }
-+
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_CQS_SET;
-+ current_command->info.cqs_set.nr_objs = nr_objs;
-+ current_command->info.cqs_set.objs = objs;
-+
-+ return 0;
-+}
-+
-+static void cleanup_cqs_wait_operation(struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command_cqs_wait_operation_info *cqs_wait_operation)
-+{
-+ WARN_ON(!cqs_wait_operation->nr_objs);
-+ WARN_ON(!cqs_wait_operation->objs);
-+ WARN_ON(!cqs_wait_operation->signaled);
-+ WARN_ON(!queue->cqs_wait_count);
-+
-+ if (--queue->cqs_wait_count == 0) {
-+ kbase_csf_event_wait_remove(queue->kctx,
-+ event_cqs_callback, queue);
-+ }
-+
-+ kfree(cqs_wait_operation->signaled);
-+ kfree(cqs_wait_operation->objs);
-+ cqs_wait_operation->signaled = NULL;
-+ cqs_wait_operation->objs = NULL;
-+}
-+
-+static int kbase_kcpu_cqs_wait_operation_process(struct kbase_device *kbdev,
-+ struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command_cqs_wait_operation_info *cqs_wait_operation)
-+{
-+ u32 i;
-+
-+ lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock);
-+
-+ if (WARN_ON(!cqs_wait_operation->objs))
-+ return -EINVAL;
-+
-+ /* Skip the CQS waits that have already been signaled when processing */
-+ for (i = find_first_zero_bit(cqs_wait_operation->signaled, cqs_wait_operation->nr_objs); i < cqs_wait_operation->nr_objs; i++) {
-+ if (!test_bit(i, cqs_wait_operation->signaled)) {
-+ struct kbase_vmap_struct *mapping;
-+ bool sig_set;
-+ u64 *evt = (u64 *)kbase_phy_alloc_mapping_get(queue->kctx,
-+ cqs_wait_operation->objs[i].addr, &mapping);
-+
-+ /* GPUCORE-28172 RDT to review */
-+ if (!queue->command_started)
-+ queue->command_started = true;
-+
-+ if (!evt) {
-+ dev_warn(kbdev->dev,
-+ "Sync memory %llx already freed", cqs_wait_operation->objs[i].addr);
-+ queue->has_error = true;
-+ return -EINVAL;
-+ }
-+
-+ switch (cqs_wait_operation->objs[i].operation) {
-+ case BASEP_CQS_WAIT_OPERATION_LE:
-+ sig_set = *evt <= cqs_wait_operation->objs[i].val;
-+ break;
-+ case BASEP_CQS_WAIT_OPERATION_GT:
-+ sig_set = *evt > cqs_wait_operation->objs[i].val;
-+ break;
-+ default:
-+ dev_warn(kbdev->dev,
-+ "Unsupported CQS wait operation %d", cqs_wait_operation->objs[i].operation);
-+
-+ kbase_phy_alloc_mapping_put(queue->kctx, mapping);
-+ queue->has_error = true;
-+
-+ return -EINVAL;
-+ }
-+
-+ /* Increment evt up to the error_state value depending on the CQS data type */
-+ switch (cqs_wait_operation->objs[i].data_type) {
-+ default:
-+ dev_warn(kbdev->dev, "Unreachable data_type=%d", cqs_wait_operation->objs[i].data_type);
-+ /* Fallthrough - hint to compiler that there's really only 2 options at present */
-+ case BASEP_CQS_DATA_TYPE_U32:
-+ evt = (u64 *)((u8 *)evt + sizeof(u32));
-+ break;
-+ case BASEP_CQS_DATA_TYPE_U64:
-+ evt = (u64 *)((u8 *)evt + sizeof(u64));
-+ break;
-+ }
-+
-+ if (sig_set) {
-+ bitmap_set(cqs_wait_operation->signaled, i, 1);
-+ if ((cqs_wait_operation->inherit_err_flags & (1U << i)) &&
-+ *evt > 0) {
-+ queue->has_error = true;
-+ }
-+
-+ /* GPUCORE-28172 RDT to review */
-+
-+ queue->command_started = false;
-+ }
-+
-+ kbase_phy_alloc_mapping_put(queue->kctx, mapping);
-+
-+ if (!sig_set)
-+ break;
-+ }
-+ }
-+
-+ /* For the queue to progress further, all cqs objects should get
-+ * signaled.
-+ */
-+ return bitmap_full(cqs_wait_operation->signaled, cqs_wait_operation->nr_objs);
-+}
-+
-+static int kbase_kcpu_cqs_wait_operation_prepare(struct kbase_kcpu_command_queue *queue,
-+ struct base_kcpu_command_cqs_wait_operation_info *cqs_wait_operation_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct base_cqs_wait_operation_info *objs;
-+ unsigned int nr_objs = cqs_wait_operation_info->nr_objs;
-+
-+ lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock);
-+
-+ if (nr_objs > BASEP_KCPU_CQS_MAX_NUM_OBJS)
-+ return -EINVAL;
-+
-+ if (!nr_objs)
-+ return -EINVAL;
-+
-+ objs = kcalloc(nr_objs, sizeof(*objs), GFP_KERNEL);
-+ if (!objs)
-+ return -ENOMEM;
-+
-+ if (copy_from_user(objs, u64_to_user_ptr(cqs_wait_operation_info->objs),
-+ nr_objs * sizeof(*objs))) {
-+ kfree(objs);
-+ return -ENOMEM;
-+ }
-+
-+ if (++queue->cqs_wait_count == 1) {
-+ if (kbase_csf_event_wait_add(queue->kctx,
-+ event_cqs_callback, queue)) {
-+ kfree(objs);
-+ queue->cqs_wait_count--;
-+ return -ENOMEM;
-+ }
-+ }
-+
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_CQS_WAIT_OPERATION;
-+ current_command->info.cqs_wait_operation.nr_objs = nr_objs;
-+ current_command->info.cqs_wait_operation.objs = objs;
-+ current_command->info.cqs_wait_operation.inherit_err_flags =
-+ cqs_wait_operation_info->inherit_err_flags;
-+
-+ current_command->info.cqs_wait_operation.signaled = kcalloc(BITS_TO_LONGS(nr_objs),
-+ sizeof(*current_command->info.cqs_wait_operation.signaled), GFP_KERNEL);
-+ if (!current_command->info.cqs_wait_operation.signaled) {
-+ if (--queue->cqs_wait_count == 0) {
-+ kbase_csf_event_wait_remove(queue->kctx,
-+ event_cqs_callback, queue);
-+ }
-+
-+ kfree(objs);
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+static void kbase_kcpu_cqs_set_operation_process(
-+ struct kbase_device *kbdev,
-+ struct kbase_kcpu_command_queue *queue,
-+ struct kbase_kcpu_command_cqs_set_operation_info *cqs_set_operation)
-+{
-+ unsigned int i;
-+
-+ lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock);
-+
-+ if (WARN_ON(!cqs_set_operation->objs))
-+ return;
-+
-+ for (i = 0; i < cqs_set_operation->nr_objs; i++) {
-+ struct kbase_vmap_struct *mapping;
-+ u64 *evt;
-+
-+ evt = (u64 *)kbase_phy_alloc_mapping_get(
-+ queue->kctx, cqs_set_operation->objs[i].addr, &mapping);
-+
-+ /* GPUCORE-28172 RDT to review */
-+
-+ if (!evt) {
-+ dev_warn(kbdev->dev,
-+ "Sync memory %llx already freed", cqs_set_operation->objs[i].addr);
-+ queue->has_error = true;
-+ } else {
-+ switch (cqs_set_operation->objs[i].operation) {
-+ case BASEP_CQS_SET_OPERATION_ADD:
-+ *evt += cqs_set_operation->objs[i].val;
-+ break;
-+ case BASEP_CQS_SET_OPERATION_SET:
-+ *evt = cqs_set_operation->objs[i].val;
-+ break;
-+ default:
-+ dev_warn(kbdev->dev,
-+ "Unsupported CQS set operation %d", cqs_set_operation->objs[i].operation);
-+ queue->has_error = true;
-+ break;
-+ }
-+
-+ /* Increment evt up to the error_state value depending on the CQS data type */
-+ switch (cqs_set_operation->objs[i].data_type) {
-+ default:
-+ dev_warn(kbdev->dev, "Unreachable data_type=%d", cqs_set_operation->objs[i].data_type);
-+ /* Fallthrough - hint to compiler that there's really only 2 options at present */
-+ case BASEP_CQS_DATA_TYPE_U32:
-+ evt = (u64 *)((u8 *)evt + sizeof(u32));
-+ break;
-+ case BASEP_CQS_DATA_TYPE_U64:
-+ evt = (u64 *)((u8 *)evt + sizeof(u64));
-+ break;
-+ }
-+
-+ /* GPUCORE-28172 RDT to review */
-+
-+ /* Always propagate errors */
-+ *evt = queue->has_error;
-+
-+ kbase_phy_alloc_mapping_put(queue->kctx, mapping);
-+ }
-+ }
-+
-+ kbase_csf_event_signal_notify_gpu(queue->kctx);
-+
-+ kfree(cqs_set_operation->objs);
-+ cqs_set_operation->objs = NULL;
-+}
-+
-+static int kbase_kcpu_cqs_set_operation_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_cqs_set_operation_info *cqs_set_operation_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+ struct base_cqs_set_operation_info *objs;
-+ unsigned int nr_objs = cqs_set_operation_info->nr_objs;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ if (nr_objs > BASEP_KCPU_CQS_MAX_NUM_OBJS)
-+ return -EINVAL;
-+
-+ if (!nr_objs)
-+ return -EINVAL;
-+
-+ objs = kcalloc(nr_objs, sizeof(*objs), GFP_KERNEL);
-+ if (!objs)
-+ return -ENOMEM;
-+
-+ if (copy_from_user(objs, u64_to_user_ptr(cqs_set_operation_info->objs),
-+ nr_objs * sizeof(*objs))) {
-+ kfree(objs);
-+ return -ENOMEM;
-+ }
-+
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_CQS_SET_OPERATION;
-+ current_command->info.cqs_set_operation.nr_objs = nr_objs;
-+ current_command->info.cqs_set_operation.objs = objs;
-+
-+ return 0;
-+}
-+
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+static void kbase_csf_fence_wait_callback(struct fence *fence,
-+ struct fence_cb *cb)
-+#else
-+static void kbase_csf_fence_wait_callback(struct dma_fence *fence,
-+ struct dma_fence_cb *cb)
-+#endif
-+{
-+ struct kbase_kcpu_command_fence_info *fence_info = container_of(cb,
-+ struct kbase_kcpu_command_fence_info, fence_cb);
-+ struct kbase_kcpu_command_queue *kcpu_queue = fence_info->kcpu_queue;
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+
-+ KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, FENCE_WAIT_END, kcpu_queue,
-+ fence->context, fence->seqno);
-+
-+ /* Resume kcpu command queue processing. */
-+ queue_work(kctx->csf.kcpu_queues.wq, &kcpu_queue->work);
-+}
-+
-+static void kbase_kcpu_fence_wait_cancel(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct kbase_kcpu_command_fence_info *fence_info)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ if (WARN_ON(!fence_info->fence))
-+ return;
-+
-+ if (kcpu_queue->fence_wait_processed) {
-+ bool removed = dma_fence_remove_callback(fence_info->fence,
-+ &fence_info->fence_cb);
-+
-+ if (removed)
-+ KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, FENCE_WAIT_END,
-+ kcpu_queue, fence_info->fence->context,
-+ fence_info->fence->seqno);
-+ }
-+
-+ /* Release the reference which is kept by the kcpu_queue */
-+ kbase_fence_put(fence_info->fence);
-+ kcpu_queue->fence_wait_processed = false;
-+
-+ fence_info->fence = NULL;
-+}
-+
-+/**
-+ * kbase_kcpu_fence_wait_process() - Process the kcpu fence wait command
-+ *
-+ * @kcpu_queue: The queue containing the fence wait command
-+ * @fence_info: Reference to a fence for which the command is waiting
-+ *
-+ * Return: 0 if fence wait is blocked, 1 if it is unblocked, negative error if
-+ * an error has occurred and fence should no longer be waited on.
-+ */
-+static int kbase_kcpu_fence_wait_process(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct kbase_kcpu_command_fence_info *fence_info)
-+{
-+ int fence_status = 0;
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+ struct fence *fence;
-+#else
-+ struct dma_fence *fence;
-+#endif
-+
-+ lockdep_assert_held(&kcpu_queue->kctx->csf.kcpu_queues.lock);
-+
-+ if (WARN_ON(!fence_info->fence))
-+ return -EINVAL;
-+
-+ fence = fence_info->fence;
-+
-+ if (kcpu_queue->fence_wait_processed) {
-+ fence_status = dma_fence_get_status(fence);
-+ } else {
-+ int cb_err = dma_fence_add_callback(fence,
-+ &fence_info->fence_cb,
-+ kbase_csf_fence_wait_callback);
-+
-+ KBASE_KTRACE_ADD_CSF_KCPU(kcpu_queue->kctx->kbdev,
-+ FENCE_WAIT_START, kcpu_queue,
-+ fence->context, fence->seqno);
-+ fence_status = cb_err;
-+ if (cb_err == 0)
-+ kcpu_queue->fence_wait_processed = true;
-+ else if (cb_err == -ENOENT)
-+ fence_status = dma_fence_get_status(fence);
-+ }
-+
-+ /*
-+ * At this point fence status can contain 3 types of values:
-+ * - Value 0 to represent that fence in question is not signalled yet
-+ * - Value 1 to represent that fence in question is signalled without
-+ * errors
-+ * - Negative error code to represent that some error has occurred such
-+ * that waiting on it is no longer valid.
-+ */
-+
-+ if (fence_status)
-+ kbase_kcpu_fence_wait_cancel(kcpu_queue, fence_info);
-+
-+ return fence_status;
-+}
-+
-+static int kbase_kcpu_fence_wait_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_fence_info *fence_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+ struct fence *fence_in;
-+#else
-+ struct dma_fence *fence_in;
-+#endif
-+ struct base_fence fence;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ if (copy_from_user(&fence, u64_to_user_ptr(fence_info->fence),
-+ sizeof(fence)))
-+ return -ENOMEM;
-+
-+ fence_in = sync_file_get_fence(fence.basep.fd);
-+
-+ if (!fence_in)
-+ return -ENOENT;
-+
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_FENCE_WAIT;
-+ current_command->info.fence.fence = fence_in;
-+ current_command->info.fence.kcpu_queue = kcpu_queue;
-+
-+ return 0;
-+}
-+
-+static int kbase_kcpu_fence_signal_process(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct kbase_kcpu_command_fence_info *fence_info)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+ int ret;
-+
-+ if (WARN_ON(!fence_info->fence))
-+ return -EINVAL;
-+
-+ ret = dma_fence_signal(fence_info->fence);
-+
-+ if (unlikely(ret < 0)) {
-+ dev_warn(kctx->kbdev->dev,
-+ "fence_signal() failed with %d\n", ret);
-+ }
-+
-+ KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, FENCE_SIGNAL, kcpu_queue,
-+ fence_info->fence->context,
-+ fence_info->fence->seqno);
-+
-+ dma_fence_put(fence_info->fence);
-+ fence_info->fence = NULL;
-+
-+ return ret;
-+}
-+
-+static int kbase_kcpu_fence_signal_prepare(
-+ struct kbase_kcpu_command_queue *kcpu_queue,
-+ struct base_kcpu_command_fence_info *fence_info,
-+ struct kbase_kcpu_command *current_command)
-+{
-+ struct kbase_context *const kctx = kcpu_queue->kctx;
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+ struct fence *fence_out;
-+#else
-+ struct dma_fence *fence_out;
-+#endif
-+ struct base_fence fence;
-+ struct sync_file *sync_file;
-+ int ret = 0;
-+ int fd;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ if (copy_from_user(&fence, u64_to_user_ptr(fence_info->fence),
-+ sizeof(fence)))
-+ return -EFAULT;
-+
-+ fence_out = kzalloc(sizeof(*fence_out), GFP_KERNEL);
-+ if (!fence_out)
-+ return -ENOMEM;
-+
-+ dma_fence_init(fence_out,
-+ &kbase_fence_ops,
-+ &kbase_csf_fence_lock,
-+ kcpu_queue->fence_context,
-+ ++kcpu_queue->fence_seqno);
-+
-+#if (KERNEL_VERSION(4, 9, 67) >= LINUX_VERSION_CODE)
-+ /* Take an extra reference to the fence on behalf of the sync file.
-+ * This is only needded on older kernels where sync_file_create()
-+ * does not take its own reference. This was changed in v4.9.68
-+ * where sync_file_create() now takes its own reference.
-+ */
-+ dma_fence_get(fence_out);
-+#endif
-+
-+ /* create a sync_file fd representing the fence */
-+ sync_file = sync_file_create(fence_out);
-+ if (!sync_file) {
-+#if (KERNEL_VERSION(4, 9, 67) >= LINUX_VERSION_CODE)
-+ dma_fence_put(fence_out);
-+#endif
-+ ret = -ENOMEM;
-+ goto file_create_fail;
-+ }
-+
-+ fd = get_unused_fd_flags(O_CLOEXEC);
-+ if (fd < 0) {
-+ ret = fd;
-+ goto fd_flags_fail;
-+ }
-+
-+ fd_install(fd, sync_file->file);
-+
-+ fence.basep.fd = fd;
-+
-+ current_command->type = BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL;
-+ current_command->info.fence.fence = fence_out;
-+
-+ if (copy_to_user(u64_to_user_ptr(fence_info->fence), &fence,
-+ sizeof(fence))) {
-+ ret = -EFAULT;
-+ goto fd_flags_fail;
-+ }
-+
-+ return 0;
-+
-+fd_flags_fail:
-+ fput(sync_file->file);
-+file_create_fail:
-+ dma_fence_put(fence_out);
-+
-+ return ret;
-+}
-+#endif /* CONFIG_SYNC_FILE */
-+
-+static void kcpu_queue_process_worker(struct work_struct *data)
-+{
-+ struct kbase_kcpu_command_queue *queue = container_of(data,
-+ struct kbase_kcpu_command_queue, work);
-+
-+ mutex_lock(&queue->kctx->csf.kcpu_queues.lock);
-+
-+ kcpu_queue_process(queue, false);
-+
-+ mutex_unlock(&queue->kctx->csf.kcpu_queues.lock);
-+}
-+
-+static int delete_queue(struct kbase_context *kctx, u32 id)
-+{
-+ int err = 0;
-+
-+ mutex_lock(&kctx->csf.kcpu_queues.lock);
-+
-+ if ((id < KBASEP_MAX_KCPU_QUEUES) && kctx->csf.kcpu_queues.array[id]) {
-+ struct kbase_kcpu_command_queue *queue =
-+ kctx->csf.kcpu_queues.array[id];
-+
-+ KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_QUEUE_DESTROY,
-+ queue, queue->num_pending_cmds, queue->cqs_wait_count);
-+
-+ /* Drain the remaining work for this queue first and go past
-+ * all the waits.
-+ */
-+ kcpu_queue_process(queue, true);
-+
-+ /* All commands should have been processed */
-+ WARN_ON(queue->num_pending_cmds);
-+
-+ /* All CQS wait commands should have been cleaned up */
-+ WARN_ON(queue->cqs_wait_count);
-+
-+ kctx->csf.kcpu_queues.array[id] = NULL;
-+ bitmap_clear(kctx->csf.kcpu_queues.in_use, id, 1);
-+
-+ /* Fire the tracepoint with the mutex held to enforce correct
-+ * ordering with the summary stream.
-+ */
-+ KBASE_TLSTREAM_TL_KBASE_DEL_KCPUQUEUE(kctx->kbdev, queue);
-+
-+ mutex_unlock(&kctx->csf.kcpu_queues.lock);
-+
-+ cancel_work_sync(&queue->work);
-+
-+ kfree(queue);
-+ } else {
-+ dev_warn(kctx->kbdev->dev,
-+ "Attempt to delete a non-existent KCPU queue\n");
-+ mutex_unlock(&kctx->csf.kcpu_queues.lock);
-+ err = -EINVAL;
-+ }
-+ return err;
-+}
-+
-+static void KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_INFO(
-+ struct kbase_device *kbdev,
-+ const struct kbase_kcpu_command_queue *queue,
-+ const struct kbase_kcpu_command_jit_alloc_info *jit_alloc,
-+ int alloc_status)
-+{
-+ u8 i;
-+
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_ALLOC_END(
-+ kbdev, queue);
-+ for (i = 0; i < jit_alloc->count; i++) {
-+ const u8 id = jit_alloc->info[i].id;
-+ const struct kbase_va_region *reg = queue->kctx->jit_alloc[id];
-+ u64 gpu_alloc_addr = 0;
-+ u64 mmu_flags = 0;
-+
-+ if ((alloc_status == 0) && !WARN_ON(!reg) &&
-+ !WARN_ON(reg == KBASE_RESERVED_REG_JIT_ALLOC)) {
-+#ifdef CONFIG_MALI_VECTOR_DUMP
-+ struct tagged_addr phy = {0};
-+#endif /* CONFIG_MALI_VECTOR_DUMP */
-+
-+ gpu_alloc_addr = reg->start_pfn << PAGE_SHIFT;
-+#ifdef CONFIG_MALI_VECTOR_DUMP
-+ mmu_flags = kbase_mmu_create_ate(kbdev,
-+ phy, reg->flags,
-+ MIDGARD_MMU_BOTTOMLEVEL,
-+ queue->kctx->jit_group_id);
-+#endif /* CONFIG_MALI_VECTOR_DUMP */
-+ }
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_ALLOC_END(
-+ kbdev, queue, alloc_status, gpu_alloc_addr, mmu_flags);
-+ }
-+}
-+
-+static void KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_END(
-+ struct kbase_device *kbdev,
-+ const struct kbase_kcpu_command_queue *queue)
-+{
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_ALLOC_END(
-+ kbdev, queue);
-+}
-+
-+static void KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_END(
-+ struct kbase_device *kbdev,
-+ const struct kbase_kcpu_command_queue *queue)
-+{
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_FREE_END(
-+ kbdev, queue);
-+}
-+
-+static void kcpu_queue_process(struct kbase_kcpu_command_queue *queue,
-+ bool ignore_waits)
-+{
-+ struct kbase_device *kbdev = queue->kctx->kbdev;
-+ bool process_next = true;
-+ size_t i;
-+
-+ lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock);
-+
-+ for (i = 0; i != queue->num_pending_cmds; ++i) {
-+ struct kbase_kcpu_command *cmd =
-+ &queue->commands[(u8)(queue->start_offset + i)];
-+ int status;
-+
-+ switch (cmd->type) {
-+ case BASE_KCPU_COMMAND_TYPE_FENCE_WAIT:
-+ if (!queue->command_started) {
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_START(
-+ kbdev, queue);
-+ queue->command_started = true;
-+ }
-+
-+ status = 0;
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
-+ if (ignore_waits) {
-+ kbase_kcpu_fence_wait_cancel(queue,
-+ &cmd->info.fence);
-+ } else {
-+ status = kbase_kcpu_fence_wait_process(queue,
-+ &cmd->info.fence);
-+
-+ if (status == 0)
-+ process_next = false;
-+ else if (status < 0)
-+ queue->has_error = true;
-+ }
-+#else
-+ dev_warn(kbdev->dev,
-+ "unexpected fence wait command found\n");
-+
-+ status = -EINVAL;
-+ queue->has_error = true;
-+#endif
-+
-+ if (process_next) {
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_END(
-+ kbdev, queue, status < 0 ? status : 0);
-+ queue->command_started = false;
-+ }
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL:
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START(
-+ kbdev, queue);
-+
-+ status = 0;
-+
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
-+ status = kbase_kcpu_fence_signal_process(
-+ queue, &cmd->info.fence);
-+
-+ if (status < 0)
-+ queue->has_error = true;
-+#else
-+ dev_warn(kbdev->dev,
-+ "unexpected fence signal command found\n");
-+
-+ status = -EINVAL;
-+ queue->has_error = true;
-+#endif
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END(
-+ kbdev, queue, status);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_CQS_WAIT:
-+ status = kbase_kcpu_cqs_wait_process(kbdev, queue,
-+ &cmd->info.cqs_wait);
-+
-+ if (!status && !ignore_waits) {
-+ process_next = false;
-+ } else {
-+ /* Either all CQS objects were signaled or
-+ * there was an error or the queue itself is
-+ * being deleted.
-+ * In all cases can move to the next command.
-+ * TBD: handle the error
-+ */
-+ cleanup_cqs_wait(queue, &cmd->info.cqs_wait);
-+ }
-+
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_CQS_SET:
-+ kbase_kcpu_cqs_set_process(kbdev, queue,
-+ &cmd->info.cqs_set);
-+
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_CQS_WAIT_OPERATION:
-+ status = kbase_kcpu_cqs_wait_operation_process(kbdev, queue,
-+ &cmd->info.cqs_wait_operation);
-+
-+ if (!status && !ignore_waits) {
-+ process_next = false;
-+ } else {
-+ /* Either all CQS objects were signaled or
-+ * there was an error or the queue itself is
-+ * being deleted.
-+ * In all cases can move to the next command.
-+ * TBD: handle the error
-+ */
-+ cleanup_cqs_wait_operation(queue, &cmd->info.cqs_wait_operation);
-+ }
-+
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_CQS_SET_OPERATION:
-+ kbase_kcpu_cqs_set_operation_process(kbdev, queue,
-+ &cmd->info.cqs_set_operation);
-+
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_ERROR_BARRIER:
-+ /* Clear the queue's error state */
-+ queue->has_error = false;
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER(
-+ kbdev, queue);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_MAP_IMPORT: {
-+ struct kbase_ctx_ext_res_meta *meta = NULL;
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START(
-+ kbdev, queue);
-+
-+ kbase_gpu_vm_lock(queue->kctx);
-+ meta = kbase_sticky_resource_acquire(
-+ queue->kctx, cmd->info.import.gpu_va);
-+ kbase_gpu_vm_unlock(queue->kctx);
-+
-+ if (meta == NULL) {
-+ queue->has_error = true;
-+ dev_warn(kbdev->dev,
-+ "failed to map an external resource\n");
-+ }
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END(
-+ kbdev, queue, meta ? 0 : 1);
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT: {
-+ bool ret;
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_START(
-+ kbdev, queue);
-+
-+ kbase_gpu_vm_lock(queue->kctx);
-+ ret = kbase_sticky_resource_release(
-+ queue->kctx, NULL, cmd->info.import.gpu_va);
-+ kbase_gpu_vm_unlock(queue->kctx);
-+
-+ if (!ret) {
-+ queue->has_error = true;
-+ dev_warn(kbdev->dev,
-+ "failed to release the reference. resource not found\n");
-+ }
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_END(
-+ kbdev, queue, ret ? 0 : 1);
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT_FORCE: {
-+ bool ret;
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_START(
-+ kbdev, queue);
-+
-+ kbase_gpu_vm_lock(queue->kctx);
-+ ret = kbase_sticky_resource_release_force(
-+ queue->kctx, NULL, cmd->info.import.gpu_va);
-+ kbase_gpu_vm_unlock(queue->kctx);
-+
-+ if (!ret) {
-+ queue->has_error = true;
-+ dev_warn(kbdev->dev,
-+ "failed to release the reference. resource not found\n");
-+ }
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_END(
-+ kbdev, queue, ret ? 0 : 1);
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_JIT_ALLOC:
-+ {
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_START(
-+ kbdev, queue);
-+
-+ status = kbase_kcpu_jit_allocate_process(queue, cmd);
-+ if (status == -EAGAIN) {
-+ process_next = false;
-+ } else {
-+ if (status != 0)
-+ queue->has_error = true;
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_INFO(
-+ kbdev, queue, &cmd->info.jit_alloc,
-+ status);
-+
-+ kbase_kcpu_jit_allocate_finish(queue, cmd);
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_END(
-+ kbdev, queue);
-+ }
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_JIT_FREE:
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_START(
-+ kbdev, queue);
-+
-+ status = kbase_kcpu_jit_free_process(queue, cmd);
-+ if (status)
-+ queue->has_error = true;
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_END(
-+ kbdev, queue);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_GROUP_SUSPEND: {
-+ struct kbase_suspend_copy_buffer *sus_buf =
-+ cmd->info.suspend_buf_copy.sus_buf;
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START(
-+ kbdev, queue);
-+
-+ status = kbase_csf_queue_group_suspend_process(
-+ queue->kctx, sus_buf,
-+ cmd->info.suspend_buf_copy.group_handle);
-+ if (status)
-+ queue->has_error = true;
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END(
-+ kbdev, queue, status);
-+
-+ if (!sus_buf->cpu_alloc) {
-+ int i;
-+
-+ for (i = 0; i < sus_buf->nr_pages; i++)
-+ put_page(sus_buf->pages[i]);
-+ } else {
-+ kbase_mem_phy_alloc_kernel_unmapped(
-+ sus_buf->cpu_alloc);
-+ kbase_mem_phy_alloc_put(sus_buf->cpu_alloc);
-+ }
-+
-+ kfree(sus_buf->pages);
-+ kfree(sus_buf);
-+ break;
-+ }
-+#if MALI_UNIT_TEST
-+ case BASE_KCPU_COMMAND_TYPE_SAMPLE_TIME: {
-+ u64 time = ktime_get_raw_ns();
-+ void *target_page = kmap(*cmd->info.sample_time.page);
-+
-+ if (target_page) {
-+ memcpy(target_page +
-+ cmd->info.sample_time.page_offset,
-+ &time, sizeof(time));
-+ kunmap(*cmd->info.sample_time.page);
-+ } else {
-+ dev_warn(kbdev->dev,
-+ "Could not kmap target page\n");
-+ queue->has_error = true;
-+ }
-+ put_page(*cmd->info.sample_time.page);
-+ kfree(cmd->info.sample_time.page);
-+ break;
-+ }
-+#endif /* MALI_UNIT_TEST */
-+ default:
-+ dev_warn(kbdev->dev,
-+ "Unrecognized command type\n");
-+ break;
-+ } /* switch */
-+
-+ /*TBD: error handling */
-+
-+ if (!process_next)
-+ break;
-+ }
-+
-+ if (i > 0) {
-+ queue->start_offset += i;
-+ queue->num_pending_cmds -= i;
-+
-+ /* If an attempt to enqueue commands failed then we must raise
-+ * an event in case the client wants to retry now that there is
-+ * free space in the buffer.
-+ */
-+ if (queue->enqueue_failed) {
-+ queue->enqueue_failed = false;
-+ kbase_csf_event_signal_cpu_only(queue->kctx);
-+ }
-+ }
-+}
-+
-+static size_t kcpu_queue_get_space(struct kbase_kcpu_command_queue *queue)
-+{
-+ return KBASEP_KCPU_QUEUE_SIZE - queue->num_pending_cmds;
-+}
-+
-+static void KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_COMMAND(
-+ const struct kbase_kcpu_command_queue *queue,
-+ const struct kbase_kcpu_command *cmd)
-+{
-+ struct kbase_device *kbdev = queue->kctx->kbdev;
-+
-+ switch (cmd->type) {
-+ case BASE_KCPU_COMMAND_TYPE_FENCE_WAIT:
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT(
-+ kbdev, queue, cmd->info.fence.fence);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL:
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_SIGNAL(
-+ kbdev, queue, cmd->info.fence.fence);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_CQS_WAIT:
-+ {
-+ const struct base_cqs_wait_info *waits =
-+ cmd->info.cqs_wait.objs;
-+ u32 inherit_err_flags = cmd->info.cqs_wait.inherit_err_flags;
-+ unsigned int i;
-+
-+ for (i = 0; i < cmd->info.cqs_wait.nr_objs; i++) {
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT(
-+ kbdev, queue, waits[i].addr, waits[i].val,
-+ (inherit_err_flags & ((u32)1 << i)) ? 1 : 0);
-+ }
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_CQS_SET:
-+ {
-+ const struct base_cqs_set *sets = cmd->info.cqs_set.objs;
-+ unsigned int i;
-+
-+ for (i = 0; i < cmd->info.cqs_set.nr_objs; i++) {
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET(
-+ kbdev, queue, sets[i].addr);
-+ }
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_CQS_WAIT_OPERATION:
-+ {
-+ /* GPUCORE-28172 RDT to review */
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_CQS_SET_OPERATION:
-+ {
-+ /* GPUCORE-28172 RDT to review */
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_ERROR_BARRIER:
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER(kbdev,
-+ queue);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_MAP_IMPORT:
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT(
-+ kbdev, queue, cmd->info.import.gpu_va);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT:
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT(
-+ kbdev, queue, cmd->info.import.gpu_va);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT_FORCE:
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE(
-+ kbdev, queue, cmd->info.import.gpu_va);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_JIT_ALLOC:
-+ {
-+ u8 i;
-+
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC(
-+ kbdev, queue);
-+ for (i = 0; i < cmd->info.jit_alloc.count; i++) {
-+ const struct base_jit_alloc_info *info =
-+ &cmd->info.jit_alloc.info[i];
-+
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_ALLOC(
-+ kbdev, queue, info->gpu_alloc_addr,
-+ info->va_pages, info->commit_pages,
-+ info->extension, info->id, info->bin_id,
-+ info->max_allocations, info->flags,
-+ info->usage_id);
-+ }
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_ALLOC(
-+ kbdev, queue);
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_JIT_FREE:
-+ {
-+ u8 i;
-+
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_FREE(
-+ kbdev, queue);
-+ for (i = 0; i < cmd->info.jit_free.count; i++) {
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_FREE(
-+ kbdev, queue, cmd->info.jit_free.ids[i]);
-+ }
-+ KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_FREE(
-+ kbdev, queue);
-+ break;
-+ }
-+ case BASE_KCPU_COMMAND_TYPE_GROUP_SUSPEND:
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND(
-+ kbdev, queue, cmd->info.suspend_buf_copy.sus_buf,
-+ cmd->info.suspend_buf_copy.group_handle);
-+ break;
-+#if MALI_UNIT_TEST
-+ case BASE_KCPU_COMMAND_TYPE_SAMPLE_TIME:
-+ /*
-+ * This is test-only KCPU command, no need to have a timeline
-+ * entry
-+ */
-+ break;
-+#endif /* MALI_UNIT_TEST */
-+ }
-+}
-+
-+int kbase_csf_kcpu_queue_enqueue(struct kbase_context *kctx,
-+ struct kbase_ioctl_kcpu_queue_enqueue *enq)
-+{
-+ struct kbase_kcpu_command_queue *queue = NULL;
-+ void __user *user_cmds = u64_to_user_ptr(enq->addr);
-+ int ret = 0;
-+ u32 i;
-+
-+ /* The offset to the first command that is being processed or yet to
-+ * be processed is of u8 type, so the number of commands inside the
-+ * queue cannot be more than 256.
-+ */
-+ BUILD_BUG_ON(KBASEP_KCPU_QUEUE_SIZE > 256);
-+
-+ /* Whilst the backend interface allows enqueueing multiple commands in
-+ * a single operation, the Base interface does not expose any mechanism
-+ * to do so. And also right now the handling is missing for the case
-+ * where multiple commands are submitted and the enqueue of one of the
-+ * command in the set fails after successfully enqueuing other commands
-+ * in the set.
-+ */
-+ if (enq->nr_commands != 1) {
-+ dev_err(kctx->kbdev->dev,
-+ "More than one commands enqueued\n");
-+ return -EINVAL;
-+ }
-+
-+ mutex_lock(&kctx->csf.kcpu_queues.lock);
-+
-+ if (!kctx->csf.kcpu_queues.array[enq->id]) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ queue = kctx->csf.kcpu_queues.array[enq->id];
-+
-+ if (kcpu_queue_get_space(queue) < enq->nr_commands) {
-+ ret = -EBUSY;
-+ queue->enqueue_failed = true;
-+ goto out;
-+ }
-+
-+ /* Copy all command's info to the command buffer.
-+ * Note: it would be more efficient to process all commands in-line
-+ * until we encounter an unresolved CQS_ / FENCE_WAIT, however, the
-+ * interface allows multiple commands to be enqueued so we must account
-+ * for the possibility to roll back.
-+ */
-+
-+ for (i = 0; (i != enq->nr_commands) && !ret; ++i, ++kctx->csf.kcpu_queues.num_cmds) {
-+ struct kbase_kcpu_command *kcpu_cmd =
-+ &queue->commands[(u8)(queue->start_offset + queue->num_pending_cmds + i)];
-+ struct base_kcpu_command command;
-+ unsigned int j;
-+
-+ if (copy_from_user(&command, user_cmds, sizeof(command))) {
-+ ret = -EFAULT;
-+ goto out;
-+ }
-+
-+ user_cmds = (void __user *)((uintptr_t)user_cmds +
-+ sizeof(struct base_kcpu_command));
-+
-+ for (j = 0; j < sizeof(command.padding); j++) {
-+ if (command.padding[j] != 0) {
-+ dev_dbg(kctx->kbdev->dev,
-+ "base_kcpu_command padding not 0\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ }
-+
-+ kcpu_cmd->enqueue_ts = kctx->csf.kcpu_queues.num_cmds;
-+ switch (command.type) {
-+ case BASE_KCPU_COMMAND_TYPE_FENCE_WAIT:
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
-+ ret = kbase_kcpu_fence_wait_prepare(queue,
-+ &command.info.fence, kcpu_cmd);
-+#else
-+ ret = -EINVAL;
-+ dev_warn(kctx->kbdev->dev, "fence wait command unsupported\n");
-+#endif
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL:
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
-+ ret = kbase_kcpu_fence_signal_prepare(queue,
-+ &command.info.fence, kcpu_cmd);
-+#else
-+ ret = -EINVAL;
-+ dev_warn(kctx->kbdev->dev, "fence signal command unsupported\n");
-+#endif
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_CQS_WAIT:
-+ ret = kbase_kcpu_cqs_wait_prepare(queue,
-+ &command.info.cqs_wait, kcpu_cmd);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_CQS_SET:
-+ ret = kbase_kcpu_cqs_set_prepare(queue,
-+ &command.info.cqs_set, kcpu_cmd);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_CQS_WAIT_OPERATION:
-+ ret = kbase_kcpu_cqs_wait_operation_prepare(queue,
-+ &command.info.cqs_wait_operation, kcpu_cmd);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_CQS_SET_OPERATION:
-+ ret = kbase_kcpu_cqs_set_operation_prepare(queue,
-+ &command.info.cqs_set_operation, kcpu_cmd);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_ERROR_BARRIER:
-+ kcpu_cmd->type = BASE_KCPU_COMMAND_TYPE_ERROR_BARRIER;
-+ ret = 0;
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_MAP_IMPORT:
-+ ret = kbase_kcpu_map_import_prepare(queue,
-+ &command.info.import, kcpu_cmd);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT:
-+ ret = kbase_kcpu_unmap_import_prepare(queue,
-+ &command.info.import, kcpu_cmd);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT_FORCE:
-+ ret = kbase_kcpu_unmap_import_force_prepare(queue,
-+ &command.info.import, kcpu_cmd);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_JIT_ALLOC:
-+ ret = kbase_kcpu_jit_allocate_prepare(queue,
-+ &command.info.jit_alloc, kcpu_cmd);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_JIT_FREE:
-+ ret = kbase_kcpu_jit_free_prepare(queue,
-+ &command.info.jit_free, kcpu_cmd);
-+ break;
-+ case BASE_KCPU_COMMAND_TYPE_GROUP_SUSPEND:
-+ ret = kbase_csf_queue_group_suspend_prepare(queue,
-+ &command.info.suspend_buf_copy,
-+ kcpu_cmd);
-+ break;
-+#if MALI_UNIT_TEST
-+ case BASE_KCPU_COMMAND_TYPE_SAMPLE_TIME: {
-+ int const page_cnt = 1;
-+
-+ kcpu_cmd->type = BASE_KCPU_COMMAND_TYPE_SAMPLE_TIME;
-+ kcpu_cmd->info.sample_time.page_addr =
-+ command.info.sample_time.time & PAGE_MASK;
-+ kcpu_cmd->info.sample_time.page_offset =
-+ command.info.sample_time.time & ~PAGE_MASK;
-+ kcpu_cmd->info.sample_time.page = kcalloc(
-+ page_cnt, sizeof(struct page *), GFP_KERNEL);
-+ if (!kcpu_cmd->info.sample_time.page) {
-+ ret = -ENOMEM;
-+ } else {
-+ int pinned_pages = get_user_pages_fast(
-+ kcpu_cmd->info.sample_time.page_addr,
-+ page_cnt, 1,
-+ kcpu_cmd->info.sample_time.page);
-+
-+ if (pinned_pages < 0) {
-+ ret = pinned_pages;
-+ kfree(kcpu_cmd->info.sample_time.page);
-+ } else if (pinned_pages != page_cnt) {
-+ ret = -EINVAL;
-+ kfree(kcpu_cmd->info.sample_time.page);
-+ }
-+ }
-+
-+ break;
-+ }
-+#endif /* MALI_UNIT_TEST */
-+ default:
-+ dev_warn(queue->kctx->kbdev->dev,
-+ "Unknown command type %u\n", command.type);
-+ ret = -EINVAL;
-+ break;
-+ }
-+ }
-+
-+ if (!ret) {
-+ /* We only instrument the enqueues after all commands have been
-+ * successfully enqueued, as if we do them during the enqueue
-+ * and there is an error, we won't be able to roll them back
-+ * like is done for the command enqueues themselves.
-+ */
-+ for (i = 0; i != enq->nr_commands; ++i) {
-+ u8 cmd_idx = (u8)(queue->start_offset + queue->num_pending_cmds + i);
-+
-+ KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_COMMAND(
-+ queue, &queue->commands[cmd_idx]);
-+ }
-+
-+ queue->num_pending_cmds += enq->nr_commands;
-+ kcpu_queue_process(queue, false);
-+ } else {
-+ /* Roll back the number of enqueued commands */
-+ kctx->csf.kcpu_queues.num_cmds -= i;
-+ }
-+
-+out:
-+ mutex_unlock(&kctx->csf.kcpu_queues.lock);
-+
-+ return ret;
-+}
-+
-+int kbase_csf_kcpu_queue_context_init(struct kbase_context *kctx)
-+{
-+ int idx;
-+
-+ bitmap_zero(kctx->csf.kcpu_queues.in_use, KBASEP_MAX_KCPU_QUEUES);
-+
-+ for (idx = 0; idx < KBASEP_MAX_KCPU_QUEUES; ++idx)
-+ kctx->csf.kcpu_queues.array[idx] = NULL;
-+
-+ kctx->csf.kcpu_queues.wq = alloc_workqueue("mali_kbase_csf_kcpu",
-+ WQ_UNBOUND | WQ_HIGHPRI, 0);
-+ if (!kctx->csf.kcpu_queues.wq)
-+ return -ENOMEM;
-+
-+ mutex_init(&kctx->csf.kcpu_queues.lock);
-+
-+ kctx->csf.kcpu_queues.num_cmds = 0;
-+
-+ return 0;
-+}
-+
-+void kbase_csf_kcpu_queue_context_term(struct kbase_context *kctx)
-+{
-+ while (!bitmap_empty(kctx->csf.kcpu_queues.in_use,
-+ KBASEP_MAX_KCPU_QUEUES)) {
-+ int id = find_first_bit(kctx->csf.kcpu_queues.in_use,
-+ KBASEP_MAX_KCPU_QUEUES);
-+
-+ if (WARN_ON(!kctx->csf.kcpu_queues.array[id]))
-+ clear_bit(id, kctx->csf.kcpu_queues.in_use);
-+ else
-+ (void)delete_queue(kctx, id);
-+ }
-+
-+ destroy_workqueue(kctx->csf.kcpu_queues.wq);
-+ mutex_destroy(&kctx->csf.kcpu_queues.lock);
-+}
-+
-+int kbase_csf_kcpu_queue_delete(struct kbase_context *kctx,
-+ struct kbase_ioctl_kcpu_queue_delete *del)
-+{
-+ return delete_queue(kctx, (u32)del->id);
-+}
-+
-+int kbase_csf_kcpu_queue_new(struct kbase_context *kctx,
-+ struct kbase_ioctl_kcpu_queue_new *newq)
-+{
-+ struct kbase_kcpu_command_queue *queue;
-+ int idx;
-+ int ret = 0;
-+
-+ /* The queue id is of u8 type and we use the index of the kcpu_queues
-+ * array as an id, so the number of elements in the array can't be
-+ * more than 256.
-+ */
-+ BUILD_BUG_ON(KBASEP_MAX_KCPU_QUEUES > 256);
-+
-+ mutex_lock(&kctx->csf.kcpu_queues.lock);
-+
-+ idx = find_first_zero_bit(kctx->csf.kcpu_queues.in_use,
-+ KBASEP_MAX_KCPU_QUEUES);
-+ if (idx >= (int)KBASEP_MAX_KCPU_QUEUES) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+
-+ if (WARN_ON(kctx->csf.kcpu_queues.array[idx])) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ queue = kzalloc(sizeof(*queue), GFP_KERNEL);
-+
-+ if (!queue) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+
-+ bitmap_set(kctx->csf.kcpu_queues.in_use, idx, 1);
-+ kctx->csf.kcpu_queues.array[idx] = queue;
-+ queue->kctx = kctx;
-+ queue->start_offset = 0;
-+ queue->num_pending_cmds = 0;
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
-+ queue->fence_context = dma_fence_context_alloc(1);
-+ queue->fence_seqno = 0;
-+ queue->fence_wait_processed = false;
-+#endif
-+ queue->enqueue_failed = false;
-+ queue->command_started = false;
-+ INIT_LIST_HEAD(&queue->jit_blocked);
-+ queue->has_error = false;
-+ INIT_WORK(&queue->work, kcpu_queue_process_worker);
-+ queue->id = idx;
-+
-+ newq->id = idx;
-+
-+ /* Fire the tracepoint with the mutex held to enforce correct ordering
-+ * with the summary stream.
-+ */
-+ KBASE_TLSTREAM_TL_KBASE_NEW_KCPUQUEUE(
-+ kctx->kbdev, queue, kctx->id, queue->num_pending_cmds);
-+
-+ KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_QUEUE_NEW, queue,
-+ queue->fence_context, 0);
-+out:
-+ mutex_unlock(&kctx->csf.kcpu_queues.lock);
-+
-+ return ret;
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.h
-new file mode 100644
-index 0000000..2f6da55
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu.h
-@@ -0,0 +1,356 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_KCPU_H_
-+#define _KBASE_CSF_KCPU_H_
-+
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+#include <linux/fence.h>
-+#else
-+#include <linux/dma-fence.h>
-+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) */
-+
-+/* The maximum number of KCPU commands in flight, enqueueing more commands
-+ * than this value shall block.
-+ */
-+#define KBASEP_KCPU_QUEUE_SIZE ((size_t)256)
-+
-+/**
-+ * struct kbase_kcpu_command_import_info - Structure which holds information
-+ * about the buffer to be imported
-+ *
-+ * @gpu_va: Address of the buffer to be imported.
-+ */
-+struct kbase_kcpu_command_import_info {
-+ u64 gpu_va;
-+};
-+
-+/**
-+ * struct kbase_kcpu_command_fence_info - Structure which holds information
-+ * about the fence object enqueued in the kcpu command queue
-+ *
-+ * @fence_cb: Fence callback
-+ * @fence: Fence
-+ * @kcpu_queue: kcpu command queue
-+ */
-+struct kbase_kcpu_command_fence_info {
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+ struct fence_cb fence_cb;
-+ struct fence *fence;
-+#else
-+ struct dma_fence_cb fence_cb;
-+ struct dma_fence *fence;
-+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) */
-+ struct kbase_kcpu_command_queue *kcpu_queue;
-+};
-+
-+/**
-+ * struct kbase_kcpu_command_cqs_set_info - Structure which holds information
-+ * about CQS objects for the kcpu CQS set command
-+ *
-+ * @objs: Array of structures which define CQS objects to be used by
-+ * the kcpu command.
-+ * @nr_objs: Number of CQS objects in the array.
-+ */
-+struct kbase_kcpu_command_cqs_set_info {
-+ struct base_cqs_set *objs;
-+ unsigned int nr_objs;
-+};
-+
-+/**
-+ * struct kbase_kcpu_command_cqs_wait_info - Structure which holds information
-+ * about CQS objects for the kcpu CQS wait command
-+ *
-+ * @objs: Array of structures which define CQS objects to be used by
-+ * the kcpu command.
-+ * @signaled: Bit array used to report the status of the CQS wait objects.
-+ * 1 is signaled, 0 otherwise.
-+ * @nr_objs: Number of CQS objects in the array.
-+ * @inherit_err_flags: Bit-pattern for the CQSs in the array who's error field
-+ * to be served as the source for importing into the
-+ * queue's error-state.
-+ */
-+struct kbase_kcpu_command_cqs_wait_info {
-+ struct base_cqs_wait_info *objs;
-+ unsigned long *signaled;
-+ unsigned int nr_objs;
-+ u32 inherit_err_flags;
-+};
-+
-+/**
-+ * struct kbase_kcpu_command_cqs_set_operation_info - Structure which holds information
-+ * about CQS objects for the kcpu CQS timeline set command
-+ *
-+ * @objs: Array of structures which define CQS timeline objects to be used by
-+ * the kcpu command.
-+ * @nr_objs: Number of CQS objects in the array.
-+ */
-+struct kbase_kcpu_command_cqs_set_operation_info {
-+ struct base_cqs_set_operation_info *objs;
-+ unsigned int nr_objs;
-+};
-+
-+/**
-+ * struct kbase_kcpu_command_cqs_wait_operation_info - Structure which holds information
-+ * about CQS objects for the kcpu CQS timeline wait command
-+ *
-+ * @objs: Array of structures which define CQS timeline objects to be used by
-+ * the kcpu command.
-+ * @signaled: Bit array used to report the status of the CQS wait objects.
-+ * 1 is signaled, 0 otherwise.
-+ * @nr_objs: Number of CQS objects in the array.
-+ */
-+struct kbase_kcpu_command_cqs_wait_operation_info {
-+ struct base_cqs_wait_operation_info *objs;
-+ unsigned long *signaled;
-+ unsigned int nr_objs;
-+ u32 inherit_err_flags;
-+};
-+
-+/**
-+ * struct kbase_kcpu_command_jit_alloc_info - Structure which holds information
-+ * needed for the kcpu command for jit allocations
-+ *
-+ * @node: Used to keep track of all JIT free/alloc commands in submission
-+ * order. This must be located in the front of this struct to
-+ * match that of kbase_kcpu_command_jit_free_info.
-+ * @info: Array of objects of the struct base_jit_alloc_info type which
-+ * specify jit allocations to be made by the kcpu command.
-+ * @count: Number of jit alloc objects in the array.
-+ * @blocked: Whether this allocation has been put into the pending list to
-+ * be retried later.
-+ */
-+struct kbase_kcpu_command_jit_alloc_info {
-+ struct list_head node;
-+ struct base_jit_alloc_info *info;
-+ u8 count;
-+ bool blocked;
-+};
-+
-+/**
-+ * struct kbase_kcpu_command_jit_free_info - Structure which holds information
-+ * needed for the kcpu jit free command
-+ *
-+ * @node: Used to keep track of all JIT free/alloc commands in submission
-+ * order. This must be located in the front of this struct to
-+ * match that of kbase_kcpu_command_jit_alloc_info.
-+ * @ids: Array of identifiers of jit allocations which are to be freed
-+ * by the kcpu command.
-+ * @count: Number of elements in the array.
-+ */
-+struct kbase_kcpu_command_jit_free_info {
-+ struct list_head node;
-+ u8 *ids;
-+ u8 count;
-+};
-+
-+/**
-+ * struct kbase_suspend_copy_buffer - information about the suspend buffer
-+ * to be copied.
-+ *
-+ * @size: size of the suspend buffer in bytes.
-+ * @pages: pointer to an array of pointers to the pages which contain
-+ * the user buffer.
-+ * @nr_pages: number of pages.
-+ * @offset: offset into the pages
-+ * @cpu_alloc: Reference to physical pages of suspend buffer allocation.
-+ */
-+struct kbase_suspend_copy_buffer {
-+ size_t size;
-+ struct page **pages;
-+ int nr_pages;
-+ size_t offset;
-+ struct kbase_mem_phy_alloc *cpu_alloc;
-+};
-+
-+/**
-+ * struct base_kcpu_command_group_suspend - structure which contains
-+ * suspend buffer data captured for a suspended queue group.
-+ *
-+ * @sus_buf: Pointer to the structure which contains details of the
-+ * user buffer and its kernel pinned pages.
-+ * @group_handle: Handle to the mapping of CSG.
-+ */
-+struct kbase_kcpu_command_group_suspend_info {
-+ struct kbase_suspend_copy_buffer *sus_buf;
-+ u8 group_handle;
-+};
-+
-+#if MALI_UNIT_TEST
-+struct kbase_kcpu_command_sample_time_info {
-+ u64 page_addr;
-+ u64 page_offset;
-+ struct page **page;
-+};
-+#endif /* MALI_UNIT_TEST */
-+
-+/**
-+ * struct kbase_cpu_command - Command which is to be part of the kernel
-+ * command queue
-+ *
-+ * @type: Type of the command.
-+ * @enqueue_ts: Denotes the relative time of enqueueing, a smaller value
-+ * indicates that it has been enqueued earlier.
-+ * @info: Structure which holds information about the command
-+ * dependent on the command type.
-+ * @info.fence: Fence
-+ * @info.cqs_wait: CQS wait
-+ * @info.cqs_set: CQS set
-+ * @info.import: import
-+ * @info.jit_alloc: jit allocation
-+ * @info.jit_free: jit deallocation
-+ * @info.suspend_buf_copy: suspend buffer copy
-+ * @info.sample_time: sample time
-+ */
-+struct kbase_kcpu_command {
-+ enum base_kcpu_command_type type;
-+ u64 enqueue_ts;
-+ union {
-+ struct kbase_kcpu_command_fence_info fence;
-+ struct kbase_kcpu_command_cqs_wait_info cqs_wait;
-+ struct kbase_kcpu_command_cqs_set_info cqs_set;
-+ struct kbase_kcpu_command_cqs_wait_operation_info cqs_wait_operation;
-+ struct kbase_kcpu_command_cqs_set_operation_info cqs_set_operation;
-+ struct kbase_kcpu_command_import_info import;
-+ struct kbase_kcpu_command_jit_alloc_info jit_alloc;
-+ struct kbase_kcpu_command_jit_free_info jit_free;
-+ struct kbase_kcpu_command_group_suspend_info suspend_buf_copy;
-+#if MALI_UNIT_TEST
-+ struct kbase_kcpu_command_sample_time_info sample_time;
-+#endif /* MALI_UNIT_TEST */
-+ } info;
-+};
-+
-+/**
-+ * struct kbase_kcpu_command_queue - a command queue executed by the kernel
-+ *
-+ * @kctx: The context to which this command queue belongs.
-+ * @commands: Array of commands which have been successfully
-+ * enqueued to this command queue.
-+ * @work: struct work_struct which contains a pointer to
-+ * the function which handles processing of kcpu
-+ * commands enqueued into a kcpu command queue;
-+ * part of kernel API for processing workqueues
-+ * @start_offset: Index of the command to be executed next
-+ * @id: KCPU command queue ID.
-+ * @num_pending_cmds: The number of commands enqueued but not yet
-+ * executed or pending
-+ * @cqs_wait_count: Tracks the number of CQS wait commands enqueued
-+ * @fence_context: The dma-buf fence context number for this kcpu
-+ * queue. A unique context number is allocated for
-+ * each kcpu queue.
-+ * @fence_seqno: The dma-buf fence sequence number for the fence
-+ * that is returned on the enqueue of fence signal
-+ * command. This is increased every time the
-+ * fence signal command is queued.
-+ * @fence_wait_processed: Used to avoid reprocessing of the fence wait
-+ * command which has blocked the processing of
-+ * commands that follow it.
-+ * @enqueue_failed: Indicates that no space has become available in
-+ * the buffer since an enqueue operation failed
-+ * because of insufficient free space.
-+ * @command_started: Indicates that the command at the front of the
-+ * queue has been started in a previous queue
-+ * process, but was not completed due to some
-+ * unmet dependencies. Ensures that instrumentation
-+ * of the execution start of these commands is only
-+ * fired exactly once.
-+ * @has_error: Indicates that the kcpu queue is in error mode
-+ * or without errors since last cleaned.
-+ * @jit_blocked: Used to keep track of command queues blocked
-+ * by a pending JIT allocation command.
-+ */
-+struct kbase_kcpu_command_queue {
-+ struct kbase_context *kctx;
-+ struct kbase_kcpu_command commands[KBASEP_KCPU_QUEUE_SIZE];
-+ struct work_struct work;
-+ u8 start_offset;
-+ u8 id;
-+ u16 num_pending_cmds;
-+ u32 cqs_wait_count;
-+ u64 fence_context;
-+ unsigned int fence_seqno;
-+ bool fence_wait_processed;
-+ bool enqueue_failed;
-+ bool command_started;
-+ struct list_head jit_blocked;
-+ bool has_error;
-+};
-+
-+/**
-+ * kbase_csf_kcpu_queue_new - Create new KCPU command queue.
-+ *
-+ * @kctx: Pointer to the kbase context within which the KCPU command
-+ * queue will be created.
-+ * @newq: Pointer to the structure which contains information about
-+ * the new KCPU command queue to be created.
-+ */
-+int kbase_csf_kcpu_queue_new(struct kbase_context *kctx,
-+ struct kbase_ioctl_kcpu_queue_new *newq);
-+
-+/**
-+ * kbase_csf_kcpu_queue_delete - Delete KCPU command queue.
-+ *
-+ * Return: 0 if successful, -EINVAL if the queue ID is invalid.
-+ *
-+ * @kctx: Pointer to the kbase context from which the KCPU command
-+ * queue is to be deleted.
-+ * @del: Pointer to the structure which specifies the KCPU command
-+ * queue to be deleted.
-+ */
-+int kbase_csf_kcpu_queue_delete(struct kbase_context *kctx,
-+ struct kbase_ioctl_kcpu_queue_delete *del);
-+
-+/**
-+ * kbase_csf_kcpu_queue_enqueue - Enqueue a KCPU command into a KCPU command
-+ * queue.
-+ *
-+ * @kctx: Pointer to the kbase context within which the KCPU command
-+ * is to be enqueued into the KCPU command queue.
-+ * @enq: Pointer to the structure which specifies the KCPU command
-+ * as well as the KCPU command queue into which the command
-+ * is to be enqueued.
-+ */
-+int kbase_csf_kcpu_queue_enqueue(struct kbase_context *kctx,
-+ struct kbase_ioctl_kcpu_queue_enqueue *enq);
-+
-+/**
-+ * kbase_csf_kcpu_queue_context_init - Initialize the kernel CPU queues context
-+ * for a GPU address space
-+ *
-+ * @kctx: Pointer to the kbase context being initialized.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+int kbase_csf_kcpu_queue_context_init(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_kcpu_queue_context_term - Terminate the kernel CPU queues context
-+ * for a GPU address space
-+ *
-+ * This function deletes any kernel CPU queues that weren't deleted before
-+ * context termination.
-+ *
-+ * @kctx: Pointer to the kbase context being terminated.
-+ */
-+void kbase_csf_kcpu_queue_context_term(struct kbase_context *kctx);
-+
-+#endif /* _KBASE_CSF_KCPU_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu_debugfs.c
-new file mode 100644
-index 0000000..0a2cde0
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu_debugfs.c
-@@ -0,0 +1,197 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_csf_kcpu_debugfs.h"
-+#include <mali_kbase.h>
-+#include <linux/seq_file.h>
-+
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
-+#include "mali_kbase_sync.h"
-+#endif
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+
-+/**
-+ * kbasep_csf_kcpu_debugfs_print_queue() - Print additional info for KCPU
-+ * queues blocked on CQS wait commands.
-+ *
-+ * @file: The seq_file to print to
-+ * @kctx: The context of the KCPU queue
-+ * @waits: Pointer to the KCPU CQS wait command info
-+ */
-+static void kbasep_csf_kcpu_debugfs_print_cqs_waits(struct seq_file *file,
-+ struct kbase_context *kctx,
-+ struct kbase_kcpu_command_cqs_wait_info *waits)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < waits->nr_objs; i++) {
-+ struct kbase_vmap_struct *mapping;
-+ u32 val;
-+ char const *msg;
-+ u32 *const cpu_ptr = (u32 *)kbase_phy_alloc_mapping_get(kctx,
-+ waits->objs[i].addr, &mapping);
-+
-+ if (!cpu_ptr)
-+ return;
-+
-+ val = *cpu_ptr;
-+
-+ kbase_phy_alloc_mapping_put(kctx, mapping);
-+
-+ msg = (waits->inherit_err_flags && (1U << i)) ? "true" :
-+ "false";
-+ seq_printf(file, " %llx(%u > %u, inherit_err: %s), ",
-+ waits->objs[i].addr, val, waits->objs[i].val, msg);
-+ }
-+}
-+
-+/**
-+ * kbasep_csf_kcpu_debugfs_print_queue() - Print debug data for a KCPU queue
-+ *
-+ * @file: The seq_file to print to
-+ * @kctx: The context of the KCPU queue
-+ * @queue: Pointer to the KCPU queue
-+ */
-+static void kbasep_csf_kcpu_debugfs_print_queue(struct seq_file *file,
-+ struct kbase_context *kctx,
-+ struct kbase_kcpu_command_queue *queue)
-+{
-+ if (WARN_ON(!queue))
-+ return;
-+
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+
-+ seq_printf(file, "%16u, %11u, %7u, %13llu %8u",
-+ queue->num_pending_cmds, queue->enqueue_failed,
-+ queue->command_started ? 1 : 0,
-+ queue->fence_context, queue->fence_seqno);
-+
-+ if (queue->command_started) {
-+ struct kbase_kcpu_command *cmd =
-+ &queue->commands[queue->start_offset];
-+ switch (cmd->type) {
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
-+ case BASE_KCPU_COMMAND_TYPE_FENCE_WAIT:
-+ {
-+ struct kbase_sync_fence_info info;
-+
-+ kbase_sync_fence_info_get(cmd->info.fence.fence, &info);
-+ seq_printf(file, ", Fence %pK %s %s",
-+ info.fence, info.name,
-+ kbase_sync_status_string(info.status));
-+ break;
-+ }
-+#endif
-+ case BASE_KCPU_COMMAND_TYPE_CQS_WAIT:
-+ seq_puts(file, ", CQS ");
-+ kbasep_csf_kcpu_debugfs_print_cqs_waits(file, kctx,
-+ &cmd->info.cqs_wait);
-+ break;
-+ default:
-+ seq_puts(file, ", U, Unknown blocking command");
-+ break;
-+ }
-+ }
-+
-+ seq_puts(file, "\n");
-+}
-+
-+/**
-+ * kbasep_csf_kcpu_debugfs_show() - Print the KCPU queues debug information
-+ *
-+ * @file: The seq_file for printing to
-+ * @data: The debugfs dentry private data, a pointer to kbase_context
-+ *
-+ * Return: Negative error code or 0 on success.
-+ */
-+static int kbasep_csf_kcpu_debugfs_show(struct seq_file *file, void *data)
-+{
-+ struct kbase_context *kctx = file->private;
-+ unsigned long idx;
-+
-+ seq_printf(file, "MALI_CSF_KCPU_DEBUGFS_VERSION: v%u\n", MALI_CSF_KCPU_DEBUGFS_VERSION);
-+ seq_puts(file, "Queue Idx(err-mode), Pending Commands, Enqueue err, Blocked, Fence context & seqno, (Wait Type, Additional info)\n");
-+ mutex_lock(&kctx->csf.kcpu_queues.lock);
-+
-+ idx = find_first_bit(kctx->csf.kcpu_queues.in_use,
-+ KBASEP_MAX_KCPU_QUEUES);
-+
-+ while (idx < KBASEP_MAX_KCPU_QUEUES) {
-+ struct kbase_kcpu_command_queue *queue =
-+ kctx->csf.kcpu_queues.array[idx];
-+
-+ seq_printf(file, "%9lu( %s ), ", idx,
-+ queue->has_error ? "InErr" : "NoErr");
-+ kbasep_csf_kcpu_debugfs_print_queue(file, kctx,
-+ kctx->csf.kcpu_queues.array[idx]);
-+
-+ idx = find_next_bit(kctx->csf.kcpu_queues.in_use,
-+ KBASEP_MAX_KCPU_QUEUES, idx + 1);
-+ }
-+
-+ mutex_unlock(&kctx->csf.kcpu_queues.lock);
-+ return 0;
-+}
-+
-+static int kbasep_csf_kcpu_debugfs_open(struct inode *in, struct file *file)
-+{
-+ return single_open(file, kbasep_csf_kcpu_debugfs_show, in->i_private);
-+}
-+
-+static const struct file_operations kbasep_csf_kcpu_debugfs_fops = {
-+ .open = kbasep_csf_kcpu_debugfs_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+void kbase_csf_kcpu_debugfs_init(struct kbase_context *kctx)
-+{
-+ struct dentry *file;
-+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
-+ const mode_t mode = 0444;
-+#else
-+ const mode_t mode = 0400;
-+#endif
-+
-+ if (WARN_ON(!kctx || IS_ERR_OR_NULL(kctx->kctx_dentry)))
-+ return;
-+
-+ file = debugfs_create_file("kcpu_queues", mode, kctx->kctx_dentry,
-+ kctx, &kbasep_csf_kcpu_debugfs_fops);
-+
-+ if (IS_ERR_OR_NULL(file)) {
-+ dev_warn(kctx->kbdev->dev,
-+ "Unable to create KCPU debugfs entry");
-+ }
-+}
-+
-+
-+#else
-+/*
-+ * Stub functions for when debugfs is disabled
-+ */
-+void kbase_csf_kcpu_debugfs_init(struct kbase_context *kctx)
-+{
-+}
-+
-+#endif /* CONFIG_DEBUG_FS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu_debugfs.h
-new file mode 100644
-index 0000000..08f2fda
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_kcpu_debugfs.h
-@@ -0,0 +1,37 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_KCPU_DEBUGFS_H_
-+#define _KBASE_CSF_KCPU_DEBUGFS_H_
-+
-+/* Forward declaration */
-+struct kbase_context;
-+
-+#define MALI_CSF_KCPU_DEBUGFS_VERSION 0
-+
-+/**
-+ * kbase_csf_kcpu_debugfs_init() - Create a debugfs entry for KCPU queues
-+ *
-+ * @kctx: The kbase_context for which to create the debugfs entry
-+ */
-+void kbase_csf_kcpu_debugfs_init(struct kbase_context *kctx);
-+
-+#endif /* _KBASE_CSF_KCPU_DEBUGFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_protected_memory.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_protected_memory.c
-new file mode 100644
-index 0000000..5997483
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_protected_memory.c
-@@ -0,0 +1,119 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_csf_protected_memory.h"
-+#include <linux/protected_memory_allocator.h>
-+
-+#if IS_ENABLED(CONFIG_OF)
-+#include <linux/of_platform.h>
-+#endif
-+
-+int kbase_csf_protected_memory_init(struct kbase_device *const kbdev)
-+{
-+ int err = 0;
-+
-+#if IS_ENABLED(CONFIG_OF)
-+ struct device_node *pma_node = of_parse_phandle(kbdev->dev->of_node,
-+ "protected-memory-allocator", 0);
-+ if (!pma_node) {
-+ dev_info(kbdev->dev, "Protected memory allocator not available\n");
-+ } else {
-+ struct platform_device *const pdev =
-+ of_find_device_by_node(pma_node);
-+
-+ kbdev->csf.pma_dev = NULL;
-+ if (!pdev) {
-+ dev_err(kbdev->dev, "Platform device for Protected memory allocator not found\n");
-+ } else {
-+ kbdev->csf.pma_dev = platform_get_drvdata(pdev);
-+ if (!kbdev->csf.pma_dev) {
-+ dev_info(kbdev->dev, "Protected memory allocator is not ready\n");
-+ err = -EPROBE_DEFER;
-+ } else if (!try_module_get(kbdev->csf.pma_dev->owner)) {
-+ dev_err(kbdev->dev, "Failed to get Protected memory allocator module\n");
-+ err = -ENODEV;
-+ } else {
-+ dev_info(kbdev->dev, "Protected memory allocator successfully loaded\n");
-+ }
-+ }
-+ of_node_put(pma_node);
-+ }
-+#endif
-+
-+ return err;
-+}
-+
-+void kbase_csf_protected_memory_term(struct kbase_device *const kbdev)
-+{
-+ if (kbdev->csf.pma_dev)
-+ module_put(kbdev->csf.pma_dev->owner);
-+}
-+
-+struct protected_memory_allocation **
-+ kbase_csf_protected_memory_alloc(
-+ struct kbase_device *const kbdev,
-+ struct tagged_addr *phys,
-+ size_t num_pages)
-+{
-+ size_t i;
-+ struct protected_memory_allocator_device *pma_dev =
-+ kbdev->csf.pma_dev;
-+ struct protected_memory_allocation **pma =
-+ kmalloc_array(num_pages, sizeof(*pma), GFP_KERNEL);
-+
-+ if (WARN_ON(!pma_dev) || WARN_ON(!phys) || !pma)
-+ return NULL;
-+
-+ for (i = 0; i < num_pages; i++) {
-+ pma[i] = pma_dev->ops.pma_alloc_page(pma_dev,
-+ KBASE_MEM_POOL_4KB_PAGE_TABLE_ORDER);
-+ if (!pma[i])
-+ break;
-+
-+ phys[i] = as_tagged(pma_dev->ops.pma_get_phys_addr(pma_dev,
-+ pma[i]));
-+ }
-+
-+ if (i != num_pages) {
-+ kbase_csf_protected_memory_free(kbdev, pma, i);
-+ return NULL;
-+ }
-+
-+ return pma;
-+}
-+
-+void kbase_csf_protected_memory_free(
-+ struct kbase_device *const kbdev,
-+ struct protected_memory_allocation **pma,
-+ size_t num_pages)
-+{
-+ size_t i;
-+ struct protected_memory_allocator_device *pma_dev =
-+ kbdev->csf.pma_dev;
-+
-+ if (WARN_ON(!pma_dev) || WARN_ON(!pma))
-+ return;
-+
-+ for (i = 0; i < num_pages; i++)
-+ pma_dev->ops.pma_free_page(pma_dev, pma[i]);
-+
-+ kfree(pma);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_protected_memory.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_protected_memory.h
-new file mode 100644
-index 0000000..4c0609e
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_protected_memory.h
-@@ -0,0 +1,71 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_PROTECTED_MEMORY_H_
-+#define _KBASE_CSF_PROTECTED_MEMORY_H_
-+
-+#include "mali_kbase.h"
-+/**
-+ * kbase_csf_protected_memory_init - Initilaise protected memory allocator.
-+ *
-+ * @kbdev: Device pointer.
-+ *
-+ * Return: 0 if success, or an error code on failure.
-+ */
-+int kbase_csf_protected_memory_init(struct kbase_device *const kbdev);
-+
-+/**
-+ * kbase_csf_protected_memory_term - Terminate prtotected memory allocator.
-+ *
-+ * @kbdev: Device pointer.
-+ */
-+void kbase_csf_protected_memory_term(struct kbase_device *const kbdev);
-+
-+/**
-+ * kbase_csf_protected_memory_alloc - Allocate protected memory pages.
-+ *
-+ * @kbdev: Device pointer.
-+ * @phys: Array of physical addresses to be filled in by the protected
-+ * memory allocator.
-+ * @num_pages: Number of pages requested to be allocated.
-+ *
-+ * Return: Pointer to an array of protected memory allocations on success,
-+ * or NULL on failure.
-+ */
-+struct protected_memory_allocation **
-+ kbase_csf_protected_memory_alloc(
-+ struct kbase_device *const kbdev,
-+ struct tagged_addr *phys,
-+ size_t num_pages);
-+
-+/**
-+ * kbase_csf_protected_memory_free - Free the allocated
-+ * protected memory pages
-+ *
-+ * @kbdev: Device pointer.
-+ * @pma: Array of pointer to protected memory allocations.
-+ * @num_pages: Number of pages to be freed.
-+ */
-+void kbase_csf_protected_memory_free(
-+ struct kbase_device *const kbdev,
-+ struct protected_memory_allocation **pma,
-+ size_t num_pages);
-+#endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_reset_gpu.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_reset_gpu.c
-new file mode 100644
-index 0000000..f6d61d7
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_reset_gpu.c
-@@ -0,0 +1,629 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <mali_kbase_ctx_sched.h>
-+#include <mali_kbase_hwcnt_context.h>
-+#include <device/mali_kbase_device.h>
-+#include <backend/gpu/mali_kbase_irq_internal.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+#include <mali_kbase_regs_history_debugfs.h>
-+#include <csf/mali_kbase_csf_trace_buffer.h>
-+#include <csf/ipa_control/mali_kbase_csf_ipa_control.h>
-+#include <mali_kbase_reset_gpu.h>
-+
-+/* Waiting timeout for GPU reset to complete */
-+#define GPU_RESET_TIMEOUT_MS (5000) /* 5 seconds */
-+#define DUMP_DWORDS_PER_LINE (4)
-+/* 16 characters needed for a 8 byte value in hex & 1 character for space */
-+#define DUMP_HEX_CHARS_PER_DWORD ((2 * 8) + 1)
-+#define DUMP_HEX_CHARS_PER_LINE \
-+ (DUMP_DWORDS_PER_LINE * DUMP_HEX_CHARS_PER_DWORD)
-+
-+static inline bool
-+kbase_csf_reset_state_is_silent(enum kbase_csf_reset_gpu_state state)
-+{
-+ return (state == KBASE_CSF_RESET_GPU_COMMITTED_SILENT);
-+}
-+
-+static inline bool
-+kbase_csf_reset_state_is_committed(enum kbase_csf_reset_gpu_state state)
-+{
-+ return (state == KBASE_CSF_RESET_GPU_COMMITTED ||
-+ state == KBASE_CSF_RESET_GPU_COMMITTED_SILENT);
-+}
-+
-+static inline bool
-+kbase_csf_reset_state_is_active(enum kbase_csf_reset_gpu_state state)
-+{
-+ return (state == KBASE_CSF_RESET_GPU_HAPPENING);
-+}
-+
-+/**
-+ * DOC: Mechanism for coherent access to the HW with respect to GPU reset
-+ *
-+ * Access to the HW from non-atomic context outside of the reset thread must
-+ * use kbase_reset_gpu_prevent_and_wait() / kbase_reset_gpu_try_prevent().
-+ *
-+ * This currently works by taking the &kbase_device's csf.reset.sem, for
-+ * 'write' access by the GPU reset thread and 'read' access by every other
-+ * thread. The use of this rw_semaphore means:
-+ *
-+ * - there will be mutual exclusion (and thus waiting) between the thread doing
-+ * reset ('writer') and threads trying to access the GPU for 'normal'
-+ * operations ('readers')
-+ *
-+ * - multiple threads may prevent reset from happening without serializing each
-+ * other prematurely. Note that at present the wait for reset to finish has
-+ * to be done higher up in the driver than actual GPU access, at a point
-+ * where it won't cause lock ordering issues. At such a point, some paths may
-+ * actually lead to no GPU access, but we would prefer to avoid serializing
-+ * at that level
-+ *
-+ * - lockdep (if enabled in the kernel) will check such uses for deadlock
-+ *
-+ * If instead &kbase_device's csf.reset.wait &wait_queue_head_t were used on
-+ * its own, we'd also need to add a &lockdep_map and appropriate lockdep calls
-+ * to make use of lockdep checking in all places where the &wait_queue_head_t
-+ * is waited upon or signaled.
-+ *
-+ * Indeed places where we wait on &kbase_device's csf.reset.wait (such as
-+ * kbase_reset_gpu_wait()) are the only places where we need extra call(s) to
-+ * lockdep, and they are made on the existing rw_semaphore.
-+ *
-+ * For non-atomic access, the &kbase_device's csf.reset.state member should be
-+ * checked instead, such as by using kbase_reset_gpu_is_active().
-+ *
-+ * Ideally the &rw_semaphore should be replaced in future with a single mutex
-+ * that protects any access to the GPU, via reset or otherwise.
-+ */
-+
-+int kbase_reset_gpu_prevent_and_wait(struct kbase_device *kbdev)
-+{
-+ down_read(&kbdev->csf.reset.sem);
-+
-+ if (atomic_read(&kbdev->csf.reset.state) ==
-+ KBASE_CSF_RESET_GPU_FAILED) {
-+ up_read(&kbdev->csf.reset.sem);
-+ return -ENOMEM;
-+ }
-+
-+ if (WARN_ON(kbase_reset_gpu_is_active(kbdev))) {
-+ up_read(&kbdev->csf.reset.sem);
-+ return -EFAULT;
-+ }
-+
-+ return 0;
-+}
-+KBASE_EXPORT_TEST_API(kbase_reset_gpu_prevent_and_wait);
-+
-+int kbase_reset_gpu_try_prevent(struct kbase_device *kbdev)
-+{
-+ if (!down_read_trylock(&kbdev->csf.reset.sem))
-+ return -EAGAIN;
-+
-+ if (atomic_read(&kbdev->csf.reset.state) ==
-+ KBASE_CSF_RESET_GPU_FAILED) {
-+ up_read(&kbdev->csf.reset.sem);
-+ return -ENOMEM;
-+ }
-+
-+ if (WARN_ON(kbase_reset_gpu_is_active(kbdev))) {
-+ up_read(&kbdev->csf.reset.sem);
-+ return -EFAULT;
-+ }
-+
-+ return 0;
-+}
-+
-+void kbase_reset_gpu_allow(struct kbase_device *kbdev)
-+{
-+ up_read(&kbdev->csf.reset.sem);
-+}
-+KBASE_EXPORT_TEST_API(kbase_reset_gpu_allow);
-+
-+void kbase_reset_gpu_assert_prevented(struct kbase_device *kbdev)
-+{
-+#if KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE
-+ lockdep_assert_held_read(&kbdev->csf.reset.sem);
-+#else
-+ lockdep_assert_held(&kbdev->csf.reset.sem);
-+#endif
-+ WARN_ON(kbase_reset_gpu_is_active(kbdev));
-+}
-+
-+void kbase_reset_gpu_assert_failed_or_prevented(struct kbase_device *kbdev)
-+{
-+ if (atomic_read(&kbdev->csf.reset.state) == KBASE_CSF_RESET_GPU_FAILED)
-+ return;
-+
-+#if KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE
-+ lockdep_assert_held_read(&kbdev->csf.reset.sem);
-+#else
-+ lockdep_assert_held(&kbdev->csf.reset.sem);
-+#endif
-+ WARN_ON(kbase_reset_gpu_is_active(kbdev));
-+}
-+
-+/* Mark the reset as now happening, and synchronize with other threads that
-+ * might be trying to access the GPU
-+ */
-+static void kbase_csf_reset_begin_hw_access_sync(
-+ struct kbase_device *kbdev,
-+ enum kbase_csf_reset_gpu_state initial_reset_state)
-+{
-+ unsigned long hwaccess_lock_flags;
-+ unsigned long scheduler_spin_lock_flags;
-+
-+ /* Note this is a WARN/atomic_set because it is a software issue for a
-+ * race to be occurring here
-+ */
-+ WARN_ON(!kbase_csf_reset_state_is_committed(initial_reset_state));
-+
-+ down_write(&kbdev->csf.reset.sem);
-+
-+ /* Threads in atomic context accessing the HW will hold one of these
-+ * locks, so synchronize with them too.
-+ */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, hwaccess_lock_flags);
-+ kbase_csf_scheduler_spin_lock(kbdev, &scheduler_spin_lock_flags);
-+ atomic_set(&kbdev->csf.reset.state, KBASE_RESET_GPU_HAPPENING);
-+ kbase_csf_scheduler_spin_unlock(kbdev, scheduler_spin_lock_flags);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, hwaccess_lock_flags);
-+}
-+
-+/* Mark the reset as finished and allow others threads to once more access the
-+ * GPU
-+ */
-+static void kbase_csf_reset_end_hw_access(struct kbase_device *kbdev,
-+ int err_during_reset,
-+ bool firmware_inited)
-+{
-+ unsigned long hwaccess_lock_flags;
-+ unsigned long scheduler_spin_lock_flags;
-+
-+ WARN_ON(!kbase_csf_reset_state_is_active(
-+ atomic_read(&kbdev->csf.reset.state)));
-+
-+ /* Once again, we synchronize with atomic context threads accessing the
-+ * HW, as otherwise any actions they defer could get lost
-+ */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, hwaccess_lock_flags);
-+ kbase_csf_scheduler_spin_lock(kbdev, &scheduler_spin_lock_flags);
-+
-+ if (!err_during_reset) {
-+ atomic_set(&kbdev->csf.reset.state,
-+ KBASE_CSF_RESET_GPU_NOT_PENDING);
-+ } else {
-+ dev_err(kbdev->dev, "Reset failed to complete");
-+ atomic_set(&kbdev->csf.reset.state, KBASE_CSF_RESET_GPU_FAILED);
-+ }
-+
-+ kbase_csf_scheduler_spin_unlock(kbdev, scheduler_spin_lock_flags);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, hwaccess_lock_flags);
-+
-+ /* Invoke the scheduling tick after formally finishing the reset,
-+ * otherwise the tick might start too soon and notice that reset
-+ * is still in progress.
-+ */
-+ up_write(&kbdev->csf.reset.sem);
-+ wake_up(&kbdev->csf.reset.wait);
-+
-+ if (!err_during_reset && likely(firmware_inited))
-+ kbase_csf_scheduler_enable_tick_timer(kbdev);
-+}
-+
-+static void kbase_csf_debug_dump_registers(struct kbase_device *kbdev)
-+{
-+ kbase_io_history_dump(kbdev);
-+
-+ dev_err(kbdev->dev, "Register state:");
-+ dev_err(kbdev->dev, " GPU_IRQ_RAWSTAT=0x%08x GPU_STATUS=0x%08x MCU_STATUS=0x%08x",
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT)),
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS)),
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(MCU_STATUS)));
-+ dev_err(kbdev->dev, " JOB_IRQ_RAWSTAT=0x%08x MMU_IRQ_RAWSTAT=0x%08x GPU_FAULTSTATUS=0x%08x",
-+ kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT)),
-+ kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_RAWSTAT)),
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS)));
-+ dev_err(kbdev->dev, " GPU_IRQ_MASK=0x%08x JOB_IRQ_MASK=0x%08x MMU_IRQ_MASK=0x%08x",
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK)),
-+ kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK)),
-+ kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK)));
-+ dev_err(kbdev->dev, " PWR_OVERRIDE0=0x%08x PWR_OVERRIDE1=0x%08x",
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE0)),
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE1)));
-+ dev_err(kbdev->dev, " SHADER_CONFIG=0x%08x L2_MMU_CONFIG=0x%08x TILER_CONFIG=0x%08x",
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(SHADER_CONFIG)),
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG)),
-+ kbase_reg_read(kbdev, GPU_CONTROL_REG(TILER_CONFIG)));
-+}
-+
-+static void kbase_csf_dump_firmware_trace_buffer(struct kbase_device *kbdev)
-+{
-+ u8 *buf, *line_str;
-+ unsigned int read_size;
-+ struct firmware_trace_buffer *tb =
-+ kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME);
-+
-+ if (tb == NULL) {
-+ dev_dbg(kbdev->dev, "Can't get the trace buffer, firmware trace dump skipped");
-+ return;
-+ }
-+
-+ buf = kmalloc(PAGE_SIZE + DUMP_HEX_CHARS_PER_LINE + 1, GFP_KERNEL);
-+ if (buf == NULL) {
-+ dev_err(kbdev->dev, "Short of memory, firmware trace dump skipped");
-+ return;
-+ }
-+ line_str = &buf[PAGE_SIZE];
-+
-+ dev_err(kbdev->dev, "Firmware trace buffer dump:");
-+ while ((read_size = kbase_csf_firmware_trace_buffer_read_data(tb, buf,
-+ PAGE_SIZE))) {
-+ u64 *ptr = (u64 *)buf;
-+ u32 num_dwords;
-+
-+ for (num_dwords = read_size / sizeof(u64);
-+ num_dwords >= DUMP_DWORDS_PER_LINE;
-+ num_dwords -= DUMP_DWORDS_PER_LINE) {
-+ dev_err(kbdev->dev, "%016llx %016llx %016llx %016llx",
-+ ptr[0], ptr[1], ptr[2], ptr[3]);
-+ ptr += DUMP_DWORDS_PER_LINE;
-+ }
-+
-+ if (num_dwords) {
-+ int pos = 0;
-+
-+ while (num_dwords--) {
-+ pos += snprintf(line_str + pos,
-+ DUMP_HEX_CHARS_PER_DWORD + 1,
-+ "%016llx ", ptr[0]);
-+ ptr++;
-+ }
-+
-+ dev_err(kbdev->dev, "%s", line_str);
-+ }
-+ }
-+
-+ kfree(buf);
-+}
-+
-+/**
-+ * kbase_csf_hwcnt_on_reset_error() - Sets HWCNT to appropriate state in the
-+ * event of an error during GPU reset.
-+ * @kbdev: Pointer to KBase device
-+ */
-+static void kbase_csf_hwcnt_on_reset_error(struct kbase_device *kbdev)
-+{
-+ unsigned long flags;
-+
-+ /* Treat this as an unrecoverable error for HWCNT */
-+ kbase_hwcnt_backend_csf_on_unrecoverable_error(&kbdev->hwcnt_gpu_iface);
-+
-+ /* Re-enable counters to ensure matching enable/disable pair.
-+ * This might reduce the hwcnt disable count to 0, and therefore
-+ * trigger actual re-enabling of hwcnt.
-+ * However, as the backend is now in the unrecoverable error state,
-+ * re-enabling will immediately fail and put the context into the error
-+ * state, preventing the hardware from being touched (which could have
-+ * risked a hang).
-+ */
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+static int kbase_csf_reset_gpu_now(struct kbase_device *kbdev,
-+ bool firmware_inited, bool silent)
-+{
-+ unsigned long flags;
-+ int err;
-+
-+ WARN_ON(kbdev->irq_reset_flush);
-+ /* The reset must now be happening otherwise other threads will not
-+ * have been synchronized with to stop their access to the HW
-+ */
-+#if KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE
-+ lockdep_assert_held_write(&kbdev->csf.reset.sem);
-+#elif KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE
-+ lockdep_assert_held_exclusive(&kbdev->csf.reset.sem);
-+#else
-+ lockdep_assert_held(&kbdev->csf.reset.sem);
-+#endif
-+ WARN_ON(!kbase_reset_gpu_is_active(kbdev));
-+
-+ /* Reset the scheduler state before disabling the interrupts as suspend
-+ * of active CSG slots would also be done as a part of reset.
-+ */
-+ if (likely(firmware_inited))
-+ kbase_csf_scheduler_reset(kbdev);
-+ cancel_work_sync(&kbdev->csf.firmware_reload_work);
-+
-+ dev_dbg(kbdev->dev, "Disable GPU hardware counters.\n");
-+ /* This call will block until counters are disabled.
-+ */
-+ kbase_hwcnt_context_disable(kbdev->hwcnt_gpu_ctx);
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ spin_lock(&kbdev->mmu_mask_change);
-+ kbase_pm_reset_start_locked(kbdev);
-+
-+ dev_dbg(kbdev->dev,
-+ "We're about to flush out the IRQs and their bottom halves\n");
-+ kbdev->irq_reset_flush = true;
-+
-+ /* Disable IRQ to avoid IRQ handlers to kick in after releasing the
-+ * spinlock; this also clears any outstanding interrupts
-+ */
-+ kbase_pm_disable_interrupts_nolock(kbdev);
-+
-+ spin_unlock(&kbdev->mmu_mask_change);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ dev_dbg(kbdev->dev, "Ensure that any IRQ handlers have finished\n");
-+ /* Must be done without any locks IRQ handlers will take.
-+ */
-+ kbase_synchronize_irqs(kbdev);
-+
-+ dev_dbg(kbdev->dev, "Flush out any in-flight work items\n");
-+ kbase_flush_mmu_wqs(kbdev);
-+
-+ dev_dbg(kbdev->dev,
-+ "The flush has completed so reset the active indicator\n");
-+ kbdev->irq_reset_flush = false;
-+
-+ mutex_lock(&kbdev->pm.lock);
-+ if (!silent)
-+ dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)",
-+ RESET_TIMEOUT);
-+
-+ /* Output the state of some interesting registers to help in the
-+ * debugging of GPU resets, and dump the firmware trace buffer
-+ */
-+ if (!silent) {
-+ kbase_csf_debug_dump_registers(kbdev);
-+ if (likely(firmware_inited))
-+ kbase_csf_dump_firmware_trace_buffer(kbdev);
-+ }
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_ipa_control_handle_gpu_reset_pre(kbdev);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ /* Tell hardware counters a reset is about to occur.
-+ * If the backend is in an unrecoverable error state (e.g. due to
-+ * firmware being unresponsive) this will transition the backend out of
-+ * it, on the assumption a reset will fix whatever problem there was.
-+ */
-+ kbase_hwcnt_backend_csf_on_before_reset(&kbdev->hwcnt_gpu_iface);
-+
-+ /* Reset the GPU */
-+ err = kbase_pm_init_hw(kbdev, 0);
-+
-+ mutex_unlock(&kbdev->pm.lock);
-+
-+ if (WARN_ON(err)) {
-+ kbase_csf_hwcnt_on_reset_error(kbdev);
-+ return err;
-+ }
-+
-+ mutex_lock(&kbdev->mmu_hw_mutex);
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_ctx_sched_restore_all_as(kbdev);
-+ kbase_ipa_control_handle_gpu_reset_post(kbdev);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ mutex_unlock(&kbdev->mmu_hw_mutex);
-+
-+ kbase_pm_enable_interrupts(kbdev);
-+
-+ mutex_lock(&kbdev->pm.lock);
-+ kbase_pm_reset_complete(kbdev);
-+ /* Synchronously wait for the reload of firmware to complete */
-+ err = kbase_pm_wait_for_desired_state(kbdev);
-+ mutex_unlock(&kbdev->pm.lock);
-+
-+ if (WARN_ON(err)) {
-+ kbase_csf_hwcnt_on_reset_error(kbdev);
-+ return err;
-+ }
-+
-+ /* Re-enable GPU hardware counters */
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ if (!silent)
-+ dev_err(kbdev->dev, "Reset complete");
-+
-+ return 0;
-+}
-+
-+static void kbase_csf_reset_gpu_worker(struct work_struct *data)
-+{
-+ struct kbase_device *kbdev = container_of(data, struct kbase_device,
-+ csf.reset.work);
-+ bool firmware_inited;
-+ unsigned long flags;
-+ int err = 0;
-+ const enum kbase_csf_reset_gpu_state initial_reset_state =
-+ atomic_read(&kbdev->csf.reset.state);
-+
-+ /* Ensure any threads (e.g. executing the CSF scheduler) have finished
-+ * using the HW
-+ */
-+ kbase_csf_reset_begin_hw_access_sync(kbdev, initial_reset_state);
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ firmware_inited = kbdev->csf.firmware_inited;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ if (!kbase_pm_context_active_handle_suspend(kbdev,
-+ KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) {
-+ bool silent =
-+ kbase_csf_reset_state_is_silent(initial_reset_state);
-+
-+ err = kbase_csf_reset_gpu_now(kbdev, firmware_inited, silent);
-+ kbase_pm_context_idle(kbdev);
-+ }
-+
-+ kbase_disjoint_state_down(kbdev);
-+
-+ /* Allow other threads to once again use the GPU */
-+ kbase_csf_reset_end_hw_access(kbdev, err, firmware_inited);
-+}
-+
-+bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev, unsigned int flags)
-+{
-+ if (flags & RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)
-+ kbase_hwcnt_backend_csf_on_unrecoverable_error(
-+ &kbdev->hwcnt_gpu_iface);
-+
-+ if (atomic_cmpxchg(&kbdev->csf.reset.state,
-+ KBASE_CSF_RESET_GPU_NOT_PENDING,
-+ KBASE_CSF_RESET_GPU_PREPARED) !=
-+ KBASE_CSF_RESET_GPU_NOT_PENDING)
-+ /* Some other thread is already resetting the GPU */
-+ return false;
-+
-+ return true;
-+}
-+KBASE_EXPORT_TEST_API(kbase_prepare_to_reset_gpu);
-+
-+bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev,
-+ unsigned int flags)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ return kbase_prepare_to_reset_gpu(kbdev, flags);
-+}
-+
-+void kbase_reset_gpu(struct kbase_device *kbdev)
-+{
-+ /* Note this is a WARN/atomic_set because it is a software issue for
-+ * a race to be occurring here
-+ */
-+ if (WARN_ON(atomic_read(&kbdev->csf.reset.state) !=
-+ KBASE_RESET_GPU_PREPARED))
-+ return;
-+
-+ atomic_set(&kbdev->csf.reset.state, KBASE_CSF_RESET_GPU_COMMITTED);
-+ dev_err(kbdev->dev, "Preparing to soft-reset GPU\n");
-+
-+ kbase_disjoint_state_up(kbdev);
-+
-+ queue_work(kbdev->csf.reset.workq, &kbdev->csf.reset.work);
-+}
-+KBASE_EXPORT_TEST_API(kbase_reset_gpu);
-+
-+void kbase_reset_gpu_locked(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ kbase_reset_gpu(kbdev);
-+}
-+
-+int kbase_reset_gpu_silent(struct kbase_device *kbdev)
-+{
-+ if (atomic_cmpxchg(&kbdev->csf.reset.state,
-+ KBASE_CSF_RESET_GPU_NOT_PENDING,
-+ KBASE_CSF_RESET_GPU_COMMITTED_SILENT) !=
-+ KBASE_CSF_RESET_GPU_NOT_PENDING) {
-+ /* Some other thread is already resetting the GPU */
-+ return -EAGAIN;
-+ }
-+
-+ kbase_disjoint_state_up(kbdev);
-+
-+ queue_work(kbdev->csf.reset.workq, &kbdev->csf.reset.work);
-+
-+ return 0;
-+}
-+
-+bool kbase_reset_gpu_is_active(struct kbase_device *kbdev)
-+{
-+ enum kbase_csf_reset_gpu_state reset_state =
-+ atomic_read(&kbdev->csf.reset.state);
-+
-+ /* For CSF, the reset is considered active only when the reset worker
-+ * is actually executing and other threads would have to wait for it to
-+ * complete
-+ */
-+ return kbase_csf_reset_state_is_active(reset_state);
-+}
-+
-+int kbase_reset_gpu_wait(struct kbase_device *kbdev)
-+{
-+ const long wait_timeout =
-+ kbase_csf_timeout_in_jiffies(GPU_RESET_TIMEOUT_MS);
-+ long remaining;
-+
-+ /* Inform lockdep we might be trying to wait on a reset (as
-+ * would've been done with down_read() - which has no 'timeout'
-+ * variant), then use wait_event_timeout() to implement the timed
-+ * wait.
-+ *
-+ * in CONFIG_PROVE_LOCKING builds, this should catch potential 'time
-+ * bound' deadlocks such as:
-+ * - incorrect lock order with respect to others locks
-+ * - current thread has prevented reset
-+ * - current thread is executing the reset worker
-+ */
-+ might_lock_read(&kbdev->csf.reset.sem);
-+
-+ remaining = wait_event_timeout(
-+ kbdev->csf.reset.wait,
-+ (atomic_read(&kbdev->csf.reset.state) ==
-+ KBASE_CSF_RESET_GPU_NOT_PENDING) ||
-+ (atomic_read(&kbdev->csf.reset.state) ==
-+ KBASE_CSF_RESET_GPU_FAILED),
-+ wait_timeout);
-+
-+ if (!remaining) {
-+ dev_warn(kbdev->dev, "Timed out waiting for the GPU reset to complete");
-+ return -ETIMEDOUT;
-+ } else if (atomic_read(&kbdev->csf.reset.state) ==
-+ KBASE_CSF_RESET_GPU_FAILED) {
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+KBASE_EXPORT_TEST_API(kbase_reset_gpu_wait);
-+
-+int kbase_reset_gpu_init(struct kbase_device *kbdev)
-+{
-+ kbdev->csf.reset.workq = alloc_workqueue("Mali reset workqueue", 0, 1);
-+ if (kbdev->csf.reset.workq == NULL)
-+ return -ENOMEM;
-+
-+ INIT_WORK(&kbdev->csf.reset.work, kbase_csf_reset_gpu_worker);
-+
-+ init_waitqueue_head(&kbdev->csf.reset.wait);
-+ init_rwsem(&kbdev->csf.reset.sem);
-+
-+ return 0;
-+}
-+
-+void kbase_reset_gpu_term(struct kbase_device *kbdev)
-+{
-+ destroy_workqueue(kbdev->csf.reset.workq);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_scheduler.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_scheduler.c
-new file mode 100644
-index 0000000..5b795d6
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_scheduler.c
-@@ -0,0 +1,5063 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include "mali_kbase_config_defaults.h"
-+#include <mali_kbase_ctx_sched.h>
-+#include <mali_kbase_reset_gpu.h>
-+#include <mali_kbase_as_fault_debugfs.h>
-+#include "mali_kbase_csf.h"
-+#include <tl/mali_kbase_tracepoints.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+#include <linux/export.h>
-+#include <uapi/gpu/arm/midgard/csf/mali_gpu_csf_registers.h>
-+#include <uapi/gpu/arm/midgard/mali_base_kernel.h>
-+
-+/* Value to indicate that a queue group is not groups_to_schedule list */
-+#define KBASEP_GROUP_PREPARED_SEQ_NUM_INVALID (U32_MAX)
-+
-+/* Waiting timeout for scheduler state change for descheduling a CSG */
-+#define CSG_SCHED_STOP_TIMEOUT_MS (50)
-+
-+#define CSG_SUSPEND_ON_RESET_WAIT_TIMEOUT_MS DEFAULT_RESET_TIMEOUT_MS
-+
-+/* Maximum number of endpoints which may run tiler jobs. */
-+#define CSG_TILER_MAX ((u8)1)
-+
-+/* Maximum dynamic CSG slot priority value */
-+#define MAX_CSG_SLOT_PRIORITY ((u8)15)
-+
-+/* CSF scheduler time slice value */
-+#define CSF_SCHEDULER_TIME_TICK_MS (100) /* 100 milliseconds */
-+
-+/*
-+ * CSF scheduler time threshold for converting "tock" requests into "tick" if
-+ * they come too close to the end of a tick interval. This avoids scheduling
-+ * twice in a row.
-+ */
-+#define CSF_SCHEDULER_TIME_TICK_THRESHOLD_MS \
-+ CSF_SCHEDULER_TIME_TICK_MS
-+
-+#define CSF_SCHEDULER_TIME_TICK_THRESHOLD_JIFFIES \
-+ msecs_to_jiffies(CSF_SCHEDULER_TIME_TICK_THRESHOLD_MS)
-+
-+/* Nanoseconds per millisecond */
-+#define NS_PER_MS ((u64)1000 * 1000)
-+
-+/*
-+ * CSF minimum time to reschedule for a new "tock" request. Bursts of "tock"
-+ * requests are not serviced immediately, but shall wait for a minimum time in
-+ * order to reduce load on the CSF scheduler thread.
-+ */
-+#define CSF_SCHEDULER_TIME_TOCK_JIFFIES 1 /* 1 jiffies-time */
-+
-+/* CS suspended and is idle (empty ring buffer) */
-+#define CS_IDLE_FLAG (1 << 0)
-+
-+/* CS suspended and is wait for a CQS condition */
-+#define CS_WAIT_SYNC_FLAG (1 << 1)
-+
-+/* 2 GPU address space slots are reserved for MCU and privileged context for HW
-+ * counter dumping. TODO remove the slot reserved for latter in GPUCORE-26293.
-+ */
-+#define NUM_RESERVED_AS_SLOTS (2)
-+
-+static int scheduler_group_schedule(struct kbase_queue_group *group);
-+static void remove_group_from_idle_wait(struct kbase_queue_group *const group);
-+static
-+void insert_group_to_runnable(struct kbase_csf_scheduler *const scheduler,
-+ struct kbase_queue_group *const group,
-+ enum kbase_csf_group_state run_state);
-+static struct kbase_queue_group *scheduler_get_protm_enter_async_group(
-+ struct kbase_device *const kbdev,
-+ struct kbase_queue_group *const group);
-+static struct kbase_queue_group *get_tock_top_group(
-+ struct kbase_csf_scheduler *const scheduler);
-+static void scheduler_enable_tick_timer_nolock(struct kbase_device *kbdev);
-+static int suspend_active_queue_groups(struct kbase_device *kbdev,
-+ unsigned long *slot_mask);
-+static void schedule_in_cycle(struct kbase_queue_group *group, bool force);
-+
-+#define kctx_as_enabled(kctx) (!kbase_ctx_flag(kctx, KCTX_AS_DISABLED_ON_FAULT))
-+
-+/**
-+ * tick_timer_callback() - Callback function for the scheduling tick hrtimer
-+ *
-+ * @timer: Pointer to the device
-+ *
-+ * This function will enqueue the scheduling tick work item for immediate
-+ * execution, if it has not been queued already.
-+ *
-+ * Return: enum value to indicate that timer should not be restarted.
-+ */
-+static enum hrtimer_restart tick_timer_callback(struct hrtimer *timer)
-+{
-+ struct kbase_device *kbdev = container_of(timer, struct kbase_device,
-+ csf.scheduler.tick_timer);
-+
-+ kbase_csf_scheduler_advance_tick(kbdev);
-+ return HRTIMER_NORESTART;
-+}
-+
-+/**
-+ * start_tick_timer() - Start the scheduling tick hrtimer.
-+ *
-+ * @kbdev: Pointer to the device
-+ *
-+ * This function will start the scheduling tick hrtimer and is supposed to
-+ * be called only from the tick work item function. The tick hrtimer should
-+ * should not be active already.
-+ */
-+static void start_tick_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ WARN_ON(scheduler->tick_timer_active);
-+ if (likely(!work_pending(&scheduler->tick_work))) {
-+ scheduler->tick_timer_active = true;
-+
-+ hrtimer_start(&scheduler->tick_timer,
-+ HR_TIMER_DELAY_MSEC(scheduler->csg_scheduling_period_ms),
-+ HRTIMER_MODE_REL);
-+ }
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+}
-+
-+/**
-+ * cancel_tick_timer() - Cancel the scheduling tick hrtimer
-+ *
-+ * @kbdev: Pointer to the device
-+ */
-+static void cancel_tick_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ scheduler->tick_timer_active = false;
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+ hrtimer_cancel(&scheduler->tick_timer);
-+}
-+
-+/**
-+ * enqueue_tick_work() - Enqueue the scheduling tick work item
-+ *
-+ * @kbdev: Pointer to the device
-+ *
-+ * This function will queue the scheduling tick work item for immediate
-+ * execution. This shall only be called when both the tick hrtimer and tick
-+ * work item are not active/pending.
-+ */
-+static void enqueue_tick_work(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ WARN_ON(scheduler->tick_timer_active);
-+ queue_work(scheduler->wq, &scheduler->tick_work);
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+}
-+
-+static void release_doorbell(struct kbase_device *kbdev, int doorbell_nr)
-+{
-+ WARN_ON(doorbell_nr >= CSF_NUM_DOORBELL);
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+ clear_bit(doorbell_nr, kbdev->csf.scheduler.doorbell_inuse_bitmap);
-+}
-+
-+static int acquire_doorbell(struct kbase_device *kbdev)
-+{
-+ int doorbell_nr;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ doorbell_nr = find_first_zero_bit(
-+ kbdev->csf.scheduler.doorbell_inuse_bitmap,
-+ CSF_NUM_DOORBELL);
-+
-+ if (doorbell_nr >= CSF_NUM_DOORBELL)
-+ return KBASEP_USER_DB_NR_INVALID;
-+
-+ set_bit(doorbell_nr, kbdev->csf.scheduler.doorbell_inuse_bitmap);
-+
-+ return doorbell_nr;
-+}
-+
-+static void unassign_user_doorbell_from_group(struct kbase_device *kbdev,
-+ struct kbase_queue_group *group)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (group->doorbell_nr != KBASEP_USER_DB_NR_INVALID) {
-+ release_doorbell(kbdev, group->doorbell_nr);
-+ group->doorbell_nr = KBASEP_USER_DB_NR_INVALID;
-+ }
-+}
-+
-+static void unassign_user_doorbell_from_queue(struct kbase_device *kbdev,
-+ struct kbase_queue *queue)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ mutex_lock(&kbdev->csf.reg_lock);
-+
-+ if (queue->doorbell_nr != KBASEP_USER_DB_NR_INVALID) {
-+ queue->doorbell_nr = KBASEP_USER_DB_NR_INVALID;
-+ /* After this the dummy page would be mapped in */
-+ unmap_mapping_range(kbdev->csf.db_filp->f_inode->i_mapping,
-+ queue->db_file_offset << PAGE_SHIFT, PAGE_SIZE, 1);
-+ }
-+
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+}
-+
-+static void assign_user_doorbell_to_group(struct kbase_device *kbdev,
-+ struct kbase_queue_group *group)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (group->doorbell_nr == KBASEP_USER_DB_NR_INVALID)
-+ group->doorbell_nr = acquire_doorbell(kbdev);
-+}
-+
-+static void assign_user_doorbell_to_queue(struct kbase_device *kbdev,
-+ struct kbase_queue *const queue)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ mutex_lock(&kbdev->csf.reg_lock);
-+
-+ /* If bind operation for the queue hasn't completed yet, then the
-+ * the CSI can't be programmed for the queue
-+ * (even in stopped state) and so the doorbell also can't be assigned
-+ * to it.
-+ */
-+ if ((queue->bind_state == KBASE_CSF_QUEUE_BOUND) &&
-+ (queue->doorbell_nr == KBASEP_USER_DB_NR_INVALID)) {
-+ WARN_ON(queue->group->doorbell_nr == KBASEP_USER_DB_NR_INVALID);
-+ queue->doorbell_nr = queue->group->doorbell_nr;
-+
-+ /* After this the real Hw doorbell page would be mapped in */
-+ unmap_mapping_range(
-+ kbdev->csf.db_filp->f_inode->i_mapping,
-+ queue->db_file_offset << PAGE_SHIFT,
-+ PAGE_SIZE, 1);
-+ }
-+
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+}
-+
-+static void scheduler_doorbell_init(struct kbase_device *kbdev)
-+{
-+ int doorbell_nr;
-+
-+ bitmap_zero(kbdev->csf.scheduler.doorbell_inuse_bitmap,
-+ CSF_NUM_DOORBELL);
-+
-+ mutex_lock(&kbdev->csf.scheduler.lock);
-+ /* Reserve doorbell 0 for use by kernel driver */
-+ doorbell_nr = acquire_doorbell(kbdev);
-+ mutex_unlock(&kbdev->csf.scheduler.lock);
-+
-+ WARN_ON(doorbell_nr != CSF_KERNEL_DOORBELL_NR);
-+}
-+
-+static u32 get_nr_active_csgs(struct kbase_device *kbdev)
-+{
-+ u32 nr_active_csgs;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ nr_active_csgs = bitmap_weight(kbdev->csf.scheduler.csg_inuse_bitmap,
-+ kbdev->csf.global_iface.group_num);
-+
-+ return nr_active_csgs;
-+}
-+
-+/**
-+ * csgs_active - returns true if any of CSG slots are in use
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Return: the interface is actively engaged flag.
-+ */
-+static bool csgs_active(struct kbase_device *kbdev)
-+{
-+ u32 nr_active_csgs;
-+
-+ mutex_lock(&kbdev->csf.scheduler.lock);
-+ nr_active_csgs = get_nr_active_csgs(kbdev);
-+ mutex_unlock(&kbdev->csf.scheduler.lock);
-+
-+ /* Right now if any of the CSG interfaces are in use
-+ * then we need to assume that there is some work pending.
-+ * In future when we have IDLE notifications from firmware implemented
-+ * then we would have a better idea of the pending work.
-+ */
-+ return (nr_active_csgs != 0);
-+}
-+
-+/**
-+ * csg_slot_in_use - returns true if a queue group has been programmed on a
-+ * given CSG slot.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @slot: Index/number of the CSG slot in question.
-+ *
-+ * Return: the interface is actively engaged flag.
-+ *
-+ * Note: Caller must hold the scheduler lock.
-+ */
-+static inline bool csg_slot_in_use(struct kbase_device *kbdev, int slot)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ return (kbdev->csf.scheduler.csg_slots[slot].resident_group != NULL);
-+}
-+
-+static bool queue_group_suspended_locked(struct kbase_queue_group *group)
-+{
-+ lockdep_assert_held(&group->kctx->kbdev->csf.scheduler.lock);
-+
-+ return (group->run_state == KBASE_CSF_GROUP_SUSPENDED ||
-+ group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_IDLE ||
-+ group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC);
-+}
-+
-+static bool queue_group_idle_locked(struct kbase_queue_group *group)
-+{
-+ lockdep_assert_held(&group->kctx->kbdev->csf.scheduler.lock);
-+
-+ return (group->run_state == KBASE_CSF_GROUP_IDLE ||
-+ group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_IDLE);
-+}
-+
-+static bool queue_group_scheduled(struct kbase_queue_group *group)
-+{
-+ return (group->run_state != KBASE_CSF_GROUP_INACTIVE &&
-+ group->run_state != KBASE_CSF_GROUP_TERMINATED &&
-+ group->run_state != KBASE_CSF_GROUP_FAULT_EVICTED);
-+}
-+
-+static bool queue_group_scheduled_locked(struct kbase_queue_group *group)
-+{
-+ lockdep_assert_held(&group->kctx->kbdev->csf.scheduler.lock);
-+
-+ return queue_group_scheduled(group);
-+}
-+
-+/**
-+ * scheduler_wait_protm_quit() - Wait for GPU to exit protected mode.
-+ *
-+ * @kbdev: Pointer to the GPU device
-+ *
-+ * This function waits for the GPU to exit protected mode which is confirmed
-+ * when active_protm_grp is set to NULL.
-+ */
-+static void scheduler_wait_protm_quit(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ long wt = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+ long remaining;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_WAIT_PROTM_QUIT, NULL,
-+ jiffies_to_msecs(wt));
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ !kbase_csf_scheduler_protected_mode_in_use(kbdev), wt);
-+
-+ if (!remaining)
-+ dev_warn(kbdev->dev, "Timeout, protm_quit wait skipped");
-+
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_WAIT_PROTM_QUIT_DONE, NULL,
-+ jiffies_to_msecs(remaining));
-+}
-+
-+/**
-+ * scheduler_force_protm_exit() - Force GPU to exit protected mode.
-+ *
-+ * @kbdev: Pointer to the GPU device
-+ *
-+ * This function sends a ping request to the firmware and waits for the GPU
-+ * to exit protected mode.
-+ */
-+static void scheduler_force_protm_exit(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ kbase_csf_firmware_ping(kbdev);
-+ scheduler_wait_protm_quit(kbdev);
-+}
-+
-+/**
-+ * scheduler_timer_is_enabled_nolock() - Check if the scheduler wakes up
-+ * automatically for periodic tasks.
-+ *
-+ * @kbdev: Pointer to the device
-+ *
-+ * This is a variant of kbase_csf_scheduler_timer_is_enabled() that assumes the
-+ * CSF scheduler lock to already have been held.
-+ *
-+ * Return: true if the scheduler is configured to wake up periodically
-+ */
-+static bool scheduler_timer_is_enabled_nolock(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ return kbdev->csf.scheduler.timer_enabled;
-+}
-+
-+static void enable_gpu_idle_fw_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (scheduler->gpu_idle_fw_timer_enabled)
-+ return;
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+
-+ /* Update the timer_enabled flag requires holding interrupt_lock */
-+ scheduler->gpu_idle_fw_timer_enabled = true;
-+ kbase_csf_firmware_enable_gpu_idle_timer(kbdev);
-+
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+}
-+
-+static void disable_gpu_idle_fw_timer_locked(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+ lockdep_assert_held(&scheduler->interrupt_lock);
-+
-+ /* Update of the timer_enabled flag requires holding interrupt_lock */
-+ if (scheduler->gpu_idle_fw_timer_enabled) {
-+ scheduler->gpu_idle_fw_timer_enabled = false;
-+ kbase_csf_firmware_disable_gpu_idle_timer(kbdev);
-+ }
-+}
-+
-+static void disable_gpu_idle_fw_timer(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (!scheduler->gpu_idle_fw_timer_enabled)
-+ return;
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ disable_gpu_idle_fw_timer_locked(kbdev);
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+}
-+
-+static void scheduler_wakeup(struct kbase_device *kbdev, bool kick)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (scheduler->state == SCHED_SUSPENDED) {
-+ dev_dbg(kbdev->dev, "Re-activating the Scheduler");
-+ kbase_csf_scheduler_pm_active(kbdev);
-+ scheduler->state = SCHED_INACTIVE;
-+
-+ if (kick)
-+ scheduler_enable_tick_timer_nolock(kbdev);
-+ }
-+}
-+
-+static void scheduler_suspend(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (!WARN_ON(scheduler->state == SCHED_SUSPENDED)) {
-+ dev_dbg(kbdev->dev, "Suspending the Scheduler");
-+ kbase_csf_scheduler_pm_idle(kbdev);
-+ scheduler->state = SCHED_SUSPENDED;
-+ }
-+}
-+
-+/**
-+ * update_idle_suspended_group_state() - Move the queue group to a non-idle
-+ * suspended state.
-+ * @group: Pointer to the queue group.
-+ *
-+ * This function is called to change the state of queue group to non-idle
-+ * suspended state, if the group was suspended when all the queues bound to it
-+ * became empty or when some queues got blocked on a sync wait & others became
-+ * empty. The group is also moved to the runnable list from idle wait list in
-+ * the latter case.
-+ * So the function gets called when a queue is kicked or sync wait condition
-+ * gets satisfied.
-+ */
-+static void update_idle_suspended_group_state(struct kbase_queue_group *group)
-+{
-+ struct kbase_csf_scheduler *scheduler =
-+ &group->kctx->kbdev->csf.scheduler;
-+ int new_val;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC) {
-+ remove_group_from_idle_wait(group);
-+ insert_group_to_runnable(scheduler, group,
-+ KBASE_CSF_GROUP_SUSPENDED);
-+ } else if (group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_IDLE) {
-+ group->run_state = KBASE_CSF_GROUP_SUSPENDED;
-+
-+ /* If scheduler is not suspended and the given group's
-+ * static priority (reflected by the scan_seq_num) is inside
-+ * the current tick slot-range, schedules an async tock.
-+ */
-+ if (scheduler->state != SCHED_SUSPENDED &&
-+ group->scan_seq_num < scheduler->num_csg_slots_for_tick)
-+ schedule_in_cycle(group, true);
-+ } else
-+ return;
-+
-+ new_val = atomic_inc_return(&scheduler->non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC,
-+ group, new_val);
-+}
-+
-+int kbase_csf_scheduler_group_get_slot_locked(struct kbase_queue_group *group)
-+{
-+ struct kbase_csf_scheduler *scheduler =
-+ &group->kctx->kbdev->csf.scheduler;
-+ int slot_num = group->csg_nr;
-+
-+ lockdep_assert_held(&scheduler->interrupt_lock);
-+
-+ if (slot_num >= 0) {
-+ if (WARN_ON(scheduler->csg_slots[slot_num].resident_group !=
-+ group))
-+ return -1;
-+ }
-+
-+ return slot_num;
-+}
-+
-+int kbase_csf_scheduler_group_get_slot(struct kbase_queue_group *group)
-+{
-+ struct kbase_csf_scheduler *scheduler =
-+ &group->kctx->kbdev->csf.scheduler;
-+ unsigned long flags;
-+ int slot_num;
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ slot_num = kbase_csf_scheduler_group_get_slot_locked(group);
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+
-+ return slot_num;
-+}
-+
-+static bool kbasep_csf_scheduler_group_is_on_slot_locked(
-+ struct kbase_queue_group *group)
-+{
-+ struct kbase_csf_scheduler *scheduler =
-+ &group->kctx->kbdev->csf.scheduler;
-+ int slot_num = group->csg_nr;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (slot_num >= 0) {
-+ if (!WARN_ON(scheduler->csg_slots[slot_num].resident_group !=
-+ group))
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+bool kbase_csf_scheduler_group_events_enabled(struct kbase_device *kbdev,
-+ struct kbase_queue_group *group)
-+{
-+ struct kbase_csf_scheduler *scheduler =
-+ &group->kctx->kbdev->csf.scheduler;
-+ int slot_num = group->csg_nr;
-+
-+ lockdep_assert_held(&scheduler->interrupt_lock);
-+
-+ if (WARN_ON(slot_num < 0))
-+ return false;
-+
-+ return test_bit(slot_num, scheduler->csgs_events_enable_mask);
-+}
-+
-+struct kbase_queue_group *kbase_csf_scheduler_get_group_on_slot(
-+ struct kbase_device *kbdev, int slot)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.interrupt_lock);
-+
-+ return kbdev->csf.scheduler.csg_slots[slot].resident_group;
-+}
-+
-+static int halt_stream_sync(struct kbase_queue *queue)
-+{
-+ struct kbase_queue_group *group = queue->group;
-+ struct kbase_device *kbdev = queue->kctx->kbdev;
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ struct kbase_csf_cmd_stream_group_info *ginfo;
-+ struct kbase_csf_cmd_stream_info *stream;
-+ int csi_index = queue->csi_index;
-+ long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+
-+ if (WARN_ON(!group) ||
-+ WARN_ON(!kbasep_csf_scheduler_group_is_on_slot_locked(group)))
-+ return -EINVAL;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+ ginfo = &global_iface->groups[group->csg_nr];
-+ stream = &ginfo->streams[csi_index];
-+
-+ if (CS_REQ_STATE_GET(kbase_csf_firmware_cs_input_read(stream, CS_REQ)) ==
-+ CS_REQ_STATE_START) {
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ (CS_ACK_STATE_GET(kbase_csf_firmware_cs_output(stream, CS_ACK))
-+ == CS_ACK_STATE_START), remaining);
-+
-+ if (!remaining) {
-+ dev_warn(kbdev->dev, "Timed out waiting for queue to start on csi %d bound to group %d on slot %d",
-+ csi_index, group->handle, group->csg_nr);
-+ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
-+ kbase_reset_gpu(kbdev);
-+
-+ return -ETIMEDOUT;
-+ }
-+
-+ remaining =
-+ kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+ }
-+
-+ /* Set state to STOP */
-+ kbase_csf_firmware_cs_input_mask(stream, CS_REQ, CS_REQ_STATE_STOP,
-+ CS_REQ_STATE_MASK);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_STOP_REQUESTED, group, queue, 0u);
-+ kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, group->csg_nr, true);
-+
-+ /* Timed wait */
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ (CS_ACK_STATE_GET(kbase_csf_firmware_cs_output(stream, CS_ACK))
-+ == CS_ACK_STATE_STOP), remaining);
-+
-+ if (!remaining) {
-+ dev_warn(kbdev->dev, "Timed out waiting for queue to stop on csi %d bound to group %d on slot %d",
-+ queue->csi_index, group->handle, group->csg_nr);
-+
-+ /* TODO GPUCORE-25328: The CSG can't be terminated, the GPU
-+ * will be reset as a work-around.
-+ */
-+ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
-+ kbase_reset_gpu(kbdev);
-+ }
-+ return (remaining) ? 0 : -ETIMEDOUT;
-+}
-+
-+static bool can_halt_stream(struct kbase_device *kbdev,
-+ struct kbase_queue_group *group)
-+{
-+ struct kbase_csf_csg_slot *const csg_slot =
-+ kbdev->csf.scheduler.csg_slots;
-+ unsigned long flags;
-+ bool can_halt;
-+ int slot;
-+
-+ if (!queue_group_scheduled(group))
-+ return true;
-+
-+ spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, flags);
-+ slot = kbase_csf_scheduler_group_get_slot_locked(group);
-+ can_halt = (slot >= 0) &&
-+ (atomic_read(&csg_slot[slot].state) == CSG_SLOT_RUNNING);
-+ spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock,
-+ flags);
-+
-+ return can_halt;
-+}
-+
-+/**
-+ * sched_halt_stream() - Stop a GPU queue when its queue group is not running
-+ * on a CSG slot.
-+ * @queue: Pointer to the GPU queue to stop.
-+ *
-+ * This function handles stopping gpu queues for groups that are either not on
-+ * a CSG slot or are on the slot but undergoing transition to
-+ * resume or suspend states.
-+ * It waits until the queue group is scheduled on a slot and starts running,
-+ * which is needed as groups that were suspended may need to resume all queues
-+ * that were enabled and running at the time of suspension.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+static int sched_halt_stream(struct kbase_queue *queue)
-+{
-+ struct kbase_queue_group *group = queue->group;
-+ struct kbase_device *kbdev = queue->kctx->kbdev;
-+ struct kbase_csf_scheduler *const scheduler =
-+ &kbdev->csf.scheduler;
-+ struct kbase_csf_csg_slot *const csg_slot =
-+ kbdev->csf.scheduler.csg_slots;
-+ bool retry_needed = false;
-+ bool retried = false;
-+ long remaining;
-+ int slot;
-+ int err = 0;
-+
-+ if (WARN_ON(!group))
-+ return -EINVAL;
-+
-+ lockdep_assert_held(&queue->kctx->csf.lock);
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ slot = kbase_csf_scheduler_group_get_slot(group);
-+
-+ if (slot >= 0) {
-+ WARN_ON(atomic_read(&csg_slot[slot].state) == CSG_SLOT_RUNNING);
-+
-+ if (atomic_read(&csg_slot[slot].state) == CSG_SLOT_READY2RUN) {
-+ dev_dbg(kbdev->dev, "Stopping a queue on csi %d when Group-%d is in under transition to running state",
-+ queue->csi_index, group->handle);
-+ retry_needed = true;
-+ }
-+ }
-+retry:
-+ /* Update the group state so that it can get scheduled soon */
-+ update_idle_suspended_group_state(group);
-+
-+ mutex_unlock(&scheduler->lock);
-+
-+ /* This function is called when the queue group is either not on a CSG
-+ * slot or is on the slot but undergoing transition.
-+ *
-+ * To stop the queue, the function needs to wait either for the queue
-+ * group to be assigned a CSG slot (and that slot has to reach the
-+ * running state) or for the eviction of the queue group from the
-+ * scheduler's list.
-+ *
-+ * In order to evaluate the latter condition, the function doesn't
-+ * really need to lock the scheduler, as any update to the run_state
-+ * of the queue group by sched_evict_group() would be visible due
-+ * to implicit barriers provided by the kernel waitqueue macros.
-+ *
-+ * The group pointer cannot disappear meanwhile, as the high level
-+ * CSF context is locked. Therefore, the scheduler would be
-+ * the only one to update the run_state of the group.
-+ */
-+ remaining = wait_event_timeout(
-+ kbdev->csf.event_wait, can_halt_stream(kbdev, group),
-+ kbase_csf_timeout_in_jiffies(
-+ 20 * kbdev->csf.scheduler.csg_scheduling_period_ms));
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ if (remaining && queue_group_scheduled_locked(group)) {
-+ slot = kbase_csf_scheduler_group_get_slot(group);
-+
-+ /* If the group is still on slot and slot is in running state
-+ * then explicitly stop the CSI of the
-+ * queue. Otherwise there are different cases to consider
-+ *
-+ * - If the queue group was already undergoing transition to
-+ * resume/start state when this function was entered then it
-+ * would not have disabled the CSI of the
-+ * queue being stopped and the previous wait would have ended
-+ * once the slot was in a running state with CS
-+ * interface still enabled.
-+ * Now the group is going through another transition either
-+ * to a suspend state or to a resume state (it could have
-+ * been suspended before the scheduler lock was grabbed).
-+ * In both scenarios need to wait again for the group to
-+ * come on a slot and that slot to reach the running state,
-+ * as that would guarantee that firmware will observe the
-+ * CSI as disabled.
-+ *
-+ * - If the queue group was either off the slot or was
-+ * undergoing transition to suspend state on entering this
-+ * function, then the group would have been resumed with the
-+ * queue's CSI in disabled state.
-+ * So now if the group is undergoing another transition
-+ * (after the resume) then just need to wait for the state
-+ * bits in the ACK register of CSI to be
-+ * set to STOP value. It is expected that firmware will
-+ * process the stop/disable request of the CS
-+ * interface after resuming the group before it processes
-+ * another state change request of the group.
-+ */
-+ if ((slot >= 0) &&
-+ (atomic_read(&csg_slot[slot].state) == CSG_SLOT_RUNNING)) {
-+ err = halt_stream_sync(queue);
-+ } else if (retry_needed && !retried) {
-+ retried = true;
-+ goto retry;
-+ } else if (slot >= 0) {
-+ struct kbase_csf_global_iface *global_iface =
-+ &kbdev->csf.global_iface;
-+ struct kbase_csf_cmd_stream_group_info *ginfo =
-+ &global_iface->groups[slot];
-+ struct kbase_csf_cmd_stream_info *stream =
-+ &ginfo->streams[queue->csi_index];
-+ u32 cs_req =
-+ kbase_csf_firmware_cs_input_read(stream, CS_REQ);
-+
-+ if (!WARN_ON(CS_REQ_STATE_GET(cs_req) !=
-+ CS_REQ_STATE_STOP)) {
-+ /* Timed wait */
-+ remaining = wait_event_timeout(
-+ kbdev->csf.event_wait,
-+ (CS_ACK_STATE_GET(
-+ kbase_csf_firmware_cs_output(
-+ stream, CS_ACK)) ==
-+ CS_ACK_STATE_STOP),
-+ kbdev->csf.fw_timeout_ms);
-+
-+ if (!remaining) {
-+ dev_warn(kbdev->dev,
-+ "Timed out waiting for queue stop ack on csi %d bound to group %d on slot %d",
-+ queue->csi_index,
-+ group->handle, group->csg_nr);
-+ err = -ETIMEDOUT;
-+ }
-+ }
-+ }
-+ } else if (!remaining) {
-+ dev_warn(kbdev->dev, "Group-%d failed to get a slot for stopping the queue on csi %d",
-+ group->handle, queue->csi_index);
-+ err = -ETIMEDOUT;
-+ }
-+
-+ return err;
-+}
-+
-+int kbase_csf_scheduler_queue_stop(struct kbase_queue *queue)
-+{
-+ struct kbase_device *kbdev = queue->kctx->kbdev;
-+ struct kbase_queue_group *group = queue->group;
-+ bool const cs_enabled = queue->enabled;
-+ int err = 0;
-+
-+ if (WARN_ON(!group))
-+ return -EINVAL;
-+
-+ kbase_reset_gpu_assert_failed_or_prevented(kbdev);
-+ lockdep_assert_held(&queue->kctx->csf.lock);
-+ mutex_lock(&kbdev->csf.scheduler.lock);
-+
-+ queue->enabled = false;
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_STOP, group, queue, cs_enabled);
-+
-+ if (cs_enabled && queue_group_scheduled_locked(group)) {
-+ struct kbase_csf_csg_slot *const csg_slot =
-+ kbdev->csf.scheduler.csg_slots;
-+ int slot = kbase_csf_scheduler_group_get_slot(group);
-+
-+ /* Since the group needs to be resumed in order to stop the queue,
-+ * check if GPU needs to be powered up.
-+ */
-+ scheduler_wakeup(kbdev, true);
-+
-+ if ((slot >= 0) &&
-+ (atomic_read(&csg_slot[slot].state) == CSG_SLOT_RUNNING))
-+ err = halt_stream_sync(queue);
-+ else
-+ err = sched_halt_stream(queue);
-+
-+ unassign_user_doorbell_from_queue(kbdev, queue);
-+ }
-+
-+ mutex_unlock(&kbdev->csf.scheduler.lock);
-+ return err;
-+}
-+
-+static void update_hw_active(struct kbase_queue *queue, bool active)
-+{
-+ CSTD_UNUSED(queue);
-+ CSTD_UNUSED(active);
-+}
-+
-+static void program_cs_extract_init(struct kbase_queue *queue)
-+{
-+ u64 *input_addr = (u64 *)queue->user_io_addr;
-+ u64 *output_addr = (u64 *)(queue->user_io_addr + PAGE_SIZE);
-+
-+ input_addr[CS_EXTRACT_INIT_LO / sizeof(u64)] =
-+ output_addr[CS_EXTRACT_LO / sizeof(u64)];
-+}
-+
-+static void program_cs_trace_cfg(struct kbase_csf_cmd_stream_info *stream,
-+ struct kbase_queue *queue)
-+{
-+ struct kbase_device *kbdev = queue->kctx->kbdev;
-+ u32 const glb_version = kbdev->csf.global_iface.version;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ /* If cs_trace_command not supported, nothing to program */
-+ if (glb_version < kbase_csf_interface_version(1, 1, 0))
-+ return;
-+
-+ /* Program for cs_trace if enabled. In the current arrangement, it is
-+ * possible for the context to enable the cs_trace after some queues
-+ * has been registered in cs_trace in disabled state. This is tracked by
-+ * the queue's trace buffer base address, which had been validated at the
-+ * queue's register_ex call.
-+ */
-+ if (kbase_csf_scheduler_queue_has_trace(queue)) {
-+ u32 cs_cfg = CS_INSTR_CONFIG_JASID_SET(
-+ queue->trace_cfg, queue->kctx->as_nr);
-+
-+ kbase_csf_firmware_cs_input(stream, CS_INSTR_CONFIG, cs_cfg);
-+ kbase_csf_firmware_cs_input(stream, CS_INSTR_BUFFER_SIZE,
-+ queue->trace_buffer_size);
-+
-+ kbase_csf_firmware_cs_input(stream, CS_INSTR_BUFFER_BASE_LO,
-+ queue->trace_buffer_base & U32_MAX);
-+ kbase_csf_firmware_cs_input(stream, CS_INSTR_BUFFER_BASE_HI,
-+ queue->trace_buffer_base >> 32);
-+
-+ kbase_csf_firmware_cs_input(
-+ stream, CS_INSTR_BUFFER_OFFSET_POINTER_LO,
-+ queue->trace_offset_ptr & U32_MAX);
-+ kbase_csf_firmware_cs_input(
-+ stream, CS_INSTR_BUFFER_OFFSET_POINTER_HI,
-+ queue->trace_offset_ptr >> 32);
-+ } else {
-+ /* Place the configuration to the disabled condition */
-+ kbase_csf_firmware_cs_input(stream, CS_INSTR_CONFIG, 0);
-+ kbase_csf_firmware_cs_input(stream, CS_INSTR_BUFFER_SIZE, 0);
-+ }
-+}
-+
-+static void program_cs(struct kbase_device *kbdev,
-+ struct kbase_queue *queue, bool ring_csg_doorbell)
-+{
-+ struct kbase_queue_group *group = queue->group;
-+ struct kbase_csf_cmd_stream_group_info *ginfo;
-+ struct kbase_csf_cmd_stream_info *stream;
-+ int csi_index = queue->csi_index;
-+ u64 user_input;
-+ u64 user_output;
-+
-+ if (WARN_ON(!group))
-+ return;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (WARN_ON(!kbasep_csf_scheduler_group_is_on_slot_locked(group)))
-+ return;
-+
-+ ginfo = &kbdev->csf.global_iface.groups[group->csg_nr];
-+
-+ if (WARN_ON(csi_index < 0) ||
-+ WARN_ON(csi_index >= ginfo->stream_num))
-+ return;
-+
-+ assign_user_doorbell_to_queue(kbdev, queue);
-+ if (queue->doorbell_nr == KBASEP_USER_DB_NR_INVALID)
-+ return;
-+
-+ WARN_ON(queue->doorbell_nr != queue->group->doorbell_nr);
-+
-+ if (queue->enabled && queue_group_suspended_locked(group))
-+ program_cs_extract_init(queue);
-+
-+ stream = &ginfo->streams[csi_index];
-+
-+ kbase_csf_firmware_cs_input(stream, CS_BASE_LO,
-+ queue->base_addr & 0xFFFFFFFF);
-+ kbase_csf_firmware_cs_input(stream, CS_BASE_HI,
-+ queue->base_addr >> 32);
-+ kbase_csf_firmware_cs_input(stream, CS_SIZE,
-+ queue->size);
-+
-+ user_input = (queue->reg->start_pfn << PAGE_SHIFT);
-+ kbase_csf_firmware_cs_input(stream, CS_USER_INPUT_LO,
-+ user_input & 0xFFFFFFFF);
-+ kbase_csf_firmware_cs_input(stream, CS_USER_INPUT_HI,
-+ user_input >> 32);
-+
-+ user_output = ((queue->reg->start_pfn + 1) << PAGE_SHIFT);
-+ kbase_csf_firmware_cs_input(stream, CS_USER_OUTPUT_LO,
-+ user_output & 0xFFFFFFFF);
-+ kbase_csf_firmware_cs_input(stream, CS_USER_OUTPUT_HI,
-+ user_output >> 32);
-+
-+ kbase_csf_firmware_cs_input(stream, CS_CONFIG,
-+ (queue->doorbell_nr << 8) | (queue->priority & 0xF));
-+
-+ /* Program the queue's cs_trace configuration */
-+ program_cs_trace_cfg(stream, queue);
-+
-+ /* Enable all interrupts for now */
-+ kbase_csf_firmware_cs_input(stream, CS_ACK_IRQ_MASK, ~((u32)0));
-+
-+ /*
-+ * Enable the CSG idle notification once the CS's ringbuffer
-+ * becomes empty or the CS becomes sync_idle, waiting sync update
-+ * or protected mode switch.
-+ */
-+ kbase_csf_firmware_cs_input_mask(stream, CS_REQ,
-+ CS_REQ_IDLE_EMPTY_MASK | CS_REQ_IDLE_SYNC_WAIT_MASK,
-+ CS_REQ_IDLE_EMPTY_MASK | CS_REQ_IDLE_SYNC_WAIT_MASK);
-+
-+ /* Set state to START/STOP */
-+ kbase_csf_firmware_cs_input_mask(stream, CS_REQ,
-+ queue->enabled ? CS_REQ_STATE_START : CS_REQ_STATE_STOP,
-+ CS_REQ_STATE_MASK);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_START, group, queue, queue->enabled);
-+
-+ kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, group->csg_nr,
-+ ring_csg_doorbell);
-+ update_hw_active(queue, true);
-+}
-+
-+int kbase_csf_scheduler_queue_start(struct kbase_queue *queue)
-+{
-+ struct kbase_queue_group *group = queue->group;
-+ struct kbase_device *kbdev = queue->kctx->kbdev;
-+ bool const cs_enabled = queue->enabled;
-+ int err = 0;
-+ bool evicted = false;
-+
-+ kbase_reset_gpu_assert_prevented(kbdev);
-+ lockdep_assert_held(&queue->kctx->csf.lock);
-+
-+ if (WARN_ON(!group || queue->bind_state != KBASE_CSF_QUEUE_BOUND))
-+ return -EINVAL;
-+
-+ mutex_lock(&kbdev->csf.scheduler.lock);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_START, group, queue,
-+ group->run_state);
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_STATUS_WAIT, queue->group,
-+ queue, queue->status_wait);
-+
-+ if (group->run_state == KBASE_CSF_GROUP_FAULT_EVICTED) {
-+ err = -EIO;
-+ evicted = true;
-+ } else if ((group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC)
-+ && CS_STATUS_WAIT_SYNC_WAIT_GET(queue->status_wait)) {
-+ dev_dbg(kbdev->dev, "blocked queue(csi_index=%d) of group %d was kicked",
-+ queue->csi_index, group->handle);
-+ } else {
-+ err = scheduler_group_schedule(group);
-+
-+ if (!err) {
-+ queue->enabled = true;
-+ if (kbasep_csf_scheduler_group_is_on_slot_locked(group)) {
-+ if (cs_enabled) {
-+ /* In normal situation, when a queue is
-+ * already running, the queue update
-+ * would be a doorbell kick on user
-+ * side. However, if such a kick is
-+ * shortly following a start or resume,
-+ * the queue may actually in transition
-+ * hence the said kick would enter the
-+ * kernel as the hw_active flag is yet
-+ * to be set. The sheduler needs to
-+ * give a kick to the corresponding
-+ * user door-bell on such a case.
-+ */
-+ kbase_csf_ring_cs_user_doorbell(kbdev, queue);
-+ } else
-+ program_cs(kbdev, queue, true);
-+ }
-+ queue_delayed_work(system_long_wq,
-+ &kbdev->csf.scheduler.ping_work,
-+ msecs_to_jiffies(FIRMWARE_PING_INTERVAL_MS));
-+ }
-+ }
-+
-+ mutex_unlock(&kbdev->csf.scheduler.lock);
-+
-+ if (evicted)
-+ kbase_csf_term_descheduled_queue_group(group);
-+
-+ return err;
-+}
-+
-+static enum kbase_csf_csg_slot_state update_csg_slot_status(
-+ struct kbase_device *kbdev, s8 slot)
-+{
-+ struct kbase_csf_csg_slot *csg_slot =
-+ &kbdev->csf.scheduler.csg_slots[slot];
-+ struct kbase_csf_cmd_stream_group_info *ginfo =
-+ &kbdev->csf.global_iface.groups[slot];
-+ u32 state;
-+ enum kbase_csf_csg_slot_state slot_state;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ state = CSG_ACK_STATE_GET(kbase_csf_firmware_csg_output(ginfo,
-+ CSG_ACK));
-+ slot_state = atomic_read(&csg_slot->state);
-+
-+ switch (slot_state) {
-+ case CSG_SLOT_READY2RUN:
-+ if ((state == CSG_ACK_STATE_START) ||
-+ (state == CSG_ACK_STATE_RESUME)) {
-+ slot_state = CSG_SLOT_RUNNING;
-+ atomic_set(&csg_slot->state, slot_state);
-+ csg_slot->trigger_jiffies = jiffies;
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STARTED, csg_slot->resident_group, state);
-+ dev_dbg(kbdev->dev, "Group %u running on slot %d\n",
-+ csg_slot->resident_group->handle, slot);
-+ }
-+ break;
-+ case CSG_SLOT_DOWN2STOP:
-+ if ((state == CSG_ACK_STATE_SUSPEND) ||
-+ (state == CSG_ACK_STATE_TERMINATE)) {
-+ slot_state = CSG_SLOT_STOPPED;
-+ atomic_set(&csg_slot->state, slot_state);
-+ csg_slot->trigger_jiffies = jiffies;
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STOPPED, csg_slot->resident_group, state);
-+ dev_dbg(kbdev->dev, "Group %u stopped on slot %d\n",
-+ csg_slot->resident_group->handle, slot);
-+ }
-+ break;
-+ case CSG_SLOT_DOWN2STOP_TIMEDOUT:
-+ case CSG_SLOT_READY2RUN_TIMEDOUT:
-+ case CSG_SLOT_READY:
-+ case CSG_SLOT_RUNNING:
-+ case CSG_SLOT_STOPPED:
-+ break;
-+ default:
-+ dev_warn(kbdev->dev, "Unknown CSG slot state %d", slot_state);
-+ break;
-+ }
-+
-+ return slot_state;
-+}
-+
-+static bool csg_slot_running(struct kbase_device *kbdev, s8 slot)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ return (update_csg_slot_status(kbdev, slot) == CSG_SLOT_RUNNING);
-+}
-+
-+static bool csg_slot_stopped_locked(struct kbase_device *kbdev, s8 slot)
-+{
-+ enum kbase_csf_csg_slot_state slot_state;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ slot_state = update_csg_slot_status(kbdev, slot);
-+
-+ return (slot_state == CSG_SLOT_STOPPED ||
-+ slot_state == CSG_SLOT_READY);
-+}
-+
-+static bool csg_slot_stopped_raw(struct kbase_device *kbdev, s8 slot)
-+{
-+ struct kbase_csf_cmd_stream_group_info *ginfo =
-+ &kbdev->csf.global_iface.groups[slot];
-+ u32 state;
-+
-+ state = CSG_ACK_STATE_GET(kbase_csf_firmware_csg_output(ginfo,
-+ CSG_ACK));
-+
-+ if (state == CSG_ACK_STATE_SUSPEND || state == CSG_ACK_STATE_TERMINATE) {
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STOPPED, kbdev->csf.scheduler.csg_slots[slot].resident_group, state);
-+ dev_dbg(kbdev->dev, "(raw status) slot %d stopped\n", slot);
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+static void halt_csg_slot(struct kbase_queue_group *group, bool suspend)
-+{
-+ struct kbase_device *kbdev = group->kctx->kbdev;
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ struct kbase_csf_csg_slot *csg_slot =
-+ kbdev->csf.scheduler.csg_slots;
-+ s8 slot;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (WARN_ON(!kbasep_csf_scheduler_group_is_on_slot_locked(group)))
-+ return;
-+
-+ slot = group->csg_nr;
-+
-+ /* When in transition, wait for it to complete */
-+ if (atomic_read(&csg_slot[slot].state) == CSG_SLOT_READY2RUN) {
-+ long remaining =
-+ kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+
-+ dev_dbg(kbdev->dev, "slot %d wait for up-running\n", slot);
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ csg_slot_running(kbdev, slot), remaining);
-+ if (!remaining)
-+ dev_warn(kbdev->dev,
-+ "slot %d timed out on up-running\n", slot);
-+ }
-+
-+ if (csg_slot_running(kbdev, slot)) {
-+ unsigned long flags;
-+ struct kbase_csf_cmd_stream_group_info *ginfo =
-+ &global_iface->groups[slot];
-+ u32 halt_cmd = suspend ? CSG_REQ_STATE_SUSPEND :
-+ CSG_REQ_STATE_TERMINATE;
-+
-+ dev_dbg(kbdev->dev, "Halting(suspend=%d) group %d of context %d_%d on slot %d",
-+ suspend, group->handle, group->kctx->tgid, group->kctx->id, slot);
-+
-+ spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, flags);
-+ /* Set state to SUSPEND/TERMINATE */
-+ kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, halt_cmd,
-+ CSG_REQ_STATE_MASK);
-+ spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock,
-+ flags);
-+ atomic_set(&csg_slot[slot].state, CSG_SLOT_DOWN2STOP);
-+ csg_slot[slot].trigger_jiffies = jiffies;
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STOP, group, halt_cmd);
-+
-+ kbase_csf_ring_csg_doorbell(kbdev, slot);
-+ }
-+}
-+
-+static void term_csg_slot(struct kbase_queue_group *group)
-+{
-+ halt_csg_slot(group, false);
-+}
-+
-+static void suspend_csg_slot(struct kbase_queue_group *group)
-+{
-+ halt_csg_slot(group, true);
-+}
-+
-+/**
-+ * evaluate_sync_update() - Evaluate the sync wait condition the GPU command
-+ * queue has been blocked on.
-+ *
-+ * @queue: Pointer to the GPU command queue
-+ *
-+ * Return: true if sync wait condition is satisfied.
-+ */
-+static bool evaluate_sync_update(struct kbase_queue *queue)
-+{
-+ struct kbase_vmap_struct *mapping;
-+ bool updated = false;
-+ u32 *sync_ptr;
-+ u32 sync_wait_cond;
-+ u32 sync_current_val;
-+ struct kbase_device *kbdev;
-+
-+ if (WARN_ON(!queue))
-+ return false;
-+
-+ kbdev = queue->kctx->kbdev;
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ sync_ptr = kbase_phy_alloc_mapping_get(queue->kctx, queue->sync_ptr,
-+ &mapping);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE, queue->group,
-+ queue, queue->sync_ptr);
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_BLOCKED_REASON,
-+ queue->group, queue, queue->blocked_reason);
-+
-+ if (!sync_ptr) {
-+ dev_dbg(queue->kctx->kbdev->dev, "sync memory VA 0x%016llX already freed",
-+ queue->sync_ptr);
-+ goto out;
-+ }
-+
-+ sync_wait_cond =
-+ CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GET(queue->status_wait);
-+
-+ WARN_ON((sync_wait_cond != CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GT) &&
-+ (sync_wait_cond != CS_STATUS_WAIT_SYNC_WAIT_CONDITION_LE));
-+
-+ sync_current_val = READ_ONCE(*sync_ptr);
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_CURRENT_VAL, queue->group,
-+ queue, sync_current_val);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_TEST_VAL, queue->group,
-+ queue, queue->sync_value);
-+
-+ if (((sync_wait_cond == CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GT) &&
-+ (sync_current_val > queue->sync_value)) ||
-+ ((sync_wait_cond == CS_STATUS_WAIT_SYNC_WAIT_CONDITION_LE) &&
-+ (sync_current_val <= queue->sync_value))) {
-+ /* The sync wait condition is satisfied so the group to which
-+ * queue is bound can be re-scheduled.
-+ */
-+ updated = true;
-+ } else {
-+ dev_dbg(queue->kctx->kbdev->dev,
-+ "sync memory not updated yet(%u)", sync_current_val);
-+ }
-+
-+ kbase_phy_alloc_mapping_put(queue->kctx, mapping);
-+out:
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_EVALUATED,
-+ queue->group, queue, updated);
-+ return updated;
-+}
-+
-+/**
-+ * save_slot_cs() - Save the state for blocked GPU command queue.
-+ *
-+ * @ginfo: Pointer to the CSG interface used by the group
-+ * the queue is bound to.
-+ * @queue: Pointer to the GPU command queue.
-+ *
-+ * This function will check if GPU command queue is blocked on a sync wait and
-+ * evaluate the wait condition. If the wait condition isn't satisfied it would
-+ * save the state needed to reevaluate the condition in future.
-+ * The group to which queue is bound shall be in idle state.
-+ *
-+ * Return: true if the queue is blocked on a sync wait operation.
-+ */
-+static
-+bool save_slot_cs(struct kbase_csf_cmd_stream_group_info const *const ginfo,
-+ struct kbase_queue *queue)
-+{
-+ struct kbase_csf_cmd_stream_info *const stream =
-+ &ginfo->streams[queue->csi_index];
-+ u32 status = kbase_csf_firmware_cs_output(stream, CS_STATUS_WAIT);
-+ bool is_waiting = false;
-+
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(stream->kbdev, QUEUE_SYNC_STATUS_WAIT,
-+ queue->group, queue, status);
-+
-+ if (CS_STATUS_WAIT_SYNC_WAIT_GET(status)) {
-+ queue->status_wait = status;
-+ queue->sync_ptr = kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_WAIT_SYNC_POINTER_LO);
-+ queue->sync_ptr |= (u64)kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_WAIT_SYNC_POINTER_HI) << 32;
-+ queue->sync_value = kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_WAIT_SYNC_VALUE);
-+
-+ queue->sb_status = CS_STATUS_SCOREBOARDS_NONZERO_GET(
-+ kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_SCOREBOARDS));
-+ queue->blocked_reason = CS_STATUS_BLOCKED_REASON_REASON_GET(
-+ kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_BLOCKED_REASON));
-+
-+ if (!evaluate_sync_update(queue)) {
-+ is_waiting = true;
-+ } else {
-+ /* Sync object already got updated & met the condition
-+ * thus it doesn't need to be reevaluated and so can
-+ * clear the 'status_wait' here.
-+ */
-+ queue->status_wait = 0;
-+ }
-+ } else {
-+ /* Invalidate wait status info that would have been recorded if
-+ * this queue was blocked when the group (in idle state) was
-+ * suspended previously. After that the group could have been
-+ * unblocked due to the kicking of another queue bound to it &
-+ * so the wait status info would have stuck with this queue.
-+ */
-+ queue->status_wait = 0;
-+ }
-+
-+ return is_waiting;
-+}
-+
-+/**
-+ * Calculate how far in the future an event should be scheduled.
-+ *
-+ * The objective of this function is making sure that a minimum period of
-+ * time is guaranteed between handling two consecutive events.
-+ *
-+ * This function guarantees a minimum period of time between two consecutive
-+ * events: given the minimum period and the distance between the current time
-+ * and the last event, the function returns the difference between the two.
-+ * However, if more time than the minimum period has already elapsed
-+ * since the last event, the function will return 0 to schedule work to handle
-+ * the event with the lowest latency possible.
-+ *
-+ * @last_event: Timestamp of the last event, in jiffies.
-+ * @time_now: Timestamp of the new event to handle, in jiffies.
-+ * Must be successive to last_event.
-+ * @period: Minimum period between two events, in jiffies.
-+ *
-+ * Return: Time to delay work to handle the current event, in jiffies
-+ */
-+static unsigned long get_schedule_delay(unsigned long last_event,
-+ unsigned long time_now,
-+ unsigned long period)
-+{
-+ const unsigned long t_distance = time_now - last_event;
-+ const unsigned long delay_t = (t_distance < period) ?
-+ (period - t_distance) : 0;
-+
-+ return delay_t;
-+}
-+
-+static void schedule_in_cycle(struct kbase_queue_group *group, bool force)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ /* Only try to schedule work for this event if no requests are pending,
-+ * otherwise the function will end up canceling previous work requests,
-+ * and scheduler is configured to wake up periodically (or the schedule
-+ * of work needs to be enforced in situation such as entering into
-+ * protected mode).
-+ */
-+ if ((likely(scheduler_timer_is_enabled_nolock(kbdev)) || force) &&
-+ !scheduler->tock_pending_request) {
-+ const unsigned long delay =
-+ get_schedule_delay(scheduler->last_schedule, jiffies,
-+ CSF_SCHEDULER_TIME_TOCK_JIFFIES);
-+ scheduler->tock_pending_request = true;
-+ dev_dbg(kbdev->dev, "Kicking async for group %d\n",
-+ group->handle);
-+ mod_delayed_work(scheduler->wq, &scheduler->tock_work, delay);
-+ }
-+}
-+
-+static
-+void insert_group_to_runnable(struct kbase_csf_scheduler *const scheduler,
-+ struct kbase_queue_group *const group,
-+ enum kbase_csf_group_state run_state)
-+{
-+ struct kbase_context *const kctx = group->kctx;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ WARN_ON(group->run_state != KBASE_CSF_GROUP_INACTIVE);
-+
-+ if (WARN_ON(group->priority >= KBASE_QUEUE_GROUP_PRIORITY_COUNT))
-+ return;
-+
-+ group->run_state = run_state;
-+
-+ if (run_state == KBASE_CSF_GROUP_RUNNABLE)
-+ group->prepared_seq_num = KBASEP_GROUP_PREPARED_SEQ_NUM_INVALID;
-+
-+ list_add_tail(&group->link,
-+ &kctx->csf.sched.runnable_groups[group->priority]);
-+ kctx->csf.sched.num_runnable_grps++;
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_INSERT_RUNNABLE, group,
-+ kctx->csf.sched.num_runnable_grps);
-+
-+ /* Add the kctx if not yet in runnable kctxs */
-+ if (kctx->csf.sched.num_runnable_grps == 1) {
-+ /* First runnable csg, adds to the runnable_kctxs */
-+ INIT_LIST_HEAD(&kctx->csf.link);
-+ list_add_tail(&kctx->csf.link, &scheduler->runnable_kctxs);
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_INSERT_RUNNABLE, kctx, 0u);
-+ }
-+
-+ scheduler->total_runnable_grps++;
-+
-+ if (likely(scheduler_timer_is_enabled_nolock(kbdev)) &&
-+ (scheduler->total_runnable_grps == 1 ||
-+ scheduler->state == SCHED_SUSPENDED)) {
-+ dev_dbg(kbdev->dev, "Kicking scheduler on first runnable group\n");
-+ /* Fire a scheduling to start the time-slice */
-+ enqueue_tick_work(kbdev);
-+ } else
-+ schedule_in_cycle(group, false);
-+
-+ /* Since a new group has become runnable, check if GPU needs to be
-+ * powered up.
-+ */
-+ scheduler_wakeup(kbdev, false);
-+}
-+
-+static
-+void remove_group_from_runnable(struct kbase_csf_scheduler *const scheduler,
-+ struct kbase_queue_group *group,
-+ enum kbase_csf_group_state run_state)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+ struct kbase_queue_group *new_head_grp;
-+ struct list_head *list =
-+ &kctx->csf.sched.runnable_groups[group->priority];
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ WARN_ON(!queue_group_scheduled_locked(group));
-+
-+ group->run_state = run_state;
-+ list_del_init(&group->link);
-+
-+ if (scheduler->top_grp == group) {
-+ /*
-+ * Note: this disables explicit rotation in the next scheduling
-+ * cycle. However, removing the top_grp is the same as an
-+ * implicit rotation (e.g. if we instead rotated the top_ctx
-+ * and then remove top_grp)
-+ *
-+ * This implicit rotation is assumed by the scheduler rotate
-+ * functions.
-+ */
-+ scheduler->top_grp = NULL;
-+
-+ /*
-+ * Trigger a scheduling tock for a CSG containing protected
-+ * content in case there has been any in order to minimise
-+ * latency.
-+ */
-+ group = scheduler_get_protm_enter_async_group(kctx->kbdev,
-+ NULL);
-+ if (group)
-+ schedule_in_cycle(group, true);
-+ }
-+
-+ kctx->csf.sched.num_runnable_grps--;
-+ KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_REMOVE_RUNNABLE, group,
-+ kctx->csf.sched.num_runnable_grps);
-+ new_head_grp = (!list_empty(list)) ?
-+ list_first_entry(list, struct kbase_queue_group, link) :
-+ NULL;
-+ KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_HEAD_RUNNABLE, new_head_grp,
-+ 0u);
-+
-+ if (kctx->csf.sched.num_runnable_grps == 0) {
-+ struct kbase_context *new_head_kctx;
-+ struct list_head *kctx_list = &scheduler->runnable_kctxs;
-+ /* drop the kctx */
-+ list_del_init(&kctx->csf.link);
-+ if (scheduler->top_ctx == kctx)
-+ scheduler->top_ctx = NULL;
-+ KBASE_KTRACE_ADD(kctx->kbdev, SCHEDULER_REMOVE_RUNNABLE, kctx,
-+ 0u);
-+ new_head_kctx = (!list_empty(kctx_list)) ?
-+ list_first_entry(kctx_list, struct kbase_context, csf.link) :
-+ NULL;
-+ KBASE_KTRACE_ADD(kctx->kbdev, SCHEDULER_HEAD_RUNNABLE,
-+ new_head_kctx, 0u);
-+ }
-+
-+ WARN_ON(scheduler->total_runnable_grps == 0);
-+ scheduler->total_runnable_grps--;
-+ if (!scheduler->total_runnable_grps) {
-+ dev_dbg(kctx->kbdev->dev, "Scheduler idle has no runnable groups");
-+ cancel_tick_timer(kctx->kbdev);
-+ WARN_ON(atomic_read(&scheduler->non_idle_offslot_grps));
-+ if (scheduler->state != SCHED_SUSPENDED)
-+ queue_work(system_wq, &scheduler->gpu_idle_work);
-+ }
-+ KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, SCHEDULER_TOP_GRP, scheduler->top_grp,
-+ scheduler->num_active_address_spaces |
-+ (((u64)scheduler->total_runnable_grps) << 32));
-+}
-+
-+static void insert_group_to_idle_wait(struct kbase_queue_group *const group)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+
-+ lockdep_assert_held(&kctx->kbdev->csf.scheduler.lock);
-+
-+ WARN_ON(group->run_state != KBASE_CSF_GROUP_IDLE);
-+
-+ list_add_tail(&group->link, &kctx->csf.sched.idle_wait_groups);
-+ kctx->csf.sched.num_idle_wait_grps++;
-+ KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_INSERT_IDLE_WAIT, group,
-+ kctx->csf.sched.num_idle_wait_grps);
-+ group->run_state = KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC;
-+ dev_dbg(kctx->kbdev->dev,
-+ "Group-%d suspended on sync_wait, total wait_groups: %u\n",
-+ group->handle, kctx->csf.sched.num_idle_wait_grps);
-+}
-+
-+static void remove_group_from_idle_wait(struct kbase_queue_group *const group)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+ struct list_head *list = &kctx->csf.sched.idle_wait_groups;
-+ struct kbase_queue_group *new_head_grp;
-+
-+ lockdep_assert_held(&kctx->kbdev->csf.scheduler.lock);
-+
-+ WARN_ON(group->run_state != KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC);
-+
-+ list_del_init(&group->link);
-+ WARN_ON(kctx->csf.sched.num_idle_wait_grps == 0);
-+ kctx->csf.sched.num_idle_wait_grps--;
-+ KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_REMOVE_IDLE_WAIT, group,
-+ kctx->csf.sched.num_idle_wait_grps);
-+ new_head_grp = (!list_empty(list)) ?
-+ list_first_entry(list, struct kbase_queue_group, link) :
-+ NULL;
-+ KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_HEAD_IDLE_WAIT,
-+ new_head_grp, 0u);
-+ group->run_state = KBASE_CSF_GROUP_INACTIVE;
-+}
-+
-+static void deschedule_idle_wait_group(struct kbase_csf_scheduler *scheduler,
-+ struct kbase_queue_group *group)
-+{
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (WARN_ON(!group))
-+ return;
-+
-+ remove_group_from_runnable(scheduler, group, KBASE_CSF_GROUP_IDLE);
-+ insert_group_to_idle_wait(group);
-+}
-+
-+static void update_offslot_non_idle_cnt_for_faulty_grp(struct kbase_queue_group *group)
-+{
-+ struct kbase_device *kbdev = group->kctx->kbdev;
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (group->prepared_seq_num < scheduler->non_idle_scanout_grps) {
-+ int new_val =
-+ atomic_dec_return(&scheduler->non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC,
-+ group, new_val);
-+ }
-+}
-+
-+static void update_offslot_non_idle_cnt_for_onslot_grp(struct kbase_queue_group *group)
-+{
-+ struct kbase_device *kbdev = group->kctx->kbdev;
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ WARN_ON(group->csg_nr < 0);
-+
-+ if (group->prepared_seq_num < scheduler->non_idle_scanout_grps) {
-+ int new_val =
-+ atomic_dec_return(&scheduler->non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC,
-+ group, new_val);
-+ }
-+}
-+
-+static void update_offslot_non_idle_cnt_on_grp_suspend(
-+ struct kbase_queue_group *group)
-+{
-+ struct kbase_device *kbdev = group->kctx->kbdev;
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (scheduler->state == SCHED_BUSY) {
-+ /* active phase or, async entering the protected mode */
-+ if (group->prepared_seq_num >=
-+ scheduler->non_idle_scanout_grps) {
-+ /* At scanout, it was tagged as on-slot idle */
-+ if (group->run_state == KBASE_CSF_GROUP_SUSPENDED) {
-+ int new_val = atomic_inc_return(
-+ &scheduler->non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC,
-+ group, new_val);
-+ }
-+ } else {
-+ if (group->run_state != KBASE_CSF_GROUP_SUSPENDED) {
-+ int new_val = atomic_dec_return(
-+ &scheduler->non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC,
-+ group, new_val);
-+ }
-+ }
-+ } else {
-+ /* async phases */
-+ if (group->run_state == KBASE_CSF_GROUP_SUSPENDED) {
-+ int new_val = atomic_inc_return(
-+ &scheduler->non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC,
-+ group, new_val);
-+ }
-+ }
-+}
-+
-+static bool confirm_cmd_buf_empty(struct kbase_queue *queue)
-+{
-+ bool cs_empty;
-+ bool cs_idle;
-+ u32 sb_status = 0;
-+
-+ struct kbase_device const *const kbdev = queue->group->kctx->kbdev;
-+ struct kbase_csf_global_iface const *const iface =
-+ &kbdev->csf.global_iface;
-+
-+ u32 glb_version = iface->version;
-+
-+ u64 *input_addr = (u64 *)queue->user_io_addr;
-+ u64 *output_addr = (u64 *)(queue->user_io_addr + PAGE_SIZE);
-+
-+ if (glb_version >= kbase_csf_interface_version(1, 0, 0)) {
-+ /* CS_STATUS_SCOREBOARD supported from CSF 1.0 */
-+ struct kbase_csf_cmd_stream_group_info const *const ginfo =
-+ &kbdev->csf.global_iface.groups[queue->group->csg_nr];
-+ struct kbase_csf_cmd_stream_info const *const stream =
-+ &ginfo->streams[queue->csi_index];
-+
-+ sb_status = CS_STATUS_SCOREBOARDS_NONZERO_GET(
-+ kbase_csf_firmware_cs_output(stream,
-+ CS_STATUS_SCOREBOARDS));
-+ }
-+
-+ cs_empty = (input_addr[CS_INSERT_LO / sizeof(u64)] ==
-+ output_addr[CS_EXTRACT_LO / sizeof(u64)]);
-+ cs_idle = cs_empty && (!sb_status);
-+
-+ return cs_idle;
-+}
-+
-+static void save_csg_slot(struct kbase_queue_group *group)
-+{
-+ struct kbase_device *kbdev = group->kctx->kbdev;
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ struct kbase_csf_cmd_stream_group_info *ginfo;
-+ u32 state;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (WARN_ON(!kbasep_csf_scheduler_group_is_on_slot_locked(group)))
-+ return;
-+
-+ ginfo = &kbdev->csf.global_iface.groups[group->csg_nr];
-+
-+ state =
-+ CSG_ACK_STATE_GET(kbase_csf_firmware_csg_output(ginfo, CSG_ACK));
-+
-+ if (!WARN_ON((state != CSG_ACK_STATE_SUSPEND) &&
-+ (state != CSG_ACK_STATE_TERMINATE))) {
-+ u32 max_streams = ginfo->stream_num;
-+ u32 i;
-+ bool sync_wait = false;
-+ bool idle = kbase_csf_firmware_csg_output(ginfo, CSG_STATUS_STATE) &
-+ CSG_STATUS_STATE_IDLE_MASK;
-+ for (i = 0; idle && i < max_streams; i++) {
-+ struct kbase_queue *const queue =
-+ group->bound_queues[i];
-+
-+ if (!queue || !queue->enabled)
-+ continue;
-+
-+ if (save_slot_cs(ginfo, queue))
-+ sync_wait = true;
-+ else {
-+ /* Need to confirm if ringbuffer of the GPU
-+ * queue is empty or not. A race can arise
-+ * between the flush of GPU queue and suspend
-+ * of CSG. If a queue is flushed after FW has
-+ * set the IDLE bit in CSG_STATUS_STATE, then
-+ * Scheduler will incorrectly consider CSG
-+ * as idle. And there may not be any further
-+ * flush call for the GPU queue, which would
-+ * have de-idled the CSG.
-+ */
-+ idle = confirm_cmd_buf_empty(queue);
-+ }
-+ }
-+
-+ if (idle) {
-+ /* Take the suspended group out of the runnable_groups
-+ * list of the context and move it to the
-+ * idle_wait_groups list.
-+ */
-+ if (sync_wait)
-+ deschedule_idle_wait_group(scheduler, group);
-+ else {
-+ group->run_state =
-+ KBASE_CSF_GROUP_SUSPENDED_ON_IDLE;
-+ dev_dbg(kbdev->dev, "Group-%d suspended: idle",
-+ group->handle);
-+ }
-+ } else {
-+ group->run_state = KBASE_CSF_GROUP_SUSPENDED;
-+ }
-+
-+ update_offslot_non_idle_cnt_on_grp_suspend(group);
-+ }
-+}
-+
-+/* Cleanup_csg_slot after it has been vacated, ready for next csg run.
-+ * Return whether there is a kctx address fault associated with the group
-+ * for which the clean-up is done.
-+ */
-+static bool cleanup_csg_slot(struct kbase_queue_group *group)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ struct kbase_csf_cmd_stream_group_info *ginfo;
-+ s8 slot;
-+ struct kbase_csf_csg_slot *csg_slot;
-+ unsigned long flags;
-+ u32 i;
-+ bool as_fault = false;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (WARN_ON(!kbasep_csf_scheduler_group_is_on_slot_locked(group)))
-+ return as_fault;
-+
-+ slot = group->csg_nr;
-+ csg_slot = &kbdev->csf.scheduler.csg_slots[slot];
-+ ginfo = &global_iface->groups[slot];
-+
-+ /* Now loop through all the bound CSs, and clean them via a stop */
-+ for (i = 0; i < ginfo->stream_num; i++) {
-+ struct kbase_csf_cmd_stream_info *stream = &ginfo->streams[i];
-+
-+ if (group->bound_queues[i]) {
-+ if (group->bound_queues[i]->enabled) {
-+ kbase_csf_firmware_cs_input_mask(stream,
-+ CS_REQ, CS_REQ_STATE_STOP,
-+ CS_REQ_STATE_MASK);
-+ }
-+
-+ unassign_user_doorbell_from_queue(kbdev,
-+ group->bound_queues[i]);
-+ }
-+ }
-+
-+ unassign_user_doorbell_from_group(kbdev, group);
-+
-+ /* The csg does not need cleanup other than drop its AS */
-+ spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, flags);
-+ as_fault = kbase_ctx_flag(kctx, KCTX_AS_DISABLED_ON_FAULT);
-+ kbase_ctx_sched_release_ctx(kctx);
-+ if (unlikely(group->faulted))
-+ as_fault = true;
-+ spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags);
-+
-+ /* now marking the slot is vacant */
-+ spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, flags);
-+ kbdev->csf.scheduler.csg_slots[slot].resident_group = NULL;
-+ clear_bit(slot, kbdev->csf.scheduler.csg_slots_idle_mask);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_CLEAR, group,
-+ kbdev->csf.scheduler.csg_slots_idle_mask[0]);
-+
-+ group->csg_nr = KBASEP_CSG_NR_INVALID;
-+ set_bit(slot, kbdev->csf.scheduler.csgs_events_enable_mask);
-+ clear_bit(slot, kbdev->csf.scheduler.csg_inuse_bitmap);
-+ spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags);
-+
-+ csg_slot->trigger_jiffies = jiffies;
-+ atomic_set(&csg_slot->state, CSG_SLOT_READY);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_CLEANED, group, slot);
-+ dev_dbg(kbdev->dev, "Cleanup done for group %d on slot %d\n",
-+ group->handle, slot);
-+
-+ KBASE_TLSTREAM_TL_KBASE_DEVICE_DEPROGRAM_CSG(kbdev,
-+ kbdev->gpu_props.props.raw_props.gpu_id, slot);
-+
-+ return as_fault;
-+}
-+
-+static void update_csg_slot_priority(struct kbase_queue_group *group, u8 prio)
-+{
-+ struct kbase_device *kbdev = group->kctx->kbdev;
-+ struct kbase_csf_csg_slot *csg_slot;
-+ struct kbase_csf_cmd_stream_group_info *ginfo;
-+ s8 slot;
-+ u8 prev_prio;
-+ u32 ep_cfg;
-+ u32 csg_req;
-+ unsigned long flags;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (WARN_ON(!kbasep_csf_scheduler_group_is_on_slot_locked(group)))
-+ return;
-+
-+ slot = group->csg_nr;
-+ csg_slot = &kbdev->csf.scheduler.csg_slots[slot];
-+ ginfo = &kbdev->csf.global_iface.groups[slot];
-+
-+ /* CSGs remaining on-slot can be either idle or runnable.
-+ * This also applies in protected mode.
-+ */
-+ WARN_ON(!((group->run_state == KBASE_CSF_GROUP_RUNNABLE) ||
-+ (group->run_state == KBASE_CSF_GROUP_IDLE)));
-+
-+ /* Update consumes a group from scanout */
-+ update_offslot_non_idle_cnt_for_onslot_grp(group);
-+
-+ if (csg_slot->priority == prio)
-+ return;
-+
-+ /* Read the csg_ep_cfg back for updating the priority field */
-+ ep_cfg = kbase_csf_firmware_csg_input_read(ginfo, CSG_EP_REQ);
-+ prev_prio = CSG_EP_REQ_PRIORITY_GET(ep_cfg);
-+ ep_cfg = CSG_EP_REQ_PRIORITY_SET(ep_cfg, prio);
-+ kbase_csf_firmware_csg_input(ginfo, CSG_EP_REQ, ep_cfg);
-+
-+ spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, flags);
-+ csg_req = kbase_csf_firmware_csg_output(ginfo, CSG_ACK);
-+ csg_req ^= CSG_REQ_EP_CFG_MASK;
-+ kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, csg_req,
-+ CSG_REQ_EP_CFG_MASK);
-+ spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags);
-+
-+ csg_slot->priority = prio;
-+
-+ dev_dbg(kbdev->dev, "Priority for group %d of context %d_%d on slot %d to be updated from %u to %u\n",
-+ group->handle, group->kctx->tgid, group->kctx->id, slot,
-+ prev_prio, prio);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_PRIO_UPDATE, group, prev_prio);
-+
-+ kbase_csf_ring_csg_doorbell(kbdev, slot);
-+ set_bit(slot, kbdev->csf.scheduler.csg_slots_prio_update);
-+}
-+
-+static void program_csg_slot(struct kbase_queue_group *group, s8 slot,
-+ u8 prio)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
-+ const u64 shader_core_mask =
-+ kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER);
-+ const u64 tiler_core_mask =
-+ kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_TILER);
-+ const u64 compute_mask = shader_core_mask & group->compute_mask;
-+ const u64 fragment_mask = shader_core_mask & group->fragment_mask;
-+ const u64 tiler_mask = tiler_core_mask & group->tiler_mask;
-+ const u8 num_cores = kbdev->gpu_props.num_cores;
-+ const u8 compute_max = min(num_cores, group->compute_max);
-+ const u8 fragment_max = min(num_cores, group->fragment_max);
-+ const u8 tiler_max = min(CSG_TILER_MAX, group->tiler_max);
-+ struct kbase_csf_cmd_stream_group_info *ginfo;
-+ u32 ep_cfg = 0;
-+ u32 csg_req;
-+ u32 state;
-+ int i;
-+ unsigned long flags;
-+ const u64 normal_suspend_buf =
-+ group->normal_suspend_buf.reg->start_pfn << PAGE_SHIFT;
-+ struct kbase_csf_csg_slot *csg_slot =
-+ &kbdev->csf.scheduler.csg_slots[slot];
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (WARN_ON(slot < 0) &&
-+ WARN_ON(slot >= global_iface->group_num))
-+ return;
-+
-+ WARN_ON(atomic_read(&csg_slot->state) != CSG_SLOT_READY);
-+
-+ ginfo = &global_iface->groups[slot];
-+
-+ /* Pick an available address space for this context */
-+ mutex_lock(&kbdev->mmu_hw_mutex);
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_ctx_sched_retain_ctx(kctx);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ mutex_unlock(&kbdev->mmu_hw_mutex);
-+
-+ if (kctx->as_nr == KBASEP_AS_NR_INVALID) {
-+ dev_warn(kbdev->dev, "Could not get a valid AS for group %d of context %d_%d on slot %d\n",
-+ group->handle, kctx->tgid, kctx->id, slot);
-+ return;
-+ }
-+
-+ spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, flags);
-+ set_bit(slot, kbdev->csf.scheduler.csg_inuse_bitmap);
-+ kbdev->csf.scheduler.csg_slots[slot].resident_group = group;
-+ group->csg_nr = slot;
-+ spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags);
-+
-+ assign_user_doorbell_to_group(kbdev, group);
-+
-+ /* Now loop through all the bound & kicked CSs, and program them */
-+ for (i = 0; i < MAX_SUPPORTED_STREAMS_PER_GROUP; i++) {
-+ struct kbase_queue *queue = group->bound_queues[i];
-+
-+ if (queue)
-+ program_cs(kbdev, queue, false);
-+ }
-+
-+
-+ /* Endpoint programming for CSG */
-+ kbase_csf_firmware_csg_input(ginfo, CSG_ALLOW_COMPUTE_LO,
-+ compute_mask & U32_MAX);
-+ kbase_csf_firmware_csg_input(ginfo, CSG_ALLOW_COMPUTE_HI,
-+ compute_mask >> 32);
-+ kbase_csf_firmware_csg_input(ginfo, CSG_ALLOW_FRAGMENT_LO,
-+ fragment_mask & U32_MAX);
-+ kbase_csf_firmware_csg_input(ginfo, CSG_ALLOW_FRAGMENT_HI,
-+ fragment_mask >> 32);
-+ kbase_csf_firmware_csg_input(ginfo, CSG_ALLOW_OTHER,
-+ tiler_mask & U32_MAX);
-+
-+
-+ ep_cfg = CSG_EP_REQ_COMPUTE_EP_SET(ep_cfg, compute_max);
-+ ep_cfg = CSG_EP_REQ_FRAGMENT_EP_SET(ep_cfg, fragment_max);
-+ ep_cfg = CSG_EP_REQ_TILER_EP_SET(ep_cfg, tiler_max);
-+ ep_cfg = CSG_EP_REQ_PRIORITY_SET(ep_cfg, prio);
-+ kbase_csf_firmware_csg_input(ginfo, CSG_EP_REQ, ep_cfg);
-+
-+ /* Program the address space number assigned to the context */
-+ kbase_csf_firmware_csg_input(ginfo, CSG_CONFIG, kctx->as_nr);
-+
-+ kbase_csf_firmware_csg_input(ginfo, CSG_SUSPEND_BUF_LO,
-+ normal_suspend_buf & U32_MAX);
-+ kbase_csf_firmware_csg_input(ginfo, CSG_SUSPEND_BUF_HI,
-+ normal_suspend_buf >> 32);
-+
-+ if (group->protected_suspend_buf.reg) {
-+ const u64 protm_suspend_buf =
-+ group->protected_suspend_buf.reg->start_pfn <<
-+ PAGE_SHIFT;
-+ kbase_csf_firmware_csg_input(ginfo, CSG_PROTM_SUSPEND_BUF_LO,
-+ protm_suspend_buf & U32_MAX);
-+ kbase_csf_firmware_csg_input(ginfo, CSG_PROTM_SUSPEND_BUF_HI,
-+ protm_suspend_buf >> 32);
-+ }
-+
-+ /* Enable all interrupts for now */
-+ kbase_csf_firmware_csg_input(ginfo, CSG_ACK_IRQ_MASK, ~((u32)0));
-+
-+ spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, flags);
-+ csg_req = kbase_csf_firmware_csg_output(ginfo, CSG_ACK);
-+ csg_req ^= CSG_REQ_EP_CFG_MASK;
-+ kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, csg_req,
-+ CSG_REQ_EP_CFG_MASK);
-+
-+ /* Set state to START/RESUME */
-+ if (queue_group_suspended_locked(group)) {
-+ state = CSG_REQ_STATE_RESUME;
-+ } else {
-+ WARN_ON(group->run_state != KBASE_CSF_GROUP_RUNNABLE);
-+ state = CSG_REQ_STATE_START;
-+ }
-+
-+ kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ,
-+ state, CSG_REQ_STATE_MASK);
-+ spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags);
-+
-+ /* Update status before rings the door-bell, marking ready => run */
-+ atomic_set(&csg_slot->state, CSG_SLOT_READY2RUN);
-+ csg_slot->trigger_jiffies = jiffies;
-+ csg_slot->priority = prio;
-+
-+ /* Trace the programming of the CSG on the slot */
-+ KBASE_TLSTREAM_TL_KBASE_DEVICE_PROGRAM_CSG(kbdev,
-+ kbdev->gpu_props.props.raw_props.gpu_id, group->handle, slot);
-+
-+ dev_dbg(kbdev->dev, "Starting group %d of context %d_%d on slot %d with priority %u\n",
-+ group->handle, kctx->tgid, kctx->id, slot, prio);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_START, group,
-+ (((u64)ep_cfg) << 32) |
-+ ((((u32)kctx->as_nr) & 0xF) << 16) |
-+ (state & (CSG_REQ_STATE_MASK >> CS_REQ_STATE_SHIFT)));
-+
-+ kbase_csf_ring_csg_doorbell(kbdev, slot);
-+
-+ /* Programming a slot consumes a group from scanout */
-+ update_offslot_non_idle_cnt_for_onslot_grp(group);
-+}
-+
-+static void remove_scheduled_group(struct kbase_device *kbdev,
-+ struct kbase_queue_group *group)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ WARN_ON(group->prepared_seq_num ==
-+ KBASEP_GROUP_PREPARED_SEQ_NUM_INVALID);
-+ WARN_ON(list_empty(&group->link_to_schedule));
-+
-+ list_del_init(&group->link_to_schedule);
-+ scheduler->ngrp_to_schedule--;
-+ group->prepared_seq_num = KBASEP_GROUP_PREPARED_SEQ_NUM_INVALID;
-+ group->kctx->csf.sched.ngrp_to_schedule--;
-+}
-+
-+static void sched_evict_group(struct kbase_queue_group *group, bool fault,
-+ bool update_non_idle_offslot_grps_cnt)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (queue_group_scheduled_locked(group)) {
-+ u32 i;
-+
-+ if (update_non_idle_offslot_grps_cnt &&
-+ (group->run_state == KBASE_CSF_GROUP_SUSPENDED ||
-+ group->run_state == KBASE_CSF_GROUP_RUNNABLE)) {
-+ int new_val = atomic_dec_return(
-+ &scheduler->non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC,
-+ group, new_val);
-+ }
-+
-+ for (i = 0; i < MAX_SUPPORTED_STREAMS_PER_GROUP; i++) {
-+ if (group->bound_queues[i])
-+ group->bound_queues[i]->enabled = false;
-+ }
-+
-+ if (group->prepared_seq_num !=
-+ KBASEP_GROUP_PREPARED_SEQ_NUM_INVALID)
-+ remove_scheduled_group(kbdev, group);
-+
-+ if (group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC)
-+ remove_group_from_idle_wait(group);
-+ else {
-+ remove_group_from_runnable(scheduler, group,
-+ KBASE_CSF_GROUP_INACTIVE);
-+ }
-+
-+ WARN_ON(group->run_state != KBASE_CSF_GROUP_INACTIVE);
-+
-+ if (fault)
-+ group->run_state = KBASE_CSF_GROUP_FAULT_EVICTED;
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_EVICT_SCHED, group,
-+ (((u64)scheduler->total_runnable_grps) << 32) |
-+ ((u32)group->run_state));
-+ dev_dbg(kbdev->dev, "group %d exited scheduler, num_runnable_grps %d\n",
-+ group->handle, scheduler->total_runnable_grps);
-+ /* Notify a group has been evicted */
-+ wake_up_all(&kbdev->csf.event_wait);
-+ }
-+}
-+
-+static int term_group_sync(struct kbase_queue_group *group)
-+{
-+ struct kbase_device *kbdev = group->kctx->kbdev;
-+ long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+ int err = 0;
-+
-+ term_csg_slot(group);
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ csg_slot_stopped_locked(kbdev, group->csg_nr), remaining);
-+
-+ if (!remaining) {
-+ dev_warn(kbdev->dev, "term request timed out for group %d of context %d_%d on slot %d",
-+ group->handle, group->kctx->tgid,
-+ group->kctx->id, group->csg_nr);
-+ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
-+ kbase_reset_gpu(kbdev);
-+ err = -ETIMEDOUT;
-+ }
-+
-+ return err;
-+}
-+
-+void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group)
-+{
-+ struct kbase_device *kbdev = group->kctx->kbdev;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ long remaining =
-+ kbase_csf_timeout_in_jiffies(CSG_SCHED_STOP_TIMEOUT_MS);
-+ bool force = false;
-+
-+ kbase_reset_gpu_assert_failed_or_prevented(kbdev);
-+ lockdep_assert_held(&group->kctx->csf.lock);
-+ mutex_lock(&scheduler->lock);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_DESCHEDULE, group, group->run_state);
-+ while (queue_group_scheduled_locked(group)) {
-+ u32 saved_state = scheduler->state;
-+
-+ if (!kbasep_csf_scheduler_group_is_on_slot_locked(group)) {
-+ sched_evict_group(group, false, true);
-+ } else if (saved_state == SCHED_INACTIVE || force) {
-+ bool as_faulty;
-+
-+ term_group_sync(group);
-+ /* Treat the csg been terminated */
-+ as_faulty = cleanup_csg_slot(group);
-+ /* remove from the scheduler list */
-+ sched_evict_group(group, as_faulty, false);
-+ }
-+
-+ /* waiting scheduler state to change */
-+ if (queue_group_scheduled_locked(group)) {
-+ mutex_unlock(&scheduler->lock);
-+ remaining = wait_event_timeout(
-+ kbdev->csf.event_wait,
-+ saved_state != scheduler->state,
-+ remaining);
-+ if (!remaining) {
-+ dev_warn(kbdev->dev, "Scheduler state change wait timed out for group %d on slot %d",
-+ group->handle, group->csg_nr);
-+ force = true;
-+ }
-+ mutex_lock(&scheduler->lock);
-+ }
-+ }
-+
-+ mutex_unlock(&scheduler->lock);
-+}
-+
-+/**
-+ * scheduler_group_schedule() - Schedule a GPU command queue group on firmware
-+ *
-+ * @group: Pointer to the queue group to be scheduled.
-+ *
-+ * This function would enable the scheduling of GPU command queue group on
-+ * firmware.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+static int scheduler_group_schedule(struct kbase_queue_group *group)
-+{
-+ struct kbase_context *kctx = group->kctx;
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_SCHEDULE, group, group->run_state);
-+ if (group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC)
-+ update_idle_suspended_group_state(group);
-+ else if (queue_group_idle_locked(group)) {
-+ WARN_ON(kctx->csf.sched.num_runnable_grps == 0);
-+ WARN_ON(kbdev->csf.scheduler.total_runnable_grps == 0);
-+
-+ if (group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_IDLE)
-+ update_idle_suspended_group_state(group);
-+ else {
-+ struct kbase_queue_group *protm_grp;
-+ unsigned long flags;
-+
-+ WARN_ON(!kbasep_csf_scheduler_group_is_on_slot_locked(
-+ group));
-+
-+ group->run_state = KBASE_CSF_GROUP_RUNNABLE;
-+
-+ /* A normal mode CSG could be idle onslot during
-+ * protected mode. In this case clear the
-+ * appropriate bit in csg_slots_idle_mask.
-+ */
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ protm_grp = scheduler->active_protm_grp;
-+ if (protm_grp && protm_grp != group) {
-+ clear_bit((unsigned int)group->csg_nr,
-+ scheduler->csg_slots_idle_mask);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_CLEAR, group,
-+ scheduler->csg_slots_idle_mask[0]);
-+ }
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock,
-+ flags);
-+
-+ /* If GPU is in protected mode then any doorbells rang
-+ * would have no effect. Check if GPU is in protected
-+ * mode and if this group has higher priority than the
-+ * active protected mode group. If so prompt the FW
-+ * to exit protected mode.
-+ */
-+ if (protm_grp &&
-+ group->scan_seq_num < protm_grp->scan_seq_num) {
-+ /* Prompt the FW to exit protected mode */
-+ scheduler_force_protm_exit(kbdev);
-+ }
-+ }
-+ } else if (!queue_group_scheduled_locked(group)) {
-+ int new_val;
-+ insert_group_to_runnable(&kbdev->csf.scheduler, group,
-+ KBASE_CSF_GROUP_RUNNABLE);
-+ /* A new group into the scheduler */
-+ new_val = atomic_inc_return(
-+ &kbdev->csf.scheduler.non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC,
-+ group, new_val);
-+ }
-+
-+ /* Since a group has become active now, check if GPU needs to be
-+ * powered up. Also rekick the Scheduler.
-+ */
-+ scheduler_wakeup(kbdev, true);
-+
-+ return 0;
-+}
-+
-+/**
-+ * set_max_csg_slots() - Set the number of available CSG slots
-+ *
-+ * @kbdev: Pointer of the GPU device.
-+ *
-+ * This function would set/limit the number of CSG slots that
-+ * can be used in the given tick/tock. It would be less than the total CSG
-+ * slots supported by firmware if the number of GPU address space slots
-+ * required to utilize all the CSG slots is more than the available
-+ * address space slots.
-+ */
-+static inline void set_max_csg_slots(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ unsigned int total_csg_slots = kbdev->csf.global_iface.group_num;
-+ unsigned int max_address_space_slots =
-+ kbdev->nr_hw_address_spaces - NUM_RESERVED_AS_SLOTS;
-+
-+ WARN_ON(scheduler->num_active_address_spaces > total_csg_slots);
-+
-+ if (likely(scheduler->num_active_address_spaces <=
-+ max_address_space_slots))
-+ scheduler->num_csg_slots_for_tick = total_csg_slots;
-+}
-+
-+/**
-+ * count_active_address_space() - Count the number of GPU address space slots
-+ *
-+ * @kbdev: Pointer of the GPU device.
-+ * @kctx: Pointer of the Kbase context.
-+ *
-+ * This function would update the counter that is tracking the number of GPU
-+ * address space slots that would be required to program the CS
-+ * group slots from the groups at the head of groups_to_schedule list.
-+ */
-+static inline void count_active_address_space(struct kbase_device *kbdev,
-+ struct kbase_context *kctx)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ unsigned int total_csg_slots = kbdev->csf.global_iface.group_num;
-+ unsigned int max_address_space_slots =
-+ kbdev->nr_hw_address_spaces - NUM_RESERVED_AS_SLOTS;
-+
-+ if (scheduler->ngrp_to_schedule <= total_csg_slots) {
-+ if (kctx->csf.sched.ngrp_to_schedule == 1)
-+ scheduler->num_active_address_spaces++;
-+
-+ if (scheduler->num_active_address_spaces <=
-+ max_address_space_slots)
-+ scheduler->num_csg_slots_for_tick++;
-+ }
-+}
-+
-+/* Two schemes are used in assigning the priority to CSG slots for a given
-+ * CSG from the 'groups_to_schedule' list.
-+ * This is needed as an idle on-slot group is deprioritized by moving it to
-+ * the tail of 'groups_to_schedule' list. As a result it can either get
-+ * evicted from the CSG slot in current tick/tock dealing, or its position
-+ * can be after the lower priority non-idle groups in the 'groups_to_schedule'
-+ * list. The latter case can result in the on-slot subset containing both
-+ * non-idle and idle CSGs, and is handled through the 2nd scheme described
-+ * below.
-+ *
-+ * First scheme :- If all the slots are going to be occupied by the non-idle or
-+ * idle groups, then a simple assignment of the priority is done as per the
-+ * position of a group in the 'groups_to_schedule' list. So maximum priority
-+ * gets assigned to the slot of a group which is at the head of the list.
-+ * Here the 'groups_to_schedule' list would effectively be ordered as per the
-+ * static priority of groups.
-+ *
-+ * Second scheme :- If the slots are going to be occupied by a mix of idle and
-+ * non-idle groups then the priority assignment needs to ensure that the
-+ * priority of a slot belonging to a higher priority idle group will always be
-+ * greater than the priority of a slot belonging to a lower priority non-idle
-+ * group, reflecting the original position of a group in the scan order (i.e
-+ * static priority) 'scan_seq_num', which is set during the prepare phase of a
-+ * tick/tock before the group is moved to 'idle_groups_to_schedule' list if it
-+ * is idle.
-+ * The priority range [MAX_CSG_SLOT_PRIORITY, 0] is partitioned with the first
-+ * 'slots_for_tick' groups in the original scan order are assigned a priority in
-+ * the subrange [MAX_CSG_SLOT_PRIORITY, MAX_CSG_SLOT_PRIORITY - slots_for_tick),
-+ * whereas rest of the groups are assigned the priority in the subrange
-+ * [MAX_CSG_SLOT_PRIORITY - slots_for_tick, 0]. This way even if an idle higher
-+ * priority group ends up after the non-idle lower priority groups in the
-+ * 'groups_to_schedule' list, it will get a higher slot priority. And this will
-+ * enable the FW to quickly start the execution of higher priority group when it
-+ * gets de-idled.
-+ */
-+static u8 get_slot_priority(struct kbase_queue_group *group)
-+{
-+ struct kbase_csf_scheduler *scheduler =
-+ &group->kctx->kbdev->csf.scheduler;
-+ u8 slot_prio;
-+ u32 slots_for_tick = scheduler->num_csg_slots_for_tick;
-+ u32 used_slots = slots_for_tick - scheduler->remaining_tick_slots;
-+ /* Check if all the slots are going to be occupied by the non-idle or
-+ * idle groups.
-+ */
-+ if (scheduler->non_idle_scanout_grps >= slots_for_tick ||
-+ !scheduler->non_idle_scanout_grps) {
-+ slot_prio = (u8)(MAX_CSG_SLOT_PRIORITY - used_slots);
-+ } else {
-+ /* There will be a mix of idle and non-idle groups. */
-+ if (group->scan_seq_num < slots_for_tick)
-+ slot_prio = (u8)(MAX_CSG_SLOT_PRIORITY -
-+ group->scan_seq_num);
-+ else if (MAX_CSG_SLOT_PRIORITY > (slots_for_tick + used_slots))
-+ slot_prio = (u8)(MAX_CSG_SLOT_PRIORITY - (slots_for_tick + used_slots));
-+ else
-+ slot_prio = 0;
-+ }
-+ return slot_prio;
-+}
-+
-+/**
-+ * update_resident_groups_priority() - Update the priority of resident groups
-+ *
-+ * @kbdev: The GPU device.
-+ *
-+ * This function will update the priority of all resident queue groups
-+ * that are at the head of groups_to_schedule list, preceding the first
-+ * non-resident group.
-+ *
-+ * This function will also adjust kbase_csf_scheduler.remaining_tick_slots on
-+ * the priority update.
-+ */
-+static void update_resident_groups_priority(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ u32 num_groups = scheduler->num_csg_slots_for_tick;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+ while (!list_empty(&scheduler->groups_to_schedule)) {
-+ struct kbase_queue_group *group =
-+ list_first_entry(&scheduler->groups_to_schedule,
-+ struct kbase_queue_group,
-+ link_to_schedule);
-+ bool resident =
-+ kbasep_csf_scheduler_group_is_on_slot_locked(group);
-+
-+ if ((group->prepared_seq_num >= num_groups) || !resident)
-+ break;
-+
-+ update_csg_slot_priority(group,
-+ get_slot_priority(group));
-+
-+ /* Drop the head group from the list */
-+ remove_scheduled_group(kbdev, group);
-+ scheduler->remaining_tick_slots--;
-+ }
-+}
-+
-+/**
-+ * program_group_on_vacant_csg_slot() - Program a non-resident group on the
-+ * given vacant CSG slot.
-+ * @kbdev: Pointer to the GPU device.
-+ * @slot: Vacant CSG slot number.
-+ *
-+ * This function will program a non-resident group at the head of
-+ * kbase_csf_scheduler.groups_to_schedule list on the given vacant
-+ * CSG slot, provided the initial position of the non-resident
-+ * group in the list is less than the number of CSG slots and there is
-+ * an available GPU address space slot.
-+ * kbase_csf_scheduler.remaining_tick_slots would also be adjusted after
-+ * programming the slot.
-+ */
-+static void program_group_on_vacant_csg_slot(struct kbase_device *kbdev,
-+ s8 slot)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ struct kbase_queue_group *const group =
-+ list_empty(&scheduler->groups_to_schedule) ? NULL :
-+ list_first_entry(&scheduler->groups_to_schedule,
-+ struct kbase_queue_group,
-+ link_to_schedule);
-+ u32 num_groups = scheduler->num_csg_slots_for_tick;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+ if (group && (group->prepared_seq_num < num_groups)) {
-+ bool ret = kbasep_csf_scheduler_group_is_on_slot_locked(group);
-+
-+ if (!WARN_ON(ret)) {
-+ if (kctx_as_enabled(group->kctx) && !group->faulted) {
-+ program_csg_slot(group, slot,
-+ get_slot_priority(group));
-+
-+ if (likely(csg_slot_in_use(kbdev, slot))) {
-+ /* Drop the head group from the list */
-+ remove_scheduled_group(kbdev, group);
-+ scheduler->remaining_tick_slots--;
-+ }
-+ } else {
-+ update_offslot_non_idle_cnt_for_faulty_grp(
-+ group);
-+ remove_scheduled_group(kbdev, group);
-+ }
-+ }
-+ }
-+}
-+
-+/**
-+ * program_vacant_csg_slot() - Program the vacant CSG slot with a non-resident
-+ * group and update the priority of resident groups.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ * @slot: Vacant CSG slot number.
-+ *
-+ * This function will first update the priority of all resident queue groups
-+ * that are at the head of groups_to_schedule list, preceding the first
-+ * non-resident group, it will then try to program the given CS
-+ * group slot with the non-resident group. Finally update the priority of all
-+ * resident queue groups following the non-resident group.
-+ *
-+ * kbase_csf_scheduler.remaining_tick_slots would also be adjusted.
-+ */
-+static void program_vacant_csg_slot(struct kbase_device *kbdev, s8 slot)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ struct kbase_csf_csg_slot *const csg_slot =
-+ scheduler->csg_slots;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+ WARN_ON(atomic_read(&csg_slot[slot].state) != CSG_SLOT_READY);
-+
-+ /* First update priority for already resident groups (if any)
-+ * before the non-resident group
-+ */
-+ update_resident_groups_priority(kbdev);
-+
-+ /* Now consume the vacant slot for the non-resident group */
-+ program_group_on_vacant_csg_slot(kbdev, slot);
-+
-+ /* Now update priority for already resident groups (if any)
-+ * following the non-resident group
-+ */
-+ update_resident_groups_priority(kbdev);
-+}
-+
-+static bool slots_state_changed(struct kbase_device *kbdev,
-+ unsigned long *slots_mask,
-+ bool (*state_check_func)(struct kbase_device *, s8))
-+{
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+ DECLARE_BITMAP(changed_slots, MAX_SUPPORTED_CSGS) = {0};
-+ bool changed = false;
-+ u32 i;
-+
-+ for_each_set_bit(i, slots_mask, num_groups) {
-+ if (state_check_func(kbdev, (s8)i)) {
-+ set_bit(i, changed_slots);
-+ changed = true;
-+ }
-+ }
-+
-+ if (changed)
-+ bitmap_copy(slots_mask, changed_slots, MAX_SUPPORTED_CSGS);
-+
-+ return changed;
-+}
-+
-+/**
-+ * program_suspending_csg_slots() - Program the CSG slots vacated on suspension
-+ * of queue groups running on them.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ *
-+ * This function will first wait for the ongoing suspension to complete on a
-+ * CSG slot and will then program the vacant slot with the
-+ * non-resident queue group inside the groups_to_schedule list.
-+ * The programming of the non-resident queue group on the vacant slot could
-+ * fail due to unavailability of free GPU address space slot and so the
-+ * programming is re-attempted after the ongoing suspension has completed
-+ * for all the CSG slots.
-+ * The priority of resident groups before and after the non-resident group
-+ * in the groups_to_schedule list would also be updated.
-+ * This would be repeated for all the slots undergoing suspension.
-+ * GPU reset would be initiated if the wait for suspend times out.
-+ */
-+static void program_suspending_csg_slots(struct kbase_device *kbdev)
-+{
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS);
-+ DECLARE_BITMAP(evicted_mask, MAX_SUPPORTED_CSGS) = {0};
-+ bool suspend_wait_failed = false;
-+ long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ /* In the current implementation, csgs_events_enable_mask would be used
-+ * only to indicate suspending CSGs.
-+ */
-+ bitmap_complement(slot_mask, scheduler->csgs_events_enable_mask,
-+ MAX_SUPPORTED_CSGS);
-+
-+ while (!bitmap_empty(slot_mask, MAX_SUPPORTED_CSGS)) {
-+ DECLARE_BITMAP(changed, MAX_SUPPORTED_CSGS);
-+
-+ bitmap_copy(changed, slot_mask, MAX_SUPPORTED_CSGS);
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ slots_state_changed(kbdev, changed,
-+ csg_slot_stopped_raw),
-+ remaining);
-+
-+ if (remaining) {
-+ u32 i;
-+
-+ for_each_set_bit(i, changed, num_groups) {
-+ struct kbase_queue_group *group =
-+ scheduler->csg_slots[i].resident_group;
-+
-+ if (WARN_ON(!csg_slot_stopped_locked(kbdev, (s8)i))) {
-+ continue;
-+ }
-+ /* The on slot csg is now stopped */
-+ clear_bit(i, slot_mask);
-+
-+ if (likely(group)) {
-+ bool as_fault;
-+ /* Only do save/cleanup if the
-+ * group is not terminated during
-+ * the sleep.
-+ */
-+ save_csg_slot(group);
-+ as_fault = cleanup_csg_slot(group);
-+ /* If AS fault detected, evict it */
-+ if (as_fault) {
-+ sched_evict_group(group, true, true);
-+ set_bit(i, evicted_mask);
-+ }
-+ }
-+
-+ program_vacant_csg_slot(kbdev, (s8)i);
-+ }
-+ } else {
-+ u32 i;
-+
-+ /* Groups that have failed to suspend in time shall
-+ * raise a fatal error as they could no longer be
-+ * safely resumed.
-+ */
-+ for_each_set_bit(i, slot_mask, num_groups) {
-+ struct kbase_queue_group *const group =
-+ scheduler->csg_slots[i].resident_group;
-+
-+ struct base_gpu_queue_group_error const
-+ err_payload = { .error_type =
-+ BASE_GPU_QUEUE_GROUP_ERROR_FATAL,
-+ .payload = {
-+ .fatal_group = {
-+ .status =
-+ GPU_EXCEPTION_TYPE_SW_FAULT_2,
-+ } } };
-+
-+ if (unlikely(group == NULL))
-+ continue;
-+
-+ kbase_csf_add_group_fatal_error(group,
-+ &err_payload);
-+ kbase_event_wakeup(group->kctx);
-+
-+ /* TODO GPUCORE-25328: The CSG can't be
-+ * terminated, the GPU will be reset as a
-+ * work-around.
-+ */
-+ dev_warn(
-+ kbdev->dev,
-+ "Group %d of context %d_%d on slot %u failed to suspend",
-+ group->handle, group->kctx->tgid,
-+ group->kctx->id, i);
-+
-+ /* The group has failed suspension, stop
-+ * further examination.
-+ */
-+ clear_bit(i, slot_mask);
-+ set_bit(i, scheduler->csgs_events_enable_mask);
-+ update_offslot_non_idle_cnt_for_onslot_grp(
-+ group);
-+ }
-+
-+ suspend_wait_failed = true;
-+ }
-+ }
-+
-+ if (!bitmap_empty(evicted_mask, MAX_SUPPORTED_CSGS))
-+ dev_info(kbdev->dev, "Scheduler evicting slots: 0x%*pb\n",
-+ num_groups, evicted_mask);
-+
-+ if (likely(!suspend_wait_failed)) {
-+ u32 i;
-+
-+ while (scheduler->ngrp_to_schedule &&
-+ scheduler->remaining_tick_slots) {
-+ i = find_first_zero_bit(scheduler->csg_inuse_bitmap,
-+ num_groups);
-+ if (WARN_ON(i == num_groups))
-+ break;
-+ program_vacant_csg_slot(kbdev, (s8)i);
-+ if (!csg_slot_in_use(kbdev, (int)i)) {
-+ dev_warn(kbdev->dev, "Couldn't use CSG slot %d despite being vacant", i);
-+ break;
-+ }
-+ }
-+ } else {
-+ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
-+ kbase_reset_gpu(kbdev);
-+ }
-+}
-+
-+static void suspend_queue_group(struct kbase_queue_group *group)
-+{
-+ unsigned long flags;
-+ struct kbase_csf_scheduler *const scheduler =
-+ &group->kctx->kbdev->csf.scheduler;
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ /* This shall be used in program_suspending_csg_slots() where we
-+ * assume that whilst CSGs are being suspended, this bitmask is not
-+ * used by anything else i.e., it indicates only the CSGs going
-+ * through suspension.
-+ */
-+ clear_bit(group->csg_nr, scheduler->csgs_events_enable_mask);
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+
-+ /* If AS fault detected, terminate the group */
-+ if (!kctx_as_enabled(group->kctx) || group->faulted)
-+ term_csg_slot(group);
-+ else
-+ suspend_csg_slot(group);
-+}
-+
-+static void wait_csg_slots_start(struct kbase_device *kbdev)
-+{
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+ DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS) = {0};
-+ u32 i;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ /* extract start slot flags for check */
-+ for (i = 0; i < num_groups; i++) {
-+ if (atomic_read(&scheduler->csg_slots[i].state) ==
-+ CSG_SLOT_READY2RUN)
-+ set_bit(i, slot_mask);
-+ }
-+
-+ while (!bitmap_empty(slot_mask, MAX_SUPPORTED_CSGS)) {
-+ DECLARE_BITMAP(changed, MAX_SUPPORTED_CSGS);
-+
-+ bitmap_copy(changed, slot_mask, MAX_SUPPORTED_CSGS);
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ slots_state_changed(kbdev, changed, csg_slot_running),
-+ remaining);
-+
-+ if (remaining) {
-+ for_each_set_bit(i, changed, num_groups) {
-+ struct kbase_queue_group *group =
-+ scheduler->csg_slots[i].resident_group;
-+
-+ /* The on slot csg is now running */
-+ clear_bit(i, slot_mask);
-+ group->run_state = KBASE_CSF_GROUP_RUNNABLE;
-+ }
-+ } else {
-+ dev_warn(kbdev->dev, "Timed out waiting for CSG slots to start, slots: 0x%*pb\n",
-+ num_groups, slot_mask);
-+
-+ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
-+ kbase_reset_gpu(kbdev);
-+ break;
-+ }
-+ }
-+}
-+
-+/**
-+ * group_on_slot_is_idle() - Check if the given slot has a CSG-idle state
-+ * flagged after the completion of a CSG status
-+ * update command
-+ *
-+ * This function is called at the start of scheduling tick to check the
-+ * idle status of a queue group resident on a CSG slot.
-+ * The caller must make sure the corresponding status update command has
-+ * been called and completed before checking this status.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ * @slot: The given slot for checking an occupying resident group's idle
-+ * state.
-+ *
-+ * Return: true if the group resident on slot is idle, otherwise false.
-+ */
-+static bool group_on_slot_is_idle(struct kbase_device *kbdev,
-+ unsigned long slot)
-+{
-+ struct kbase_csf_cmd_stream_group_info *ginfo =
-+ &kbdev->csf.global_iface.groups[slot];
-+ bool idle = kbase_csf_firmware_csg_output(ginfo, CSG_STATUS_STATE) &
-+ CSG_STATUS_STATE_IDLE_MASK;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ return idle;
-+}
-+
-+/**
-+ * slots_update_state_changed() - Check the handshake state of a subset of
-+ * command group slots.
-+ *
-+ * Checks the state of a subset of slots selected through the slots_mask
-+ * bit_map. Records which slots' handshake completed and send it back in the
-+ * slots_done bit_map.
-+ *
-+ * @kbdev: The GPU device.
-+ * @field_mask: The field mask for checking the state in the csg_req/ack.
-+ * @slots_mask: A bit_map specifying the slots to check.
-+ * @slots_done: A cleared bit_map for returning the slots that
-+ * have finished update.
-+ *
-+ * Return: true if the slots_done is set for at least one slot.
-+ * Otherwise false.
-+ */
-+static
-+bool slots_update_state_changed(struct kbase_device *kbdev, u32 field_mask,
-+ const unsigned long *slots_mask, unsigned long *slots_done)
-+{
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+ bool changed = false;
-+ u32 i;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ for_each_set_bit(i, slots_mask, num_groups) {
-+ struct kbase_csf_cmd_stream_group_info const *const ginfo =
-+ &kbdev->csf.global_iface.groups[i];
-+ u32 state = kbase_csf_firmware_csg_input_read(ginfo, CSG_REQ);
-+
-+ state ^= kbase_csf_firmware_csg_output(ginfo, CSG_ACK);
-+
-+ if (!(state & field_mask)) {
-+ set_bit(i, slots_done);
-+ changed = true;
-+ }
-+ }
-+
-+ return changed;
-+}
-+
-+/**
-+ * wait_csg_slots_handshake_ack - Wait the req/ack handshakes to complete on
-+ * the specified groups.
-+ *
-+ * This function waits for the acknowledgement of the request that have
-+ * already been placed for the CSG slots by the caller. Currently used for
-+ * the CSG priority update and status update requests.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ * @field_mask: The field mask for checking the state in the csg_req/ack.
-+ * @slot_mask: Bitmap reflecting the slots, the function will modify
-+ * the acknowledged slots by clearing their corresponding
-+ * bits.
-+ * @wait_in_jiffies: Wait duration in jiffies, controlling the time-out.
-+ *
-+ * Return: 0 on all specified slots acknowledged; otherwise -ETIMEDOUT. For
-+ * timed out condition with unacknowledged slots, their bits remain
-+ * set in the slot_mask.
-+ */
-+static int wait_csg_slots_handshake_ack(struct kbase_device *kbdev,
-+ u32 field_mask, unsigned long *slot_mask, long wait_in_jiffies)
-+{
-+ const u32 num_groups = kbdev->csf.global_iface.group_num;
-+ long remaining = wait_in_jiffies;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ while (!bitmap_empty(slot_mask, num_groups) &&
-+ !kbase_reset_gpu_is_active(kbdev)) {
-+ DECLARE_BITMAP(dones, MAX_SUPPORTED_CSGS) = { 0 };
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ slots_update_state_changed(kbdev, field_mask,
-+ slot_mask, dones),
-+ remaining);
-+
-+ if (remaining)
-+ bitmap_andnot(slot_mask, slot_mask, dones, num_groups);
-+ else
-+ /* Timed-out on the wait */
-+ return -ETIMEDOUT;
-+ }
-+
-+ return 0;
-+}
-+
-+static void wait_csg_slots_finish_prio_update(struct kbase_device *kbdev)
-+{
-+ unsigned long *slot_mask =
-+ kbdev->csf.scheduler.csg_slots_prio_update;
-+ long wait_time = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+ int ret = wait_csg_slots_handshake_ack(kbdev, CSG_REQ_EP_CFG_MASK,
-+ slot_mask, wait_time);
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (ret != 0) {
-+ /* The update timeout is not regarded as a serious
-+ * issue, no major consequences are expected as a
-+ * result, so just warn the case.
-+ */
-+ dev_warn(
-+ kbdev->dev,
-+ "Timeout on CSG_REQ:EP_CFG, skipping the update wait: slot mask=0x%lx",
-+ slot_mask[0]);
-+ }
-+}
-+
-+void kbase_csf_scheduler_evict_ctx_slots(struct kbase_device *kbdev,
-+ struct kbase_context *kctx, struct list_head *evicted_groups)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ struct kbase_queue_group *group;
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+ u32 slot;
-+ DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS) = {0};
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+ mutex_lock(&scheduler->lock);
-+
-+ /* This code is only called during reset, so we don't wait for the CSG
-+ * slots to be stopped
-+ */
-+ WARN_ON(!kbase_reset_gpu_is_active(kbdev));
-+
-+ KBASE_KTRACE_ADD(kbdev, EVICT_CTX_SLOTS, kctx, 0u);
-+ for (slot = 0; slot < num_groups; slot++) {
-+ group = kbdev->csf.scheduler.csg_slots[slot].resident_group;
-+ if (group && group->kctx == kctx) {
-+ bool as_fault;
-+
-+ term_csg_slot(group);
-+ as_fault = cleanup_csg_slot(group);
-+ /* remove the group from the scheduler list */
-+ sched_evict_group(group, as_fault, false);
-+ /* return the evicted group to the caller */
-+ list_add_tail(&group->link, evicted_groups);
-+ set_bit(slot, slot_mask);
-+ }
-+ }
-+
-+ dev_info(kbdev->dev, "Evicting context %d_%d slots: 0x%*pb\n",
-+ kctx->tgid, kctx->id, num_groups, slot_mask);
-+
-+ mutex_unlock(&scheduler->lock);
-+}
-+
-+/**
-+ * scheduler_slot_protm_ack - Acknowledging the protected region requests
-+ * from the resident group on a given slot.
-+ *
-+ * The function assumes that the given slot is in stable running state and
-+ * has already been judged by the caller on that any pending protected region
-+ * requests of the resident group should be acknowledged.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ * @group: Pointer to the resident group on the given slot.
-+ * @slot: The slot that the given group is actively operating on.
-+ *
-+ * Return: true if the group has pending protm request(s) and is acknowledged.
-+ * The caller should arrange to enter the protected mode for servicing
-+ * it. Otherwise return false, indicating the group has no pending protm
-+ * request.
-+ */
-+static bool scheduler_slot_protm_ack(struct kbase_device *const kbdev,
-+ struct kbase_queue_group *const group,
-+ const int slot)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ bool protm_ack = false;
-+ struct kbase_csf_cmd_stream_group_info *ginfo =
-+ &kbdev->csf.global_iface.groups[slot];
-+ u32 max_csi;
-+ int i;
-+
-+ if (WARN_ON(scheduler->csg_slots[slot].resident_group != group))
-+ return protm_ack;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+ lockdep_assert_held(&group->kctx->kbdev->csf.scheduler.interrupt_lock);
-+
-+ max_csi = ginfo->stream_num;
-+ for (i = find_first_bit(group->protm_pending_bitmap, max_csi);
-+ i < max_csi;
-+ i = find_next_bit(group->protm_pending_bitmap, max_csi, i + 1)) {
-+ struct kbase_queue *queue = group->bound_queues[i];
-+
-+ clear_bit(i, group->protm_pending_bitmap);
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, PROTM_PENDING_CLEAR, group,
-+ queue, group->protm_pending_bitmap[0]);
-+
-+ if (!WARN_ON(!queue) && queue->enabled) {
-+ struct kbase_csf_cmd_stream_info *stream =
-+ &ginfo->streams[i];
-+ u32 cs_protm_ack = kbase_csf_firmware_cs_output(
-+ stream, CS_ACK) &
-+ CS_ACK_PROTM_PEND_MASK;
-+ u32 cs_protm_req = kbase_csf_firmware_cs_input_read(
-+ stream, CS_REQ) &
-+ CS_REQ_PROTM_PEND_MASK;
-+
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_PROTM_ACK, group,
-+ queue, cs_protm_ack ^ cs_protm_req);
-+
-+ if (cs_protm_ack == cs_protm_req) {
-+ dev_dbg(kbdev->dev,
-+ "PROTM-ack already done for queue-%d group-%d slot-%d",
-+ queue->csi_index, group->handle, slot);
-+ continue;
-+ }
-+
-+ kbase_csf_firmware_cs_input_mask(stream, CS_REQ,
-+ cs_protm_ack,
-+ CS_ACK_PROTM_PEND_MASK);
-+ protm_ack = true;
-+ dev_dbg(kbdev->dev,
-+ "PROTM-ack for queue-%d, group-%d slot-%d",
-+ queue->csi_index, group->handle, slot);
-+ }
-+ }
-+
-+ return protm_ack;
-+}
-+
-+/**
-+ * scheduler_group_check_protm_enter - Request the given group to be evaluated
-+ * for triggering the protected mode.
-+ *
-+ * The function assumes the given group is either an active running group or
-+ * the scheduler internally maintained field scheduler->top_grp.
-+ *
-+ * If the GPU is not already running in protected mode and the input group
-+ * has protected region requests from its bound queues, the requests are
-+ * acknowledged and the GPU is instructed to enter the protected mode.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ * @input_grp: Pointer to the GPU queue group.
-+ */
-+static void scheduler_group_check_protm_enter(struct kbase_device *const kbdev,
-+ struct kbase_queue_group *const input_grp)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+ bool protm_in_use;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+
-+ protm_in_use = kbase_csf_scheduler_protected_mode_in_use(kbdev);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_CHECK_PROTM_ENTER, input_grp,
-+ protm_in_use);
-+
-+ /* Firmware samples the PROTM_PEND ACK bit for CSs when
-+ * Host sends PROTM_ENTER global request. So if PROTM_PEND ACK bit
-+ * is set for a CS after Host has sent the PROTM_ENTER
-+ * Global request, then there is no guarantee that firmware will
-+ * notice that prior to switching to protected mode. And firmware
-+ * may not again raise the PROTM_PEND interrupt for that CS
-+ * later on. To avoid that uncertainty PROTM_PEND ACK bit
-+ * is not set for a CS if the request to enter protected
-+ * mode has already been sent. It will be set later (after the exit
-+ * from protected mode has taken place) when the group to which
-+ * CS is bound becomes the top group.
-+ *
-+ * The actual decision of entering protected mode is hinging on the
-+ * input group is the top priority group, or, in case the previous
-+ * top-group is evicted from the scheduler during the tick, its would
-+ * be replacement, and that it is currently in a stable state (i.e. the
-+ * slot state is running).
-+ */
-+ if (!protm_in_use && !WARN_ON(!input_grp)) {
-+ const int slot =
-+ kbase_csf_scheduler_group_get_slot_locked(input_grp);
-+
-+ /* check the input_grp is running and requesting protected mode
-+ */
-+ if (slot >= 0 &&
-+ atomic_read(&scheduler->csg_slots[slot].state) ==
-+ CSG_SLOT_RUNNING) {
-+ if (kctx_as_enabled(input_grp->kctx) &&
-+ scheduler_slot_protm_ack(kbdev, input_grp, slot)) {
-+ /* Option of acknowledging to multiple
-+ * CSGs from the same kctx is dropped,
-+ * after consulting with the
-+ * architecture team. See the comment in
-+ * GPUCORE-21394.
-+ */
-+
-+ /* Disable the idle timer */
-+ disable_gpu_idle_fw_timer_locked(kbdev);
-+
-+ /* Switch to protected mode */
-+ scheduler->active_protm_grp = input_grp;
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_ENTER_PROTM,
-+ input_grp, 0u);
-+
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+ kbase_csf_enter_protected_mode(kbdev);
-+ return;
-+ }
-+ }
-+ }
-+
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+}
-+
-+static void scheduler_apply(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ const u32 total_csg_slots = kbdev->csf.global_iface.group_num;
-+ const u32 available_csg_slots = scheduler->num_csg_slots_for_tick;
-+ u32 suspend_cnt = 0;
-+ u32 remain_cnt = 0;
-+ u32 resident_cnt = 0;
-+ struct kbase_queue_group *group;
-+ u32 i;
-+ u32 spare;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ /* Suspend those resident groups not in the run list */
-+ for (i = 0; i < total_csg_slots; i++) {
-+ group = scheduler->csg_slots[i].resident_group;
-+ if (group) {
-+ resident_cnt++;
-+ if (group->prepared_seq_num >= available_csg_slots) {
-+ suspend_queue_group(group);
-+ suspend_cnt++;
-+ } else
-+ remain_cnt++;
-+ }
-+ }
-+
-+ /* Initialize the remaining avialable csg slots for the tick/tock */
-+ scheduler->remaining_tick_slots = available_csg_slots;
-+
-+ /* If there are spare slots, apply heads in the list */
-+ spare = (available_csg_slots > resident_cnt) ?
-+ (available_csg_slots - resident_cnt) : 0;
-+ while (!list_empty(&scheduler->groups_to_schedule)) {
-+ group = list_first_entry(&scheduler->groups_to_schedule,
-+ struct kbase_queue_group,
-+ link_to_schedule);
-+
-+ if (kbasep_csf_scheduler_group_is_on_slot_locked(group) &&
-+ group->prepared_seq_num < available_csg_slots) {
-+ /* One of the resident remainders */
-+ update_csg_slot_priority(group,
-+ get_slot_priority(group));
-+ } else if (spare != 0) {
-+ s8 slot = (s8)find_first_zero_bit(
-+ kbdev->csf.scheduler.csg_inuse_bitmap,
-+ total_csg_slots);
-+
-+ if (WARN_ON(slot >= (s8)total_csg_slots))
-+ break;
-+
-+ if (!kctx_as_enabled(group->kctx) || group->faulted) {
-+ /* Drop the head group and continue */
-+ update_offslot_non_idle_cnt_for_faulty_grp(
-+ group);
-+ remove_scheduled_group(kbdev, group);
-+ continue;
-+ }
-+ program_csg_slot(group, slot,
-+ get_slot_priority(group));
-+ if (unlikely(!csg_slot_in_use(kbdev, slot)))
-+ break;
-+
-+ spare--;
-+ } else
-+ break;
-+
-+ /* Drop the head csg from the list */
-+ remove_scheduled_group(kbdev, group);
-+ if (!WARN_ON(!scheduler->remaining_tick_slots))
-+ scheduler->remaining_tick_slots--;
-+ }
-+
-+ /* Dealing with groups currently going through suspend */
-+ program_suspending_csg_slots(kbdev);
-+}
-+
-+static void scheduler_ctx_scan_groups(struct kbase_device *kbdev,
-+ struct kbase_context *kctx, int priority)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ struct kbase_queue_group *group;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+ if (WARN_ON(priority < 0) ||
-+ WARN_ON(priority >= KBASE_QUEUE_GROUP_PRIORITY_COUNT))
-+ return;
-+
-+ if (!kctx_as_enabled(kctx))
-+ return;
-+
-+ list_for_each_entry(group, &kctx->csf.sched.runnable_groups[priority],
-+ link) {
-+ if (WARN_ON(!list_empty(&group->link_to_schedule)))
-+ /* This would be a bug */
-+ list_del_init(&group->link_to_schedule);
-+
-+ if (unlikely(group->faulted))
-+ continue;
-+
-+ /* Set the scanout sequence number, starting from 0 */
-+ group->scan_seq_num = scheduler->csg_scan_count_for_tick++;
-+
-+ if (queue_group_idle_locked(group)) {
-+ list_add_tail(&group->link_to_schedule,
-+ &scheduler->idle_groups_to_schedule);
-+ continue;
-+ }
-+
-+ if (!scheduler->ngrp_to_schedule) {
-+ /* keep the top csg's origin */
-+ scheduler->top_ctx = kctx;
-+ scheduler->top_grp = group;
-+ }
-+
-+ list_add_tail(&group->link_to_schedule,
-+ &scheduler->groups_to_schedule);
-+ group->prepared_seq_num = scheduler->ngrp_to_schedule++;
-+
-+ kctx->csf.sched.ngrp_to_schedule++;
-+ count_active_address_space(kbdev, kctx);
-+ }
-+}
-+
-+/**
-+ * scheduler_rotate_groups() - Rotate the runnable queue groups to provide
-+ * fairness of scheduling within a single
-+ * kbase_context.
-+ *
-+ * Since only kbase_csf_scheduler's top_grp (i.e. the queue group assigned
-+ * the highest slot priority) is guaranteed to get the resources that it
-+ * needs we only rotate the kbase_context corresponding to it -
-+ * kbase_csf_scheduler's top_ctx.
-+ *
-+ * The priority level chosen for rotation is the one containing the previous
-+ * scheduling cycle's kbase_csf_scheduler's top_grp.
-+ *
-+ * In a 'fresh-slice-cycle' this always corresponds to the highest group
-+ * priority in use by kbase_csf_scheduler's top_ctx. That is, it's the priority
-+ * level of the previous scheduling cycle's first runnable kbase_context.
-+ *
-+ * We choose this priority level because when higher priority work is
-+ * scheduled, we should always cause the scheduler to run and do a scan. The
-+ * scan always enumerates the highest priority work first (whether that be
-+ * based on process priority or group priority), and thus
-+ * kbase_csf_scheduler's top_grp will point to the first of those high priority
-+ * groups, which necessarily must be the highest priority group in
-+ * kbase_csf_scheduler's top_ctx. The fresh-slice-cycle will run later and pick
-+ * up that group appropriately.
-+ *
-+ * If kbase_csf_scheduler's top_grp was instead evicted (and thus is NULL),
-+ * then no explicit rotation occurs on the next fresh-slice-cycle schedule, but
-+ * will set up kbase_csf_scheduler's top_ctx again for the next scheduling
-+ * cycle. Implicitly, a rotation had already occurred by removing
-+ * the kbase_csf_scheduler's top_grp
-+ *
-+ * If kbase_csf_scheduler's top_grp became idle and all other groups belonging
-+ * to kbase_csf_scheduler's top_grp's priority level in kbase_csf_scheduler's
-+ * top_ctx are also idle, then the effect of this will be to rotate idle
-+ * groups, which might not actually become resident in the next
-+ * scheduling slice. However this is acceptable since a queue group becoming
-+ * idle is implicitly a rotation (as above with evicted queue groups), as it
-+ * automatically allows a new queue group to take the maximum slot priority
-+ * whilst the idle kbase_csf_scheduler's top_grp ends up near the back of
-+ * the kbase_csf_scheduler's groups_to_schedule list. In this example, it will
-+ * be for a group in the next lowest priority level or in absence of those the
-+ * next kbase_context's queue groups.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ */
-+static void scheduler_rotate_groups(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ struct kbase_context *const top_ctx = scheduler->top_ctx;
-+ struct kbase_queue_group *const top_grp = scheduler->top_grp;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+ if (top_ctx && top_grp) {
-+ struct list_head *list =
-+ &top_ctx->csf.sched.runnable_groups[top_grp->priority];
-+
-+ WARN_ON(top_grp->kctx != top_ctx);
-+ if (!WARN_ON(list_empty(list))) {
-+ struct kbase_queue_group *new_head_grp;
-+ list_move_tail(&top_grp->link, list);
-+ new_head_grp = (!list_empty(list)) ?
-+ list_first_entry(list, struct kbase_queue_group, link) :
-+ NULL;
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_ROTATE_RUNNABLE,
-+ top_grp, top_ctx->csf.sched.num_runnable_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_HEAD_RUNNABLE,
-+ new_head_grp, 0u);
-+ dev_dbg(kbdev->dev,
-+ "groups rotated for a context, num_runnable_groups: %u\n",
-+ scheduler->top_ctx->csf.sched.num_runnable_grps);
-+ }
-+ }
-+}
-+
-+static void scheduler_rotate_ctxs(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ struct list_head *list = &scheduler->runnable_kctxs;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+ if (scheduler->top_ctx) {
-+ if (!WARN_ON(list_empty(list))) {
-+ struct kbase_context *pos;
-+ bool found = false;
-+
-+ /* Locate the ctx on the list */
-+ list_for_each_entry(pos, list, csf.link) {
-+ if (scheduler->top_ctx == pos) {
-+ found = true;
-+ break;
-+ }
-+ }
-+
-+ if (!WARN_ON(!found)) {
-+ struct kbase_context *new_head_kctx;
-+ list_move_tail(&pos->csf.link, list);
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_ROTATE_RUNNABLE, pos,
-+ 0u);
-+ new_head_kctx = (!list_empty(list)) ?
-+ list_first_entry(list, struct kbase_context, csf.link) :
-+ NULL;
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_HEAD_RUNNABLE,
-+ new_head_kctx, 0u);
-+ dev_dbg(kbdev->dev, "contexts rotated\n");
-+ }
-+ }
-+ }
-+}
-+
-+/**
-+ * scheduler_update_idle_slots_status() - Get the status update for the CSG
-+ * slots for which the IDLE notification was received
-+ * previously.
-+ *
-+ * This function sends a CSG status update request for all the CSG slots
-+ * present in the bitmap scheduler->csg_slots_idle_mask and wait for the
-+ * request to complete.
-+ * The bits set in the scheduler->csg_slots_idle_mask bitmap are cleared by
-+ * this function.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ * @csg_bitmap: Bitmap of the CSG slots for which
-+ * the status update request completed successfully.
-+ * @failed_csg_bitmap: Bitmap of the CSG slots for which
-+ * the status update request timedout.
-+ */
-+static void scheduler_update_idle_slots_status(struct kbase_device *kbdev,
-+ unsigned long *csg_bitmap, unsigned long *failed_csg_bitmap)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ const u32 num_groups = kbdev->csf.global_iface.group_num;
-+ struct kbase_csf_global_iface *const global_iface =
-+ &kbdev->csf.global_iface;
-+ unsigned long flags, i;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ for_each_set_bit(i, scheduler->csg_slots_idle_mask, num_groups) {
-+ struct kbase_csf_csg_slot *csg_slot = &scheduler->csg_slots[i];
-+ struct kbase_queue_group *group = csg_slot->resident_group;
-+ struct kbase_csf_cmd_stream_group_info *const ginfo =
-+ &global_iface->groups[i];
-+ u32 csg_req;
-+
-+ clear_bit(i, scheduler->csg_slots_idle_mask);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_CLEAR, group,
-+ scheduler->csg_slots_idle_mask[0]);
-+ if (WARN_ON(!group))
-+ continue;
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STATUS_UPDATE, group,
-+ i);
-+
-+ csg_req = kbase_csf_firmware_csg_output(ginfo, CSG_ACK);
-+ csg_req ^= CSG_REQ_STATUS_UPDATE_MASK;
-+ kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, csg_req,
-+ CSG_REQ_STATUS_UPDATE_MASK);
-+
-+ set_bit(i, csg_bitmap);
-+ }
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+
-+ /* The groups are aggregated into a single kernel doorbell request */
-+ if (!bitmap_empty(csg_bitmap, num_groups)) {
-+ long wt =
-+ kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
-+ u32 db_slots = (u32)csg_bitmap[0];
-+
-+ kbase_csf_ring_csg_slots_doorbell(kbdev, db_slots);
-+
-+ if (wait_csg_slots_handshake_ack(kbdev,
-+ CSG_REQ_STATUS_UPDATE_MASK, csg_bitmap, wt)) {
-+ dev_warn(
-+ kbdev->dev,
-+ "Timeout on CSG_REQ:STATUS_UPDATE, treat groups as not idle: slot mask=0x%lx",
-+ csg_bitmap[0]);
-+
-+ /* Store the bitmap of timed out slots */
-+ bitmap_copy(failed_csg_bitmap, csg_bitmap, num_groups);
-+ csg_bitmap[0] = ~csg_bitmap[0] & db_slots;
-+ } else {
-+ KBASE_KTRACE_ADD(kbdev, SLOTS_STATUS_UPDATE_ACK, NULL,
-+ db_slots);
-+ csg_bitmap[0] = db_slots;
-+ }
-+ }
-+}
-+
-+/**
-+ * scheduler_handle_idle_slots() - Update the idle status of queue groups
-+ * resident on CSG slots for which the
-+ * IDLE notification was received previously.
-+ *
-+ * This function is called at the start of scheduling tick/tock to reconfirm
-+ * the idle status of queue groups resident on CSG slots for
-+ * which idle notification was received previously, i.e. all the CSG slots
-+ * present in the bitmap scheduler->csg_slots_idle_mask.
-+ * The confirmation is done by sending the CSG status update request to the
-+ * firmware. On completion, the firmware will mark the idleness at the
-+ * slot's interface CSG_STATUS_STATE register accordingly.
-+ *
-+ * The run state of the groups resident on still idle CSG slots is changed to
-+ * KBASE_CSF_GROUP_IDLE and the bitmap scheduler->csg_slots_idle_mask is
-+ * updated accordingly.
-+ * The bits corresponding to slots for which the status update request timedout
-+ * remain set in scheduler->csg_slots_idle_mask.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ */
-+static void scheduler_handle_idle_slots(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+ unsigned long flags, i;
-+ DECLARE_BITMAP(csg_bitmap, MAX_SUPPORTED_CSGS) = { 0 };
-+ DECLARE_BITMAP(failed_csg_bitmap, MAX_SUPPORTED_CSGS) = { 0 };
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ scheduler_update_idle_slots_status(kbdev, csg_bitmap,
-+ failed_csg_bitmap);
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ for_each_set_bit(i, csg_bitmap, num_groups) {
-+ struct kbase_csf_csg_slot *csg_slot = &scheduler->csg_slots[i];
-+ struct kbase_queue_group *group = csg_slot->resident_group;
-+
-+ if (WARN_ON(atomic_read(&csg_slot->state) != CSG_SLOT_RUNNING))
-+ continue;
-+ if (WARN_ON(!group))
-+ continue;
-+ if (WARN_ON(group->run_state != KBASE_CSF_GROUP_RUNNABLE &&
-+ group->run_state != KBASE_CSF_GROUP_IDLE))
-+ continue;
-+ if (WARN_ON(group->priority >= KBASE_QUEUE_GROUP_PRIORITY_COUNT))
-+ continue;
-+
-+ if (group_on_slot_is_idle(kbdev, i)) {
-+ group->run_state = KBASE_CSF_GROUP_IDLE;
-+ set_bit(i, scheduler->csg_slots_idle_mask);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_SET,
-+ group, scheduler->csg_slots_idle_mask[0]);
-+ } else
-+ group->run_state = KBASE_CSF_GROUP_RUNNABLE;
-+ }
-+
-+ bitmap_or(scheduler->csg_slots_idle_mask,
-+ scheduler->csg_slots_idle_mask,
-+ failed_csg_bitmap, num_groups);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_SET, NULL,
-+ scheduler->csg_slots_idle_mask[0]);
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+}
-+
-+static void scheduler_scan_idle_groups(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ struct kbase_queue_group *group, *n;
-+
-+ list_for_each_entry_safe(group, n, &scheduler->idle_groups_to_schedule,
-+ link_to_schedule) {
-+
-+ WARN_ON(!queue_group_idle_locked(group));
-+
-+ if (!scheduler->ngrp_to_schedule) {
-+ /* keep the top csg's origin */
-+ scheduler->top_ctx = group->kctx;
-+ scheduler->top_grp = group;
-+ }
-+
-+ group->prepared_seq_num = scheduler->ngrp_to_schedule++;
-+ list_move_tail(&group->link_to_schedule,
-+ &scheduler->groups_to_schedule);
-+
-+ group->kctx->csf.sched.ngrp_to_schedule++;
-+ count_active_address_space(kbdev, group->kctx);
-+ }
-+}
-+
-+static void scheduler_rotate(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ /* Dealing with rotation */
-+ scheduler_rotate_groups(kbdev);
-+ scheduler_rotate_ctxs(kbdev);
-+}
-+
-+static struct kbase_queue_group *get_tock_top_group(
-+ struct kbase_csf_scheduler *const scheduler)
-+{
-+ struct kbase_context *kctx;
-+ int i;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+ for (i = 0; i < KBASE_QUEUE_GROUP_PRIORITY_COUNT; ++i) {
-+ list_for_each_entry(kctx,
-+ &scheduler->runnable_kctxs, csf.link) {
-+ struct kbase_queue_group *group;
-+
-+ list_for_each_entry(group,
-+ &kctx->csf.sched.runnable_groups[i],
-+ link) {
-+ if (queue_group_idle_locked(group))
-+ continue;
-+
-+ return group;
-+ }
-+ }
-+ }
-+
-+ return NULL;
-+}
-+
-+static int suspend_active_groups_on_powerdown(struct kbase_device *kbdev,
-+ bool is_suspend)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS) = { 0 };
-+
-+ int ret = suspend_active_queue_groups(kbdev, slot_mask);
-+
-+ if (ret) {
-+ /* The suspend of CSGs failed, trigger the GPU reset and wait
-+ * for it to complete to be in a deterministic state.
-+ */
-+ dev_warn(kbdev->dev, "Timed out waiting for CSG slots to suspend on power down, slot_mask: 0x%*pb\n",
-+ kbdev->csf.global_iface.group_num, slot_mask);
-+
-+ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
-+ kbase_reset_gpu(kbdev);
-+
-+ if (is_suspend) {
-+ mutex_unlock(&scheduler->lock);
-+ kbase_reset_gpu_wait(kbdev);
-+ mutex_lock(&scheduler->lock);
-+ }
-+ return -1;
-+ }
-+
-+ /* Check if the groups became active whilst the suspend was ongoing,
-+ * but only for the case where the system suspend is not in progress
-+ */
-+ if (!is_suspend && atomic_read(&scheduler->non_idle_offslot_grps))
-+ return -1;
-+
-+ return 0;
-+}
-+
-+static bool scheduler_idle_suspendable(struct kbase_device *kbdev)
-+{
-+ bool suspend;
-+ unsigned long flags;
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (scheduler->state == SCHED_SUSPENDED)
-+ return false;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ if (scheduler->total_runnable_grps) {
-+ spin_lock(&scheduler->interrupt_lock);
-+
-+ /* Check both on-slots and off-slots groups idle status */
-+ suspend = kbase_csf_scheduler_all_csgs_idle(kbdev) &&
-+ !atomic_read(&scheduler->non_idle_offslot_grps) &&
-+ kbase_pm_idle_groups_sched_suspendable(kbdev);
-+
-+ spin_unlock(&scheduler->interrupt_lock);
-+ } else
-+ suspend = kbase_pm_no_runnables_sched_suspendable(kbdev);
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ return suspend;
-+}
-+
-+static void gpu_idle_worker(struct work_struct *work)
-+{
-+ struct kbase_device *kbdev = container_of(
-+ work, struct kbase_device, csf.scheduler.gpu_idle_work);
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ bool reset_active = false;
-+ bool scheduler_is_idle_suspendable = false;
-+ bool all_groups_suspended = false;
-+
-+ KBASE_KTRACE_ADD(kbdev, IDLE_WORKER_BEGIN, NULL, 0u);
-+
-+#define __ENCODE_KTRACE_INFO(reset, idle, all_suspend) \
-+ (((u32)reset) | (((u32)idle) << 4) | (((u32)all_suspend) << 8))
-+
-+ if (kbase_reset_gpu_try_prevent(kbdev)) {
-+ dev_warn(kbdev->dev, "Quit idle for failing to prevent gpu reset.\n");
-+ KBASE_KTRACE_ADD(kbdev, IDLE_WORKER_END, NULL,
-+ __ENCODE_KTRACE_INFO(true, false, false));
-+ return;
-+ }
-+ mutex_lock(&scheduler->lock);
-+
-+ /* Cycle completed, disable the firmware idle timer */
-+ disable_gpu_idle_fw_timer(kbdev);
-+ scheduler_is_idle_suspendable = scheduler_idle_suspendable(kbdev);
-+ reset_active = kbase_reset_gpu_is_active(kbdev);
-+ if (scheduler_is_idle_suspendable && !reset_active) {
-+ all_groups_suspended =
-+ !suspend_active_groups_on_powerdown(kbdev, false);
-+
-+ if (all_groups_suspended) {
-+ dev_dbg(kbdev->dev, "Scheduler becomes idle suspended now");
-+ scheduler_suspend(kbdev);
-+ cancel_tick_timer(kbdev);
-+ } else {
-+ dev_dbg(kbdev->dev, "Aborting suspend scheduler (grps: %d)",
-+ atomic_read(&scheduler->non_idle_offslot_grps));
-+ /* Bring forward the next tick */
-+ kbase_csf_scheduler_advance_tick(kbdev);
-+ }
-+ }
-+
-+ mutex_unlock(&scheduler->lock);
-+ kbase_reset_gpu_allow(kbdev);
-+ KBASE_KTRACE_ADD(kbdev, IDLE_WORKER_END, NULL,
-+ __ENCODE_KTRACE_INFO(reset_active, scheduler_is_idle_suspendable, all_groups_suspended));
-+#undef __ENCODE_KTRACE_INFO
-+}
-+
-+static int scheduler_prepare(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ int i;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ /* Empty the groups_to_schedule */
-+ while (!list_empty(&scheduler->groups_to_schedule)) {
-+ struct kbase_queue_group *grp =
-+ list_first_entry(&scheduler->groups_to_schedule,
-+ struct kbase_queue_group,
-+ link_to_schedule);
-+
-+ remove_scheduled_group(kbdev, grp);
-+ }
-+
-+ /* Pre-scan init scheduler fields */
-+ if (WARN_ON(scheduler->ngrp_to_schedule != 0))
-+ scheduler->ngrp_to_schedule = 0;
-+ scheduler->top_ctx = NULL;
-+ scheduler->top_grp = NULL;
-+ scheduler->csg_scan_count_for_tick = 0;
-+ WARN_ON(!list_empty(&scheduler->idle_groups_to_schedule));
-+ scheduler->num_active_address_spaces = 0;
-+ scheduler->num_csg_slots_for_tick = 0;
-+ bitmap_zero(scheduler->csg_slots_prio_update, MAX_SUPPORTED_CSGS);
-+
-+ /* Scan out to run groups */
-+ for (i = 0; i < KBASE_QUEUE_GROUP_PRIORITY_COUNT; ++i) {
-+ struct kbase_context *kctx;
-+
-+ list_for_each_entry(kctx, &scheduler->runnable_kctxs, csf.link)
-+ scheduler_ctx_scan_groups(kbdev, kctx, i);
-+ }
-+
-+ /* Update this tick's non-idle groups */
-+ scheduler->non_idle_scanout_grps = scheduler->ngrp_to_schedule;
-+
-+ /* Initial number of non-idle off-slot groups, before the scheduler's
-+ * scheduler_apply() operation. This gives a sensible start point view
-+ * of the tick. It will be subject to up/downs during the scheduler
-+ * active phase.
-+ */
-+ atomic_set(&scheduler->non_idle_offslot_grps,
-+ scheduler->non_idle_scanout_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC, NULL,
-+ scheduler->non_idle_scanout_grps);
-+
-+ /* Adds those idle but runnable groups to the scanout list */
-+ scheduler_scan_idle_groups(kbdev);
-+
-+ /* After adding the idle CSGs, the two counts should be the same */
-+ WARN_ON(scheduler->csg_scan_count_for_tick != scheduler->ngrp_to_schedule);
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_TOP_GRP, scheduler->top_grp,
-+ scheduler->num_active_address_spaces |
-+ (((u64)scheduler->ngrp_to_schedule) << 32));
-+ set_max_csg_slots(kbdev);
-+ dev_dbg(kbdev->dev, "prepared groups length: %u, num_active_address_spaces: %u\n",
-+ scheduler->ngrp_to_schedule, scheduler->num_active_address_spaces);
-+ return 0;
-+}
-+
-+static void scheduler_handle_idle_timer_onoff(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ /* After the scheduler apply operation, the internal variable
-+ * scheduler->non_idle_offslot_grps reflects the end-point view
-+ * of the count at the end of the active phase.
-+ *
-+ * Any changes that follow (after the scheduler has dropped the
-+ * scheduler->lock), reflects async operations to the scheduler,
-+ * such as a group gets killed (evicted) or a new group inserted,
-+ * cqs wait-sync triggered state transtion etc.
-+ *
-+ * The condition for enable the idle timer is that there is no
-+ * non-idle groups off-slots. If there is non-idle group off-slot,
-+ * the timer should be disabled.
-+ */
-+ if (atomic_read(&scheduler->non_idle_offslot_grps))
-+ disable_gpu_idle_fw_timer(kbdev);
-+ else
-+ enable_gpu_idle_fw_timer(kbdev);
-+}
-+
-+static void schedule_actions(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+ struct kbase_queue_group *protm_grp;
-+ int ret;
-+ bool skip_idle_slots_update;
-+ bool new_protm_top_grp = false;
-+
-+ kbase_reset_gpu_assert_prevented(kbdev);
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ ret = kbase_pm_wait_for_desired_state(kbdev);
-+ if (ret) {
-+ dev_err(kbdev->dev, "Wait for MCU power on failed");
-+ return;
-+ }
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ skip_idle_slots_update = kbase_csf_scheduler_protected_mode_in_use(kbdev);
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+
-+ /* Skip updating on-slot idle CSGs if GPU is in protected mode. */
-+ if (!skip_idle_slots_update)
-+ scheduler_handle_idle_slots(kbdev);
-+
-+ scheduler_prepare(kbdev);
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ protm_grp = scheduler->active_protm_grp;
-+
-+ /* Avoid update if the top-group remains unchanged and in protected
-+ * mode. For the said case, all the slots update is effectively
-+ * competing against the active protected mode group (typically the
-+ * top-group). If we update other slots, even on leaving the
-+ * top-group slot untouched, the firmware would exit the protected mode
-+ * for interacting with the host-driver. After it, as the top-group
-+ * would again raise the request for entering protected mode, we would
-+ * be actively doing the switching over twice without progressing the
-+ * queue jobs.
-+ */
-+ if (protm_grp && scheduler->top_grp == protm_grp) {
-+ int new_val;
-+ dev_dbg(kbdev->dev, "Scheduler keep protm exec: group-%d",
-+ protm_grp->handle);
-+ new_val = atomic_dec_return(&scheduler->non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC,
-+ protm_grp, new_val);
-+ } else if (scheduler->top_grp) {
-+ if (protm_grp)
-+ dev_dbg(kbdev->dev, "Scheduler drop protm exec: group-%d",
-+ protm_grp->handle);
-+
-+ if (!bitmap_empty(scheduler->top_grp->protm_pending_bitmap,
-+ kbdev->csf.global_iface.groups[0].stream_num)) {
-+ dev_dbg(kbdev->dev, "Scheduler prepare protm exec: group-%d of context %d_%d",
-+ scheduler->top_grp->handle,
-+ scheduler->top_grp->kctx->tgid,
-+ scheduler->top_grp->kctx->id);
-+
-+ /* When entering protected mode all CSG slots can be occupied
-+ * but only the protected mode CSG will be running. Any event
-+ * that would trigger the execution of an on-slot idle CSG will
-+ * need to be handled by the host during protected mode.
-+ */
-+ new_protm_top_grp = true;
-+ }
-+
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+
-+ scheduler_apply(kbdev);
-+
-+ /* Post-apply, all the committed groups in this tick are on
-+ * slots, time to arrange the idle timer on/off decision.
-+ */
-+ scheduler_handle_idle_timer_onoff(kbdev);
-+
-+ /* Scheduler is dropping the exec of the previous protm_grp,
-+ * Until the protm quit completes, the GPU is effectively
-+ * locked in the secure mode.
-+ */
-+ if (protm_grp)
-+ scheduler_force_protm_exit(kbdev);
-+
-+ wait_csg_slots_start(kbdev);
-+ wait_csg_slots_finish_prio_update(kbdev);
-+
-+ if (new_protm_top_grp) {
-+ scheduler_group_check_protm_enter(kbdev,
-+ scheduler->top_grp);
-+ }
-+
-+ return;
-+ }
-+
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+ return;
-+}
-+
-+static void schedule_on_tock(struct work_struct *work)
-+{
-+ struct kbase_device *kbdev = container_of(work, struct kbase_device,
-+ csf.scheduler.tock_work.work);
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ int err = kbase_reset_gpu_try_prevent(kbdev);
-+ /* Regardless of whether reset failed or is currently happening, exit
-+ * early
-+ */
-+ if (err)
-+ return;
-+
-+ mutex_lock(&scheduler->lock);
-+ if (scheduler->state == SCHED_SUSPENDED)
-+ goto exit_no_schedule_unlock;
-+
-+ WARN_ON(!(scheduler->state == SCHED_INACTIVE));
-+ scheduler->state = SCHED_BUSY;
-+
-+ /* Undertaking schedule action steps */
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_TOCK, NULL, 0u);
-+ schedule_actions(kbdev);
-+
-+ /* Record time information */
-+ scheduler->last_schedule = jiffies;
-+
-+ /* Tock is serviced */
-+ scheduler->tock_pending_request = false;
-+
-+ scheduler->state = SCHED_INACTIVE;
-+ mutex_unlock(&scheduler->lock);
-+ kbase_reset_gpu_allow(kbdev);
-+
-+ dev_dbg(kbdev->dev,
-+ "Waking up for event after schedule-on-tock completes.");
-+ wake_up_all(&kbdev->csf.event_wait);
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_TOCK_END, NULL, 0u);
-+ return;
-+
-+exit_no_schedule_unlock:
-+ mutex_unlock(&scheduler->lock);
-+ kbase_reset_gpu_allow(kbdev);
-+}
-+
-+static void schedule_on_tick(struct work_struct *work)
-+{
-+ struct kbase_device *kbdev = container_of(work, struct kbase_device,
-+ csf.scheduler.tick_work);
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ int err = kbase_reset_gpu_try_prevent(kbdev);
-+ /* Regardless of whether reset failed or is currently happening, exit
-+ * early
-+ */
-+ if (err)
-+ return;
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ WARN_ON(scheduler->tick_timer_active);
-+ if (scheduler->state == SCHED_SUSPENDED)
-+ goto exit_no_schedule_unlock;
-+
-+ scheduler->state = SCHED_BUSY;
-+ /* Do scheduling stuff */
-+ scheduler_rotate(kbdev);
-+
-+ /* Undertaking schedule action steps */
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_TICK, NULL,
-+ scheduler->total_runnable_grps);
-+ schedule_actions(kbdev);
-+
-+ /* Record time information */
-+ scheduler->last_schedule = jiffies;
-+
-+ /* Kicking next scheduling if needed */
-+ if (likely(scheduler_timer_is_enabled_nolock(kbdev)) &&
-+ (scheduler->total_runnable_grps > 0)) {
-+ start_tick_timer(kbdev);
-+ dev_dbg(kbdev->dev,
-+ "scheduling for next tick, num_runnable_groups:%u\n",
-+ scheduler->total_runnable_grps);
-+ }
-+
-+ scheduler->state = SCHED_INACTIVE;
-+ mutex_unlock(&scheduler->lock);
-+ kbase_reset_gpu_allow(kbdev);
-+
-+ dev_dbg(kbdev->dev, "Waking up for event after schedule-on-tick completes.");
-+ wake_up_all(&kbdev->csf.event_wait);
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_TICK_END, NULL,
-+ scheduler->total_runnable_grps);
-+ return;
-+
-+exit_no_schedule_unlock:
-+ mutex_unlock(&scheduler->lock);
-+ kbase_reset_gpu_allow(kbdev);
-+}
-+
-+static int wait_csg_slots_suspend(struct kbase_device *kbdev,
-+ const unsigned long *slot_mask,
-+ unsigned int timeout_ms)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ long remaining = kbase_csf_timeout_in_jiffies(timeout_ms);
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+ int err = 0;
-+ DECLARE_BITMAP(slot_mask_local, MAX_SUPPORTED_CSGS);
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ bitmap_copy(slot_mask_local, slot_mask, MAX_SUPPORTED_CSGS);
-+
-+ while (!bitmap_empty(slot_mask_local, MAX_SUPPORTED_CSGS)
-+ && remaining) {
-+ DECLARE_BITMAP(changed, MAX_SUPPORTED_CSGS);
-+
-+ bitmap_copy(changed, slot_mask_local, MAX_SUPPORTED_CSGS);
-+
-+ remaining = wait_event_timeout(kbdev->csf.event_wait,
-+ slots_state_changed(kbdev, changed,
-+ csg_slot_stopped_locked),
-+ remaining);
-+
-+ if (remaining) {
-+ u32 i;
-+
-+ for_each_set_bit(i, changed, num_groups) {
-+ struct kbase_queue_group *group;
-+
-+ if (WARN_ON(!csg_slot_stopped_locked(kbdev, (s8)i)))
-+ continue;
-+
-+ /* The on slot csg is now stopped */
-+ clear_bit(i, slot_mask_local);
-+
-+ group = scheduler->csg_slots[i].resident_group;
-+ if (likely(group)) {
-+ /* Only do save/cleanup if the
-+ * group is not terminated during
-+ * the sleep.
-+ */
-+ save_csg_slot(group);
-+ if (cleanup_csg_slot(group))
-+ sched_evict_group(group, true, true);
-+ }
-+ }
-+ } else {
-+ dev_warn(kbdev->dev, "Timed out waiting for CSG slots to suspend, slot_mask: 0x%*pb\n",
-+ num_groups, slot_mask_local);
-+ err = -ETIMEDOUT;
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+static int suspend_active_queue_groups(struct kbase_device *kbdev,
-+ unsigned long *slot_mask)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+ u32 slot_num;
-+ int ret;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ for (slot_num = 0; slot_num < num_groups; slot_num++) {
-+ struct kbase_queue_group *group =
-+ scheduler->csg_slots[slot_num].resident_group;
-+
-+ if (group) {
-+ suspend_queue_group(group);
-+ set_bit(slot_num, slot_mask);
-+ }
-+ }
-+
-+ ret = wait_csg_slots_suspend(kbdev, slot_mask, kbdev->reset_timeout_ms);
-+ return ret;
-+}
-+
-+static int suspend_active_queue_groups_on_reset(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS) = { 0 };
-+ int ret;
-+ int ret2;
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ ret = suspend_active_queue_groups(kbdev, slot_mask);
-+
-+ if (ret) {
-+ dev_warn(kbdev->dev, "Timed out waiting for CSG slots to suspend before reset, slot_mask: 0x%*pb\n",
-+ kbdev->csf.global_iface.group_num, slot_mask);
-+ }
-+
-+ /* Need to flush the GPU cache to ensure suspend buffer
-+ * contents are not lost on reset of GPU.
-+ * Do this even if suspend operation had timed out for some of
-+ * the CSG slots.
-+ * In case the scheduler already in suspended state, the
-+ * cache clean is required as the async reset request from
-+ * the debugfs may race against the scheduler suspend operation
-+ * due to the extra context ref-count, which prevents the
-+ * L2 powering down cache clean operation in the non racing
-+ * case.
-+ */
-+ kbase_gpu_start_cache_clean(kbdev);
-+ ret2 = kbase_gpu_wait_cache_clean_timeout(kbdev,
-+ kbdev->reset_timeout_ms);
-+ if (ret2) {
-+ dev_warn(kbdev->dev, "Timed out waiting for cache clean to complete before reset");
-+ if (!ret)
-+ ret = ret2;
-+ }
-+
-+ mutex_unlock(&scheduler->lock);
-+
-+ return ret;
-+}
-+
-+/**
-+ * scheduler_handle_reset_in_protected_mode() - Update the state of normal mode
-+ * groups when reset is done during
-+ * protected mode execution.
-+ *
-+ * @group: Pointer to the device.
-+ *
-+ * This function is called at the time of GPU reset, before the suspension of
-+ * queue groups, to handle the case when the reset is getting performed whilst
-+ * GPU is in protected mode.
-+ * On entry to protected mode all the groups, except the top group that executes
-+ * in protected mode, are implicitly suspended by the FW. Thus this function
-+ * simply marks the normal mode groups as suspended (and cleans up the
-+ * corresponding CSG slots) to prevent their potential forceful eviction from
-+ * the Scheduler. So if GPU was in protected mode and there was no fault, then
-+ * only the protected mode group would be suspended in the regular way post exit
-+ * from this function. And if GPU was in normal mode, then all on-slot groups
-+ * will get suspended in the regular way.
-+ *
-+ * Return: true if the groups remaining on the CSG slots need to be suspended in
-+ * the regular way by sending CSG SUSPEND reqs to FW, otherwise false.
-+ */
-+static bool scheduler_handle_reset_in_protected_mode(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ u32 const num_groups = kbdev->csf.global_iface.group_num;
-+ struct kbase_queue_group *protm_grp;
-+ bool suspend_on_slot_groups;
-+ unsigned long flags;
-+ u32 csg_nr;
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ protm_grp = scheduler->active_protm_grp;
-+
-+ /* If GPU wasn't in protected mode or had exited it before the GPU reset
-+ * then all the on-slot groups can be suspended in the regular way by
-+ * sending CSG SUSPEND requests to FW.
-+ * If there wasn't a fault for protected mode group, then it would
-+ * also need to be suspended in the regular way before the reset.
-+ */
-+ suspend_on_slot_groups = !(protm_grp && protm_grp->faulted);
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+
-+ if (!protm_grp)
-+ goto unlock;
-+
-+ /* GPU is in protected mode, so all the on-slot groups barring the
-+ * the protected mode group can be marked as suspended right away.
-+ */
-+ for (csg_nr = 0; csg_nr < num_groups; csg_nr++) {
-+ struct kbase_queue_group *const group =
-+ kbdev->csf.scheduler.csg_slots[csg_nr].resident_group;
-+ int new_val;
-+
-+ if (!group || (group == protm_grp))
-+ continue;
-+
-+ cleanup_csg_slot(group);
-+ group->run_state = KBASE_CSF_GROUP_SUSPENDED;
-+
-+ /* Simply treat the normal mode groups as non-idle. The tick
-+ * scheduled after the reset will re-initialize the counter
-+ * anyways.
-+ */
-+ new_val = atomic_inc_return(&scheduler->non_idle_offslot_grps);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC,
-+ group, new_val);
-+ }
-+
-+unlock:
-+ mutex_unlock(&scheduler->lock);
-+ return suspend_on_slot_groups;
-+}
-+
-+static void scheduler_inner_reset(struct kbase_device *kbdev)
-+{
-+ u32 const num_groups = kbdev->csf.global_iface.group_num;
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+
-+ WARN_ON(csgs_active(kbdev));
-+
-+ /* Cancel any potential queued delayed work(s) */
-+ cancel_work_sync(&kbdev->csf.scheduler.gpu_idle_work);
-+ cancel_tick_timer(kbdev);
-+ cancel_work_sync(&scheduler->tick_work);
-+ cancel_delayed_work_sync(&scheduler->tock_work);
-+ cancel_delayed_work_sync(&scheduler->ping_work);
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ bitmap_fill(scheduler->csgs_events_enable_mask, MAX_SUPPORTED_CSGS);
-+ if (scheduler->active_protm_grp)
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_EXIT_PROTM,
-+ scheduler->active_protm_grp, 0u);
-+ scheduler->active_protm_grp = NULL;
-+ memset(kbdev->csf.scheduler.csg_slots, 0,
-+ num_groups * sizeof(struct kbase_csf_csg_slot));
-+ bitmap_zero(kbdev->csf.scheduler.csg_inuse_bitmap, num_groups);
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+
-+ scheduler->top_ctx = NULL;
-+ scheduler->top_grp = NULL;
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_TOP_GRP, scheduler->top_grp,
-+ scheduler->num_active_address_spaces |
-+ (((u64)scheduler->total_runnable_grps) << 32));
-+
-+ mutex_unlock(&scheduler->lock);
-+}
-+
-+void kbase_csf_scheduler_reset(struct kbase_device *kbdev)
-+{
-+ struct kbase_context *kctx;
-+
-+ WARN_ON(!kbase_reset_gpu_is_active(kbdev));
-+
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_RESET, NULL, 0u);
-+
-+ if (scheduler_handle_reset_in_protected_mode(kbdev) &&
-+ !suspend_active_queue_groups_on_reset(kbdev)) {
-+ /* As all groups have been successfully evicted from the CSG
-+ * slots, clear out thee scheduler data fields and return
-+ */
-+ scheduler_inner_reset(kbdev);
-+ return;
-+ }
-+
-+ mutex_lock(&kbdev->kctx_list_lock);
-+
-+ /* The loop to iterate over the kbase contexts is present due to lock
-+ * ordering issue between kctx->csf.lock & kbdev->csf.scheduler.lock.
-+ * CSF ioctls first take kctx->csf.lock which is context-specific and
-+ * then take kbdev->csf.scheduler.lock for global actions like assigning
-+ * a CSG slot.
-+ * If the lock ordering constraint was not there then could have
-+ * directly looped over the active queue groups.
-+ */
-+ list_for_each_entry(kctx, &kbdev->kctx_list, kctx_list_link) {
-+ /* Firmware reload would reinitialize the CSG & CS interface IO
-+ * pages, so just need to internally mark the currently active
-+ * queue groups as terminated (similar to the unexpected OoM
-+ * event case).
-+ * No further work can now get executed for the active groups
-+ * (new groups would have to be created to execute work) and
-+ * in near future Clients would be duly informed of this
-+ * reset. The resources (like User IO pages, GPU queue memory)
-+ * allocated for the associated queues would be freed when the
-+ * Clients do the teardown when they become aware of the reset.
-+ */
-+ kbase_csf_active_queue_groups_reset(kbdev, kctx);
-+ }
-+
-+ mutex_unlock(&kbdev->kctx_list_lock);
-+
-+ /* After queue groups reset, the scheduler data fields clear out */
-+ scheduler_inner_reset(kbdev);
-+}
-+
-+static void firmware_aliveness_monitor(struct work_struct *work)
-+{
-+ struct kbase_device *kbdev = container_of(work, struct kbase_device,
-+ csf.scheduler.ping_work.work);
-+ int err;
-+
-+ /* Ensure that reset will not be occurring while this function is being
-+ * executed as otherwise calling kbase_reset_gpu when reset is already
-+ * occurring is a programming error.
-+ *
-+ * We must use the 'try' variant as the Reset worker can try to flush
-+ * this workqueue, which would otherwise deadlock here if we tried to
-+ * wait for the reset (and thus ourselves) to complete.
-+ */
-+ err = kbase_reset_gpu_try_prevent(kbdev);
-+ if (err) {
-+ /* It doesn't matter whether the value was -EAGAIN or a fatal
-+ * error, just stop processing. In case of -EAGAIN, the Reset
-+ * worker will restart the scheduler later to resume ping
-+ */
-+ return;
-+ }
-+
-+ mutex_lock(&kbdev->csf.scheduler.lock);
-+
-+#ifdef CONFIG_MALI_DEBUG
-+ if (fw_debug) {
-+ /* ping requests cause distraction in firmware debugging */
-+ goto exit;
-+ }
-+#endif
-+
-+ if (kbdev->csf.scheduler.state == SCHED_SUSPENDED)
-+ goto exit;
-+
-+ if (get_nr_active_csgs(kbdev) != 1)
-+ goto exit;
-+
-+ if (kbase_csf_scheduler_protected_mode_in_use(kbdev))
-+ goto exit;
-+
-+ if (kbase_pm_context_active_handle_suspend(kbdev,
-+ KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE)) {
-+ /* Suspend pending - no real need to ping */
-+ goto exit;
-+ }
-+
-+ kbase_pm_wait_for_desired_state(kbdev);
-+
-+ err = kbase_csf_firmware_ping_wait(kbdev);
-+
-+ if (err) {
-+ /* It is acceptable to enqueue a reset whilst we've prevented
-+ * them, it will happen after we've allowed them again
-+ */
-+ if (kbase_prepare_to_reset_gpu(
-+ kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR))
-+ kbase_reset_gpu(kbdev);
-+ } else if (get_nr_active_csgs(kbdev) == 1) {
-+ queue_delayed_work(system_long_wq,
-+ &kbdev->csf.scheduler.ping_work,
-+ msecs_to_jiffies(FIRMWARE_PING_INTERVAL_MS));
-+ }
-+
-+ kbase_pm_context_idle(kbdev);
-+exit:
-+ mutex_unlock(&kbdev->csf.scheduler.lock);
-+ kbase_reset_gpu_allow(kbdev);
-+ return;
-+}
-+
-+int kbase_csf_scheduler_group_copy_suspend_buf(struct kbase_queue_group *group,
-+ struct kbase_suspend_copy_buffer *sus_buf)
-+{
-+ struct kbase_context *const kctx = group->kctx;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ int err = 0;
-+
-+ kbase_reset_gpu_assert_prevented(kbdev);
-+ lockdep_assert_held(&kctx->csf.lock);
-+ mutex_lock(&scheduler->lock);
-+
-+ if (kbasep_csf_scheduler_group_is_on_slot_locked(group)) {
-+ DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS) = {0};
-+
-+ set_bit(kbase_csf_scheduler_group_get_slot(group), slot_mask);
-+
-+ if (!WARN_ON(scheduler->state == SCHED_SUSPENDED))
-+ suspend_queue_group(group);
-+ err = wait_csg_slots_suspend(kbdev, slot_mask,
-+ kbdev->csf.fw_timeout_ms);
-+ if (err) {
-+ dev_warn(kbdev->dev, "Timed out waiting for the group %d to suspend on slot %d",
-+ group->handle, group->csg_nr);
-+ goto exit;
-+ }
-+ }
-+
-+ if (queue_group_suspended_locked(group)) {
-+ unsigned int target_page_nr = 0, i = 0;
-+ u64 offset = sus_buf->offset;
-+ size_t to_copy = sus_buf->size;
-+
-+ if (scheduler->state != SCHED_SUSPENDED) {
-+ /* Similar to the case of HW counters, need to flush
-+ * the GPU cache before reading from the suspend buffer
-+ * pages as they are mapped and cached on GPU side.
-+ */
-+ kbase_gpu_start_cache_clean(kbdev);
-+ kbase_gpu_wait_cache_clean(kbdev);
-+ } else {
-+ /* Make sure power down transitions have completed,
-+ * i.e. L2 has been powered off as that would ensure
-+ * its contents are flushed to memory.
-+ * This is needed as Scheduler doesn't wait for the
-+ * power down to finish.
-+ */
-+ kbase_pm_wait_for_desired_state(kbdev);
-+ }
-+
-+ for (i = 0; i < PFN_UP(sus_buf->size) &&
-+ target_page_nr < sus_buf->nr_pages; i++) {
-+ struct page *pg =
-+ as_page(group->normal_suspend_buf.phy[i]);
-+ void *sus_page = kmap(pg);
-+
-+ if (sus_page) {
-+ kbase_sync_single_for_cpu(kbdev,
-+ kbase_dma_addr(pg),
-+ PAGE_SIZE, DMA_BIDIRECTIONAL);
-+
-+ err = kbase_mem_copy_to_pinned_user_pages(
-+ sus_buf->pages, sus_page,
-+ &to_copy, sus_buf->nr_pages,
-+ &target_page_nr, offset);
-+ kunmap(pg);
-+ if (err)
-+ break;
-+ } else {
-+ err = -ENOMEM;
-+ break;
-+ }
-+ }
-+ schedule_in_cycle(group, false);
-+ } else {
-+ /* If addr-space fault, the group may have been evicted */
-+ err = -EIO;
-+ }
-+
-+exit:
-+ mutex_unlock(&scheduler->lock);
-+ return err;
-+}
-+
-+KBASE_EXPORT_TEST_API(kbase_csf_scheduler_group_copy_suspend_buf);
-+
-+/**
-+ * group_sync_updated() - Evaluate sync wait condition of all blocked command
-+ * queues of the group.
-+ *
-+ * @group: Pointer to the command queue group that has blocked command queue(s)
-+ * bound to it.
-+ *
-+ * Return: true if sync wait condition is satisfied for at least one blocked
-+ * queue of the group.
-+ */
-+static bool group_sync_updated(struct kbase_queue_group *group)
-+{
-+ bool updated = false;
-+ int stream;
-+
-+ /* Groups can also be blocked on-slot during protected mode. */
-+ WARN_ON(group->run_state != KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC &&
-+ group->run_state != KBASE_CSF_GROUP_IDLE);
-+
-+ for (stream = 0; stream < MAX_SUPPORTED_STREAMS_PER_GROUP; ++stream) {
-+ struct kbase_queue *const queue = group->bound_queues[stream];
-+
-+ /* To check the necessity of sync-wait evaluation,
-+ * we rely on the cached 'status_wait' instead of reading it
-+ * directly from shared memory as the CSG has been already
-+ * evicted from the CSG slot, thus this CSG doesn't have
-+ * valid information in the shared memory.
-+ */
-+ if (queue && queue->enabled &&
-+ CS_STATUS_WAIT_SYNC_WAIT_GET(queue->status_wait))
-+ if (evaluate_sync_update(queue)) {
-+ updated = true;
-+ queue->status_wait = 0;
-+ }
-+ }
-+
-+ return updated;
-+}
-+
-+/**
-+ * scheduler_get_protm_enter_async_group() - Check if the GPU queue group
-+ * can be now allowed to execute in protected mode.
-+ *
-+ * @kbdev: Pointer to the GPU device.
-+ * @group: Pointer to the GPU queue group.
-+ *
-+ * This function is called outside the scheduling tick/tock to determine
-+ * if the given GPU queue group can now execute in protected mode or not.
-+ * If the group pointer passed is NULL then the evaluation is done for the
-+ * highest priority group on the scheduler maintained group lists without
-+ * tick associated rotation actions. This is referred as the 'top-group'
-+ * in a tock action sense.
-+ *
-+ * It returns the same group pointer, that was passed as an argument, if that
-+ * group matches the highest priority group and has pending protected region
-+ * requests otherwise NULL is returned.
-+ *
-+ * If the group pointer passed is NULL then the internal evaluated highest
-+ * priority group is returned if that has pending protected region requests
-+ * otherwise NULL is returned.
-+ *
-+ * The evaluated highest priority group may not necessarily be the same as the
-+ * scheduler->top_grp. This can happen if there is dynamic de-idle update
-+ * during the tick interval for some on-slots groups that were idle during the
-+ * scheduler normal scheduling action, where the scheduler->top_grp was set.
-+ * The recorded scheduler->top_grp is untouched by this evualuation, so will not
-+ * affect the scheduler context/priority list rotation arrangement.
-+ *
-+ * Return: the pointer to queue group that can currently execute in protected
-+ * mode or NULL.
-+ */
-+static struct kbase_queue_group *scheduler_get_protm_enter_async_group(
-+ struct kbase_device *const kbdev,
-+ struct kbase_queue_group *const group)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ struct kbase_queue_group *match_grp, *input_grp;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ if (scheduler->state != SCHED_INACTIVE)
-+ return NULL;
-+
-+ match_grp = get_tock_top_group(scheduler);
-+ input_grp = group ? group : match_grp;
-+
-+ if (input_grp && (input_grp == match_grp)) {
-+ struct kbase_csf_cmd_stream_group_info *ginfo =
-+ &kbdev->csf.global_iface.groups[0];
-+ unsigned long *pending =
-+ input_grp->protm_pending_bitmap;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+
-+ if (kbase_csf_scheduler_protected_mode_in_use(kbdev) ||
-+ bitmap_empty(pending, ginfo->stream_num))
-+ input_grp = NULL;
-+
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+ } else {
-+ input_grp = NULL;
-+ }
-+
-+ return input_grp;
-+}
-+
-+void kbase_csf_scheduler_group_protm_enter(struct kbase_queue_group *group)
-+{
-+ struct kbase_device *const kbdev = group->kctx->kbdev;
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ int err = kbase_reset_gpu_try_prevent(kbdev);
-+ /* Regardless of whether reset failed or is currently happening, exit
-+ * early
-+ */
-+ if (err)
-+ return;
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ /* Check if the group is now eligible for execution in protected mode. */
-+ if (scheduler_get_protm_enter_async_group(kbdev, group))
-+ scheduler_group_check_protm_enter(kbdev, group);
-+
-+ mutex_unlock(&scheduler->lock);
-+ kbase_reset_gpu_allow(kbdev);
-+}
-+
-+/**
-+ * check_sync_update_for_idle_group_protm() - Check the sync wait condition
-+ * for all the queues bound to
-+ * the given group.
-+ *
-+ * @group: Pointer to the group that requires evaluation.
-+ *
-+ * This function is called if the GPU is in protected mode and there are on
-+ * slot idle groups with higher priority than the active protected mode group.
-+ * This function will evaluate the sync condition, if any, of all the queues
-+ * bound to the given group.
-+ *
-+ * Return true if the sync condition of at least one queue has been satisfied.
-+ */
-+static bool check_sync_update_for_idle_group_protm(
-+ struct kbase_queue_group *group)
-+{
-+ struct kbase_device *const kbdev = group->kctx->kbdev;
-+ struct kbase_csf_scheduler *const scheduler =
-+ &kbdev->csf.scheduler;
-+ bool sync_update_done = false;
-+ int i;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ for (i = 0; i < MAX_SUPPORTED_STREAMS_PER_GROUP; i++) {
-+ struct kbase_queue *queue = group->bound_queues[i];
-+
-+ if (queue && queue->enabled && !sync_update_done) {
-+ struct kbase_csf_cmd_stream_group_info *const ginfo =
-+ &kbdev->csf.global_iface.groups[group->csg_nr];
-+ struct kbase_csf_cmd_stream_info *const stream =
-+ &ginfo->streams[queue->csi_index];
-+ u32 status = kbase_csf_firmware_cs_output(
-+ stream, CS_STATUS_WAIT);
-+ unsigned long flags;
-+
-+ KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_STATUS_WAIT,
-+ queue->group, queue, status);
-+
-+ if (!CS_STATUS_WAIT_SYNC_WAIT_GET(status))
-+ continue;
-+
-+ /* Save the information of sync object of the command
-+ * queue so the callback function, 'group_sync_updated'
-+ * can evaluate the sync object when it gets updated
-+ * later.
-+ */
-+ queue->status_wait = status;
-+ queue->sync_ptr = kbase_csf_firmware_cs_output(
-+ stream, CS_STATUS_WAIT_SYNC_POINTER_LO);
-+ queue->sync_ptr |= (u64)kbase_csf_firmware_cs_output(
-+ stream, CS_STATUS_WAIT_SYNC_POINTER_HI) << 32;
-+ queue->sync_value = kbase_csf_firmware_cs_output(
-+ stream, CS_STATUS_WAIT_SYNC_VALUE);
-+ queue->blocked_reason =
-+ CS_STATUS_BLOCKED_REASON_REASON_GET(
-+ kbase_csf_firmware_cs_output(
-+ stream,
-+ CS_STATUS_BLOCKED_REASON));
-+
-+ if (!evaluate_sync_update(queue))
-+ continue;
-+
-+ /* Update csg_slots_idle_mask and group's run_state */
-+ if (group->run_state != KBASE_CSF_GROUP_RUNNABLE) {
-+ /* Only clear the group's idle flag if it has been dealt
-+ * with by the scheduler's tick/tock action, otherwise
-+ * leave it untouched.
-+ */
-+ spin_lock_irqsave(&scheduler->interrupt_lock,
-+ flags);
-+ clear_bit((unsigned int)group->csg_nr,
-+ scheduler->csg_slots_idle_mask);
-+ KBASE_KTRACE_ADD_CSF_GRP(
-+ kbdev, CSG_SLOT_IDLE_CLEAR, group,
-+ scheduler->csg_slots_idle_mask[0]);
-+ spin_unlock_irqrestore(
-+ &scheduler->interrupt_lock, flags);
-+ group->run_state = KBASE_CSF_GROUP_RUNNABLE;
-+ }
-+
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_SYNC_UPDATE_DONE, group, 0u);
-+ sync_update_done = true;
-+ }
-+ }
-+
-+ return sync_update_done;
-+}
-+
-+/**
-+ * check_sync_update_for_idle_groups_protm() - Check the sync wait condition
-+ * for the idle groups on slot
-+ * during protected mode.
-+ *
-+ * @kbdev: Pointer to the GPU device
-+ *
-+ * This function checks the gpu queues of all the idle groups on slot during
-+ * protected mode that has a higher priority than the active protected mode
-+ * group.
-+ *
-+ * Return true if the sync condition of at least one queue in a group has been
-+ * satisfied.
-+ */
-+static bool check_sync_update_for_idle_groups_protm(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ struct kbase_queue_group *protm_grp;
-+ bool exit_protm = false;
-+ unsigned long flags;
-+ u32 num_groups;
-+ u32 i;
-+
-+ lockdep_assert_held(&scheduler->lock);
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ protm_grp = scheduler->active_protm_grp;
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+
-+ if (!protm_grp)
-+ return exit_protm;
-+
-+ num_groups = kbdev->csf.global_iface.group_num;
-+
-+ for_each_set_bit(i, scheduler->csg_slots_idle_mask, num_groups) {
-+ struct kbase_csf_csg_slot *csg_slot =
-+ &scheduler->csg_slots[i];
-+ struct kbase_queue_group *group = csg_slot->resident_group;
-+
-+ if (group->scan_seq_num < protm_grp->scan_seq_num) {
-+ /* If sync update has been performed for the group that
-+ * has a higher priority than the protm group, then we
-+ * need to exit protected mode.
-+ */
-+ if (check_sync_update_for_idle_group_protm(group))
-+ exit_protm = true;
-+ }
-+ }
-+
-+ return exit_protm;
-+}
-+
-+/**
-+ * check_group_sync_update_worker() - Check the sync wait condition for all the
-+ * blocked queue groups
-+ *
-+ * @work: Pointer to the context-specific work item for evaluating the wait
-+ * condition for all the queue groups in idle_wait_groups list.
-+ *
-+ * This function checks the gpu queues of all the groups present in both
-+ * idle_wait_groups list of a context and all on slot idle groups (if GPU
-+ * is in protected mode).
-+ * If the sync wait condition for at least one queue bound to the group has
-+ * been satisfied then the group is moved to the per context list of
-+ * runnable groups so that Scheduler can consider scheduling the group
-+ * in next tick or exit protected mode.
-+ */
-+static void check_group_sync_update_worker(struct work_struct *work)
-+{
-+ struct kbase_context *const kctx = container_of(work,
-+ struct kbase_context, csf.sched.sync_update_work);
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ KBASE_KTRACE_ADD(kbdev, GROUP_SYNC_UPDATE_WORKER_BEGIN, kctx, 0u);
-+ if (kctx->csf.sched.num_idle_wait_grps != 0) {
-+ struct kbase_queue_group *group, *temp;
-+
-+ list_for_each_entry_safe(group, temp,
-+ &kctx->csf.sched.idle_wait_groups, link) {
-+ if (group_sync_updated(group)) {
-+ /* Move this group back in to the runnable
-+ * groups list of the context.
-+ */
-+ update_idle_suspended_group_state(group);
-+ KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_SYNC_UPDATE_DONE, group, 0u);
-+ }
-+ }
-+ } else {
-+ WARN_ON(!list_empty(&kctx->csf.sched.idle_wait_groups));
-+ }
-+
-+ if (check_sync_update_for_idle_groups_protm(kbdev))
-+ scheduler_force_protm_exit(kbdev);
-+ KBASE_KTRACE_ADD(kbdev, GROUP_SYNC_UPDATE_WORKER_END, kctx, 0u);
-+
-+ mutex_unlock(&scheduler->lock);
-+}
-+
-+static
-+enum kbase_csf_event_callback_action check_group_sync_update_cb(void *param)
-+{
-+ struct kbase_context *const kctx = param;
-+
-+ KBASE_KTRACE_ADD(kctx->kbdev, SYNC_UPDATE_EVENT, kctx, 0u);
-+ queue_work(kctx->csf.sched.sync_update_wq,
-+ &kctx->csf.sched.sync_update_work);
-+
-+ return KBASE_CSF_EVENT_CALLBACK_KEEP;
-+}
-+
-+int kbase_csf_scheduler_context_init(struct kbase_context *kctx)
-+{
-+ int priority;
-+ int err;
-+
-+ for (priority = 0; priority < KBASE_QUEUE_GROUP_PRIORITY_COUNT;
-+ ++priority) {
-+ INIT_LIST_HEAD(&kctx->csf.sched.runnable_groups[priority]);
-+ }
-+
-+ kctx->csf.sched.num_runnable_grps = 0;
-+ INIT_LIST_HEAD(&kctx->csf.sched.idle_wait_groups);
-+ kctx->csf.sched.num_idle_wait_grps = 0;
-+ kctx->csf.sched.ngrp_to_schedule = 0;
-+
-+ kctx->csf.sched.sync_update_wq =
-+ alloc_ordered_workqueue("mali_kbase_csf_sync_update_wq",
-+ WQ_HIGHPRI);
-+ if (!kctx->csf.sched.sync_update_wq) {
-+ dev_err(kctx->kbdev->dev,
-+ "Failed to initialize scheduler context workqueue");
-+ return -ENOMEM;
-+ }
-+
-+ INIT_WORK(&kctx->csf.sched.sync_update_work,
-+ check_group_sync_update_worker);
-+
-+ err = kbase_csf_event_wait_add(kctx, check_group_sync_update_cb, kctx);
-+
-+ if (err) {
-+ dev_err(kctx->kbdev->dev,
-+ "Failed to register a sync update callback");
-+ destroy_workqueue(kctx->csf.sched.sync_update_wq);
-+ }
-+
-+ return err;
-+}
-+
-+void kbase_csf_scheduler_context_term(struct kbase_context *kctx)
-+{
-+ kbase_csf_event_wait_remove(kctx, check_group_sync_update_cb, kctx);
-+ cancel_work_sync(&kctx->csf.sched.sync_update_work);
-+ destroy_workqueue(kctx->csf.sched.sync_update_wq);
-+}
-+
-+int kbase_csf_scheduler_init(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ u32 num_groups = kbdev->csf.global_iface.group_num;
-+
-+ bitmap_zero(scheduler->csg_inuse_bitmap, num_groups);
-+ bitmap_zero(scheduler->csg_slots_idle_mask, num_groups);
-+
-+ scheduler->csg_slots = kcalloc(num_groups,
-+ sizeof(*scheduler->csg_slots), GFP_KERNEL);
-+ if (!scheduler->csg_slots) {
-+ dev_err(kbdev->dev,
-+ "Failed to allocate memory for csg slot status array\n");
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+int kbase_csf_scheduler_early_init(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ scheduler->timer_enabled = true;
-+
-+ scheduler->wq = alloc_ordered_workqueue("csf_scheduler_wq", WQ_HIGHPRI);
-+ if (!scheduler->wq) {
-+ dev_err(kbdev->dev, "Failed to allocate scheduler workqueue\n");
-+ return -ENOMEM;
-+ }
-+
-+ INIT_WORK(&scheduler->tick_work, schedule_on_tick);
-+ INIT_DEFERRABLE_WORK(&scheduler->tock_work, schedule_on_tock);
-+
-+ INIT_DEFERRABLE_WORK(&scheduler->ping_work, firmware_aliveness_monitor);
-+ BUILD_BUG_ON(CSF_FIRMWARE_TIMEOUT_MS >= FIRMWARE_PING_INTERVAL_MS);
-+
-+ mutex_init(&scheduler->lock);
-+ spin_lock_init(&scheduler->interrupt_lock);
-+
-+ /* Internal lists */
-+ INIT_LIST_HEAD(&scheduler->runnable_kctxs);
-+ INIT_LIST_HEAD(&scheduler->groups_to_schedule);
-+ INIT_LIST_HEAD(&scheduler->idle_groups_to_schedule);
-+
-+ BUILD_BUG_ON(MAX_SUPPORTED_CSGS >
-+ (sizeof(scheduler->csgs_events_enable_mask) * BITS_PER_BYTE));
-+ bitmap_fill(scheduler->csgs_events_enable_mask, MAX_SUPPORTED_CSGS);
-+ scheduler->state = SCHED_SUSPENDED;
-+ scheduler->pm_active_count = 0;
-+ scheduler->ngrp_to_schedule = 0;
-+ scheduler->total_runnable_grps = 0;
-+ scheduler->top_ctx = NULL;
-+ scheduler->top_grp = NULL;
-+ scheduler->last_schedule = 0;
-+ scheduler->tock_pending_request = false;
-+ scheduler->active_protm_grp = NULL;
-+ scheduler->gpu_idle_fw_timer_enabled = false;
-+ scheduler->csg_scheduling_period_ms = CSF_SCHEDULER_TIME_TICK_MS;
-+ scheduler_doorbell_init(kbdev);
-+
-+ INIT_WORK(&scheduler->gpu_idle_work, gpu_idle_worker);
-+ atomic_set(&scheduler->non_idle_offslot_grps, 0);
-+
-+ hrtimer_init(&scheduler->tick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-+ scheduler->tick_timer.function = tick_timer_callback;
-+ scheduler->tick_timer_active = false;
-+
-+ return 0;
-+}
-+
-+void kbase_csf_scheduler_term(struct kbase_device *kbdev)
-+{
-+ if (kbdev->csf.scheduler.csg_slots) {
-+ WARN_ON(atomic_read(&kbdev->csf.scheduler.non_idle_offslot_grps));
-+ WARN_ON(csgs_active(kbdev));
-+ flush_work(&kbdev->csf.scheduler.gpu_idle_work);
-+ mutex_lock(&kbdev->csf.scheduler.lock);
-+ if (WARN_ON(kbdev->csf.scheduler.state != SCHED_SUSPENDED))
-+ scheduler_suspend(kbdev);
-+ mutex_unlock(&kbdev->csf.scheduler.lock);
-+ cancel_delayed_work_sync(&kbdev->csf.scheduler.ping_work);
-+ cancel_tick_timer(kbdev);
-+ cancel_work_sync(&kbdev->csf.scheduler.tick_work);
-+ cancel_delayed_work_sync(&kbdev->csf.scheduler.tock_work);
-+ mutex_destroy(&kbdev->csf.scheduler.lock);
-+ kfree(kbdev->csf.scheduler.csg_slots);
-+ kbdev->csf.scheduler.csg_slots = NULL;
-+ }
-+}
-+
-+void kbase_csf_scheduler_early_term(struct kbase_device *kbdev)
-+{
-+ if (kbdev->csf.scheduler.wq)
-+ destroy_workqueue(kbdev->csf.scheduler.wq);
-+}
-+
-+/**
-+ * scheduler_enable_tick_timer_nolock - Enable the scheduler tick timer.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * This function will restart the scheduler tick so that regular scheduling can
-+ * be resumed without any explicit trigger (like kicking of GPU queues). This
-+ * is a variant of kbase_csf_scheduler_enable_tick_timer() that assumes the
-+ * CSF scheduler lock to already have been held.
-+ */
-+static void scheduler_enable_tick_timer_nolock(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&kbdev->csf.scheduler.lock);
-+
-+ if (unlikely(!scheduler_timer_is_enabled_nolock(kbdev)))
-+ return;
-+
-+ WARN_ON((scheduler->state != SCHED_INACTIVE) &&
-+ (scheduler->state != SCHED_SUSPENDED));
-+
-+ if (scheduler->total_runnable_grps > 0) {
-+ enqueue_tick_work(kbdev);
-+ dev_dbg(kbdev->dev, "Re-enabling the scheduler timer\n");
-+ } else if (scheduler->state != SCHED_SUSPENDED) {
-+ queue_work(system_wq, &scheduler->gpu_idle_work);
-+ }
-+}
-+
-+void kbase_csf_scheduler_enable_tick_timer(struct kbase_device *kbdev)
-+{
-+ mutex_lock(&kbdev->csf.scheduler.lock);
-+ scheduler_enable_tick_timer_nolock(kbdev);
-+ mutex_unlock(&kbdev->csf.scheduler.lock);
-+}
-+
-+bool kbase_csf_scheduler_timer_is_enabled(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ bool enabled;
-+
-+ mutex_lock(&scheduler->lock);
-+ enabled = scheduler_timer_is_enabled_nolock(kbdev);
-+ mutex_unlock(&scheduler->lock);
-+
-+ return enabled;
-+}
-+
-+void kbase_csf_scheduler_timer_set_enabled(struct kbase_device *kbdev,
-+ bool enable)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ bool currently_enabled;
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ currently_enabled = scheduler_timer_is_enabled_nolock(kbdev);
-+ if (currently_enabled && !enable) {
-+ scheduler->timer_enabled = false;
-+ cancel_tick_timer(kbdev);
-+ cancel_delayed_work(&scheduler->tock_work);
-+ mutex_unlock(&scheduler->lock);
-+ /* The non-sync version to cancel the normal work item is not
-+ * available, so need to drop the lock before cancellation.
-+ */
-+ cancel_work_sync(&scheduler->tick_work);
-+ } else if (!currently_enabled && enable) {
-+ scheduler->timer_enabled = true;
-+
-+ scheduler_enable_tick_timer_nolock(kbdev);
-+ mutex_unlock(&scheduler->lock);
-+ }
-+}
-+
-+void kbase_csf_scheduler_kick(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ if (unlikely(scheduler_timer_is_enabled_nolock(kbdev)))
-+ goto out;
-+
-+ if (scheduler->total_runnable_grps > 0) {
-+ enqueue_tick_work(kbdev);
-+ dev_dbg(kbdev->dev, "Kicking the scheduler manually\n");
-+ }
-+
-+out:
-+ mutex_unlock(&scheduler->lock);
-+}
-+
-+void kbase_csf_scheduler_pm_suspend(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ /* Cancel any potential queued delayed work(s) */
-+ cancel_work_sync(&scheduler->tick_work);
-+ cancel_delayed_work_sync(&scheduler->tock_work);
-+
-+ if (kbase_reset_gpu_prevent_and_wait(kbdev)) {
-+ dev_warn(kbdev->dev,
-+ "Stop PM suspending for failing to prevent gpu reset.\n");
-+ return;
-+ }
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ disable_gpu_idle_fw_timer(kbdev);
-+
-+ if (scheduler->state != SCHED_SUSPENDED) {
-+ suspend_active_groups_on_powerdown(kbdev, true);
-+ dev_info(kbdev->dev, "Scheduler PM suspend");
-+ scheduler_suspend(kbdev);
-+ cancel_tick_timer(kbdev);
-+ }
-+ mutex_unlock(&scheduler->lock);
-+
-+ kbase_reset_gpu_allow(kbdev);
-+}
-+KBASE_EXPORT_TEST_API(kbase_csf_scheduler_pm_suspend);
-+
-+void kbase_csf_scheduler_pm_resume(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+
-+ mutex_lock(&scheduler->lock);
-+
-+ if (scheduler->total_runnable_grps > 0) {
-+ WARN_ON(scheduler->state != SCHED_SUSPENDED);
-+ dev_info(kbdev->dev, "Scheduler PM resume");
-+ scheduler_wakeup(kbdev, true);
-+ }
-+ mutex_unlock(&scheduler->lock);
-+}
-+KBASE_EXPORT_TEST_API(kbase_csf_scheduler_pm_resume);
-+
-+void kbase_csf_scheduler_pm_active(struct kbase_device *kbdev)
-+{
-+ unsigned long flags;
-+ u32 prev_count;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ prev_count = kbdev->csf.scheduler.pm_active_count++;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ /* On 0 => 1, make a pm_ctx_active request */
-+ if (!prev_count)
-+ kbase_pm_context_active(kbdev);
-+ else
-+ WARN_ON(prev_count == U32_MAX);
-+}
-+KBASE_EXPORT_TEST_API(kbase_csf_scheduler_pm_active);
-+
-+void kbase_csf_scheduler_pm_idle(struct kbase_device *kbdev)
-+{
-+ unsigned long flags;
-+ u32 prev_count;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ prev_count = kbdev->csf.scheduler.pm_active_count--;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ if (prev_count == 1)
-+ kbase_pm_context_idle(kbdev);
-+ else
-+ WARN_ON(prev_count == 0);
-+}
-+KBASE_EXPORT_TEST_API(kbase_csf_scheduler_pm_idle);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_scheduler.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_scheduler.h
-new file mode 100644
-index 0000000..428ecbe
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_scheduler.h
-@@ -0,0 +1,494 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_SCHEDULER_H_
-+#define _KBASE_CSF_SCHEDULER_H_
-+
-+#include "mali_kbase_csf.h"
-+
-+/**
-+ * kbase_csf_scheduler_queue_start() - Enable the running of GPU command queue
-+ * on firmware.
-+ *
-+ * @queue: Pointer to the GPU command queue to be started.
-+ *
-+ * This function would enable the start of a CSI, within a
-+ * CSG, to which the @queue was bound.
-+ * If the CSG is already scheduled and resident, the CSI will be started
-+ * right away, otherwise once the group is made resident.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_scheduler_queue_start(struct kbase_queue *queue);
-+
-+/**
-+ * kbase_csf_scheduler_queue_stop() - Disable the running of GPU command queue
-+ * on firmware.
-+ *
-+ * @queue: Pointer to the GPU command queue to be stopped.
-+ *
-+ * This function would stop the CSI, within a CSG, to which @queue was bound.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_scheduler_queue_stop(struct kbase_queue *queue);
-+
-+/**
-+ * kbase_csf_scheduler_group_protm_enter - Handle the protm enter event for the
-+ * GPU command queue group.
-+ *
-+ * @group: The command queue group.
-+ *
-+ * This function could request the firmware to enter the protected mode
-+ * and allow the execution of protected region instructions for all the
-+ * bound queues of the group that have protm pending bit set in their
-+ * respective CS_ACK register.
-+ */
-+void kbase_csf_scheduler_group_protm_enter(struct kbase_queue_group *group);
-+
-+/**
-+ * kbase_csf_scheduler_group_get_slot() - Checks if a queue group is
-+ * programmed on a firmware CSG slot
-+ * and returns the slot number.
-+ *
-+ * @group: The command queue group.
-+ *
-+ * Return: The slot number, if the group is programmed on a slot.
-+ * Otherwise returns a negative number.
-+ *
-+ * Note: This function should not be used if the interrupt_lock is held. Use
-+ * kbase_csf_scheduler_group_get_slot_locked() instead.
-+ */
-+int kbase_csf_scheduler_group_get_slot(struct kbase_queue_group *group);
-+
-+/**
-+ * kbase_csf_scheduler_group_get_slot_locked() - Checks if a queue group is
-+ * programmed on a firmware CSG slot
-+ * and returns the slot number.
-+ *
-+ * @group: The command queue group.
-+ *
-+ * Return: The slot number, if the group is programmed on a slot.
-+ * Otherwise returns a negative number.
-+ *
-+ * Note: Caller must hold the interrupt_lock.
-+ */
-+int kbase_csf_scheduler_group_get_slot_locked(struct kbase_queue_group *group);
-+
-+/**
-+ * kbase_csf_scheduler_group_events_enabled() - Checks if interrupt events
-+ * should be handled for a queue group.
-+ *
-+ * @kbdev: The device of the group.
-+ * @group: The queue group.
-+ *
-+ * Return: true if interrupt events should be handled.
-+ *
-+ * Note: Caller must hold the interrupt_lock.
-+ */
-+bool kbase_csf_scheduler_group_events_enabled(struct kbase_device *kbdev,
-+ struct kbase_queue_group *group);
-+
-+/**
-+ * kbase_csf_scheduler_get_group_on_slot()- Gets the queue group that has been
-+ * programmed to a firmware CSG slot.
-+ *
-+ * @kbdev: The GPU device.
-+ * @slot: The slot for which to get the queue group.
-+ *
-+ * Return: Pointer to the programmed queue group.
-+ *
-+ * Note: Caller must hold the interrupt_lock.
-+ */
-+struct kbase_queue_group *kbase_csf_scheduler_get_group_on_slot(
-+ struct kbase_device *kbdev, int slot);
-+
-+/**
-+ * kbase_csf_scheduler_group_deschedule() - Deschedule a GPU command queue
-+ * group from the firmware.
-+ *
-+ * @group: Pointer to the queue group to be descheduled.
-+ *
-+ * This function would disable the scheduling of GPU command queue group on
-+ * firmware.
-+ */
-+void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group);
-+
-+/**
-+ * kbase_csf_scheduler_evict_ctx_slots() - Evict all GPU command queue groups
-+ * of a given context that are active
-+ * running from the firmware.
-+ *
-+ * @kbdev: The GPU device.
-+ * @kctx: Kbase context for the evict operation.
-+ * @evicted_groups: List_head for returning evicted active queue groups.
-+ *
-+ * This function would disable the scheduling of GPU command queue groups active
-+ * on firmware slots from the given Kbase context. The affected groups are
-+ * added to the supplied list_head argument.
-+ */
-+void kbase_csf_scheduler_evict_ctx_slots(struct kbase_device *kbdev,
-+ struct kbase_context *kctx, struct list_head *evicted_groups);
-+
-+/**
-+ * kbase_csf_scheduler_context_init() - Initialize the context-specific part
-+ * for CSF scheduler.
-+ *
-+ * @kctx: Pointer to kbase context that is being created.
-+ *
-+ * This function must be called during Kbase context creation.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_scheduler_context_init(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_scheduler_init - Initialize the CSF scheduler
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * The scheduler does the arbitration for the CSG slots
-+ * provided by the firmware between the GPU command queue groups created
-+ * by the Clients.
-+ * This function must be called after loading firmware and parsing its capabilities.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_scheduler_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_early_init - Early initialization for the CSF scheduler
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Initialize necessary resources such as locks, workqueue for CSF scheduler.
-+ * This must be called at kbase probe.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_scheduler_early_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_context_term() - Terminate the context-specific part
-+ * for CSF scheduler.
-+ *
-+ * @kctx: Pointer to kbase context that is being terminated.
-+ *
-+ * This function must be called during Kbase context termination.
-+ */
-+void kbase_csf_scheduler_context_term(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_scheduler_term - Terminate the CSF scheduler.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * This should be called when unload of firmware is done on device
-+ * termination.
-+ */
-+void kbase_csf_scheduler_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_early_term - Early termination of the CSF scheduler.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * This should be called only when kbase probe fails or gets rmmoded.
-+ */
-+void kbase_csf_scheduler_early_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_reset - Reset the state of all active GPU command
-+ * queue groups.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * This function will first iterate through all the active/scheduled GPU
-+ * command queue groups and suspend them (to avoid losing work for groups
-+ * that are not stuck). The groups that could not get suspended would be
-+ * descheduled and marked as terminated (which will then lead to unbinding
-+ * of all the queues bound to them) and also no more work would be allowed
-+ * to execute for them.
-+ *
-+ * This is similar to the action taken in response to an unexpected OoM event.
-+ * No explicit re-initialization is done for CSG & CS interface I/O pages;
-+ * instead, that happens implicitly on firmware reload.
-+ *
-+ * Should be called only after initiating the GPU reset.
-+ */
-+void kbase_csf_scheduler_reset(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_enable_tick_timer - Enable the scheduler tick timer.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * This function will restart the scheduler tick so that regular scheduling can
-+ * be resumed without any explicit trigger (like kicking of GPU queues).
-+ */
-+void kbase_csf_scheduler_enable_tick_timer(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_group_copy_suspend_buf - Suspend a queue
-+ * group and copy suspend buffer.
-+ *
-+ * This function is called to suspend a queue group and copy the suspend_buffer
-+ * contents to the input buffer provided.
-+ *
-+ * @group: Pointer to the queue group to be suspended.
-+ * @sus_buf: Pointer to the structure which contains details of the
-+ * user buffer and its kernel pinned pages to which we need to copy
-+ * the group suspend buffer.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_scheduler_group_copy_suspend_buf(struct kbase_queue_group *group,
-+ struct kbase_suspend_copy_buffer *sus_buf);
-+
-+/**
-+ * kbase_csf_scheduler_lock - Acquire the global Scheduler lock.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * This function will take the global scheduler lock, in order to serialize
-+ * against the Scheduler actions, for access to CS IO pages.
-+ */
-+static inline void kbase_csf_scheduler_lock(struct kbase_device *kbdev)
-+{
-+ mutex_lock(&kbdev->csf.scheduler.lock);
-+}
-+
-+/**
-+ * kbase_csf_scheduler_unlock - Release the global Scheduler lock.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+static inline void kbase_csf_scheduler_unlock(struct kbase_device *kbdev)
-+{
-+ mutex_unlock(&kbdev->csf.scheduler.lock);
-+}
-+
-+/**
-+ * kbase_csf_scheduler_spin_lock - Acquire Scheduler interrupt spinlock.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @flags: Pointer to the memory location that would store the previous
-+ * interrupt state.
-+ *
-+ * This function will take the global scheduler lock, in order to serialize
-+ * against the Scheduler actions, for access to CS IO pages.
-+ */
-+static inline void kbase_csf_scheduler_spin_lock(struct kbase_device *kbdev,
-+ unsigned long *flags)
-+{
-+ spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, *flags);
-+}
-+
-+/**
-+ * kbase_csf_scheduler_spin_unlock - Release Scheduler interrupt spinlock.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @flags: Previously stored interrupt state when Scheduler interrupt
-+ * spinlock was acquired.
-+ */
-+static inline void kbase_csf_scheduler_spin_unlock(struct kbase_device *kbdev,
-+ unsigned long flags)
-+{
-+ spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags);
-+}
-+
-+/**
-+ * kbase_csf_scheduler_spin_lock_assert_held - Assert if the Scheduler
-+ * interrupt spinlock is held.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+static inline void
-+kbase_csf_scheduler_spin_lock_assert_held(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.interrupt_lock);
-+}
-+
-+/**
-+ * kbase_csf_scheduler_timer_is_enabled() - Check if the scheduler wakes up
-+ * automatically for periodic tasks.
-+ *
-+ * @kbdev: Pointer to the device
-+ *
-+ * Return: true if the scheduler is configured to wake up periodically
-+ */
-+bool kbase_csf_scheduler_timer_is_enabled(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_timer_set_enabled() - Enable/disable periodic
-+ * scheduler tasks.
-+ *
-+ * @kbdev: Pointer to the device
-+ * @enable: Whether to enable periodic scheduler tasks
-+ */
-+void kbase_csf_scheduler_timer_set_enabled(struct kbase_device *kbdev,
-+ bool enable);
-+
-+/**
-+ * kbase_csf_scheduler_kick - Perform pending scheduling tasks once.
-+ *
-+ * Note: This function is only effective if the scheduling timer is disabled.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_scheduler_kick(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_protected_mode_in_use() - Check if the scheduler is
-+ * running with protected mode tasks.
-+ *
-+ * @kbdev: Pointer to the device
-+ *
-+ * Return: true if the scheduler is running with protected mode tasks
-+ */
-+static inline bool kbase_csf_scheduler_protected_mode_in_use(
-+ struct kbase_device *kbdev)
-+{
-+ return (kbdev->csf.scheduler.active_protm_grp != NULL);
-+}
-+
-+/**
-+ * kbase_csf_scheduler_pm_active - Perform scheduler power active operation
-+ *
-+ * Note: This function will increase the scheduler's internal pm_active_count
-+ * value, ensuring that both GPU and MCU are powered for access.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_scheduler_pm_active(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_pm_idle - Perform the scheduler power idle operation
-+ *
-+ * Note: This function will decrease the scheduler's internal pm_active_count
-+ * value. On reaching 0, the MCU and GPU could be powered off.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ */
-+void kbase_csf_scheduler_pm_idle(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_pm_resume - Reactivate the scheduler on system resume
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * This function will make the scheduler resume the scheduling of queue groups
-+ * and take the power managemenet reference, if there are any runnable groups.
-+ */
-+void kbase_csf_scheduler_pm_resume(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_pm_suspend - Idle the scheduler on system suspend
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * This function will make the scheduler suspend all the running queue groups
-+ * and drop its power managemenet reference.
-+ */
-+void kbase_csf_scheduler_pm_suspend(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_scheduler_all_csgs_idle() - Check if the scheduler internal
-+ * runtime used slots are all tagged as idle command queue groups.
-+ *
-+ * @kbdev: Pointer to the device
-+ *
-+ * Return: true if all the used slots are tagged as idle CSGs.
-+ */
-+static inline bool kbase_csf_scheduler_all_csgs_idle(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->csf.scheduler.interrupt_lock);
-+ return bitmap_equal(kbdev->csf.scheduler.csg_slots_idle_mask,
-+ kbdev->csf.scheduler.csg_inuse_bitmap,
-+ kbdev->csf.global_iface.group_num);
-+}
-+
-+/**
-+ * kbase_csf_scheduler_advance_tick_nolock() - Advance the scheduling tick
-+ *
-+ * @kbdev: Pointer to the device
-+ *
-+ * This function advances the scheduling tick by enqueing the tick work item for
-+ * immediate execution, but only if the tick hrtimer is active. If the timer
-+ * is inactive then the tick work item is already in flight.
-+ * The caller must hold the interrupt lock.
-+ */
-+static inline void
-+kbase_csf_scheduler_advance_tick_nolock(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+
-+ lockdep_assert_held(&scheduler->interrupt_lock);
-+
-+ if (scheduler->tick_timer_active) {
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_ADVANCE_TICK, NULL, 0u);
-+ scheduler->tick_timer_active = false;
-+ queue_work(scheduler->wq, &scheduler->tick_work);
-+ } else {
-+ KBASE_KTRACE_ADD(kbdev, SCHEDULER_NOADVANCE_TICK, NULL, 0u);
-+ }
-+}
-+
-+/**
-+ * kbase_csf_scheduler_advance_tick() - Advance the scheduling tick
-+ *
-+ * @kbdev: Pointer to the device
-+ *
-+ * This function advances the scheduling tick by enqueing the tick work item for
-+ * immediate execution, but only if the tick hrtimer is active. If the timer
-+ * is inactive then the tick work item is already in flight.
-+ */
-+static inline void kbase_csf_scheduler_advance_tick(struct kbase_device *kbdev)
-+{
-+ struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&scheduler->interrupt_lock, flags);
-+ kbase_csf_scheduler_advance_tick_nolock(kbdev);
-+ spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-+}
-+
-+/**
-+ * kbase_csf_scheduler_queue_has_trace() - report whether the queue has been
-+ * configured to operate with the
-+ * cs_trace feature.
-+ *
-+ * @queue: Pointer to the queue.
-+ *
-+ * Return: True if the gpu queue is configured to operate with the cs_trace
-+ * feature, otherwise false.
-+ */
-+static inline bool kbase_csf_scheduler_queue_has_trace(struct kbase_queue *queue)
-+{
-+ lockdep_assert_held(&queue->kctx->kbdev->csf.scheduler.lock);
-+ /* In the current arrangement, it is possible for the context to enable
-+ * the cs_trace after some queues have been registered with cs_trace in
-+ * disabled state. So each queue has its own enabled/disabled condition.
-+ */
-+ return (queue->trace_buffer_size && queue->trace_buffer_base);
-+}
-+
-+#endif /* _KBASE_CSF_SCHEDULER_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.c
-new file mode 100644
-index 0000000..8ecf235
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.c
-@@ -0,0 +1,611 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <tl/mali_kbase_tracepoints.h>
-+
-+#include "mali_kbase_csf_tiler_heap.h"
-+#include "mali_kbase_csf_tiler_heap_def.h"
-+#include "mali_kbase_csf_heap_context_alloc.h"
-+
-+/**
-+ * encode_chunk_ptr - Encode the address and size of a chunk as an integer.
-+ *
-+ * The size and address of the next chunk in a list are packed into a single
-+ * 64-bit value for storage in a chunk's header. This function returns that
-+ * value.
-+ *
-+ * @chunk_size: Size of a tiler heap chunk, in bytes.
-+ * @chunk_addr: GPU virtual address of the same tiler heap chunk.
-+ *
-+ * Return: Next chunk pointer suitable for writing into a chunk header.
-+ */
-+static u64 encode_chunk_ptr(u32 const chunk_size, u64 const chunk_addr)
-+{
-+ u64 encoded_size, encoded_addr;
-+
-+ WARN_ON(chunk_size & ~CHUNK_SIZE_MASK);
-+ WARN_ON(chunk_addr & ~CHUNK_ADDR_MASK);
-+
-+ encoded_size =
-+ (u64)(chunk_size >> CHUNK_HDR_NEXT_SIZE_ENCODE_SHIFT) <<
-+ CHUNK_HDR_NEXT_SIZE_POS;
-+
-+ encoded_addr =
-+ (chunk_addr >> CHUNK_HDR_NEXT_ADDR_ENCODE_SHIFT) <<
-+ CHUNK_HDR_NEXT_ADDR_POS;
-+
-+ return (encoded_size & CHUNK_HDR_NEXT_SIZE_MASK) |
-+ (encoded_addr & CHUNK_HDR_NEXT_ADDR_MASK);
-+}
-+
-+/**
-+ * get_last_chunk - Get the last chunk of a tiler heap
-+ *
-+ * @heap: Pointer to the tiler heap.
-+ *
-+ * Return: The address of the most recently-linked chunk, or NULL if none.
-+ */
-+static struct kbase_csf_tiler_heap_chunk *get_last_chunk(
-+ struct kbase_csf_tiler_heap *const heap)
-+{
-+ lockdep_assert_held(&heap->kctx->csf.tiler_heaps.lock);
-+
-+ if (list_empty(&heap->chunks_list))
-+ return NULL;
-+
-+ return list_last_entry(&heap->chunks_list,
-+ struct kbase_csf_tiler_heap_chunk, link);
-+}
-+
-+/**
-+ * link_chunk - Link a chunk into a tiler heap
-+ *
-+ * Unless the @chunk is the first in the kernel's list of chunks belonging to
-+ * a given tiler heap, this function stores the size and address of the @chunk
-+ * in the header of the preceding chunk. This requires the GPU memory region
-+ * containing the header to be be mapped temporarily, which can fail.
-+ *
-+ * @heap: Pointer to the tiler heap.
-+ * @chunk: Pointer to the heap chunk to be linked.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+static int link_chunk(struct kbase_csf_tiler_heap *const heap,
-+ struct kbase_csf_tiler_heap_chunk *const chunk)
-+{
-+ struct kbase_csf_tiler_heap_chunk *const prev = get_last_chunk(heap);
-+
-+ if (prev) {
-+ struct kbase_context *const kctx = heap->kctx;
-+ struct kbase_vmap_struct map;
-+ u64 *const prev_hdr = kbase_vmap_prot(kctx, prev->gpu_va,
-+ sizeof(*prev_hdr), KBASE_REG_CPU_WR, &map);
-+
-+ if (unlikely(!prev_hdr)) {
-+ dev_err(kctx->kbdev->dev,
-+ "Failed to map tiler heap chunk 0x%llX\n",
-+ prev->gpu_va);
-+ return -ENOMEM;
-+ }
-+
-+ *prev_hdr = encode_chunk_ptr(heap->chunk_size, chunk->gpu_va);
-+ kbase_vunmap(kctx, &map);
-+
-+ dev_dbg(kctx->kbdev->dev,
-+ "Linked tiler heap chunks, 0x%llX -> 0x%llX\n",
-+ prev->gpu_va, chunk->gpu_va);
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * init_chunk - Initialize and link a tiler heap chunk
-+ *
-+ * Zero-initialize a new chunk's header (including its pointer to the next
-+ * chunk, which doesn't exist yet) and then update the previous chunk's
-+ * header to link the new chunk into the chunk list.
-+ *
-+ * @heap: Pointer to the tiler heap.
-+ * @chunk: Pointer to the heap chunk to be initialized and linked.
-+ * @link_with_prev: Flag to indicate if the new chunk needs to be linked with
-+ * the previously allocated chunk.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+static int init_chunk(struct kbase_csf_tiler_heap *const heap,
-+ struct kbase_csf_tiler_heap_chunk *const chunk, bool link_with_prev)
-+{
-+ struct kbase_vmap_struct map;
-+ struct u64 *chunk_hdr = NULL;
-+ struct kbase_context *const kctx = heap->kctx;
-+
-+ if (unlikely(chunk->gpu_va & ~CHUNK_ADDR_MASK)) {
-+ dev_err(kctx->kbdev->dev,
-+ "Tiler heap chunk address is unusable\n");
-+ return -EINVAL;
-+ }
-+
-+ chunk_hdr = kbase_vmap_prot(kctx,
-+ chunk->gpu_va, CHUNK_HDR_SIZE, KBASE_REG_CPU_WR, &map);
-+
-+ if (unlikely(!chunk_hdr)) {
-+ dev_err(kctx->kbdev->dev,
-+ "Failed to map a tiler heap chunk header\n");
-+ return -ENOMEM;
-+ }
-+
-+ memset(chunk_hdr, 0, CHUNK_HDR_SIZE);
-+ kbase_vunmap(kctx, &map);
-+
-+ if (link_with_prev)
-+ return link_chunk(heap, chunk);
-+ else
-+ return 0;
-+}
-+
-+/**
-+ * create_chunk - Create a tiler heap chunk
-+ *
-+ * This function allocates a chunk of memory for a tiler heap and adds it to
-+ * the end of the list of chunks associated with that heap. The size of the
-+ * chunk is not a parameter because it is configured per-heap not per-chunk.
-+ *
-+ * @heap: Pointer to the tiler heap for which to allocate memory.
-+ * @link_with_prev: Flag to indicate if the chunk to be allocated needs to be
-+ * linked with the previously allocated chunk.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+static int create_chunk(struct kbase_csf_tiler_heap *const heap,
-+ bool link_with_prev)
-+{
-+ int err = 0;
-+ struct kbase_context *const kctx = heap->kctx;
-+ u64 nr_pages = PFN_UP(heap->chunk_size);
-+ u64 flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR |
-+ BASE_MEM_PROT_CPU_WR | BASEP_MEM_NO_USER_FREE |
-+ BASE_MEM_COHERENT_LOCAL;
-+ struct kbase_csf_tiler_heap_chunk *chunk = NULL;
-+
-+ flags |= base_mem_group_id_set(kctx->jit_group_id);
-+
-+#if defined(CONFIG_MALI_DEBUG) || defined(CONFIG_MALI_VECTOR_DUMP)
-+ flags |= BASE_MEM_PROT_CPU_RD;
-+#endif
-+
-+ lockdep_assert_held(&kctx->csf.tiler_heaps.lock);
-+
-+ chunk = kzalloc(sizeof(*chunk), GFP_KERNEL);
-+ if (unlikely(!chunk)) {
-+ dev_err(kctx->kbdev->dev,
-+ "No kernel memory for a new tiler heap chunk\n");
-+ return -ENOMEM;
-+ }
-+
-+ /* Allocate GPU memory for the new chunk. */
-+ INIT_LIST_HEAD(&chunk->link);
-+ chunk->region = kbase_mem_alloc(kctx, nr_pages, nr_pages, 0,
-+ &flags, &chunk->gpu_va);
-+
-+ if (unlikely(!chunk->region)) {
-+ dev_err(kctx->kbdev->dev,
-+ "Failed to allocate a tiler heap chunk\n");
-+ err = -ENOMEM;
-+ } else {
-+ err = init_chunk(heap, chunk, link_with_prev);
-+ if (unlikely(err)) {
-+ kbase_gpu_vm_lock(kctx);
-+ chunk->region->flags &= ~KBASE_REG_NO_USER_FREE;
-+ kbase_mem_free_region(kctx, chunk->region);
-+ kbase_gpu_vm_unlock(kctx);
-+ }
-+ }
-+
-+ if (unlikely(err)) {
-+ kfree(chunk);
-+ } else {
-+ list_add_tail(&chunk->link, &heap->chunks_list);
-+ heap->chunk_count++;
-+
-+ dev_dbg(kctx->kbdev->dev, "Created tiler heap chunk 0x%llX\n",
-+ chunk->gpu_va);
-+ }
-+
-+ return err;
-+}
-+
-+/**
-+ * delete_chunk - Delete a tiler heap chunk
-+ *
-+ * This function frees a tiler heap chunk previously allocated by @create_chunk
-+ * and removes it from the list of chunks associated with the heap.
-+ *
-+ * WARNING: The deleted chunk is not unlinked from the list of chunks used by
-+ * the GPU, therefore it is only safe to use this function when
-+ * deleting a heap.
-+ *
-+ * @heap: Pointer to the tiler heap for which @chunk was allocated.
-+ * @chunk: Pointer to a chunk to be deleted.
-+ */
-+static void delete_chunk(struct kbase_csf_tiler_heap *const heap,
-+ struct kbase_csf_tiler_heap_chunk *const chunk)
-+{
-+ struct kbase_context *const kctx = heap->kctx;
-+
-+ lockdep_assert_held(&kctx->csf.tiler_heaps.lock);
-+
-+ kbase_gpu_vm_lock(kctx);
-+ chunk->region->flags &= ~KBASE_REG_NO_USER_FREE;
-+ kbase_mem_free_region(kctx, chunk->region);
-+ kbase_gpu_vm_unlock(kctx);
-+ list_del(&chunk->link);
-+ heap->chunk_count--;
-+ kfree(chunk);
-+}
-+
-+/**
-+ * delete_all_chunks - Delete all chunks belonging to a tiler heap
-+ *
-+ * This function empties the list of chunks associated with a tiler heap by
-+ * freeing all chunks previously allocated by @create_chunk.
-+ *
-+ * @heap: Pointer to a tiler heap.
-+ */
-+static void delete_all_chunks(struct kbase_csf_tiler_heap *heap)
-+{
-+ struct list_head *entry = NULL, *tmp = NULL;
-+ struct kbase_context *const kctx = heap->kctx;
-+
-+ lockdep_assert_held(&kctx->csf.tiler_heaps.lock);
-+
-+ list_for_each_safe(entry, tmp, &heap->chunks_list) {
-+ struct kbase_csf_tiler_heap_chunk *chunk = list_entry(
-+ entry, struct kbase_csf_tiler_heap_chunk, link);
-+
-+ delete_chunk(heap, chunk);
-+ }
-+}
-+
-+/**
-+ * create_initial_chunks - Create the initial list of chunks for a tiler heap
-+ *
-+ * This function allocates a given number of chunks for a tiler heap and
-+ * adds them to the list of chunks associated with that heap.
-+ *
-+ * @heap: Pointer to the tiler heap for which to allocate memory.
-+ * @nchunks: Number of chunks to create.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+static int create_initial_chunks(struct kbase_csf_tiler_heap *const heap,
-+ u32 const nchunks)
-+{
-+ int err = 0;
-+ u32 i;
-+
-+ for (i = 0; (i < nchunks) && likely(!err); i++)
-+ err = create_chunk(heap, true);
-+
-+ if (unlikely(err))
-+ delete_all_chunks(heap);
-+
-+ return err;
-+}
-+
-+/**
-+ * delete_heap - Delete a tiler heap
-+ *
-+ * This function frees any chunks allocated for a tiler heap previously
-+ * initialized by @kbase_csf_tiler_heap_init and removes it from the list of
-+ * heaps associated with the kbase context. The heap context structure used by
-+ * the firmware is also freed.
-+ *
-+ * @heap: Pointer to a tiler heap to be deleted.
-+ */
-+static void delete_heap(struct kbase_csf_tiler_heap *heap)
-+{
-+ struct kbase_context *const kctx = heap->kctx;
-+
-+ dev_dbg(kctx->kbdev->dev, "Deleting tiler heap 0x%llX\n", heap->gpu_va);
-+
-+ lockdep_assert_held(&kctx->csf.tiler_heaps.lock);
-+
-+ delete_all_chunks(heap);
-+
-+ /* We could optimize context destruction by not freeing leaked heap
-+ * contexts but it doesn't seem worth the extra complexity.
-+ */
-+ kbase_csf_heap_context_allocator_free(&kctx->csf.tiler_heaps.ctx_alloc,
-+ heap->gpu_va);
-+
-+ list_del(&heap->link);
-+
-+ WARN_ON(heap->chunk_count);
-+ KBASE_TLSTREAM_AUX_TILER_HEAP_STATS(kctx->kbdev, kctx->id,
-+ heap->heap_id, 0, 0, heap->max_chunks, heap->chunk_size, 0,
-+ heap->target_in_flight, 0);
-+
-+ kfree(heap);
-+}
-+
-+/**
-+ * find_tiler_heap - Find a tiler heap from the address of its heap context
-+ *
-+ * Each tiler heap managed by the kernel has an associated heap context
-+ * structure used by the firmware. This function finds a tiler heap object from
-+ * the GPU virtual address of its associated heap context. The heap context
-+ * should have been allocated by @kbase_csf_heap_context_allocator_alloc in the
-+ * same @kctx.
-+ *
-+ * @kctx: Pointer to the kbase context to search for a tiler heap.
-+ * @heap_gpu_va: GPU virtual address of a heap context structure.
-+ *
-+ * Return: pointer to the tiler heap object, or NULL if not found.
-+ */
-+static struct kbase_csf_tiler_heap *find_tiler_heap(
-+ struct kbase_context *const kctx, u64 const heap_gpu_va)
-+{
-+ struct kbase_csf_tiler_heap *heap = NULL;
-+
-+ lockdep_assert_held(&kctx->csf.tiler_heaps.lock);
-+
-+ list_for_each_entry(heap, &kctx->csf.tiler_heaps.list, link) {
-+ if (heap_gpu_va == heap->gpu_va)
-+ return heap;
-+ }
-+
-+ dev_dbg(kctx->kbdev->dev, "Tiler heap 0x%llX was not found\n",
-+ heap_gpu_va);
-+
-+ return NULL;
-+}
-+
-+int kbase_csf_tiler_heap_context_init(struct kbase_context *const kctx)
-+{
-+ int err = kbase_csf_heap_context_allocator_init(
-+ &kctx->csf.tiler_heaps.ctx_alloc, kctx);
-+
-+ if (unlikely(err))
-+ return err;
-+
-+ INIT_LIST_HEAD(&kctx->csf.tiler_heaps.list);
-+ mutex_init(&kctx->csf.tiler_heaps.lock);
-+
-+ dev_dbg(kctx->kbdev->dev, "Initialized a context for tiler heaps\n");
-+
-+ return 0;
-+}
-+
-+void kbase_csf_tiler_heap_context_term(struct kbase_context *const kctx)
-+{
-+ struct list_head *entry = NULL, *tmp = NULL;
-+
-+ dev_dbg(kctx->kbdev->dev, "Terminating a context for tiler heaps\n");
-+
-+ mutex_lock(&kctx->csf.tiler_heaps.lock);
-+
-+ list_for_each_safe(entry, tmp, &kctx->csf.tiler_heaps.list) {
-+ struct kbase_csf_tiler_heap *heap = list_entry(
-+ entry, struct kbase_csf_tiler_heap, link);
-+ delete_heap(heap);
-+ }
-+
-+ mutex_unlock(&kctx->csf.tiler_heaps.lock);
-+ mutex_destroy(&kctx->csf.tiler_heaps.lock);
-+
-+ kbase_csf_heap_context_allocator_term(&kctx->csf.tiler_heaps.ctx_alloc);
-+}
-+
-+int kbase_csf_tiler_heap_init(struct kbase_context *const kctx,
-+ u32 const chunk_size, u32 const initial_chunks, u32 const max_chunks,
-+ u16 const target_in_flight, u64 *const heap_gpu_va,
-+ u64 *const first_chunk_va)
-+{
-+ int err = 0;
-+ struct kbase_csf_tiler_heap *heap = NULL;
-+ struct kbase_csf_heap_context_allocator *const ctx_alloc =
-+ &kctx->csf.tiler_heaps.ctx_alloc;
-+
-+ dev_dbg(kctx->kbdev->dev,
-+ "Creating a tiler heap with %u chunks (limit: %u) of size %u\n",
-+ initial_chunks, max_chunks, chunk_size);
-+
-+ if (chunk_size == 0)
-+ return -EINVAL;
-+
-+ if (chunk_size & ~CHUNK_SIZE_MASK)
-+ return -EINVAL;
-+
-+ if (initial_chunks == 0)
-+ return -EINVAL;
-+
-+ if (initial_chunks > max_chunks)
-+ return -EINVAL;
-+
-+ if (target_in_flight == 0)
-+ return -EINVAL;
-+
-+ heap = kzalloc(sizeof(*heap), GFP_KERNEL);
-+ if (unlikely(!heap)) {
-+ dev_err(kctx->kbdev->dev,
-+ "No kernel memory for a new tiler heap\n");
-+ return -ENOMEM;
-+ }
-+
-+ heap->kctx = kctx;
-+ heap->chunk_size = chunk_size;
-+ heap->max_chunks = max_chunks;
-+ heap->target_in_flight = target_in_flight;
-+ INIT_LIST_HEAD(&heap->chunks_list);
-+
-+ heap->gpu_va = kbase_csf_heap_context_allocator_alloc(ctx_alloc);
-+
-+ mutex_lock(&kctx->csf.tiler_heaps.lock);
-+
-+ if (unlikely(!heap->gpu_va)) {
-+ dev_err(kctx->kbdev->dev,
-+ "Failed to allocate a tiler heap context\n");
-+ err = -ENOMEM;
-+ } else {
-+ err = create_initial_chunks(heap, initial_chunks);
-+ if (unlikely(err)) {
-+ kbase_csf_heap_context_allocator_free(ctx_alloc,
-+ heap->gpu_va);
-+ }
-+ }
-+
-+ if (unlikely(err)) {
-+ kfree(heap);
-+ } else {
-+ struct kbase_csf_tiler_heap_chunk const *first_chunk =
-+ list_first_entry(&heap->chunks_list,
-+ struct kbase_csf_tiler_heap_chunk, link);
-+
-+ kctx->csf.tiler_heaps.nr_of_heaps++;
-+ heap->heap_id = kctx->csf.tiler_heaps.nr_of_heaps;
-+ list_add(&heap->link, &kctx->csf.tiler_heaps.list);
-+
-+ *heap_gpu_va = heap->gpu_va;
-+ *first_chunk_va = first_chunk->gpu_va;
-+
-+ KBASE_TLSTREAM_AUX_TILER_HEAP_STATS(
-+ kctx->kbdev, kctx->id, heap->heap_id,
-+ PFN_UP(heap->chunk_size * heap->max_chunks),
-+ PFN_UP(heap->chunk_size * heap->chunk_count),
-+ heap->max_chunks, heap->chunk_size, heap->chunk_count,
-+ heap->target_in_flight, 0);
-+
-+ dev_dbg(kctx->kbdev->dev, "Created tiler heap 0x%llX\n",
-+ heap->gpu_va);
-+ }
-+
-+ mutex_unlock(&kctx->csf.tiler_heaps.lock);
-+
-+ return err;
-+}
-+
-+int kbase_csf_tiler_heap_term(struct kbase_context *const kctx,
-+ u64 const heap_gpu_va)
-+{
-+ int err = 0;
-+ struct kbase_csf_tiler_heap *heap = NULL;
-+
-+ mutex_lock(&kctx->csf.tiler_heaps.lock);
-+
-+ heap = find_tiler_heap(kctx, heap_gpu_va);
-+ if (likely(heap))
-+ delete_heap(heap);
-+ else
-+ err = -EINVAL;
-+
-+ mutex_unlock(&kctx->csf.tiler_heaps.lock);
-+
-+ return err;
-+}
-+
-+/**
-+ * alloc_new_chunk - Allocate a new chunk for the tiler heap.
-+ *
-+ * This function will allocate a new chunk for the chunked tiler heap depending
-+ * on the settings provided by userspace when the heap was created and the
-+ * heap's statistics (like number of render passes in-flight).
-+ *
-+ * @heap: Pointer to the tiler heap.
-+ * @nr_in_flight: Number of render passes that are in-flight, must not be zero.
-+ * @pending_frag_count: Number of render passes in-flight with completed vertex/tiler stage.
-+ * The minimum value is zero but it must be less or equal to
-+ * the total number of render passes in flight
-+ * @new_chunk_ptr: Where to store the GPU virtual address & size of the new
-+ * chunk allocated for the heap.
-+ *
-+ * Return: 0 if a new chunk was allocated otherwise an appropriate negative
-+ * error code.
-+ */
-+static int alloc_new_chunk(struct kbase_csf_tiler_heap *heap,
-+ u32 nr_in_flight, u32 pending_frag_count, u64 *new_chunk_ptr)
-+{
-+ int err = -ENOMEM;
-+
-+ lockdep_assert_held(&heap->kctx->csf.tiler_heaps.lock);
-+
-+ if (WARN_ON(!nr_in_flight) ||
-+ WARN_ON(pending_frag_count > nr_in_flight))
-+ return -EINVAL;
-+
-+ if (nr_in_flight <= heap->target_in_flight) {
-+ if (heap->chunk_count < heap->max_chunks) {
-+ /* Not exceeded the target number of render passes yet so be
-+ * generous with memory.
-+ */
-+ err = create_chunk(heap, false);
-+
-+ if (likely(!err)) {
-+ struct kbase_csf_tiler_heap_chunk *new_chunk =
-+ get_last_chunk(heap);
-+ if (!WARN_ON(!new_chunk)) {
-+ *new_chunk_ptr =
-+ encode_chunk_ptr(heap->chunk_size,
-+ new_chunk->gpu_va);
-+ return 0;
-+ }
-+ }
-+ } else if (pending_frag_count > 0) {
-+ err = -EBUSY;
-+ } else {
-+ err = -ENOMEM;
-+ }
-+ } else {
-+ /* Reached target number of render passes in flight.
-+ * Wait for some of them to finish
-+ */
-+ err = -EBUSY;
-+ }
-+
-+ return err;
-+}
-+
-+int kbase_csf_tiler_heap_alloc_new_chunk(struct kbase_context *kctx,
-+ u64 gpu_heap_va, u32 nr_in_flight, u32 pending_frag_count, u64 *new_chunk_ptr)
-+{
-+ struct kbase_csf_tiler_heap *heap;
-+ int err = -EINVAL;
-+
-+ mutex_lock(&kctx->csf.tiler_heaps.lock);
-+
-+ heap = find_tiler_heap(kctx, gpu_heap_va);
-+
-+ if (likely(heap)) {
-+ err = alloc_new_chunk(heap, nr_in_flight, pending_frag_count,
-+ new_chunk_ptr);
-+
-+ KBASE_TLSTREAM_AUX_TILER_HEAP_STATS(
-+ kctx->kbdev, kctx->id, heap->heap_id,
-+ PFN_UP(heap->chunk_size * heap->max_chunks),
-+ PFN_UP(heap->chunk_size * heap->chunk_count),
-+ heap->max_chunks, heap->chunk_size, heap->chunk_count,
-+ heap->target_in_flight, nr_in_flight);
-+ }
-+
-+ mutex_unlock(&kctx->csf.tiler_heaps.lock);
-+
-+ return err;
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.h
-new file mode 100644
-index 0000000..04c27f7
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap.h
-@@ -0,0 +1,115 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_TILER_HEAP_H_
-+#define _KBASE_CSF_TILER_HEAP_H_
-+
-+#include <mali_kbase.h>
-+
-+/**
-+ * kbase_csf_tiler_heap_context_init - Initialize the tiler heaps context for a
-+ * GPU address space
-+ *
-+ * @kctx: Pointer to the kbase context being initialized.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+int kbase_csf_tiler_heap_context_init(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_tiler_heap_context_term - Terminate the tiler heaps context for a
-+ * GPU address space
-+ *
-+ * This function deletes any chunked tiler heaps that weren't deleted before
-+ * context termination.
-+ *
-+ * @kctx: Pointer to the kbase context being terminated.
-+ */
-+void kbase_csf_tiler_heap_context_term(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_csf_tiler_heap_init - Initialize a chunked tiler memory heap.
-+ *
-+ * @kctx: Pointer to the kbase context in which to allocate resources for the
-+ * tiler heap.
-+ * @chunk_size: Size of each chunk, in bytes. Must be page-aligned.
-+ * @initial_chunks: The initial number of chunks to allocate. Must not be
-+ * zero or greater than @max_chunks.
-+ * @max_chunks: The maximum number of chunks that the heap should be allowed
-+ * to use. Must not be less than @initial_chunks.
-+ * @target_in_flight: Number of render-passes that the driver should attempt to
-+ * keep in flight for which allocation of new chunks is
-+ * allowed. Must not be zero.
-+ * @gpu_heap_va: Where to store the GPU virtual address of the context that was
-+ * set up for the tiler heap.
-+ * @first_chunk_va: Where to store the GPU virtual address of the first chunk
-+ * allocated for the heap. This points to the header of the
-+ * heap chunk and not to the low address of free memory in it.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+int kbase_csf_tiler_heap_init(struct kbase_context *kctx,
-+ u32 chunk_size, u32 initial_chunks, u32 max_chunks,
-+ u16 target_in_flight, u64 *gpu_heap_va,
-+ u64 *first_chunk_va);
-+
-+/**
-+ * kbasep_cs_tiler_heap_term - Terminate a chunked tiler memory heap.
-+ *
-+ * This function will terminate a chunked tiler heap and cause all the chunks
-+ * (initial and those added during out-of-memory processing) to be freed.
-+ * It is the caller's responsibility to ensure no further operations on this
-+ * heap will happen before calling this function.
-+ *
-+ * @kctx: Pointer to the kbase context in which the tiler heap was initialized.
-+ * @gpu_heap_va: The GPU virtual address of the context that was set up for the
-+ * tiler heap.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+int kbase_csf_tiler_heap_term(struct kbase_context *kctx, u64 gpu_heap_va);
-+
-+/**
-+ * kbase_csf_tiler_heap_alloc_new_chunk - Allocate a new chunk for tiler heap.
-+ *
-+ * This function will allocate a new chunk for the chunked tiler heap depending
-+ * on the settings provided by userspace when the heap was created and the
-+ * heap's statistics (like number of render passes in-flight).
-+ * It would return an appropriate error code if a new chunk couldn't be
-+ * allocated.
-+ *
-+ * @kctx: Pointer to the kbase context in which the tiler heap was initialized.
-+ * @gpu_heap_va: GPU virtual address of the heap context.
-+ * @nr_in_flight: Number of render passes that are in-flight, must not be zero.
-+ * @pending_frag_count: Number of render passes in-flight with completed vertex/tiler stage.
-+ * The minimum value is zero but it must be less or equal to
-+ * the total number of render passes in flight
-+ * @new_chunk_ptr: Where to store the GPU virtual address & size of the new
-+ * chunk allocated for the heap.
-+ *
-+ * Return: 0 if a new chunk was allocated otherwise an appropriate negative
-+ * error code (like -EBUSY when a free chunk is expected to be
-+ * available upon completion of a render pass and -EINVAL when
-+ * invalid value was passed for one of the argument).
-+ */
-+int kbase_csf_tiler_heap_alloc_new_chunk(struct kbase_context *kctx,
-+ u64 gpu_heap_va, u32 nr_in_flight, u32 pending_frag_count, u64 *new_chunk_ptr);
-+#endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_debugfs.c
-new file mode 100644
-index 0000000..f46beed
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_debugfs.c
-@@ -0,0 +1,106 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_csf_tiler_heap_debugfs.h"
-+#include "mali_kbase_csf_tiler_heap_def.h"
-+#include <mali_kbase.h>
-+#include <linux/seq_file.h>
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+
-+/**
-+ * kbasep_csf_tiler_heap_debugfs_show() - Print tiler heap information for per context
-+ *
-+ * @file: The seq_file for printing to
-+ * @data: The debugfs dentry private data, a pointer to kbase_context
-+ *
-+ * Return: Negative error code or 0 on success.
-+ */
-+static int kbasep_csf_tiler_heap_debugfs_show(struct seq_file *file, void *data)
-+{
-+ struct kbase_context *kctx = file->private;
-+ struct kbase_csf_tiler_heap_context *tiler_heaps_p = &kctx->csf.tiler_heaps;
-+ struct kbase_csf_tiler_heap *heap;
-+ struct kbase_csf_tiler_heap_chunk *chunk;
-+
-+ seq_printf(file, "MALI_CSF_TILER_HEAP_DEBUGFS_VERSION: v%u\n", MALI_CSF_TILER_HEAP_DEBUGFS_VERSION);
-+
-+ mutex_lock(&tiler_heaps_p->lock);
-+
-+ list_for_each_entry(heap, &tiler_heaps_p->list, link) {
-+ if (heap->kctx != kctx)
-+ continue;
-+
-+ seq_printf(file, "HEAP(gpu_va = 0x%llx):\n", heap->gpu_va);
-+ seq_printf(file, "\tchunk_size = %u\n", heap->chunk_size);
-+ seq_printf(file, "\tchunk_count = %u\n", heap->chunk_count);
-+ seq_printf(file, "\tmax_chunks = %u\n", heap->max_chunks);
-+ seq_printf(file, "\ttarget_in_flight = %u\n", heap->target_in_flight);
-+
-+ list_for_each_entry(chunk, &heap->chunks_list, link)
-+ seq_printf(file, "\t\tchunk gpu_va = 0x%llx\n",
-+ chunk->gpu_va);
-+ }
-+
-+ mutex_unlock(&tiler_heaps_p->lock);
-+
-+ return 0;
-+}
-+
-+static int kbasep_csf_tiler_heap_debugfs_open(struct inode *in, struct file *file)
-+{
-+ return single_open(file, kbasep_csf_tiler_heap_debugfs_show, in->i_private);
-+}
-+
-+static const struct file_operations kbasep_csf_tiler_heap_debugfs_fops = {
-+ .open = kbasep_csf_tiler_heap_debugfs_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+void kbase_csf_tiler_heap_debugfs_init(struct kbase_context *kctx)
-+{
-+ struct dentry *file;
-+
-+ if (WARN_ON(!kctx || IS_ERR_OR_NULL(kctx->kctx_dentry)))
-+ return;
-+
-+ file = debugfs_create_file("tiler_heaps", 0444, kctx->kctx_dentry,
-+ kctx, &kbasep_csf_tiler_heap_debugfs_fops);
-+
-+ if (IS_ERR_OR_NULL(file)) {
-+ dev_warn(kctx->kbdev->dev,
-+ "Unable to create tiler heap debugfs entry");
-+ }
-+}
-+
-+
-+#else
-+/*
-+ * Stub functions for when debugfs is disabled
-+ */
-+void kbase_csf_tiler_heap_debugfs_init(struct kbase_context *kctx)
-+{
-+}
-+
-+#endif /* CONFIG_DEBUG_FS */
-+
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_debugfs.h
-new file mode 100644
-index 0000000..92ae91a
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_debugfs.h
-@@ -0,0 +1,37 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_TILER_HEAP_DEBUGFS_H_
-+#define _KBASE_CSF_TILER_HEAP_DEBUGFS_H_
-+
-+/* Forward declaration */
-+struct kbase_context;
-+
-+#define MALI_CSF_TILER_HEAP_DEBUGFS_VERSION 0
-+
-+/**
-+ * kbase_csf_tiler_heap_debugfs_init() - Create a debugfs entry for per context tiler heap
-+ *
-+ * @kctx: The kbase_context for which to create the debugfs entry
-+ */
-+void kbase_csf_tiler_heap_debugfs_init(struct kbase_context *kctx);
-+
-+#endif /* _KBASE_CSF_TILER_HEAP_DEBUGFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_def.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_def.h
-new file mode 100644
-index 0000000..fb439cf
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tiler_heap_def.h
-@@ -0,0 +1,114 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_TILER_HEAP_DEF_H_
-+#define _KBASE_CSF_TILER_HEAP_DEF_H_
-+
-+#include <mali_kbase.h>
-+
-+/* Size of a tiler heap chunk header, in bytes. */
-+#define CHUNK_HDR_SIZE ((size_t)64)
-+
-+/* Bit-position of the next chunk's size when stored in a chunk header. */
-+#define CHUNK_HDR_NEXT_SIZE_POS (0)
-+
-+/* Bit-position of the next chunk's address when stored in a chunk header. */
-+#define CHUNK_HDR_NEXT_ADDR_POS (12)
-+
-+/* Bitmask of the next chunk's size when stored in a chunk header. */
-+#define CHUNK_HDR_NEXT_SIZE_MASK (((u64)1 << CHUNK_HDR_NEXT_ADDR_POS) - 1u)
-+
-+/* Bitmask of the address of the next chunk when stored in a chunk header. */
-+#define CHUNK_HDR_NEXT_ADDR_MASK (~CHUNK_HDR_NEXT_SIZE_MASK)
-+
-+/* Right-shift before storing the next chunk's size in a chunk header. */
-+#define CHUNK_HDR_NEXT_SIZE_ENCODE_SHIFT (12)
-+
-+/* Right-shift before storing the next chunk's address in a chunk header. */
-+#define CHUNK_HDR_NEXT_ADDR_ENCODE_SHIFT (12)
-+
-+/* Bitmask of valid chunk sizes. This is also the maximum chunk size, in bytes.
-+ */
-+#define CHUNK_SIZE_MASK \
-+ ((CHUNK_HDR_NEXT_SIZE_MASK >> CHUNK_HDR_NEXT_SIZE_POS) << \
-+ CHUNK_HDR_NEXT_SIZE_ENCODE_SHIFT)
-+
-+/* Bitmask of valid chunk addresses. This is also the highest address. */
-+#define CHUNK_ADDR_MASK \
-+ ((CHUNK_HDR_NEXT_ADDR_MASK >> CHUNK_HDR_NEXT_ADDR_POS) << \
-+ CHUNK_HDR_NEXT_ADDR_ENCODE_SHIFT)
-+
-+/**
-+ * struct kbase_csf_tiler_heap_chunk - A tiler heap chunk managed by the kernel
-+ *
-+ * Chunks are allocated upon initialization of a tiler heap or in response to
-+ * out-of-memory events from the firmware. Chunks are always fully backed by
-+ * physical memory to avoid the overhead of processing GPU page faults. The
-+ * allocated GPU memory regions are linked together independent of the list of
-+ * kernel objects of this type.
-+ *
-+ * @link: Link to this chunk in a list of chunks belonging to a
-+ * @kbase_csf_tiler_heap.
-+ * @region: Pointer to the GPU memory region allocated for the chunk.
-+ * @gpu_va: GPU virtual address of the start of the memory region.
-+ * This points to the header of the chunk and not to the low address
-+ * of free memory within it.
-+ */
-+struct kbase_csf_tiler_heap_chunk {
-+ struct list_head link;
-+ struct kbase_va_region *region;
-+ u64 gpu_va;
-+};
-+
-+/**
-+ * struct kbase_csf_tiler_heap - A tiler heap managed by the kernel
-+ *
-+ * @kctx: Pointer to the kbase context with which this heap is
-+ * associated.
-+ * @link: Link to this heap in a list of tiler heaps belonging to
-+ * the @kbase_csf_tiler_heap_context.
-+ * @chunk_size: Size of each chunk, in bytes. Must be page-aligned.
-+ * @chunk_count: The number of chunks currently allocated. Must not be
-+ * zero or greater than @max_chunks.
-+ * @max_chunks: The maximum number of chunks that the heap should be
-+ * allowed to use. Must not be less than @chunk_count.
-+ * @target_in_flight: Number of render-passes that the driver should attempt
-+ * to keep in flight for which allocation of new chunks is
-+ * allowed. Must not be zero.
-+ * @gpu_va: The GPU virtual address of the heap context structure that
-+ * was allocated for the firmware. This is also used to
-+ * uniquely identify the heap.
-+ * @heap_id: Unique id representing the heap, assigned during heap
-+ * initialization.
-+ * @chunks_list: Linked list of allocated chunks.
-+ */
-+struct kbase_csf_tiler_heap {
-+ struct kbase_context *kctx;
-+ struct list_head link;
-+ u32 chunk_size;
-+ u32 chunk_count;
-+ u32 max_chunks;
-+ u16 target_in_flight;
-+ u64 gpu_va;
-+ u64 heap_id;
-+ struct list_head chunks_list;
-+};
-+#endif /* !_KBASE_CSF_TILER_HEAP_DEF_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_timeout.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_timeout.c
-new file mode 100644
-index 0000000..4d93fe5
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_timeout.c
-@@ -0,0 +1,178 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/device.h>
-+#include <linux/mutex.h>
-+#include <linux/sysfs.h>
-+#include <linux/of.h>
-+
-+#include "mali_kbase.h"
-+#include "mali_kbase_config_defaults.h"
-+#include "mali_kbase_csf_firmware.h"
-+#include "mali_kbase_csf_timeout.h"
-+#include "mali_kbase_reset_gpu.h"
-+#include "backend/gpu/mali_kbase_pm_internal.h"
-+
-+/**
-+ * set_timeout - set a new global progress timeout.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * @timeout: the maximum number of GPU cycles without forward progress to allow
-+ * to elapse before terminating a GPU command queue group.
-+ *
-+ * Return: 0 on success, or negative on failure
-+ * (e.g. -ERANGE if the requested timeout is too large).
-+ */
-+static int set_timeout(struct kbase_device *const kbdev, u64 const timeout)
-+{
-+ if (timeout > GLB_PROGRESS_TIMER_TIMEOUT_MAX) {
-+ dev_err(kbdev->dev, "Timeout %llu is too large.\n", timeout);
-+ return -ERANGE;
-+ }
-+
-+ dev_dbg(kbdev->dev, "New progress timeout: %llu cycles\n", timeout);
-+
-+ atomic64_set(&kbdev->csf.progress_timeout, timeout);
-+
-+ return 0;
-+}
-+
-+/**
-+ * progress_timeout_store - Store the progress_timeout device attribute.
-+ * @dev: The device that has the attribute.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The value written to the sysfs file.
-+ * @count: The number of bytes written to the sysfs file.
-+ *
-+ * This function is called when the progress_timeout sysfs file is written to.
-+ * It checks the data written, and if valid updates the progress timeout value.
-+ * The function also checks gpu reset status, if the gpu is in reset process,
-+ * the function will return an error code (-EBUSY), and no change for timeout
-+ * value.
-+ *
-+ * Return: @count if the function succeeded. An error code on failure.
-+ */
-+static ssize_t progress_timeout_store(struct device * const dev,
-+ struct device_attribute * const attr, const char * const buf,
-+ size_t const count)
-+{
-+ struct kbase_device *const kbdev = dev_get_drvdata(dev);
-+ int err;
-+ u64 timeout;
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ err = kbase_reset_gpu_try_prevent(kbdev);
-+ if (err) {
-+ dev_warn(kbdev->dev,
-+ "Couldn't process progress_timeout write operation for GPU reset.\n");
-+ return -EBUSY;
-+ }
-+
-+ err = kstrtou64(buf, 0, &timeout);
-+ if (err)
-+ dev_err(kbdev->dev,
-+ "Couldn't process progress_timeout write operation.\n"
-+ "Use format <progress_timeout>\n");
-+ else
-+ err = set_timeout(kbdev, timeout);
-+
-+ if (!err) {
-+ kbase_csf_scheduler_pm_active(kbdev);
-+
-+ err = kbase_pm_wait_for_desired_state(kbdev);
-+ if (!err)
-+ err = kbase_csf_firmware_set_timeout(kbdev, timeout);
-+
-+ kbase_csf_scheduler_pm_idle(kbdev);
-+ }
-+
-+ kbase_reset_gpu_allow(kbdev);
-+ if (err)
-+ return err;
-+
-+ return count;
-+}
-+
-+/**
-+ * progress_timeout_show - Show the progress_timeout device attribute.
-+ * @dev: The device that has the attribute.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The output buffer to receive the global timeout.
-+ *
-+ * This function is called to get the progress timeout value.
-+ *
-+ * Return: The number of bytes output to @buf.
-+ */
-+static ssize_t progress_timeout_show(struct device * const dev,
-+ struct device_attribute * const attr, char * const buf)
-+{
-+ struct kbase_device *const kbdev = dev_get_drvdata(dev);
-+ int err;
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ err = scnprintf(buf, PAGE_SIZE, "%llu\n", kbase_csf_timeout_get(kbdev));
-+
-+ return err;
-+
-+}
-+
-+static DEVICE_ATTR(progress_timeout, 0644, progress_timeout_show,
-+ progress_timeout_store);
-+
-+int kbase_csf_timeout_init(struct kbase_device *const kbdev)
-+{
-+ u64 timeout = DEFAULT_PROGRESS_TIMEOUT;
-+ int err;
-+
-+#if IS_ENABLED(CONFIG_OF)
-+ err = of_property_read_u64(kbdev->dev->of_node,
-+ "progress_timeout", &timeout);
-+ if (!err)
-+ dev_info(kbdev->dev, "Found progress_timeout = %llu in Devicetree\n",
-+ timeout);
-+#endif
-+
-+ err = set_timeout(kbdev, timeout);
-+ if (err)
-+ return err;
-+
-+ err = sysfs_create_file(&kbdev->dev->kobj,
-+ &dev_attr_progress_timeout.attr);
-+ if (err)
-+ dev_err(kbdev->dev, "SysFS file creation failed\n");
-+
-+ return err;
-+}
-+
-+void kbase_csf_timeout_term(struct kbase_device * const kbdev)
-+{
-+ sysfs_remove_file(&kbdev->dev->kobj, &dev_attr_progress_timeout.attr);
-+}
-+
-+u64 kbase_csf_timeout_get(struct kbase_device *const kbdev)
-+{
-+ return atomic64_read(&kbdev->csf.progress_timeout);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_timeout.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_timeout.h
-new file mode 100644
-index 0000000..b406eaa
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_timeout.h
-@@ -0,0 +1,66 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_TIMEOUT_H_
-+#define _KBASE_CSF_TIMEOUT_H_
-+
-+struct kbase_device;
-+
-+/**
-+ * kbase_csf_timeout_init - Initialize the progress timeout.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ * Must be zero-initialized.
-+ *
-+ * The progress timeout is the number of GPU clock cycles allowed to elapse
-+ * before the driver terminates a GPU command queue group in which a task is
-+ * making no forward progress on an endpoint (e.g. a shader core). This function
-+ * determines the initial value and also creates a sysfs file to allow the
-+ * timeout to be reconfigured later.
-+ *
-+ * Reconfigures the global firmware interface to enable the current timeout.
-+ *
-+ * Return: 0 on success, or negative on failure.
-+ */
-+int kbase_csf_timeout_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_timeout_term - Terminate the progress timeout.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Removes the sysfs file which allowed the timeout to be reconfigured.
-+ * Does nothing if called on a zero-initialized object.
-+ */
-+void kbase_csf_timeout_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_timeout_get - get the current global progress timeout.
-+ *
-+ * @kbdev: Instance of a GPU platform device that implements a CSF interface.
-+ *
-+ * Return: the maximum number of GPU cycles that is allowed to elapse without
-+ * forward progress before the driver terminates a GPU command queue
-+ * group.
-+ */
-+u64 kbase_csf_timeout_get(struct kbase_device *const kbdev);
-+
-+#endif /* _KBASE_CSF_TIMEOUT_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tl_reader.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tl_reader.c
-new file mode 100644
-index 0000000..1824c2d
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tl_reader.c
-@@ -0,0 +1,534 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_csf_tl_reader.h"
-+
-+#include "mali_kbase_csf_trace_buffer.h"
-+#include "mali_kbase_reset_gpu.h"
-+
-+#include "tl/mali_kbase_tlstream.h"
-+#include "tl/mali_kbase_tl_serialize.h"
-+#include "tl/mali_kbase_tracepoints.h"
-+
-+#include "mali_kbase_pm.h"
-+#include "mali_kbase_hwaccess_time.h"
-+
-+#include <linux/gcd.h>
-+#include <linux/math64.h>
-+#include <asm/arch_timer.h>
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+#include "tl/mali_kbase_timeline_priv.h"
-+#include <linux/debugfs.h>
-+
-+#if (KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE)
-+#define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE
-+#endif
-+#endif
-+
-+/* Name of the CSFFW timeline tracebuffer. */
-+#define KBASE_CSFFW_TRACEBUFFER_NAME "timeline"
-+/* Name of the timeline header metatadata */
-+#define KBASE_CSFFW_TIMELINE_HEADER_NAME "timeline_header"
-+
-+/**
-+ * struct kbase_csffw_tl_message - CSFFW timeline message.
-+ *
-+ * @msg_id: Message ID.
-+ * @timestamp: Timestamp of the event.
-+ * @cycle_counter: Cycle number of the event.
-+ *
-+ * Contain fields that are common for all CSFFW timeline messages.
-+ */
-+struct kbase_csffw_tl_message {
-+ u32 msg_id;
-+ u64 timestamp;
-+ u64 cycle_counter;
-+} __packed __aligned(4);
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+static int kbase_csf_tl_debugfs_poll_interval_read(void *data, u64 *val)
-+{
-+ struct kbase_device *kbdev = (struct kbase_device *)data;
-+ struct kbase_csf_tl_reader *self = &kbdev->timeline->csf_tl_reader;
-+
-+ *val = self->timer_interval;
-+
-+ return 0;
-+}
-+
-+static int kbase_csf_tl_debugfs_poll_interval_write(void *data, u64 val)
-+{
-+ struct kbase_device *kbdev = (struct kbase_device *)data;
-+ struct kbase_csf_tl_reader *self = &kbdev->timeline->csf_tl_reader;
-+
-+ if (val > KBASE_CSF_TL_READ_INTERVAL_MAX || val < KBASE_CSF_TL_READ_INTERVAL_MIN) {
-+ return -EINVAL;
-+ }
-+
-+ self->timer_interval = (u32)val;
-+
-+ return 0;
-+}
-+
-+DEFINE_DEBUGFS_ATTRIBUTE(kbase_csf_tl_poll_interval_fops,
-+ kbase_csf_tl_debugfs_poll_interval_read,
-+ kbase_csf_tl_debugfs_poll_interval_write, "%llu\n");
-+
-+
-+void kbase_csf_tl_reader_debugfs_init(struct kbase_device *kbdev)
-+{
-+ debugfs_create_file("csf_tl_poll_interval_in_ms", S_IRUGO | S_IWUSR,
-+ kbdev->debugfs_instr_directory, kbdev,
-+ &kbase_csf_tl_poll_interval_fops);
-+
-+}
-+#endif
-+
-+/**
-+ * get_cpu_gpu_time() - Get current CPU and GPU timestamps.
-+ *
-+ * @kbdev: Kbase device.
-+ * @cpu_ts: Output CPU timestamp.
-+ * @gpu_ts: Output GPU timestamp.
-+ * @gpu_cycle: Output GPU cycle counts.
-+ */
-+static void get_cpu_gpu_time(
-+ struct kbase_device *kbdev,
-+ u64 *cpu_ts,
-+ u64 *gpu_ts,
-+ u64 *gpu_cycle)
-+{
-+ struct timespec64 ts;
-+
-+ kbase_pm_context_active(kbdev);
-+ kbase_backend_get_gpu_time(kbdev, gpu_cycle, gpu_ts, &ts);
-+ kbase_pm_context_idle(kbdev);
-+
-+ if (cpu_ts)
-+ *cpu_ts = ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
-+}
-+
-+
-+/**
-+ * kbase_ts_converter_init() - Initialize system timestamp converter.
-+ *
-+ * @self: System Timestamp Converter instance.
-+ * @kbdev: Kbase device pointer
-+ *
-+ * Return: Zero on success, -1 otherwise.
-+ */
-+static int kbase_ts_converter_init(
-+ struct kbase_ts_converter *self,
-+ struct kbase_device *kbdev)
-+{
-+ u64 cpu_ts = 0;
-+ u64 gpu_ts = 0;
-+ u64 freq;
-+ u64 common_factor;
-+
-+ get_cpu_gpu_time(kbdev, &cpu_ts, &gpu_ts, NULL);
-+ freq = arch_timer_get_cntfrq();
-+
-+ if (!freq) {
-+ dev_warn(kbdev->dev, "arch_timer_get_rate() is zero!");
-+ return -1;
-+ }
-+
-+ common_factor = gcd(NSEC_PER_SEC, freq);
-+
-+ self->multiplier = div64_u64(NSEC_PER_SEC, common_factor);
-+ self->divisor = div64_u64(freq, common_factor);
-+ self->offset =
-+ cpu_ts - div64_u64(gpu_ts * self->multiplier, self->divisor);
-+
-+ return 0;
-+}
-+
-+/**
-+ * kbase_ts_converter_convert() - Convert GPU timestamp to CPU timestamp.
-+ *
-+ * @self: System Timestamp Converter instance.
-+ * @gpu_ts: System timestamp value to converter.
-+ *
-+ * Return: The CPU timestamp.
-+ */
-+static void kbase_ts_converter_convert(
-+ const struct kbase_ts_converter *self,
-+ u64 *gpu_ts)
-+{
-+ u64 old_gpu_ts = *gpu_ts;
-+ *gpu_ts = div64_u64(old_gpu_ts * self->multiplier,
-+ self->divisor) + self->offset;
-+}
-+
-+/**
-+ * tl_reader_overflow_notify() - Emit stream overflow tracepoint.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ * @msg_buf_start: Start of the message.
-+ * @msg_buf_end: End of the message buffer.
-+ */
-+static void tl_reader_overflow_notify(
-+ const struct kbase_csf_tl_reader *self,
-+ u8 *const msg_buf_start,
-+ u8 *const msg_buf_end)
-+{
-+ struct kbase_device *kbdev = self->kbdev;
-+ struct kbase_csffw_tl_message message = {0};
-+
-+ /* Reuse the timestamp and cycle count from current event if possible */
-+ if (msg_buf_start + sizeof(message) <= msg_buf_end)
-+ memcpy(&message, msg_buf_start, sizeof(message));
-+
-+ KBASE_TLSTREAM_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW(
-+ kbdev, message.timestamp, message.cycle_counter);
-+}
-+
-+/**
-+ * tl_reader_overflow_check() - Check if an overflow has happened
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ * @event_id: Incoming event id.
-+ *
-+ * Return: True, if an overflow has happened, False otherwise.
-+ */
-+static bool tl_reader_overflow_check(
-+ struct kbase_csf_tl_reader *self,
-+ u16 event_id)
-+{
-+ struct kbase_device *kbdev = self->kbdev;
-+ bool has_overflow = false;
-+
-+ /* 0 is a special event_id and reserved for the very first tracepoint
-+ * after reset, we should skip overflow check when reset happened.
-+ */
-+ if (event_id != 0) {
-+ has_overflow = self->got_first_event
-+ && self->expected_event_id != event_id;
-+
-+ if (has_overflow)
-+ dev_warn(kbdev->dev,
-+ "CSFFW overflow, event_id: %u, expected: %u.",
-+ event_id, self->expected_event_id);
-+ }
-+
-+ self->got_first_event = true;
-+ self->expected_event_id = event_id + 1;
-+ /* When event_id reaches its max value, it skips 0 and wraps to 1. */
-+ if (self->expected_event_id == 0)
-+ self->expected_event_id++;
-+
-+ return has_overflow;
-+}
-+
-+/**
-+ * tl_reader_reset() - Reset timeline tracebuffer reader state machine.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ *
-+ * Reset the reader to the default state, i.e. set all the
-+ * mutable fields to zero.
-+ */
-+static void tl_reader_reset(struct kbase_csf_tl_reader *self)
-+{
-+ self->got_first_event = false;
-+ self->is_active = false;
-+ self->expected_event_id = 0;
-+ self->tl_header.btc = 0;
-+}
-+
-+int kbase_csf_tl_reader_flush_buffer(struct kbase_csf_tl_reader *self)
-+{
-+ int ret = 0;
-+ struct kbase_device *kbdev = self->kbdev;
-+ struct kbase_tlstream *stream = self->stream;
-+
-+ u8 *read_buffer = self->read_buffer;
-+ const size_t read_buffer_size = sizeof(self->read_buffer);
-+
-+ u32 bytes_read;
-+ u8 *csffw_data_begin;
-+ u8 *csffw_data_end;
-+ u8 *csffw_data_it;
-+
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&self->read_lock, flags);
-+
-+ /* If not running, early exit. */
-+ if (!self->is_active) {
-+ spin_unlock_irqrestore(&self->read_lock, flags);
-+ return -EBUSY;
-+ }
-+
-+ /* Copying the whole buffer in a single shot. We assume
-+ * that the buffer will not contain partially written messages.
-+ */
-+ bytes_read = kbase_csf_firmware_trace_buffer_read_data(
-+ self->trace_buffer, read_buffer, read_buffer_size);
-+ csffw_data_begin = read_buffer;
-+ csffw_data_end = read_buffer + bytes_read;
-+
-+ for (csffw_data_it = csffw_data_begin;
-+ csffw_data_it < csffw_data_end;) {
-+ u32 event_header;
-+ u16 event_id;
-+ u16 event_size;
-+ unsigned long acq_flags;
-+ char *buffer;
-+
-+ /* Can we safely read event_id? */
-+ if (csffw_data_it + sizeof(event_header) > csffw_data_end) {
-+ dev_warn(
-+ kbdev->dev,
-+ "Unable to parse CSFFW tracebuffer event header.");
-+ ret = -EBUSY;
-+ break;
-+ }
-+
-+ /* Read and parse the event header. */
-+ memcpy(&event_header, csffw_data_it, sizeof(event_header));
-+ event_id = (event_header >> 0) & 0xFFFF;
-+ event_size = (event_header >> 16) & 0xFFFF;
-+ csffw_data_it += sizeof(event_header);
-+
-+ /* Detect if an overflow has happened. */
-+ if (tl_reader_overflow_check(self, event_id))
-+ tl_reader_overflow_notify(self,
-+ csffw_data_it,
-+ csffw_data_end);
-+
-+ /* Can we safely read the message body? */
-+ if (csffw_data_it + event_size > csffw_data_end) {
-+ dev_warn(kbdev->dev,
-+ "event_id: %u, can't read with event_size: %u.",
-+ event_id, event_size);
-+ ret = -EBUSY;
-+ break;
-+ }
-+
-+ /* Convert GPU timestamp to CPU timestamp. */
-+ {
-+ struct kbase_csffw_tl_message *msg =
-+ (struct kbase_csffw_tl_message *) csffw_data_it;
-+ kbase_ts_converter_convert(
-+ &self->ts_converter,
-+ &msg->timestamp);
-+ }
-+
-+ /* Copy the message out to the tl_stream. */
-+ buffer = kbase_tlstream_msgbuf_acquire(
-+ stream, event_size, &acq_flags);
-+ kbasep_serialize_bytes(buffer, 0, csffw_data_it, event_size);
-+ kbase_tlstream_msgbuf_release(stream, acq_flags);
-+ csffw_data_it += event_size;
-+ }
-+
-+ spin_unlock_irqrestore(&self->read_lock, flags);
-+ return ret;
-+}
-+
-+static void kbasep_csf_tl_reader_read_callback(struct timer_list *timer)
-+{
-+ struct kbase_csf_tl_reader *self =
-+ container_of(timer, struct kbase_csf_tl_reader, read_timer);
-+
-+ int rcode;
-+
-+ kbase_csf_tl_reader_flush_buffer(self);
-+
-+ rcode = mod_timer(&self->read_timer,
-+ jiffies + msecs_to_jiffies(self->timer_interval));
-+
-+ CSTD_UNUSED(rcode);
-+}
-+
-+/**
-+ * tl_reader_init_late() - Late CSFFW TL Reader initialization.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ * @kbdev: Kbase device.
-+ *
-+ * Late initialization is done once at kbase_csf_tl_reader_start() time.
-+ * This is because the firmware image is not parsed
-+ * by the kbase_csf_tl_reader_init() time.
-+ *
-+ * Return: Zero on success, -1 otherwise.
-+ */
-+static int tl_reader_init_late(
-+ struct kbase_csf_tl_reader *self,
-+ struct kbase_device *kbdev)
-+{
-+ struct firmware_trace_buffer *tb;
-+ size_t hdr_size = 0;
-+ const char *hdr = NULL;
-+
-+ if (self->kbdev)
-+ return 0;
-+
-+ tb = kbase_csf_firmware_get_trace_buffer(
-+ kbdev, KBASE_CSFFW_TRACEBUFFER_NAME);
-+ hdr = kbase_csf_firmware_get_timeline_metadata(
-+ kbdev, KBASE_CSFFW_TIMELINE_HEADER_NAME, &hdr_size);
-+
-+ if (!tb) {
-+ dev_warn(
-+ kbdev->dev,
-+ "'%s' tracebuffer is not present in the firmware image.",
-+ KBASE_CSFFW_TRACEBUFFER_NAME);
-+ return -1;
-+ }
-+
-+ if (!hdr) {
-+ dev_warn(
-+ kbdev->dev,
-+ "'%s' timeline metadata is not present in the firmware image.",
-+ KBASE_CSFFW_TIMELINE_HEADER_NAME);
-+ return -1;
-+ }
-+
-+ if (kbase_ts_converter_init(&self->ts_converter, kbdev)) {
-+ return -1;
-+ }
-+
-+ self->kbdev = kbdev;
-+ self->trace_buffer = tb;
-+ self->tl_header.data = hdr;
-+ self->tl_header.size = hdr_size;
-+
-+ return 0;
-+}
-+
-+/**
-+ * tl_reader_update_enable_bit() - Update the first bit of a CSFFW tracebuffer.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ * @value: The value to set.
-+ *
-+ * Update the first bit of a CSFFW tracebufer and then reset the GPU.
-+ * This is to make these changes visible to the MCU.
-+ *
-+ * Return: 0 on success, or negative error code for failure.
-+ */
-+static int tl_reader_update_enable_bit(
-+ struct kbase_csf_tl_reader *self,
-+ bool value)
-+{
-+ int err = 0;
-+
-+ err = kbase_csf_firmware_trace_buffer_update_trace_enable_bit(
-+ self->trace_buffer, 0, value);
-+
-+ return err;
-+}
-+
-+void kbase_csf_tl_reader_init(struct kbase_csf_tl_reader *self,
-+ struct kbase_tlstream *stream)
-+{
-+ self->timer_interval = KBASE_CSF_TL_READ_INTERVAL_DEFAULT;
-+
-+ kbase_timer_setup(&self->read_timer,
-+ kbasep_csf_tl_reader_read_callback);
-+
-+ self->stream = stream;
-+
-+ /* This will be initialized by tl_reader_init_late() */
-+ self->kbdev = NULL;
-+ self->trace_buffer = NULL;
-+ self->tl_header.data = NULL;
-+ self->tl_header.size = 0;
-+
-+ spin_lock_init(&self->read_lock);
-+
-+ tl_reader_reset(self);
-+}
-+
-+void kbase_csf_tl_reader_term(struct kbase_csf_tl_reader *self)
-+{
-+ del_timer_sync(&self->read_timer);
-+}
-+
-+int kbase_csf_tl_reader_start(struct kbase_csf_tl_reader *self,
-+ struct kbase_device *kbdev)
-+{
-+ int rcode;
-+
-+ /* If already running, early exit. */
-+ if (self->is_active)
-+ return 0;
-+
-+ if (tl_reader_init_late(self, kbdev)) {
-+ return -EINVAL;
-+ }
-+
-+ tl_reader_reset(self);
-+
-+ self->is_active = true;
-+ /* Set bytes to copy to the header size. This is to trigger copying
-+ * of the header to the user space.
-+ */
-+ self->tl_header.btc = self->tl_header.size;
-+
-+ /* Enable the tracebuffer on the CSFFW side. */
-+ rcode = tl_reader_update_enable_bit(self, true);
-+ if (rcode != 0)
-+ return rcode;
-+
-+ rcode = mod_timer(&self->read_timer,
-+ jiffies + msecs_to_jiffies(self->timer_interval));
-+
-+ return 0;
-+}
-+
-+void kbase_csf_tl_reader_stop(struct kbase_csf_tl_reader *self)
-+{
-+ unsigned long flags;
-+
-+ /* If is not running, early exit. */
-+ if (!self->is_active)
-+ return;
-+
-+ /* Disable the tracebuffer on the CSFFW side. */
-+ tl_reader_update_enable_bit(self, false);
-+
-+ del_timer_sync(&self->read_timer);
-+
-+ spin_lock_irqsave(&self->read_lock, flags);
-+
-+ tl_reader_reset(self);
-+
-+ spin_unlock_irqrestore(&self->read_lock, flags);
-+}
-+
-+void kbase_csf_tl_reader_reset(struct kbase_csf_tl_reader *self)
-+{
-+ u64 gpu_cycle = 0;
-+ struct kbase_device *kbdev = self->kbdev;
-+
-+ if (!kbdev)
-+ return;
-+
-+ kbase_csf_tl_reader_flush_buffer(self);
-+
-+ get_cpu_gpu_time(kbdev, NULL, NULL, &gpu_cycle);
-+ KBASE_TLSTREAM_TL_KBASE_CSFFW_RESET(kbdev, gpu_cycle);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tl_reader.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tl_reader.h
-new file mode 100644
-index 0000000..1b0fcd7
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_tl_reader.h
-@@ -0,0 +1,185 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSFFW_TL_READER_H_
-+#define _KBASE_CSFFW_TL_READER_H_
-+
-+#include <linux/spinlock.h>
-+#include <linux/timer.h>
-+#include <asm/page.h>
-+
-+/* The number of pages used for CSFFW trace buffer. Can be tweaked. */
-+#define KBASE_CSF_TL_BUFFER_NR_PAGES 128
-+/* CSFFW Timeline read polling minimum period in milliseconds. */
-+#define KBASE_CSF_TL_READ_INTERVAL_MIN 20
-+/* CSFFW Timeline read polling default period in milliseconds. */
-+#define KBASE_CSF_TL_READ_INTERVAL_DEFAULT 200
-+/* CSFFW Timeline read polling maximum period in milliseconds. */
-+#define KBASE_CSF_TL_READ_INTERVAL_MAX (60*1000)
-+
-+struct firmware_trace_buffer;
-+struct kbase_tlstream;
-+struct kbase_device;
-+
-+/**
-+ * struct kbase_ts_converter -
-+ * System timestamp to CPU timestamp converter state.
-+ *
-+ * @multiplier: Numerator of the converter's fraction.
-+ * @divisor: Denominator of the converter's fraction.
-+ * @offset: Converter's offset term.
-+ *
-+ * According to Generic timer spec, system timer:
-+ * - Increments at a fixed frequency
-+ * - Starts operating from zero
-+ *
-+ * Hence CPU time is a linear function of System Time.
-+ *
-+ * CPU_ts = alpha * SYS_ts + beta
-+ *
-+ * Where
-+ * - alpha = 10^9/SYS_ts_freq
-+ * - beta is calculated by two timer samples taken at the same time:
-+ * beta = CPU_ts_s - SYS_ts_s * alpha
-+ *
-+ * Since alpha is a rational number, we minimizing possible
-+ * rounding error by simplifying the ratio. Thus alpha is stored
-+ * as a simple `multiplier / divisor` ratio.
-+ *
-+ */
-+struct kbase_ts_converter {
-+ u64 multiplier;
-+ u64 divisor;
-+ s64 offset;
-+};
-+
-+/**
-+ * struct kbase_csf_tl_reader - CSFFW timeline reader state.
-+ *
-+ * @read_timer: Timer used for periodical tracebufer reading.
-+ * @timer_interval: Timer polling period in milliseconds.
-+ * @stream: Timeline stream where to the tracebuffer content
-+ * is copied.
-+ * @kbdev: KBase device.
-+ * @trace_buffer: CSF Firmware timeline tracebuffer.
-+ * @tl_header: CSFFW Timeline header
-+ * @tl_header.data: CSFFW Timeline header content.
-+ * @tl_header.size: CSFFW Timeline header size.
-+ * @tl_header.btc: CSFFW Timeline header remaining bytes to copy to
-+ * the user space.
-+ * @ts_converter: Timestamp converter state.
-+ * @got_first_event: True, if a CSFFW timelime session has been enabled
-+ * and the first event was received.
-+ * @is_active: True, if a CSFFW timelime session has been enabled.
-+ * @expected_event_id: The last 16 bit event ID received from CSFFW. It
-+ * is only valid when got_first_event is true.
-+ * @read_buffer: Temporary buffer used for CSFFW timeline data
-+ * reading from the tracebufer.
-+ * @read_lock: CSFFW timeline reader lock.
-+ */
-+struct kbase_csf_tl_reader {
-+ struct timer_list read_timer;
-+ u32 timer_interval;
-+ struct kbase_tlstream *stream;
-+
-+ struct kbase_device *kbdev;
-+ struct firmware_trace_buffer *trace_buffer;
-+ struct {
-+ const char *data;
-+ size_t size;
-+ size_t btc;
-+ } tl_header;
-+ struct kbase_ts_converter ts_converter;
-+
-+ bool got_first_event;
-+ bool is_active;
-+ u16 expected_event_id;
-+
-+ u8 read_buffer[PAGE_SIZE * KBASE_CSF_TL_BUFFER_NR_PAGES];
-+ spinlock_t read_lock;
-+};
-+
-+/**
-+ * kbase_csf_tl_reader_init() - Initialize CSFFW Timelime Stream Reader.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ * @stream: Destination timeline stream.
-+ */
-+void kbase_csf_tl_reader_init(struct kbase_csf_tl_reader *self,
-+ struct kbase_tlstream *stream);
-+
-+/**
-+ * kbase_csf_tl_reader_term() - Terminate CSFFW Timelime Stream Reader.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ */
-+void kbase_csf_tl_reader_term(struct kbase_csf_tl_reader *self);
-+
-+/**
-+ * kbase_csf_tl_reader_flush_buffer() -
-+ * Flush trace from buffer into CSFFW timeline stream.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ *
-+ * Return: Zero on success, negative error code (EBUSY) otherwise
-+ */
-+
-+int kbase_csf_tl_reader_flush_buffer(struct kbase_csf_tl_reader *self);
-+
-+/**
-+ * kbase_csf_tl_reader_start() -
-+ * Start asynchronous copying of CSFFW timeline stream.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ * @kbdev: Kbase device.
-+ *
-+ * Return: zero on success, a negative error code otherwise.
-+ */
-+int kbase_csf_tl_reader_start(struct kbase_csf_tl_reader *self,
-+ struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_tl_reader_stop() -
-+ * Stop asynchronous copying of CSFFW timeline stream.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ */
-+void kbase_csf_tl_reader_stop(struct kbase_csf_tl_reader *self);
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+/**
-+ * kbase_csf_tl_reader_debugfs_init() -
-+ * Initialize debugfs for CSFFW Timelime Stream Reader.
-+ *
-+ * @kbdev: Kbase device.
-+ */
-+void kbase_csf_tl_reader_debugfs_init(struct kbase_device *kbdev);
-+#endif
-+
-+/**
-+ * kbase_csf_tl_reader_reset() -
-+ * Reset CSFFW timeline reader, it should be called before reset CSFFW.
-+ *
-+ * @self: CSFFW TL Reader instance.
-+ */
-+void kbase_csf_tl_reader_reset(struct kbase_csf_tl_reader *self);
-+
-+#endif /* _KBASE_CSFFW_TL_READER_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_trace_buffer.c b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_trace_buffer.c
-new file mode 100644
-index 0000000..a6343c8
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_trace_buffer.c
-@@ -0,0 +1,688 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase.h"
-+#include "mali_kbase_defs.h"
-+#include "mali_kbase_csf_firmware.h"
-+#include "mali_kbase_csf_trace_buffer.h"
-+#include "mali_kbase_reset_gpu.h"
-+#include "mali_kbase_csf_tl_reader.h"
-+
-+#include <linux/list.h>
-+#include <linux/mman.h>
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+#if (KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE)
-+#define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE
-+#endif
-+#endif
-+
-+/**
-+ * struct firmware_trace_buffer - Trace Buffer within the MCU firmware
-+ *
-+ * The firmware relays information to the host by writing on memory buffers
-+ * which are allocated and partially configured by the host. These buffers
-+ * are called Trace Buffers: each of them has a specific purpose and is
-+ * identified by a name and a set of memory addresses where the host can
-+ * set pointers to host-allocated structures.
-+ *
-+ * @kbdev: Pointer to the Kbase device.
-+ * @node: List head linking all trace buffers to
-+ * kbase_device:csf.firmware_trace_buffers
-+ * @data_mapping: MCU shared memory mapping used for the data buffer.
-+ * @updatable: Indicates whether config items can be updated with
-+ * FIRMWARE_CONFIG_UPDATE
-+ * @type: The type of the trace buffer.
-+ * @trace_enable_entry_count: Number of Trace Enable bits.
-+ * @gpu_va: Structure containing all the Firmware addresses
-+ * that are accessed by the MCU.
-+ * @gpu_va.size_address: The address where the MCU shall read the size of
-+ * the data buffer.
-+ * @gpu_va.insert_address: The address that shall be dereferenced by the MCU
-+ * to write the Insert offset.
-+ * @gpu_va.extract_address: The address that shall be dereferenced by the MCU
-+ * to read the Extract offset.
-+ * @gpu_va.data_address: The address that shall be dereferenced by the MCU
-+ * to write the Trace Buffer.
-+ * @gpu_va.trace_enable: The address where the MCU shall read the array of
-+ * Trace Enable bits describing which trace points
-+ * and features shall be enabled.
-+ * @cpu_va: Structure containing CPU addresses of variables
-+ * which are permanently mapped on the CPU address
-+ * space.
-+ * @cpu_va.insert_cpu_va: CPU virtual address of the Insert variable.
-+ * @cpu_va.extract_cpu_va: CPU virtual address of the Extract variable.
-+ * @num_pages: Size of the data buffer, in pages.
-+ * @trace_enable_init_mask: Initial value for the trace enable bit mask.
-+ * @name: NULL terminated string which contains the name of the trace buffer.
-+ */
-+struct firmware_trace_buffer {
-+ struct kbase_device *kbdev;
-+ struct list_head node;
-+ struct kbase_csf_mapping data_mapping;
-+ bool updatable;
-+ u32 type;
-+ u32 trace_enable_entry_count;
-+ struct gpu_va {
-+ u32 size_address;
-+ u32 insert_address;
-+ u32 extract_address;
-+ u32 data_address;
-+ u32 trace_enable;
-+ } gpu_va;
-+ struct cpu_va {
-+ u32 *insert_cpu_va;
-+ u32 *extract_cpu_va;
-+ } cpu_va;
-+ u32 num_pages;
-+ u32 trace_enable_init_mask[CSF_FIRMWARE_TRACE_ENABLE_INIT_MASK_MAX];
-+ char name[1]; /* this field must be last */
-+};
-+
-+/**
-+ * struct firmware_trace_buffer_data - Configuration data for trace buffers
-+ *
-+ * Describe how to set up a trace buffer interface.
-+ * Trace buffers are identified by name and they require a data buffer and
-+ * an initial mask of values for the trace enable bits.
-+ *
-+ * @name: Name identifier of the trace buffer
-+ * @trace_enable_init_mask: Initial value to assign to the trace enable bits
-+ * @size: Size of the data buffer to allocate for the trace buffer, in pages.
-+ * The size of a data buffer must always be a power of 2.
-+ */
-+struct firmware_trace_buffer_data {
-+ char name[64];
-+ u32 trace_enable_init_mask[CSF_FIRMWARE_TRACE_ENABLE_INIT_MASK_MAX];
-+ size_t size;
-+};
-+
-+/*
-+ * Table of configuration data for trace buffers.
-+ *
-+ * This table contains the configuration data for the trace buffers that are
-+ * expected to be parsed from the firmware.
-+ */
-+static const struct firmware_trace_buffer_data
-+trace_buffer_data[] = {
-+#ifndef MALI_KBASE_BUILD
-+ { "fwutf", {0}, 1 },
-+#endif
-+ { FW_TRACE_BUF_NAME, {0}, 4 },
-+ { "benchmark", {0}, 2 },
-+ { "timeline", {0}, KBASE_CSF_TL_BUFFER_NR_PAGES },
-+};
-+
-+int kbase_csf_firmware_trace_buffers_init(struct kbase_device *kbdev)
-+{
-+ struct firmware_trace_buffer *trace_buffer;
-+ int ret = 0;
-+ u32 mcu_rw_offset = 0, mcu_write_offset = 0;
-+ const u32 cache_line_alignment = kbase_get_cache_line_alignment(kbdev);
-+
-+ if (list_empty(&kbdev->csf.firmware_trace_buffers.list)) {
-+ dev_dbg(kbdev->dev, "No trace buffers to initialise\n");
-+ return 0;
-+ }
-+
-+ /* GPU-readable,writable memory used for Extract variables */
-+ ret = kbase_csf_firmware_mcu_shared_mapping_init(
-+ kbdev, 1, PROT_WRITE,
-+ KBASE_REG_GPU_RD | KBASE_REG_GPU_WR,
-+ &kbdev->csf.firmware_trace_buffers.mcu_rw);
-+ if (ret != 0) {
-+ dev_err(kbdev->dev, "Failed to map GPU-rw MCU shared memory\n");
-+ goto out;
-+ }
-+
-+ /* GPU-writable memory used for Insert variables */
-+ ret = kbase_csf_firmware_mcu_shared_mapping_init(
-+ kbdev, 1, PROT_READ, KBASE_REG_GPU_WR,
-+ &kbdev->csf.firmware_trace_buffers.mcu_write);
-+ if (ret != 0) {
-+ dev_err(kbdev->dev, "Failed to map GPU-writable MCU shared memory\n");
-+ goto out;
-+ }
-+
-+ list_for_each_entry(trace_buffer, &kbdev->csf.firmware_trace_buffers.list, node) {
-+ u32 extract_gpu_va, insert_gpu_va, data_buffer_gpu_va,
-+ trace_enable_size_dwords;
-+ u32 *extract_cpu_va, *insert_cpu_va;
-+ unsigned int i;
-+
-+ /* GPU-writable data buffer for the individual trace buffer */
-+ ret = kbase_csf_firmware_mcu_shared_mapping_init(
-+ kbdev, trace_buffer->num_pages, PROT_READ, KBASE_REG_GPU_WR,
-+ &trace_buffer->data_mapping);
-+ if (ret) {
-+ dev_err(kbdev->dev, "Failed to map GPU-writable MCU shared memory for a trace buffer\n");
-+ goto out;
-+ }
-+
-+ extract_gpu_va =
-+ (kbdev->csf.firmware_trace_buffers.mcu_rw.va_reg->start_pfn << PAGE_SHIFT) +
-+ mcu_rw_offset;
-+ extract_cpu_va = (u32*)(
-+ kbdev->csf.firmware_trace_buffers.mcu_rw.cpu_addr +
-+ mcu_rw_offset);
-+ insert_gpu_va =
-+ (kbdev->csf.firmware_trace_buffers.mcu_write.va_reg->start_pfn << PAGE_SHIFT) +
-+ mcu_write_offset;
-+ insert_cpu_va = (u32*)(
-+ kbdev->csf.firmware_trace_buffers.mcu_write.cpu_addr +
-+ mcu_write_offset);
-+ data_buffer_gpu_va =
-+ (trace_buffer->data_mapping.va_reg->start_pfn << PAGE_SHIFT);
-+
-+ /* Initialize the Extract variable */
-+ *extract_cpu_va = 0;
-+
-+ /* Each FW address shall be mapped and set individually, as we can't
-+ * assume anything about their location in the memory address space.
-+ */
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.data_address, data_buffer_gpu_va);
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.insert_address, insert_gpu_va);
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.extract_address, extract_gpu_va);
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.size_address,
-+ trace_buffer->num_pages << PAGE_SHIFT);
-+
-+ trace_enable_size_dwords =
-+ (trace_buffer->trace_enable_entry_count + 31) >> 5;
-+
-+ for (i = 0; i < trace_enable_size_dwords; i++) {
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.trace_enable + i*4,
-+ trace_buffer->trace_enable_init_mask[i]);
-+ }
-+
-+ /* Store CPU virtual addresses for permanently mapped variables */
-+ trace_buffer->cpu_va.insert_cpu_va = insert_cpu_va;
-+ trace_buffer->cpu_va.extract_cpu_va = extract_cpu_va;
-+
-+ /* Update offsets */
-+ mcu_write_offset += cache_line_alignment;
-+ mcu_rw_offset += cache_line_alignment;
-+ }
-+
-+out:
-+ return ret;
-+}
-+
-+void kbase_csf_firmware_trace_buffers_term(struct kbase_device *kbdev)
-+{
-+ if (list_empty(&kbdev->csf.firmware_trace_buffers.list))
-+ return;
-+
-+ while (!list_empty(&kbdev->csf.firmware_trace_buffers.list)) {
-+ struct firmware_trace_buffer *trace_buffer;
-+
-+ trace_buffer = list_first_entry(&kbdev->csf.firmware_trace_buffers.list,
-+ struct firmware_trace_buffer, node);
-+ kbase_csf_firmware_mcu_shared_mapping_term(kbdev, &trace_buffer->data_mapping);
-+ list_del(&trace_buffer->node);
-+
-+ kfree(trace_buffer);
-+ }
-+
-+ kbase_csf_firmware_mcu_shared_mapping_term(
-+ kbdev, &kbdev->csf.firmware_trace_buffers.mcu_rw);
-+ kbase_csf_firmware_mcu_shared_mapping_term(
-+ kbdev, &kbdev->csf.firmware_trace_buffers.mcu_write);
-+}
-+
-+int kbase_csf_firmware_parse_trace_buffer_entry(struct kbase_device *kbdev,
-+ const u32 *entry,
-+ unsigned int size,
-+ bool updatable)
-+{
-+ const char *name = (char *)&entry[7];
-+ const unsigned int name_len = size - TRACE_BUFFER_ENTRY_NAME_OFFSET;
-+ struct firmware_trace_buffer *trace_buffer;
-+ unsigned int i;
-+
-+ /* Allocate enough space for struct firmware_trace_buffer and the
-+ * trace buffer name (with NULL termination).
-+ */
-+ trace_buffer =
-+ kmalloc(sizeof(*trace_buffer) + name_len + 1, GFP_KERNEL);
-+
-+ if (!trace_buffer)
-+ return -ENOMEM;
-+
-+ memcpy(&trace_buffer->name, name, name_len);
-+ trace_buffer->name[name_len] = '\0';
-+
-+ for (i = 0; i < ARRAY_SIZE(trace_buffer_data); i++) {
-+ if (!strcmp(trace_buffer_data[i].name, trace_buffer->name)) {
-+ unsigned int j;
-+
-+ trace_buffer->kbdev = kbdev;
-+ trace_buffer->updatable = updatable;
-+ trace_buffer->type = entry[0];
-+ trace_buffer->gpu_va.size_address = entry[1];
-+ trace_buffer->gpu_va.insert_address = entry[2];
-+ trace_buffer->gpu_va.extract_address = entry[3];
-+ trace_buffer->gpu_va.data_address = entry[4];
-+ trace_buffer->gpu_va.trace_enable = entry[5];
-+ trace_buffer->trace_enable_entry_count = entry[6];
-+ trace_buffer->num_pages = trace_buffer_data[i].size;
-+
-+ for (j = 0; j < CSF_FIRMWARE_TRACE_ENABLE_INIT_MASK_MAX; j++) {
-+ trace_buffer->trace_enable_init_mask[j] =
-+ trace_buffer_data[i].trace_enable_init_mask[j];
-+ }
-+ break;
-+ }
-+ }
-+
-+ if (i < ARRAY_SIZE(trace_buffer_data)) {
-+ list_add(&trace_buffer->node, &kbdev->csf.firmware_trace_buffers.list);
-+ dev_dbg(kbdev->dev, "Trace buffer '%s'", trace_buffer->name);
-+ } else {
-+ dev_dbg(kbdev->dev, "Unknown trace buffer '%s'", trace_buffer->name);
-+ kfree(trace_buffer);
-+ }
-+
-+ return 0;
-+}
-+
-+void kbase_csf_firmware_reload_trace_buffers_data(struct kbase_device *kbdev)
-+{
-+ struct firmware_trace_buffer *trace_buffer;
-+ u32 mcu_rw_offset = 0, mcu_write_offset = 0;
-+ const u32 cache_line_alignment = kbase_get_cache_line_alignment(kbdev);
-+
-+ list_for_each_entry(trace_buffer, &kbdev->csf.firmware_trace_buffers.list, node) {
-+ u32 extract_gpu_va, insert_gpu_va, data_buffer_gpu_va,
-+ trace_enable_size_dwords;
-+ u32 *extract_cpu_va, *insert_cpu_va;
-+ unsigned int i;
-+
-+ /* Rely on the fact that all required mappings already exist */
-+ extract_gpu_va =
-+ (kbdev->csf.firmware_trace_buffers.mcu_rw.va_reg->start_pfn << PAGE_SHIFT) +
-+ mcu_rw_offset;
-+ extract_cpu_va = (u32*)(
-+ kbdev->csf.firmware_trace_buffers.mcu_rw.cpu_addr +
-+ mcu_rw_offset);
-+ insert_gpu_va =
-+ (kbdev->csf.firmware_trace_buffers.mcu_write.va_reg->start_pfn << PAGE_SHIFT) +
-+ mcu_write_offset;
-+ insert_cpu_va = (u32*)(
-+ kbdev->csf.firmware_trace_buffers.mcu_write.cpu_addr +
-+ mcu_write_offset);
-+ data_buffer_gpu_va =
-+ (trace_buffer->data_mapping.va_reg->start_pfn << PAGE_SHIFT);
-+
-+ /* Notice that the function only re-updates firmware memory locations
-+ * with information that allows access to the trace buffers without
-+ * really resetting their state. For instance, the Insert offset will
-+ * not change and, as a consequence, the Extract offset is not going
-+ * to be reset to keep consistency.
-+ */
-+
-+ /* Each FW address shall be mapped and set individually, as we can't
-+ * assume anything about their location in the memory address space.
-+ */
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.data_address, data_buffer_gpu_va);
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.insert_address, insert_gpu_va);
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.extract_address, extract_gpu_va);
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.size_address,
-+ trace_buffer->num_pages << PAGE_SHIFT);
-+
-+ trace_enable_size_dwords =
-+ (trace_buffer->trace_enable_entry_count + 31) >> 5;
-+
-+ for (i = 0; i < trace_enable_size_dwords; i++) {
-+ kbase_csf_update_firmware_memory(
-+ kbdev, trace_buffer->gpu_va.trace_enable + i*4,
-+ trace_buffer->trace_enable_init_mask[i]);
-+ }
-+
-+ /* Store CPU virtual addresses for permanently mapped variables,
-+ * as they might have slightly changed.
-+ */
-+ trace_buffer->cpu_va.insert_cpu_va = insert_cpu_va;
-+ trace_buffer->cpu_va.extract_cpu_va = extract_cpu_va;
-+
-+ /* Update offsets */
-+ mcu_write_offset += cache_line_alignment;
-+ mcu_rw_offset += cache_line_alignment;
-+ }
-+}
-+
-+struct firmware_trace_buffer *kbase_csf_firmware_get_trace_buffer(
-+ struct kbase_device *kbdev, const char *name)
-+{
-+ struct firmware_trace_buffer *trace_buffer;
-+
-+ list_for_each_entry(trace_buffer, &kbdev->csf.firmware_trace_buffers.list, node) {
-+ if (!strcmp(trace_buffer->name, name))
-+ return trace_buffer;
-+ }
-+
-+ return NULL;
-+}
-+EXPORT_SYMBOL(kbase_csf_firmware_get_trace_buffer);
-+
-+unsigned int kbase_csf_firmware_trace_buffer_get_trace_enable_bits_count(
-+ const struct firmware_trace_buffer *trace_buffer)
-+{
-+ return trace_buffer->trace_enable_entry_count;
-+}
-+EXPORT_SYMBOL(kbase_csf_firmware_trace_buffer_get_trace_enable_bits_count);
-+
-+static void kbasep_csf_firmware_trace_buffer_update_trace_enable_bit(
-+ struct firmware_trace_buffer *tb, unsigned int bit, bool value)
-+{
-+ struct kbase_device *kbdev = tb->kbdev;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ if (bit < tb->trace_enable_entry_count) {
-+ unsigned int trace_enable_reg_offset = bit >> 5;
-+ u32 trace_enable_bit_mask = 1u << (bit & 0x1F);
-+
-+ if (value) {
-+ tb->trace_enable_init_mask[trace_enable_reg_offset] |=
-+ trace_enable_bit_mask;
-+ } else {
-+ tb->trace_enable_init_mask[trace_enable_reg_offset] &=
-+ ~trace_enable_bit_mask;
-+ }
-+
-+ /* This is not strictly needed as the caller is supposed to
-+ * reload the firmware image (through GPU reset) after updating
-+ * the bitmask. Otherwise there is no guarantee that firmware
-+ * will take into account the updated bitmask for all types of
-+ * trace buffers, since firmware could continue to use the
-+ * value of bitmask it cached after the boot.
-+ */
-+ kbase_csf_update_firmware_memory(
-+ kbdev,
-+ tb->gpu_va.trace_enable + trace_enable_reg_offset * 4,
-+ tb->trace_enable_init_mask[trace_enable_reg_offset]);
-+ }
-+}
-+
-+int kbase_csf_firmware_trace_buffer_update_trace_enable_bit(
-+ struct firmware_trace_buffer *tb, unsigned int bit, bool value)
-+{
-+ struct kbase_device *kbdev = tb->kbdev;
-+ int err = 0;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+
-+ /* If trace buffer update cannot be performed with
-+ * FIRMWARE_CONFIG_UPDATE then we need to do a
-+ * silent reset before we update the memory.
-+ */
-+ if (!tb->updatable) {
-+ /* If there is already a GPU reset pending then inform
-+ * the User to retry the update.
-+ */
-+ if (kbase_reset_gpu_silent(kbdev)) {
-+ dev_warn(
-+ kbdev->dev,
-+ "GPU reset already in progress when enabling firmware timeline.");
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ return -EAGAIN;
-+ }
-+ }
-+
-+ kbasep_csf_firmware_trace_buffer_update_trace_enable_bit(tb, bit,
-+ value);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ if (tb->updatable)
-+ err = kbase_csf_trigger_firmware_config_update(kbdev);
-+
-+ return err;
-+}
-+EXPORT_SYMBOL(kbase_csf_firmware_trace_buffer_update_trace_enable_bit);
-+
-+bool kbase_csf_firmware_trace_buffer_is_empty(
-+ const struct firmware_trace_buffer *trace_buffer)
-+{
-+ return *(trace_buffer->cpu_va.insert_cpu_va) ==
-+ *(trace_buffer->cpu_va.extract_cpu_va);
-+}
-+EXPORT_SYMBOL(kbase_csf_firmware_trace_buffer_is_empty);
-+
-+unsigned int kbase_csf_firmware_trace_buffer_read_data(
-+ struct firmware_trace_buffer *trace_buffer, u8 *data, unsigned int num_bytes)
-+{
-+ unsigned int bytes_copied;
-+ u8 *data_cpu_va = trace_buffer->data_mapping.cpu_addr;
-+ u32 extract_offset = *(trace_buffer->cpu_va.extract_cpu_va);
-+ u32 insert_offset = *(trace_buffer->cpu_va.insert_cpu_va);
-+ u32 buffer_size = trace_buffer->num_pages << PAGE_SHIFT;
-+
-+ if (insert_offset >= extract_offset) {
-+ bytes_copied = min_t(unsigned int, num_bytes,
-+ (insert_offset - extract_offset));
-+ memcpy(data, &data_cpu_va[extract_offset], bytes_copied);
-+ extract_offset += bytes_copied;
-+ } else {
-+ unsigned int bytes_copied_head, bytes_copied_tail;
-+
-+ bytes_copied_tail = min_t(unsigned int, num_bytes,
-+ (buffer_size - extract_offset));
-+ memcpy(data, &data_cpu_va[extract_offset], bytes_copied_tail);
-+
-+ bytes_copied_head = min_t(unsigned int,
-+ (num_bytes - bytes_copied_tail), insert_offset);
-+ memcpy(&data[bytes_copied_tail], data_cpu_va, bytes_copied_head);
-+
-+ bytes_copied = bytes_copied_head + bytes_copied_tail;
-+ extract_offset += bytes_copied;
-+ if (extract_offset >= buffer_size)
-+ extract_offset = bytes_copied_head;
-+ }
-+
-+ *(trace_buffer->cpu_va.extract_cpu_va) = extract_offset;
-+
-+ return bytes_copied;
-+}
-+EXPORT_SYMBOL(kbase_csf_firmware_trace_buffer_read_data);
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+
-+#define U32_BITS 32
-+static u64 get_trace_buffer_active_mask64(struct firmware_trace_buffer *tb)
-+{
-+ u64 active_mask = tb->trace_enable_init_mask[0];
-+
-+ if (tb->trace_enable_entry_count > U32_BITS)
-+ active_mask |= (u64)tb->trace_enable_init_mask[1] << U32_BITS;
-+
-+ return active_mask;
-+}
-+
-+static void update_trace_buffer_active_mask64(struct firmware_trace_buffer *tb,
-+ u64 mask)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < tb->trace_enable_entry_count; i++)
-+ kbasep_csf_firmware_trace_buffer_update_trace_enable_bit(
-+ tb, i, (mask >> i) & 1);
-+}
-+
-+static int set_trace_buffer_active_mask64(struct firmware_trace_buffer *tb,
-+ u64 mask)
-+{
-+ struct kbase_device *kbdev = tb->kbdev;
-+ unsigned long flags;
-+ int err = 0;
-+
-+ if (!tb->updatable) {
-+ /* If there is already a GPU reset pending, need a retry */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ if (kbase_reset_gpu_silent(kbdev))
-+ err = -EAGAIN;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ }
-+
-+ if (!err) {
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ update_trace_buffer_active_mask64(tb, mask);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ /* if we can update the config we need to just trigger
-+ * FIRMWARE_CONFIG_UPDATE.
-+ */
-+ if (tb->updatable)
-+ err = kbase_csf_trigger_firmware_config_update(kbdev);
-+ }
-+
-+ return err;
-+}
-+
-+static int kbase_csf_firmware_trace_enable_mask_read(void *data, u64 *val)
-+{
-+ struct kbase_device *kbdev = (struct kbase_device *)data;
-+ struct firmware_trace_buffer *tb =
-+ kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME);
-+
-+ if (tb == NULL) {
-+ dev_err(kbdev->dev, "Couldn't get the firmware trace buffer");
-+ return -EIO;
-+ }
-+ /* The enabled traces limited to u64 here, regarded practical */
-+ *val = get_trace_buffer_active_mask64(tb);
-+ return 0;
-+}
-+
-+static int kbase_csf_firmware_trace_enable_mask_write(void *data, u64 val)
-+{
-+ struct kbase_device *kbdev = (struct kbase_device *)data;
-+ struct firmware_trace_buffer *tb =
-+ kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME);
-+ u64 new_mask;
-+ unsigned int enable_bits_count;
-+
-+ if (tb == NULL) {
-+ dev_err(kbdev->dev, "Couldn't get the firmware trace buffer");
-+ return -EIO;
-+ }
-+
-+ /* Ignore unsupported types */
-+ enable_bits_count =
-+ kbase_csf_firmware_trace_buffer_get_trace_enable_bits_count(tb);
-+ if (enable_bits_count > 64) {
-+ dev_dbg(kbdev->dev, "Limit enabled bits count from %u to 64",
-+ enable_bits_count);
-+ enable_bits_count = 64;
-+ }
-+ new_mask = val & ((1 << enable_bits_count) - 1);
-+
-+ if (new_mask != get_trace_buffer_active_mask64(tb))
-+ return set_trace_buffer_active_mask64(tb, new_mask);
-+ else
-+ return 0;
-+}
-+
-+static int kbasep_csf_firmware_trace_debugfs_open(struct inode *in,
-+ struct file *file)
-+{
-+ struct kbase_device *kbdev = in->i_private;
-+
-+ file->private_data = kbdev;
-+ dev_dbg(kbdev->dev, "Opened firmware trace buffer dump debugfs file");
-+
-+ return 0;
-+}
-+
-+static ssize_t kbasep_csf_firmware_trace_debugfs_read(struct file *file,
-+ char __user *buf, size_t size, loff_t *ppos)
-+{
-+ struct kbase_device *kbdev = file->private_data;
-+ u8 *pbyte;
-+ unsigned int n_read;
-+ unsigned long not_copied;
-+ /* Limit the kernel buffer to no more than two pages */
-+ size_t mem = MIN(size, 2 * PAGE_SIZE);
-+ unsigned long flags;
-+
-+ struct firmware_trace_buffer *tb =
-+ kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME);
-+
-+ if (tb == NULL) {
-+ dev_err(kbdev->dev, "Couldn't get the firmware trace buffer");
-+ return -EIO;
-+ }
-+
-+ pbyte = kmalloc(mem, GFP_KERNEL);
-+ if (pbyte == NULL) {
-+ dev_err(kbdev->dev, "Couldn't allocate memory for trace buffer dump");
-+ return -ENOMEM;
-+ }
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ n_read = kbase_csf_firmware_trace_buffer_read_data(tb, pbyte, mem);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ /* Do the copy, if we have obtained some trace data */
-+ not_copied = (n_read) ? copy_to_user(buf, pbyte, n_read) : 0;
-+ kfree(pbyte);
-+
-+ if (!not_copied) {
-+ *ppos += n_read;
-+ return n_read;
-+ }
-+
-+ dev_err(kbdev->dev, "Couldn't copy trace buffer data to user space buffer");
-+ return -EFAULT;
-+}
-+
-+
-+DEFINE_SIMPLE_ATTRIBUTE(kbase_csf_firmware_trace_enable_mask_fops,
-+ kbase_csf_firmware_trace_enable_mask_read,
-+ kbase_csf_firmware_trace_enable_mask_write, "%llx\n");
-+
-+static const struct file_operations kbasep_csf_firmware_trace_debugfs_fops = {
-+ .owner = THIS_MODULE,
-+ .open = kbasep_csf_firmware_trace_debugfs_open,
-+ .read = kbasep_csf_firmware_trace_debugfs_read,
-+ .llseek = no_llseek,
-+};
-+
-+void kbase_csf_firmware_trace_buffer_debugfs_init(struct kbase_device *kbdev)
-+{
-+ debugfs_create_file("fw_trace_enable_mask", 0644,
-+ kbdev->mali_debugfs_directory, kbdev,
-+ &kbase_csf_firmware_trace_enable_mask_fops);
-+
-+ debugfs_create_file("fw_traces", 0444,
-+ kbdev->mali_debugfs_directory, kbdev,
-+ &kbasep_csf_firmware_trace_debugfs_fops);
-+}
-+#endif /* CONFIG_DEBUG_FS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_trace_buffer.h b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_trace_buffer.h
-new file mode 100644
-index 0000000..b9f481d
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/csf/mali_kbase_csf_trace_buffer.h
-@@ -0,0 +1,182 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CSF_TRACE_BUFFER_H_
-+#define _KBASE_CSF_TRACE_BUFFER_H_
-+
-+#include <linux/types.h>
-+
-+#define CSF_FIRMWARE_TRACE_ENABLE_INIT_MASK_MAX (4)
-+#define FW_TRACE_BUF_NAME "fwlog"
-+
-+/* Forward declarations */
-+struct firmware_trace_buffer;
-+struct kbase_device;
-+
-+/**
-+ * kbase_csf_firmware_trace_buffers_init - Initialize trace buffers
-+ *
-+ * Allocate resources for trace buffers. In particular:
-+ * - One memory page of GPU-readable, CPU-writable memory is used for
-+ * the Extract variables of all trace buffers.
-+ * - One memory page of GPU-writable, CPU-readable memory is used for
-+ * the Insert variables of all trace buffers.
-+ * - A data buffer of GPU-writable, CPU-readable memory is allocated
-+ * for each trace buffer.
-+ *
-+ * After that, firmware addresses are written with pointers to the
-+ * insert, extract and data buffer variables. The size and the trace
-+ * enable bits are not dereferenced by the GPU and shall be written
-+ * in the firmware addresses directly.
-+ *
-+ * This function relies on the assumption that the list of
-+ * firmware_trace_buffer elements in the device has already been
-+ * populated with data from the firmware image parsing.
-+ *
-+ * Return: 0 if success, or an error code on failure.
-+ *
-+ * @kbdev: Device pointer
-+ */
-+int kbase_csf_firmware_trace_buffers_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_trace_buffer_term - Terminate trace buffers
-+ *
-+ * @kbdev: Device pointer
-+ */
-+void kbase_csf_firmware_trace_buffers_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_parse_trace_buffer_entry - Process a "trace buffer" section
-+ *
-+ * Read a "trace buffer" section adding metadata for the related trace buffer
-+ * to the kbase_device:csf.firmware_trace_buffers list.
-+ *
-+ * Unexpected trace buffers will not be parsed and, as a consequence,
-+ * will not be initialized.
-+ *
-+ * Return: 0 if successful, negative error code on failure.
-+ *
-+ * @kbdev: Kbase device structure
-+ * @entry: Pointer to the section
-+ * @size: Size (in bytes) of the section
-+ * @updatable: Indicates whether config items can be updated with FIRMWARE_CONFIG_UPDATE
-+ */
-+int kbase_csf_firmware_parse_trace_buffer_entry(struct kbase_device *kbdev,
-+ const u32 *entry,
-+ unsigned int size,
-+ bool updatable);
-+
-+/**
-+ * kbase_csf_firmware_reload_trace_buffers_data -
-+ * Reload trace buffers data for firmware reboot
-+ *
-+ * Helper function used when rebooting the firmware to reload the initial setup
-+ * for all the trace buffers which have been previously parsed and initialized.
-+ *
-+ * Almost all of the operations done in the initialization process are
-+ * replicated, with the difference that they might be done in a different order
-+ * and that the variables of a given trace buffer may be mapped to different
-+ * offsets within the same existing mappings.
-+ *
-+ * In other words, the re-initialization done by this function will be
-+ * equivalent but not necessarily identical to the original initialization.
-+ *
-+ * @kbdev: Device pointer
-+ */
-+void kbase_csf_firmware_reload_trace_buffers_data(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_csf_firmware_get_trace_buffer - Get a trace buffer
-+ *
-+ * Return: handle to a trace buffer, given the name, or NULL if a trace buffer
-+ * with that name couldn't be found.
-+ *
-+ * @kbdev: Device pointer
-+ * @name: Name of the trace buffer to find
-+ */
-+struct firmware_trace_buffer *kbase_csf_firmware_get_trace_buffer(
-+ struct kbase_device *kbdev, const char *name);
-+
-+/**
-+ * kbase_csf_firmware_trace_buffer_get_trace_enable_bits_count -
-+ * Get number of trace enable bits for a trace buffer
-+ *
-+ * Return: Number of trace enable bits in a trace buffer.
-+ *
-+ * @trace_buffer: Trace buffer handle
-+ */
-+unsigned int kbase_csf_firmware_trace_buffer_get_trace_enable_bits_count(
-+ const struct firmware_trace_buffer *trace_buffer);
-+
-+/**
-+ * kbase_csf_firmware_trace_buffer_update_trace_enable_bit -
-+ * Update a trace enable bit
-+ *
-+ * Update the value of a given trace enable bit.
-+ *
-+ * @trace_buffer: Trace buffer handle
-+ * @bit: Bit to update
-+ * @value: New value for the given bit
-+ *
-+ * Return: 0 if successful, negative error code on failure.
-+ */
-+int kbase_csf_firmware_trace_buffer_update_trace_enable_bit(
-+ struct firmware_trace_buffer *trace_buffer, unsigned int bit,
-+ bool value);
-+
-+/**
-+ * kbase_csf_firmware_trace_buffer_is_empty - Empty trace buffer predicate
-+ *
-+ * Return: True if the trace buffer is empty, or false otherwise.
-+ *
-+ * @trace_buffer: Trace buffer handle
-+ */
-+bool kbase_csf_firmware_trace_buffer_is_empty(
-+ const struct firmware_trace_buffer *trace_buffer);
-+
-+/**
-+ * kbase_csf_firmware_trace_buffer_read_data - Read data from a trace buffer
-+ *
-+ * Read available data from a trace buffer. The client provides a data buffer
-+ * of a given size and the maximum number of bytes to read.
-+ *
-+ * Return: Number of bytes read from the trace buffer.
-+ *
-+ * @trace_buffer: Trace buffer handle
-+ * @data: Pointer to a client-allocated where data shall be written.
-+ * @num_bytes: Maximum number of bytes to read from the trace buffer.
-+ */
-+unsigned int kbase_csf_firmware_trace_buffer_read_data(
-+ struct firmware_trace_buffer *trace_buffer, u8 *data, unsigned int num_bytes);
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+/**
-+ * kbase_csf_fw_trace_buffer_debugfs_init() - Add debugfs entries for setting
-+ * enable mask and dumping the binary
-+ * firmware trace buffer
-+ *
-+ * @kbdev: Pointer to the device
-+ */
-+void kbase_csf_firmware_trace_buffer_debugfs_init(struct kbase_device *kbdev);
-+#endif /* CONFIG_DEBUG_FS */
-+
-+#endif /* _KBASE_CSF_TRACE_BUFFER_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/debug/Kbuild
-new file mode 100644
-index 0000000..1682c0f
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/Kbuild
-@@ -0,0 +1,27 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+mali_kbase-y += debug/mali_kbase_debug_ktrace.o
-+
-+ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
-+ mali_kbase-y += debug/backend/mali_kbase_debug_ktrace_csf.o
-+else
-+ mali_kbase-y += debug/backend/mali_kbase_debug_ktrace_jm.o
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_codes_csf.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_codes_csf.h
-new file mode 100644
-index 0000000..d05f802
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_codes_csf.h
-@@ -0,0 +1,278 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * ***** IMPORTANT: THIS IS NOT A NORMAL HEADER FILE *****
-+ * ***** DO NOT INCLUDE DIRECTLY *****
-+ * ***** THE LACK OF HEADER GUARDS IS INTENTIONAL *****
-+ */
-+
-+/*
-+ * The purpose of this header file is just to contain a list of trace code
-+ * identifiers
-+ *
-+ * When updating this file, also remember to update
-+ * mali_kbase_debug_linux_ktrace_csf.h
-+ *
-+ * IMPORTANT: THIS FILE MUST NOT BE USED FOR ANY OTHER PURPOSE OTHER THAN THAT
-+ * DESCRIBED IN mali_kbase_debug_ktrace_codes.h
-+ */
-+
-+#if 0 /* Dummy section to avoid breaking formatting */
-+int dummy_array[] = {
-+#endif
-+ /*
-+ * Generic CSF events
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(EVICT_CTX_SLOTS),
-+ /* info_val[0:7] == fw version_minor
-+ * info_val[15:8] == fw version_major
-+ * info_val[63:32] == fw version_hash
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(FIRMWARE_BOOT),
-+ KBASE_KTRACE_CODE_MAKE_CODE(FIRMWARE_REBOOT),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TOCK),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TOCK_END),
-+ /* info_val == total number of runnable groups across all kctxs */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TICK),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TICK_END),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_RESET),
-+ /* info_val = timeout in ms */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_WAIT_PROTM_QUIT),
-+ /* info_val = remaining ms timeout, or 0 if timedout */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_WAIT_PROTM_QUIT_DONE),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SYNC_UPDATE_EVENT),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SYNC_UPDATE_EVENT_NOTIFY_GPU),
-+
-+ /* info_val = JOB_IRQ_STATUS */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSF_INTERRUPT),
-+ /* info_val = JOB_IRQ_STATUS */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSF_INTERRUPT_END),
-+ /* info_val = JOB_IRQ_STATUS */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_INTERRUPT_PROCESS),
-+ /* info_val = GLB_REQ ^ GLB_ACQ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(GLB_REQ_ACQ),
-+ /* info_val[31:0] = num non idle offslot groups
-+ * info_val[32] = scheduler can suspend on idle
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_CAN_IDLE),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_ADVANCE_TICK),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_NOADVANCE_TICK),
-+ /* kctx is added to the back of the list */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_INSERT_RUNNABLE),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_REMOVE_RUNNABLE),
-+ /* kctx is moved to the back of the list */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_ROTATE_RUNNABLE),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_HEAD_RUNNABLE),
-+
-+ KBASE_KTRACE_CODE_MAKE_CODE(IDLE_WORKER_BEGIN),
-+ /* 4-bit encoding of boolean values (ease of reading as hex values)
-+ *
-+ * info_val[3:0] = was reset active/failed to be prevented
-+ * info_val[7:4] = whether scheduler was both idle and suspendable
-+ * info_val[11:8] = whether all groups were suspended
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(IDLE_WORKER_END),
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_SYNC_UPDATE_WORKER_BEGIN),
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_SYNC_UPDATE_WORKER_END),
-+
-+ /* info_val = bitmask of slots that gave an ACK for STATUS_UPDATE */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SLOTS_STATUS_UPDATE_ACK),
-+
-+ /*
-+ * Group events
-+ */
-+ /* info_val[2:0] == CSG_REQ state issued
-+ * info_val[19:16] == as_nr
-+ * info_val[63:32] == endpoint config (max number of endpoints allowed)
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_START),
-+ /* info_val == CSG_REQ state issued */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_STOP),
-+ /* info_val == CSG_ACK state */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_STARTED),
-+ /* info_val == CSG_ACK state */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_STOPPED),
-+ /* info_val == slot cleaned */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_CLEANED),
-+ /* info_val = slot requesting STATUS_UPDATE */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_STATUS_UPDATE),
-+ /* info_val = scheduler's new csg_slots_idle_mask[0]
-+ * group->csg_nr indicates which bit was set
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_IDLE_SET),
-+ /* info_val = scheduler's new csg_slots_idle_mask[0]
-+ * group->csg_nr indicates which bit was cleared
-+ *
-+ * in case of no group, multiple bits may have been updated
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_IDLE_CLEAR),
-+ /* info_val == previous priority */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_PRIO_UPDATE),
-+ /* info_val == CSG_REQ ^ CSG_ACK */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SYNC_UPDATE_INTERRUPT),
-+ /* info_val == CSG_REQ ^ CSG_ACK */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_IDLE_INTERRUPT),
-+ /* info_val == CSG_REQ ^ CSG_ACK */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_PROGRESS_TIMER_INTERRUPT),
-+ /* info_val[31:0] == CSG_REQ ^ CSG_ACQ
-+ * info_val[63:32] == CSG_IRQ_REQ ^ CSG_IRQ_ACK
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSG_INTERRUPT_PROCESS_END),
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_SYNC_UPDATE_DONE),
-+ /* info_val == run state of the group */
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_DESCHEDULE),
-+ /* info_val == run state of the group */
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_SCHEDULE),
-+ /* info_val[31:0] == new run state of the evicted group
-+ * info_val[63:32] == number of runnable groups
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_EVICT_SCHED),
-+
-+ /* info_val == new num_runnable_grps
-+ * group is added to the back of the list for its priority level
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_INSERT_RUNNABLE),
-+ /* info_val == new num_runnable_grps
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_REMOVE_RUNNABLE),
-+ /* info_val == num_runnable_grps
-+ * group is moved to the back of the list for its priority level
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_ROTATE_RUNNABLE),
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_HEAD_RUNNABLE),
-+ /* info_val == new num_idle_wait_grps
-+ * group is added to the back of the list
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_INSERT_IDLE_WAIT),
-+ /* info_val == new num_idle_wait_grps
-+ * group is added to the back of the list
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_REMOVE_IDLE_WAIT),
-+ KBASE_KTRACE_CODE_MAKE_CODE(GROUP_HEAD_IDLE_WAIT),
-+
-+ /* info_val == is scheduler running with protected mode tasks */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_CHECK_PROTM_ENTER),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_ENTER_PROTM),
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_EXIT_PROTM),
-+ /* info_val[31:0] == number of GPU address space slots in use
-+ * info_val[63:32] == number of runnable groups
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TOP_GRP),
-+ /* info_val == new count of off-slot non-idle groups
-+ * no group indicates it was set rather than incremented
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_NONIDLE_OFFSLOT_INC),
-+ /* info_val == new count of off-slot non-idle groups */
-+ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_NONIDLE_OFFSLOT_DEC),
-+
-+ KBASE_KTRACE_CODE_MAKE_CODE(PROTM_EVENT_WORKER_BEGIN),
-+ KBASE_KTRACE_CODE_MAKE_CODE(PROTM_EVENT_WORKER_END),
-+
-+ /*
-+ * Group + Queue events
-+ */
-+ /* info_val == queue->enabled */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSI_START),
-+ /* info_val == queue->enabled before stop */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSI_STOP),
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSI_STOP_REQUESTED),
-+ /* info_val == CS_REQ ^ CS_ACK that were not processed due to the group
-+ * being suspended
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSI_IGNORED_INTERRUPTS_GROUP_SUSPEND),
-+ /* info_val == CS_REQ ^ CS_ACK */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSI_FAULT_INTERRUPT),
-+ /* info_val == CS_REQ ^ CS_ACK */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSI_TILER_OOM_INTERRUPT),
-+ /* info_val == CS_REQ ^ CS_ACK */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSI_PROTM_PEND_INTERRUPT),
-+ /* info_val == CS_ACK_PROTM_PEND ^ CS_REQ_PROTM_PEND */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CSI_PROTM_ACK),
-+ /* info_val == group->run_State (for group the queue is bound to) */
-+ KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_START),
-+ KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_STOP),
-+ /* info_val == contents of CS_STATUS_WAIT_SYNC_POINTER */
-+ KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE),
-+ /* info_val == bool for result of the evaluation */
-+ KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE_EVALUATED),
-+ /* info_val == contents of CS_STATUS_WAIT */
-+ KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_STATUS_WAIT),
-+ /* info_val == current sync value pointed to by queue->sync_ptr */
-+ KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_CURRENT_VAL),
-+ /* info_val == current value of CS_STATUS_WAIT_SYNC_VALUE */
-+ KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_TEST_VAL),
-+ /* info_val == current value of CS_STATUS_BLOCKED_REASON */
-+ KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_BLOCKED_REASON),
-+ /* info_val = group's new protm_pending_bitmap[0]
-+ * queue->csi_index indicates which bit was set
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(PROTM_PENDING_SET),
-+ /* info_val = group's new protm_pending_bitmap[0]
-+ * queue->csi_index indicates which bit was cleared
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(PROTM_PENDING_CLEAR),
-+
-+ /*
-+ * KCPU queue events
-+ */
-+ /* KTrace info_val == KCPU queue fence context
-+ * KCPU extra_info_val == N/A.
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(KCPU_QUEUE_NEW),
-+ /* KTrace info_val == Number of pending commands in KCPU queue when
-+ * it is destroyed.
-+ * KCPU extra_info_val == Number of CQS wait operations present in
-+ * the KCPU queue when it is destroyed.
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(KCPU_QUEUE_DESTROY),
-+ /* KTrace info_val == CQS event memory address
-+ * KCPU extra_info_val == Upper 32 bits of event memory, i.e. contents
-+ * of error field.
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CQS_SET),
-+ /* KTrace info_val == Number of CQS objects to be waited upon
-+ * KCPU extra_info_val == N/A.
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CQS_WAIT_START),
-+ /* KTrace info_val == CQS event memory address
-+ * KCPU extra_info_val == 1 if CQS was signaled with an error and queue
-+ * inherited the error, otherwise 0.
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(CQS_WAIT_END),
-+ /* KTrace info_val == Fence context
-+ * KCPU extra_info_val == Fence seqno.
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(FENCE_SIGNAL),
-+ /* KTrace info_val == Fence context
-+ * KCPU extra_info_val == Fence seqno.
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(FENCE_WAIT_START),
-+ /* KTrace info_val == Fence context
-+ * KCPU extra_info_val == Fence seqno.
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(FENCE_WAIT_END),
-+
-+#if 0 /* Dummy section to avoid breaking formatting */
-+};
-+#endif
-+
-+/* ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_codes_jm.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_codes_jm.h
-index d534f30..f419f70 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_codes_jm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_codes_jm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2015,2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2015, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -30,6 +29,9 @@
- * The purpose of this header file is just to contain a list of trace code
- * identifiers
- *
-+ * When updating this file, also remember to update
-+ * mali_kbase_debug_linux_ktrace_jm.h
-+ *
- * IMPORTANT: THIS FILE MUST NOT BE USED FOR ANY OTHER PURPOSE OTHER THAN THAT
- * DESCRIBED IN mali_kbase_debug_ktrace_codes.h
- */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_csf.c
-new file mode 100644
-index 0000000..824ca4b
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_csf.c
-@@ -0,0 +1,193 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include "debug/mali_kbase_debug_ktrace_internal.h"
-+#include "debug/backend/mali_kbase_debug_ktrace_csf.h"
-+
-+#if KBASE_KTRACE_TARGET_RBUF
-+
-+void kbasep_ktrace_backend_format_header(char *buffer, int sz, s32 *written)
-+{
-+ *written += MAX(snprintf(buffer + *written, MAX(sz - *written, 0),
-+ "group,slot,prio,csi,kcpu"), 0);
-+}
-+
-+void kbasep_ktrace_backend_format_msg(struct kbase_ktrace_msg *trace_msg,
-+ char *buffer, int sz, s32 *written)
-+{
-+ const union kbase_ktrace_backend * const be_msg = &trace_msg->backend;
-+ /* At present, no need to check for KBASE_KTRACE_FLAG_BACKEND, as the
-+ * other backend-specific flags currently imply this anyway
-+ */
-+
-+ /* group parts */
-+ if (be_msg->gpu.flags & KBASE_KTRACE_FLAG_CSF_GROUP) {
-+ const s8 slot = be_msg->gpu.csg_nr;
-+ /* group,slot, */
-+ *written += MAX(snprintf(buffer + *written,
-+ MAX(sz - *written, 0),
-+ "%u,%d,", be_msg->gpu.group_handle, slot), 0);
-+
-+ /* prio */
-+ if (slot >= 0)
-+ *written += MAX(snprintf(buffer + *written,
-+ MAX(sz - *written, 0),
-+ "%u", be_msg->gpu.slot_prio), 0);
-+
-+ /* , */
-+ *written += MAX(snprintf(buffer + *written,
-+ MAX(sz - *written, 0),
-+ ","), 0);
-+ } else {
-+ /* No group,slot,prio fields, but ensure ending with "," */
-+ *written += MAX(snprintf(buffer + *written,
-+ MAX(sz - *written, 0),
-+ ",,,"), 0);
-+ }
-+
-+ /* queue parts: csi */
-+ if (trace_msg->backend.gpu.flags & KBASE_KTRACE_FLAG_CSF_QUEUE)
-+ *written += MAX(snprintf(buffer + *written,
-+ MAX(sz - *written, 0),
-+ "%d", be_msg->gpu.csi_index), 0);
-+
-+ /* , */
-+ *written += MAX(snprintf(buffer + *written,
-+ MAX(sz - *written, 0),
-+ ","), 0);
-+
-+ if (be_msg->gpu.flags & KBASE_KTRACE_FLAG_CSF_KCPU) {
-+ /* kcpu data */
-+ *written += MAX(snprintf(buffer + *written,
-+ MAX(sz - *written, 0),
-+ "kcpu %d (0x%llx)",
-+ be_msg->kcpu.id,
-+ be_msg->kcpu.extra_info_val), 0);
-+ }
-+
-+ /* Don't end with a trailing "," - this is a 'standalone' formatted
-+ * msg, caller will handle the delimiters
-+ */
-+}
-+
-+void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
-+ enum kbase_ktrace_code code, struct kbase_queue_group *group,
-+ struct kbase_queue *queue, kbase_ktrace_flag_t flags,
-+ u64 info_val)
-+{
-+ unsigned long irqflags;
-+ struct kbase_ktrace_msg *trace_msg;
-+ struct kbase_context *kctx = NULL;
-+
-+ spin_lock_irqsave(&kbdev->ktrace.lock, irqflags);
-+
-+ /* Reserve and update indices */
-+ trace_msg = kbasep_ktrace_reserve(&kbdev->ktrace);
-+
-+ /* Determine the kctx */
-+ if (group)
-+ kctx = group->kctx;
-+ else if (queue)
-+ kctx = queue->kctx;
-+
-+ /* Fill the common part of the message (including backend.gpu.flags) */
-+ kbasep_ktrace_msg_init(&kbdev->ktrace, trace_msg, code, kctx, flags,
-+ info_val);
-+
-+ /* Indicate to the common code that backend-specific parts will be
-+ * valid
-+ */
-+ trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_BACKEND;
-+
-+ /* Fill the CSF-specific parts of the message
-+ *
-+ * Generally, no need to use default initializers when queue/group not
-+ * present - can usually check the flags instead.
-+ */
-+
-+ if (queue) {
-+ trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_CSF_QUEUE;
-+ trace_msg->backend.gpu.csi_index = queue->csi_index;
-+ }
-+
-+ if (group) {
-+ const s8 slot = group->csg_nr;
-+
-+ trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_CSF_GROUP;
-+
-+ trace_msg->backend.gpu.csg_nr = slot;
-+
-+ if (slot >= 0) {
-+ struct kbase_csf_csg_slot *csg_slot =
-+ &kbdev->csf.scheduler.csg_slots[slot];
-+
-+ trace_msg->backend.gpu.slot_prio =
-+ csg_slot->priority;
-+ }
-+ /* slot >=0 indicates whether slot_prio valid, so no need to
-+ * initialize in the case where it's invalid
-+ */
-+
-+ trace_msg->backend.gpu.group_handle = group->handle;
-+ }
-+
-+ WARN_ON((trace_msg->backend.gpu.flags & ~KBASE_KTRACE_FLAG_ALL));
-+
-+ /* Done */
-+ spin_unlock_irqrestore(&kbdev->ktrace.lock, irqflags);
-+}
-+
-+void kbasep_ktrace_add_csf_kcpu(struct kbase_device *kbdev,
-+ enum kbase_ktrace_code code,
-+ struct kbase_kcpu_command_queue *queue,
-+ u64 info_val1, u64 info_val2)
-+{
-+ unsigned long irqflags;
-+ struct kbase_ktrace_msg *trace_msg;
-+ struct kbase_context *kctx = queue->kctx;
-+
-+ spin_lock_irqsave(&kbdev->ktrace.lock, irqflags);
-+
-+ /* Reserve and update indices */
-+ trace_msg = kbasep_ktrace_reserve(&kbdev->ktrace);
-+
-+ /* Fill the common part of the message */
-+ kbasep_ktrace_msg_init(&kbdev->ktrace, trace_msg, code, kctx, 0,
-+ info_val1);
-+
-+ /* Indicate to the common code that backend-specific parts will be
-+ * valid
-+ */
-+ trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_BACKEND;
-+
-+ /* Fill the KCPU-specific parts of the message */
-+ trace_msg->backend.kcpu.id = queue->id;
-+ trace_msg->backend.kcpu.extra_info_val = info_val2;
-+ trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_CSF_KCPU;
-+
-+ WARN_ON((trace_msg->backend.gpu.flags & ~KBASE_KTRACE_FLAG_ALL));
-+
-+ /* Done */
-+ spin_unlock_irqrestore(&kbdev->ktrace.lock, irqflags);
-+}
-+
-+#endif /* KBASE_KTRACE_TARGET_RBUF */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_csf.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_csf.h
-new file mode 100644
-index 0000000..0593c30
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_csf.h
-@@ -0,0 +1,203 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_DEBUG_KTRACE_CSF_H_
-+#define _KBASE_DEBUG_KTRACE_CSF_H_
-+
-+/*
-+ * KTrace target for internal ringbuffer
-+ */
-+#if KBASE_KTRACE_TARGET_RBUF
-+/**
-+ * kbasep_ktrace_add_csf - internal function to add trace about CSF
-+ * @kbdev: kbase device
-+ * @code: trace code
-+ * @group: queue group, or NULL if no queue group
-+ * @queue: queue, or NULL if no queue
-+ * @flags: flags about the message
-+ * @info_val: generic information about @code to add to the trace
-+ *
-+ * PRIVATE: do not use directly. Use KBASE_KTRACE_ADD_CSF() instead.
-+ */
-+
-+void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
-+ enum kbase_ktrace_code code, struct kbase_queue_group *group,
-+ struct kbase_queue *queue, kbase_ktrace_flag_t flags,
-+ u64 info_val);
-+
-+/**
-+ * kbasep_ktrace_add_csf_kcpu - internal function to add trace about the CSF
-+ * KCPU queues.
-+ * @kbdev: kbase device
-+ * @code: trace code
-+ * @queue: queue, or NULL if no queue
-+ * @info_val1: Main infoval variable with information based on the KCPU
-+ * ktrace call. Refer to mali_kbase_debug_ktrace_codes_csf.h
-+ * for information on the infoval values.
-+ * @info_val2: Extra infoval variable with information based on the KCPU
-+ * ktrace call. Refer to mali_kbase_debug_ktrace_codes_csf.h
-+ * for information on the infoval values.
-+ *
-+ * PRIVATE: do not use directly. Use KBASE_KTRACE_ADD_CSF_KCPU() instead.
-+ */
-+void kbasep_ktrace_add_csf_kcpu(struct kbase_device *kbdev,
-+ enum kbase_ktrace_code code,
-+ struct kbase_kcpu_command_queue *queue,
-+ u64 info_val1, u64 info_val2);
-+
-+#define KBASE_KTRACE_RBUF_ADD_CSF(kbdev, code, group, queue, flags, info_val) \
-+ kbasep_ktrace_add_csf(kbdev, KBASE_KTRACE_CODE(code), group, queue, \
-+ flags, info_val)
-+
-+#define KBASE_KTRACE_RBUF_ADD_CSF_KCPU(kbdev, code, queue, info_val1, \
-+ info_val2) kbasep_ktrace_add_csf_kcpu(kbdev, KBASE_KTRACE_CODE(code), \
-+ queue, info_val1, info_val2)
-+
-+#else /* KBASE_KTRACE_TARGET_RBUF */
-+
-+#define KBASE_KTRACE_RBUF_ADD_CSF(kbdev, code, group, queue, flags, info_val) \
-+ do {\
-+ CSTD_UNUSED(kbdev);\
-+ CSTD_NOP(code);\
-+ CSTD_UNUSED(group);\
-+ CSTD_UNUSED(queue);\
-+ CSTD_UNUSED(flags);\
-+ CSTD_UNUSED(info_val);\
-+ CSTD_NOP(0);\
-+ } while (0)
-+
-+#define KBASE_KTRACE_RBUF_ADD_CSF_KCPU(kbdev, code, queue, info_val1, info_val2) \
-+ do {\
-+ CSTD_UNUSED(kbdev);\
-+ CSTD_NOP(code);\
-+ CSTD_UNUSED(queue);\
-+ CSTD_UNUSED(info_val1);\
-+ CSTD_UNUSED(info_val2);\
-+ } while (0)
-+
-+#endif /* KBASE_KTRACE_TARGET_RBUF */
-+
-+/*
-+ * KTrace target for Linux's ftrace
-+ *
-+ * Note: the header file(s) that define the trace_mali_<...> tracepoints are
-+ * included by the parent header file
-+ */
-+#if KBASE_KTRACE_TARGET_FTRACE
-+
-+#define KBASE_KTRACE_FTRACE_ADD_CSF(kbdev, code, group, queue, info_val) \
-+ trace_mali_##code(kbdev, group, queue, info_val)
-+
-+#define KBASE_KTRACE_FTRACE_ADD_KCPU(code, queue, info_val1, info_val2) \
-+ trace_mali_##code(queue, info_val1, info_val2)
-+
-+#else /* KBASE_KTRACE_TARGET_FTRACE */
-+
-+#define KBASE_KTRACE_FTRACE_ADD_CSF(kbdev, code, group, queue, info_val) \
-+ do {\
-+ CSTD_UNUSED(kbdev);\
-+ CSTD_NOP(code);\
-+ CSTD_UNUSED(group);\
-+ CSTD_UNUSED(queue);\
-+ CSTD_UNUSED(info_val);\
-+ CSTD_NOP(0);\
-+ } while (0)
-+
-+#define KBASE_KTRACE_FTRACE_ADD_KCPU(code, queue, info_val1, info_val2) \
-+ do {\
-+ CSTD_NOP(code);\
-+ CSTD_UNUSED(queue);\
-+ CSTD_UNUSED(info_val1);\
-+ CSTD_UNUSED(info_val2);\
-+ } while (0)
-+
-+#endif /* KBASE_KTRACE_TARGET_FTRACE */
-+
-+/*
-+ * Master set of macros to route KTrace to any of the targets
-+ */
-+
-+/**
-+ * KBASE_KTRACE_ADD_CSF_GRP - Add trace values about a group, with info
-+ * @kbdev: kbase device
-+ * @code: trace code
-+ * @group: queue group, or NULL if no queue group
-+ * @info_val: generic information about @code to add to the trace
-+ *
-+ * Note: Any functions called through this macro will still be evaluated in
-+ * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when
-+ * KBASE_KTRACE_ENABLE == 0 any functions called to get the parameters supplied
-+ * to this macro must:
-+ * a) be static or static inline, and
-+ * b) just return 0 and have no other statements present in the body.
-+ */
-+#define KBASE_KTRACE_ADD_CSF_GRP(kbdev, code, group, info_val) \
-+ do { \
-+ /* capture values that could come from non-pure fn calls */ \
-+ struct kbase_queue_group *__group = group; \
-+ u64 __info_val = info_val; \
-+ KBASE_KTRACE_RBUF_ADD_CSF(kbdev, code, __group, NULL, 0u, \
-+ __info_val); \
-+ KBASE_KTRACE_FTRACE_ADD_CSF(kbdev, code, __group, NULL, \
-+ __info_val); \
-+ } while (0)
-+
-+/**
-+ * KBASE_KTRACE_ADD_CSF_GRP_Q - Add trace values about a group, queue, with info
-+ * @kbdev: kbase device
-+ * @code: trace code
-+ * @group: queue group, or NULL if no queue group
-+ * @queue: queue, or NULL if no queue
-+ * @info_val: generic information about @code to add to the trace
-+ *
-+ * Note: Any functions called through this macro will still be evaluated in
-+ * Release builds (CONFIG_MALI_DEBUG not defined). Therefore, when
-+ * KBASE_KTRACE_ENABLE == 0 any functions called to get the parameters supplied
-+ * to this macro must:
-+ * a) be static or static inline, and
-+ * b) just return 0 and have no other statements present in the body.
-+ */
-+#define KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, code, group, queue, info_val) \
-+ do { \
-+ /* capture values that could come from non-pure fn calls */ \
-+ struct kbase_queue_group *__group = group; \
-+ struct kbase_queue *__queue = queue; \
-+ u64 __info_val = info_val; \
-+ KBASE_KTRACE_RBUF_ADD_CSF(kbdev, code, __group, __queue, 0u, \
-+ __info_val); \
-+ KBASE_KTRACE_FTRACE_ADD_CSF(kbdev, code, __group, \
-+ __queue, __info_val); \
-+ } while (0)
-+
-+
-+#define KBASE_KTRACE_ADD_CSF_KCPU(kbdev, code, queue, info_val1, info_val2) \
-+ do { \
-+ /* capture values that could come from non-pure fn calls */ \
-+ struct kbase_kcpu_command_queue *__queue = queue; \
-+ u64 __info_val1 = info_val1; \
-+ u64 __info_val2 = info_val2; \
-+ KBASE_KTRACE_RBUF_ADD_CSF_KCPU(kbdev, code, __queue, \
-+ __info_val1, __info_val2); \
-+ KBASE_KTRACE_FTRACE_ADD_KCPU(code, __queue, \
-+ __info_val1, __info_val2); \
-+ } while (0)
-+
-+#endif /* _KBASE_DEBUG_KTRACE_CSF_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_defs_csf.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_defs_csf.h
-new file mode 100644
-index 0000000..7f32cd2
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_defs_csf.h
-@@ -0,0 +1,116 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_DEBUG_KTRACE_DEFS_CSF_H_
-+#define _KBASE_DEBUG_KTRACE_DEFS_CSF_H_
-+
-+#if KBASE_KTRACE_TARGET_RBUF
-+/**
-+ * DOC: KTrace version history, CSF variant
-+ *
-+ * 1.0:
-+ * First version, with version information in the header.
-+ *
-+ * 1.1:
-+ * kctx field is no longer a pointer, and is now an ID of the format %d_%u as
-+ * used by kctx directories in mali debugfs entries: (tgid creating the kctx),
-+ * (unique kctx id)
-+ *
-+ * ftrace backend now outputs kctx field (as %d_%u format).
-+ *
-+ * Add fields group, slot, prio, csi into backend-specific part.
-+ *
-+ * 1.2:
-+ * There is a new class of KCPU traces; with this, a new KCPU column in the
-+ * ringbuffer RBUF (mali_trace) between csi and info_val, which is empty
-+ * for non-kcpu related traces, and usually displays the KCPU Queue ID and
-+ * an extra information value. ftrace also displays these KCPU traces.
-+ *
-+ * 1.3:
-+ * Add a lot of extra new traces. Tweak some existing scheduler related traces
-+ * to contain extra information information/happen at slightly different times.
-+ * SCHEDULER_EXIT_PROTM now has group information
-+ */
-+#define KBASE_KTRACE_VERSION_MAJOR 1
-+#define KBASE_KTRACE_VERSION_MINOR 3
-+
-+/* indicates if the trace message has valid queue-group related info. */
-+#define KBASE_KTRACE_FLAG_CSF_GROUP (((kbase_ktrace_flag_t)1) << 0)
-+
-+/* indicates if the trace message has valid queue related info. */
-+#define KBASE_KTRACE_FLAG_CSF_QUEUE (((kbase_ktrace_flag_t)1) << 1)
-+
-+/* indicates if the trace message has valid KCPU-queue related info. */
-+#define KBASE_KTRACE_FLAG_CSF_KCPU (((kbase_ktrace_flag_t)1) << 2)
-+
-+/* Collect all the flags together for debug checking */
-+#define KBASE_KTRACE_FLAG_BACKEND_ALL \
-+ (KBASE_KTRACE_FLAG_CSF_GROUP | KBASE_KTRACE_FLAG_CSF_QUEUE | \
-+ KBASE_KTRACE_FLAG_CSF_KCPU)
-+
-+/**
-+ * union kbase_ktrace_backend - backend specific part of a trace message
-+ * @kcpu: kcpu union member
-+ * @kcpu.code: Identifies the event, refer to enum kbase_ktrace_code.
-+ * @kcpu.flags: indicates information about the trace message itself. Used
-+ * during dumping of the message.
-+ * @kcpu.id: ID of the KCPU queue.
-+ * @kcpu.extra_info_val: value specific to the type of KCPU event being traced.
-+ * Refer to the KPU specific code in enum kbase_ktrace_code in
-+ * mali_kbase_debug_ktrace_codes_csf.h
-+ * @gpu: gpu union member
-+ * @gpu.code: Identifies the event, refer to enum kbase_ktrace_code.
-+ * @gpu.flags: indicates information about the trace message itself. Used
-+ * during dumping of the message.
-+ * @gpu.group_handle: Handle identifying the associated queue group. Only valid
-+ * when @flags contains KBASE_KTRACE_FLAG_CSF_GROUP.
-+ * @gpu.csg_nr: Number/index of the associated queue group's CS group to
-+ * which it is mapped, or negative if none associated. Only
-+ * valid when @flags contains KBASE_KTRACE_FLAG_CSF_GROUP.
-+ * @gpu.slot_prio: The priority of the slot for the associated group, if it
-+ * was scheduled. Hence, only valid when @csg_nr >=0 and
-+ * @flags contains KBASE_KTRACE_FLAG_CSF_GROUP.
-+ * @gpu.csi_index: ID of the associated queue's CS HW interface.
-+ * Only valid when @flags contains KBASE_KTRACE_FLAG_CSF_QUEUE.
-+ */
-+
-+union kbase_ktrace_backend {
-+ /* Place 64 and 32-bit members together */
-+ /* Pack smaller members together */
-+ struct {
-+ kbase_ktrace_code_t code;
-+ kbase_ktrace_flag_t flags;
-+ u8 id;
-+ u64 extra_info_val;
-+ } kcpu;
-+
-+ struct {
-+ kbase_ktrace_code_t code;
-+ kbase_ktrace_flag_t flags;
-+ u8 group_handle;
-+ s8 csg_nr;
-+ u8 slot_prio;
-+ s8 csi_index;
-+ } gpu;
-+};
-+
-+#endif /* KBASE_KTRACE_TARGET_RBUF */
-+#endif /* _KBASE_DEBUG_KTRACE_DEFS_CSF_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_defs_jm.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_defs_jm.h
-index 55b66ad..c01f930 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_defs_jm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_defs_jm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,25 +17,44 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_DEBUG_KTRACE_DEFS_JM_H_
- #define _KBASE_DEBUG_KTRACE_DEFS_JM_H_
-
-+#if KBASE_KTRACE_TARGET_RBUF
- /**
- * DOC: KTrace version history, JM variant
-+ *
- * 1.0:
-- * - Original version (implicit, header did not carry version information)
-+ * Original version (implicit, header did not carry version information).
-+ *
- * 2.0:
-- * - Introduced version information into the header
-- * - some changes of parameter names in header
-- * - trace now uses all 64-bits of info_val
-- * - Non-JM specific parts moved to using info_val instead of refcount/gpu_addr
-+ * Introduced version information into the header.
-+ *
-+ * Some changes of parameter names in header.
-+ *
-+ * Trace now uses all 64-bits of info_val.
-+ *
-+ * Non-JM specific parts moved to using info_val instead of refcount/gpu_addr.
-+ *
-+ * 2.1:
-+ * kctx field is no longer a pointer, and is now an ID of the format %d_%u as
-+ * used by kctx directories in mali debugfs entries: (tgid creating the kctx),
-+ * (unique kctx id).
-+ *
-+ * ftrace backend now outputs kctx field (as %d_%u format).
-+ *
- */
- #define KBASE_KTRACE_VERSION_MAJOR 2
--#define KBASE_KTRACE_VERSION_MINOR 0
-+#define KBASE_KTRACE_VERSION_MINOR 1
-+#endif /* KBASE_KTRACE_TARGET_RBUF */
-+
-+/*
-+ * Note: mali_kbase_debug_ktrace_jm.h needs these value even if the RBUF target
-+ * is disabled (they get discarded with CSTD_UNUSED(), but they're still
-+ * referenced)
-+ */
-
- /* indicates if the trace message has a valid refcount member */
- #define KBASE_KTRACE_FLAG_JM_REFCOUNT (((kbase_ktrace_flag_t)1) << 0)
-@@ -43,33 +63,47 @@
- /* indicates if the trace message has valid atom related info. */
- #define KBASE_KTRACE_FLAG_JM_ATOM (((kbase_ktrace_flag_t)1) << 2)
-
-+#if KBASE_KTRACE_TARGET_RBUF
-+/* Collect all the flags together for debug checking */
-+#define KBASE_KTRACE_FLAG_BACKEND_ALL \
-+ (KBASE_KTRACE_FLAG_JM_REFCOUNT | KBASE_KTRACE_FLAG_JM_JOBSLOT \
-+ | KBASE_KTRACE_FLAG_JM_ATOM)
-
- /**
-- * struct kbase_ktrace_backend - backend specific part of a trace message
-+ * union kbase_ktrace_backend - backend specific part of a trace message
-+ * Contains only a struct but is a union such that it is compatible with
-+ * generic JM and CSF KTrace calls.
- *
-- * @atom_udata: Copy of the user data sent for the atom in base_jd_submit.
-- * Only valid if KBASE_KTRACE_FLAG_JM_ATOM is set in @flags
-- * @gpu_addr: GPU address, usually of the job-chain represented by an atom.
-- * @atom_number: id of the atom for which trace message was added. Only valid
-- * if KBASE_KTRACE_FLAG_JM_ATOM is set in @flags
-- * @code: Identifies the event, refer to enum kbase_ktrace_code.
-- * @flags: indicates information about the trace message itself. Used
-- * during dumping of the message.
-- * @jobslot: job-slot for which trace message was added, valid only for
-- * job-slot management events.
-- * @refcount: reference count for the context, valid for certain events
-- * related to scheduler core and policy.
-+ * @gpu: gpu union member
-+ * @gpu.atom_udata: Copy of the user data sent for the atom in base_jd_submit.
-+ * Only valid if KBASE_KTRACE_FLAG_JM_ATOM is set in @flags
-+ * @gpu.gpu_addr: GPU address, usually of the job-chain represented by an
-+ * atom.
-+ * @gpu.atom_number: id of the atom for which trace message was added. Only
-+ * valid if KBASE_KTRACE_FLAG_JM_ATOM is set in @flags
-+ * @gpu.code: Identifies the event, refer to enum kbase_ktrace_code.
-+ * @gpu.flags: indicates information about the trace message itself. Used
-+ * during dumping of the message.
-+ * @gpu.jobslot: job-slot for which trace message was added, valid only for
-+ * job-slot management events.
-+ * @gpu.refcount: reference count for the context, valid for certain events
-+ * related to scheduler core and policy.
- */
--struct kbase_ktrace_backend {
-- /* Place 64 and 32-bit members together */
-- u64 atom_udata[2]; /* Only valid for KBASE_KTRACE_FLAG_JM_ATOM */
-- u64 gpu_addr;
-- int atom_number; /* Only valid for KBASE_KTRACE_FLAG_JM_ATOM */
-- /* Pack smaller members together */
-- kbase_ktrace_code_t code;
-- kbase_ktrace_flag_t flags;
-- u8 jobslot;
-- u8 refcount;
-+union kbase_ktrace_backend {
-+ struct {
-+ /* Place 64 and 32-bit members together */
-+ u64 atom_udata[2]; /* Only valid for
-+ * KBASE_KTRACE_FLAG_JM_ATOM
-+ */
-+ u64 gpu_addr;
-+ int atom_number; /* Only valid for KBASE_KTRACE_FLAG_JM_ATOM */
-+ /* Pack smaller members together */
-+ kbase_ktrace_code_t code;
-+ kbase_ktrace_flag_t flags;
-+ u8 jobslot;
-+ u8 refcount;
-+ } gpu;
- };
-+#endif /* KBASE_KTRACE_TARGET_RBUF */
-
- #endif /* _KBASE_DEBUG_KTRACE_DEFS_JM_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_jm.c
-index e651a09..fed9c1f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_jm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_jm.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,9 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-+
- #include <mali_kbase.h>
- #include "debug/mali_kbase_debug_ktrace_internal.h"
- #include "debug/backend/mali_kbase_debug_ktrace_jm.h"
-@@ -35,38 +35,39 @@ void kbasep_ktrace_backend_format_msg(struct kbase_ktrace_msg *trace_msg,
- char *buffer, int sz, s32 *written)
- {
- /* katom */
-- if (trace_msg->backend.flags & KBASE_KTRACE_FLAG_JM_ATOM)
-+ if (trace_msg->backend.gpu.flags & KBASE_KTRACE_FLAG_JM_ATOM)
- *written += MAX(snprintf(buffer + *written,
- MAX(sz - *written, 0),
- "atom %d (ud: 0x%llx 0x%llx)",
-- trace_msg->backend.atom_number,
-- trace_msg->backend.atom_udata[0],
-- trace_msg->backend.atom_udata[1]), 0);
-+ trace_msg->backend.gpu.atom_number,
-+ trace_msg->backend.gpu.atom_udata[0],
-+ trace_msg->backend.gpu.atom_udata[1]), 0);
-
- /* gpu_addr */
-- if (trace_msg->backend.flags & KBASE_KTRACE_FLAG_BACKEND)
-+ if (trace_msg->backend.gpu.flags & KBASE_KTRACE_FLAG_BACKEND)
- *written += MAX(snprintf(buffer + *written,
- MAX(sz - *written, 0),
-- ",%.8llx,", trace_msg->backend.gpu_addr), 0);
-+ ",%.8llx,", trace_msg->backend.gpu.gpu_addr),
-+ 0);
- else
- *written += MAX(snprintf(buffer + *written,
- MAX(sz - *written, 0),
- ",,"), 0);
-
- /* jobslot */
-- if (trace_msg->backend.flags & KBASE_KTRACE_FLAG_JM_JOBSLOT)
-+ if (trace_msg->backend.gpu.flags & KBASE_KTRACE_FLAG_JM_JOBSLOT)
- *written += MAX(snprintf(buffer + *written,
- MAX(sz - *written, 0),
-- "%d", trace_msg->backend.jobslot), 0);
-+ "%d", trace_msg->backend.gpu.jobslot), 0);
-
- *written += MAX(snprintf(buffer + *written, MAX(sz - *written, 0),
- ","), 0);
-
- /* refcount */
-- if (trace_msg->backend.flags & KBASE_KTRACE_FLAG_JM_REFCOUNT)
-+ if (trace_msg->backend.gpu.flags & KBASE_KTRACE_FLAG_JM_REFCOUNT)
- *written += MAX(snprintf(buffer + *written,
- MAX(sz - *written, 0),
-- "%d", trace_msg->backend.refcount), 0);
-+ "%d", trace_msg->backend.gpu.refcount), 0);
- }
-
- void kbasep_ktrace_add_jm(struct kbase_device *kbdev,
-@@ -83,28 +84,31 @@ void kbasep_ktrace_add_jm(struct kbase_device *kbdev,
- /* Reserve and update indices */
- trace_msg = kbasep_ktrace_reserve(&kbdev->ktrace);
-
-- /* Fill the common part of the message (including backend.flags) */
-+ /* Fill the common part of the message (including backend.gpu.flags) */
- kbasep_ktrace_msg_init(&kbdev->ktrace, trace_msg, code, kctx, flags,
- info_val);
-
- /* Indicate to the common code that backend-specific parts will be
- * valid
- */
-- trace_msg->backend.flags |= KBASE_KTRACE_FLAG_BACKEND;
-+ trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_BACKEND;
-
- /* Fill the JM-specific parts of the message */
- if (katom) {
-- trace_msg->backend.flags |= KBASE_KTRACE_FLAG_JM_ATOM;
-+ trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_JM_ATOM;
-
-- trace_msg->backend.atom_number = kbase_jd_atom_id(katom->kctx, katom);
-- trace_msg->backend.atom_udata[0] = katom->udata.blob[0];
-- trace_msg->backend.atom_udata[1] = katom->udata.blob[1];
-+ trace_msg->backend.gpu.atom_number =
-+ kbase_jd_atom_id(katom->kctx, katom);
-+ trace_msg->backend.gpu.atom_udata[0] = katom->udata.blob[0];
-+ trace_msg->backend.gpu.atom_udata[1] = katom->udata.blob[1];
- }
-
-- trace_msg->backend.gpu_addr = gpu_addr;
-- trace_msg->backend.jobslot = jobslot;
-+ trace_msg->backend.gpu.gpu_addr = gpu_addr;
-+ trace_msg->backend.gpu.jobslot = jobslot;
- /* Clamp refcount */
-- trace_msg->backend.refcount = MIN((unsigned int)refcount, 0xFF);
-+ trace_msg->backend.gpu.refcount = MIN((unsigned int)refcount, 0xFF);
-+
-+ WARN_ON((trace_msg->backend.gpu.flags & ~KBASE_KTRACE_FLAG_ALL));
-
- /* Done */
- spin_unlock_irqrestore(&kbdev->ktrace.lock, irqflags);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_jm.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_jm.h
-index c1bacf9..8b09d05 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_jm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_ktrace_jm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_DEBUG_KTRACE_JM_H_
-@@ -47,89 +46,24 @@ void kbasep_ktrace_add_jm(struct kbase_device *kbdev,
- kbase_ktrace_flag_t flags, int refcount, int jobslot,
- u64 info_val);
-
--#define KBASE_KTRACE_RBUF_ADD_JM_SLOT(kbdev, code, kctx, katom, gpu_addr, \
-- jobslot) \
-- kbasep_ktrace_add_jm(kbdev, KBASE_KTRACE_CODE(code), kctx, katom, \
-- gpu_addr, KBASE_KTRACE_FLAG_JM_JOBSLOT, 0, jobslot, 0)
--
--#define KBASE_KTRACE_RBUF_ADD_JM_SLOT_INFO(kbdev, code, kctx, katom, gpu_addr, \
-- jobslot, info_val) \
-+#define KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, gpu_addr, flags, \
-+ refcount, jobslot, info_val) \
- kbasep_ktrace_add_jm(kbdev, KBASE_KTRACE_CODE(code), kctx, katom, \
-- gpu_addr, KBASE_KTRACE_FLAG_JM_JOBSLOT, 0, jobslot, \
-- info_val)
--
--#define KBASE_KTRACE_RBUF_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, gpu_addr, \
-- refcount) \
-- kbasep_ktrace_add_jm(kbdev, KBASE_KTRACE_CODE(code), kctx, katom, \
-- gpu_addr, KBASE_KTRACE_FLAG_JM_REFCOUNT, refcount, 0, 0)
--#define KBASE_KTRACE_RBUF_ADD_JM_REFCOUNT_INFO(kbdev, code, kctx, katom, \
-- gpu_addr, refcount, info_val) \
-- kbasep_ktrace_add_jm(kbdev, KBASE_KTRACE_CODE(code), kctx, katom, \
-- gpu_addr, KBASE_KTRACE_FLAG_JM_REFCOUNT, refcount, 0, \
-- info_val)
--
--#define KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, gpu_addr, info_val) \
-- kbasep_ktrace_add_jm(kbdev, KBASE_KTRACE_CODE(code), kctx, katom, \
-- gpu_addr, 0, 0, 0, info_val)
-+ gpu_addr, flags, refcount, jobslot, info_val)
-
- #else /* KBASE_KTRACE_TARGET_RBUF */
--#define KBASE_KTRACE_RBUF_ADD_JM_SLOT(kbdev, code, kctx, katom, gpu_addr, \
-- jobslot) \
-- do {\
-- CSTD_UNUSED(kbdev);\
-- CSTD_NOP(code);\
-- CSTD_UNUSED(kctx);\
-- CSTD_UNUSED(katom);\
-- CSTD_UNUSED(gpu_addr);\
-- CSTD_UNUSED(jobslot);\
-- CSTD_NOP(0);\
-- } while (0)
--
--#define KBASE_KTRACE_RBUF_ADD_JM_SLOT_INFO(kbdev, code, kctx, katom, gpu_addr, \
-- jobslot, info_val) \
-- do {\
-- CSTD_UNUSED(kbdev);\
-- CSTD_NOP(code);\
-- CSTD_UNUSED(kctx);\
-- CSTD_UNUSED(katom);\
-- CSTD_UNUSED(gpu_addr);\
-- CSTD_UNUSED(jobslot);\
-- CSTD_UNUSED(info_val);\
-- CSTD_NOP(0);\
-- } while (0)
-
--#define KBASE_KTRACE_RBUF_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, gpu_addr, \
-- refcount) \
-+#define KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, gpu_addr, flags, \
-+ refcount, jobslot, info_val) \
- do {\
- CSTD_UNUSED(kbdev);\
- CSTD_NOP(code);\
- CSTD_UNUSED(kctx);\
- CSTD_UNUSED(katom);\
- CSTD_UNUSED(gpu_addr);\
-+ CSTD_UNUSED(flags);\
- CSTD_UNUSED(refcount);\
-- CSTD_NOP(0);\
-- } while (0)
--
--#define KBASE_KTRACE_RBUF_ADD_JM_REFCOUNT_INFO(kbdev, code, kctx, katom, \
-- gpu_addr, refcount, info_val) \
-- do {\
-- CSTD_UNUSED(kbdev);\
-- CSTD_NOP(code);\
-- CSTD_UNUSED(kctx);\
-- CSTD_UNUSED(katom);\
-- CSTD_UNUSED(gpu_addr);\
-- CSTD_UNUSED(info_val);\
-- CSTD_NOP(0);\
-- } while (0)
--
--#define KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, gpu_addr, \
-- info_val)\
-- do {\
-- CSTD_UNUSED(kbdev);\
-- CSTD_NOP(code);\
-- CSTD_UNUSED(kctx);\
-- CSTD_UNUSED(katom);\
-- CSTD_UNUSED(gpu_addr);\
-+ CSTD_UNUSED(jobslot);\
- CSTD_UNUSED(info_val);\
- CSTD_NOP(0);\
- } while (0)
-@@ -137,27 +71,30 @@ void kbasep_ktrace_add_jm(struct kbase_device *kbdev,
-
- /*
- * KTrace target for Linux's ftrace
-+ *
-+ * Note: the header file(s) that define the trace_mali_<...> tracepoints are
-+ * included by the parent header file
- */
- #if KBASE_KTRACE_TARGET_FTRACE
- #define KBASE_KTRACE_FTRACE_ADD_JM_SLOT(kbdev, code, kctx, katom, gpu_addr, \
- jobslot) \
-- trace_mali_##code(jobslot, 0)
-+ trace_mali_##code(kctx, jobslot, 0)
-
- #define KBASE_KTRACE_FTRACE_ADD_JM_SLOT_INFO(kbdev, code, kctx, katom, \
- gpu_addr, jobslot, info_val) \
-- trace_mali_##code(jobslot, info_val)
-+ trace_mali_##code(kctx, jobslot, info_val)
-
- #define KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, \
- gpu_addr, refcount) \
-- trace_mali_##code(refcount, 0)
-+ trace_mali_##code(kctx, refcount, 0)
-
- #define KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT_INFO(kbdev, code, kctx, katom, \
- gpu_addr, refcount, info_val) \
-- trace_mali_##code(refcount, info_val)
-+ trace_mali_##code(kctx, refcount, info_val)
-
- #define KBASE_KTRACE_FTRACE_ADD_JM(kbdev, code, kctx, katom, gpu_addr, \
- info_val) \
-- trace_mali_##code(gpu_addr, info_val)
-+ trace_mali_##code(kctx, gpu_addr, info_val)
- #else /* KBASE_KTRACE_TARGET_FTRACE */
- #define KBASE_KTRACE_FTRACE_ADD_JM_SLOT(kbdev, code, kctx, katom, gpu_addr, \
- jobslot) \
-@@ -247,7 +184,9 @@ void kbasep_ktrace_add_jm(struct kbase_device *kbdev,
- /* capture values that could come from non-pure function calls */ \
- u64 __gpu_addr = gpu_addr; \
- int __jobslot = jobslot; \
-- KBASE_KTRACE_RBUF_ADD_JM_SLOT(kbdev, code, kctx, katom, __gpu_addr, __jobslot); \
-+ KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, \
-+ KBASE_KTRACE_FLAG_JM_JOBSLOT, 0, __jobslot, \
-+ 0); \
- KBASE_KTRACE_FTRACE_ADD_JM_SLOT(kbdev, code, kctx, katom, __gpu_addr, __jobslot); \
- } while (0)
-
-@@ -275,7 +214,9 @@ void kbasep_ktrace_add_jm(struct kbase_device *kbdev,
- u64 __gpu_addr = gpu_addr; \
- int __jobslot = jobslot; \
- u64 __info_val = info_val; \
-- KBASE_KTRACE_RBUF_ADD_JM_SLOT_INFO(kbdev, code, kctx, katom, __gpu_addr, __jobslot, __info_val); \
-+ KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, \
-+ KBASE_KTRACE_FLAG_JM_JOBSLOT, 0, __jobslot, \
-+ __info_val); \
- KBASE_KTRACE_FTRACE_ADD_JM_SLOT_INFO(kbdev, code, kctx, katom, __gpu_addr, __jobslot, __info_val); \
- } while (0)
-
-@@ -301,7 +242,9 @@ void kbasep_ktrace_add_jm(struct kbase_device *kbdev,
- /* capture values that could come from non-pure function calls */ \
- u64 __gpu_addr = gpu_addr; \
- int __refcount = refcount; \
-- KBASE_KTRACE_RBUF_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, __gpu_addr, __refcount); \
-+ KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, \
-+ KBASE_KTRACE_FLAG_JM_REFCOUNT, __refcount, 0, \
-+ 0u); \
- KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, __gpu_addr, __refcount); \
- } while (0)
-
-@@ -330,7 +273,9 @@ void kbasep_ktrace_add_jm(struct kbase_device *kbdev,
- u64 __gpu_addr = gpu_addr; \
- int __refcount = refcount; \
- u64 __info_val = info_val; \
-- KBASE_KTRACE_RBUF_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, __gpu_addr, __refcount, __info_val); \
-+ KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, \
-+ KBASE_KTRACE_FLAG_JM_REFCOUNT, __refcount, 0, \
-+ __info_val); \
- KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, __gpu_addr, __refcount, __info_val); \
- } while (0)
-
-@@ -355,7 +300,8 @@ void kbasep_ktrace_add_jm(struct kbase_device *kbdev,
- /* capture values that could come from non-pure function calls */ \
- u64 __gpu_addr = gpu_addr; \
- u64 __info_val = info_val; \
-- KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, __info_val); \
-+ KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, \
-+ 0u, 0, 0, __info_val); \
- KBASE_KTRACE_FTRACE_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, __info_val); \
- } while (0)
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_linux_ktrace_csf.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_linux_ktrace_csf.h
-new file mode 100644
-index 0000000..4b23fc9
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_linux_ktrace_csf.h
-@@ -0,0 +1,241 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * NOTE: This must **only** be included through mali_linux_trace.h,
-+ * otherwise it will fail to setup tracepoints correctly
-+ */
-+
-+#if !defined(_KBASE_DEBUG_LINUX_KTRACE_CSF_H_) || defined(TRACE_HEADER_MULTI_READ)
-+#define _KBASE_DEBUG_LINUX_KTRACE_CSF_H_
-+
-+/*
-+ * Generic CSF events - using the common DEFINE_MALI_ADD_EVENT
-+ */
-+DEFINE_MALI_ADD_EVENT(EVICT_CTX_SLOTS);
-+DEFINE_MALI_ADD_EVENT(FIRMWARE_BOOT);
-+DEFINE_MALI_ADD_EVENT(FIRMWARE_REBOOT);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_TOCK);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_TOCK_END);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK_END);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_RESET);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_WAIT_PROTM_QUIT);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_WAIT_PROTM_QUIT_DONE);
-+DEFINE_MALI_ADD_EVENT(SYNC_UPDATE_EVENT);
-+DEFINE_MALI_ADD_EVENT(SYNC_UPDATE_EVENT_NOTIFY_GPU);
-+DEFINE_MALI_ADD_EVENT(CSF_INTERRUPT);
-+DEFINE_MALI_ADD_EVENT(CSF_INTERRUPT_END);
-+DEFINE_MALI_ADD_EVENT(CSG_INTERRUPT_PROCESS);
-+DEFINE_MALI_ADD_EVENT(GLB_REQ_ACQ);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_CAN_IDLE);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_ADVANCE_TICK);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_NOADVANCE_TICK);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_INSERT_RUNNABLE);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_REMOVE_RUNNABLE);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_ROTATE_RUNNABLE);
-+DEFINE_MALI_ADD_EVENT(SCHEDULER_HEAD_RUNNABLE);
-+DEFINE_MALI_ADD_EVENT(IDLE_WORKER_BEGIN);
-+DEFINE_MALI_ADD_EVENT(IDLE_WORKER_END);
-+DEFINE_MALI_ADD_EVENT(GROUP_SYNC_UPDATE_WORKER_BEGIN);
-+DEFINE_MALI_ADD_EVENT(GROUP_SYNC_UPDATE_WORKER_END);
-+DEFINE_MALI_ADD_EVENT(SLOTS_STATUS_UPDATE_ACK);
-+
-+DECLARE_EVENT_CLASS(mali_csf_grp_q_template,
-+ TP_PROTO(struct kbase_device *kbdev, struct kbase_queue_group *group,
-+ struct kbase_queue *queue, u64 info_val),
-+ TP_ARGS(kbdev, group, queue, info_val),
-+ TP_STRUCT__entry(
-+ __field(u64, info_val)
-+ __field(pid_t, kctx_tgid)
-+ __field(u32, kctx_id)
-+ __field(u8, group_handle)
-+ __field(s8, csg_nr)
-+ __field(u8, slot_prio)
-+ __field(s8, csi_index)
-+ ),
-+ TP_fast_assign(
-+ {
-+ struct kbase_context *kctx = NULL;
-+
-+ __entry->info_val = info_val;
-+ /* Note: if required in future, we could record some
-+ * flags in __entry about whether the group/queue parts
-+ * are valid, and add that to the trace message e.g.
-+ * by using __print_flags()/__print_symbolic()
-+ */
-+ if (queue) {
-+ /* Note: kctx overridden by group->kctx later if group is valid */
-+ kctx = queue->kctx;
-+ __entry->csi_index = queue->csi_index;
-+ } else {
-+ __entry->csi_index = -1;
-+ }
-+
-+ if (group) {
-+ kctx = group->kctx;
-+ __entry->group_handle = group->handle;
-+ __entry->csg_nr = group->csg_nr;
-+ if (group->csg_nr >= 0)
-+ __entry->slot_prio = kbdev->csf.scheduler.csg_slots[group->csg_nr].priority;
-+ else
-+ __entry->slot_prio = 0u;
-+ } else {
-+ __entry->group_handle = 0u;
-+ __entry->csg_nr = -1;
-+ __entry->slot_prio = 0u;
-+ }
-+ __entry->kctx_id = (kctx) ? kctx->id : 0u;
-+ __entry->kctx_tgid = (kctx) ? kctx->tgid : 0;
-+ }
-+
-+ ),
-+ TP_printk("kctx=%d_%u group=%u slot=%d prio=%u csi=%d info=0x%llx",
-+ __entry->kctx_tgid, __entry->kctx_id,
-+ __entry->group_handle, __entry->csg_nr,
-+ __entry->slot_prio, __entry->csi_index,
-+ __entry->info_val)
-+);
-+
-+/*
-+ * Group events
-+ */
-+#define DEFINE_MALI_CSF_GRP_EVENT(name) \
-+ DEFINE_EVENT_PRINT(mali_csf_grp_q_template, mali_##name, \
-+ TP_PROTO(struct kbase_device *kbdev, struct kbase_queue_group *group, \
-+ struct kbase_queue *queue, u64 info_val), \
-+ TP_ARGS(kbdev, group, queue, info_val), \
-+ TP_printk("kctx=%d_%u group=%u slot=%d prio=%u info=0x%llx", \
-+ __entry->kctx_tgid, __entry->kctx_id, __entry->group_handle, \
-+ __entry->csg_nr, __entry->slot_prio, __entry->info_val))
-+
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_START);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STOP);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STARTED);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STOPPED);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_CLEANED);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STATUS_UPDATE);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_IDLE_SET);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_IDLE_CLEAR);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_PRIO_UPDATE);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_SYNC_UPDATE_INTERRUPT);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_IDLE_INTERRUPT);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_PROGRESS_TIMER_INTERRUPT);
-+DEFINE_MALI_CSF_GRP_EVENT(CSG_INTERRUPT_PROCESS_END);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_SYNC_UPDATE_DONE);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_DESCHEDULE);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_SCHEDULE);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_EVICT_SCHED);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_INSERT_RUNNABLE);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_REMOVE_RUNNABLE);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_ROTATE_RUNNABLE);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_HEAD_RUNNABLE);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_INSERT_IDLE_WAIT);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_REMOVE_IDLE_WAIT);
-+DEFINE_MALI_CSF_GRP_EVENT(GROUP_HEAD_IDLE_WAIT);
-+DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_CHECK_PROTM_ENTER);
-+DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_ENTER_PROTM);
-+DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_EXIT_PROTM);
-+DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_TOP_GRP);
-+DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_NONIDLE_OFFSLOT_INC);
-+DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_NONIDLE_OFFSLOT_DEC);
-+DEFINE_MALI_CSF_GRP_EVENT(PROTM_EVENT_WORKER_BEGIN);
-+DEFINE_MALI_CSF_GRP_EVENT(PROTM_EVENT_WORKER_END);
-+
-+#undef DEFINE_MALI_CSF_GRP_EVENT
-+
-+/*
-+ * Group + Queue events
-+ */
-+#define DEFINE_MALI_CSF_GRP_Q_EVENT(name) \
-+ DEFINE_EVENT(mali_csf_grp_q_template, mali_##name, \
-+ TP_PROTO(struct kbase_device *kbdev, struct kbase_queue_group *group, \
-+ struct kbase_queue *queue, u64 info_val), \
-+ TP_ARGS(kbdev, group, queue, info_val))
-+
-+DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_START);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_STOP);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_STOP_REQUESTED);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_IGNORED_INTERRUPTS_GROUP_SUSPEND);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_FAULT_INTERRUPT);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_TILER_OOM_INTERRUPT);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_PROTM_PEND_INTERRUPT);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_PROTM_ACK);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_START);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_STOP);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE_EVALUATED);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_STATUS_WAIT);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_CURRENT_VAL);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_TEST_VAL);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_BLOCKED_REASON);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(PROTM_PENDING_SET);
-+DEFINE_MALI_CSF_GRP_Q_EVENT(PROTM_PENDING_CLEAR);
-+
-+#undef DEFINE_MALI_CSF_GRP_Q_EVENT
-+
-+/*
-+ * KCPU queue events
-+ */
-+DECLARE_EVENT_CLASS(mali_csf_kcpu_queue_template,
-+ TP_PROTO(struct kbase_kcpu_command_queue *queue,
-+ u64 info_val1, u64 info_val2),
-+ TP_ARGS(queue, info_val1, info_val2),
-+ TP_STRUCT__entry(
-+ __field(u64, info_val1)
-+ __field(u64, info_val2)
-+ __field(pid_t, kctx_tgid)
-+ __field(u32, kctx_id)
-+ __field(u8, id)
-+ ),
-+ TP_fast_assign(
-+ {
-+ __entry->info_val1 = info_val1;
-+ __entry->info_val2 = info_val2;
-+ __entry->kctx_id = queue->kctx->id;
-+ __entry->kctx_tgid = queue->kctx->tgid;
-+ __entry->id = queue->id;
-+ }
-+
-+ ),
-+ TP_printk("kctx=%d_%u id=%u info_val1=0x%llx info_val2=0x%llx",
-+ __entry->kctx_tgid, __entry->kctx_id, __entry->id,
-+ __entry->info_val1, __entry->info_val2)
-+);
-+
-+#define DEFINE_MALI_CSF_KCPU_EVENT(name) \
-+ DEFINE_EVENT(mali_csf_kcpu_queue_template, mali_##name, \
-+ TP_PROTO(struct kbase_kcpu_command_queue *queue, \
-+ u64 info_val1, u64 info_val2), \
-+ TP_ARGS(queue, info_val1, info_val2))
-+
-+DEFINE_MALI_CSF_KCPU_EVENT(KCPU_QUEUE_NEW);
-+DEFINE_MALI_CSF_KCPU_EVENT(KCPU_QUEUE_DESTROY);
-+DEFINE_MALI_CSF_KCPU_EVENT(CQS_SET);
-+DEFINE_MALI_CSF_KCPU_EVENT(CQS_WAIT_START);
-+DEFINE_MALI_CSF_KCPU_EVENT(CQS_WAIT_END);
-+DEFINE_MALI_CSF_KCPU_EVENT(FENCE_SIGNAL);
-+DEFINE_MALI_CSF_KCPU_EVENT(FENCE_WAIT_START);
-+DEFINE_MALI_CSF_KCPU_EVENT(FENCE_WAIT_END);
-+
-+#undef DEFINE_MALI_CSF_KCPU_EVENT
-+
-+#endif /* !defined(_KBASE_DEBUG_LINUX_KTRACE_CSF_H_) || defined(TRACE_HEADER_MULTI_READ) */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_linux_ktrace_jm.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_linux_ktrace_jm.h
-index d964e5a..2e88e69 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_linux_ktrace_jm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/backend/mali_kbase_debug_linux_ktrace_jm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014,2018,2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -29,23 +28,28 @@
- #define _KBASE_DEBUG_LINUX_KTRACE_JM_H_
-
- DECLARE_EVENT_CLASS(mali_jm_slot_template,
-- TP_PROTO(int jobslot, u64 info_val),
-- TP_ARGS(jobslot, info_val),
-+ TP_PROTO(struct kbase_context *kctx, int jobslot, u64 info_val),
-+ TP_ARGS(kctx, jobslot, info_val),
- TP_STRUCT__entry(
-+ __field(pid_t, kctx_tgid)
-+ __field(u32, kctx_id)
- __field(unsigned int, jobslot)
- __field(u64, info_val)
- ),
- TP_fast_assign(
-+ __entry->kctx_id = (kctx) ? kctx->id : 0u;
-+ __entry->kctx_tgid = (kctx) ? kctx->tgid : 0;
- __entry->jobslot = jobslot;
- __entry->info_val = info_val;
- ),
-- TP_printk("jobslot=%u info=0x%llx", __entry->jobslot, __entry->info_val)
-+ TP_printk("kctx=%d_%u jobslot=%u info=0x%llx", __entry->kctx_tgid,
-+ __entry->kctx_id, __entry->jobslot, __entry->info_val)
- );
-
- #define DEFINE_MALI_JM_SLOT_EVENT(name) \
- DEFINE_EVENT(mali_jm_slot_template, mali_##name, \
-- TP_PROTO(int jobslot, u64 info_val), \
-- TP_ARGS(jobslot, info_val))
-+ TP_PROTO(struct kbase_context *kctx, int jobslot, u64 info_val), \
-+ TP_ARGS(kctx, jobslot, info_val))
- DEFINE_MALI_JM_SLOT_EVENT(JM_SUBMIT);
- DEFINE_MALI_JM_SLOT_EVENT(JM_JOB_DONE);
- DEFINE_MALI_JM_SLOT_EVENT(JM_UPDATE_HEAD);
-@@ -75,23 +79,28 @@ DEFINE_MALI_JM_SLOT_EVENT(JS_POLICY_DEQUEUE_JOB_IRQ);
- #undef DEFINE_MALI_JM_SLOT_EVENT
-
- DECLARE_EVENT_CLASS(mali_jm_refcount_template,
-- TP_PROTO(int refcount, u64 info_val),
-- TP_ARGS(refcount, info_val),
-+ TP_PROTO(struct kbase_context *kctx, int refcount, u64 info_val),
-+ TP_ARGS(kctx, refcount, info_val),
- TP_STRUCT__entry(
-+ __field(pid_t, kctx_tgid)
-+ __field(u32, kctx_id)
- __field(unsigned int, refcount)
- __field(u64, info_val)
- ),
- TP_fast_assign(
-+ __entry->kctx_id = (kctx) ? kctx->id : 0u;
-+ __entry->kctx_tgid = (kctx) ? kctx->tgid : 0;
- __entry->refcount = refcount;
- __entry->info_val = info_val;
- ),
-- TP_printk("refcount=%u info=0x%llx", __entry->refcount, __entry->info_val)
-+ TP_printk("kctx=%d_%u refcount=%u info=0x%llx", __entry->kctx_tgid,
-+ __entry->kctx_id, __entry->refcount, __entry->info_val)
- );
-
- #define DEFINE_MALI_JM_REFCOUNT_EVENT(name) \
- DEFINE_EVENT(mali_jm_refcount_template, mali_##name, \
-- TP_PROTO(int refcount, u64 info_val), \
-- TP_ARGS(refcount, info_val))
-+ TP_PROTO(struct kbase_context *kctx, int refcount, u64 info_val), \
-+ TP_ARGS(kctx, refcount, info_val))
- DEFINE_MALI_JM_REFCOUNT_EVENT(JS_ADD_JOB);
- DEFINE_MALI_JM_REFCOUNT_EVENT(JS_REMOVE_JOB);
- DEFINE_MALI_JM_REFCOUNT_EVENT(JS_TRY_SCHEDULE_HEAD_CTX);
-@@ -106,23 +115,28 @@ DEFINE_MALI_JM_REFCOUNT_EVENT(JS_POLICY_FOREACH_CTX_JOBS);
- #undef DEFINE_MALI_JM_REFCOUNT_EVENT
-
- DECLARE_EVENT_CLASS(mali_jm_add_template,
-- TP_PROTO(u64 gpu_addr, u64 info_val),
-- TP_ARGS(gpu_addr, info_val),
-+ TP_PROTO(struct kbase_context *kctx, u64 gpu_addr, u64 info_val),
-+ TP_ARGS(kctx, gpu_addr, info_val),
- TP_STRUCT__entry(
-+ __field(pid_t, kctx_tgid)
-+ __field(u32, kctx_id)
- __field(u64, gpu_addr)
- __field(u64, info_val)
- ),
- TP_fast_assign(
-+ __entry->kctx_id = (kctx) ? kctx->id : 0u;
-+ __entry->kctx_tgid = (kctx) ? kctx->tgid : 0;
- __entry->gpu_addr = gpu_addr;
- __entry->info_val = info_val;
- ),
-- TP_printk("gpu_addr=0x%llx info=0x%llx", __entry->gpu_addr, __entry->info_val)
-+ TP_printk("kctx=%d_%u gpu_addr=0x%llx info=0x%llx", __entry->kctx_tgid,
-+ __entry->kctx_id, __entry->gpu_addr, __entry->info_val)
- );
-
- #define DEFINE_MALI_JM_ADD_EVENT(name) \
- DEFINE_EVENT(mali_jm_add_template, mali_##name, \
-- TP_PROTO(u64 gpu_addr, u64 info_val), \
-- TP_ARGS(gpu_addr, info_val))
-+ TP_PROTO(struct kbase_context *kctx, u64 gpu_addr, u64 info_val), \
-+ TP_ARGS(kctx, gpu_addr, info_val))
- DEFINE_MALI_JM_ADD_EVENT(JD_DONE_WORKER);
- DEFINE_MALI_JM_ADD_EVENT(JD_DONE_WORKER_END);
- DEFINE_MALI_JM_ADD_EVENT(JD_CANCEL_WORKER);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace.c b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace.c
-index 6322abb..9bf8610 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,9 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-+
- #include <mali_kbase.h>
- #include "debug/mali_kbase_debug_ktrace_internal.h"
-
-@@ -27,11 +27,6 @@ int kbase_ktrace_init(struct kbase_device *kbdev)
- #if KBASE_KTRACE_TARGET_RBUF
- struct kbase_ktrace_msg *rbuf;
-
-- /* See also documentation of enum kbase_ktrace_code */
-- compiletime_assert(sizeof(kbase_ktrace_code_t) == sizeof(unsigned long long) ||
-- KBASE_KTRACE_CODE_COUNT <= (1ull << (sizeof(kbase_ktrace_code_t) * BITS_PER_BYTE)),
-- "kbase_ktrace_code_t not wide enough for KBASE_KTRACE_CODE_COUNT");
--
- rbuf = kmalloc_array(KBASE_KTRACE_SIZE, sizeof(*rbuf), GFP_KERNEL);
-
- if (!rbuf)
-@@ -91,15 +86,25 @@ static void kbasep_ktrace_format_msg(struct kbase_ktrace_msg *trace_msg,
-
- /* Initial part of message:
- *
-- * secs,thread_id,cpu,code,kctx,
-+ * secs,thread_id,cpu,code,
- */
- written += MAX(snprintf(buffer + written, MAX(sz - written, 0),
-- "%d.%.6d,%d,%d,%s,%p,",
-+ "%d.%.6d,%d,%d,%s,",
- (int)trace_msg->timestamp.tv_sec,
- (int)(trace_msg->timestamp.tv_nsec / 1000),
- trace_msg->thread_id, trace_msg->cpu,
-- kbasep_ktrace_code_string[trace_msg->backend.code],
-- trace_msg->kctx), 0);
-+ kbasep_ktrace_code_string[trace_msg->backend.gpu.code]),
-+ 0);
-+
-+ /* kctx part: */
-+ if (trace_msg->kctx_tgid) {
-+ written += MAX(snprintf(buffer + written, MAX(sz - written, 0),
-+ "%d_%u",
-+ trace_msg->kctx_tgid, trace_msg->kctx_id), 0);
-+ }
-+ /* Trailing comma */
-+ written += MAX(snprintf(buffer + written, MAX(sz - written, 0),
-+ ","), 0);
-
- /* Backend parts */
- kbasep_ktrace_backend_format_msg(trace_msg, buffer, sz,
-@@ -156,11 +161,19 @@ void kbasep_ktrace_msg_init(struct kbase_ktrace *ktrace,
-
- ktime_get_real_ts64(&trace_msg->timestamp);
-
-- trace_msg->kctx = kctx;
--
-+ /* No need to store a flag about whether there was a kctx, tgid==0 is
-+ * sufficient
-+ */
-+ if (kctx) {
-+ trace_msg->kctx_tgid = kctx->tgid;
-+ trace_msg->kctx_id = kctx->id;
-+ } else {
-+ trace_msg->kctx_tgid = 0;
-+ trace_msg->kctx_id = 0;
-+ }
- trace_msg->info_val = info_val;
-- trace_msg->backend.code = code;
-- trace_msg->backend.flags = flags;
-+ trace_msg->backend.gpu.code = code;
-+ trace_msg->backend.gpu.flags = flags;
- }
-
- void kbasep_ktrace_add(struct kbase_device *kbdev, enum kbase_ktrace_code code,
-@@ -170,12 +183,14 @@ void kbasep_ktrace_add(struct kbase_device *kbdev, enum kbase_ktrace_code code,
- unsigned long irqflags;
- struct kbase_ktrace_msg *trace_msg;
-
-+ WARN_ON((flags & ~KBASE_KTRACE_FLAG_COMMON_ALL));
-+
- spin_lock_irqsave(&kbdev->ktrace.lock, irqflags);
-
- /* Reserve and update indices */
- trace_msg = kbasep_ktrace_reserve(&kbdev->ktrace);
-
-- /* Fill the common part of the message (including backend.flags) */
-+ /* Fill the common part of the message (including backend.gpu.flags) */
- kbasep_ktrace_msg_init(&kbdev->ktrace, trace_msg, code, kctx, flags,
- info_val);
-
-@@ -225,7 +240,7 @@ void kbasep_ktrace_dump(struct kbase_device *kbdev)
- spin_unlock_irqrestore(&kbdev->ktrace.lock, flags);
- }
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- struct trace_seq_state {
- struct kbase_ktrace_msg trace_buf[KBASE_KTRACE_SIZE];
- u32 start;
-@@ -333,7 +348,7 @@ void kbase_ktrace_debugfs_init(struct kbase_device *kbdev)
-
- #else /* KBASE_KTRACE_TARGET_RBUF */
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- void kbase_ktrace_debugfs_init(struct kbase_device *kbdev)
- {
- CSTD_UNUSED(kbdev);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace.h
-index 0dd8b7a..f943696 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -37,7 +36,15 @@
- #ifndef _KBASE_DEBUG_KTRACE_H_
- #define _KBASE_DEBUG_KTRACE_H_
-
-+#if KBASE_KTRACE_TARGET_FTRACE
-+#include "mali_linux_trace.h"
-+#endif
-+
-+#if MALI_USE_CSF
-+#include "debug/backend/mali_kbase_debug_ktrace_csf.h"
-+#else
- #include "debug/backend/mali_kbase_debug_ktrace_jm.h"
-+#endif
-
- /**
- * kbase_ktrace_init - initialize kbase ktrace.
-@@ -58,7 +65,7 @@ void kbase_ktrace_term(struct kbase_device *kbdev);
- */
- void kbase_ktrace_hook_wrapper(void *param);
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- /**
- * kbase_ktrace_debugfs_init - initialize kbase ktrace for debugfs usage, if
- * the selected targets support it.
-@@ -140,10 +147,9 @@ void kbasep_ktrace_dump(struct kbase_device *kbdev);
- * KTrace target for Linux's ftrace
- */
- #if KBASE_KTRACE_TARGET_FTRACE
--#include "mali_linux_trace.h"
-
- #define KBASE_KTRACE_FTRACE_ADD(kbdev, code, kctx, info_val) \
-- trace_mali_##code(info_val)
-+ trace_mali_##code(kctx, info_val)
-
- #else /* KBASE_KTRACE_TARGET_FTRACE */
- #define KBASE_KTRACE_FTRACE_ADD(kbdev, code, kctx, info_val) \
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_codes.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_codes.h
-index 364ed60..3309834 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_codes.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_codes.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2015,2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2015, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -30,6 +29,9 @@
- * The purpose of this header file is just to contain a list of trace code
- * identifiers
- *
-+ * When updating this file, also remember to update
-+ * mali_kbase_debug_linux_ktrace.h
-+ *
- * Each identifier is wrapped in a macro, so that its string form and enum form
- * can be created
- *
-@@ -112,6 +114,7 @@ int dummy_array[] = {
- KBASE_KTRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_DESIRED_TILER),
- KBASE_KTRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_AVAILABLE),
- KBASE_KTRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_AVAILABLE_TILER),
-+ KBASE_KTRACE_CODE_MAKE_CODE(PM_CORES_CHANGE_AVAILABLE_L2),
- KBASE_KTRACE_CODE_MAKE_CODE(PM_CORES_AVAILABLE),
- KBASE_KTRACE_CODE_MAKE_CODE(PM_CORES_AVAILABLE_TILER),
- KBASE_KTRACE_CODE_MAKE_CODE(PM_DESIRED_REACHED),
-@@ -142,9 +145,20 @@ int dummy_array[] = {
- KBASE_KTRACE_CODE_MAKE_CODE(SCHED_RETAIN_CTX_NOLOCK),
- /* info_val == kctx->refcount */
- KBASE_KTRACE_CODE_MAKE_CODE(SCHED_RELEASE_CTX),
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ /*
-+ * Arbitration events
-+ */
-+ KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_LOST),
-+ KBASE_KTRACE_CODE_MAKE_CODE(ARB_VM_STATE),
-+ KBASE_KTRACE_CODE_MAKE_CODE(ARB_VM_EVT),
-+#endif
-
--
-+#if MALI_USE_CSF
-+#include "debug/backend/mali_kbase_debug_ktrace_codes_csf.h"
-+#else
- #include "debug/backend/mali_kbase_debug_ktrace_codes_jm.h"
-+#endif
- /*
- * Unused code just to make it easier to not have a comma at the end.
- * All other codes MUST come before this
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_defs.h
-index d6baaf1..4694b78 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_defs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_DEBUG_KTRACE_DEFS_H_
-@@ -58,6 +57,16 @@
- #define KBASE_KTRACE_TARGET_RBUF 0
- #endif /* KBASE_KTRACE_ENABLE */
-
-+/*
-+ * Note: Some backends define flags in this type even if the RBUF target is
-+ * disabled (they get discarded with CSTD_UNUSED(), but they're still
-+ * referenced)
-+ */
-+typedef u8 kbase_ktrace_flag_t;
-+
-+#if KBASE_KTRACE_TARGET_RBUF
-+typedef u8 kbase_ktrace_code_t;
-+
- /*
- * NOTE: KBASE_KTRACE_VERSION_MAJOR, KBASE_KTRACE_VERSION_MINOR are kept in
- * the backend, since updates can be made to one backend in a way that doesn't
-@@ -67,20 +76,28 @@
- * updated.
- */
-
--#if KBASE_KTRACE_TARGET_RBUF
--typedef u8 kbase_ktrace_flag_t;
--typedef u8 kbase_ktrace_code_t;
--
- /*
-- * struct kbase_ktrace_backend - backend specific part of a trace message
-- *
-- * At the very least, this must contain a kbase_ktrace_code_t 'code' member and
-- * a kbase_ktrace_flag_t 'flags' member
-+ * union kbase_ktrace_backend - backend specific part of a trace message.
-+ * At the very least, this must contain a kbase_ktrace_code_t 'code' member
-+ * and a kbase_ktrace_flag_t 'flags' inside a "gpu" sub-struct. Should a
-+ * backend need several sub structs in its union to optimize the data storage
-+ * for different message types, then it can use a "common initial sequence" to
-+ * allow 'flags' and 'code' to pack optimally without corrupting them.
-+ * Different backends need not share common initial sequences between them, they
-+ * only need to ensure they have gpu.flags and gpu.code members, it
-+ * is up to the backend then how to order these.
- */
--struct kbase_ktrace_backend;
-+union kbase_ktrace_backend;
-+
-+#endif /* KBASE_KTRACE_TARGET_RBUF */
-
-+#if MALI_USE_CSF
-+#include "debug/backend/mali_kbase_debug_ktrace_defs_csf.h"
-+#else
- #include "debug/backend/mali_kbase_debug_ktrace_defs_jm.h"
-+#endif
-
-+#if KBASE_KTRACE_TARGET_RBUF
- /* Indicates if the trace message has backend related info.
- *
- * If not set, consider the &kbase_ktrace_backend part of a &kbase_ktrace_msg
-@@ -90,7 +107,14 @@ struct kbase_ktrace_backend;
- */
- #define KBASE_KTRACE_FLAG_BACKEND (((kbase_ktrace_flag_t)1) << 7)
-
--#define KBASE_KTRACE_SHIFT 8 /* 256 entries */
-+/* Collect all the common flags together for debug checking */
-+#define KBASE_KTRACE_FLAG_COMMON_ALL \
-+ (KBASE_KTRACE_FLAG_BACKEND)
-+
-+#define KBASE_KTRACE_FLAG_ALL \
-+ (KBASE_KTRACE_FLAG_COMMON_ALL | KBASE_KTRACE_FLAG_BACKEND_ALL)
-+
-+#define KBASE_KTRACE_SHIFT (9) /* 512 entries */
- #define KBASE_KTRACE_SIZE (1 << KBASE_KTRACE_SHIFT)
- #define KBASE_KTRACE_MASK ((1 << KBASE_KTRACE_SHIFT)-1)
-
-@@ -121,24 +145,23 @@ enum kbase_ktrace_code {
- * added.
- * @cpu: indicates which CPU the @thread_id was scheduled on when the
- * trace message was added.
-- * @kctx: Pointer to the kbase context for which the trace message was
-- * added. Will be NULL for certain trace messages associated with
-- * the &kbase_device itself, such as power management events.
-- * Will point to the appropriate context corresponding to
-- * backend-specific events.
-+ * @kctx_tgid: Thread group ID of the &kbase_context associated with the
-+ * message, or 0 if none associated.
-+ * @kctx_id: Unique identifier of the &kbase_context associated with the
-+ * message. Only valid if @kctx_tgid != 0.
- * @info_val: value specific to the type of event being traced. Refer to the
-- * specific code in enum kbase_ktrace_code
-+ * specific code in enum kbase_ktrace_code.
- * @backend: backend-specific trace information. All backends must implement
-- * a minimum common set of members
-+ * a minimum common set of members.
- */
- struct kbase_ktrace_msg {
- struct timespec64 timestamp;
- u32 thread_id;
- u32 cpu;
-- void *kctx;
-+ pid_t kctx_tgid;
-+ u32 kctx_id;
- u64 info_val;
--
-- struct kbase_ktrace_backend backend;
-+ union kbase_ktrace_backend backend;
- };
-
- struct kbase_ktrace {
-@@ -148,5 +171,17 @@ struct kbase_ktrace {
- struct kbase_ktrace_msg *rbuf;
- };
-
-+
-+static inline void kbase_ktrace_compiletime_asserts(void)
-+{
-+ /* See also documentation of enum kbase_ktrace_code */
-+ compiletime_assert(sizeof(kbase_ktrace_code_t) == sizeof(unsigned long long) ||
-+ KBASE_KTRACE_CODE_COUNT <= (1ull << (sizeof(kbase_ktrace_code_t) * BITS_PER_BYTE)),
-+ "kbase_ktrace_code_t not wide enough for KBASE_KTRACE_CODE_COUNT");
-+ compiletime_assert((KBASE_KTRACE_FLAG_BACKEND_ALL & KBASE_KTRACE_FLAG_COMMON_ALL) == 0,
-+ "KTrace backend flags intersect with KTrace common flags");
-+
-+}
-+
- #endif /* KBASE_KTRACE_TARGET_RBUF */
- #endif /* _KBASE_DEBUG_KTRACE_DEFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_internal.h
-index e450760..d9bd351 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_internal.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_ktrace_internal.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_DEBUG_KTRACE_INTERNAL_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_linux_ktrace.h b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_linux_ktrace.h
-index 18e4f7c..b56dec4 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_linux_ktrace.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/debug/mali_kbase_debug_linux_ktrace.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014,2018,2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -31,21 +30,29 @@
- #if KBASE_KTRACE_TARGET_FTRACE
-
- DECLARE_EVENT_CLASS(mali_add_template,
-- TP_PROTO(u64 info_val),
-- TP_ARGS(info_val),
-+ TP_PROTO(struct kbase_context *kctx, u64 info_val),
-+ TP_ARGS(kctx, info_val),
- TP_STRUCT__entry(
-+ __field(pid_t, kctx_tgid)
-+ __field(u32, kctx_id)
- __field(u64, info_val)
- ),
- TP_fast_assign(
-+ __entry->kctx_id = (kctx) ? kctx->id : 0u;
-+ __entry->kctx_tgid = (kctx) ? kctx->tgid : 0;
- __entry->info_val = info_val;
- ),
-- TP_printk("info=0x%llx", __entry->info_val)
-+ TP_printk("kctx=%d_%u info=0x%llx", __entry->kctx_tgid,
-+ __entry->kctx_id, __entry->info_val)
- );
-
-+/* DEFINE_MALI_ADD_EVENT is available also to backends for backend-specific
-+ * simple trace codes
-+ */
- #define DEFINE_MALI_ADD_EVENT(name) \
- DEFINE_EVENT(mali_add_template, mali_##name, \
-- TP_PROTO(u64 info_val), \
-- TP_ARGS(info_val))
-+ TP_PROTO(struct kbase_context *kctx, u64 info_val), \
-+ TP_ARGS(kctx, info_val))
- DEFINE_MALI_ADD_EVENT(CORE_CTX_DESTROY);
- DEFINE_MALI_ADD_EVENT(CORE_CTX_HWINSTR_TERM);
- DEFINE_MALI_ADD_EVENT(CORE_GPU_IRQ);
-@@ -78,6 +85,7 @@ DEFINE_MALI_ADD_EVENT(PM_CORES_AVAILABLE);
- DEFINE_MALI_ADD_EVENT(PM_CORES_AVAILABLE_TILER);
- DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_AVAILABLE);
- DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_AVAILABLE_TILER);
-+DEFINE_MALI_ADD_EVENT(PM_CORES_CHANGE_AVAILABLE_L2);
- DEFINE_MALI_ADD_EVENT(PM_GPU_ON);
- DEFINE_MALI_ADD_EVENT(PM_GPU_OFF);
- DEFINE_MALI_ADD_EVENT(PM_SET_POLICY);
-@@ -89,10 +97,20 @@ DEFINE_MALI_ADD_EVENT(PM_CONTEXT_IDLE);
- DEFINE_MALI_ADD_EVENT(PM_WAKE_WAITERS);
- DEFINE_MALI_ADD_EVENT(SCHED_RETAIN_CTX_NOLOCK);
- DEFINE_MALI_ADD_EVENT(SCHED_RELEASE_CTX);
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-
--#undef DEFINE_MALI_ADD_EVENT
-+DEFINE_MALI_ADD_EVENT(ARB_GPU_LOST);
-+DEFINE_MALI_ADD_EVENT(ARB_VM_STATE);
-+DEFINE_MALI_ADD_EVENT(ARB_VM_EVT);
-
--#include "mali_kbase_debug_linux_ktrace_jm.h"
-+#endif
-+#if MALI_USE_CSF
-+#include "backend/mali_kbase_debug_linux_ktrace_csf.h"
-+#else
-+#include "backend/mali_kbase_debug_linux_ktrace_jm.h"
-+#endif
-+
-+#undef DEFINE_MALI_ADD_EVENT
-
- #endif /* KBASE_KTRACE_TARGET_FTRACE */
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Makefile b/dvalin/kernel/drivers/gpu/arm/midgard/device/Kbuild
-similarity index 56%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Makefile
-rename to dvalin/kernel/drivers/gpu/arm/midgard/device/Kbuild
-index d848e87..90e7024 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Makefile
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/device/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,21 +16,18 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
--#
--
--# linux build system bootstrap for out-of-tree module
-
--# default to building for the host
--ARCH ?= $(shell uname -m)
-+mali_kbase-y += \
-+ device/mali_kbase_device.o \
-+ device/mali_kbase_device_hw.o
-
--ifeq ($(KDIR),)
--$(error Must specify KDIR to point to the kernel to target))
-+ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
-+ mali_kbase-y += \
-+ device/backend/mali_kbase_device_csf.o \
-+ device/backend/mali_kbase_device_hw_csf.o
-+else
-+ mali_kbase-y += \
-+ device/backend/mali_kbase_device_jm.o \
-+ device/backend/mali_kbase_device_hw_jm.o
- endif
--
--all:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) $(SCONS_CONFIGS) EXTRA_CFLAGS=-I$(CURDIR)/../include modules
--
--clean:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_csf.c
-new file mode 100644
-index 0000000..0c5052b
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_csf.c
-@@ -0,0 +1,464 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <device/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
-+
-+#include <mali_kbase_hwaccess_backend.h>
-+#include <mali_kbase_hwcnt_backend_csf_if_fw.h>
-+#include <mali_kbase_ctx_sched.h>
-+#include <mali_kbase_reset_gpu.h>
-+#include <csf/mali_kbase_csf.h>
-+#include <csf/ipa_control/mali_kbase_csf_ipa_control.h>
-+
-+
-+#include <mali_kbase.h>
-+#include <backend/gpu/mali_kbase_irq_internal.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+#include <backend/gpu/mali_kbase_js_internal.h>
-+#include <backend/gpu/mali_kbase_clk_rate_trace_mgr.h>
-+#include <csf/mali_kbase_csf_csg_debugfs.h>
-+#include <mali_kbase_hwcnt_virtualizer.h>
-+#include <mali_kbase_vinstr.h>
-+
-+/**
-+ * kbase_device_firmware_hwcnt_term - Terminate CSF firmware and HWC
-+ *
-+ * @kbdev: An instance of the GPU platform device, allocated from the probe
-+ * method of the driver.
-+ *
-+ * When a kbase driver is removed, terminate CSF firmware and hardware counter
-+ * components.
-+ */
-+static void kbase_device_firmware_hwcnt_term(struct kbase_device *kbdev)
-+{
-+ if (kbdev->csf.firmware_inited) {
-+ kbase_vinstr_term(kbdev->vinstr_ctx);
-+ kbase_hwcnt_virtualizer_term(kbdev->hwcnt_gpu_virt);
-+ kbase_hwcnt_backend_csf_metadata_term(&kbdev->hwcnt_gpu_iface);
-+ kbase_csf_firmware_term(kbdev);
-+ }
-+}
-+
-+/**
-+ * kbase_backend_late_init - Perform any backend-specific initialization.
-+ * @kbdev: Device pointer
-+ *
-+ * Return: 0 on success, or an error code on failure.
-+ */
-+static int kbase_backend_late_init(struct kbase_device *kbdev)
-+{
-+ int err;
-+
-+ err = kbase_hwaccess_pm_init(kbdev);
-+ if (err)
-+ return err;
-+
-+ err = kbase_reset_gpu_init(kbdev);
-+ if (err)
-+ goto fail_reset_gpu_init;
-+
-+ err = kbase_hwaccess_pm_powerup(kbdev, PM_HW_ISSUES_DETECT);
-+ if (err)
-+ goto fail_pm_powerup;
-+
-+ err = kbase_backend_timer_init(kbdev);
-+ if (err)
-+ goto fail_timer;
-+
-+#ifdef CONFIG_MALI_DEBUG
-+#ifndef CONFIG_MALI_NO_MALI
-+ if (kbasep_common_test_interrupt_handlers(kbdev) != 0) {
-+ dev_err(kbdev->dev, "Interrupt assignment check failed.\n");
-+ err = -EINVAL;
-+ goto fail_interrupt_test;
-+ }
-+#endif /* !CONFIG_MALI_NO_MALI */
-+#endif /* CONFIG_MALI_DEBUG */
-+
-+ kbase_ipa_control_init(kbdev);
-+
-+ /* Initialise the metrics subsystem, it couldn't be initialized earlier
-+ * due to dependency on kbase_ipa_control.
-+ */
-+ err = kbasep_pm_metrics_init(kbdev);
-+ if (err)
-+ goto fail_pm_metrics_init;
-+
-+ /* Do the initialisation of devfreq.
-+ * Devfreq needs backend_timer_init() for completion of its
-+ * initialisation and it also needs to catch the first callback
-+ * occurrence of the runtime_suspend event for maintaining state
-+ * coherence with the backend power management, hence needs to be
-+ * placed before the kbase_pm_context_idle().
-+ */
-+ err = kbase_backend_devfreq_init(kbdev);
-+ if (err)
-+ goto fail_devfreq_init;
-+
-+ /* Update gpuprops with L2_FEATURES if applicable */
-+ err = kbase_gpuprops_update_l2_features(kbdev);
-+ if (err)
-+ goto fail_update_l2_features;
-+
-+ init_waitqueue_head(&kbdev->hwaccess.backend.reset_wait);
-+
-+ kbase_pm_context_idle(kbdev);
-+
-+ mutex_init(&kbdev->fw_load_lock);
-+
-+ return 0;
-+
-+fail_update_l2_features:
-+ kbase_backend_devfreq_term(kbdev);
-+fail_devfreq_init:
-+ kbasep_pm_metrics_term(kbdev);
-+fail_pm_metrics_init:
-+ kbase_ipa_control_term(kbdev);
-+
-+#ifdef CONFIG_MALI_DEBUG
-+#ifndef CONFIG_MALI_NO_MALI
-+fail_interrupt_test:
-+#endif /* !CONFIG_MALI_NO_MALI */
-+#endif /* CONFIG_MALI_DEBUG */
-+
-+ kbase_backend_timer_term(kbdev);
-+fail_timer:
-+ kbase_pm_context_idle(kbdev);
-+ kbase_hwaccess_pm_halt(kbdev);
-+fail_pm_powerup:
-+ kbase_reset_gpu_term(kbdev);
-+fail_reset_gpu_init:
-+ kbase_hwaccess_pm_term(kbdev);
-+
-+ return err;
-+}
-+
-+/**
-+ * kbase_backend_late_term - Perform any backend-specific termination.
-+ * @kbdev: Device pointer
-+ */
-+static void kbase_backend_late_term(struct kbase_device *kbdev)
-+{
-+ kbase_backend_devfreq_term(kbdev);
-+ kbasep_pm_metrics_term(kbdev);
-+ kbase_ipa_control_term(kbdev);
-+ kbase_hwaccess_pm_halt(kbdev);
-+ kbase_reset_gpu_term(kbdev);
-+ kbase_hwaccess_pm_term(kbdev);
-+}
-+
-+/**
-+ * kbase_csf_early_init - Early initialization for firmware & scheduler.
-+ * @kbdev: Device pointer
-+ *
-+ * Return: 0 on success, error code otherwise.
-+ */
-+static int kbase_csf_early_init(struct kbase_device *kbdev)
-+{
-+ int err = kbase_csf_firmware_early_init(kbdev);
-+
-+ if (err)
-+ return err;
-+
-+ err = kbase_csf_scheduler_early_init(kbdev);
-+
-+ return err;
-+}
-+
-+/**
-+ * kbase_csf_early_init - Early termination for firmware & scheduler.
-+ * @kbdev: Device pointer
-+ */
-+static void kbase_csf_early_term(struct kbase_device *kbdev)
-+{
-+ kbase_csf_scheduler_early_term(kbdev);
-+}
-+
-+/**
-+ * kbase_device_hwcnt_backend_csf_if_init - Create hardware counter backend
-+ * firmware interface.
-+ * @kbdev: Device pointer
-+ */
-+static int kbase_device_hwcnt_backend_csf_if_init(struct kbase_device *kbdev)
-+{
-+ return kbase_hwcnt_backend_csf_if_fw_create(
-+ kbdev, &kbdev->hwcnt_backend_csf_if_fw);
-+}
-+
-+/**
-+ * kbase_device_hwcnt_backend_csf_if_term - Terminate hardware counter backend
-+ * firmware interface.
-+ * @kbdev: Device pointer
-+ */
-+static void kbase_device_hwcnt_backend_csf_if_term(struct kbase_device *kbdev)
-+{
-+ kbase_hwcnt_backend_csf_if_fw_destroy(&kbdev->hwcnt_backend_csf_if_fw);
-+}
-+
-+/**
-+ * kbase_device_hwcnt_backend_csf_init - Create hardware counter backend.
-+ * @kbdev: Device pointer
-+ */
-+
-+static int kbase_device_hwcnt_backend_csf_init(struct kbase_device *kbdev)
-+{
-+ return kbase_hwcnt_backend_csf_create(
-+ &kbdev->hwcnt_backend_csf_if_fw,
-+ KBASE_HWCNT_BACKEND_CSF_RING_BUFFER_COUNT,
-+ &kbdev->hwcnt_gpu_iface);
-+}
-+
-+/**
-+ * kbase_device_hwcnt_backend_csf_term - Terminate hardware counter backend.
-+ * @kbdev: Device pointer
-+ */
-+static void kbase_device_hwcnt_backend_csf_term(struct kbase_device *kbdev)
-+{
-+ kbase_hwcnt_backend_csf_destroy(&kbdev->hwcnt_gpu_iface);
-+}
-+
-+static const struct kbase_device_init dev_init[] = {
-+ { assign_irqs, NULL, "IRQ search failed" },
-+ { registers_map, registers_unmap, "Register map failed" },
-+ { power_control_init, power_control_term,
-+ "Power control initialization failed" },
-+ { kbase_device_io_history_init, kbase_device_io_history_term,
-+ "Register access history initialization failed" },
-+ { kbase_device_early_init, kbase_device_early_term,
-+ "Early device initialization failed" },
-+ { kbase_device_populate_max_freq, NULL,
-+ "Populating max frequency failed" },
-+ { kbase_device_misc_init, kbase_device_misc_term,
-+ "Miscellaneous device initialization failed" },
-+ { kbase_device_pcm_dev_init, kbase_device_pcm_dev_term,
-+ "Priority control manager initialization failed" },
-+ { kbase_ctx_sched_init, kbase_ctx_sched_term,
-+ "Context scheduler initialization failed" },
-+ { kbase_mem_init, kbase_mem_term,
-+ "Memory subsystem initialization failed" },
-+ { kbase_csf_protected_memory_init, kbase_csf_protected_memory_term,
-+ "Protected memory allocator initialization failed" },
-+ { kbase_device_coherency_init, NULL, "Device coherency init failed" },
-+ { kbase_protected_mode_init, kbase_protected_mode_term,
-+ "Protected mode subsystem initialization failed" },
-+ { kbase_device_list_init, kbase_device_list_term,
-+ "Device list setup failed" },
-+ { kbase_device_timeline_init, kbase_device_timeline_term,
-+ "Timeline stream initialization failed" },
-+ { kbase_clk_rate_trace_manager_init, kbase_clk_rate_trace_manager_term,
-+ "Clock rate trace manager initialization failed" },
-+ { kbase_device_hwcnt_backend_csf_if_init,
-+ kbase_device_hwcnt_backend_csf_if_term,
-+ "GPU hwcnt backend CSF interface creation failed" },
-+ { kbase_device_hwcnt_backend_csf_init,
-+ kbase_device_hwcnt_backend_csf_term,
-+ "GPU hwcnt backend creation failed" },
-+ { kbase_device_hwcnt_context_init, kbase_device_hwcnt_context_term,
-+ "GPU hwcnt context initialization failed" },
-+ { kbase_backend_late_init, kbase_backend_late_term,
-+ "Late backend initialization failed" },
-+ { kbase_csf_early_init, kbase_csf_early_term,
-+ "Early CSF initialization failed" },
-+ { NULL, kbase_device_firmware_hwcnt_term, NULL },
-+#ifdef MALI_KBASE_BUILD
-+ { kbase_device_debugfs_init, kbase_device_debugfs_term,
-+ "DebugFS initialization failed" },
-+ /* Sysfs init needs to happen before registering the device with
-+ * misc_register(), otherwise it causes a race condition between
-+ * registering the device and a uevent event being generated for
-+ * userspace, causing udev rules to run which might expect certain
-+ * sysfs attributes present. As a result of the race condition
-+ * we avoid, some Mali sysfs entries may have appeared to udev
-+ * to not exist.
-+ * For more information, see
-+ * https://www.kernel.org/doc/Documentation/driver-model/device.txt, the
-+ * paragraph that starts with "Word of warning", currently the
-+ * second-last paragraph.
-+ */
-+ { kbase_sysfs_init, kbase_sysfs_term, "SysFS group creation failed" },
-+ { kbase_device_misc_register, kbase_device_misc_deregister,
-+ "Misc device registration failed" },
-+ { kbase_gpuprops_populate_user_buffer, kbase_gpuprops_free_user_buffer,
-+ "GPU property population failed" },
-+ { kbase_device_late_init, kbase_device_late_term,
-+ "Late device initialization failed" },
-+#endif
-+};
-+
-+static void kbase_device_term_partial(struct kbase_device *kbdev,
-+ unsigned int i)
-+{
-+ while (i-- > 0) {
-+ if (dev_init[i].term)
-+ dev_init[i].term(kbdev);
-+ }
-+}
-+
-+void kbase_device_term(struct kbase_device *kbdev)
-+{
-+ kbdev->csf.mali_file_inode = NULL;
-+ kbase_device_term_partial(kbdev, ARRAY_SIZE(dev_init));
-+ kbase_mem_halt(kbdev);
-+}
-+
-+int kbase_device_init(struct kbase_device *kbdev)
-+{
-+ int err = 0;
-+ unsigned int i = 0;
-+
-+ dev_info(kbdev->dev, "Kernel DDK version %s", MALI_RELEASE_NAME);
-+
-+ kbase_device_id_init(kbdev);
-+ kbase_disjoint_init(kbdev);
-+
-+ for (i = 0; i < ARRAY_SIZE(dev_init); i++) {
-+ if (dev_init[i].init) {
-+ err = dev_init[i].init(kbdev);
-+ if (err) {
-+ dev_err(kbdev->dev, "%s error = %d\n",
-+ dev_init[i].err_mes, err);
-+ kbase_device_term_partial(kbdev, i);
-+ break;
-+ }
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+/**
-+ * kbase_device_hwcnt_csf_deferred_init - Initialize CSF deferred HWC components
-+ *
-+ * @kbdev: An instance of the GPU platform device, allocated from the probe
-+ * method of the driver.
-+ *
-+ * Hardware counter components depending on firmware are initialized after CSF
-+ * firmware is loaded.
-+ *
-+ * @return 0 on success. An error code on failure.
-+ */
-+static int kbase_device_hwcnt_csf_deferred_init(struct kbase_device *kbdev)
-+{
-+ int ret = 0;
-+
-+ /* For CSF GPUs, HWC metadata needs to query information from CSF
-+ * firmware, so the initialization of HWC metadata only can be called
-+ * after firmware initialized, but firmware initialization depends on
-+ * HWC backend initialization, so we need to separate HWC backend
-+ * metadata initialization from HWC backend initialization.
-+ */
-+ ret = kbase_hwcnt_backend_csf_metadata_init(&kbdev->hwcnt_gpu_iface);
-+ if (ret) {
-+ dev_err(kbdev->dev,
-+ "GPU hwcnt backend metadata creation failed");
-+ return ret;
-+ }
-+
-+ ret = kbase_hwcnt_virtualizer_init(
-+ kbdev->hwcnt_gpu_ctx,
-+ KBASE_HWCNT_GPU_VIRTUALIZER_DUMP_THRESHOLD_NS,
-+ &kbdev->hwcnt_gpu_virt);
-+ if (ret) {
-+ dev_err(kbdev->dev,
-+ "GPU hwcnt virtualizer initialization failed");
-+ goto virt_fail;
-+ }
-+
-+ ret = kbase_vinstr_init(kbdev->hwcnt_gpu_virt, &kbdev->vinstr_ctx);
-+ if (ret) {
-+ dev_err(kbdev->dev,
-+ "Virtual instrumentation initialization failed");
-+ goto vinstr_fail;
-+ }
-+
-+ return ret;
-+
-+vinstr_fail:
-+ kbase_hwcnt_virtualizer_term(kbdev->hwcnt_gpu_virt);
-+
-+virt_fail:
-+ kbase_hwcnt_backend_csf_metadata_term(&kbdev->hwcnt_gpu_iface);
-+ return ret;
-+}
-+
-+/**
-+ * kbase_csf_firmware_deferred_init - Load and initialize CSF firmware
-+ *
-+ * @kbdev: An instance of the GPU platform device, allocated from the probe
-+ * method of the driver.
-+ *
-+ * Called when a device file is opened for the first time.
-+ * To meet Android GKI vendor guideline, firmware load is deferred at
-+ * the time when @ref kbase_open is called for the first time.
-+ *
-+ * @return 0 on success. An error code on failure.
-+ */
-+static int kbase_csf_firmware_deferred_init(struct kbase_device *kbdev)
-+{
-+ int err = 0;
-+
-+ lockdep_assert_held(&kbdev->fw_load_lock);
-+
-+ kbase_pm_context_active(kbdev);
-+
-+ err = kbase_csf_firmware_init(kbdev);
-+ if (!err) {
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->pm.backend.mcu_state = KBASE_MCU_ON;
-+ kbdev->csf.firmware_inited = true;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ } else {
-+ dev_err(kbdev->dev, "Firmware initialization failed");
-+ }
-+
-+ kbase_pm_context_idle(kbdev);
-+
-+ return err;
-+}
-+
-+int kbase_device_firmware_init_once(struct kbase_device *kbdev)
-+{
-+ int ret = 0;
-+
-+ mutex_lock(&kbdev->fw_load_lock);
-+
-+ if (!kbdev->csf.firmware_inited) {
-+ ret = kbase_csf_firmware_deferred_init(kbdev);
-+ if (ret)
-+ goto out;
-+
-+ ret = kbase_device_hwcnt_csf_deferred_init(kbdev);
-+ if (ret) {
-+ kbase_csf_firmware_term(kbdev);
-+ goto out;
-+ }
-+
-+ kbase_csf_debugfs_init(kbdev);
-+ }
-+
-+out:
-+ mutex_unlock(&kbdev->fw_load_lock);
-+
-+ return ret;
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_hw_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_hw_csf.c
-new file mode 100644
-index 0000000..3fce637
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_hw_csf.c
-@@ -0,0 +1,163 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <gpu/mali_kbase_gpu_fault.h>
-+#include <backend/gpu/mali_kbase_instr_internal.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+#include <device/mali_kbase_device.h>
-+#include <mali_kbase_reset_gpu.h>
-+#include <mmu/mali_kbase_mmu.h>
-+#include <mali_kbase_ctx_sched.h>
-+
-+/**
-+ * kbase_report_gpu_fault - Report a GPU fault of the device.
-+ *
-+ * @kbdev: Kbase device pointer
-+ * @status: Fault status
-+ * @as_nr: Faulty address space
-+ * @as_valid: true if address space is valid
-+ *
-+ * This function is called from the interrupt handler when a GPU fault occurs.
-+ */
-+static void kbase_report_gpu_fault(struct kbase_device *kbdev, u32 status,
-+ u32 as_nr, bool as_valid)
-+{
-+ u64 address = (u64) kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(GPU_FAULTADDRESS_HI)) << 32;
-+
-+ address |= kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(GPU_FAULTADDRESS_LO));
-+
-+ /* Report GPU fault for all contexts in case either
-+ * the address space is invalid or it's MCU address space.
-+ */
-+ meson_gpu_fault ++;
-+ kbase_mmu_gpu_fault_interrupt(kbdev, status, as_nr, address, as_valid);
-+}
-+
-+static void kbase_gpu_fault_interrupt(struct kbase_device *kbdev)
-+{
-+ const u32 status = kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(GPU_FAULTSTATUS));
-+ const bool as_valid = status & GPU_FAULTSTATUS_JASID_VALID_FLAG;
-+ const u32 as_nr = (status & GPU_FAULTSTATUS_JASID_MASK) >>
-+ GPU_FAULTSTATUS_JASID_SHIFT;
-+ bool bus_fault = (status & GPU_FAULTSTATUS_EXCEPTION_TYPE_MASK) ==
-+ GPU_FAULTSTATUS_EXCEPTION_TYPE_GPU_BUS_FAULT;
-+
-+ if (bus_fault) {
-+ /* If as_valid, reset gpu when ASID is for MCU. */
-+ if (!as_valid || (as_nr == MCU_AS_NR)) {
-+ kbase_report_gpu_fault(kbdev, status, as_nr, as_valid);
-+
-+ dev_err(kbdev->dev, "GPU bus fault triggering gpu-reset ...\n");
-+ if (kbase_prepare_to_reset_gpu(
-+ kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR))
-+ kbase_reset_gpu(kbdev);
-+ } else {
-+ /* Handle Bus fault */
-+ if (kbase_mmu_bus_fault_interrupt(kbdev, status, as_nr))
-+ dev_warn(kbdev->dev,
-+ "fail to handle GPU bus fault ...\n");
-+ }
-+ } else
-+ kbase_report_gpu_fault(kbdev, status, as_nr, as_valid);
-+}
-+
-+void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val)
-+{
-+ KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, val);
-+ if (val & GPU_FAULT)
-+ kbase_gpu_fault_interrupt(kbdev);
-+
-+ if (val & GPU_PROTECTED_FAULT) {
-+ struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
-+ unsigned long flags;
-+
-+ dev_err_ratelimited(kbdev->dev, "GPU fault in protected mode");
-+
-+ /* Mask the protected fault interrupt to avoid the potential
-+ * deluge of such interrupts. It will be unmasked on GPU reset.
-+ */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK),
-+ GPU_IRQ_REG_ALL & ~GPU_PROTECTED_FAULT);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ if (!WARN_ON(!kbase_csf_scheduler_protected_mode_in_use(
-+ kbdev))) {
-+ struct base_gpu_queue_group_error const
-+ err_payload = { .error_type =
-+ BASE_GPU_QUEUE_GROUP_ERROR_FATAL,
-+ .payload = {
-+ .fatal_group = {
-+ .status =
-+ GPU_EXCEPTION_TYPE_SW_FAULT_0,
-+ } } };
-+
-+ scheduler->active_protm_grp->faulted = true;
-+ kbase_csf_add_group_fatal_error(
-+ scheduler->active_protm_grp, &err_payload);
-+ kbase_event_wakeup(scheduler->active_protm_grp->kctx);
-+ }
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+
-+ if (kbase_prepare_to_reset_gpu(
-+ kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR))
-+ kbase_reset_gpu(kbdev);
-+ }
-+
-+ if (val & RESET_COMPLETED)
-+ kbase_pm_reset_done(kbdev);
-+
-+ KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, val);
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), val);
-+
-+ /* kbase_pm_check_transitions (called by kbase_pm_power_changed) 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. The same applies to kbase_clean_caches_done() - if another
-+ * clean was queued, it might trigger another clean, which might
-+ * generate another interrupt which shouldn't be missed.
-+ */
-+
-+ if (val & CLEAN_CACHES_COMPLETED)
-+ kbase_clean_caches_done(kbdev);
-+
-+ if (val & (POWER_CHANGED_ALL | MCU_STATUS_GPU_IRQ)) {
-+ kbase_pm_power_changed(kbdev);
-+ } else if (val & CLEAN_CACHES_COMPLETED) {
-+ /* If cache line evict messages can be lost when shader cores
-+ * power down then we need to flush the L2 cache before powering
-+ * down cores. When the flush completes, the shaders' state
-+ * machine needs to be re-invoked to proceed with powering down
-+ * cores.
-+ */
-+ if (kbdev->pm.backend.l2_always_on ||
-+ kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_921))
-+ kbase_pm_power_changed(kbdev);
-+ }
-+
-+ KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_DONE, NULL, val);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_hw_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_hw_jm.c
-new file mode 100644
-index 0000000..384e385
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_hw_jm.c
-@@ -0,0 +1,98 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <gpu/mali_kbase_gpu_fault.h>
-+#include <backend/gpu/mali_kbase_instr_internal.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+#include <device/mali_kbase_device.h>
-+#include <mali_kbase_reset_gpu.h>
-+#include <mmu/mali_kbase_mmu.h>
-+
-+/**
-+ * kbase_report_gpu_fault - Report a GPU fault.
-+ * @kbdev: Kbase device pointer
-+ * @multiple: Zero if only GPU_FAULT was raised, non-zero if MULTIPLE_GPU_FAULTS
-+ * was also set
-+ *
-+ * This function is called from the interrupt handler when a GPU fault occurs.
-+ * It reports the details of the fault using dev_warn().
-+ */
-+static void kbase_report_gpu_fault(struct kbase_device *kbdev, int multiple)
-+{
-+ u32 status = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS));
-+ u64 address = (u64) kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(GPU_FAULTADDRESS_HI)) << 32;
-+
-+ address |= kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(GPU_FAULTADDRESS_LO));
-+ meson_gpu_fault ++;
-+ dev_warn(kbdev->dev, "GPU Fault 0x%08x (%s) at 0x%016llx",
-+ status,
-+ kbase_gpu_exception_name(status & 0xFF),
-+ address);
-+ if (multiple)
-+ dev_warn(kbdev->dev, "There were multiple GPU faults - some have not been reported\n");
-+}
-+
-+void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val)
-+{
-+ KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, 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);
-+
-+ KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, val);
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), val);
-+
-+ /* kbase_pm_check_transitions (called by kbase_pm_power_changed) 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. The same applies to kbase_clean_caches_done() - if another
-+ * clean was queued, it might trigger another clean, which might
-+ * generate another interrupt which shouldn't be missed.
-+ */
-+
-+ if (val & CLEAN_CACHES_COMPLETED)
-+ kbase_clean_caches_done(kbdev);
-+
-+ if (val & POWER_CHANGED_ALL) {
-+ kbase_pm_power_changed(kbdev);
-+ } else if (val & CLEAN_CACHES_COMPLETED) {
-+ /* If cache line evict messages can be lost when shader cores
-+ * power down then we need to flush the L2 cache before powering
-+ * down cores. When the flush completes, the shaders' state
-+ * machine needs to be re-invoked to proceed with powering down
-+ * cores.
-+ */
-+ if (kbdev->pm.backend.l2_always_on ||
-+ kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_921))
-+ kbase_pm_power_changed(kbdev);
-+ }
-+
-+ KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_DONE, NULL, val);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_jm.c
-index fbba2e7..6a6ab60 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_jm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/device/backend/mali_kbase_device_jm.c
-@@ -1,12 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -17,21 +17,17 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#include "../mali_kbase_device_internal.h"
--#include "../mali_kbase_device.h"
-+#include <device/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
-+#include <mali_kbase_hwaccess_instr.h>
-
- #include <mali_kbase_config_defaults.h>
- #include <mali_kbase_hwaccess_backend.h>
- #include <mali_kbase_ctx_sched.h>
- #include <mali_kbase_reset_gpu.h>
-
--#ifdef CONFIG_MALI_NO_MALI
--#include <mali_kbase_model_linux.h>
--#endif
-
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- #include <arbiter/mali_kbase_arbiter_pm.h>
-@@ -43,6 +39,7 @@
- #include <backend/gpu/mali_kbase_js_internal.h>
- #include <backend/gpu/mali_kbase_pm_internal.h>
- #include <mali_kbase_dummy_job_wa.h>
-+#include <backend/gpu/mali_kbase_clk_rate_trace_mgr.h>
-
- /**
- * kbase_backend_late_init - Perform any backend-specific initialization.
-@@ -95,9 +92,6 @@ static int kbase_backend_late_init(struct kbase_device *kbdev)
- if (err)
- goto fail_devfreq_init;
-
-- /* Idle the GPU and/or cores, if the policy wants it to */
-- kbase_pm_context_idle(kbdev);
--
- /* Update gpuprops with L2_FEATURES if applicable */
- err = kbase_gpuprops_update_l2_features(kbdev);
- if (err)
-@@ -105,9 +99,15 @@ static int kbase_backend_late_init(struct kbase_device *kbdev)
-
- init_waitqueue_head(&kbdev->hwaccess.backend.reset_wait);
-
-+ /* Idle the GPU and/or cores, if the policy wants it to */
-+ kbase_pm_context_idle(kbdev);
-+
-+ mutex_init(&kbdev->fw_load_lock);
-+
- return 0;
-
- fail_update_l2_features:
-+ kbase_backend_devfreq_term(kbdev);
- fail_devfreq_init:
- kbase_job_slot_term(kbdev);
- fail_job_slot:
-@@ -120,6 +120,7 @@ fail_interrupt_test:
-
- kbase_backend_timer_term(kbdev);
- fail_timer:
-+ kbase_pm_context_idle(kbdev);
- kbase_hwaccess_pm_halt(kbdev);
- fail_pm_powerup:
- kbase_reset_gpu_term(kbdev);
-@@ -144,57 +145,65 @@ static void kbase_backend_late_term(struct kbase_device *kbdev)
- kbase_hwaccess_pm_term(kbdev);
- }
-
-+static int kbase_device_hwcnt_backend_jm_init(struct kbase_device *kbdev)
-+{
-+ return kbase_hwcnt_backend_jm_create(kbdev, &kbdev->hwcnt_gpu_iface);
-+}
-+
-+static void kbase_device_hwcnt_backend_jm_term(struct kbase_device *kbdev)
-+{
-+ kbase_hwcnt_backend_jm_destroy(&kbdev->hwcnt_gpu_iface);
-+}
-+
- static const struct kbase_device_init dev_init[] = {
--#ifdef CONFIG_MALI_NO_MALI
-- {kbase_gpu_device_create, kbase_gpu_device_destroy,
-- "Dummy model initialization failed"},
--#else
-- {assign_irqs, NULL,
-- "IRQ search failed"},
-- {registers_map, registers_unmap,
-- "Register map failed"},
--#endif
-- {kbase_device_io_history_init, kbase_device_io_history_term,
-- "Register access history initialization failed"},
-- {kbase_device_pm_init, kbase_device_pm_term,
-- "Power management initialization failed"},
-- {kbase_device_early_init, kbase_device_early_term,
-- "Early device initialization failed"},
-- {kbase_device_populate_max_freq, NULL,
-- "Populating max frequency failed"},
-- {kbase_device_misc_init, kbase_device_misc_term,
-- "Miscellaneous device initialization failed"},
-- {kbase_ctx_sched_init, kbase_ctx_sched_term,
-- "Context scheduler initialization failed"},
-- {kbase_mem_init, kbase_mem_term,
-- "Memory subsystem initialization failed"},
-- {kbase_device_coherency_init, NULL,
-- "Device coherency init failed"},
-- {kbase_protected_mode_init, kbase_protected_mode_term,
-- "Protected mode subsystem initialization failed"},
-- {kbase_device_list_init, kbase_device_list_term,
-- "Device list setup failed"},
-- {kbasep_js_devdata_init, kbasep_js_devdata_term,
-- "Job JS devdata initialization failed"},
-- {kbase_device_timeline_init, kbase_device_timeline_term,
-- "Timeline stream initialization failed"},
-- {kbase_device_hwcnt_backend_gpu_init,
-- kbase_device_hwcnt_backend_gpu_term,
-- "GPU hwcnt backend creation failed"},
-- {kbase_device_hwcnt_context_init, kbase_device_hwcnt_context_term,
-- "GPU hwcnt context initialization failed"},
-- {kbase_device_hwcnt_virtualizer_init,
-- kbase_device_hwcnt_virtualizer_term,
-- "GPU hwcnt virtualizer initialization failed"},
-- {kbase_device_vinstr_init, kbase_device_vinstr_term,
-- "Virtual instrumentation initialization failed"},
-- {kbase_backend_late_init, kbase_backend_late_term,
-- "Late backend initialization failed"},
-+ { assign_irqs, NULL, "IRQ search failed" },
-+ { registers_map, registers_unmap, "Register map failed" },
-+ { kbase_device_io_history_init, kbase_device_io_history_term,
-+ "Register access history initialization failed" },
-+ { kbase_device_pm_init, kbase_device_pm_term,
-+ "Power management initialization failed" },
-+ { kbase_device_early_init, kbase_device_early_term,
-+ "Early device initialization failed" },
-+ { kbase_device_populate_max_freq, NULL,
-+ "Populating max frequency failed" },
-+ { kbase_device_misc_init, kbase_device_misc_term,
-+ "Miscellaneous device initialization failed" },
-+ { kbase_device_pcm_dev_init, kbase_device_pcm_dev_term,
-+ "Priority control manager initialization failed" },
-+ { kbase_ctx_sched_init, kbase_ctx_sched_term,
-+ "Context scheduler initialization failed" },
-+ { kbase_mem_init, kbase_mem_term,
-+ "Memory subsystem initialization failed" },
-+ { kbase_device_coherency_init, NULL, "Device coherency init failed" },
-+ { kbase_protected_mode_init, kbase_protected_mode_term,
-+ "Protected mode subsystem initialization failed" },
-+ { kbase_device_list_init, kbase_device_list_term,
-+ "Device list setup failed" },
-+ { kbasep_js_devdata_init, kbasep_js_devdata_term,
-+ "Job JS devdata initialization failed" },
-+ { kbase_device_timeline_init, kbase_device_timeline_term,
-+ "Timeline stream initialization failed" },
-+ { kbase_clk_rate_trace_manager_init, kbase_clk_rate_trace_manager_term,
-+ "Clock rate trace manager initialization failed" },
-+ { kbase_instr_backend_init, kbase_instr_backend_term,
-+ "Instrumentation backend initialization failed" },
-+ { kbase_device_hwcnt_backend_jm_init,
-+ kbase_device_hwcnt_backend_jm_term,
-+ "GPU hwcnt backend creation failed" },
-+ { kbase_device_hwcnt_context_init, kbase_device_hwcnt_context_term,
-+ "GPU hwcnt context initialization failed" },
-+ { kbase_device_hwcnt_virtualizer_init,
-+ kbase_device_hwcnt_virtualizer_term,
-+ "GPU hwcnt virtualizer initialization failed" },
-+ { kbase_device_vinstr_init, kbase_device_vinstr_term,
-+ "Virtual instrumentation initialization failed" },
-+ { kbase_backend_late_init, kbase_backend_late_term,
-+ "Late backend initialization failed" },
- #ifdef MALI_KBASE_BUILD
-- {kbase_debug_job_fault_dev_init, kbase_debug_job_fault_dev_term,
-- "Job fault debug initialization failed"},
-- {kbase_device_debugfs_init, kbase_device_debugfs_term,
-- "DebugFS initialization failed"},
-+ { kbase_debug_job_fault_dev_init, kbase_debug_job_fault_dev_term,
-+ "Job fault debug initialization failed" },
-+ { kbase_device_debugfs_init, kbase_device_debugfs_term,
-+ "DebugFS initialization failed" },
- /* Sysfs init needs to happen before registering the device with
- * misc_register(), otherwise it causes a race condition between
- * registering the device and a uevent event being generated for
-@@ -207,17 +216,15 @@ static const struct kbase_device_init dev_init[] = {
- * paragraph that starts with "Word of warning", currently the
- * second-last paragraph.
- */
-- {kbase_sysfs_init, kbase_sysfs_term, "SysFS group creation failed"},
-- {kbase_device_misc_register, kbase_device_misc_deregister,
-- "Misc device registration failed"},
--#ifdef CONFIG_MALI_BUSLOG
-- {buslog_init, buslog_term, "Bus log client registration failed"},
-+ { kbase_sysfs_init, kbase_sysfs_term, "SysFS group creation failed" },
-+ { kbase_device_misc_register, kbase_device_misc_deregister,
-+ "Misc device registration failed" },
-+ { kbase_gpuprops_populate_user_buffer, kbase_gpuprops_free_user_buffer,
-+ "GPU property population failed" },
- #endif
-- {kbase_gpuprops_populate_user_buffer, kbase_gpuprops_free_user_buffer,
-- "GPU property population failed"},
--#endif
-- {kbase_dummy_job_wa_load, kbase_dummy_job_wa_cleanup,
-- "Dummy job workaround load failed"},
-+ { NULL, kbase_dummy_job_wa_cleanup, NULL },
-+ { kbase_device_late_init, kbase_device_late_term,
-+ "Late device initialization failed" },
- };
-
- static void kbase_device_term_partial(struct kbase_device *kbdev,
-@@ -247,14 +254,34 @@ int kbase_device_init(struct kbase_device *kbdev)
- kbase_disjoint_init(kbdev);
-
- for (i = 0; i < ARRAY_SIZE(dev_init); i++) {
-- err = dev_init[i].init(kbdev);
-- if (err) {
-- dev_err(kbdev->dev, "%s error = %d\n",
-+ if (dev_init[i].init) {
-+ err = dev_init[i].init(kbdev);
-+ if (err) {
-+ if (err != -EPROBE_DEFER)
-+ dev_err(kbdev->dev, "%s error = %d\n",
- dev_init[i].err_mes, err);
-- kbase_device_term_partial(kbdev, i);
-- break;
-+ kbase_device_term_partial(kbdev, i);
-+ break;
-+ }
- }
- }
-
- return err;
- }
-+
-+int kbase_device_firmware_init_once(struct kbase_device *kbdev)
-+{
-+ int ret = 0;
-+
-+ mutex_lock(&kbdev->fw_load_lock);
-+
-+ if (!kbdev->dummy_job_wa_loaded) {
-+ ret = kbase_dummy_job_wa_load(kbdev);
-+ if (!ret)
-+ kbdev->dummy_job_wa_loaded = true;
-+ }
-+
-+ mutex_unlock(&kbdev->fw_load_lock);
-+
-+ return ret;
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device.c b/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device.c
-index 76f14e5..1ebd8aa 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device.c
-@@ -1,12 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -17,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Base kernel device APIs
- */
-@@ -34,12 +30,14 @@
- #include <linux/module.h>
- #include <linux/of_platform.h>
- #include <linux/types.h>
-+#include <linux/oom.h>
-
- #include <mali_kbase.h>
- #include <mali_kbase_defs.h>
- #include <mali_kbase_hwaccess_instr.h>
- #include <mali_kbase_hw.h>
- #include <mali_kbase_config_defaults.h>
-+#include <linux/priority_control_manager.h>
-
- #include <tl/mali_kbase_timeline.h>
- #include "mali_kbase_vinstr.h"
-@@ -50,6 +48,7 @@
- #include "mali_kbase_device_internal.h"
- #include "backend/gpu/mali_kbase_pm_internal.h"
- #include "backend/gpu/mali_kbase_irq_internal.h"
-+#include "mali_kbase_regs_history_debugfs.h"
-
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- #include "arbiter/mali_kbase_arbiter_pm.h"
-@@ -75,64 +74,152 @@ struct kbase_device *kbase_device_alloc(void)
- return kzalloc(sizeof(struct kbase_device), GFP_KERNEL);
- }
-
--static int kbase_device_as_init(struct kbase_device *kbdev, int i)
-+/**
-+ * kbase_device_all_as_init() - Initialise address space objects of the device.
-+ *
-+ * @kbdev: Pointer to kbase device.
-+ *
-+ * Return: 0 on success otherwise non-zero.
-+ */
-+static int kbase_device_all_as_init(struct kbase_device *kbdev)
- {
-- kbdev->as[i].number = i;
-- kbdev->as[i].bf_data.addr = 0ULL;
-- kbdev->as[i].pf_data.addr = 0ULL;
-+ int i, err = 0;
-
-- kbdev->as[i].pf_wq = alloc_workqueue("mali_mmu%d", 0, 1, i);
-- if (!kbdev->as[i].pf_wq)
-- return -EINVAL;
-+ for (i = 0; i < kbdev->nr_hw_address_spaces; i++) {
-+ err = kbase_mmu_as_init(kbdev, i);
-+ if (err)
-+ break;
-+ }
-
-- INIT_WORK(&kbdev->as[i].work_pagefault, page_fault_worker);
-- INIT_WORK(&kbdev->as[i].work_busfault, bus_fault_worker);
-+ if (err) {
-+ while (i-- > 0)
-+ kbase_mmu_as_term(kbdev, i);
-+ }
-
-- return 0;
-+ return err;
- }
-
--static void kbase_device_as_term(struct kbase_device *kbdev, int i)
-+static void kbase_device_all_as_term(struct kbase_device *kbdev)
- {
-- destroy_workqueue(kbdev->as[i].pf_wq);
-+ int i;
-+
-+ for (i = 0; i < kbdev->nr_hw_address_spaces; i++)
-+ kbase_mmu_as_term(kbdev, i);
- }
-
--static int kbase_device_all_as_init(struct kbase_device *kbdev)
-+int kbase_device_pcm_dev_init(struct kbase_device *const kbdev)
- {
-- int i, err;
-+ int err = 0;
-
-- for (i = 0; i < kbdev->nr_hw_address_spaces; i++) {
-- err = kbase_device_as_init(kbdev, i);
-- if (err)
-- goto free_workqs;
-- }
-+#if IS_ENABLED(CONFIG_OF)
-+ struct device_node *prio_ctrl_node;
-
-- return 0;
--
--free_workqs:
-- for (; i > 0; i--)
-- kbase_device_as_term(kbdev, i);
-+ /* Check to see whether or not a platform specific priority control manager
-+ * is available.
-+ */
-+ prio_ctrl_node = of_parse_phandle(kbdev->dev->of_node,
-+ "priority-control-manager", 0);
-+ if (!prio_ctrl_node) {
-+ dev_info(kbdev->dev,
-+ "No priority control manager is configured");
-+ } else {
-+ struct platform_device *const pdev =
-+ of_find_device_by_node(prio_ctrl_node);
-+
-+ if (!pdev) {
-+ dev_err(kbdev->dev,
-+ "The configured priority control manager was not found");
-+ } else {
-+ struct priority_control_manager_device *pcm_dev =
-+ platform_get_drvdata(pdev);
-+ if (!pcm_dev) {
-+ dev_info(kbdev->dev, "Priority control manager is not ready");
-+ err = -EPROBE_DEFER;
-+ } else if (!try_module_get(pcm_dev->owner)) {
-+ dev_err(kbdev->dev, "Failed to get priority control manager module");
-+ err = -ENODEV;
-+ } else {
-+ dev_info(kbdev->dev, "Priority control manager successfully loaded");
-+ kbdev->pcm_dev = pcm_dev;
-+ }
-+ }
-+ of_node_put(prio_ctrl_node);
-+ }
-+#endif /* CONFIG_OF */
-
- return err;
- }
-
--static void kbase_device_all_as_term(struct kbase_device *kbdev)
-+void kbase_device_pcm_dev_term(struct kbase_device *const kbdev)
- {
-- int i;
-+ if (kbdev->pcm_dev)
-+ module_put(kbdev->pcm_dev->owner);
-+}
-
-- for (i = 0; i < kbdev->nr_hw_address_spaces; i++)
-- kbase_device_as_term(kbdev, i);
-+#define KBASE_PAGES_TO_KIB(pages) (((unsigned int)pages) << (PAGE_SHIFT - 10))
-+
-+/**
-+ * mali_oom_notifier_handler - Mali driver out-of-memory handler
-+ *
-+ * @nb - notifier block - used to retrieve kbdev pointer
-+ * @action - action (unused)
-+ * @data - data pointer (unused)
-+ * This function simply lists memory usage by the Mali driver, per GPU device,
-+ * for diagnostic purposes.
-+ */
-+static int mali_oom_notifier_handler(struct notifier_block *nb,
-+ unsigned long action, void *data)
-+{
-+ struct kbase_device *kbdev;
-+ struct kbase_context *kctx = NULL;
-+ unsigned long kbdev_alloc_total;
-+
-+ if (WARN_ON(nb == NULL))
-+ return NOTIFY_BAD;
-+
-+ kbdev = container_of(nb, struct kbase_device, oom_notifier_block);
-+
-+ kbdev_alloc_total =
-+ KBASE_PAGES_TO_KIB(atomic_read(&(kbdev->memdev.used_pages)));
-+
-+ dev_err(kbdev->dev, "OOM notifier: dev %s %lu kB\n", kbdev->devname,
-+ kbdev_alloc_total);
-+
-+ mutex_lock(&kbdev->kctx_list_lock);
-+
-+ list_for_each_entry (kctx, &kbdev->kctx_list, kctx_list_link) {
-+ struct pid *pid_struct;
-+ struct task_struct *task;
-+ unsigned long task_alloc_total =
-+ KBASE_PAGES_TO_KIB(atomic_read(&(kctx->used_pages)));
-+
-+ rcu_read_lock();
-+ pid_struct = find_get_pid(kctx->pid);
-+ task = pid_task(pid_struct, PIDTYPE_PID);
-+
-+ dev_err(kbdev->dev,
-+ "OOM notifier: tsk %s tgid (%u) pid (%u) %lu kB\n",
-+ task ? task->comm : "[null task]", kctx->tgid,
-+ kctx->pid, task_alloc_total);
-+
-+ put_pid(pid_struct);
-+ rcu_read_unlock();
-+ }
-+
-+ mutex_unlock(&kbdev->kctx_list_lock);
-+ return NOTIFY_OK;
- }
-
- int kbase_device_misc_init(struct kbase_device * const kbdev)
- {
- int err;
--#ifdef CONFIG_ARM64
-+#if IS_ENABLED(CONFIG_ARM64)
- struct device_node *np = NULL;
- #endif /* CONFIG_ARM64 */
-
- spin_lock_init(&kbdev->mmu_mask_change);
- mutex_init(&kbdev->mmu_hw_mutex);
--#ifdef CONFIG_ARM64
-+#if IS_ENABLED(CONFIG_ARM64)
- kbdev->cci_snoop_enabled = false;
- np = kbdev->dev->of_node;
- if (np != NULL) {
-@@ -153,6 +240,7 @@ int kbase_device_misc_init(struct kbase_device * const kbdev)
- }
- }
- #endif /* CONFIG_ARM64 */
-+
- /* Get the list of workarounds for issues on the current HW
- * (identified by the GPU_ID register)
- */
-@@ -169,11 +257,6 @@ int kbase_device_misc_init(struct kbase_device * const kbdev)
- if (err)
- goto fail;
-
-- /* On Linux 4.0+, dma coherency is determined from device tree */
--#if defined(CONFIG_ARM64) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-- set_dma_ops(kbdev->dev, &noncoherent_swiotlb_dma_ops);
--#endif
--
- /* Workaround a pre-3.13 Linux issue, where dma_mask is NULL when our
- * device structure was created by device-tree
- */
-@@ -194,9 +277,7 @@ int kbase_device_misc_init(struct kbase_device * const kbdev)
-
- err = kbase_device_all_as_init(kbdev);
- if (err)
-- goto as_init_failed;
--
-- spin_lock_init(&kbdev->hwcnt.lock);
-+ goto dma_set_mask_failed;
-
- err = kbase_ktrace_init(kbdev);
- if (err)
-@@ -208,30 +289,28 @@ int kbase_device_misc_init(struct kbase_device * const kbdev)
-
- atomic_set(&kbdev->ctx_num, 0);
-
-- err = kbase_instr_backend_init(kbdev);
-- if (err)
-- goto term_trace;
--
- kbdev->pm.dvfs_period = DEFAULT_PM_DVFS_PERIOD;
-
- kbdev->reset_timeout_ms = DEFAULT_RESET_TIMEOUT_MS;
-
-- if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU))
-- kbdev->mmu_mode = kbase_mmu_mode_get_aarch64();
-- else
-- kbdev->mmu_mode = kbase_mmu_mode_get_lpae();
-+ kbdev->mmu_mode = kbase_mmu_mode_get_aarch64();
-
- mutex_init(&kbdev->kctx_list_lock);
- INIT_LIST_HEAD(&kbdev->kctx_list);
-
-- spin_lock_init(&kbdev->hwaccess_lock);
-+ dev_dbg(kbdev->dev, "Registering mali_oom_notifier_handlern");
-+ kbdev->oom_notifier_block.notifier_call = mali_oom_notifier_handler;
-+ err = register_oom_notifier(&kbdev->oom_notifier_block);
-
-+ if (err) {
-+ dev_err(kbdev->dev,
-+ "Unable to register OOM notifier for Mali - but will continue\n");
-+ kbdev->oom_notifier_block.notifier_call = NULL;
-+ }
- return 0;
--term_trace:
-- kbase_ktrace_term(kbdev);
-+
- term_as:
- kbase_device_all_as_term(kbdev);
--as_init_failed:
- dma_set_mask_failed:
- fail:
- return err;
-@@ -247,11 +326,12 @@ void kbase_device_misc_term(struct kbase_device *kbdev)
- kbase_debug_assert_register_hook(NULL, NULL);
- #endif
-
-- kbase_instr_backend_term(kbdev);
--
- kbase_ktrace_term(kbdev);
-
- kbase_device_all_as_term(kbdev);
-+
-+ if (kbdev->oom_notifier_block.notifier_call)
-+ unregister_oom_notifier(&kbdev->oom_notifier_block);
- }
-
- void kbase_device_free(struct kbase_device *kbdev)
-@@ -271,16 +351,6 @@ void kbase_increment_device_id(void)
- kbase_dev_nr++;
- }
-
--int kbase_device_hwcnt_backend_gpu_init(struct kbase_device *kbdev)
--{
-- return kbase_hwcnt_backend_gpu_create(kbdev, &kbdev->hwcnt_gpu_iface);
--}
--
--void kbase_device_hwcnt_backend_gpu_term(struct kbase_device *kbdev)
--{
-- kbase_hwcnt_backend_gpu_destroy(&kbdev->hwcnt_gpu_iface);
--}
--
- int kbase_device_hwcnt_context_init(struct kbase_device *kbdev)
- {
- return kbase_hwcnt_context_init(&kbdev->hwcnt_gpu_iface,
-@@ -400,7 +470,18 @@ int kbase_device_early_init(struct kbase_device *kbdev)
- /* We're done accessing the GPU registers for now. */
- kbase_pm_register_access_disable(kbdev);
-
-+ /* This spinlock has to be initialized before installing interrupt
-+ * handlers that require to hold it to process interrupts.
-+ */
-+ spin_lock_init(&kbdev->hwaccess_lock);
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ if (kbdev->arb.arb_if)
-+ err = kbase_arbiter_pm_install_interrupts(kbdev);
-+ else
-+ err = kbase_install_interrupts(kbdev);
-+#else
- err = kbase_install_interrupts(kbdev);
-+#endif
- if (err)
- goto fail_interrupts;
-
-@@ -427,3 +508,17 @@ void kbase_device_early_term(struct kbase_device *kbdev)
- kbase_pm_runtime_term(kbdev);
- kbasep_platform_device_term(kbdev);
- }
-+
-+int kbase_device_late_init(struct kbase_device *kbdev)
-+{
-+ int err;
-+
-+ err = kbasep_platform_device_late_init(kbdev);
-+
-+ return err;
-+}
-+
-+void kbase_device_late_term(struct kbase_device *kbdev)
-+{
-+ kbasep_platform_device_late_term(kbdev);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device.h b/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device.h
-index 16f1d70..517c16b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
-@@ -47,6 +46,19 @@ void kbase_device_put_list(const struct list_head *dev_list);
- */
- void kbase_increment_device_id(void);
-
-+/**
-+ * kbase_device_firmware_init_once - Initialize firmware and HWC
-+ *
-+ * @kbdev: An instance of the GPU platform device, allocated from the probe
-+ * method of the driver.
-+ *
-+ * When a device file is opened for the first time,
-+ * load firmware and initialize hardware counter components.
-+ *
-+ * @return 0 on success. An error code on failure.
-+ */
-+int kbase_device_firmware_init_once(struct kbase_device *kbdev);
-+
- /**
- * kbase_device_init - Device initialisation.
- *
-@@ -69,3 +81,109 @@ int kbase_device_init(struct kbase_device *kbdev);
- *
- */
- void kbase_device_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_reg_write - write to GPU register
-+ * @kbdev: Kbase device pointer
-+ * @offset: Offset of register
-+ * @value: Value to write
-+ *
-+ * Caller must ensure the GPU is powered (@kbdev->pm.gpu_powered != false).
-+ */
-+void kbase_reg_write(struct kbase_device *kbdev, u32 offset, u32 value);
-+
-+/**
-+ * kbase_reg_read - read from GPU register
-+ * @kbdev: Kbase device pointer
-+ * @offset: Offset of register
-+ *
-+ * Caller must ensure the GPU is powered (@kbdev->pm.gpu_powered != false).
-+ *
-+ * Return: Value in desired register
-+ */
-+u32 kbase_reg_read(struct kbase_device *kbdev, u32 offset);
-+
-+/**
-+ * kbase_is_gpu_removed() - Has the GPU been removed.
-+ * @kbdev: Kbase device pointer
-+ *
-+ * When Kbase takes too long to give up the GPU, the Arbiter
-+ * can remove it. This will then be followed by a GPU lost event.
-+ * This function will return true if the GPU has been removed.
-+ * When this happens register reads will be zero. A zero GPU_ID is
-+ * invalid so this is used to detect when GPU is removed.
-+ *
-+ * Return: True if GPU removed
-+ */
-+bool kbase_is_gpu_removed(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_gpu_start_cache_clean - Start a cache clean
-+ * @kbdev: Kbase device
-+ *
-+ * Issue a cache clean and invalidate command to hardware. This function will
-+ * take hwaccess_lock.
-+ */
-+void kbase_gpu_start_cache_clean(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_gpu_start_cache_clean_nolock - Start a cache clean
-+ * @kbdev: Kbase device
-+ *
-+ * Issue a cache clean and invalidate command to hardware. hwaccess_lock
-+ * must be held by the caller.
-+ */
-+void kbase_gpu_start_cache_clean_nolock(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_gpu_wait_cache_clean - Wait for cache cleaning to finish
-+ * @kbdev: Kbase device
-+ *
-+ * This function will take hwaccess_lock, and may sleep.
-+ */
-+void kbase_gpu_wait_cache_clean(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_gpu_wait_cache_clean_timeout - Wait for certain time for cache
-+ * cleaning to finish
-+ * @kbdev: Kbase device
-+ * @wait_timeout_ms: Time in milliseconds, to wait for cache clean to complete.
-+ *
-+ * This function will take hwaccess_lock, and may sleep. This is supposed to be
-+ * called from paths (like GPU reset) where an indefinite wait for the
-+ * completion of cache clean operation can cause deadlock, as the operation may
-+ * never complete.
-+ *
-+ * Return: 0 if successful or a negative error code on failure.
-+ */
-+int kbase_gpu_wait_cache_clean_timeout(struct kbase_device *kbdev,
-+ unsigned int wait_timeout_ms);
-+
-+/**
-+ * kbase_gpu_cache_clean_wait_complete - Called after the cache cleaning is
-+ * finished. Would also be called after
-+ * the GPU reset.
-+ * @kbdev: Kbase device
-+ *
-+ * Caller must hold the hwaccess_lock.
-+ */
-+void kbase_gpu_cache_clean_wait_complete(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_clean_caches_done - Issue preiously queued cache clean request or
-+ * wake up the requester that issued cache clean.
-+ * @kbdev: Kbase device
-+ *
-+ * Caller must hold the hwaccess_lock.
-+ */
-+void kbase_clean_caches_done(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_gpu_interrupt - GPU interrupt handler
-+ * @kbdev: Kbase device pointer
-+ * @val: The value of the GPU IRQ status register which triggered the call
-+ *
-+ * This function is called from the interrupt handler when a GPU irq is to be
-+ * handled.
-+ */
-+void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device_hw.c b/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device_hw.c
-new file mode 100644
-index 0000000..e80559a
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device_hw.c
-@@ -0,0 +1,182 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2014-2016, 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <gpu/mali_kbase_gpu_fault.h>
-+#include <backend/gpu/mali_kbase_instr_internal.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+#include <device/mali_kbase_device.h>
-+#include <mali_kbase_reset_gpu.h>
-+#include <mmu/mali_kbase_mmu.h>
-+
-+#if !IS_ENABLED(CONFIG_MALI_NO_MALI)
-+void kbase_reg_write(struct kbase_device *kbdev, u32 offset, u32 value)
-+{
-+ KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered);
-+ KBASE_DEBUG_ASSERT(kbdev->dev != NULL);
-+
-+ writel(value, kbdev->reg + offset);
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+ if (unlikely(kbdev->io_history.enabled))
-+ kbase_io_history_add(&kbdev->io_history, kbdev->reg + offset,
-+ value, 1);
-+#endif /* CONFIG_DEBUG_FS */
-+ dev_dbg(kbdev->dev, "w: reg %08x val %08x", offset, value);
-+}
-+
-+KBASE_EXPORT_TEST_API(kbase_reg_write);
-+
-+u32 kbase_reg_read(struct kbase_device *kbdev, u32 offset)
-+{
-+ u32 val;
-+
-+ KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered);
-+ KBASE_DEBUG_ASSERT(kbdev->dev != NULL);
-+
-+ val = readl(kbdev->reg + offset);
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+ if (unlikely(kbdev->io_history.enabled))
-+ kbase_io_history_add(&kbdev->io_history, kbdev->reg + offset,
-+ val, 0);
-+#endif /* CONFIG_DEBUG_FS */
-+ dev_dbg(kbdev->dev, "r: reg %08x val %08x", offset, val);
-+
-+ return val;
-+}
-+
-+KBASE_EXPORT_TEST_API(kbase_reg_read);
-+
-+bool kbase_is_gpu_removed(struct kbase_device *kbdev)
-+{
-+ u32 val;
-+
-+ val = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_ID));
-+
-+ return val == 0;
-+}
-+#endif /* !IS_ENABLED(CONFIG_MALI_NO_MALI) */
-+
-+void kbase_gpu_start_cache_clean_nolock(struct kbase_device *kbdev)
-+{
-+ u32 irq_mask;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ if (kbdev->cache_clean_in_progress) {
-+ /* If this is called while another clean is in progress, we
-+ * can't rely on the current one to flush any new changes in
-+ * the cache. Instead, trigger another cache clean immediately
-+ * after this one finishes.
-+ */
-+ kbdev->cache_clean_queued = true;
-+ return;
-+ }
-+
-+ /* Enable interrupt */
-+ irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK));
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK),
-+ irq_mask | CLEAN_CACHES_COMPLETED);
-+
-+ KBASE_KTRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, 0);
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-+ GPU_COMMAND_CLEAN_INV_CACHES);
-+
-+ kbdev->cache_clean_in_progress = true;
-+}
-+
-+void kbase_gpu_start_cache_clean(struct kbase_device *kbdev)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_gpu_start_cache_clean_nolock(kbdev);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+}
-+
-+void kbase_gpu_cache_clean_wait_complete(struct kbase_device *kbdev)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ kbdev->cache_clean_queued = false;
-+ kbdev->cache_clean_in_progress = false;
-+ wake_up(&kbdev->cache_clean_wait);
-+}
-+
-+void kbase_clean_caches_done(struct kbase_device *kbdev)
-+{
-+ u32 irq_mask;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+
-+ if (kbdev->cache_clean_queued) {
-+ kbdev->cache_clean_queued = false;
-+
-+ KBASE_KTRACE_ADD(kbdev, CORE_GPU_CLEAN_INV_CACHES, NULL, 0);
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-+ GPU_COMMAND_CLEAN_INV_CACHES);
-+ } else {
-+ /* Disable interrupt */
-+ irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK));
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK),
-+ irq_mask & ~CLEAN_CACHES_COMPLETED);
-+
-+ kbase_gpu_cache_clean_wait_complete(kbdev);
-+ }
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+}
-+
-+static inline bool get_cache_clean_flag(struct kbase_device *kbdev)
-+{
-+ bool cache_clean_in_progress;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ cache_clean_in_progress = kbdev->cache_clean_in_progress;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ return cache_clean_in_progress;
-+}
-+
-+void kbase_gpu_wait_cache_clean(struct kbase_device *kbdev)
-+{
-+ while (get_cache_clean_flag(kbdev)) {
-+ wait_event_interruptible(kbdev->cache_clean_wait,
-+ !kbdev->cache_clean_in_progress);
-+ }
-+}
-+
-+int kbase_gpu_wait_cache_clean_timeout(struct kbase_device *kbdev,
-+ unsigned int wait_timeout_ms)
-+{
-+ long remaining = msecs_to_jiffies(wait_timeout_ms);
-+
-+ while (remaining && get_cache_clean_flag(kbdev)) {
-+ remaining = wait_event_timeout(kbdev->cache_clean_wait,
-+ !kbdev->cache_clean_in_progress,
-+ remaining);
-+ }
-+
-+ return (remaining ? 0 : -ETIMEDOUT);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device_internal.h
-index 9f96db0..d422407 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device_internal.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/device/mali_kbase_device_internal.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
-@@ -43,9 +42,6 @@ void kbase_device_vinstr_term(struct kbase_device *kbdev);
- int kbase_device_timeline_init(struct kbase_device *kbdev);
- void kbase_device_timeline_term(struct kbase_device *kbdev);
-
--int kbase_device_hwcnt_backend_gpu_init(struct kbase_device *kbdev);
--void kbase_device_hwcnt_backend_gpu_term(struct kbase_device *kbdev);
--
- int kbase_device_hwcnt_context_init(struct kbase_device *kbdev);
- void kbase_device_hwcnt_context_term(struct kbase_device *kbdev);
-
-@@ -76,3 +72,17 @@ int kbase_device_early_init(struct kbase_device *kbdev);
- * @kbdev: Device pointer
- */
- void kbase_device_early_term(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_device_late_init - Complete any device-specific initialization.
-+ * @kbdev: Device pointer
-+ *
-+ * Return: 0 on success, or an error code on failure.
-+ */
-+int kbase_device_late_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_device_late_term - Complete any device-specific termination.
-+ * @kbdev: Device pointer
-+ */
-+void kbase_device_late_term(struct kbase_device *kbdev);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Kconfig b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/Kbuild
-similarity index 65%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Kconfig
-rename to dvalin/kernel/drivers/gpu/arm/midgard/gpu/Kbuild
-index 0cdb474..c3ab811 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Kconfig
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,14 +16,12 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
-+mali_kbase-y += gpu/mali_kbase_gpu.o
-
--config MALI_KUTF
-- tristate "Mali Kernel Unit Test Framework"
-- default m
-- help
-- Enables MALI testing framework. To compile it as a module,
-- choose M here - this will generate a single module called kutf.
-+ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
-+ mali_kbase-y += gpu/backend/mali_kbase_gpu_fault_csf.o
-+else
-+ mali_kbase-y += gpu/backend/mali_kbase_gpu_fault_jm.o
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_fault_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_fault_csf.c
-new file mode 100644
-index 0000000..f9d4c14
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_fault_csf.c
-@@ -0,0 +1,104 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <uapi/gpu/arm/midgard/csf/mali_gpu_csf_registers.h>
-+#include <gpu/mali_kbase_gpu_fault.h>
-+
-+const char *kbase_gpu_exception_name(u32 const exception_code)
-+{
-+ const char *e;
-+
-+ switch (exception_code) {
-+ /* CS exceptions */
-+ case CS_FAULT_EXCEPTION_TYPE_CS_RESOURCE_TERMINATED:
-+ e = "CS_RESOURCE_TERMINATED";
-+ break;
-+ case CS_FAULT_EXCEPTION_TYPE_CS_INHERIT_FAULT:
-+ e = "CS_INHERIT_FAULT";
-+ break;
-+ /* CS fatal exceptions */
-+ case CS_FATAL_EXCEPTION_TYPE_CS_CONFIG_FAULT:
-+ e = "CS_CONFIG_FAULT";
-+ break;
-+ case CS_FATAL_EXCEPTION_TYPE_CS_ENDPOINT_FAULT:
-+ e = "FATAL_CS_ENDPOINT_FAULT";
-+ break;
-+ case CS_FATAL_EXCEPTION_TYPE_CS_BUS_FAULT:
-+ e = "FATAL_CS_BUS_FAULT";
-+ break;
-+ case CS_FATAL_EXCEPTION_TYPE_CS_INVALID_INSTRUCTION:
-+ e = "FATAL_CS_INVALID_INSTRUCTION";
-+ break;
-+ case CS_FATAL_EXCEPTION_TYPE_CS_CALL_STACK_OVERFLOW:
-+ e = "FATAL_CS_CALL_STACK_OVERFLOW";
-+ break;
-+ /* Shader exceptions */
-+ case CS_FAULT_EXCEPTION_TYPE_INSTR_INVALID_PC:
-+ e = "INSTR_INVALID_PC";
-+ break;
-+ case CS_FAULT_EXCEPTION_TYPE_INSTR_INVALID_ENC:
-+ e = "INSTR_INVALID_ENC";
-+ break;
-+ case CS_FAULT_EXCEPTION_TYPE_INSTR_BARRIER_FAULT:
-+ e = "INSTR_BARRIER_FAULT";
-+ break;
-+ /* Misc exceptions */
-+ case CS_FAULT_EXCEPTION_TYPE_DATA_INVALID_FAULT:
-+ e = "DATA_INVALID_FAULT";
-+ break;
-+ case CS_FAULT_EXCEPTION_TYPE_TILE_RANGE_FAULT:
-+ e = "TILE_RANGE_FAULT";
-+ break;
-+ case CS_FAULT_EXCEPTION_TYPE_ADDR_RANGE_FAULT:
-+ e = "ADDR_RANGE_FAULT";
-+ break;
-+ case CS_FAULT_EXCEPTION_TYPE_IMPRECISE_FAULT:
-+ e = "IMPRECISE_FAULT";
-+ break;
-+ /* FW exceptions */
-+ case CS_FATAL_EXCEPTION_TYPE_FIRMWARE_INTERNAL_ERROR:
-+ e = "FIRMWARE_INTERNAL_ERROR";
-+ break;
-+ case CS_FAULT_EXCEPTION_TYPE_RESOURCE_EVICTION_TIMEOUT:
-+ e = "RESOURCE_EVICTION_TIMEOUT";
-+ break;
-+ /* GPU Fault */
-+ case GPU_FAULTSTATUS_EXCEPTION_TYPE_GPU_BUS_FAULT:
-+ e = "GPU_BUS_FAULT";
-+ break;
-+ case GPU_FAULTSTATUS_EXCEPTION_TYPE_GPU_SHAREABILITY_FAULT:
-+ e = "GPU_SHAREABILITY_FAULT";
-+ break;
-+ case GPU_FAULTSTATUS_EXCEPTION_TYPE_SYSTEM_SHAREABILITY_FAULT:
-+ e = "SYSTEM_SHAREABILITY_FAULT";
-+ break;
-+ case GPU_FAULTSTATUS_EXCEPTION_TYPE_GPU_CACHEABILITY_FAULT:
-+ e = "GPU_CACHEABILITY_FAULT";
-+ break;
-+ /* Any other exception code is unknown */
-+ default:
-+ e = "UNKNOWN";
-+ break;
-+ }
-+
-+ return e;
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_fault_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_fault_jm.c
-index 63132dc..37015cc 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_fault_jm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_fault_jm.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,13 +17,11 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
-
--#include "../mali_kbase_gpu_fault.h"
-+#include <gpu/mali_kbase_gpu_fault.h>
-
- const char *kbase_gpu_exception_name(u32 const exception_code)
- {
-@@ -119,8 +118,6 @@ const char *kbase_gpu_exception_name(u32 const exception_code)
- e = "TRANSLATION_FAULT";
- break;
- case 0xC8:
-- e = "PERMISSION_FAULT";
-- break;
- case 0xC9:
- case 0xCA:
- case 0xCB:
-@@ -141,8 +138,6 @@ const char *kbase_gpu_exception_name(u32 const exception_code)
- e = "TRANSTAB_BUS_FAULT";
- break;
- case 0xD8:
-- e = "ACCESS_FLAG";
-- break;
- case 0xD9:
- case 0xDA:
- case 0xDB:
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu.c b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu.c
-index 3128db4..8a84ef5 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,11 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
- #include <mali_kbase_defs.h>
-+#include <gpu/mali_kbase_gpu_fault.h>
-
- const char *kbase_gpu_access_type_name(u32 fault_status)
- {
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_fault.h b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_fault.h
-index b59b9d1..d1e9f77 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_fault.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_fault.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,14 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_GPU_FAULT_H_
- #define _KBASE_GPU_FAULT_H_
-
--/** Returns the name associated with a Mali exception code
-- *
-+/**
-+ * kbase_gpu_exception_name() -
-+ * Returns the name associated with a Mali exception code
- * @exception_code: exception code
- *
- * This function is called from the interrupt handler when a GPU fault occurs.
-@@ -33,17 +33,6 @@
- */
- const char *kbase_gpu_exception_name(u32 exception_code);
-
--/** Returns the name associated with a Mali fatal exception code
-- *
-- * @fatal_exception_code: fatal exception code
-- *
-- * This function is called from the interrupt handler when a GPU fatal
-- * exception occurs.
-- *
-- * Return: name associated with the fatal exception code
-- */
--const char *kbase_gpu_fatal_exception_name(u32 const fatal_exception_code);
--
- /**
- * kbase_gpu_access_type_name - Convert MMU_AS_CONTROL.FAULTSTATUS.ACCESS_TYPE
- * into string.
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_regmap.h b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_regmap.h
-index 759f30d..47e7781 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_regmap.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_regmap.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,422 +17,17 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_GPU_REGMAP_H_
- #define _KBASE_GPU_REGMAP_H_
-
--#include "mali_kbase_gpu_coherency.h"
--#include "mali_kbase_gpu_id.h"
--#include "backend/mali_kbase_gpu_regmap_jm.h"
--
--/* Begin Register Offsets */
--/* GPU control registers */
--
--#define GPU_CONTROL_BASE 0x0000
--#define GPU_CONTROL_REG(r) (GPU_CONTROL_BASE + (r))
--#define GPU_ID 0x000 /* (RO) GPU and revision identifier */
--#define L2_FEATURES 0x004 /* (RO) Level 2 cache features */
--#define TILER_FEATURES 0x00C /* (RO) Tiler Features */
--#define MEM_FEATURES 0x010 /* (RO) Memory system features */
--#define MMU_FEATURES 0x014 /* (RO) MMU features */
--#define AS_PRESENT 0x018 /* (RO) Address space slots present */
--#define GPU_IRQ_RAWSTAT 0x020 /* (RW) */
--#define GPU_IRQ_CLEAR 0x024 /* (WO) */
--#define GPU_IRQ_MASK 0x028 /* (RW) */
--#define GPU_IRQ_STATUS 0x02C /* (RO) */
--
--#define GPU_COMMAND 0x030 /* (WO) */
--#define GPU_STATUS 0x034 /* (RO) */
--
--#define GPU_DBGEN (1 << 8) /* DBGEN wire status */
--
--#define GPU_FAULTSTATUS 0x03C /* (RO) GPU exception type and fault status */
--#define GPU_FAULTADDRESS_LO 0x040 /* (RO) GPU exception fault address, low word */
--#define GPU_FAULTADDRESS_HI 0x044 /* (RO) GPU exception fault address, high word */
--
--#define L2_CONFIG 0x048 /* (RW) Level 2 cache configuration */
--
--#define GROUPS_L2_COHERENT (1 << 0) /* Cores groups are l2 coherent */
--#define SUPER_L2_COHERENT (1 << 1) /* Shader cores within a core
-- * supergroup are l2 coherent
-- */
--
--#define PWR_KEY 0x050 /* (WO) Power manager key register */
--#define PWR_OVERRIDE0 0x054 /* (RW) Power manager override settings */
--#define PWR_OVERRIDE1 0x058 /* (RW) Power manager override settings */
--
--#define CYCLE_COUNT_LO 0x090 /* (RO) Cycle counter, low word */
--#define CYCLE_COUNT_HI 0x094 /* (RO) Cycle counter, high word */
--#define TIMESTAMP_LO 0x098 /* (RO) Global time stamp counter, low word */
--#define TIMESTAMP_HI 0x09C /* (RO) Global time stamp counter, high word */
--
--#define THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */
--#define THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */
--#define THREAD_MAX_BARRIER_SIZE 0x0A8 /* (RO) Maximum threads waiting at a barrier */
--#define THREAD_FEATURES 0x0AC /* (RO) Thread features */
--#define THREAD_TLS_ALLOC 0x310 /* (RO) Number of threads per core that TLS must be allocated for */
--
--#define TEXTURE_FEATURES_0 0x0B0 /* (RO) Support flags for indexed texture formats 0..31 */
--#define TEXTURE_FEATURES_1 0x0B4 /* (RO) Support flags for indexed texture formats 32..63 */
--#define TEXTURE_FEATURES_2 0x0B8 /* (RO) Support flags for indexed texture formats 64..95 */
--#define TEXTURE_FEATURES_3 0x0BC /* (RO) Support flags for texture order */
--
--#define TEXTURE_FEATURES_REG(n) GPU_CONTROL_REG(TEXTURE_FEATURES_0 + ((n) << 2))
--
--#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */
--#define SHADER_PRESENT_HI 0x104 /* (RO) Shader core present bitmap, high word */
--
--#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */
--#define TILER_PRESENT_HI 0x114 /* (RO) Tiler core present bitmap, high word */
--
--#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */
--#define L2_PRESENT_HI 0x124 /* (RO) Level 2 cache present bitmap, high word */
--
--#define STACK_PRESENT_LO 0xE00 /* (RO) Core stack present bitmap, low word */
--#define STACK_PRESENT_HI 0xE04 /* (RO) Core stack present bitmap, high word */
--
--#define SHADER_READY_LO 0x140 /* (RO) Shader core ready bitmap, low word */
--#define SHADER_READY_HI 0x144 /* (RO) Shader core ready bitmap, high word */
--
--#define TILER_READY_LO 0x150 /* (RO) Tiler core ready bitmap, low word */
--#define TILER_READY_HI 0x154 /* (RO) Tiler core ready bitmap, high word */
--
--#define L2_READY_LO 0x160 /* (RO) Level 2 cache ready bitmap, low word */
--#define L2_READY_HI 0x164 /* (RO) Level 2 cache ready bitmap, high word */
--
--#define STACK_READY_LO 0xE10 /* (RO) Core stack ready bitmap, low word */
--#define STACK_READY_HI 0xE14 /* (RO) Core stack ready bitmap, high word */
--
--#define SHADER_PWRON_LO 0x180 /* (WO) Shader core power on bitmap, low word */
--#define SHADER_PWRON_HI 0x184 /* (WO) Shader core power on bitmap, high word */
--
--#define TILER_PWRON_LO 0x190 /* (WO) Tiler core power on bitmap, low word */
--#define TILER_PWRON_HI 0x194 /* (WO) Tiler core power on bitmap, high word */
--
--#define L2_PWRON_LO 0x1A0 /* (WO) Level 2 cache power on bitmap, low word */
--#define L2_PWRON_HI 0x1A4 /* (WO) Level 2 cache power on bitmap, high word */
--
--#define STACK_PWRON_LO 0xE20 /* (RO) Core stack power on bitmap, low word */
--#define STACK_PWRON_HI 0xE24 /* (RO) Core stack power on bitmap, high word */
--
--#define SHADER_PWROFF_LO 0x1C0 /* (WO) Shader core power off bitmap, low word */
--#define SHADER_PWROFF_HI 0x1C4 /* (WO) Shader core power off bitmap, high word */
--
--#define TILER_PWROFF_LO 0x1D0 /* (WO) Tiler core power off bitmap, low word */
--#define TILER_PWROFF_HI 0x1D4 /* (WO) Tiler core power off bitmap, high word */
--
--#define L2_PWROFF_LO 0x1E0 /* (WO) Level 2 cache power off bitmap, low word */
--#define L2_PWROFF_HI 0x1E4 /* (WO) Level 2 cache power off bitmap, high word */
--
--#define STACK_PWROFF_LO 0xE30 /* (RO) Core stack power off bitmap, low word */
--#define STACK_PWROFF_HI 0xE34 /* (RO) Core stack power off bitmap, high word */
--
--#define SHADER_PWRTRANS_LO 0x200 /* (RO) Shader core power transition bitmap, low word */
--#define SHADER_PWRTRANS_HI 0x204 /* (RO) Shader core power transition bitmap, high word */
--
--#define TILER_PWRTRANS_LO 0x210 /* (RO) Tiler core power transition bitmap, low word */
--#define TILER_PWRTRANS_HI 0x214 /* (RO) Tiler core power transition bitmap, high word */
--
--#define L2_PWRTRANS_LO 0x220 /* (RO) Level 2 cache power transition bitmap, low word */
--#define L2_PWRTRANS_HI 0x224 /* (RO) Level 2 cache power transition bitmap, high word */
--
--#define STACK_PWRTRANS_LO 0xE40 /* (RO) Core stack power transition bitmap, low word */
--#define STACK_PWRTRANS_HI 0xE44 /* (RO) Core stack power transition bitmap, high word */
--
--#define SHADER_PWRACTIVE_LO 0x240 /* (RO) Shader core active bitmap, low word */
--#define SHADER_PWRACTIVE_HI 0x244 /* (RO) Shader core active bitmap, high word */
--
--#define TILER_PWRACTIVE_LO 0x250 /* (RO) Tiler core active bitmap, low word */
--#define TILER_PWRACTIVE_HI 0x254 /* (RO) Tiler core active bitmap, high word */
--
--#define L2_PWRACTIVE_LO 0x260 /* (RO) Level 2 cache active bitmap, low word */
--#define L2_PWRACTIVE_HI 0x264 /* (RO) Level 2 cache active bitmap, high word */
--
--#define COHERENCY_FEATURES 0x300 /* (RO) Coherency features present */
--#define COHERENCY_ENABLE 0x304 /* (RW) Coherency enable */
--
--#define SHADER_CONFIG 0xF04 /* (RW) Shader core configuration (implementation-specific) */
--#define TILER_CONFIG 0xF08 /* (RW) Tiler core configuration (implementation-specific) */
--#define L2_MMU_CONFIG 0xF0C /* (RW) L2 cache and MMU configuration (implementation-specific) */
--
--/* Job control registers */
--
--#define JOB_CONTROL_BASE 0x1000
--
--#define JOB_CONTROL_REG(r) (JOB_CONTROL_BASE + (r))
--
--#define JOB_IRQ_RAWSTAT 0x000 /* Raw interrupt status register */
--#define JOB_IRQ_CLEAR 0x004 /* Interrupt clear register */
--#define JOB_IRQ_MASK 0x008 /* Interrupt mask register */
--#define JOB_IRQ_STATUS 0x00C /* Interrupt status register */
--
--/* MMU control registers */
--
--#define MEMORY_MANAGEMENT_BASE 0x2000
--#define MMU_REG(r) (MEMORY_MANAGEMENT_BASE + (r))
--
--#define MMU_IRQ_RAWSTAT 0x000 /* (RW) Raw interrupt status register */
--#define MMU_IRQ_CLEAR 0x004 /* (WO) Interrupt clear register */
--#define MMU_IRQ_MASK 0x008 /* (RW) Interrupt mask register */
--#define MMU_IRQ_STATUS 0x00C /* (RO) Interrupt status register */
--
--#define MMU_AS0 0x400 /* Configuration registers for address space 0 */
--#define MMU_AS1 0x440 /* Configuration registers for address space 1 */
--#define MMU_AS2 0x480 /* Configuration registers for address space 2 */
--#define MMU_AS3 0x4C0 /* Configuration registers for address space 3 */
--#define MMU_AS4 0x500 /* Configuration registers for address space 4 */
--#define MMU_AS5 0x540 /* Configuration registers for address space 5 */
--#define MMU_AS6 0x580 /* Configuration registers for address space 6 */
--#define MMU_AS7 0x5C0 /* Configuration registers for address space 7 */
--#define MMU_AS8 0x600 /* Configuration registers for address space 8 */
--#define MMU_AS9 0x640 /* Configuration registers for address space 9 */
--#define MMU_AS10 0x680 /* Configuration registers for address space 10 */
--#define MMU_AS11 0x6C0 /* Configuration registers for address space 11 */
--#define MMU_AS12 0x700 /* Configuration registers for address space 12 */
--#define MMU_AS13 0x740 /* Configuration registers for address space 13 */
--#define MMU_AS14 0x780 /* Configuration registers for address space 14 */
--#define MMU_AS15 0x7C0 /* Configuration registers for address space 15 */
--
--/* MMU address space control registers */
--
--#define MMU_AS_REG(n, r) (MMU_REG(MMU_AS0 + ((n) << 6)) + (r))
--
--#define AS_TRANSTAB_LO 0x00 /* (RW) Translation Table Base Address for address space n, low word */
--#define AS_TRANSTAB_HI 0x04 /* (RW) Translation Table Base Address for address space n, high word */
--#define AS_MEMATTR_LO 0x08 /* (RW) Memory attributes for address space n, low word. */
--#define AS_MEMATTR_HI 0x0C /* (RW) Memory attributes for address space n, high word. */
--#define AS_LOCKADDR_LO 0x10 /* (RW) Lock region address for address space n, low word */
--#define AS_LOCKADDR_HI 0x14 /* (RW) Lock region address for address space n, high word */
--#define AS_COMMAND 0x18 /* (WO) MMU command register for address space n */
--#define AS_FAULTSTATUS 0x1C /* (RO) MMU fault status register for address space n */
--#define AS_FAULTADDRESS_LO 0x20 /* (RO) Fault Address for address space n, low word */
--#define AS_FAULTADDRESS_HI 0x24 /* (RO) Fault Address for address space n, high word */
--#define AS_STATUS 0x28 /* (RO) Status flags for address space n */
--
--/* (RW) Translation table configuration for address space n, low word */
--#define AS_TRANSCFG_LO 0x30
--/* (RW) Translation table configuration for address space n, high word */
--#define AS_TRANSCFG_HI 0x34
--/* (RO) Secondary fault address for address space n, low word */
--#define AS_FAULTEXTRA_LO 0x38
--/* (RO) Secondary fault address for address space n, high word */
--#define AS_FAULTEXTRA_HI 0x3C
--
--/* End Register Offsets */
--
--/* IRQ flags */
--#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */
--#define MULTIPLE_GPU_FAULTS (1 << 7) /* More than one GPU Fault occurred. */
--#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. */
--#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */
--#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down. */
--
--#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when a performance count sample has completed. */
--#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */
--
--/* Include POWER_CHANGED_SINGLE in debug builds for use in irq latency test.
-- */
--#define GPU_IRQ_REG_COMMON (GPU_FAULT | MULTIPLE_GPU_FAULTS | RESET_COMPLETED \
-- | POWER_CHANGED_ALL | PRFCNT_SAMPLE_COMPLETED)
-+#include <uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_regmap.h>
-
-+/* Include POWER_CHANGED_SINGLE in debug builds for use in irq latency test. */
- #ifdef CONFIG_MALI_DEBUG
-+#undef GPU_IRQ_REG_ALL
- #define GPU_IRQ_REG_ALL (GPU_IRQ_REG_COMMON | POWER_CHANGED_SINGLE)
--#else /* CONFIG_MALI_DEBUG */
--#define GPU_IRQ_REG_ALL (GPU_IRQ_REG_COMMON)
- #endif /* CONFIG_MALI_DEBUG */
-
--/*
-- * MMU_IRQ_RAWSTAT register values. Values are valid also for
-- * MMU_IRQ_CLEAR, MMU_IRQ_MASK, MMU_IRQ_STATUS registers.
-- */
--
--#define MMU_PAGE_FAULT_FLAGS 16
--
--/* Macros returning a bitmask to retrieve page fault or bus error flags from
-- * MMU registers */
--#define MMU_PAGE_FAULT(n) (1UL << (n))
--#define MMU_BUS_ERROR(n) (1UL << ((n) + MMU_PAGE_FAULT_FLAGS))
--
--/*
-- * Begin LPAE MMU TRANSTAB register values
-- */
--#define AS_TRANSTAB_LPAE_ADDR_SPACE_MASK 0xfffff000
--#define AS_TRANSTAB_LPAE_ADRMODE_UNMAPPED (0u << 0)
--#define AS_TRANSTAB_LPAE_ADRMODE_IDENTITY (1u << 1)
--#define AS_TRANSTAB_LPAE_ADRMODE_TABLE (3u << 0)
--#define AS_TRANSTAB_LPAE_READ_INNER (1u << 2)
--#define AS_TRANSTAB_LPAE_SHARE_OUTER (1u << 4)
--
--#define AS_TRANSTAB_LPAE_ADRMODE_MASK 0x00000003
--
--/*
-- * Begin AARCH64 MMU TRANSTAB register values
-- */
--#define MMU_HW_OUTA_BITS 40
--#define AS_TRANSTAB_BASE_MASK ((1ULL << MMU_HW_OUTA_BITS) - (1ULL << 4))
--
--/*
-- * Begin MMU STATUS register values
-- */
--#define AS_STATUS_AS_ACTIVE 0x01
--
--#define AS_FAULTSTATUS_EXCEPTION_CODE_MASK (0x7<<3)
--#define AS_FAULTSTATUS_EXCEPTION_CODE_TRANSLATION_FAULT (0x0<<3)
--#define AS_FAULTSTATUS_EXCEPTION_CODE_PERMISSION_FAULT (0x1<<3)
--#define AS_FAULTSTATUS_EXCEPTION_CODE_TRANSTAB_BUS_FAULT (0x2<<3)
--#define AS_FAULTSTATUS_EXCEPTION_CODE_ACCESS_FLAG (0x3<<3)
--#define AS_FAULTSTATUS_EXCEPTION_CODE_ADDRESS_SIZE_FAULT (0x4<<3)
--#define AS_FAULTSTATUS_EXCEPTION_CODE_MEMORY_ATTRIBUTES_FAULT (0x5<<3)
--
--#define AS_FAULTSTATUS_EXCEPTION_TYPE_SHIFT 0
--#define AS_FAULTSTATUS_EXCEPTION_TYPE_MASK (0xFF << AS_FAULTSTATUS_EXCEPTION_TYPE_SHIFT)
--#define AS_FAULTSTATUS_EXCEPTION_TYPE_GET(reg_val) \
-- (((reg_val)&AS_FAULTSTATUS_EXCEPTION_TYPE_MASK) >> AS_FAULTSTATUS_EXCEPTION_TYPE_SHIFT)
--
--#define AS_FAULTSTATUS_ACCESS_TYPE_SHIFT 8
--#define AS_FAULTSTATUS_ACCESS_TYPE_MASK (0x3 << AS_FAULTSTATUS_ACCESS_TYPE_SHIFT)
--#define AS_FAULTSTATUS_ACCESS_TYPE_GET(reg_val) \
-- (((reg_val)&AS_FAULTSTATUS_ACCESS_TYPE_MASK) >> AS_FAULTSTATUS_ACCESS_TYPE_SHIFT)
--
--#define AS_FAULTSTATUS_ACCESS_TYPE_ATOMIC (0x0)
--#define AS_FAULTSTATUS_ACCESS_TYPE_EX (0x1)
--#define AS_FAULTSTATUS_ACCESS_TYPE_READ (0x2)
--#define AS_FAULTSTATUS_ACCESS_TYPE_WRITE (0x3)
--
--#define AS_FAULTSTATUS_SOURCE_ID_SHIFT 16
--#define AS_FAULTSTATUS_SOURCE_ID_MASK (0xFFFF << AS_FAULTSTATUS_SOURCE_ID_SHIFT)
--#define AS_FAULTSTATUS_SOURCE_ID_GET(reg_val) \
-- (((reg_val)&AS_FAULTSTATUS_SOURCE_ID_MASK) >> AS_FAULTSTATUS_SOURCE_ID_SHIFT)
--
--/*
-- * Begin MMU TRANSCFG register values
-- */
--#define AS_TRANSCFG_ADRMODE_LEGACY 0
--#define AS_TRANSCFG_ADRMODE_UNMAPPED 1
--#define AS_TRANSCFG_ADRMODE_IDENTITY 2
--#define AS_TRANSCFG_ADRMODE_AARCH64_4K 6
--#define AS_TRANSCFG_ADRMODE_AARCH64_64K 8
--
--#define AS_TRANSCFG_ADRMODE_MASK 0xF
--
--/*
-- * Begin TRANSCFG register values
-- */
--#define AS_TRANSCFG_PTW_MEMATTR_MASK (3ull << 24)
--#define AS_TRANSCFG_PTW_MEMATTR_NON_CACHEABLE (1ull << 24)
--#define AS_TRANSCFG_PTW_MEMATTR_WRITE_BACK (2ull << 24)
--
--#define AS_TRANSCFG_PTW_SH_MASK ((3ull << 28))
--#define AS_TRANSCFG_PTW_SH_OS (2ull << 28)
--#define AS_TRANSCFG_PTW_SH_IS (3ull << 28)
--#define AS_TRANSCFG_R_ALLOCATE (1ull << 30)
--
--/*
-- * Begin Command Values
-- */
--
--/* AS_COMMAND register commands */
--#define AS_COMMAND_NOP 0x00 /* NOP Operation */
--#define AS_COMMAND_UPDATE 0x01 /* Broadcasts the values in AS_TRANSTAB and ASn_MEMATTR to all MMUs */
--#define AS_COMMAND_LOCK 0x02 /* Issue a lock region command to all MMUs */
--#define AS_COMMAND_UNLOCK 0x03 /* Issue a flush region command to all MMUs */
--#define AS_COMMAND_FLUSH 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs
-- (deprecated - only for use with T60x) */
--#define AS_COMMAND_FLUSH_PT 0x04 /* Flush all L2 caches then issue a flush region command to all MMUs */
--#define AS_COMMAND_FLUSH_MEM 0x05 /* Wait for memory accesses to complete, flush all the L1s cache then
-- flush all L2 caches then issue a flush region command to all MMUs */
--
--/* GPU_STATUS values */
--#define GPU_STATUS_PRFCNT_ACTIVE (1 << 2) /* Set if the performance counters are active. */
--#define GPU_STATUS_PROTECTED_MODE_ACTIVE (1 << 7) /* Set if protected mode is active */
--
--/* PRFCNT_CONFIG register values */
--#define PRFCNT_CONFIG_MODE_SHIFT 0 /* Counter mode position. */
--#define PRFCNT_CONFIG_AS_SHIFT 4 /* Address space bitmap position. */
--#define PRFCNT_CONFIG_SETSELECT_SHIFT 8 /* Set select position. */
--
--/* The performance counters are disabled. */
--#define PRFCNT_CONFIG_MODE_OFF 0
--/* The performance counters are enabled, but are only written out when a
-- * PRFCNT_SAMPLE command is issued using the GPU_COMMAND register.
-- */
--#define PRFCNT_CONFIG_MODE_MANUAL 1
--/* The performance counters are enabled, and are written out each time a tile
-- * finishes rendering.
-- */
--#define PRFCNT_CONFIG_MODE_TILE 2
--
--/* AS<n>_MEMATTR values from MMU_MEMATTR_STAGE1: */
--/* Use GPU implementation-defined caching policy. */
--#define AS_MEMATTR_IMPL_DEF_CACHE_POLICY 0x88ull
--/* The attribute set to force all resources to be cached. */
--#define AS_MEMATTR_FORCE_TO_CACHE_ALL 0x8Full
--/* Inner write-alloc cache setup, no outer caching */
--#define AS_MEMATTR_WRITE_ALLOC 0x8Dull
--
--/* Use GPU implementation-defined caching policy. */
--#define AS_MEMATTR_LPAE_IMPL_DEF_CACHE_POLICY 0x48ull
--/* The attribute set to force all resources to be cached. */
--#define AS_MEMATTR_LPAE_FORCE_TO_CACHE_ALL 0x4Full
--/* Inner write-alloc cache setup, no outer caching */
--#define AS_MEMATTR_LPAE_WRITE_ALLOC 0x4Dull
--/* Set to implementation defined, outer caching */
--#define AS_MEMATTR_LPAE_OUTER_IMPL_DEF 0x88ull
--/* Set to write back memory, outer caching */
--#define AS_MEMATTR_LPAE_OUTER_WA 0x8Dull
--/* There is no LPAE support for non-cacheable, since the memory type is always
-- * write-back.
-- * Marking this setting as reserved for LPAE
-- */
--#define AS_MEMATTR_LPAE_NON_CACHEABLE_RESERVED
--
--/* L2_MMU_CONFIG register */
--#define L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY_SHIFT (23)
--#define L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY (0x1 << L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY_SHIFT)
--
--/* End L2_MMU_CONFIG register */
--
--/* THREAD_* registers */
--
--/* THREAD_FEATURES IMPLEMENTATION_TECHNOLOGY values */
--#define IMPLEMENTATION_UNSPECIFIED 0
--#define IMPLEMENTATION_SILICON 1
--#define IMPLEMENTATION_FPGA 2
--#define IMPLEMENTATION_MODEL 3
--
--/* Default values when registers are not supported by the implemented hardware */
--#define THREAD_MT_DEFAULT 256
--#define THREAD_MWS_DEFAULT 256
--#define THREAD_MBS_DEFAULT 256
--#define THREAD_MR_DEFAULT 1024
--#define THREAD_MTQ_DEFAULT 4
--#define THREAD_MTGS_DEFAULT 10
--
--/* End THREAD_* registers */
--
--/* SHADER_CONFIG register */
--#define SC_LS_ALLOW_ATTR_TYPES (1ul << 16)
--#define SC_TLS_HASH_ENABLE (1ul << 17)
--#define SC_LS_ATTR_CHECK_DISABLE (1ul << 18)
--#define SC_VAR_ALGORITHM (1ul << 29)
--/* End SHADER_CONFIG register */
--
--/* TILER_CONFIG register */
--#define TC_CLOCK_GATE_OVERRIDE (1ul << 0)
--/* End TILER_CONFIG register */
--
--/* L2_CONFIG register */
--#define L2_CONFIG_SIZE_SHIFT 16
--#define L2_CONFIG_SIZE_MASK (0xFFul << L2_CONFIG_SIZE_SHIFT)
--#define L2_CONFIG_HASH_SHIFT 24
--#define L2_CONFIG_HASH_MASK (0xFFul << L2_CONFIG_HASH_SHIFT)
--/* End L2_CONFIG register */
--
--/* IDVS_GROUP register */
--#define IDVS_GROUP_SIZE_SHIFT (16)
--#define IDVS_GROUP_MAX_SIZE (0x3F)
--
- #endif /* _KBASE_GPU_REGMAP_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/Kbuild
-index 3d9cf80..96977e9 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2016-2018 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2016-2018, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,14 +16,20 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- mali_kbase-y += \
-- ipa/mali_kbase_ipa_simple.o \
-- ipa/mali_kbase_ipa.o \
-- ipa/mali_kbase_ipa_vinstr_g7x.o \
-- ipa/mali_kbase_ipa_vinstr_common.o
-+ ipa/mali_kbase_ipa_simple.o \
-+ ipa/mali_kbase_ipa.o
-+
-+mali_kbase-$(CONFIG_DEBUG_FS) += ipa/mali_kbase_ipa_debugfs.o
-
--mali_kbase-$(CONFIG_DEBUG_FS) += ipa/mali_kbase_ipa_debugfs.o
-\ No newline at end of file
-+ifeq ($(MALI_USE_CSF),1)
-+ mali_kbase-y += \
-+ ipa/backend/mali_kbase_ipa_counter_csf.o \
-+ ipa/backend/mali_kbase_ipa_counter_common_csf.o
-+else
-+ mali_kbase-y += \
-+ ipa/backend/mali_kbase_ipa_counter_jm.o \
-+ ipa/backend/mali_kbase_ipa_counter_common_jm.o
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_csf.c
-new file mode 100644
-index 0000000..81dc56b
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_csf.c
-@@ -0,0 +1,457 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_ipa_counter_common_csf.h"
-+#include "ipa/mali_kbase_ipa_debugfs.h"
-+
-+#define DEFAULT_SCALING_FACTOR 5
-+
-+/* If the value of GPU_ACTIVE is below this, use the simple model
-+ * instead, to avoid extrapolating small amounts of counter data across
-+ * large sample periods.
-+ */
-+#define DEFAULT_MIN_SAMPLE_CYCLES 10000
-+
-+/* Typical value for the sampling interval is expected to be less than 100ms,
-+ * So 5 seconds is a reasonable upper limit for the time gap between the
-+ * 2 samples.
-+ */
-+#define MAX_SAMPLE_INTERVAL_MS ((s64)5000)
-+
-+/* Maximum increment that is expected for a counter value during a sampling
-+ * interval is derived assuming
-+ * - max sampling interval of 1 second.
-+ * - max GPU frequency of 2 GHz.
-+ * - max number of cores as 32.
-+ * - max increment of 4 in per core counter value at every clock cycle.
-+ *
-+ * So max increment = 2 * 10^9 * 32 * 4 = ~2^38.
-+ * If a counter increases by an amount greater than this value, then an error
-+ * will be returned and the simple power model will be used.
-+ */
-+#define MAX_COUNTER_INCREMENT (((u64)1 << 38) - 1)
-+
-+static inline s64 kbase_ipa_add_saturate(s64 a, s64 b)
-+{
-+ s64 rtn;
-+
-+ if (a > 0 && (S64_MAX - a) < b)
-+ rtn = S64_MAX;
-+ else if (a < 0 && (S64_MIN - a) > b)
-+ rtn = S64_MIN;
-+ else
-+ rtn = a + b;
-+
-+ return rtn;
-+}
-+
-+static s64 kbase_ipa_group_energy(s32 coeff, u64 counter_value)
-+{
-+ /* Range: 0 < counter_value < 2^38 */
-+
-+ /* Range: -2^59 < ret < 2^59 (as -2^21 < coeff < 2^21) */
-+ return counter_value * (s64)coeff;
-+}
-+
-+/**
-+ * kbase_ipa_attach_ipa_control() - register with kbase_ipa_control
-+ * @model_data: Pointer to counter model data
-+ *
-+ * Register IPA counter model as a client of kbase_ipa_control, which
-+ * provides an interface to retreive the accumulated value of hardware
-+ * counters to calculate energy consumption.
-+ *
-+ * Return: 0 on success, or an error code.
-+ */
-+static int
-+kbase_ipa_attach_ipa_control(struct kbase_ipa_counter_model_data *model_data)
-+{
-+ struct kbase_device *kbdev = model_data->kbdev;
-+ struct kbase_ipa_control_perf_counter *perf_counters;
-+ u32 cnt_idx = 0;
-+ int err;
-+ size_t i;
-+
-+ /* Value for GPU_ACTIVE counter also needs to be queried. It is required
-+ * for the normalization of top-level and shader core counters.
-+ */
-+ model_data->num_counters = 1 + model_data->num_top_level_cntrs +
-+ model_data->num_shader_cores_cntrs;
-+
-+ perf_counters = kcalloc(model_data->num_counters,
-+ sizeof(*perf_counters), GFP_KERNEL);
-+
-+ if (!perf_counters) {
-+ dev_err(kbdev->dev,
-+ "Failed to allocate memory for perf_counters array");
-+ return -ENOMEM;
-+ }
-+
-+ /* Fill in the description for GPU_ACTIVE counter which is always
-+ * needed, as mentioned above, regardless of the energy model used
-+ * by the CSF GPUs.
-+ */
-+ perf_counters[cnt_idx].type = KBASE_IPA_CORE_TYPE_CSHW;
-+ perf_counters[cnt_idx].idx = GPU_ACTIVE_CNT_IDX;
-+ perf_counters[cnt_idx].gpu_norm = false;
-+ perf_counters[cnt_idx].scaling_factor = 1;
-+ cnt_idx++;
-+
-+ for (i = 0; i < model_data->num_top_level_cntrs; ++i) {
-+ const struct kbase_ipa_counter *counter =
-+ &model_data->top_level_cntrs_def[i];
-+
-+ perf_counters[cnt_idx].type = counter->counter_block_type;
-+ perf_counters[cnt_idx].idx = counter->counter_block_offset;
-+ perf_counters[cnt_idx].gpu_norm = false;
-+ perf_counters[cnt_idx].scaling_factor = 1;
-+ cnt_idx++;
-+ }
-+
-+ for (i = 0; i < model_data->num_shader_cores_cntrs; ++i) {
-+ const struct kbase_ipa_counter *counter =
-+ &model_data->shader_cores_cntrs_def[i];
-+
-+ perf_counters[cnt_idx].type = counter->counter_block_type;
-+ perf_counters[cnt_idx].idx = counter->counter_block_offset;
-+ perf_counters[cnt_idx].gpu_norm = false;
-+ perf_counters[cnt_idx].scaling_factor = 1;
-+ cnt_idx++;
-+ }
-+
-+ err = kbase_ipa_control_register(kbdev, perf_counters,
-+ model_data->num_counters,
-+ &model_data->ipa_control_client);
-+ if (err)
-+ dev_err(kbdev->dev,
-+ "Failed to register IPA with kbase_ipa_control");
-+
-+ kfree(perf_counters);
-+ return err;
-+}
-+
-+/**
-+ * kbase_ipa_detach_ipa_control() - De-register from kbase_ipa_control.
-+ * @model_data: Pointer to counter model data
-+ */
-+static void
-+kbase_ipa_detach_ipa_control(struct kbase_ipa_counter_model_data *model_data)
-+{
-+ if (model_data->ipa_control_client) {
-+ kbase_ipa_control_unregister(model_data->kbdev,
-+ model_data->ipa_control_client);
-+ model_data->ipa_control_client = NULL;
-+ }
-+}
-+
-+static int calculate_coeff(struct kbase_ipa_counter_model_data *model_data,
-+ const struct kbase_ipa_counter *const cnt_defs,
-+ size_t num_counters, s32 *counter_coeffs,
-+ u64 *counter_values, u32 active_cycles, u32 *coeffp)
-+{
-+ u64 coeff = 0, coeff_mul = 0;
-+ s64 total_energy = 0;
-+ size_t i;
-+
-+ /* Range for the 'counter_value' is [0, 2^38)
-+ * Range for the 'coeff' is [-2^21, 2^21]
-+ * So range for the 'group_energy' is [-2^59, 2^59) and range for the
-+ * 'total_energy' is +/- 2^59 * number of IPA groups (~16), i.e.
-+ * [-2^63, 2^63).
-+ */
-+ for (i = 0; i < num_counters; i++) {
-+ s32 coeff = counter_coeffs[i];
-+ u64 counter_value = counter_values[i];
-+ s64 group_energy = kbase_ipa_group_energy(coeff, counter_value);
-+
-+ if (counter_value > MAX_COUNTER_INCREMENT) {
-+ dev_warn(model_data->kbdev->dev,
-+ "Increment in counter %s more than expected",
-+ cnt_defs[i].name);
-+ return -ERANGE;
-+ }
-+
-+ total_energy =
-+ kbase_ipa_add_saturate(total_energy, group_energy);
-+ }
-+
-+ /* Range: 0 <= coeff < 2^63 */
-+ if (total_energy >= 0)
-+ coeff = total_energy;
-+ else
-+ dev_dbg(model_data->kbdev->dev,
-+ "Energy value came negative as %lld", total_energy);
-+
-+ /* Range: 0 <= coeff < 2^63 (because active_cycles >= 1). However, this
-+ * can be constrained further: the value of counters that are being
-+ * used for dynamic power estimation can only increment by about 128
-+ * maximum per clock cycle. This is because max number of shader
-+ * cores is expected to be 32 (max number of L2 slices is expected to
-+ * be 8) and some counters (per shader core) like SC_BEATS_RD_TEX_EXT &
-+ * SC_EXEC_STARVE_ARITH can increment by 4 every clock cycle.
-+ * Each "beat" is defined as 128 bits and each shader core can
-+ * (currently) do 512 bits read and 512 bits write to/from the L2
-+ * cache per cycle, so the SC_BEATS_RD_TEX_EXT counter can increment
-+ * [0, 4] per shader core per cycle.
-+ * We can thus write the range of 'coeff' in terms of active_cycles:
-+ *
-+ * coeff = SUM(coeffN * counterN * num_cores_for_counterN)
-+ * coeff <= SUM(coeffN * counterN) * max_cores
-+ * coeff <= num_IPA_groups * max_coeff * max_counter * max_cores
-+ * (substitute max_counter = 2^2 * active_cycles)
-+ * coeff <= num_IPA_groups * max_coeff * 2^2 * active_cycles * max_cores
-+ * coeff <= 2^4 * 2^21 * 2^2 * active_cycles * 2^5
-+ * coeff <= 2^32 * active_cycles
-+ *
-+ * So after the division: 0 <= coeff <= 2^32
-+ */
-+ coeff = div_u64(coeff, active_cycles);
-+
-+ /* Not all models were derived at the same reference voltage. Voltage
-+ * scaling is done by multiplying by V^2, so we need to *divide* by
-+ * Vref^2 here.
-+ * Range: 0 <= coeff <= 2^35
-+ */
-+ coeff = div_u64(coeff * 1000, max(model_data->reference_voltage, 1));
-+ /* Range: 0 <= coeff <= 2^38 */
-+ coeff = div_u64(coeff * 1000, max(model_data->reference_voltage, 1));
-+
-+ /* Scale by user-specified integer factor.
-+ * Range: 0 <= coeff_mul < 2^43
-+ */
-+ coeff_mul = coeff * model_data->scaling_factor;
-+
-+ /* The power models have results with units
-+ * mW/(MHz V^2), i.e. nW/(Hz V^2). With precision of 1/1000000, this
-+ * becomes fW/(Hz V^2), which are the units of coeff_mul. However,
-+ * kbase_scale_dynamic_power() expects units of pW/(Hz V^2), so divide
-+ * by 1000.
-+ * Range: 0 <= coeff_mul < 2^33
-+ */
-+ coeff_mul = div_u64(coeff_mul, 1000u);
-+
-+ /* Clamp to a sensible range - 2^16 gives about 14W at 400MHz/750mV */
-+ *coeffp = clamp(coeff_mul, (u64)0, (u64)1 << 16);
-+
-+ return 0;
-+}
-+
-+int kbase_ipa_counter_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp)
-+{
-+ struct kbase_ipa_counter_model_data *model_data =
-+ (struct kbase_ipa_counter_model_data *)model->model_data;
-+ struct kbase_device *kbdev = model->kbdev;
-+ s32 *counter_coeffs_p = model_data->counter_coeffs;
-+ u64 *cnt_values_p = model_data->counter_values;
-+ const u64 num_counters = model_data->num_counters;
-+ u32 active_cycles;
-+ ktime_t now, diff;
-+ s64 diff_ms;
-+ int ret;
-+
-+ lockdep_assert_held(&kbdev->ipa.lock);
-+
-+ /* The last argument is supposed to be a pointer to the location that
-+ * will store the time for which GPU has been in protected mode since
-+ * last query. This can be passed as NULL as counter model itself will
-+ * not be used when GPU enters protected mode, as IPA is supposed to
-+ * switch to the simple power model.
-+ */
-+ ret = kbase_ipa_control_query(kbdev,
-+ model_data->ipa_control_client,
-+ cnt_values_p, num_counters, NULL);
-+ if (WARN_ON(ret))
-+ return ret;
-+
-+ now = ktime_get();
-+ diff = ktime_sub(now, kbdev->ipa.last_sample_time);
-+ diff_ms = ktime_to_ms(diff);
-+
-+ kbdev->ipa.last_sample_time = now;
-+
-+ /* The counter values cannot be relied upon if the sampling interval was
-+ * too long. Typically this will happen when the polling is started
-+ * after the temperature has risen above a certain trip point. After
-+ * that regular calls every 25-100 ms interval are expected.
-+ */
-+ if (diff_ms > MAX_SAMPLE_INTERVAL_MS) {
-+ dev_dbg(kbdev->dev,
-+ "Last sample was taken %lld milli seconds ago",
-+ diff_ms);
-+ return -EOVERFLOW;
-+ }
-+
-+ /* Range: 0 (GPU not used at all), to the max sampling interval, say
-+ * 1 seconds, * max GPU frequency (GPU 100% utilized).
-+ * 0 <= active_cycles <= 1 * ~2GHz
-+ * 0 <= active_cycles < 2^31
-+ */
-+ if (*cnt_values_p > U32_MAX) {
-+ dev_warn(kbdev->dev,
-+ "Increment in GPU_ACTIVE counter more than expected");
-+ return -ERANGE;
-+ }
-+
-+ active_cycles = (u32)*cnt_values_p;
-+
-+ /* If the value of the active_cycles is less than the threshold, then
-+ * return an error so that IPA framework can approximate using the
-+ * cached simple model results instead. This may be more accurate
-+ * than extrapolating using a very small counter dump.
-+ */
-+ if (active_cycles < (u32)max(model_data->min_sample_cycles, 0))
-+ return -ENODATA;
-+
-+ /* Range: 1 <= active_cycles < 2^31 */
-+ active_cycles = max(1u, active_cycles);
-+
-+ cnt_values_p++;
-+ ret = calculate_coeff(model_data, model_data->top_level_cntrs_def,
-+ model_data->num_top_level_cntrs,
-+ counter_coeffs_p, cnt_values_p, active_cycles,
-+ &coeffp[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL]);
-+ if (ret)
-+ return ret;
-+
-+ cnt_values_p += model_data->num_top_level_cntrs;
-+ counter_coeffs_p += model_data->num_top_level_cntrs;
-+ ret = calculate_coeff(model_data, model_data->shader_cores_cntrs_def,
-+ model_data->num_shader_cores_cntrs,
-+ counter_coeffs_p, cnt_values_p, active_cycles,
-+ &coeffp[KBASE_IPA_BLOCK_TYPE_SHADER_CORES]);
-+
-+ return ret;
-+}
-+
-+void kbase_ipa_counter_reset_data(struct kbase_ipa_model *model)
-+{
-+ struct kbase_ipa_counter_model_data *model_data =
-+ (struct kbase_ipa_counter_model_data *)model->model_data;
-+ u64 *cnt_values_p = model_data->counter_values;
-+ const u64 num_counters = model_data->num_counters;
-+ int ret;
-+
-+ lockdep_assert_held(&model->kbdev->ipa.lock);
-+
-+ ret = kbase_ipa_control_query(model->kbdev,
-+ model_data->ipa_control_client,
-+ cnt_values_p, num_counters, NULL);
-+ WARN_ON(ret);
-+}
-+
-+int kbase_ipa_counter_common_model_init(struct kbase_ipa_model *model,
-+ const struct kbase_ipa_counter *top_level_cntrs_def,
-+ size_t num_top_level_cntrs,
-+ const struct kbase_ipa_counter *shader_cores_cntrs_def,
-+ size_t num_shader_cores_cntrs,
-+ s32 reference_voltage)
-+{
-+ struct kbase_ipa_counter_model_data *model_data;
-+ s32 *counter_coeffs_p;
-+ int err = 0;
-+ size_t i;
-+
-+ if (!model || !top_level_cntrs_def || !shader_cores_cntrs_def ||
-+ !num_top_level_cntrs || !num_shader_cores_cntrs)
-+ return -EINVAL;
-+
-+ model_data = kzalloc(sizeof(*model_data), GFP_KERNEL);
-+ if (!model_data)
-+ return -ENOMEM;
-+
-+ model_data->kbdev = model->kbdev;
-+
-+ model_data->top_level_cntrs_def = top_level_cntrs_def;
-+ model_data->num_top_level_cntrs = num_top_level_cntrs;
-+
-+ model_data->shader_cores_cntrs_def = shader_cores_cntrs_def;
-+ model_data->num_shader_cores_cntrs = num_shader_cores_cntrs;
-+
-+ model->model_data = (void *)model_data;
-+
-+ counter_coeffs_p = model_data->counter_coeffs;
-+
-+ for (i = 0; i < model_data->num_top_level_cntrs; ++i) {
-+ const struct kbase_ipa_counter *counter =
-+ &model_data->top_level_cntrs_def[i];
-+
-+ *counter_coeffs_p = counter->coeff_default_value;
-+
-+ err = kbase_ipa_model_add_param_s32(
-+ model, counter->name, counter_coeffs_p, 1, false);
-+ if (err)
-+ goto exit;
-+
-+ counter_coeffs_p++;
-+ }
-+
-+ for (i = 0; i < model_data->num_shader_cores_cntrs; ++i) {
-+ const struct kbase_ipa_counter *counter =
-+ &model_data->shader_cores_cntrs_def[i];
-+
-+ *counter_coeffs_p = counter->coeff_default_value;
-+
-+ err = kbase_ipa_model_add_param_s32(
-+ model, counter->name, counter_coeffs_p, 1, false);
-+ if (err)
-+ goto exit;
-+
-+ counter_coeffs_p++;
-+ }
-+
-+ model_data->scaling_factor = DEFAULT_SCALING_FACTOR;
-+ err = kbase_ipa_model_add_param_s32(
-+ model, "scale", &model_data->scaling_factor, 1, false);
-+ if (err)
-+ goto exit;
-+
-+ model_data->min_sample_cycles = DEFAULT_MIN_SAMPLE_CYCLES;
-+ err = kbase_ipa_model_add_param_s32(model, "min_sample_cycles",
-+ &model_data->min_sample_cycles, 1,
-+ false);
-+ if (err)
-+ goto exit;
-+
-+ model_data->reference_voltage = reference_voltage;
-+ err = kbase_ipa_model_add_param_s32(model, "reference_voltage",
-+ &model_data->reference_voltage, 1,
-+ false);
-+ if (err)
-+ goto exit;
-+
-+ err = kbase_ipa_attach_ipa_control(model_data);
-+
-+exit:
-+ if (err) {
-+ kbase_ipa_model_param_free_all(model);
-+ kfree(model_data);
-+ }
-+ return err;
-+}
-+
-+void kbase_ipa_counter_common_model_term(struct kbase_ipa_model *model)
-+{
-+ struct kbase_ipa_counter_model_data *model_data =
-+ (struct kbase_ipa_counter_model_data *)model->model_data;
-+
-+ kbase_ipa_detach_ipa_control(model_data);
-+ kfree(model_data);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_csf.h b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_csf.h
-new file mode 100644
-index 0000000..37d2efc
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_csf.h
-@@ -0,0 +1,159 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_IPA_COUNTER_COMMON_CSF_H_
-+#define _KBASE_IPA_COUNTER_COMMON_CSF_H_
-+
-+#include "mali_kbase.h"
-+#include "csf/ipa_control/mali_kbase_csf_ipa_control.h"
-+
-+/* Maximum number of HW counters used by the IPA counter model. */
-+#define KBASE_IPA_MAX_COUNTER_DEF_NUM 24
-+
-+struct kbase_ipa_counter_model_data;
-+
-+/**
-+ * struct kbase_ipa_counter_model_data - IPA counter model context per device
-+ * @kbdev: Pointer to kbase device
-+ * @ipa_control_client: Handle returned on registering IPA counter model as a
-+ * client of kbase_ipa_control.
-+ * @top_level_cntrs_def: Array of description of HW counters used by the IPA
-+ * counter model for top-level.
-+ * @num_top_level_cntrs: Number of elements in @top_level_cntrs_def array.
-+ * @shader_cores_cntrs_def: Array of description of HW counters used by the IPA
-+ * counter model for shader cores.
-+ * @num_shader_cores_cntrs: Number of elements in @shader_cores_cntrs_def array.
-+ * @counter_coeffs: Buffer to store coefficient value used for HW counters
-+ * @counter_values: Buffer to store the accumulated value of HW counters
-+ * retreived from kbase_ipa_control.
-+ * @num_counters: Number of counters queried from kbase_ipa_control.
-+ * @reference_voltage: voltage, in mV, of the operating point used when
-+ * deriving the power model coefficients. Range approx
-+ * 0.1V - 5V (~= 8V): 2^7 <= reference_voltage <= 2^13
-+ * @scaling_factor: User-specified power scaling factor. This is an
-+ * integer, which is multiplied by the power coefficient
-+ * just before OPP scaling.
-+ * Range approx 0-32: 0 < scaling_factor < 2^5
-+ * @min_sample_cycles: If the value of the GPU_ACTIVE counter (the number of
-+ * cycles the GPU was working) is less than
-+ * min_sample_cycles, the counter model will return an
-+ * error, causing the IPA framework to approximate using
-+ * the cached simple model results instead. This may be
-+ * more accurate than extrapolating using a very small
-+ * counter dump.
-+ */
-+struct kbase_ipa_counter_model_data {
-+ struct kbase_device *kbdev;
-+ void *ipa_control_client;
-+ const struct kbase_ipa_counter *top_level_cntrs_def;
-+ size_t num_top_level_cntrs;
-+ const struct kbase_ipa_counter *shader_cores_cntrs_def;
-+ size_t num_shader_cores_cntrs;
-+ s32 counter_coeffs[KBASE_IPA_MAX_COUNTER_DEF_NUM];
-+ u64 counter_values[KBASE_IPA_MAX_COUNTER_DEF_NUM];
-+ u64 num_counters;
-+ s32 reference_voltage;
-+ s32 scaling_factor;
-+ s32 min_sample_cycles;
-+};
-+
-+/**
-+ * struct kbase_ipa_counter - represents a single HW counter used by IPA model
-+ * @name: Name of the HW counter used by IPA counter model
-+ * for energy estimation.
-+ * @coeff_default_value: Default value of coefficient for the counter.
-+ * Coefficients are interpreted as fractions where the
-+ * denominator is 1000000.
-+ * @counter_block_offset: Index to the counter within the counter block of
-+ * type @counter_block_type.
-+ * @counter_block_type: Type of the counter block.
-+ */
-+struct kbase_ipa_counter {
-+ const char *name;
-+ s32 coeff_default_value;
-+ u32 counter_block_offset;
-+ enum kbase_ipa_core_type counter_block_type;
-+};
-+
-+/**
-+ * kbase_ipa_counter_dynamic_coeff() - calculate dynamic power based on HW counters
-+ * @model: pointer to instantiated model
-+ * @coeffp: pointer to location where calculated power, in
-+ * pW/(Hz V^2), is stored for top level and shader cores.
-+ *
-+ * This is a GPU-agnostic implementation of the get_dynamic_coeff()
-+ * function of an IPA model. It relies on the model being populated
-+ * with GPU-specific attributes at initialization time.
-+ *
-+ * Return: 0 on success, or an error code.
-+ */
-+int kbase_ipa_counter_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp);
-+
-+/**
-+ * kbase_ipa_counter_reset_data() - Reset the counters data used for dynamic
-+ * power estimation
-+ * @model: pointer to instantiated model
-+ *
-+ * Retrieve the accumulated value of HW counters from the kbase_ipa_control
-+ * component, without doing any processing, which is effectively a reset as the
-+ * next call to kbase_ipa_counter_dynamic_coeff() will see the increment in
-+ * counter values from this point onwards.
-+ */
-+void kbase_ipa_counter_reset_data(struct kbase_ipa_model *model);
-+
-+/**
-+ * kbase_ipa_counter_common_model_init() - initialize ipa power model
-+ * @model: Pointer to the ipa power model to initialize
-+ * @top_level_cntrs_def: Array corresponding to the HW counters used in the
-+ * top level counter model, contains the counter index,
-+ * default value of the coefficient.
-+ * @num_top_level_cntrs: Number of elements in the array @top_level_cntrs_def
-+ * @shader_cores_cntrs_def: Array corresponding to the HW counters used in the
-+ * shader cores counter model, contains the counter index,
-+ * default value of the coefficient.
-+ * @num_shader_cores_cntrs: Number of elements in the array
-+ * @shader_cores_cntrs_def.
-+ * @reference_voltage: voltage, in mV, of the operating point used when
-+ * deriving the power model coefficients.
-+ *
-+ * This function performs initialization steps common for ipa counter based
-+ * model of all CSF GPUs. The set of counters and their respective weights
-+ * could be different for each GPU. The tuple of counter index and weight
-+ * is passed via @top_level_cntrs_def and @shader_cores_cntrs_def array.
-+ *
-+ * Return: 0 on success, error code otherwise
-+ */
-+int kbase_ipa_counter_common_model_init(struct kbase_ipa_model *model,
-+ const struct kbase_ipa_counter *top_level_cntrs_def,
-+ size_t num_top_level_cntrs,
-+ const struct kbase_ipa_counter *shader_cores_cntrs_def,
-+ size_t num_shader_cores_cntrs,
-+ s32 reference_voltage);
-+/**
-+ * kbase_ipa_counter_common_model_term() - terminate ipa power model
-+ * @model: ipa power model to terminate
-+ *
-+ * This function performs all necessary steps to terminate ipa power model
-+ * including clean up of resources allocated to hold model data.
-+ */
-+void kbase_ipa_counter_common_model_term(struct kbase_ipa_model *model);
-+
-+#endif /* _KBASE_IPA_COUNTER_COMMON_CSF_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_vinstr_common.c b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_jm.c
-similarity index 95%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_vinstr_common.c
-rename to dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_jm.c
-index 9fae8f1..4737b0e 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_vinstr_common.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_jm.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2017-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#include "mali_kbase_ipa_vinstr_common.h"
--#include "mali_kbase_ipa_debugfs.h"
-+#include "mali_kbase_ipa_counter_common_jm.h"
-+#include "ipa/mali_kbase_ipa_debugfs.h"
-
- #define DEFAULT_SCALING_FACTOR 5
-
-@@ -145,6 +144,9 @@ int kbase_ipa_attach_vinstr(struct kbase_ipa_model_vinstr_data *model_data)
-
- kbase_hwcnt_enable_map_enable_all(&enable_map);
-
-+ /* Disable cycle counter only. */
-+ enable_map.clk_enable_map = 0;
-+
- errcode = kbase_hwcnt_virtualizer_client_create(
- hvirt, &enable_map, &model_data->hvirt_cli);
- kbase_hwcnt_enable_map_free(&enable_map);
-@@ -270,6 +272,12 @@ err0:
- return err;
- }
-
-+void kbase_ipa_vinstr_reset_data(struct kbase_ipa_model *model)
-+{
-+ /* Currently not implemented */
-+ WARN_ON_ONCE(1);
-+}
-+
- int kbase_ipa_vinstr_common_model_init(struct kbase_ipa_model *model,
- const struct kbase_ipa_group *ipa_groups_def,
- size_t ipa_group_size,
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_vinstr_common.h b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_jm.h
-similarity index 85%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_vinstr_common.h
-rename to dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_jm.h
-index 46e3cd4..3486a9b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_vinstr_common.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_common_jm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifndef _KBASE_IPA_VINSTR_COMMON_H_
--#define _KBASE_IPA_VINSTR_COMMON_H_
-+#ifndef _KBASE_IPA_COUNTER_COMMON_JM_H_
-+#define _KBASE_IPA_COUNTER_COMMON_JM_H_
-
- #include "mali_kbase.h"
- #include "mali_kbase_hwcnt_virtualizer.h"
-@@ -42,11 +41,13 @@
-
- struct kbase_ipa_model_vinstr_data;
-
--typedef u32 (*kbase_ipa_get_active_cycles_callback)(struct kbase_ipa_model_vinstr_data *);
-+typedef u32
-+kbase_ipa_get_active_cycles_callback(struct kbase_ipa_model_vinstr_data *);
-
- /**
- * struct kbase_ipa_model_vinstr_data - IPA context per device
- * @kbdev: pointer to kbase device
-+ * @group_values: values of coefficients for IPA groups
- * @groups_def: Array of IPA groups.
- * @groups_def_num: Number of elements in the array of IPA groups.
- * @get_active_cycles: Callback to return number of active cycles during
-@@ -73,7 +74,7 @@ struct kbase_ipa_model_vinstr_data {
- s32 group_values[KBASE_IPA_MAX_GROUP_DEF_NUM];
- const struct kbase_ipa_group *groups_def;
- size_t groups_def_num;
-- kbase_ipa_get_active_cycles_callback get_active_cycles;
-+ kbase_ipa_get_active_cycles_callback *get_active_cycles;
- struct kbase_hwcnt_virtualizer_client *hvirt_cli;
- struct kbase_hwcnt_dump_buffer dump_buf;
- s32 reference_voltage;
-@@ -102,7 +103,7 @@ struct kbase_ipa_group {
- * @model_data: pointer to model data
- * @coeff: model coefficient. Unity is ~2^20, so range approx
- * +/- 4.0: -2^22 < coeff < 2^22
-- * @counter offset in bytes of the counter used to calculate energy
-+ * @counter: offset in bytes of the counter used to calculate energy
- * for IPA group
- *
- * Calculate energy estimation based on hardware counter `counter'
-@@ -149,7 +150,7 @@ s64 kbase_ipa_single_counter(
-
- /**
- * attach_vinstr() - attach a vinstr_buffer to an IPA model.
-- * @model_data pointer to model data
-+ * @model_data: pointer to model data
- *
- * Attach a vinstr_buffer to an IPA model. The vinstr_buffer
- * allows access to the hardware counters used to calculate
-@@ -161,7 +162,7 @@ int kbase_ipa_attach_vinstr(struct kbase_ipa_model_vinstr_data *model_data);
-
- /**
- * detach_vinstr() - detach a vinstr_buffer from an IPA model.
-- * @model_data pointer to model data
-+ * @model_data: pointer to model data
- *
- * Detach a vinstr_buffer from an IPA model.
- */
-@@ -181,6 +182,19 @@ void kbase_ipa_detach_vinstr(struct kbase_ipa_model_vinstr_data *model_data);
- */
- int kbase_ipa_vinstr_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp);
-
-+/**
-+ * kbase_ipa_vinstr_reset_data() - Reset the counters data used for dynamic
-+ * power estimation
-+ * @model: pointer to instantiated model
-+ *
-+ * Currently it is not implemented for JM GPUs.
-+ * When implemented it is expected to retrieve the accumulated value of HW
-+ * counters from the Vinstr component, without doing any processing, which is
-+ * effectively a reset as the next call to kbase_ipa_counter_dynamic_coeff()
-+ * will see the increment in counter values from this point onwards.
-+ */
-+void kbase_ipa_vinstr_reset_data(struct kbase_ipa_model *model);
-+
- /**
- * kbase_ipa_vinstr_common_model_init() - initialize ipa power model
- * @model: ipa power model to initialize
-@@ -202,7 +216,7 @@ int kbase_ipa_vinstr_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp);
- int kbase_ipa_vinstr_common_model_init(struct kbase_ipa_model *model,
- const struct kbase_ipa_group *ipa_groups_def,
- size_t ipa_group_size,
-- kbase_ipa_get_active_cycles_callback get_active_cycles,
-+ kbase_ipa_get_active_cycles_callback *get_active_cycles,
- s32 reference_voltage);
-
- /**
-@@ -214,4 +228,4 @@ int kbase_ipa_vinstr_common_model_init(struct kbase_ipa_model *model,
- */
- void kbase_ipa_vinstr_common_model_term(struct kbase_ipa_model *model);
-
--#endif /* _KBASE_IPA_VINSTR_COMMON_H_ */
-+#endif /* _KBASE_IPA_COUNTER_COMMON_JM_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_csf.c
-new file mode 100644
-index 0000000..1852c3c
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_csf.c
-@@ -0,0 +1,171 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_ipa_counter_common_csf.h"
-+#include "mali_kbase.h"
-+
-+/* MEMSYS counter block offsets */
-+#define L2_RD_MSG_IN (16)
-+#define L2_WR_MSG_IN (18)
-+#define L2_READ_LOOKUP (26)
-+#define L2_EXT_WRITE_NOSNP_FULL (43)
-+
-+/* SC counter block offsets */
-+#define FRAG_QUADS_EZS_UPDATE (13)
-+#define FULL_QUAD_WARPS (21)
-+#define EXEC_INSTR_FMA (27)
-+#define EXEC_INSTR_CVT (28)
-+#define TEX_FILT_NUM_OPS (39)
-+#define LS_MEM_READ_SHORT (45)
-+#define LS_MEM_WRITE_SHORT (47)
-+#define VARY_SLOT_16 (51)
-+
-+/* Tiler counter block offsets */
-+#define IDVS_POS_SHAD_STALL (23)
-+#define PREFETCH_STALL (25)
-+#define VFETCH_POS_READ_WAIT (29)
-+#define VFETCH_VERTEX_WAIT (30)
-+#define IDVS_VAR_SHAD_STALL (38)
-+
-+#define COUNTER_DEF(cnt_name, coeff, cnt_idx, block_type) \
-+ { \
-+ .name = cnt_name, \
-+ .coeff_default_value = coeff, \
-+ .counter_block_offset = cnt_idx, \
-+ .counter_block_type = block_type, \
-+ }
-+
-+#define CSHW_COUNTER_DEF(cnt_name, coeff, cnt_idx) \
-+ COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_CSHW)
-+
-+#define MEMSYS_COUNTER_DEF(cnt_name, coeff, cnt_idx) \
-+ COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_MEMSYS)
-+
-+#define SC_COUNTER_DEF(cnt_name, coeff, cnt_idx) \
-+ COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_SHADER)
-+
-+#define TILER_COUNTER_DEF(cnt_name, coeff, cnt_idx) \
-+ COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_TILER)
-+
-+/* Tables of description of HW counters used by IPA counter model.
-+ *
-+ * These tables provide a description of each performance counter
-+ * used by the top level counter model for energy estimation.
-+ */
-+static const struct kbase_ipa_counter ipa_top_level_cntrs_def_todx[] = {
-+ MEMSYS_COUNTER_DEF("l2_rd_msg_in", 295631, L2_RD_MSG_IN),
-+ MEMSYS_COUNTER_DEF("l2_ext_write_nosnp_ull", 325168, L2_EXT_WRITE_NOSNP_FULL),
-+
-+ TILER_COUNTER_DEF("prefetch_stall", 145435, PREFETCH_STALL),
-+ TILER_COUNTER_DEF("idvs_var_shad_stall", -171917, IDVS_VAR_SHAD_STALL),
-+ TILER_COUNTER_DEF("idvs_pos_shad_stall", 109980, IDVS_POS_SHAD_STALL),
-+ TILER_COUNTER_DEF("vfetch_pos_read_wait", -119118, VFETCH_POS_READ_WAIT),
-+};
-+
-+
-+/* These tables provide a description of each performance counter
-+ * used by the shader cores counter model for energy estimation.
-+ */
-+static const struct kbase_ipa_counter ipa_shader_core_cntrs_def_todx[] = {
-+ SC_COUNTER_DEF("exec_instr_fma", 505449, EXEC_INSTR_FMA),
-+ SC_COUNTER_DEF("tex_filt_num_operations", 574869, TEX_FILT_NUM_OPS),
-+ SC_COUNTER_DEF("ls_mem_read_short", 60917, LS_MEM_READ_SHORT),
-+ SC_COUNTER_DEF("frag_quads_ezs_update", 694555, FRAG_QUADS_EZS_UPDATE),
-+ SC_COUNTER_DEF("ls_mem_write_short", 698290, LS_MEM_WRITE_SHORT),
-+ SC_COUNTER_DEF("vary_slot_16", 181069, VARY_SLOT_16),
-+};
-+
-+
-+#define IPA_POWER_MODEL_OPS(gpu, init_token) \
-+ const struct kbase_ipa_model_ops kbase_ ## gpu ## _ipa_model_ops = { \
-+ .name = "mali-" #gpu "-power-model", \
-+ .init = kbase_ ## init_token ## _power_model_init, \
-+ .term = kbase_ipa_counter_common_model_term, \
-+ .get_dynamic_coeff = kbase_ipa_counter_dynamic_coeff, \
-+ .reset_counter_data = kbase_ipa_counter_reset_data, \
-+ }; \
-+ KBASE_EXPORT_TEST_API(kbase_ ## gpu ## _ipa_model_ops)
-+
-+#define STANDARD_POWER_MODEL(gpu, reference_voltage) \
-+ static int kbase_ ## gpu ## _power_model_init(\
-+ struct kbase_ipa_model *model) \
-+ { \
-+ BUILD_BUG_ON((1 + \
-+ ARRAY_SIZE(ipa_top_level_cntrs_def_ ## gpu) +\
-+ ARRAY_SIZE(ipa_shader_core_cntrs_def_ ## gpu)) > \
-+ KBASE_IPA_MAX_COUNTER_DEF_NUM); \
-+ return kbase_ipa_counter_common_model_init(model, \
-+ ipa_top_level_cntrs_def_ ## gpu, \
-+ ARRAY_SIZE(ipa_top_level_cntrs_def_ ## gpu), \
-+ ipa_shader_core_cntrs_def_ ## gpu, \
-+ ARRAY_SIZE(ipa_shader_core_cntrs_def_ ## gpu), \
-+ (reference_voltage)); \
-+ } \
-+ IPA_POWER_MODEL_OPS(gpu, gpu)
-+
-+
-+#define ALIAS_POWER_MODEL(gpu, as_gpu) \
-+ IPA_POWER_MODEL_OPS(gpu, as_gpu)
-+
-+/* Reference voltage value is 750 mV.
-+ */
-+STANDARD_POWER_MODEL(todx, 750);
-+
-+
-+/* Assuming LODX is an alias of TODX for IPA */
-+ALIAS_POWER_MODEL(lodx, todx);
-+
-+static const struct kbase_ipa_model_ops *ipa_counter_model_ops[] = {
-+ &kbase_todx_ipa_model_ops, &kbase_lodx_ipa_model_ops,
-+};
-+
-+const struct kbase_ipa_model_ops *kbase_ipa_counter_model_ops_find(
-+ struct kbase_device *kbdev, const char *name)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(ipa_counter_model_ops); ++i) {
-+ const struct kbase_ipa_model_ops *ops =
-+ ipa_counter_model_ops[i];
-+
-+ if (!strcmp(ops->name, name))
-+ return ops;
-+ }
-+
-+ dev_err(kbdev->dev, "power model \'%s\' not found\n", name);
-+
-+ return NULL;
-+}
-+
-+const char *kbase_ipa_counter_model_name_from_id(u32 gpu_id)
-+{
-+ const u32 prod_id = (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >>
-+ GPU_ID_VERSION_PRODUCT_ID_SHIFT;
-+
-+ switch (GPU_ID2_MODEL_MATCH_VALUE(prod_id)) {
-+ case GPU_ID2_PRODUCT_TODX:
-+ return "mali-todx-power-model";
-+ case GPU_ID2_PRODUCT_LODX:
-+ return "mali-lodx-power-model";
-+ default:
-+ return NULL;
-+ }
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_vinstr_g7x.c b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_jm.c
-similarity index 83%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_vinstr_g7x.c
-rename to dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_jm.c
-index 270b75e..2f4c9d9 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_vinstr_g7x.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/backend/mali_kbase_ipa_counter_jm.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2016-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2016-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,11 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-+
- #include <linux/thermal.h>
-
--#include "mali_kbase_ipa_vinstr_common.h"
-+#include "mali_kbase_ipa_counter_common_jm.h"
- #include "mali_kbase.h"
-
-
-@@ -97,7 +97,6 @@ static u32 kbase_g7x_power_model_get_sc_counter(struct kbase_ipa_model_vinstr_da
- const u32 sc_base = MEMSYS_BASE +
- (model_data->kbdev->gpu_props.props.l2_props.num_l2_slices *
- KBASE_IPA_NR_BYTES_PER_BLOCK);
--
- return sc_base + counter_block_offset;
- }
-
-@@ -178,7 +177,7 @@ static u32 kbase_g7x_get_active_cycles(
- return kbase_ipa_single_counter(model_data, 1, counter);
- }
-
--/** Table of IPA group definitions.
-+/* Table of IPA group definitions.
- *
- * For each IPA group, this table defines a function to access the given performance block counter (or counters,
- * if the operation needs to be iterated on multiple blocks) and calculate energy estimation.
-@@ -415,6 +414,39 @@ static const struct kbase_ipa_group ipa_groups_def_tbex[] = {
- },
- };
-
-+static const struct kbase_ipa_group ipa_groups_def_tbax[] = {
-+ {
-+ .name = "l2_access",
-+ .default_value = 599800,
-+ .op = kbase_g7x_sum_all_memsys_blocks,
-+ .counter_block_offset = MEMSYS_L2_ANY_LOOKUP,
-+ },
-+ {
-+ .name = "exec_instr_msg",
-+ .default_value = 1830200,
-+ .op = kbase_g7x_sum_all_shader_cores,
-+ .counter_block_offset = SC_EXEC_INSTR_MSG,
-+ },
-+ {
-+ .name = "exec_instr_fma",
-+ .default_value = 407300,
-+ .op = kbase_g7x_sum_all_shader_cores,
-+ .counter_block_offset = SC_EXEC_INSTR_FMA,
-+ },
-+ {
-+ .name = "tex_filt_num_operations",
-+ .default_value = 224500,
-+ .op = kbase_g7x_sum_all_shader_cores,
-+ .counter_block_offset = SC_TEX_FILT_NUM_OPERATIONS,
-+ },
-+ {
-+ .name = "gpu_active",
-+ .default_value = 153800,
-+ .op = kbase_g7x_jm_single_counter,
-+ .counter_block_offset = JM_GPU_ACTIVE,
-+ },
-+};
-+
-
- #define IPA_POWER_MODEL_OPS(gpu, init_token) \
- const struct kbase_ipa_model_ops kbase_ ## gpu ## _ipa_model_ops = { \
-@@ -422,6 +454,7 @@ static const struct kbase_ipa_group ipa_groups_def_tbex[] = {
- .init = kbase_ ## init_token ## _power_model_init, \
- .term = kbase_ipa_vinstr_common_model_term, \
- .get_dynamic_coeff = kbase_ipa_vinstr_dynamic_coeff, \
-+ .reset_counter_data = kbase_ipa_vinstr_reset_data, \
- }; \
- KBASE_EXPORT_TEST_API(kbase_ ## gpu ## _ipa_model_ops)
-
-@@ -449,8 +482,74 @@ STANDARD_POWER_MODEL(g52_r1, 1000);
- STANDARD_POWER_MODEL(g51, 1000);
- STANDARD_POWER_MODEL(g77, 1000);
- STANDARD_POWER_MODEL(tbex, 1000);
-+STANDARD_POWER_MODEL(tbax, 1000);
-
- /* g52 is an alias of g76 (TNOX) for IPA */
- ALIAS_POWER_MODEL(g52, g76);
- /* tnax is an alias of g77 (TTRX) for IPA */
- ALIAS_POWER_MODEL(tnax, g77);
-+
-+static const struct kbase_ipa_model_ops *ipa_counter_model_ops[] = {
-+ &kbase_g71_ipa_model_ops,
-+ &kbase_g72_ipa_model_ops,
-+ &kbase_g76_ipa_model_ops,
-+ &kbase_g52_ipa_model_ops,
-+ &kbase_g52_r1_ipa_model_ops,
-+ &kbase_g51_ipa_model_ops,
-+ &kbase_g77_ipa_model_ops,
-+ &kbase_tnax_ipa_model_ops,
-+ &kbase_tbex_ipa_model_ops,
-+ &kbase_tbax_ipa_model_ops
-+};
-+
-+const struct kbase_ipa_model_ops *kbase_ipa_counter_model_ops_find(
-+ struct kbase_device *kbdev, const char *name)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(ipa_counter_model_ops); ++i) {
-+ const struct kbase_ipa_model_ops *ops =
-+ ipa_counter_model_ops[i];
-+
-+ if (!strcmp(ops->name, name))
-+ return ops;
-+ }
-+
-+ dev_err(kbdev->dev, "power model \'%s\' not found\n", name);
-+
-+ return NULL;
-+}
-+
-+const char *kbase_ipa_counter_model_name_from_id(u32 gpu_id)
-+{
-+ const u32 prod_id = (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >>
-+ GPU_ID_VERSION_PRODUCT_ID_SHIFT;
-+
-+ switch (GPU_ID2_MODEL_MATCH_VALUE(prod_id)) {
-+ case GPU_ID2_PRODUCT_TMIX:
-+ return "mali-g71-power-model";
-+ case GPU_ID2_PRODUCT_THEX:
-+ return "mali-g72-power-model";
-+ case GPU_ID2_PRODUCT_TNOX:
-+ return "mali-g76-power-model";
-+ case GPU_ID2_PRODUCT_TSIX:
-+ return "mali-g51-power-model";
-+ case GPU_ID2_PRODUCT_TGOX:
-+ if ((gpu_id & GPU_ID2_VERSION_MAJOR) ==
-+ (0 << GPU_ID2_VERSION_MAJOR_SHIFT))
-+ /* g52 aliased to g76 power-model's ops */
-+ return "mali-g52-power-model";
-+ else
-+ return "mali-g52_r1-power-model";
-+ case GPU_ID2_PRODUCT_TNAX:
-+ return "mali-tnax-power-model";
-+ case GPU_ID2_PRODUCT_TTRX:
-+ return "mali-g77-power-model";
-+ case GPU_ID2_PRODUCT_TBEX:
-+ return "mali-tbex-power-model";
-+ case GPU_ID2_PRODUCT_TBAX:
-+ return "mali-tbax-power-model";
-+ default:
-+ return NULL;
-+ }
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa.c b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa.c
-old mode 100644
-new mode 100755
-index d663ccb..24d7b06
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2016-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2016-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,9 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-+
- #include <linux/thermal.h>
- #include <linux/devfreq_cooling.h>
- #include <linux/of.h>
-@@ -27,30 +27,19 @@
- #include "mali_kbase_ipa_debugfs.h"
- #include "mali_kbase_ipa_simple.h"
- #include "backend/gpu/mali_kbase_pm_internal.h"
--
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
-+#include "backend/gpu/mali_kbase_devfreq.h"
- #include <linux/pm_opp.h>
--#else
--#include <linux/opp.h>
--#define dev_pm_opp_find_freq_exact opp_find_freq_exact
--#define dev_pm_opp_get_voltage opp_get_voltage
--#define dev_pm_opp opp
--#endif
-
- #define KBASE_IPA_FALLBACK_MODEL_NAME "mali-simple-power-model"
-
--static const struct kbase_ipa_model_ops *kbase_ipa_all_model_ops[] = {
-- &kbase_simple_ipa_model_ops,
-- &kbase_g71_ipa_model_ops,
-- &kbase_g72_ipa_model_ops,
-- &kbase_g76_ipa_model_ops,
-- &kbase_g52_ipa_model_ops,
-- &kbase_g52_r1_ipa_model_ops,
-- &kbase_g51_ipa_model_ops,
-- &kbase_g77_ipa_model_ops,
-- &kbase_tnax_ipa_model_ops,
-- &kbase_tbex_ipa_model_ops
--};
-+/* Polling by thermal governor starts when the temperature exceeds the certain
-+ * trip point. In order to have meaningful value for the counters, when the
-+ * polling starts and first call to kbase_get_real_power() is made, it is
-+ * required to reset the counter values every now and then.
-+ * It is reasonable to do the reset every second if no polling is being done,
-+ * the counter model implementation also assumes max sampling interval of 1 sec.
-+ */
-+#define RESET_INTERVAL_MS ((s64)1000)
-
- int kbase_ipa_model_recalculate(struct kbase_ipa_model *model)
- {
-@@ -71,53 +60,24 @@ int kbase_ipa_model_recalculate(struct kbase_ipa_model *model)
- }
-
- const struct kbase_ipa_model_ops *kbase_ipa_model_ops_find(struct kbase_device *kbdev,
-- const char *name)
-+ const char *name)
- {
-- int i;
-+ if (!strcmp(name, kbase_simple_ipa_model_ops.name))
-+ return &kbase_simple_ipa_model_ops;
-
-- for (i = 0; i < ARRAY_SIZE(kbase_ipa_all_model_ops); ++i) {
-- const struct kbase_ipa_model_ops *ops = kbase_ipa_all_model_ops[i];
--
-- if (!strcmp(ops->name, name))
-- return ops;
-- }
--
-- dev_err(kbdev->dev, "power model \'%s\' not found\n", name);
--
-- return NULL;
-+ return kbase_ipa_counter_model_ops_find(kbdev, name);
- }
- KBASE_EXPORT_TEST_API(kbase_ipa_model_ops_find);
-
- const char *kbase_ipa_model_name_from_id(u32 gpu_id)
- {
-- const u32 prod_id = (gpu_id & GPU_ID_VERSION_PRODUCT_ID) >>
-- GPU_ID_VERSION_PRODUCT_ID_SHIFT;
--
-- switch (GPU_ID2_MODEL_MATCH_VALUE(prod_id)) {
-- case GPU_ID2_PRODUCT_TMIX:
-- return "mali-g71-power-model";
-- case GPU_ID2_PRODUCT_THEX:
-- return "mali-g72-power-model";
-- case GPU_ID2_PRODUCT_TNOX:
-- return "mali-g76-power-model";
-- case GPU_ID2_PRODUCT_TSIX:
-- return "mali-g51-power-model";
-- case GPU_ID2_PRODUCT_TGOX:
-- if ((gpu_id & GPU_ID2_VERSION_MAJOR) ==
-- (0 << GPU_ID2_VERSION_MAJOR_SHIFT))
-- /* g52 aliased to g76 power-model's ops */
-- return "mali-g52-power-model";
-- else
-- return "mali-g52_r1-power-model";
-- case GPU_ID2_PRODUCT_TNAX:
-- return "mali-tnax-power-model";
-- case GPU_ID2_PRODUCT_TTRX:
-- return "mali-g77-power-model";
-- case GPU_ID2_PRODUCT_TBEX:
-- return "mali-tbex-power-model";
-- default:
-+ const char* model_name =
-+ kbase_ipa_counter_model_name_from_id(gpu_id);
-+
-+ if (!model_name)
- return KBASE_IPA_FALLBACK_MODEL_NAME;
-- }
-+ else
-+ return model_name;
- }
- KBASE_EXPORT_TEST_API(kbase_ipa_model_name_from_id);
-
-@@ -364,6 +324,8 @@ int kbase_ipa_init(struct kbase_device *kbdev)
- kbdev->ipa.configured_model = default_model;
- }
-
-+ kbdev->ipa.last_sample_time = ktime_get();
-+
- end:
- if (err)
- kbase_ipa_term_locked(kbdev);
-@@ -418,7 +380,8 @@ static u32 kbase_scale_dynamic_power(const u32 c, const u32 freq,
- const u32 v2f = v2f_big / 1000;
-
- /* Range (working backwards from next line): 0 < v2fc < 2^23 uW.
-- * Must be < 2^42 to avoid overflowing the return value. */
-+ * Must be < 2^42 to avoid overflowing the return value.
-+ */
- const u64 v2fc = (u64) c * (u64) v2f;
-
- /* Range: 0 < v2fc / 1000 < 2^13 mW */
-@@ -514,8 +477,9 @@ static u32 get_static_power_locked(struct kbase_device *kbdev,
- return power;
- }
-
--#if defined(CONFIG_MALI_PWRSOFT_765) || \
-- LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
-+#if KERNEL_VERSION(5, 10, 0) > LINUX_VERSION_CODE
-+#if defined(CONFIG_MALI_PWRSOFT_765) || \
-+ KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE
- static unsigned long kbase_get_static_power(struct devfreq *df,
- unsigned long voltage)
- #else
-@@ -524,8 +488,8 @@ static unsigned long kbase_get_static_power(unsigned long voltage)
- {
- struct kbase_ipa_model *model;
- u32 power = 0;
--#if defined(CONFIG_MALI_PWRSOFT_765) || \
-- LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
-+#if defined(CONFIG_MALI_PWRSOFT_765) || \
-+ KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE
- struct kbase_device *kbdev = dev_get_drvdata(&df->dev);
- #else
- struct kbase_device *kbdev = kbase_find_device(-1);
-@@ -541,16 +505,55 @@ static unsigned long kbase_get_static_power(unsigned long voltage)
-
- mutex_unlock(&kbdev->ipa.lock);
-
--#if !(defined(CONFIG_MALI_PWRSOFT_765) || \
-- LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
-+#if !(defined(CONFIG_MALI_PWRSOFT_765) || \
-+ KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE)
- kbase_release_device(kbdev);
- #endif
-
- return power;
- }
-+#endif /* KERNEL_VERSION(5, 10, 0) > LINUX_VERSION_CODE */
-+
-+/**
-+ * opp_translate_freq_voltage() - Translate nominal OPP frequency from
-+ * devicetree into the real frequency for
-+ * top-level and shader cores.
-+ * @kbdev: Device pointer
-+ * @nominal_freq: Nominal frequency in Hz.
-+ * @nominal_voltage: Nominal voltage, in mV.
-+ * @freqs: Pointer to array of real frequency values.
-+ * @volts: Pointer to array of voltages.
-+ *
-+ * If there are 2 clock domains, then top-level and shader cores can operate
-+ * at different frequency and voltage level. The nominal frequency ("opp-hz")
-+ * used by devfreq from the devicetree may not be same as the real frequency
-+ * at which top-level and shader cores are operating, so a translation is
-+ * needed.
-+ * Nominal voltage shall always be same as the real voltage for top-level.
-+ */
-+static void opp_translate_freq_voltage(struct kbase_device *kbdev,
-+ unsigned long nominal_freq,
-+ unsigned long nominal_voltage,
-+ unsigned long *freqs,
-+ unsigned long *volts)
-+{
-+ u64 core_mask;
-+
-+ kbase_devfreq_opp_translate(kbdev, nominal_freq, &core_mask,
-+ freqs, volts);
-+ CSTD_UNUSED(core_mask);
-+
-+ if (kbdev->nr_clocks == 1) {
-+ freqs[KBASE_IPA_BLOCK_TYPE_SHADER_CORES] =
-+ freqs[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL];
-+ volts[KBASE_IPA_BLOCK_TYPE_SHADER_CORES] =
-+ volts[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL];
-+ }
-+}
-
--#if defined(CONFIG_MALI_PWRSOFT_765) || \
-- LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
-+#if KERNEL_VERSION(5, 10, 0) > LINUX_VERSION_CODE
-+#if defined(CONFIG_MALI_PWRSOFT_765) || \
-+ KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE
- static unsigned long kbase_get_dynamic_power(struct devfreq *df,
- unsigned long freq,
- unsigned long voltage)
-@@ -560,10 +563,13 @@ static unsigned long kbase_get_dynamic_power(unsigned long freq,
- #endif
- {
- struct kbase_ipa_model *model;
-- u32 power_coeff = 0, power = 0;
-+ unsigned long freqs[KBASE_IPA_BLOCK_TYPE_NUM] = {0};
-+ unsigned long volts[KBASE_IPA_BLOCK_TYPE_NUM] = {0};
-+ u32 power_coeffs[KBASE_IPA_BLOCK_TYPE_NUM] = {0};
-+ u32 power = 0;
- int err = 0;
--#if defined(CONFIG_MALI_PWRSOFT_765) || \
-- LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
-+#if defined(CONFIG_MALI_PWRSOFT_765) || \
-+ KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE
- struct kbase_device *kbdev = dev_get_drvdata(&df->dev);
- #else
- struct kbase_device *kbdev = kbase_find_device(-1);
-@@ -576,34 +582,53 @@ static unsigned long kbase_get_dynamic_power(unsigned long freq,
-
- model = kbdev->ipa.fallback_model;
-
-- err = model->ops->get_dynamic_coeff(model, &power_coeff);
--
-- if (!err)
-- power = kbase_scale_dynamic_power(power_coeff, freq, voltage);
-- else
-+ err = model->ops->get_dynamic_coeff(model, power_coeffs);
-+
-+ if (!err) {
-+ opp_translate_freq_voltage(kbdev, freq, voltage, freqs, volts);
-+
-+ power = kbase_scale_dynamic_power(
-+ power_coeffs[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL],
-+ freqs[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL],
-+ volts[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL]);
-+
-+ /* Here unlike kbase_get_real_power(), shader core frequency is
-+ * used for the scaling as simple power model is used to obtain
-+ * the value of dynamic coefficient (which is is a fixed value
-+ * retrieved from the device tree).
-+ */
-+ power += kbase_scale_dynamic_power(
-+ power_coeffs[KBASE_IPA_BLOCK_TYPE_SHADER_CORES],
-+ freqs[KBASE_IPA_BLOCK_TYPE_SHADER_CORES],
-+ volts[KBASE_IPA_BLOCK_TYPE_SHADER_CORES]);
-+ } else
- dev_err_ratelimited(kbdev->dev,
- "Model %s returned error code %d\n",
- model->ops->name, err);
-
- mutex_unlock(&kbdev->ipa.lock);
-
--#if !(defined(CONFIG_MALI_PWRSOFT_765) || \
-- LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
-+#if !(defined(CONFIG_MALI_PWRSOFT_765) || \
-+ KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE)
- kbase_release_device(kbdev);
- #endif
-
- return power;
- }
-+#endif /* KERNEL_VERSION(5, 10, 0) > LINUX_VERSION_CODE */
-
- int kbase_get_real_power_locked(struct kbase_device *kbdev, u32 *power,
- unsigned long freq,
- unsigned long voltage)
- {
- struct kbase_ipa_model *model;
-- u32 power_coeff = 0;
-- int err = 0;
-+ unsigned long freqs[KBASE_IPA_BLOCK_TYPE_NUM] = {0};
-+ unsigned long volts[KBASE_IPA_BLOCK_TYPE_NUM] = {0};
-+ u32 power_coeffs[KBASE_IPA_BLOCK_TYPE_NUM] = {0};
- struct kbasep_pm_metrics diff;
- u64 total_time;
-+ bool skip_utilization_scaling = false;
-+ int err = 0;
-
- lockdep_assert_held(&kbdev->ipa.lock);
-
-@@ -611,30 +636,62 @@ int kbase_get_real_power_locked(struct kbase_device *kbdev, u32 *power,
-
- model = get_current_model(kbdev);
-
-- err = model->ops->get_dynamic_coeff(model, &power_coeff);
-+ err = model->ops->get_dynamic_coeff(model, power_coeffs);
-
- /* If the counter model returns an error (e.g. switching back to
- * protected mode and failing to read counters, or a counter sample
- * with too few cycles), revert to the fallback model.
- */
- if (err && model != kbdev->ipa.fallback_model) {
-+ /* No meaningful scaling for GPU utilization can be done if
-+ * the sampling interval was too long. This is equivalent to
-+ * assuming GPU was busy throughout (similar to what is done
-+ * during protected mode).
-+ */
-+ if (err == -EOVERFLOW)
-+ skip_utilization_scaling = true;
-+
- model = kbdev->ipa.fallback_model;
-- err = model->ops->get_dynamic_coeff(model, &power_coeff);
-+ err = model->ops->get_dynamic_coeff(model, power_coeffs);
- }
-
-- if (err)
-+ if (WARN_ON(err))
- return err;
-
-- *power = kbase_scale_dynamic_power(power_coeff, freq, voltage);
-+ opp_translate_freq_voltage(kbdev, freq, voltage, freqs, volts);
-
-- /* time_busy / total_time cannot be >1, so assigning the 64-bit
-- * result of div_u64 to *power cannot overflow.
-- */
-- total_time = diff.time_busy + (u64) diff.time_idle;
-- *power = div_u64(*power * (u64) diff.time_busy,
-- max(total_time, 1ull));
-+ *power = kbase_scale_dynamic_power(
-+ power_coeffs[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL],
-+ freqs[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL],
-+ volts[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL]);
-+
-+ if (power_coeffs[KBASE_IPA_BLOCK_TYPE_SHADER_CORES]) {
-+ unsigned long freq = freqs[KBASE_IPA_BLOCK_TYPE_SHADER_CORES];
-
-- *power += get_static_power_locked(kbdev, model, voltage);
-+ /* As per the HW team, the top-level frequency needs to be used
-+ * for the scaling if the counter based model was used as
-+ * counter values are normalized with the GPU_ACTIVE counter
-+ * value, which increments at the rate of top-level frequency.
-+ */
-+ if (model != kbdev->ipa.fallback_model)
-+ freq = freqs[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL];
-+
-+ *power += kbase_scale_dynamic_power(
-+ power_coeffs[KBASE_IPA_BLOCK_TYPE_SHADER_CORES],
-+ freq, volts[KBASE_IPA_BLOCK_TYPE_SHADER_CORES]);
-+ }
-+
-+ if (!skip_utilization_scaling) {
-+ /* time_busy / total_time cannot be >1, so assigning the 64-bit
-+ * result of div_u64 to *power cannot overflow.
-+ */
-+ total_time = diff.time_busy + (u64) diff.time_idle;
-+ *power = div_u64(*power * (u64) diff.time_busy,
-+ max(total_time, 1ull));
-+ }
-+
-+ *power += get_static_power_locked(kbdev, model,
-+ volts[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL]);
-
- return err;
- }
-@@ -658,18 +715,42 @@ int kbase_get_real_power(struct devfreq *df, u32 *power,
- }
- KBASE_EXPORT_TEST_API(kbase_get_real_power);
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
--struct devfreq_cooling_ops kbase_ipa_power_model_ops = {
--#else
- struct devfreq_cooling_power kbase_ipa_power_model_ops = {
--#endif
--#ifdef CONFIG_MALI_DEVFREQ
-+#if KERNEL_VERSION(5, 10, 0) > LINUX_VERSION_CODE
- .get_static_power = &kbase_get_static_power,
- .get_dynamic_power = &kbase_get_dynamic_power,
--#endif
--#if defined(CONFIG_MALI_PWRSOFT_765) || \
-- LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
-+#endif /* KERNEL_VERSION(5, 10, 0) > LINUX_VERSION_CODE */
-+#if defined(CONFIG_MALI_PWRSOFT_765) || \
-+ KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE
- .get_real_power = &kbase_get_real_power,
- #endif
- };
- KBASE_EXPORT_TEST_API(kbase_ipa_power_model_ops);
-+
-+void kbase_ipa_reset_data(struct kbase_device *kbdev)
-+{
-+ ktime_t now, diff;
-+ s64 elapsed_time;
-+
-+ mutex_lock(&kbdev->ipa.lock);
-+
-+ now = ktime_get();
-+ diff = ktime_sub(now, kbdev->ipa.last_sample_time);
-+ elapsed_time = ktime_to_ms(diff);
-+
-+ if (elapsed_time > RESET_INTERVAL_MS) {
-+ struct kbasep_pm_metrics diff;
-+ struct kbase_ipa_model *model;
-+
-+ kbase_pm_get_dvfs_metrics(
-+ kbdev, &kbdev->ipa.last_metrics, &diff);
-+
-+ model = get_current_model(kbdev);
-+ if (model != kbdev->ipa.fallback_model)
-+ model->ops->reset_counter_data(model);
-+
-+ kbdev->ipa.last_sample_time = ktime_get();
-+ }
-+
-+ mutex_unlock(&kbdev->ipa.lock);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa.h b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa.h
-index 92aace9..c668af9 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2016-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2016-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_IPA_H_
-@@ -27,6 +26,20 @@
-
- struct devfreq;
-
-+/**
-+ * enum kbase_ipa_block_type - Type of block for which power estimation is done.
-+ *
-+ * @KBASE_IPA_BLOCK_TYPE_TOP_LEVEL: Top-level block, that covers CSHW,
-+ * MEMSYS, Tiler.
-+ * @KBASE_IPA_BLOCK_TYPE_SHADER_CORES: All Shader cores.
-+ * @KBASE_IPA_BLOCK_TYPE_NUM: Number of blocks.
-+ */
-+enum kbase_ipa_block_type {
-+ KBASE_IPA_BLOCK_TYPE_TOP_LEVEL,
-+ KBASE_IPA_BLOCK_TYPE_SHADER_CORES,
-+ KBASE_IPA_BLOCK_TYPE_NUM
-+};
-+
- /**
- * struct kbase_ipa_model - Object describing a particular IPA model.
- * @kbdev: pointer to kbase device
-@@ -89,7 +102,8 @@ struct kbase_ipa_model_ops {
- int (*init)(struct kbase_ipa_model *model);
- /* Called immediately after init(), or when a parameter is changed, so
- * that any coefficients derived from model parameters can be
-- * recalculated. */
-+ * recalculated
-+ */
- int (*recalculate)(struct kbase_ipa_model *model);
- void (*term)(struct kbase_ipa_model *model);
- /*
-@@ -101,7 +115,9 @@ struct kbase_ipa_model_ops {
- * is then scaled by the IPA framework according to the current OPP's
- * frequency and voltage.
- *
-- * Return: 0 on success, or an error code.
-+ * Return: 0 on success, or an error code. -EOVERFLOW error code will
-+ * indicate that sampling interval was too large and no meaningful
-+ * scaling for GPU utiliation can be done.
- */
- int (*get_dynamic_coeff)(struct kbase_ipa_model *model, u32 *coeffp);
- /*
-@@ -115,6 +131,18 @@ struct kbase_ipa_model_ops {
- * Return: 0 on success, or an error code.
- */
- int (*get_static_coeff)(struct kbase_ipa_model *model, u32 *coeffp);
-+
-+ /*
-+ * reset_counter_data() - Reset the HW counter data used for calculating
-+ * dynamic power coefficient
-+ * @model: pointer to model
-+ *
-+ * This method is currently applicable only to the counter based model.
-+ * The next call to get_dynamic_coeff() will have to calculate the
-+ * dynamic power coefficient based on the HW counter data generated
-+ * from this point onwards.
-+ */
-+ void (*reset_counter_data)(struct kbase_ipa_model *model);
- };
-
- /**
-@@ -163,6 +191,17 @@ int kbase_ipa_model_recalculate(struct kbase_ipa_model *model);
- const struct kbase_ipa_model_ops *kbase_ipa_model_ops_find(struct kbase_device *kbdev,
- const char *name);
-
-+/**
-+ * kbase_ipa_counter_model_ops_find - Lookup an IPA counter model using its name
-+ * @kbdev: pointer to kbase device
-+ * @name: name of counter model to lookup
-+ *
-+ * Return: Pointer to counter model's 'ops' structure, or NULL if the lookup
-+ * failed.
-+ */
-+const struct kbase_ipa_model_ops *kbase_ipa_counter_model_ops_find(
-+ struct kbase_device *kbdev, const char *name);
-+
- /**
- * kbase_ipa_model_name_from_id - Find the best model for a given GPU ID
- * @gpu_id: GPU ID of GPU the model will be used for
-@@ -172,6 +211,16 @@ const struct kbase_ipa_model_ops *kbase_ipa_model_ops_find(struct kbase_device *
- */
- const char *kbase_ipa_model_name_from_id(u32 gpu_id);
-
-+/**
-+ * kbase_ipa_counter_model_name_from_id - Find the best counter model for a
-+ * given GPU ID
-+ * @gpu_id: GPU ID of GPU the counter model will be used for
-+ *
-+ * Return: The name of the appropriate counter-based model, or NULL if the
-+ * no counter model exists.
-+ */
-+const char *kbase_ipa_counter_model_name_from_id(u32 gpu_id);
-+
- /**
- * kbase_ipa_init_model - Initilaize the particular IPA model
- * @kbdev: pointer to kbase device
-@@ -183,7 +232,7 @@ const char *kbase_ipa_model_name_from_id(u32 gpu_id);
- * Return: pointer to kbase_ipa_model on success, NULL on error
- */
- struct kbase_ipa_model *kbase_ipa_init_model(struct kbase_device *kbdev,
-- const struct kbase_ipa_model_ops *ops);
-+ const struct kbase_ipa_model_ops *ops);
- /**
- * kbase_ipa_term_model - Terminate the particular IPA model
- * @model: pointer to the IPA model object, already initialized
-@@ -202,16 +251,6 @@ void kbase_ipa_term_model(struct kbase_ipa_model *model);
- */
- void kbase_ipa_protection_mode_switch_event(struct kbase_device *kbdev);
-
--extern const struct kbase_ipa_model_ops kbase_g71_ipa_model_ops;
--extern const struct kbase_ipa_model_ops kbase_g72_ipa_model_ops;
--extern const struct kbase_ipa_model_ops kbase_g76_ipa_model_ops;
--extern const struct kbase_ipa_model_ops kbase_g52_ipa_model_ops;
--extern const struct kbase_ipa_model_ops kbase_g52_r1_ipa_model_ops;
--extern const struct kbase_ipa_model_ops kbase_g51_ipa_model_ops;
--extern const struct kbase_ipa_model_ops kbase_g77_ipa_model_ops;
--extern const struct kbase_ipa_model_ops kbase_tnax_ipa_model_ops;
--extern const struct kbase_ipa_model_ops kbase_tbex_ipa_model_ops;
--
- /**
- * kbase_get_real_power() - get the real power consumption of the GPU
- * @df: dynamic voltage and frequency scaling information for the GPU.
-@@ -237,11 +276,20 @@ int kbase_get_real_power_locked(struct kbase_device *kbdev, u32 *power,
- unsigned long voltage);
- #endif /* MALI_UNIT_TEST */
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
--extern struct devfreq_cooling_ops kbase_ipa_power_model_ops;
--#else
- extern struct devfreq_cooling_power kbase_ipa_power_model_ops;
--#endif
-+
-+/**
-+ * kbase_ipa_reset_data() - Reset the data required for power estimation.
-+ * @kbdev: Pointer to kbase device.
-+ *
-+ * This function is called to ensure a meaningful baseline for
-+ * kbase_get_real_power(), when thermal governor starts the polling, and
-+ * that is achieved by updating the GPU utilization metrics and retrieving
-+ * the accumulated value of HW counters.
-+ * Basically this function collects all the data required for power estimation
-+ * but does not process it.
-+ */
-+void kbase_ipa_reset_data(struct kbase_device *kbdev);
-
- #else /* !(defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_debugfs.c
-index 30a3b7d..5976389 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_debugfs.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_debugfs.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2017-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/debugfs.h>
-@@ -28,7 +27,7 @@
- #include "mali_kbase_ipa.h"
- #include "mali_kbase_ipa_debugfs.h"
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
-+#if (KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE)
- #define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE
- #endif
-
-@@ -160,7 +159,8 @@ int kbase_ipa_model_param_add(struct kbase_ipa_model *model, const char *name,
- return -ENOMEM;
-
- /* 'name' is stack-allocated for array elements, so copy it into
-- * heap-allocated storage */
-+ * heap-allocated storage
-+ */
- param->name = kstrdup(name, GFP_KERNEL);
-
- if (!param->name) {
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_debugfs.h
-index a983d9c..f690367 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_debugfs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_debugfs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_IPA_DEBUGFS_H_
-@@ -28,7 +27,7 @@ enum kbase_ipa_model_param_type {
- PARAM_TYPE_STRING,
- };
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-
- void kbase_ipa_debugfs_init(struct kbase_device *kbdev);
- int kbase_ipa_model_param_add(struct kbase_ipa_model *model, const char *name,
-@@ -63,6 +62,9 @@ static inline int kbase_ipa_model_param_add(struct kbase_ipa_model *model,
- static inline void kbase_ipa_model_param_free_all(struct kbase_ipa_model *model)
- { }
-
-+static inline void kbase_ipa_model_param_set_s32(struct kbase_ipa_model *model,
-+ const char *name, s32 val)
-+{ }
- #endif /* CONFIG_DEBUG_FS */
-
- #endif /* _KBASE_IPA_DEBUGFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_simple.c b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_simple.c
-index 852559e..55f1d1c 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_simple.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_simple.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2016-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2016-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,13 +17,11 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <uapi/linux/thermal.h>
- #include <linux/thermal.h>
--#ifdef CONFIG_DEVFREQ_THERMAL
-+#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
- #include <linux/devfreq_cooling.h>
- #endif
- #include <linux/of.h>
-@@ -34,20 +33,18 @@
- #include "mali_kbase_ipa_simple.h"
- #include "mali_kbase_ipa_debugfs.h"
-
--#if MALI_UNIT_TEST
--
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
--static unsigned long dummy_temp;
-+/* This is used if the dynamic power for top-level is estimated separately
-+ * through the counter model. To roughly match the contribution of top-level
-+ * power in the total dynamic power, when calculated through counter model,
-+ * this scalar is used for the dynamic coefficient specified in the device tree
-+ * for simple power model. This value was provided by the HW team after
-+ * taking all the power data collected and dividing top level power by shader
-+ * core power and then averaging it across all samples.
-+ */
-+#define TOP_LEVEL_DYN_COEFF_SCALER (3)
-
--static int kbase_simple_power_model_get_dummy_temp(
-- struct thermal_zone_device *tz,
-- unsigned long *temp)
--{
-- *temp = READ_ONCE(dummy_temp);
-- return 0;
--}
-+#if MALI_UNIT_TEST
-
--#else
- static int dummy_temp;
-
- static int kbase_simple_power_model_get_dummy_temp(
-@@ -57,7 +54,6 @@ static int kbase_simple_power_model_get_dummy_temp(
- *temp = READ_ONCE(dummy_temp);
- return 0;
- }
--#endif
-
- /* Intercept calls to the kernel function using a macro */
- #ifdef thermal_zone_get_temp
-@@ -143,16 +139,13 @@ static u32 calculate_temp_scaling_factor(s32 ts[4], s64 t)
-
- /* We can't call thermal_zone_get_temp() directly in model_static_coeff(),
- * because we don't know if tz->lock is held in the same thread. So poll it in
-- * a separate thread to get around this. */
-+ * a separate thread to get around this.
-+ */
- static int poll_temperature(void *data)
- {
- struct kbase_ipa_model_simple_data *model_data =
- (struct kbase_ipa_model_simple_data *) data;
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
-- unsigned long temp;
--#else
- int temp;
--#endif
-
- while (!kthread_should_stop()) {
- struct thermal_zone_device *tz = READ_ONCE(model_data->gpu_tz);
-@@ -208,7 +201,21 @@ static int model_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp)
- struct kbase_ipa_model_simple_data *model_data =
- (struct kbase_ipa_model_simple_data *) model->model_data;
-
-+#if MALI_USE_CSF
-+ /* On CSF GPUs, the dynamic power for top-level and shader cores is
-+ * estimated separately. Currently there is a single dynamic
-+ * coefficient value provided in the device tree for simple model.
-+ * As per the discussion with HW team the coefficient value needs to
-+ * be scaled down for top-level to limit its contribution in the
-+ * total dyanmic power.
-+ */
-+ coeffp[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL] =
-+ model_data->dynamic_coefficient / TOP_LEVEL_DYN_COEFF_SCALER;
-+ coeffp[KBASE_IPA_BLOCK_TYPE_SHADER_CORES] =
-+ model_data->dynamic_coefficient;
-+#else
- *coeffp = model_data->dynamic_coefficient;
-+#endif
-
- return 0;
- }
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_simple.h b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_simple.h
-index fed67d5..fb174e2 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_simple.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/ipa/mali_kbase_ipa_simple.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_IPA_SIMPLE_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_defs.h
-index aac561b..c490f1c 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_defs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Definitions (types, defines, etcs) specific to Job Manager Kbase.
- * They are placed here to allow the hierarchy of header files to work.
-@@ -129,7 +126,7 @@
- /* Reset the GPU after each atom completion */
- #define KBASE_SERIALIZE_RESET (1 << 2)
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- /**
- * struct base_job_fault_event - keeps track of the atom which faulted or which
- * completed after the faulty atom but before the
-@@ -409,6 +406,16 @@ struct kbase_ext_res {
- * sync through soft jobs and for the implicit
- * synchronization required on access to external
- * resources.
-+ * @dma_fence.fence_in: Input fence
-+ * @dma_fence.fence: Points to the dma-buf output fence for this atom.
-+ * @dma_fence.context: The dma-buf fence context number for this atom. A
-+ * unique context number is allocated to each katom in
-+ * the context on context creation.
-+ * @dma_fence.seqno: The dma-buf fence sequence number for this atom. This
-+ * is increased every time this katom uses dma-buf fence
-+ * @dma_fence.callbacks: List of all callbacks set up to wait on other fences
-+ * @dma_fence.dep_count: Atomic counter of number of outstandind dma-buf fence
-+ * dependencies for this atom.
- * @event_code: Event code for the job chain represented by the atom,
- * both HW and low-level SW events are represented by
- * event codes.
-@@ -443,6 +450,8 @@ struct kbase_ext_res {
- * @blocked: flag indicating that atom's resubmission to GPU is
- * blocked till the work item is scheduled to return the
- * atom to JS.
-+ * @seq_nr: user-space sequence number, to order atoms in some
-+ * temporal order
- * @pre_dep: Pointer to atom that this atom has same-slot
- * dependency on
- * @post_dep: Pointer to atom that has same-slot dependency on
-@@ -477,11 +486,19 @@ struct kbase_ext_res {
- * when transitioning into or out of protected mode.
- * Atom will be either entering or exiting the
- * protected mode.
-+ * @protected_state.enter: entering the protected mode.
-+ * @protected_state.exit: exiting the protected mode.
- * @runnable_tree_node: The node added to context's job slot specific rb tree
- * when the atom becomes runnable.
- * @age: Age of atom relative to other atoms in the context,
- * is snapshot of the age_count counter in kbase
- * context.
-+ * @jobslot: Job slot to use when BASE_JD_REQ_JOB_SLOT is specified.
-+ * @renderpass_id:Renderpass identifier used to associate an atom that has
-+ * BASE_JD_REQ_START_RENDERPASS set in its core requirements
-+ * with an atom that has BASE_JD_REQ_END_RENDERPASS set.
-+ * @jc_fragment: Set of GPU fragment job chains
-+ * @retry_count: TODO: Not used,to be removed
- */
- struct kbase_jd_atom {
- struct work_struct work;
-@@ -496,9 +513,9 @@ struct kbase_jd_atom {
- struct list_head jd_item;
- bool in_jd_list;
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- u8 jit_ids[2];
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- u16 nr_extres;
- struct kbase_ext_res *extres;
-@@ -516,7 +533,6 @@ struct kbase_jd_atom {
- * when working with this sub struct
- */
- #if defined(CONFIG_SYNC_FILE)
-- /* Input fence */
- #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence_in;
- #else
-@@ -539,14 +555,7 @@ struct kbase_jd_atom {
- #else
- struct dma_fence *fence;
- #endif
-- /* The dma-buf fence context number for this atom. A unique
-- * context number is allocated to each katom in the context on
-- * context creation.
-- */
- unsigned int context;
-- /* The dma-buf fence sequence number for this atom. This is
-- * increased every time this katom uses dma-buf fence.
-- */
- atomic_t seqno;
- /* This contains a list of all callbacks set up to wait on
- * other fences. This atom must be held back from JS until all
-@@ -593,7 +602,7 @@ struct kbase_jd_atom {
-
- wait_queue_head_t completed;
- enum kbase_jd_atom_state status;
--#ifdef CONFIG_GPU_TRACEPOINTS
-+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
- int work_id;
- #endif
- int slot_nr;
-@@ -608,6 +617,8 @@ struct kbase_jd_atom {
-
- atomic_t blocked;
-
-+ u64 seq_nr;
-+
- struct kbase_jd_atom *pre_dep;
- struct kbase_jd_atom *post_dep;
-
-@@ -616,7 +627,7 @@ struct kbase_jd_atom {
-
- u32 flush_id;
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- struct base_job_fault_event fault_event;
- #endif
- struct list_head queue;
-@@ -778,6 +789,7 @@ struct kbase_jd_renderpass {
- * @jit_pending_alloc: A list of just-in-time memory allocation
- * soft-jobs which will be reattempted after the
- * impending free of other active allocations.
-+ * @max_priority: Max priority level allowed for this context.
- */
- struct kbase_jd_context {
- struct mutex lock;
-@@ -792,12 +804,13 @@ struct kbase_jd_context {
- u32 job_nr;
- size_t tb_wrap_offset;
-
--#ifdef CONFIG_GPU_TRACEPOINTS
-+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
- atomic_t work_id;
- #endif
-
- struct list_head jit_atoms_head;
- struct list_head jit_pending_alloc;
-+ int max_priority;
- };
-
- /**
-@@ -815,4 +828,27 @@ struct jsctx_queue {
- struct list_head x_dep_head;
- };
-
-+/**
-+ * struct kbase_as - Object representing an address space of GPU.
-+ * @number: Index at which this address space structure is present
-+ * in an array of address space structures embedded inside
-+ * the &struct kbase_device.
-+ * @pf_wq: Workqueue for processing work items related to
-+ * Page fault and Bus fault handling.
-+ * @work_pagefault: Work item for the Page fault handling.
-+ * @work_busfault: Work item for the Bus fault handling.
-+ * @pf_data: Data relating to Page fault.
-+ * @bf_data: Data relating to Bus fault.
-+ * @current_setup: Stores the MMU configuration for this address space.
-+ */
-+struct kbase_as {
-+ int number;
-+ struct workqueue_struct *pf_wq;
-+ struct work_struct work_pagefault;
-+ struct work_struct work_busfault;
-+ struct kbase_fault pf_data;
-+ struct kbase_fault bf_data;
-+ struct kbase_mmu_setup current_setup;
-+};
-+
- #endif /* _KBASE_JM_DEFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_js.h b/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_js.h
-index 6c222ce..5e0c4bc 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_js.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_js.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -32,6 +31,7 @@
-
- /**
- * kbasep_js_devdata_init - Initialize the Job Scheduler
-+ * @kbdev: The kbase_device to operate on
- *
- * The struct kbasep_js_device_data sub-structure of kbdev must be zero
- * initialized before passing to the kbasep_js_devdata_init() function. This is
-@@ -41,6 +41,7 @@ int kbasep_js_devdata_init(struct kbase_device * const kbdev);
-
- /**
- * kbasep_js_devdata_halt - Halt the Job Scheduler.
-+ * @kbdev: The kbase_device to operate on
- *
- * It is safe to call this on kbdev even if it the kbasep_js_device_data
- * sub-structure was never initialized/failed initialization, to give efficient
-@@ -58,6 +59,7 @@ void kbasep_js_devdata_halt(struct kbase_device *kbdev);
-
- /**
- * kbasep_js_devdata_term - Terminate the Job Scheduler
-+ * @kbdev: The kbase_device to operate on
- *
- * It is safe to call this on kbdev even if it the kbasep_js_device_data
- * sub-structure was never initialized/failed initialization, to give efficient
-@@ -75,6 +77,7 @@ void kbasep_js_devdata_term(struct kbase_device *kbdev);
- /**
- * kbasep_js_kctx_init - Initialize the Scheduling Component of a
- * struct kbase_context on the Job Scheduler.
-+ * @kctx: The kbase_context to operate on
- *
- * This effectively registers a struct kbase_context with a Job Scheduler.
- *
-@@ -89,6 +92,7 @@ int kbasep_js_kctx_init(struct kbase_context *const kctx);
- /**
- * kbasep_js_kctx_term - Terminate the Scheduling Component of a
- * struct kbase_context on the Job Scheduler
-+ * @kctx: The kbase_context to operate on
- *
- * This effectively de-registers a struct kbase_context from its Job Scheduler
- *
-@@ -108,6 +112,8 @@ void kbasep_js_kctx_term(struct kbase_context *kctx);
- * kbasep_js_add_job - Add a job chain to the Job Scheduler,
- * and take necessary actions to
- * schedule the context/run the job.
-+ * @kctx: The kbase_context to operate on
-+ * @atom: Atom to add
- *
- * This atomically does the following:
- * * Update the numbers of jobs information
-@@ -151,7 +157,10 @@ bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom);
- /**
- * kbasep_js_remove_job - Remove a job chain from the Job Scheduler,
- * except for its 'retained state'.
-- *
-+ * @kbdev: The kbase_device to operate on
-+ * @kctx: The kbase_context to operate on
-+ * @atom: Atom to remove
-+*
- * Completely removing a job requires several calls:
- * * kbasep_js_copy_atom_retained_state(), to capture the 'retained state' of
- * the atom
-@@ -185,6 +194,9 @@ void kbasep_js_remove_job(struct kbase_device *kbdev,
- * kbasep_js_remove_cancelled_job - Completely remove a job chain from the
- * Job Scheduler, in the case
- * where the job chain was cancelled.
-+ * @kbdev: The kbase_device to operate on
-+ * @kctx: The kbase_context to operate on
-+ * @katom: Atom to remove
- *
- * This is a variant of kbasep_js_remove_job() that takes care of removing all
- * of the retained state too. This is generally useful for cancelled atoms,
-@@ -215,6 +227,9 @@ bool kbasep_js_remove_cancelled_job(struct kbase_device *kbdev,
- * kbasep_js_runpool_requeue_or_kill_ctx - Handling the requeuing/killing of a
- * context that was evicted from the
- * policy queue or runpool.
-+ * @kbdev: The kbase_device to operate on
-+ * @kctx: The kbase_context to operate on
-+ * @has_pm_ref: tells whether to release Power Manager active reference
- *
- * This should be used whenever handing off a context that has been evicted
- * from the policy queue or the runpool:
-@@ -242,6 +257,8 @@ void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev,
- /**
- * kbasep_js_runpool_release_ctx - Release a refcount of a context being busy,
- * allowing it to be scheduled out.
-+ * @kbdev: The kbase_device to operate on
-+ * @kctx: The kbase_context to operate on
- *
- * When the refcount reaches zero and the context might be scheduled out
- * (depending on whether the Scheduling Policy has deemed it so, or if it has
-@@ -296,6 +313,9 @@ void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev,
- * kbasep_js_runpool_release_ctx_and_katom_retained_state - Variant of
- * kbasep_js_runpool_release_ctx() that handles additional
- * actions from completing an atom.
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
-+ * @katom_retained_state: Retained state from the atom
- *
- * This is usually called as part of completing an atom and releasing the
- * refcount on the context held by the atom.
-@@ -315,8 +335,12 @@ void kbasep_js_runpool_release_ctx_and_katom_retained_state(
- struct kbasep_js_atom_retained_state *katom_retained_state);
-
- /**
-- * kbasep_js_runpool_release_ctx_nolock - Variant of
-- * kbase_js_runpool_release_ctx() that assumes that
-+ * kbasep_js_runpool_release_ctx_nolock -
-+ * Variant of kbase_js_runpool_release_ctx() w/out locks
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
-+ *
-+ * Variant of kbase_js_runpool_release_ctx() that assumes that
- * kbasep_js_device_data::runpool_mutex and
- * kbasep_js_kctx_info::ctx::jsctx_mutex are held by the caller, and does not
- * attempt to schedule new contexts.
-@@ -326,6 +350,8 @@ void kbasep_js_runpool_release_ctx_nolock(struct kbase_device *kbdev,
-
- /**
- * kbasep_js_schedule_privileged_ctx - Schedule in a privileged context
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
- *
- * This schedules a context in regardless of the context priority.
- * If the runpool is full, a context will be forced out of the runpool and the
-@@ -351,6 +377,8 @@ void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev,
- /**
- * kbasep_js_release_privileged_ctx - Release a privileged context,
- * allowing it to be scheduled out.
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
- *
- * See kbasep_js_runpool_release_ctx for potential side effects.
- *
-@@ -368,6 +396,7 @@ void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev,
-
- /**
- * kbase_js_try_run_jobs - Try to submit the next job on each slot
-+ * @kbdev: KBase device
- *
- * The following locks may be used:
- * * kbasep_js_device_data::runpool_mutex
-@@ -378,6 +407,7 @@ void kbase_js_try_run_jobs(struct kbase_device *kbdev);
- /**
- * kbasep_js_suspend - Suspend the job scheduler during a Power Management
- * Suspend event.
-+ * @kbdev: KBase device
- *
- * Causes all contexts to be removed from the runpool, and prevents any
- * contexts from (re)entering the runpool.
-@@ -401,6 +431,7 @@ void kbasep_js_suspend(struct kbase_device *kbdev);
- /**
- * kbasep_js_resume - Resume the Job Scheduler after a Power Management
- * Resume event.
-+ * @kbdev: KBase device
- *
- * This restores the actions from kbasep_js_suspend():
- * * Schedules contexts back into the runpool
-@@ -412,7 +443,7 @@ void kbasep_js_resume(struct kbase_device *kbdev);
- * kbase_js_dep_resolved_submit - Submit an atom to the job scheduler.
- *
- * @kctx: Context pointer
-- * @atom: Pointer to the atom to submit
-+ * @katom: Pointer to the atom to submit
- *
- * The atom is enqueued on the context's ringbuffer. The caller must have
- * ensured that all dependencies can be represented in the ringbuffer.
-@@ -457,7 +488,7 @@ struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js);
- * kbase_js_unpull - Return an atom to the job scheduler ringbuffer.
- *
- * @kctx: Context pointer
-- * @atom: Pointer to the atom to unpull
-+ * @katom: Pointer to the atom to unpull
- *
- * An atom is 'unpulled' if execution is stopped but intended to be returned to
- * later. The most common reason for this is that the atom has been
-@@ -584,7 +615,6 @@ void kbase_js_set_timeouts(struct kbase_device *kbdev);
- */
- void kbase_js_set_ctx_priority(struct kbase_context *kctx, int new_priority);
-
--
- /**
- * kbase_js_update_ctx_priority - update the context priority
- *
-@@ -603,6 +633,8 @@ void kbase_js_update_ctx_priority(struct kbase_context *kctx);
- /**
- * kbasep_js_is_submit_allowed - Check that a context is allowed to submit
- * jobs on this policy
-+ * @js_devdata: KBase Job Scheduler Device Data
-+ * @kctx: KBase context
- *
- * The purpose of this abstraction is to hide the underlying data size,
- * and wrap up the long repeated line of code.
-@@ -625,13 +657,15 @@ static inline bool kbasep_js_is_submit_allowed(
- test_bit = (u16) (1u << kctx->as_nr);
-
- is_allowed = (bool) (js_devdata->runpool_irq.submit_allowed & test_bit);
-- dev_dbg(kctx->kbdev->dev, "JS: submit %s allowed on %p (as=%d)",
-+ dev_dbg(kctx->kbdev->dev, "JS: submit %s allowed on %pK (as=%d)",
- is_allowed ? "is" : "isn't", (void *)kctx, kctx->as_nr);
- return is_allowed;
- }
-
- /**
- * kbasep_js_set_submit_allowed - Allow a context to submit jobs on this policy
-+ * @js_devdata: KBase Job Scheduler Device Data
-+ * @kctx: KBase context
- *
- * The purpose of this abstraction is to hide the underlying data size,
- * and wrap up the long repeated line of code.
-@@ -650,7 +684,7 @@ static inline void kbasep_js_set_submit_allowed(
-
- set_bit = (u16) (1u << kctx->as_nr);
-
-- dev_dbg(kctx->kbdev->dev, "JS: Setting Submit Allowed on %p (as=%d)",
-+ dev_dbg(kctx->kbdev->dev, "JS: Setting Submit Allowed on %pK (as=%d)",
- kctx, kctx->as_nr);
-
- js_devdata->runpool_irq.submit_allowed |= set_bit;
-@@ -659,6 +693,8 @@ static inline void kbasep_js_set_submit_allowed(
- /**
- * kbasep_js_clear_submit_allowed - Prevent a context from submitting more
- * jobs on this policy
-+ * @js_devdata: KBase Job Scheduler Device Data
-+ * @kctx: KBase context
- *
- * The purpose of this abstraction is to hide the underlying data size,
- * and wrap up the long repeated line of code.
-@@ -679,13 +715,17 @@ static inline void kbasep_js_clear_submit_allowed(
- clear_bit = (u16) (1u << kctx->as_nr);
- clear_mask = ~clear_bit;
-
-- dev_dbg(kctx->kbdev->dev, "JS: Clearing Submit Allowed on %p (as=%d)",
-+ dev_dbg(kctx->kbdev->dev, "JS: Clearing Submit Allowed on %pK (as=%d)",
- kctx, kctx->as_nr);
-
- js_devdata->runpool_irq.submit_allowed &= clear_mask;
- }
-
- /**
-+ * kbasep_js_atom_retained_state_init_invalid -
-+ * Create an initial 'invalid' atom retained state
-+ * @retained_state: pointer where to create and initialize the state
-+ *
- * Create an initial 'invalid' atom retained state, that requires no
- * atom-related work to be done on releasing with
- * kbasep_js_runpool_release_ctx_and_katom_retained_state()
-@@ -699,6 +739,10 @@ static inline void kbasep_js_atom_retained_state_init_invalid(
- }
-
- /**
-+ * kbasep_js_atom_retained_state_copy() - Copy atom state
-+ * @retained_state: where to copy
-+ * @katom: where to copy from
-+ *
- * Copy atom state that can be made available after jd_done_nolock() is called
- * on that atom.
- */
-@@ -743,7 +787,7 @@ static inline bool kbasep_js_has_atom_finished(
- * kbasep_js_atom_retained_state_is_valid - Determine whether a struct
- * kbasep_js_atom_retained_state
- * is valid
-- * @katom_retained_state the atom's retained state to check
-+ * @katom_retained_state: the atom's retained state to check
- *
- * An invalid struct kbasep_js_atom_retained_state is allowed, and indicates
- * that the code should just ignore it.
-@@ -759,6 +803,8 @@ static inline bool kbasep_js_atom_retained_state_is_valid(
-
- /**
- * kbase_js_runpool_inc_context_count - Increment number of running contexts.
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
- *
- * The following locking conditions are made on the caller:
- * * The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex.
-@@ -795,6 +841,8 @@ static inline void kbase_js_runpool_inc_context_count(
- /**
- * kbase_js_runpool_dec_context_count - decrement number of running contexts.
- *
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
- * 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
-@@ -889,4 +937,17 @@ static inline base_jd_prio kbasep_js_sched_prio_to_atom_prio(int sched_prio)
- return kbasep_js_relative_priority_to_atom[prio_idx];
- }
-
-+/**
-+ * kbase_js_priority_check - Check the priority requested
-+ *
-+ * @kbdev: Device pointer
-+ * @priority: Requested priority
-+ *
-+ * This will determine whether the requested priority can be satisfied.
-+ *
-+ * Return: The same or lower priority than requested.
-+ */
-+
-+base_jd_prio kbase_js_priority_check(struct kbase_device *kbdev, base_jd_prio priority);
-+
- #endif /* _KBASE_JM_JS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_js_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_js_defs.h
-index 0b48615..75152fb 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_js_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_js_defs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2018, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,33 +17,15 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /**
-- * @file mali_kbase_js.h
-- * Job Scheduler Type Definitions
-+ * DOC: Job Scheduler Type Definitions
- */
-
- #ifndef _KBASE_JS_DEFS_H_
- #define _KBASE_JS_DEFS_H_
-
--/**
-- * @addtogroup base_api
-- * @{
-- */
--
--/**
-- * @addtogroup base_kbase_api
-- * @{
-- */
--
--/**
-- * @addtogroup kbase_js
-- * @{
-- */
- /* Forward decls */
- struct kbase_device;
- struct kbase_jd_atom;
-@@ -50,11 +33,14 @@ struct kbase_jd_atom;
-
- typedef u32 kbase_context_flags;
-
--/** Callback function run on all of a context's jobs registered with the Job
-- * Scheduler */
--typedef void (*kbasep_js_ctx_job_cb)(struct kbase_device *kbdev, struct kbase_jd_atom *katom);
-+/*
-+ * typedef kbasep_js_ctx_job_cb - Callback function run on all of a context's
-+ * jobs registered with the Job Scheduler
-+ */
-+typedef void kbasep_js_ctx_job_cb(struct kbase_device *kbdev,
-+ struct kbase_jd_atom *katom);
-
--/**
-+/*
- * @brief Maximum number of jobs that can be submitted to a job slot whilst
- * inside the IRQ handler.
- *
-@@ -65,7 +51,15 @@ typedef void (*kbasep_js_ctx_job_cb)(struct kbase_device *kbdev, struct kbase_jd
- #define KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ 2
-
- /**
-- * @brief Context attributes
-+ * enum kbasep_js_ctx_attr - Context attributes
-+ * @KBASEP_JS_CTX_ATTR_COMPUTE: Attribute indicating a context that contains
-+ * Compute jobs.
-+ * @KBASEP_JS_CTX_ATTR_NON_COMPUTE: Attribute indicating a context that contains
-+ * Non-Compute jobs.
-+ * @KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES: Attribute indicating that a context
-+ * contains compute-job atoms that aren't restricted to a coherent group,
-+ * and can run on all cores.
-+ * @KBASEP_JS_CTX_ATTR_COUNT: Must be the last in the enum
- *
- * Each context attribute can be thought of as a boolean value that caches some
- * state information about either the runpool, or the context:
-@@ -82,61 +76,70 @@ typedef void (*kbasep_js_ctx_job_cb)(struct kbase_device *kbdev, struct kbase_jd
- * - The runpool holds a refcount of how many contexts in the runpool have this
- * attribute.
- * - The context holds a refcount of how many atoms have this attribute.
-+ *
-+ * KBASEP_JS_CTX_ATTR_COMPUTE:
-+ * Attribute indicating a context that contains Compute jobs. That is,
-+ * the context has jobs of type @ref BASE_JD_REQ_ONLY_COMPUTE
-+ *
-+ * @note A context can be both 'Compute' and 'Non Compute' if it contains
-+ * both types of jobs.
-+ *
-+ * KBASEP_JS_CTX_ATTR_NON_COMPUTE:
-+ * Attribute indicating a context that contains Non-Compute jobs. That is,
-+ * the context has some jobs that are \b not of type @ref
-+ * BASE_JD_REQ_ONLY_COMPUTE.
-+ *
-+ * @note A context can be both 'Compute' and 'Non Compute' if it contains
-+ * both types of jobs.
-+ *
-+ * KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES:
-+ * Attribute indicating that a context contains compute-job atoms that
-+ * aren't restricted to a coherent group, and can run on all cores.
-+ *
-+ * Specifically, this is when the atom's \a core_req satisfy:
-+ * - (\a core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T) // uses slot 1 or slot 2
-+ * - && !(\a core_req & BASE_JD_REQ_COHERENT_GROUP) // not restricted to coherent groups
-+ *
-+ * Such atoms could be blocked from running if one of the coherent groups
-+ * is being used by another job slot, so tracking this context attribute
-+ * allows us to prevent such situations.
-+ *
-+ * @note This doesn't take into account the 1-coregroup case, where all
-+ * compute atoms would effectively be able to run on 'all cores', but
-+ * contexts will still not always get marked with this attribute. Instead,
-+ * it is the caller's responsibility to take into account the number of
-+ * coregroups when interpreting this attribute.
-+ *
-+ * @note Whilst Tiler atoms are normally combined with
-+ * BASE_JD_REQ_COHERENT_GROUP, it is possible to send such atoms without
-+ * BASE_JD_REQ_COHERENT_GROUP set. This is an unlikely case, but it's easy
-+ * enough to handle anyway.
-+ *
-+ *
- */
- enum kbasep_js_ctx_attr {
-- /** Attribute indicating a context that contains Compute jobs. That is,
-- * the context has jobs of type @ref BASE_JD_REQ_ONLY_COMPUTE
-- *
-- * @note A context can be both 'Compute' and 'Non Compute' if it contains
-- * both types of jobs.
-- */
- KBASEP_JS_CTX_ATTR_COMPUTE,
--
-- /** Attribute indicating a context that contains Non-Compute jobs. That is,
-- * the context has some jobs that are \b not of type @ref
-- * BASE_JD_REQ_ONLY_COMPUTE.
-- *
-- * @note A context can be both 'Compute' and 'Non Compute' if it contains
-- * both types of jobs.
-- */
- KBASEP_JS_CTX_ATTR_NON_COMPUTE,
--
-- /** Attribute indicating that a context contains compute-job atoms that
-- * aren't restricted to a coherent group, and can run on all cores.
-- *
-- * Specifically, this is when the atom's \a core_req satisfy:
-- * - (\a core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T) // uses slot 1 or slot 2
-- * - && !(\a core_req & BASE_JD_REQ_COHERENT_GROUP) // not restricted to coherent groups
-- *
-- * Such atoms could be blocked from running if one of the coherent groups
-- * is being used by another job slot, so tracking this context attribute
-- * allows us to prevent such situations.
-- *
-- * @note This doesn't take into account the 1-coregroup case, where all
-- * compute atoms would effectively be able to run on 'all cores', but
-- * contexts will still not always get marked with this attribute. Instead,
-- * it is the caller's responsibility to take into account the number of
-- * coregroups when interpreting this attribute.
-- *
-- * @note Whilst Tiler atoms are normally combined with
-- * BASE_JD_REQ_COHERENT_GROUP, it is possible to send such atoms without
-- * BASE_JD_REQ_COHERENT_GROUP set. This is an unlikely case, but it's easy
-- * enough to handle anyway.
-- */
- KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES,
--
-- /** Must be the last in the enum */
- KBASEP_JS_CTX_ATTR_COUNT
- };
-
- enum {
-- /** Bit indicating that new atom should be started because this atom completed */
-+ /*
-+ * Bit indicating that new atom should be started because this atom
-+ * completed
-+ */
- KBASE_JS_ATOM_DONE_START_NEW_ATOMS = (1u << 0),
-- /** Bit indicating that the atom was evicted from the JS_NEXT registers */
-+ /*
-+ * Bit indicating that the atom was evicted from the JS_NEXT registers
-+ */
- KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT = (1u << 1)
- };
-
--/** Combination of KBASE_JS_ATOM_DONE_<...> bits */
-+/**
-+ * typedef kbasep_js_atom_done_code - Combination of KBASE_JS_ATOM_DONE_<...>
-+ * bits
-+ */
- typedef u32 kbasep_js_atom_done_code;
-
- /*
-@@ -168,7 +171,9 @@ enum {
- * Internal atom priority defines for kbase_jd_atom::sched_prio
- */
- enum {
-- KBASE_JS_ATOM_SCHED_PRIO_HIGH = 0,
-+ KBASE_JS_ATOM_SCHED_PRIO_FIRST = 0,
-+ KBASE_JS_ATOM_SCHED_PRIO_REALTIME = KBASE_JS_ATOM_SCHED_PRIO_FIRST,
-+ KBASE_JS_ATOM_SCHED_PRIO_HIGH,
- KBASE_JS_ATOM_SCHED_PRIO_MED,
- KBASE_JS_ATOM_SCHED_PRIO_LOW,
- KBASE_JS_ATOM_SCHED_PRIO_COUNT,
-@@ -183,7 +188,70 @@ enum {
- #define KBASE_JS_ATOM_SCHED_PRIO_DEFAULT KBASE_JS_ATOM_SCHED_PRIO_MED
-
- /**
-- * @brief KBase Device Data Job Scheduler sub-structure
-+ * struct kbasep_js_device_data - KBase Device Data Job Scheduler sub-structure
-+ * @runpool_irq: Sub-structure to collect together Job Scheduling data used in
-+ * IRQ context. The hwaccess_lock must be held when accessing.
-+ * @runpool_irq.submit_allowed: Bitvector indicating whether a currently
-+ * scheduled context is allowed to submit jobs. When bit 'N' is set in
-+ * this, it indicates whether the context bound to address space 'N' is
-+ * allowed to submit jobs.
-+ * @runpool_irq.ctx_attr_ref_count: Array of Context Attributes Ref_counters:
-+ * Each is large enough to hold a refcount of the number of contexts
-+ * that can fit into the runpool. This is currently BASE_MAX_NR_AS.
-+ * Note that when BASE_MAX_NR_AS==16 we need 5 bits (not 4) to store
-+ * the refcount. Hence, it's not worthwhile reducing this to
-+ * bit-manipulation on u32s to save space (where in contrast, 4 bit
-+ * sub-fields would be easy to do and would save space).
-+ * Whilst this must not become negative, the sign bit is used for:
-+ * - error detection in debug builds
-+ * - Optimization: it is undefined for a signed int to overflow, and so
-+ * the compiler can optimize for that never happening (thus, no masking
-+ * is required on updating the variable)
-+ * @runpool_irq.slot_affinities: Affinity management and tracking. Bitvector
-+ * to aid affinity checking. Element 'n' bit 'i' indicates that slot 'n'
-+ * is using core i (i.e. slot_affinity_refcount[n][i] > 0)
-+ * @runpool_irq.slot_affinity_refcount: Array of fefcount for each core owned
-+ * by each slot. Used to generate the slot_affinities array of bitvectors.
-+ * The value of the refcount will not exceed BASE_JM_SUBMIT_SLOTS,
-+ * because it is refcounted only when a job is definitely about to be
-+ * submitted to a slot, and is de-refcounted immediately after a job
-+ * finishes
-+ * @schedule_sem: Scheduling semaphore. This must be held when calling
-+ * kbase_jm_kick()
-+ * @ctx_list_pullable: List of contexts that can currently be pulled from
-+ * @ctx_list_unpullable: List of contexts that can not currently be pulled
-+ * from, but have jobs currently running.
-+ * @nr_user_contexts_running: Number of currently scheduled user contexts
-+ * (excluding ones that are not submitting jobs)
-+ * @nr_all_contexts_running: Number of currently scheduled contexts (including
-+ * ones that are not submitting jobs)
-+ * @js_reqs: Core Requirements to match up with base_js_atom's core_req memeber
-+ * @note This is a write-once member, and so no locking is required to
-+ * read
-+ * @scheduling_period_ns: Value for JS_SCHEDULING_PERIOD_NS
-+ * @soft_stop_ticks: Value for JS_SOFT_STOP_TICKS
-+ * @soft_stop_ticks_cl: Value for JS_SOFT_STOP_TICKS_CL
-+ * @hard_stop_ticks_ss: Value for JS_HARD_STOP_TICKS_SS
-+ * @hard_stop_ticks_cl: Value for JS_HARD_STOP_TICKS_CL
-+ * @hard_stop_ticks_dumping: Value for JS_HARD_STOP_TICKS_DUMPING
-+ * @gpu_reset_ticks_ss: Value for JS_RESET_TICKS_SS
-+ * @gpu_reset_ticks_cl: Value for JS_RESET_TICKS_CL
-+ * @gpu_reset_ticks_dumping: Value for JS_RESET_TICKS_DUMPING
-+ * @ctx_timeslice_ns: Value for JS_CTX_TIMESLICE_NS
-+ * @suspended_soft_jobs_list: List of suspended soft jobs
-+ * @softstop_always: Support soft-stop on a single context
-+ * @init_status:The initialized-flag is placed at the end, to avoid
-+ * cache-pollution (we should only be using this during init/term paths).
-+ * @note This is a write-once member, and so no locking is required to
-+ * read
-+ * @nr_contexts_pullable:Number of contexts that can currently be pulled from
-+ * @nr_contexts_runnable:Number of contexts that can either be pulled from or
-+ * arecurrently running
-+ * @soft_job_timeout_ms:Value for JS_SOFT_JOB_TIMEOUT
-+ * @queue_mutex: Queue Lock, used to access the Policy's queue of contexts
-+ * independently of the Run Pool.
-+ * Of course, you don't need the Run Pool lock to access this.
-+ * @runpool_mutex: Run Pool mutex, for managing contexts within the runpool.
- *
- * This encapsulates the current context of the Job Scheduler on a particular
- * device. This context is global to the device, and is not tied to any
-@@ -191,121 +259,49 @@ enum {
- *
- * nr_contexts_running and as_free are optimized for packing together (by making
- * them smaller types than u32). The operations on them should rarely involve
-- * masking. The use of signed types for arithmetic indicates to the compiler that
-- * the value will not rollover (which would be undefined behavior), and so under
-- * the Total License model, it is free to make optimizations based on that (i.e.
-- * to remove masking).
-+ * masking. The use of signed types for arithmetic indicates to the compiler
-+ * that the value will not rollover (which would be undefined behavior), and so
-+ * under the Total License model, it is free to make optimizations based on
-+ * that (i.e. to remove masking).
- */
- struct kbasep_js_device_data {
-- /* Sub-structure to collect together Job Scheduling data used in IRQ
-- * context. The hwaccess_lock must be held when accessing. */
- struct runpool_irq {
-- /** Bitvector indicating whether a currently scheduled context is allowed to submit jobs.
-- * When bit 'N' is set in this, it indicates whether the context bound to address space
-- * 'N' is allowed to submit jobs.
-- */
- u16 submit_allowed;
--
-- /** Context Attributes:
-- * Each is large enough to hold a refcount of the number of contexts
-- * that can fit into the runpool. This is currently BASE_MAX_NR_AS
-- *
-- * Note that when BASE_MAX_NR_AS==16 we need 5 bits (not 4) to store
-- * the refcount. Hence, it's not worthwhile reducing this to
-- * bit-manipulation on u32s to save space (where in contrast, 4 bit
-- * sub-fields would be easy to do and would save space).
-- *
-- * Whilst this must not become negative, the sign bit is used for:
-- * - error detection in debug builds
-- * - Optimization: it is undefined for a signed int to overflow, and so
-- * the compiler can optimize for that never happening (thus, no masking
-- * is required on updating the variable) */
- s8 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT];
--
-- /*
-- * Affinity management and tracking
-- */
-- /** Bitvector to aid affinity checking. Element 'n' bit 'i' indicates
-- * that slot 'n' is using core i (i.e. slot_affinity_refcount[n][i] > 0) */
- u64 slot_affinities[BASE_JM_MAX_NR_SLOTS];
-- /** Refcount for each core owned by each slot. Used to generate the
-- * slot_affinities array of bitvectors
-- *
-- * The value of the refcount will not exceed BASE_JM_SUBMIT_SLOTS,
-- * because it is refcounted only when a job is definitely about to be
-- * submitted to a slot, and is de-refcounted immediately after a job
-- * finishes */
- s8 slot_affinity_refcount[BASE_JM_MAX_NR_SLOTS][64];
- } runpool_irq;
--
-- /**
-- * Scheduling semaphore. This must be held when calling
-- * kbase_jm_kick()
-- */
- struct semaphore schedule_sem;
--
-- /**
-- * List of contexts that can currently be pulled from
-- */
-- struct list_head ctx_list_pullable[BASE_JM_MAX_NR_SLOTS][KBASE_JS_ATOM_SCHED_PRIO_COUNT];
-- /**
-- * List of contexts that can not currently be pulled from, but have
-- * jobs currently running.
-- */
-- struct list_head ctx_list_unpullable[BASE_JM_MAX_NR_SLOTS][KBASE_JS_ATOM_SCHED_PRIO_COUNT];
--
-- /** Number of currently scheduled user contexts (excluding ones that are not submitting jobs) */
-+ struct list_head ctx_list_pullable[BASE_JM_MAX_NR_SLOTS]
-+ [KBASE_JS_ATOM_SCHED_PRIO_COUNT];
-+ struct list_head ctx_list_unpullable[BASE_JM_MAX_NR_SLOTS]
-+ [KBASE_JS_ATOM_SCHED_PRIO_COUNT];
- s8 nr_user_contexts_running;
-- /** Number of currently scheduled contexts (including ones that are not submitting jobs) */
- s8 nr_all_contexts_running;
--
-- /** Core Requirements to match up with base_js_atom's core_req memeber
-- * @note This is a write-once member, and so no locking is required to read */
- base_jd_core_req js_reqs[BASE_JM_MAX_NR_SLOTS];
-
-- u32 scheduling_period_ns; /*< Value for JS_SCHEDULING_PERIOD_NS */
-- u32 soft_stop_ticks; /*< Value for JS_SOFT_STOP_TICKS */
-- u32 soft_stop_ticks_cl; /*< Value for JS_SOFT_STOP_TICKS_CL */
-- u32 hard_stop_ticks_ss; /*< Value for JS_HARD_STOP_TICKS_SS */
-- u32 hard_stop_ticks_cl; /*< Value for JS_HARD_STOP_TICKS_CL */
-- u32 hard_stop_ticks_dumping; /*< Value for JS_HARD_STOP_TICKS_DUMPING */
-- u32 gpu_reset_ticks_ss; /*< Value for JS_RESET_TICKS_SS */
-- u32 gpu_reset_ticks_cl; /*< Value for JS_RESET_TICKS_CL */
-- u32 gpu_reset_ticks_dumping; /*< Value for JS_RESET_TICKS_DUMPING */
-- u32 ctx_timeslice_ns; /**< Value for JS_CTX_TIMESLICE_NS */
-+ u32 scheduling_period_ns;
-+ u32 soft_stop_ticks;
-+ u32 soft_stop_ticks_cl;
-+ u32 hard_stop_ticks_ss;
-+ u32 hard_stop_ticks_cl;
-+ u32 hard_stop_ticks_dumping;
-+ u32 gpu_reset_ticks_ss;
-+ u32 gpu_reset_ticks_cl;
-+ u32 gpu_reset_ticks_dumping;
-+ u32 ctx_timeslice_ns;
-
-- /** List of suspended soft jobs */
- struct list_head suspended_soft_jobs_list;
-
- #ifdef CONFIG_MALI_DEBUG
-- /* Support soft-stop on a single context */
- bool softstop_always;
- #endif /* CONFIG_MALI_DEBUG */
--
-- /** The initalized-flag is placed at the end, to avoid cache-pollution (we should
-- * only be using this during init/term paths).
-- * @note This is a write-once member, and so no locking is required to read */
- int init_status;
--
-- /* Number of contexts that can currently be pulled from */
- u32 nr_contexts_pullable;
--
-- /* Number of contexts that can either be pulled from or are currently
-- * running */
- atomic_t nr_contexts_runnable;
--
-- /** Value for JS_SOFT_JOB_TIMEOUT */
- atomic_t soft_job_timeout_ms;
--
-- /**
-- * Queue Lock, used to access the Policy's queue of contexts
-- * independently of the Run Pool.
-- *
-- * Of course, you don't need the Run Pool lock to access this.
-- */
- struct mutex queue_mutex;
--
-- /**
-+ /*
- * Run Pool mutex, for managing contexts within the runpool.
- * Unless otherwise specified, you must hold this lock whilst accessing
- * any members that follow
-@@ -317,61 +313,59 @@ struct kbasep_js_device_data {
- };
-
- /**
-- * @brief KBase Context Job Scheduling information structure
-+ * struct kbasep_js_kctx_info - KBase Context Job Scheduling information
-+ * structure
-+ * @ctx: Job Scheduler Context information sub-structure.Its members are
-+ * accessed regardless of whether the context is:
-+ * - In the Policy's Run Pool
-+ * - In the Policy's Queue
-+ * - Not queued nor in the Run Pool.
-+ * You must obtain the @ctx.jsctx_mutex before accessing any other members
-+ * of this substructure.
-+ * You may not access any of its members from IRQ context.
-+ * @ctx.jsctx_mutex: Job Scheduler Context lock
-+ * @ctx.nr_jobs: Number of jobs <b>ready to run</b> - does \em not include
-+ * the jobs waiting in the dispatcher, and dependency-only
-+ * jobs. See kbase_jd_context::job_nr for such jobs
-+ * @ctx.ctx_attr_ref_count: Context Attributes ref count. Each is large enough
-+ * to hold a refcount of the number of atoms on the context.
-+ * @ctx.is_scheduled_wait: Wait queue to wait for KCTX_SHEDULED flag state
-+ * changes.
-+ * @ctx.ctx_list_entry: Link implementing JS queues. Context can be present on
-+ * one list per job slot.
-+ * @init_status: The initalized-flag is placed at the end, to avoid
-+ * cache-pollution (we should only be using this during init/term paths)
- *
- * This is a substructure in the struct kbase_context that encapsulates all the
- * scheduling information.
- */
- struct kbasep_js_kctx_info {
--
-- /**
-- * Job Scheduler Context information sub-structure. These members are
-- * accessed regardless of whether the context is:
-- * - In the Policy's Run Pool
-- * - In the Policy's Queue
-- * - Not queued nor in the Run Pool.
-- *
-- * You must obtain the jsctx_mutex before accessing any other members of
-- * this substructure.
-- *
-- * You may not access any of these members from IRQ context.
-- */
- struct kbase_jsctx {
-- struct mutex jsctx_mutex; /**< Job Scheduler Context lock */
-+ struct mutex jsctx_mutex;
-
-- /** Number of jobs <b>ready to run</b> - does \em not include the jobs waiting in
-- * the dispatcher, and dependency-only jobs. See kbase_jd_context::job_nr
-- * for such jobs*/
- u32 nr_jobs;
--
-- /** Context Attributes:
-- * Each is large enough to hold a refcount of the number of atoms on
-- * the context. **/
- u32 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT];
--
-- /**
-- * Wait queue to wait for KCTX_SHEDULED flag state changes.
-- * */
- wait_queue_head_t is_scheduled_wait;
--
-- /** Link implementing JS queues. Context can be present on one
-- * list per job slot
-- */
- struct list_head ctx_list_entry[BASE_JM_MAX_NR_SLOTS];
- } ctx;
--
-- /* The initalized-flag is placed at the end, to avoid cache-pollution (we should
-- * only be using this during init/term paths) */
- int init_status;
- };
-
--/** Subset of atom state that can be available after jd_done_nolock() is called
-+/**
-+ * struct kbasep_js_atom_retained_state - Subset of atom state.
-+ * @event_code: to determine whether the atom has finished
-+ * @core_req: core requirements
-+ * @sched_priority: priority
-+ * @device_nr: Core group atom was executed on
-+ *
-+ * Subset of atom state that can be available after jd_done_nolock() is called
- * on that atom. A copy must be taken via kbasep_js_atom_retained_state_copy(),
-- * because the original atom could disappear. */
-+ * because the original atom could disappear.
-+ */
- struct kbasep_js_atom_retained_state {
-- /** Event code - to determine whether the atom has finished */
-+ /* Event code - to determine whether the atom has finished */
- enum base_jd_event_code event_code;
-- /** core requirements */
-+ /* core requirements */
- base_jd_core_req core_req;
- /* priority */
- int sched_priority;
-@@ -380,30 +374,23 @@ struct kbasep_js_atom_retained_state {
-
- };
-
--/**
-+/*
- * Value signifying 'no retry on a slot required' for:
- * - kbase_js_atom_retained_state::retry_submit_on_slot
- * - kbase_jd_atom::retry_submit_on_slot
- */
- #define KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID (-1)
-
--/**
-- * base_jd_core_req value signifying 'invalid' for a kbase_jd_atom_retained_state.
-- *
-- * @see kbase_atom_retained_state_is_valid()
-+/*
-+ * base_jd_core_req value signifying 'invalid' for a
-+ * kbase_jd_atom_retained_state. See kbase_atom_retained_state_is_valid()
- */
- #define KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID BASE_JD_REQ_DEP
-
--/**
-- * @brief The JS timer resolution, in microseconds
-- *
-+/*
-+ * The JS timer resolution, in microseconds
- * Any non-zero difference in time will be at least this size.
- */
- #define KBASEP_JS_TICK_RESOLUTION_US 1
-
--
-- /** @} *//* end group kbase_js */
-- /** @} *//* end group base_kbase_api */
-- /** @} *//* end group base_api */
--
--#endif /* _KBASE_JS_DEFS_H_ */
-+#endif /* _KBASE_JS_DEFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h
-index 6885f8d..93cd05f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_hwconfig_features.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features,
-@@ -50,12 +49,12 @@ enum base_hw_feature {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_COHERENCY_REG,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_TLS_HASHING,
- BASE_HW_FEATURE_THREAD_GROUP_SPLIT,
- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
- BASE_HW_FEATURE_IDVS_GROUP_SIZE,
- BASE_HW_FEATURE_L2_CONFIG,
-+ BASE_HW_FEATURE_ASN_HASH,
- BASE_HW_FEATURE_END
- };
-
-@@ -85,7 +84,6 @@ static const enum base_hw_feature base_hw_features_tMIx[] = {
- BASE_HW_FEATURE_THREAD_GROUP_SPLIT,
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_END
- };
-
-@@ -112,7 +110,6 @@ static const enum base_hw_feature base_hw_features_tHEx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_END
- };
-
-@@ -139,7 +136,6 @@ static const enum base_hw_feature base_hw_features_tSIx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_END
- };
-
-@@ -166,7 +162,6 @@ static const enum base_hw_feature base_hw_features_tDVx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_END
- };
-
-@@ -193,7 +188,6 @@ static const enum base_hw_feature base_hw_features_tNOx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_TLS_HASHING,
- BASE_HW_FEATURE_IDVS_GROUP_SIZE,
- BASE_HW_FEATURE_END
-@@ -222,7 +216,6 @@ static const enum base_hw_feature base_hw_features_tGOx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_TLS_HASHING,
- BASE_HW_FEATURE_IDVS_GROUP_SIZE,
- BASE_HW_FEATURE_END
-@@ -250,7 +243,6 @@ static const enum base_hw_feature base_hw_features_tTRx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_IDVS_GROUP_SIZE,
- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
- BASE_HW_FEATURE_END
-@@ -278,7 +270,6 @@ static const enum base_hw_feature base_hw_features_tNAx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_IDVS_GROUP_SIZE,
- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
- BASE_HW_FEATURE_END
-@@ -306,14 +297,13 @@ static const enum base_hw_feature base_hw_features_tBEx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_IDVS_GROUP_SIZE,
- BASE_HW_FEATURE_L2_CONFIG,
- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
- BASE_HW_FEATURE_END
- };
-
--static const enum base_hw_feature base_hw_features_tDUx[] = {
-+static const enum base_hw_feature base_hw_features_tBAx[] = {
- BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION,
- BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS,
- BASE_HW_FEATURE_XAFFINITY,
-@@ -335,14 +325,13 @@ static const enum base_hw_feature base_hw_features_tDUx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_IDVS_GROUP_SIZE,
- BASE_HW_FEATURE_L2_CONFIG,
- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
- BASE_HW_FEATURE_END
- };
-
--static const enum base_hw_feature base_hw_features_tODx[] = {
-+static const enum base_hw_feature base_hw_features_tDUx[] = {
- BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION,
- BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS,
- BASE_HW_FEATURE_XAFFINITY,
-@@ -364,13 +353,13 @@ static const enum base_hw_feature base_hw_features_tODx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
-+ BASE_HW_FEATURE_IDVS_GROUP_SIZE,
- BASE_HW_FEATURE_L2_CONFIG,
- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
- BASE_HW_FEATURE_END
- };
-
--static const enum base_hw_feature base_hw_features_tGRx[] = {
-+static const enum base_hw_feature base_hw_features_tODx[] = {
- BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION,
- BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS,
- BASE_HW_FEATURE_XAFFINITY,
-@@ -392,13 +381,12 @@ static const enum base_hw_feature base_hw_features_tGRx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_L2_CONFIG,
- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
- BASE_HW_FEATURE_END
- };
-
--static const enum base_hw_feature base_hw_features_tVAx[] = {
-+static const enum base_hw_feature base_hw_features_tGRx[] = {
- BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION,
- BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS,
- BASE_HW_FEATURE_XAFFINITY,
-@@ -420,13 +408,12 @@ static const enum base_hw_feature base_hw_features_tVAx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_L2_CONFIG,
- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
- BASE_HW_FEATURE_END
- };
-
--static const enum base_hw_feature base_hw_features_tTUx[] = {
-+static const enum base_hw_feature base_hw_features_tVAx[] = {
- BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION,
- BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS,
- BASE_HW_FEATURE_XAFFINITY,
-@@ -448,39 +435,10 @@ static const enum base_hw_feature base_hw_features_tTUx[] = {
- BASE_HW_FEATURE_FLUSH_REDUCTION,
- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
- BASE_HW_FEATURE_L2_CONFIG,
- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
- BASE_HW_FEATURE_END
- };
-
--static const enum base_hw_feature base_hw_features_tE2x[] = {
-- BASE_HW_FEATURE_JOBCHAIN_DISAMBIGUATION,
-- BASE_HW_FEATURE_PWRON_DURING_PWROFF_TRANS,
-- BASE_HW_FEATURE_XAFFINITY,
-- BASE_HW_FEATURE_WARPING,
-- BASE_HW_FEATURE_INTERPIPE_REG_ALIASING,
-- BASE_HW_FEATURE_32_BIT_UNIFORM_ADDRESS,
-- BASE_HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL,
-- BASE_HW_FEATURE_BRNDOUT_CC,
-- BASE_HW_FEATURE_BRNDOUT_KILL,
-- BASE_HW_FEATURE_LD_ST_LEA_TEX,
-- BASE_HW_FEATURE_LD_ST_TILEBUFFER,
-- BASE_HW_FEATURE_LINEAR_FILTER_FLOAT,
-- BASE_HW_FEATURE_MRT,
-- BASE_HW_FEATURE_MSAA_16X,
-- BASE_HW_FEATURE_NEXT_INSTRUCTION_TYPE,
-- BASE_HW_FEATURE_OUT_OF_ORDER_EXEC,
-- BASE_HW_FEATURE_T7XX_PAIRING_RULES,
-- BASE_HW_FEATURE_TEST4_DATUM_MODE,
-- BASE_HW_FEATURE_FLUSH_REDUCTION,
-- BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
-- BASE_HW_FEATURE_COHERENCY_REG,
-- BASE_HW_FEATURE_AARCH64_MMU,
-- BASE_HW_FEATURE_IDVS_GROUP_SIZE,
-- BASE_HW_FEATURE_L2_CONFIG,
-- BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
-- BASE_HW_FEATURE_END
--};
-
- #endif /* _BASE_HWCONFIG_FEATURES_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h
-index 3966069..beda1e4 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_hwconfig_issues.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features,
-@@ -59,6 +58,7 @@ enum base_hw_issue {
- BASE_HW_ISSUE_TTRX_3470,
- BASE_HW_ISSUE_TTRX_3464,
- BASE_HW_ISSUE_TTRX_3485,
-+ BASE_HW_ISSUE_GPU2019_3212,
- BASE_HW_ISSUE_END
- };
-
-@@ -532,79 +532,89 @@ static const enum base_hw_issue base_hw_issues_lBEx_r1p1[] = {
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_tDUx_r0p0[] = {
-+static const enum base_hw_issue base_hw_issues_tBAx_r0p0[] = {
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
-+ BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
- BASE_HW_ISSUE_TTRX_921,
- BASE_HW_ISSUE_TTRX_3414,
- BASE_HW_ISSUE_TTRX_3083,
-+ BASE_HW_ISSUE_TTRX_3470,
-+ BASE_HW_ISSUE_TTRX_3464,
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_model_tDUx[] = {
-- BASE_HW_ISSUE_5736,
-+static const enum base_hw_issue base_hw_issues_tBAx_r1p0[] = {
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
-+ BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
-+ BASE_HW_ISSUE_TTRX_921,
- BASE_HW_ISSUE_TTRX_3414,
- BASE_HW_ISSUE_TTRX_3083,
-+ BASE_HW_ISSUE_TTRX_3470,
-+ BASE_HW_ISSUE_TTRX_3464,
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_tODx_r0p0[] = {
-- BASE_HW_ISSUE_9435,
-- BASE_HW_ISSUE_TSIX_2033,
-- BASE_HW_ISSUE_TTRX_1337,
-- BASE_HW_ISSUE_END
--};
--
--static const enum base_hw_issue base_hw_issues_model_tODx[] = {
-+static const enum base_hw_issue base_hw_issues_model_tBAx[] = {
- BASE_HW_ISSUE_5736,
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
-+ BASE_HW_ISSUE_TTRX_3414,
-+ BASE_HW_ISSUE_TTRX_3083,
-+ BASE_HW_ISSUE_TTRX_3470,
-+ BASE_HW_ISSUE_TTRX_3464,
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_tGRx_r0p0[] = {
-+static const enum base_hw_issue base_hw_issues_tDUx_r0p0[] = {
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
-+ BASE_HW_ISSUE_TTRX_921,
-+ BASE_HW_ISSUE_TTRX_3414,
-+ BASE_HW_ISSUE_TTRX_3083,
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_model_tGRx[] = {
-+static const enum base_hw_issue base_hw_issues_model_tDUx[] = {
- BASE_HW_ISSUE_5736,
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
-+ BASE_HW_ISSUE_TTRX_3414,
-+ BASE_HW_ISSUE_TTRX_3083,
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_tVAx_r0p0[] = {
-+static const enum base_hw_issue base_hw_issues_tODx_r0p0[] = {
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
-+ BASE_HW_ISSUE_GPU2019_3212,
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_model_tVAx[] = {
-+static const enum base_hw_issue base_hw_issues_model_tODx[] = {
- BASE_HW_ISSUE_5736,
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
-+ BASE_HW_ISSUE_GPU2019_3212,
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_tTUx_r0p0[] = {
-+static const enum base_hw_issue base_hw_issues_tGRx_r0p0[] = {
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_model_tTUx[] = {
-+static const enum base_hw_issue base_hw_issues_model_tGRx[] = {
- BASE_HW_ISSUE_5736,
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
-@@ -612,24 +622,20 @@ static const enum base_hw_issue base_hw_issues_model_tTUx[] = {
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_tE2x_r0p0[] = {
-+static const enum base_hw_issue base_hw_issues_tVAx_r0p0[] = {
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
-- BASE_HW_ISSUE_TTRX_921,
-- BASE_HW_ISSUE_TTRX_3414,
-- BASE_HW_ISSUE_TTRX_3083,
- BASE_HW_ISSUE_END
- };
-
--static const enum base_hw_issue base_hw_issues_model_tE2x[] = {
-+static const enum base_hw_issue base_hw_issues_model_tVAx[] = {
- BASE_HW_ISSUE_5736,
- BASE_HW_ISSUE_9435,
- BASE_HW_ISSUE_TSIX_2033,
- BASE_HW_ISSUE_TTRX_1337,
-- BASE_HW_ISSUE_TTRX_3414,
-- BASE_HW_ISSUE_TTRX_3083,
- BASE_HW_ISSUE_END
- };
-
-+
- #endif /* _BASE_HWCONFIG_ISSUES_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase.h
-index 907142d..56db8ca 100755
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #ifndef _KBASE_H_
- #define _KBASE_H_
-
-@@ -38,7 +35,7 @@
- #include <linux/mutex.h>
- #include <linux/rwsem.h>
- #include <linux/sched.h>
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
-+#if (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE)
- #include <linux/sched/mm.h>
- #endif
- #include <linux/slab.h>
-@@ -46,8 +43,9 @@
- #include <linux/vmalloc.h>
- #include <linux/wait.h>
- #include <linux/workqueue.h>
-+#include <linux/interrupt.h>
-
--#include "mali_base_kernel.h"
-+#include <uapi/gpu/arm/midgard/mali_base_kernel.h>
- #include <mali_kbase_linux.h>
-
- /*
-@@ -66,26 +64,40 @@
- #include "mali_kbase_gpu_memory_debugfs.h"
- #include "mali_kbase_mem_profile_debugfs.h"
- #include "mali_kbase_gpuprops.h"
--#include "mali_kbase_ioctl.h"
-+#include <uapi/gpu/arm/midgard/mali_kbase_ioctl.h>
-+#if !MALI_USE_CSF
- #include "mali_kbase_debug_job_fault.h"
- #include "mali_kbase_jd_debugfs.h"
- #include "mali_kbase_jm.h"
- #include "mali_kbase_js.h"
-+#endif /* !MALI_USE_CSF */
-
- #include "ipa/mali_kbase_ipa.h"
-
--#ifdef CONFIG_GPU_TRACEPOINTS
-+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
- #include <trace/events/gpu.h>
- #endif
-
- #include "mali_linux_trace.h"
-
-+#if MALI_USE_CSF
-+#include "csf/mali_kbase_csf.h"
-+#endif
-
- #ifndef u64_to_user_ptr
- /* Introduced in Linux v4.6 */
- #define u64_to_user_ptr(x) ((void __user *)(uintptr_t)x)
- #endif
-
-+#if MALI_USE_CSF
-+/* Physical memory group ID for CSF user I/O.
-+ */
-+#define KBASE_MEM_GROUP_CSF_IO BASE_MEM_GROUP_DEFAULT
-+
-+/* Physical memory group ID for CSF firmware.
-+ */
-+#define KBASE_MEM_GROUP_CSF_FW BASE_MEM_GROUP_DEFAULT
-+#endif
-
- /* Physical memory group ID for a special page which can alias several regions.
- */
-@@ -140,9 +152,9 @@ void kbase_release_device(struct kbase_device *kbdev);
- * the flag @ref KBASE_REG_TILER_ALIGN_TOP (check the flags of the kbase
- * region):
- * - alignment offset is set to the difference between the kbase region
-- * extent (converted from the original value in pages to bytes) and the kbase
-+ * extension (converted from the original value in pages to bytes) and the kbase
- * region initial_commit (also converted from the original value in pages to
-- * bytes); alignment mask is set to the kbase region extent in bytes and
-+ * bytes); alignment mask is set to the kbase region extension in bytes and
- * decremented by 1.
- *
- * Return: if successful, address of the unmapped area aligned as required;
-@@ -184,7 +196,7 @@ void kbase_device_pm_term(struct kbase_device *kbdev);
- int power_control_init(struct kbase_device *kbdev);
- void power_control_term(struct kbase_device *kbdev);
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- void kbase_device_debugfs_term(struct kbase_device *kbdev);
- int kbase_device_debugfs_init(struct kbase_device *kbdev);
- #else /* CONFIG_DEBUG_FS */
-@@ -201,11 +213,8 @@ void registers_unmap(struct kbase_device *kbdev);
-
- int kbase_device_coherency_init(struct kbase_device *kbdev);
-
--#ifdef CONFIG_MALI_BUSLOG
--int buslog_init(struct kbase_device *kbdev);
--void buslog_term(struct kbase_device *kbdev);
--#endif
-
-+#if !MALI_USE_CSF
- int kbase_jd_init(struct kbase_context *kctx);
- void kbase_jd_exit(struct kbase_context *kctx);
-
-@@ -213,9 +222,9 @@ void kbase_jd_exit(struct kbase_context *kctx);
- * kbase_jd_submit - Submit atoms to the job dispatcher
- *
- * @kctx: The kbase context to submit to
-- * @user_addr: The address in user space of the struct base_jd_atom_v2 array
-+ * @user_addr: The address in user space of the struct base_jd_atom array
- * @nr_atoms: The number of atoms in the array
-- * @stride: sizeof(struct base_jd_atom_v2)
-+ * @stride: sizeof(struct base_jd_atom)
- * @uk6_atom: true if the atoms are legacy atoms (struct base_jd_atom_v2_uk6)
- *
- * Return: 0 on success or error code
-@@ -306,9 +315,12 @@ void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action,
- void kbase_job_check_leave_disjoint(struct kbase_device *kbdev,
- struct kbase_jd_atom *target_katom);
-
-+#endif /* !MALI_USE_CSF */
-
- void kbase_event_post(struct kbase_context *ctx, struct kbase_jd_atom *event);
-+#if !MALI_USE_CSF
- int kbase_event_dequeue(struct kbase_context *ctx, struct base_jd_event_v2 *uevent);
-+#endif /* !MALI_USE_CSF */
- int kbase_event_pending(struct kbase_context *ctx);
- int kbase_event_init(struct kbase_context *kctx);
- void kbase_event_close(struct kbase_context *kctx);
-@@ -372,6 +384,7 @@ static inline void kbase_free_user_buffer(
- */
- int kbase_mem_copy_from_extres(struct kbase_context *kctx,
- struct kbase_debug_copy_buffer *buf_data);
-+#if !MALI_USE_CSF
- int kbase_process_soft_job(struct kbase_jd_atom *katom);
- int kbase_prepare_soft_job(struct kbase_jd_atom *katom);
- void kbase_finish_soft_job(struct kbase_jd_atom *katom);
-@@ -387,18 +400,21 @@ int kbase_soft_event_update(struct kbase_context *kctx,
-
- void kbasep_soft_job_timeout_worker(struct timer_list *timer);
- void kbasep_complete_triggered_soft_events(struct kbase_context *kctx, u64 evt);
-+#endif /* !MALI_USE_CSF */
-
- void kbasep_as_do_poke(struct work_struct *work);
-
- /**
- * Check whether a system suspend is in progress, or has already been suspended
-+ * @kbdev: The kbase device structure for the device
- *
- * 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 false if a suspend is not in progress
-- * @return !=false otherwise
-+ * Return:
-+ * * false if a suspend is not in progress
-+ * * !=false otherwise
- */
- static inline bool kbase_pm_is_suspending(struct kbase_device *kbdev)
- {
-@@ -419,7 +435,27 @@ static inline bool kbase_pm_is_suspending(struct kbase_device *kbdev)
- */
- static inline bool kbase_pm_is_gpu_lost(struct kbase_device *kbdev)
- {
-- return kbdev->pm.gpu_lost;
-+ return (atomic_read(&kbdev->pm.gpu_lost) == 0 ? false : true);
-+}
-+
-+/*
-+ * Set or clear gpu lost state
-+ *
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ * @gpu_lost: true to activate GPU lost state, FALSE is deactive it
-+ *
-+ * Puts power management code into gpu lost state or takes it out of the
-+ * state. Once in gpu lost state new GPU jobs will no longer be
-+ * scheduled.
-+ */
-+static inline void kbase_pm_set_gpu_lost(struct kbase_device *kbdev,
-+ bool gpu_lost)
-+{
-+ const int new_val = (gpu_lost ? 1 : 0);
-+ const int cur_val = atomic_xchg(&kbdev->pm.gpu_lost, new_val);
-+
-+ if (new_val != cur_val)
-+ KBASE_KTRACE_ADD(kbdev, ARB_GPU_LOST, NULL, new_val);
- }
- #endif
-
-@@ -455,9 +491,12 @@ void kbase_pm_metrics_start(struct kbase_device *kbdev);
- */
- void kbase_pm_metrics_stop(struct kbase_device *kbdev);
-
-+#if !MALI_USE_CSF
- /**
- * Return the atom's ID, as was originally supplied by userspace in
-- * base_jd_atom_v2::atom_number
-+ * base_jd_atom::atom_number
-+ * @kctx: KBase context pointer
-+ * @katom: Atome for which to return ID
- */
- static inline int kbase_jd_atom_id(struct kbase_context *kctx, struct kbase_jd_atom *katom)
- {
-@@ -484,6 +523,7 @@ static inline struct kbase_jd_atom *kbase_jd_atom_from_id(
- {
- return &kctx->jctx.atoms[id];
- }
-+#endif /* !MALI_USE_CSF */
-
- /**
- * Initialize the disjoint state
-@@ -508,7 +548,7 @@ static inline struct kbase_jd_atom *kbase_jd_atom_from_id(
- * The disjoint event counter is also incremented immediately whenever a job is soft stopped
- * and during context creation.
- *
-- * @param kbdev The kbase device
-+ * @kbdev: The kbase device
- *
- * Return: 0 on success and non-zero value on failure.
- */
-@@ -518,7 +558,7 @@ void kbase_disjoint_init(struct kbase_device *kbdev);
- * Increase the count of disjoint events
- * called when a disjoint event has happened
- *
-- * @param kbdev The kbase device
-+ * @kbdev: The kbase device
- */
- void kbase_disjoint_event(struct kbase_device *kbdev);
-
-@@ -528,14 +568,14 @@ void kbase_disjoint_event(struct kbase_device *kbdev);
- * This should be called when something happens which could be disjoint if the GPU
- * is in a disjoint state. The state refcount keeps track of this.
- *
-- * @param kbdev The kbase device
-+ * @kbdev: The kbase device
- */
- void kbase_disjoint_event_potential(struct kbase_device *kbdev);
-
- /**
- * Returns the count of disjoint events
- *
-- * @param kbdev The kbase device
-+ * @kbdev: The kbase device
- * @return the count of disjoint events
- */
- u32 kbase_disjoint_event_get(struct kbase_device *kbdev);
-@@ -547,7 +587,7 @@ u32 kbase_disjoint_event_get(struct kbase_device *kbdev);
- * eventually after the disjoint state has completed @ref kbase_disjoint_state_down
- * should be called
- *
-- * @param kbdev The kbase device
-+ * @kbdev: The kbase device
- */
- void kbase_disjoint_state_up(struct kbase_device *kbdev);
-
-@@ -558,68 +598,43 @@ void kbase_disjoint_state_up(struct kbase_device *kbdev);
- *
- * Called after @ref kbase_disjoint_state_up once the disjoint state is over
- *
-- * @param kbdev The kbase device
-+ * @kbdev: The kbase device
- */
- void kbase_disjoint_state_down(struct kbase_device *kbdev);
-
- /**
-- * If a job is soft stopped and the number of contexts is >= this value
-- * it is reported as a disjoint event
-- */
--#define KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD 2
--
--#if !defined(UINT64_MAX)
-- #define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFFULL)
--#endif
--
--#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_NO_MALI)
--
--/* kbase_io_history_init - initialize data struct for register access history
-- *
-- * @kbdev The register history to initialize
-- * @n The number of register accesses that the buffer could hold
-+ * kbase_device_pcm_dev_init() - Initialize the priority control manager device
- *
-- * @return 0 if successfully initialized, failure otherwise
-- */
--int kbase_io_history_init(struct kbase_io_history *h, u16 n);
--
--/* kbase_io_history_term - uninit all resources for the register access history
-+ * @kbdev: Pointer to the structure for the kbase device
- *
-- * @h The register history to terminate
-- */
--void kbase_io_history_term(struct kbase_io_history *h);
--
--/* kbase_io_history_dump - print the register history to the kernel ring buffer
-+ * Pointer to the priority control manager device is retrieved from the device
-+ * tree and a reference is taken on the module implementing the callbacks for
-+ * priority control manager operations.
- *
-- * @kbdev Pointer to kbase_device containing the register history to dump
-+ * Return: 0 if successful, or an error code on failure
- */
--void kbase_io_history_dump(struct kbase_device *kbdev);
-+int kbase_device_pcm_dev_init(struct kbase_device *const kbdev);
-
- /**
-- * kbase_io_history_resize - resize the register access history buffer.
-+ * kbase_device_pcm_dev_term() - Performs priority control manager device
-+ * deinitialization.
- *
-- * @h: Pointer to a valid register history to resize
-- * @new_size: Number of accesses the buffer could hold
-+ * @kbdev: Pointer to the structure for the kbase device
- *
-- * A successful resize will clear all recent register accesses.
-- * If resizing fails for any reason (e.g., could not allocate memory, invalid
-- * buffer size) then the original buffer will be kept intact.
-- *
-- * @return 0 if the buffer was resized, failure otherwise
-+ * Reference is released on the module implementing the callbacks for priority
-+ * control manager operations.
- */
--int kbase_io_history_resize(struct kbase_io_history *h, u16 new_size);
--
--#else /* CONFIG_DEBUG_FS */
-+void kbase_device_pcm_dev_term(struct kbase_device *const kbdev);
-
--#define kbase_io_history_init(...) ((int)0)
--
--#define kbase_io_history_term CSTD_NOP
--
--#define kbase_io_history_dump CSTD_NOP
--
--#define kbase_io_history_resize CSTD_NOP
-+/**
-+ * If a job is soft stopped and the number of contexts is >= this value
-+ * it is reported as a disjoint event
-+ */
-+#define KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD 2
-
--#endif /* CONFIG_DEBUG_FS */
-+#if !defined(UINT64_MAX)
-+ #define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFFULL)
-+#endif
-
- /*meson graphics start */
- extern int meson_gpu_data_invalid_count;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_as_fault_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_as_fault_debugfs.c
-index 2e2e394..027eb8c 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_as_fault_debugfs.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_as_fault_debugfs.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2016-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2016-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/debugfs.h>
-@@ -26,7 +25,7 @@
- #include <mali_kbase_as_fault_debugfs.h>
- #include <device/mali_kbase_device.h>
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- #ifdef CONFIG_MALI_DEBUG
-
- static int kbase_as_fault_read(struct seq_file *sfile, void *data)
-@@ -80,7 +79,7 @@ static const struct file_operations as_fault_fops = {
- */
- void kbase_as_fault_debugfs_init(struct kbase_device *kbdev)
- {
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- #ifdef CONFIG_MALI_DEBUG
- uint i;
- char as_name[64];
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_as_fault_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_as_fault_debugfs.h
-index 496d8b1..919fbc1 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_as_fault_debugfs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_as_fault_debugfs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2016, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_AS_FAULT_DEBUG_FS_H
-@@ -39,7 +38,7 @@ void kbase_as_fault_debugfs_init(struct kbase_device *kbdev);
- static inline void
- kbase_as_fault_debugfs_new(struct kbase_device *kbdev, int as_no)
- {
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- #ifdef CONFIG_MALI_DEBUG
- kbdev->debugfs_as_read_bitmap |= (1ULL << as_no);
- #endif /* CONFIG_DEBUG_FS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_bits.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_bits.h
-index 2c11093..a085fd8 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_bits.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_bits.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,17 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--/*
-- *
-- * (C) COPYRIGHT 2019 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.
- */
-
- #ifndef _KBASE_BITS_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c
-index 27a03cf..af51ed8 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cache_policy.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Cache Policy API.
- */
-@@ -58,10 +55,11 @@ void kbase_sync_single_for_device(struct kbase_device *kbdev, dma_addr_t handle,
- {
- dma_sync_single_for_device(kbdev->dev, handle, size, dir);
- }
--
-+KBASE_EXPORT_TEST_API(kbase_sync_single_for_device);
-
- void kbase_sync_single_for_cpu(struct kbase_device *kbdev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir)
- {
- dma_sync_single_for_cpu(kbdev->dev, handle, size, dir);
- }
-+KBASE_EXPORT_TEST_API(kbase_sync_single_for_cpu);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h
-index 8a1e529..7da33a6 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cache_policy.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2013, 2015 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2013, 2015, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Cache Policy API.
- */
-@@ -30,7 +27,7 @@
- #define _KBASE_CACHE_POLICY_H_
-
- #include "mali_kbase.h"
--#include "mali_base_kernel.h"
-+#include <uapi/gpu/arm/midgard/mali_base_kernel.h>
-
- /**
- * kbase_cache_enabled - Choose the cache policy for a specific region
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_caps.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_caps.h
-new file mode 100644
-index 0000000..c232e21
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_caps.h
-@@ -0,0 +1,61 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/**
-+ * DOC: Driver Capability Queries.
-+ */
-+
-+#ifndef _KBASE_CAPS_H_
-+#define _KBASE_CAPS_H_
-+
-+#include <linux/types.h>
-+
-+typedef enum mali_kbase_cap {
-+ MALI_KBASE_CAP_SYSTEM_MONITOR = 0,
-+ MALI_KBASE_CAP_JIT_PRESSURE_LIMIT,
-+ MALI_KBASE_CAP_MEM_GROW_ON_GPF,
-+ MALI_KBASE_CAP_MEM_PROTECTED,
-+ MALI_KBASE_NUM_CAPS
-+} mali_kbase_cap;
-+
-+extern bool mali_kbase_supports_cap(unsigned long api_version, mali_kbase_cap cap);
-+
-+static inline bool mali_kbase_supports_system_monitor(unsigned long api_version)
-+{
-+ return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_SYSTEM_MONITOR);
-+}
-+
-+static inline bool mali_kbase_supports_jit_pressure_limit(unsigned long api_version)
-+{
-+ return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_JIT_PRESSURE_LIMIT);
-+}
-+
-+static inline bool mali_kbase_supports_mem_grow_on_gpf(unsigned long api_version)
-+{
-+ return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_MEM_GROW_ON_GPF);
-+}
-+
-+static inline bool mali_kbase_supports_mem_protected(unsigned long api_version)
-+{
-+ return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_MEM_PROTECTED);
-+}
-+
-+#endif /* __KBASE_CAPS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ccswe.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ccswe.c
-new file mode 100644
-index 0000000..6a1e7e4
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ccswe.c
-@@ -0,0 +1,100 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_ccswe.h"
-+#include "mali_kbase_linux.h"
-+
-+#include <linux/math64.h>
-+#include <linux/time.h>
-+
-+static u64 kbasep_ccswe_cycle_at_no_lock(
-+ struct kbase_ccswe *self, u64 timestamp_ns)
-+{
-+ s64 diff_s, diff_ns;
-+ u32 gpu_freq;
-+
-+ lockdep_assert_held(&self->access);
-+
-+ diff_ns = timestamp_ns - self->timestamp_ns;
-+ gpu_freq = diff_ns > 0 ? self->gpu_freq : self->prev_gpu_freq;
-+
-+ diff_s = div_s64(diff_ns, NSEC_PER_SEC);
-+ diff_ns -= diff_s * NSEC_PER_SEC;
-+
-+ return self->cycles_elapsed + diff_s * gpu_freq
-+ + div_s64(diff_ns * gpu_freq, NSEC_PER_SEC);
-+}
-+
-+void kbase_ccswe_init(struct kbase_ccswe *self)
-+{
-+ memset(self, 0, sizeof(*self));
-+
-+ spin_lock_init(&self->access);
-+}
-+
-+u64 kbase_ccswe_cycle_at(struct kbase_ccswe *self, u64 timestamp_ns)
-+{
-+ unsigned long flags;
-+ u64 result;
-+
-+ spin_lock_irqsave(&self->access, flags);
-+ result = kbasep_ccswe_cycle_at_no_lock(self, timestamp_ns);
-+ spin_unlock_irqrestore(&self->access, flags);
-+
-+ return result;
-+}
-+
-+void kbase_ccswe_freq_change(
-+ struct kbase_ccswe *self, u64 timestamp_ns, u32 gpu_freq)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&self->access, flags);
-+
-+ /* The time must go only forward. */
-+ if (WARN_ON(timestamp_ns < self->timestamp_ns))
-+ goto exit;
-+
-+ /* If this is the first frequency change, cycles_elapsed is zero. */
-+ if (self->timestamp_ns)
-+ self->cycles_elapsed = kbasep_ccswe_cycle_at_no_lock(
-+ self, timestamp_ns);
-+
-+ self->timestamp_ns = timestamp_ns;
-+ self->prev_gpu_freq = self->gpu_freq;
-+ self->gpu_freq = gpu_freq;
-+exit:
-+ spin_unlock_irqrestore(&self->access, flags);
-+}
-+
-+void kbase_ccswe_reset(struct kbase_ccswe *self)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&self->access, flags);
-+
-+ self->timestamp_ns = 0;
-+ self->cycles_elapsed = 0;
-+ self->gpu_freq = 0;
-+ self->prev_gpu_freq = 0;
-+
-+ spin_unlock_irqrestore(&self->access, flags);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ccswe.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ccswe.h
-new file mode 100644
-index 0000000..8e55ffc
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ccswe.h
-@@ -0,0 +1,96 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_CCSWE_H_
-+#define _KBASE_CCSWE_H_
-+
-+#include <linux/spinlock.h>
-+
-+/**
-+ * struct kbase_ccswe - Cycle count software estimator.
-+ *
-+ * @access: Spinlock protecting this structure access.
-+ * @timestamp_ns: Timestamp(ns) when the last frequency change
-+ * occurred.
-+ * @cycles_elapsed: Number of cycles elapsed before the last frequency
-+ * change
-+ * @gpu_freq: Current GPU frequency(Hz) value.
-+ * @prev_gpu_freq: Previous GPU frequency(Hz) before the last frequency
-+ * change.
-+ */
-+struct kbase_ccswe {
-+ spinlock_t access;
-+ u64 timestamp_ns;
-+ u64 cycles_elapsed;
-+ u32 gpu_freq;
-+ u32 prev_gpu_freq;
-+};
-+
-+/**
-+ * kbase_ccswe_init() - initialize the cycle count estimator.
-+ *
-+ * @self: Cycles count software estimator instance.
-+ */
-+void kbase_ccswe_init(struct kbase_ccswe *self);
-+
-+
-+/**
-+ * kbase_ccswe_cycle_at() - Estimate cycle count at given timestamp.
-+ *
-+ * @self: Cycles count software estimator instance.
-+ * @timestamp_ns: The timestamp(ns) for cycle count estimation.
-+ *
-+ * The timestamp must be bigger than the timestamp of the penultimate
-+ * frequency change. If only one frequency change occurred, the
-+ * timestamp must be bigger than the timestamp of the frequency change.
-+ * This is to allow the following code to be executed w/o synchronization.
-+ * If lines below executed atomically, it is safe to assume that only
-+ * one frequency change may happen in between.
-+ *
-+ * u64 ts = ktime_get_raw_ns();
-+ * u64 cycle = kbase_ccswe_cycle_at(&ccswe, ts)
-+ *
-+ * Returns: estimated value of cycle count at a given time.
-+ */
-+u64 kbase_ccswe_cycle_at(struct kbase_ccswe *self, u64 timestamp_ns);
-+
-+/**
-+ * kbase_ccswe_freq_change() - update GPU frequency.
-+ *
-+ * @self: Cycles count software estimator instance.
-+ * @timestamp_ns: Timestamp(ns) when frequency change occurred.
-+ * @gpu_freq: New GPU frequency value.
-+ *
-+ * The timestamp must be bigger than the timestamp of the previous
-+ * frequency change. The function is to be called at the frequency
-+ * change moment (not later).
-+ */
-+void kbase_ccswe_freq_change(
-+ struct kbase_ccswe *self, u64 timestamp_ns, u32 gpu_freq);
-+
-+/**
-+ * kbase_ccswe_reset() - reset estimator state
-+ *
-+ * @self: Cycles count software estimator instance.
-+ */
-+void kbase_ccswe_reset(struct kbase_ccswe *self);
-+
-+#endif /* _KBASE_CCSWE_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config.c
-index ce7070d..37dbca1 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2015,2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2015, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #include <mali_kbase.h>
- #include <mali_kbase_defs.h>
- #include <mali_kbase_config_defaults.h>
-@@ -46,3 +43,62 @@ void kbasep_platform_device_term(struct kbase_device *kbdev)
- platform_funcs_p->platform_term_func(kbdev);
- }
-
-+int kbasep_platform_device_late_init(struct kbase_device *kbdev)
-+{
-+ struct kbase_platform_funcs_conf *platform_funcs_p;
-+
-+ platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS;
-+ if (platform_funcs_p && platform_funcs_p->platform_late_init_func)
-+ platform_funcs_p->platform_late_init_func(kbdev);
-+
-+ return 0;
-+}
-+
-+void kbasep_platform_device_late_term(struct kbase_device *kbdev)
-+{
-+ struct kbase_platform_funcs_conf *platform_funcs_p;
-+
-+ platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS;
-+ if (platform_funcs_p && platform_funcs_p->platform_late_term_func)
-+ platform_funcs_p->platform_late_term_func(kbdev);
-+}
-+
-+#if !MALI_USE_CSF
-+int kbasep_platform_context_init(struct kbase_context *kctx)
-+{
-+ struct kbase_platform_funcs_conf *platform_funcs_p;
-+
-+ platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS;
-+ if (platform_funcs_p && platform_funcs_p->platform_handler_context_init_func)
-+ return platform_funcs_p->platform_handler_context_init_func(kctx);
-+
-+ return 0;
-+}
-+
-+void kbasep_platform_context_term(struct kbase_context *kctx)
-+{
-+ struct kbase_platform_funcs_conf *platform_funcs_p;
-+
-+ platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS;
-+ if (platform_funcs_p && platform_funcs_p->platform_handler_context_term_func)
-+ platform_funcs_p->platform_handler_context_term_func(kctx);
-+}
-+
-+void kbasep_platform_event_atom_submit(struct kbase_jd_atom *katom)
-+{
-+ struct kbase_platform_funcs_conf *platform_funcs_p;
-+
-+ platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS;
-+ if (platform_funcs_p && platform_funcs_p->platform_handler_atom_submit_func)
-+ platform_funcs_p->platform_handler_atom_submit_func(katom);
-+}
-+
-+void kbasep_platform_event_atom_complete(struct kbase_jd_atom *katom)
-+{
-+ struct kbase_platform_funcs_conf *platform_funcs_p;
-+
-+ platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS;
-+ if (platform_funcs_p && platform_funcs_p->platform_handler_atom_complete_func)
-+ platform_funcs_p->platform_handler_atom_complete_func(katom);
-+}
-+#endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config.h
-index 69723ea..e7eb334 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2017, 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2017, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_config.h
-- * Configuration API and Attributes for KBase
-+ * DOC: Configuration API and Attributes for KBase
- */
-
- #ifndef _KBASE_CONFIG_H_
-@@ -32,37 +28,31 @@
-
- #include <linux/mm.h>
- #include <mali_malisw.h>
--#include <mali_kbase_backend_config.h>
-+#include <backend/gpu/mali_kbase_backend_config.h>
- #include <linux/rbtree.h>
-
--/**
-- * @addtogroup base_api
-- * @{
-- */
--
--/**
-- * @addtogroup base_kbase_api
-- * @{
-- */
--
--/**
-- * @addtogroup kbase_config Configuration API and Attributes
-- * @{
-- */
--
- /* Forward declaration of struct kbase_device */
- struct kbase_device;
-
-+#if !MALI_USE_CSF
-+/* Forward declaration of struct kbase_context */
-+struct kbase_context;
-+
-+/* Forward declaration of struct kbase_atom */
-+struct kbase_jd_atom;
-+#endif
-+
- /**
-- * kbase_platform_funcs_conf - Specifies platform init/term function pointers
-+ * struct kbase_platform_funcs_conf - Specifies platform integration function
-+ * pointers for DDK events such as device init and term.
- *
- * Specifies the functions pointers for platform specific initialization and
-- * termination. By default no functions are required. No additional platform
-- * specific control is necessary.
-+ * termination as well as other events. By default no functions are required.
-+ * No additional platform specific control is necessary.
- */
- struct kbase_platform_funcs_conf {
- /**
-- * platform_init_func - platform specific init function pointer
-+ * @platform_init_func: platform specific init function pointer
- * @kbdev - kbase_device pointer
- *
- * Returns 0 on success, negative error code otherwise.
-@@ -77,7 +67,7 @@ struct kbase_platform_funcs_conf {
- */
- int (*platform_init_func)(struct kbase_device *kbdev);
- /**
-- * platform_term_func - platform specific termination function pointer
-+ * @platform_term_func: platform specific termination function pointer
- * @kbdev - kbase_device pointer
- *
- * Function pointer for platform specific termination or NULL if no
-@@ -88,6 +78,84 @@ struct kbase_platform_funcs_conf {
- * can be accessed (and possibly terminated) in here.
- */
- void (*platform_term_func)(struct kbase_device *kbdev);
-+
-+ /**
-+ * @platform_late_init_func: platform specific late init function pointer
-+ * @kbdev - kbase_device pointer
-+ *
-+ * Function pointer to inform that the kbase driver initialization completed
-+ * or NULL if no such function is required. At this point the GPU driver will be
-+ * fully initialized.
-+ *
-+ * The platform specific private pointer kbase_device::platform_context
-+ * can be accessed (and possibly terminated) in here.
-+ */
-+ int (*platform_late_init_func)(struct kbase_device *kbdev);
-+
-+ /**
-+ * @platform_late_term_func: platform specific late termination function pointer
-+ * @kbdev - kbase_device pointer
-+ *
-+ * Function pointer for platform specific termination or NULL if no
-+ * termination function is required. At this point the GPU driver will complete
-+ * termination process
-+ *
-+ * The platform specific private pointer kbase_device::platform_context
-+ * can be accessed (and possibly terminated) in here.
-+ */
-+ void (*platform_late_term_func)(struct kbase_device *kbdev);
-+
-+#if !MALI_USE_CSF
-+ /**
-+ * @platform_handler_context_init_func: platform specific handler for
-+ * when a new kbase_context is created.
-+ * @kctx - kbase_context pointer
-+ *
-+ * Returns 0 on success, negative error code otherwise.
-+ *
-+ * Function pointer for platform specific initialization of a kernel
-+ * context or NULL if not required. Called at the last stage of kernel
-+ * context initialization.
-+ */
-+ int (*platform_handler_context_init_func)(struct kbase_context *kctx);
-+ /**
-+ * @platform_handler_context_term_func: platform specific handler for
-+ * when a kbase_context is terminated.
-+ * @kctx - kbase_context pointer
-+ *
-+ * Function pointer for platform specific termination of a kernel
-+ * context or NULL if not required. Called at the first stage of kernel
-+ * context termination.
-+ */
-+ void (*platform_handler_context_term_func)(struct kbase_context *kctx);
-+ /**
-+ * @platform_handler_atom_submit_func: platform specific handler for
-+ * when a kbase_jd_atom is submitted.
-+ * @katom - kbase_jd_atom pointer
-+ *
-+ * Function pointer for platform specific handling at the point when an
-+ * atom is submitted to the GPU or set to NULL if not required. The
-+ * function cannot assume that it is running in a process context.
-+ *
-+ * Context: The caller must hold the hwaccess_lock. Function must be
-+ * runnable in an interrupt context.
-+ */
-+ void (*platform_handler_atom_submit_func)(struct kbase_jd_atom *katom);
-+ /**
-+ * @platform_handler_atom_complete_func: platform specific handler for
-+ * when a kbase_jd_atom completes.
-+ * @katom - kbase_jd_atom pointer
-+ *
-+ * Function pointer for platform specific handling at the point when an
-+ * atom stops running on the GPU or set to NULL if not required. The
-+ * function cannot assume that it is running in a process context.
-+ *
-+ * Context: The caller must hold the hwaccess_lock. Function must be
-+ * runnable in an interrupt context.
-+ */
-+ void (*platform_handler_atom_complete_func)(
-+ struct kbase_jd_atom *katom);
-+#endif
- };
-
- /*
-@@ -223,7 +291,90 @@ struct kbase_pm_callback_conf {
- int (*soft_reset_callback)(struct kbase_device *kbdev);
- };
-
--#ifdef CONFIG_OF
-+/* struct kbase_gpu_clk_notifier_data - Data for clock rate change notifier.
-+ *
-+ * Pointer to this structure is supposed to be passed to the gpu clock rate
-+ * change notifier function. This structure is deliberately aligned with the
-+ * common clock framework notification structure 'struct clk_notifier_data'
-+ * and such alignment should be maintained.
-+ *
-+ * @gpu_clk_handle: Handle of the GPU clock for which notifier was registered.
-+ * @old_rate: Previous rate of this GPU clock in Hz.
-+ * @new_rate: New rate of this GPU clock in Hz.
-+ */
-+struct kbase_gpu_clk_notifier_data {
-+ void *gpu_clk_handle;
-+ unsigned long old_rate;
-+ unsigned long new_rate;
-+};
-+
-+/**
-+ * struct kbase_clk_rate_trace_op_conf - Specifies GPU clock rate trace
-+ * operations.
-+ *
-+ * Specifies the functions pointers for platform specific GPU clock rate trace
-+ * operations. By default no functions are required.
-+ */
-+struct kbase_clk_rate_trace_op_conf {
-+ /**
-+ * @enumerate_gpu_clk: Enumerate a GPU clock on the given index
-+ * @kbdev - kbase_device pointer
-+ * @index - GPU clock index
-+ *
-+ * Returns a handle unique to the given GPU clock, or NULL if the clock
-+ * array has been exhausted at the given index value.
-+ *
-+ * Kbase will use this function pointer to enumerate the existence of a
-+ * GPU clock on the given index.
-+ */
-+ void *(*enumerate_gpu_clk)(struct kbase_device *kbdev,
-+ unsigned int index);
-+
-+ /**
-+ * @get_gpu_clk_rate: Get the current rate for an enumerated clock.
-+ * @kbdev - kbase_device pointer
-+ * @gpu_clk_handle - Handle unique to the enumerated GPU clock
-+ *
-+ * Returns current rate of the GPU clock in unit of Hz.
-+ */
-+ unsigned long (*get_gpu_clk_rate)(struct kbase_device *kbdev,
-+ void *gpu_clk_handle);
-+
-+ /**
-+ * @gpu_clk_notifier_register: Register a clock rate change notifier.
-+ * @kbdev - kbase_device pointer
-+ * @gpu_clk_handle - Handle unique to the enumerated GPU clock
-+ * @nb - notifier block containing the callback function
-+ * pointer
-+ *
-+ * Returns 0 on success, negative error code otherwise.
-+ *
-+ * This function pointer is used to register a callback function that
-+ * is supposed to be invoked whenever the rate of clock corresponding
-+ * to @gpu_clk_handle changes.
-+ * @nb contains the pointer to callback function.
-+ * The callback function expects the pointer of type
-+ * 'struct kbase_gpu_clk_notifier_data' as the third argument.
-+ */
-+ int (*gpu_clk_notifier_register)(struct kbase_device *kbdev,
-+ void *gpu_clk_handle, struct notifier_block *nb);
-+
-+ /**
-+ * @gpu_clk_notifier_unregister: Unregister clock rate change notifier
-+ * @kbdev - kbase_device pointer
-+ * @gpu_clk_handle - Handle unique to the enumerated GPU clock
-+ * @nb - notifier block containing the callback function
-+ * pointer
-+ *
-+ * This function pointer is used to unregister a callback function that
-+ * was previously registered to get notified of the change in rate
-+ * of clock corresponding to @gpu_clk_handle.
-+ */
-+ void (*gpu_clk_notifier_unregister)(struct kbase_device *kbdev,
-+ void *gpu_clk_handle, struct notifier_block *nb);
-+};
-+
-+#if IS_ENABLED(CONFIG_OF)
- struct kbase_platform_config {
- };
- #else
-@@ -253,7 +404,7 @@ struct kbase_platform_config {
- #endif /* CONFIG_OF */
-
- /**
-- * @brief Gets the pointer to platform config.
-+ * kbase_get_platform_config - Gets the pointer to platform config.
- *
- * @return Pointer to the platform config
- */
-@@ -284,6 +435,83 @@ int kbasep_platform_device_init(struct kbase_device *kbdev);
- */
- void kbasep_platform_device_term(struct kbase_device *kbdev);
-
-+/**
-+ * kbasep_platform_device_late_init: - Platform specific call to finish hardware
-+ * initialization
-+ * @kbdev: kbase device pointer
-+ *
-+ * 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.
-+ *
-+ * Return: 0 if no errors have been found in the config.
-+ * Negative error code otherwise.
-+ */
-+int kbasep_platform_device_late_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbasep_platform_device_late_term - Platform specific call to finish hardware
-+ * termination
-+ * @kbdev: Kbase device pointer
-+ *
-+ * 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.
-+ *
-+ */
-+void kbasep_platform_device_late_term(struct kbase_device *kbdev);
-+
-+#if !MALI_USE_CSF
-+/**
-+ * kbasep_platform_context_init - Platform specific callback when a kernel
-+ * context is created
-+ * @kctx: kbase_context pointer
-+ *
-+ * Function calls a platform defined routine if specified in the configuration
-+ * attributes. The routine can initialize any per kernel context structures
-+ * that are required for the GPU block to function.
-+ *
-+ * Return: 0 if no errors were encountered. Negative error code otherwise.
-+ */
-+int kbasep_platform_context_init(struct kbase_context *kctx);
-+
-+/**
-+ * kbasep_platform_context_term - Platform specific callback when a kernel
-+ * context is terminated
-+ * @kctx: kbase_context pointer
-+ *
-+ * Function calls a platform defined routine if specified in the configuration
-+ * attributes. The routine should terminate any per kernel context structures
-+ * created as part of &kbasep_platform_context_init.
-+ *
-+ */
-+void kbasep_platform_context_term(struct kbase_context *kctx);
-+
-+/**
-+ * kbasep_platform_event_atom_submit - Platform specific callback when an atom
-+ * is submitted to the GPU
-+ * @katom: kbase_jd_atom pointer
-+ *
-+ * Function calls a platform defined routine if specified in the configuration
-+ * attributes. The routine should not assume that it is in a process context.
-+ *
-+ * Return: 0 if no errors were encountered. Negative error code otherwise.
-+ */
-+void kbasep_platform_event_atom_submit(struct kbase_jd_atom *katom);
-+
-+/**
-+ * kbasep_platform_event_atom_complete - Platform specific callback when an atom
-+ * has stopped running on the GPU
-+ * @katom: kbase_jd_atom pointer
-+ *
-+ * Function calls a platform defined routine if specified in the configuration
-+ * attributes. The routine should not assume that it is in a process context.
-+ *
-+ */
-+void kbasep_platform_event_atom_complete(struct kbase_jd_atom *katom);
-+#endif
-+
- #ifndef CONFIG_OF
- /**
- * kbase_platform_register - Register a platform device for the GPU
-@@ -304,8 +532,4 @@ int kbase_platform_register(void);
- void kbase_platform_unregister(void);
- #endif
-
-- /** @} *//* end group kbase_config */
-- /** @} *//* end group base_kbase_api */
-- /** @} *//* end group base_api */
--
- #endif /* _KBASE_CONFIG_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h
-index e079281..63c36e2 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2013-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2013-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,14 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-- * @file mali_kbase_config_defaults.h
-- *
-- * Default values for configuration settings
-+ * DOC: Default values for configuration settings
- *
- */
-
-@@ -88,29 +85,38 @@ enum {
- };
-
- /**
-- * Default period for DVFS sampling
-+ * Default period for DVFS sampling (can be overridden by platform header)
- */
-+#ifndef DEFAULT_PM_DVFS_PERIOD
- #define DEFAULT_PM_DVFS_PERIOD 100 /* 100ms */
-+#endif
-
- /**
- * Power Management poweroff tick granuality. This is in nanoseconds to
-- * allow HR timer support.
-+ * allow HR timer support (can be overridden by platform header).
- *
- * On each scheduling tick, the power manager core may decide to:
- * -# Power off one or more shader cores
- * -# Power off the entire GPU
- */
-+#ifndef DEFAULT_PM_GPU_POWEROFF_TICK_NS
- #define DEFAULT_PM_GPU_POWEROFF_TICK_NS (400000) /* 400us */
-+#endif
-
- /**
- * Power Manager number of ticks before shader cores are powered off
-+ * (can be overridden by platform header).
- */
-+#ifndef DEFAULT_PM_POWEROFF_TICK_SHADER
- #define DEFAULT_PM_POWEROFF_TICK_SHADER (2) /* 400-800us */
-+#endif
-
- /**
-- * Default scheduling tick granuality
-+ * Default scheduling tick granuality (can be overridden by platform header)
- */
-+#ifndef DEFAULT_JS_SCHEDULING_PERIOD_NS
- #define DEFAULT_JS_SCHEDULING_PERIOD_NS (100000000u) /* 100ms */
-+#endif
-
- /**
- * Default minimum number of scheduling ticks before jobs are soft-stopped.
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
-index fb2353e..ce84219 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
-@@ -28,37 +27,39 @@
- #ifdef CONFIG_MALI_DEVFREQ
- #include <linux/devfreq.h>
- #include <backend/gpu/mali_kbase_devfreq.h>
--#ifdef CONFIG_DEVFREQ_THERMAL
-+#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
- #include <ipa/mali_kbase_ipa_debugfs.h>
- #endif /* CONFIG_DEVFREQ_THERMAL */
- #endif /* CONFIG_MALI_DEVFREQ */
--#ifdef CONFIG_MALI_NO_MALI
--#include "mali_kbase_model_linux.h"
--#include <backend/gpu/mali_kbase_model_dummy.h>
--#endif /* CONFIG_MALI_NO_MALI */
- #include "mali_kbase_mem_profile_debugfs_buf_size.h"
--#include "mali_kbase_debug_mem_view.h"
- #include "mali_kbase_mem.h"
- #include "mali_kbase_mem_pool_debugfs.h"
-+#include "mali_kbase_mem_pool_group.h"
- #include "mali_kbase_debugfs_helper.h"
--#if !MALI_CUSTOMER_RELEASE
--#include "mali_kbase_regs_dump_debugfs.h"
--#endif /* !MALI_CUSTOMER_RELEASE */
- #include "mali_kbase_regs_history_debugfs.h"
- #include <mali_kbase_hwaccess_backend.h>
- #include <mali_kbase_hwaccess_time.h>
-+#if !MALI_USE_CSF
- #include <mali_kbase_hwaccess_jm.h>
--#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY_VIA_DEBUG_FS
-+#endif /* !MALI_USE_CSF */
-+#ifdef CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
- #include <mali_kbase_hwaccess_instr.h>
- #endif
--#include <mali_kbase_ctx_sched.h>
- #include <mali_kbase_reset_gpu.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
--#include "mali_kbase_ioctl.h"
-+#include <uapi/gpu/arm/midgard/mali_kbase_ioctl.h>
-+#if !MALI_USE_CSF
-+#include "mali_kbase_kinstr_jm.h"
-+#endif
- #include "mali_kbase_hwcnt_context.h"
- #include "mali_kbase_hwcnt_virtualizer.h"
- #include "mali_kbase_hwcnt_legacy.h"
- #include "mali_kbase_vinstr.h"
-+#if MALI_USE_CSF
-+#include "csf/mali_kbase_csf_firmware.h"
-+#include "csf/mali_kbase_csf_tiler_heap.h"
-+#include "csf/mali_kbase_csf_csg_debugfs.h"
-+#include "csf/mali_kbase_csf_cpu_queue_debugfs.h"
-+#endif
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- #include "arbiter/mali_kbase_arbiter_pm.h"
- #endif
-@@ -68,7 +69,8 @@
- #ifdef CONFIG_MALI_CINSTR_GWT
- #include "mali_kbase_gwt.h"
- #endif
--#include "mali_kbase_pm_internal.h"
-+#include "backend/gpu/mali_kbase_pm_internal.h"
-+#include "mali_kbase_dvfs_debugfs.h"
-
- #include <linux/module.h>
- #include <linux/init.h>
-@@ -99,13 +101,7 @@
-
- #include <mali_kbase_config.h>
-
--
--#if (KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE)
- #include <linux/pm_opp.h>
--#else
--#include <linux/opp.h>
--#endif
--
- #include <linux/pm_runtime.h>
-
- #include <tl/mali_kbase_timeline.h>
-@@ -114,6 +110,8 @@
- #include <device/mali_kbase_device.h>
- #include <context/mali_kbase_context.h>
-
-+#include <mali_kbase_caps.h>
-+
- /* GPU IRQ Tags */
- #define JOB_IRQ_TAG 0
- #define MMU_IRQ_TAG 1
-@@ -121,6 +119,72 @@
-
- #define KERNEL_SIDE_DDK_VERSION_STRING "K:" MALI_RELEASE_NAME "(GPL)"
-
-+/**
-+ * KBASE_API_VERSION - KBase API Version
-+ * @major: Kernel major version
-+ * @minor: Kernel minor version
-+ */
-+#define KBASE_API_VERSION(major, minor) ((((major) & 0xFFF) << 20) | \
-+ (((minor) & 0xFFF) << 8) | \
-+ ((0 & 0xFF) << 0))
-+
-+#define KBASE_API_MIN(api_version) ((api_version >> 8) & 0xFFF)
-+#define KBASE_API_MAJ(api_version) ((api_version >> 20) & 0xFFF)
-+
-+/**
-+ * typedef mali_kbase_capability_def - kbase capabilities table
-+ */
-+typedef struct mali_kbase_capability_def {
-+ u16 required_major;
-+ u16 required_minor;
-+} mali_kbase_capability_def;
-+
-+/*
-+ * This must be kept in-sync with mali_kbase_cap
-+ *
-+ * TODO: The alternative approach would be to embed the cap enum values
-+ * in the table. Less efficient but potentially safer.
-+ */
-+static mali_kbase_capability_def kbase_caps_table[MALI_KBASE_NUM_CAPS] = {
-+#if MALI_USE_CSF
-+ { 1, 0 }, /* SYSTEM_MONITOR */
-+ { 1, 0 }, /* JIT_PRESSURE_LIMIT */
-+ { 1, 0 }, /* MEM_GROW_ON_GPF */
-+ { 1, 0 } /* MEM_PROTECTED */
-+#else
-+ { 11, 15 }, /* SYSTEM_MONITOR */
-+ { 11, 25 }, /* JIT_PRESSURE_LIMIT */
-+ { 11, 2 }, /* MEM_GROW_ON_GPF */
-+ { 11, 2 } /* MEM_PROTECTED */
-+#endif
-+};
-+
-+/**
-+ * mali_kbase_supports_cap - Query whether a kbase capability is supported
-+ *
-+ * @api_version: API version to convert
-+ * @cap: Capability to query for - see mali_kbase_caps.h
-+ */
-+bool mali_kbase_supports_cap(unsigned long api_version, mali_kbase_cap cap)
-+{
-+ bool supported = false;
-+ unsigned long required_ver;
-+
-+ mali_kbase_capability_def const *cap_def;
-+
-+ if (WARN_ON(cap < 0))
-+ return false;
-+
-+ if (WARN_ON(cap >= MALI_KBASE_NUM_CAPS))
-+ return false;
-+
-+ cap_def = &kbase_caps_table[(int)cap];
-+ required_ver = KBASE_API_VERSION(cap_def->required_major, cap_def->required_minor);
-+ supported = (api_version >= required_ver);
-+
-+ return supported;
-+}
-+
- /**
- * kbase_file_new - Create an object representing a device file
- *
-@@ -152,7 +216,7 @@ static struct kbase_file *kbase_file_new(struct kbase_device *const kbdev,
- }
-
- /**
-- * kbase_file_get_api_version - Set the application programmer interface version
-+ * kbase_file_set_api_version - Set the application programmer interface version
- *
- * @kfile: A device file created by kbase_file_new()
- * @major: Major version number (must not exceed 12 bits)
-@@ -271,7 +335,7 @@ static void kbase_file_delete(struct kbase_file *const kfile)
- if (atomic_read(&kfile->setup_state) == KBASE_FILE_COMPLETE) {
- struct kbase_context *kctx = kfile->kctx;
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- kbasep_mem_profile_debugfs_remove(kctx);
- #endif
-
-@@ -326,31 +390,18 @@ static int kbase_api_handshake(struct kbase_file *kfile,
- * the flags have been set. Originally it was created on file open
- * (with job submission disabled) but we don't support that usage.
- */
-- if (kbase_file_get_api_version(kfile) < KBASE_API_VERSION(11, 15))
-+ if (!mali_kbase_supports_system_monitor(kbase_file_get_api_version(kfile)))
- err = kbase_file_create_kctx(kfile,
- BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED);
-
- return err;
- }
-
--/**
-- * enum mali_error - Mali error codes shared with userspace
-- *
-- * This is subset of those common Mali errors that can be returned to userspace.
-- * Values of matching user and kernel space enumerators MUST be the same.
-- * MALI_ERROR_NONE is guaranteed to be 0.
-- *
-- * @MALI_ERROR_NONE: Success
-- * @MALI_ERROR_OUT_OF_GPU_MEMORY: Not used in the kernel driver
-- * @MALI_ERROR_OUT_OF_MEMORY: Memory allocation failure
-- * @MALI_ERROR_FUNCTION_FAILED: Generic error code
-- */
--enum mali_error {
-- MALI_ERROR_NONE = 0,
-- MALI_ERROR_OUT_OF_GPU_MEMORY,
-- MALI_ERROR_OUT_OF_MEMORY,
-- MALI_ERROR_FUNCTION_FAILED,
--};
-+static int kbase_api_handshake_dummy(struct kbase_file *kfile,
-+ struct kbase_ioctl_version_check *version)
-+{
-+ return -EPERM;
-+}
-
- static struct kbase_device *to_kbase_device(struct device *dev)
- {
-@@ -377,7 +428,7 @@ int assign_irqs(struct kbase_device *kbdev)
- return -ENOENT;
- }
-
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- if (!strncasecmp(irq_res->name, "JOB", 4)) {
- irqtag = JOB_IRQ_TAG;
- } else if (!strncasecmp(irq_res->name, "MMU", 4)) {
-@@ -428,10 +479,10 @@ void kbase_release_device(struct kbase_device *kbdev)
- }
- EXPORT_SYMBOL(kbase_release_device);
-
--#ifdef CONFIG_DEBUG_FS
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) && \
-- !(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 28) && \
-- LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && \
-+ !(KERNEL_VERSION(4, 4, 28) <= LINUX_VERSION_CODE && \
-+ KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE)
- /*
- * Older versions, before v4.6, of the kernel doesn't have
- * kstrtobool_from_user(), except longterm 4.4.y which had it added in 4.4.28
-@@ -545,7 +596,7 @@ static int kbase_file_create_kctx(struct kbase_file *const kfile,
- {
- struct kbase_device *kbdev = NULL;
- struct kbase_context *kctx = NULL;
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- char kctx_name[64];
- #endif
-
-@@ -576,9 +627,11 @@ static int kbase_file_create_kctx(struct kbase_file *const kfile,
- if (kbdev->infinite_cache_active_default)
- kbase_ctx_flag_set(kctx, KCTX_INFINITE_CACHE);
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- snprintf(kctx_name, 64, "%d_%d", kctx->tgid, kctx->id);
-
-+ mutex_init(&kctx->mem_profile_lock);
-+
- kctx->kctx_dentry = debugfs_create_dir(kctx_name,
- kbdev->debugfs_ctx_directory);
-
-@@ -599,8 +652,6 @@ static int kbase_file_create_kctx(struct kbase_file *const kfile,
- debugfs_create_file("force_same_va", 0600, kctx->kctx_dentry,
- kctx, &kbase_force_same_va_fops);
-
-- mutex_init(&kctx->mem_profile_lock);
--
- kbase_context_debugfs_init(kctx);
- }
- #endif /* CONFIG_DEBUG_FS */
-@@ -612,7 +663,6 @@ static int kbase_file_create_kctx(struct kbase_file *const kfile,
-
- return 0;
- }
--
- static int kbase_open(struct inode *inode, struct file *filp)
- {
- struct kbase_device *kbdev = NULL;
-@@ -624,6 +674,13 @@ static int kbase_open(struct inode *inode, struct file *filp)
- if (!kbdev)
- return -ENODEV;
-
-+ /* Device-wide firmware load is moved here from probing to comply with
-+ * Android GKI vendor guideline.
-+ */
-+ ret = kbase_device_firmware_init_once(kbdev);
-+ if (ret)
-+ goto out;
-+
- kfile = kbase_file_new(kbdev, filp);
- if (!kfile) {
- ret = -ENOMEM;
-@@ -635,7 +692,7 @@ static int kbase_open(struct inode *inode, struct file *filp)
-
- return 0;
-
-- out:
-+out:
- kbase_release_device(kbdev);
- return ret;
- }
-@@ -663,11 +720,13 @@ static int kbase_api_set_flags(struct kbase_file *kfile,
- /* For backward compatibility, the context may have been created before
- * the flags were set.
- */
-- if (api_version >= KBASE_API_VERSION(11, 15)) {
-+ if (mali_kbase_supports_system_monitor(api_version)) {
- err = kbase_file_create_kctx(kfile, flags->create_flags);
- } else {
-+#if !MALI_USE_CSF
- struct kbasep_js_kctx_info *js_kctx_info = NULL;
- unsigned long irq_flags = 0;
-+#endif
-
- /* If setup is incomplete (e.g. because the API version
- * wasn't set) then we have to give up.
-@@ -676,6 +735,12 @@ static int kbase_api_set_flags(struct kbase_file *kfile,
- if (unlikely(!kctx))
- return -EPERM;
-
-+#if MALI_USE_CSF
-+ /* On CSF GPUs Job Manager interface isn't used to submit jobs
-+ * (there are no job slots). So the legacy job manager path to
-+ * submit jobs needs to remain disabled for CSF GPUs.
-+ */
-+#else
- js_kctx_info = &kctx->jctx.sched_info;
- mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
- spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, irq_flags);
-@@ -687,11 +752,13 @@ static int kbase_api_set_flags(struct kbase_file *kfile,
-
- spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, irq_flags);
- mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
-+#endif
- }
-
- return err;
- }
-
-+#if !MALI_USE_CSF
- static int kbase_api_job_submit(struct kbase_context *kctx,
- struct kbase_ioctl_job_submit *submit)
- {
-@@ -699,6 +766,7 @@ static int kbase_api_job_submit(struct kbase_context *kctx,
- submit->nr_atoms,
- submit->stride, false);
- }
-+#endif /* !MALI_USE_CSF */
-
- static int kbase_api_get_gpuprops(struct kbase_context *kctx,
- struct kbase_ioctl_get_gpuprops *get_props)
-@@ -724,11 +792,13 @@ static int kbase_api_get_gpuprops(struct kbase_context *kctx,
- return kprops->prop_buffer_size;
- }
-
-+#if !MALI_USE_CSF
- static int kbase_api_post_term(struct kbase_context *kctx)
- {
- kbase_event_close(kctx);
- return 0;
- }
-+#endif /* !MALI_USE_CSF */
-
- static int kbase_api_mem_alloc(struct kbase_context *kctx,
- union kbase_ioctl_mem_alloc *alloc)
-@@ -762,11 +832,23 @@ static int kbase_api_mem_alloc(struct kbase_context *kctx,
- flags |= BASE_MEM_SAME_VA;
- }
-
-+#if MALI_USE_CSF
-+ /* If CSF event memory allocation, need to force certain flags.
-+ * SAME_VA - GPU address needs to be used as a CPU address, explicit
-+ * mmap has to be avoided.
-+ * CACHED_CPU - Frequent access to the event memory by CPU.
-+ * COHERENT_SYSTEM - No explicit cache maintenance around the access
-+ * to event memory so need to leverage the coherency support.
-+ */
-+ if (flags & BASE_MEM_CSF_EVENT) {
-+ flags |= (BASE_MEM_SAME_VA |
-+ BASE_MEM_CACHED_CPU |
-+ BASE_MEM_COHERENT_SYSTEM);
-+ }
-+#endif
-
-- reg = kbase_mem_alloc(kctx, alloc->in.va_pages,
-- alloc->in.commit_pages,
-- alloc->in.extent,
-- &flags, &gpu_va);
-+ reg = kbase_mem_alloc(kctx, alloc->in.va_pages, alloc->in.commit_pages,
-+ alloc->in.extension, &flags, &gpu_va);
-
- if (!reg)
- return -ENOMEM;
-@@ -790,6 +872,14 @@ static int kbase_api_mem_free(struct kbase_context *kctx,
- return kbase_mem_free(kctx, free->gpu_addr);
- }
-
-+#if !MALI_USE_CSF
-+static int kbase_api_kinstr_jm_fd(struct kbase_context *kctx,
-+ union kbase_kinstr_jm_fd *arg)
-+{
-+ return kbase_kinstr_jm_get_fd(kctx->kinstr_jm, arg);
-+}
-+#endif
-+
- static int kbase_api_hwcnt_reader_setup(struct kbase_context *kctx,
- struct kbase_ioctl_hwcnt_reader_setup *setup)
- {
-@@ -883,17 +973,6 @@ static int kbase_api_get_cpu_gpu_timeinfo(struct kbase_context *kctx,
- return 0;
- }
-
--#ifdef CONFIG_MALI_NO_MALI
--static int kbase_api_hwcnt_set(struct kbase_context *kctx,
-- struct kbase_ioctl_hwcnt_values *values)
--{
-- gpu_model_set_dummy_prfcnt_sample(
-- (u32 __user *)(uintptr_t)values->data,
-- values->size);
--
-- return 0;
--}
--#endif
-
- static int kbase_api_disjoint_query(struct kbase_context *kctx,
- struct kbase_ioctl_disjoint_query *query)
-@@ -1058,10 +1137,7 @@ static int kbase_api_mem_alias(struct kbase_context *kctx,
- u64 flags;
- int err;
-
-- if (alias->in.nents == 0 || alias->in.nents > 2048)
-- return -EINVAL;
--
-- if (alias->in.stride > (U64_MAX / 2048))
-+ if (alias->in.nents == 0 || alias->in.nents > BASE_MEM_ALIAS_MAX_ENTS)
- return -EINVAL;
-
- ai = vmalloc(sizeof(*ai) * alias->in.nents);
-@@ -1185,6 +1261,7 @@ static int kbase_api_mem_profile_add(struct kbase_context *kctx,
- return kbasep_mem_profile_debugfs_insert(kctx, buf, data->len);
- }
-
-+#if !MALI_USE_CSF
- static int kbase_api_soft_event_update(struct kbase_context *kctx,
- struct kbase_ioctl_soft_event_update *update)
- {
-@@ -1193,6 +1270,7 @@ static int kbase_api_soft_event_update(struct kbase_context *kctx,
-
- return kbase_soft_event_update(kctx, update->event, update->new_status);
- }
-+#endif /* !MALI_USE_CSF */
-
- static int kbase_api_sticky_resource_map(struct kbase_context *kctx,
- struct kbase_ioctl_sticky_resource_map *map)
-@@ -1263,18 +1341,6 @@ static int kbase_api_sticky_resource_unmap(struct kbase_context *kctx,
- }
-
- #if MALI_UNIT_TEST
--static int kbase_api_tlstream_test(struct kbase_context *kctx,
-- struct kbase_ioctl_tlstream_test *test)
--{
-- kbase_timeline_test(
-- kctx->kbdev,
-- test->tpw_count,
-- test->msg_delay,
-- test->msg_count,
-- test->aux_msg);
--
-- return 0;
--}
-
- static int kbase_api_tlstream_stats(struct kbase_context *kctx,
- struct kbase_ioctl_tlstream_stats *stats)
-@@ -1287,55 +1353,266 @@ static int kbase_api_tlstream_stats(struct kbase_context *kctx,
- }
- #endif /* MALI_UNIT_TEST */
-
-+#if MALI_USE_CSF
-+static int kbasep_cs_event_signal(struct kbase_context *kctx)
-+{
-+ kbase_csf_event_signal_notify_gpu(kctx);
-+ return 0;
-+}
-+
-+static int kbasep_cs_queue_register(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_register *reg)
-+{
-+ kctx->jit_group_id = BASE_MEM_GROUP_DEFAULT;
-+
-+ return kbase_csf_queue_register(kctx, reg);
-+}
-+
-+static int kbasep_cs_queue_register_ex(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_register_ex *reg)
-+{
-+ kctx->jit_group_id = BASE_MEM_GROUP_DEFAULT;
-+
-+ return kbase_csf_queue_register_ex(kctx, reg);
-+}
-+
-+static int kbasep_cs_queue_terminate(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_terminate *term)
-+{
-+ kbase_csf_queue_terminate(kctx, term);
-+
-+ return 0;
-+}
-+
-+static int kbasep_cs_queue_bind(struct kbase_context *kctx,
-+ union kbase_ioctl_cs_queue_bind *bind)
-+{
-+ return kbase_csf_queue_bind(kctx, bind);
-+}
-+
-+static int kbasep_cs_queue_kick(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_kick *kick)
-+{
-+ return kbase_csf_queue_kick(kctx, kick);
-+}
-+
-+static int kbasep_cs_queue_group_create(struct kbase_context *kctx,
-+ union kbase_ioctl_cs_queue_group_create *create)
-+{
-+ return kbase_csf_queue_group_create(kctx, create);
-+}
-+
-+static int kbasep_cs_queue_group_terminate(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_queue_group_term *term)
-+{
-+ kbase_csf_queue_group_terminate(kctx, term->group_handle);
-+
-+ return 0;
-+}
-+
-+static int kbasep_kcpu_queue_new(struct kbase_context *kctx,
-+ struct kbase_ioctl_kcpu_queue_new *new)
-+{
-+ return kbase_csf_kcpu_queue_new(kctx, new);
-+}
-+
-+static int kbasep_kcpu_queue_delete(struct kbase_context *kctx,
-+ struct kbase_ioctl_kcpu_queue_delete *delete)
-+{
-+ return kbase_csf_kcpu_queue_delete(kctx, delete);
-+}
-+
-+static int kbasep_kcpu_queue_enqueue(struct kbase_context *kctx,
-+ struct kbase_ioctl_kcpu_queue_enqueue *enqueue)
-+{
-+ return kbase_csf_kcpu_queue_enqueue(kctx, enqueue);
-+}
-+
-+static int kbasep_cs_tiler_heap_init(struct kbase_context *kctx,
-+ union kbase_ioctl_cs_tiler_heap_init *heap_init)
-+{
-+ kctx->jit_group_id = heap_init->in.group_id;
-+
-+ return kbase_csf_tiler_heap_init(kctx, heap_init->in.chunk_size,
-+ heap_init->in.initial_chunks, heap_init->in.max_chunks,
-+ heap_init->in.target_in_flight,
-+ &heap_init->out.gpu_heap_va, &heap_init->out.first_chunk_va);
-+}
-+
-+static int kbasep_cs_tiler_heap_term(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_tiler_heap_term *heap_term)
-+{
-+ return kbase_csf_tiler_heap_term(kctx, heap_term->gpu_heap_va);
-+}
-+
-+static int kbase_ioctl_cs_get_glb_iface(struct kbase_context *kctx,
-+ union kbase_ioctl_cs_get_glb_iface *param)
-+{
-+ struct basep_cs_stream_control *stream_data = NULL;
-+ struct basep_cs_group_control *group_data = NULL;
-+ void __user *user_groups, *user_streams;
-+ int err = 0;
-+ u32 const max_group_num = param->in.max_group_num;
-+ u32 const max_total_stream_num = param->in.max_total_stream_num;
-+
-+ if (max_group_num > MAX_SUPPORTED_CSGS)
-+ return -EINVAL;
-+
-+ if (max_total_stream_num >
-+ MAX_SUPPORTED_CSGS * MAX_SUPPORTED_STREAMS_PER_GROUP)
-+ return -EINVAL;
-+
-+ user_groups = u64_to_user_ptr(param->in.groups_ptr);
-+ user_streams = u64_to_user_ptr(param->in.streams_ptr);
-+
-+ if (max_group_num > 0) {
-+ if (!user_groups)
-+ err = -EINVAL;
-+ else {
-+ group_data = kcalloc(max_group_num,
-+ sizeof(*group_data), GFP_KERNEL);
-+ if (!group_data)
-+ err = -ENOMEM;
-+ }
-+ }
-+
-+ if (max_total_stream_num > 0) {
-+ if (!user_streams)
-+ err = -EINVAL;
-+ else {
-+ stream_data = kcalloc(max_total_stream_num,
-+ sizeof(*stream_data), GFP_KERNEL);
-+ if (!stream_data)
-+ err = -ENOMEM;
-+ }
-+ }
-+
-+ if (!err) {
-+ param->out.total_stream_num = kbase_csf_firmware_get_glb_iface(
-+ kctx->kbdev, group_data, max_group_num, stream_data,
-+ max_total_stream_num, ¶m->out.glb_version,
-+ ¶m->out.features, ¶m->out.group_num,
-+ ¶m->out.prfcnt_size, ¶m->out.instr_features);
-+
-+ if (copy_to_user(user_groups, group_data,
-+ MIN(max_group_num, param->out.group_num) *
-+ sizeof(*group_data)))
-+ err = -EFAULT;
-+ }
-+
-+ if (!err)
-+ if (copy_to_user(user_streams, stream_data,
-+ MIN(max_total_stream_num, param->out.total_stream_num) *
-+ sizeof(*stream_data)))
-+ err = -EFAULT;
-+
-+ kfree(group_data);
-+ kfree(stream_data);
-+ return err;
-+}
-+
-+static int kbasep_ioctl_cs_cpu_queue_dump(struct kbase_context *kctx,
-+ struct kbase_ioctl_cs_cpu_queue_info *cpu_queue_info)
-+{
-+ return kbase_csf_cpu_queue_dump(kctx, cpu_queue_info->buffer,
-+ cpu_queue_info->size);
-+}
-+
-+#endif /* MALI_USE_CSF */
-+
-+static int kbasep_ioctl_context_priority_check(struct kbase_context *kctx,
-+ struct kbase_ioctl_context_priority_check *priority_check)
-+{
-+#if MALI_USE_CSF
-+ priority_check->priority = kbase_csf_priority_check(kctx->kbdev, priority_check->priority);
-+#else
-+ base_jd_prio req_priority = (base_jd_prio)priority_check->priority;
-+
-+ priority_check->priority = (u8)kbase_js_priority_check(kctx->kbdev, req_priority);
-+#endif
-+ return 0;
-+}
-
--#define KBASE_HANDLE_IOCTL(cmd, function, arg) \
-- do { \
-- BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_NONE); \
-- return function(arg); \
-+#define KBASE_HANDLE_IOCTL(cmd, function, arg) \
-+ do { \
-+ int ret; \
-+ BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_NONE); \
-+ dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
-+ ret = function(arg); \
-+ dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, \
-+ #function); \
-+ return ret; \
- } while (0)
-
--#define KBASE_HANDLE_IOCTL_IN(cmd, function, type, arg) \
-- do { \
-- type param; \
-- int err; \
-- BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_WRITE); \
-- BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
-- err = copy_from_user(¶m, uarg, sizeof(param)); \
-- if (err) \
-- return -EFAULT; \
-- return function(arg, ¶m); \
-+#define KBASE_HANDLE_IOCTL_IN(cmd, function, type, arg) \
-+ do { \
-+ type param; \
-+ int ret, err; \
-+ dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
-+ BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_WRITE); \
-+ BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
-+ err = copy_from_user(¶m, uarg, sizeof(param)); \
-+ if (err) \
-+ return -EFAULT; \
-+ ret = function(arg, ¶m); \
-+ dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, \
-+ #function); \
-+ return ret; \
- } while (0)
-
--#define KBASE_HANDLE_IOCTL_OUT(cmd, function, type, arg) \
-- do { \
-- type param; \
-- int ret, err; \
-- BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_READ); \
-- BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
-- memset(¶m, 0, sizeof(param)); \
-- ret = function(arg, ¶m); \
-- err = copy_to_user(uarg, ¶m, sizeof(param)); \
-- if (err) \
-- return -EFAULT; \
-- return ret; \
-+#define KBASE_HANDLE_IOCTL_OUT(cmd, function, type, arg) \
-+ do { \
-+ type param; \
-+ int ret, err; \
-+ dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
-+ BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_READ); \
-+ BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
-+ memset(¶m, 0, sizeof(param)); \
-+ ret = function(arg, ¶m); \
-+ err = copy_to_user(uarg, ¶m, sizeof(param)); \
-+ if (err) \
-+ return -EFAULT; \
-+ dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, \
-+ #function); \
-+ return ret; \
- } while (0)
-
--#define KBASE_HANDLE_IOCTL_INOUT(cmd, function, type, arg) \
-- do { \
-- type param; \
-- int ret, err; \
-- BUILD_BUG_ON(_IOC_DIR(cmd) != (_IOC_WRITE|_IOC_READ)); \
-- BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
-- err = copy_from_user(¶m, uarg, sizeof(param)); \
-- if (err) \
-- return -EFAULT; \
-- ret = function(arg, ¶m); \
-- err = copy_to_user(uarg, ¶m, sizeof(param)); \
-- if (err) \
-- return -EFAULT; \
-- return ret; \
-+#define KBASE_HANDLE_IOCTL_INOUT(cmd, function, type, arg) \
-+ do { \
-+ type param; \
-+ int ret, err; \
-+ dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
-+ BUILD_BUG_ON(_IOC_DIR(cmd) != (_IOC_WRITE | _IOC_READ)); \
-+ BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
-+ err = copy_from_user(¶m, uarg, sizeof(param)); \
-+ if (err) \
-+ return -EFAULT; \
-+ ret = function(arg, ¶m); \
-+ err = copy_to_user(uarg, ¶m, sizeof(param)); \
-+ if (err) \
-+ return -EFAULT; \
-+ dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, \
-+ #function); \
-+ return ret; \
- } while (0)
-
-+static int kbasep_ioctl_set_limited_core_count(struct kbase_context *kctx,
-+ struct kbase_ioctl_set_limited_core_count *set_limited_core_count)
-+{
-+ const u64 shader_core_mask =
-+ kbase_pm_get_present_cores(kctx->kbdev, KBASE_PM_CORE_SHADER);
-+ const u64 limited_core_mask =
-+ ((u64)1 << (set_limited_core_count->max_core_count)) - 1;
-+
-+ if ((shader_core_mask & limited_core_mask) == 0) {
-+ /* At least one shader core must be available after applying the mask */
-+ return -EINVAL;
-+ }
-+
-+ kctx->limited_core_mask = limited_core_mask;
-+ return 0;
-+}
-+
- static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- {
- struct kbase_file *const kfile = filp->private_data;
-@@ -1352,6 +1629,13 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- kfile);
- break;
-
-+ case KBASE_IOCTL_VERSION_CHECK_RESERVED:
-+ KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_VERSION_CHECK_RESERVED,
-+ kbase_api_handshake_dummy,
-+ struct kbase_ioctl_version_check,
-+ kfile);
-+ break;
-+
- case KBASE_IOCTL_SET_FLAGS:
- KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_SET_FLAGS,
- kbase_api_set_flags,
-@@ -1366,23 +1650,27 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-
- /* Normal ioctls */
- switch (cmd) {
-+#if !MALI_USE_CSF
- case KBASE_IOCTL_JOB_SUBMIT:
- KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_JOB_SUBMIT,
- kbase_api_job_submit,
- struct kbase_ioctl_job_submit,
- kctx);
- break;
-+#endif /* !MALI_USE_CSF */
- case KBASE_IOCTL_GET_GPUPROPS:
- KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_GET_GPUPROPS,
- kbase_api_get_gpuprops,
- struct kbase_ioctl_get_gpuprops,
- kctx);
- break;
-+#if !MALI_USE_CSF
- case KBASE_IOCTL_POST_TERM:
- KBASE_HANDLE_IOCTL(KBASE_IOCTL_POST_TERM,
- kbase_api_post_term,
- kctx);
- break;
-+#endif /* !MALI_USE_CSF */
- case KBASE_IOCTL_MEM_ALLOC:
- KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_MEM_ALLOC,
- kbase_api_mem_alloc,
-@@ -1515,12 +1803,14 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- kctx);
- break;
-
-+#if !MALI_USE_CSF
- case KBASE_IOCTL_SOFT_EVENT_UPDATE:
- KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_SOFT_EVENT_UPDATE,
- kbase_api_soft_event_update,
- struct kbase_ioctl_soft_event_update,
- kctx);
- break;
-+#endif /* !MALI_USE_CSF */
-
- case KBASE_IOCTL_STICKY_RESOURCE_MAP:
- KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_STICKY_RESOURCE_MAP,
-@@ -1536,6 +1826,14 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- break;
-
- /* Instrumentation. */
-+#if !MALI_USE_CSF
-+ case KBASE_IOCTL_KINSTR_JM_FD:
-+ KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_KINSTR_JM_FD,
-+ kbase_api_kinstr_jm_fd,
-+ union kbase_kinstr_jm_fd,
-+ kctx);
-+ break;
-+#endif
- case KBASE_IOCTL_HWCNT_READER_SETUP:
- KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_HWCNT_READER_SETUP,
- kbase_api_hwcnt_reader_setup,
-@@ -1564,14 +1862,6 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- union kbase_ioctl_get_cpu_gpu_timeinfo,
- kctx);
- break;
--#ifdef CONFIG_MALI_NO_MALI
-- case KBASE_IOCTL_HWCNT_SET:
-- KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_HWCNT_SET,
-- kbase_api_hwcnt_set,
-- struct kbase_ioctl_hwcnt_values,
-- kctx);
-- break;
--#endif
- #ifdef CONFIG_MALI_CINSTR_GWT
- case KBASE_IOCTL_CINSTR_GWT_START:
- KBASE_HANDLE_IOCTL(KBASE_IOCTL_CINSTR_GWT_START,
-@@ -1590,13 +1880,98 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- kctx);
- break;
- #endif
--#if MALI_UNIT_TEST
-- case KBASE_IOCTL_TLSTREAM_TEST:
-- KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_TLSTREAM_TEST,
-- kbase_api_tlstream_test,
-- struct kbase_ioctl_tlstream_test,
-+#if MALI_USE_CSF
-+ case KBASE_IOCTL_CS_EVENT_SIGNAL:
-+ KBASE_HANDLE_IOCTL(KBASE_IOCTL_CS_EVENT_SIGNAL,
-+ kbasep_cs_event_signal,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_QUEUE_REGISTER:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_CS_QUEUE_REGISTER,
-+ kbasep_cs_queue_register,
-+ struct kbase_ioctl_cs_queue_register,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_QUEUE_REGISTER_EX:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_CS_QUEUE_REGISTER_EX,
-+ kbasep_cs_queue_register_ex,
-+ struct kbase_ioctl_cs_queue_register_ex,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_QUEUE_TERMINATE:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_CS_QUEUE_TERMINATE,
-+ kbasep_cs_queue_terminate,
-+ struct kbase_ioctl_cs_queue_terminate,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_QUEUE_BIND:
-+ KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_CS_QUEUE_BIND,
-+ kbasep_cs_queue_bind,
-+ union kbase_ioctl_cs_queue_bind,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_QUEUE_KICK:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_CS_QUEUE_KICK,
-+ kbasep_cs_queue_kick,
-+ struct kbase_ioctl_cs_queue_kick,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_QUEUE_GROUP_CREATE:
-+ KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_CS_QUEUE_GROUP_CREATE,
-+ kbasep_cs_queue_group_create,
-+ union kbase_ioctl_cs_queue_group_create,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_QUEUE_GROUP_TERMINATE:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_CS_QUEUE_GROUP_TERMINATE,
-+ kbasep_cs_queue_group_terminate,
-+ struct kbase_ioctl_cs_queue_group_term,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_KCPU_QUEUE_CREATE:
-+ KBASE_HANDLE_IOCTL_OUT(KBASE_IOCTL_KCPU_QUEUE_CREATE,
-+ kbasep_kcpu_queue_new,
-+ struct kbase_ioctl_kcpu_queue_new,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_KCPU_QUEUE_DELETE:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_KCPU_QUEUE_DELETE,
-+ kbasep_kcpu_queue_delete,
-+ struct kbase_ioctl_kcpu_queue_delete,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_KCPU_QUEUE_ENQUEUE:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_KCPU_QUEUE_ENQUEUE,
-+ kbasep_kcpu_queue_enqueue,
-+ struct kbase_ioctl_kcpu_queue_enqueue,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_TILER_HEAP_INIT:
-+ KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_CS_TILER_HEAP_INIT,
-+ kbasep_cs_tiler_heap_init,
-+ union kbase_ioctl_cs_tiler_heap_init,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_TILER_HEAP_TERM:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_CS_TILER_HEAP_TERM,
-+ kbasep_cs_tiler_heap_term,
-+ struct kbase_ioctl_cs_tiler_heap_term,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_GET_GLB_IFACE:
-+ KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_CS_GET_GLB_IFACE,
-+ kbase_ioctl_cs_get_glb_iface,
-+ union kbase_ioctl_cs_get_glb_iface,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_CS_CPU_QUEUE_DUMP:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_CS_CPU_QUEUE_DUMP,
-+ kbasep_ioctl_cs_cpu_queue_dump,
-+ struct kbase_ioctl_cs_cpu_queue_info,
- kctx);
- break;
-+#endif /* MALI_USE_CSF */
-+#if MALI_UNIT_TEST
- case KBASE_IOCTL_TLSTREAM_STATS:
- KBASE_HANDLE_IOCTL_OUT(KBASE_IOCTL_TLSTREAM_STATS,
- kbase_api_tlstream_stats,
-@@ -1604,6 +1979,18 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- kctx);
- break;
- #endif /* MALI_UNIT_TEST */
-+ case KBASE_IOCTL_CONTEXT_PRIORITY_CHECK:
-+ KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_CONTEXT_PRIORITY_CHECK,
-+ kbasep_ioctl_context_priority_check,
-+ struct kbase_ioctl_context_priority_check,
-+ kctx);
-+ break;
-+ case KBASE_IOCTL_SET_LIMITED_CORE_COUNT:
-+ KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_SET_LIMITED_CORE_COUNT,
-+ kbasep_ioctl_set_limited_core_count,
-+ struct kbase_ioctl_set_limited_core_count,
-+ kctx);
-+ break;
- }
-
- dev_warn(kbdev->dev, "Unknown ioctl 0x%x nr:%d", cmd, _IOC_NR(cmd));
-@@ -1611,6 +1998,51 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- return -ENOIOCTLCMD;
- }
-
-+#if MALI_USE_CSF
-+static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
-+{
-+ struct kbase_file *const kfile = filp->private_data;
-+ struct kbase_context *const kctx =
-+ kbase_file_get_kctx_if_setup_complete(kfile);
-+ struct base_csf_notification event_data = {
-+ .type = BASE_CSF_NOTIFICATION_EVENT };
-+ const size_t data_size = sizeof(event_data);
-+ bool read_event = false, read_error = false;
-+
-+ if (unlikely(!kctx))
-+ return -EPERM;
-+
-+ if (atomic_read(&kctx->event_count))
-+ read_event = true;
-+ else
-+ read_error = kbase_csf_read_error(kctx, &event_data);
-+
-+ if (!read_event && !read_error) {
-+ bool dump = kbase_csf_cpu_queue_read_dump_req(kctx,
-+ &event_data);
-+ /* This condition is not treated as an error.
-+ * It is possible that event handling thread was woken up due
-+ * to a fault/error that occurred for a queue group, but before
-+ * the corresponding fault data was read by the thread the
-+ * queue group was already terminated by the userspace.
-+ */
-+ if (!dump)
-+ dev_dbg(kctx->kbdev->dev,
-+ "Neither event nor error signaled");
-+ }
-+
-+ if (copy_to_user(buf, &event_data, data_size) != 0) {
-+ dev_warn(kctx->kbdev->dev,
-+ "Failed to copy data\n");
-+ return -EFAULT;
-+ }
-+
-+ if (read_event)
-+ atomic_set(&kctx->event_count, 0);
-+
-+ return data_size;
-+}
-+#else /* MALI_USE_CSF */
- static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
- {
- struct kbase_file *const kfile = filp->private_data;
-@@ -1654,6 +2086,7 @@ static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, lof
- out:
- return out_count * sizeof(uevent);
- }
-+#endif /* MALI_USE_CSF */
-
- static unsigned int kbase_poll(struct file *filp, poll_table *wait)
- {
-@@ -1674,19 +2107,31 @@ static unsigned int kbase_poll(struct file *filp, poll_table *wait)
- void kbase_event_wakeup(struct kbase_context *kctx)
- {
- KBASE_DEBUG_ASSERT(kctx);
--
-+ dev_dbg(kctx->kbdev->dev, "Waking event queue for context %pK\n",
-+ (void *)kctx);
- wake_up_interruptible(&kctx->event_queue);
- }
-
- KBASE_EXPORT_TEST_API(kbase_event_wakeup);
-
-+#if MALI_USE_CSF
-+int kbase_event_pending(struct kbase_context *ctx)
-+{
-+ WARN_ON_ONCE(!ctx);
-+
-+ return (atomic_read(&ctx->event_count) != 0) ||
-+ kbase_csf_error_pending(ctx) ||
-+ kbase_csf_cpu_queue_dump_needed(ctx);
-+}
-+#else
- int kbase_event_pending(struct kbase_context *ctx)
- {
- KBASE_DEBUG_ASSERT(ctx);
-
- return (atomic_read(&ctx->event_count) != 0) ||
-- (atomic_read(&ctx->event_closed) != 0);
-+ (atomic_read(&ctx->event_closed) != 0);
- }
-+#endif
-
- KBASE_EXPORT_TEST_API(kbase_event_pending);
-
-@@ -1740,42 +2185,166 @@ static const struct file_operations kbase_fops = {
- .get_unmapped_area = kbase_get_unmapped_area,
- };
-
--/**
-- * show_policy - Show callback for the power_policy sysfs file.
-- *
-- * This function is called to get the contents of the power_policy sysfs
-- * file. This is a list of the available policies with the currently active one
-- * surrounded by square brackets.
-- *
-- * @dev: The device this sysfs file is for
-- * @attr: The attributes of the sysfs file
-- * @buf: The output buffer for the sysfs file contents
-- *
-- * Return: The number of bytes output to @buf.
-- */
--static ssize_t show_policy(struct device *dev, struct device_attribute *attr, char *const buf)
-+static ssize_t show_gpu_memory(struct device *dev, struct device_attribute *attr, char * const buf)
- {
- struct kbase_device *kbdev;
-- const struct kbase_pm_policy *current_policy;
-- const struct kbase_pm_policy *const *policy_list;
-- int policy_count;
-- int i;
- ssize_t ret = 0;
-+ struct list_head *entry;
-+ const struct list_head *kbdev_list;
-
- kbdev = to_kbase_device(dev);
-
- if (!kbdev)
- return -ENODEV;
-
-- current_policy = kbase_pm_get_policy(kbdev);
-+ kbdev_list = kbase_device_get_list();
-+ list_for_each(entry, kbdev_list) {
-+ struct kbase_device *kbdev = NULL;
-+ struct kbase_context *kctx;
-+
-+ kbdev = list_entry(entry, struct kbase_device, entry);
-+ /* output the total memory usage and cap for this device */
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "%-16s %-16s %10u\n",
-+ kbdev->devname,
-+ "total used_pages",
-+ atomic_read(&(kbdev->memdev.used_pages)));
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "----------------------------------------------------\n");
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "%-16s %-16s %-16s\n",
-+ "kctx", "pid", "used_pages");
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "----------------------------------------------------\n");
-+ mutex_lock(&kbdev->kctx_list_lock);
-+ list_for_each_entry(kctx, &kbdev->kctx_list, kctx_list_link) {
-+ /* output the memory usage and cap for each kctx
-+ * opened on this device */
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "%p %10u %10u\n",
-+ kctx,
-+ kctx->tgid,
-+ atomic_read(&(kctx->used_pages)));
-+ }
-+ mutex_unlock(&kbdev->kctx_list_lock);
-+ }
-
-- policy_count = kbase_pm_list_policies(kbdev, &policy_list);
-+ kbase_device_put_list(kbdev_list);
-
-- for (i = 0; i < policy_count && ret < PAGE_SIZE; i++) {
-- if (policy_list[i] == current_policy)
-- ret += scnprintf(buf + ret, PAGE_SIZE - ret, "[%s] ", policy_list[i]->name);
-- else
-- ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s ", policy_list[i]->name);
-+
-+ return ret;
-+}
-+
-+static ssize_t set_gpu_memory(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-+{
-+ struct kbase_device *kbdev;
-+ ssize_t err = count;
-+
-+ kbdev = to_kbase_device(dev);
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ return err;
-+}
-+
-+static DEVICE_ATTR(gpu_memory, S_IRUGO | S_IWUSR, show_gpu_memory, set_gpu_memory);
-+
-+static ssize_t show_ctx_mem_pool_size(struct device *dev, struct device_attribute *attr, char * const buf)
-+{
-+ struct list_head *entry;
-+ const struct list_head *kbdev_list;
-+ ssize_t ret = 0;
-+ int i = 0;
-+ struct kbase_device *const kbdev = to_kbase_device(dev);
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ kbdev_list = kbase_device_get_list();
-+ list_for_each(entry, kbdev_list) {
-+ struct kbase_device *kbdev = NULL;
-+ struct kbase_context *kctx;
-+
-+ kbdev = list_entry(entry, struct kbase_device, entry);
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "%-16s %-16s %-16s\n",
-+ "kctx", "pid", "cached_pages");
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "----------------------------------------------------\n");
-+ mutex_lock(&kbdev->kctx_list_lock);
-+ list_for_each_entry(kctx, &kbdev->kctx_list, kctx_list_link) {
-+ /* output the memory cached and cap for each kctx
-+ * opened on this device */
-+ unsigned long cached_mem = 0;
-+ for (i = 0; i < MEMORY_GROUP_MANAGER_NR_GROUPS; i++)
-+ //pr_info("[%d]:kctx->mem_pools.small[%d] = %d", kctx->tgid, i, kctx->mem_pools.small[i].cur_size);
-+ cached_mem += kctx->mem_pools.small[i].cur_size;
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "%p %10u %10lu\n",
-+ kctx,
-+ kctx->tgid,
-+ cached_mem);
-+ }
-+ mutex_unlock(&kbdev->kctx_list_lock);
-+ }
-+
-+ kbase_device_put_list(kbdev_list);
-+
-+ return ret;
-+}
-+
-+static ssize_t set_ctx_mem_pool_size(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-+{
-+ struct kbase_device *kbdev;
-+ ssize_t err = count;
-+
-+ kbdev = to_kbase_device(dev);
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ return err;
-+}
-+
-+static DEVICE_ATTR(ctx_mem_pool_size, S_IRUGO | S_IWUSR, show_ctx_mem_pool_size, set_ctx_mem_pool_size);
-+
-+/**
-+ * show_policy - Show callback for the power_policy sysfs file.
-+ *
-+ * This function is called to get the contents of the power_policy sysfs
-+ * file. This is a list of the available policies with the currently active one
-+ * surrounded by square brackets.
-+ *
-+ * @dev: The device this sysfs file is for
-+ * @attr: The attributes of the sysfs file
-+ * @buf: The output buffer for the sysfs file contents
-+ *
-+ * Return: The number of bytes output to @buf.
-+ */
-+static ssize_t show_policy(struct device *dev, struct device_attribute *attr, char *const buf)
-+{
-+ struct kbase_device *kbdev;
-+ const struct kbase_pm_policy *current_policy;
-+ const struct kbase_pm_policy *const *policy_list;
-+ int policy_count;
-+ int i;
-+ ssize_t ret = 0;
-+
-+ kbdev = to_kbase_device(dev);
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ current_policy = kbase_pm_get_policy(kbdev);
-+
-+ policy_count = kbase_pm_list_policies(kbdev, &policy_list);
-+
-+ for (i = 0; i < policy_count && ret < PAGE_SIZE; i++) {
-+ if (policy_list[i] == current_policy)
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "[%s] ", policy_list[i]->name);
-+ else
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s ", policy_list[i]->name);
- }
-
- if (ret < PAGE_SIZE - 1) {
-@@ -1800,7 +2369,7 @@ static ssize_t show_policy(struct device *dev, struct device_attribute *attr, ch
- * @dev: The device with sysfs file is for
- * @attr: The attributes of the sysfs file
- * @buf: The value written to the sysfs file
-- * @count: The number of bytes written to the sysfs file
-+ * @count: The number of bytes to write to the sysfs file
- *
- * Return: @count if the function succeeded. An error code on failure.
- */
-@@ -1859,6 +2428,7 @@ static DEVICE_ATTR(power_policy, S_IRUGO | S_IWUSR, show_policy, set_policy);
- static ssize_t show_core_mask(struct device *dev, struct device_attribute *attr, char * const buf)
- {
- struct kbase_device *kbdev;
-+ unsigned long flags;
- ssize_t ret = 0;
-
- kbdev = to_kbase_device(dev);
-@@ -1866,6 +2436,19 @@ static ssize_t show_core_mask(struct device *dev, struct device_attribute *attr,
- if (!kbdev)
- return -ENODEV;
-
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+
-+#if MALI_USE_CSF
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "Current debug core mask : 0x%llX\n",
-+ kbdev->pm.debug_core_mask);
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "Current desired core mask : 0x%llX\n",
-+ kbase_pm_ca_get_core_mask(kbdev));
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
-+ "Current in use core mask : 0x%llX\n",
-+ kbdev->pm.backend.shaders_avail);
-+#else
- ret += scnprintf(buf + ret, PAGE_SIZE - ret,
- "Current core mask (JS0) : 0x%llX\n",
- kbdev->pm.debug_core_mask[0]);
-@@ -1875,10 +2458,14 @@ static ssize_t show_core_mask(struct device *dev, struct device_attribute *attr,
- ret += scnprintf(buf + ret, PAGE_SIZE - ret,
- "Current core mask (JS2) : 0x%llX\n",
- kbdev->pm.debug_core_mask[2]);
-+#endif /* MALI_USE_CSF */
-+
- ret += scnprintf(buf + ret, PAGE_SIZE - ret,
- "Available core mask : 0x%llX\n",
- kbdev->gpu_props.props.raw_props.shader_present);
-
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
- return ret;
- }
-
-@@ -1890,24 +2477,42 @@ static ssize_t show_core_mask(struct device *dev, struct device_attribute *attr,
- * @dev: The device with sysfs file is for
- * @attr: The attributes of the sysfs file
- * @buf: The value written to the sysfs file
-- * @count: The number of bytes written to the sysfs file
-+ * @count: The number of bytes to write to the sysfs file
- *
- * Return: @count if the function succeeded. An error code on failure.
- */
- static ssize_t set_core_mask(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
- {
- struct kbase_device *kbdev;
-+#if MALI_USE_CSF
-+ u64 new_core_mask;
-+#else
- u64 new_core_mask[3];
-- int items, i;
-+ u64 group0_core_mask;
-+ int i;
-+#endif /* MALI_USE_CSF */
-+
-+ int items;
- ssize_t err = count;
- unsigned long flags;
-- u64 shader_present, group0_core_mask;
-+ u64 shader_present;
-
- kbdev = to_kbase_device(dev);
-
- if (!kbdev)
- return -ENODEV;
-
-+#if MALI_USE_CSF
-+ items = sscanf(buf, "%llx", &new_core_mask);
-+
-+ if (items != 1) {
-+ dev_err(kbdev->dev,
-+ "Couldn't process core mask write operation.\n"
-+ "Use format <core_mask>\n");
-+ err = -EINVAL;
-+ goto end;
-+ }
-+#else
- items = sscanf(buf, "%llx %llx %llx",
- &new_core_mask[0], &new_core_mask[1],
- &new_core_mask[2]);
-@@ -1922,11 +2527,35 @@ static ssize_t set_core_mask(struct device *dev, struct device_attribute *attr,
-
- if (items == 1)
- new_core_mask[1] = new_core_mask[2] = new_core_mask[0];
-+#endif
-
- mutex_lock(&kbdev->pm.lock);
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-
- shader_present = kbdev->gpu_props.props.raw_props.shader_present;
-+
-+#if MALI_USE_CSF
-+ if ((new_core_mask & shader_present) != new_core_mask) {
-+ dev_err(dev,
-+ "Invalid core mask 0x%llX: Includes non-existent cores (present = 0x%llX)",
-+ new_core_mask, shader_present);
-+ err = -EINVAL;
-+ goto unlock;
-+
-+ } else if (!(new_core_mask & shader_present &
-+ kbdev->pm.backend.ca_cores_enabled)) {
-+ dev_err(dev,
-+ "Invalid core mask 0x%llX: No intersection with currently available cores (present = 0x%llX, CA enabled = 0x%llX\n",
-+ new_core_mask,
-+ kbdev->gpu_props.props.raw_props.shader_present,
-+ kbdev->pm.backend.ca_cores_enabled);
-+ err = -EINVAL;
-+ goto unlock;
-+ }
-+
-+ if (kbdev->pm.debug_core_mask != new_core_mask)
-+ kbase_pm_set_debug_core_mask(kbdev, new_core_mask);
-+#else
- group0_core_mask = kbdev->gpu_props.props.coherency_info.group[0].core_mask;
-
- for (i = 0; i < 3; ++i) {
-@@ -1949,6 +2578,11 @@ static ssize_t set_core_mask(struct device *dev, struct device_attribute *attr,
- new_core_mask[i], i, group0_core_mask);
- err = -EINVAL;
- goto unlock;
-+ } else if (!(new_core_mask[i] & kbdev->gpu_props.curr_config.shader_present)) {
-+ dev_err(dev, "Invalid core mask 0x%llX for JS %d: No intersection with current core mask 0x%llX\n",
-+ new_core_mask[i], i, kbdev->gpu_props.curr_config.shader_present);
-+ err = -EINVAL;
-+ goto unlock;
- }
- }
-
-@@ -1961,6 +2595,7 @@ static ssize_t set_core_mask(struct device *dev, struct device_attribute *attr,
- kbase_pm_set_debug_core_mask(kbdev, new_core_mask[0],
- new_core_mask[1], new_core_mask[2]);
- }
-+#endif /* MALI_USE_CSF */
-
- unlock:
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-@@ -1978,6 +2613,7 @@ end:
- */
- static DEVICE_ATTR(core_mask, S_IRUGO | S_IWUSR, show_core_mask, set_core_mask);
-
-+#if !MALI_USE_CSF
- /**
- * set_soft_job_timeout - Store callback for the soft_job_timeout sysfs
- * file.
-@@ -1985,7 +2621,7 @@ static DEVICE_ATTR(core_mask, S_IRUGO | S_IWUSR, show_core_mask, set_core_mask);
- * @dev: The device this sysfs file is for.
- * @attr: The attributes of the sysfs file.
- * @buf: The value written to the sysfs file.
-- * @count: The number of bytes written to the sysfs file.
-+ * @count: The number of bytes to write to the sysfs file.
- *
- * This allows setting the timeout for software jobs. Waiting soft event wait
- * jobs will be cancelled after this period expires, while soft fence wait jobs
-@@ -2078,7 +2714,7 @@ static u32 timeout_ms_to_ticks(struct kbase_device *kbdev, long timeout_ms,
- * @dev: The device with sysfs file is for
- * @attr: The attributes of the sysfs file
- * @buf: The value written to the sysfs file
-- * @count: The number of bytes written to the sysfs file
-+ * @count: The number of bytes to write to the sysfs file
- *
- * Return: @count if the function succeeded. An error code on failure.
- */
-@@ -2255,7 +2891,7 @@ static u32 get_new_js_timeout(
- * @dev: The device the sysfs file is for
- * @attr: The attributes of the sysfs file
- * @buf: The value written to the sysfs file
-- * @count: The number of bytes written to the sysfs file
-+ * @count: The number of bytes to write to the sysfs file
- *
- * This function is called when the js_scheduling_period sysfs file is written
- * to. It checks the data written, and if valid updates the js_scheduling_period
-@@ -2295,7 +2931,8 @@ static ssize_t set_js_scheduling_period(struct device *dev,
-
- /* If no contexts have been scheduled since js_timeouts was last written
- * to, the new timeouts might not have been latched yet. So check if an
-- * update is pending and use the new values if necessary. */
-+ * update is pending and use the new values if necessary.
-+ */
-
- /* Use previous 'new' scheduling period as a base if present. */
- old_period = js_data->scheduling_period_ns;
-@@ -2420,9 +3057,10 @@ static ssize_t show_js_softstop_always(struct device *dev,
- */
- static DEVICE_ATTR(js_softstop_always, S_IRUGO | S_IWUSR, show_js_softstop_always, set_js_softstop_always);
- #endif /* CONFIG_MALI_DEBUG */
-+#endif /* !MALI_USE_CSF */
-
- #ifdef CONFIG_MALI_DEBUG
--typedef void (kbasep_debug_command_func) (struct kbase_device *);
-+typedef void kbasep_debug_command_func(struct kbase_device *);
-
- enum kbasep_debug_command_code {
- KBASEP_DEBUG_COMMAND_DUMPTRACE,
-@@ -2568,24 +3206,20 @@ static ssize_t kbase_show_gpuinfo(struct device *dev,
- .name = "Mali-G77" },
- { .id = GPU_ID2_PRODUCT_TBEX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
- .name = "Mali-G78" },
-+ { .id = GPU_ID2_PRODUCT_TBAX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
-+ .name = "Mali-G78AE" },
- { .id = GPU_ID2_PRODUCT_LBEX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
- .name = "Mali-G68" },
- { .id = GPU_ID2_PRODUCT_TNAX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
- .name = "Mali-G57" },
- { .id = GPU_ID2_PRODUCT_TODX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
-- .name = "Mali-TODX" },
-+ .name = "Mali-G710" },
-+ { .id = GPU_ID2_PRODUCT_LODX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
-+ .name = "Mali-G610" },
- { .id = GPU_ID2_PRODUCT_TGRX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
-- .name = "Mali-TGRX" },
-+ .name = "Mali-G510" },
- { .id = GPU_ID2_PRODUCT_TVAX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
-- .name = "Mali-TVAX" },
-- { .id = GPU_ID2_PRODUCT_LODX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
-- .name = "Mali-LODX" },
-- { .id = GPU_ID2_PRODUCT_TTUX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
-- .name = "Mali-TTUX" },
-- { .id = GPU_ID2_PRODUCT_LTUX >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
-- .name = "Mali-LTUX" },
-- { .id = GPU_ID2_PRODUCT_TE2X >> GPU_ID_VERSION_PRODUCT_ID_SHIFT,
-- .name = "Mali-TE2X" },
-+ .name = "Mali-G310" },
- };
- const char *product_name = "(Unknown Mali GPU)";
- struct kbase_device *kbdev;
-@@ -2728,7 +3362,8 @@ static ssize_t set_pm_poweroff(struct device *dev,
-
- stt = &kbdev->pm.backend.shader_tick_timer;
- stt->configured_interval = HR_TIMER_DELAY_NSEC(gpu_poweroff_time);
-- stt->configured_ticks = poweroff_shader_ticks;
-+ stt->default_ticks = poweroff_shader_ticks;
-+ stt->configured_ticks = stt->default_ticks;
-
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
-@@ -2766,7 +3401,7 @@ static ssize_t show_pm_poweroff(struct device *dev,
- stt = &kbdev->pm.backend.shader_tick_timer;
- ret = scnprintf(buf, PAGE_SIZE, "%llu %u 0\n",
- ktime_to_ns(stt->configured_interval),
-- stt->configured_ticks);
-+ stt->default_ticks);
-
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
-@@ -2776,6 +3411,75 @@ static ssize_t show_pm_poweroff(struct device *dev,
- static DEVICE_ATTR(pm_poweroff, S_IRUGO | S_IWUSR, show_pm_poweroff,
- set_pm_poweroff);
-
-+#if MALI_USE_CSF
-+/**
-+ * set_idle_hysteresis_time - Store callback for CSF idle_hysteresis_time
-+ * sysfs file.
-+ * @dev: The device with sysfs file is for
-+ * @attr: The attributes of the sysfs file
-+ * @buf: The value written to the sysfs file
-+ * @count: The number of bytes written to the sysfs file
-+ *
-+ * This function is called when the idle_hysteresis_time sysfs file is
-+ * written to.
-+ *
-+ * This file contains values of the idle idle hysteresis duration.
-+ *
-+ * Return: @count if the function succeeded. An error code on failure.
-+ */
-+static ssize_t set_idle_hysteresis_time(struct device *dev,
-+ struct device_attribute *attr, const char *buf, size_t count)
-+{
-+ struct kbase_device *kbdev;
-+ u32 dur;
-+
-+ kbdev = to_kbase_device(dev);
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ if (kstrtou32(buf, 0, &dur)) {
-+ dev_err(kbdev->dev, "Couldn't process idle_hysteresis_time write operation.\n"
-+ "Use format <idle_hysteresis_time>\n");
-+ return -EINVAL;
-+ }
-+
-+ kbase_csf_firmware_set_gpu_idle_hysteresis_time(kbdev, dur);
-+
-+ return count;
-+}
-+
-+/**
-+ * show_idle_hysteresis_time - Show callback for CSF idle_hysteresis_time
-+ * sysfs entry.
-+ * @dev: The device this sysfs file is for.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The output buffer to receive the GPU information.
-+ *
-+ * This function is called to get the current idle hysteresis duration in ms.
-+ *
-+ * Return: The number of bytes output to @buf.
-+ */
-+static ssize_t show_idle_hysteresis_time(struct device *dev,
-+ struct device_attribute *attr, char * const buf)
-+{
-+ struct kbase_device *kbdev;
-+ ssize_t ret;
-+ u32 dur;
-+
-+ kbdev = to_kbase_device(dev);
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ dur = kbase_csf_firmware_get_gpu_idle_hysteresis_time(kbdev);
-+ ret = scnprintf(buf, PAGE_SIZE, "%u\n", dur);
-+
-+ return ret;
-+}
-+
-+static DEVICE_ATTR(idle_hysteresis_time, S_IRUGO | S_IWUSR,
-+ show_idle_hysteresis_time, set_idle_hysteresis_time);
-+#endif
-+
- /**
- * set_reset_timeout - Store callback for the reset_timeout sysfs file.
- * @dev: The device with sysfs file is for
-@@ -3013,122 +3717,359 @@ static DEVICE_ATTR(lp_mem_pool_max_size, S_IRUGO | S_IWUSR, show_lp_mem_pool_max
- set_lp_mem_pool_max_size);
-
- /**
-- * show_js_ctx_scheduling_mode - Show callback for js_ctx_scheduling_mode sysfs
-- * entry.
-+ * show_simplified_mem_pool_max_size - Show the maximum size for the memory
-+ * pool 0 of small (4KiB) pages.
- * @dev: The device this sysfs file is for.
- * @attr: The attributes of the sysfs file.
-- * @buf: The output buffer to receive the context scheduling mode information.
-+ * @buf: The output buffer to receive the max size.
- *
-- * This function is called to get the context scheduling mode being used by JS.
-+ * This function is called to get the maximum size for the memory pool 0 of
-+ * small (4KiB) pages. It is assumed that the maximum size value is same for
-+ * all the pools.
- *
- * Return: The number of bytes output to @buf.
- */
--static ssize_t show_js_ctx_scheduling_mode(struct device *dev,
-+static ssize_t show_simplified_mem_pool_max_size(struct device *dev,
- struct device_attribute *attr, char * const buf)
- {
-- struct kbase_device *kbdev;
-+ struct kbase_device *const kbdev = to_kbase_device(dev);
-
-- kbdev = to_kbase_device(dev);
- if (!kbdev)
- return -ENODEV;
-
-- return scnprintf(buf, PAGE_SIZE, "%u\n", kbdev->js_ctx_scheduling_mode);
-+ return kbase_debugfs_helper_get_attr_to_string(buf, PAGE_SIZE,
-+ kbdev->mem_pools.small, 1, kbase_mem_pool_debugfs_max_size);
- }
-
- /**
-- * set_js_ctx_scheduling_mode - Set callback for js_ctx_scheduling_mode sysfs
-- * entry.
-- * @dev: The device this sysfs file is for.
-- * @attr: The attributes of the sysfs file.
-- * @buf: The value written to the sysfs file.
-- * @count: The number of bytes written to the sysfs file.
-+ * set_simplified_mem_pool_max_size - Set the same maximum size for all the
-+ * memory pools of small (4KiB) pages.
-+ * @dev: The device with sysfs file is for
-+ * @attr: The attributes of the sysfs file
-+ * @buf: The value written to the sysfs file
-+ * @count: The number of bytes written to the sysfs file
- *
-- * This function is called when the js_ctx_scheduling_mode sysfs file is written
-- * to. It checks the data written, and if valid updates the ctx scheduling mode
-- * being by JS.
-+ * This function is called to set the same maximum size for all the memory
-+ * pools of small (4KiB) pages.
- *
-- * Return: @count if the function succeeded. An error code on failure.
-+ * Return: The number of bytes output to @buf.
- */
--static ssize_t set_js_ctx_scheduling_mode(struct device *dev,
-+static ssize_t set_simplified_mem_pool_max_size(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
-- struct kbase_context *kctx;
-- u32 new_js_ctx_scheduling_mode;
-- struct kbase_device *kbdev;
-- unsigned long flags;
-- int ret;
-+ struct kbase_device *const kbdev = to_kbase_device(dev);
-+ unsigned long new_size;
-+ int gid;
-+ int err;
-
-- kbdev = to_kbase_device(dev);
- if (!kbdev)
- return -ENODEV;
-
-- ret = kstrtouint(buf, 0, &new_js_ctx_scheduling_mode);
-- if (ret || new_js_ctx_scheduling_mode >= KBASE_JS_PRIORITY_MODE_COUNT) {
-- dev_err(kbdev->dev, "Couldn't process js_ctx_scheduling_mode"
-- " write operation.\n"
-- "Use format <js_ctx_scheduling_mode>\n");
-+ err = kstrtoul(buf, 0, &new_size);
-+ if (err)
- return -EINVAL;
-- }
--
-- if (new_js_ctx_scheduling_mode == kbdev->js_ctx_scheduling_mode)
-- return count;
--
-- mutex_lock(&kbdev->kctx_list_lock);
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
--
-- /* Update the context priority mode */
-- kbdev->js_ctx_scheduling_mode = new_js_ctx_scheduling_mode;
--
-- /* Adjust priority of all the contexts as per the new mode */
-- list_for_each_entry(kctx, &kbdev->kctx_list, kctx_list_link)
-- kbase_js_update_ctx_priority(kctx);
--
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-- mutex_unlock(&kbdev->kctx_list_lock);
-
-- dev_dbg(kbdev->dev, "JS ctx scheduling mode: %u\n", new_js_ctx_scheduling_mode);
-+ for (gid = 0; gid < MEMORY_GROUP_MANAGER_NR_GROUPS; ++gid)
-+ kbase_mem_pool_debugfs_set_max_size(
-+ kbdev->mem_pools.small, gid, (size_t)new_size);
-
- return count;
- }
-
--static DEVICE_ATTR(js_ctx_scheduling_mode, S_IRUGO | S_IWUSR,
-- show_js_ctx_scheduling_mode,
-- set_js_ctx_scheduling_mode);
--
--#ifdef MALI_KBASE_BUILD
--#ifdef CONFIG_DEBUG_FS
--
--/* Number of entries in serialize_jobs_settings[] */
--#define NR_SERIALIZE_JOBS_SETTINGS 5
--/* Maximum string length in serialize_jobs_settings[].name */
--#define MAX_SERIALIZE_JOBS_NAME_LEN 16
--
--static struct
--{
-- char *name;
-- u8 setting;
--} serialize_jobs_settings[NR_SERIALIZE_JOBS_SETTINGS] = {
-- {"none", 0},
-- {"intra-slot", KBASE_SERIALIZE_INTRA_SLOT},
-- {"inter-slot", KBASE_SERIALIZE_INTER_SLOT},
-- {"full", KBASE_SERIALIZE_INTRA_SLOT | KBASE_SERIALIZE_INTER_SLOT},
-- {"full-reset", KBASE_SERIALIZE_INTRA_SLOT | KBASE_SERIALIZE_INTER_SLOT |
-- KBASE_SERIALIZE_RESET}
--};
-+static DEVICE_ATTR(max_size, 0600, show_simplified_mem_pool_max_size,
-+ set_simplified_mem_pool_max_size);
-
- /**
-- * kbasep_serialize_jobs_seq_show - Show callback for the serialize_jobs debugfs
-- * file
-- * @sfile: seq_file pointer
-- * @data: Private callback data
-+ * show_simplified_lp_mem_pool_max_size - Show the maximum size for the memory
-+ * pool 0 of large (2MiB) pages.
-+ * @dev: The device this sysfs file is for.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The output buffer to receive the total current pool size.
- *
-- * This function is called to get the contents of the serialize_jobs debugfs
-- * file. This is a list of the available settings with the currently active one
-- * surrounded by square brackets.
-+ * This function is called to get the maximum size for the memory pool 0 of
-+ * large (2MiB) pages. It is assumed that the maximum size value is same for
-+ * all the pools.
- *
-- * Return: 0 on success, or an error code on error
-+ * Return: The number of bytes output to @buf.
- */
--static int kbasep_serialize_jobs_seq_show(struct seq_file *sfile, void *data)
-+static ssize_t show_simplified_lp_mem_pool_max_size(struct device *dev,
-+ struct device_attribute *attr, char * const buf)
-+{
-+ struct kbase_device *const kbdev = to_kbase_device(dev);
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ return kbase_debugfs_helper_get_attr_to_string(buf, PAGE_SIZE,
-+ kbdev->mem_pools.large, 1, kbase_mem_pool_debugfs_max_size);
-+}
-+
-+/**
-+ * set_simplified_lp_mem_pool_max_size - Set the same maximum size for all the
-+ * memory pools of large (2MiB) pages.
-+ * @dev: The device with sysfs file is for
-+ * @attr: The attributes of the sysfs file
-+ * @buf: The value written to the sysfs file
-+ * @count: The number of bytes written to the sysfs file
-+ *
-+ * This function is called to set the same maximum size for all the memory
-+ * pools of large (2MiB) pages.
-+ *
-+ * Return: The number of bytes output to @buf.
-+ */
-+static ssize_t set_simplified_lp_mem_pool_max_size(struct device *dev,
-+ struct device_attribute *attr, const char *buf, size_t count)
-+{
-+ struct kbase_device *const kbdev = to_kbase_device(dev);
-+ unsigned long new_size;
-+ int gid;
-+ int err;
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ err = kstrtoul(buf, 0, &new_size);
-+ if (err)
-+ return -EINVAL;
-+
-+ for (gid = 0; gid < MEMORY_GROUP_MANAGER_NR_GROUPS; ++gid)
-+ kbase_mem_pool_debugfs_set_max_size(
-+ kbdev->mem_pools.large, gid, (size_t)new_size);
-+
-+ return count;
-+}
-+
-+static DEVICE_ATTR(lp_max_size, 0600, show_simplified_lp_mem_pool_max_size,
-+ set_simplified_lp_mem_pool_max_size);
-+
-+/**
-+ * show_simplified_ctx_default_max_size - Show the default maximum size for the
-+ * memory pool 0 of small (4KiB) pages.
-+ * @dev: The device this sysfs file is for.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The output buffer to receive the pool size.
-+ *
-+ * This function is called to get the default ctx maximum size for the memory
-+ * pool 0 of small (4KiB) pages. It is assumed that maximum size value is same
-+ * for all the pools. The maximum size for the pool of large (2MiB) pages will
-+ * be same as max size of the pool of small (4KiB) pages in terms of bytes.
-+ *
-+ * Return: The number of bytes output to @buf.
-+ */
-+static ssize_t show_simplified_ctx_default_max_size(struct device *dev,
-+ struct device_attribute *attr, char * const buf)
-+{
-+ struct kbase_device *kbdev = to_kbase_device(dev);
-+ size_t max_size;
-+
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ max_size = kbase_mem_pool_config_debugfs_max_size(
-+ kbdev->mem_pool_defaults.small, 0);
-+
-+ return scnprintf(buf, PAGE_SIZE, "%zu\n", max_size);
-+}
-+
-+/**
-+ * set_simplified_ctx_default_max_size - Set the same default maximum size for
-+ * all the pools created for new
-+ * contexts. This covers the pool of
-+ * large pages as well and its max size
-+ * will be same as max size of the pool
-+ * of small pages in terms of bytes.
-+ * @dev: The device this sysfs file is for.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The value written to the sysfs file.
-+ * @count: The number of bytes written to the sysfs file.
-+ *
-+ * This function is called to set the same maximum size for all pools created
-+ * for new contexts.
-+ *
-+ * Return: @count if the function succeeded. An error code on failure.
-+ */
-+static ssize_t set_simplified_ctx_default_max_size(struct device *dev,
-+ struct device_attribute *attr, const char *buf, size_t count)
-+{
-+ struct kbase_device *kbdev;
-+ unsigned long new_size;
-+ int err;
-+
-+ kbdev = to_kbase_device(dev);
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ err = kstrtoul(buf, 0, &new_size);
-+ if (err)
-+ return -EINVAL;
-+
-+ kbase_mem_pool_group_config_set_max_size(
-+ &kbdev->mem_pool_defaults, (size_t)new_size);
-+
-+ return count;
-+}
-+
-+static DEVICE_ATTR(ctx_default_max_size, 0600,
-+ show_simplified_ctx_default_max_size,
-+ set_simplified_ctx_default_max_size);
-+
-+#if !MALI_USE_CSF
-+/**
-+ * show_js_ctx_scheduling_mode - Show callback for js_ctx_scheduling_mode sysfs
-+ * entry.
-+ * @dev: The device this sysfs file is for.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The output buffer to receive the context scheduling mode information.
-+ *
-+ * This function is called to get the context scheduling mode being used by JS.
-+ *
-+ * Return: The number of bytes output to @buf.
-+ */
-+static ssize_t show_js_ctx_scheduling_mode(struct device *dev,
-+ struct device_attribute *attr, char * const buf)
-+{
-+ struct kbase_device *kbdev;
-+
-+ kbdev = to_kbase_device(dev);
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ return scnprintf(buf, PAGE_SIZE, "%u\n", kbdev->js_ctx_scheduling_mode);
-+}
-+
-+/**
-+ * set_js_ctx_scheduling_mode - Set callback for js_ctx_scheduling_mode sysfs
-+ * entry.
-+ * @dev: The device this sysfs file is for.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The value written to the sysfs file.
-+ * @count: The number of bytes written to the sysfs file.
-+ *
-+ * This function is called when the js_ctx_scheduling_mode sysfs file is written
-+ * to. It checks the data written, and if valid updates the ctx scheduling mode
-+ * being by JS.
-+ *
-+ * Return: @count if the function succeeded. An error code on failure.
-+ */
-+static ssize_t set_js_ctx_scheduling_mode(struct device *dev,
-+ struct device_attribute *attr, const char *buf, size_t count)
-+{
-+ struct kbase_context *kctx;
-+ u32 new_js_ctx_scheduling_mode;
-+ struct kbase_device *kbdev;
-+ unsigned long flags;
-+ int ret;
-+
-+ kbdev = to_kbase_device(dev);
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ ret = kstrtouint(buf, 0, &new_js_ctx_scheduling_mode);
-+ if (ret || new_js_ctx_scheduling_mode >= KBASE_JS_PRIORITY_MODE_COUNT) {
-+ dev_err(kbdev->dev, "Couldn't process js_ctx_scheduling_mode"
-+ " write operation.\n"
-+ "Use format <js_ctx_scheduling_mode>\n");
-+ return -EINVAL;
-+ }
-+
-+ if (new_js_ctx_scheduling_mode == kbdev->js_ctx_scheduling_mode)
-+ return count;
-+
-+ mutex_lock(&kbdev->kctx_list_lock);
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+
-+ /* Update the context priority mode */
-+ kbdev->js_ctx_scheduling_mode = new_js_ctx_scheduling_mode;
-+
-+ /* Adjust priority of all the contexts as per the new mode */
-+ list_for_each_entry(kctx, &kbdev->kctx_list, kctx_list_link)
-+ kbase_js_update_ctx_priority(kctx);
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ mutex_unlock(&kbdev->kctx_list_lock);
-+
-+ dev_dbg(kbdev->dev, "JS ctx scheduling mode: %u\n", new_js_ctx_scheduling_mode);
-+
-+ return count;
-+}
-+
-+static DEVICE_ATTR(js_ctx_scheduling_mode, S_IRUGO | S_IWUSR,
-+ show_js_ctx_scheduling_mode,
-+ set_js_ctx_scheduling_mode);
-+
-+#ifdef MALI_KBASE_BUILD
-+
-+/* Number of entries in serialize_jobs_settings[] */
-+#define NR_SERIALIZE_JOBS_SETTINGS 5
-+/* Maximum string length in serialize_jobs_settings[].name */
-+#define MAX_SERIALIZE_JOBS_NAME_LEN 16
-+
-+static struct
-+{
-+ char *name;
-+ u8 setting;
-+} serialize_jobs_settings[NR_SERIALIZE_JOBS_SETTINGS] = {
-+ {"none", 0},
-+ {"intra-slot", KBASE_SERIALIZE_INTRA_SLOT},
-+ {"inter-slot", KBASE_SERIALIZE_INTER_SLOT},
-+ {"full", KBASE_SERIALIZE_INTRA_SLOT | KBASE_SERIALIZE_INTER_SLOT},
-+ {"full-reset", KBASE_SERIALIZE_INTRA_SLOT | KBASE_SERIALIZE_INTER_SLOT |
-+ KBASE_SERIALIZE_RESET}
-+};
-+
-+/**
-+ * update_serialize_jobs_setting - Update the serialization setting for the
-+ * submission of GPU jobs.
-+ *
-+ * This function is called when the serialize_jobs sysfs/debugfs file is
-+ * written to. It matches the requested setting against the available settings
-+ * and if a matching setting is found updates kbdev->serialize_jobs.
-+ *
-+ * @kbdev: An instance of the GPU platform device, allocated from the probe
-+ * method of the driver.
-+ * @buf: Buffer containing the value written to the sysfs/debugfs file.
-+ * @count: The number of bytes to write to the sysfs/debugfs file.
-+ *
-+ * Return: @count if the function succeeded. An error code on failure.
-+ */
-+static ssize_t update_serialize_jobs_setting(struct kbase_device *kbdev,
-+ const char *buf, size_t count)
-+{
-+ int i;
-+ bool valid = false;
-+
-+ for (i = 0; i < NR_SERIALIZE_JOBS_SETTINGS; i++) {
-+ if (sysfs_streq(serialize_jobs_settings[i].name, buf)) {
-+ kbdev->serialize_jobs =
-+ serialize_jobs_settings[i].setting;
-+ valid = true;
-+ break;
-+ }
-+ }
-+
-+ if (!valid) {
-+ dev_err(kbdev->dev, "serialize_jobs: invalid setting");
-+ return -EINVAL;
-+ }
-+
-+ return count;
-+}
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+/**
-+ * kbasep_serialize_jobs_seq_debugfs_show - Show callback for the serialize_jobs
-+ * debugfs file
-+ * @sfile: seq_file pointer
-+ * @data: Private callback data
-+ *
-+ * This function is called to get the contents of the serialize_jobs debugfs
-+ * file. This is a list of the available settings with the currently active one
-+ * surrounded by square brackets.
-+ *
-+ * Return: 0 on success, or an error code on error
-+ */
-+static int kbasep_serialize_jobs_seq_debugfs_show(struct seq_file *sfile,
-+ void *data)
- {
- struct kbase_device *kbdev = sfile->private;
- int i;
-@@ -3169,8 +4110,6 @@ static ssize_t kbasep_serialize_jobs_debugfs_write(struct file *file,
- struct seq_file *s = file->private_data;
- struct kbase_device *kbdev = s->private;
- char buf[MAX_SERIALIZE_JOBS_NAME_LEN];
-- int i;
-- bool valid = false;
-
- CSTD_UNUSED(ppos);
-
-@@ -3180,21 +4119,7 @@ static ssize_t kbasep_serialize_jobs_debugfs_write(struct file *file,
-
- buf[count] = 0;
-
-- for (i = 0; i < NR_SERIALIZE_JOBS_SETTINGS; i++) {
-- if (sysfs_streq(serialize_jobs_settings[i].name, buf)) {
-- kbdev->serialize_jobs =
-- serialize_jobs_settings[i].setting;
-- valid = true;
-- break;
-- }
-- }
--
-- if (!valid) {
-- dev_err(kbdev->dev, "serialize_jobs: invalid setting\n");
-- return -EINVAL;
-- }
--
-- return count;
-+ return update_serialize_jobs_setting(kbdev, buf, count);
- }
-
- /**
-@@ -3208,7 +4133,8 @@ static ssize_t kbasep_serialize_jobs_debugfs_write(struct file *file,
- static int kbasep_serialize_jobs_debugfs_open(struct inode *in,
- struct file *file)
- {
-- return single_open(file, kbasep_serialize_jobs_seq_show, in->i_private);
-+ return single_open(file, kbasep_serialize_jobs_seq_debugfs_show,
-+ in->i_private);
- }
-
- static const struct file_operations kbasep_serialize_jobs_debugfs_fops = {
-@@ -3221,27 +4147,101 @@ static const struct file_operations kbasep_serialize_jobs_debugfs_fops = {
- };
-
- #endif /* CONFIG_DEBUG_FS */
-+
-+/**
-+ * show_serialize_jobs_sysfs - Show callback for serialize_jobs sysfs file.
-+ *
-+ * This function is called to get the contents of the serialize_jobs sysfs
-+ * file. This is a list of the available settings with the currently active
-+ * one surrounded by square brackets.
-+ *
-+ * @dev: The device this sysfs file is for
-+ * @attr: The attributes of the sysfs file
-+ * @buf: The output buffer for the sysfs file contents
-+ *
-+ * Return: The number of bytes output to @buf.
-+ */
-+static ssize_t show_serialize_jobs_sysfs(struct device *dev,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct kbase_device *kbdev = to_kbase_device(dev);
-+ ssize_t ret = 0;
-+ int i;
-+
-+ for (i = 0; i < NR_SERIALIZE_JOBS_SETTINGS; i++) {
-+ if (kbdev->serialize_jobs ==
-+ serialize_jobs_settings[i].setting)
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "[%s]",
-+ serialize_jobs_settings[i].name);
-+ else
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s ",
-+ serialize_jobs_settings[i].name);
-+ }
-+
-+ if (ret < PAGE_SIZE - 1) {
-+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
-+ } else {
-+ buf[PAGE_SIZE - 2] = '\n';
-+ buf[PAGE_SIZE - 1] = '\0';
-+ ret = PAGE_SIZE - 1;
-+ }
-+
-+ return ret;
-+}
-+
-+/**
-+ * store_serialize_jobs_sysfs - Store callback for serialize_jobs sysfs file.
-+ *
-+ * This function is called when the serialize_jobs sysfs file is written to.
-+ * It matches the requested setting against the available settings and if a
-+ * matching setting is found updates kbdev->serialize_jobs.
-+ *
-+ * @dev: The device this sysfs file is for
-+ * @attr: The attributes of the sysfs file
-+ * @buf: The value written to the sysfs file
-+ * @count: The number of bytes to write to the sysfs file
-+ *
-+ * Return: @count if the function succeeded. An error code on failure.
-+ */
-+static ssize_t store_serialize_jobs_sysfs(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ return update_serialize_jobs_setting(to_kbase_device(dev), buf, count);
-+}
-+
-+static DEVICE_ATTR(serialize_jobs, 0600, show_serialize_jobs_sysfs,
-+ store_serialize_jobs_sysfs);
- #endif /* MALI_KBASE_BUILD */
-+#endif /* !MALI_USE_CSF */
-
- static void kbasep_protected_mode_hwcnt_disable_worker(struct work_struct *data)
- {
- struct kbase_device *kbdev = container_of(data, struct kbase_device,
- protected_mode_hwcnt_disable_work);
-+ spinlock_t *backend_lock;
- unsigned long flags;
-
- bool do_disable;
-
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+#if MALI_USE_CSF
-+ backend_lock = &kbdev->csf.scheduler.interrupt_lock;
-+#else
-+ backend_lock = &kbdev->hwaccess_lock;
-+#endif
-+
-+ spin_lock_irqsave(backend_lock, flags);
- do_disable = !kbdev->protected_mode_hwcnt_desired &&
- !kbdev->protected_mode_hwcnt_disabled;
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ spin_unlock_irqrestore(backend_lock, flags);
-
- if (!do_disable)
- return;
-
- kbase_hwcnt_context_disable(kbdev->hwcnt_gpu_ctx);
-
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ spin_lock_irqsave(backend_lock, flags);
- do_disable = !kbdev->protected_mode_hwcnt_desired &&
- !kbdev->protected_mode_hwcnt_disabled;
-
-@@ -3251,7 +4251,9 @@ static void kbasep_protected_mode_hwcnt_disable_worker(struct work_struct *data)
- * the state machine.
- */
- kbdev->protected_mode_hwcnt_disabled = true;
-+#if !MALI_USE_CSF
- kbase_backend_slot_update(kbdev);
-+#endif /* !MALI_USE_CSF */
- } else {
- /* Protected mode state was updated while we were doing the
- * disable, so we need to undo the disable we just performed.
-@@ -3259,9 +4261,10 @@ static void kbasep_protected_mode_hwcnt_disable_worker(struct work_struct *data)
- kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx);
- }
-
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ spin_unlock_irqrestore(backend_lock, flags);
- }
-
-+#ifndef PLATFORM_PROTECTED_CALLBACKS
- static int kbasep_protected_mode_enable(struct protected_mode_device *pdev)
- {
- struct kbase_device *kbdev = pdev->data;
-@@ -3281,6 +4284,9 @@ static const struct protected_mode_ops kbasep_native_protected_ops = {
- .protected_mode_disable = kbasep_protected_mode_disable
- };
-
-+#define PLATFORM_PROTECTED_CALLBACKS (&kbasep_native_protected_ops)
-+#endif /* PLATFORM_PROTECTED_CALLBACKS */
-+
- int kbase_protected_mode_init(struct kbase_device *kbdev)
- {
- /* Use native protected ops */
-@@ -3289,7 +4295,7 @@ int kbase_protected_mode_init(struct kbase_device *kbdev)
- if (!kbdev->protected_dev)
- return -ENOMEM;
- kbdev->protected_dev->data = kbdev;
-- kbdev->protected_ops = &kbasep_native_protected_ops;
-+ kbdev->protected_ops = PLATFORM_PROTECTED_CALLBACKS;
- INIT_WORK(&kbdev->protected_mode_hwcnt_disable_work,
- kbasep_protected_mode_hwcnt_disable_worker);
- kbdev->protected_mode_hwcnt_desired = true;
-@@ -3303,15 +4309,6 @@ void kbase_protected_mode_term(struct kbase_device *kbdev)
- kfree(kbdev->protected_dev);
- }
-
--#ifdef CONFIG_MALI_NO_MALI
--static int kbase_common_reg_map(struct kbase_device *kbdev)
--{
-- return 0;
--}
--static void kbase_common_reg_unmap(struct kbase_device * const kbdev)
--{
--}
--#else /* CONFIG_MALI_NO_MALI */
- static int kbase_common_reg_map(struct kbase_device *kbdev)
- {
- int err = 0;
-@@ -3347,7 +4344,6 @@ static void kbase_common_reg_unmap(struct kbase_device * const kbdev)
- kbdev->reg_size = 0;
- }
- }
--#endif /* CONFIG_MALI_NO_MALI */
-
- int registers_map(struct kbase_device * const kbdev)
- {
-@@ -3367,6 +4363,15 @@ int registers_map(struct kbase_device * const kbdev)
- kbdev->reg_start = reg_res->start;
- kbdev->reg_size = resource_size(reg_res);
-
-+#if MALI_USE_CSF
-+ if (kbdev->reg_size <
-+ (CSF_HW_DOORBELL_PAGE_OFFSET +
-+ CSF_NUM_DOORBELL * CSF_HW_DOORBELL_PAGE_SIZE)) {
-+ dev_err(kbdev->dev, "Insufficient register space, will override to the required size\n");
-+ kbdev->reg_size = CSF_HW_DOORBELL_PAGE_OFFSET +
-+ CSF_NUM_DOORBELL * CSF_HW_DOORBELL_PAGE_SIZE;
-+ }
-+#endif
-
- err = kbase_common_reg_map(kbdev);
- if (err) {
-@@ -3448,6 +4453,7 @@ int kbase_device_pm_init(struct kbase_device *kbdev)
- u32 gpu_model_id;
-
- if (kbase_is_pv_enabled(kbdev->dev->of_node)) {
-+ dev_info(kbdev->dev, "Arbitration interface enabled\n");
- if (kbase_is_pm_enabled(kbdev->dev->of_node)) {
- /* Arbitration AND power management invalid */
- dev_err(kbdev->dev, "Invalid combination of arbitration AND power management\n");
-@@ -3471,13 +4477,16 @@ int kbase_device_pm_init(struct kbase_device *kbdev)
- gpu_model_id = GPU_ID2_MODEL_MATCH_VALUE(product_id);
-
- if (gpu_model_id != GPU_ID2_PRODUCT_TGOX
-- && gpu_model_id != GPU_ID2_PRODUCT_TNOX) {
-+ && gpu_model_id != GPU_ID2_PRODUCT_TNOX
-+ && gpu_model_id != GPU_ID2_PRODUCT_TBAX) {
- kbase_arbiter_pm_early_term(kbdev);
- dev_err(kbdev->dev, "GPU platform not suitable for arbitration\n");
- return -EPERM;
- }
- }
- } else {
-+ kbdev->arb.arb_if = NULL;
-+ kbdev->arb.arb_dev = NULL;
- err = power_control_init(kbdev);
- }
- #else
-@@ -3489,7 +4498,7 @@ int kbase_device_pm_init(struct kbase_device *kbdev)
- void kbase_device_pm_term(struct kbase_device *kbdev)
- {
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- if (kbase_is_pv_enabled(kbdev->dev->of_node))
- kbase_arbiter_pm_early_term(kbdev);
- else
-@@ -3502,7 +4511,7 @@ void kbase_device_pm_term(struct kbase_device *kbdev)
-
- int power_control_init(struct kbase_device *kbdev)
- {
--#if KERNEL_VERSION(3, 18, 0) > LINUX_VERSION_CODE || !defined(CONFIG_OF)
-+#ifndef CONFIG_OF
- /* Power control initialization requires at least the capability to get
- * regulators and clocks from the device tree, as well as parsing
- * arrays of unsigned integer values.
-@@ -3597,12 +4606,6 @@ int power_control_init(struct kbase_device *kbdev)
- * on the device tree of the platform shouldn't prevent the driver
- * from completing its initialization.
- */
--#if (KERNEL_VERSION(4, 4, 0) > LINUX_VERSION_CODE && \
-- !defined(LSK_OPPV2_BACKPORT))
-- err = of_init_opp_table(kbdev->dev);
-- CSTD_UNUSED(err);
--#else
--
- #if defined(CONFIG_PM_OPP)
- #if ((KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE) && \
- defined(CONFIG_REGULATOR))
-@@ -3614,8 +4617,6 @@ int power_control_init(struct kbase_device *kbdev)
- err = dev_pm_opp_of_add_table(kbdev->dev);
- CSTD_UNUSED(err);
- #endif /* CONFIG_PM_OPP */
--
--#endif /* KERNEL_VERSION(4, 4, 0) > LINUX_VERSION_CODE */
- return 0;
-
- clocks_probe_defer:
-@@ -3624,20 +4625,13 @@ clocks_probe_defer:
- regulator_put(kbdev->regulators[i]);
- #endif
- return err;
--#endif /* KERNEL_VERSION(3, 18, 0) > LINUX_VERSION_CODE */
-+#endif /* CONFIG_OF */
- }
-
- void power_control_term(struct kbase_device *kbdev)
- {
- unsigned int i;
-
--#if (KERNEL_VERSION(4, 4, 0) > LINUX_VERSION_CODE && \
-- !defined(LSK_OPPV2_BACKPORT))
--#if KERNEL_VERSION(3, 19, 0) <= LINUX_VERSION_CODE
-- of_free_opp_table(kbdev->dev);
--#endif
--#else
--
- #if defined(CONFIG_PM_OPP)
- dev_pm_opp_of_remove_table(kbdev->dev);
- #if ((KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE) && \
-@@ -3647,8 +4641,6 @@ void power_control_term(struct kbase_device *kbdev)
- #endif /* (KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE */
- #endif /* CONFIG_PM_OPP */
-
--#endif /* KERNEL_VERSION(4, 4, 0) > LINUX_VERSION_CODE */
--
- for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
- if (kbdev->clocks[i]) {
- if (__clk_is_enabled(kbdev->clocks[i]))
-@@ -3659,24 +4651,23 @@ void power_control_term(struct kbase_device *kbdev)
- break;
- }
-
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) && defined(CONFIG_OF) \
-- && defined(CONFIG_REGULATOR)
-+#if defined(CONFIG_OF) && defined(CONFIG_REGULATOR)
- for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
- if (kbdev->regulators[i]) {
- regulator_put(kbdev->regulators[i]);
- kbdev->regulators[i] = NULL;
- }
- }
--#endif /* LINUX_VERSION_CODE >= 3, 12, 0 */
-+#endif
- }
-
- #ifdef MALI_KBASE_BUILD
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-
- static void trigger_reset(struct kbase_device *kbdev)
- {
- kbase_pm_context_active(kbdev);
-- if (kbase_prepare_to_reset_gpu(kbdev))
-+ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
- kbase_reset_gpu(kbdev);
- kbase_pm_context_idle(kbdev);
- }
-@@ -3704,7 +4695,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_##type##_quirks, type##_quirks_get,\
- MAKE_QUIRK_ACCESSORS(sc);
- MAKE_QUIRK_ACCESSORS(tiler);
- MAKE_QUIRK_ACCESSORS(mmu);
--MAKE_QUIRK_ACCESSORS(jm);
-+MAKE_QUIRK_ACCESSORS(gpu);
-
- static ssize_t kbase_device_debugfs_reset_write(struct file *file,
- const char __user *ubuf, size_t count, loff_t *ppos)
-@@ -3825,7 +4816,9 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev)
- kbdev->mali_debugfs_directory = debugfs_create_dir(kbdev->devname,
- NULL);
- if (!kbdev->mali_debugfs_directory) {
-- dev_err(kbdev->dev, "Couldn't create mali debugfs directory\n");
-+ dev_err(kbdev->dev,
-+ "Couldn't create mali debugfs directory: %s\n",
-+ kbdev->devname);
- err = -ENOMEM;
- goto out;
- }
-@@ -3838,6 +4831,14 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev)
- goto out;
- }
-
-+ kbdev->debugfs_instr_directory = debugfs_create_dir("instrumentation",
-+ kbdev->mali_debugfs_directory);
-+ if (!kbdev->debugfs_instr_directory) {
-+ dev_err(kbdev->dev, "Couldn't create mali debugfs instrumentation directory\n");
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
- debugfs_ctx_defaults_directory = debugfs_create_dir("defaults",
- kbdev->debugfs_ctx_directory);
- if (!debugfs_ctx_defaults_directory) {
-@@ -3846,20 +4847,20 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev)
- goto out;
- }
-
--#if !MALI_CUSTOMER_RELEASE
-- kbasep_regs_dump_debugfs_init(kbdev);
--#endif /* !MALI_CUSTOMER_RELEASE */
- kbasep_regs_history_debugfs_init(kbdev);
-
-+#if !MALI_USE_CSF
- kbase_debug_job_fault_debugfs_init(kbdev);
-+#endif /* !MALI_USE_CSF */
-
- kbasep_gpu_memory_debugfs_init(kbdev);
- kbase_as_fault_debugfs_init(kbdev);
--#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY_VIA_DEBUG_FS
-+#ifdef CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
- kbase_instr_backend_debugfs_init(kbdev);
- #endif
- /* fops_* variables created by invocations of macro
-- * MAKE_QUIRK_ACCESSORS() above. */
-+ * MAKE_QUIRK_ACCESSORS() above.
-+ */
- debugfs_create_file("quirks_sc", 0644,
- kbdev->mali_debugfs_directory, kbdev,
- &fops_sc_quirks);
-@@ -3869,9 +4870,8 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev)
- debugfs_create_file("quirks_mmu", 0644,
- kbdev->mali_debugfs_directory, kbdev,
- &fops_mmu_quirks);
-- debugfs_create_file("quirks_jm", 0644,
-- kbdev->mali_debugfs_directory, kbdev,
-- &fops_jm_quirks);
-+ debugfs_create_file("quirks_gpu", 0644, kbdev->mali_debugfs_directory,
-+ kbdev, &fops_gpu_quirks);
-
- debugfs_create_bool("infinite_cache", mode,
- debugfs_ctx_defaults_directory,
-@@ -3900,16 +4900,20 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev)
- kbase_ktrace_debugfs_init(kbdev);
-
- #ifdef CONFIG_MALI_DEVFREQ
--#ifdef CONFIG_DEVFREQ_THERMAL
-+#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
- if (kbdev->devfreq)
- kbase_ipa_debugfs_init(kbdev);
- #endif /* CONFIG_DEVFREQ_THERMAL */
- #endif /* CONFIG_MALI_DEVFREQ */
-
-+#if !MALI_USE_CSF
- debugfs_create_file("serialize_jobs", S_IRUGO | S_IWUSR,
- kbdev->mali_debugfs_directory, kbdev,
- &kbasep_serialize_jobs_debugfs_fops);
-
-+#endif
-+ kbase_dvfs_status_debugfs_init(kbdev);
-+
- return 0;
-
- out:
-@@ -3926,7 +4930,7 @@ void kbase_device_debugfs_term(struct kbase_device *kbdev)
-
- int kbase_device_coherency_init(struct kbase_device *kbdev)
- {
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- u32 supported_coherency_bitmap =
- kbdev->gpu_props.props.raw_props.coherency_mode;
- const void *coherency_override_dts;
-@@ -3953,7 +4957,7 @@ int kbase_device_coherency_init(struct kbase_device *kbdev)
- kbdev->system_coherency = COHERENCY_NONE;
-
- /* device tree may override the coherency */
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- coherency_override_dts = of_get_property(kbdev->dev->of_node,
- "system-coherency",
- NULL);
-@@ -3961,6 +4965,17 @@ int kbase_device_coherency_init(struct kbase_device *kbdev)
-
- override_coherency = be32_to_cpup(coherency_override_dts);
-
-+#if MALI_USE_CSF && !IS_ENABLED(CONFIG_MALI_NO_MALI)
-+ /* ACE coherency mode is not supported by Driver on CSF GPUs.
-+ * Return an error to signal the invalid device tree configuration.
-+ */
-+ if (override_coherency == COHERENCY_ACE) {
-+ dev_err(kbdev->dev,
-+ "ACE coherency not supported, wrong DT configuration");
-+ return -EINVAL;
-+ }
-+#endif
-+
- if ((override_coherency <= COHERENCY_NONE) &&
- (supported_coherency_bitmap &
- COHERENCY_FEATURE_BIT(override_coherency))) {
-@@ -3984,67 +4999,226 @@ int kbase_device_coherency_init(struct kbase_device *kbdev)
- return 0;
- }
-
--#ifdef CONFIG_MALI_BUSLOG
-
--/* Callback used by the kbase bus logger client, to initiate a GPU reset
-- * when the bus log is restarted. GPU reset is used as reference point
-- * in HW bus log analyses.
-+#if MALI_USE_CSF
-+/**
-+ * csg_scheduling_period_store - Store callback for the csg_scheduling_period
-+ * sysfs file.
-+ * @dev: The device with sysfs file is for
-+ * @attr: The attributes of the sysfs file
-+ * @buf: The value written to the sysfs file
-+ * @count: The number of bytes written to the sysfs file
-+ *
-+ * This function is called when the csg_scheduling_period sysfs file is written
-+ * to. It checks the data written, and if valid updates the reset timeout.
-+ *
-+ * Return: @count if the function succeeded. An error code on failure.
- */
--static void kbase_logging_started_cb(void *data)
-+static ssize_t csg_scheduling_period_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
- {
-- struct kbase_device *kbdev = (struct kbase_device *)data;
-+ struct kbase_device *kbdev;
-+ int ret;
-+ unsigned int csg_scheduling_period;
-
-- if (kbase_prepare_to_reset_gpu(kbdev))
-- kbase_reset_gpu(kbdev);
-- dev_info(kbdev->dev, "KBASE - Bus logger restarted\n");
-+ kbdev = to_kbase_device(dev);
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ ret = kstrtouint(buf, 0, &csg_scheduling_period);
-+ if (ret || csg_scheduling_period == 0) {
-+ dev_err(kbdev->dev,
-+ "Couldn't process csg_scheduling_period write operation.\n"
-+ "Use format 'csg_scheduling_period_ms', and csg_scheduling_period_ms > 0\n");
-+ return -EINVAL;
-+ }
-+
-+ kbase_csf_scheduler_lock(kbdev);
-+ kbdev->csf.scheduler.csg_scheduling_period_ms = csg_scheduling_period;
-+ dev_dbg(kbdev->dev, "CSG scheduling period: %ums\n",
-+ csg_scheduling_period);
-+ kbase_csf_scheduler_unlock(kbdev);
-+
-+ return count;
- }
-
--int buslog_init(struct kbase_device *kbdev)
-+/**
-+ * csg_scheduling_period_show - Show callback for the csg_scheduling_period
-+ * sysfs entry.
-+ * @dev: The device this sysfs file is for.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The output buffer to receive the GPU information.
-+ *
-+ * This function is called to get the current reset timeout.
-+ *
-+ * Return: The number of bytes output to @buf.
-+ */
-+static ssize_t csg_scheduling_period_show(struct device *dev,
-+ struct device_attribute *attr,
-+ char *const buf)
- {
-- int err = 0;
-+ struct kbase_device *kbdev;
-+ ssize_t ret;
-
-- err = bl_core_client_register(kbdev->devname,
-- kbase_logging_started_cb,
-- kbdev, &kbdev->buslogger,
-- THIS_MODULE, NULL);
-- if (err == 0)
-- bl_core_set_threshold(kbdev->buslogger, 1024*1024*1024);
-+ kbdev = to_kbase_device(dev);
-+ if (!kbdev)
-+ return -ENODEV;
-
-- return err;
-+ ret = scnprintf(buf, PAGE_SIZE, "%u\n",
-+ kbdev->csf.scheduler.csg_scheduling_period_ms);
-+
-+ return ret;
- }
-
--void buslog_term(struct kbase_device *kbdev)
-+static DEVICE_ATTR(csg_scheduling_period, 0644, csg_scheduling_period_show,
-+ csg_scheduling_period_store);
-+
-+/**
-+ * fw_timeout_store - Store callback for the fw_timeout sysfs file.
-+ * @dev: The device with sysfs file is for
-+ * @attr: The attributes of the sysfs file
-+ * @buf: The value written to the sysfs file
-+ * @count: The number of bytes written to the sysfs file
-+ *
-+ * This function is called when the fw_timeout sysfs file is written to. It
-+ * checks the data written, and if valid updates the reset timeout.
-+ *
-+ * Return: @count if the function succeeded. An error code on failure.
-+ */
-+static ssize_t fw_timeout_store(struct device *dev,
-+ struct device_attribute *attr, const char *buf,
-+ size_t count)
- {
-- bl_core_client_unregister(kbdev->buslogger);
-+ struct kbase_device *kbdev;
-+ int ret;
-+ unsigned int fw_timeout;
-+
-+ kbdev = to_kbase_device(dev);
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ ret = kstrtouint(buf, 0, &fw_timeout);
-+ if (ret || fw_timeout == 0) {
-+ dev_err(kbdev->dev, "%s\n%s\n%u",
-+ "Couldn't process fw_timeout write operation.",
-+ "Use format 'fw_timeout_ms', and fw_timeout_ms > 0",
-+ FIRMWARE_PING_INTERVAL_MS);
-+ return -EINVAL;
-+ }
-+
-+ kbase_csf_scheduler_lock(kbdev);
-+ kbdev->csf.fw_timeout_ms = fw_timeout;
-+ kbase_csf_scheduler_unlock(kbdev);
-+ dev_dbg(kbdev->dev, "Firmware timeout: %ums\n", fw_timeout);
-+
-+ return count;
- }
--#endif
-+
-+/**
-+ * fw_timeout_show - Show callback for the firmware timeout sysfs entry.
-+ * @dev: The device this sysfs file is for.
-+ * @attr: The attributes of the sysfs file.
-+ * @buf: The output buffer to receive the GPU information.
-+ *
-+ * This function is called to get the current reset timeout.
-+ *
-+ * Return: The number of bytes output to @buf.
-+ */
-+static ssize_t fw_timeout_show(struct device *dev,
-+ struct device_attribute *attr, char *const buf)
-+{
-+ struct kbase_device *kbdev;
-+ ssize_t ret;
-+
-+ kbdev = to_kbase_device(dev);
-+ if (!kbdev)
-+ return -ENODEV;
-+
-+ ret = scnprintf(buf, PAGE_SIZE, "%u\n", kbdev->csf.fw_timeout_ms);
-+
-+ return ret;
-+}
-+
-+static DEVICE_ATTR(fw_timeout, 0644, fw_timeout_show, fw_timeout_store);
-+#endif /* MALI_USE_CSF */
-+
-+static struct attribute *kbase_scheduling_attrs[] = {
-+#if !MALI_USE_CSF
-+ &dev_attr_serialize_jobs.attr,
-+#endif /* !MALI_USE_CSF */
-+ NULL
-+};
-
- static struct attribute *kbase_attrs[] = {
- #ifdef CONFIG_MALI_DEBUG
- &dev_attr_debug_command.attr,
-+#if !MALI_USE_CSF
- &dev_attr_js_softstop_always.attr,
-+#endif /* !MALI_USE_CSF */
- #endif
-+#if !MALI_USE_CSF
- &dev_attr_js_timeouts.attr,
- &dev_attr_soft_job_timeout.attr,
-+#endif /* !MALI_USE_CSF */
- &dev_attr_gpuinfo.attr,
- &dev_attr_dvfs_period.attr,
- &dev_attr_pm_poweroff.attr,
-+#if MALI_USE_CSF
-+ &dev_attr_idle_hysteresis_time.attr,
-+#endif
- &dev_attr_reset_timeout.attr,
-+#if !MALI_USE_CSF
- &dev_attr_js_scheduling_period.attr,
-+#else
-+ &dev_attr_csg_scheduling_period.attr,
-+ &dev_attr_fw_timeout.attr,
-+#endif /* !MALI_USE_CSF */
- &dev_attr_power_policy.attr,
- &dev_attr_core_mask.attr,
-+ &dev_attr_gpu_memory.attr,
- &dev_attr_mem_pool_size.attr,
- &dev_attr_mem_pool_max_size.attr,
- &dev_attr_lp_mem_pool_size.attr,
- &dev_attr_lp_mem_pool_max_size.attr,
-+#if !MALI_USE_CSF
- &dev_attr_js_ctx_scheduling_mode.attr,
-+#endif /* !MALI_USE_CSF */
-+ NULL
-+};
-+
-+static struct attribute *kbase_mempool_attrs[] = {
-+ &dev_attr_max_size.attr,
-+ &dev_attr_lp_max_size.attr,
-+ &dev_attr_ctx_default_max_size.attr,
- NULL
- };
-
-+#define SYSFS_SCHEDULING_GROUP "scheduling"
-+static const struct attribute_group kbase_scheduling_attr_group = {
-+ .name = SYSFS_SCHEDULING_GROUP,
-+ .attrs = kbase_scheduling_attrs,
-+};
-+
-+#define SYSFS_MEMPOOL_GROUP "mempool"
-+static const struct attribute_group kbase_mempool_attr_group = {
-+ .name = SYSFS_MEMPOOL_GROUP,
-+ .attrs = kbase_mempool_attrs,
-+};
-+
- static const struct attribute_group kbase_attr_group = {
- .attrs = kbase_attrs,
- };
-
-+static struct attribute *ctx_attrs[] = {
-+ &dev_attr_ctx_mem_pool_size.attr,
-+ NULL
-+};
-+
-+static const struct attribute_group kbase_ctx_attr_group = {
-+ .attrs = ctx_attrs,
-+};
-+
- int kbase_sysfs_init(struct kbase_device *kbdev)
- {
- int err = 0;
-@@ -4056,11 +5230,39 @@ int kbase_sysfs_init(struct kbase_device *kbdev)
- kbdev->mdev.mode = 0666;
-
- err = sysfs_create_group(&kbdev->dev->kobj, &kbase_attr_group);
-+ err += sysfs_create_group(&kbdev->dev->kobj, &kbase_ctx_attr_group);
-+ if (err)
-+ return err;
-+
-+ err = sysfs_create_group(&kbdev->dev->kobj,
-+ &kbase_scheduling_attr_group);
-+ if (err) {
-+ dev_err(kbdev->dev, "Creation of %s sysfs group failed",
-+ SYSFS_SCHEDULING_GROUP);
-+ sysfs_remove_group(&kbdev->dev->kobj,
-+ &kbase_attr_group);
-+ return err;
-+ }
-+
-+ err = sysfs_create_group(&kbdev->dev->kobj,
-+ &kbase_mempool_attr_group);
-+ if (err) {
-+ dev_err(kbdev->dev, "Creation of %s sysfs group failed",
-+ SYSFS_MEMPOOL_GROUP);
-+ sysfs_remove_group(&kbdev->dev->kobj,
-+ &kbase_scheduling_attr_group);
-+ sysfs_remove_group(&kbdev->dev->kobj,
-+ &kbase_attr_group);
-+ }
-+
- return err;
- }
-
- void kbase_sysfs_term(struct kbase_device *kbdev)
- {
-+ sysfs_remove_group(&kbdev->dev->kobj, &kbase_ctx_attr_group);
-+ sysfs_remove_group(&kbdev->dev->kobj, &kbase_mempool_attr_group);
-+ sysfs_remove_group(&kbdev->dev->kobj, &kbase_scheduling_attr_group);
- sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group);
- put_device(kbdev->dev);
- }
-@@ -4119,7 +5321,8 @@ static int kbase_platform_device_probe(struct platform_device *pdev)
-
- if (err) {
- if (err == -EPROBE_DEFER)
-- dev_err(kbdev->dev, "Device initialization Deferred\n");
-+ dev_info(kbdev->dev,
-+ "Device initialization Deferred\n");
- else
- dev_err(kbdev->dev, "Device initialization failed\n");
-
-@@ -4161,8 +5364,11 @@ static int kbase_device_suspend(struct device *dev)
-
- kbase_pm_suspend(kbdev);
-
--#if defined(CONFIG_MALI_DEVFREQ) && \
-- (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-+#ifdef CONFIG_MALI_MIDGARD_DVFS
-+ kbase_pm_metrics_stop(kbdev);
-+#endif
-+
-+#ifdef CONFIG_MALI_DEVFREQ
- dev_dbg(dev, "Callback %s\n", __func__);
- if (kbdev->devfreq) {
- kbase_devfreq_enqueue_work(kbdev, DEVFREQ_WORK_SUSPEND);
-@@ -4190,8 +5396,11 @@ static int kbase_device_resume(struct device *dev)
-
- kbase_pm_resume(kbdev);
-
--#if defined(CONFIG_MALI_DEVFREQ) && \
-- (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-+#ifdef CONFIG_MALI_MIDGARD_DVFS
-+ kbase_pm_metrics_start(kbdev);
-+#endif
-+
-+#ifdef CONFIG_MALI_DEVFREQ
- dev_dbg(dev, "Callback %s\n", __func__);
- if (kbdev->devfreq) {
- mutex_lock(&kbdev->pm.lock);
-@@ -4224,8 +5433,12 @@ static int kbase_device_runtime_suspend(struct device *dev)
- return -ENODEV;
-
- dev_dbg(dev, "Callback %s\n", __func__);
--#if defined(CONFIG_MALI_DEVFREQ) && \
-- (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-+
-+#ifdef CONFIG_MALI_MIDGARD_DVFS
-+ kbase_pm_metrics_stop(kbdev);
-+#endif
-+
-+#ifdef CONFIG_MALI_DEVFREQ
- if (kbdev->devfreq)
- kbase_devfreq_enqueue_work(kbdev, DEVFREQ_WORK_SUSPEND);
- #endif
-@@ -4263,8 +5476,11 @@ static int kbase_device_runtime_resume(struct device *dev)
- dev_dbg(dev, "runtime resume\n");
- }
-
--#if defined(CONFIG_MALI_DEVFREQ) && \
-- (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-+#ifdef CONFIG_MALI_MIDGARD_DVFS
-+ kbase_pm_metrics_start(kbdev);
-+#endif
-+
-+#ifdef CONFIG_MALI_DEVFREQ
- if (kbdev->devfreq)
- kbase_devfreq_enqueue_work(kbdev, DEVFREQ_WORK_RESUME);
- #endif
-@@ -4317,7 +5533,7 @@ static const struct dev_pm_ops kbase_pm_ops = {
- #endif /* KBASE_PM_RUNTIME */
- };
-
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- static const struct of_device_id kbase_dt_ids[] = {
- { .compatible = "arm,malit6xx" },
- { .compatible = "arm,mali-midgard" },
-@@ -4332,9 +5548,9 @@ static struct platform_driver kbase_platform_driver = {
- .remove = kbase_platform_device_remove,
- .driver = {
- .name = kbase_drv_name,
-- .owner = THIS_MODULE,
- .pm = &kbase_pm_ops,
- .of_match_table = of_match_ptr(kbase_dt_ids),
-+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- },
- };
-
-@@ -4342,7 +5558,7 @@ static struct platform_driver kbase_platform_driver = {
- * The driver will not provide a shortcut to create the Mali platform device
- * anymore when using Device Tree.
- */
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- module_platform_driver(kbase_platform_driver);
- #else
-
-@@ -4377,6 +5593,7 @@ MODULE_LICENSE("GPL");
- MODULE_VERSION(MALI_RELEASE_NAME " (UK version " \
- __stringify(BASE_UK_VERSION_MAJOR) "." \
- __stringify(BASE_UK_VERSION_MINOR) ")");
-+MODULE_SOFTDEP("pre: memory_group_manager");
-
- #define CREATE_TRACE_POINTS
- /* Create the trace points (otherwise we just get code to call a tracepoint) */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cs_experimental.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cs_experimental.h
-index e1fffc3..4dc09e4 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cs_experimental.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_cs_experimental.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,18 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--
--/*
-- * (C) COPYRIGHT 2019-2020 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.
-- *
- */
-
- #ifndef _KBASE_CS_EXPERIMENTAL_H_
-@@ -41,9 +30,6 @@
- */
- static inline void mali_kbase_print_cs_experimental(void)
- {
--#if MALI_JIT_PRESSURE_LIMIT
-- pr_info("mali_kbase: JIT_PRESSURE_LIMIT (experimental) enabled");
--#endif /* MALI_JIT_PRESSURE_LIMIT */
- #if MALI_INCREMENTAL_RENDERING
- pr_info("mali_kbase: INCREMENTAL_RENDERING (experimental) enabled");
- #endif /* MALI_INCREMENTAL_RENDERING */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ctx_sched.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ctx_sched.c
-index cea91bc..d06380d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ctx_sched.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ctx_sched.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2017-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,13 +17,9 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
--#include <mali_kbase_config_defaults.h>
--
- #include <mali_kbase_defs.h>
- #include "mali_kbase_ctx_sched.h"
- #include "tl/mali_kbase_tracepoints.h"
-@@ -46,7 +43,8 @@ int kbase_ctx_sched_init(struct kbase_device *kbdev)
- int as_present = (1U << kbdev->nr_hw_address_spaces) - 1;
-
- /* These two must be recalculated if nr_hw_address_spaces changes
-- * (e.g. for HW workarounds) */
-+ * (e.g. for HW workarounds)
-+ */
- kbdev->nr_user_address_spaces = kbdev->nr_hw_address_spaces;
- kbdev->as_free = as_present; /* All ASs initially free */
-
-@@ -212,6 +210,13 @@ void kbase_ctx_sched_restore_all_as(struct kbase_device *kbdev)
- for (i = 0; i != kbdev->nr_hw_address_spaces; ++i) {
- struct kbase_context *kctx;
-
-+#if MALI_USE_CSF
-+ if ((i == MCU_AS_NR) && kbdev->csf.firmware_inited) {
-+ kbase_mmu_update(kbdev, &kbdev->csf.mcu_mmu,
-+ MCU_AS_NR);
-+ continue;
-+ }
-+#endif
- kctx = kbdev->as_to_kctx[i];
- if (kctx) {
- if (atomic_read(&kctx->refcount)) {
-@@ -254,7 +259,7 @@ struct kbase_context *kbase_ctx_sched_as_to_ctx_refcount(
-
- found_kctx = kbdev->as_to_kctx[as_nr];
-
-- if (found_kctx != NULL)
-+ if (!WARN_ON(found_kctx == NULL))
- kbase_ctx_sched_retain_ctx_refcount(found_kctx);
-
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-@@ -264,6 +269,21 @@ struct kbase_context *kbase_ctx_sched_as_to_ctx_refcount(
-
- struct kbase_context *kbase_ctx_sched_as_to_ctx(struct kbase_device *kbdev,
- size_t as_nr)
-+{
-+ unsigned long flags;
-+ struct kbase_context *found_kctx;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+
-+ found_kctx = kbase_ctx_sched_as_to_ctx_nolock(kbdev, as_nr);
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ return found_kctx;
-+}
-+
-+struct kbase_context *kbase_ctx_sched_as_to_ctx_nolock(
-+ struct kbase_device *kbdev, size_t as_nr)
- {
- struct kbase_context *found_kctx;
-
-@@ -273,13 +293,14 @@ struct kbase_context *kbase_ctx_sched_as_to_ctx(struct kbase_device *kbdev,
- if (WARN_ON(as_nr >= BASE_MAX_NR_AS))
- return NULL;
-
-- found_kctx = kbdev->as_to_kctx[as_nr];
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-
-- if (WARN_ON(!found_kctx))
-- return NULL;
-+ found_kctx = kbdev->as_to_kctx[as_nr];
-
-- if (WARN_ON(atomic_read(&found_kctx->refcount) <= 0))
-- return NULL;
-+ if (found_kctx) {
-+ if (atomic_read(&found_kctx->refcount) <= 0)
-+ found_kctx = NULL;
-+ }
-
- return found_kctx;
- }
-@@ -342,3 +363,40 @@ void kbase_ctx_sched_release_ctx_lock(struct kbase_context *kctx)
-
- spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags);
- }
-+
-+#if MALI_USE_CSF
-+bool kbase_ctx_sched_inc_refcount_if_as_valid(struct kbase_context *kctx)
-+{
-+ struct kbase_device *kbdev;
-+ bool added_ref = false;
-+ unsigned long flags;
-+
-+ if (WARN_ON(kctx == NULL))
-+ return added_ref;
-+
-+ kbdev = kctx->kbdev;
-+
-+ if (WARN_ON(kbdev == NULL))
-+ return added_ref;
-+
-+ mutex_lock(&kbdev->mmu_hw_mutex);
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+
-+ if ((kctx->as_nr != KBASEP_AS_NR_INVALID) &&
-+ (kctx == kbdev->as_to_kctx[kctx->as_nr])) {
-+ atomic_inc(&kctx->refcount);
-+
-+ if (kbdev->as_free & (1u << kctx->as_nr))
-+ kbdev->as_free &= ~(1u << kctx->as_nr);
-+
-+ KBASE_KTRACE_ADD(kbdev, SCHED_RETAIN_CTX_NOLOCK, kctx,
-+ kbase_ktrace_get_ctx_refcnt(kctx));
-+ added_ref = true;
-+ }
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ mutex_unlock(&kbdev->mmu_hw_mutex);
-+
-+ return added_ref;
-+}
-+#endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ctx_sched.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ctx_sched.h
-index 1affa71..334724f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ctx_sched.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ctx_sched.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017-2018, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_CTX_SCHED_H_
-@@ -26,7 +25,7 @@
- #include <mali_kbase.h>
-
- /**
-- * The Context Scheduler manages address space assignment and reference
-+ * DOC: The Context Scheduler manages address space assignment and reference
- * counting to kbase_context. The interface has been designed to minimise
- * interactions between the Job Scheduler and Power Management/MMU to support
- * the existing Job Scheduler interface.
-@@ -41,7 +40,7 @@
- */
-
- /**
-- * kbase_ctx_sched_init - Initialise the context scheduler
-+ * kbase_ctx_sched_init() - Initialise the context scheduler
- * @kbdev: The device for which the context scheduler needs to be initialised
- *
- * This must be called during device initialisation. The number of hardware
-@@ -167,6 +166,21 @@ struct kbase_context *kbase_ctx_sched_as_to_ctx_refcount(
- struct kbase_context *kbase_ctx_sched_as_to_ctx(struct kbase_device *kbdev,
- size_t as_nr);
-
-+/**
-+ * kbase_ctx_sched_as_to_ctx_nolock - Lookup a context based on its current
-+ * address space.
-+ * @kbdev: The device for which the returned context must belong
-+ * @as_nr: address space assigned to the context of interest
-+ *
-+ * The following lock must be held by the caller:
-+ * * kbase_device::hwaccess_lock
-+ *
-+ * Return: a valid struct kbase_context on success or NULL on failure,
-+ * indicating that no context was found in as_nr.
-+ */
-+struct kbase_context *kbase_ctx_sched_as_to_ctx_nolock(
-+ struct kbase_device *kbdev, size_t as_nr);
-+
- /**
- * kbase_ctx_sched_inc_refcount_nolock - Refcount a context as being busy,
- * preventing it from being scheduled out.
-@@ -206,4 +220,22 @@ bool kbase_ctx_sched_inc_refcount(struct kbase_context *kctx);
- */
- void kbase_ctx_sched_release_ctx_lock(struct kbase_context *kctx);
-
-+#if MALI_USE_CSF
-+/**
-+ * kbase_ctx_sched_inc_refcount_if_as_valid - Refcount the context if it has GPU
-+ * address space slot assigned to it.
-+ *
-+ * @kctx: Context to be refcounted
-+ *
-+ * This function takes a reference on the context if it has a GPU address space
-+ * slot assigned to it. The address space slot will not be available for
-+ * re-assignment until the reference is released.
-+ *
-+ * Return: true if refcount succeeded and the address space slot will not be
-+ * reassigned, false if the refcount failed (because the address space slot
-+ * was not assigned).
-+ */
-+bool kbase_ctx_sched_inc_refcount_if_as_valid(struct kbase_context *kctx);
-+#endif
-+
- #endif /* _KBASE_CTX_SCHED_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug.c
-index 118f787..6d3b109 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2014 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2014, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #include <mali_kbase.h>
-
- static struct kbasep_debug_assert_cb kbasep_debug_assert_registered_cb = {
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug.h
-index 2fdb72d..10a3c85 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2015, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2015, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #ifndef _KBASE_DEBUG_H
- #define _KBASE_DEBUG_H
-
-@@ -43,7 +40,7 @@
- #endif /* KBASE_DEBUG_DISABLE_ASSERTS */
-
- /** Function type that is called on an KBASE_DEBUG_ASSERT() or KBASE_DEBUG_ASSERT_MSG() */
--typedef void (kbase_debug_assert_hook) (void *);
-+typedef void kbase_debug_assert_hook(void *);
-
- struct kbasep_debug_assert_cb {
- kbase_debug_assert_hook *func;
-@@ -51,9 +48,9 @@ struct 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
-+ * KBASEP_DEBUG_PRINT_TRACE - 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
- #define KBASEP_DEBUG_PRINT_TRACE \
-@@ -68,21 +65,22 @@ struct kbasep_debug_assert_cb {
- #endif
-
- /**
-- * @def KBASEP_DEBUG_ASSERT_OUT(trace, function, ...)
-- * @brief (Private) system printing function associated to the @ref 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.
-+ * KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) - (Private) system printing
-+ * function associated to the @ref KBASE_DEBUG_ASSERT_MSG event.
-+ * @trace: location in the code from where the message is printed
-+ * @function: function from where the message is printed
-+ * @...: 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 { \
-- pr_err("Mali<ASSERT>: %s function:%s ", trace, function);\
-- pr_err(__VA_ARGS__);\
-- pr_err("\n");\
-- } while (false)
-+#define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) \
-+ do { \
-+ pr_err("Mali<ASSERT>: %s function:%s ", trace, function); \
-+ pr_err(__VA_ARGS__); \
-+ pr_err("\n"); \
-+ } while (false)
- #else
- #define KBASEP_DEBUG_ASSERT_OUT(trace, function, ...) CSTD_NOP()
- #endif
-@@ -94,12 +92,12 @@ struct kbasep_debug_assert_cb {
- #endif
-
- /**
-- * @def KBASE_DEBUG_ASSERT(expr)
-- * @brief Calls @ref KBASE_PRINT_ASSERT and prints the expression @a expr if @a expr is false
-+ * KBASE_DEBUG_ASSERT(expr) - Calls @ref KBASE_PRINT_ASSERT and prints the
-+ * expression @a expr if @a expr is false
-+ * @expr: Boolean expression
- *
- * @note This macro does nothing if the flag @ref KBASE_DEBUG_DISABLE_ASSERTS is set to 1
- *
-- * @param expr Boolean expression
- */
- #define KBASE_DEBUG_ASSERT(expr) \
- KBASE_DEBUG_ASSERT_MSG(expr, #expr)
-@@ -107,15 +105,15 @@ struct kbasep_debug_assert_cb {
- #if KBASE_DEBUG_DISABLE_ASSERTS
- #define KBASE_DEBUG_ASSERT_MSG(expr, ...) CSTD_NOP()
- #else
-- /**
-- * @def KBASE_DEBUG_ASSERT_MSG(expr, ...)
-- * @brief Calls @ref KBASEP_DEBUG_ASSERT_OUT and prints the given message if @a expr is false
-- *
-- * @note This macro does nothing if the flag @ref 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.
-- */
-+/**
-+ * KBASE_DEBUG_ASSERT_MSG() - Calls @ref KBASEP_DEBUG_ASSERT_OUT and prints the
-+ * given message if @a expr is false
-+ * @expr: Boolean expression
-+ * @...: Message to display when @a expr is false, as a format string followed
-+ * by format arguments.
-+ *
-+ * This macro does nothing if the flag KBASE_DEBUG_DISABLE_ASSERTS is set to 1
-+ */
- #define KBASE_DEBUG_ASSERT_MSG(expr, ...) \
- do { \
- if (!(expr)) { \
-@@ -127,10 +125,8 @@ struct kbasep_debug_assert_cb {
- #endif /* KBASE_DEBUG_DISABLE_ASSERTS */
-
- /**
-- * @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.
-+ * KBASE_DEBUG_CODE( X ) - Executes the code inside the macro only in debug mode
-+ * @X: Code to compile only in debug mode.
- */
- #ifdef CONFIG_MALI_DEBUG
- #define KBASE_DEBUG_CODE(X) X
-@@ -141,7 +137,9 @@ struct kbasep_debug_assert_cb {
- /** @} */
-
- /**
-- * @brief Register a function to call on ASSERT
-+ * kbase_debug_assert_register_hook - Register a function to call on ASSERT
-+ * @func: the function to call when an assert is triggered.
-+ * @param: the parameter to pass to \a func when calling it
- *
- * 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.
-@@ -151,13 +149,12 @@ struct kbasep_debug_assert_cb {
- * @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()
-+ * kbasep_debug_assert_call_hook - 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
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_job_fault.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_job_fault.c
-index dbc774d..4f021b3 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_job_fault.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_job_fault.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2016, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,13 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
- #include <linux/spinlock.h>
- #include <mali_kbase_hwaccess_jm.h>
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-
- static bool kbase_is_job_fault_event_pending(struct kbase_device *kbdev)
- {
-@@ -518,23 +517,24 @@ void kbase_debug_job_fault_dev_term(struct kbase_device *kbdev)
- /*
- * Initialize the relevant data structure per context
- */
--void kbase_debug_job_fault_context_init(struct kbase_context *kctx)
-+int kbase_debug_job_fault_context_init(struct kbase_context *kctx)
- {
-
- /* We need allocate double size register range
- * Because this memory will keep the register address and value
- */
- kctx->reg_dump = vmalloc(0x4000 * 2);
-- if (kctx->reg_dump == NULL)
-- return;
--
-- if (kbase_debug_job_fault_reg_snapshot_init(kctx, 0x4000) == false) {
-- vfree(kctx->reg_dump);
-- kctx->reg_dump = NULL;
-+ if (kctx->reg_dump != NULL) {
-+ if (kbase_debug_job_fault_reg_snapshot_init(kctx, 0x4000) ==
-+ false) {
-+ vfree(kctx->reg_dump);
-+ kctx->reg_dump = NULL;
-+ }
-+ INIT_LIST_HEAD(&kctx->job_fault_resume_event_list);
-+ atomic_set(&kctx->job_fault_count, 0);
- }
-- INIT_LIST_HEAD(&kctx->job_fault_resume_event_list);
-- atomic_set(&kctx->job_fault_count, 0);
-
-+ return 0;
- }
-
- /*
-@@ -549,6 +549,14 @@ void kbase_debug_job_fault_kctx_unblock(struct kbase_context *kctx)
- {
- WARN_ON(!kbase_ctx_flag(kctx, KCTX_DYING));
-
-+ /* Return early if the job fault part of the kbase_device is not
-+ * initialized yet. An error can happen during the device probe after
-+ * the privileged Kbase context was created for the HW counter dumping
-+ * but before the job fault part is initialized.
-+ */
-+ if (!kctx->kbdev->job_fault_resume_workq)
-+ return;
-+
- kbase_ctx_remove_pending_event(kctx);
- }
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_job_fault.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_job_fault.h
-index ef69627..39aeed0 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_job_fault.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_job_fault.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2016, 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2016, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_DEBUG_JOB_FAULT_H
-@@ -54,8 +53,9 @@ void kbase_debug_job_fault_dev_term(struct kbase_device *kbdev);
- * kbase_debug_job_fault_context_init - Initialize the relevant
- * data structure per context
- * @kctx: KBase context pointer
-+ * @return 0 on success
- */
--void kbase_debug_job_fault_context_init(struct kbase_context *kctx);
-+int kbase_debug_job_fault_context_init(struct kbase_context *kctx);
-
- /**
- * kbase_debug_job_fault_context_term - Release the relevant
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_mem_view.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_mem_view.c
-index 4788137..5a99b5e 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_mem_view.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_mem_view.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2013-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2013-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -30,11 +29,7 @@
- #include <linux/list.h>
- #include <linux/file.h>
-
--#ifdef CONFIG_DEBUG_FS
--
--#if (KERNEL_VERSION(4, 1, 0) > LINUX_VERSION_CODE)
--#define get_file_rcu(x) atomic_long_inc_not_zero(&(x)->f_count)
--#endif
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-
- struct debug_mem_mapping {
- struct list_head node;
-@@ -179,6 +174,13 @@ static int debug_mem_zone_open(struct rb_root *rbtree,
- /* Empty region - ignore */
- continue;
-
-+ if (reg->flags & KBASE_REG_PROTECTED) {
-+ /* CPU access to protected memory is forbidden - so
-+ * skip this GPU virtual region.
-+ */
-+ continue;
-+ }
-+
- mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
- if (!mapping) {
- ret = -ENOMEM;
-@@ -222,19 +224,19 @@ static int debug_mem_open(struct inode *i, struct file *file)
- kbase_gpu_vm_lock(kctx);
-
- ret = debug_mem_zone_open(&kctx->reg_rbtree_same, mem_data);
-- if (0 != ret) {
-+ if (ret != 0) {
- kbase_gpu_vm_unlock(kctx);
- goto out;
- }
-
- ret = debug_mem_zone_open(&kctx->reg_rbtree_custom, mem_data);
-- if (0 != ret) {
-+ if (ret != 0) {
- kbase_gpu_vm_unlock(kctx);
- goto out;
- }
-
- ret = debug_mem_zone_open(&kctx->reg_rbtree_exec, mem_data);
-- if (0 != ret) {
-+ if (ret != 0) {
- kbase_gpu_vm_unlock(kctx);
- goto out;
- }
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_mem_view.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_mem_view.h
-index b948b7c..d034832 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_mem_view.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debug_mem_view.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2013-2015, 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2013-2015, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_DEBUG_MEM_VIEW_H
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c
-index 37e507b..973739f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/debugfs.h>
-@@ -46,10 +45,9 @@
- *
- * Return: 0 if success, negative error code otherwise.
- */
--static int set_attr_from_string(
-- char *const buf,
-- void *const array, size_t const nelems,
-- kbase_debugfs_helper_set_attr_fn const set_attr_fn)
-+static int
-+set_attr_from_string(char *const buf, void *const array, size_t const nelems,
-+ kbase_debugfs_helper_set_attr_fn *const set_attr_fn)
- {
- size_t index, err = 0;
- char *ptr = buf;
-@@ -90,9 +88,62 @@ static int set_attr_from_string(
- return err;
- }
-
-+int kbase_debugfs_string_validator(char *const buf)
-+{
-+ size_t index;
-+ int err = 0;
-+ char *ptr = buf;
-+
-+ for (index = 0; *ptr; ++index) {
-+ unsigned long test_number;
-+ size_t len;
-+
-+ /* Drop leading spaces */
-+ while (*ptr == ' ')
-+ ptr++;
-+
-+ /* Strings passed into the validator will be NULL terminated
-+ * by nature, so here strcspn only needs to delimit by
-+ * newlines, spaces and NULL terminator (delimited natively).
-+ */
-+ len = strcspn(ptr, "\n ");
-+ if (len == 0) {
-+ /* No more values (allow this) */
-+ break;
-+ }
-+
-+ /* Substitute a nul terminator for a space character to make
-+ * the substring valid for kstrtoul, and then replace it back.
-+ */
-+ if (ptr[len] == ' ') {
-+ ptr[len] = '\0';
-+ err = kstrtoul(ptr, 0, &test_number);
-+ ptr[len] = ' ';
-+
-+ /* len should only be incremented if there is a valid
-+ * number to follow - otherwise this will skip over
-+ * the NULL terminator in cases with no ending newline
-+ */
-+ len++;
-+ } else {
-+ /* This would occur at the last element before a space
-+ * or a NULL terminator.
-+ */
-+ err = kstrtoul(ptr, 0, &test_number);
-+ }
-+
-+ if (err)
-+ break;
-+ /* Skip the substring (including any premature nul terminator)
-+ */
-+ ptr += len;
-+ }
-+ return err;
-+}
-+
- int kbase_debugfs_helper_set_attr_from_string(
- const char *const buf, void *const array, size_t const nelems,
-- kbase_debugfs_helper_set_attr_fn const set_attr_fn)
-+ kbase_debugfs_helper_set_attr_fn *const set_attr_fn)
- {
- char *const wbuf = kstrdup(buf, GFP_KERNEL);
- int err = 0;
-@@ -100,6 +151,13 @@ int kbase_debugfs_helper_set_attr_from_string(
- if (!wbuf)
- return -ENOMEM;
-
-+ /* validate string before actually writing values */
-+ err = kbase_debugfs_string_validator(wbuf);
-+ if (err) {
-+ kfree(wbuf);
-+ return err;
-+ }
-+
- err = set_attr_from_string(wbuf, array, nelems,
- set_attr_fn);
-
-@@ -108,9 +166,9 @@ int kbase_debugfs_helper_set_attr_from_string(
- }
-
- ssize_t kbase_debugfs_helper_get_attr_to_string(
-- char *const buf, size_t const size,
-- void *const array, size_t const nelems,
-- kbase_debugfs_helper_get_attr_fn const get_attr_fn)
-+ char *const buf, size_t const size, void *const array,
-+ size_t const nelems,
-+ kbase_debugfs_helper_get_attr_fn *const get_attr_fn)
- {
- ssize_t total = 0;
- size_t index;
-@@ -128,10 +186,10 @@ ssize_t kbase_debugfs_helper_get_attr_to_string(
- return total;
- }
-
--int kbase_debugfs_helper_seq_write(struct file *const file,
-- const char __user *const ubuf, size_t const count,
-- size_t const nelems,
-- kbase_debugfs_helper_set_attr_fn const set_attr_fn)
-+int kbase_debugfs_helper_seq_write(
-+ struct file *const file, const char __user *const ubuf,
-+ size_t const count, size_t const nelems,
-+ kbase_debugfs_helper_set_attr_fn *const set_attr_fn)
- {
- const struct seq_file *const sfile = file->private_data;
- void *const array = sfile->private;
-@@ -154,6 +212,14 @@ int kbase_debugfs_helper_seq_write(struct file *const file,
- }
-
- buf[count] = '\0';
-+
-+ /* validate string before actually writing values */
-+ err = kbase_debugfs_string_validator(buf);
-+ if (err) {
-+ kfree(buf);
-+ return err;
-+ }
-+
- err = set_attr_from_string(buf,
- array, nelems, set_attr_fn);
- kfree(buf);
-@@ -161,9 +227,9 @@ int kbase_debugfs_helper_seq_write(struct file *const file,
- return err;
- }
-
--int kbase_debugfs_helper_seq_read(struct seq_file *const sfile,
-- size_t const nelems,
-- kbase_debugfs_helper_get_attr_fn const get_attr_fn)
-+int kbase_debugfs_helper_seq_read(
-+ struct seq_file *const sfile, size_t const nelems,
-+ kbase_debugfs_helper_get_attr_fn *const get_attr_fn)
- {
- void *const array = sfile->private;
- size_t index;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.h
-index c3c9efa..4c69d8b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_debugfs_helper.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_DEBUGFS_HELPER_H_
-@@ -31,8 +30,8 @@
- * @index: An element index. The valid range depends on the use-case.
- * @value: Attribute value to be set.
- */
--typedef void (*kbase_debugfs_helper_set_attr_fn)(
-- void *array, size_t index, size_t value);
-+typedef void kbase_debugfs_helper_set_attr_fn(void *array, size_t index,
-+ size_t value);
-
- /**
- * kbase_debugfs_helper_set_attr_from_string - Parse a string to reconfigure an
-@@ -56,7 +55,30 @@ typedef void (*kbase_debugfs_helper_set_attr_fn)(
- */
- int kbase_debugfs_helper_set_attr_from_string(
- const char *buf, void *array, size_t nelems,
-- kbase_debugfs_helper_set_attr_fn set_attr_fn);
-+ kbase_debugfs_helper_set_attr_fn *set_attr_fn);
-+
-+/**
-+ * kbase_debugfs_string_validator - Validate a string to be written to a
-+ * debugfs file for any incorrect formats
-+ * or wrong values.
-+ *
-+ * This function is to be used before any writes to debugfs values are done
-+ * such that any strings with erroneous values (such as octal 09 or
-+ * hexadecimal 0xGH are fully ignored) - without this validation, any correct
-+ * values before the first incorrect one will still be entered into the
-+ * debugfs file. This essentially iterates the values through kstrtoul to see
-+ * if it is valid.
-+ *
-+ * It is largely similar to set_attr_from_string to iterate through the values
-+ * of the input string. This function also requires the input string to be
-+ * writable.
-+ *
-+ * @buf: Null-terminated string to validate.
-+ *
-+ * Return: 0 with no error, else -22 (the invalid return value of kstrtoul) if
-+ * any value in the string was wrong or with an incorrect format.
-+ */
-+int kbase_debugfs_string_validator(char *const buf);
-
- /**
- * typedef kbase_debugfs_helper_get_attr_fn - Type of function to get an
-@@ -67,8 +89,7 @@ int kbase_debugfs_helper_set_attr_from_string(
- *
- * Return: Value of attribute.
- */
--typedef size_t (*kbase_debugfs_helper_get_attr_fn)(
-- void *array, size_t index);
-+typedef size_t kbase_debugfs_helper_get_attr_fn(void *array, size_t index);
-
- /**
- * kbase_debugfs_helper_get_attr_to_string - Construct a formatted string
-@@ -89,7 +110,7 @@ typedef size_t (*kbase_debugfs_helper_get_attr_fn)(
- */
- ssize_t kbase_debugfs_helper_get_attr_to_string(
- char *buf, size_t size, void *array, size_t nelems,
-- kbase_debugfs_helper_get_attr_fn get_attr_fn);
-+ kbase_debugfs_helper_get_attr_fn *get_attr_fn);
-
- /**
- * kbase_debugfs_helper_seq_read - Implements reads from a virtual file for an
-@@ -110,8 +131,8 @@ ssize_t kbase_debugfs_helper_get_attr_to_string(
- * Return: 0 if success, negative error code otherwise.
- */
- int kbase_debugfs_helper_seq_read(
-- struct seq_file *const sfile, size_t const nelems,
-- kbase_debugfs_helper_get_attr_fn const get_attr_fn);
-+ struct seq_file *sfile, size_t nelems,
-+ kbase_debugfs_helper_get_attr_fn *get_attr_fn);
-
- /**
- * kbase_debugfs_helper_seq_write - Implements writes to a virtual file for an
-@@ -132,10 +153,10 @@ int kbase_debugfs_helper_seq_read(
- *
- * Return: 0 if success, negative error code otherwise.
- */
--int kbase_debugfs_helper_seq_write(struct file *const file,
-- const char __user *const ubuf, size_t const count,
-- size_t const nelems,
-- kbase_debugfs_helper_set_attr_fn const set_attr_fn);
-+int kbase_debugfs_helper_seq_write(struct file *file,
-+ const char __user *ubuf, size_t count,
-+ size_t nelems,
-+ kbase_debugfs_helper_set_attr_fn *set_attr_fn);
-
- #endif /*_KBASE_DEBUGFS_HELPER_H_ */
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h
-index 7056d80..146695c 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,17 +17,11 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @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.
-+ * DOC: Defintions (types, defines, etcs) common to Kbase. They are placed here
-+ * to allow the hierarchy of header files to work.
- */
-
- #ifndef _KBASE_DEFS_H_
-@@ -37,10 +32,14 @@
- #include <mali_base_hwconfig_issues.h>
- #include <mali_kbase_mem_lowlevel.h>
- #include <mmu/mali_kbase_mmu_hw.h>
--#include <mali_kbase_instr_defs.h>
-+#include <backend/gpu/mali_kbase_instr_defs.h>
- #include <mali_kbase_pm.h>
- #include <mali_kbase_gpuprops_types.h>
--#include <mali_kbase_hwcnt_backend_gpu.h>
-+#if MALI_USE_CSF
-+#include <mali_kbase_hwcnt_backend_csf.h>
-+#else
-+#include <mali_kbase_hwcnt_backend_jm.h>
-+#endif
- #include <protected_mode_switcher.h>
-
- #include <linux/atomic.h>
-@@ -49,9 +48,6 @@
- #include <linux/file.h>
- #include <linux/sizes.h>
-
--#ifdef CONFIG_MALI_BUSLOG
--#include <linux/bus_logger.h>
--#endif
-
- #if defined(CONFIG_SYNC)
- #include <sync.h>
-@@ -59,7 +55,7 @@
- #include "mali_kbase_fence_defs.h"
- #endif
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- #include <linux/debugfs.h>
- #endif /* CONFIG_DEBUG_FS */
-
-@@ -75,8 +71,7 @@
- #include <linux/regulator/consumer.h>
- #include <linux/memory_group_manager.h>
-
--#if defined(CONFIG_PM_RUNTIME) || \
-- (defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
-+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM)
- #define KBASE_PM_RUNTIME 1
- #endif
-
-@@ -123,6 +118,11 @@
- */
- #define KBASE_LOCK_REGION_MIN_SIZE_LOG2 (15)
-
-+/**
-+ * Maximum number of GPU memory region zones
-+ */
-+#define KBASE_REG_ZONE_MAX 4ul
-+
- #include "mali_kbase_hwaccess_defs.h"
-
- /* Maximum number of pages of memory that require a permanent mapping, per
-@@ -138,24 +138,29 @@
- */
- #define KBASE_HWCNT_GPU_VIRTUALIZER_DUMP_THRESHOLD_NS (200 * NSEC_PER_USEC)
-
-+#if MALI_USE_CSF
-+/* The buffer count of CSF hwcnt backend ring buffer, which is used when CSF
-+ * hwcnt backend allocate the ring buffer to communicate with CSF firmware for
-+ * HWC dump samples.
-+ * To meet the hardware requirement, this number MUST be power of 2, otherwise,
-+ * CSF hwcnt backend creation will be failed.
-+ */
-+#define KBASE_HWCNT_BACKEND_CSF_RING_BUFFER_COUNT (128)
-+#endif
-+
- /* Maximum number of clock/regulator pairs that may be referenced by
- * the device node.
- * This is dependent on support for of_property_read_u64_array() in the
- * kernel.
- */
--#if (KERNEL_VERSION(4, 0, 0) <= LINUX_VERSION_CODE) || \
-- defined(LSK_OPPV2_BACKPORT)
- #define BASE_MAX_NR_CLOCKS_REGULATORS (2)
--#else
--#define BASE_MAX_NR_CLOCKS_REGULATORS (1)
--#endif
-
- /* Forward declarations */
- struct kbase_context;
- struct kbase_device;
- struct kbase_as;
- struct kbase_mmu_setup;
--struct kbase_ipa_model_vinstr_data;
-+struct kbase_kinstr_jm;
-
- /**
- * struct kbase_io_access - holds information about 1 register access
-@@ -178,11 +183,7 @@ struct kbase_io_access {
- * @buf: array of kbase_io_access
- */
- struct kbase_io_history {
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
- bool enabled;
--#else
-- u32 enabled;
--#endif
-
- spinlock_t lock;
- size_t count;
-@@ -242,29 +243,6 @@ struct kbase_fault {
- bool protected_mode;
- };
-
--/**
-- * struct kbase_as - object representing an address space of GPU.
-- * @number: Index at which this address space structure is present
-- * in an array of address space structures embedded inside the
-- * struct kbase_device.
-- * @pf_wq: Workqueue for processing work items related to Bus fault
-- * and Page fault handling.
-- * @work_pagefault: Work item for the Page fault handling.
-- * @work_busfault: Work item for the Bus fault handling.
-- * @pf_data: Data relating to page fault.
-- * @bf_data: Data relating to bus fault.
-- * @current_setup: Stores the MMU configuration for this address space.
-- */
--struct kbase_as {
-- int number;
-- struct workqueue_struct *pf_wq;
-- struct work_struct work_pagefault;
-- struct work_struct work_busfault;
-- struct kbase_fault pf_data;
-- struct kbase_fault bf_data;
-- struct kbase_mmu_setup current_setup;
--};
--
- /**
- * struct kbase_mmu_table - object representing a set of GPU page tables
- * @mmu_teardown_pages: Buffer of 4 Pages in size, used to cache the entries
-@@ -291,7 +269,11 @@ struct kbase_mmu_table {
- struct kbase_context *kctx;
- };
-
-+#if MALI_USE_CSF
-+#include "csf/mali_kbase_csf_defs.h"
-+#else
- #include "jm/mali_kbase_jm_defs.h"
-+#endif
-
- static inline int kbase_as_has_bus_fault(struct kbase_as *as,
- struct kbase_fault *fault)
-@@ -320,71 +302,115 @@ struct kbasep_mem_device {
- atomic_t ir_threshold;
- };
-
-+struct kbase_clk_rate_listener;
-+
-+/**
-+ * typedef kbase_clk_rate_listener_on_change_t() - Frequency change callback
-+ *
-+ * @listener: Clock frequency change listener.
-+ * @clk_index: Index of the clock for which the change has occurred.
-+ * @clk_rate_hz: Clock frequency(Hz).
-+ *
-+ * A callback to call when clock rate changes. The function must not
-+ * sleep. No clock rate manager functions must be called from here, as
-+ * its lock is taken.
-+ */
-+typedef void
-+kbase_clk_rate_listener_on_change_t(struct kbase_clk_rate_listener *listener,
-+ u32 clk_index, u32 clk_rate_hz);
-+
-+/**
-+ * struct kbase_clk_rate_listener - Clock frequency listener
-+ *
-+ * @node: List node.
-+ * @notify: Callback to be called when GPU frequency changes.
-+ */
-+struct kbase_clk_rate_listener {
-+ struct list_head node;
-+ kbase_clk_rate_listener_on_change_t *notify;
-+};
-+
- /**
-- * Data stored per device for power management.
-+ * struct kbase_clk_rate_trace_manager - Data stored per device for GPU clock
-+ * rate trace manager.
- *
-- * This structure contains data for the power management framework. There is one
-- * instance of this structure per device in the system.
-+ * @gpu_idle: Tracks the idle state of GPU.
-+ * @clks: Array of pointer to structures storing data for every
-+ * enumerated GPU clock.
-+ * @clk_rate_trace_ops: Pointer to the platform specific GPU clock rate trace
-+ * operations.
-+ * @gpu_clk_rate_trace_write: Pointer to the function that would emit the
-+ * tracepoint for the clock rate change.
-+ * @listeners: List of listener attached.
-+ * @lock: Lock to serialize the actions of GPU clock rate trace
-+ * manager.
-+ */
-+struct kbase_clk_rate_trace_manager {
-+ bool gpu_idle;
-+ struct kbase_clk_data *clks[BASE_MAX_NR_CLOCKS_REGULATORS];
-+ struct kbase_clk_rate_trace_op_conf *clk_rate_trace_ops;
-+ struct list_head listeners;
-+ spinlock_t lock;
-+};
-+
-+/**
-+ * struct kbase_pm_device_data - Data stored per device for power management.
-+ * @lock: The lock protecting Power Management structures accessed outside of
-+ * IRQ.
-+ * This lock must also be held whenever the GPU is being powered on or
-+ * off.
-+ * @active_count: The reference count of active contexts on this device. Note
-+ * that some code paths keep shaders/the tiler powered whilst this is 0.
-+ * Use kbase_pm_is_active() instead to check for such cases.
-+ * @suspending: Flag indicating suspending/suspended
-+ * @gpu_lost: Flag indicating gpu lost
-+ * This structure contains data for the power management framework. There
-+ * is one instance of this structure per device in the system.
-+ * @zero_active_count_wait: Wait queue set when active_count == 0
-+ * @resume_wait: system resume of GPU device.
-+ * @debug_core_mask: Bit masks identifying the available shader cores that are
-+ * specified via sysfs. One mask per job slot.
-+ * @debug_core_mask_all: Bit masks identifying the available shader cores that
-+ * are specified via sysfs.
-+ * @callback_power_runtime_init: Callback for initializing the runtime power
-+ * management. Return 0 on success, else error code
-+ * @callback_power_runtime_term: Callback for terminating the runtime power
-+ * management.
-+ * @dvfs_period: Time in milliseconds between each dvfs sample
-+ * @backend: KBase PM backend data
-+ * @arb_vm_state: The state of the arbiter VM machine
-+ * @gpu_users_waiting: Used by virtualization to notify the arbiter that there
-+ * are users waiting for the GPU so that it can request and resume the
-+ * driver.
-+ * @clk_rtm: The state of the GPU clock rate trace manager
- */
- struct kbase_pm_device_data {
-- /**
-- * The lock protecting Power Management structures accessed outside of
-- * IRQ.
-- *
-- * This lock must also be held whenever the GPU is being powered on or
-- * off.
-- */
- struct mutex lock;
--
-- /**
-- * The reference count of active contexts on this device. Note that
-- * some code paths keep shaders/the tiler powered whilst this is 0. Use
-- * kbase_pm_is_active() instead to check for such cases.
-- */
- int active_count;
-- /** Flag indicating suspending/suspended */
- bool suspending;
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
-- /* Flag indicating gpu lost */
-- bool gpu_lost;
-+ atomic_t gpu_lost;
- #endif /* CONFIG_MALI_ARBITER_SUPPORT */
-- /* Wait queue set when active_count == 0 */
- wait_queue_head_t zero_active_count_wait;
-+ wait_queue_head_t resume_wait;
-
-- /**
-- * Bit masks identifying the available shader cores that are specified
-- * via sysfs. One mask per job slot.
-- */
-+#if MALI_USE_CSF
-+ u64 debug_core_mask;
-+#else
-+ /* One mask per job slot. */
- u64 debug_core_mask[BASE_JM_MAX_NR_SLOTS];
- u64 debug_core_mask_all;
-+#endif /* MALI_USE_CSF */
-
-- /**
-- * Callback for initializing the runtime power management.
-- *
-- * @param kbdev The kbase device
-- *
-- * @return 0 on success, else error code
-- */
-- int (*callback_power_runtime_init)(struct kbase_device *kbdev);
--
-- /**
-- * Callback for terminating the runtime power management.
-- *
-- * @param kbdev The kbase device
-- */
-+ int (*callback_power_runtime_init)(struct kbase_device *kbdev);
- void (*callback_power_runtime_term)(struct kbase_device *kbdev);
--
-- /* Time in milliseconds between each dvfs sample */
- u32 dvfs_period;
--
- struct kbase_pm_backend_data backend;
--
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
-- /**
-- * The state of the arbiter VM machine
-- */
- struct kbase_arbiter_vm_state *arb_vm_state;
-+ atomic_t gpu_users_waiting;
- #endif /* CONFIG_MALI_ARBITER_SUPPORT */
-+ struct kbase_clk_rate_trace_manager clk_rtm;
- };
-
- /**
-@@ -524,7 +550,6 @@ struct kbase_mmu_mode {
- unsigned long flags;
- };
-
--struct kbase_mmu_mode const *kbase_mmu_mode_get_lpae(void);
- struct kbase_mmu_mode const *kbase_mmu_mode_get_aarch64(void);
-
- #define DEVNAME_SIZE 16
-@@ -559,6 +584,32 @@ struct kbase_devfreq_queue_info {
- enum kbase_devfreq_work_type acted_type;
- };
-
-+/**
-+ * struct kbase_process - Representing an object of a kbase process instantiated
-+ * when the first kbase context is created under it.
-+ * @tgid: Thread group ID.
-+ * @total_gpu_pages: Total gpu pages allocated across all the contexts
-+ * of this process, it accounts for both native allocations
-+ * and dma_buf imported allocations.
-+ * @kctx_list: List of kbase contexts created for the process.
-+ * @kprcs_node: Node to a rb_tree, kbase_device will maintain a rb_tree
-+ * based on key tgid, kprcs_node is the node link to
-+ * &struct_kbase_device.process_root.
-+ * @dma_buf_root: RB tree of the dma-buf imported allocations, imported
-+ * across all the contexts created for this process.
-+ * Used to ensure that pages of allocation are accounted
-+ * only once for the process, even if the allocation gets
-+ * imported multiple times for the process.
-+ */
-+struct kbase_process {
-+ pid_t tgid;
-+ size_t total_gpu_pages;
-+ struct list_head kctx_list;
-+
-+ struct rb_node kprcs_node;
-+ struct rb_root dma_buf_root;
-+};
-+
- /**
- * struct kbase_device - Object representing an instance of GPU platform device,
- * allocated from the probe method of mali driver.
-@@ -568,8 +619,8 @@ struct kbase_devfreq_queue_info {
- * issues present in the GPU.
- * @hw_quirks_mmu: Configuration to be used for the MMU as per the HW
- * issues present in the GPU.
-- * @hw_quirks_jm: Configuration to be used for the Job Manager as per
-- * the HW issues present in the GPU.
-+ * @hw_quirks_gpu: Configuration to be used for the Job Manager or CSF/MCU
-+ * subsystems as per the HW issues present in the GPU.
- * @entry: Links the device instance to the global list of GPU
- * devices. The list would have as many entries as there
- * are GPU device instances.
-@@ -586,6 +637,8 @@ struct kbase_devfreq_queue_info {
- * @irqs: Array containing IRQ resource info for 3 types of
- * interrupts : Job scheduling, MMU & GPU events (like
- * power management, cache etc.)
-+ * @irqs.irq: irq number
-+ * @irqs.flags: irq flags
- * @clocks: Pointer to the input clock resources referenced by
- * the GPU device node.
- * @nr_clocks: Number of clocks set in the clocks array.
-@@ -619,6 +672,8 @@ struct kbase_devfreq_queue_info {
- * accesses made by the driver.
- * @pm: Per device object for storing data for power management
- * framework.
-+ * @fw_load_lock: Mutex to protect firmware loading in @ref kbase_open.
-+ * @csf: CSF object for the GPU device.
- * @js_data: Per device object encapsulating the current context of
- * Job Scheduler, which is global to the device and is not
- * tied to any particular struct kbase_context running on
-@@ -646,11 +701,21 @@ struct kbase_devfreq_queue_info {
- * @disjoint_event: struct for keeping track of the disjoint information,
- * that whether the GPU is in a disjoint state and the
- * number of disjoint events that have occurred on GPU.
-+ * @disjoint_event.count: disjoint event count
-+ * @disjoint_event.state: disjoint event state
- * @nr_hw_address_spaces: Number of address spaces actually available in the
- * GPU, remains constant after driver initialisation.
- * @nr_user_address_spaces: Number of address spaces available to user contexts
-+ * @hwcnt_backend_csf_if_fw: Firmware interface to access CSF GPU performance
-+ * counters.
- * @hwcnt: Structure used for instrumentation and HW counters
- * dumping
-+ * @hwcnt.lock: The lock should be used when accessing any of the
-+ * following members
-+ * @hwcnt.kctx: kbase context
-+ * @hwcnt.addr: HW counter address
-+ * @hwcnt.addr_bytes: HW counter size in bytes
-+ * @hwcnt.backend: Kbase instrumentation backend
- * @hwcnt_gpu_iface: Backend interface for GPU hardware counter access.
- * @hwcnt_gpu_ctx: Context for GPU hardware counter access.
- * @hwaccess_lock must be held when calling
-@@ -661,6 +726,7 @@ struct kbase_devfreq_queue_info {
- * are enabled. If zero, there is no timeline client and
- * therefore timeline is disabled.
- * @timeline: Timeline context created per device.
-+ * @ktrace: kbase device's ktrace
- * @trace_lock: Lock to serialize the access to trace buffer.
- * @trace_first_out: Index/offset in the trace buffer at which the first
- * unread message is present.
-@@ -686,6 +752,8 @@ struct kbase_devfreq_queue_info {
- * including any contexts that might be created for
- * hardware counters.
- * @kctx_list_lock: Lock protecting concurrent accesses to @kctx_list.
-+ * @group_max_uid_in_devices: Max value of any queue group UID in any kernel
-+ * context in the kbase device.
- * @devfreq_profile: Describes devfreq profile for the Mali GPU device, passed
- * to devfreq_add_device() to add devfreq feature to Mali
- * GPU device.
-@@ -714,6 +782,7 @@ struct kbase_devfreq_queue_info {
- * table in devicetree.
- * @num_opps: Number of operating performance points available for the Mali
- * GPU device.
-+ * @last_devfreq_metrics: last PM metrics
- * @devfreq_queue: Per device object for storing data that manages devfreq
- * suspend & resume request queue and the related items.
- * @devfreq_cooling: Pointer returned on registering devfreq cooling device
-@@ -724,6 +793,17 @@ struct kbase_devfreq_queue_info {
- * previously entered protected mode.
- * @ipa: Top level structure for IPA, containing pointers to both
- * configured & fallback models.
-+ * @ipa.lock: Access to this struct must be with ipa.lock held
-+ * @ipa.configured_model: ipa model to use
-+ * @ipa.fallback_model: ipa fallback model
-+ * @ipa.last_metrics: Values of the PM utilization metrics from last time
-+ * the power model was invoked. The utilization is
-+ * calculated as the difference between last_metrics
-+ * and the current values.
-+ * @ipa.force_fallback_model: true if use of fallback model has been forced by
-+ * the User
-+ * @ipa.last_sample_time: Records the time when counters, used for dynamic
-+ * energy estimation, were last sampled.
- * @previous_frequency: Previous frequency of GPU clock used for
- * BASE_HW_ISSUE_GPU2017_1336 workaround, This clock is
- * restored when L2 is powered on.
-@@ -732,6 +812,7 @@ struct kbase_devfreq_queue_info {
- * @mali_debugfs_directory: Root directory for the debugfs files created by the driver
- * @debugfs_ctx_directory: Directory inside the @mali_debugfs_directory containing
- * a sub-directory for every context.
-+ * @debugfs_instr_directory: Instrumentation debugfs directory
- * @debugfs_as_read_bitmap: bitmap of address spaces for which the bus or page fault
- * has occurred.
- * @job_fault_wq: Waitqueue to block the job fault dumping daemon till the
-@@ -748,6 +829,8 @@ struct kbase_devfreq_queue_info {
- * @job_fault_event_lock: Lock to protect concurrent accesses to @job_fault_event_list
- * @regs_dump_debugfs_data: Contains the offset of register to be read through debugfs
- * file "read_register".
-+ * @regs_dump_debugfs_data.reg_offset: Contains the offset of register to be
-+ * read through debugfs file "read_register".
- * @ctx_num: Total number of contexts created for the device.
- * @io_history: Pointer to an object keeping a track of all recent
- * register accesses. The history of register accesses
-@@ -806,12 +889,40 @@ struct kbase_devfreq_queue_info {
- * Job Scheduler
- * @l2_size_override: Used to set L2 cache size via device tree blob
- * @l2_hash_override: Used to set L2 cache hash via device tree blob
-+ * @l2_hash_values_override: true if @l2_hash_values is valid.
-+ * @l2_hash_values: Used to set L2 asn_hash via device tree blob
-+ * @process_root: rb_tree root node for maintaining a rb_tree of
-+ * kbase_process based on key tgid(thread group ID).
-+ * @dma_buf_root: rb_tree root node for maintaining a rb_tree of
-+ * &struct kbase_dma_buf based on key dma_buf.
-+ * We maintain a rb_tree of dma_buf mappings under
-+ * kbase_device and kbase_process, one indicates a
-+ * mapping and gpu memory usage at device level and
-+ * other one at process level.
-+ * @total_gpu_pages: Total GPU pages used for the complete GPU device.
-+ * @dma_buf_lock: This mutex should be held while accounting for
-+ * @total_gpu_pages from imported dma buffers.
-+ * @gpu_mem_usage_lock: This spinlock should be held while accounting
-+ * @total_gpu_pages for both native and dma-buf imported
-+ * allocations.
-+ * @dummy_job_wa: struct for dummy job execution workaround for the
-+ * GPU hang issue
-+ * @dummy_job_wa.ctx: dummy job workaround context
-+ * @dummy_job_wa.jc: dummy job workaround job
-+ * @dummy_job_wa.slot: dummy job workaround slot
-+ * @dummy_job_wa.flags: dummy job workaround flags
-+ * @dummy_job_wa_loaded: Flag for indicating that the workaround blob has
-+ * been loaded. Protected by @fw_load_lock.
-+ * @arb: Pointer to the arbiter device
-+ * @pcm_dev: The priority control manager device.
-+ * @oom_notifier_block: notifier_block containing kernel-registered out-of-
-+ * memory handler.
- */
- struct kbase_device {
- u32 hw_quirks_sc;
- u32 hw_quirks_tiler;
- u32 hw_quirks_mmu;
-- u32 hw_quirks_jm;
-+ u32 hw_quirks_gpu;
-
- struct list_head entry;
- struct device *dev;
-@@ -827,7 +938,7 @@ struct kbase_device {
-
- struct clk *clocks[BASE_MAX_NR_CLOCKS_REGULATORS];
- unsigned int nr_clocks;
--#ifdef CONFIG_REGULATOR
-+#if IS_ENABLED(CONFIG_REGULATOR)
- struct regulator *regulators[BASE_MAX_NR_CLOCKS_REGULATORS];
- unsigned int nr_regulators;
- #if (KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE)
-@@ -837,16 +948,6 @@ struct kbase_device {
- char devname[DEVNAME_SIZE];
- u32 id;
-
--#ifdef CONFIG_MALI_NO_MALI
-- void *model;
-- struct kmem_cache *irq_slab;
-- struct workqueue_struct *irq_workq;
-- atomic_t serving_job_irq;
-- atomic_t serving_gpu_irq;
-- atomic_t serving_mmu_irq;
-- spinlock_t reg_op_lock;
--#endif /* CONFIG_MALI_NO_MALI */
--
- struct kbase_pm_device_data pm;
-
- struct kbase_mem_pool_group mem_pools;
-@@ -874,8 +975,10 @@ struct kbase_device {
- s8 nr_hw_address_spaces;
- s8 nr_user_address_spaces;
-
-+#if MALI_USE_CSF
-+ struct kbase_hwcnt_backend_csf_if hwcnt_backend_csf_if_fw;
-+#else
- struct kbase_hwcnt {
-- /* The lock should be used when accessing any of the following members */
- spinlock_t lock;
-
- struct kbase_context *kctx;
-@@ -884,6 +987,7 @@ struct kbase_device {
-
- struct kbase_instr_backend backend;
- } hwcnt;
-+#endif
-
- struct kbase_hwcnt_backend_interface hwcnt_gpu_iface;
- struct kbase_hwcnt_context *hwcnt_gpu_ctx;
-@@ -906,6 +1010,7 @@ struct kbase_device {
-
- struct list_head kctx_list;
- struct mutex kctx_list_lock;
-+ atomic_t group_max_uid_in_devices;
-
- #ifdef CONFIG_MALI_DEVFREQ
- struct devfreq_dev_profile devfreq_profile;
-@@ -917,17 +1022,10 @@ struct kbase_device {
- struct kbase_devfreq_opp *devfreq_table;
- int num_opps;
- struct kbasep_pm_metrics last_devfreq_metrics;
--
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
- struct kbase_devfreq_queue_info devfreq_queue;
--#endif
-
--#ifdef CONFIG_DEVFREQ_THERMAL
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
-- struct devfreq_cooling_device *devfreq_cooling;
--#else
-+#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL)
- struct thermal_cooling_device *devfreq_cooling;
--#endif
- bool ipa_protection_mode_switched;
- struct {
- /* Access to this struct must be with ipa.lock held */
-@@ -940,11 +1038,13 @@ struct kbase_device {
- * the difference between last_metrics and the current values.
- */
- struct kbasep_pm_metrics last_metrics;
-- /* Model data to pass to ipa_gpu_active/idle() */
-- struct kbase_ipa_model_vinstr_data *model_data;
-
- /* true if use of fallback model has been forced by the User */
- bool force_fallback_model;
-+ /* Records the time when counters, used for dynamic energy
-+ * estimation, were last sampled.
-+ */
-+ ktime_t last_sample_time;
- } ipa;
- #endif /* CONFIG_DEVFREQ_THERMAL */
- #endif /* CONFIG_MALI_DEVFREQ */
-@@ -952,9 +1052,10 @@ struct kbase_device {
-
- atomic_t job_fault_debug;
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- struct dentry *mali_debugfs_directory;
- struct dentry *debugfs_ctx_directory;
-+ struct dentry *debugfs_instr_directory;
-
- #ifdef CONFIG_MALI_DEBUG
- u64 debugfs_as_read_bitmap;
-@@ -968,14 +1069,14 @@ struct kbase_device {
-
- #if !MALI_CUSTOMER_RELEASE
- struct {
-- u16 reg_offset;
-+ u32 reg_offset;
- } regs_dump_debugfs_data;
- #endif /* !MALI_CUSTOMER_RELEASE */
- #endif /* CONFIG_DEBUG_FS */
-
- atomic_t ctx_num;
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- struct kbase_io_history io_history;
- #endif /* CONFIG_DEBUG_FS */
-
-@@ -985,8 +1086,7 @@ struct kbase_device {
-
- bool poweroff_pending;
-
--
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
-+#if (KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE)
- bool infinite_cache_active_default;
- #else
- u32 infinite_cache_active_default;
-@@ -1015,9 +1115,6 @@ struct kbase_device {
-
- struct work_struct protected_mode_hwcnt_disable_work;
-
--#ifdef CONFIG_MALI_BUSLOG
-- struct bus_logger_client *buslogger;
--#endif
-
- bool irq_reset_flush;
-
-@@ -1029,7 +1126,14 @@ struct kbase_device {
-
- u8 l2_size_override;
- u8 l2_hash_override;
-+ bool l2_hash_values_override;
-+ u32 l2_hash_values[ASN_HASH_COUNT];
-
-+ struct mutex fw_load_lock;
-+#if MALI_USE_CSF
-+ /* CSF object for the GPU device. */
-+ struct kbase_csf_device csf;
-+#else
- struct kbasep_js_device_data js_data;
-
- /* See KBASE_JS_*_PRIORITY_MODE for details. */
-@@ -1042,6 +1146,14 @@ struct kbase_device {
- u8 backup_serialize_jobs;
- #endif /* CONFIG_MALI_CINSTR_GWT */
-
-+#endif /* MALI_USE_CSF */
-+
-+ struct rb_root process_root;
-+ struct rb_root dma_buf_root;
-+
-+ size_t total_gpu_pages;
-+ struct mutex dma_buf_lock;
-+ spinlock_t gpu_mem_usage_lock;
-
- struct {
- struct kbase_context *ctx;
-@@ -1049,16 +1161,16 @@ struct kbase_device {
- int slot;
- u64 flags;
- } dummy_job_wa;
-+ bool dummy_job_wa_loaded;
-
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
-- /* Pointer to the arbiter device */
- struct kbase_arbiter_device arb;
- #endif
--};
-+ /* Priority Control Manager device */
-+ struct priority_control_manager_device *pcm_dev;
-
--#define KBASE_API_VERSION(major, minor) ((((major) & 0xFFF) << 20) | \
-- (((minor) & 0xFFF) << 8) | \
-- ((0 & 0xFF) << 0))
-+ struct notifier_block oom_notifier_block;
-+};
-
- /**
- * enum kbase_file_state - Initialization state of a file opened by @kbase_open
-@@ -1109,7 +1221,92 @@ struct kbase_file {
- unsigned long api_version;
- atomic_t setup_state;
- };
--
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+/**
-+ * enum kbase_context_flags - Flags for kbase contexts
-+ *
-+ * @KCTX_COMPAT: Set when the context process is a compat process, 32-bit
-+ * process on a 64-bit kernel.
-+ *
-+ * @KCTX_RUNNABLE_REF: Set when context is counted in
-+ * kbdev->js_data.nr_contexts_runnable. Must hold queue_mutex when accessing.
-+ *
-+ * @KCTX_ACTIVE: Set when the context is active.
-+ *
-+ * @KCTX_PULLED: Set when last kick() caused atoms to be pulled from this
-+ * context.
-+ *
-+ * @KCTX_MEM_PROFILE_INITIALIZED: Set when the context's memory profile has been
-+ * initialized.
-+ *
-+ * @KCTX_INFINITE_CACHE: Set when infinite cache is to be enabled for new
-+ * allocations. Existing allocations will not change.
-+ *
-+ * @KCTX_SUBMIT_DISABLED: Set to prevent context from submitting any jobs.
-+ *
-+ * @KCTX_PRIVILEGED:Set if the context uses an address space and should be kept
-+ * scheduled in.
-+ *
-+ * @KCTX_SCHEDULED: Set when the context is scheduled on the Run Pool.
-+ * This is only ever updated whilst the jsctx_mutex is held.
-+ *
-+ * @KCTX_DYING: Set when the context process is in the process of being evicted.
-+ *
-+ * @KCTX_NO_IMPLICIT_SYNC: Set when explicit Android fences are in use on this
-+ * context, to disable use of implicit dma-buf fences. This is used to avoid
-+ * potential synchronization deadlocks.
-+ *
-+ * @KCTX_FORCE_SAME_VA: Set when BASE_MEM_SAME_VA should be forced on memory
-+ * allocations. For 64-bit clients it is enabled by default, and disabled by
-+ * default on 32-bit clients. Being able to clear this flag is only used for
-+ * testing purposes of the custom zone allocation on 64-bit user-space builds,
-+ * where we also require more control than is available through e.g. the JIT
-+ * allocation mechanism. However, the 64-bit user-space client must still
-+ * reserve a JIT region using KBASE_IOCTL_MEM_JIT_INIT
-+ *
-+ * @KCTX_PULLED_SINCE_ACTIVE_JS0: Set when the context has had an atom pulled
-+ * from it for job slot 0. This is reset when the context first goes active or
-+ * is re-activated on that slot.
-+ *
-+ * @KCTX_PULLED_SINCE_ACTIVE_JS1: Set when the context has had an atom pulled
-+ * from it for job slot 1. This is reset when the context first goes active or
-+ * is re-activated on that slot.
-+ *
-+ * @KCTX_PULLED_SINCE_ACTIVE_JS2: Set when the context has had an atom pulled
-+ * from it for job slot 2. This is reset when the context first goes active or
-+ * is re-activated on that slot.
-+ *
-+ * @KCTX_AS_DISABLED_ON_FAULT: Set when the GPU address space is disabled for
-+ * the context due to unhandled page(or bus) fault. It is cleared when the
-+ * refcount for the context drops to 0 or on when the address spaces are
-+ * re-enabled on GPU reset or power cycle.
-+ *
-+ * @KCTX_JPL_ENABLED: Set when JIT physical page limit is less than JIT virtual
-+ * address page limit, so we must take care to not exceed the physical limit
-+ *
-+ * All members need to be separate bits. This enum is intended for use in a
-+ * bitmask where multiple values get OR-ed together.
-+ */
-+enum kbase_context_flags {
-+ KCTX_COMPAT = 1U << 0,
-+ KCTX_RUNNABLE_REF = 1U << 1,
-+ KCTX_ACTIVE = 1U << 2,
-+ KCTX_PULLED = 1U << 3,
-+ KCTX_MEM_PROFILE_INITIALIZED = 1U << 4,
-+ KCTX_INFINITE_CACHE = 1U << 5,
-+ KCTX_SUBMIT_DISABLED = 1U << 6,
-+ KCTX_PRIVILEGED = 1U << 7,
-+ KCTX_SCHEDULED = 1U << 8,
-+ KCTX_DYING = 1U << 9,
-+ KCTX_NO_IMPLICIT_SYNC = 1U << 10,
-+ KCTX_FORCE_SAME_VA = 1U << 11,
-+ KCTX_PULLED_SINCE_ACTIVE_JS0 = 1U << 12,
-+ KCTX_PULLED_SINCE_ACTIVE_JS1 = 1U << 13,
-+ KCTX_PULLED_SINCE_ACTIVE_JS2 = 1U << 14,
-+ KCTX_AS_DISABLED_ON_FAULT = 1U << 15,
-+ KCTX_JPL_ENABLED = 1U << 16,
-+};
-+#else
- /**
- * enum kbase_context_flags - Flags for kbase contexts
- *
-@@ -1190,6 +1387,7 @@ enum kbase_context_flags {
- KCTX_PULLED_SINCE_ACTIVE_JS2 = 1U << 14,
- KCTX_AS_DISABLED_ON_FAULT = 1U << 15,
- };
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- struct kbase_sub_alloc {
- struct list_head link;
-@@ -1197,6 +1395,21 @@ struct kbase_sub_alloc {
- DECLARE_BITMAP(sub_pages, SZ_2M / SZ_4K);
- };
-
-+/**
-+ * struct kbase_reg_zone - Information about GPU memory region zones
-+ * @base_pfn: Page Frame Number in GPU virtual address space for the start of
-+ * the Zone
-+ * @va_size_pages: Size of the Zone in pages
-+ *
-+ * Track information about a zone KBASE_REG_ZONE() and related macros.
-+ * In future, this could also store the &rb_root that are currently in
-+ * &kbase_context
-+ */
-+struct kbase_reg_zone {
-+ u64 base_pfn;
-+ u64 va_size_pages;
-+};
-+
- /**
- * struct kbase_context - Kernel base context
- *
-@@ -1247,6 +1460,7 @@ struct kbase_sub_alloc {
- * @reg_rbtree_exec: RB tree of the memory regions allocated from the EXEC_VA
- * zone of the GPU virtual address space. Used for GPU-executable
- * allocations which don't need the SAME_VA property.
-+ * @reg_zone: Zone information for the reg_rbtree_<...> members.
- * @cookies: Bitmask containing of BITS_PER_LONG bits, used mainly for
- * SAME_VA allocations to defer the reservation of memory region
- * (from the GPU virtual address space) from base_mem_alloc
-@@ -1271,6 +1485,7 @@ struct kbase_sub_alloc {
- * which actually created the context. This is usually,
- * but not necessarily, the same as the thread which
- * opened the device file /dev/malixx instance.
-+ * @csf: kbase csf context
- * @jctx: object encapsulating all the Job dispatcher related state,
- * including the array of atoms.
- * @used_pages: Keeps a track of the number of 4KB physical pages in use
-@@ -1287,6 +1502,8 @@ struct kbase_sub_alloc {
- * evictable/reclaimable.
- * @evict_list: List head for the list containing the allocations which
- * can be evicted or freed up in the shrinker callback.
-+ * @evict_nents: Total number of pages allocated by the allocations within
-+ * @evict_list (atomic).
- * @waiting_soft_jobs: List head for the list containing softjob atoms, which
- * are either waiting for the event set operation, or waiting
- * for the signaling of input fence or waiting for the GPU
-@@ -1297,6 +1514,8 @@ struct kbase_sub_alloc {
- * waiting atoms and the waitqueue to process the work item
- * queued for the atoms blocked on the signaling of dma-buf
- * fences.
-+ * @dma_fence.waiting_resource: list head for the list of dma-buf fence
-+ * @dma_fence.wq: waitqueue to process the work item queued
- * @as_nr: id of the address space being used for the scheduled in
- * context. This is effectively part of the Run Pool, because
- * it only has a valid setting (!=KBASEP_AS_NR_INVALID) whilst
-@@ -1315,15 +1534,13 @@ struct kbase_sub_alloc {
- * at any point.
- * Generally the reference count is incremented when the context
- * is scheduled in and an atom is pulled from the context's per
-- * slot runnable tree.
-+ * slot runnable tree in JM GPU or GPU command queue
-+ * group is programmed on CSG slot in CSF GPU.
- * @mm_update_lock: lock used for handling of special tracking page.
- * @process_mm: Pointer to the memory descriptor of the process which
- * created the context. Used for accounting the physical
- * pages used for GPU allocations, done for the context,
- * to the memory consumed by the process.
-- * @same_va_end: End address of the SAME_VA zone (in 4KB page units)
-- * @exec_va_start: Start address of the EXEC_VA zone (in 4KB page units)
-- * or U64_MAX if the EXEC_VA zone is uninitialized.
- * @gpu_va_end: End address of the GPU va space (in 4KB page units)
- * @jit_va: Indicates if a JIT_VA zone has been created.
- * @mem_profile_data: Buffer containing the profiling information provided by
-@@ -1399,6 +1616,16 @@ struct kbase_sub_alloc {
- * that were used (i.e. the
- * &struct_kbase_va_region.used_pages for regions
- * that have had a usage report).
-+ * @jit_phys_pages_to_be_allocated: Count of the physical pages that are being
-+ * now allocated for just-in-time memory
-+ * allocations of a context (across all the
-+ * threads). This is supposed to be updated
-+ * with @reg_lock held before allocating
-+ * the backing pages. This helps ensure that
-+ * total physical memory usage for just in
-+ * time memory allocation remains within the
-+ * @jit_phys_pages_limit in multi-threaded
-+ * scenarios.
- * @jit_active_head: List containing the just-in-time memory allocations
- * which are in use.
- * @jit_pool_head: List containing the just-in-time memory allocations
-@@ -1425,6 +1652,10 @@ struct kbase_sub_alloc {
- * is used to determine the atom's age when it is added to
- * the runnable RB-tree.
- * @trim_level: Level of JIT allocation trimming to perform on free (0-100%)
-+ * @kprcs: Reference to @struct kbase_process that the current
-+ * kbase_context belongs to.
-+ * @kprcs_link: List link for the list of kbase context maintained
-+ * under kbase_process.
- * @gwt_enabled: Indicates if tracking of GPU writes is enabled, protected by
- * kbase_context.reg_lock.
- * @gwt_was_enabled: Simple sticky bit flag to know if GWT was ever enabled.
-@@ -1435,6 +1666,12 @@ struct kbase_sub_alloc {
- * for context scheduling, protected by hwaccess_lock.
- * @atoms_count: Number of GPU atoms currently in use, per priority
- * @create_flags: Flags used in context creation.
-+ * @kinstr_jm: Kernel job manager instrumentation context handle
-+ * @tl_kctx_list_node: List item into the device timeline's list of
-+ * contexts, for timeline summarization.
-+ * @limited_core_mask: The mask that is applied to the affinity in case of atoms
-+ * marked with BASE_JD_REQ_LIMITED_CORE_MASK.
-+ * @platform_data: Pointer to platform specific per-context data.
- *
- * A kernel base context is an entity among which the GPU is scheduled.
- * Each context has its own GPU address space.
-@@ -1453,7 +1690,9 @@ struct kbase_context {
- struct list_head event_list;
- struct list_head event_coalesce_list;
- struct mutex event_mutex;
-+#if !MALI_USE_CSF
- atomic_t event_closed;
-+#endif
- struct workqueue_struct *event_workq;
- atomic_t event_count;
- int event_coalesce_count;
-@@ -1470,7 +1709,11 @@ struct kbase_context {
- struct rb_root reg_rbtree_same;
- struct rb_root reg_rbtree_custom;
- struct rb_root reg_rbtree_exec;
-+ struct kbase_reg_zone reg_zone[KBASE_REG_ZONE_MAX];
-
-+#if MALI_USE_CSF
-+ struct kbase_csf_context csf;
-+#else
- struct kbase_jd_context jctx;
- struct jsctx_queue jsctx_queue
- [KBASE_JS_ATOM_SCHED_PRIO_COUNT][BASE_JM_MAX_NR_SLOTS];
-@@ -1488,6 +1731,7 @@ struct kbase_context {
- s16 atoms_count[KBASE_JS_ATOM_SCHED_PRIO_COUNT];
- u32 slots_pullable;
- u32 age_count;
-+#endif /* MALI_USE_CSF */
-
- DECLARE_BITMAP(cookies, BITS_PER_LONG);
- struct kbase_va_region *pending_regions[BITS_PER_LONG];
-@@ -1503,6 +1747,7 @@ struct kbase_context {
-
- struct shrinker reclaim;
- struct list_head evict_list;
-+ atomic_t evict_nents;
-
- struct list_head waiting_soft_jobs;
- spinlock_t waiting_soft_jobs_lock;
-@@ -1519,12 +1764,10 @@ struct kbase_context {
-
- spinlock_t mm_update_lock;
- struct mm_struct __rcu *process_mm;
-- u64 same_va_end;
-- u64 exec_va_start;
- u64 gpu_va_end;
- bool jit_va;
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- char *mem_profile_data;
- size_t mem_profile_size;
- struct mutex mem_profile_lock;
-@@ -1545,10 +1788,11 @@ struct kbase_context {
- u8 jit_current_allocations_per_bin[256];
- u8 jit_version;
- u8 jit_group_id;
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- u64 jit_phys_pages_limit;
- u64 jit_current_phys_pressure;
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+ u64 jit_phys_pages_to_be_allocated;
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
- struct list_head jit_active_head;
- struct list_head jit_pool_head;
- struct list_head jit_destroy_head;
-@@ -1559,6 +1803,9 @@ struct kbase_context {
-
- u8 trim_level;
-
-+ struct kbase_process *kprcs;
-+ struct list_head kprcs_link;
-+
- #ifdef CONFIG_MALI_CINSTR_GWT
- bool gwt_enabled;
- bool gwt_was_enabled;
-@@ -1567,6 +1814,17 @@ struct kbase_context {
- #endif
-
- base_context_create_flags create_flags;
-+
-+#if !MALI_USE_CSF
-+ struct kbase_kinstr_jm *kinstr_jm;
-+#endif
-+ struct list_head tl_kctx_list_node;
-+
-+ u64 limited_core_mask;
-+
-+#if !MALI_USE_CSF
-+ void *platform_data;
-+#endif
- };
-
- #ifdef CONFIG_MALI_CINSTR_GWT
-@@ -1653,29 +1911,4 @@ static inline bool kbase_device_is_cpu_coherent(struct kbase_device *kbdev)
- /* Maximum number of loops polling the GPU for an AS command to complete before we assume the GPU has hung */
- #define KBASE_AS_INACTIVE_MAX_LOOPS 100000000
-
--/* JobDescriptorHeader - taken from the architecture specifications, the layout
-- * is currently identical for all GPU archs. */
--struct job_descriptor_header {
-- u32 exception_status;
-- u32 first_incomplete_task;
-- u64 fault_pointer;
-- u8 job_descriptor_size : 1;
-- u8 job_type : 7;
-- u8 job_barrier : 1;
-- u8 _reserved_01 : 1;
-- u8 _reserved_1 : 1;
-- u8 _reserved_02 : 1;
-- u8 _reserved_03 : 1;
-- u8 _reserved_2 : 1;
-- u8 _reserved_04 : 1;
-- u8 _reserved_05 : 1;
-- u16 job_index;
-- u16 job_dependency_index_1;
-- u16 job_dependency_index_2;
-- union {
-- u64 _64;
-- u32 _32;
-- } next_job;
--};
--
- #endif /* _KBASE_DEFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c
-index b5ac414..7d6e475 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_disjoint_events.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dma_fence.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dma_fence.c
-index 25acbcb..69ff8cc 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dma_fence.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dma_fence.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2017,2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2016, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,26 +17,21 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /* Include mali_kbase_dma_fence.h before checking for CONFIG_MALI_DMA_FENCE as
- * it will be set there.
- */
- #include "mali_kbase_dma_fence.h"
--
- #include <linux/atomic.h>
- #include <linux/list.h>
- #include <linux/lockdep.h>
- #include <linux/mutex.h>
--#include <linux/reservation.h>
-+#include <linux/version.h>
- #include <linux/slab.h>
- #include <linux/spinlock.h>
- #include <linux/workqueue.h>
- #include <linux/ww_mutex.h>
--
- #include <mali_kbase.h>
-
- static void
-@@ -59,7 +55,11 @@ static int
- kbase_dma_fence_lock_reservations(struct kbase_dma_fence_resv_info *info,
- struct ww_acquire_ctx *ctx)
- {
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- struct reservation_object *content_res = NULL;
-+#else
-+ struct dma_resv *content_res = NULL;
-+#endif
- unsigned int content_res_idx = 0;
- unsigned int r;
- int err = 0;
-@@ -205,7 +205,7 @@ out:
- }
-
- static void
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- kbase_dma_fence_cb(struct fence *fence, struct fence_cb *cb)
- #else
- kbase_dma_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
-@@ -225,12 +225,19 @@ kbase_dma_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
- kbase_dma_fence_queue_work(katom);
- }
-
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- static int
- kbase_dma_fence_add_reservation_callback(struct kbase_jd_atom *katom,
- struct reservation_object *resv,
- bool exclusive)
-+#else
-+static int
-+kbase_dma_fence_add_reservation_callback(struct kbase_jd_atom *katom,
-+ struct dma_resv *resv,
-+ bool exclusive)
-+#endif
- {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *excl_fence = NULL;
- struct fence **shared_fences = NULL;
- #else
-@@ -240,7 +247,12 @@ kbase_dma_fence_add_reservation_callback(struct kbase_jd_atom *katom,
- unsigned int shared_count = 0;
- int err, i;
-
-- err = reservation_object_get_fences_rcu(resv,
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
-+ err = reservation_object_get_fences_rcu(
-+#else
-+ err = dma_resv_get_fences_rcu(
-+#endif
-+ resv,
- &excl_fence,
- &shared_count,
- &shared_fences);
-@@ -294,9 +306,15 @@ out:
- return err;
- }
-
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- void kbase_dma_fence_add_reservation(struct reservation_object *resv,
- struct kbase_dma_fence_resv_info *info,
- bool exclusive)
-+#else
-+void kbase_dma_fence_add_reservation(struct dma_resv *resv,
-+ struct kbase_dma_fence_resv_info *info,
-+ bool exclusive)
-+#endif
- {
- unsigned int i;
-
-@@ -317,7 +335,7 @@ int kbase_dma_fence_wait(struct kbase_jd_atom *katom,
- struct kbase_dma_fence_resv_info *info)
- {
- int err, i;
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence;
- #else
- struct dma_fence *fence;
-@@ -346,10 +364,17 @@ int kbase_dma_fence_wait(struct kbase_jd_atom *katom,
- }
-
- for (i = 0; i < info->dma_fence_resv_count; i++) {
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- struct reservation_object *obj = info->resv_objs[i];
--
-+#else
-+ struct dma_resv *obj = info->resv_objs[i];
-+#endif
- if (!test_bit(i, info->dma_fence_excl_bitmap)) {
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- err = reservation_object_reserve_shared(obj);
-+#else
-+ err = dma_resv_reserve_shared(obj, 0);
-+#endif
- if (err) {
- dev_err(katom->kctx->kbdev->dev,
- "Error %d reserving space for shared fence.\n", err);
-@@ -363,7 +388,11 @@ int kbase_dma_fence_wait(struct kbase_jd_atom *katom,
- goto end;
- }
-
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- reservation_object_add_shared_fence(obj, fence);
-+#else
-+ dma_resv_add_shared_fence(obj, fence);
-+#endif
- } else {
- err = kbase_dma_fence_add_reservation_callback(katom, obj, true);
- if (err) {
-@@ -372,7 +401,11 @@ int kbase_dma_fence_wait(struct kbase_jd_atom *katom,
- goto end;
- }
-
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- reservation_object_add_excl_fence(obj, fence);
-+#else
-+ dma_resv_add_excl_fence(obj, fence);
-+#endif
- }
- }
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dma_fence.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dma_fence.h
-index 2a4d6fc..38d3581 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dma_fence.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dma_fence.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2016, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_DMA_FENCE_H_
-@@ -26,10 +25,14 @@
- #ifdef CONFIG_MALI_DMA_FENCE
-
- #include <linux/list.h>
-+#include <linux/version.h>
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- #include <linux/reservation.h>
-+#else
-+#include <linux/dma-resv.h>
-+#endif
- #include <mali_kbase_fence.h>
-
--
- /* Forward declaration from mali_kbase_defs.h */
- struct kbase_jd_atom;
- struct kbase_context;
-@@ -45,7 +48,11 @@ struct kbase_context;
- * reservation objects.
- */
- struct kbase_dma_fence_resv_info {
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- struct reservation_object **resv_objs;
-+#else
-+ struct dma_resv **resv_objs;
-+#endif
- unsigned int dma_fence_resv_count;
- unsigned long *dma_fence_excl_bitmap;
- };
-@@ -60,9 +67,15 @@ struct kbase_dma_fence_resv_info {
- * reservation_objects. At the same time keeps track of which objects require
- * exclusive access in dma_fence_excl_bitmap.
- */
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- void kbase_dma_fence_add_reservation(struct reservation_object *resv,
- struct kbase_dma_fence_resv_info *info,
- bool exclusive);
-+#else
-+void kbase_dma_fence_add_reservation(struct dma_resv *resv,
-+ struct kbase_dma_fence_resv_info *info,
-+ bool exclusive);
-+#endif
-
- /**
- * kbase_dma_fence_wait() - Creates a new fence and attaches it to the resv_objs
-@@ -122,8 +135,7 @@ void kbase_dma_fence_term(struct kbase_context *kctx);
- */
- int kbase_dma_fence_init(struct kbase_context *kctx);
-
--
--#else /* CONFIG_MALI_DMA_FENCE */
-+#else /* !CONFIG_MALI_DMA_FENCE */
- /* Dummy functions for when dma-buf fence isn't enabled. */
-
- static inline int kbase_dma_fence_init(struct kbase_context *kctx)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dummy_job_wa.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dummy_job_wa.c
-index 188e53b..1e91ba0 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dummy_job_wa.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dummy_job_wa.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -25,7 +24,7 @@
- */
-
- #include <mali_kbase.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include <mali_kbase_dummy_job_wa.h>
-
- #include <linux/firmware.h>
-@@ -282,6 +281,8 @@ int kbase_dummy_job_wa_load(struct kbase_device *kbdev)
- int err;
- struct kbase_context *kctx;
-
-+ lockdep_assert_held(&kbdev->fw_load_lock);
-+
- if (!wa_blob_load_needed(kbdev))
- return 0;
-
-@@ -427,6 +428,10 @@ void kbase_dummy_job_wa_cleanup(struct kbase_device *kbdev)
- {
- struct kbase_context *wa_ctx;
-
-+ /* return if the dummy job has not been loaded */
-+ if (kbdev->dummy_job_wa_loaded == false)
-+ return;
-+
- /* Can be safely called even if the file wasn't created on probe */
- sysfs_remove_file(&kbdev->dev->kobj, &dev_attr_dummy_job_wa_info.attr);
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dummy_job_wa.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dummy_job_wa.h
-index 5bbe37d..8713ba1 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dummy_job_wa.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dummy_job_wa.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_DUMMY_JOB_WORKAROUND_
-@@ -31,6 +30,34 @@
- KBASE_DUMMY_JOB_WA_FLAG_WAIT_POWERUP | \
- KBASE_DUMMY_JOB_WA_FLAG_LOGICAL_SHADER_POWER)
-
-+#if MALI_USE_CSF
-+
-+static inline int kbase_dummy_job_wa_load(struct kbase_device *kbdev)
-+{
-+ CSTD_UNUSED(kbdev);
-+ return 0;
-+}
-+
-+static inline void kbase_dummy_job_wa_cleanup(struct kbase_device *kbdev)
-+{
-+ CSTD_UNUSED(kbdev);
-+}
-+
-+static inline int kbase_dummy_job_wa_execute(struct kbase_device *kbdev,
-+ u64 cores)
-+{
-+ CSTD_UNUSED(kbdev);
-+ CSTD_UNUSED(cores);
-+ return 0;
-+}
-+
-+static inline bool kbase_dummy_job_wa_enabled(struct kbase_device *kbdev)
-+{
-+ CSTD_UNUSED(kbdev);
-+ return false;
-+}
-+
-+#else
-
- int kbase_dummy_job_wa_load(struct kbase_device *kbdev);
- void kbase_dummy_job_wa_cleanup(struct kbase_device *kbdev);
-@@ -41,5 +68,6 @@ static inline bool kbase_dummy_job_wa_enabled(struct kbase_device *kbdev)
- return (kbdev->dummy_job_wa.ctx != NULL);
- }
-
-+#endif /* MALI_USE_CSF */
-
- #endif /* _KBASE_DUMMY_JOB_WORKAROUND_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dvfs_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dvfs_debugfs.c
-new file mode 100644
-index 0000000..1e584de
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dvfs_debugfs.c
-@@ -0,0 +1,98 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_dvfs_debugfs.h"
-+#include <mali_kbase.h>
-+#include <linux/seq_file.h>
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+
-+/**
-+ * kbasep_dvfs_utilization_debugfs_show() - Print the DVFS utilization info
-+ *
-+ * @file: The seq_file for printing to
-+ * @data: The debugfs dentry private data, a pointer to kbase_context
-+ *
-+ * Return: Negative error code or 0 on success.
-+ */
-+static int kbasep_dvfs_utilization_debugfs_show(struct seq_file *file, void *data)
-+{
-+ struct kbase_device *kbdev = file->private;
-+
-+#if MALI_USE_CSF
-+ seq_printf(file, "busy_time: %u idle_time: %u protm_time: %u\n",
-+ kbdev->pm.backend.metrics.values.time_busy,
-+ kbdev->pm.backend.metrics.values.time_idle,
-+ kbdev->pm.backend.metrics.values.time_in_protm);
-+#else
-+ seq_printf(file, "busy_time: %u idle_time: %u\n",
-+ kbdev->pm.backend.metrics.values.time_busy,
-+ kbdev->pm.backend.metrics.values.time_idle);
-+#endif
-+
-+ return 0;
-+}
-+
-+static int kbasep_dvfs_utilization_debugfs_open(struct inode *in,
-+ struct file *file)
-+{
-+ return single_open(file, kbasep_dvfs_utilization_debugfs_show,
-+ in->i_private);
-+}
-+
-+static const struct file_operations kbasep_dvfs_utilization_debugfs_fops = {
-+ .open = kbasep_dvfs_utilization_debugfs_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+void kbase_dvfs_status_debugfs_init(struct kbase_device *kbdev)
-+{
-+ struct dentry *file;
-+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
-+ const mode_t mode = 0444;
-+#else
-+ const mode_t mode = 0400;
-+#endif
-+
-+ if (WARN_ON(!kbdev || IS_ERR_OR_NULL(kbdev->mali_debugfs_directory)))
-+ return;
-+
-+ file = debugfs_create_file("dvfs_utilization", mode,
-+ kbdev->mali_debugfs_directory, kbdev,
-+ &kbasep_dvfs_utilization_debugfs_fops);
-+
-+ if (IS_ERR_OR_NULL(file)) {
-+ dev_warn(kbdev->dev,
-+ "Unable to create dvfs debugfs entry");
-+ }
-+}
-+
-+#else
-+/*
-+ * Stub functions for when debugfs is disabled
-+ */
-+void kbase_dvfs_status_debugfs_init(struct kbase_device *kbdev)
-+{
-+}
-+
-+#endif /* CONFIG_DEBUG_FS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dvfs_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dvfs_debugfs.h
-new file mode 100644
-index 0000000..8334db7
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_dvfs_debugfs.h
-@@ -0,0 +1,35 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_DVFS_DEBUGFS_H_
-+#define _KBASE_DVFS_DEBUGFS_H_
-+
-+/* Forward declaration */
-+struct kbase_device;
-+
-+/**
-+ * kbase_dvfs_status_debugfs_init() - Create a debugfs entry for DVFS queries
-+ *
-+ * @kbdev: Pointer to the GPU device for which to create the debugfs entry
-+ */
-+void kbase_dvfs_status_debugfs_init(struct kbase_device *kbdev);
-+
-+#endif /* _KBASE_DVFS_DEBUGFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_event.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_event.c
-index c8b8f22..910c511 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_event.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_event.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2016,2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #include <mali_kbase.h>
- #include <mali_kbase_debug.h>
- #include <tl/mali_kbase_tracepoints.h>
-@@ -45,7 +42,7 @@ static struct base_jd_udata kbase_event_process(struct kbase_context *kctx, stru
- KBASE_TLSTREAM_TL_DEL_ATOM(kbdev, katom);
-
- katom->status = KBASE_JD_ATOM_STATE_UNUSED;
-- dev_dbg(kbdev->dev, "Atom %p status to unused\n", (void *)katom);
-+ dev_dbg(kbdev->dev, "Atom %pK status to unused\n", (void *)katom);
- wake_up(&katom->completed);
-
- return data;
-@@ -82,7 +79,7 @@ int kbase_event_dequeue(struct kbase_context *ctx, struct base_jd_event_v2 *ueve
-
- mutex_unlock(&ctx->event_mutex);
-
-- dev_dbg(ctx->kbdev->dev, "event dequeuing %p\n", (void *)atom);
-+ dev_dbg(ctx->kbdev->dev, "event dequeuing %pK\n", (void *)atom);
- uevent->event_code = atom->event_code;
-
- uevent->atom_number = (atom - ctx->jctx.atoms);
-@@ -154,7 +151,8 @@ static int kbase_event_coalesce(struct kbase_context *kctx)
- const int event_count = kctx->event_coalesce_count;
-
- /* Join the list of pending events onto the tail of the main list
-- and reset it */
-+ * and reset it
-+ */
- list_splice_tail_init(&kctx->event_coalesce_list, &kctx->event_list);
- kctx->event_coalesce_count = 0;
-
-@@ -166,7 +164,17 @@ void kbase_event_post(struct kbase_context *ctx, struct kbase_jd_atom *atom)
- {
- struct kbase_device *kbdev = ctx->kbdev;
-
-- dev_dbg(kbdev->dev, "Posting event for atom %p\n", (void *)atom);
-+ dev_dbg(kbdev->dev, "Posting event for atom %pK\n", (void *)atom);
-+
-+ if (WARN_ON(atom->status != KBASE_JD_ATOM_STATE_COMPLETED)) {
-+ dev_warn(kbdev->dev,
-+ "%s: Atom %d (%pK) not completed (status %d)\n",
-+ __func__,
-+ kbase_jd_atom_id(atom->kctx, atom),
-+ atom->kctx,
-+ atom->status);
-+ return;
-+ }
-
- if (atom->core_req & BASE_JD_REQ_EVENT_ONLY_ON_FAILURE) {
- if (atom->event_code == BASE_JD_EVENT_DONE) {
-@@ -227,7 +235,7 @@ int kbase_event_init(struct kbase_context *kctx)
- kctx->event_coalesce_count = 0;
- kctx->event_workq = alloc_workqueue("kbase_event", WQ_MEM_RECLAIM, 1);
-
-- if (NULL == kctx->event_workq)
-+ if (kctx->event_workq == NULL)
- return -EINVAL;
-
- return 0;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence.c
-index 7a715b3..01557cd 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,79 +17,18 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/atomic.h>
- #include <linux/list.h>
- #include <linux/spinlock.h>
--#include <mali_kbase_fence_defs.h>
- #include <mali_kbase_fence.h>
- #include <mali_kbase.h>
-
- /* Spin lock protecting all Mali fences as fence->lock. */
- static DEFINE_SPINLOCK(kbase_fence_lock);
-
--static const char *
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
--kbase_fence_get_driver_name(struct fence *fence)
--#else
--kbase_fence_get_driver_name(struct dma_fence *fence)
--#endif
--{
-- return kbase_drv_name;
--}
--
--static const char *
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
--kbase_fence_get_timeline_name(struct fence *fence)
--#else
--kbase_fence_get_timeline_name(struct dma_fence *fence)
--#endif
--{
-- return kbase_timeline_name;
--}
--
--static bool
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
--kbase_fence_enable_signaling(struct fence *fence)
--#else
--kbase_fence_enable_signaling(struct dma_fence *fence)
--#endif
--{
-- return true;
--}
--
--static void
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
--kbase_fence_fence_value_str(struct fence *fence, char *str, int size)
--#else
--kbase_fence_fence_value_str(struct dma_fence *fence, char *str, int size)
--#endif
--{
--#if (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE)
-- snprintf(str, size, "%u", fence->seqno);
--#else
-- snprintf(str, size, "%llu", fence->seqno);
--#endif
--}
--
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
--const struct fence_ops kbase_fence_ops = {
-- .wait = fence_default_wait,
--#else
--const struct dma_fence_ops kbase_fence_ops = {
-- .wait = dma_fence_default_wait,
--#endif
-- .get_driver_name = kbase_fence_get_driver_name,
-- .get_timeline_name = kbase_fence_get_timeline_name,
-- .enable_signaling = kbase_fence_enable_signaling,
-- .fence_value_str = kbase_fence_fence_value_str
--};
--
--
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *
- kbase_fence_out_new(struct kbase_jd_atom *katom)
- #else
-@@ -96,7 +36,7 @@ struct dma_fence *
- kbase_fence_out_new(struct kbase_jd_atom *katom)
- #endif
- {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence;
- #else
- struct dma_fence *fence;
-@@ -157,7 +97,7 @@ kbase_fence_free_callbacks(struct kbase_jd_atom *katom)
- return res;
- }
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- int
- kbase_fence_add_callback(struct kbase_jd_atom *katom,
- struct fence *fence,
-@@ -211,4 +151,3 @@ kbase_fence_add_callback(struct kbase_jd_atom *katom,
-
- return err;
- }
--
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence.h
-index 8e7024e..37823d5 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2018, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_FENCE_H_
-@@ -35,7 +34,7 @@
- #include "mali_kbase_fence_defs.h"
- #include "mali_kbase.h"
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- extern const struct fence_ops kbase_fence_ops;
- #else
- extern const struct dma_fence_ops kbase_fence_ops;
-@@ -49,7 +48,7 @@ extern const struct dma_fence_ops kbase_fence_ops;
- * @node: List head for linking this callback to the katom
- */
- struct kbase_fence_cb {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence_cb fence_cb;
- struct fence *fence;
- #else
-@@ -66,7 +65,7 @@ struct kbase_fence_cb {
- *
- * return: A new fence object on success, NULL on failure.
- */
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *kbase_fence_out_new(struct kbase_jd_atom *katom);
- #else
- struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom);
-@@ -88,6 +87,7 @@ struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom);
- #endif
-
-
-+#if !MALI_USE_CSF
- /**
- * kbase_fence_out_remove() - Removes the output fence from atom
- * @katom: Atom to remove output fence for
-@@ -168,7 +168,7 @@ static inline int kbase_fence_out_signal(struct kbase_jd_atom *katom,
- * Return: 0 on success: fence was either already signaled, or callback was
- * set up. Negative error code is returned on error.
- */
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- int kbase_fence_add_callback(struct kbase_jd_atom *katom,
- struct fence *fence,
- fence_func_t callback);
-@@ -269,6 +269,7 @@ bool kbase_fence_free_callbacks(struct kbase_jd_atom *katom);
- */
- #define kbase_fence_out_get(katom) dma_fence_get((katom)->dma_fence.fence)
-
-+#endif /* !MALI_USE_CSF */
-
- /**
- * kbase_fence_put() - Releases a reference to a fence
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence_defs.h
-index 607a95c..7a150bd 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence_defs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_FENCE_DEFS_H_
-@@ -28,11 +27,9 @@
- * This file hides the compatibility issues with this for the rest the driver
- */
-
--#if defined(CONFIG_MALI_DMA_FENCE) || defined(CONFIG_SYNC_FILE)
--
- #include <linux/version.h>
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-
- #include <linux/fence.h>
-
-@@ -55,7 +52,7 @@
-
- #include <linux/dma-fence.h>
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
-+#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE)
- #define dma_fence_get_status(a) (dma_fence_is_signaled(a) ? \
- (a)->status ?: 1 \
- : 0)
-@@ -63,6 +60,4 @@
-
- #endif /* < 4.10.0 */
-
--#endif /* CONFIG_MALI_DMA_FENCE || CONFIG_SYNC_FILE */
--
- #endif /* _KBASE_FENCE_DEFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence_ops.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence_ops.c
-new file mode 100644
-index 0000000..14ddf03
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_fence_ops.c
-@@ -0,0 +1,83 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <linux/atomic.h>
-+#include <linux/list.h>
-+#include <mali_kbase_fence_defs.h>
-+#include <mali_kbase.h>
-+
-+static const char *
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+kbase_fence_get_driver_name(struct fence *fence)
-+#else
-+kbase_fence_get_driver_name(struct dma_fence *fence)
-+#endif
-+{
-+ return kbase_drv_name;
-+}
-+
-+static const char *
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+kbase_fence_get_timeline_name(struct fence *fence)
-+#else
-+kbase_fence_get_timeline_name(struct dma_fence *fence)
-+#endif
-+{
-+ return kbase_timeline_name;
-+}
-+
-+static bool
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+kbase_fence_enable_signaling(struct fence *fence)
-+#else
-+kbase_fence_enable_signaling(struct dma_fence *fence)
-+#endif
-+{
-+ return true;
-+}
-+
-+static void
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+kbase_fence_fence_value_str(struct fence *fence, char *str, int size)
-+#else
-+kbase_fence_fence_value_str(struct dma_fence *fence, char *str, int size)
-+#endif
-+{
-+#if (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE)
-+ snprintf(str, size, "%u", fence->seqno);
-+#else
-+ snprintf(str, size, "%llu", fence->seqno);
-+#endif
-+}
-+
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-+const struct fence_ops kbase_fence_ops = {
-+ .wait = fence_default_wait,
-+#else
-+const struct dma_fence_ops kbase_fence_ops = {
-+ .wait = dma_fence_default_wait,
-+#endif
-+ .get_driver_name = kbase_fence_get_driver_name,
-+ .get_timeline_name = kbase_fence_get_timeline_name,
-+ .enable_signaling = kbase_fence_enable_signaling,
-+ .fence_value_str = kbase_fence_fence_value_str
-+};
-+
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gator.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gator.h
-index 6428f08..88c96e0 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gator.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gator.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* NB taken from gator */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c
-index 93f1565..6eaae83 100755
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2017, 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2017, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,24 +17,23 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
- #include <device/mali_kbase_device.h>
-
--#ifdef CONFIG_DEBUG_FS
--/** Show callback for the @c gpu_memory debugfs file.
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+/**
-+ * kbasep_gpu_memory_seq_show - Show callback for the @c gpu_memory debugfs file
-+ * @sfile: The debugfs entry
-+ * @data: Data associated with the entry
- *
- * This function is called to get the contents of the @c gpu_memory debugfs
- * file. This is a report of current gpu memory usage.
- *
-- * @param sfile The debugfs entry
-- * @param data Data associated with the entry
-- *
-- * @return 0 if successfully prints data in debugfs entry file
-- * -1 if it encountered an error
-+ * Return:
-+ * * 0 if successfully prints data in debugfs entry file
-+ * * -1 if it encountered an error
- */
-
- static int kbasep_gpu_memory_seq_show(struct seq_file *sfile, void *data)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h
-index 28a871a..6d5423f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpu_memory_debugfs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2014, 2016 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2014, 2016, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_gpu_memory_debugfs.h
-- * Header file for gpu_memory entry in debugfs
-+ * DOC: Header file for gpu_memory entry in debugfs
- *
- */
-
-@@ -34,8 +30,20 @@
- #include <linux/debugfs.h>
- #include <linux/seq_file.h>
-
-+/* kbase_io_history_add - add new entry to the register access history
-+ *
-+ * @h: Pointer to the history data structure
-+ * @addr: Register address
-+ * @value: The value that is either read from or written to the register
-+ * @write: 1 if it's a register write, 0 if it's a read
-+ */
-+void kbase_io_history_add(struct kbase_io_history *h, void __iomem const *addr,
-+ u32 value, u8 write);
-+
- /**
-- * @brief Initialize gpu_memory debugfs entry
-+ * kbasep_gpu_memory_debugfs_init - Initialize gpu_memory debugfs entry
-+ *
-+ * @kbdev: Device pointer
- */
- void kbasep_gpu_memory_debugfs_init(struct kbase_device *kbdev);
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c
-index ae2458f..e4d52c9 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c
-@@ -1,12 +1,12 @@
--// SPDX-License-Identifier: GPL-2.0
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -17,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Base kernel property query APIs
- */
-@@ -32,9 +28,9 @@
- #include <mali_kbase_gpuprops.h>
- #include <mali_kbase_hwaccess_gpuprops.h>
- #include <mali_kbase_config_defaults.h>
--#include "mali_kbase_ioctl.h"
-+#include <uapi/gpu/arm/midgard/mali_kbase_ioctl.h>
- #include <linux/clk.h>
--#include <mali_kbase_pm_internal.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
- #include <linux/of_platform.h>
- #include <linux/moduleparam.h>
-
-@@ -48,7 +44,7 @@ static void kbase_gpuprops_construct_coherent_groups(
- u64 first_set, first_set_prev;
- u32 num_groups = 0;
-
-- KBASE_DEBUG_ASSERT(NULL != props);
-+ KBASE_DEBUG_ASSERT(props != NULL);
-
- props->coherency_info.coherency = props->raw_props.mem_features;
- props->coherency_info.num_core_groups = hweight64(props->raw_props.l2_present);
-@@ -107,6 +103,71 @@ static void kbase_gpuprops_construct_coherent_groups(
- props->coherency_info.num_groups = num_groups;
- }
-
-+/**
-+ * kbase_gpuprops_get_curr_config_props - Get the current allocated resources
-+ * @kbdev: The &struct kbase_device structure for the device
-+ * @curr_config: The &struct curr_config_props structure to receive the result
-+ *
-+ * Fill the &struct curr_config_props structure with values from the GPU
-+ * configuration registers.
-+ *
-+ * Return: Zero on success, Linux error code on failure
-+ */
-+int kbase_gpuprops_get_curr_config_props(struct kbase_device *kbdev,
-+ struct curr_config_props * const curr_config)
-+{
-+ struct kbase_current_config_regdump curr_config_regdump;
-+ int err;
-+
-+ if (WARN_ON(!kbdev) || WARN_ON(!curr_config))
-+ return -EINVAL;
-+
-+ /* If update not needed just return. */
-+ if (!curr_config->update_needed)
-+ return 0;
-+
-+ /* Dump relevant registers */
-+ err = kbase_backend_gpuprops_get_curr_config(kbdev,
-+ &curr_config_regdump);
-+ if (err)
-+ return err;
-+
-+ curr_config->l2_slices =
-+ KBASE_UBFX32(curr_config_regdump.mem_features, 8U, 4) + 1;
-+
-+ curr_config->l2_present =
-+ ((u64) curr_config_regdump.l2_present_hi << 32) +
-+ curr_config_regdump.l2_present_lo;
-+
-+ curr_config->shader_present =
-+ ((u64) curr_config_regdump.shader_present_hi << 32) +
-+ curr_config_regdump.shader_present_lo;
-+
-+ curr_config->num_cores = hweight64(curr_config->shader_present);
-+
-+ curr_config->update_needed = false;
-+
-+ return 0;
-+}
-+
-+/**
-+ * kbase_gpuprops_req_curr_config_update - Request Current Config Update
-+ * @kbdev: The &struct kbase_device structure for the device
-+ *
-+ * Requests the current configuration to be updated next time the
-+ * kbase_gpuprops_get_curr_config_props() is called.
-+ *
-+ * Return: Zero on success, Linux error code on failure
-+ */
-+int kbase_gpuprops_req_curr_config_update(struct kbase_device *kbdev)
-+{
-+ if (WARN_ON(!kbdev))
-+ return -EINVAL;
-+
-+ kbdev->gpu_props.curr_config.update_needed = true;
-+ return 0;
-+}
-+
- /**
- * kbase_gpuprops_get_props - Get the GPU configuration
- * @gpu_props: The &struct base_gpu_props structure
-@@ -124,8 +185,8 @@ static int kbase_gpuprops_get_props(struct base_gpu_props * const gpu_props,
- int i;
- int err;
-
-- KBASE_DEBUG_ASSERT(NULL != kbdev);
-- KBASE_DEBUG_ASSERT(NULL != gpu_props);
-+ KBASE_DEBUG_ASSERT(kbdev != NULL);
-+ KBASE_DEBUG_ASSERT(gpu_props != NULL);
-
- /* Dump relevant registers */
- err = kbase_backend_gpuprops_get(kbdev, ®dump);
-@@ -166,6 +227,10 @@ static int kbase_gpuprops_get_props(struct base_gpu_props * const gpu_props,
- gpu_props->raw_props.thread_features = regdump.thread_features;
- gpu_props->raw_props.thread_tls_alloc = regdump.thread_tls_alloc;
-
-+ gpu_props->raw_props.gpu_features =
-+ ((u64) regdump.gpu_features_hi << 32) +
-+ regdump.gpu_features_lo;
-+
- return 0;
- }
-
-@@ -182,6 +247,59 @@ void kbase_gpuprops_update_core_props_gpu_id(
- KBASE_UBFX32(gpu_props->raw_props.gpu_id, 16U, 16);
- }
-
-+/**
-+ * kbase_gpuprops_update_max_config_props - Updates the max config properties in
-+ * the base_gpu_props.
-+ * @base_props: The &struct base_gpu_props structure
-+ * @kbdev: The &struct kbase_device structure for the device
-+ *
-+ * Updates the &struct base_gpu_props structure with the max config properties.
-+ */
-+static void kbase_gpuprops_update_max_config_props(
-+ struct base_gpu_props * const base_props, struct kbase_device *kbdev)
-+{
-+ int l2_n = 0;
-+
-+ if (WARN_ON(!kbdev) || WARN_ON(!base_props))
-+ return;
-+
-+ /* return if the max_config is not set during arbif initialization */
-+ if (kbdev->gpu_props.max_config.core_mask == 0)
-+ return;
-+
-+ /*
-+ * Set the base_props with the maximum config values to ensure that the
-+ * user space will always be based on the maximum resources available.
-+ */
-+ base_props->l2_props.num_l2_slices =
-+ kbdev->gpu_props.max_config.l2_slices;
-+ base_props->raw_props.shader_present =
-+ kbdev->gpu_props.max_config.core_mask;
-+ /*
-+ * Update l2_present in the raw data to be consistent with the
-+ * max_config.l2_slices number.
-+ */
-+ base_props->raw_props.l2_present = 0;
-+ for (l2_n = 0; l2_n < base_props->l2_props.num_l2_slices; l2_n++) {
-+ base_props->raw_props.l2_present <<= 1;
-+ base_props->raw_props.l2_present |= 0x1;
-+ }
-+ /*
-+ * Update the coherency_info data using just one core group. For
-+ * architectures where the max_config is provided by the arbiter it is
-+ * not necessary to split the shader core groups in different coherent
-+ * groups.
-+ */
-+ base_props->coherency_info.coherency =
-+ base_props->raw_props.mem_features;
-+ base_props->coherency_info.num_core_groups = 1;
-+ base_props->coherency_info.num_groups = 1;
-+ base_props->coherency_info.group[0].core_mask =
-+ kbdev->gpu_props.max_config.core_mask;
-+ base_props->coherency_info.group[0].num_cores =
-+ hweight32(kbdev->gpu_props.max_config.core_mask);
-+}
-+
- /**
- * kbase_gpuprops_calculate_props - Calculate the derived properties
- * @gpu_props: The &struct base_gpu_props structure
-@@ -195,7 +313,6 @@ static void kbase_gpuprops_calculate_props(
- {
- int i;
- u32 gpu_id;
-- u32 product_id;
-
- /* Populate the base_gpu_props structure */
- kbase_gpuprops_update_core_props_gpu_id(gpu_props);
-@@ -218,7 +335,8 @@ static void kbase_gpuprops_calculate_props(
-
- /* Field with number of l2 slices is added to MEM_FEATURES register
- * since t76x. Below code assumes that for older GPU reserved bits will
-- * be read as zero. */
-+ * be read as zero.
-+ */
- gpu_props->l2_props.num_l2_slices =
- KBASE_UBFX32(gpu_props->raw_props.mem_features, 8U, 4) + 1;
-
-@@ -251,9 +369,19 @@ static void kbase_gpuprops_calculate_props(
- * Workaround for the incorrectly applied THREAD_FEATURES to tDUx.
- */
- gpu_id = kbdev->gpu_props.props.raw_props.gpu_id;
-- product_id = gpu_id & GPU_ID_VERSION_PRODUCT_ID;
-- product_id >>= GPU_ID_VERSION_PRODUCT_ID_SHIFT;
-
-+#if MALI_USE_CSF
-+ gpu_props->thread_props.max_registers =
-+ KBASE_UBFX32(gpu_props->raw_props.thread_features,
-+ 0U, 22);
-+ gpu_props->thread_props.impl_tech =
-+ KBASE_UBFX32(gpu_props->raw_props.thread_features,
-+ 22U, 2);
-+ gpu_props->thread_props.max_task_queue =
-+ KBASE_UBFX32(gpu_props->raw_props.thread_features,
-+ 24U, 8);
-+ gpu_props->thread_props.max_thread_group_split = 0;
-+#else
- if ((gpu_id & GPU_ID2_PRODUCT_MODEL) == GPU_ID2_PRODUCT_TDUX) {
- gpu_props->thread_props.max_registers =
- KBASE_UBFX32(gpu_props->raw_props.thread_features,
-@@ -279,6 +407,7 @@ static void kbase_gpuprops_calculate_props(
- KBASE_UBFX32(gpu_props->raw_props.thread_features,
- 30U, 2);
- }
-+#endif
-
- /* If values are not specified, then use defaults */
- if (gpu_props->thread_props.max_registers == 0) {
-@@ -286,8 +415,30 @@ static void kbase_gpuprops_calculate_props(
- gpu_props->thread_props.max_task_queue = THREAD_MTQ_DEFAULT;
- gpu_props->thread_props.max_thread_group_split = THREAD_MTGS_DEFAULT;
- }
-- /* Initialize the coherent_group structure for each group */
-- kbase_gpuprops_construct_coherent_groups(gpu_props);
-+
-+ /*
-+ * If the maximum resources allocated information is available it is
-+ * necessary to update the base_gpu_props with the max_config info to
-+ * the userspace. This is applicable to systems that receive this
-+ * information from the arbiter.
-+ */
-+ if (kbdev->gpu_props.max_config.core_mask)
-+ /* Update the max config properties in the base_gpu_props */
-+ kbase_gpuprops_update_max_config_props(gpu_props,
-+ kbdev);
-+ else
-+ /* Initialize the coherent_group structure for each group */
-+ kbase_gpuprops_construct_coherent_groups(gpu_props);
-+}
-+
-+void kbase_gpuprops_set_max_config(struct kbase_device *kbdev,
-+ const struct max_config_props *max_config)
-+{
-+ if (WARN_ON(!kbdev) || WARN_ON(!max_config))
-+ return;
-+
-+ kbdev->gpu_props.max_config.l2_slices = max_config->l2_slices;
-+ kbdev->gpu_props.max_config.core_mask = max_config->core_mask;
- }
-
- void kbase_gpuprops_set(struct kbase_device *kbdev)
-@@ -295,7 +446,8 @@ void kbase_gpuprops_set(struct kbase_device *kbdev)
- struct kbase_gpu_props *gpu_props;
- struct gpu_raw_gpu_props *raw;
-
-- KBASE_DEBUG_ASSERT(NULL != kbdev);
-+ if (WARN_ON(!kbdev))
-+ return;
- gpu_props = &kbdev->gpu_props;
- raw = &gpu_props->props.raw_props;
-
-@@ -315,9 +467,19 @@ void kbase_gpuprops_set(struct kbase_device *kbdev)
- 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_core_groups =
-+ gpu_props->props.coherency_info.num_core_groups;
- gpu_props->num_address_spaces = hweight32(raw->as_present);
- gpu_props->num_job_slots = hweight32(raw->js_present);
-+
-+ /*
-+ * Current configuration is used on HW interactions so that the maximum
-+ * config is just used for user space avoiding interactions with parts
-+ * of the hardware that might not be allocated to the kbase instance at
-+ * that moment.
-+ */
-+ kbase_gpuprops_req_curr_config_update(kbdev);
-+ kbase_gpuprops_get_curr_config_props(kbdev, &gpu_props->curr_config);
- }
-
- int kbase_gpuprops_set_features(struct kbase_device *kbdev)
-@@ -355,13 +517,34 @@ int kbase_gpuprops_set_features(struct kbase_device *kbdev)
- * in sysfs.
- */
- static u8 override_l2_size;
--module_param(override_l2_size, byte, 0);
-+module_param(override_l2_size, byte, 0000);
- MODULE_PARM_DESC(override_l2_size, "Override L2 size config for testing");
-
- static u8 override_l2_hash;
--module_param(override_l2_hash, byte, 0);
-+module_param(override_l2_hash, byte, 0000);
- MODULE_PARM_DESC(override_l2_hash, "Override L2 hash config for testing");
-
-+static u32 l2_hash_values[ASN_HASH_COUNT] = {
-+ 0,
-+};
-+static int num_override_l2_hash_values;
-+module_param_array(l2_hash_values, uint, &num_override_l2_hash_values, 0000);
-+MODULE_PARM_DESC(l2_hash_values, "Override L2 hash values config for testing");
-+
-+/* Definitions for range of supported user defined hash functions for GPUs
-+ * that support L2_CONFIG and not ASN_HASH features. Supported hash function
-+ * range from 0b1000-0b1111 inclusive. Selection of any other values will
-+ * lead to undefined behavior.
-+ */
-+#define USER_DEFINED_HASH_LO ((u8)0x08)
-+#define USER_DEFINED_HASH_HI ((u8)0x0F)
-+
-+enum l2_config_override_result {
-+ L2_CONFIG_OVERRIDE_FAIL = -1,
-+ L2_CONFIG_OVERRIDE_NONE,
-+ L2_CONFIG_OVERRIDE_OK,
-+};
-+
- /**
- * kbase_read_l2_config_from_dt - Read L2 configuration
- * @kbdev: The kbase device for which to get the L2 configuration.
-@@ -370,30 +553,67 @@ MODULE_PARM_DESC(override_l2_hash, "Override L2 hash config for testing");
- * Override values in module parameters take priority over override values in
- * device tree.
- *
-- * Return: true if either size or hash was overridden, false if no overrides
-- * were found.
-+ * Return: L2_CONFIG_OVERRIDE_OK if either size or hash, or both was properly
-+ * overridden, L2_CONFIG_OVERRIDE_NONE if no overrides are provided.
-+ * L2_CONFIG_OVERRIDE_FAIL otherwise.
- */
--static bool kbase_read_l2_config_from_dt(struct kbase_device * const kbdev)
-+static enum l2_config_override_result
-+kbase_read_l2_config_from_dt(struct kbase_device *const kbdev)
- {
- struct device_node *np = kbdev->dev->of_node;
-
- if (!np)
-- return false;
-+ return L2_CONFIG_OVERRIDE_NONE;
-
- if (override_l2_size)
- kbdev->l2_size_override = override_l2_size;
- else if (of_property_read_u8(np, "l2-size", &kbdev->l2_size_override))
- kbdev->l2_size_override = 0;
-
-- if (override_l2_hash)
-+ /* Check overriding value is supported, if not will result in
-+ * undefined behavior.
-+ */
-+ if (override_l2_hash >= USER_DEFINED_HASH_LO &&
-+ override_l2_hash <= USER_DEFINED_HASH_HI)
- kbdev->l2_hash_override = override_l2_hash;
- else if (of_property_read_u8(np, "l2-hash", &kbdev->l2_hash_override))
- kbdev->l2_hash_override = 0;
-
-- if (kbdev->l2_size_override || kbdev->l2_hash_override)
-- return true;
-+ kbdev->l2_hash_values_override = false;
-+ if (num_override_l2_hash_values) {
-+ int i;
-+
-+ kbdev->l2_hash_values_override = true;
-+ for (i = 0; i < num_override_l2_hash_values; i++)
-+ kbdev->l2_hash_values[i] = l2_hash_values[i];
-+ } else if (!of_property_read_u32_array(np, "l2-hash-values",
-+ kbdev->l2_hash_values,
-+ ASN_HASH_COUNT))
-+ kbdev->l2_hash_values_override = true;
-+
-+ if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_ASN_HASH) &&
-+ (kbdev->l2_hash_override)) {
-+ dev_err(kbdev->dev, "l2-hash not supported\n");
-+ return L2_CONFIG_OVERRIDE_FAIL;
-+ }
-+
-+ if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_ASN_HASH) &&
-+ (kbdev->l2_hash_values_override)) {
-+ dev_err(kbdev->dev, "l2-hash-values not supported\n");
-+ return L2_CONFIG_OVERRIDE_FAIL;
-+ }
-+
-+ if (kbdev->l2_hash_override && kbdev->l2_hash_values_override) {
-+ dev_err(kbdev->dev,
-+ "both l2-hash & l2-hash-values not supported\n");
-+ return L2_CONFIG_OVERRIDE_FAIL;
-+ }
-+
-+ if (kbdev->l2_size_override || kbdev->l2_hash_override ||
-+ kbdev->l2_hash_values_override)
-+ return L2_CONFIG_OVERRIDE_OK;
-
-- return false;
-+ return L2_CONFIG_OVERRIDE_NONE;
- }
-
- int kbase_gpuprops_update_l2_features(struct kbase_device *kbdev)
-@@ -405,8 +625,25 @@ int kbase_gpuprops_update_l2_features(struct kbase_device *kbdev)
- struct base_gpu_props *gpu_props = &kbdev->gpu_props.props;
-
- /* Check for L2 cache size & hash overrides */
-- if (!kbase_read_l2_config_from_dt(kbdev))
-- return 0;
-+ switch (kbase_read_l2_config_from_dt(kbdev)) {
-+ case L2_CONFIG_OVERRIDE_FAIL:
-+ err = -EIO;
-+ goto exit;
-+ case L2_CONFIG_OVERRIDE_NONE:
-+ goto exit;
-+ default:
-+ break;
-+ }
-+
-+ /* pm.active_count is expected to be 1 here, which is set in
-+ * kbase_hwaccess_pm_powerup().
-+ */
-+ WARN_ON(kbdev->pm.active_count != 1);
-+ /* The new settings for L2 cache can only be applied when it is
-+ * off, so first do the power down.
-+ */
-+ kbase_pm_context_idle(kbdev);
-+ kbase_pm_wait_for_desired_state(kbdev);
-
- /* Need L2 to get powered to reflect to L2_FEATURES */
- kbase_pm_context_active(kbdev);
-@@ -417,21 +654,21 @@ int kbase_gpuprops_update_l2_features(struct kbase_device *kbdev)
- /* Dump L2_FEATURES register */
- err = kbase_backend_gpuprops_get_l2_features(kbdev, ®dump);
- if (err)
-- goto idle_gpu;
-+ goto exit;
-
- dev_info(kbdev->dev, "Reflected L2_FEATURES is 0x%x\n",
-- regdump.l2_features);
-+ regdump.l2_features);
-+ dev_info(kbdev->dev, "Reflected L2_CONFIG is 0x%08x\n",
-+ regdump.l2_config);
-+
-
- /* Update gpuprops with reflected L2_FEATURES */
- gpu_props->raw_props.l2_features = regdump.l2_features;
- gpu_props->l2_props.log2_cache_size =
- KBASE_UBFX32(gpu_props->raw_props.l2_features, 16U, 8);
--
--idle_gpu:
-- /* Let GPU idle */
-- kbase_pm_context_idle(kbdev);
- }
-
-+exit:
- return err;
- }
-
-@@ -511,7 +748,7 @@ static struct {
- PROP(RAW_THREAD_FEATURES, raw_props.thread_features),
- PROP(RAW_THREAD_TLS_ALLOC, raw_props.thread_tls_alloc),
- PROP(RAW_COHERENCY_MODE, raw_props.coherency_mode),
--
-+ PROP(RAW_GPU_FEATURES, raw_props.gpu_features),
- PROP(COHERENCY_NUM_GROUPS, coherency_info.num_groups),
- PROP(COHERENCY_NUM_CORE_GROUPS, coherency_info.num_core_groups),
- PROP(COHERENCY_COHERENCY, coherency_info.coherency),
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h
-index 5eee794..b20b99b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2015, 2017, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,29 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--/*
-- *
-- * (C) COPYRIGHT 2011-2015, 2017, 2019-2020 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
-+ * DOC: Base kernel property query APIs
- */
-
- #ifndef _KBASE_GPUPROPS_H_
-@@ -64,11 +46,10 @@ struct kbase_device;
- (((u32)(value) >> (u32)(offset)) & (u32)((1ULL << (u32)(size)) - 1))
-
- /**
-- * @brief Set up Kbase GPU properties.
-+ * kbase_gpuprops_set - Set up Kbase GPU properties.
-+ * @kbdev: The struct kbase_device structure for the device
- *
- * Set up Kbase GPU properties with information from the GPU registers
-- *
-- * @param kbdev The struct kbase_device structure for the device
- */
- void kbase_gpuprops_set(struct kbase_device *kbdev);
-
-@@ -89,6 +70,8 @@ int kbase_gpuprops_set_features(struct kbase_device *kbdev);
- * @kbdev: Device pointer
- *
- * This function updates l2_features and the log2 cache size.
-+ * The function expects GPU to be powered up and value of pm.active_count
-+ * to be 1.
- *
- * Return: Zero on success, Linux error code for failure
- */
-@@ -132,4 +115,38 @@ int kbase_device_populate_max_freq(struct kbase_device *kbdev);
- void kbase_gpuprops_update_core_props_gpu_id(
- struct base_gpu_props * const gpu_props);
-
-+/**
-+ * kbase_gpuprops_set_max_config - Set the max config information
-+ * @kbdev: Device pointer
-+ * @max_config: Maximum configuration data to be updated
-+ *
-+ * This function sets max_config in the kbase_gpu_props.
-+ */
-+void kbase_gpuprops_set_max_config(struct kbase_device *kbdev,
-+ const struct max_config_props *max_config);
-+
-+/**
-+ * kbase_gpuprops_get_curr_config_props - Get the current allocated resources
-+ * @kbdev: The &struct kbase_device structure for the device
-+ * @curr_config: The &struct curr_config_props structure to receive the result
-+ *
-+ * Fill the &struct curr_config_props structure with values from the GPU
-+ * configuration registers.
-+ *
-+ * Return: Zero on success, Linux error code on failure
-+ */
-+int kbase_gpuprops_get_curr_config_props(struct kbase_device *kbdev,
-+ struct curr_config_props * const curr_config);
-+
-+/**
-+ * kbase_gpuprops_req_curr_config_update - Request Current Config Update
-+ * @kbdev: The &struct kbase_device structure for the device
-+ *
-+ * Requests the current configuration to be updated next time the
-+ * kbase_gpuprops_get_curr_config_props() is called.
-+ *
-+ * Return: Zero on success, Linux error code on failure
-+ */
-+int kbase_gpuprops_req_curr_config_update(struct kbase_device *kbdev);
-+
- #endif /* _KBASE_GPUPROPS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h
-index ec6f1c3..02705a0 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops_types.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2018, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,21 +17,16 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_gpuprops_types.h
-- * Base kernel property query APIs
-+ * DOC: Base kernel property query APIs
- */
-
- #ifndef _KBASE_GPUPROPS_TYPES_H_
- #define _KBASE_GPUPROPS_TYPES_H_
-
--#include "mali_base_kernel.h"
-+#include <uapi/gpu/arm/midgard/mali_base_kernel.h>
-
- #define KBASE_GPU_SPEED_MHZ 123
- #define KBASE_GPU_PC_SIZE_LOG2 24U
-@@ -38,6 +34,7 @@
- struct kbase_gpuprops_regdump {
- u32 gpu_id;
- u32 l2_features;
-+ u32 l2_config;
- u32 core_features;
- u32 tiler_features;
- u32 mem_features;
-@@ -60,6 +57,30 @@ struct kbase_gpuprops_regdump {
- u32 stack_present_lo;
- u32 stack_present_hi;
- u32 coherency_features;
-+ u32 gpu_features_lo;
-+ u32 gpu_features_hi;
-+};
-+
-+/**
-+ * struct kbase_current_config_regdump - Register dump for current resources
-+ * allocated to the GPU.
-+ * @mem_features: Memory system features. Contains information about the
-+ * features of the memory system. Used here to get the L2 slice
-+ * count.
-+ * @shader_present_lo: Shader core present bitmap. Low word.
-+ * @shader_present_hi: Shader core present bitmap. High word.
-+ * @l2_present_lo: L2 cache present bitmap. Low word.
-+ * @l2_present_hi: L2 cache present bitmap. High word.
-+ *
-+ * Register dump structure used to store the resgisters data realated to the
-+ * current resources allocated to the GPU.
-+ */
-+struct kbase_current_config_regdump {
-+ u32 mem_features;
-+ u32 shader_present_lo;
-+ u32 shader_present_hi;
-+ u32 l2_present_lo;
-+ u32 l2_present_hi;
- };
-
- struct kbase_gpu_cache_props {
-@@ -76,6 +97,50 @@ struct kbase_gpu_mmu_props {
- u8 pa_bits;
- };
-
-+/**
-+ * struct max_config_props - Properties based on the maximum resources
-+ * available.
-+ * @l2_slices: Maximum number of L2 slices that can be assinged to the GPU
-+ * during runtime.
-+ * @padding: Padding to a multiple of 64 bits.
-+ * @core_mask: Largest core mask bitmap that can be assigned to the GPU during
-+ * runtime.
-+ *
-+ * Properties based on the maximum resources available (not necessarly
-+ * allocated at that moment). Used to provide the maximum configuration to the
-+ * userspace allowing the applications to allocate enough resources in case the
-+ * real allocated resources change.
-+ */
-+struct max_config_props {
-+ u8 l2_slices;
-+ u8 padding[3];
-+ u32 core_mask;
-+};
-+
-+/**
-+ * struct curr_config_props - Properties based on the current resources
-+ * allocated to the GPU.
-+ * @l2_present: Current L2 present bitmap that is allocated to the GPU.
-+ * @shader_present: Current shader present bitmap that is allocated to the GPU.
-+ * @num_cores: Current number of shader cores allocated to the GPU.
-+ * @l2_slices: Current number of L2 slices allocated to the GPU.
-+ * @update_needed: Defines if it is necessary to re-read the registers to
-+ * update the current allocated resources.
-+ * @padding: Padding to a multiple of 64 bits.
-+ *
-+ * Properties based on the current resource available. Used for operations with
-+ * hardware interactions to avoid using userspace data that can be based on
-+ * the maximum resource available.
-+ */
-+struct curr_config_props {
-+ u64 l2_present;
-+ u64 shader_present;
-+ u16 num_cores;
-+ u8 l2_slices;
-+ bool update_needed;
-+ u8 padding[4];
-+};
-+
- struct kbase_gpu_props {
- /* kernel-only properties */
- u8 num_cores;
-@@ -88,6 +153,12 @@ struct kbase_gpu_props {
- struct kbase_gpu_mem_props mem;
- struct kbase_gpu_mmu_props mmu;
-
-+ /* Properties based on the current resource available */
-+ struct curr_config_props curr_config;
-+
-+ /* Properties based on the maximum resource available */
-+ struct max_config_props max_config;
-+
- /* Properties shared with userspace */
- struct base_gpu_props props;
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gwt.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gwt.c
-index 6a47c9d..2a20a3d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gwt.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gwt.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase_gwt.h"
-@@ -71,6 +70,7 @@ int kbase_gpu_gwt_start(struct kbase_context *kctx)
- INIT_LIST_HEAD(&kctx->gwt_current_list);
- INIT_LIST_HEAD(&kctx->gwt_snapshot_list);
-
-+#if !MALI_USE_CSF
- /* If GWT is enabled using new vector dumping format
- * from user space, back up status of the job serialization flag and
- * use full serialisation of jobs for dumping.
-@@ -80,6 +80,7 @@ int kbase_gpu_gwt_start(struct kbase_context *kctx)
- kctx->kbdev->serialize_jobs = KBASE_SERIALIZE_INTRA_SLOT |
- KBASE_SERIALIZE_INTER_SLOT;
-
-+#endif
- /* Mark gwt enabled before making pages read only in case a
- write page fault is triggered while we're still in this loop.
- (kbase_gpu_vm_lock() doesn't prevent this!)
-@@ -113,7 +114,9 @@ int kbase_gpu_gwt_stop(struct kbase_context *kctx)
- kfree(pos);
- }
-
-+#if !MALI_USE_CSF
- kctx->kbdev->serialize_jobs = kctx->kbdev->backup_serialize_jobs;
-+#endif
-
- kbase_gpu_gwt_setup_pages(kctx, ~0UL);
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gwt.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gwt.h
-index 7e7746e..30de43d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gwt.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_gwt.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,13 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #if !defined(_KBASE_GWT_H)
- #define _KBASE_GWT_H
-
- #include <mali_kbase.h>
--#include <mali_kbase_ioctl.h>
-+#include <uapi/gpu/arm/midgard/mali_kbase_ioctl.h>
-
- /**
- * kbase_gpu_gwt_start - Start the GPU write tracking
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hw.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hw.c
-index f8a9248..7ad583c 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hw.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hw.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Run-time work-arounds helpers
- */
-@@ -68,6 +65,9 @@ void kbase_hw_set_features_mask(struct kbase_device *kbdev)
- case GPU_ID2_PRODUCT_TBEX:
- features = base_hw_features_tBEx;
- break;
-+ case GPU_ID2_PRODUCT_TBAX:
-+ features = base_hw_features_tBAx;
-+ break;
- case GPU_ID2_PRODUCT_TDUX:
- features = base_hw_features_tDUx;
- break;
-@@ -81,14 +81,6 @@ void kbase_hw_set_features_mask(struct kbase_device *kbdev)
- case GPU_ID2_PRODUCT_TVAX:
- features = base_hw_features_tVAx;
- break;
-- case GPU_ID2_PRODUCT_TTUX:
-- /* Fallthrough */
-- case GPU_ID2_PRODUCT_LTUX:
-- features = base_hw_features_tTUx;
-- break;
-- case GPU_ID2_PRODUCT_TE2X:
-- features = base_hw_features_tE2x;
-- break;
- default:
- features = base_hw_features_generic;
- break;
-@@ -140,103 +132,99 @@ static const enum base_hw_issue *kbase_hw_get_issues_for_new_id(
- };
-
- static const struct base_hw_product base_hw_products[] = {
-- {GPU_ID2_PRODUCT_TMIX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 1),
-- base_hw_issues_tMIx_r0p0_05dev0},
-- {GPU_ID2_VERSION_MAKE(0, 0, 2), base_hw_issues_tMIx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tMIx_r0p1},
-- {U32_MAX /* sentinel value */, NULL} } },
--
-- {GPU_ID2_PRODUCT_THEX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tHEx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tHEx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tHEx_r0p1},
-- {GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tHEx_r0p1},
-- {GPU_ID2_VERSION_MAKE(0, 2, 0), base_hw_issues_tHEx_r0p2},
-- {GPU_ID2_VERSION_MAKE(0, 3, 0), base_hw_issues_tHEx_r0p3},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TSIX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tSIx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tSIx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tSIx_r0p1},
-- {GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tSIx_r1p0},
-- {GPU_ID2_VERSION_MAKE(1, 1, 0), base_hw_issues_tSIx_r1p1},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TDVX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tDVx_r0p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TNOX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tNOx_r0p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TGOX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tGOx_r0p0},
-- {GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tGOx_r1p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TTRX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTRx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 0, 3), base_hw_issues_tTRx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tTRx_r0p1},
-- {GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tTRx_r0p1},
-- {GPU_ID2_VERSION_MAKE(0, 2, 0), base_hw_issues_tTRx_r0p2},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TNAX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tNAx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 0, 3), base_hw_issues_tNAx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 0, 4), base_hw_issues_tNAx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 0, 5), base_hw_issues_tNAx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tNAx_r0p1},
-- {GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tNAx_r0p1},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_LBEX,
-- {{GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_lBEx_r1p0},
-- {GPU_ID2_VERSION_MAKE(1, 1, 0), base_hw_issues_lBEx_r1p1},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TBEX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tBEx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 0, 3), base_hw_issues_tBEx_r0p0},
-- {GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tBEx_r0p1},
-- {GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tBEx_r1p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TDUX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tDUx_r0p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TODX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tODx_r0p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_LODX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tODx_r0p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TGRX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tGRx_r0p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TVAX,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tVAx_r0p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TTUX,
-- {{GPU_ID2_VERSION_MAKE(2, 0, 0), base_hw_issues_tTUx_r0p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_LTUX,
-- {{GPU_ID2_VERSION_MAKE(3, 0, 0), base_hw_issues_tTUx_r0p0},
-- {U32_MAX, NULL} } },
--
-- {GPU_ID2_PRODUCT_TE2X,
-- {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tE2x_r0p0},
-- {U32_MAX, NULL} } },
-+ { GPU_ID2_PRODUCT_TMIX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 1),
-+ base_hw_issues_tMIx_r0p0_05dev0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 2), base_hw_issues_tMIx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tMIx_r0p1 },
-+ { U32_MAX /* sentinel value */, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_THEX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tHEx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tHEx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tHEx_r0p1 },
-+ { GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tHEx_r0p1 },
-+ { GPU_ID2_VERSION_MAKE(0, 2, 0), base_hw_issues_tHEx_r0p2 },
-+ { GPU_ID2_VERSION_MAKE(0, 3, 0), base_hw_issues_tHEx_r0p3 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TSIX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tSIx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tSIx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tSIx_r0p1 },
-+ { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tSIx_r1p0 },
-+ { GPU_ID2_VERSION_MAKE(1, 1, 0), base_hw_issues_tSIx_r1p1 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TDVX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tDVx_r0p0 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TNOX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tNOx_r0p0 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TGOX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tGOx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tGOx_r1p0 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TTRX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTRx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 3), base_hw_issues_tTRx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tTRx_r0p1 },
-+ { GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tTRx_r0p1 },
-+ { GPU_ID2_VERSION_MAKE(0, 2, 0), base_hw_issues_tTRx_r0p2 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TNAX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tNAx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 3), base_hw_issues_tNAx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 4), base_hw_issues_tNAx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 5), base_hw_issues_tNAx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tNAx_r0p1 },
-+ { GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tNAx_r0p1 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_LBEX,
-+ { { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_lBEx_r1p0 },
-+ { GPU_ID2_VERSION_MAKE(1, 1, 0), base_hw_issues_lBEx_r1p1 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TBEX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tBEx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 3), base_hw_issues_tBEx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tBEx_r0p1 },
-+ { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tBEx_r1p0 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TBAX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tBAx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tBAx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 2), base_hw_issues_tBAx_r0p0 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TDUX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tDUx_r0p0 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TODX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tODx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 4), base_hw_issues_tODx_r0p0 },
-+ { GPU_ID2_VERSION_MAKE(0, 0, 5), base_hw_issues_tODx_r0p0 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_LODX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tODx_r0p0 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TGRX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tGRx_r0p0 },
-+ { U32_MAX, NULL } } },
-+
-+ { GPU_ID2_PRODUCT_TVAX,
-+ { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tVAx_r0p0 },
-+ { U32_MAX, NULL } } },
- };
-
- u32 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id;
-@@ -269,8 +257,8 @@ static const enum base_hw_issue *kbase_hw_get_issues_for_new_id(
- }
-
- /* Check whether this is a candidate for most recent
-- known version not later than the actual
-- version. */
-+ * known version not later than the actual version.
-+ */
- if ((version > product->map[v].version) &&
- (product->map[v].version >= fallback_version)) {
- #if MALI_CUSTOMER_RELEASE
-@@ -287,7 +275,8 @@ static const enum base_hw_issue *kbase_hw_get_issues_for_new_id(
-
- if ((issues == NULL) && (fallback_issues != NULL)) {
- /* Fall back to the issue set of the most recent known
-- version not later than the actual version. */
-+ * version not later than the actual version.
-+ */
- issues = fallback_issues;
-
- #if MALI_CUSTOMER_RELEASE
-@@ -340,7 +329,8 @@ int kbase_hw_set_issues_mask(struct kbase_device *kbdev)
-
- #if !MALI_CUSTOMER_RELEASE
- /* The GPU ID might have been replaced with the last
-- known version of the same GPU. */
-+ * known version of the same GPU.
-+ */
- gpu_id = kbdev->gpu_props.props.raw_props.gpu_id;
- #endif
- } else {
-@@ -374,6 +364,9 @@ int kbase_hw_set_issues_mask(struct kbase_device *kbdev)
- case GPU_ID2_PRODUCT_TBEX:
- issues = base_hw_issues_model_tBEx;
- break;
-+ case GPU_ID2_PRODUCT_TBAX:
-+ issues = base_hw_issues_model_tBAx;
-+ break;
- case GPU_ID2_PRODUCT_TDUX:
- issues = base_hw_issues_model_tDUx;
- break;
-@@ -387,13 +380,6 @@ int kbase_hw_set_issues_mask(struct kbase_device *kbdev)
- case GPU_ID2_PRODUCT_TVAX:
- issues = base_hw_issues_model_tVAx;
- break;
-- case GPU_ID2_PRODUCT_TTUX:
-- case GPU_ID2_PRODUCT_LTUX:
-- issues = base_hw_issues_model_tTUx;
-- break;
-- case GPU_ID2_PRODUCT_TE2X:
-- issues = base_hw_issues_model_tE2x;
-- break;
- default:
- dev_err(kbdev->dev,
- "Unknown GPU ID %x", gpu_id);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hw.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hw.h
-index f386b16..6c04a23 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hw.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hw.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file
-- * Run-time work-arounds helpers
-+ * DOC: Run-time work-arounds helpers
- */
-
- #ifndef _KBASE_HW_H_
-@@ -33,13 +29,17 @@
- #include "mali_kbase_defs.h"
-
- /**
-- * @brief Tell whether a work-around should be enabled
-+ * Tell whether a work-around should be enabled
-+ * @kbdev: Device pointer
-+ * @issue: issue to be checked
- */
- #define kbase_hw_has_issue(kbdev, issue)\
- test_bit(issue, &(kbdev)->hw_issues_mask[0])
-
- /**
-- * @brief Tell whether a feature is supported
-+ * Tell whether a feature is supported
-+ * @kbdev: Device pointer
-+ * @feature: feature to be checked
- */
- #define kbase_hw_has_feature(kbdev, feature)\
- test_bit(feature, &(kbdev)->hw_features_mask[0])
-@@ -63,7 +63,8 @@
- int kbase_hw_set_issues_mask(struct kbase_device *kbdev);
-
- /**
-- * @brief Set the features mask depending on the GPU ID
-+ * Set the features mask depending on the GPU ID
-+ * @kbdev: Device pointer
- */
- void kbase_hw_set_features_mask(struct kbase_device *kbdev);
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_backend.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_backend.h
-index 89df251..0da4eb2 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_backend.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_backend.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2015, 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2015, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * HW access backend common APIs
- */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_defs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_defs.h
-index 124a2d9..62a6ec5 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_defs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_defs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2016, 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2016-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,20 +17,16 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /**
-- * @file mali_kbase_hwaccess_gpu_defs.h
-- * HW access common definitions
-+ * DOC: HW access common definitions
- */
-
- #ifndef _KBASE_HWACCESS_DEFS_H_
- #define _KBASE_HWACCESS_DEFS_H_
-
--#include <mali_kbase_jm_defs.h>
-+#include <backend/gpu/mali_kbase_jm_defs.h>
-
- /**
- * struct kbase_hwaccess_data - object encapsulating the GPU backend specific
-@@ -43,7 +40,9 @@
- * @backend: GPU backend specific data for HW access layer
- */
- struct kbase_hwaccess_data {
-+#if !MALI_USE_CSF
- struct kbase_context *active_kctx[BASE_JM_MAX_NR_SLOTS];
-+#endif
-
- struct kbase_backend_data backend;
- };
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_gpuprops.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_gpuprops.h
-index 3ae0dbe..71ccc91 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_gpuprops.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_gpuprops.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2015, 2018, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,25 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//* SPDX-License-Identifier: GPL-2.0 */
--/*
-- *
-- * (C) COPYRIGHT 2014-2015, 2018, 2019-2020 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.
-- *
- */
-
--
- /**
- * Base kernel property query backend APIs
- */
-@@ -55,6 +39,23 @@
- int kbase_backend_gpuprops_get(struct kbase_device *kbdev,
- struct kbase_gpuprops_regdump *regdump);
-
-+/**
-+ * kbase_backend_gpuprops_get_curr_config() - Fill @curr_config_regdump with
-+ * relevant GPU properties read from
-+ * the GPU registers.
-+ * @kbdev: Device pointer.
-+ * @curr_config_regdump: Pointer to struct kbase_current_config_regdump
-+ * structure.
-+ *
-+ * The caller should ensure that GPU remains powered-on during this function and
-+ * the caller must ensure this function returns success before using the values
-+ * returned in the curr_config_regdump in any part of the kernel.
-+ *
-+ * Return: Zero for succeess or a Linux error code
-+ */
-+int kbase_backend_gpuprops_get_curr_config(struct kbase_device *kbdev,
-+ struct kbase_current_config_regdump *curr_config_regdump);
-+
- /**
- * kbase_backend_gpuprops_get_features - Fill @regdump with GPU properties read
- * from GPU
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_instr.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_instr.h
-index be85491..f836953 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_instr.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_instr.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2015, 2017-2018, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2015, 2017-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * HW Access instrumentation common APIs
- */
-@@ -29,27 +26,26 @@
- #ifndef _KBASE_HWACCESS_INSTR_H_
- #define _KBASE_HWACCESS_INSTR_H_
-
--#include <mali_kbase_instr_defs.h>
-+#include <backend/gpu/mali_kbase_instr_defs.h>
-
- /**
- * struct kbase_instr_hwcnt_enable - Enable hardware counter collection.
- * @dump_buffer: GPU address to write counters to.
- * @dump_buffer_bytes: Size in bytes of the buffer pointed to by dump_buffer.
-- * @jm_bm: counters selection bitmask (JM).
-+ * @fe_bm: counters selection bitmask (Front End).
- * @shader_bm: counters selection bitmask (Shader).
- * @tiler_bm: counters selection bitmask (Tiler).
- * @mmu_l2_bm: counters selection bitmask (MMU_L2).
-- * @use_secondary: use secondary performance counters set for applicable
-- * counter blocks.
-+ * @counter_set: the performance counter set to use.
- */
- struct kbase_instr_hwcnt_enable {
- u64 dump_buffer;
- u64 dump_buffer_bytes;
-- u32 jm_bm;
-+ u32 fe_bm;
- u32 shader_bm;
- u32 tiler_bm;
- u32 mmu_l2_bm;
-- bool use_secondary;
-+ u8 counter_set;
- };
-
- /**
-@@ -139,7 +135,7 @@ int kbase_instr_backend_init(struct kbase_device *kbdev);
- */
- void kbase_instr_backend_term(struct kbase_device *kbdev);
-
--#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY_VIA_DEBUG_FS
-+#ifdef CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
- /**
- * kbase_instr_backend_debugfs_init() - Add a debugfs entry for the
- * hardware counter set.
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_jm.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_jm.h
-index 3d5934e..8689647 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_jm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_jm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * HW access job manager common APIs
- */
-@@ -31,7 +29,7 @@
- /**
- * kbase_backend_run_atom() - Run an atom on the GPU
- * @kbdev: Device pointer
-- * @atom: Atom to run
-+ * @katom: Atom to run
- *
- * Caller must hold the HW access lock
- */
-@@ -154,6 +152,7 @@ void kbase_backend_cache_clean(struct kbase_device *kbdev,
- void kbase_backend_complete_wq(struct kbase_device *kbdev,
- struct kbase_jd_atom *katom);
-
-+#if !MALI_USE_CSF
- /**
- * kbase_backend_complete_wq_post_sched - Perform backend-specific actions
- * required on completing an atom, after
-@@ -166,6 +165,7 @@ void kbase_backend_complete_wq(struct kbase_device *kbdev,
- */
- void kbase_backend_complete_wq_post_sched(struct kbase_device *kbdev,
- base_jd_core_req core_req);
-+#endif /* !MALI_USE_CSF */
-
- /**
- * kbase_backend_reset() - The GPU is being reset. Cancel all jobs on the GPU
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_pm.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_pm.h
-index bbaf6ea..36bbe2d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_pm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_pm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2015, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2015, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,14 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /**
-- * @file mali_kbase_hwaccess_pm.h
-- * HW access power manager common APIs
-+ * DOC: HW access power manager common APIs
- */
-
- #ifndef _KBASE_HWACCESS_PM_H_
-@@ -32,7 +29,7 @@
- #include <gpu/mali_kbase_gpu_regmap.h>
- #include <linux/atomic.h>
-
--#include <mali_kbase_pm_defs.h>
-+#include <backend/gpu/mali_kbase_pm_defs.h>
-
- /* Forward definition - see mali_kbase.h */
- struct kbase_device;
-@@ -80,24 +77,21 @@ int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev,
- * the time this function returns, regardless of whether or not the active power
- * policy asks for the GPU to be powered off.
- *
-- * @param kbdev The kbase device structure for the device (must be a valid
-- * pointer)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- */
- void kbase_hwaccess_pm_halt(struct kbase_device *kbdev);
-
- /**
- * Perform any backend-specific actions to suspend the GPU
- *
-- * @param kbdev The kbase device structure for the device (must be a valid
-- * pointer)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- */
- void kbase_hwaccess_pm_suspend(struct kbase_device *kbdev);
-
- /**
- * Perform any backend-specific actions to resume the GPU from a suspend
- *
-- * @param kbdev The kbase device structure for the device (must be a valid
-- * pointer)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- */
- void kbase_hwaccess_pm_resume(struct kbase_device *kbdev);
-
-@@ -105,8 +99,7 @@ void kbase_hwaccess_pm_resume(struct kbase_device *kbdev);
- * Perform any required actions for activating the GPU. Called when the first
- * context goes active.
- *
-- * @param kbdev The kbase device structure for the device (must be a valid
-- * pointer)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- */
- void kbase_hwaccess_pm_gpu_active(struct kbase_device *kbdev);
-
-@@ -114,35 +107,43 @@ void kbase_hwaccess_pm_gpu_active(struct kbase_device *kbdev);
- * Perform any required actions for idling the GPU. Called when the last
- * context goes idle.
- *
-- * @param kbdev The kbase device structure for the device (must be a valid
-- * pointer)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- */
- void kbase_hwaccess_pm_gpu_idle(struct kbase_device *kbdev);
-
--
-+#if MALI_USE_CSF
-+/**
-+ * Set the debug core mask.
-+ *
-+ * This determines which cores the power manager is allowed to use.
-+ *
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ * @new_core_mask: The core mask to use
-+ */
-+void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev,
-+ u64 new_core_mask);
-+#else
- /**
- * Set the debug core mask.
- *
- * This determines which cores the power manager is allowed to use.
- *
-- * @param kbdev The kbase device structure for the device (must be a
-- * valid pointer)
-- * @param new_core_mask_js0 The core mask to use for job slot 0
-- * @param new_core_mask_js0 The core mask to use for job slot 1
-- * @param new_core_mask_js0 The core mask to use for job slot 2
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ * @new_core_mask_js0: The core mask to use for job slot 0
-+ * @new_core_mask_js1: The core mask to use for job slot 1
-+ * @new_core_mask_js2: The core mask to use for job slot 2
- */
- void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev,
- u64 new_core_mask_js0, u64 new_core_mask_js1,
- u64 new_core_mask_js2);
--
-+#endif /* MALI_USE_CSF */
-
- /**
- * Get the current policy.
- *
- * Returns the policy that is currently active.
- *
-- * @param kbdev The kbase device structure for the device (must be a valid
-- * pointer)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- *
- * @return The current policy
- */
-@@ -152,10 +153,9 @@ const struct kbase_pm_ca_policy
- /**
- * Change the policy to the one specified.
- *
-- * @param kbdev The kbase device structure for the device (must be a valid
-- * pointer)
-- * @param policy The policy to change to (valid pointer returned from
-- * @ref kbase_pm_ca_list_policies)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ * @policy: The policy to change to (valid pointer returned from
-+ * @ref kbase_pm_ca_list_policies)
- */
- void kbase_pm_ca_set_policy(struct kbase_device *kbdev,
- const struct kbase_pm_ca_policy *policy);
-@@ -163,23 +163,20 @@ void kbase_pm_ca_set_policy(struct kbase_device *kbdev,
- /**
- * Retrieve a static list of the available policies.
- *
-- * @param[out] policies An array pointer to take the list of policies. This may
-- * be NULL. The contents of this array must not be
-- * modified.
-+ * @policies: An array pointer to take the list of policies. This may be NULL.
-+ * The contents of this array must not be modified.
- *
- * @return The number of policies
- */
- int
- kbase_pm_ca_list_policies(const struct kbase_pm_ca_policy * const **policies);
-
--
- /**
- * Get the current policy.
- *
- * Returns the policy that is currently active.
- *
-- * @param kbdev The kbase device structure for the device (must be a valid
-- * pointer)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- *
- * @return The current policy
- */
-@@ -188,9 +185,9 @@ const struct kbase_pm_policy *kbase_pm_get_policy(struct kbase_device *kbdev);
- /**
- * Change the policy to the one specified.
- *
-- * @param kbdev The kbase device structure for the device (must be a valid
-+ * @kbdev: The kbase device structure for the device (must be a valid
- * pointer)
-- * @param policy The policy to change to (valid pointer returned from
-+ * @policy: The policy to change to (valid pointer returned from
- * @ref kbase_pm_list_policies)
- */
- void kbase_pm_set_policy(struct kbase_device *kbdev,
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_time.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_time.h
-index a61e5b9..8a4ece4 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_time.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwaccess_time.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014,2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,13 +16,6 @@
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- */
--
--
--/**
- *
- */
-
-@@ -30,13 +24,27 @@
-
- /**
- * kbase_backend_get_gpu_time() - Get current GPU time
-+ * @kbdev: Device pointer
-+ * @cycle_counter: Pointer to u64 to store cycle counter in.
-+ * @system_time: Pointer to u64 to store system time in
-+ * @ts: Pointer to struct timespec to store current monotonic
-+ * time in
-+ */
-+void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter,
-+ u64 *system_time, struct timespec64 *ts);
-+
-+/**
-+ * kbase_backend_get_gpu_time_norequest() - Get current GPU time without
-+ * request/release cycle counter
- * @kbdev: Device pointer
- * @cycle_counter: Pointer to u64 to store cycle counter in
- * @system_time: Pointer to u64 to store system time in
- * @ts: Pointer to struct timespec to store current monotonic
- * time in
- */
--void kbase_backend_get_gpu_time(struct kbase_device *kbdev, u64 *cycle_counter,
-- u64 *system_time, struct timespec64 *ts);
-+void kbase_backend_get_gpu_time_norequest(struct kbase_device *kbdev,
-+ u64 *cycle_counter,
-+ u64 *system_time,
-+ struct timespec64 *ts);
-
- #endif /* _KBASE_BACKEND_TIME_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt.c
-index 14ec5cb..ea4893d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2018, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -28,9 +27,6 @@
- #include "mali_kbase_hwcnt_accumulator.h"
- #include "mali_kbase_hwcnt_backend.h"
- #include "mali_kbase_hwcnt_types.h"
--#include "mali_malisw.h"
--#include "mali_kbase_debug.h"
--#include "mali_kbase_linux.h"
-
- #include <linux/mutex.h>
- #include <linux/spinlock.h>
-@@ -51,6 +47,7 @@ enum kbase_hwcnt_accum_state {
-
- /**
- * struct kbase_hwcnt_accumulator - Hardware counter accumulator structure.
-+ * @metadata: Pointer to immutable hwcnt metadata.
- * @backend: Pointer to created counter backend.
- * @state: The current state of the accumulator.
- * - State transition from disabled->enabled or
-@@ -89,6 +86,7 @@ enum kbase_hwcnt_accum_state {
- * accum_lock.
- */
- struct kbase_hwcnt_accumulator {
-+ const struct kbase_hwcnt_metadata *metadata;
- struct kbase_hwcnt_backend *backend;
- enum kbase_hwcnt_accum_state state;
- struct kbase_hwcnt_enable_map enable_map;
-@@ -117,6 +115,10 @@ struct kbase_hwcnt_accumulator {
- * state_lock.
- * - Can be read while holding either lock.
- * @accum: Hardware counter accumulator structure.
-+ * @wq: Centralized workqueue for users of hardware counters to
-+ * submit async hardware counter related work. Never directly
-+ * called, but it's expected that a lot of the functions in this
-+ * API will end up called from the enqueued async work.
- */
- struct kbase_hwcnt_context {
- const struct kbase_hwcnt_backend_interface *iface;
-@@ -125,6 +127,7 @@ struct kbase_hwcnt_context {
- struct mutex accum_lock;
- bool accum_inited;
- struct kbase_hwcnt_accumulator accum;
-+ struct workqueue_struct *wq;
- };
-
- int kbase_hwcnt_context_init(
-@@ -138,7 +141,7 @@ int kbase_hwcnt_context_init(
-
- hctx = kzalloc(sizeof(*hctx), GFP_KERNEL);
- if (!hctx)
-- return -ENOMEM;
-+ goto err_alloc_hctx;
-
- hctx->iface = iface;
- spin_lock_init(&hctx->state_lock);
-@@ -146,11 +149,21 @@ int kbase_hwcnt_context_init(
- mutex_init(&hctx->accum_lock);
- hctx->accum_inited = false;
-
-+ hctx->wq =
-+ alloc_workqueue("mali_kbase_hwcnt", WQ_HIGHPRI | WQ_UNBOUND, 0);
-+ if (!hctx->wq)
-+ goto err_alloc_workqueue;
-+
- *out_hctx = hctx;
-
- return 0;
-+
-+ destroy_workqueue(hctx->wq);
-+err_alloc_workqueue:
-+ kfree(hctx);
-+err_alloc_hctx:
-+ return -ENOMEM;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_context_init);
-
- void kbase_hwcnt_context_term(struct kbase_hwcnt_context *hctx)
- {
-@@ -159,9 +172,13 @@ void kbase_hwcnt_context_term(struct kbase_hwcnt_context *hctx)
-
- /* Make sure we didn't leak the accumulator */
- WARN_ON(hctx->accum_inited);
-+
-+ /* We don't expect any work to be pending on this workqueue.
-+ * Regardless, this will safely drain and complete the work.
-+ */
-+ destroy_workqueue(hctx->wq);
- kfree(hctx);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_context_term);
-
- /**
- * kbasep_hwcnt_accumulator_term() - Terminate the accumulator for the context.
-@@ -197,22 +214,23 @@ static int kbasep_hwcnt_accumulator_init(struct kbase_hwcnt_context *hctx)
- if (errcode)
- goto error;
-
-+ hctx->accum.metadata = hctx->iface->metadata(hctx->iface->info);
- hctx->accum.state = ACCUM_STATE_ERROR;
-
-- errcode = kbase_hwcnt_enable_map_alloc(
-- hctx->iface->metadata, &hctx->accum.enable_map);
-+ errcode = kbase_hwcnt_enable_map_alloc(hctx->accum.metadata,
-+ &hctx->accum.enable_map);
- if (errcode)
- goto error;
-
- hctx->accum.enable_map_any_enabled = false;
-
-- errcode = kbase_hwcnt_dump_buffer_alloc(
-- hctx->iface->metadata, &hctx->accum.accum_buf);
-+ errcode = kbase_hwcnt_dump_buffer_alloc(hctx->accum.metadata,
-+ &hctx->accum.accum_buf);
- if (errcode)
- goto error;
-
-- errcode = kbase_hwcnt_enable_map_alloc(
-- hctx->iface->metadata, &hctx->accum.scratch_map);
-+ errcode = kbase_hwcnt_enable_map_alloc(hctx->accum.metadata,
-+ &hctx->accum.scratch_map);
- if (errcode)
- goto error;
-
-@@ -242,6 +260,7 @@ static void kbasep_hwcnt_accumulator_disable(
- bool backend_enabled = false;
- struct kbase_hwcnt_accumulator *accum;
- unsigned long flags;
-+ u64 dump_time_ns;
-
- WARN_ON(!hctx);
- lockdep_assert_held(&hctx->accum_lock);
-@@ -271,7 +290,7 @@ static void kbasep_hwcnt_accumulator_disable(
- goto disable;
-
- /* Try and accumulate before disabling */
-- errcode = hctx->iface->dump_request(accum->backend);
-+ errcode = hctx->iface->dump_request(accum->backend, &dump_time_ns);
- if (errcode)
- goto disable;
-
-@@ -365,8 +384,8 @@ static int kbasep_hwcnt_accumulator_dump(
- WARN_ON(!hctx);
- WARN_ON(!ts_start_ns);
- WARN_ON(!ts_end_ns);
-- WARN_ON(dump_buf && (dump_buf->metadata != hctx->iface->metadata));
-- WARN_ON(new_map && (new_map->metadata != hctx->iface->metadata));
-+ WARN_ON(dump_buf && (dump_buf->metadata != hctx->accum.metadata));
-+ WARN_ON(new_map && (new_map->metadata != hctx->accum.metadata));
- WARN_ON(!hctx->accum_inited);
- lockdep_assert_held(&hctx->accum_lock);
-
-@@ -419,23 +438,16 @@ static int kbasep_hwcnt_accumulator_dump(
-
- /* Initiate the dump if the backend is enabled. */
- if ((state == ACCUM_STATE_ENABLED) && cur_map_any_enabled) {
-- /* Disable pre-emption, to make the timestamp as accurate as
-- * possible.
-- */
-- preempt_disable();
-- {
-+ if (dump_buf) {
-+ errcode = hctx->iface->dump_request(
-+ accum->backend, &dump_time_ns);
-+ dump_requested = true;
-+ } else {
- dump_time_ns = hctx->iface->timestamp_ns(
-- accum->backend);
-- if (dump_buf) {
-- errcode = hctx->iface->dump_request(
- accum->backend);
-- dump_requested = true;
-- } else {
-- errcode = hctx->iface->dump_clear(
-- accum->backend);
-- }
-+ errcode = hctx->iface->dump_clear(accum->backend);
- }
-- preempt_enable();
-+
- if (errcode)
- goto error;
- } else {
-@@ -615,7 +627,6 @@ int kbase_hwcnt_accumulator_acquire(
-
- return 0;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_accumulator_acquire);
-
- void kbase_hwcnt_accumulator_release(struct kbase_hwcnt_accumulator *accum)
- {
-@@ -650,7 +661,6 @@ void kbase_hwcnt_accumulator_release(struct kbase_hwcnt_accumulator *accum)
- spin_unlock_irqrestore(&hctx->state_lock, flags);
- mutex_unlock(&hctx->accum_lock);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_accumulator_release);
-
- void kbase_hwcnt_context_disable(struct kbase_hwcnt_context *hctx)
- {
-@@ -669,7 +679,6 @@ void kbase_hwcnt_context_disable(struct kbase_hwcnt_context *hctx)
-
- mutex_unlock(&hctx->accum_lock);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_context_disable);
-
- bool kbase_hwcnt_context_disable_atomic(struct kbase_hwcnt_context *hctx)
- {
-@@ -698,7 +707,6 @@ bool kbase_hwcnt_context_disable_atomic(struct kbase_hwcnt_context *hctx)
-
- return atomic_disabled;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_context_disable_atomic);
-
- void kbase_hwcnt_context_enable(struct kbase_hwcnt_context *hctx)
- {
-@@ -718,7 +726,6 @@ void kbase_hwcnt_context_enable(struct kbase_hwcnt_context *hctx)
-
- spin_unlock_irqrestore(&hctx->state_lock, flags);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_context_enable);
-
- const struct kbase_hwcnt_metadata *kbase_hwcnt_context_metadata(
- struct kbase_hwcnt_context *hctx)
-@@ -726,9 +733,17 @@ const struct kbase_hwcnt_metadata *kbase_hwcnt_context_metadata(
- if (!hctx)
- return NULL;
-
-- return hctx->iface->metadata;
-+ return hctx->iface->metadata(hctx->iface->info);
-+}
-+
-+bool kbase_hwcnt_context_queue_work(struct kbase_hwcnt_context *hctx,
-+ struct work_struct *work)
-+{
-+ if (WARN_ON(!hctx) || WARN_ON(!work))
-+ return false;
-+
-+ return queue_work(hctx->wq, work);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_context_metadata);
-
- int kbase_hwcnt_accumulator_set_counters(
- struct kbase_hwcnt_accumulator *accum,
-@@ -745,8 +760,8 @@ int kbase_hwcnt_accumulator_set_counters(
-
- hctx = container_of(accum, struct kbase_hwcnt_context, accum);
-
-- if ((new_map->metadata != hctx->iface->metadata) ||
-- (dump_buf && (dump_buf->metadata != hctx->iface->metadata)))
-+ if ((new_map->metadata != hctx->accum.metadata) ||
-+ (dump_buf && (dump_buf->metadata != hctx->accum.metadata)))
- return -EINVAL;
-
- mutex_lock(&hctx->accum_lock);
-@@ -758,7 +773,6 @@ int kbase_hwcnt_accumulator_set_counters(
-
- return errcode;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_accumulator_set_counters);
-
- int kbase_hwcnt_accumulator_dump(
- struct kbase_hwcnt_accumulator *accum,
-@@ -774,7 +788,7 @@ int kbase_hwcnt_accumulator_dump(
-
- hctx = container_of(accum, struct kbase_hwcnt_context, accum);
-
-- if (dump_buf && (dump_buf->metadata != hctx->iface->metadata))
-+ if (dump_buf && (dump_buf->metadata != hctx->accum.metadata))
- return -EINVAL;
-
- mutex_lock(&hctx->accum_lock);
-@@ -786,7 +800,6 @@ int kbase_hwcnt_accumulator_dump(
-
- return errcode;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_accumulator_dump);
-
- u64 kbase_hwcnt_accumulator_timestamp_ns(struct kbase_hwcnt_accumulator *accum)
- {
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_accumulator.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_accumulator.h
-index eb82ea4..4887eaa 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_accumulator.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_accumulator.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend.h
-index b7aa0e1..0b5a188 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -41,11 +40,25 @@ struct kbase_hwcnt_dump_buffer;
- struct kbase_hwcnt_backend_info;
-
- /*
-- * struct kbase_hwcnt_backend_info - Opaque pointer to a hardware counter
-- * backend, used to perform dumps.
-+ * struct kbase_hwcnt_backend - Opaque pointer to a hardware counter
-+ * backend, used to perform dumps.
- */
- struct kbase_hwcnt_backend;
-
-+/*
-+ * typedef kbase_hwcnt_backend_metadata_fn - Get the immutable hardware counter
-+ * metadata that describes the layout
-+ * of the counter data structures.
-+ * @info: Non-NULL pointer to backend info.
-+ *
-+ * Multiple calls to this function with the same info are guaranteed to return
-+ * the same metadata object each time.
-+ *
-+ * Return: Non-NULL pointer to immutable hardware counter metadata.
-+ */
-+typedef const struct kbase_hwcnt_metadata *
-+kbase_hwcnt_backend_metadata_fn(const struct kbase_hwcnt_backend_info *info);
-+
- /**
- * typedef kbase_hwcnt_backend_init_fn - Initialise a counter backend.
- * @info: Non-NULL pointer to backend info.
-@@ -56,16 +69,15 @@ struct kbase_hwcnt_backend;
- *
- * Return: 0 on success, else error code.
- */
--typedef int (*kbase_hwcnt_backend_init_fn)(
-- const struct kbase_hwcnt_backend_info *info,
-- struct kbase_hwcnt_backend **out_backend);
-+typedef int
-+kbase_hwcnt_backend_init_fn(const struct kbase_hwcnt_backend_info *info,
-+ struct kbase_hwcnt_backend **out_backend);
-
- /**
- * typedef kbase_hwcnt_backend_term_fn - Terminate a counter backend.
- * @backend: Pointer to backend to be terminated.
- */
--typedef void (*kbase_hwcnt_backend_term_fn)(
-- struct kbase_hwcnt_backend *backend);
-+typedef void kbase_hwcnt_backend_term_fn(struct kbase_hwcnt_backend *backend);
-
- /**
- * typedef kbase_hwcnt_backend_timestamp_ns_fn - Get the current backend
-@@ -74,8 +86,8 @@ typedef void (*kbase_hwcnt_backend_term_fn)(
- *
- * Return: Backend timestamp in nanoseconds.
- */
--typedef u64 (*kbase_hwcnt_backend_timestamp_ns_fn)(
-- struct kbase_hwcnt_backend *backend);
-+typedef u64
-+kbase_hwcnt_backend_timestamp_ns_fn(struct kbase_hwcnt_backend *backend);
-
- /**
- * typedef kbase_hwcnt_backend_dump_enable_fn - Start counter dumping with the
-@@ -90,7 +102,7 @@ typedef u64 (*kbase_hwcnt_backend_timestamp_ns_fn)(
- *
- * Return: 0 on success, else error code.
- */
--typedef int (*kbase_hwcnt_backend_dump_enable_fn)(
-+typedef int kbase_hwcnt_backend_dump_enable_fn(
- struct kbase_hwcnt_backend *backend,
- const struct kbase_hwcnt_enable_map *enable_map);
-
-@@ -106,7 +118,7 @@ typedef int (*kbase_hwcnt_backend_dump_enable_fn)(
- *
- * Return: 0 on success, else error code.
- */
--typedef int (*kbase_hwcnt_backend_dump_enable_nolock_fn)(
-+typedef int kbase_hwcnt_backend_dump_enable_nolock_fn(
- struct kbase_hwcnt_backend *backend,
- const struct kbase_hwcnt_enable_map *enable_map);
-
-@@ -118,8 +130,8 @@ typedef int (*kbase_hwcnt_backend_dump_enable_nolock_fn)(
- * If the backend is already disabled, does nothing.
- * Any undumped counter values since the last dump get will be lost.
- */
--typedef void (*kbase_hwcnt_backend_dump_disable_fn)(
-- struct kbase_hwcnt_backend *backend);
-+typedef void
-+kbase_hwcnt_backend_dump_disable_fn(struct kbase_hwcnt_backend *backend);
-
- /**
- * typedef kbase_hwcnt_backend_dump_clear_fn - Reset all the current undumped
-@@ -130,21 +142,24 @@ typedef void (*kbase_hwcnt_backend_dump_disable_fn)(
- *
- * Return: 0 on success, else error code.
- */
--typedef int (*kbase_hwcnt_backend_dump_clear_fn)(
-- struct kbase_hwcnt_backend *backend);
-+typedef int
-+kbase_hwcnt_backend_dump_clear_fn(struct kbase_hwcnt_backend *backend);
-
- /**
- * typedef kbase_hwcnt_backend_dump_request_fn - Request an asynchronous counter
- * dump.
- * @backend: Non-NULL pointer to backend.
-+ * @dump_time_ns: Non-NULL pointer where the timestamp of when the dump was
-+ * requested will be written out to on success.
- *
- * If the backend is not enabled or another dump is already in progress,
- * returns an error.
- *
- * Return: 0 on success, else error code.
- */
--typedef int (*kbase_hwcnt_backend_dump_request_fn)(
-- struct kbase_hwcnt_backend *backend);
-+typedef int
-+kbase_hwcnt_backend_dump_request_fn(struct kbase_hwcnt_backend *backend,
-+ u64 *dump_time_ns);
-
- /**
- * typedef kbase_hwcnt_backend_dump_wait_fn - Wait until the last requested
-@@ -155,8 +170,8 @@ typedef int (*kbase_hwcnt_backend_dump_request_fn)(
- *
- * Return: 0 on success, else error code.
- */
--typedef int (*kbase_hwcnt_backend_dump_wait_fn)(
-- struct kbase_hwcnt_backend *backend);
-+typedef int
-+kbase_hwcnt_backend_dump_wait_fn(struct kbase_hwcnt_backend *backend);
-
- /**
- * typedef kbase_hwcnt_backend_dump_get_fn - Copy or accumulate enable the
-@@ -168,24 +183,25 @@ typedef int (*kbase_hwcnt_backend_dump_wait_fn)(
- * @accumulate: True if counters should be accumulated into dump_buffer, rather
- * than copied.
- *
-- * If the backend is not enabled, returns an error.
-- * If a dump is in progress (i.e. dump_wait has not yet returned successfully)
-- * then the resultant contents of the dump buffer will be undefined.
-+ * The resultant contents of the dump buffer are only well defined if a prior
-+ * call to dump_wait returned successfully, and a new dump has not yet been
-+ * requested by a call to dump_request.
- *
- * Return: 0 on success, else error code.
- */
--typedef int (*kbase_hwcnt_backend_dump_get_fn)(
-- struct kbase_hwcnt_backend *backend,
-- struct kbase_hwcnt_dump_buffer *dump_buffer,
-- const struct kbase_hwcnt_enable_map *enable_map,
-- bool accumulate);
-+typedef int
-+kbase_hwcnt_backend_dump_get_fn(struct kbase_hwcnt_backend *backend,
-+ struct kbase_hwcnt_dump_buffer *dump_buffer,
-+ const struct kbase_hwcnt_enable_map *enable_map,
-+ bool accumulate);
-
- /**
- * struct kbase_hwcnt_backend_interface - Hardware counter backend virtual
- * interface.
-- * @metadata: Immutable hardware counter metadata.
- * @info: Immutable info used to initialise an instance of the
- * backend.
-+ * @metadata: Function ptr to get the immutable hardware counter
-+ * metadata.
- * @init: Function ptr to initialise an instance of the backend.
- * @term: Function ptr to terminate an instance of the backend.
- * @timestamp_ns: Function ptr to get the current backend timestamp.
-@@ -200,18 +216,18 @@ typedef int (*kbase_hwcnt_backend_dump_get_fn)(
- * buffer.
- */
- struct kbase_hwcnt_backend_interface {
-- const struct kbase_hwcnt_metadata *metadata;
- const struct kbase_hwcnt_backend_info *info;
-- kbase_hwcnt_backend_init_fn init;
-- kbase_hwcnt_backend_term_fn term;
-- kbase_hwcnt_backend_timestamp_ns_fn timestamp_ns;
-- kbase_hwcnt_backend_dump_enable_fn dump_enable;
-- kbase_hwcnt_backend_dump_enable_nolock_fn dump_enable_nolock;
-- kbase_hwcnt_backend_dump_disable_fn dump_disable;
-- kbase_hwcnt_backend_dump_clear_fn dump_clear;
-- kbase_hwcnt_backend_dump_request_fn dump_request;
-- kbase_hwcnt_backend_dump_wait_fn dump_wait;
-- kbase_hwcnt_backend_dump_get_fn dump_get;
-+ kbase_hwcnt_backend_metadata_fn *metadata;
-+ kbase_hwcnt_backend_init_fn *init;
-+ kbase_hwcnt_backend_term_fn *term;
-+ kbase_hwcnt_backend_timestamp_ns_fn *timestamp_ns;
-+ kbase_hwcnt_backend_dump_enable_fn *dump_enable;
-+ kbase_hwcnt_backend_dump_enable_nolock_fn *dump_enable_nolock;
-+ kbase_hwcnt_backend_dump_disable_fn *dump_disable;
-+ kbase_hwcnt_backend_dump_clear_fn *dump_clear;
-+ kbase_hwcnt_backend_dump_request_fn *dump_request;
-+ kbase_hwcnt_backend_dump_wait_fn *dump_wait;
-+ kbase_hwcnt_backend_dump_get_fn *dump_get;
- };
-
- #endif /* _KBASE_HWCNT_BACKEND_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf.c
-new file mode 100644
-index 0000000..58b5e72
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf.c
-@@ -0,0 +1,1864 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_hwcnt_backend_csf.h"
-+#include "mali_kbase_hwcnt_gpu.h"
-+#include "mali_kbase_hwcnt_types.h"
-+
-+#include <linux/log2.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/wait.h>
-+#include <linux/workqueue.h>
-+#include <linux/completion.h>
-+
-+#ifndef BASE_MAX_NR_CLOCKS_REGULATORS
-+#define BASE_MAX_NR_CLOCKS_REGULATORS 2
-+#endif
-+
-+/**
-+ * enum kbase_hwcnt_backend_csf_dump_state - HWC CSF backend dumping states.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE: Initial state, or the state if there is
-+ * an error.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_DUMP_REQUESTED: A dump has been requested and we are
-+ * waiting for an ACK, this ACK could come from either PRFCNT_ACK,
-+ * PROTMODE_ENTER_ACK, or if an error occurs.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT: Checking the insert
-+ * immediately after receiving the ACK, so we know which index corresponds to
-+ * the buffer we requested.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_DUMP_WORKER_LAUNCHED: The insert has been saved and
-+ * now we have kicked off the worker.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_DUMP_ACCUMULATING: The insert has been saved and now
-+ * we have kicked off the worker to accumulate up to that insert and then copy
-+ * the delta to the user buffer to prepare for dump_get().
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED: The dump completed successfully.
-+ *
-+ * Valid state transitions:
-+ * IDLE -> REQUESTED (on dump request)
-+ * REQUESTED -> QUERYING_INSERT (on dump ack)
-+ * QUERYING_INSERT -> WORKER_LAUNCHED (on worker submission)
-+ * WORKER_LAUNCHED -> ACCUMULATING (while the worker is accumulating)
-+ * ACCUMULATING -> COMPLETED (on accumulation completion)
-+ * COMPLETED -> REQUESTED (on dump request)
-+ * COMPLETED -> IDLE (on disable)
-+ * ANY -> IDLE (on error)
-+ */
-+enum kbase_hwcnt_backend_csf_dump_state {
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE,
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_REQUESTED,
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT,
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_WORKER_LAUNCHED,
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_ACCUMULATING,
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED,
-+};
-+
-+/**
-+ * enum kbase_hwcnt_backend_csf_enable_state - HWC CSF backend enable states.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_DISABLED: Initial state, and the state when backend
-+ * is disabled.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED: Enable request is in
-+ * progress, waiting for firmware acknowledgment.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_ENABLED: Enable request has been acknowledged,
-+ * enable is done.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED: Disable request is in
-+ * progress, waiting for firmware acknowledgment.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER: Disable request has been
-+ * acknowledged, waiting for dump workers to be finished.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER: An
-+ * unrecoverable error happened, waiting for dump workers to be finished.
-+ *
-+ * @KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR: An unrecoverable error
-+ * happened, and dump workers have finished, waiting for reset.
-+ *
-+ * Valid state transitions:
-+ * DISABLED -> TRANSITIONING_TO_ENABLED (on enable)
-+ * TRANSITIONING_TO_ENABLED -> ENABLED (on enable ack)
-+ * ENABLED -> TRANSITIONING_TO_DISABLED (on disable)
-+ * TRANSITIONING_TO_DISABLED -> DISABLED_WAIT_FOR_WORKER (on disable ack)
-+ * DISABLED_WAIT_FOR_WORKER -> DISABLED (after workers are flushed)
-+ * DISABLED -> UNRECOVERABLE_ERROR (on unrecoverable error)
-+ * ANY but DISABLED -> UNRECOVERABLE_ERROR_WAIT_FOR_WORKER (on unrecoverable
-+ * error)
-+ * UNRECOVERABLE_ERROR -> DISABLED (on before reset)
-+ */
-+enum kbase_hwcnt_backend_csf_enable_state {
-+ KBASE_HWCNT_BACKEND_CSF_DISABLED,
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED,
-+ KBASE_HWCNT_BACKEND_CSF_ENABLED,
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED,
-+ KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER,
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER,
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR,
-+};
-+
-+/**
-+ * struct kbase_hwcnt_backend_csf_info - Information used to create an instance
-+ * of a CSF hardware counter backend.
-+ * @backend: Pointer to access CSF backend.
-+ * @fw_in_protected_mode: True if FW is running in protected mode, else
-+ * false.
-+ * @unrecoverable_error_happened: True if an recoverable error happened, else
-+ * false.
-+ * @csf_if: CSF interface object pointer.
-+ * @ring_buf_cnt: Dump buffer count in the ring buffer.
-+ * @counter_set: The performance counter set to use.
-+ * @metadata: Hardware counter metadata.
-+ * @prfcnt_info: Performance counter information.
-+ */
-+struct kbase_hwcnt_backend_csf_info {
-+ struct kbase_hwcnt_backend_csf *backend;
-+ bool fw_in_protected_mode;
-+ bool unrecoverable_error_happened;
-+ struct kbase_hwcnt_backend_csf_if *csf_if;
-+ u32 ring_buf_cnt;
-+ enum kbase_hwcnt_set counter_set;
-+ const struct kbase_hwcnt_metadata *metadata;
-+ struct kbase_hwcnt_backend_csf_if_prfcnt_info prfcnt_info;
-+};
-+
-+/**
-+ * struct kbase_hwcnt_csf_physical_layout - HWC sample memory physical layout
-+ * information.
-+ * @fe_cnt: Front end block count.
-+ * @tiler_cnt: Tiler block count.
-+ * @mmu_l2_cnt: Memory system(MMU and L2 cache) block count.
-+ * @shader_cnt: Shader Core block count.
-+ * @block_cnt: Total block count (sum of all other block counts).
-+ * @shader_avail_mask: Bitmap of all shader cores in the system.
-+ * @offset_enable_mask: Offset of enable mask in the block.
-+ * @headers_per_block: Header size per block.
-+ * @counters_per_block: Counters size per block.
-+ * @values_per_block: Total size per block.
-+ */
-+struct kbase_hwcnt_csf_physical_layout {
-+ size_t fe_cnt;
-+ size_t tiler_cnt;
-+ size_t mmu_l2_cnt;
-+ size_t shader_cnt;
-+ size_t block_cnt;
-+ u64 shader_avail_mask;
-+ size_t offset_enable_mask;
-+ size_t headers_per_block;
-+ size_t counters_per_block;
-+ size_t values_per_block;
-+};
-+
-+/**
-+ * struct kbase_hwcnt_backend_csf - Instance of a CSF hardware counter backend.
-+ * @info: CSF Info used to create the backend.
-+ * @dump_state: The dumping state of the backend.
-+ * @enable_state: The CSF backend internal enabled state.
-+ * @insert_index_to_accumulate: The insert index in the ring buffer which need
-+ * to accumulate up to.
-+ * @enable_state_waitq: Wait queue object used to notify the enable
-+ * changing flag is done.
-+ * @to_user_buf: HWC sample buffer for client user.
-+ * @accum_buf: HWC sample buffer used as an internal
-+ * accumulator.
-+ * @old_sample_buf: HWC sample buffer to save the previous values
-+ * for delta calculation.
-+ * @ring_buf: Opaque pointer for ring buffer object.
-+ * @ring_buf_cpu_base: CPU base address of the allocated ring buffer.
-+ * @clk_enable_map: The enable map specifying enabled clock domains.
-+ * @cycle_count_elapsed: Cycle count elapsed for a given sample period.
-+ * @prev_cycle_count: Previous cycle count to calculate the cycle
-+ * count for sample period.
-+ * @phys_layout: Physical memory layout information of HWC
-+ * sample buffer.
-+ * @dump_completed: Completion signaled by the dump worker when
-+ * it is completed accumulating up to the
-+ * insert_index_to_accumulate.
-+ * Should be initialized to the "complete" state.
-+ * @hwc_dump_workq: Single threaded work queue for HWC workers
-+ * execution.
-+ * @hwc_dump_work: Worker to accumulate samples.
-+ * @hwc_threshold_work: Worker for consuming available samples when
-+ * threshold interrupt raised.
-+ */
-+struct kbase_hwcnt_backend_csf {
-+ struct kbase_hwcnt_backend_csf_info *info;
-+ enum kbase_hwcnt_backend_csf_dump_state dump_state;
-+ enum kbase_hwcnt_backend_csf_enable_state enable_state;
-+ u32 insert_index_to_accumulate;
-+ wait_queue_head_t enable_state_waitq;
-+ u32 *to_user_buf;
-+ u32 *accum_buf;
-+ u32 *old_sample_buf;
-+ struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf;
-+ void *ring_buf_cpu_base;
-+ u64 clk_enable_map;
-+ u64 cycle_count_elapsed[BASE_MAX_NR_CLOCKS_REGULATORS];
-+ u64 prev_cycle_count[BASE_MAX_NR_CLOCKS_REGULATORS];
-+ struct kbase_hwcnt_csf_physical_layout phys_layout;
-+ struct completion dump_completed;
-+ struct workqueue_struct *hwc_dump_workq;
-+ struct work_struct hwc_dump_work;
-+ struct work_struct hwc_threshold_work;
-+};
-+
-+static bool kbasep_hwcnt_backend_csf_backend_exists(
-+ struct kbase_hwcnt_backend_csf_info *csf_info)
-+{
-+ WARN_ON(!csf_info);
-+ csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx);
-+ return (csf_info->backend != NULL);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_cc_initial_sample() - Initialize cycle count
-+ * tracking.
-+ *
-+ * @backend_csf: Non-NULL pointer to backend.
-+ * @enable_map: Non-NULL pointer to enable map specifying enabled counters.
-+ */
-+static void kbasep_hwcnt_backend_csf_cc_initial_sample(
-+ struct kbase_hwcnt_backend_csf *backend_csf,
-+ const struct kbase_hwcnt_enable_map *enable_map)
-+{
-+ u64 clk_enable_map = enable_map->clk_enable_map;
-+ u64 cycle_counts[BASE_MAX_NR_CLOCKS_REGULATORS];
-+ size_t clk;
-+
-+ /* Read cycle count from CSF interface for both clock domains. */
-+ backend_csf->info->csf_if->get_gpu_cycle_count(
-+ backend_csf->info->csf_if->ctx, cycle_counts, clk_enable_map);
-+
-+ kbase_hwcnt_metadata_for_each_clock(enable_map->metadata, clk) {
-+ if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, clk))
-+ backend_csf->prev_cycle_count[clk] = cycle_counts[clk];
-+ }
-+
-+ /* Keep clk_enable_map for dump_request. */
-+ backend_csf->clk_enable_map = clk_enable_map;
-+}
-+
-+static void
-+kbasep_hwcnt_backend_csf_cc_update(struct kbase_hwcnt_backend_csf *backend_csf)
-+{
-+ u64 cycle_counts[BASE_MAX_NR_CLOCKS_REGULATORS];
-+ size_t clk;
-+
-+ backend_csf->info->csf_if->assert_lock_held(
-+ backend_csf->info->csf_if->ctx);
-+
-+ backend_csf->info->csf_if->get_gpu_cycle_count(
-+ backend_csf->info->csf_if->ctx, cycle_counts,
-+ backend_csf->clk_enable_map);
-+
-+ kbase_hwcnt_metadata_for_each_clock(backend_csf->info->metadata, clk) {
-+ if (kbase_hwcnt_clk_enable_map_enabled(
-+ backend_csf->clk_enable_map, clk)) {
-+ backend_csf->cycle_count_elapsed[clk] =
-+ cycle_counts[clk] -
-+ backend_csf->prev_cycle_count[clk];
-+ backend_csf->prev_cycle_count[clk] = cycle_counts[clk];
-+ }
-+ }
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_timestamp_ns_fn */
-+static u64
-+kbasep_hwcnt_backend_csf_timestamp_ns(struct kbase_hwcnt_backend *backend)
-+{
-+ struct kbase_hwcnt_backend_csf *backend_csf =
-+ (struct kbase_hwcnt_backend_csf *)backend;
-+
-+ if (!backend_csf || !backend_csf->info || !backend_csf->info->csf_if)
-+ return 0;
-+
-+ return backend_csf->info->csf_if->timestamp_ns(
-+ backend_csf->info->csf_if->ctx);
-+}
-+
-+/** kbasep_hwcnt_backend_csf_process_enable_map() - Process the enable_map to
-+ * guarantee headers are
-+ * enabled if any counter is
-+ * required.
-+ *@phys_enable_map: HWC physical enable map to be processed.
-+ */
-+static void kbasep_hwcnt_backend_csf_process_enable_map(
-+ struct kbase_hwcnt_physical_enable_map *phys_enable_map)
-+{
-+ WARN_ON(!phys_enable_map);
-+
-+ /* Enable header if any counter is required from user, the header is
-+ * controlled by bit 0 of the enable mask.
-+ */
-+ if (phys_enable_map->fe_bm)
-+ phys_enable_map->fe_bm |= 1;
-+
-+ if (phys_enable_map->tiler_bm)
-+ phys_enable_map->tiler_bm |= 1;
-+
-+ if (phys_enable_map->mmu_l2_bm)
-+ phys_enable_map->mmu_l2_bm |= 1;
-+
-+ if (phys_enable_map->shader_bm)
-+ phys_enable_map->shader_bm |= 1;
-+}
-+
-+static void kbasep_hwcnt_backend_csf_init_layout(
-+ const struct kbase_hwcnt_backend_csf_if_prfcnt_info *prfcnt_info,
-+ struct kbase_hwcnt_csf_physical_layout *phys_layout)
-+{
-+ WARN_ON(!prfcnt_info);
-+ WARN_ON(!phys_layout);
-+
-+ phys_layout->fe_cnt = 1;
-+ phys_layout->tiler_cnt = 1;
-+ phys_layout->mmu_l2_cnt = prfcnt_info->l2_count;
-+ phys_layout->shader_cnt = fls64(prfcnt_info->core_mask);
-+ phys_layout->block_cnt = phys_layout->fe_cnt + phys_layout->tiler_cnt +
-+ phys_layout->mmu_l2_cnt +
-+ phys_layout->shader_cnt;
-+
-+ phys_layout->shader_avail_mask = prfcnt_info->core_mask;
-+
-+ phys_layout->headers_per_block = KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
-+ phys_layout->values_per_block =
-+ prfcnt_info->prfcnt_block_size / KBASE_HWCNT_VALUE_BYTES;
-+ phys_layout->counters_per_block =
-+ phys_layout->values_per_block - phys_layout->headers_per_block;
-+ phys_layout->offset_enable_mask = KBASE_HWCNT_V5_PRFCNT_EN_HEADER;
-+}
-+
-+static void kbasep_hwcnt_backend_csf_reset_internal_buffers(
-+ struct kbase_hwcnt_backend_csf *backend_csf)
-+{
-+ memset(backend_csf->to_user_buf, 0,
-+ backend_csf->info->prfcnt_info.dump_bytes);
-+ memset(backend_csf->accum_buf, 0,
-+ backend_csf->info->prfcnt_info.dump_bytes);
-+ memset(backend_csf->old_sample_buf, 0,
-+ backend_csf->info->prfcnt_info.dump_bytes);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header(
-+ struct kbase_hwcnt_backend_csf *backend_csf, u32 *sample)
-+{
-+ u32 block_idx;
-+ const struct kbase_hwcnt_csf_physical_layout *phys_layout;
-+ u32 *block_buf;
-+
-+ phys_layout = &backend_csf->phys_layout;
-+
-+ for (block_idx = 0; block_idx < phys_layout->block_cnt; block_idx++) {
-+ block_buf = sample + block_idx * phys_layout->values_per_block;
-+ block_buf[phys_layout->offset_enable_mask] = 0;
-+ }
-+}
-+
-+static void kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header(
-+ struct kbase_hwcnt_backend_csf *backend_csf)
-+{
-+ u32 idx;
-+ u32 *sample;
-+ char *cpu_dump_base;
-+ size_t dump_bytes = backend_csf->info->prfcnt_info.dump_bytes;
-+
-+ cpu_dump_base = (char *)backend_csf->ring_buf_cpu_base;
-+
-+ for (idx = 0; idx < backend_csf->info->ring_buf_cnt; idx++) {
-+ sample = (u32 *)&cpu_dump_base[idx * dump_bytes];
-+ kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header(
-+ backend_csf, sample);
-+ }
-+}
-+
-+static void kbasep_hwcnt_backend_csf_update_user_sample(
-+ struct kbase_hwcnt_backend_csf *backend_csf)
-+{
-+ /* Copy the data into the sample and wait for the user to get it. */
-+ memcpy(backend_csf->to_user_buf, backend_csf->accum_buf,
-+ backend_csf->info->prfcnt_info.dump_bytes);
-+
-+ /* After copied data into user sample, clear the accumulator values to
-+ * prepare for the next accumulator, such as the next request or
-+ * threshold.
-+ */
-+ memset(backend_csf->accum_buf, 0,
-+ backend_csf->info->prfcnt_info.dump_bytes);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_accumulate_sample(
-+ const struct kbase_hwcnt_csf_physical_layout *phys_layout,
-+ size_t dump_bytes, u32 *accum_buf, const u32 *old_sample_buf,
-+ const u32 *new_sample_buf, bool clearing_samples)
-+{
-+ size_t block_idx, ctr_idx;
-+ const u32 *old_block = old_sample_buf;
-+ const u32 *new_block = new_sample_buf;
-+ u32 *acc_block = accum_buf;
-+
-+ for (block_idx = 0; block_idx < phys_layout->block_cnt; block_idx++) {
-+ const u32 old_enable_mask =
-+ old_block[phys_layout->offset_enable_mask];
-+ const u32 new_enable_mask =
-+ new_block[phys_layout->offset_enable_mask];
-+
-+ if (new_enable_mask == 0) {
-+ /* Hardware block was unavailable or we didn't turn on
-+ * any counters. Do nothing.
-+ */
-+ } else {
-+ /* Hardware block was available and it had some counters
-+ * enabled. We need to update the accumulation buffer.
-+ */
-+
-+ /* Unconditionally copy the headers. */
-+ memcpy(acc_block, new_block,
-+ phys_layout->headers_per_block *
-+ KBASE_HWCNT_VALUE_BYTES);
-+
-+ /* Accumulate counter samples
-+ *
-+ * When accumulating samples we need to take into
-+ * account whether the counter sampling method involves
-+ * clearing counters back to zero after each sample is
-+ * taken.
-+ *
-+ * The intention for CSF was that all HW should use
-+ * counters which wrap to zero when their maximum value
-+ * is reached. This, combined with non-clearing
-+ * sampling, enables multiple concurrent users to
-+ * request samples without interfering with each other.
-+ *
-+ * However some early HW may not support wrapping
-+ * counters, for these GPUs counters must be cleared on
-+ * sample to avoid loss of data due to counters
-+ * saturating at their maximum value.
-+ */
-+ if (!clearing_samples) {
-+ if (old_enable_mask == 0) {
-+ /* Hardware block was previously
-+ * unavailable. Accumulate the new
-+ * counters only, as we know previous
-+ * values are zeroes.
-+ */
-+ for (ctr_idx =
-+ phys_layout
-+ ->headers_per_block;
-+ ctr_idx <
-+ phys_layout->values_per_block;
-+ ctr_idx++) {
-+ acc_block[ctr_idx] +=
-+ new_block[ctr_idx];
-+ }
-+ } else {
-+ /* Hardware block was previously
-+ * available. Accumulate the delta
-+ * between old and new counter values.
-+ */
-+ for (ctr_idx =
-+ phys_layout
-+ ->headers_per_block;
-+ ctr_idx <
-+ phys_layout->values_per_block;
-+ ctr_idx++) {
-+ acc_block[ctr_idx] +=
-+ new_block[ctr_idx] -
-+ old_block[ctr_idx];
-+ }
-+ }
-+ } else {
-+ for (ctr_idx = phys_layout->headers_per_block;
-+ ctr_idx < phys_layout->values_per_block;
-+ ctr_idx++) {
-+ acc_block[ctr_idx] +=
-+ new_block[ctr_idx];
-+ }
-+ }
-+ }
-+ old_block += phys_layout->values_per_block;
-+ new_block += phys_layout->values_per_block;
-+ acc_block += phys_layout->values_per_block;
-+ }
-+
-+ WARN_ON(old_block !=
-+ old_sample_buf + dump_bytes / KBASE_HWCNT_VALUE_BYTES);
-+ WARN_ON(new_block !=
-+ new_sample_buf + dump_bytes / KBASE_HWCNT_VALUE_BYTES);
-+ WARN_ON(acc_block != accum_buf + dump_bytes / KBASE_HWCNT_VALUE_BYTES);
-+ (void)dump_bytes;
-+}
-+
-+static void kbasep_hwcnt_backend_csf_accumulate_samples(
-+ struct kbase_hwcnt_backend_csf *backend_csf, u32 extract_index_to_start,
-+ u32 insert_index_to_stop)
-+{
-+ u32 raw_idx;
-+ unsigned long flags;
-+ u8 *cpu_dump_base = (u8 *)backend_csf->ring_buf_cpu_base;
-+ const size_t ring_buf_cnt = backend_csf->info->ring_buf_cnt;
-+ const size_t buf_dump_bytes = backend_csf->info->prfcnt_info.dump_bytes;
-+ bool clearing_samples = backend_csf->info->prfcnt_info.clearing_samples;
-+ u32 *old_sample_buf = backend_csf->old_sample_buf;
-+ u32 *new_sample_buf;
-+
-+ if (extract_index_to_start == insert_index_to_stop)
-+ /* No samples to accumulate. Early out. */
-+ return;
-+
-+ /* Sync all the buffers to CPU side before read the data. */
-+ backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx,
-+ backend_csf->ring_buf,
-+ extract_index_to_start,
-+ insert_index_to_stop, true);
-+
-+ /* Consider u32 wrap case, '!=' is used here instead of '<' operator */
-+ for (raw_idx = extract_index_to_start; raw_idx != insert_index_to_stop;
-+ raw_idx++) {
-+ /* The logical "&" acts as a modulo operation since buf_count
-+ * must be a power of two.
-+ */
-+ const u32 buf_idx = raw_idx & (ring_buf_cnt - 1);
-+
-+ new_sample_buf =
-+ (u32 *)&cpu_dump_base[buf_idx * buf_dump_bytes];
-+
-+ kbasep_hwcnt_backend_csf_accumulate_sample(
-+ &backend_csf->phys_layout, buf_dump_bytes,
-+ backend_csf->accum_buf, old_sample_buf, new_sample_buf,
-+ clearing_samples);
-+
-+ old_sample_buf = new_sample_buf;
-+ }
-+
-+ /* Save the newest buffer as the old buffer for next time. */
-+ memcpy(backend_csf->old_sample_buf, new_sample_buf, buf_dump_bytes);
-+
-+ /* Reset the prfcnt_en header on each sample before releasing them. */
-+ for (raw_idx = extract_index_to_start; raw_idx != insert_index_to_stop;
-+ raw_idx++) {
-+ const u32 buf_idx = raw_idx & (ring_buf_cnt - 1);
-+ u32 *sample = (u32 *)&cpu_dump_base[buf_idx * buf_dump_bytes];
-+
-+ kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header(
-+ backend_csf, sample);
-+ }
-+
-+ /* Sync zeroed buffers to avoid coherency issues on future use. */
-+ backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx,
-+ backend_csf->ring_buf,
-+ extract_index_to_start,
-+ insert_index_to_stop, false);
-+
-+ /* After consuming all samples between extract_idx and insert_idx,
-+ * set the raw extract index to insert_idx so that the sample buffers
-+ * can be released back to the ring buffer pool.
-+ */
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+ backend_csf->info->csf_if->set_extract_index(
-+ backend_csf->info->csf_if->ctx, insert_index_to_stop);
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ struct kbase_hwcnt_backend_csf *backend_csf,
-+ enum kbase_hwcnt_backend_csf_enable_state new_state)
-+{
-+ backend_csf->info->csf_if->assert_lock_held(
-+ backend_csf->info->csf_if->ctx);
-+
-+ if (backend_csf->enable_state != new_state) {
-+ backend_csf->enable_state = new_state;
-+
-+ wake_up(&backend_csf->enable_state_waitq);
-+ }
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_dump_worker() - HWC dump worker.
-+ * @work: Work structure.
-+ *
-+ * To accumulate all available samples in the ring buffer when a request has
-+ * been done.
-+ *
-+ */
-+static void kbasep_hwcnt_backend_csf_dump_worker(struct work_struct *work)
-+{
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf *backend_csf;
-+ u32 insert_index_to_acc;
-+ u32 extract_index;
-+ u32 insert_index;
-+
-+ WARN_ON(!work);
-+ backend_csf = container_of(work, struct kbase_hwcnt_backend_csf,
-+ hwc_dump_work);
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+ /* Assert the backend is not destroyed. */
-+ WARN_ON(backend_csf != backend_csf->info->backend);
-+
-+ /* The backend was disabled or had an error while the worker was being
-+ * launched.
-+ */
-+ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) {
-+ WARN_ON(backend_csf->dump_state !=
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE);
-+ WARN_ON(!completion_done(&backend_csf->dump_completed));
-+ backend_csf->info->csf_if->unlock(
-+ backend_csf->info->csf_if->ctx, flags);
-+ return;
-+ }
-+
-+ WARN_ON(backend_csf->dump_state !=
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_WORKER_LAUNCHED);
-+
-+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_ACCUMULATING;
-+ insert_index_to_acc = backend_csf->insert_index_to_accumulate;
-+
-+ /* Read the raw extract and insert indexes from the CSF interface. */
-+ backend_csf->info->csf_if->get_indexes(backend_csf->info->csf_if->ctx,
-+ &extract_index, &insert_index);
-+
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+
-+ /* Accumulate up to the insert we grabbed at the prfcnt request
-+ * interrupt.
-+ */
-+ kbasep_hwcnt_backend_csf_accumulate_samples(backend_csf, extract_index,
-+ insert_index_to_acc);
-+
-+ /* Copy to the user buffer so if a threshold interrupt fires
-+ * between now and get(), the accumulations are untouched.
-+ */
-+ kbasep_hwcnt_backend_csf_update_user_sample(backend_csf);
-+
-+ /* Dump done, set state back to COMPLETED for next request. */
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+ /* Assert the backend is not destroyed. */
-+ WARN_ON(backend_csf != backend_csf->info->backend);
-+
-+ /* The backend was disabled or had an error while we were accumulating.
-+ */
-+ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) {
-+ WARN_ON(backend_csf->dump_state !=
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE);
-+ WARN_ON(!completion_done(&backend_csf->dump_completed));
-+ backend_csf->info->csf_if->unlock(
-+ backend_csf->info->csf_if->ctx, flags);
-+ return;
-+ }
-+
-+ WARN_ON(backend_csf->dump_state !=
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_ACCUMULATING);
-+
-+ /* Our work here is done - set the wait object and unblock waiters. */
-+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED;
-+ complete_all(&backend_csf->dump_completed);
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_threshold_worker() - Threshold worker.
-+ *
-+ * @work: Work structure.
-+ *
-+ * Called when a HWC threshold interrupt raised to consume all available samples
-+ * in the ring buffer.
-+ */
-+static void kbasep_hwcnt_backend_csf_threshold_worker(struct work_struct *work)
-+{
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf *backend_csf;
-+ u32 extract_index;
-+ u32 insert_index;
-+
-+ WARN_ON(!work);
-+
-+ backend_csf = container_of(work, struct kbase_hwcnt_backend_csf,
-+ hwc_threshold_work);
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+
-+ /* Assert the backend is not destroyed. */
-+ WARN_ON(backend_csf != backend_csf->info->backend);
-+
-+ /* Read the raw extract and insert indexes from the CSF interface. */
-+ backend_csf->info->csf_if->get_indexes(backend_csf->info->csf_if->ctx,
-+ &extract_index, &insert_index);
-+
-+ /* The backend was disabled or had an error while the worker was being
-+ * launched.
-+ */
-+ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) {
-+ backend_csf->info->csf_if->unlock(
-+ backend_csf->info->csf_if->ctx, flags);
-+ return;
-+ }
-+
-+ /* Early out if we are not in the IDLE state or COMPLETED state, as this
-+ * means a concurrent dump is in progress and we don't want to
-+ * interfere.
-+ */
-+ if ((backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE) &&
-+ (backend_csf->dump_state !=
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED)) {
-+ backend_csf->info->csf_if->unlock(
-+ backend_csf->info->csf_if->ctx, flags);
-+ return;
-+ }
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+
-+ /* Accumulate everything we possibly can. We grabbed the insert index
-+ * immediately after we acquired the lock but before we checked whether
-+ * a concurrent dump was triggered. This ensures that if a concurrent
-+ * dump was triggered between releasing the lock and now, we know for a
-+ * fact that our insert will not exceed the concurrent dump's
-+ * insert_to_accumulate, so we don't risk accumulating too much data.
-+ */
-+ kbasep_hwcnt_backend_csf_accumulate_samples(backend_csf, extract_index,
-+ insert_index);
-+
-+ /* No need to wake up anything since it is not a user dump request. */
-+}
-+
-+static void kbase_hwcnt_backend_csf_submit_dump_worker(
-+ struct kbase_hwcnt_backend_csf_info *csf_info)
-+{
-+ u32 extract_index;
-+
-+ WARN_ON(!csf_info);
-+ csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx);
-+
-+ WARN_ON(!kbasep_hwcnt_backend_csf_backend_exists(csf_info));
-+ WARN_ON(csf_info->backend->enable_state !=
-+ KBASE_HWCNT_BACKEND_CSF_ENABLED);
-+ WARN_ON(csf_info->backend->dump_state !=
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT);
-+
-+ /* Save insert index now so that the dump worker only accumulates the
-+ * HWC data associated with this request. Extract index is not stored
-+ * as that needs to be checked when accumulating to prevent re-reading
-+ * buffers that have already been read and returned to the GPU.
-+ */
-+ csf_info->csf_if->get_indexes(
-+ csf_info->csf_if->ctx, &extract_index,
-+ &csf_info->backend->insert_index_to_accumulate);
-+ csf_info->backend->dump_state =
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_WORKER_LAUNCHED;
-+
-+ /* Submit the accumulator task into the work queue. */
-+ queue_work(csf_info->backend->hwc_dump_workq,
-+ &csf_info->backend->hwc_dump_work);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_get_physical_enable(
-+ struct kbase_hwcnt_backend_csf *backend_csf,
-+ const struct kbase_hwcnt_enable_map *enable_map,
-+ struct kbase_hwcnt_backend_csf_if_enable *enable)
-+{
-+ enum kbase_hwcnt_physical_set phys_counter_set;
-+ struct kbase_hwcnt_physical_enable_map phys_enable_map;
-+
-+ kbase_hwcnt_gpu_enable_map_to_physical(&phys_enable_map, enable_map);
-+
-+ /* process the enable_map to guarantee the block header is enabled which
-+ * is needed for delta calculation.
-+ */
-+ kbasep_hwcnt_backend_csf_process_enable_map(&phys_enable_map);
-+
-+ kbase_hwcnt_gpu_set_to_physical(&phys_counter_set,
-+ backend_csf->info->counter_set);
-+
-+ /* Use processed enable_map to enable HWC in HW level. */
-+ enable->fe_bm = phys_enable_map.fe_bm;
-+ enable->shader_bm = phys_enable_map.shader_bm;
-+ enable->tiler_bm = phys_enable_map.tiler_bm;
-+ enable->mmu_l2_bm = phys_enable_map.mmu_l2_bm;
-+ enable->counter_set = phys_counter_set;
-+ enable->clk_enable_map = enable_map->clk_enable_map;
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_dump_enable_nolock_fn */
-+static int kbasep_hwcnt_backend_csf_dump_enable_nolock(
-+ struct kbase_hwcnt_backend *backend,
-+ const struct kbase_hwcnt_enable_map *enable_map)
-+{
-+ struct kbase_hwcnt_backend_csf *backend_csf =
-+ (struct kbase_hwcnt_backend_csf *)backend;
-+ struct kbase_hwcnt_backend_csf_if_enable enable;
-+
-+ if (!backend_csf || !enable_map ||
-+ (enable_map->metadata != backend_csf->info->metadata))
-+ return -EINVAL;
-+
-+ backend_csf->info->csf_if->assert_lock_held(
-+ backend_csf->info->csf_if->ctx);
-+
-+ kbasep_hwcnt_backend_csf_get_physical_enable(backend_csf, enable_map,
-+ &enable);
-+
-+ /* enable_state should be DISABLED before we transfer it to enabled */
-+ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED)
-+ return -EIO;
-+
-+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE;
-+ WARN_ON(!completion_done(&backend_csf->dump_completed));
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED);
-+
-+ backend_csf->info->csf_if->dump_enable(backend_csf->info->csf_if->ctx,
-+ backend_csf->ring_buf, &enable);
-+
-+ kbasep_hwcnt_backend_csf_cc_initial_sample(backend_csf, enable_map);
-+
-+ return 0;
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_dump_enable_fn */
-+static int kbasep_hwcnt_backend_csf_dump_enable(
-+ struct kbase_hwcnt_backend *backend,
-+ const struct kbase_hwcnt_enable_map *enable_map)
-+{
-+ int errcode;
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf *backend_csf =
-+ (struct kbase_hwcnt_backend_csf *)backend;
-+
-+ if (!backend_csf)
-+ return -EINVAL;
-+
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+ errcode = kbasep_hwcnt_backend_csf_dump_enable_nolock(backend,
-+ enable_map);
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+ return errcode;
-+}
-+
-+static void kbasep_hwcnt_backend_csf_wait_enable_transition_complete(
-+ struct kbase_hwcnt_backend_csf *backend_csf, unsigned long *lock_flags)
-+{
-+ backend_csf->info->csf_if->assert_lock_held(
-+ backend_csf->info->csf_if->ctx);
-+
-+ while ((backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) ||
-+ (backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED)) {
-+ backend_csf->info->csf_if->unlock(
-+ backend_csf->info->csf_if->ctx, *lock_flags);
-+
-+ wait_event(
-+ backend_csf->enable_state_waitq,
-+ (backend_csf->enable_state !=
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) &&
-+ (backend_csf->enable_state !=
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED));
-+
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx,
-+ lock_flags);
-+ }
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_dump_disable_fn */
-+static void
-+kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend)
-+{
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf *backend_csf =
-+ (struct kbase_hwcnt_backend_csf *)backend;
-+ bool do_disable = false;
-+
-+ WARN_ON(!backend_csf);
-+
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+
-+ /* Make sure we wait until any previous enable or disable have completed
-+ * before doing anything.
-+ */
-+ kbasep_hwcnt_backend_csf_wait_enable_transition_complete(backend_csf,
-+ &flags);
-+
-+ if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_DISABLED ||
-+ backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) {
-+ /* If we are already disabled or in an unrecoverable error
-+ * state, there is nothing for us to do.
-+ */
-+ backend_csf->info->csf_if->unlock(
-+ backend_csf->info->csf_if->ctx, flags);
-+ return;
-+ }
-+
-+ if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) {
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf,
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED);
-+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE;
-+ complete_all(&backend_csf->dump_completed);
-+ /* Only disable if we were previously enabled - in all other
-+ * cases the call to disable will have already been made.
-+ */
-+ do_disable = true;
-+ }
-+
-+ WARN_ON(backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE);
-+ WARN_ON(!completion_done(&backend_csf->dump_completed));
-+
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+
-+ /* Block until any async work has completed. We have transitioned out of
-+ * the ENABLED state so we can guarantee no new work will concurrently
-+ * be submitted.
-+ */
-+ flush_workqueue(backend_csf->hwc_dump_workq);
-+
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+
-+ if (do_disable)
-+ backend_csf->info->csf_if->dump_disable(
-+ backend_csf->info->csf_if->ctx);
-+
-+ kbasep_hwcnt_backend_csf_wait_enable_transition_complete(backend_csf,
-+ &flags);
-+
-+ switch (backend_csf->enable_state) {
-+ case KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER:
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf, KBASE_HWCNT_BACKEND_CSF_DISABLED);
-+ break;
-+ case KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER:
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf,
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR);
-+ break;
-+ default:
-+ WARN_ON(true);
-+ break;
-+ }
-+
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+
-+ /* After disable, zero the header of all buffers in the ring buffer back
-+ * to 0 to prepare for the next enable.
-+ */
-+ kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header(backend_csf);
-+
-+ /* Sync zeroed buffers to avoid coherency issues on future use. */
-+ backend_csf->info->csf_if->ring_buf_sync(
-+ backend_csf->info->csf_if->ctx, backend_csf->ring_buf, 0,
-+ backend_csf->info->ring_buf_cnt, false);
-+
-+ /* Reset accumulator, old_sample_buf and user_sample to all-0 to prepare
-+ * for next enable.
-+ */
-+ kbasep_hwcnt_backend_csf_reset_internal_buffers(backend_csf);
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_dump_request_fn */
-+static int
-+kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *backend,
-+ u64 *dump_time_ns)
-+{
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf *backend_csf =
-+ (struct kbase_hwcnt_backend_csf *)backend;
-+ bool do_request = false;
-+
-+ if (!backend_csf)
-+ return -EINVAL;
-+
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+
-+ /* If we're transitioning to enabled there's nothing to accumulate, and
-+ * the user dump buffer is already zeroed. We can just short circuit to
-+ * the DUMP_COMPLETED state.
-+ */
-+ if (backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) {
-+ backend_csf->dump_state =
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED;
-+ *dump_time_ns = kbasep_hwcnt_backend_csf_timestamp_ns(backend);
-+ kbasep_hwcnt_backend_csf_cc_update(backend_csf);
-+ backend_csf->info->csf_if->unlock(
-+ backend_csf->info->csf_if->ctx, flags);
-+ return 0;
-+ }
-+
-+ /* Otherwise, make sure we're already enabled. */
-+ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) {
-+ backend_csf->info->csf_if->unlock(
-+ backend_csf->info->csf_if->ctx, flags);
-+ return -EIO;
-+ }
-+
-+ /* Make sure that this is either the first request since enable or the
-+ * previous dump has completed, so we can avoid midway through a dump.
-+ */
-+ if ((backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE) &&
-+ (backend_csf->dump_state !=
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED)) {
-+ backend_csf->info->csf_if->unlock(
-+ backend_csf->info->csf_if->ctx, flags);
-+ /* HWC is disabled or another dump is ongoing, or we are on
-+ * fault.
-+ */
-+ return -EIO;
-+ }
-+
-+ /* Reset the completion so dump_wait() has something to wait on. */
-+ reinit_completion(&backend_csf->dump_completed);
-+
-+ if ((backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) &&
-+ !backend_csf->info->fw_in_protected_mode) {
-+ /* Only do the request if we are fully enabled and not in
-+ * protected mode.
-+ */
-+ backend_csf->dump_state =
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_REQUESTED;
-+ do_request = true;
-+ } else {
-+ /* Skip the request and waiting for ack and go straight to
-+ * checking the insert and kicking off the worker to do the dump
-+ */
-+ backend_csf->dump_state =
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT;
-+ }
-+
-+ /* CSF firmware might enter protected mode now, but still call request.
-+ * That is fine, as we changed state while holding the lock, so the
-+ * protected mode enter function will query the insert and launch the
-+ * dumping worker.
-+ * At some point we will get the dump request ACK saying a dump is done,
-+ * but we can ignore it if we are not in the REQUESTED state and process
-+ * it in next round dumping worker.
-+ */
-+
-+ *dump_time_ns = kbasep_hwcnt_backend_csf_timestamp_ns(backend);
-+ kbasep_hwcnt_backend_csf_cc_update(backend_csf);
-+
-+ if (do_request)
-+ backend_csf->info->csf_if->dump_request(
-+ backend_csf->info->csf_if->ctx);
-+ else
-+ kbase_hwcnt_backend_csf_submit_dump_worker(backend_csf->info);
-+
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+ return 0;
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_dump_wait_fn */
-+static int
-+kbasep_hwcnt_backend_csf_dump_wait(struct kbase_hwcnt_backend *backend)
-+{
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf *backend_csf =
-+ (struct kbase_hwcnt_backend_csf *)backend;
-+ int errcode;
-+
-+ if (!backend_csf)
-+ return -EINVAL;
-+
-+ wait_for_completion(&backend_csf->dump_completed);
-+
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+ /* Make sure the last dump actually succeeded. */
-+ errcode = (backend_csf->dump_state ==
-+ KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED) ?
-+ 0 :
-+ -EIO;
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+
-+ return errcode;
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_dump_clear_fn */
-+static int
-+kbasep_hwcnt_backend_csf_dump_clear(struct kbase_hwcnt_backend *backend)
-+{
-+ struct kbase_hwcnt_backend_csf *backend_csf =
-+ (struct kbase_hwcnt_backend_csf *)backend;
-+ int errcode;
-+ u64 ts;
-+
-+ if (!backend_csf)
-+ return -EINVAL;
-+
-+ /* Request a dump so we can clear all current counters. */
-+ errcode = kbasep_hwcnt_backend_csf_dump_request(backend, &ts);
-+ if (!errcode)
-+ /* Wait for the manual dump or auto dump to be done and
-+ * accumulator to be updated.
-+ */
-+ errcode = kbasep_hwcnt_backend_csf_dump_wait(backend);
-+
-+ return errcode;
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_dump_get_fn */
-+static int kbasep_hwcnt_backend_csf_dump_get(
-+ struct kbase_hwcnt_backend *backend,
-+ struct kbase_hwcnt_dump_buffer *dst,
-+ const struct kbase_hwcnt_enable_map *dst_enable_map, bool accumulate)
-+{
-+ struct kbase_hwcnt_backend_csf *backend_csf =
-+ (struct kbase_hwcnt_backend_csf *)backend;
-+ int ret;
-+ size_t clk;
-+
-+ if (!backend_csf || !dst || !dst_enable_map ||
-+ (backend_csf->info->metadata != dst->metadata) ||
-+ (dst_enable_map->metadata != dst->metadata))
-+ return -EINVAL;
-+
-+ kbase_hwcnt_metadata_for_each_clock(dst_enable_map->metadata, clk) {
-+ if (!kbase_hwcnt_clk_enable_map_enabled(
-+ dst_enable_map->clk_enable_map, clk))
-+ continue;
-+
-+ /* Extract elapsed cycle count for each clock domain. */
-+ dst->clk_cnt_buf[clk] = backend_csf->cycle_count_elapsed[clk];
-+ }
-+
-+ /* We just return the user buffer without checking the current state,
-+ * as it is undefined to call this function without a prior succeeding
-+ * one to dump_wait().
-+ */
-+ ret = kbase_hwcnt_csf_dump_get(dst, backend_csf->to_user_buf,
-+ dst_enable_map, accumulate);
-+
-+ return ret;
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_destroy() - Destroy CSF backend.
-+ * @backend_csf: Pointer to CSF backend to destroy.
-+ *
-+ * Can be safely called on a backend in any state of partial construction.
-+ *
-+ */
-+static void
-+kbasep_hwcnt_backend_csf_destroy(struct kbase_hwcnt_backend_csf *backend_csf)
-+{
-+ if (!backend_csf)
-+ return;
-+
-+ destroy_workqueue(backend_csf->hwc_dump_workq);
-+
-+ backend_csf->info->csf_if->ring_buf_free(backend_csf->info->csf_if->ctx,
-+ backend_csf->ring_buf);
-+
-+ kfree(backend_csf->accum_buf);
-+ backend_csf->accum_buf = NULL;
-+
-+ kfree(backend_csf->old_sample_buf);
-+ backend_csf->old_sample_buf = NULL;
-+
-+ kfree(backend_csf->to_user_buf);
-+ backend_csf->to_user_buf = NULL;
-+
-+ kfree(backend_csf);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_create() - Create a CSF backend instance.
-+ *
-+ * @csf_info: Non-NULL pointer to backend info.
-+ * @out_backend: Non-NULL pointer to where backend is stored on success.
-+ * Return: 0 on success, else error code.
-+ */
-+static int
-+kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info *csf_info,
-+ struct kbase_hwcnt_backend_csf **out_backend)
-+{
-+ struct kbase_hwcnt_backend_csf *backend_csf = NULL;
-+ int errcode = -ENOMEM;
-+
-+ WARN_ON(!csf_info);
-+ WARN_ON(!out_backend);
-+
-+ backend_csf = kzalloc(sizeof(*backend_csf), GFP_KERNEL);
-+ if (!backend_csf)
-+ goto alloc_error;
-+
-+ backend_csf->info = csf_info;
-+ kbasep_hwcnt_backend_csf_init_layout(&csf_info->prfcnt_info,
-+ &backend_csf->phys_layout);
-+
-+ backend_csf->accum_buf =
-+ kzalloc(csf_info->prfcnt_info.dump_bytes, GFP_KERNEL);
-+ if (!backend_csf->accum_buf)
-+ goto err_alloc_acc_buf;
-+
-+ backend_csf->old_sample_buf =
-+ kzalloc(csf_info->prfcnt_info.dump_bytes, GFP_KERNEL);
-+ if (!backend_csf->old_sample_buf)
-+ goto err_alloc_pre_sample_buf;
-+
-+ backend_csf->to_user_buf =
-+ kzalloc(csf_info->prfcnt_info.dump_bytes, GFP_KERNEL);
-+ if (!backend_csf->to_user_buf)
-+ goto err_alloc_user_sample_buf;
-+
-+ errcode = csf_info->csf_if->ring_buf_alloc(
-+ csf_info->csf_if->ctx, csf_info->ring_buf_cnt,
-+ &backend_csf->ring_buf_cpu_base, &backend_csf->ring_buf);
-+ if (errcode)
-+ goto err_ring_buf_alloc;
-+
-+ /* Zero all performance enable header to prepare for first enable. */
-+ kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header(backend_csf);
-+
-+ /* Sync zeroed buffers to avoid coherency issues on use. */
-+ backend_csf->info->csf_if->ring_buf_sync(
-+ backend_csf->info->csf_if->ctx, backend_csf->ring_buf, 0,
-+ backend_csf->info->ring_buf_cnt, false);
-+
-+ init_completion(&backend_csf->dump_completed);
-+
-+ init_waitqueue_head(&backend_csf->enable_state_waitq);
-+
-+ /* Allocate a single threaded work queue for dump worker and threshold
-+ * worker.
-+ */
-+ backend_csf->hwc_dump_workq =
-+ alloc_workqueue("mali_hwc_dump_wq", WQ_HIGHPRI | WQ_UNBOUND, 1);
-+ if (!backend_csf->hwc_dump_workq)
-+ goto err_alloc_workqueue;
-+
-+ INIT_WORK(&backend_csf->hwc_dump_work,
-+ kbasep_hwcnt_backend_csf_dump_worker);
-+ INIT_WORK(&backend_csf->hwc_threshold_work,
-+ kbasep_hwcnt_backend_csf_threshold_worker);
-+
-+ backend_csf->enable_state = KBASE_HWCNT_BACKEND_CSF_DISABLED;
-+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE;
-+ complete_all(&backend_csf->dump_completed);
-+
-+ *out_backend = backend_csf;
-+ return 0;
-+
-+ destroy_workqueue(backend_csf->hwc_dump_workq);
-+err_alloc_workqueue:
-+ backend_csf->info->csf_if->ring_buf_free(backend_csf->info->csf_if->ctx,
-+ backend_csf->ring_buf);
-+err_ring_buf_alloc:
-+ kfree(backend_csf->to_user_buf);
-+ backend_csf->to_user_buf = NULL;
-+err_alloc_user_sample_buf:
-+ kfree(backend_csf->old_sample_buf);
-+ backend_csf->old_sample_buf = NULL;
-+err_alloc_pre_sample_buf:
-+ kfree(backend_csf->accum_buf);
-+ backend_csf->accum_buf = NULL;
-+err_alloc_acc_buf:
-+ kfree(backend_csf);
-+alloc_error:
-+ return errcode;
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_init_fn */
-+static int
-+kbasep_hwcnt_backend_csf_init(const struct kbase_hwcnt_backend_info *info,
-+ struct kbase_hwcnt_backend **out_backend)
-+{
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf *backend_csf = NULL;
-+ struct kbase_hwcnt_backend_csf_info *csf_info =
-+ (struct kbase_hwcnt_backend_csf_info *)info;
-+ int errcode;
-+ bool success = false;
-+
-+ if (!info || !out_backend)
-+ return -EINVAL;
-+
-+ /* Create the backend. */
-+ errcode = kbasep_hwcnt_backend_csf_create(csf_info, &backend_csf);
-+ if (errcode)
-+ return errcode;
-+
-+ /* If it was not created before, attach it to csf_info.
-+ * Use spin lock to avoid concurrent initialization.
-+ */
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+ if (csf_info->backend == NULL) {
-+ csf_info->backend = backend_csf;
-+ *out_backend = (struct kbase_hwcnt_backend *)backend_csf;
-+ success = true;
-+ if (csf_info->unrecoverable_error_happened)
-+ backend_csf->enable_state =
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR;
-+ }
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+
-+ /* Destroy the new created backend if the backend has already created
-+ * before. In normal case, this won't happen if the client call init()
-+ * function properly.
-+ */
-+ if (!success) {
-+ kbasep_hwcnt_backend_csf_destroy(backend_csf);
-+ return -EBUSY;
-+ }
-+
-+ return 0;
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_term_fn */
-+static void kbasep_hwcnt_backend_csf_term(struct kbase_hwcnt_backend *backend)
-+{
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf *backend_csf =
-+ (struct kbase_hwcnt_backend_csf *)backend;
-+
-+ if (!backend)
-+ return;
-+
-+ kbasep_hwcnt_backend_csf_dump_disable(backend);
-+
-+ /* Set the backend in csf_info to NULL so we won't handle any external
-+ * notification anymore since we are terminating.
-+ */
-+ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags);
-+ backend_csf->info->backend = NULL;
-+ backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx,
-+ flags);
-+
-+ kbasep_hwcnt_backend_csf_destroy(backend_csf);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_info_destroy() - Destroy a CSF backend info.
-+ * @info: Pointer to info to destroy.
-+ *
-+ * Can be safely called on a backend info in any state of partial construction.
-+ *
-+ */
-+static void kbasep_hwcnt_backend_csf_info_destroy(
-+ const struct kbase_hwcnt_backend_csf_info *info)
-+{
-+ if (!info)
-+ return;
-+
-+ /* The backend should be destroyed before the info object destroy. */
-+ WARN_ON(info->backend != NULL);
-+
-+ /* The metadata should be destroyed before the info object destroy. */
-+ WARN_ON(info->metadata != NULL);
-+
-+ kfree(info);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_info_create() - Create a CSF backend info.
-+ *
-+ * @csf_if: Non-NULL pointer to a hwcnt backend CSF interface structure
-+ * used to create backend interface.
-+ * @ring_buf_cnt: The buffer count of the CSF hwcnt backend ring buffer.
-+ * MUST be power of 2.
-+ * @out_info: Non-NULL pointer to where info is stored on success.
-+ * @return 0 on success, else error code.
-+ */
-+static int kbasep_hwcnt_backend_csf_info_create(
-+ struct kbase_hwcnt_backend_csf_if *csf_if, u32 ring_buf_cnt,
-+ const struct kbase_hwcnt_backend_csf_info **out_info)
-+{
-+ struct kbase_hwcnt_backend_csf_info *info = NULL;
-+
-+ WARN_ON(!csf_if);
-+ WARN_ON(!out_info);
-+ WARN_ON(!is_power_of_2(ring_buf_cnt));
-+
-+ info = kzalloc(sizeof(*info), GFP_KERNEL);
-+ if (!info)
-+ return -ENOMEM;
-+
-+#if defined(CONFIG_MALI_PRFCNT_SET_SECONDARY)
-+ info->counter_set = KBASE_HWCNT_SET_SECONDARY;
-+#elif defined(CONFIG_MALI_PRFCNT_SET_TERTIARY)
-+ info->counter_set = KBASE_HWCNT_SET_TERTIARY;
-+#else
-+ /* Default to primary */
-+ info->counter_set = KBASE_HWCNT_SET_PRIMARY;
-+#endif
-+
-+ info->backend = NULL;
-+ info->csf_if = csf_if;
-+ info->ring_buf_cnt = ring_buf_cnt;
-+ info->fw_in_protected_mode = false;
-+ info->unrecoverable_error_happened = false;
-+
-+ *out_info = info;
-+
-+ return 0;
-+}
-+
-+/* CSF backend implementation of kbase_hwcnt_backend_metadata_fn */
-+static const struct kbase_hwcnt_metadata *
-+kbasep_hwcnt_backend_csf_metadata(const struct kbase_hwcnt_backend_info *info)
-+{
-+ if (!info)
-+ return NULL;
-+
-+ WARN_ON(!((const struct kbase_hwcnt_backend_csf_info *)info)->metadata);
-+
-+ return ((const struct kbase_hwcnt_backend_csf_info *)info)->metadata;
-+}
-+
-+static void kbasep_hwcnt_backend_csf_handle_unrecoverable_error(
-+ struct kbase_hwcnt_backend_csf *backend_csf)
-+{
-+ bool do_disable = false;
-+
-+ backend_csf->info->csf_if->assert_lock_held(
-+ backend_csf->info->csf_if->ctx);
-+
-+ /* We are already in or transitioning to the unrecoverable error state.
-+ * Early out.
-+ */
-+ if ((backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) ||
-+ (backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER))
-+ return;
-+
-+ /* If we are disabled, we know we have no pending workers, so skip the
-+ * waiting state.
-+ */
-+ if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_DISABLED) {
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf,
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR);
-+ return;
-+ }
-+
-+ /* Trigger a disable only if we are not already transitioning to
-+ * disabled, we don't want to disable twice if an unrecoverable error
-+ * happens while we are disabling.
-+ */
-+ do_disable = (backend_csf->enable_state !=
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED);
-+
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf,
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER);
-+
-+ /* Transition the dump to the IDLE state and unblock any waiters. The
-+ * IDLE state signifies an error.
-+ */
-+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE;
-+ complete_all(&backend_csf->dump_completed);
-+
-+ /* Trigger a disable only if we are not already transitioning to
-+ * disabled, - we don't want to disable twice if an unrecoverable error
-+ * happens while we are disabling.
-+ */
-+ if (do_disable)
-+ backend_csf->info->csf_if->dump_disable(
-+ backend_csf->info->csf_if->ctx);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_handle_recoverable_error(
-+ struct kbase_hwcnt_backend_csf *backend_csf)
-+{
-+ backend_csf->info->csf_if->assert_lock_held(
-+ backend_csf->info->csf_if->ctx);
-+
-+ switch (backend_csf->enable_state) {
-+ case KBASE_HWCNT_BACKEND_CSF_DISABLED:
-+ case KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER:
-+ case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED:
-+ case KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR:
-+ case KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER:
-+ /* Already disabled or disabling, or in an unrecoverable error.
-+ * Nothing to be done to handle the error.
-+ */
-+ return;
-+ case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED:
-+ /* A seemingly recoverable error that occurs while we are
-+ * transitioning to enabled is probably unrecoverable.
-+ */
-+ kbasep_hwcnt_backend_csf_handle_unrecoverable_error(
-+ backend_csf);
-+ return;
-+ case KBASE_HWCNT_BACKEND_CSF_ENABLED:
-+ /* Start transitioning to the disabled state. We can't wait for
-+ * it as this recoverable error might be triggered from an
-+ * interrupt. The wait will be done in the eventual call to
-+ * disable().
-+ */
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf,
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED);
-+ /* Transition the dump to the IDLE state and unblock any
-+ * waiters. The IDLE state signifies an error.
-+ */
-+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE;
-+ complete_all(&backend_csf->dump_completed);
-+
-+ backend_csf->info->csf_if->dump_disable(
-+ backend_csf->info->csf_if->ctx);
-+ return;
-+ }
-+}
-+
-+void kbase_hwcnt_backend_csf_protm_entered(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ struct kbase_hwcnt_backend_csf_info *csf_info =
-+ (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+
-+ csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx);
-+ csf_info->fw_in_protected_mode = true;
-+
-+ /* Call on_prfcnt_sample() to trigger collection of the protected mode
-+ * entry auto-sample if there is currently a pending dump request.
-+ */
-+ kbase_hwcnt_backend_csf_on_prfcnt_sample(iface);
-+}
-+
-+void kbase_hwcnt_backend_csf_protm_exited(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+
-+ csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx);
-+ csf_info->fw_in_protected_mode = false;
-+}
-+
-+void kbase_hwcnt_backend_csf_on_unrecoverable_error(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+
-+ csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags);
-+ csf_info->unrecoverable_error_happened = true;
-+ /* Early out if the backend does not exist. */
-+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
-+ csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags);
-+ return;
-+ }
-+
-+ kbasep_hwcnt_backend_csf_handle_unrecoverable_error(csf_info->backend);
-+
-+ csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags);
-+}
-+
-+void kbase_hwcnt_backend_csf_on_before_reset(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ unsigned long flags;
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+ struct kbase_hwcnt_backend_csf *backend_csf;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+
-+ csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags);
-+ csf_info->unrecoverable_error_happened = false;
-+ /* Early out if the backend does not exist. */
-+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
-+ csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags);
-+ return;
-+ }
-+ backend_csf = csf_info->backend;
-+
-+ if ((backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED) &&
-+ (backend_csf->enable_state !=
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR)) {
-+ /* Before a reset occurs, we must either have been disabled
-+ * (else we lose data) or we should have encountered an
-+ * unrecoverable error. Either way, we will have disabled the
-+ * interface and waited for any workers that might have still
-+ * been in flight.
-+ * If not in these states, fire off one more disable to make
-+ * sure everything is turned off before the power is pulled.
-+ * We can't wait for this disable to complete, but it doesn't
-+ * really matter, the power is being pulled.
-+ */
-+ kbasep_hwcnt_backend_csf_handle_unrecoverable_error(
-+ csf_info->backend);
-+ }
-+
-+ /* A reset is the only way to exit the unrecoverable error state */
-+ if (backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) {
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf, KBASE_HWCNT_BACKEND_CSF_DISABLED);
-+ }
-+
-+ csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags);
-+}
-+
-+void kbase_hwcnt_backend_csf_on_prfcnt_sample(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+ struct kbase_hwcnt_backend_csf *backend_csf;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+ csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx);
-+
-+ /* Early out if the backend does not exist. */
-+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info))
-+ return;
-+ backend_csf = csf_info->backend;
-+
-+ /* If the current state is not REQUESTED, this HWC sample will be
-+ * skipped and processed in next dump_request.
-+ */
-+ if (backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_REQUESTED)
-+ return;
-+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT;
-+
-+ kbase_hwcnt_backend_csf_submit_dump_worker(csf_info);
-+}
-+
-+void kbase_hwcnt_backend_csf_on_prfcnt_threshold(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+ struct kbase_hwcnt_backend_csf *backend_csf;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+ csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx);
-+
-+ /* Early out if the backend does not exist. */
-+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info))
-+ return;
-+ backend_csf = csf_info->backend;
-+
-+ if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED)
-+ /* Submit the threshold work into the work queue to consume the
-+ * available samples.
-+ */
-+ queue_work(backend_csf->hwc_dump_workq,
-+ &backend_csf->hwc_threshold_work);
-+}
-+
-+void kbase_hwcnt_backend_csf_on_prfcnt_overflow(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+ csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx);
-+
-+ /* Early out if the backend does not exist. */
-+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info))
-+ return;
-+
-+ /* Called when an overflow occurs. We treat this as a recoverable error,
-+ * so we start transitioning to the disabled state.
-+ * We could try and handle it while enabled, but in a real system we
-+ * never expect an overflow to occur so there is no point implementing
-+ * complex recovery code when we can just turn ourselves off instead for
-+ * a while.
-+ */
-+ kbasep_hwcnt_backend_csf_handle_recoverable_error(csf_info->backend);
-+}
-+
-+void kbase_hwcnt_backend_csf_on_prfcnt_enable(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+ struct kbase_hwcnt_backend_csf *backend_csf;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+ csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx);
-+
-+ /* Early out if the backend does not exist. */
-+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info))
-+ return;
-+ backend_csf = csf_info->backend;
-+
-+ if (backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) {
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf, KBASE_HWCNT_BACKEND_CSF_ENABLED);
-+ } else if (backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_ENABLED) {
-+ /* Unexpected, but we are already in the right state so just
-+ * ignore it.
-+ */
-+ } else {
-+ /* Unexpected state change, assume everything is broken until
-+ * we reset.
-+ */
-+ kbasep_hwcnt_backend_csf_handle_unrecoverable_error(
-+ csf_info->backend);
-+ }
-+}
-+
-+void kbase_hwcnt_backend_csf_on_prfcnt_disable(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+ struct kbase_hwcnt_backend_csf *backend_csf;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+ csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx);
-+
-+ /* Early out if the backend does not exist. */
-+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info))
-+ return;
-+ backend_csf = csf_info->backend;
-+
-+ if (backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED) {
-+ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(
-+ backend_csf,
-+ KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER);
-+ } else if (backend_csf->enable_state ==
-+ KBASE_HWCNT_BACKEND_CSF_DISABLED) {
-+ /* Unexpected, but we are already in the right state so just
-+ * ignore it.
-+ */
-+ } else {
-+ /* Unexpected state change, assume everything is broken until
-+ * we reset.
-+ */
-+ kbasep_hwcnt_backend_csf_handle_unrecoverable_error(
-+ csf_info->backend);
-+ }
-+}
-+
-+int kbase_hwcnt_backend_csf_metadata_init(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ int errcode;
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+ struct kbase_hwcnt_gpu_info gpu_info;
-+
-+ if (!iface)
-+ return -EINVAL;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+
-+ WARN_ON(!csf_info->csf_if->get_prfcnt_info);
-+
-+ csf_info->csf_if->get_prfcnt_info(csf_info->csf_if->ctx,
-+ &csf_info->prfcnt_info);
-+
-+ /* The clock domain counts should not exceed the number of maximum
-+ * number of clock regulators.
-+ */
-+ if (csf_info->prfcnt_info.clk_cnt > BASE_MAX_NR_CLOCKS_REGULATORS)
-+ return -EIO;
-+
-+ gpu_info.l2_count = csf_info->prfcnt_info.l2_count;
-+ gpu_info.core_mask = csf_info->prfcnt_info.core_mask;
-+ gpu_info.clk_cnt = csf_info->prfcnt_info.clk_cnt;
-+ gpu_info.prfcnt_values_per_block =
-+ csf_info->prfcnt_info.prfcnt_block_size /
-+ KBASE_HWCNT_VALUE_BYTES;
-+ errcode = kbase_hwcnt_csf_metadata_create(
-+ &gpu_info, csf_info->counter_set, &csf_info->metadata);
-+ if (errcode)
-+ return errcode;
-+
-+ /*
-+ * Dump abstraction size should be exactly the same size and layout as
-+ * the physical dump size, for backwards compatibility.
-+ */
-+ WARN_ON(csf_info->prfcnt_info.dump_bytes !=
-+ csf_info->metadata->dump_buf_bytes);
-+
-+ return 0;
-+}
-+
-+void kbase_hwcnt_backend_csf_metadata_term(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ struct kbase_hwcnt_backend_csf_info *csf_info;
-+
-+ if (!iface)
-+ return;
-+
-+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
-+ if (csf_info->metadata) {
-+ kbase_hwcnt_csf_metadata_destroy(csf_info->metadata);
-+ csf_info->metadata = NULL;
-+ }
-+}
-+
-+int kbase_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_if *csf_if,
-+ u32 ring_buf_cnt,
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ int errcode;
-+ const struct kbase_hwcnt_backend_csf_info *info = NULL;
-+
-+ if (!iface || !csf_if)
-+ return -EINVAL;
-+
-+ /* The buffer count must be power of 2 */
-+ if (!is_power_of_2(ring_buf_cnt))
-+ return -EINVAL;
-+
-+ errcode = kbasep_hwcnt_backend_csf_info_create(csf_if, ring_buf_cnt,
-+ &info);
-+ if (errcode)
-+ return errcode;
-+
-+ iface->info = (struct kbase_hwcnt_backend_info *)info;
-+ iface->metadata = kbasep_hwcnt_backend_csf_metadata;
-+ iface->init = kbasep_hwcnt_backend_csf_init;
-+ iface->term = kbasep_hwcnt_backend_csf_term;
-+ iface->timestamp_ns = kbasep_hwcnt_backend_csf_timestamp_ns;
-+ iface->dump_enable = kbasep_hwcnt_backend_csf_dump_enable;
-+ iface->dump_enable_nolock = kbasep_hwcnt_backend_csf_dump_enable_nolock;
-+ iface->dump_disable = kbasep_hwcnt_backend_csf_dump_disable;
-+ iface->dump_clear = kbasep_hwcnt_backend_csf_dump_clear;
-+ iface->dump_request = kbasep_hwcnt_backend_csf_dump_request;
-+ iface->dump_wait = kbasep_hwcnt_backend_csf_dump_wait;
-+ iface->dump_get = kbasep_hwcnt_backend_csf_dump_get;
-+
-+ return 0;
-+}
-+
-+void kbase_hwcnt_backend_csf_destroy(struct kbase_hwcnt_backend_interface *iface)
-+{
-+ if (!iface)
-+ return;
-+
-+ kbasep_hwcnt_backend_csf_info_destroy(
-+ (const struct kbase_hwcnt_backend_csf_info *)iface->info);
-+ memset(iface, 0, sizeof(*iface));
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf.h
-new file mode 100644
-index 0000000..ce1af9a
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf.h
-@@ -0,0 +1,162 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/**
-+ * Concrete implementation of mali_kbase_hwcnt_backend interface for CSF
-+ * backend.
-+ */
-+
-+#ifndef _KBASE_HWCNT_BACKEND_CSF_H_
-+#define _KBASE_HWCNT_BACKEND_CSF_H_
-+
-+#include "mali_kbase_hwcnt_backend.h"
-+#include "mali_kbase_hwcnt_backend_csf_if.h"
-+
-+/**
-+ * kbase_hwcnt_backend_csf_create() - Create a CSF hardware counter backend
-+ * interface.
-+ * @csf_if: Non-NULL pointer to a hwcnt backend CSF interface structure
-+ * used to create backend interface.
-+ * @ring_buf_cnt: The buffer count of CSF hwcnt backend, used when allocate ring
-+ * buffer, MUST be power of 2.
-+ * @iface: Non-NULL pointer to backend interface structure that is filled
-+ * in on creation success.
-+ *
-+ * Calls to iface->dump_enable_nolock() require the CSF Scheduler IRQ lock.
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+int kbase_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_if *csf_if,
-+ u32 ring_buf_cnt,
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_metadata_init() - Initialize the metadata for a CSF
-+ * hardware counter backend.
-+ * @iface: Non-NULL pointer to backend interface structure
-+ * Return: 0 on success, else error code.
-+ */
-+int kbase_hwcnt_backend_csf_metadata_init(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_metadata_term() - Terminate the metadata for a CSF
-+ * hardware counter backend.
-+ * @iface: Non-NULL pointer to backend interface structure.
-+ */
-+void kbase_hwcnt_backend_csf_metadata_term(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_destroy() - Destroy a CSF hardware counter backend
-+ * interface.
-+ * @iface: Pointer to interface to destroy.
-+ *
-+ * Can be safely called on an all-zeroed interface, or on an already destroyed
-+ * interface.
-+ */
-+void kbase_hwcnt_backend_csf_destroy(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_protm_entered() - CSF HWC backend function to receive
-+ * notification that protected mode
-+ * has been entered.
-+ * @iface: Non-NULL pointer to HWC backend interface.
-+ */
-+void kbase_hwcnt_backend_csf_protm_entered(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_protm_exited() - CSF HWC backend function to receive
-+ * notification that protected mode has
-+ * been exited.
-+ * @iface: Non-NULL pointer to HWC backend interface.
-+ */
-+void kbase_hwcnt_backend_csf_protm_exited(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_on_unrecoverable_error() - CSF HWC backend function
-+ * called when unrecoverable
-+ * errors are detected.
-+ * @iface: Non-NULL pointer to HWC backend interface.
-+ *
-+ * This should be called on encountering errors that can only be recovered from
-+ * with reset, or that may put HWC logic in state that could result in hang. For
-+ * example, on bus error, or when FW becomes unresponsive.
-+ */
-+void kbase_hwcnt_backend_csf_on_unrecoverable_error(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_on_before_reset() - CSF HWC backend function to be
-+ * called immediately before a
-+ * reset. Takes us out of the
-+ * unrecoverable error state, if we
-+ * were in it.
-+ * @iface: Non-NULL pointer to HWC backend interface.
-+ */
-+void kbase_hwcnt_backend_csf_on_before_reset(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_on_prfcnt_sample() - CSF performance counter sample
-+ * complete interrupt handler.
-+ * @iface: Non-NULL pointer to HWC backend interface.
-+ */
-+void kbase_hwcnt_backend_csf_on_prfcnt_sample(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_on_prfcnt_threshold() - CSF performance counter
-+ * buffer reach threshold
-+ * interrupt handler.
-+ * @iface: Non-NULL pointer to HWC backend interface.
-+ */
-+void kbase_hwcnt_backend_csf_on_prfcnt_threshold(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_on_prfcnt_overflow() - CSF performance counter buffer
-+ * overflow interrupt handler.
-+ * @iface: Non-NULL pointer to HWC backend interface.
-+ */
-+void kbase_hwcnt_backend_csf_on_prfcnt_overflow(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_on_prfcnt_enable() - CSF performance counter enabled
-+ * interrupt handler.
-+ * @iface: Non-NULL pointer to HWC backend interface.
-+ */
-+void kbase_hwcnt_backend_csf_on_prfcnt_enable(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_on_prfcnt_disable() - CSF performance counter
-+ * disabled interrupt handler.
-+ * @iface: Non-NULL pointer to HWC backend interface.
-+ */
-+void kbase_hwcnt_backend_csf_on_prfcnt_disable(
-+ struct kbase_hwcnt_backend_interface *iface);
-+
-+#endif /* _KBASE_HWCNT_BACKEND_CSF_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if.h
-new file mode 100644
-index 0000000..f6387c2
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if.h
-@@ -0,0 +1,311 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * Virtual interface for CSF hardware counter backend.
-+ */
-+
-+#ifndef _KBASE_HWCNT_BACKEND_CSF_IF_H_
-+#define _KBASE_HWCNT_BACKEND_CSF_IF_H_
-+
-+#include <linux/types.h>
-+
-+/**
-+ * struct kbase_hwcnt_backend_csf_if_ctx - Opaque pointer to a CSF interface
-+ * context.
-+ */
-+struct kbase_hwcnt_backend_csf_if_ctx;
-+
-+/**
-+ * struct kbase_hwcnt_backend_csf_if_ring_buf - Opaque pointer to a CSF
-+ * interface ring buffer.
-+ */
-+struct kbase_hwcnt_backend_csf_if_ring_buf;
-+
-+/**
-+ * struct kbase_hwcnt_backend_csf_if_enable - enable hardware counter collection
-+ * structure.
-+ * @fe_bm: Front End counters selection bitmask.
-+ * @shader_bm: Shader counters selection bitmask.
-+ * @tiler_bm: Tiler counters selection bitmask.
-+ * @mmu_l2_bm: MMU_L2 counters selection bitmask.
-+ * @counter_set: The performance counter set to enable.
-+ * @clk_enable_map: An array of u64 bitfields, each bit of which enables cycle
-+ * counter for a given clock domain.
-+ */
-+struct kbase_hwcnt_backend_csf_if_enable {
-+ u32 fe_bm;
-+ u32 shader_bm;
-+ u32 tiler_bm;
-+ u32 mmu_l2_bm;
-+ u8 counter_set;
-+ u64 clk_enable_map;
-+};
-+
-+/**
-+ * struct kbase_hwcnt_backend_csf_if_prfcnt_info - Performance counter
-+ * information.
-+ * @dump_bytes: Bytes of GPU memory required to perform a performance
-+ * counter dump.
-+ * @prfcnt_block_size Bytes of each performance counter block.
-+ * @l2_count: The MMU L2 cache count.
-+ * @core_mask: Shader core mask.
-+ * @clk_cnt: Clock domain count in the system.
-+ * @clearing_samples: Indicates whether counters are cleared after each sample
-+ * is taken.
-+ */
-+struct kbase_hwcnt_backend_csf_if_prfcnt_info {
-+ size_t dump_bytes;
-+ size_t prfcnt_block_size;
-+ size_t l2_count;
-+ u64 core_mask;
-+ u8 clk_cnt;
-+ bool clearing_samples;
-+};
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_assert_lock_held_fn - Assert that the
-+ * backend spinlock is
-+ * held.
-+ * @ctx: Non-NULL pointer to a CSF context.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_assert_lock_held_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_lock_fn - Acquire backend spinlock.
-+ *
-+ * @ctx: Non-NULL pointer to a CSF context.
-+ * @flags: Pointer to the memory location that would store the previous
-+ * interrupt state.
-+ */
-+typedef void
-+kbase_hwcnt_backend_csf_if_lock_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ unsigned long *flags);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_unlock_fn - Release backend spinlock.
-+ *
-+ * @ctx: Non-NULL pointer to a CSF context.
-+ * @flags: Previously stored interrupt state when Scheduler interrupt
-+ * spinlock was acquired.
-+ */
-+typedef void
-+kbase_hwcnt_backend_csf_if_unlock_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ unsigned long flags);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn - Get performance
-+ * counter information.
-+ * @ctx: Non-NULL pointer to a CSF context.
-+ * @prfcnt_info: Non-NULL pointer to struct where performance counter
-+ * information should be stored.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ struct kbase_hwcnt_backend_csf_if_prfcnt_info *prfcnt_info);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn - Allocate a ring buffer
-+ * for CSF interface.
-+ * @ctx: Non-NULL pointer to a CSF context.
-+ * @buf_count: The buffer count in the ring buffer to be allocated,
-+ * MUST be power of 2.
-+ * @cpu_dump_base: Non-NULL pointer to where ring buffer CPU base address is
-+ * stored when success.
-+ * @ring_buf: Non-NULL pointer to where ring buffer is stored when success.
-+ *
-+ * A ring buffer is needed by the CSF interface to do manual HWC sample and
-+ * automatic HWC samples, the buffer count in the ring buffer MUST be power
-+ * of 2 to meet the hardware requirement.
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+typedef int kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 buf_count,
-+ void **cpu_dump_base,
-+ struct kbase_hwcnt_backend_csf_if_ring_buf **ring_buf);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_ring_buf_sync_fn - Sync HWC dump buffers
-+ * memory.
-+ * @ctx: Non-NULL pointer to a CSF context.
-+ * @ring_buf: Non-NULL pointer to the ring buffer.
-+ * @buf_index_first: The first buffer index in the ring buffer to be synced,
-+ * inclusive.
-+ * @buf_index_last: The last buffer index in the ring buffer to be synced,
-+ * exclusive.
-+ * @for_cpu: The direction of sync to be applied, set to true when CPU
-+ * cache needs invalidating before reading the buffer, and set
-+ * to false after CPU writes to flush these before this memory
-+ * is overwritten by the GPU.
-+ *
-+ * Flush cached HWC dump buffer data to ensure that all writes from GPU and CPU
-+ * are correctly observed.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_ring_buf_sync_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf,
-+ u32 buf_index_first, u32 buf_index_last, bool for_cpu);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_ring_buf_free_fn - Free a ring buffer for
-+ * the CSF interface.
-+ *
-+ * @ctx: Non-NULL pointer to a CSF interface context.
-+ * @ring_buf: Non-NULL pointer to the ring buffer which to be freed.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_ring_buf_free_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_timestamp_ns_fn - Get the current
-+ * timestamp of the CSF
-+ * interface.
-+ * @ctx: Non-NULL pointer to a CSF interface context.
-+ *
-+ * Return: CSF interface timestamp in nanoseconds.
-+ */
-+typedef u64 kbase_hwcnt_backend_csf_if_timestamp_ns_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_dump_enable_fn - Setup and enable hardware
-+ * counter in CSF interface.
-+ * @ctx: Non-NULL pointer to a CSF interface context.
-+ * @ring_buf: Non-NULL pointer to the ring buffer which used to setup the HWC.
-+ * @enable: Non-NULL pointer to the enable map of HWC.
-+ *
-+ * Requires lock to be taken before calling.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_dump_enable_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf,
-+ struct kbase_hwcnt_backend_csf_if_enable *enable);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_dump_disable_fn - Disable hardware counter
-+ * in CSF interface.
-+ * @ctx: Non-NULL pointer to a CSF interface context.
-+ *
-+ * Requires lock to be taken before calling.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_dump_disable_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_dump_request_fn - Request a HWC dump.
-+ *
-+ * @ctx: Non-NULL pointer to the interface context.
-+ *
-+ * Requires lock to be taken before calling.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_dump_request_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_get_indexes_fn - Get current extract and
-+ * insert indexes of the
-+ * ring buffer.
-+ *
-+ * @ctx: Non-NULL pointer to a CSF interface context.
-+ * @extract_index: Non-NULL pointer where current extract index to be saved.
-+ * @insert_index: Non-NULL pointer where current insert index to be saved.
-+ *
-+ * Requires lock to be taken before calling.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_get_indexes_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 *extract_index,
-+ u32 *insert_index);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_set_extract_index_fn - Update the extract
-+ * index of the ring
-+ * buffer.
-+ *
-+ * @ctx: Non-NULL pointer to a CSF interface context.
-+ * @extract_index: New extract index to be set.
-+ *
-+ * Requires lock to be taken before calling.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_set_extract_index_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 extract_index);
-+
-+/**
-+ * typedef kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn - Get the current
-+ * GPU cycle count.
-+ * @ctx: Non-NULL pointer to a CSF interface context.
-+ * @cycle_counts: Non-NULL pointer to an array where cycle counts to be saved,
-+ * the array size should be at least as big as the number of
-+ * clock domains returned by get_prfcnt_info interface.
-+ * @clk_enable_map: An array of bitfields, each bit specifies an enabled clock
-+ * domain.
-+ *
-+ * Requires lock to be taken before calling.
-+ */
-+typedef void kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u64 *cycle_counts,
-+ u64 clk_enable_map);
-+
-+/**
-+ * struct kbase_hwcnt_backend_csf_if - Hardware counter backend CSF virtual
-+ * interface.
-+ * @ctx: CSF interface context.
-+ * @assert_lock_held: Function ptr to assert backend spinlock is held.
-+ * @lock: Function ptr to acquire backend spinlock.
-+ * @unlock: Function ptr to release backend spinlock.
-+ * @get_prfcnt_info: Function ptr to get performance counter related
-+ * information.
-+ * @ring_buf_alloc: Function ptr to allocate ring buffer for CSF HWC.
-+ * @ring_buf_sync: Function ptr to sync ring buffer to CPU.
-+ * @ring_buf_free: Function ptr to free ring buffer for CSF HWC.
-+ * @timestamp_ns: Function ptr to get the current CSF interface
-+ * timestamp.
-+ * @dump_enable: Function ptr to enable dumping.
-+ * @dump_enable_nolock: Function ptr to enable dumping while the
-+ * backend-specific spinlock is already held.
-+ * @dump_disable: Function ptr to disable dumping.
-+ * @dump_request: Function ptr to request a dump.
-+ * @get_indexes: Function ptr to get extract and insert indexes of the
-+ * ring buffer.
-+ * @set_extract_index: Function ptr to set extract index of ring buffer.
-+ * @get_gpu_cycle_count: Function ptr to get the GPU cycle count.
-+ */
-+struct kbase_hwcnt_backend_csf_if {
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx;
-+ kbase_hwcnt_backend_csf_if_assert_lock_held_fn *assert_lock_held;
-+ kbase_hwcnt_backend_csf_if_lock_fn *lock;
-+ kbase_hwcnt_backend_csf_if_unlock_fn *unlock;
-+ kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn *get_prfcnt_info;
-+ kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn *ring_buf_alloc;
-+ kbase_hwcnt_backend_csf_if_ring_buf_sync_fn *ring_buf_sync;
-+ kbase_hwcnt_backend_csf_if_ring_buf_free_fn *ring_buf_free;
-+ kbase_hwcnt_backend_csf_if_timestamp_ns_fn *timestamp_ns;
-+ kbase_hwcnt_backend_csf_if_dump_enable_fn *dump_enable;
-+ kbase_hwcnt_backend_csf_if_dump_disable_fn *dump_disable;
-+ kbase_hwcnt_backend_csf_if_dump_request_fn *dump_request;
-+ kbase_hwcnt_backend_csf_if_get_indexes_fn *get_indexes;
-+ kbase_hwcnt_backend_csf_if_set_extract_index_fn *set_extract_index;
-+ kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn *get_gpu_cycle_count;
-+};
-+
-+#endif /* #define _KBASE_HWCNT_BACKEND_CSF_IF_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if_fw.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if_fw.c
-new file mode 100644
-index 0000000..979299f
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if_fw.c
-@@ -0,0 +1,787 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * CSF GPU HWC backend firmware interface APIs.
-+ */
-+
-+#include <mali_kbase.h>
-+#include <gpu/mali_kbase_gpu_regmap.h>
-+#include <device/mali_kbase_device.h>
-+#include "mali_kbase_hwcnt_gpu.h"
-+#include "mali_kbase_hwcnt_types.h"
-+#include <uapi/gpu/arm/midgard/csf/mali_gpu_csf_registers.h>
-+
-+#include "csf/mali_kbase_csf_firmware.h"
-+#include "mali_kbase_hwcnt_backend_csf_if_fw.h"
-+#include "mali_kbase_hwaccess_time.h"
-+#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
-+
-+#include <linux/log2.h>
-+#include "mali_kbase_ccswe.h"
-+
-+
-+/** The number of nanoseconds in a second. */
-+#define NSECS_IN_SEC 1000000000ull /* ns */
-+
-+/* Ring buffer virtual address start at 4GB */
-+#define KBASE_HWC_CSF_RING_BUFFER_VA_START (1ull << 32)
-+
-+/**
-+ * struct kbase_hwcnt_backend_csf_if_fw_ring_buf - ring buffer for CSF interface
-+ * used to save the manual and
-+ * auto HWC samples from
-+ * firmware.
-+ * @gpu_dump_base: Starting GPU base address of the ring buffer.
-+ * @cpu_dump_base: Starting CPU address for the mapping.
-+ * @buf_count: Buffer count in the ring buffer, MUST be power of 2.
-+ * @as_nr: Address space number for the memory mapping.
-+ * @phys: Physical memory allocation used by the mapping.
-+ * @num_pages: Size of the mapping, in memory pages.
-+ */
-+struct kbase_hwcnt_backend_csf_if_fw_ring_buf {
-+ u64 gpu_dump_base;
-+ void *cpu_dump_base;
-+ size_t buf_count;
-+ u32 as_nr;
-+ struct tagged_addr *phys;
-+ size_t num_pages;
-+};
-+
-+/**
-+ * struct kbase_hwcnt_backend_csf_if_fw_ctx - Firmware context for the CSF
-+ * interface, used to communicate
-+ * with firmware.
-+ * @kbdev: KBase device.
-+ * @buf_bytes: The size in bytes for each buffer in the ring buffer.
-+ * @clk_cnt: The number of clock domains in the system.
-+ * The maximum is 64.
-+ * @clk_enable_map: Bitmask of enabled clocks
-+ * @rate_listener: Clock rate listener callback state.
-+ * @ccswe_shader_cores: Shader cores cycle count software estimator.
-+ */
-+struct kbase_hwcnt_backend_csf_if_fw_ctx {
-+ struct kbase_device *kbdev;
-+ size_t buf_bytes;
-+ u8 clk_cnt;
-+ u64 clk_enable_map;
-+ struct kbase_clk_rate_listener rate_listener;
-+ struct kbase_ccswe ccswe_shader_cores;
-+};
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_assert_lock_held(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx;
-+ struct kbase_device *kbdev;
-+
-+ WARN_ON(!ctx);
-+
-+ fw_ctx = (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+ kbdev = fw_ctx->kbdev;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+}
-+
-+static void
-+kbasep_hwcnt_backend_csf_if_fw_lock(struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ unsigned long *flags)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx;
-+ struct kbase_device *kbdev;
-+
-+ WARN_ON(!ctx);
-+
-+ fw_ctx = (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+ kbdev = fw_ctx->kbdev;
-+
-+ kbase_csf_scheduler_spin_lock(kbdev, flags);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_unlock(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, unsigned long flags)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx;
-+ struct kbase_device *kbdev;
-+
-+ WARN_ON(!ctx);
-+
-+ fw_ctx = (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+ kbdev = fw_ctx->kbdev;
-+
-+ kbase_csf_scheduler_spin_lock_assert_held(kbdev);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_if_fw_on_freq_change() - On freq change callback
-+ *
-+ * @rate_listener: Callback state
-+ * @clk_index: Clock index
-+ * @clk_rate_hz: Clock frequency(hz)
-+ */
-+static void kbasep_hwcnt_backend_csf_if_fw_on_freq_change(
-+ struct kbase_clk_rate_listener *rate_listener, u32 clk_index,
-+ u32 clk_rate_hz)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ container_of(rate_listener,
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx,
-+ rate_listener);
-+ u64 timestamp_ns;
-+
-+ if (clk_index != KBASE_CLOCK_DOMAIN_SHADER_CORES)
-+ return;
-+
-+ timestamp_ns = ktime_get_raw_ns();
-+ kbase_ccswe_freq_change(&fw_ctx->ccswe_shader_cores, timestamp_ns,
-+ clk_rate_hz);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_if_fw_cc_enable() - Enable cycle count tracking
-+ *
-+ * @fw_ctx: Non-NULL pointer to CSF firmware interface context.
-+ * @clk_enable_map: Non-NULL pointer to enable map specifying enabled counters.
-+ */
-+static void kbasep_hwcnt_backend_csf_if_fw_cc_enable(
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx, u64 clk_enable_map)
-+{
-+ struct kbase_device *kbdev = fw_ctx->kbdev;
-+
-+ if (kbase_hwcnt_clk_enable_map_enabled(
-+ clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) {
-+ /* software estimation for non-top clock domains */
-+ struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm;
-+ const struct kbase_clk_data *clk_data =
-+ rtm->clks[KBASE_CLOCK_DOMAIN_SHADER_CORES];
-+ u32 cur_freq;
-+ unsigned long flags;
-+ u64 timestamp_ns;
-+
-+ timestamp_ns = ktime_get_raw_ns();
-+
-+ spin_lock_irqsave(&rtm->lock, flags);
-+
-+ cur_freq = (u32)clk_data->clock_val;
-+ kbase_ccswe_reset(&fw_ctx->ccswe_shader_cores);
-+ kbase_ccswe_freq_change(&fw_ctx->ccswe_shader_cores,
-+ timestamp_ns, cur_freq);
-+
-+ kbase_clk_rate_trace_manager_subscribe_no_lock(
-+ rtm, &fw_ctx->rate_listener);
-+
-+ spin_unlock_irqrestore(&rtm->lock, flags);
-+ }
-+
-+ fw_ctx->clk_enable_map = clk_enable_map;
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_if_fw_cc_disable() - Disable cycle count tracking
-+ *
-+ * @fw_ctx: Non-NULL pointer to CSF firmware interface context.
-+ */
-+static void kbasep_hwcnt_backend_csf_if_fw_cc_disable(
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx)
-+{
-+ struct kbase_device *kbdev = fw_ctx->kbdev;
-+ struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm;
-+ u64 clk_enable_map = fw_ctx->clk_enable_map;
-+
-+ if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map,
-+ KBASE_CLOCK_DOMAIN_SHADER_CORES))
-+ kbase_clk_rate_trace_manager_unsubscribe(
-+ rtm, &fw_ctx->rate_listener);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ struct kbase_hwcnt_backend_csf_if_prfcnt_info *prfcnt_info)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx;
-+ struct kbase_device *kbdev;
-+ u32 prfcnt_size;
-+ u32 prfcnt_hw_size = 0;
-+ u32 prfcnt_fw_size = 0;
-+ u32 prfcnt_block_size = KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK *
-+ KBASE_HWCNT_VALUE_BYTES;
-+
-+ WARN_ON(!ctx);
-+ WARN_ON(!prfcnt_info);
-+
-+ fw_ctx = (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+ kbdev = fw_ctx->kbdev;
-+ prfcnt_size = kbdev->csf.global_iface.prfcnt_size;
-+ prfcnt_hw_size = (prfcnt_size & 0xFF) << 8;
-+ prfcnt_fw_size = (prfcnt_size >> 16) << 8;
-+ fw_ctx->buf_bytes = prfcnt_hw_size + prfcnt_fw_size;
-+
-+
-+ prfcnt_info->dump_bytes = fw_ctx->buf_bytes;
-+ prfcnt_info->prfcnt_block_size = prfcnt_block_size;
-+ prfcnt_info->l2_count = kbdev->gpu_props.props.l2_props.num_l2_slices;
-+ prfcnt_info->core_mask =
-+ kbdev->gpu_props.props.coherency_info.group[0].core_mask;
-+
-+ prfcnt_info->clk_cnt = fw_ctx->clk_cnt;
-+ prfcnt_info->clearing_samples = true;
-+
-+ /* Block size must be multiple of counter size. */
-+ WARN_ON((prfcnt_info->prfcnt_block_size % KBASE_HWCNT_VALUE_BYTES) !=
-+ 0);
-+ /* Total size must be multiple of block size. */
-+ WARN_ON((prfcnt_info->dump_bytes % prfcnt_info->prfcnt_block_size) !=
-+ 0);
-+}
-+
-+static int kbasep_hwcnt_backend_csf_if_fw_ring_buf_alloc(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 buf_count,
-+ void **cpu_dump_base,
-+ struct kbase_hwcnt_backend_csf_if_ring_buf **out_ring_buf)
-+{
-+ struct kbase_device *kbdev;
-+ struct tagged_addr *phys;
-+ struct page **page_list;
-+ void *cpu_addr;
-+ int ret;
-+ int i;
-+ size_t num_pages;
-+ u64 flags;
-+ struct kbase_hwcnt_backend_csf_if_fw_ring_buf *fw_ring_buf;
-+
-+ pgprot_t cpu_map_prot = PAGE_KERNEL;
-+ u64 gpu_va_base = KBASE_HWC_CSF_RING_BUFFER_VA_START;
-+
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+
-+ WARN_ON(!ctx);
-+ WARN_ON(!cpu_dump_base);
-+ WARN_ON(!out_ring_buf);
-+
-+ kbdev = fw_ctx->kbdev;
-+
-+ /* The buffer count must be power of 2 */
-+ if (!is_power_of_2(buf_count))
-+ return -EINVAL;
-+
-+ /* alignment failure */
-+ if (gpu_va_base & (2048 - 1))
-+ return -EINVAL;
-+
-+ fw_ring_buf = kzalloc(sizeof(*fw_ring_buf), GFP_KERNEL);
-+ if (!fw_ring_buf)
-+ return -ENOMEM;
-+
-+ num_pages = PFN_UP(fw_ctx->buf_bytes * buf_count);
-+ phys = kmalloc_array(num_pages, sizeof(*phys), GFP_KERNEL);
-+ if (!phys)
-+ goto phys_alloc_error;
-+
-+ page_list = kmalloc_array(num_pages, sizeof(*page_list), GFP_KERNEL);
-+ if (!page_list)
-+ goto page_list_alloc_error;
-+
-+ /* Get physical page for the buffer */
-+ ret = kbase_mem_pool_alloc_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages,
-+ phys, false);
-+ if (ret != num_pages)
-+ goto phys_mem_pool_alloc_error;
-+
-+ /* Get the CPU virtual address */
-+ for (i = 0; i < num_pages; i++)
-+ page_list[i] = as_page(phys[i]);
-+
-+ cpu_addr = vmap(page_list, num_pages, VM_MAP, cpu_map_prot);
-+ if (!cpu_addr)
-+ goto vmap_error;
-+
-+ flags = KBASE_REG_GPU_WR | KBASE_REG_GPU_NX |
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE);
-+
-+ /* Update MMU table */
-+ ret = kbase_mmu_insert_pages(kbdev, &kbdev->csf.mcu_mmu,
-+ gpu_va_base >> PAGE_SHIFT, phys, num_pages,
-+ flags, MCU_AS_NR, KBASE_MEM_GROUP_CSF_FW);
-+ if (ret)
-+ goto mmu_insert_failed;
-+
-+ kfree(page_list);
-+
-+ fw_ring_buf->gpu_dump_base = gpu_va_base;
-+ fw_ring_buf->cpu_dump_base = cpu_addr;
-+ fw_ring_buf->phys = phys;
-+ fw_ring_buf->num_pages = num_pages;
-+ fw_ring_buf->buf_count = buf_count;
-+ fw_ring_buf->as_nr = MCU_AS_NR;
-+
-+ *cpu_dump_base = fw_ring_buf->cpu_dump_base;
-+ *out_ring_buf =
-+ (struct kbase_hwcnt_backend_csf_if_ring_buf *)fw_ring_buf;
-+
-+
-+ return 0;
-+
-+mmu_insert_failed:
-+ vunmap(cpu_addr);
-+vmap_error:
-+ kbase_mem_pool_free_pages(
-+ &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages,
-+ phys, false, false);
-+phys_mem_pool_alloc_error:
-+ kfree(page_list);
-+page_list_alloc_error:
-+ kfree(phys);
-+phys_alloc_error:
-+ kfree(fw_ring_buf);
-+ return -ENOMEM;
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_sync(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf,
-+ u32 buf_index_first, u32 buf_index_last, bool for_cpu)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ring_buf *fw_ring_buf =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ring_buf *)ring_buf;
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+ size_t i;
-+ size_t pg_first;
-+ size_t pg_last;
-+ u64 start_address;
-+ u64 stop_address;
-+ u32 ring_buf_index_first;
-+ u32 ring_buf_index_last;
-+
-+ WARN_ON(!ctx);
-+ WARN_ON(!ring_buf);
-+
-+ /* The index arguments for this function form an inclusive, exclusive
-+ * range.
-+ * However, when masking back to the available buffers we will make this
-+ * inclusive at both ends so full flushes are not 0 -> 0.
-+ */
-+ ring_buf_index_first = buf_index_first & (fw_ring_buf->buf_count - 1);
-+ ring_buf_index_last =
-+ (buf_index_last - 1) & (fw_ring_buf->buf_count - 1);
-+
-+ /* The start address is the offset of the first buffer. */
-+ start_address = fw_ctx->buf_bytes * ring_buf_index_first;
-+ pg_first = start_address >> PAGE_SHIFT;
-+
-+ /* The stop address is the last byte in the final buffer. */
-+ stop_address = (fw_ctx->buf_bytes * (ring_buf_index_last + 1)) - 1;
-+ pg_last = stop_address >> PAGE_SHIFT;
-+
-+ /* Check whether the buffer range wraps. */
-+ if (start_address > stop_address) {
-+ /* sync the first part to the end of ring buffer. */
-+ for (i = pg_first; i < fw_ring_buf->num_pages; i++) {
-+ struct page *pg = as_page(fw_ring_buf->phys[i]);
-+
-+ if (for_cpu) {
-+ kbase_sync_single_for_cpu(fw_ctx->kbdev,
-+ kbase_dma_addr(pg),
-+ PAGE_SIZE,
-+ DMA_BIDIRECTIONAL);
-+ } else {
-+ kbase_sync_single_for_device(fw_ctx->kbdev,
-+ kbase_dma_addr(pg),
-+ PAGE_SIZE,
-+ DMA_BIDIRECTIONAL);
-+ }
-+ }
-+
-+ /* second part starts from page 0. */
-+ pg_first = 0;
-+ }
-+
-+ for (i = pg_first; i <= pg_last; i++) {
-+ struct page *pg = as_page(fw_ring_buf->phys[i]);
-+
-+ if (for_cpu) {
-+ kbase_sync_single_for_cpu(fw_ctx->kbdev,
-+ kbase_dma_addr(pg), PAGE_SIZE,
-+ DMA_BIDIRECTIONAL);
-+ } else {
-+ kbase_sync_single_for_device(fw_ctx->kbdev,
-+ kbase_dma_addr(pg),
-+ PAGE_SIZE,
-+ DMA_BIDIRECTIONAL);
-+ }
-+ }
-+}
-+
-+static u64 kbasep_hwcnt_backend_csf_if_fw_timestamp_ns(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx)
-+{
-+ CSTD_UNUSED(ctx);
-+ return ktime_get_raw_ns();
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_free(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ring_buf *fw_ring_buf =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ring_buf *)ring_buf;
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+
-+ if (!fw_ring_buf)
-+ return;
-+
-+ if (fw_ring_buf->phys) {
-+ u64 gpu_va_base = KBASE_HWC_CSF_RING_BUFFER_VA_START;
-+
-+ WARN_ON(kbase_mmu_teardown_pages(
-+ fw_ctx->kbdev, &fw_ctx->kbdev->csf.mcu_mmu,
-+ gpu_va_base >> PAGE_SHIFT, fw_ring_buf->num_pages,
-+ MCU_AS_NR));
-+
-+ vunmap(fw_ring_buf->cpu_dump_base);
-+
-+ kbase_mem_pool_free_pages(
-+ &fw_ctx->kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW],
-+ fw_ring_buf->num_pages, fw_ring_buf->phys, false,
-+ false);
-+
-+ kfree(fw_ring_buf->phys);
-+
-+ kfree(fw_ring_buf);
-+ }
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_dump_enable(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx,
-+ struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf,
-+ struct kbase_hwcnt_backend_csf_if_enable *enable)
-+{
-+ u32 prfcnt_config;
-+ struct kbase_device *kbdev;
-+ struct kbase_csf_global_iface *global_iface;
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+ struct kbase_hwcnt_backend_csf_if_fw_ring_buf *fw_ring_buf =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ring_buf *)ring_buf;
-+
-+ WARN_ON(!ctx);
-+ WARN_ON(!ring_buf);
-+ WARN_ON(!enable);
-+ kbasep_hwcnt_backend_csf_if_fw_assert_lock_held(ctx);
-+
-+ kbdev = fw_ctx->kbdev;
-+ global_iface = &kbdev->csf.global_iface;
-+
-+ /* Configure */
-+ prfcnt_config = fw_ring_buf->buf_count;
-+ prfcnt_config |= enable->counter_set << PRFCNT_CONFIG_SETSELECT_SHIFT;
-+
-+ /* Configure the ring buffer base address */
-+ kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_JASID,
-+ fw_ring_buf->as_nr);
-+ kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_BASE_LO,
-+ fw_ring_buf->gpu_dump_base & U32_MAX);
-+ kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_BASE_HI,
-+ fw_ring_buf->gpu_dump_base >> 32);
-+
-+ /* Set extract position to 0 */
-+ kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_EXTRACT, 0);
-+
-+ /* Configure the enable bitmap */
-+ kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_CSF_EN,
-+ enable->fe_bm);
-+ kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_SHADER_EN,
-+ enable->shader_bm);
-+ kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_MMU_L2_EN,
-+ enable->mmu_l2_bm);
-+ kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_TILER_EN,
-+ enable->tiler_bm);
-+
-+ /* Configure the HWC set and buffer size */
-+ kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_CONFIG,
-+ prfcnt_config);
-+
-+ kbdev->csf.hwcnt.enable_pending = true;
-+
-+ /* Unmask the interrupts */
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_ACK_IRQ_MASK,
-+ GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK,
-+ GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK);
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_ACK_IRQ_MASK,
-+ GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK,
-+ GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK);
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_ACK_IRQ_MASK,
-+ GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK,
-+ GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK);
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_ACK_IRQ_MASK,
-+ GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK,
-+ GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK);
-+
-+ /* Enable the HWC */
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ,
-+ (1 << GLB_REQ_PRFCNT_ENABLE_SHIFT),
-+ GLB_REQ_PRFCNT_ENABLE_MASK);
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+
-+ prfcnt_config = kbase_csf_firmware_global_input_read(global_iface,
-+ GLB_PRFCNT_CONFIG);
-+
-+ kbasep_hwcnt_backend_csf_if_fw_cc_enable(fw_ctx,
-+ enable->clk_enable_map);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_dump_disable(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx)
-+{
-+ struct kbase_device *kbdev;
-+ struct kbase_csf_global_iface *global_iface;
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+
-+ WARN_ON(!ctx);
-+ kbasep_hwcnt_backend_csf_if_fw_assert_lock_held(ctx);
-+
-+ kbdev = fw_ctx->kbdev;
-+ global_iface = &kbdev->csf.global_iface;
-+
-+ /* Disable the HWC */
-+ kbdev->csf.hwcnt.enable_pending = true;
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ, 0,
-+ GLB_REQ_PRFCNT_ENABLE_MASK);
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+
-+ /* mask the interrupts */
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_ACK_IRQ_MASK, 0,
-+ GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK);
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_ACK_IRQ_MASK, 0,
-+ GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK);
-+ kbase_csf_firmware_global_input_mask(
-+ global_iface, GLB_ACK_IRQ_MASK, 0,
-+ GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK);
-+
-+ /* In case we have a previous request in flight when the disable
-+ * happens.
-+ */
-+ kbdev->csf.hwcnt.request_pending = false;
-+
-+ kbasep_hwcnt_backend_csf_if_fw_cc_disable(fw_ctx);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_dump_request(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx)
-+{
-+ u32 glb_req;
-+ struct kbase_device *kbdev;
-+ struct kbase_csf_global_iface *global_iface;
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+
-+ WARN_ON(!ctx);
-+ kbasep_hwcnt_backend_csf_if_fw_assert_lock_held(ctx);
-+
-+ kbdev = fw_ctx->kbdev;
-+ global_iface = &kbdev->csf.global_iface;
-+
-+ /* Trigger dumping */
-+ kbdev->csf.hwcnt.request_pending = true;
-+ glb_req = kbase_csf_firmware_global_input_read(global_iface, GLB_REQ);
-+ glb_req ^= GLB_REQ_PRFCNT_SAMPLE_MASK;
-+ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ, glb_req,
-+ GLB_REQ_PRFCNT_SAMPLE_MASK);
-+ kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_get_indexes(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 *extract_index,
-+ u32 *insert_index)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+
-+ WARN_ON(!ctx);
-+ WARN_ON(!extract_index);
-+ WARN_ON(!insert_index);
-+ kbasep_hwcnt_backend_csf_if_fw_assert_lock_held(ctx);
-+
-+ *extract_index = kbase_csf_firmware_global_input_read(
-+ &fw_ctx->kbdev->csf.global_iface, GLB_PRFCNT_EXTRACT);
-+ *insert_index = kbase_csf_firmware_global_output(
-+ &fw_ctx->kbdev->csf.global_iface, GLB_PRFCNT_INSERT);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_set_extract_index(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 extract_idx)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+
-+ WARN_ON(!ctx);
-+ kbasep_hwcnt_backend_csf_if_fw_assert_lock_held(ctx);
-+
-+ /* Set the raw extract index to release the buffer back to the ring
-+ * buffer.
-+ */
-+ kbase_csf_firmware_global_input(&fw_ctx->kbdev->csf.global_iface,
-+ GLB_PRFCNT_EXTRACT, extract_idx);
-+}
-+
-+static void kbasep_hwcnt_backend_csf_if_fw_get_gpu_cycle_count(
-+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u64 *cycle_counts,
-+ u64 clk_enable_map)
-+{
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
-+ u8 clk;
-+ u64 timestamp_ns = ktime_get_raw_ns();
-+
-+ WARN_ON(!ctx);
-+ WARN_ON(!cycle_counts);
-+ kbasep_hwcnt_backend_csf_if_fw_assert_lock_held(ctx);
-+
-+ for (clk = 0; clk < fw_ctx->clk_cnt; clk++) {
-+ if (!(clk_enable_map & (1ull << clk)))
-+ continue;
-+
-+ if (clk == KBASE_CLOCK_DOMAIN_TOP) {
-+ /* Read cycle count for top clock domain. */
-+ kbase_backend_get_gpu_time_norequest(
-+ fw_ctx->kbdev, &cycle_counts[clk], NULL, NULL);
-+ } else {
-+ /* Estimate cycle count for non-top clock domain. */
-+ cycle_counts[clk] = kbase_ccswe_cycle_at(
-+ &fw_ctx->ccswe_shader_cores, timestamp_ns);
-+ }
-+ }
-+}
-+
-+/**
-+ * kbasep_hwcnt_backedn_csf_if_fw_cts_destroy() - Destroy a CSF FW interface context.
-+ *
-+ * @fw_ctx: Pointer to context to destroy.
-+ */
-+static void kbasep_hwcnt_backend_csf_if_fw_ctx_destroy(
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx)
-+{
-+ if (!fw_ctx)
-+ return;
-+
-+ kfree(fw_ctx);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_csf_if_fw_ctx_create() - Create a CSF Firmware context.
-+ *
-+ * @kbdev: Non_NULL pointer to kbase device.
-+ * @out_ctx: Non-NULL pointer to where info is stored on success.
-+ * Return: 0 on success, else error code.
-+ */
-+static int kbasep_hwcnt_backend_csf_if_fw_ctx_create(
-+ struct kbase_device *kbdev,
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx **out_ctx)
-+{
-+ u8 clk;
-+ int errcode = -ENOMEM;
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *ctx = NULL;
-+
-+ WARN_ON(!kbdev);
-+ WARN_ON(!out_ctx);
-+
-+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-+ if (!ctx)
-+ goto error;
-+
-+ ctx->kbdev = kbdev;
-+
-+ /* Determine the number of available clock domains. */
-+ for (clk = 0; clk < BASE_MAX_NR_CLOCKS_REGULATORS; clk++) {
-+ if (kbdev->pm.clk_rtm.clks[clk] == NULL)
-+ break;
-+ }
-+ ctx->clk_cnt = clk;
-+
-+ ctx->clk_enable_map = 0;
-+ kbase_ccswe_init(&ctx->ccswe_shader_cores);
-+ ctx->rate_listener.notify =
-+ kbasep_hwcnt_backend_csf_if_fw_on_freq_change;
-+
-+ *out_ctx = ctx;
-+
-+ return 0;
-+error:
-+ kbasep_hwcnt_backend_csf_if_fw_ctx_destroy(ctx);
-+ return errcode;
-+}
-+
-+void kbase_hwcnt_backend_csf_if_fw_destroy(
-+ struct kbase_hwcnt_backend_csf_if *if_fw)
-+{
-+ if (!if_fw)
-+ return;
-+
-+ kbasep_hwcnt_backend_csf_if_fw_ctx_destroy(
-+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)if_fw->ctx);
-+ memset(if_fw, 0, sizeof(*if_fw));
-+}
-+
-+int kbase_hwcnt_backend_csf_if_fw_create(
-+ struct kbase_device *kbdev, struct kbase_hwcnt_backend_csf_if *if_fw)
-+{
-+ int errcode;
-+ struct kbase_hwcnt_backend_csf_if_fw_ctx *ctx = NULL;
-+
-+ if (!kbdev || !if_fw)
-+ return -EINVAL;
-+
-+ errcode = kbasep_hwcnt_backend_csf_if_fw_ctx_create(kbdev, &ctx);
-+ if (errcode)
-+ return errcode;
-+
-+ if_fw->ctx = (struct kbase_hwcnt_backend_csf_if_ctx *)ctx;
-+ if_fw->assert_lock_held =
-+ kbasep_hwcnt_backend_csf_if_fw_assert_lock_held;
-+ if_fw->lock = kbasep_hwcnt_backend_csf_if_fw_lock;
-+ if_fw->unlock = kbasep_hwcnt_backend_csf_if_fw_unlock;
-+ if_fw->get_prfcnt_info = kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info;
-+ if_fw->ring_buf_alloc = kbasep_hwcnt_backend_csf_if_fw_ring_buf_alloc;
-+ if_fw->ring_buf_sync = kbasep_hwcnt_backend_csf_if_fw_ring_buf_sync;
-+ if_fw->ring_buf_free = kbasep_hwcnt_backend_csf_if_fw_ring_buf_free;
-+ if_fw->timestamp_ns = kbasep_hwcnt_backend_csf_if_fw_timestamp_ns;
-+ if_fw->dump_enable = kbasep_hwcnt_backend_csf_if_fw_dump_enable;
-+ if_fw->dump_disable = kbasep_hwcnt_backend_csf_if_fw_dump_disable;
-+ if_fw->dump_request = kbasep_hwcnt_backend_csf_if_fw_dump_request;
-+ if_fw->get_gpu_cycle_count =
-+ kbasep_hwcnt_backend_csf_if_fw_get_gpu_cycle_count;
-+ if_fw->get_indexes = kbasep_hwcnt_backend_csf_if_fw_get_indexes;
-+ if_fw->set_extract_index =
-+ kbasep_hwcnt_backend_csf_if_fw_set_extract_index;
-+
-+ return 0;
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if_fw.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if_fw.h
-new file mode 100644
-index 0000000..b69668b
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_csf_if_fw.h
-@@ -0,0 +1,50 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * Concrete implementation of kbase_hwcnt_backend_csf_if interface for CSF FW
-+ */
-+
-+#ifndef _KBASE_HWCNT_BACKEND_CSF_IF_FW_H_
-+#define _KBASE_HWCNT_BACKEND_CSF_IF_FW_H_
-+
-+#include "mali_kbase_hwcnt_backend_csf_if.h"
-+
-+/**
-+ * kbase_hwcnt_backend_csf_if_fw_create() - Create a firmware CSF interface
-+ * of hardware counter backend.
-+ * @kbdev: Non-NULL pointer to Kbase device.
-+ * @if_fw: Non-NULL pointer to backend interface structure that is filled in on
-+ * creation success.
-+ * Return: 0 on success, else error code.
-+ */
-+int kbase_hwcnt_backend_csf_if_fw_create(
-+ struct kbase_device *kbdev, struct kbase_hwcnt_backend_csf_if *if_fw);
-+
-+/**
-+ * kbase_hwcnt_backend_csf_if_fw_destroy() - Destroy a firmware CSF interface of
-+ * hardware counter backend.
-+ * @if_fw: Pointer to a CSF interface to destroy.
-+ */
-+void kbase_hwcnt_backend_csf_if_fw_destroy(
-+ struct kbase_hwcnt_backend_csf_if *if_fw);
-+
-+#endif /* _KBASE_HWCNT_BACKEND_CSF_IF_FW_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_gpu.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_gpu.c
-deleted file mode 100644
-index 407c768..0000000
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_gpu.c
-+++ /dev/null
-@@ -1,510 +0,0 @@
--/*
-- *
-- * (C) COPYRIGHT 2018-2020 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- */
--
--#include "mali_kbase_hwcnt_backend_gpu.h"
--#include "mali_kbase_hwcnt_gpu.h"
--#include "mali_kbase_hwcnt_types.h"
--#include "mali_kbase.h"
--#include "mali_kbase_pm_ca.h"
--#include "mali_kbase_hwaccess_instr.h"
--#ifdef CONFIG_MALI_NO_MALI
--#include "backend/gpu/mali_kbase_model_dummy.h"
--#endif
--
--
--/**
-- * struct kbase_hwcnt_backend_gpu_info - Information used to create an instance
-- * of a GPU hardware counter backend.
-- * @kbdev: KBase device.
-- * @use_secondary: True if secondary performance counters should be used,
-- * else false. Ignored if secondary counters are not supported.
-- * @metadata: Hardware counter metadata.
-- * @dump_bytes: Bytes of GPU memory required to perform a
-- * hardware counter dump.
-- */
--struct kbase_hwcnt_backend_gpu_info {
-- struct kbase_device *kbdev;
-- bool use_secondary;
-- const struct kbase_hwcnt_metadata *metadata;
-- size_t dump_bytes;
--};
--
--/**
-- * struct kbase_hwcnt_backend_gpu - Instance of a GPU hardware counter backend.
-- * @info: Info used to create the backend.
-- * @kctx: KBase context used for GPU memory allocation and
-- * counter dumping.
-- * @gpu_dump_va: GPU hardware counter dump buffer virtual address.
-- * @cpu_dump_va: CPU mapping of gpu_dump_va.
-- * @vmap: Dump buffer vmap.
-- * @enabled: True if dumping has been enabled, else false.
-- * @pm_core_mask: PM state sync-ed shaders core mask for the enabled dumping.
-- */
--struct kbase_hwcnt_backend_gpu {
-- const struct kbase_hwcnt_backend_gpu_info *info;
-- struct kbase_context *kctx;
-- u64 gpu_dump_va;
-- void *cpu_dump_va;
-- struct kbase_vmap_struct *vmap;
-- bool enabled;
-- u64 pm_core_mask;
--};
--
--/* GPU backend implementation of kbase_hwcnt_backend_timestamp_ns_fn */
--static u64 kbasep_hwcnt_backend_gpu_timestamp_ns(
-- struct kbase_hwcnt_backend *backend)
--{
-- (void)backend;
-- return ktime_get_raw_ns();
--}
--
--/* GPU backend implementation of kbase_hwcnt_backend_dump_enable_nolock_fn */
--static int kbasep_hwcnt_backend_gpu_dump_enable_nolock(
-- struct kbase_hwcnt_backend *backend,
-- const struct kbase_hwcnt_enable_map *enable_map)
--{
-- int errcode;
-- struct kbase_hwcnt_backend_gpu *backend_gpu =
-- (struct kbase_hwcnt_backend_gpu *)backend;
-- struct kbase_context *kctx;
-- struct kbase_device *kbdev;
-- struct kbase_hwcnt_physical_enable_map phys;
-- struct kbase_instr_hwcnt_enable enable;
--
-- if (!backend_gpu || !enable_map || backend_gpu->enabled ||
-- (enable_map->metadata != backend_gpu->info->metadata))
-- return -EINVAL;
--
-- kctx = backend_gpu->kctx;
-- kbdev = backend_gpu->kctx->kbdev;
--
-- lockdep_assert_held(&kbdev->hwaccess_lock);
--
-- kbase_hwcnt_gpu_enable_map_to_physical(&phys, enable_map);
--
-- enable.jm_bm = phys.jm_bm;
-- enable.shader_bm = phys.shader_bm;
-- enable.tiler_bm = phys.tiler_bm;
-- enable.mmu_l2_bm = phys.mmu_l2_bm;
-- enable.use_secondary = backend_gpu->info->use_secondary;
-- enable.dump_buffer = backend_gpu->gpu_dump_va;
-- enable.dump_buffer_bytes = backend_gpu->info->dump_bytes;
--
-- errcode = kbase_instr_hwcnt_enable_internal(kbdev, kctx, &enable);
-- if (errcode)
-- goto error;
--
-- backend_gpu->pm_core_mask = kbase_pm_ca_get_instr_core_mask(kbdev);
-- backend_gpu->enabled = true;
--
-- return 0;
--error:
-- return errcode;
--}
--
--/* GPU backend implementation of kbase_hwcnt_backend_dump_enable_fn */
--static int kbasep_hwcnt_backend_gpu_dump_enable(
-- struct kbase_hwcnt_backend *backend,
-- const struct kbase_hwcnt_enable_map *enable_map)
--{
-- unsigned long flags;
-- int errcode;
-- struct kbase_hwcnt_backend_gpu *backend_gpu =
-- (struct kbase_hwcnt_backend_gpu *)backend;
-- struct kbase_device *kbdev;
--
-- if (!backend_gpu)
-- return -EINVAL;
--
-- kbdev = backend_gpu->kctx->kbdev;
--
-- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
--
-- errcode = kbasep_hwcnt_backend_gpu_dump_enable_nolock(
-- backend, enable_map);
--
-- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
--
-- return errcode;
--}
--
--/* GPU backend implementation of kbase_hwcnt_backend_dump_disable_fn */
--static void kbasep_hwcnt_backend_gpu_dump_disable(
-- struct kbase_hwcnt_backend *backend)
--{
-- int errcode;
-- struct kbase_hwcnt_backend_gpu *backend_gpu =
-- (struct kbase_hwcnt_backend_gpu *)backend;
--
-- if (WARN_ON(!backend_gpu) || !backend_gpu->enabled)
-- return;
--
-- errcode = kbase_instr_hwcnt_disable_internal(backend_gpu->kctx);
-- WARN_ON(errcode);
--
-- backend_gpu->enabled = false;
--}
--
--/* GPU backend implementation of kbase_hwcnt_backend_dump_clear_fn */
--static int kbasep_hwcnt_backend_gpu_dump_clear(
-- struct kbase_hwcnt_backend *backend)
--{
-- struct kbase_hwcnt_backend_gpu *backend_gpu =
-- (struct kbase_hwcnt_backend_gpu *)backend;
--
-- if (!backend_gpu || !backend_gpu->enabled)
-- return -EINVAL;
--
-- return kbase_instr_hwcnt_clear(backend_gpu->kctx);
--}
--
--/* GPU backend implementation of kbase_hwcnt_backend_dump_request_fn */
--static int kbasep_hwcnt_backend_gpu_dump_request(
-- struct kbase_hwcnt_backend *backend)
--{
-- struct kbase_hwcnt_backend_gpu *backend_gpu =
-- (struct kbase_hwcnt_backend_gpu *)backend;
--
-- if (!backend_gpu || !backend_gpu->enabled)
-- return -EINVAL;
--
-- return kbase_instr_hwcnt_request_dump(backend_gpu->kctx);
--}
--
--/* GPU backend implementation of kbase_hwcnt_backend_dump_wait_fn */
--static int kbasep_hwcnt_backend_gpu_dump_wait(
-- struct kbase_hwcnt_backend *backend)
--{
-- struct kbase_hwcnt_backend_gpu *backend_gpu =
-- (struct kbase_hwcnt_backend_gpu *)backend;
--
-- if (!backend_gpu || !backend_gpu->enabled)
-- return -EINVAL;
--
-- return kbase_instr_hwcnt_wait_for_dump(backend_gpu->kctx);
--}
--
--/* GPU backend implementation of kbase_hwcnt_backend_dump_get_fn */
--static int kbasep_hwcnt_backend_gpu_dump_get(
-- struct kbase_hwcnt_backend *backend,
-- struct kbase_hwcnt_dump_buffer *dst,
-- const struct kbase_hwcnt_enable_map *dst_enable_map,
-- bool accumulate)
--{
-- struct kbase_hwcnt_backend_gpu *backend_gpu =
-- (struct kbase_hwcnt_backend_gpu *)backend;
--
-- if (!backend_gpu || !dst || !dst_enable_map ||
-- (backend_gpu->info->metadata != dst->metadata) ||
-- (dst_enable_map->metadata != dst->metadata))
-- return -EINVAL;
--
-- /* Invalidate the kernel buffer before reading from it. */
-- kbase_sync_mem_regions(
-- backend_gpu->kctx, backend_gpu->vmap, KBASE_SYNC_TO_CPU);
--
-- return kbase_hwcnt_gpu_dump_get(
-- dst, backend_gpu->cpu_dump_va, dst_enable_map,
-- backend_gpu->pm_core_mask, accumulate);
--}
--
--/**
-- * kbasep_hwcnt_backend_gpu_dump_alloc() - Allocate a GPU dump buffer.
-- * @info: Non-NULL pointer to GPU backend info.
-- * @kctx: Non-NULL pointer to kbase context.
-- * @gpu_dump_va: Non-NULL pointer to where GPU dump buffer virtual address
-- * is stored on success.
-- *
-- * Return: 0 on success, else error code.
-- */
--static int kbasep_hwcnt_backend_gpu_dump_alloc(
-- const struct kbase_hwcnt_backend_gpu_info *info,
-- struct kbase_context *kctx,
-- u64 *gpu_dump_va)
--{
-- struct kbase_va_region *reg;
-- u64 flags;
-- u64 nr_pages;
--
-- WARN_ON(!info);
-- WARN_ON(!kctx);
-- WARN_ON(!gpu_dump_va);
--
-- flags = BASE_MEM_PROT_CPU_RD |
-- BASE_MEM_PROT_GPU_WR |
-- BASEP_MEM_PERMANENT_KERNEL_MAPPING |
-- BASE_MEM_CACHED_CPU;
--
-- if (kctx->kbdev->mmu_mode->flags & KBASE_MMU_MODE_HAS_NON_CACHEABLE)
-- flags |= BASE_MEM_UNCACHED_GPU;
--
-- nr_pages = PFN_UP(info->dump_bytes);
--
-- reg = kbase_mem_alloc(kctx, nr_pages, nr_pages, 0, &flags, gpu_dump_va);
--
-- if (!reg)
-- return -ENOMEM;
--
-- return 0;
--}
--
--/**
-- * kbasep_hwcnt_backend_gpu_dump_free() - Free an allocated GPU dump buffer.
-- * @kctx: Non-NULL pointer to kbase context.
-- * @gpu_dump_va: GPU dump buffer virtual address.
-- */
--static void kbasep_hwcnt_backend_gpu_dump_free(
-- struct kbase_context *kctx,
-- u64 gpu_dump_va)
--{
-- WARN_ON(!kctx);
-- if (gpu_dump_va)
-- kbase_mem_free(kctx, gpu_dump_va);
--}
--
--/**
-- * kbasep_hwcnt_backend_gpu_destroy() - Destroy a GPU backend.
-- * @backend: Pointer to GPU backend to destroy.
-- *
-- * Can be safely called on a backend in any state of partial construction.
-- */
--static void kbasep_hwcnt_backend_gpu_destroy(
-- struct kbase_hwcnt_backend_gpu *backend)
--{
-- if (!backend)
-- return;
--
-- if (backend->kctx) {
-- struct kbase_context *kctx = backend->kctx;
-- struct kbase_device *kbdev = kctx->kbdev;
--
-- if (backend->cpu_dump_va)
-- kbase_phy_alloc_mapping_put(kctx, backend->vmap);
--
-- if (backend->gpu_dump_va)
-- kbasep_hwcnt_backend_gpu_dump_free(
-- kctx, backend->gpu_dump_va);
--
-- kbasep_js_release_privileged_ctx(kbdev, kctx);
-- kbase_destroy_context(kctx);
-- }
--
-- kfree(backend);
--}
--
--/**
-- * kbasep_hwcnt_backend_gpu_create() - Create a GPU backend.
-- * @info: Non-NULL pointer to backend info.
-- * @out_backend: Non-NULL pointer to where backend is stored on success.
-- *
-- * Return: 0 on success, else error code.
-- */
--static int kbasep_hwcnt_backend_gpu_create(
-- const struct kbase_hwcnt_backend_gpu_info *info,
-- struct kbase_hwcnt_backend_gpu **out_backend)
--{
--
-- int errcode;
-- struct kbase_device *kbdev;
-- struct kbase_hwcnt_backend_gpu *backend = NULL;
--
-- WARN_ON(!info);
-- WARN_ON(!out_backend);
--
-- kbdev = info->kbdev;
--
-- backend = kzalloc(sizeof(*backend), GFP_KERNEL);
-- if (!backend)
-- goto alloc_error;
--
-- backend->info = info;
--
-- backend->kctx = kbase_create_context(kbdev, true,
-- BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED, 0, NULL);
-- if (!backend->kctx)
-- goto alloc_error;
--
-- kbasep_js_schedule_privileged_ctx(kbdev, backend->kctx);
--
-- errcode = kbasep_hwcnt_backend_gpu_dump_alloc(
-- info, backend->kctx, &backend->gpu_dump_va);
-- if (errcode)
-- goto error;
--
-- backend->cpu_dump_va = kbase_phy_alloc_mapping_get(backend->kctx,
-- backend->gpu_dump_va, &backend->vmap);
-- if (!backend->cpu_dump_va)
-- goto alloc_error;
--
--#ifdef CONFIG_MALI_NO_MALI
-- /* The dummy model needs the CPU mapping. */
-- gpu_model_set_dummy_prfcnt_base_cpu(backend->cpu_dump_va);
--#endif
--
-- *out_backend = backend;
-- return 0;
--
--alloc_error:
-- errcode = -ENOMEM;
--error:
-- kbasep_hwcnt_backend_gpu_destroy(backend);
-- return errcode;
--}
--
--/* GPU backend implementation of kbase_hwcnt_backend_init_fn */
--static int kbasep_hwcnt_backend_gpu_init(
-- const struct kbase_hwcnt_backend_info *info,
-- struct kbase_hwcnt_backend **out_backend)
--{
-- int errcode;
-- struct kbase_hwcnt_backend_gpu *backend = NULL;
--
-- if (!info || !out_backend)
-- return -EINVAL;
--
-- errcode = kbasep_hwcnt_backend_gpu_create(
-- (const struct kbase_hwcnt_backend_gpu_info *) info, &backend);
-- if (errcode)
-- return errcode;
--
-- *out_backend = (struct kbase_hwcnt_backend *)backend;
--
-- return 0;
--}
--
--/* GPU backend implementation of kbase_hwcnt_backend_term_fn */
--static void kbasep_hwcnt_backend_gpu_term(struct kbase_hwcnt_backend *backend)
--{
-- if (!backend)
-- return;
--
-- kbasep_hwcnt_backend_gpu_dump_disable(backend);
-- kbasep_hwcnt_backend_gpu_destroy(
-- (struct kbase_hwcnt_backend_gpu *)backend);
--}
--
--/**
-- * kbasep_hwcnt_backend_gpu_info_destroy() - Destroy a GPU backend info.
-- * @info: Pointer to info to destroy.
-- *
-- * Can be safely called on a backend info in any state of partial construction.
-- */
--static void kbasep_hwcnt_backend_gpu_info_destroy(
-- const struct kbase_hwcnt_backend_gpu_info *info)
--{
-- if (!info)
-- return;
--
-- kbase_hwcnt_gpu_metadata_destroy(info->metadata);
-- kfree(info);
--}
--
--/**
-- * kbasep_hwcnt_backend_gpu_info_create() - Create a GPU backend info.
-- * @kbdev: Non_NULL pointer to kbase device.
-- * @out_info: Non-NULL pointer to where info is stored on success.
-- *
-- * Return 0 on success, else error code.
-- */
--static int kbasep_hwcnt_backend_gpu_info_create(
-- struct kbase_device *kbdev,
-- const struct kbase_hwcnt_backend_gpu_info **out_info)
--{
-- int errcode = -ENOMEM;
-- struct kbase_hwcnt_gpu_info hwcnt_gpu_info;
-- struct kbase_hwcnt_backend_gpu_info *info = NULL;
--
-- WARN_ON(!kbdev);
-- WARN_ON(!out_info);
--
-- errcode = kbase_hwcnt_gpu_info_init(kbdev, &hwcnt_gpu_info);
-- if (errcode)
-- return errcode;
--
-- info = kzalloc(sizeof(*info), GFP_KERNEL);
-- if (!info)
-- goto error;
--
-- info->kbdev = kbdev;
--
--#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY
-- info->use_secondary = true;
--#else
-- info->use_secondary = false;
--#endif
--
-- errcode = kbase_hwcnt_gpu_metadata_create(
-- &hwcnt_gpu_info, info->use_secondary,
-- &info->metadata,
-- &info->dump_bytes);
-- if (errcode)
-- goto error;
--
-- *out_info = info;
--
-- return 0;
--error:
-- kbasep_hwcnt_backend_gpu_info_destroy(info);
-- return errcode;
--}
--
--int kbase_hwcnt_backend_gpu_create(
-- struct kbase_device *kbdev,
-- struct kbase_hwcnt_backend_interface *iface)
--{
-- int errcode;
-- const struct kbase_hwcnt_backend_gpu_info *info = NULL;
--
-- if (!kbdev || !iface)
-- return -EINVAL;
--
-- errcode = kbasep_hwcnt_backend_gpu_info_create(kbdev, &info);
--
-- if (errcode)
-- return errcode;
--
-- iface->metadata = info->metadata;
-- iface->info = (struct kbase_hwcnt_backend_info *)info;
-- iface->init = kbasep_hwcnt_backend_gpu_init;
-- iface->term = kbasep_hwcnt_backend_gpu_term;
-- iface->timestamp_ns = kbasep_hwcnt_backend_gpu_timestamp_ns;
-- iface->dump_enable = kbasep_hwcnt_backend_gpu_dump_enable;
-- iface->dump_enable_nolock = kbasep_hwcnt_backend_gpu_dump_enable_nolock;
-- iface->dump_disable = kbasep_hwcnt_backend_gpu_dump_disable;
-- iface->dump_clear = kbasep_hwcnt_backend_gpu_dump_clear;
-- iface->dump_request = kbasep_hwcnt_backend_gpu_dump_request;
-- iface->dump_wait = kbasep_hwcnt_backend_gpu_dump_wait;
-- iface->dump_get = kbasep_hwcnt_backend_gpu_dump_get;
--
-- return 0;
--}
--
--void kbase_hwcnt_backend_gpu_destroy(
-- struct kbase_hwcnt_backend_interface *iface)
--{
-- if (!iface)
-- return;
--
-- kbasep_hwcnt_backend_gpu_info_destroy(
-- (const struct kbase_hwcnt_backend_gpu_info *)iface->info);
-- memset(iface, 0, sizeof(*iface));
--}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_jm.c
-new file mode 100644
-index 0000000..64001b1
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_jm.c
-@@ -0,0 +1,793 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include "mali_kbase_hwcnt_backend_jm.h"
-+#include "mali_kbase_hwcnt_gpu.h"
-+#include "mali_kbase_hwcnt_types.h"
-+#include "mali_kbase.h"
-+#include "backend/gpu/mali_kbase_pm_ca.h"
-+#include "mali_kbase_hwaccess_instr.h"
-+#include "mali_kbase_hwaccess_time.h"
-+#include "mali_kbase_ccswe.h"
-+
-+#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
-+
-+#include "backend/gpu/mali_kbase_pm_internal.h"
-+
-+/**
-+ * struct kbase_hwcnt_backend_jm_info - Information used to create an instance
-+ * of a JM hardware counter backend.
-+ * @kbdev: KBase device.
-+ * @counter_set: The performance counter set to use.
-+ * @metadata: Hardware counter metadata.
-+ * @dump_bytes: Bytes of GPU memory required to perform a
-+ * hardware counter dump.
-+ */
-+struct kbase_hwcnt_backend_jm_info {
-+ struct kbase_device *kbdev;
-+ enum kbase_hwcnt_set counter_set;
-+ const struct kbase_hwcnt_metadata *metadata;
-+ size_t dump_bytes;
-+};
-+
-+/**
-+ * struct kbase_hwcnt_backend_jm - Instance of a JM hardware counter backend.
-+ * @info: Info used to create the backend.
-+ * @kctx: KBase context used for GPU memory allocation and
-+ * counter dumping.
-+ * @gpu_dump_va: GPU hardware counter dump buffer virtual address.
-+ * @cpu_dump_va: CPU mapping of gpu_dump_va.
-+ * @vmap: Dump buffer vmap.
-+ * @enabled: True if dumping has been enabled, else false.
-+ * @pm_core_mask: PM state sync-ed shaders core mask for the enabled
-+ * dumping.
-+ * @curr_config: Current allocated hardware resources to correctly map the src
-+ * raw dump buffer to the dst dump buffer.
-+ * @clk_enable_map: The enable map specifying enabled clock domains.
-+ * @cycle_count_elapsed:
-+ * Cycle count elapsed for a given sample period.
-+ * The top clock cycle, index 0, is read directly from
-+ * hardware, but the other clock domains need to be
-+ * calculated with software estimation.
-+ * @prev_cycle_count: Previous cycle count to calculate the cycle count for
-+ * sample period.
-+ * @rate_listener: Clock rate listener callback state.
-+ * @ccswe_shader_cores: Shader cores cycle count software estimator.
-+ */
-+struct kbase_hwcnt_backend_jm {
-+ const struct kbase_hwcnt_backend_jm_info *info;
-+ struct kbase_context *kctx;
-+ u64 gpu_dump_va;
-+ void *cpu_dump_va;
-+ struct kbase_vmap_struct *vmap;
-+ bool enabled;
-+ u64 pm_core_mask;
-+ struct kbase_hwcnt_curr_config curr_config;
-+ u64 clk_enable_map;
-+ u64 cycle_count_elapsed[BASE_MAX_NR_CLOCKS_REGULATORS];
-+ u64 prev_cycle_count[BASE_MAX_NR_CLOCKS_REGULATORS];
-+ struct kbase_clk_rate_listener rate_listener;
-+ struct kbase_ccswe ccswe_shader_cores;
-+};
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_gpu_info_init() - Initialise an info structure used
-+ * to create the hwcnt metadata.
-+ * @kbdev: Non-NULL pointer to kbase device.
-+ * @info: Non-NULL pointer to data structure to be filled in.
-+ *
-+ * The initialised info struct will only be valid for use while kbdev is valid.
-+ */
-+static int
-+kbasep_hwcnt_backend_jm_gpu_info_init(struct kbase_device *kbdev,
-+ struct kbase_hwcnt_gpu_info *info)
-+{
-+ size_t clk;
-+
-+ if (!kbdev || !info)
-+ return -EINVAL;
-+
-+ {
-+ const struct base_gpu_props *props = &kbdev->gpu_props.props;
-+ const size_t l2_count = props->l2_props.num_l2_slices;
-+ const size_t core_mask =
-+ props->coherency_info.group[0].core_mask;
-+
-+ info->l2_count = l2_count;
-+ info->core_mask = core_mask;
-+ info->prfcnt_values_per_block =
-+ KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK;
-+ }
-+
-+ /* Determine the number of available clock domains. */
-+ for (clk = 0; clk < BASE_MAX_NR_CLOCKS_REGULATORS; clk++) {
-+ if (kbdev->pm.clk_rtm.clks[clk] == NULL)
-+ break;
-+ }
-+ info->clk_cnt = clk;
-+
-+ return 0;
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_on_freq_change() - On freq change callback
-+ *
-+ * @rate_listener: Callback state
-+ * @clk_index: Clock index
-+ * @clk_rate_hz: Clock frequency(hz)
-+ */
-+static void kbasep_hwcnt_backend_jm_on_freq_change(
-+ struct kbase_clk_rate_listener *rate_listener,
-+ u32 clk_index,
-+ u32 clk_rate_hz)
-+{
-+ struct kbase_hwcnt_backend_jm *backend_jm = container_of(
-+ rate_listener, struct kbase_hwcnt_backend_jm, rate_listener);
-+ u64 timestamp_ns;
-+
-+ if (clk_index != KBASE_CLOCK_DOMAIN_SHADER_CORES)
-+ return;
-+
-+ timestamp_ns = ktime_get_raw_ns();
-+ kbase_ccswe_freq_change(
-+ &backend_jm->ccswe_shader_cores, timestamp_ns, clk_rate_hz);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_cc_enable() - Enable cycle count tracking
-+ *
-+ * @backend_jm: Non-NULL pointer to backend.
-+ * @enable_map: Non-NULL pointer to enable map specifying enabled counters.
-+ * @timestamp_ns: Timestamp(ns) when HWCNT were enabled.
-+ */
-+static void kbasep_hwcnt_backend_jm_cc_enable(
-+ struct kbase_hwcnt_backend_jm *backend_jm,
-+ const struct kbase_hwcnt_enable_map *enable_map,
-+ u64 timestamp_ns)
-+{
-+ struct kbase_device *kbdev = backend_jm->kctx->kbdev;
-+ u64 clk_enable_map = enable_map->clk_enable_map;
-+ u64 cycle_count;
-+
-+ if (kbase_hwcnt_clk_enable_map_enabled(
-+ clk_enable_map, KBASE_CLOCK_DOMAIN_TOP)) {
-+ /* turn on the cycle counter */
-+ kbase_pm_request_gpu_cycle_counter_l2_is_on(kbdev);
-+ /* Read cycle count for top clock domain. */
-+ kbase_backend_get_gpu_time_norequest(
-+ kbdev, &cycle_count, NULL, NULL);
-+
-+ backend_jm->prev_cycle_count[KBASE_CLOCK_DOMAIN_TOP] =
-+ cycle_count;
-+ }
-+
-+ if (kbase_hwcnt_clk_enable_map_enabled(
-+ clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) {
-+ /* software estimation for non-top clock domains */
-+ struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm;
-+ const struct kbase_clk_data *clk_data =
-+ rtm->clks[KBASE_CLOCK_DOMAIN_SHADER_CORES];
-+ u32 cur_freq;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&rtm->lock, flags);
-+
-+ cur_freq = (u32) clk_data->clock_val;
-+ kbase_ccswe_reset(&backend_jm->ccswe_shader_cores);
-+ kbase_ccswe_freq_change(
-+ &backend_jm->ccswe_shader_cores,
-+ timestamp_ns,
-+ cur_freq);
-+
-+ kbase_clk_rate_trace_manager_subscribe_no_lock(
-+ rtm, &backend_jm->rate_listener);
-+
-+ spin_unlock_irqrestore(&rtm->lock, flags);
-+
-+ /* ccswe was reset. The estimated cycle is zero. */
-+ backend_jm->prev_cycle_count[
-+ KBASE_CLOCK_DOMAIN_SHADER_CORES] = 0;
-+ }
-+
-+ /* Keep clk_enable_map for dump_request. */
-+ backend_jm->clk_enable_map = clk_enable_map;
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_cc_disable() - Disable cycle count tracking
-+ *
-+ * @backend_jm: Non-NULL pointer to backend.
-+ */
-+static void kbasep_hwcnt_backend_jm_cc_disable(
-+ struct kbase_hwcnt_backend_jm *backend_jm)
-+{
-+ struct kbase_device *kbdev = backend_jm->kctx->kbdev;
-+ struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm;
-+ u64 clk_enable_map = backend_jm->clk_enable_map;
-+
-+ if (kbase_hwcnt_clk_enable_map_enabled(
-+ clk_enable_map, KBASE_CLOCK_DOMAIN_TOP)) {
-+ /* turn off the cycle counter */
-+ kbase_pm_release_gpu_cycle_counter(kbdev);
-+ }
-+
-+ if (kbase_hwcnt_clk_enable_map_enabled(
-+ clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) {
-+
-+ kbase_clk_rate_trace_manager_unsubscribe(
-+ rtm, &backend_jm->rate_listener);
-+ }
-+}
-+
-+
-+/**
-+ * kbasep_hwcnt_gpu_update_curr_config() - Update the destination buffer with
-+ * current config information.
-+ * @kbdev: Non-NULL pointer to kbase device.
-+ * @curr_config: Non-NULL pointer to return the current configuration of
-+ * hardware allocated to the GPU.
-+ *
-+ * The current configuration information is used for architectures where the
-+ * max_config interface is available from the Arbiter. In this case the current
-+ * allocated hardware is not always the same, so the current config information
-+ * is used to correctly map the current allocated resources to the memory layout
-+ * that is copied to the user space.
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+static int kbasep_hwcnt_gpu_update_curr_config(
-+ struct kbase_device *kbdev,
-+ struct kbase_hwcnt_curr_config *curr_config)
-+{
-+ if (WARN_ON(!kbdev) || WARN_ON(!curr_config))
-+ return -EINVAL;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ curr_config->num_l2_slices =
-+ kbdev->gpu_props.curr_config.l2_slices;
-+ curr_config->shader_present =
-+ kbdev->gpu_props.curr_config.shader_present;
-+ return 0;
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_timestamp_ns_fn */
-+static u64 kbasep_hwcnt_backend_jm_timestamp_ns(
-+ struct kbase_hwcnt_backend *backend)
-+{
-+ (void)backend;
-+ return ktime_get_raw_ns();
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_dump_enable_nolock_fn */
-+static int kbasep_hwcnt_backend_jm_dump_enable_nolock(
-+ struct kbase_hwcnt_backend *backend,
-+ const struct kbase_hwcnt_enable_map *enable_map)
-+{
-+ int errcode;
-+ struct kbase_hwcnt_backend_jm *backend_jm =
-+ (struct kbase_hwcnt_backend_jm *)backend;
-+ struct kbase_context *kctx;
-+ struct kbase_device *kbdev;
-+ struct kbase_hwcnt_physical_enable_map phys_enable_map;
-+ enum kbase_hwcnt_physical_set phys_counter_set;
-+ struct kbase_instr_hwcnt_enable enable;
-+ u64 timestamp_ns;
-+
-+ if (!backend_jm || !enable_map || backend_jm->enabled ||
-+ (enable_map->metadata != backend_jm->info->metadata))
-+ return -EINVAL;
-+
-+ kctx = backend_jm->kctx;
-+ kbdev = backend_jm->kctx->kbdev;
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ kbase_hwcnt_gpu_enable_map_to_physical(&phys_enable_map, enable_map);
-+
-+ kbase_hwcnt_gpu_set_to_physical(&phys_counter_set,
-+ backend_jm->info->counter_set);
-+
-+ enable.fe_bm = phys_enable_map.fe_bm;
-+ enable.shader_bm = phys_enable_map.shader_bm;
-+ enable.tiler_bm = phys_enable_map.tiler_bm;
-+ enable.mmu_l2_bm = phys_enable_map.mmu_l2_bm;
-+ enable.counter_set = phys_counter_set;
-+ enable.dump_buffer = backend_jm->gpu_dump_va;
-+ enable.dump_buffer_bytes = backend_jm->info->dump_bytes;
-+
-+ timestamp_ns = kbasep_hwcnt_backend_jm_timestamp_ns(backend);
-+
-+ /* Update the current configuration information. */
-+ errcode = kbasep_hwcnt_gpu_update_curr_config(kbdev,
-+ &backend_jm->curr_config);
-+ if (errcode)
-+ goto error;
-+
-+ errcode = kbase_instr_hwcnt_enable_internal(kbdev, kctx, &enable);
-+ if (errcode)
-+ goto error;
-+
-+ backend_jm->pm_core_mask = kbase_pm_ca_get_instr_core_mask(kbdev);
-+
-+ backend_jm->enabled = true;
-+
-+ kbasep_hwcnt_backend_jm_cc_enable(backend_jm, enable_map, timestamp_ns);
-+
-+ return 0;
-+error:
-+ return errcode;
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_dump_enable_fn */
-+static int kbasep_hwcnt_backend_jm_dump_enable(
-+ struct kbase_hwcnt_backend *backend,
-+ const struct kbase_hwcnt_enable_map *enable_map)
-+{
-+ unsigned long flags;
-+ int errcode;
-+ struct kbase_hwcnt_backend_jm *backend_jm =
-+ (struct kbase_hwcnt_backend_jm *)backend;
-+ struct kbase_device *kbdev;
-+
-+ if (!backend_jm)
-+ return -EINVAL;
-+
-+ kbdev = backend_jm->kctx->kbdev;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+
-+ errcode = kbasep_hwcnt_backend_jm_dump_enable_nolock(
-+ backend, enable_map);
-+
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ return errcode;
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_dump_disable_fn */
-+static void kbasep_hwcnt_backend_jm_dump_disable(
-+ struct kbase_hwcnt_backend *backend)
-+{
-+ int errcode;
-+ struct kbase_hwcnt_backend_jm *backend_jm =
-+ (struct kbase_hwcnt_backend_jm *)backend;
-+
-+ if (WARN_ON(!backend_jm) || !backend_jm->enabled)
-+ return;
-+
-+ kbasep_hwcnt_backend_jm_cc_disable(backend_jm);
-+
-+ errcode = kbase_instr_hwcnt_disable_internal(backend_jm->kctx);
-+ WARN_ON(errcode);
-+
-+ backend_jm->enabled = false;
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_dump_clear_fn */
-+static int kbasep_hwcnt_backend_jm_dump_clear(
-+ struct kbase_hwcnt_backend *backend)
-+{
-+ struct kbase_hwcnt_backend_jm *backend_jm =
-+ (struct kbase_hwcnt_backend_jm *)backend;
-+
-+ if (!backend_jm || !backend_jm->enabled)
-+ return -EINVAL;
-+
-+ return kbase_instr_hwcnt_clear(backend_jm->kctx);
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_dump_request_fn */
-+static int kbasep_hwcnt_backend_jm_dump_request(
-+ struct kbase_hwcnt_backend *backend,
-+ u64 *dump_time_ns)
-+{
-+ struct kbase_hwcnt_backend_jm *backend_jm =
-+ (struct kbase_hwcnt_backend_jm *)backend;
-+ struct kbase_device *kbdev;
-+ const struct kbase_hwcnt_metadata *metadata;
-+ u64 current_cycle_count;
-+ size_t clk;
-+ int ret;
-+
-+ if (!backend_jm || !backend_jm->enabled || !dump_time_ns)
-+ return -EINVAL;
-+
-+ kbdev = backend_jm->kctx->kbdev;
-+ metadata = backend_jm->info->metadata;
-+
-+ /* Disable pre-emption, to make the timestamp as accurate as possible */
-+ preempt_disable();
-+ {
-+ *dump_time_ns = kbasep_hwcnt_backend_jm_timestamp_ns(backend);
-+ ret = kbase_instr_hwcnt_request_dump(backend_jm->kctx);
-+
-+ kbase_hwcnt_metadata_for_each_clock(metadata, clk) {
-+ if (!kbase_hwcnt_clk_enable_map_enabled(
-+ backend_jm->clk_enable_map, clk))
-+ continue;
-+
-+ if (clk == KBASE_CLOCK_DOMAIN_TOP) {
-+ /* Read cycle count for top clock domain. */
-+ kbase_backend_get_gpu_time_norequest(
-+ kbdev, ¤t_cycle_count,
-+ NULL, NULL);
-+ } else {
-+ /*
-+ * Estimate cycle count for non-top clock
-+ * domain.
-+ */
-+ current_cycle_count = kbase_ccswe_cycle_at(
-+ &backend_jm->ccswe_shader_cores,
-+ *dump_time_ns);
-+ }
-+ backend_jm->cycle_count_elapsed[clk] =
-+ current_cycle_count -
-+ backend_jm->prev_cycle_count[clk];
-+
-+ /*
-+ * Keep the current cycle count for later calculation.
-+ */
-+ backend_jm->prev_cycle_count[clk] = current_cycle_count;
-+ }
-+ }
-+ preempt_enable();
-+
-+ return ret;
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_dump_wait_fn */
-+static int kbasep_hwcnt_backend_jm_dump_wait(
-+ struct kbase_hwcnt_backend *backend)
-+{
-+ struct kbase_hwcnt_backend_jm *backend_jm =
-+ (struct kbase_hwcnt_backend_jm *)backend;
-+
-+ if (!backend_jm || !backend_jm->enabled)
-+ return -EINVAL;
-+
-+ return kbase_instr_hwcnt_wait_for_dump(backend_jm->kctx);
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_dump_get_fn */
-+static int kbasep_hwcnt_backend_jm_dump_get(
-+ struct kbase_hwcnt_backend *backend,
-+ struct kbase_hwcnt_dump_buffer *dst,
-+ const struct kbase_hwcnt_enable_map *dst_enable_map,
-+ bool accumulate)
-+{
-+ struct kbase_hwcnt_backend_jm *backend_jm =
-+ (struct kbase_hwcnt_backend_jm *)backend;
-+ size_t clk;
-+
-+ if (!backend_jm || !dst || !dst_enable_map ||
-+ (backend_jm->info->metadata != dst->metadata) ||
-+ (dst_enable_map->metadata != dst->metadata))
-+ return -EINVAL;
-+
-+ /* Invalidate the kernel buffer before reading from it. */
-+ kbase_sync_mem_regions(
-+ backend_jm->kctx, backend_jm->vmap, KBASE_SYNC_TO_CPU);
-+
-+ kbase_hwcnt_metadata_for_each_clock(dst_enable_map->metadata, clk) {
-+ if (!kbase_hwcnt_clk_enable_map_enabled(
-+ dst_enable_map->clk_enable_map, clk))
-+ continue;
-+
-+ /* Extract elapsed cycle count for each clock domain. */
-+ dst->clk_cnt_buf[clk] = backend_jm->cycle_count_elapsed[clk];
-+ }
-+
-+ return kbase_hwcnt_jm_dump_get(dst, backend_jm->cpu_dump_va,
-+ dst_enable_map, backend_jm->pm_core_mask,
-+ &backend_jm->curr_config, accumulate);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_dump_alloc() - Allocate a GPU dump buffer.
-+ * @info: Non-NULL pointer to JM backend info.
-+ * @kctx: Non-NULL pointer to kbase context.
-+ * @gpu_dump_va: Non-NULL pointer to where GPU dump buffer virtual address
-+ * is stored on success.
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+static int kbasep_hwcnt_backend_jm_dump_alloc(
-+ const struct kbase_hwcnt_backend_jm_info *info,
-+ struct kbase_context *kctx,
-+ u64 *gpu_dump_va)
-+{
-+ struct kbase_va_region *reg;
-+ u64 flags;
-+ u64 nr_pages;
-+
-+ WARN_ON(!info);
-+ WARN_ON(!kctx);
-+ WARN_ON(!gpu_dump_va);
-+
-+ flags = BASE_MEM_PROT_CPU_RD |
-+ BASE_MEM_PROT_GPU_WR |
-+ BASEP_MEM_PERMANENT_KERNEL_MAPPING |
-+ BASE_MEM_CACHED_CPU |
-+ BASE_MEM_UNCACHED_GPU;
-+
-+ nr_pages = PFN_UP(info->dump_bytes);
-+
-+ reg = kbase_mem_alloc(kctx, nr_pages, nr_pages, 0, &flags, gpu_dump_va);
-+
-+ if (!reg)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_dump_free() - Free an allocated GPU dump buffer.
-+ * @kctx: Non-NULL pointer to kbase context.
-+ * @gpu_dump_va: GPU dump buffer virtual address.
-+ */
-+static void kbasep_hwcnt_backend_jm_dump_free(
-+ struct kbase_context *kctx,
-+ u64 gpu_dump_va)
-+{
-+ WARN_ON(!kctx);
-+ if (gpu_dump_va)
-+ kbase_mem_free(kctx, gpu_dump_va);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_destroy() - Destroy a JM backend.
-+ * @backend: Pointer to JM backend to destroy.
-+ *
-+ * Can be safely called on a backend in any state of partial construction.
-+ */
-+static void kbasep_hwcnt_backend_jm_destroy(
-+ struct kbase_hwcnt_backend_jm *backend)
-+{
-+ if (!backend)
-+ return;
-+
-+ if (backend->kctx) {
-+ struct kbase_context *kctx = backend->kctx;
-+ struct kbase_device *kbdev = kctx->kbdev;
-+
-+ if (backend->cpu_dump_va)
-+ kbase_phy_alloc_mapping_put(kctx, backend->vmap);
-+
-+ if (backend->gpu_dump_va)
-+ kbasep_hwcnt_backend_jm_dump_free(
-+ kctx, backend->gpu_dump_va);
-+
-+ kbasep_js_release_privileged_ctx(kbdev, kctx);
-+ kbase_destroy_context(kctx);
-+ }
-+
-+ kfree(backend);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_create() - Create a JM backend.
-+ * @info: Non-NULL pointer to backend info.
-+ * @out_backend: Non-NULL pointer to where backend is stored on success.
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+static int kbasep_hwcnt_backend_jm_create(
-+ const struct kbase_hwcnt_backend_jm_info *info,
-+ struct kbase_hwcnt_backend_jm **out_backend)
-+{
-+ int errcode;
-+ struct kbase_device *kbdev;
-+ struct kbase_hwcnt_backend_jm *backend = NULL;
-+
-+ WARN_ON(!info);
-+ WARN_ON(!out_backend);
-+
-+ kbdev = info->kbdev;
-+
-+ backend = kzalloc(sizeof(*backend), GFP_KERNEL);
-+ if (!backend)
-+ goto alloc_error;
-+
-+ backend->info = info;
-+
-+ backend->kctx = kbase_create_context(kbdev, true,
-+ BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED, 0, NULL);
-+ if (!backend->kctx)
-+ goto alloc_error;
-+
-+ kbasep_js_schedule_privileged_ctx(kbdev, backend->kctx);
-+
-+ errcode = kbasep_hwcnt_backend_jm_dump_alloc(
-+ info, backend->kctx, &backend->gpu_dump_va);
-+ if (errcode)
-+ goto error;
-+
-+ backend->cpu_dump_va = kbase_phy_alloc_mapping_get(backend->kctx,
-+ backend->gpu_dump_va, &backend->vmap);
-+ if (!backend->cpu_dump_va)
-+ goto alloc_error;
-+
-+ kbase_ccswe_init(&backend->ccswe_shader_cores);
-+ backend->rate_listener.notify = kbasep_hwcnt_backend_jm_on_freq_change;
-+
-+
-+ *out_backend = backend;
-+ return 0;
-+
-+alloc_error:
-+ errcode = -ENOMEM;
-+error:
-+ kbasep_hwcnt_backend_jm_destroy(backend);
-+ return errcode;
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_metadata_fn */
-+static const struct kbase_hwcnt_metadata *
-+kbasep_hwcnt_backend_jm_metadata(const struct kbase_hwcnt_backend_info *info)
-+{
-+ if (!info)
-+ return NULL;
-+
-+ return ((const struct kbase_hwcnt_backend_jm_info *)info)->metadata;
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_init_fn */
-+static int kbasep_hwcnt_backend_jm_init(
-+ const struct kbase_hwcnt_backend_info *info,
-+ struct kbase_hwcnt_backend **out_backend)
-+{
-+ int errcode;
-+ struct kbase_hwcnt_backend_jm *backend = NULL;
-+
-+ if (!info || !out_backend)
-+ return -EINVAL;
-+
-+ errcode = kbasep_hwcnt_backend_jm_create(
-+ (const struct kbase_hwcnt_backend_jm_info *) info, &backend);
-+ if (errcode)
-+ return errcode;
-+
-+ *out_backend = (struct kbase_hwcnt_backend *)backend;
-+
-+ return 0;
-+}
-+
-+/* JM backend implementation of kbase_hwcnt_backend_term_fn */
-+static void kbasep_hwcnt_backend_jm_term(struct kbase_hwcnt_backend *backend)
-+{
-+ if (!backend)
-+ return;
-+
-+ kbasep_hwcnt_backend_jm_dump_disable(backend);
-+ kbasep_hwcnt_backend_jm_destroy(
-+ (struct kbase_hwcnt_backend_jm *)backend);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_info_destroy() - Destroy a JM backend info.
-+ * @info: Pointer to info to destroy.
-+ *
-+ * Can be safely called on a backend info in any state of partial construction.
-+ */
-+static void kbasep_hwcnt_backend_jm_info_destroy(
-+ const struct kbase_hwcnt_backend_jm_info *info)
-+{
-+ if (!info)
-+ return;
-+
-+ kbase_hwcnt_jm_metadata_destroy(info->metadata);
-+ kfree(info);
-+}
-+
-+/**
-+ * kbasep_hwcnt_backend_jm_info_create() - Create a JM backend info.
-+ * @kbdev: Non_NULL pointer to kbase device.
-+ * @out_info: Non-NULL pointer to where info is stored on success.
-+ *
-+ * Return 0 on success, else error code.
-+ */
-+static int kbasep_hwcnt_backend_jm_info_create(
-+ struct kbase_device *kbdev,
-+ const struct kbase_hwcnt_backend_jm_info **out_info)
-+{
-+ int errcode = -ENOMEM;
-+ struct kbase_hwcnt_gpu_info hwcnt_gpu_info;
-+ struct kbase_hwcnt_backend_jm_info *info = NULL;
-+
-+ WARN_ON(!kbdev);
-+ WARN_ON(!out_info);
-+
-+ errcode = kbasep_hwcnt_backend_jm_gpu_info_init(kbdev, &hwcnt_gpu_info);
-+ if (errcode)
-+ return errcode;
-+
-+ info = kzalloc(sizeof(*info), GFP_KERNEL);
-+ if (!info)
-+ goto error;
-+
-+ info->kbdev = kbdev;
-+
-+#if defined(CONFIG_MALI_PRFCNT_SET_SECONDARY)
-+ info->counter_set = KBASE_HWCNT_SET_SECONDARY;
-+#elif defined(CONFIG_MALI_PRFCNT_SET_TERTIARY)
-+ info->counter_set = KBASE_HWCNT_SET_TERTIARY;
-+#else
-+ /* Default to primary */
-+ info->counter_set = KBASE_HWCNT_SET_PRIMARY;
-+#endif
-+
-+ errcode = kbase_hwcnt_jm_metadata_create(&hwcnt_gpu_info,
-+ info->counter_set,
-+ &info->metadata,
-+ &info->dump_bytes);
-+ if (errcode)
-+ goto error;
-+
-+ *out_info = info;
-+
-+ return 0;
-+error:
-+ kbasep_hwcnt_backend_jm_info_destroy(info);
-+ return errcode;
-+}
-+
-+int kbase_hwcnt_backend_jm_create(
-+ struct kbase_device *kbdev,
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ int errcode;
-+ const struct kbase_hwcnt_backend_jm_info *info = NULL;
-+
-+ if (!kbdev || !iface)
-+ return -EINVAL;
-+
-+ errcode = kbasep_hwcnt_backend_jm_info_create(kbdev, &info);
-+
-+ if (errcode)
-+ return errcode;
-+
-+ iface->info = (struct kbase_hwcnt_backend_info *)info;
-+ iface->metadata = kbasep_hwcnt_backend_jm_metadata;
-+ iface->init = kbasep_hwcnt_backend_jm_init;
-+ iface->term = kbasep_hwcnt_backend_jm_term;
-+ iface->timestamp_ns = kbasep_hwcnt_backend_jm_timestamp_ns;
-+ iface->dump_enable = kbasep_hwcnt_backend_jm_dump_enable;
-+ iface->dump_enable_nolock = kbasep_hwcnt_backend_jm_dump_enable_nolock;
-+ iface->dump_disable = kbasep_hwcnt_backend_jm_dump_disable;
-+ iface->dump_clear = kbasep_hwcnt_backend_jm_dump_clear;
-+ iface->dump_request = kbasep_hwcnt_backend_jm_dump_request;
-+ iface->dump_wait = kbasep_hwcnt_backend_jm_dump_wait;
-+ iface->dump_get = kbasep_hwcnt_backend_jm_dump_get;
-+
-+ return 0;
-+}
-+
-+void kbase_hwcnt_backend_jm_destroy(
-+ struct kbase_hwcnt_backend_interface *iface)
-+{
-+ if (!iface)
-+ return;
-+
-+ kbasep_hwcnt_backend_jm_info_destroy(
-+ (const struct kbase_hwcnt_backend_jm_info *)iface->info);
-+ memset(iface, 0, sizeof(*iface));
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_gpu.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_jm.h
-similarity index 75%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_gpu.h
-rename to dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_jm.h
-index 7712f14..5319516 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_gpu.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_backend_jm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,24 +17,22 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-- * Concrete implementation of mali_kbase_hwcnt_backend interface for GPU
-+ * Concrete implementation of mali_kbase_hwcnt_backend interface for JM
- * backend.
- */
-
--#ifndef _KBASE_HWCNT_BACKEND_GPU_H_
--#define _KBASE_HWCNT_BACKEND_GPU_H_
-+#ifndef _KBASE_HWCNT_BACKEND_JM_H_
-+#define _KBASE_HWCNT_BACKEND_JM_H_
-
- #include "mali_kbase_hwcnt_backend.h"
-
- struct kbase_device;
-
- /**
-- * kbase_hwcnt_backend_gpu_create() - Create a GPU hardware counter backend
-+ * kbase_hwcnt_backend_jm_create() - Create a JM hardware counter backend
- * interface.
- * @kbdev: Non-NULL pointer to kbase device.
- * @iface: Non-NULL pointer to backend interface structure that is filled in
-@@ -43,19 +42,19 @@ struct kbase_device;
- *
- * Return: 0 on success, else error code.
- */
--int kbase_hwcnt_backend_gpu_create(
-+int kbase_hwcnt_backend_jm_create(
- struct kbase_device *kbdev,
- struct kbase_hwcnt_backend_interface *iface);
-
- /**
-- * kbase_hwcnt_backend_gpu_destroy() - Destroy a GPU hardware counter backend
-+ * kbase_hwcnt_backend_jm_destroy() - Destroy a JM hardware counter backend
- * interface.
- * @iface: Pointer to interface to destroy.
- *
- * Can be safely called on an all-zeroed interface, or on an already destroyed
- * interface.
- */
--void kbase_hwcnt_backend_gpu_destroy(
-+void kbase_hwcnt_backend_jm_destroy(
- struct kbase_hwcnt_backend_interface *iface);
-
--#endif /* _KBASE_HWCNT_BACKEND_GPU_H_ */
-+#endif /* _KBASE_HWCNT_BACKEND_JM_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_context.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_context.h
-index bc50ad1..1adf2ef 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_context.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_context.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-@@ -28,6 +27,7 @@
- #define _KBASE_HWCNT_CONTEXT_H_
-
- #include <linux/types.h>
-+#include <linux/workqueue.h>
-
- struct kbase_hwcnt_backend_interface;
- struct kbase_hwcnt_context;
-@@ -66,7 +66,7 @@ const struct kbase_hwcnt_metadata *kbase_hwcnt_context_metadata(
-
- /**
- * kbase_hwcnt_context_disable() - Increment the disable count of the context.
-- * @hctx: Pointer to the hardware counter context.
-+ * @hctx: Non-NULL pointer to the hardware counter context.
- *
- * If a call to this function increments the disable count from 0 to 1, and
- * an accumulator has been acquired, then a counter dump will be performed
-@@ -84,7 +84,7 @@ void kbase_hwcnt_context_disable(struct kbase_hwcnt_context *hctx);
- * kbase_hwcnt_context_disable_atomic() - Increment the disable count of the
- * context if possible in an atomic
- * context.
-- * @hctx: Pointer to the hardware counter context.
-+ * @hctx: Non-NULL pointer to the hardware counter context.
- *
- * This function will only succeed if hardware counters are effectively already
- * disabled, i.e. there is no accumulator, the disable count is already
-@@ -99,7 +99,7 @@ bool kbase_hwcnt_context_disable_atomic(struct kbase_hwcnt_context *hctx);
-
- /**
- * kbase_hwcnt_context_enable() - Decrement the disable count of the context.
-- * @hctx: Pointer to the hardware counter context.
-+ * @hctx: Non-NULL pointer to the hardware counter context.
- *
- * If a call to this function decrements the disable count from 1 to 0, and
- * an accumulator has been acquired, then counters will be re-enabled via the
-@@ -116,4 +116,36 @@ bool kbase_hwcnt_context_disable_atomic(struct kbase_hwcnt_context *hctx);
- */
- void kbase_hwcnt_context_enable(struct kbase_hwcnt_context *hctx);
-
-+/**
-+ * kbase_hwcnt_context_queue_work() - Queue hardware counter related async
-+ * work on a workqueue specialized for
-+ * hardware counters.
-+ * @hctx: Non-NULL pointer to the hardware counter context.
-+ * @work: Non-NULL pointer to work to queue.
-+ *
-+ * Return: false if work was already on a queue, true otherwise.
-+ *
-+ * Performance counter related work is high priority, short running, and
-+ * generally CPU locality is unimportant. There is no standard workqueue that
-+ * can service this flavor of work.
-+ *
-+ * Rather than have each user of counters define their own workqueue, we have
-+ * a centralized one in here that anybody using this hardware counter API
-+ * should use.
-+ *
-+ * Before the context is destroyed, all work submitted must have been completed.
-+ * Given that the work enqueued via this function is likely to be hardware
-+ * counter related and will therefore use the context object, this is likely
-+ * to be behavior that will occur naturally.
-+ *
-+ * Historical note: prior to this centralized workqueue, the system_highpri_wq
-+ * was used. This was generally fine, except when a particularly long running,
-+ * higher priority thread ended up scheduled on the enqueuing CPU core. Given
-+ * that hardware counters requires tight integration with power management,
-+ * this meant progress through the power management states could be stalled
-+ * for however long that higher priority thread took.
-+ */
-+bool kbase_hwcnt_context_queue_work(struct kbase_hwcnt_context *hctx,
-+ struct work_struct *work);
-+
- #endif /* _KBASE_HWCNT_CONTEXT_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_gpu.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_gpu.c
-index 095c765..2975269 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_gpu.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_gpu.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,170 +17,111 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase_hwcnt_gpu.h"
- #include "mali_kbase_hwcnt_types.h"
--#include "mali_kbase.h"
--#ifdef CONFIG_MALI_NO_MALI
--#include "backend/gpu/mali_kbase_model_dummy.h"
--#endif
--
--#define KBASE_HWCNT_V4_BLOCKS_PER_GROUP 8
--#define KBASE_HWCNT_V4_SC_BLOCKS_PER_GROUP 4
--#define KBASE_HWCNT_V4_MAX_GROUPS \
-- (KBASE_HWCNT_AVAIL_MASK_BITS / KBASE_HWCNT_V4_BLOCKS_PER_GROUP)
--#define KBASE_HWCNT_V4_HEADERS_PER_BLOCK 4
--#define KBASE_HWCNT_V4_COUNTERS_PER_BLOCK 60
--#define KBASE_HWCNT_V4_VALUES_PER_BLOCK \
-- (KBASE_HWCNT_V4_HEADERS_PER_BLOCK + KBASE_HWCNT_V4_COUNTERS_PER_BLOCK)
--/* Index of the PRFCNT_EN header into a V4 counter block */
--#define KBASE_HWCNT_V4_PRFCNT_EN_HEADER 2
--
--#define KBASE_HWCNT_V5_BLOCK_TYPE_COUNT 4
--#define KBASE_HWCNT_V5_HEADERS_PER_BLOCK 4
--#define KBASE_HWCNT_V5_COUNTERS_PER_BLOCK 60
--#define KBASE_HWCNT_V5_VALUES_PER_BLOCK \
-- (KBASE_HWCNT_V5_HEADERS_PER_BLOCK + KBASE_HWCNT_V5_COUNTERS_PER_BLOCK)
--/* Index of the PRFCNT_EN header into a V5 counter block */
--#define KBASE_HWCNT_V5_PRFCNT_EN_HEADER 2
--
--/**
-- * kbasep_hwcnt_backend_gpu_metadata_v4_create() - Create hardware counter
-- * metadata for a v4 GPU.
-- * @v4_info: Non-NULL pointer to hwcnt info for a v4 GPU.
-- * @metadata: Non-NULL pointer to where created metadata is stored on success.
-- *
-- * Return: 0 on success, else error code.
-- */
--static int kbasep_hwcnt_backend_gpu_metadata_v4_create(
-- const struct kbase_hwcnt_gpu_v4_info *v4_info,
-- const struct kbase_hwcnt_metadata **metadata)
--{
-- size_t grp;
-- int errcode = -ENOMEM;
-- struct kbase_hwcnt_description desc;
-- struct kbase_hwcnt_group_description *grps;
-- size_t avail_mask_bit;
-
-- WARN_ON(!v4_info);
-- WARN_ON(!metadata);
-+#include <linux/bug.h>
-+#include <linux/err.h>
-
-- /* Check if there are enough bits in the availability mask to represent
-- * all the hardware counter blocks in the system.
-- */
-- if (v4_info->cg_count > KBASE_HWCNT_V4_MAX_GROUPS)
-- return -EINVAL;
-
-- grps = kcalloc(v4_info->cg_count, sizeof(*grps), GFP_KERNEL);
-- if (!grps)
-- goto clean_up;
--
-- desc.grp_cnt = v4_info->cg_count;
-- desc.grps = grps;
--
-- for (grp = 0; grp < v4_info->cg_count; grp++) {
-- size_t blk;
-- size_t sc;
-- const u64 core_mask = v4_info->cgs[grp].core_mask;
-- struct kbase_hwcnt_block_description *blks = kcalloc(
-- KBASE_HWCNT_V4_BLOCKS_PER_GROUP,
-- sizeof(*blks),
-- GFP_KERNEL);
--
-- if (!blks)
-- goto clean_up;
--
-- grps[grp].type = KBASE_HWCNT_GPU_GROUP_TYPE_V4;
-- grps[grp].blk_cnt = KBASE_HWCNT_V4_BLOCKS_PER_GROUP;
-- grps[grp].blks = blks;
--
-- for (blk = 0; blk < KBASE_HWCNT_V4_BLOCKS_PER_GROUP; blk++) {
-- blks[blk].inst_cnt = 1;
-- blks[blk].hdr_cnt =
-- KBASE_HWCNT_V4_HEADERS_PER_BLOCK;
-- blks[blk].ctr_cnt =
-- KBASE_HWCNT_V4_COUNTERS_PER_BLOCK;
-+static void kbasep_get_fe_block_type(u64 *dst, enum kbase_hwcnt_set counter_set,
-+ bool is_csf)
-+{
-+ switch (counter_set) {
-+ case KBASE_HWCNT_SET_PRIMARY:
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE;
-+ break;
-+ case KBASE_HWCNT_SET_SECONDARY:
-+ if (is_csf) {
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE2;
-+ } else {
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED;
- }
--
-- for (sc = 0; sc < KBASE_HWCNT_V4_SC_BLOCKS_PER_GROUP; sc++) {
-- blks[sc].type = core_mask & (1ull << sc) ?
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_SHADER :
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_RESERVED;
-+ break;
-+ case KBASE_HWCNT_SET_TERTIARY:
-+ if (is_csf) {
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE3;
-+ } else {
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED;
- }
--
-- blks[4].type = KBASE_HWCNT_GPU_V4_BLOCK_TYPE_TILER;
-- blks[5].type = KBASE_HWCNT_GPU_V4_BLOCK_TYPE_MMU_L2;
-- blks[6].type = KBASE_HWCNT_GPU_V4_BLOCK_TYPE_RESERVED;
-- blks[7].type = (grp == 0) ?
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_JM :
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_RESERVED;
--
-- WARN_ON(KBASE_HWCNT_V4_BLOCKS_PER_GROUP != 8);
-+ break;
-+ default:
-+ WARN_ON(true);
- }
-+}
-
-- /* Initialise the availability mask */
-- desc.avail_mask = 0;
-- avail_mask_bit = 0;
--
-- for (grp = 0; grp < desc.grp_cnt; grp++) {
-- size_t blk;
-- const struct kbase_hwcnt_block_description *blks =
-- desc.grps[grp].blks;
-- for (blk = 0; blk < desc.grps[grp].blk_cnt; blk++) {
-- WARN_ON(blks[blk].inst_cnt != 1);
-- if (blks[blk].type !=
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_RESERVED)
-- desc.avail_mask |= (1ull << avail_mask_bit);
--
-- avail_mask_bit++;
-- }
-+static void kbasep_get_tiler_block_type(u64 *dst,
-+ enum kbase_hwcnt_set counter_set)
-+{
-+ switch (counter_set) {
-+ case KBASE_HWCNT_SET_PRIMARY:
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_TILER;
-+ break;
-+ case KBASE_HWCNT_SET_SECONDARY:
-+ case KBASE_HWCNT_SET_TERTIARY:
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED;
-+ break;
-+ default:
-+ WARN_ON(true);
- }
-+}
-
-- errcode = kbase_hwcnt_metadata_create(&desc, metadata);
--
-- /* Always clean up, as metadata will make a copy of the input args */
--clean_up:
-- if (grps) {
-- for (grp = 0; grp < v4_info->cg_count; grp++)
-- kfree(grps[grp].blks);
-- kfree(grps);
-+static void kbasep_get_sc_block_type(u64 *dst, enum kbase_hwcnt_set counter_set,
-+ bool is_csf)
-+{
-+ switch (counter_set) {
-+ case KBASE_HWCNT_SET_PRIMARY:
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC;
-+ break;
-+ case KBASE_HWCNT_SET_SECONDARY:
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC2;
-+ break;
-+ case KBASE_HWCNT_SET_TERTIARY:
-+ if (is_csf) {
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC3;
-+ } else {
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED;
-+ }
-+ break;
-+ default:
-+ WARN_ON(true);
- }
-- return errcode;
- }
-
--/**
-- * kbasep_hwcnt_backend_gpu_v4_dump_bytes() - Get the raw dump buffer size for a
-- * V4 GPU.
-- * @v4_info: Non-NULL pointer to hwcnt info for a v4 GPU.
-- *
-- * Return: Size of buffer the V4 GPU needs to perform a counter dump.
-- */
--static size_t kbasep_hwcnt_backend_gpu_v4_dump_bytes(
-- const struct kbase_hwcnt_gpu_v4_info *v4_info)
-+static void kbasep_get_memsys_block_type(u64 *dst,
-+ enum kbase_hwcnt_set counter_set)
- {
-- return v4_info->cg_count *
-- KBASE_HWCNT_V4_BLOCKS_PER_GROUP *
-- KBASE_HWCNT_V4_VALUES_PER_BLOCK *
-- KBASE_HWCNT_VALUE_BYTES;
-+ switch (counter_set) {
-+ case KBASE_HWCNT_SET_PRIMARY:
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS;
-+ break;
-+ case KBASE_HWCNT_SET_SECONDARY:
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS2;
-+ break;
-+ case KBASE_HWCNT_SET_TERTIARY:
-+ *dst = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED;
-+ break;
-+ default:
-+ WARN_ON(true);
-+ }
- }
-
- /**
-- * kbasep_hwcnt_backend_gpu_metadata_v5_create() - Create hardware counter
-- * metadata for a v5 GPU.
-- * @v5_info: Non-NULL pointer to hwcnt info for a v5 GPU.
-- * @use_secondary: True if secondary performance counters should be used, else
-- * false. Ignored if secondary counters are not supported.
-+ * kbasep_hwcnt_backend_gpu_metadata_create() - Create hardware counter metadata
-+ * for the GPU.
-+ * @gpu_info: Non-NULL pointer to hwcnt info for current GPU.
-+ * @is_csf: true for CSF GPU, otherwise false.
-+ * @counter_set: The performance counter set to use.
- * @metadata: Non-NULL pointer to where created metadata is stored
- * on success.
- *
- * Return: 0 on success, else error code.
- */
--static int kbasep_hwcnt_backend_gpu_metadata_v5_create(
-- const struct kbase_hwcnt_gpu_v5_info *v5_info,
-- bool use_secondary,
-+static int kbasep_hwcnt_backend_gpu_metadata_create(
-+ const struct kbase_hwcnt_gpu_info *gpu_info, const bool is_csf,
-+ enum kbase_hwcnt_set counter_set,
- const struct kbase_hwcnt_metadata **metadata)
- {
- struct kbase_hwcnt_description desc;
-@@ -189,13 +131,13 @@ static int kbasep_hwcnt_backend_gpu_metadata_v5_create(
- size_t non_sc_block_count;
- size_t sc_block_count;
-
-- WARN_ON(!v5_info);
-+ WARN_ON(!gpu_info);
- WARN_ON(!metadata);
-
- /* Calculate number of block instances that aren't shader cores */
-- non_sc_block_count = 2 + v5_info->l2_count;
-+ non_sc_block_count = 2 + gpu_info->l2_count;
- /* Calculate number of block instances that are shader cores */
-- sc_block_count = fls64(v5_info->core_mask);
-+ sc_block_count = fls64(gpu_info->core_mask);
-
- /*
- * A system can have up to 64 shader cores, but the 64-bit
-@@ -207,25 +149,26 @@ static int kbasep_hwcnt_backend_gpu_metadata_v5_create(
- if ((sc_block_count + non_sc_block_count) > KBASE_HWCNT_AVAIL_MASK_BITS)
- return -EINVAL;
-
-- /* One Job Manager block */
-- blks[0].type = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_JM;
-+ /* One Front End block */
-+ kbasep_get_fe_block_type(&blks[0].type, counter_set, is_csf);
- blks[0].inst_cnt = 1;
- blks[0].hdr_cnt = KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
-- blks[0].ctr_cnt = KBASE_HWCNT_V5_COUNTERS_PER_BLOCK;
-+ blks[0].ctr_cnt = gpu_info->prfcnt_values_per_block -
-+ KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
-
- /* One Tiler block */
-- blks[1].type = KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_TILER;
-+ kbasep_get_tiler_block_type(&blks[1].type, counter_set);
- blks[1].inst_cnt = 1;
- blks[1].hdr_cnt = KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
-- blks[1].ctr_cnt = KBASE_HWCNT_V5_COUNTERS_PER_BLOCK;
-+ blks[1].ctr_cnt = gpu_info->prfcnt_values_per_block -
-+ KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
-
- /* l2_count memsys blks */
-- blks[2].type = use_secondary ?
-- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS2 :
-- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS;
-- blks[2].inst_cnt = v5_info->l2_count;
-+ kbasep_get_memsys_block_type(&blks[2].type, counter_set);
-+ blks[2].inst_cnt = gpu_info->l2_count;
- blks[2].hdr_cnt = KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
-- blks[2].ctr_cnt = KBASE_HWCNT_V5_COUNTERS_PER_BLOCK;
-+ blks[2].ctr_cnt = gpu_info->prfcnt_values_per_block -
-+ KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
-
- /*
- * There are as many shader cores in the system as there are bits set in
-@@ -243,12 +186,11 @@ static int kbasep_hwcnt_backend_gpu_metadata_v5_create(
- * requirements, and embed the core mask into the availability mask so
- * we can determine later which shader cores physically exist.
- */
-- blks[3].type = use_secondary ?
-- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC2 :
-- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC;
-+ kbasep_get_sc_block_type(&blks[3].type, counter_set, is_csf);
- blks[3].inst_cnt = sc_block_count;
- blks[3].hdr_cnt = KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
-- blks[3].ctr_cnt = KBASE_HWCNT_V5_COUNTERS_PER_BLOCK;
-+ blks[3].ctr_cnt = gpu_info->prfcnt_values_per_block -
-+ KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
-
- WARN_ON(KBASE_HWCNT_V5_BLOCK_TYPE_COUNT != 4);
-
-@@ -258,61 +200,35 @@ static int kbasep_hwcnt_backend_gpu_metadata_v5_create(
-
- desc.grp_cnt = 1;
- desc.grps = &group;
-+ desc.clk_cnt = gpu_info->clk_cnt;
-
- /* The JM, Tiler, and L2s are always available, and are before cores */
- desc.avail_mask = (1ull << non_sc_block_count) - 1;
- /* Embed the core mask directly in the availability mask */
-- desc.avail_mask |= (v5_info->core_mask << non_sc_block_count);
-+ desc.avail_mask |= (gpu_info->core_mask << non_sc_block_count);
-
- return kbase_hwcnt_metadata_create(&desc, metadata);
- }
-
- /**
-- * kbasep_hwcnt_backend_gpu_v5_dump_bytes() - Get the raw dump buffer size for a
-- * V5 GPU.
-- * @v5_info: Non-NULL pointer to hwcnt info for a v5 GPU.
-+ * kbasep_hwcnt_backend_jm_dump_bytes() - Get the raw dump buffer size for the
-+ * GPU.
-+ * @gpu_info: Non-NULL pointer to hwcnt info for the GPU.
- *
-- * Return: Size of buffer the V5 GPU needs to perform a counter dump.
-+ * Return: Size of buffer the GPU needs to perform a counter dump.
- */
--static size_t kbasep_hwcnt_backend_gpu_v5_dump_bytes(
-- const struct kbase_hwcnt_gpu_v5_info *v5_info)
-+static size_t
-+kbasep_hwcnt_backend_jm_dump_bytes(const struct kbase_hwcnt_gpu_info *gpu_info)
- {
-- WARN_ON(!v5_info);
-- return (2 + v5_info->l2_count + fls64(v5_info->core_mask)) *
-- KBASE_HWCNT_V5_VALUES_PER_BLOCK *
-- KBASE_HWCNT_VALUE_BYTES;
--}
-+ WARN_ON(!gpu_info);
-
--int kbase_hwcnt_gpu_info_init(
-- struct kbase_device *kbdev,
-- struct kbase_hwcnt_gpu_info *info)
--{
-- if (!kbdev || !info)
-- return -EINVAL;
--
--#ifdef CONFIG_MALI_NO_MALI
-- /* NO_MALI uses V5 layout, regardless of the underlying platform. */
-- info->type = KBASE_HWCNT_GPU_GROUP_TYPE_V5;
-- info->v5.l2_count = KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS;
-- info->v5.core_mask = (1ull << KBASE_DUMMY_MODEL_MAX_SHADER_CORES) - 1;
--#else
-- {
-- const struct base_gpu_props *props = &kbdev->gpu_props.props;
-- const size_t l2_count = props->l2_props.num_l2_slices;
-- const size_t core_mask =
-- props->coherency_info.group[0].core_mask;
--
-- info->type = KBASE_HWCNT_GPU_GROUP_TYPE_V5;
-- info->v5.l2_count = l2_count;
-- info->v5.core_mask = core_mask;
-- }
--#endif
-- return 0;
-+ return (2 + gpu_info->l2_count + fls64(gpu_info->core_mask)) *
-+ gpu_info->prfcnt_values_per_block * KBASE_HWCNT_VALUE_BYTES;
- }
-
--int kbase_hwcnt_gpu_metadata_create(
-- const struct kbase_hwcnt_gpu_info *info,
-- bool use_secondary,
-+int kbase_hwcnt_jm_metadata_create(
-+ const struct kbase_hwcnt_gpu_info *gpu_info,
-+ enum kbase_hwcnt_set counter_set,
- const struct kbase_hwcnt_metadata **out_metadata,
- size_t *out_dump_bytes)
- {
-@@ -320,23 +236,19 @@ int kbase_hwcnt_gpu_metadata_create(
- const struct kbase_hwcnt_metadata *metadata;
- size_t dump_bytes;
-
-- if (!info || !out_metadata || !out_dump_bytes)
-+ if (!gpu_info || !out_metadata || !out_dump_bytes)
- return -EINVAL;
-
-- switch (info->type) {
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V4:
-- dump_bytes = kbasep_hwcnt_backend_gpu_v4_dump_bytes(&info->v4);
-- errcode = kbasep_hwcnt_backend_gpu_metadata_v4_create(
-- &info->v4, &metadata);
-- break;
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V5:
-- dump_bytes = kbasep_hwcnt_backend_gpu_v5_dump_bytes(&info->v5);
-- errcode = kbasep_hwcnt_backend_gpu_metadata_v5_create(
-- &info->v5, use_secondary, &metadata);
-- break;
-- default:
-- return -EINVAL;
-- }
-+ /*
-+ * For architectures where a max_config interface is available
-+ * from the arbiter, the v5 dump bytes and the metadata v5 are
-+ * based on the maximum possible allocation of the HW in the
-+ * GPU cause it needs to be prepared for the worst case where
-+ * all the available L2 cache and Shader cores are allocated.
-+ */
-+ dump_bytes = kbasep_hwcnt_backend_jm_dump_bytes(gpu_info);
-+ errcode = kbasep_hwcnt_backend_gpu_metadata_create(
-+ gpu_info, false, counter_set, &metadata);
- if (errcode)
- return errcode;
-
-@@ -351,9 +263,37 @@ int kbase_hwcnt_gpu_metadata_create(
-
- return 0;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_metadata_create);
-
--void kbase_hwcnt_gpu_metadata_destroy(
-+void kbase_hwcnt_jm_metadata_destroy(const struct kbase_hwcnt_metadata *metadata)
-+{
-+ if (!metadata)
-+ return;
-+
-+ kbase_hwcnt_metadata_destroy(metadata);
-+}
-+
-+int kbase_hwcnt_csf_metadata_create(
-+ const struct kbase_hwcnt_gpu_info *gpu_info,
-+ enum kbase_hwcnt_set counter_set,
-+ const struct kbase_hwcnt_metadata **out_metadata)
-+{
-+ int errcode;
-+ const struct kbase_hwcnt_metadata *metadata;
-+
-+ if (!gpu_info || !out_metadata)
-+ return -EINVAL;
-+
-+ errcode = kbasep_hwcnt_backend_gpu_metadata_create(
-+ gpu_info, true, counter_set, &metadata);
-+ if (errcode)
-+ return errcode;
-+
-+ *out_metadata = metadata;
-+
-+ return 0;
-+}
-+
-+void kbase_hwcnt_csf_metadata_destroy(
- const struct kbase_hwcnt_metadata *metadata)
- {
- if (!metadata)
-@@ -361,7 +301,127 @@ void kbase_hwcnt_gpu_metadata_destroy(
-
- kbase_hwcnt_metadata_destroy(metadata);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_metadata_destroy);
-+
-+int kbase_hwcnt_gpu_metadata_create_truncate_64(
-+ const struct kbase_hwcnt_metadata **dst_md,
-+ const struct kbase_hwcnt_metadata *src_md)
-+{
-+ struct kbase_hwcnt_description desc;
-+ struct kbase_hwcnt_group_description group;
-+ struct kbase_hwcnt_block_description
-+ blks[KBASE_HWCNT_V5_BLOCK_TYPE_COUNT];
-+ size_t prfcnt_values_per_block;
-+ size_t blk;
-+
-+ if (!dst_md || !src_md || !src_md->grp_metadata ||
-+ !src_md->grp_metadata[0].blk_metadata)
-+ return -EINVAL;
-+
-+ /* Only support 1 group count and KBASE_HWCNT_V5_BLOCK_TYPE_COUNT block
-+ * count in the metadata.
-+ */
-+ if ((kbase_hwcnt_metadata_group_count(src_md) != 1) ||
-+ (kbase_hwcnt_metadata_block_count(src_md, 0) !=
-+ KBASE_HWCNT_V5_BLOCK_TYPE_COUNT))
-+ return -EINVAL;
-+
-+ /* Get the values count in the first block. */
-+ prfcnt_values_per_block =
-+ kbase_hwcnt_metadata_block_values_count(src_md, 0, 0);
-+
-+ /* check all blocks should have same values count. */
-+ for (blk = 0; blk < KBASE_HWCNT_V5_BLOCK_TYPE_COUNT; blk++) {
-+ size_t val_cnt =
-+ kbase_hwcnt_metadata_block_values_count(src_md, 0, blk);
-+ if (val_cnt != prfcnt_values_per_block)
-+ return -EINVAL;
-+ }
-+
-+ /* Only support 64 and 128 entries per block. */
-+ if ((prfcnt_values_per_block != 64) && (prfcnt_values_per_block != 128))
-+ return -EINVAL;
-+
-+ if (prfcnt_values_per_block == 64) {
-+ /* If the values per block is 64, no need to truncate. */
-+ *dst_md = NULL;
-+ return 0;
-+ }
-+
-+ /* Truncate from 128 to 64 entries per block to keep API backward
-+ * compatibility.
-+ */
-+ prfcnt_values_per_block = 64;
-+
-+ for (blk = 0; blk < KBASE_HWCNT_V5_BLOCK_TYPE_COUNT; blk++) {
-+ blks[blk].type =
-+ kbase_hwcnt_metadata_block_type(src_md, 0, blk);
-+ blks[blk].inst_cnt = kbase_hwcnt_metadata_block_instance_count(
-+ src_md, 0, blk);
-+ blks[blk].hdr_cnt = kbase_hwcnt_metadata_block_headers_count(
-+ src_md, 0, blk);
-+ blks[blk].ctr_cnt = prfcnt_values_per_block - blks[blk].hdr_cnt;
-+ }
-+
-+ group.type = kbase_hwcnt_metadata_group_type(src_md, 0);
-+ group.blk_cnt = KBASE_HWCNT_V5_BLOCK_TYPE_COUNT;
-+ group.blks = blks;
-+
-+ desc.grp_cnt = kbase_hwcnt_metadata_group_count(src_md);
-+ desc.avail_mask = src_md->avail_mask;
-+ desc.clk_cnt = src_md->clk_cnt;
-+ desc.grps = &group;
-+
-+ return kbase_hwcnt_metadata_create(&desc, dst_md);
-+}
-+
-+void kbase_hwcnt_dump_buffer_copy_strict_narrow(
-+ struct kbase_hwcnt_dump_buffer *dst,
-+ const struct kbase_hwcnt_dump_buffer *src,
-+ const struct kbase_hwcnt_enable_map *dst_enable_map)
-+{
-+ const struct kbase_hwcnt_metadata *metadata;
-+ size_t grp, blk, blk_inst;
-+ size_t clk;
-+
-+ if (WARN_ON(!dst) || WARN_ON(!src) || WARN_ON(!dst_enable_map) ||
-+ WARN_ON(dst == src) || WARN_ON(dst->metadata == src->metadata) ||
-+ WARN_ON(dst->metadata->grp_cnt != src->metadata->grp_cnt) ||
-+ WARN_ON(src->metadata->grp_cnt != 1) ||
-+ WARN_ON(dst->metadata->grp_metadata[0].blk_cnt !=
-+ src->metadata->grp_metadata[0].blk_cnt) ||
-+ WARN_ON(dst->metadata->grp_metadata[0].blk_cnt != 4) ||
-+ WARN_ON(dst->metadata->grp_metadata[0].blk_metadata[0].ctr_cnt >
-+ src->metadata->grp_metadata[0].blk_metadata[0].ctr_cnt))
-+ return;
-+
-+ /* Don't use src metadata since src buffer is bigger than dst buffer. */
-+ metadata = dst->metadata;
-+
-+ kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) {
-+ u32 *dst_blk = kbase_hwcnt_dump_buffer_block_instance(
-+ dst, grp, blk, blk_inst);
-+ const u32 *src_blk = kbase_hwcnt_dump_buffer_block_instance(
-+ src, grp, blk, blk_inst);
-+ const u64 *blk_em = kbase_hwcnt_enable_map_block_instance(
-+ dst_enable_map, grp, blk, blk_inst);
-+ size_t val_cnt = kbase_hwcnt_metadata_block_values_count(
-+ metadata, grp, blk);
-+ /* Align upwards to include padding bytes */
-+ val_cnt = KBASE_HWCNT_ALIGN_UPWARDS(
-+ val_cnt, (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT /
-+ KBASE_HWCNT_VALUE_BYTES));
-+
-+ kbase_hwcnt_dump_buffer_block_copy_strict(dst_blk, src_blk,
-+ blk_em, val_cnt);
-+ }
-+
-+ kbase_hwcnt_metadata_for_each_clock(metadata, clk) {
-+ bool clk_enabled = kbase_hwcnt_clk_enable_map_enabled(
-+ dst_enable_map->clk_enable_map, clk);
-+
-+ dst->clk_cnt_buf[clk] = clk_enabled ? src->clk_cnt_buf[clk] : 0;
-+ }
-+}
-
- static bool is_block_type_shader(
- const u64 grp_type,
-@@ -370,44 +430,53 @@ static bool is_block_type_shader(
- {
- bool is_shader = false;
-
-+ /* Warn on unknown group type */
-+ if (WARN_ON(grp_type != KBASE_HWCNT_GPU_GROUP_TYPE_V5))
-+ return false;
-+
-+ if (blk_type == KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC ||
-+ blk_type == KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC2 ||
-+ blk_type == KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC3)
-+ is_shader = true;
-+
-+ return is_shader;
-+}
-+
-+static bool is_block_type_l2_cache(
-+ const u64 grp_type,
-+ const u64 blk_type)
-+{
-+ bool is_l2_cache = false;
-+
- switch (grp_type) {
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V4:
-- /* blk-value in [0, KBASE_HWCNT_V4_SC_BLOCKS_PER_GROUP-1]
-- * corresponds to a shader, or its implementation
-- * reserved. As such, here we use the blk index value to
-- * tell the reserved case.
-- */
-- if (blk_type == KBASE_HWCNT_GPU_V4_BLOCK_TYPE_SHADER ||
-- (blk < KBASE_HWCNT_V4_SC_BLOCKS_PER_GROUP &&
-- blk_type == KBASE_HWCNT_GPU_V4_BLOCK_TYPE_RESERVED))
-- is_shader = true;
-- break;
- case KBASE_HWCNT_GPU_GROUP_TYPE_V5:
-- if (blk_type == KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC ||
-- blk_type == KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC2)
-- is_shader = true;
-+ if (blk_type == KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS ||
-+ blk_type == KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS2)
-+ is_l2_cache = true;
- break;
- default:
- /* Warn on unknown group type */
- WARN_ON(true);
- }
-
-- return is_shader;
-+ return is_l2_cache;
- }
-
--int kbase_hwcnt_gpu_dump_get(
-- struct kbase_hwcnt_dump_buffer *dst,
-- void *src,
-- const struct kbase_hwcnt_enable_map *dst_enable_map,
-- u64 pm_core_mask,
-- bool accumulate)
-+int kbase_hwcnt_jm_dump_get(struct kbase_hwcnt_dump_buffer *dst, void *src,
-+ const struct kbase_hwcnt_enable_map *dst_enable_map,
-+ u64 pm_core_mask,
-+ const struct kbase_hwcnt_curr_config *curr_config,
-+ bool accumulate)
- {
- const struct kbase_hwcnt_metadata *metadata;
- const u32 *dump_src;
- size_t src_offset, grp, blk, blk_inst;
-- size_t grp_prev = 0;
- u64 core_mask = pm_core_mask;
-
-+ /* Variables to deal with the current configuration */
-+ int l2_count = 0;
-+ bool hw_res_available = true;
-+
- if (!dst || !src || !dst_enable_map ||
- (dst_enable_map->metadata != dst->metadata))
- return -EINVAL;
-@@ -429,27 +498,43 @@ int kbase_hwcnt_gpu_dump_get(
- const bool is_shader_core = is_block_type_shader(
- kbase_hwcnt_metadata_group_type(metadata, grp),
- blk_type, blk);
-+ const bool is_l2_cache = is_block_type_l2_cache(
-+ kbase_hwcnt_metadata_group_type(metadata, grp),
-+ blk_type);
-
-- if (grp != grp_prev) {
-- /* grp change would only happen with V4. V5 and
-- * further are envisaged to be single group
-- * scenario only. Here needs to drop the lower
-- * group core-mask by shifting right with
-- * KBASE_HWCNT_V4_SC_BLOCKS_PER_GROUP.
-- */
-- core_mask = pm_core_mask >>
-- KBASE_HWCNT_V4_SC_BLOCKS_PER_GROUP;
-- grp_prev = grp;
-+ /*
-+ * If l2 blocks is greater than the current allocated number of
-+ * L2 slices, there is no hw allocated to that block.
-+ */
-+ if (is_l2_cache) {
-+ l2_count++;
-+ if (l2_count > curr_config->num_l2_slices)
-+ hw_res_available = false;
-+ else
-+ hw_res_available = true;
-+ }
-+ /*
-+ * For the shader cores, the current shader_mask allocated is
-+ * always a subgroup of the maximum shader_mask, so after
-+ * jumping any L2 cache not available the available shader cores
-+ * will always have a matching set of blk instances available to
-+ * accumulate them.
-+ */
-+ else {
-+ hw_res_available = true;
- }
-
-- /* Early out if no values in the dest block are enabled */
-+ /*
-+ * Early out if no values in the dest block are enabled or if
-+ * the resource target of the block is not available in the HW.
-+ */
- if (kbase_hwcnt_enable_map_block_enabled(
- dst_enable_map, grp, blk, blk_inst)) {
- u32 *dst_blk = kbase_hwcnt_dump_buffer_block_instance(
- dst, grp, blk, blk_inst);
- const u32 *src_blk = dump_src + src_offset;
-
-- if (!is_shader_core || (core_mask & 1)) {
-+ if ((!is_shader_core || (core_mask & 1)) && hw_res_available) {
- if (accumulate) {
- kbase_hwcnt_dump_buffer_block_accumulate(
- dst_blk, src_blk, hdr_cnt,
-@@ -465,14 +550,60 @@ int kbase_hwcnt_gpu_dump_get(
- }
- }
-
-- src_offset += (hdr_cnt + ctr_cnt);
-+ /* Just increase the src_offset if the HW is available */
-+ if (hw_res_available)
-+ src_offset += (hdr_cnt + ctr_cnt);
- if (is_shader_core)
- core_mask = core_mask >> 1;
- }
-
- return 0;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_dump_get);
-+
-+int kbase_hwcnt_csf_dump_get(struct kbase_hwcnt_dump_buffer *dst, void *src,
-+ const struct kbase_hwcnt_enable_map *dst_enable_map,
-+ bool accumulate)
-+{
-+ const struct kbase_hwcnt_metadata *metadata;
-+ const u32 *dump_src;
-+ size_t src_offset, grp, blk, blk_inst;
-+
-+ if (!dst || !src || !dst_enable_map ||
-+ (dst_enable_map->metadata != dst->metadata))
-+ return -EINVAL;
-+
-+ metadata = dst->metadata;
-+ dump_src = (const u32 *)src;
-+ src_offset = 0;
-+
-+ kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) {
-+ const size_t hdr_cnt = kbase_hwcnt_metadata_block_headers_count(
-+ metadata, grp, blk);
-+ const size_t ctr_cnt =
-+ kbase_hwcnt_metadata_block_counters_count(metadata, grp,
-+ blk);
-+
-+ /* Early out if no values in the dest block are enabled */
-+ if (kbase_hwcnt_enable_map_block_enabled(dst_enable_map, grp,
-+ blk, blk_inst)) {
-+ u32 *dst_blk = kbase_hwcnt_dump_buffer_block_instance(
-+ dst, grp, blk, blk_inst);
-+ const u32 *src_blk = dump_src + src_offset;
-+
-+ if (accumulate) {
-+ kbase_hwcnt_dump_buffer_block_accumulate(
-+ dst_blk, src_blk, hdr_cnt, ctr_cnt);
-+ } else {
-+ kbase_hwcnt_dump_buffer_block_copy(
-+ dst_blk, src_blk, (hdr_cnt + ctr_cnt));
-+ }
-+ }
-+
-+ src_offset += (hdr_cnt + ctr_cnt);
-+ }
-+
-+ return 0;
-+}
-
- /**
- * kbasep_hwcnt_backend_gpu_block_map_to_physical() - Convert from a block
-@@ -563,7 +694,7 @@ void kbase_hwcnt_gpu_enable_map_to_physical(
- {
- const struct kbase_hwcnt_metadata *metadata;
-
-- u64 jm_bm = 0;
-+ u64 fe_bm = 0;
- u64 shader_bm = 0;
- u64 tiler_bm = 0;
- u64 mmu_l2_bm = 0;
-@@ -581,45 +712,26 @@ void kbase_hwcnt_gpu_enable_map_to_physical(
- metadata, grp);
- const u64 blk_type = kbase_hwcnt_metadata_block_type(
- metadata, grp, blk);
-- const size_t blk_val_cnt =
-- kbase_hwcnt_metadata_block_values_count(
-- metadata, grp, blk);
- const u64 *blk_map = kbase_hwcnt_enable_map_block_instance(
- src, grp, blk, blk_inst);
-
-- switch ((enum kbase_hwcnt_gpu_group_type)grp_type) {
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V4:
-- WARN_ON(blk_val_cnt != KBASE_HWCNT_V4_VALUES_PER_BLOCK);
-- switch ((enum kbase_hwcnt_gpu_v4_block_type)blk_type) {
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_SHADER:
-- shader_bm |= *blk_map;
-- break;
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_TILER:
-- tiler_bm |= *blk_map;
-- break;
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_MMU_L2:
-- mmu_l2_bm |= *blk_map;
-- break;
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_JM:
-- jm_bm |= *blk_map;
-- break;
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_RESERVED:
-- break;
-- default:
-- WARN_ON(true);
-- }
-- break;
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V5:
-- WARN_ON(blk_val_cnt != KBASE_HWCNT_V5_VALUES_PER_BLOCK);
-+ if ((enum kbase_hwcnt_gpu_group_type)grp_type ==
-+ KBASE_HWCNT_GPU_GROUP_TYPE_V5) {
- switch ((enum kbase_hwcnt_gpu_v5_block_type)blk_type) {
-- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_JM:
-- jm_bm |= *blk_map;
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED:
-+ /* Nothing to do in this case. */
-+ break;
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE:
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE2:
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE3:
-+ fe_bm |= *blk_map;
- break;
- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_TILER:
- tiler_bm |= *blk_map;
- break;
- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC:
- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC2:
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC3:
- shader_bm |= *blk_map;
- break;
- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS:
-@@ -629,14 +741,13 @@ void kbase_hwcnt_gpu_enable_map_to_physical(
- default:
- WARN_ON(true);
- }
-- break;
-- default:
-+ } else {
- WARN_ON(true);
- }
- }
-
-- dst->jm_bm =
-- kbasep_hwcnt_backend_gpu_block_map_to_physical(jm_bm, 0);
-+ dst->fe_bm =
-+ kbasep_hwcnt_backend_gpu_block_map_to_physical(fe_bm, 0);
- dst->shader_bm =
- kbasep_hwcnt_backend_gpu_block_map_to_physical(shader_bm, 0);
- dst->tiler_bm =
-@@ -644,7 +755,24 @@ void kbase_hwcnt_gpu_enable_map_to_physical(
- dst->mmu_l2_bm =
- kbasep_hwcnt_backend_gpu_block_map_to_physical(mmu_l2_bm, 0);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_enable_map_to_physical);
-+
-+void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst,
-+ enum kbase_hwcnt_set src)
-+{
-+ switch (src) {
-+ case KBASE_HWCNT_SET_PRIMARY:
-+ *dst = KBASE_HWCNT_PHYSICAL_SET_PRIMARY;
-+ break;
-+ case KBASE_HWCNT_SET_SECONDARY:
-+ *dst = KBASE_HWCNT_PHYSICAL_SET_SECONDARY;
-+ break;
-+ case KBASE_HWCNT_SET_TERTIARY:
-+ *dst = KBASE_HWCNT_PHYSICAL_SET_TERTIARY;
-+ break;
-+ default:
-+ WARN_ON(true);
-+ }
-+}
-
- void kbase_hwcnt_gpu_enable_map_from_physical(
- struct kbase_hwcnt_enable_map *dst,
-@@ -653,7 +781,7 @@ void kbase_hwcnt_gpu_enable_map_from_physical(
- const struct kbase_hwcnt_metadata *metadata;
-
- u64 ignored_hi;
-- u64 jm_bm;
-+ u64 fe_bm;
- u64 shader_bm;
- u64 tiler_bm;
- u64 mmu_l2_bm;
-@@ -665,7 +793,7 @@ void kbase_hwcnt_gpu_enable_map_from_physical(
- metadata = dst->metadata;
-
- kbasep_hwcnt_backend_gpu_block_map_from_physical(
-- src->jm_bm, &jm_bm, &ignored_hi);
-+ src->fe_bm, &fe_bm, &ignored_hi);
- kbasep_hwcnt_backend_gpu_block_map_from_physical(
- src->shader_bm, &shader_bm, &ignored_hi);
- kbasep_hwcnt_backend_gpu_block_map_from_physical(
-@@ -678,45 +806,26 @@ void kbase_hwcnt_gpu_enable_map_from_physical(
- metadata, grp);
- const u64 blk_type = kbase_hwcnt_metadata_block_type(
- metadata, grp, blk);
-- const size_t blk_val_cnt =
-- kbase_hwcnt_metadata_block_values_count(
-- metadata, grp, blk);
- u64 *blk_map = kbase_hwcnt_enable_map_block_instance(
- dst, grp, blk, blk_inst);
-
-- switch ((enum kbase_hwcnt_gpu_group_type)grp_type) {
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V4:
-- WARN_ON(blk_val_cnt != KBASE_HWCNT_V4_VALUES_PER_BLOCK);
-- switch ((enum kbase_hwcnt_gpu_v4_block_type)blk_type) {
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_SHADER:
-- *blk_map = shader_bm;
-- break;
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_TILER:
-- *blk_map = tiler_bm;
-- break;
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_MMU_L2:
-- *blk_map = mmu_l2_bm;
-- break;
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_JM:
-- *blk_map = jm_bm;
-- break;
-- case KBASE_HWCNT_GPU_V4_BLOCK_TYPE_RESERVED:
-- break;
-- default:
-- WARN_ON(true);
-- }
-- break;
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V5:
-- WARN_ON(blk_val_cnt != KBASE_HWCNT_V5_VALUES_PER_BLOCK);
-+ if ((enum kbase_hwcnt_gpu_group_type)grp_type ==
-+ KBASE_HWCNT_GPU_GROUP_TYPE_V5) {
- switch ((enum kbase_hwcnt_gpu_v5_block_type)blk_type) {
-- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_JM:
-- *blk_map = jm_bm;
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED:
-+ /* Nothing to do in this case. */
-+ break;
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE:
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE2:
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE3:
-+ *blk_map = fe_bm;
- break;
- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_TILER:
- *blk_map = tiler_bm;
- break;
- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC:
- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC2:
-+ case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC3:
- *blk_map = shader_bm;
- break;
- case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS:
-@@ -726,13 +835,11 @@ void kbase_hwcnt_gpu_enable_map_from_physical(
- default:
- WARN_ON(true);
- }
-- break;
-- default:
-+ } else {
- WARN_ON(true);
- }
- }
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_enable_map_from_physical);
-
- void kbase_hwcnt_gpu_patch_dump_headers(
- struct kbase_hwcnt_dump_buffer *buf,
-@@ -758,16 +865,11 @@ void kbase_hwcnt_gpu_patch_dump_headers(
- kbasep_hwcnt_backend_gpu_block_map_to_physical(
- blk_map[0], 0);
-
-- switch ((enum kbase_hwcnt_gpu_group_type)grp_type) {
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V4:
-- buf_blk[KBASE_HWCNT_V4_PRFCNT_EN_HEADER] = prfcnt_en;
-- break;
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V5:
-+ if ((enum kbase_hwcnt_gpu_group_type)grp_type ==
-+ KBASE_HWCNT_GPU_GROUP_TYPE_V5) {
- buf_blk[KBASE_HWCNT_V5_PRFCNT_EN_HEADER] = prfcnt_en;
-- break;
-- default:
-+ } else {
- WARN_ON(true);
- }
- }
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_patch_dump_headers);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_gpu.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_gpu.h
-index 12891e0..50ae80d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_gpu.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_gpu.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_HWCNT_GPU_H_
-@@ -30,125 +29,157 @@ struct kbase_hwcnt_metadata;
- struct kbase_hwcnt_enable_map;
- struct kbase_hwcnt_dump_buffer;
-
-+#define KBASE_HWCNT_V5_BLOCK_TYPE_COUNT 4
-+#define KBASE_HWCNT_V5_HEADERS_PER_BLOCK 4
-+#define KBASE_HWCNT_V5_DEFAULT_COUNTERS_PER_BLOCK 60
-+#define KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK \
-+ (KBASE_HWCNT_V5_HEADERS_PER_BLOCK + \
-+ KBASE_HWCNT_V5_DEFAULT_COUNTERS_PER_BLOCK)
-+/** Index of the PRFCNT_EN header into a V5 counter block */
-+#define KBASE_HWCNT_V5_PRFCNT_EN_HEADER 2
-+
- /**
- * enum kbase_hwcnt_gpu_group_type - GPU hardware counter group types, used to
- * identify metadata groups.
-- * @KBASE_HWCNT_GPU_GROUP_TYPE_V4: GPU V4 group type.
- * @KBASE_HWCNT_GPU_GROUP_TYPE_V5: GPU V5 group type.
- */
- enum kbase_hwcnt_gpu_group_type {
-- KBASE_HWCNT_GPU_GROUP_TYPE_V4 = 0x10,
- KBASE_HWCNT_GPU_GROUP_TYPE_V5,
- };
-
--/**
-- * enum kbase_hwcnt_gpu_v4_block_type - GPU V4 hardware counter block types,
-- * used to identify metadata blocks.
-- * @KBASE_HWCNT_GPU_V4_BLOCK_TYPE_SHADER: Shader block.
-- * @KBASE_HWCNT_GPU_V4_BLOCK_TYPE_TILER: Tiler block.
-- * @KBASE_HWCNT_GPU_V4_BLOCK_TYPE_MMU_L2: MMU/L2 block.
-- * @KBASE_HWCNT_GPU_V4_BLOCK_TYPE_JM: Job Manager block.
-- * @KBASE_HWCNT_GPU_V4_BLOCK_TYPE_RESERVED: Reserved block.
-- */
--enum kbase_hwcnt_gpu_v4_block_type {
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_SHADER = 0x20,
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_TILER,
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_MMU_L2,
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_JM,
-- KBASE_HWCNT_GPU_V4_BLOCK_TYPE_RESERVED,
--};
--
- /**
- * enum kbase_hwcnt_gpu_v5_block_type - GPU V5 hardware counter block types,
- * used to identify metadata blocks.
-- * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_JM: Job Manager block.
-- * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_TILER: Tiler block.
-- * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC: Shader Core block.
-- * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC2: Secondary Shader Core block.
-- * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS: Memsys block.
-- * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS2: Secondary Memsys block.
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED: Undefined block (e.g. if a
-+ * counter set that a block
-+ * doesn't support is used).
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE: Front End block (Job manager
-+ * or CSF HW).
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE2: Secondary Front End block (Job
-+ * manager or CSF HW).
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE3: Tertiary Front End block (Job
-+ * manager or CSF HW).
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_TILER: Tiler block.
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC: Shader Core block.
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC2: Secondary Shader Core block.
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC3: Tertiary Shader Core block.
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS: Memsys block.
-+ * @KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS2: Secondary Memsys block.
- */
- enum kbase_hwcnt_gpu_v5_block_type {
-- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_JM = 0x40,
-+ KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED,
-+ KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE,
-+ KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE2,
-+ KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE3,
- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_TILER,
- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC,
- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC2,
-+ KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC3,
- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS,
- KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS2,
- };
-
-+/**
-+ * enum kbase_hwcnt_set - GPU hardware counter sets
-+ * @KBASE_HWCNT_SET_PRIMARY: The Primary set of counters
-+ * @KBASE_HWCNT_SET_SECONDARY: The Secondary set of counters
-+ * @KBASE_HWCNT_SET_TERTIARY: The Tertiary set of counters
-+ */
-+enum kbase_hwcnt_set {
-+ KBASE_HWCNT_SET_PRIMARY,
-+ KBASE_HWCNT_SET_SECONDARY,
-+ KBASE_HWCNT_SET_TERTIARY,
-+};
-+
- /**
- * struct kbase_hwcnt_physical_enable_map - Representation of enable map
- * directly used by GPU.
-- * @jm_bm: Job Manager counters selection bitmask.
-+ * @fe_bm: Front end (JM/CSHW) counters selection bitmask.
- * @shader_bm: Shader counters selection bitmask.
- * @tiler_bm: Tiler counters selection bitmask.
- * @mmu_l2_bm: MMU_L2 counters selection bitmask.
- */
- struct kbase_hwcnt_physical_enable_map {
-- u32 jm_bm;
-+ u32 fe_bm;
- u32 shader_bm;
- u32 tiler_bm;
- u32 mmu_l2_bm;
- };
-
--/**
-- * struct kbase_hwcnt_gpu_v4_info - Information about hwcnt blocks on v4 GPUs.
-- * @cg_count: Core group count.
-- * @cgs: Non-NULL pointer to array of cg_count coherent group structures.
-- *
-- * V4 devices are Mali-T6xx or Mali-T72x, and have one or more core groups,
-- * where each core group may have a physically different layout.
-+/*
-+ * Values for Hardware Counter SET_SELECT value.
-+ * Directly passed to HW.
- */
--struct kbase_hwcnt_gpu_v4_info {
-- size_t cg_count;
-- const struct mali_base_gpu_coherent_group *cgs;
-+enum kbase_hwcnt_physical_set {
-+ KBASE_HWCNT_PHYSICAL_SET_PRIMARY = 0,
-+ KBASE_HWCNT_PHYSICAL_SET_SECONDARY = 1,
-+ KBASE_HWCNT_PHYSICAL_SET_TERTIARY = 2,
- };
-
- /**
-- * struct kbase_hwcnt_gpu_v5_info - Information about hwcnt blocks on v5 GPUs.
-- * @l2_count: L2 cache count.
-- * @core_mask: Shader core mask. May be sparse.
-+ * struct kbase_hwcnt_gpu_info - Information about hwcnt blocks on the GPUs.
-+ * @l2_count: L2 cache count.
-+ * @core_mask: Shader core mask. May be sparse.
-+ * @clk_cnt: Number of clock domains available.
-+ * @prfcnt_values_per_block: Total entries (header + counters) of performance
-+ * counter per block.
- */
--struct kbase_hwcnt_gpu_v5_info {
-+struct kbase_hwcnt_gpu_info {
- size_t l2_count;
- u64 core_mask;
-+ u8 clk_cnt;
-+ size_t prfcnt_values_per_block;
- };
-
- /**
-- * struct kbase_hwcnt_gpu_info - Tagged union with information about the current
-- * GPU's hwcnt blocks.
-- * @type: GPU type.
-- * @v4: Info filled in if a v4 GPU.
-- * @v5: Info filled in if a v5 GPU.
-- */
--struct kbase_hwcnt_gpu_info {
-- enum kbase_hwcnt_gpu_group_type type;
-- union {
-- struct kbase_hwcnt_gpu_v4_info v4;
-- struct kbase_hwcnt_gpu_v5_info v5;
-- };
--};
--
--/**
-- * kbase_hwcnt_gpu_info_init() - Initialise an info structure used to create the
-- * hwcnt metadata.
-- * @kbdev: Non-NULL pointer to kbase device.
-- * @info: Non-NULL pointer to data structure to be filled in.
-+ * struct kbase_hwcnt_curr_config - Current Configuration of HW allocated to the
-+ * GPU.
-+ * @num_l2_slices: Current number of L2 slices allocated to the GPU.
-+ * @shader_present: Current shader present bitmap that is allocated to the GPU.
- *
-- * The initialised info struct will only be valid for use while kbdev is valid.
-+ * For architectures with the max_config interface available from the Arbiter,
-+ * the current resources allocated may change during runtime due to a
-+ * re-partitioning (possible with partition manager). Thus, the HWC needs to be
-+ * prepared to report any possible set of counters. For this reason the memory
-+ * layout in the userspace is based on the maximum possible allocation. On the
-+ * other hand, each partition has just the view of its currently allocated
-+ * resources. Therefore, it is necessary to correctly map the dumped HWC values
-+ * from the registers into this maximum memory layout so that it can be exposed
-+ * to the userspace side correctly.
-+ *
-+ * For L2 cache just the number is enough once the allocated ones will be
-+ * accumulated on the first L2 slots available in the destination buffer.
-+ *
-+ * For the correct mapping of the shader cores it is necessary to jump all the
-+ * L2 cache slots in the destination buffer that are not allocated. But, it is
-+ * not necessary to add any logic to map the shader cores bitmap into the memory
-+ * layout because the shader_present allocated will always be a subset of the
-+ * maximum shader_present. It is possible because:
-+ * 1 - Partitions are made of slices and they are always ordered from the ones
-+ * with more shader cores to the ones with less.
-+ * 2 - The shader cores in a slice are always contiguous.
-+ * 3 - A partition can only have a contiguous set of slices allocated to it.
-+ * So, for example, if 4 slices are available in total, 1 with 4 cores, 2 with
-+ * 3 cores and 1 with 2 cores. The maximum possible shader_present would be:
-+ * 0x0011|0111|0111|1111 -> note the order and that the shader cores are
-+ * contiguous in any slice.
-+ * Supposing that a partition takes the two slices in the middle, the current
-+ * config shader_present for this partition would be:
-+ * 0x0111|0111 -> note that this is a subset of the maximum above and the slices
-+ * are contiguous.
-+ * Therefore, by directly copying any subset of the maximum possible
-+ * shader_present the mapping is already achieved.
- */
--int kbase_hwcnt_gpu_info_init(
-- struct kbase_device *kbdev,
-- struct kbase_hwcnt_gpu_info *info);
-+struct kbase_hwcnt_curr_config {
-+ size_t num_l2_slices;
-+ u64 shader_present;
-+};
-
- /**
-- * kbase_hwcnt_gpu_metadata_create() - Create hardware counter metadata for the
-- * current GPU.
-- * @info: Non-NULL pointer to info struct initialised by
-- * kbase_hwcnt_gpu_info_init.
-- * @use_secondary: True if secondary performance counters should be used, else
-- * false. Ignored if secondary counters are not supported.
-+ * kbase_hwcnt_jm_metadata_create() - Create hardware counter metadata for the
-+ * JM GPUs.
-+ * @info: Non-NULL pointer to info struct.
-+ * @counter_set: The performance counter set used.
- * @out_metadata: Non-NULL pointer to where created metadata is stored on
- * success.
- * @out_dump_bytes: Non-NULL pointer to where the size of the GPU counter dump
-@@ -156,44 +187,133 @@ int kbase_hwcnt_gpu_info_init(
- *
- * Return: 0 on success, else error code.
- */
--int kbase_hwcnt_gpu_metadata_create(
-+int kbase_hwcnt_jm_metadata_create(
- const struct kbase_hwcnt_gpu_info *info,
-- bool use_secondary,
-+ enum kbase_hwcnt_set counter_set,
- const struct kbase_hwcnt_metadata **out_metadata,
- size_t *out_dump_bytes);
-
- /**
-- * kbase_hwcnt_gpu_metadata_destroy() - Destroy GPU hardware counter metadata.
-+ * kbase_hwcnt_jm_metadata_destroy() - Destroy JM GPU hardware counter metadata.
-+ *
-+ * @metadata: Pointer to metadata to destroy.
-+ */
-+void kbase_hwcnt_jm_metadata_destroy(
-+ const struct kbase_hwcnt_metadata *metadata);
-+
-+/**
-+ * kbase_hwcnt_csf_metadata_create() - Create hardware counter metadata for the
-+ * CSF GPUs.
-+ * @info: Non-NULL pointer to info struct.
-+ * @counter_set: The performance counter set used.
-+ * @out_metadata: Non-NULL pointer to where created metadata is stored on
-+ * success.
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+int kbase_hwcnt_csf_metadata_create(
-+ const struct kbase_hwcnt_gpu_info *info,
-+ enum kbase_hwcnt_set counter_set,
-+ const struct kbase_hwcnt_metadata **out_metadata);
-+
-+/**
-+ * kbase_hwcnt_csf_metadata_destroy() - Destroy CSF GPU hardware counter
-+ * metadata.
- * @metadata: Pointer to metadata to destroy.
- */
--void kbase_hwcnt_gpu_metadata_destroy(
-+void kbase_hwcnt_csf_metadata_destroy(
- const struct kbase_hwcnt_metadata *metadata);
-
- /**
-- * kbase_hwcnt_gpu_dump_get() - Copy or accumulate enabled counters from the raw
-+ * kbase_hwcnt_gpu_metadata_create_truncate_64() - Create HWC metadata with HWC
-+ * block entries truncated
-+ * to 64.
-+ *
-+ * @dst_md: Non-NULL pointer to where created metadata is stored on success.
-+ * @src_md: Non-NULL pointer to the HWC metadata used as the source to create
-+ * dst_md.
-+ *
-+ * If the total block entries in src_md is 64, metadata dst_md returns NULL
-+ * since no need to truncate.
-+ * if the total block entries in src_md is 128, then a new metadata with block
-+ * entries truncated to 64 will be created for dst_md, which keeps the interface
-+ * to user clients backward compatible.
-+ * If the total block entries in src_md is other values, function returns error
-+ * since it's not supported.
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+int kbase_hwcnt_gpu_metadata_create_truncate_64(
-+ const struct kbase_hwcnt_metadata **dst_md,
-+ const struct kbase_hwcnt_metadata *src_md);
-+
-+/**
-+ * kbase_hwcnt_dump_buffer_copy_strict_narrow() - Copy all enabled values from
-+ * src to dst.
-+ *
-+ * @dst: Non-NULL pointer to dst dump buffer.
-+ * @src: Non-NULL pointer to src dump buffer.
-+ * @dst_enable_map: Non-NULL pointer to enable map specifying enabled values.
-+ *
-+ * After the operation, all non-enabled values (including padding bytes) will be
-+ * zero.
-+ *
-+ * The dst and src have different metadata, and the dst metadata is narrower
-+ * than src metadata.
-+ */
-+void kbase_hwcnt_dump_buffer_copy_strict_narrow(
-+ struct kbase_hwcnt_dump_buffer *dst,
-+ const struct kbase_hwcnt_dump_buffer *src,
-+ const struct kbase_hwcnt_enable_map *dst_enable_map);
-+
-+/**
-+ * kbase_hwcnt_jm_dump_get() - Copy or accumulate enabled counters from the raw
-+ * dump buffer in src into the dump buffer
-+ * abstraction in dst.
-+ * @dst: Non-NULL pointer to dst dump buffer.
-+ * @src: Non-NULL pointer to src raw dump buffer, of same length
-+ * as returned in out_dump_bytes parameter of
-+ * kbase_hwcnt_jm_metadata_create.
-+ * @dst_enable_map: Non-NULL pointer to enable map specifying enabled values.
-+ * @pm_core_mask: PM state synchronized shaders core mask with the dump.
-+ * @curr_config: Current allocated hardware resources to correctly map the
-+ * src raw dump buffer to the dst dump buffer.
-+ * @accumulate: True if counters in src should be accumulated into dst,
-+ * rather than copied.
-+ *
-+ * The dst and dst_enable_map MUST have been created from the same metadata as
-+ * returned from the call to kbase_hwcnt_jm_metadata_create as was used to get
-+ * the length of src.
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+int kbase_hwcnt_jm_dump_get(struct kbase_hwcnt_dump_buffer *dst, void *src,
-+ const struct kbase_hwcnt_enable_map *dst_enable_map,
-+ const u64 pm_core_mask,
-+ const struct kbase_hwcnt_curr_config *curr_config,
-+ bool accumulate);
-+
-+/**
-+ * kbase_hwcnt_csf_dump_get() - Copy or accumulate enabled counters from the raw
- * dump buffer in src into the dump buffer
- * abstraction in dst.
- * @dst: Non-NULL pointer to dst dump buffer.
- * @src: Non-NULL pointer to src raw dump buffer, of same length
- * as returned in out_dump_bytes parameter of
-- * kbase_hwcnt_gpu_metadata_create.
-+ * kbase_hwcnt_csf_metadata_create.
- * @dst_enable_map: Non-NULL pointer to enable map specifying enabled values.
-- * @pm_core_mask: PM state synchronized shaders core mask with the dump.
- * @accumulate: True if counters in src should be accumulated into dst,
- * rather than copied.
- *
- * The dst and dst_enable_map MUST have been created from the same metadata as
-- * returned from the call to kbase_hwcnt_gpu_metadata_create as was used to get
-+ * returned from the call to kbase_hwcnt_csf_metadata_create as was used to get
- * the length of src.
- *
- * Return: 0 on success, else error code.
- */
--int kbase_hwcnt_gpu_dump_get(
-- struct kbase_hwcnt_dump_buffer *dst,
-- void *src,
-- const struct kbase_hwcnt_enable_map *dst_enable_map,
-- const u64 pm_core_mask,
-- bool accumulate);
-+int kbase_hwcnt_csf_dump_get(struct kbase_hwcnt_dump_buffer *dst, void *src,
-+ const struct kbase_hwcnt_enable_map *dst_enable_map,
-+ bool accumulate);
-
- /**
- * kbase_hwcnt_gpu_enable_map_to_physical() - Convert an enable map abstraction
-@@ -202,7 +322,7 @@ int kbase_hwcnt_gpu_dump_get(
- * @src: Non-NULL pointer to src enable map abstraction.
- *
- * The src must have been created from a metadata returned from a call to
-- * kbase_hwcnt_gpu_metadata_create.
-+ * kbase_hwcnt_jm_metadata_create or kbase_hwcnt_csf_metadata_create.
- *
- * This is a lossy conversion, as the enable map abstraction has one bit per
- * individual counter block value, but the physical enable map uses 1 bit for
-@@ -212,6 +332,16 @@ void kbase_hwcnt_gpu_enable_map_to_physical(
- struct kbase_hwcnt_physical_enable_map *dst,
- const struct kbase_hwcnt_enable_map *src);
-
-+/**
-+ * kbase_hwcnt_gpu_set_to_physical() - Map counter set selection to physical
-+ * SET_SELECT value.
-+ *
-+ * @dst: Non-NULL pointer to dst physical SET_SELECT value.
-+ * @src: Non-NULL pointer to src counter set selection.
-+ */
-+void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst,
-+ enum kbase_hwcnt_set src);
-+
- /**
- * kbase_hwcnt_gpu_enable_map_from_physical() - Convert a physical enable map to
- * an enable map abstraction.
-@@ -219,7 +349,7 @@ void kbase_hwcnt_gpu_enable_map_to_physical(
- * @src: Non-NULL pointer to src physical enable map.
- *
- * The dst must have been created from a metadata returned from a call to
-- * kbase_hwcnt_gpu_metadata_create.
-+ * kbase_hwcnt_jm_metadata_create or kbase_hwcnt_csf_metadata_create.
- *
- * This is a lossy conversion, as the physical enable map can technically
- * support counter blocks with 128 counters each, but no hardware actually uses
-@@ -238,7 +368,7 @@ void kbase_hwcnt_gpu_enable_map_from_physical(
- * @enable_map: Non-NULL pointer to enable map.
- *
- * The buf and enable_map must have been created from a metadata returned from
-- * a call to kbase_hwcnt_gpu_metadata_create.
-+ * a call to kbase_hwcnt_jm_metadata_create or kbase_hwcnt_csf_metadata_create.
- *
- * This function should be used before handing off a dump buffer over the
- * kernel-user boundary, to ensure the header is accurate for the enable map
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_legacy.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_legacy.c
-index b0e6aee..0687253 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_legacy.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_legacy.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,13 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase_hwcnt_legacy.h"
- #include "mali_kbase_hwcnt_virtualizer.h"
- #include "mali_kbase_hwcnt_types.h"
- #include "mali_kbase_hwcnt_gpu.h"
--#include "mali_kbase_ioctl.h"
-+#include <uapi/gpu/arm/midgard/mali_kbase_ioctl.h>
-
- #include <linux/slab.h>
- #include <linux/uaccess.h>
-@@ -69,7 +68,7 @@ int kbase_hwcnt_legacy_client_create(
- goto error;
-
- /* Translate from the ioctl enable map to the internal one */
-- phys_em.jm_bm = enable->jm_bm;
-+ phys_em.fe_bm = enable->fe_bm;
- phys_em.shader_bm = enable->shader_bm;
- phys_em.tiler_bm = enable->tiler_bm;
- phys_em.mmu_l2_bm = enable->mmu_l2_bm;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_legacy.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_legacy.h
-index 7a610ae..36ff44d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_legacy.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_legacy.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_types.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_types.c
-index 1e9efde..492f572 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_types.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_types.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,26 +17,11 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase_hwcnt_types.h"
--#include "mali_kbase.h"
--
--/* Minimum alignment of each block of hardware counters */
--#define KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT \
-- (KBASE_HWCNT_BITFIELD_BITS * KBASE_HWCNT_VALUE_BYTES)
-
--/**
-- * KBASE_HWCNT_ALIGN_UPWARDS() - Align a value to an alignment.
-- * @value: The value to align upwards.
-- * @alignment: The alignment.
-- *
-- * Return: A number greater than or equal to value that is aligned to alignment.
-- */
--#define KBASE_HWCNT_ALIGN_UPWARDS(value, alignment) \
-- (value + ((alignment - (value % alignment)) % alignment))
-+#include <linux/slab.h>
-
- int kbase_hwcnt_metadata_create(
- const struct kbase_hwcnt_description *desc,
-@@ -55,6 +41,10 @@ int kbase_hwcnt_metadata_create(
- if (!desc || !out_metadata)
- return -EINVAL;
-
-+ /* The maximum number of clock domains is 64. */
-+ if (desc->clk_cnt > (sizeof(u64) * BITS_PER_BYTE))
-+ return -EINVAL;
-+
- /* Calculate the bytes needed to tightly pack the metadata */
-
- /* Top level metadata */
-@@ -158,6 +148,7 @@ int kbase_hwcnt_metadata_create(
- enable_map_count * KBASE_HWCNT_BITFIELD_BYTES;
- metadata->dump_buf_bytes = dump_buf_count * KBASE_HWCNT_VALUE_BYTES;
- metadata->avail_mask = desc->avail_mask;
-+ metadata->clk_cnt = desc->clk_cnt;
-
- WARN_ON(size != offset);
- /* Due to the block alignment, there should be exactly one enable map
-@@ -170,13 +161,11 @@ int kbase_hwcnt_metadata_create(
- *out_metadata = metadata;
- return 0;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_metadata_create);
-
- void kbase_hwcnt_metadata_destroy(const struct kbase_hwcnt_metadata *metadata)
- {
- kfree(metadata);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_metadata_destroy);
-
- int kbase_hwcnt_enable_map_alloc(
- const struct kbase_hwcnt_metadata *metadata,
-@@ -187,45 +176,55 @@ int kbase_hwcnt_enable_map_alloc(
- if (!metadata || !enable_map)
- return -EINVAL;
-
-- enable_map_buf = kzalloc(metadata->enable_map_bytes, GFP_KERNEL);
-- if (!enable_map_buf)
-- return -ENOMEM;
-+ if (metadata->enable_map_bytes > 0) {
-+ enable_map_buf =
-+ kzalloc(metadata->enable_map_bytes, GFP_KERNEL);
-+ if (!enable_map_buf)
-+ return -ENOMEM;
-+ } else {
-+ enable_map_buf = NULL;
-+ }
-
- enable_map->metadata = metadata;
-- enable_map->enable_map = enable_map_buf;
-+ enable_map->hwcnt_enable_map = enable_map_buf;
- return 0;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_enable_map_alloc);
-
- void kbase_hwcnt_enable_map_free(struct kbase_hwcnt_enable_map *enable_map)
- {
- if (!enable_map)
- return;
-
-- kfree(enable_map->enable_map);
-- enable_map->enable_map = NULL;
-+ kfree(enable_map->hwcnt_enable_map);
-+ enable_map->hwcnt_enable_map = NULL;
- enable_map->metadata = NULL;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_enable_map_free);
-
- int kbase_hwcnt_dump_buffer_alloc(
- const struct kbase_hwcnt_metadata *metadata,
- struct kbase_hwcnt_dump_buffer *dump_buf)
- {
-- u32 *buf;
-+ size_t dump_buf_bytes;
-+ size_t clk_cnt_buf_bytes;
-+ u8 *buf;
-
- if (!metadata || !dump_buf)
- return -EINVAL;
-
-- buf = kmalloc(metadata->dump_buf_bytes, GFP_KERNEL);
-+ dump_buf_bytes = metadata->dump_buf_bytes;
-+ clk_cnt_buf_bytes = sizeof(*dump_buf->clk_cnt_buf) * metadata->clk_cnt;
-+
-+ /* Make a single allocation for both dump_buf and clk_cnt_buf. */
-+ buf = kmalloc(dump_buf_bytes + clk_cnt_buf_bytes, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- dump_buf->metadata = metadata;
-- dump_buf->dump_buf = buf;
-+ dump_buf->dump_buf = (u32 *)buf;
-+ dump_buf->clk_cnt_buf = (u64 *)(buf + dump_buf_bytes);
-+
- return 0;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_alloc);
-
- void kbase_hwcnt_dump_buffer_free(struct kbase_hwcnt_dump_buffer *dump_buf)
- {
-@@ -235,7 +234,6 @@ void kbase_hwcnt_dump_buffer_free(struct kbase_hwcnt_dump_buffer *dump_buf)
- kfree(dump_buf->dump_buf);
- memset(dump_buf, 0, sizeof(*dump_buf));
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_free);
-
- int kbase_hwcnt_dump_buffer_array_alloc(
- const struct kbase_hwcnt_metadata *metadata,
-@@ -246,10 +244,16 @@ int kbase_hwcnt_dump_buffer_array_alloc(
- size_t buf_idx;
- unsigned int order;
- unsigned long addr;
-+ size_t dump_buf_bytes;
-+ size_t clk_cnt_buf_bytes;
-
- if (!metadata || !dump_bufs)
- return -EINVAL;
-
-+ dump_buf_bytes = metadata->dump_buf_bytes;
-+ clk_cnt_buf_bytes =
-+ sizeof(*dump_bufs->bufs->clk_cnt_buf) * metadata->clk_cnt;
-+
- /* Allocate memory for the dump buffer struct array */
- buffers = kmalloc_array(n, sizeof(*buffers), GFP_KERNEL);
- if (!buffers)
-@@ -258,8 +262,8 @@ int kbase_hwcnt_dump_buffer_array_alloc(
- /* Allocate pages for the actual dump buffers, as they tend to be fairly
- * large.
- */
-- order = get_order(metadata->dump_buf_bytes * n);
-- addr = __get_free_pages(GFP_KERNEL, order);
-+ order = get_order((dump_buf_bytes + clk_cnt_buf_bytes) * n);
-+ addr = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
-
- if (!addr) {
- kfree(buffers);
-@@ -273,15 +277,18 @@ int kbase_hwcnt_dump_buffer_array_alloc(
-
- /* Set the buffer of each dump buf */
- for (buf_idx = 0; buf_idx < n; buf_idx++) {
-- const size_t offset = metadata->dump_buf_bytes * buf_idx;
-+ const size_t dump_buf_offset = dump_buf_bytes * buf_idx;
-+ const size_t clk_cnt_buf_offset =
-+ (dump_buf_bytes * n) + (clk_cnt_buf_bytes * buf_idx);
-
- buffers[buf_idx].metadata = metadata;
-- buffers[buf_idx].dump_buf = (u32 *)(addr + offset);
-+ buffers[buf_idx].dump_buf = (u32 *)(addr + dump_buf_offset);
-+ buffers[buf_idx].clk_cnt_buf =
-+ (u64 *)(addr + clk_cnt_buf_offset);
- }
-
- return 0;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_array_alloc);
-
- void kbase_hwcnt_dump_buffer_array_free(
- struct kbase_hwcnt_dump_buffer_array *dump_bufs)
-@@ -293,7 +300,6 @@ void kbase_hwcnt_dump_buffer_array_free(
- free_pages(dump_bufs->page_addr, dump_bufs->page_order);
- memset(dump_bufs, 0, sizeof(*dump_bufs));
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_array_free);
-
- void kbase_hwcnt_dump_buffer_zero(
- struct kbase_hwcnt_dump_buffer *dst,
-@@ -324,8 +330,10 @@ void kbase_hwcnt_dump_buffer_zero(
-
- kbase_hwcnt_dump_buffer_block_zero(dst_blk, val_cnt);
- }
-+
-+ memset(dst->clk_cnt_buf, 0,
-+ sizeof(*dst->clk_cnt_buf) * metadata->clk_cnt);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_zero);
-
- void kbase_hwcnt_dump_buffer_zero_strict(
- struct kbase_hwcnt_dump_buffer *dst)
-@@ -334,8 +342,10 @@ void kbase_hwcnt_dump_buffer_zero_strict(
- return;
-
- memset(dst->dump_buf, 0, dst->metadata->dump_buf_bytes);
-+
-+ memset(dst->clk_cnt_buf, 0,
-+ sizeof(*dst->clk_cnt_buf) * dst->metadata->clk_cnt);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_zero_strict);
-
- void kbase_hwcnt_dump_buffer_zero_non_enabled(
- struct kbase_hwcnt_dump_buffer *dst,
-@@ -375,7 +385,6 @@ void kbase_hwcnt_dump_buffer_zero_non_enabled(
- }
- }
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_zero_non_enabled);
-
- void kbase_hwcnt_dump_buffer_copy(
- struct kbase_hwcnt_dump_buffer *dst,
-@@ -384,6 +393,7 @@ void kbase_hwcnt_dump_buffer_copy(
- {
- const struct kbase_hwcnt_metadata *metadata;
- size_t grp, blk, blk_inst;
-+ size_t clk;
-
- if (WARN_ON(!dst) ||
- WARN_ON(!src) ||
-@@ -413,8 +423,13 @@ void kbase_hwcnt_dump_buffer_copy(
-
- kbase_hwcnt_dump_buffer_block_copy(dst_blk, src_blk, val_cnt);
- }
-+
-+ kbase_hwcnt_metadata_for_each_clock(metadata, clk) {
-+ if (kbase_hwcnt_clk_enable_map_enabled(
-+ dst_enable_map->clk_enable_map, clk))
-+ dst->clk_cnt_buf[clk] = src->clk_cnt_buf[clk];
-+ }
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_copy);
-
- void kbase_hwcnt_dump_buffer_copy_strict(
- struct kbase_hwcnt_dump_buffer *dst,
-@@ -423,6 +438,7 @@ void kbase_hwcnt_dump_buffer_copy_strict(
- {
- const struct kbase_hwcnt_metadata *metadata;
- size_t grp, blk, blk_inst;
-+ size_t clk;
-
- if (WARN_ON(!dst) ||
- WARN_ON(!src) ||
-@@ -451,8 +467,15 @@ void kbase_hwcnt_dump_buffer_copy_strict(
- kbase_hwcnt_dump_buffer_block_copy_strict(
- dst_blk, src_blk, blk_em, val_cnt);
- }
-+
-+ kbase_hwcnt_metadata_for_each_clock(metadata, clk) {
-+ bool clk_enabled =
-+ kbase_hwcnt_clk_enable_map_enabled(
-+ dst_enable_map->clk_enable_map, clk);
-+
-+ dst->clk_cnt_buf[clk] = clk_enabled ? src->clk_cnt_buf[clk] : 0;
-+ }
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_copy_strict);
-
- void kbase_hwcnt_dump_buffer_accumulate(
- struct kbase_hwcnt_dump_buffer *dst,
-@@ -461,6 +484,7 @@ void kbase_hwcnt_dump_buffer_accumulate(
- {
- const struct kbase_hwcnt_metadata *metadata;
- size_t grp, blk, blk_inst;
-+ size_t clk;
-
- if (WARN_ON(!dst) ||
- WARN_ON(!src) ||
-@@ -494,8 +518,13 @@ void kbase_hwcnt_dump_buffer_accumulate(
- kbase_hwcnt_dump_buffer_block_accumulate(
- dst_blk, src_blk, hdr_cnt, ctr_cnt);
- }
-+
-+ kbase_hwcnt_metadata_for_each_clock(metadata, clk) {
-+ if (kbase_hwcnt_clk_enable_map_enabled(
-+ dst_enable_map->clk_enable_map, clk))
-+ dst->clk_cnt_buf[clk] += src->clk_cnt_buf[clk];
-+ }
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_accumulate);
-
- void kbase_hwcnt_dump_buffer_accumulate_strict(
- struct kbase_hwcnt_dump_buffer *dst,
-@@ -504,6 +533,7 @@ void kbase_hwcnt_dump_buffer_accumulate_strict(
- {
- const struct kbase_hwcnt_metadata *metadata;
- size_t grp, blk, blk_inst;
-+ size_t clk;
-
- if (WARN_ON(!dst) ||
- WARN_ON(!src) ||
-@@ -534,5 +564,12 @@ void kbase_hwcnt_dump_buffer_accumulate_strict(
- kbase_hwcnt_dump_buffer_block_accumulate_strict(
- dst_blk, src_blk, blk_em, hdr_cnt, ctr_cnt);
- }
-+
-+ kbase_hwcnt_metadata_for_each_clock(metadata, clk) {
-+ if (kbase_hwcnt_clk_enable_map_enabled(
-+ dst_enable_map->clk_enable_map, clk))
-+ dst->clk_cnt_buf[clk] += src->clk_cnt_buf[clk];
-+ else
-+ dst->clk_cnt_buf[clk] = 0;
-+ }
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_accumulate_strict);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_types.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_types.h
-index 4d78c84..da12952 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_types.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_types.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-@@ -85,7 +84,6 @@
- #include <linux/kernel.h>
- #include <linux/string.h>
- #include <linux/types.h>
--#include "mali_malisw.h"
-
- /* Number of bytes in each bitfield */
- #define KBASE_HWCNT_BITFIELD_BYTES (sizeof(u64))
-@@ -101,6 +99,21 @@
- */
- #define KBASE_HWCNT_AVAIL_MASK_BITS (sizeof(u64) * BITS_PER_BYTE)
-
-+/* Minimum alignment of each block of hardware counters */
-+#define KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT \
-+ (KBASE_HWCNT_BITFIELD_BITS * KBASE_HWCNT_VALUE_BYTES)
-+
-+/**
-+ * KBASE_HWCNT_ALIGN_UPWARDS() - Calculate next aligned value.
-+ * @value: The value to align upwards.
-+ * @alignment: The alignment boundary.
-+ *
-+ * Return: Input value if already aligned to the specified boundary, or next
-+ * (incrementing upwards) aligned value.
-+ */
-+#define KBASE_HWCNT_ALIGN_UPWARDS(value, alignment) \
-+ (value + ((alignment - (value % alignment)) % alignment))
-+
- /**
- * struct kbase_hwcnt_block_description - Description of one or more identical,
- * contiguous, Hardware Counter Blocks.
-@@ -136,11 +149,13 @@ struct kbase_hwcnt_group_description {
- * @grps: Non-NULL pointer to an array of grp_cnt group descriptions,
- * describing each Hardware Counter Group in the system.
- * @avail_mask: Flat Availability Mask for all block instances in the system.
-+ * @clk_cnt: The number of clock domains in the system. The maximum is 64.
- */
- struct kbase_hwcnt_description {
- size_t grp_cnt;
- const struct kbase_hwcnt_group_description *grps;
- u64 avail_mask;
-+ u8 clk_cnt;
- };
-
- /**
-@@ -220,6 +235,7 @@ struct kbase_hwcnt_group_metadata {
- * @enable_map_bytes: The size in bytes of an Enable Map needed for the system.
- * @dump_buf_bytes: The size in bytes of a Dump Buffer needed for the system.
- * @avail_mask: The Availability Mask for the system.
-+ * @clk_cnt: The number of clock domains in the system.
- */
- struct kbase_hwcnt_metadata {
- size_t grp_cnt;
-@@ -227,6 +243,7 @@ struct kbase_hwcnt_metadata {
- size_t enable_map_bytes;
- size_t dump_buf_bytes;
- u64 avail_mask;
-+ u8 clk_cnt;
- };
-
- /**
-@@ -234,13 +251,16 @@ struct kbase_hwcnt_metadata {
- * bitfields.
- * @metadata: Non-NULL pointer to metadata used to identify, and to describe
- * the layout of the enable map.
-- * @enable_map: Non-NULL pointer of size metadata->enable_map_bytes to an array
-- * of u64 bitfields, each bit of which enables one hardware
-+ * @hwcnt_enable_map: Non-NULL pointer of size metadata->enable_map_bytes to an
-+ * array of u64 bitfields, each bit of which enables one hardware
- * counter.
-+ * @clk_enable_map: An array of u64 bitfields, each bit of which enables cycle
-+ * counter for a given clock domain.
- */
- struct kbase_hwcnt_enable_map {
- const struct kbase_hwcnt_metadata *metadata;
-- u64 *enable_map;
-+ u64 *hwcnt_enable_map;
-+ u64 clk_enable_map;
- };
-
- /**
-@@ -250,10 +270,13 @@ struct kbase_hwcnt_enable_map {
- * the layout of the Dump Buffer.
- * @dump_buf: Non-NULL pointer of size metadata->dump_buf_bytes to an array
- * of u32 values.
-+ * @clk_cnt_buf: A pointer to an array of u64 values for cycle count elapsed
-+ * for each clock domain.
- */
- struct kbase_hwcnt_dump_buffer {
- const struct kbase_hwcnt_metadata *metadata;
- u32 *dump_buf;
-+ u64 *clk_cnt_buf;
- };
-
- /**
-@@ -349,8 +372,7 @@ void kbase_hwcnt_metadata_destroy(const struct kbase_hwcnt_metadata *metadata);
- * @grp: Index of the group in the metadata.
- * @blk: Index of the block in the group.
- *
-- * Return: Number of u32 counter headers in each instance of block blk in
-- * group grp.
-+ * Return: Number of counter headers in each instance of block blk in group grp.
- */
- #define kbase_hwcnt_metadata_block_headers_count(metadata, grp, blk) \
- ((metadata)->grp_metadata[(grp)].blk_metadata[(blk)].hdr_cnt)
-@@ -361,19 +383,29 @@ void kbase_hwcnt_metadata_destroy(const struct kbase_hwcnt_metadata *metadata);
- * @grp: Index of the group in the metadata.
- * @blk: Index of the block in the group.
- *
-- * Return: Number of u32 counters in each instance of block blk in group
-- * grp.
-+ * Return: Number of counters in each instance of block blk in group grp.
- */
- #define kbase_hwcnt_metadata_block_counters_count(metadata, grp, blk) \
- ((metadata)->grp_metadata[(grp)].blk_metadata[(blk)].ctr_cnt)
-
-+/**
-+ * kbase_hwcnt_metadata_block_enable_map_stride() - Get the enable map stride.
-+ * @metadata: Non-NULL pointer to metadata.
-+ * @grp: Index of the group in the metadata.
-+ * @blk: Index of the block in the group.
-+ *
-+ * Return: enable map stride in each instance of block blk in group grp.
-+ */
-+#define kbase_hwcnt_metadata_block_enable_map_stride(metadata, grp, blk) \
-+ ((metadata)->grp_metadata[(grp)].blk_metadata[(blk)].enable_map_stride)
-+
- /**
- * kbase_hwcnt_metadata_block_values_count() - Get the number of values.
- * @metadata: Non-NULL pointer to metadata.
- * @grp: Index of the group in the metadata.
- * @blk: Index of the block in the group.
- *
-- * Return: Number of u32 headers plus counters in each instance of block blk
-+ * Return: Number of headers plus counters in each instance of block blk
- * in group grp.
- */
- #define kbase_hwcnt_metadata_block_values_count(metadata, grp, blk) \
-@@ -473,7 +505,7 @@ void kbase_hwcnt_enable_map_free(struct kbase_hwcnt_enable_map *enable_map);
- * block instance.
- */
- #define kbase_hwcnt_enable_map_block_instance(map, grp, blk, blk_inst) \
-- ((map)->enable_map + \
-+ ((map)->hwcnt_enable_map + \
- (map)->metadata->grp_metadata[(grp)].enable_map_index + \
- (map)->metadata->grp_metadata[(grp)].blk_metadata[(blk)].enable_map_index + \
- (map)->metadata->grp_metadata[(grp)].blk_metadata[(blk)].enable_map_stride * (blk_inst))
-@@ -520,7 +552,11 @@ static inline void kbase_hwcnt_enable_map_block_disable_all(
- static inline void kbase_hwcnt_enable_map_disable_all(
- struct kbase_hwcnt_enable_map *dst)
- {
-- memset(dst->enable_map, 0, dst->metadata->enable_map_bytes);
-+ if (dst->hwcnt_enable_map != NULL)
-+ memset(dst->hwcnt_enable_map, 0,
-+ dst->metadata->enable_map_bytes);
-+
-+ dst->clk_enable_map = 0;
- }
-
- /**
-@@ -569,6 +605,8 @@ static inline void kbase_hwcnt_enable_map_enable_all(
- kbase_hwcnt_metadata_for_each_block(dst->metadata, grp, blk, blk_inst)
- kbase_hwcnt_enable_map_block_enable_all(
- dst, grp, blk, blk_inst);
-+
-+ dst->clk_enable_map = (1ull << dst->metadata->clk_cnt) - 1;
- }
-
- /**
-@@ -582,9 +620,13 @@ static inline void kbase_hwcnt_enable_map_copy(
- struct kbase_hwcnt_enable_map *dst,
- const struct kbase_hwcnt_enable_map *src)
- {
-- memcpy(dst->enable_map,
-- src->enable_map,
-- dst->metadata->enable_map_bytes);
-+ if (dst->hwcnt_enable_map != NULL) {
-+ memcpy(dst->hwcnt_enable_map,
-+ src->hwcnt_enable_map,
-+ dst->metadata->enable_map_bytes);
-+ }
-+
-+ dst->clk_enable_map = src->clk_enable_map;
- }
-
- /**
-@@ -602,8 +644,12 @@ static inline void kbase_hwcnt_enable_map_union(
- dst->metadata->enable_map_bytes / KBASE_HWCNT_BITFIELD_BYTES;
- size_t i;
-
-- for (i = 0; i < bitfld_count; i++)
-- dst->enable_map[i] |= src->enable_map[i];
-+ if (dst->hwcnt_enable_map != NULL) {
-+ for (i = 0; i < bitfld_count; i++)
-+ dst->hwcnt_enable_map[i] |= src->hwcnt_enable_map[i];
-+ }
-+
-+ dst->clk_enable_map |= src->clk_enable_map;
- }
-
- /**
-@@ -656,6 +702,12 @@ static inline bool kbase_hwcnt_enable_map_any_enabled(
- const struct kbase_hwcnt_enable_map *enable_map)
- {
- size_t grp, blk, blk_inst;
-+ const u64 clk_enable_map_mask =
-+ (1ull << enable_map->metadata->clk_cnt) - 1;
-+
-+ if (enable_map->metadata->clk_cnt > 0 &&
-+ (enable_map->clk_enable_map & clk_enable_map_mask))
-+ return true;
-
- kbase_hwcnt_metadata_for_each_block(
- enable_map->metadata, grp, blk, blk_inst) {
-@@ -749,12 +801,10 @@ void kbase_hwcnt_dump_buffer_free(struct kbase_hwcnt_dump_buffer *dump_buf);
- * kbase_hwcnt_dump_buffer_array_alloc() - Allocate an array of dump buffers.
- * @metadata: Non-NULL pointer to metadata describing the system.
- * @n: Number of dump buffers to allocate
-- * @dump_bufs: Non-NULL pointer to dump buffer array to be initialised. Each
-- * dump buffer in the array will be initialised to undefined values,
-- * so must be used as a copy dest, or cleared before use.
-+ * @dump_bufs: Non-NULL pointer to dump buffer array to be initialised.
- *
-- * A single contiguous page allocation will be used for all of the buffers
-- * inside the array, where:
-+ * A single zeroed contiguous page allocation will be used for all of the
-+ * buffers inside the array, where:
- * dump_bufs[n].dump_buf == page_addr + n * metadata.dump_buf_bytes
- *
- * Return: 0 on success, else error code.
-@@ -1084,4 +1134,29 @@ static inline void kbase_hwcnt_dump_buffer_block_accumulate_strict(
- }
- }
-
-+/**
-+ * Iterate over each clock domain in the metadata.
-+ *
-+ * @md: Non-NULL pointer to metadata.
-+ * @clk: size_t variable used as clock iterator.
-+ */
-+#define kbase_hwcnt_metadata_for_each_clock(md, clk) \
-+ for ((clk) = 0; (clk) < (md)->clk_cnt; (clk)++)
-+
-+/**
-+ * kbase_hwcnt_clk_enable_map_enabled() - Check if the given index is enabled
-+ * in clk_enable_map.
-+ * @clk_enable_map: An enable map for clock domains.
-+ * @index: Index of the enable map for clock domain.
-+ *
-+ * Return: true if the index of the clock domain is enabled, else false.
-+ */
-+static inline bool kbase_hwcnt_clk_enable_map_enabled(
-+ const u64 clk_enable_map, const size_t index)
-+{
-+ if (clk_enable_map & (1ull << index))
-+ return true;
-+ return false;
-+}
-+
- #endif /* _KBASE_HWCNT_TYPES_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_virtualizer.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_virtualizer.c
-index 917e47c..52ecb7b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_virtualizer.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_virtualizer.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,17 +17,12 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase_hwcnt_virtualizer.h"
- #include "mali_kbase_hwcnt_accumulator.h"
- #include "mali_kbase_hwcnt_context.h"
- #include "mali_kbase_hwcnt_types.h"
--#include "mali_malisw.h"
--#include "mali_kbase_debug.h"
--#include "mali_kbase_linux.h"
-
- #include <linux/mutex.h>
- #include <linux/slab.h>
-@@ -87,7 +83,6 @@ const struct kbase_hwcnt_metadata *kbase_hwcnt_virtualizer_metadata(
-
- return hvirt->metadata;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_virtualizer_metadata);
-
- /**
- * kbasep_hwcnt_virtualizer_client_free - Free a virtualizer client's memory.
-@@ -496,7 +491,6 @@ int kbase_hwcnt_virtualizer_client_set_counters(
-
- return errcode;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_virtualizer_client_set_counters);
-
- /**
- * kbasep_hwcnt_virtualizer_client_dump - Perform a dump of the client's
-@@ -686,7 +680,6 @@ int kbase_hwcnt_virtualizer_client_dump(
-
- return errcode;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_virtualizer_client_dump);
-
- int kbase_hwcnt_virtualizer_client_create(
- struct kbase_hwcnt_virtualizer *hvirt,
-@@ -719,7 +712,6 @@ int kbase_hwcnt_virtualizer_client_create(
- *out_hvcli = hvcli;
- return 0;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_virtualizer_client_create);
-
- void kbase_hwcnt_virtualizer_client_destroy(
- struct kbase_hwcnt_virtualizer_client *hvcli)
-@@ -735,7 +727,6 @@ void kbase_hwcnt_virtualizer_client_destroy(
-
- kbasep_hwcnt_virtualizer_client_free(hvcli);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_virtualizer_client_destroy);
-
- int kbase_hwcnt_virtualizer_init(
- struct kbase_hwcnt_context *hctx,
-@@ -766,7 +757,6 @@ int kbase_hwcnt_virtualizer_init(
- *out_hvirt = virt;
- return 0;
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_virtualizer_init);
-
- void kbase_hwcnt_virtualizer_term(
- struct kbase_hwcnt_virtualizer *hvirt)
-@@ -787,4 +777,12 @@ void kbase_hwcnt_virtualizer_term(
-
- kfree(hvirt);
- }
--KBASE_EXPORT_TEST_API(kbase_hwcnt_virtualizer_term);
-+
-+bool kbase_hwcnt_virtualizer_queue_work(struct kbase_hwcnt_virtualizer *hvirt,
-+ struct work_struct *work)
-+{
-+ if (WARN_ON(!hvirt) || WARN_ON(!work))
-+ return false;
-+
-+ return kbase_hwcnt_context_queue_work(hvirt->hctx, work);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_virtualizer.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_virtualizer.h
-index 8f628c3..e3a8137 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_virtualizer.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_virtualizer.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-@@ -31,6 +30,7 @@
- #define _KBASE_HWCNT_VIRTUALIZER_H_
-
- #include <linux/types.h>
-+#include <linux/workqueue.h>
-
- struct kbase_hwcnt_context;
- struct kbase_hwcnt_virtualizer;
-@@ -142,4 +142,19 @@ int kbase_hwcnt_virtualizer_client_dump(
- u64 *ts_end_ns,
- struct kbase_hwcnt_dump_buffer *dump_buf);
-
-+/**
-+ * kbase_hwcnt_virtualizer_queue_work() - Queue hardware counter related async
-+ * work on a workqueue specialized for
-+ * hardware counters.
-+ * @hvirt: Non-NULL pointer to the hardware counter virtualizer.
-+ * @work: Non-NULL pointer to work to queue.
-+ *
-+ * Return: false if work was already on a queue, true otherwise.
-+ *
-+ * This is a convenience function that directly calls the underlying
-+ * kbase_hwcnt_context's kbase_hwcnt_context_queue_work.
-+ */
-+bool kbase_hwcnt_virtualizer_queue_work(struct kbase_hwcnt_virtualizer *hvirt,
-+ struct work_struct *work);
-+
- #endif /* _KBASE_HWCNT_VIRTUALIZER_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd.c
-index 43f4b4d..83977f8 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,22 +17,20 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #include <linux/dma-buf.h>
--#ifdef CONFIG_COMPAT
-+#if IS_ENABLED(CONFIG_COMPAT)
- #include <linux/compat.h>
- #endif
- #include <mali_kbase.h>
- #include <linux/random.h>
- #include <linux/version.h>
- #include <linux/ratelimit.h>
-+#include <linux/priority_control_manager.h>
-
- #include <mali_kbase_jm.h>
-+#include <mali_kbase_kinstr_jm.h>
- #include <mali_kbase_hwaccess_jm.h>
- #include <tl/mali_kbase_tracepoints.h>
- #include <mali_linux_trace.h>
-@@ -39,24 +38,17 @@
- #include "mali_kbase_dma_fence.h"
- #include <mali_kbase_cs_experimental.h>
-
--#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a)
-+#include <mali_kbase_caps.h>
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
--/* random32 was renamed to prandom_u32 in 3.8 */
--#define prandom_u32 random32
--#endif
-+#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a)
-
- /* Return whether katom will run on the GPU or not. Currently only soft jobs and
-- * dependency-only atoms do not run on the GPU */
-+ * dependency-only atoms do not run on the GPU
-+ */
- #define IS_GPU_ATOM(katom) (!((katom->core_req & BASE_JD_REQ_SOFT_JOB) || \
- ((katom->core_req & BASE_JD_REQ_ATOM_TYPE) == \
- BASE_JD_REQ_DEP)))
-
--/* Minimum API version that supports the just-in-time memory allocation pressure
-- * limit feature.
-- */
--#define MIN_API_VERSION_WITH_JPL KBASE_API_VERSION(11, 20)
--
- /*
- * This is the kernel side of the API. Only entry points are:
- * - kbase_jd_submit(): Called from userspace to submit a single bag
-@@ -70,13 +62,22 @@
- static void __user *
- get_compat_pointer(struct kbase_context *kctx, const u64 p)
- {
--#ifdef CONFIG_COMPAT
-+#if IS_ENABLED(CONFIG_COMPAT)
- if (kbase_ctx_flag(kctx, KCTX_COMPAT))
- return compat_ptr(p);
- #endif
- return u64_to_user_ptr(p);
- }
-
-+/* Mark an atom as complete, and trace it in kinstr_jm */
-+static void jd_mark_atom_complete(struct kbase_jd_atom *katom)
-+{
-+ katom->status = KBASE_JD_ATOM_STATE_COMPLETED;
-+ kbase_kinstr_jm_atom_complete(katom);
-+ dev_dbg(katom->kctx->kbdev->dev, "Atom %pK status to completed\n",
-+ (void *)katom);
-+}
-+
- /* 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.
-@@ -88,7 +89,7 @@ static bool jd_run_atom(struct kbase_jd_atom *katom)
- {
- struct kbase_context *kctx = katom->kctx;
-
-- dev_dbg(kctx->kbdev->dev, "JD run atom %p in kctx %p\n",
-+ dev_dbg(kctx->kbdev->dev, "JD run atom %pK in kctx %pK\n",
- (void *)katom, (void *)kctx);
-
- KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED);
-@@ -97,30 +98,24 @@ static bool jd_run_atom(struct kbase_jd_atom *katom)
- /* Dependency only atom */
- trace_sysgraph(SGR_SUBMIT, kctx->id,
- kbase_jd_atom_id(katom->kctx, katom));
-- katom->status = KBASE_JD_ATOM_STATE_COMPLETED;
-- dev_dbg(kctx->kbdev->dev, "Atom %p status to completed\n",
-- (void *)katom);
-- return 0;
-+ jd_mark_atom_complete(katom);
-+ return false;
- } else if (katom->core_req & BASE_JD_REQ_SOFT_JOB) {
- /* Soft-job */
- if (katom->will_fail_event_code) {
- kbase_finish_soft_job(katom);
-- katom->status = KBASE_JD_ATOM_STATE_COMPLETED;
-- dev_dbg(kctx->kbdev->dev,
-- "Atom %p status to completed\n", (void *)katom);
-- return 0;
-+ jd_mark_atom_complete(katom);
-+ return false;
- }
- if (kbase_process_soft_job(katom) == 0) {
- kbase_finish_soft_job(katom);
-- katom->status = KBASE_JD_ATOM_STATE_COMPLETED;
-- dev_dbg(kctx->kbdev->dev,
-- "Atom %p status to completed\n", (void *)katom);
-+ jd_mark_atom_complete(katom);
- }
-- return 0;
-+ return false;
- }
-
- katom->status = KBASE_JD_ATOM_STATE_IN_JS;
-- dev_dbg(kctx->kbdev->dev, "Atom %p status to in JS\n", (void *)katom);
-+ dev_dbg(kctx->kbdev->dev, "Atom %pK status to in JS\n", (void *)katom);
- /* Queue an action about whether we should try scheduling a context */
- return kbasep_js_add_job(kctx, katom);
- }
-@@ -205,7 +200,7 @@ static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom)
- * jctx.lock must be held when this is called.
- */
-
--static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const struct base_jd_atom_v2 *user_atom)
-+static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const struct base_jd_atom *user_atom)
- {
- int err_ret_val = -EINVAL;
- u32 res_no;
-@@ -242,7 +237,8 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st
-
- /* copy user buffer to the end of our real buffer.
- * Make sure the struct sizes haven't changed in a way
-- * we don't support */
-+ * we don't support
-+ */
- BUILD_BUG_ON(sizeof(*input_extres) > sizeof(*katom->extres));
- input_extres = (struct base_external_resource *)
- (((unsigned char *)katom->extres) +
-@@ -258,9 +254,14 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st
-
- #ifdef CONFIG_MALI_DMA_FENCE
- if (implicit_sync) {
-- info.resv_objs = kmalloc_array(katom->nr_extres,
-- sizeof(struct reservation_object *),
-- GFP_KERNEL);
-+ info.resv_objs =
-+ kmalloc_array(katom->nr_extres,
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
-+ sizeof(struct reservation_object *),
-+#else
-+ sizeof(struct dma_resv *),
-+#endif
-+ GFP_KERNEL);
- if (!info.resv_objs) {
- err_ret_val = -ENOMEM;
- goto early_err_out;
-@@ -277,7 +278,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st
- #endif /* CONFIG_MALI_DMA_FENCE */
-
- /* Take the processes mmap lock */
-- down_read(¤t->mm->mmap_sem);
-+ down_read(kbase_mem_get_process_mmap_lock());
-
- /* need to keep the GPU VM locked while we set up UMM buffers */
- kbase_gpu_vm_lock(katom->kctx);
-@@ -314,8 +315,11 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st
- #ifdef CONFIG_MALI_DMA_FENCE
- if (implicit_sync &&
- reg->gpu_alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) {
-+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
- struct reservation_object *resv;
--
-+#else
-+ struct dma_resv *resv;
-+#endif
- resv = reg->gpu_alloc->imported.umm.dma_buf->resv;
- if (resv)
- kbase_dma_fence_add_reservation(resv, &info,
-@@ -328,7 +332,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st
- * at least not before the first write) as we overwrite elements
- * as we loop and could be overwriting ourself, so no writes
- * until the last read for an element.
-- * */
-+ */
- katom->extres[res_no].gpu_address = reg->start_pfn << PAGE_SHIFT; /* save the start_pfn (as an address, not pfn) to use fast lookup later */
- katom->extres[res_no].alloc = alloc;
- }
-@@ -337,7 +341,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st
- kbase_gpu_vm_unlock(katom->kctx);
-
- /* Release the processes mmap lock */
-- up_read(¤t->mm->mmap_sem);
-+ up_read(kbase_mem_get_process_mmap_lock());
-
- #ifdef CONFIG_MALI_DMA_FENCE
- if (implicit_sync) {
-@@ -362,7 +366,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st
- #ifdef CONFIG_MALI_DMA_FENCE
- failed_dma_fence_setup:
- /* Lock the processes mmap lock */
-- down_read(¤t->mm->mmap_sem);
-+ down_read(kbase_mem_get_process_mmap_lock());
-
- /* lock before we unmap */
- kbase_gpu_vm_lock(katom->kctx);
-@@ -378,7 +382,7 @@ failed_dma_fence_setup:
- kbase_gpu_vm_unlock(katom->kctx);
-
- /* Release the processes mmap lock */
-- up_read(¤t->mm->mmap_sem);
-+ up_read(kbase_mem_get_process_mmap_lock());
-
- early_err_out:
- kfree(katom->extres);
-@@ -455,9 +459,6 @@ static inline void jd_resolve_dep(struct list_head *out_list,
- #endif /* CONFIG_MALI_DMA_FENCE */
-
- if (dep_satisfied) {
-- trace_sysgraph(SGR_DEP_RES,
-- dep_atom->kctx->id,
-- kbase_jd_atom_id(katom->kctx, dep_atom));
- dep_atom->in_jd_list = true;
- list_add_tail(&dep_atom->jd_item, out_list);
- }
-@@ -481,7 +482,8 @@ static inline void jd_resolve_dep(struct list_head *out_list,
- static bool is_dep_valid(struct kbase_jd_atom *katom)
- {
- /* If there's no dependency then this is 'valid' from the perspective of
-- * early dependency submission */
-+ * early dependency submission
-+ */
- if (!katom)
- return true;
-
-@@ -490,7 +492,8 @@ static bool is_dep_valid(struct kbase_jd_atom *katom)
- return false;
-
- /* If dependency has completed and has failed or will fail then it is
-- * not valid */
-+ * not valid
-+ */
- if (katom->status >= KBASE_JD_ATOM_STATE_HW_COMPLETED &&
- (katom->event_code != BASE_JD_EVENT_DONE ||
- katom->will_fail_event_code))
-@@ -544,10 +547,6 @@ static void jd_try_submitting_deps(struct list_head *out_list,
- #endif /* CONFIG_MALI_DMA_FENCE */
-
- if (dep0_valid && dep1_valid && dep_satisfied) {
-- trace_sysgraph(SGR_DEP_RES,
-- dep_atom->kctx->id,
-- kbase_jd_atom_id(dep_atom->kctx,
-- dep_atom));
- dep_atom->in_jd_list = true;
- list_add(&dep_atom->jd_item, out_list);
- }
-@@ -556,7 +555,7 @@ static void jd_try_submitting_deps(struct list_head *out_list,
- }
- }
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /**
- * jd_update_jit_usage - Update just-in-time physical memory usage for an atom.
- *
-@@ -632,8 +631,8 @@ static void jd_update_jit_usage(struct kbase_jd_atom *katom)
- u64 addr_end;
-
- if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) {
-- const unsigned long extent_bytes = reg->extent
-- << PAGE_SHIFT;
-+ const unsigned long extension_bytes =
-+ reg->extension << PAGE_SHIFT;
- const u64 low_ptr = ptr[LOW];
- const u64 high_ptr = ptr[HIGH];
-
-@@ -654,8 +653,8 @@ static void jd_update_jit_usage(struct kbase_jd_atom *katom)
- * this, but here to avoid future maintenance
- * hazards
- */
-- WARN_ON(!is_power_of_2(extent_bytes));
-- addr_end = ALIGN(read_val, extent_bytes);
-+ WARN_ON(!is_power_of_2(extension_bytes));
-+ addr_end = ALIGN(read_val, extension_bytes);
- } else {
- addr_end = read_val = READ_ONCE(*ptr);
- }
-@@ -696,7 +695,7 @@ static void jd_update_jit_usage(struct kbase_jd_atom *katom)
-
- kbase_jit_retry_pending_alloc(kctx);
- }
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- /*
- * Perform the necessary handling of an atom that has finished running
-@@ -721,12 +720,14 @@ bool jd_done_nolock(struct kbase_jd_atom *katom,
-
- KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED);
-
--#if MALI_JIT_PRESSURE_LIMIT
-- jd_update_jit_usage(katom);
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (kbase_ctx_flag(kctx, KCTX_JPL_ENABLED))
-+ jd_update_jit_usage(katom);
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- /* 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 */
-+ * can happen *before* the jobs that the atom depends on have completed
-+ */
- for (i = 0; i < 2; i++) {
- if (kbase_jd_katom_dep_atom(&katom->dep[i])) {
- list_del(&katom->dep_item[i]);
-@@ -734,9 +735,7 @@ bool jd_done_nolock(struct kbase_jd_atom *katom,
- }
- }
-
-- katom->status = KBASE_JD_ATOM_STATE_COMPLETED;
-- dev_dbg(kctx->kbdev->dev, "Atom %p status to completed\n",
-- (void *)katom);
-+ jd_mark_atom_complete(katom);
- list_add_tail(&katom->jd_item, &completed_jobs);
-
- while (!list_empty(&completed_jobs)) {
-@@ -759,7 +758,7 @@ bool jd_done_nolock(struct kbase_jd_atom *katom,
- list_del(runnable_jobs.next);
- node->in_jd_list = false;
-
-- dev_dbg(kctx->kbdev->dev, "List node %p has status %d\n",
-+ dev_dbg(kctx->kbdev->dev, "List node %pK has status %d\n",
- node, node->status);
-
- KBASE_DEBUG_ASSERT(node->status != KBASE_JD_ATOM_STATE_UNUSED);
-@@ -786,7 +785,8 @@ bool jd_done_nolock(struct kbase_jd_atom *katom,
- !node->will_fail_event_code) {
- /* Node successfully submitted, try submitting
- * dependencies as they may now be representable
-- * in JS */
-+ * in JS
-+ */
- jd_try_submitting_deps(&runnable_jobs, node);
- }
- }
-@@ -802,10 +802,14 @@ bool jd_done_nolock(struct kbase_jd_atom *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. */
-+ * '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) */
-+ /* 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)
-+ */
-+ wake_up(&kctx->jctx.zero_jobs_wait);
- }
-
- return need_to_try_schedule_context;
-@@ -813,7 +817,7 @@ bool jd_done_nolock(struct kbase_jd_atom *katom,
-
- KBASE_EXPORT_TEST_API(jd_done_nolock);
-
--#ifdef CONFIG_GPU_TRACEPOINTS
-+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
- enum {
- CORE_REQ_DEP_ONLY,
- CORE_REQ_SOFT,
-@@ -868,8 +872,23 @@ static const char *kbasep_map_core_reqs_to_string(base_jd_core_req core_req)
- }
- #endif
-
-+/* Trace an atom submission. */
-+static void jd_trace_atom_submit(struct kbase_context *const kctx,
-+ struct kbase_jd_atom *const katom,
-+ int *priority)
-+{
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+
-+ KBASE_TLSTREAM_TL_NEW_ATOM(kbdev, katom, kbase_jd_atom_id(kctx, katom));
-+ KBASE_TLSTREAM_TL_RET_ATOM_CTX(kbdev, katom, kctx);
-+ if (priority)
-+ KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITY(kbdev, katom, *priority);
-+ KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(kbdev, katom, TL_ATOM_STATE_IDLE);
-+ kbase_kinstr_jm_atom_queue(katom);
-+}
-+
- static bool jd_submit_atom(struct kbase_context *const kctx,
-- const struct base_jd_atom_v2 *const user_atom,
-+ const struct base_jd_atom *const user_atom,
- const struct base_jd_fragment *const user_jc_incr,
- struct kbase_jd_atom *const katom)
- {
-@@ -879,14 +898,17 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- int i;
- int sched_prio;
- bool will_fail = false;
-+ unsigned long flags;
-+ enum kbase_jd_atom_state status;
-
-- dev_dbg(kbdev->dev, "User did JD submit atom %p\n", (void *)katom);
-+ dev_dbg(kbdev->dev, "User did JD submit atom %pK\n", (void *)katom);
-
- /* Update the TOTAL number of jobs. This includes those not tracked by
-- * the scheduler: 'not ready to run' and 'dependency-only' jobs. */
-+ * the scheduler: 'not ready to run' and 'dependency-only' jobs.
-+ */
- jctx->job_nr++;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
-+#if KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE
- katom->start_timestamp.tv64 = 0;
- #else
- katom->start_timestamp = 0;
-@@ -899,6 +921,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- katom->jc = user_atom->jc;
- katom->core_req = user_atom->core_req;
- katom->jobslot = user_atom->jobslot;
-+ katom->seq_nr = user_atom->seq_nr;
- katom->atom_flags = 0;
- katom->retry_count = 0;
- katom->need_cache_flush_cores_retained = 0;
-@@ -911,19 +934,19 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
-
- trace_sysgraph(SGR_ARRIVE, kctx->id, user_atom->atom_number);
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /* Older API version atoms might have random values where jit_id now
- * lives, but we must maintain backwards compatibility - handle the
- * issue.
- */
-- if (kctx->api_version < MIN_API_VERSION_WITH_JPL) {
-+ if (!mali_kbase_supports_jit_pressure_limit(kctx->api_version)) {
- katom->jit_ids[0] = 0;
- katom->jit_ids[1] = 0;
- } else {
- katom->jit_ids[0] = user_atom->jit_id[0];
- katom->jit_ids[1] = user_atom->jit_id[1];
- }
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- katom->renderpass_id = user_atom->renderpass_id;
-
-@@ -953,23 +976,14 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- katom->event_code = BASE_JD_EVENT_JOB_CONFIG_FAULT;
- katom->status = KBASE_JD_ATOM_STATE_COMPLETED;
- dev_dbg(kbdev->dev,
-- "Atom %p status to completed\n",
-+ "Atom %pK status to completed\n",
- (void *)katom);
-
- /* Wrong dependency setup. Atom will be sent
- * back to user space. Do not record any
-- * dependencies. */
-- KBASE_TLSTREAM_TL_NEW_ATOM(
-- kbdev,
-- katom,
-- kbase_jd_atom_id(kctx, katom));
-- KBASE_TLSTREAM_TL_RET_ATOM_CTX(
-- kbdev,
-- katom, kctx);
-- KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(
-- kbdev,
-- katom,
-- TL_ATOM_STATE_IDLE);
-+ * dependencies.
-+ */
-+ jd_trace_atom_submit(kctx, katom, NULL);
-
- return jd_done_nolock(katom, NULL);
- }
-@@ -1005,19 +1019,13 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- /* Atom has completed, propagate the error code if any */
- katom->event_code = dep_atom->event_code;
- katom->status = KBASE_JD_ATOM_STATE_QUEUED;
-- dev_dbg(kbdev->dev, "Atom %p status to queued\n",
-+ dev_dbg(kbdev->dev, "Atom %pK status to queued\n",
- (void *)katom);
-
- /* This atom will be sent back to user space.
- * Do not record any dependencies.
- */
-- KBASE_TLSTREAM_TL_NEW_ATOM(
-- kbdev,
-- katom,
-- kbase_jd_atom_id(kctx, katom));
-- KBASE_TLSTREAM_TL_RET_ATOM_CTX(kbdev, katom, kctx);
-- KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(kbdev, katom,
-- TL_ATOM_STATE_IDLE);
-+ jd_trace_atom_submit(kctx, katom, NULL);
-
- will_fail = true;
-
-@@ -1045,20 +1053,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- return jd_done_nolock(katom, NULL);
- }
-
-- if (katom->core_req & BASE_JD_REQ_SOFT_JOB) {
-- /* This softjob has failed due to a previous
-- * dependency, however we should still run the
-- * prepare & finish functions
-- */
-- if (kbase_prepare_soft_job(katom) != 0) {
-- katom->event_code =
-- BASE_JD_EVENT_JOB_INVALID;
-- return jd_done_nolock(katom, NULL);
-- }
-- }
--
- katom->will_fail_event_code = katom->event_code;
-- return false;
- }
-
- /* These must occur after the above loop to ensure that an atom
-@@ -1067,22 +1062,19 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- */
- katom->event_code = BASE_JD_EVENT_DONE;
- katom->status = KBASE_JD_ATOM_STATE_QUEUED;
-- dev_dbg(kbdev->dev, "Atom %p status to queued\n", (void *)katom);
-+ dev_dbg(kbdev->dev, "Atom %pK status to queued\n", (void *)katom);
-
- /* For invalid priority, be most lenient and choose the default */
- sched_prio = kbasep_js_atom_prio_to_sched_prio(user_atom->prio);
- if (sched_prio == KBASE_JS_ATOM_SCHED_PRIO_INVALID)
- sched_prio = KBASE_JS_ATOM_SCHED_PRIO_DEFAULT;
-- katom->sched_priority = sched_prio;
-+
-+ /* Cap the priority to jctx.max_priority */
-+ katom->sched_priority = (sched_prio < kctx->jctx.max_priority) ?
-+ kctx->jctx.max_priority : sched_prio;
-
- /* Create a new atom. */
-- KBASE_TLSTREAM_TL_NEW_ATOM(
-- kbdev,
-- katom,
-- kbase_jd_atom_id(kctx, katom));
-- KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(kbdev, katom, TL_ATOM_STATE_IDLE);
-- KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITY(kbdev, katom, katom->sched_priority);
-- KBASE_TLSTREAM_TL_RET_ATOM_CTX(kbdev, katom, kctx);
-+ jd_trace_atom_submit(kctx, katom, &katom->sched_priority);
-
- #if !MALI_INCREMENTAL_RENDERING
- /* Reject atoms for incremental rendering if not supported */
-@@ -1149,8 +1141,8 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- }
- }
-
--#if !MALI_JIT_PRESSURE_LIMIT
-- if ((kctx->api_version >= MIN_API_VERSION_WITH_JPL) &&
-+#if !MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (mali_kbase_supports_jit_pressure_limit(kctx->api_version) &&
- (user_atom->jit_id[0] || user_atom->jit_id[1])) {
- /* JIT pressure limit is disabled, but we are receiving non-0
- * JIT IDs - atom is invalid.
-@@ -1158,7 +1150,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- katom->event_code = BASE_JD_EVENT_JOB_INVALID;
- return jd_done_nolock(katom, NULL);
- }
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- /* Validate the atom. Function will return error if the atom is
- * malformed.
-@@ -1180,7 +1172,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- }
- }
-
--#ifdef CONFIG_GPU_TRACEPOINTS
-+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
- katom->work_id = atomic_inc_return(&jctx->work_id);
- trace_gpu_job_enqueue(kctx->id, katom->work_id,
- kbasep_map_core_reqs_to_string(katom->core_req));
-@@ -1207,13 +1199,24 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
- bool need_to_try_schedule_context;
-
- katom->status = KBASE_JD_ATOM_STATE_IN_JS;
-- dev_dbg(kctx->kbdev->dev, "Atom %p status to in JS\n",
-+ dev_dbg(kctx->kbdev->dev, "Atom %pK status to in JS\n",
- (void *)katom);
-
- need_to_try_schedule_context = kbasep_js_add_job(kctx, katom);
- /* If job was cancelled then resolve immediately */
- if (katom->event_code != BASE_JD_EVENT_JOB_CANCELLED)
- return need_to_try_schedule_context;
-+
-+ /* Synchronize with backend reset */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ status = katom->status;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ if (status == KBASE_JD_ATOM_STATE_HW_COMPLETED) {
-+ dev_dbg(kctx->kbdev->dev,
-+ "Atom %d cancelled on HW\n",
-+ kbase_jd_atom_id(katom->kctx, katom));
-+ return need_to_try_schedule_context;
-+ }
- }
-
- /* This is a pure dependency. Resolve it immediately */
-@@ -1231,6 +1234,9 @@ int kbase_jd_submit(struct kbase_context *kctx,
- struct kbase_device *kbdev;
- u32 latest_flush;
-
-+ bool jd_atom_is_v2 = (stride == sizeof(struct base_jd_atom_v2) ||
-+ stride == offsetof(struct base_jd_atom_v2, renderpass_id));
-+
- /*
- * kbase_jd_submit isn't expected to fail and so all errors with the
- * jobs are reported by immediately failing them (through event system)
-@@ -1245,7 +1251,9 @@ int kbase_jd_submit(struct kbase_context *kctx,
- }
-
- if (stride != offsetof(struct base_jd_atom_v2, renderpass_id) &&
-- stride != sizeof(struct base_jd_atom_v2)) {
-+ stride != sizeof(struct base_jd_atom_v2) &&
-+ stride != offsetof(struct base_jd_atom, renderpass_id) &&
-+ stride != sizeof(struct base_jd_atom)) {
- dev_err(kbdev->dev,
- "Stride %u passed to job_submit isn't supported by the kernel\n",
- stride);
-@@ -1256,16 +1264,29 @@ int kbase_jd_submit(struct kbase_context *kctx,
- latest_flush = kbase_backend_get_current_flush_id(kbdev);
-
- for (i = 0; i < nr_atoms; i++) {
-- struct base_jd_atom_v2 user_atom;
-+ struct base_jd_atom user_atom;
- struct base_jd_fragment user_jc_incr;
- struct kbase_jd_atom *katom;
-
-- if (copy_from_user(&user_atom, user_addr, stride) != 0) {
-- dev_err(kbdev->dev,
-- "Invalid atom address %p passed to job_submit\n",
-- user_addr);
-- err = -EFAULT;
-- break;
-+ if (unlikely(jd_atom_is_v2)) {
-+ if (copy_from_user(&user_atom.jc, user_addr, sizeof(struct base_jd_atom_v2)) != 0) {
-+ dev_dbg(kbdev->dev,
-+ "Invalid atom address %p passed to job_submit\n",
-+ user_addr);
-+ err = -EFAULT;
-+ break;
-+ }
-+
-+ /* no seq_nr in v2 */
-+ user_atom.seq_nr = 0;
-+ } else {
-+ if (copy_from_user(&user_atom, user_addr, stride) != 0) {
-+ dev_dbg(kbdev->dev,
-+ "Invalid atom address %p passed to job_submit\n",
-+ user_addr);
-+ err = -EFAULT;
-+ break;
-+ }
- }
-
- if (stride == offsetof(struct base_jd_atom_v2, renderpass_id)) {
-@@ -1399,7 +1420,7 @@ void kbase_jd_done_worker(struct work_struct *data)
- js_kctx_info = &kctx->jctx.sched_info;
- js_devdata = &kbdev->js_data;
-
-- dev_dbg(kbdev->dev, "Enter atom %p done worker for kctx %p\n",
-+ dev_dbg(kbdev->dev, "Enter atom %pK done worker for kctx %pK\n",
- (void *)katom, (void *)kctx);
-
- KBASE_KTRACE_ADD_JM(kbdev, JD_DONE_WORKER, kctx, katom, katom->jc, 0);
-@@ -1423,7 +1444,7 @@ void kbase_jd_done_worker(struct work_struct *data)
- if (katom->event_code == BASE_JD_EVENT_STOPPED) {
- unsigned long flags;
-
-- dev_dbg(kbdev->dev, "Atom %p has been promoted to stopped\n",
-+ dev_dbg(kbdev->dev, "Atom %pK has been promoted to stopped\n",
- (void *)katom);
- mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
- mutex_unlock(&js_devdata->queue_mutex);
-@@ -1431,7 +1452,7 @@ void kbase_jd_done_worker(struct work_struct *data)
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-
- katom->status = KBASE_JD_ATOM_STATE_IN_JS;
-- dev_dbg(kctx->kbdev->dev, "Atom %p status to in JS\n",
-+ dev_dbg(kctx->kbdev->dev, "Atom %pK status to in JS\n",
- (void *)katom);
- kbase_js_unpull(kctx, katom);
-
-@@ -1518,7 +1539,9 @@ void kbase_jd_done_worker(struct work_struct *data)
- 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 */
-+ * 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);
-
-@@ -1526,7 +1549,8 @@ void kbase_jd_done_worker(struct work_struct *data)
-
- if (!atomic_dec_return(&kctx->work_count)) {
- /* If worker now idle then post all events that jd_done_nolock()
-- * has queued */
-+ * has queued
-+ */
- mutex_lock(&jctx->lock);
- while (!list_empty(&kctx->completed_jobs)) {
- struct kbase_jd_atom *atom = list_entry(
-@@ -1546,7 +1570,7 @@ void kbase_jd_done_worker(struct work_struct *data)
-
- KBASE_KTRACE_ADD_JM(kbdev, JD_DONE_WORKER_END, kctx, NULL, cache_jc, 0);
-
-- dev_dbg(kbdev->dev, "Leave atom %p done worker for kctx %p\n",
-+ dev_dbg(kbdev->dev, "Leave atom %pK done worker for kctx %pK\n",
- (void *)katom, (void *)kctx);
- }
-
-@@ -1601,7 +1625,8 @@ static void jd_cancel_worker(struct work_struct *data)
- need_to_try_schedule_context = jd_done_nolock(katom, NULL);
- /* 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. */
-+ * around this too.
-+ */
- KBASE_DEBUG_ASSERT(!need_to_try_schedule_context);
-
- /* katom may have been freed now, do not use! */
-@@ -1652,7 +1677,7 @@ void kbase_jd_done(struct kbase_jd_atom *katom, int slot_nr,
-
- atomic_inc(&kctx->work_count);
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- /* a failed job happened and is waiting for dumping*/
- if (!katom->will_fail_event_code &&
- kbase_debug_job_fault_process(katom, katom->event_code))
-@@ -1670,12 +1695,12 @@ void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom)
- {
- struct kbase_context *kctx;
-
-- KBASE_DEBUG_ASSERT(NULL != kbdev);
-- KBASE_DEBUG_ASSERT(NULL != katom);
-+ KBASE_DEBUG_ASSERT(kbdev != NULL);
-+ KBASE_DEBUG_ASSERT(katom != NULL);
- kctx = katom->kctx;
-- KBASE_DEBUG_ASSERT(NULL != kctx);
-+ KBASE_DEBUG_ASSERT(kctx != NULL);
-
-- dev_dbg(kbdev->dev, "JD: cancelling atom %p\n", (void *)katom);
-+ dev_dbg(kbdev->dev, "JD: cancelling atom %pK\n", (void *)katom);
- KBASE_KTRACE_ADD_JM(kbdev, JD_CANCEL, kctx, katom, katom->jc, 0);
-
- /* This should only be done from a context that is not scheduled */
-@@ -1731,7 +1756,7 @@ void kbase_jd_zap_context(struct kbase_context *kctx)
- flush_workqueue(kctx->dma_fence.wq);
- #endif
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- kbase_debug_job_fault_kctx_unblock(kctx);
- #endif
-
-@@ -1744,12 +1769,15 @@ int kbase_jd_init(struct kbase_context *kctx)
- {
- int i;
- int mali_err = 0;
-+ struct priority_control_manager_device *pcm_device = NULL;
-
- KBASE_DEBUG_ASSERT(kctx);
-+ pcm_device = kctx->kbdev->pcm_dev;
-+ kctx->jctx.max_priority = KBASE_JS_ATOM_SCHED_PRIO_REALTIME;
-
- kctx->jctx.job_done_wq = alloc_workqueue("mali_jd",
- WQ_HIGHPRI | WQ_UNBOUND, 1);
-- if (NULL == kctx->jctx.job_done_wq) {
-+ if (kctx->jctx.job_done_wq == NULL) {
- mali_err = -ENOMEM;
- goto out1;
- }
-@@ -1785,6 +1813,11 @@ int kbase_jd_init(struct kbase_context *kctx)
- INIT_LIST_HEAD(&kctx->completed_jobs);
- atomic_set(&kctx->work_count, 0);
-
-+ /* Check if there are platform rules for maximum priority */
-+ if (pcm_device)
-+ kctx->jctx.max_priority = pcm_device->ops.pcm_scheduler_priority_check(
-+ pcm_device, current, KBASE_JS_ATOM_SCHED_PRIO_REALTIME);
-+
- return 0;
-
- out1:
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c
-index e9a161f..67d1bd9 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,9 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-
- #include <linux/seq_file.h>
- #include <mali_kbase.h>
-@@ -29,7 +28,7 @@
- #if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE)
- #include <mali_kbase_sync.h>
- #endif
--#include <mali_kbase_ioctl.h>
-+#include <uapi/gpu/arm/midgard/mali_kbase_ioctl.h>
-
- struct kbase_jd_debugfs_depinfo {
- u8 id;
-@@ -47,13 +46,13 @@ static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom,
- case BASE_JD_REQ_SOFT_FENCE_TRIGGER:
- res = kbase_sync_fence_out_info_get(atom, &info);
- if (res == 0)
-- seq_printf(sfile, "Sa([%p]%d) ",
-+ seq_printf(sfile, "Sa([%pK]%d) ",
- info.fence, info.status);
- break;
- case BASE_JD_REQ_SOFT_FENCE_WAIT:
- res = kbase_sync_fence_in_info_get(atom, &info);
- if (res == 0)
-- seq_printf(sfile, "Wa([%p]%d) ",
-+ seq_printf(sfile, "Wa([%pK]%d) ",
- info.fence, info.status);
- break;
- default:
-@@ -66,42 +65,40 @@ static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom,
- struct kbase_fence_cb *cb;
-
- if (atom->dma_fence.fence) {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence = atom->dma_fence.fence;
- #else
- struct dma_fence *fence = atom->dma_fence.fence;
- #endif
-
- seq_printf(sfile,
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
-- "Sd(%u#%u: %s) ",
-+#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE)
-+ "Sd(%u#%u: %s) ",
- #else
-- "Sd(%llu#%u: %s) ",
-+ "Sd(%llu#%u: %s) ",
- #endif
-- fence->context,
-- fence->seqno,
-- dma_fence_is_signaled(fence) ?
-- "signaled" : "active");
-+ fence->context, fence->seqno,
-+ dma_fence_is_signaled(fence) ? "signaled" :
-+ "active");
- }
-
- list_for_each_entry(cb, &atom->dma_fence.callbacks,
- node) {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence = cb->fence;
- #else
- struct dma_fence *fence = cb->fence;
- #endif
-
- seq_printf(sfile,
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
-- "Wd(%u#%u: %s) ",
-+#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE)
-+ "Wd(%u#%u: %s) ",
- #else
-- "Wd(%llu#%u: %s) ",
-+ "Wd(%llu#%u: %s) ",
- #endif
-- fence->context,
-- fence->seqno,
-- dma_fence_is_signaled(fence) ?
-- "signaled" : "active");
-+ fence->context, fence->seqno,
-+ dma_fence_is_signaled(fence) ? "signaled" :
-+ "active");
- }
- }
- #endif /* CONFIG_MALI_DMA_FENCE */
-@@ -180,7 +177,8 @@ static int kbasep_jd_debugfs_atoms_show(struct seq_file *sfile, void *data)
-
- /* start_timestamp is cleared as soon as the atom leaves UNUSED state
- * and set before a job is submitted to the h/w, a non-zero value means
-- * it is valid */
-+ * it is valid
-+ */
- if (ktime_to_ns(atom->start_timestamp))
- start_timestamp = ktime_to_ns(
- ktime_sub(ktime_get(), atom->start_timestamp));
-@@ -228,6 +226,12 @@ static const struct file_operations kbasep_jd_debugfs_atoms_fops = {
-
- void kbasep_jd_debugfs_ctx_init(struct kbase_context *kctx)
- {
-+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
-+ const mode_t mode = S_IRUGO;
-+#else
-+ const mode_t mode = S_IRUSR;
-+#endif
-+
- /* Caller already ensures this, but we keep the pattern for
- * maintenance safety.
- */
-@@ -236,7 +240,7 @@ void kbasep_jd_debugfs_ctx_init(struct kbase_context *kctx)
- return;
-
- /* Expose all atoms */
-- debugfs_create_file("atoms", S_IRUGO, kctx->kctx_dentry, kctx,
-+ debugfs_create_file("atoms", mode, kctx->kctx_dentry, kctx,
- &kbasep_jd_debugfs_atoms_fops);
-
- }
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h
-index 697bdef..8e6140c 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jd_debugfs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,13 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-- * @file mali_kbase_jd_debugfs.h
-- * Header file for job dispatcher-related entries in debugfs
-+ * DOC: Header file for job dispatcher-related entries in debugfs
- */
-
- #ifndef _KBASE_JD_DEBUGFS_H
-@@ -38,7 +36,7 @@ struct kbase_context;
- /**
- * kbasep_jd_debugfs_ctx_init() - Add debugfs entries for JD system
- *
-- * @kctx Pointer to kbase_context
-+ * @kctx: Pointer to kbase_context
- */
- void kbasep_jd_debugfs_ctx_init(struct kbase_context *kctx);
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jm.c
-index 3f17dd7..6995050 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jm.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * HW access job manager common APIs
- */
-@@ -29,6 +27,7 @@
- #include "mali_kbase_hwaccess_jm.h"
- #include "mali_kbase_jm.h"
-
-+#if !MALI_USE_CSF
- /**
- * kbase_jm_next_job() - Attempt to run the next @nr_jobs_to_submit jobs on slot
- * @js on the active context.
-@@ -46,7 +45,7 @@ static bool kbase_jm_next_job(struct kbase_device *kbdev, int js,
-
- kctx = kbdev->hwaccess.active_kctx[js];
- dev_dbg(kbdev->dev,
-- "Trying to run the next %d jobs in kctx %p (s:%d)\n",
-+ "Trying to run the next %d jobs in kctx %pK (s:%d)\n",
- nr_jobs_to_submit, (void *)kctx, js);
-
- if (!kctx)
-@@ -118,7 +117,7 @@ void kbase_jm_idle_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)
-
- for (js = 0; js < BASE_JM_MAX_NR_SLOTS; js++) {
- if (kbdev->hwaccess.active_kctx[js] == kctx) {
-- dev_dbg(kbdev->dev, "Marking kctx %p as inactive (s:%d)\n",
-+ dev_dbg(kbdev->dev, "Marking kctx %pK as inactive (s:%d)\n",
- (void *)kctx, js);
- kbdev->hwaccess.active_kctx[js] = NULL;
- }
-@@ -130,7 +129,7 @@ struct kbase_jd_atom *kbase_jm_return_atom_to_js(struct kbase_device *kbdev,
- {
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
-- dev_dbg(kbdev->dev, "Atom %p is returning with event code 0x%x\n",
-+ dev_dbg(kbdev->dev, "Atom %pK is returning with event code 0x%x\n",
- (void *)katom, katom->event_code);
-
- if (katom->event_code != BASE_JD_EVENT_STOPPED &&
-@@ -149,3 +148,4 @@ struct kbase_jd_atom *kbase_jm_complete(struct kbase_device *kbdev,
-
- return kbase_js_complete_atom(katom, end_timestamp);
- }
-+#endif /* !MALI_USE_CSF */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jm.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jm.h
-index a3c7744..c6b28f3 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_jm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2016, 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2013-2014, 2016, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- /*
- * Job manager common APIs
- */
-@@ -28,6 +26,7 @@
- #ifndef _KBASE_JM_H_
- #define _KBASE_JM_H_
-
-+#if !MALI_USE_CSF
- /**
- * kbase_jm_kick() - Indicate that there are jobs ready to run.
- * @kbdev: Device pointer
-@@ -73,7 +72,9 @@ void kbase_jm_try_kick(struct kbase_device *kbdev, u32 js_mask);
- * kbase_jm_kick_all() otherwise it will do nothing.
- */
- void kbase_jm_try_kick_all(struct kbase_device *kbdev);
-+#endif /* !MALI_USE_CSF */
-
-+#if !MALI_USE_CSF
- /**
- * kbase_jm_idle_ctx() - Mark a context as idle.
- * @kbdev: Device pointer
-@@ -111,5 +112,6 @@ struct kbase_jd_atom *kbase_jm_return_atom_to_js(struct kbase_device *kbdev,
- */
- struct kbase_jd_atom *kbase_jm_complete(struct kbase_device *kbdev,
- struct kbase_jd_atom *katom, ktime_t *end_timestamp);
-+#endif /* !MALI_USE_CSF */
-
- #endif /* _KBASE_JM_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js.c
-index 0b0c5bf..3682486 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Job Scheduler Implementation
- */
-@@ -37,6 +34,7 @@
-
- #include "mali_kbase_jm.h"
- #include "mali_kbase_hwaccess_jm.h"
-+#include <linux/priority_control_manager.h>
-
- /*
- * Private types
-@@ -45,26 +43,30 @@
- /* 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 */
-+ * one to keep the runpool full
-+ */
- KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED = (1u << 0),
- /* Ctx attributes were changed - caller should try scheduling all
-- * contexts */
-+ * contexts
-+ */
- KBASEP_JS_RELEASE_RESULT_SCHED_ALL = (1u << 1)
- };
-
- typedef u32 kbasep_js_release_result;
-
- const int kbasep_js_atom_priority_to_relative[BASE_JD_NR_PRIO_LEVELS] = {
-- KBASE_JS_ATOM_SCHED_PRIO_MED, /* BASE_JD_PRIO_MEDIUM */
-- KBASE_JS_ATOM_SCHED_PRIO_HIGH, /* BASE_JD_PRIO_HIGH */
-- KBASE_JS_ATOM_SCHED_PRIO_LOW /* BASE_JD_PRIO_LOW */
-+ KBASE_JS_ATOM_SCHED_PRIO_MED, /* BASE_JD_PRIO_MEDIUM */
-+ KBASE_JS_ATOM_SCHED_PRIO_HIGH, /* BASE_JD_PRIO_HIGH */
-+ KBASE_JS_ATOM_SCHED_PRIO_LOW, /* BASE_JD_PRIO_LOW */
-+ KBASE_JS_ATOM_SCHED_PRIO_REALTIME /* BASE_JD_PRIO_REALTIME */
- };
-
- const base_jd_prio
- kbasep_js_relative_priority_to_atom[KBASE_JS_ATOM_SCHED_PRIO_COUNT] = {
-- BASE_JD_PRIO_HIGH, /* KBASE_JS_ATOM_SCHED_PRIO_HIGH */
-- BASE_JD_PRIO_MEDIUM, /* KBASE_JS_ATOM_SCHED_PRIO_MED */
-- BASE_JD_PRIO_LOW /* KBASE_JS_ATOM_SCHED_PRIO_LOW */
-+ BASE_JD_PRIO_REALTIME, /* KBASE_JS_ATOM_SCHED_PRIO_REALTIME */
-+ BASE_JD_PRIO_HIGH, /* KBASE_JS_ATOM_SCHED_PRIO_HIGH */
-+ BASE_JD_PRIO_MEDIUM, /* KBASE_JS_ATOM_SCHED_PRIO_MED */
-+ BASE_JD_PRIO_LOW /* KBASE_JS_ATOM_SCHED_PRIO_LOW */
- };
-
-
-@@ -79,7 +81,7 @@ static int kbase_js_get_slot(struct kbase_device *kbdev,
- struct kbase_jd_atom *katom);
-
- static void kbase_js_foreach_ctx_job(struct kbase_context *kctx,
-- kbasep_js_ctx_job_cb callback);
-+ kbasep_js_ctx_job_cb *callback);
-
- /* Helper for ktrace */
- #if KBASE_KTRACE_ENABLE
-@@ -160,7 +162,7 @@ jsctx_rb_none_to_pull_prio(struct kbase_context *kctx, int js, int prio)
- none_to_pull = RB_EMPTY_ROOT(&rb->runnable_tree);
-
- dev_dbg(kctx->kbdev->dev,
-- "Slot %d (prio %d) is %spullable in kctx %p\n",
-+ "Slot %d (prio %d) is %spullable in kctx %pK\n",
- js, prio, none_to_pull ? "not " : "", kctx);
-
- return none_to_pull;
-@@ -184,7 +186,7 @@ jsctx_rb_none_to_pull(struct kbase_context *kctx, int js)
-
- lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
-
-- for (prio = KBASE_JS_ATOM_SCHED_PRIO_HIGH;
-+ for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST;
- prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
- if (!jsctx_rb_none_to_pull_prio(kctx, js, prio))
- return false;
-@@ -210,9 +212,8 @@ jsctx_rb_none_to_pull(struct kbase_context *kctx, int js)
- *
- * The HW access lock must always be held when calling this function.
- */
--static void
--jsctx_queue_foreach_prio(struct kbase_context *kctx, int js, int prio,
-- kbasep_js_ctx_job_cb callback)
-+static void jsctx_queue_foreach_prio(struct kbase_context *kctx, int js,
-+ int prio, kbasep_js_ctx_job_cb *callback)
- {
- struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js];
-
-@@ -234,7 +235,7 @@ jsctx_queue_foreach_prio(struct kbase_context *kctx, int js, int prio,
- WARN_ON(!(entry->core_req &
- BASE_JD_REQ_END_RENDERPASS));
- dev_dbg(kctx->kbdev->dev,
-- "Del runnable atom %p from X_DEP list\n",
-+ "Del runnable atom %pK from X_DEP list\n",
- (void *)entry);
-
- list_del(&entry->queue);
-@@ -250,7 +251,7 @@ jsctx_queue_foreach_prio(struct kbase_context *kctx, int js, int prio,
- WARN_ON(!(entry->atom_flags &
- KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST));
- dev_dbg(kctx->kbdev->dev,
-- "Del blocked atom %p from X_DEP list\n",
-+ "Del blocked atom %pK from X_DEP list\n",
- (void *)entry);
-
- list_del(queue->x_dep_head.next);
-@@ -271,13 +272,12 @@ jsctx_queue_foreach_prio(struct kbase_context *kctx, int js, int prio,
- * jsctx_queue_foreach_prio() to iterate over the queue and invoke @callback
- * for each entry, and remove the entry from the queue.
- */
--static inline void
--jsctx_queue_foreach(struct kbase_context *kctx, int js,
-- kbasep_js_ctx_job_cb callback)
-+static inline void jsctx_queue_foreach(struct kbase_context *kctx, int js,
-+ kbasep_js_ctx_job_cb *callback)
- {
- int prio;
-
-- for (prio = KBASE_JS_ATOM_SCHED_PRIO_HIGH;
-+ for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST;
- prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++)
- jsctx_queue_foreach_prio(kctx, js, prio, callback);
- }
-@@ -301,7 +301,7 @@ jsctx_rb_peek_prio(struct kbase_context *kctx, int js, int prio)
-
- lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
- dev_dbg(kctx->kbdev->dev,
-- "Peeking runnable tree of kctx %p for prio %d (s:%d)\n",
-+ "Peeking runnable tree of kctx %pK for prio %d (s:%d)\n",
- (void *)kctx, prio, js);
-
- node = rb_first(&rb->runnable_tree);
-@@ -319,7 +319,7 @@ jsctx_rb_peek_prio(struct kbase_context *kctx, int js, int prio)
- * @js: Job slot id to check.
- *
- * Check the ring buffers for all priorities, starting from
-- * KBASE_JS_ATOM_SCHED_PRIO_HIGH, for the specified @js and @prio and return a
-+ * KBASE_JS_ATOM_SCHED_PRIO_REALTIME, for the specified @js and @prio and return a
- * pointer to the next atom, unless all the priority's ring buffers are empty.
- *
- * Caller must hold the hwaccess_lock.
-@@ -333,7 +333,7 @@ jsctx_rb_peek(struct kbase_context *kctx, int js)
-
- lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
-
-- for (prio = KBASE_JS_ATOM_SCHED_PRIO_HIGH;
-+ for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST;
- prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
- struct kbase_jd_atom *katom;
-
-@@ -363,7 +363,7 @@ jsctx_rb_pull(struct kbase_context *kctx, struct kbase_jd_atom *katom)
-
- lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
-
-- dev_dbg(kctx->kbdev->dev, "Erasing atom %p from runnable tree of kctx %p\n",
-+ dev_dbg(kctx->kbdev->dev, "Erasing atom %pK from runnable tree of kctx %pK\n",
- (void *)katom, (void *)kctx);
-
- /* Atoms must be pulled in the correct order. */
-@@ -385,7 +385,7 @@ jsctx_tree_add(struct kbase_context *kctx, struct kbase_jd_atom *katom)
-
- lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
-
-- dev_dbg(kbdev->dev, "Adding atom %p to runnable tree of kctx %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "Adding atom %pK to runnable tree of kctx %pK (s:%d)\n",
- (void *)katom, (void *)kctx, js);
-
- while (*new) {
-@@ -448,7 +448,8 @@ int kbasep_js_devdata_init(struct kbase_device * const kbdev)
-
- #ifdef CONFIG_MALI_DEBUG
- /* Soft-stop will be disabled on a single context by default unless
-- * softstop_always is set */
-+ * softstop_always is set
-+ */
- jsdd->softstop_always = false;
- #endif /* CONFIG_MALI_DEBUG */
- jsdd->nr_all_contexts_running = 0;
-@@ -531,14 +532,15 @@ int kbasep_js_devdata_init(struct kbase_device * const kbdev)
- kbdev->gpu_props.props.raw_props.js_features[i]);
-
- /* On error, we could continue on: providing none of the below resources
-- * rely on the ones above */
-+ * rely on the ones above
-+ */
-
- mutex_init(&jsdd->runpool_mutex);
- mutex_init(&jsdd->queue_mutex);
- sema_init(&jsdd->schedule_sem, 1);
-
- for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) {
-- for (j = 0; j < KBASE_JS_ATOM_SCHED_PRIO_COUNT; ++j) {
-+ for (j = KBASE_JS_ATOM_SCHED_PRIO_FIRST; j < KBASE_JS_ATOM_SCHED_PRIO_COUNT; ++j) {
- INIT_LIST_HEAD(&jsdd->ctx_list_pullable[i][j]);
- INIT_LIST_HEAD(&jsdd->ctx_list_unpullable[i][j]);
- }
-@@ -595,16 +597,18 @@ int kbasep_js_kctx_init(struct kbase_context *const kctx)
- sizeof(js_kctx_info->ctx.ctx_attr_ref_count));
-
- /* Initially, the context is disabled from submission until the create
-- * flags are set */
-+ * flags are set
-+ */
- kbase_ctx_flag_set(kctx, KCTX_SUBMIT_DISABLED);
-
- /* On error, we could continue on: providing none of the below resources
-- * rely on the ones above */
-+ * rely on the ones above
-+ */
- mutex_init(&js_kctx_info->ctx.jsctx_mutex);
-
- init_waitqueue_head(&js_kctx_info->ctx.is_scheduled_wait);
-
-- for (i = 0; i < KBASE_JS_ATOM_SCHED_PRIO_COUNT; i++) {
-+ for (i = KBASE_JS_ATOM_SCHED_PRIO_FIRST; i < KBASE_JS_ATOM_SCHED_PRIO_COUNT; i++) {
- for (j = 0; j < BASE_JM_MAX_NR_SLOTS; j++) {
- INIT_LIST_HEAD(&kctx->jsctx_queue[i][j].x_dep_head);
- kctx->jsctx_queue[i][j].runnable_tree = RB_ROOT;
-@@ -678,7 +682,7 @@ static bool kbase_js_ctx_list_add_pullable_nolock(struct kbase_device *kbdev,
- bool ret = false;
-
- lockdep_assert_held(&kbdev->hwaccess_lock);
-- dev_dbg(kbdev->dev, "Add pullable tail kctx %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "Add pullable tail kctx %pK (s:%d)\n",
- (void *)kctx, js);
-
- if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]))
-@@ -720,7 +724,7 @@ static bool kbase_js_ctx_list_add_pullable_head_nolock(
- bool ret = false;
-
- lockdep_assert_held(&kbdev->hwaccess_lock);
-- dev_dbg(kbdev->dev, "Add pullable head kctx %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "Add pullable head kctx %pK (s:%d)\n",
- (void *)kctx, js);
-
- if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]))
-@@ -796,7 +800,7 @@ static bool kbase_js_ctx_list_add_unpullable_nolock(struct kbase_device *kbdev,
- bool ret = false;
-
- lockdep_assert_held(&kbdev->hwaccess_lock);
-- dev_dbg(kbdev->dev, "Add unpullable tail kctx %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "Add unpullable tail kctx %pK (s:%d)\n",
- (void *)kctx, js);
-
- list_move_tail(&kctx->jctx.sched_info.ctx.ctx_list_entry[js],
-@@ -879,7 +883,7 @@ static struct kbase_context *kbase_js_ctx_list_pop_head_nolock(
-
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
-- for (i = 0; i < KBASE_JS_ATOM_SCHED_PRIO_COUNT; i++) {
-+ for (i = KBASE_JS_ATOM_SCHED_PRIO_FIRST; i < KBASE_JS_ATOM_SCHED_PRIO_COUNT; i++) {
- if (list_empty(&kbdev->js_data.ctx_list_pullable[js][i]))
- continue;
-
-@@ -889,7 +893,7 @@ static struct kbase_context *kbase_js_ctx_list_pop_head_nolock(
-
- list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]);
- dev_dbg(kbdev->dev,
-- "Popped %p from the pullable queue (s:%d)\n",
-+ "Popped %pK from the pullable queue (s:%d)\n",
- (void *)kctx, js);
- return kctx;
- }
-@@ -943,25 +947,25 @@ static bool kbase_js_ctx_pullable(struct kbase_context *kctx, int js,
-
- if (is_scheduled) {
- if (!kbasep_js_is_submit_allowed(js_devdata, kctx)) {
-- dev_dbg(kbdev->dev, "JS: No submit allowed for kctx %p\n",
-+ dev_dbg(kbdev->dev, "JS: No submit allowed for kctx %pK\n",
- (void *)kctx);
- return false;
- }
- }
- katom = jsctx_rb_peek(kctx, js);
- if (!katom) {
-- dev_dbg(kbdev->dev, "JS: No pullable atom in kctx %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "JS: No pullable atom in kctx %pK (s:%d)\n",
- (void *)kctx, js);
- return false; /* No pullable atoms */
- }
- if (kctx->blocked_js[js][katom->sched_priority]) {
- dev_dbg(kbdev->dev,
-- "JS: kctx %p is blocked from submitting atoms at priority %d (s:%d)\n",
-+ "JS: kctx %pK is blocked from submitting atoms at priority %d (s:%d)\n",
- (void *)kctx, katom->sched_priority, js);
- return false;
- }
- if (atomic_read(&katom->blocked)) {
-- dev_dbg(kbdev->dev, "JS: Atom %p is blocked in js_ctx_pullable\n",
-+ dev_dbg(kbdev->dev, "JS: Atom %pK is blocked in js_ctx_pullable\n",
- (void *)katom);
- return false; /* next atom blocked */
- }
-@@ -970,20 +974,20 @@ static bool kbase_js_ctx_pullable(struct kbase_context *kctx, int js,
- KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB ||
- katom->x_pre_dep->will_fail_event_code) {
- dev_dbg(kbdev->dev,
-- "JS: X pre-dep %p is not present in slot FIFO or will fail\n",
-+ "JS: X pre-dep %pK is not present in slot FIFO or will fail\n",
- (void *)katom->x_pre_dep);
- return false;
- }
- if ((katom->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) &&
- kbase_backend_nr_atoms_on_slot(kctx->kbdev, js)) {
- dev_dbg(kbdev->dev,
-- "JS: Atom %p has cross-slot fail dependency and atoms on slot (s:%d)\n",
-+ "JS: Atom %pK has cross-slot fail dependency and atoms on slot (s:%d)\n",
- (void *)katom, js);
- return false;
- }
- }
-
-- dev_dbg(kbdev->dev, "JS: Atom %p is pullable in kctx %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "JS: Atom %pK is pullable in kctx %pK (s:%d)\n",
- (void *)katom, (void *)kctx, js);
-
- return true;
-@@ -1007,7 +1011,7 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- int dep_prio = dep_atom->sched_priority;
-
- dev_dbg(kbdev->dev,
-- "Checking dep %d of atom %p (s:%d) on %p (s:%d)\n",
-+ "Checking dep %d of atom %pK (s:%d) on %pK (s:%d)\n",
- i, (void *)katom, js, (void *)dep_atom, dep_js);
-
- /* Dependent atom must already have been submitted */
-@@ -1020,7 +1024,8 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- }
-
- /* Dependencies with different priorities can't
-- be represented in the ringbuffer */
-+ * be represented in the ringbuffer
-+ */
- if (prio != dep_prio) {
- dev_dbg(kbdev->dev,
- "Different atom priorities\n");
-@@ -1030,7 +1035,8 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
-
- if (js == dep_js) {
- /* Only one same-slot dependency can be
-- * represented in the ringbuffer */
-+ * represented in the ringbuffer
-+ */
- if (has_dep) {
- dev_dbg(kbdev->dev,
- "Too many same-slot deps\n");
-@@ -1038,7 +1044,8 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- break;
- }
- /* Each dependee atom can only have one
-- * same-slot dependency */
-+ * same-slot dependency
-+ */
- if (dep_atom->post_dep) {
- dev_dbg(kbdev->dev,
- "Too many same-slot successors\n");
-@@ -1048,7 +1055,8 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- has_dep = true;
- } else {
- /* Only one cross-slot dependency can be
-- * represented in the ringbuffer */
-+ * represented in the ringbuffer
-+ */
- if (has_x_dep) {
- dev_dbg(kbdev->dev,
- "Too many cross-slot deps\n");
-@@ -1056,7 +1064,8 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- break;
- }
- /* Each dependee atom can only have one
-- * cross-slot dependency */
-+ * cross-slot dependency
-+ */
- if (dep_atom->x_post_dep) {
- dev_dbg(kbdev->dev,
- "Too many cross-slot successors\n");
-@@ -1064,7 +1073,8 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- break;
- }
- /* The dependee atom can not already be in the
-- * HW access ringbuffer */
-+ * HW access ringbuffer
-+ */
- if (dep_atom->gpu_rb_state !=
- KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) {
- dev_dbg(kbdev->dev,
-@@ -1074,7 +1084,8 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- break;
- }
- /* The dependee atom can not already have
-- * completed */
-+ * completed
-+ */
- if (dep_atom->status !=
- KBASE_JD_ATOM_STATE_IN_JS) {
- dev_dbg(kbdev->dev,
-@@ -1092,7 +1103,8 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- }
-
- /* If dependencies can be represented by ringbuffer then clear them from
-- * atom structure */
-+ * atom structure
-+ */
- if (ret) {
- for (i = 0; i < 2; i++) {
- struct kbase_jd_atom *dep_atom = katom->dep[i].atom;
-@@ -1101,7 +1113,7 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- int dep_js = kbase_js_get_slot(kbdev, dep_atom);
-
- dev_dbg(kbdev->dev,
-- "Clearing dep %d of atom %p (s:%d) on %p (s:%d)\n",
-+ "Clearing dep %d of atom %pK (s:%d) on %pK (s:%d)\n",
- i, (void *)katom, js, (void *)dep_atom,
- dep_js);
-
-@@ -1116,7 +1128,7 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- katom->atom_flags |=
- KBASE_KATOM_FLAG_X_DEP_BLOCKED;
-
-- dev_dbg(kbdev->dev, "Set X_DEP flag on atom %p\n",
-+ dev_dbg(kbdev->dev, "Set X_DEP flag on atom %pK\n",
- (void *)katom);
-
- katom->x_pre_dep = dep_atom;
-@@ -1140,7 +1152,7 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx,
- }
- } else {
- dev_dbg(kbdev->dev,
-- "Deps of atom %p (s:%d) could not be represented\n",
-+ "Deps of atom %pK (s:%d) could not be represented\n",
- (void *)katom, js);
- }
-
-@@ -1181,7 +1193,7 @@ void kbase_js_update_ctx_priority(struct kbase_context *kctx)
- /* Determine the new priority for context, as per the priority
- * of currently in-use atoms.
- */
-- for (prio = KBASE_JS_ATOM_SCHED_PRIO_HIGH;
-+ for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST;
- prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
- if (kctx->atoms_count[prio]) {
- new_priority = prio;
-@@ -1192,6 +1204,7 @@ void kbase_js_update_ctx_priority(struct kbase_context *kctx)
-
- kbase_js_set_ctx_priority(kctx, new_priority);
- }
-+KBASE_EXPORT_TEST_API(kbase_js_update_ctx_priority);
-
- /**
- * js_add_start_rp() - Add an atom that starts a renderpass to the job scheduler
-@@ -1222,7 +1235,7 @@ static int js_add_start_rp(struct kbase_jd_atom *const start_katom)
- if (rp->state != KBASE_JD_RP_COMPLETE)
- return -EINVAL;
-
-- dev_dbg(kctx->kbdev->dev, "JS add start atom %p of RP %d\n",
-+ dev_dbg(kctx->kbdev->dev, "JS add start atom %pK of RP %d\n",
- (void *)start_katom, start_katom->renderpass_id);
-
- /* The following members are read when updating the job slot
-@@ -1265,7 +1278,7 @@ static int js_add_end_rp(struct kbase_jd_atom *const end_katom)
-
- rp = &kctx->jctx.renderpasses[end_katom->renderpass_id];
-
-- dev_dbg(kbdev->dev, "JS add end atom %p in state %d of RP %d\n",
-+ dev_dbg(kbdev->dev, "JS add end atom %pK in state %d of RP %d\n",
- (void *)end_katom, (int)rp->state, end_katom->renderpass_id);
-
- if (rp->state == KBASE_JD_RP_COMPLETE)
-@@ -1332,7 +1345,7 @@ bool kbasep_js_add_job(struct kbase_context *kctx,
- /* Refcount ctx.nr_jobs */
- KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs < U32_MAX);
- ++(js_kctx_info->ctx.nr_jobs);
-- dev_dbg(kbdev->dev, "Add atom %p to kctx %p; now %d in ctx\n",
-+ dev_dbg(kbdev->dev, "Add atom %pK to kctx %pK; now %d in ctx\n",
- (void *)atom, (void *)kctx, js_kctx_info->ctx.nr_jobs);
-
- /* Lock for state available during IRQ */
-@@ -1345,13 +1358,14 @@ bool kbasep_js_add_job(struct kbase_context *kctx,
- /* Dependencies could not be represented */
- --(js_kctx_info->ctx.nr_jobs);
- dev_dbg(kbdev->dev,
-- "Remove atom %p from kctx %p; now %d in ctx\n",
-+ "Remove atom %pK from kctx %pK; now %d in ctx\n",
- (void *)atom, (void *)kctx, js_kctx_info->ctx.nr_jobs);
-
- /* Setting atom status back to queued as it still has unresolved
-- * dependencies */
-+ * dependencies
-+ */
- atom->status = KBASE_JD_ATOM_STATE_QUEUED;
-- dev_dbg(kbdev->dev, "Atom %p status to queued\n", (void *)atom);
-+ dev_dbg(kbdev->dev, "Atom %pK status to queued\n", (void *)atom);
-
- /* Undo the count, as the atom will get added again later but
- * leave the context priority adjusted or boosted, in case if
-@@ -1389,7 +1403,8 @@ bool kbasep_js_add_job(struct kbase_context *kctx,
- kbdev, kctx, atom->slot_nr);
- }
- /* If this context is active and the atom is the first on its slot,
-- * kick the job manager to attempt to fast-start the atom */
-+ * kick the job manager to attempt to fast-start the atom
-+ */
- if (enqueue_required && kctx ==
- kbdev->hwaccess.active_kctx[atom->slot_nr])
- kbase_jm_try_kick(kbdev, 1 << atom->slot_nr);
-@@ -1404,22 +1419,25 @@ bool kbasep_js_add_job(struct kbase_context *kctx,
- if (kbase_ctx_flag(kctx, KCTX_DYING)) {
- /* A job got added while/after kbase_job_zap_context()
- * was called on a non-scheduled context. Kill that job
-- * by killing the context. */
-+ * by killing the context.
-+ */
- kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx,
- false);
- } else if (js_kctx_info->ctx.nr_jobs == 1) {
- /* Handle Refcount going from 0 to 1: schedule the
-- * context on the Queue */
-+ * context on the Queue
-+ */
- KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED));
-- dev_dbg(kbdev->dev, "JS: Enqueue Context %p", kctx);
-+ dev_dbg(kbdev->dev, "JS: Enqueue Context %pK", kctx);
-
-- /* Queue was updated - caller must try to
-- * schedule the head context */
-+ /* Queue was updated - caller must try to schedule the
-+ * head context
-+ */
- WARN_ON(!enqueue_required);
- }
- }
- out_unlock:
-- dev_dbg(kbdev->dev, "Enqueue of kctx %p is %srequired\n",
-+ dev_dbg(kbdev->dev, "Enqueue of kctx %pK is %srequired\n",
- kctx, enqueue_required ? "" : "not ");
-
- mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
-@@ -1448,7 +1466,7 @@ void kbasep_js_remove_job(struct kbase_device *kbdev,
- KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs > 0);
- --(js_kctx_info->ctx.nr_jobs);
- dev_dbg(kbdev->dev,
-- "Remove atom %p from kctx %p; now %d in ctx\n",
-+ "Remove atom %pK from kctx %pK; now %d in ctx\n",
- (void *)atom, (void *)kctx, js_kctx_info->ctx.nr_jobs);
-
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-@@ -1478,7 +1496,8 @@ bool kbasep_js_remove_cancelled_job(struct kbase_device *kbdev,
- *
- * This is because it returns 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 */
-+ * 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(&kbdev->hwaccess_lock, flags);
-@@ -1525,7 +1544,8 @@ static kbasep_js_release_result kbasep_js_run_jobs_after_ctx_and_atom_release(
-
- if (js_devdata->nr_user_contexts_running != 0 && runpool_ctx_attr_change) {
- /* A change in runpool ctx attributes might mean we can
-- * run more jobs than before */
-+ * run more jobs than before
-+ */
- result = KBASEP_JS_RELEASE_RESULT_SCHED_ALL;
-
- KBASE_KTRACE_ADD_JM_SLOT(kbdev, JD_DONE_TRY_RUN_NEXT_JOB,
-@@ -1624,7 +1644,8 @@ static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(
-
- /* Make a set of checks to see if the context should be scheduled out.
- * Note that there'll always be at least 1 reference to the context
-- * which was previously acquired by kbasep_js_schedule_ctx(). */
-+ * which was previously acquired by kbasep_js_schedule_ctx().
-+ */
- if (new_ref_count == 1 &&
- (!kbasep_js_is_submit_allowed(js_devdata, kctx) ||
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
-@@ -1635,8 +1656,9 @@ static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(
- int slot;
-
- /* Last reference, and we've been told to remove this context
-- * from the Run Pool */
-- dev_dbg(kbdev->dev, "JS: RunPool Remove Context %p because refcount=%d, jobs=%d, allowed=%d",
-+ * from the Run Pool
-+ */
-+ dev_dbg(kbdev->dev, "JS: RunPool Remove Context %pK because refcount=%d, jobs=%d, allowed=%d",
- kctx, new_ref_count, js_kctx_info->ctx.nr_jobs,
- kbasep_js_is_submit_allowed(js_devdata, kctx));
-
-@@ -1646,7 +1668,7 @@ static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(
-
- for (slot = 0; slot < num_slots; slot++) {
- if (kbdev->hwaccess.active_kctx[slot] == kctx) {
-- dev_dbg(kbdev->dev, "Marking kctx %p as inactive (s:%d)\n",
-+ dev_dbg(kbdev->dev, "Marking kctx %pK as inactive (s:%d)\n",
- (void *)kctx, slot);
- kbdev->hwaccess.active_kctx[slot] = NULL;
- }
-@@ -1662,7 +1684,8 @@ static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(
- kbasep_js_ctx_attr_runpool_release_ctx(kbdev, kctx);
-
- /* Releasing the context and katom retained state can allow
-- * more jobs to run */
-+ * more jobs to run
-+ */
- release_result |=
- kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev,
- kctx, katom_retained_state,
-@@ -1702,7 +1725,8 @@ static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal(
- kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED);
- /* 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. */
-+ * and jobs have finished.
-+ */
- wake_up(&js_kctx_info->ctx.is_scheduled_wait);
-
- /* Queue an action to occur after we've dropped the lock */
-@@ -1744,9 +1768,10 @@ void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev,
-
- if (kbase_ctx_flag(kctx, KCTX_DYING)) {
- /* Dying: don't requeue, but kill all jobs on the context. This
-- * happens asynchronously */
-+ * happens asynchronously
-+ */
- dev_dbg(kbdev->dev,
-- "JS: ** Killing Context %p on RunPool Remove **", kctx);
-+ "JS: ** Killing Context %pK on RunPool Remove **", kctx);
- kbase_js_foreach_ctx_job(kctx, &kbase_jd_cancel);
- }
- }
-@@ -1798,7 +1823,8 @@ void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev,
- }
-
- /* Variant of kbasep_js_runpool_release_ctx() that doesn't call into
-- * kbase_js_sched_all() */
-+ * kbase_js_sched_all()
-+ */
- static void kbasep_js_runpool_release_ctx_no_schedule(
- struct kbase_device *kbdev, struct kbase_context *kctx)
- {
-@@ -1851,7 +1877,7 @@ static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev,
- bool kctx_suspended = false;
- int as_nr;
-
-- dev_dbg(kbdev->dev, "Scheduling kctx %p (s:%d)\n", kctx, js);
-+ dev_dbg(kbdev->dev, "Scheduling kctx %pK (s:%d)\n", kctx, js);
-
- js_devdata = &kbdev->js_data;
- js_kctx_info = &kctx->jctx.sched_info;
-@@ -1867,7 +1893,8 @@ static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev,
- kbdev, kctx);
- if (as_nr != KBASEP_AS_NR_INVALID) {
- /* Attempt to retain the context again, this should
-- * succeed */
-+ * succeed
-+ */
- mutex_lock(&kbdev->mmu_hw_mutex);
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- as_nr = kbase_ctx_sched_retain_ctx(kctx);
-@@ -1926,7 +1953,8 @@ static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev,
- KBASE_TLSTREAM_TL_RET_AS_CTX(kbdev, &kbdev->as[kctx->as_nr], kctx);
-
- /* Cause any future waiter-on-termination to wait until the context is
-- * descheduled */
-+ * descheduled
-+ */
- wake_up(&js_kctx_info->ctx.is_scheduled_wait);
-
- /* Re-check for suspending: a suspend could've occurred, and all the
-@@ -1939,7 +1967,8 @@ static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev,
- * 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) */
-+ * wait for this lock to drop)
-+ */
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- if (kbase_pm_is_suspending(kbdev) || kbase_pm_is_gpu_lost(kbdev)) {
- #else
-@@ -1967,13 +1996,15 @@ static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev,
- 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 */
-+ * out immediately
-+ */
-
- if (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 */
-+ * into this function
-+ */
- kbasep_js_runpool_release_ctx_no_schedule(kbdev, kctx);
- return false;
- }
-@@ -1992,7 +2023,7 @@ static bool kbase_js_use_ctx(struct kbase_device *kbdev,
- kbase_backend_use_ctx_sched(kbdev, kctx, js)) {
-
- dev_dbg(kbdev->dev,
-- "kctx %p already has ASID - mark as active (s:%d)\n",
-+ "kctx %pK already has ASID - mark as active (s:%d)\n",
- (void *)kctx, js);
-
- if (kbdev->hwaccess.active_kctx[js] != kctx) {
-@@ -2059,7 +2090,8 @@ void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev,
- kbase_js_sync_timers(kbdev);
-
- /* Fast-starting requires the jsctx_mutex to be dropped,
-- * because it works on multiple ctxs */
-+ * because it works on multiple ctxs
-+ */
- mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
- mutex_unlock(&js_devdata->queue_mutex);
-
-@@ -2071,7 +2103,8 @@ void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev,
- kbase_ctx_flag(kctx, KCTX_SCHEDULED));
- } else {
- /* Already scheduled in - We need to retain it to keep the
-- * corresponding address space */
-+ * corresponding address space
-+ */
- WARN_ON(!kbase_ctx_sched_inc_refcount(kctx));
- mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
- mutex_unlock(&js_devdata->queue_mutex);
-@@ -2116,7 +2149,8 @@ void kbasep_js_suspend(struct kbase_device *kbdev)
- 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 */
-+ * had no refcount to begin with
-+ */
- for (i = BASE_MAX_NR_AS - 1; i >= 0; --i) {
- struct kbase_context *kctx = kbdev->as_to_kctx[i];
-
-@@ -2137,7 +2171,8 @@ void kbasep_js_suspend(struct kbase_device *kbdev)
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
- /* De-ref the previous retain to ensure each context gets pulled out
-- * sometime later. */
-+ * sometime later.
-+ */
- for (i = 0;
- i < BASE_MAX_NR_AS;
- ++i, retained = retained >> 1) {
-@@ -2148,7 +2183,8 @@ void kbasep_js_suspend(struct kbase_device *kbdev)
- }
-
- /* Caller must wait for all Power Manager active references to be
-- * dropped */
-+ * dropped
-+ */
- }
-
- void kbasep_js_resume(struct kbase_device *kbdev)
-@@ -2162,7 +2198,7 @@ void kbasep_js_resume(struct kbase_device *kbdev)
-
- mutex_lock(&js_devdata->queue_mutex);
- for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) {
-- for (prio = KBASE_JS_ATOM_SCHED_PRIO_HIGH;
-+ for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST;
- prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
- struct kbase_context *kctx, *n;
- unsigned long flags;
-@@ -2283,7 +2319,8 @@ bool kbase_js_dep_resolved_submit(struct kbase_context *kctx,
- lockdep_assert_held(&kctx->jctx.lock);
-
- /* If slot will transition from unpullable to pullable then add to
-- * pullable list */
-+ * pullable list
-+ */
- if (jsctx_rb_none_to_pull(kctx, katom->slot_nr)) {
- enqueue_required = true;
- } else {
-@@ -2297,7 +2334,7 @@ bool kbase_js_dep_resolved_submit(struct kbase_context *kctx,
- int js = katom->slot_nr;
- struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js];
-
-- dev_dbg(kctx->kbdev->dev, "Add atom %p to X_DEP list (s:%d)\n",
-+ dev_dbg(kctx->kbdev->dev, "Add atom %pK to X_DEP list (s:%d)\n",
- (void *)katom, js);
-
- list_add_tail(&katom->queue, &queue->x_dep_head);
-@@ -2307,7 +2344,7 @@ bool kbase_js_dep_resolved_submit(struct kbase_context *kctx,
- add_required = false;
- }
- } else {
-- dev_dbg(kctx->kbdev->dev, "Atom %p not added to X_DEP list\n",
-+ dev_dbg(kctx->kbdev->dev, "Atom %pK not added to X_DEP list\n",
- (void *)katom);
- }
-
-@@ -2321,7 +2358,7 @@ bool kbase_js_dep_resolved_submit(struct kbase_context *kctx,
- }
-
- dev_dbg(kctx->kbdev->dev,
-- "Enqueue of kctx %p is %srequired to submit atom %p\n",
-+ "Enqueue of kctx %pK is %srequired to submit atom %pK\n",
- kctx, enqueue_required ? "" : "not ", katom);
-
- return enqueue_required;
-@@ -2348,7 +2385,7 @@ static void kbase_js_move_to_tree(struct kbase_jd_atom *katom)
-
- if (!kbase_js_atom_blocked_on_x_dep(katom)) {
- dev_dbg(kctx->kbdev->dev,
-- "Del atom %p from X_DEP list in js_move_to_tree\n",
-+ "Del atom %pK from X_DEP list in js_move_to_tree\n",
- (void *)katom);
-
- list_del(&katom->queue);
-@@ -2366,7 +2403,7 @@ static void kbase_js_move_to_tree(struct kbase_jd_atom *katom)
- }
- } else {
- dev_dbg(kctx->kbdev->dev,
-- "Atom %p blocked on x-dep in js_move_to_tree\n",
-+ "Atom %pK blocked on x-dep in js_move_to_tree\n",
- (void *)katom);
- break;
- }
-@@ -2409,10 +2446,8 @@ static void kbase_js_evict_deps(struct kbase_context *kctx,
- KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST))) {
- /* Remove dependency.*/
- x_dep->atom_flags &= ~KBASE_KATOM_FLAG_X_DEP_BLOCKED;
-- trace_sysgraph(SGR_DEP_RES, kctx->id,
-- kbase_jd_atom_id(kctx, x_dep));
-
-- dev_dbg(kctx->kbdev->dev, "Cleared X_DEP flag on atom %p\n",
-+ dev_dbg(kctx->kbdev->dev, "Cleared X_DEP flag on atom %pK\n",
- (void *)x_dep);
-
- /* Fail if it had a data dependency. */
-@@ -2434,14 +2469,14 @@ struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js)
- KBASE_DEBUG_ASSERT(kctx);
-
- kbdev = kctx->kbdev;
-- dev_dbg(kbdev->dev, "JS: pulling an atom from kctx %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "JS: pulling an atom from kctx %pK (s:%d)\n",
- (void *)kctx, js);
-
- js_devdata = &kbdev->js_data;
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
- if (!kbasep_js_is_submit_allowed(js_devdata, kctx)) {
-- dev_dbg(kbdev->dev, "JS: No submit allowed for kctx %p\n",
-+ dev_dbg(kbdev->dev, "JS: No submit allowed for kctx %pK\n",
- (void *)kctx);
- return NULL;
- }
-@@ -2454,25 +2489,26 @@ struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js)
-
- katom = jsctx_rb_peek(kctx, js);
- if (!katom) {
-- dev_dbg(kbdev->dev, "JS: No pullable atom in kctx %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "JS: No pullable atom in kctx %pK (s:%d)\n",
- (void *)kctx, js);
- return NULL;
- }
- if (kctx->blocked_js[js][katom->sched_priority]) {
- dev_dbg(kbdev->dev,
-- "JS: kctx %p is blocked from submitting atoms at priority %d (s:%d)\n",
-+ "JS: kctx %pK is blocked from submitting atoms at priority %d (s:%d)\n",
- (void *)kctx, katom->sched_priority, js);
- return NULL;
- }
- if (atomic_read(&katom->blocked)) {
-- dev_dbg(kbdev->dev, "JS: Atom %p is blocked in js_pull\n",
-+ dev_dbg(kbdev->dev, "JS: Atom %pK is blocked in js_pull\n",
- (void *)katom);
- return NULL;
- }
-
- /* Due to ordering restrictions when unpulling atoms on failure, we do
- * not allow multiple runs of fail-dep atoms from the same context to be
-- * present on the same slot */
-+ * present on the same slot
-+ */
- if (katom->pre_dep && atomic_read(&kctx->atoms_pulled_slot[js])) {
- struct kbase_jd_atom *prev_atom =
- kbase_backend_inspect_tail(kbdev, js);
-@@ -2486,14 +2522,14 @@ struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js)
- KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB ||
- katom->x_pre_dep->will_fail_event_code) {
- dev_dbg(kbdev->dev,
-- "JS: X pre-dep %p is not present in slot FIFO or will fail\n",
-+ "JS: X pre-dep %pK is not present in slot FIFO or will fail\n",
- (void *)katom->x_pre_dep);
- return NULL;
- }
- if ((katom->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) &&
- kbase_backend_nr_atoms_on_slot(kbdev, js)) {
- dev_dbg(kbdev->dev,
-- "JS: Atom %p has cross-slot fail dependency and atoms on slot (s:%d)\n",
-+ "JS: Atom %pK has cross-slot fail dependency and atoms on slot (s:%d)\n",
- (void *)katom, js);
- return NULL;
- }
-@@ -2518,7 +2554,7 @@ struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js)
-
- katom->ticks = 0;
-
-- dev_dbg(kbdev->dev, "JS: successfully pulled atom %p from kctx %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "JS: successfully pulled atom %pK from kctx %pK (s:%d)\n",
- (void *)katom, (void *)kctx, js);
-
- return katom;
-@@ -2561,7 +2597,7 @@ static void js_return_of_start_rp(struct kbase_jd_atom *const start_katom)
- return;
-
- dev_dbg(kctx->kbdev->dev,
-- "JS return start atom %p in state %d of RP %d\n",
-+ "JS return start atom %pK in state %d of RP %d\n",
- (void *)start_katom, (int)rp->state,
- start_katom->renderpass_id);
-
-@@ -2589,7 +2625,7 @@ static void js_return_of_start_rp(struct kbase_jd_atom *const start_katom)
- /* Prevent the tiler job being pulled for execution in the
- * job scheduler again.
- */
-- dev_dbg(kbdev->dev, "Blocking start atom %p\n",
-+ dev_dbg(kbdev->dev, "Blocking start atom %pK\n",
- (void *)start_katom);
- atomic_inc(&start_katom->blocked);
-
-@@ -2601,14 +2637,14 @@ static void js_return_of_start_rp(struct kbase_jd_atom *const start_katom)
- /* Was the fragment job chain submitted to kbase yet? */
- end_katom = rp->end_katom;
- if (end_katom) {
-- dev_dbg(kctx->kbdev->dev, "JS return add end atom %p\n",
-+ dev_dbg(kctx->kbdev->dev, "JS return add end atom %pK\n",
- (void *)end_katom);
-
- if (rp->state == KBASE_JD_RP_RETRY_OOM) {
- /* Allow the end of the renderpass to be pulled for
- * execution again to continue incremental rendering.
- */
-- dev_dbg(kbdev->dev, "Unblocking end atom %p\n",
-+ dev_dbg(kbdev->dev, "Unblocking end atom %pK\n",
- (void *)end_katom);
- atomic_dec(&end_katom->blocked);
- WARN_ON(!(end_katom->atom_flags &
-@@ -2670,7 +2706,7 @@ static void js_return_of_end_rp(struct kbase_jd_atom *const end_katom)
- return;
-
- dev_dbg(kctx->kbdev->dev,
-- "JS return end atom %p in state %d of RP %d\n",
-+ "JS return end atom %pK in state %d of RP %d\n",
- (void *)end_katom, (int)rp->state, end_katom->renderpass_id);
-
- if (WARN_ON(rp->state != KBASE_JD_RP_OOM &&
-@@ -2692,14 +2728,14 @@ static void js_return_of_end_rp(struct kbase_jd_atom *const end_katom)
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
- dev_dbg(kbdev->dev,
-- "Reset backing to %zu pages for region %p\n",
-+ "Reset backing to %zu pages for region %pK\n",
- reg->threshold_pages, (void *)reg);
-
- if (!WARN_ON(reg->flags & KBASE_REG_VA_FREED))
- kbase_mem_shrink(kctx, reg, reg->threshold_pages);
-
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-- dev_dbg(kbdev->dev, "Deleting region %p from list\n",
-+ dev_dbg(kbdev->dev, "Deleting region %pK from list\n",
- (void *)reg);
- list_del_init(®->link);
- kbase_va_region_alloc_put(kctx, reg);
-@@ -2717,7 +2753,7 @@ static void js_return_of_end_rp(struct kbase_jd_atom *const end_katom)
- */
- start_katom = rp->start_katom;
- if (!WARN_ON(!start_katom)) {
-- dev_dbg(kbdev->dev, "Unblocking start atom %p\n",
-+ dev_dbg(kbdev->dev, "Unblocking start atom %pK\n",
- (void *)start_katom);
- atomic_dec(&start_katom->blocked);
- (void)kbase_js_ctx_list_add_pullable_head_nolock(kbdev, kctx,
-@@ -2743,7 +2779,7 @@ static void js_return_worker(struct work_struct *data)
- unsigned long flags;
- base_jd_core_req core_req = katom->core_req;
-
-- dev_dbg(kbdev->dev, "%s for atom %p with event code 0x%x\n",
-+ dev_dbg(kbdev->dev, "%s for atom %pK with event code 0x%x\n",
- __func__, (void *)katom, katom->event_code);
-
- if (katom->event_code != BASE_JD_EVENT_END_RP_DONE)
-@@ -2771,13 +2807,15 @@ static void js_return_worker(struct work_struct *data)
- timer_sync |= kbase_js_ctx_list_remove_nolock(kbdev, kctx, js);
-
- /* If this slot has been blocked due to soft-stopped atoms, and all
-- * atoms have now been processed, then unblock the slot */
-+ * atoms have now been processed, then unblock the slot
-+ */
- if (!kctx->atoms_pulled_slot_pri[js][prio] &&
- kctx->blocked_js[js][prio]) {
- kctx->blocked_js[js][prio] = false;
-
- /* Only mark the slot as pullable if the context is not idle -
-- * that case is handled below */
-+ * that case is handled below
-+ */
- if (atomic_read(&kctx->atoms_pulled) &&
- kbase_js_ctx_pullable(kctx, js, true))
- timer_sync |= kbase_js_ctx_list_add_pullable_nolock(
-@@ -2786,12 +2824,12 @@ static void js_return_worker(struct work_struct *data)
-
- if (!atomic_read(&kctx->atoms_pulled)) {
- dev_dbg(kbdev->dev,
-- "No atoms currently pulled from context %p\n",
-+ "No atoms currently pulled from context %pK\n",
- (void *)kctx);
-
- if (!kctx->slots_pullable) {
- dev_dbg(kbdev->dev,
-- "Context %p %s counted as runnable\n",
-+ "Context %pK %s counted as runnable\n",
- (void *)kctx,
- kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF) ?
- "is" : "isn't");
-@@ -2827,7 +2865,7 @@ static void js_return_worker(struct work_struct *data)
-
- if (context_idle) {
- dev_dbg(kbdev->dev,
-- "Context %p %s counted as active\n",
-+ "Context %pK %s counted as active\n",
- (void *)kctx,
- kbase_ctx_flag(kctx, KCTX_ACTIVE) ?
- "is" : "isn't");
-@@ -2866,13 +2904,13 @@ static void js_return_worker(struct work_struct *data)
-
- kbase_backend_complete_wq_post_sched(kbdev, core_req);
-
-- dev_dbg(kbdev->dev, "Leaving %s for atom %p\n",
-+ dev_dbg(kbdev->dev, "Leaving %s for atom %pK\n",
- __func__, (void *)katom);
- }
-
- void kbase_js_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom)
- {
-- dev_dbg(kctx->kbdev->dev, "Unpulling atom %p in kctx %p\n",
-+ dev_dbg(kctx->kbdev->dev, "Unpulling atom %pK in kctx %pK\n",
- (void *)katom, (void *)kctx);
-
- lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
-@@ -2927,7 +2965,7 @@ static bool js_complete_start_rp(struct kbase_context *kctx,
- return false;
-
- dev_dbg(kctx->kbdev->dev,
-- "Start atom %p is done in state %d of RP %d\n",
-+ "Start atom %pK is done in state %d of RP %d\n",
- (void *)start_katom, (int)rp->state,
- start_katom->renderpass_id);
-
-@@ -2939,7 +2977,7 @@ static bool js_complete_start_rp(struct kbase_context *kctx,
- unsigned long flags;
-
- dev_dbg(kctx->kbdev->dev,
-- "Start atom %p completed before soft-stop\n",
-+ "Start atom %pK completed before soft-stop\n",
- (void *)start_katom);
-
- kbase_gpu_vm_lock(kctx);
-@@ -2951,7 +2989,7 @@ static bool js_complete_start_rp(struct kbase_context *kctx,
- struct kbase_va_region, link);
-
- WARN_ON(reg->flags & KBASE_REG_VA_FREED);
-- dev_dbg(kctx->kbdev->dev, "Deleting region %p from list\n",
-+ dev_dbg(kctx->kbdev->dev, "Deleting region %pK from list\n",
- (void *)reg);
- list_del_init(®->link);
- kbase_va_region_alloc_put(kctx, reg);
-@@ -2961,7 +2999,7 @@ static bool js_complete_start_rp(struct kbase_context *kctx,
- kbase_gpu_vm_unlock(kctx);
- } else {
- dev_dbg(kctx->kbdev->dev,
-- "Start atom %p did not exceed memory threshold\n",
-+ "Start atom %pK did not exceed memory threshold\n",
- (void *)start_katom);
-
- WARN_ON(rp->state != KBASE_JD_RP_START &&
-@@ -2978,7 +3016,7 @@ static bool js_complete_start_rp(struct kbase_context *kctx,
- /* Allow the end of the renderpass to be pulled for
- * execution again to continue incremental rendering.
- */
-- dev_dbg(kbdev->dev, "Unblocking end atom %p!\n",
-+ dev_dbg(kbdev->dev, "Unblocking end atom %pK!\n",
- (void *)end_katom);
- atomic_dec(&end_katom->blocked);
-
-@@ -3022,7 +3060,7 @@ static void js_complete_end_rp(struct kbase_context *kctx,
- if (WARN_ON(rp->end_katom != end_katom))
- return;
-
-- dev_dbg(kbdev->dev, "End atom %p is done in state %d of RP %d\n",
-+ dev_dbg(kbdev->dev, "End atom %pK is done in state %d of RP %d\n",
- (void *)end_katom, (int)rp->state, end_katom->renderpass_id);
-
- if (WARN_ON(rp->state == KBASE_JD_RP_COMPLETE) ||
-@@ -3056,7 +3094,7 @@ bool kbase_js_complete_atom_wq(struct kbase_context *kctx,
- kbdev = kctx->kbdev;
- atom_slot = katom->slot_nr;
-
-- dev_dbg(kbdev->dev, "%s for atom %p (s:%d)\n",
-+ dev_dbg(kbdev->dev, "%s for atom %pK (s:%d)\n",
- __func__, (void *)katom, atom_slot);
-
- /* Update the incremental rendering state machine.
-@@ -3075,7 +3113,7 @@ bool kbase_js_complete_atom_wq(struct kbase_context *kctx,
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-
- if (katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE) {
-- dev_dbg(kbdev->dev, "Atom %p is in runnable_tree\n",
-+ dev_dbg(kbdev->dev, "Atom %pK is in runnable_tree\n",
- (void *)katom);
-
- context_idle = !atomic_dec_return(&kctx->atoms_pulled);
-@@ -3091,11 +3129,12 @@ bool kbase_js_complete_atom_wq(struct kbase_context *kctx,
- }
-
- /* If this slot has been blocked due to soft-stopped atoms, and
-- * all atoms have now been processed, then unblock the slot */
-+ * all atoms have now been processed, then unblock the slot
-+ */
- if (!kctx->atoms_pulled_slot_pri[atom_slot][prio]
- && kctx->blocked_js[atom_slot][prio]) {
- dev_dbg(kbdev->dev,
-- "kctx %p is no longer blocked from submitting on slot %d at priority %d\n",
-+ "kctx %pK is no longer blocked from submitting on slot %d at priority %d\n",
- (void *)kctx, atom_slot, prio);
-
- kctx->blocked_js[atom_slot][prio] = false;
-@@ -3149,7 +3188,7 @@ bool kbase_js_complete_atom_wq(struct kbase_context *kctx,
- * jd_done_worker().
- */
- if (context_idle) {
-- dev_dbg(kbdev->dev, "kctx %p is no longer active\n",
-+ dev_dbg(kbdev->dev, "kctx %pK is no longer active\n",
- (void *)kctx);
- kbase_ctx_flag_clear(kctx, KCTX_ACTIVE);
- }
-@@ -3200,7 +3239,7 @@ static bool js_end_rp_is_complete(struct kbase_jd_atom *const end_katom)
- return true;
-
- dev_dbg(kbdev->dev,
-- "JS complete end atom %p in state %d of RP %d\n",
-+ "JS complete end atom %pK in state %d of RP %d\n",
- (void *)end_katom, (int)rp->state,
- end_katom->renderpass_id);
-
-@@ -3229,7 +3268,7 @@ struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom,
- struct kbase_jd_atom *x_dep = katom->x_post_dep;
-
- kbdev = kctx->kbdev;
-- dev_dbg(kbdev->dev, "Atom %p complete in kctx %p (post-dep %p)\n",
-+ dev_dbg(kbdev->dev, "Atom %pK complete in kctx %pK (post-dep %pK)\n",
- (void *)katom, (void *)kctx, (void *)x_dep);
-
- lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
-@@ -3245,7 +3284,7 @@ struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom,
- katom->event_code = katom->will_fail_event_code;
-
- katom->status = KBASE_JD_ATOM_STATE_HW_COMPLETED;
-- dev_dbg(kbdev->dev, "Atom %p status to HW completed\n", (void *)katom);
-+ dev_dbg(kbdev->dev, "Atom %pK status to HW completed\n", (void *)katom);
-
- if (katom->event_code != BASE_JD_EVENT_DONE) {
- kbase_js_evict_deps(kctx, katom, katom->slot_nr,
-@@ -3267,9 +3306,7 @@ struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom,
- bool was_pullable = kbase_js_ctx_pullable(kctx, x_dep->slot_nr,
- false);
- x_dep->atom_flags &= ~KBASE_KATOM_FLAG_X_DEP_BLOCKED;
-- trace_sysgraph(SGR_DEP_RES, kctx->id,
-- kbase_jd_atom_id(katom->kctx, x_dep));
-- dev_dbg(kbdev->dev, "Cleared X_DEP flag on atom %p\n",
-+ dev_dbg(kbdev->dev, "Cleared X_DEP flag on atom %pK\n",
- (void *)x_dep);
-
- kbase_js_move_to_tree(x_dep);
-@@ -3280,13 +3317,13 @@ struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom,
- x_dep->slot_nr);
-
- if (x_dep->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE) {
-- dev_dbg(kbdev->dev, "Atom %p is in runnable tree\n",
-+ dev_dbg(kbdev->dev, "Atom %pK is in runnable tree\n",
- (void *)x_dep);
- return x_dep;
- }
- } else {
- dev_dbg(kbdev->dev,
-- "No cross-slot dep to unblock for atom %p\n",
-+ "No cross-slot dep to unblock for atom %pK\n",
- (void *)katom);
- }
-
-@@ -3317,13 +3354,13 @@ bool kbase_js_atom_blocked_on_x_dep(struct kbase_jd_atom *const katom)
-
- if (!(katom->atom_flags &
- KBASE_KATOM_FLAG_X_DEP_BLOCKED)) {
-- dev_dbg(kbdev->dev, "Atom %p is not blocked on a cross-slot dependency",
-+ dev_dbg(kbdev->dev, "Atom %pK is not blocked on a cross-slot dependency",
- (void *)katom);
- return false;
- }
-
- if (!(katom->core_req & BASE_JD_REQ_END_RENDERPASS)) {
-- dev_dbg(kbdev->dev, "Atom %p is blocked on a cross-slot dependency",
-+ dev_dbg(kbdev->dev, "Atom %pK is blocked on a cross-slot dependency",
- (void *)katom);
- return true;
- }
-@@ -3349,12 +3386,12 @@ bool kbase_js_atom_blocked_on_x_dep(struct kbase_jd_atom *const katom)
- * if it only depends on the tiler job chain.
- */
- if (katom->x_pre_dep != rp->start_katom) {
-- dev_dbg(kbdev->dev, "Dependency is on %p not start atom %p\n",
-+ dev_dbg(kbdev->dev, "Dependency is on %pK not start atom %pK\n",
- (void *)katom->x_pre_dep, (void *)rp->start_katom);
- return true;
- }
-
-- dev_dbg(kbdev->dev, "Ignoring cross-slot dep on atom %p\n",
-+ dev_dbg(kbdev->dev, "Ignoring cross-slot dep on atom %pK\n",
- (void *)katom->x_pre_dep);
-
- return false;
-@@ -3368,7 +3405,7 @@ void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
- bool ctx_waiting[BASE_JM_MAX_NR_SLOTS];
- int js;
-
-- dev_dbg(kbdev->dev, "%s kbdev %p mask 0x%x\n",
-+ dev_dbg(kbdev->dev, "%s kbdev %pK mask 0x%x\n",
- __func__, (void *)kbdev, (unsigned int)js_mask);
-
- js_devdata = &kbdev->js_data;
-@@ -3403,7 +3440,7 @@ void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
- context_idle = true;
-
- dev_dbg(kbdev->dev,
-- "kctx %p is not active (s:%d)\n",
-+ "kctx %pK is not active (s:%d)\n",
- (void *)kctx, js);
-
- if (kbase_pm_context_active_handle_suspend(
-@@ -3412,7 +3449,8 @@ void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
- dev_dbg(kbdev->dev,
- "Suspend pending (s:%d)\n", js);
- /* Suspend pending - return context to
-- * queue and stop scheduling */
-+ * queue and stop scheduling
-+ */
- mutex_lock(
- &kctx->jctx.sched_info.ctx.jsctx_mutex);
- if (kbase_js_ctx_list_add_pullable_head(
-@@ -3432,7 +3470,7 @@ void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
- &kctx->jctx.sched_info.ctx.jsctx_mutex);
-
- dev_dbg(kbdev->dev,
-- "kctx %p cannot be used at this time\n",
-+ "kctx %pK cannot be used at this time\n",
- kctx);
-
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-@@ -3474,7 +3512,7 @@ void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
- bool pullable;
-
- dev_dbg(kbdev->dev,
-- "No atoms pulled from kctx %p (s:%d)\n",
-+ "No atoms pulled from kctx %pK (s:%d)\n",
- (void *)kctx, js);
-
- pullable = kbase_js_ctx_pullable(kctx, js,
-@@ -3483,7 +3521,8 @@ void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
- /* Failed to pull jobs - push to head of list.
- * Unless this context is already 'active', in
- * which case it's effectively already scheduled
-- * so push it to the back of the list. */
-+ * so push it to the back of the list.
-+ */
- if (pullable && kctx == last_active[js] &&
- kbase_ctx_flag(kctx,
- (KCTX_PULLED_SINCE_ACTIVE_JS0 <<
-@@ -3508,7 +3547,8 @@ void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
- * slot, then we need to remove the active
- * marker to prevent it from submitting atoms in
- * the IRQ handler, which would prevent this
-- * context from making progress. */
-+ * context from making progress.
-+ */
- if (last_active[js] && kctx != last_active[js]
- && kbase_js_ctx_pullable(
- last_active[js], js, true))
-@@ -3534,7 +3574,7 @@ void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
- break; /* Could not run atoms on this slot */
- }
-
-- dev_dbg(kbdev->dev, "Push kctx %p to back of list\n",
-+ dev_dbg(kbdev->dev, "Push kctx %pK to back of list\n",
- (void *)kctx);
- if (kbase_js_ctx_pullable(kctx, js, true))
- timer_sync |=
-@@ -3556,7 +3596,7 @@ void kbase_js_sched(struct kbase_device *kbdev, int js_mask)
- for (js = 0; js < BASE_JM_MAX_NR_SLOTS; js++) {
- if (kbdev->hwaccess.active_kctx[js] == last_active[js] &&
- ctx_waiting[js]) {
-- dev_dbg(kbdev->dev, "Marking kctx %p as inactive (s:%d)\n",
-+ dev_dbg(kbdev->dev, "Marking kctx %pK as inactive (s:%d)\n",
- (void *)last_active[js], js);
- kbdev->hwaccess.active_kctx[js] = NULL;
- }
-@@ -3580,13 +3620,14 @@ void kbase_js_zap_context(struct kbase_context *kctx)
-
- /* First, atomically do the following:
- * - mark the context as dying
-- * - try to evict it from the queue */
-+ * - try to evict it from the queue
-+ */
- mutex_lock(&kctx->jctx.lock);
- mutex_lock(&js_devdata->queue_mutex);
- mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
- kbase_ctx_flag_set(kctx, KCTX_DYING);
-
-- dev_dbg(kbdev->dev, "Zap: Try Evict Ctx %p", kctx);
-+ dev_dbg(kbdev->dev, "Zap: Try Evict Ctx %pK", kctx);
-
- /*
- * At this point we know:
-@@ -3650,13 +3691,14 @@ void kbase_js_zap_context(struct kbase_context *kctx)
-
- KBASE_KTRACE_ADD_JM(kbdev, JM_ZAP_NON_SCHEDULED, kctx, NULL, 0u, kbase_ctx_flag(kctx, KCTX_SCHEDULED));
-
-- dev_dbg(kbdev->dev, "Zap: Ctx %p scheduled=0", kctx);
-+ dev_dbg(kbdev->dev, "Zap: Ctx %pK scheduled=0", kctx);
-
- /* Only cancel jobs when we evicted from the
- * queue. No Power Manager active reference was held.
- *
-- * Having is_dying set ensures that this kills, and
-- * doesn't requeue */
-+ * Having is_dying set ensures that this kills, and doesn't
-+ * requeue
-+ */
- kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, false);
-
- mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
-@@ -3667,9 +3709,10 @@ void kbase_js_zap_context(struct kbase_context *kctx)
- bool was_retained;
-
- /* Case c: didn't evict, but it is scheduled - it's in the Run
-- * Pool */
-+ * Pool
-+ */
- KBASE_KTRACE_ADD_JM(kbdev, JM_ZAP_SCHEDULED, kctx, NULL, 0u, kbase_ctx_flag(kctx, KCTX_SCHEDULED));
-- dev_dbg(kbdev->dev, "Zap: Ctx %p is in RunPool", kctx);
-+ dev_dbg(kbdev->dev, "Zap: Ctx %pK is in RunPool", kctx);
-
- /* Disable the ctx from submitting any more jobs */
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-@@ -3678,18 +3721,21 @@ void kbase_js_zap_context(struct kbase_context *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 */
-+ * somewhere will be removing the context later on
-+ */
- was_retained = kbase_ctx_sched_inc_refcount_nolock(kctx);
-
- /* Since it's scheduled and we have the jsctx_mutex, it must be
-- * retained successfully */
-+ * retained successfully
-+ */
- KBASE_DEBUG_ASSERT(was_retained);
-
-- dev_dbg(kbdev->dev, "Zap: Ctx %p Kill Any Running jobs", kctx);
-+ dev_dbg(kbdev->dev, "Zap: Ctx %pK 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. */
-+ * more new jobs will appear after we do this.
-+ */
- kbase_backend_jm_kill_running_jobs_from_kctx(kctx);
-
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-@@ -3697,7 +3743,7 @@ void kbase_js_zap_context(struct kbase_context *kctx)
- mutex_unlock(&js_devdata->queue_mutex);
- mutex_unlock(&kctx->jctx.lock);
-
-- dev_dbg(kbdev->dev, "Zap: Ctx %p Release (may or may not schedule out immediately)",
-+ dev_dbg(kbdev->dev, "Zap: Ctx %pK Release (may or may not schedule out immediately)",
- kctx);
-
- kbasep_js_runpool_release_ctx(kbdev, kctx);
-@@ -3711,7 +3757,8 @@ void kbase_js_zap_context(struct kbase_context *kctx)
- * to be destroyed, and the context to be de-scheduled (if it was on the
- * runpool).
- *
-- * kbase_jd_zap_context() will do this. */
-+ * kbase_jd_zap_context() will do this.
-+ */
- }
-
- static inline int trace_get_refcnt(struct kbase_device *kbdev,
-@@ -3739,7 +3786,7 @@ static inline int trace_get_refcnt(struct kbase_device *kbdev,
- * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex.
- */
- static void kbase_js_foreach_ctx_job(struct kbase_context *kctx,
-- kbasep_js_ctx_job_cb callback)
-+ kbasep_js_ctx_job_cb *callback)
- {
- struct kbase_device *kbdev;
- unsigned long flags;
-@@ -3758,3 +3805,18 @@ static void kbase_js_foreach_ctx_job(struct kbase_context *kctx,
-
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
- }
-+
-+base_jd_prio kbase_js_priority_check(struct kbase_device *kbdev, base_jd_prio priority)
-+{
-+ struct priority_control_manager_device *pcm_device = kbdev->pcm_dev;
-+ int req_priority, out_priority;
-+ base_jd_prio out_jd_priority = priority;
-+
-+ if (pcm_device) {
-+ req_priority = kbasep_js_atom_prio_to_sched_prio(priority);
-+ out_priority = pcm_device->ops.pcm_scheduler_priority_check(pcm_device, current, req_priority);
-+ out_jd_priority = kbasep_js_sched_prio_to_atom_prio(out_priority);
-+ }
-+ return out_jd_priority;
-+}
-+
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js.h
-index 541acd4..96974c8 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_js.h
-- * Job Scheduler APIs.
-+ * DOC: Job Scheduler APIs.
- */
-
- #ifndef _KBASE_JS_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c
-index 141d04a..7775648 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2016, 2018, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2016, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- #include <mali_kbase.h>
- #include <mali_kbase_config.h>
-
-@@ -29,8 +27,11 @@
- */
-
- /**
-- * @brief Check whether a ctx has a certain attribute, and if so, retain that
-+ * Check whether a ctx has a certain attribute, and if so, retain that
- * attribute on the runpool.
-+ * @kbdev: Device pointer
-+ * @kctx: KBase context
-+ * @attribute: Atribute to check/retain
- *
- * Requires:
- * - jsctx mutex
-@@ -75,8 +76,11 @@ static bool kbasep_js_ctx_attr_runpool_retain_attr(struct kbase_device *kbdev, s
- }
-
- /**
-- * @brief Check whether a ctx has a certain attribute, and if so, release that
-+ * Check whether a ctx has a certain attribute, and if so, release that
- * attribute on the runpool.
-+ * @kbdev: Device pointer
-+ * @kctx: KBase context
-+ * @attribute: Atribute to release
- *
- * Requires:
- * - jsctx mutex
-@@ -120,8 +124,11 @@ static bool kbasep_js_ctx_attr_runpool_release_attr(struct kbase_device *kbdev,
- }
-
- /**
-- * @brief Retain a certain attribute on a ctx, also retaining it on the runpool
-+ * Retain a certain attribute on a ctx, also retaining it on the runpool
- * if the context is scheduled.
-+ * @kbdev: Device pointer
-+ * @kctx: KBase context
-+ * @attribute: Atribute to retain
- *
- * Requires:
- * - jsctx mutex
-@@ -156,9 +163,12 @@ static bool kbasep_js_ctx_attr_ctx_retain_attr(struct kbase_device *kbdev, struc
- return runpool_state_changed;
- }
-
--/*
-- * @brief Release a certain attribute on a ctx, also releasing it from the runpool
-+/**
-+ * Release a certain attribute on a ctx, also releasing it from the runpool
- * if the context is scheduled.
-+ * @kbdev: Device pointer
-+ * @kctx: KBase context
-+ * @attribute: Atribute to release
- *
- * Requires:
- * - jsctx mutex
-@@ -211,7 +221,8 @@ void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kb
-
- /* We don't need to know about state changed, because retaining a
- * context occurs on scheduling it, and that itself will also try
-- * to run new atoms */
-+ * to run new atoms
-+ */
- CSTD_UNUSED(runpool_state_changed);
- }
- }
-@@ -251,9 +262,9 @@ void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase
- runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES);
- }
-
-- /* We don't need to know about state changed, because retaining an
-- * atom occurs on adding it, and that itself will also try to run
-- * new atoms */
-+ /* We don't need to know about state changed, because retaining an atom
-+ * occurs on adding it, and that itself will also try to run new atoms
-+ */
- CSTD_UNUSED(runpool_state_changed);
- }
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h
-index 25fd397..6f29241 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_js_ctx_attr.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2015, 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2015, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,37 +17,19 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_js_ctx_attr.h
-- * Job Scheduler Context Attribute APIs
-+ * DOC: Job Scheduler Context Attribute APIs
- */
-
- #ifndef _KBASE_JS_CTX_ATTR_H_
- #define _KBASE_JS_CTX_ATTR_H_
-
--/**
-- * @addtogroup base_api
-- * @{
-- */
--
--/**
-- * @addtogroup base_kbase_api
-- * @{
-- */
--
--/**
-- * @addtogroup kbase_js
-- * @{
-- */
--
- /**
- * Retain all attributes of a context
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
- *
- * This occurs on scheduling in the context on the runpool (but after
- * is_scheduled is set)
-@@ -60,6 +43,8 @@ void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kb
-
- /**
- * Release all attributes of a context
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
- *
- * This occurs on scheduling out the context from the runpool (but before
- * is_scheduled is cleared)
-@@ -79,6 +64,9 @@ bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct k
-
- /**
- * Retain all attributes of an atom
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
-+ * @katom: Atom
- *
- * This occurs on adding an atom to a context
- *
-@@ -90,6 +78,9 @@ void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase
-
- /**
- * Release all attributes of an atom, given its retained state.
-+ * @kbdev: KBase device
-+ * @kctx: KBase context
-+ * @katom_retained_state: Retained state
- *
- * This occurs after (permanently) removing an atom from a context
- *
-@@ -107,7 +98,7 @@ void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase
- */
- bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, struct kbasep_js_atom_retained_state *katom_retained_state);
-
--/**
-+/*
- * Requires:
- * - runpool_irq spinlock
- */
-@@ -122,7 +113,7 @@ static inline s8 kbasep_js_ctx_attr_count_on_runpool(struct kbase_device *kbdev,
- return js_devdata->runpool_irq.ctx_attr_ref_count[attribute];
- }
-
--/**
-+/*
- * Requires:
- * - runpool_irq spinlock
- */
-@@ -132,7 +123,7 @@ static inline bool kbasep_js_ctx_attr_is_attr_on_runpool(struct kbase_device *kb
- return (bool) kbasep_js_ctx_attr_count_on_runpool(kbdev, attribute);
- }
-
--/**
-+/*
- * Requires:
- * - jsctx mutex
- */
-@@ -148,8 +139,4 @@ static inline bool kbasep_js_ctx_attr_is_attr_on_ctx(struct kbase_context *kctx,
- return (bool) (js_kctx_info->ctx.ctx_attr_ref_count[attribute]);
- }
-
-- /** @} *//* end group kbase_js */
-- /** @} *//* end group base_kbase_api */
-- /** @} *//* end group base_api */
--
- #endif /* _KBASE_JS_DEFS_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_kinstr_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_kinstr_jm.c
-new file mode 100644
-index 0000000..1b23b41
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_kinstr_jm.c
-@@ -0,0 +1,894 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * mali_kbase_kinstr_jm.c
-+ * Kernel driver public interface to job manager atom tracing
-+ */
-+
-+#include "mali_kbase_kinstr_jm.h"
-+#include <uapi/gpu/arm/midgard/mali_kbase_kinstr_jm_reader.h>
-+
-+#include "mali_kbase.h"
-+#include "mali_kbase_linux.h"
-+
-+#include <backend/gpu/mali_kbase_jm_rb.h>
-+
-+#include <asm/barrier.h>
-+#include <linux/anon_inodes.h>
-+#include <linux/circ_buf.h>
-+#include <linux/fs.h>
-+#include <linux/kref.h>
-+#include <linux/ktime.h>
-+#include <linux/log2.h>
-+#include <linux/mutex.h>
-+#include <linux/rculist_bl.h>
-+#include <linux/poll.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/version.h>
-+#include <linux/wait.h>
-+
-+#if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE
-+#include <linux/build_bug.h>
-+#else
-+// Stringify the expression if no message is given.
-+#define static_assert(e, ...) __static_assert(e, #__VA_ARGS__, #e)
-+#define __static_assert(e, msg, ...) _Static_assert(e, msg)
-+#endif
-+
-+#if KERNEL_VERSION(4, 16, 0) >= LINUX_VERSION_CODE
-+typedef unsigned int __poll_t;
-+#endif
-+
-+#ifndef ENOTSUP
-+#define ENOTSUP EOPNOTSUPP
-+#endif
-+
-+/* The module printing prefix */
-+#define PR_ "mali_kbase_kinstr_jm: "
-+
-+/* Allows us to perform ASM goto for the tracing
-+ * https://www.kernel.org/doc/Documentation/static-keys.txt
-+ */
-+DEFINE_STATIC_KEY_FALSE(basep_kinstr_jm_reader_static_key);
-+
-+#define KBASE_KINSTR_JM_VERSION 2
-+
-+/**
-+ * struct kbase_kinstr_jm - The context for the kernel job manager atom tracing
-+ * @readers: a bitlocked list of opened readers. Readers are attached to the
-+ * private data of a file descriptor that the user opens with the
-+ * KBASE_IOCTL_KINSTR_JM_FD IO control call.
-+ * @refcount: reference count for the context. Any reader will have a link
-+ * back to the context so that they can remove themselves from the
-+ * list.
-+ *
-+ * This is opaque outside this compilation unit
-+ */
-+struct kbase_kinstr_jm {
-+ struct hlist_bl_head readers;
-+ struct kref refcount;
-+};
-+
-+/**
-+ * struct kbase_kinstr_jm_atom_state_change - Represents an atom changing to a
-+ * new state
-+ * @timestamp: Raw monotonic nanoseconds of the state change
-+ * @state: The state that the atom has moved to
-+ * @atom: The atom number that has changed state
-+ * @flags: Flags associated with the state change. See
-+ * KBASE_KINSTR_JM_ATOM_STATE_FLAG_* defines.
-+ * @reserved: Reserved for future use.
-+ * @data: Extra data for the state change. Active member depends on state.
-+ * @data.start: Extra data for the state change. Active member depends on
-+ * state.
-+ * @data.start.slot: Extra data for the state change. Active member depends on
-+ * state.
-+ * @data.padding: Padding
-+ *
-+ * We can add new fields to the structure and old user code will gracefully
-+ * ignore the new fields.
-+ *
-+ * We can change the size of the structure and old user code will gracefully
-+ * skip over the new size via `struct kbase_kinstr_jm_fd_out->size`.
-+ *
-+ * If we remove fields, the version field in `struct
-+ * kbase_kinstr_jm_fd_out->version` will be incremented and old user code will
-+ * gracefully fail and tell the user that the kernel API is too new and has
-+ * backwards-incompatible changes. Note that one userspace can opt to handle
-+ * multiple kernel major versions of the structure.
-+ *
-+ * If we need to change the _meaning_ of one of the fields, i.e. the state
-+ * machine has had a incompatible change, we can keep the same members in the
-+ * structure and update the version as above. User code will no longer
-+ * recognise that it has the supported field and can gracefully explain to the
-+ * user that the kernel API is no longer supported.
-+ *
-+ * When making changes to this structure, make sure they are either:
-+ * - additions to the end (for minor version bumps (i.e. only a size increase))
-+ * such that the layout of existing fields doesn't change, or;
-+ * - update the version reported to userspace so that it can fail explicitly.
-+ */
-+struct kbase_kinstr_jm_atom_state_change {
-+ u64 timestamp;
-+ s8 state; /* enum kbase_kinstr_jm_reader_atom_state */
-+ u8 atom;
-+ u8 flags;
-+ u8 reserved[1];
-+ /* Tagged union based on state. Ensure members are aligned correctly! */
-+ union {
-+ struct {
-+ u8 slot;
-+ } start;
-+ u8 padding[4];
-+ } data;
-+};
-+static_assert(
-+ ((1 << 8 * sizeof(((struct kbase_kinstr_jm_atom_state_change *)0)->state)) - 1) >=
-+ KBASE_KINSTR_JM_READER_ATOM_STATE_COUNT);
-+
-+#define KBASE_KINSTR_JM_ATOM_STATE_FLAG_OVERFLOW BIT(0)
-+
-+/**
-+ * struct reader_changes - The circular buffer of kernel atom state changes
-+ * @data: The allocated buffer. This is allocated when the user requests
-+ * the reader file descriptor. It is released when the user calls
-+ * close() on the fd. When accessing this, lock the producer spin
-+ * lock to prevent races on the allocated memory. The consume lock
-+ * does not need to be held because newly-inserted data will always
-+ * be outside the currenly-read range.
-+ * @producer: The producing spinlock which allows us to push changes into the
-+ * buffer at the same time as a user read occurring. This needs to
-+ * be locked when saving/restoring the IRQ because we can receive an
-+ * interrupt from the GPU when an atom completes. The CPU could have
-+ * a task preempted that is holding this lock.
-+ * @consumer: The consuming mutex which locks around the user read().
-+ * Must be held when updating the tail of the circular buffer.
-+ * @head: The head of the circular buffer. Can be used with Linux @c CIRC_
-+ * helpers. The producer should lock and update this with an SMP
-+ * store when a new change lands. The consumer can read with an
-+ * SMP load. This allows the producer to safely insert new changes
-+ * into the circular buffer.
-+ * @tail: The tail of the circular buffer. Can be used with Linux @c CIRC_
-+ * helpers. The producer should do a READ_ONCE load and the consumer
-+ * should SMP store.
-+ * @size: The number of changes that are allowed in @c data. Can be used
-+ * with Linux @c CIRC_ helpers. Will always be a power of two. The
-+ * producer lock should be held when updating this and stored with
-+ * an SMP release memory barrier. This means that the consumer can
-+ * do an SMP load.
-+ * @threshold: The number of changes above which threads polling on the reader
-+ * file descriptor will be woken up.
-+ */
-+struct reader_changes {
-+ struct kbase_kinstr_jm_atom_state_change *data;
-+ spinlock_t producer;
-+ struct mutex consumer;
-+ u32 head;
-+ u32 tail;
-+ u32 size;
-+ u32 threshold;
-+};
-+
-+/**
-+ * reader_changes_is_valid_size() - Determines if requested changes buffer size
-+ * is valid.
-+ * @size: The requested memory size
-+ *
-+ * We have a constraint that the underlying physical buffer must be a
-+ * power of two so that we can use the efficient circular buffer helpers that
-+ * the kernel provides. It also needs to be representable within a u32.
-+ *
-+ * Return:
-+ * * true - the size is valid
-+ * * false - the size is invalid
-+ */
-+static inline bool reader_changes_is_valid_size(const size_t size)
-+{
-+ typedef struct reader_changes changes_t;
-+ const size_t elem_size = sizeof(*((changes_t *)0)->data);
-+ const size_t size_size = sizeof(((changes_t *)0)->size);
-+ const size_t size_max = (1ull << (size_size * 8)) - 1;
-+
-+ return is_power_of_2(size) && /* Is a power of two */
-+ ((size / elem_size) <= size_max); /* Small enough */
-+}
-+
-+/**
-+ * reader_changes_init() - Initializes the reader changes and allocates the
-+ * changes buffer
-+ * @changes: The context pointer, must point to a zero-inited allocated reader
-+ * changes structure. We may support allocating the structure in the
-+ * future.
-+ * @size: The requested changes buffer size
-+ *
-+ * Return:
-+ * (0, U16_MAX] - the number of data elements allocated
-+ * -EINVAL - a pointer was invalid
-+ * -ENOTSUP - we do not support allocation of the context
-+ * -ERANGE - the requested memory size was invalid
-+ * -ENOMEM - could not allocate the memory
-+ * -EADDRINUSE - the buffer memory was already allocated
-+ */
-+static int reader_changes_init(struct reader_changes *const changes,
-+ const size_t size)
-+{
-+ BUILD_BUG_ON((PAGE_SIZE % sizeof(*changes->data)) != 0);
-+
-+ if (!reader_changes_is_valid_size(size)) {
-+ pr_warn(PR_ "invalid size %zu\n", size);
-+ return -ERANGE;
-+ }
-+
-+ changes->data = vmalloc(size);
-+ if (!changes->data)
-+ return -ENOMEM;
-+
-+ spin_lock_init(&changes->producer);
-+ mutex_init(&changes->consumer);
-+
-+ changes->size = size / sizeof(*changes->data);
-+ changes->threshold = min(((size_t)(changes->size)) / 4,
-+ ((size_t)(PAGE_SIZE)) / sizeof(*changes->data));
-+
-+ return changes->size;
-+}
-+
-+/**
-+ * reader_changes_term() - Cleans up a reader changes structure
-+ * @changes: The context to clean up
-+ *
-+ * Releases the allocated state changes memory
-+ */
-+static void reader_changes_term(struct reader_changes *const changes)
-+{
-+ struct kbase_kinstr_jm_atom_state_change *data = NULL;
-+ unsigned long irq;
-+
-+ /*
-+ * Although changes->data is used on the consumer side, too, no active
-+ * consumer is possible by the time we clean up the reader changes, so
-+ * no need to take the consumer lock. However, we do need the producer
-+ * lock because the list removal can race with list traversal.
-+ */
-+ spin_lock_irqsave(&changes->producer, irq);
-+ swap(changes->data, data);
-+ spin_unlock_irqrestore(&changes->producer, irq);
-+
-+ mutex_destroy(&changes->consumer);
-+ vfree(data);
-+}
-+
-+/**
-+ * reader_changes_count_locked() - Retrieves the count of state changes from the
-+ * tail to the physical end of the buffer
-+ * @changes: The state changes context
-+ *
-+ * The consumer mutex must be held. Uses the CIRC_CNT_TO_END macro to
-+ * determine the count, so there may be more items. However, that's the maximum
-+ * number that can be read in one contiguous read.
-+ *
-+ * Return: the number of changes in the circular buffer until the end of the
-+ * allocation
-+ */
-+static u32 reader_changes_count_locked(struct reader_changes *const changes)
-+{
-+ u32 head;
-+
-+ lockdep_assert_held_once(&changes->consumer);
-+
-+ head = smp_load_acquire(&changes->head);
-+
-+ return CIRC_CNT_TO_END(head, changes->tail, changes->size);
-+}
-+
-+/**
-+ * reader_changes_count() - Retrieves the count of state changes from the
-+ * tail to the physical end of the buffer
-+ * @changes: The state changes context
-+ *
-+ * Return: the number of changes in the circular buffer until the end of the
-+ * allocation
-+ */
-+static u32 reader_changes_count(struct reader_changes *const changes)
-+{
-+ u32 ret;
-+
-+ mutex_lock(&changes->consumer);
-+ ret = reader_changes_count_locked(changes);
-+ mutex_unlock(&changes->consumer);
-+ return ret;
-+}
-+
-+/**
-+ * reader_changes_push() - Pushes a change into the reader circular buffer.
-+ * @changes: The buffer to insert the change into
-+ * @change: Kernel atom change to insert
-+ * @wait_queue: The queue to be kicked when changes should be read from
-+ * userspace. Kicked when a threshold is reached or there is
-+ * overflow.
-+ */
-+static void reader_changes_push(
-+ struct reader_changes *const changes,
-+ const struct kbase_kinstr_jm_atom_state_change *const change,
-+ wait_queue_head_t *const wait_queue)
-+{
-+ u32 head, tail, size, space;
-+ unsigned long irq;
-+ struct kbase_kinstr_jm_atom_state_change *data;
-+
-+ spin_lock_irqsave(&changes->producer, irq);
-+
-+ /* We may be called for a reader_changes that's awaiting cleanup. */
-+ data = changes->data;
-+ if (!data)
-+ goto unlock;
-+
-+ size = changes->size;
-+ head = changes->head;
-+ tail = smp_load_acquire(&changes->tail);
-+
-+ space = CIRC_SPACE(head, tail, size);
-+ if (space >= 1) {
-+ data[head] = *change;
-+ if (space == 1) {
-+ data[head].flags |=
-+ KBASE_KINSTR_JM_ATOM_STATE_FLAG_OVERFLOW;
-+ pr_warn(PR_ "overflow of circular buffer\n");
-+ }
-+ smp_store_release(&changes->head, (head + 1) & (size - 1));
-+ }
-+
-+ /* Wake for either overflow or over-threshold cases. */
-+ if (CIRC_CNT(head + 1, tail, size) >= changes->threshold)
-+ wake_up_interruptible(wait_queue);
-+
-+unlock:
-+ spin_unlock_irqrestore(&changes->producer, irq);
-+}
-+
-+/**
-+ * struct reader - Allows the kernel state changes to be read by user space.
-+ * @node: The node in the @c readers locked list
-+ * @rcu_head: storage for the RCU callback to free this reader (see kfree_rcu)
-+ * @changes: The circular buffer of user changes
-+ * @wait_queue: A wait queue for poll
-+ * @context: a pointer to the parent context that created this reader. Can be
-+ * used to remove the reader from the list of readers. Reference
-+ * counted.
-+ *
-+ * The reader is a circular buffer in kernel space. State changes are pushed
-+ * into the buffer. The flow from user space is:
-+ *
-+ * * Request file descriptor with KBASE_IOCTL_KINSTR_JM_FD. This will
-+ * allocate the kernel side circular buffer with a size specified in the
-+ * ioctl argument.
-+ * * The user will then poll the file descriptor for data
-+ * * Upon receiving POLLIN, perform a read() on the file descriptor to get
-+ * the data out.
-+ * * The buffer memory will be freed when the file descriptor is closed
-+ */
-+struct reader {
-+ struct hlist_bl_node node;
-+ struct rcu_head rcu_head;
-+ struct reader_changes changes;
-+ wait_queue_head_t wait_queue;
-+ struct kbase_kinstr_jm *context;
-+};
-+
-+static struct kbase_kinstr_jm *
-+kbase_kinstr_jm_ref_get(struct kbase_kinstr_jm *const ctx);
-+static void kbase_kinstr_jm_ref_put(struct kbase_kinstr_jm *const ctx);
-+static int kbase_kinstr_jm_readers_add(struct kbase_kinstr_jm *const ctx,
-+ struct reader *const reader);
-+static void kbase_kinstr_jm_readers_del(struct kbase_kinstr_jm *const ctx,
-+ struct reader *const reader);
-+
-+/**
-+ * reader_term() - Terminate a instrumentation job manager reader context.
-+ * @reader: Pointer to context to be terminated.
-+ */
-+static void reader_term(struct reader *const reader)
-+{
-+ if (!reader)
-+ return;
-+
-+ kbase_kinstr_jm_readers_del(reader->context, reader);
-+ reader_changes_term(&reader->changes);
-+ kbase_kinstr_jm_ref_put(reader->context);
-+
-+ kfree_rcu(reader, rcu_head);
-+}
-+
-+/**
-+ * reader_init() - Initialise a instrumentation job manager reader context.
-+ * @out_reader: Non-NULL pointer to where the pointer to the created context
-+ * will be stored on success.
-+ * @ctx: the pointer to the parent context. Reference count will be
-+ * increased if initialization is successful
-+ * @num_changes: The number of changes to allocate a buffer for
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+static int reader_init(struct reader **const out_reader,
-+ struct kbase_kinstr_jm *const ctx,
-+ size_t const num_changes)
-+{
-+ struct reader *reader = NULL;
-+ const size_t change_size = sizeof(struct kbase_kinstr_jm_atom_state_change);
-+ int status;
-+
-+ if (!out_reader || !ctx || !num_changes)
-+ return -EINVAL;
-+
-+ reader = kzalloc(sizeof(*reader), GFP_KERNEL);
-+ if (!reader)
-+ return -ENOMEM;
-+
-+ INIT_HLIST_BL_NODE(&reader->node);
-+ init_waitqueue_head(&reader->wait_queue);
-+
-+ reader->context = kbase_kinstr_jm_ref_get(ctx);
-+
-+ status = reader_changes_init(&reader->changes, num_changes * change_size);
-+ if (status < 0)
-+ goto fail;
-+
-+ status = kbase_kinstr_jm_readers_add(ctx, reader);
-+ if (status < 0)
-+ goto fail;
-+
-+ *out_reader = reader;
-+
-+ return 0;
-+
-+fail:
-+ kbase_kinstr_jm_ref_put(reader->context);
-+ kfree(reader);
-+ return status;
-+}
-+
-+/**
-+ * reader_release() - Invoked when the reader file descriptor is released
-+ * @node: The inode that the file descriptor that the file corresponds to. In
-+ * our case our reader file descriptor is backed by an anonymous node so
-+ * not much is in this.
-+ * @file: the file data. Our reader context is held in the private data
-+ * Return: zero on success
-+ */
-+static int reader_release(struct inode *const node, struct file *const file)
-+{
-+ struct reader *const reader = file->private_data;
-+
-+ reader_term(reader);
-+ file->private_data = NULL;
-+
-+ return 0;
-+}
-+
-+/**
-+ * reader_changes_copy_to_user() - Copy any changes from a changes structure to
-+ * the user-provided buffer.
-+ * @changes: The changes structure from which to copy.
-+ * @buffer: The user buffer to copy the data to.
-+ * @buffer_size: The number of bytes in the buffer.
-+ * Return: The number of bytes copied or negative errno on failure.
-+ */
-+static ssize_t reader_changes_copy_to_user(struct reader_changes *const changes,
-+ char __user *buffer,
-+ size_t buffer_size)
-+{
-+ ssize_t ret = 0;
-+ struct kbase_kinstr_jm_atom_state_change const *src_buf = READ_ONCE(
-+ changes->data);
-+ size_t const entry_size = sizeof(*src_buf);
-+ size_t changes_tail, changes_count, read_size;
-+
-+ /* Needed for the quick buffer capacity calculation below.
-+ * Note that we can't use is_power_of_2() since old compilers don't
-+ * understand it's a constant expression.
-+ */
-+#define is_power_of_two(x) ((x) && !((x) & ((x) - 1)))
-+ static_assert(is_power_of_two(
-+ sizeof(struct kbase_kinstr_jm_atom_state_change)));
-+#undef is_power_of_two
-+
-+ lockdep_assert_held_once(&changes->consumer);
-+
-+ /* Read continuously until either:
-+ * - we've filled the output buffer, or
-+ * - there are no changes when we check.
-+ *
-+ * If more changes arrive while we're copying to the user, we can copy
-+ * those as well, space permitting.
-+ */
-+ do {
-+ changes_tail = changes->tail;
-+ changes_count = reader_changes_count_locked(changes);
-+ read_size = min(changes_count * entry_size,
-+ buffer_size & ~(entry_size - 1));
-+
-+ if (!read_size)
-+ break;
-+
-+ if (copy_to_user(buffer, &(src_buf[changes_tail]), read_size))
-+ return -EFAULT;
-+
-+ buffer += read_size;
-+ buffer_size -= read_size;
-+ ret += read_size;
-+ changes_tail = (changes_tail + read_size / entry_size) &
-+ (changes->size - 1);
-+ smp_store_release(&changes->tail, changes_tail);
-+ } while (read_size);
-+
-+ return ret;
-+}
-+
-+/**
-+ * reader_read() - Handles a read call on the reader file descriptor
-+ *
-+ * @filp: The file that the read was performed on
-+ * @buffer: The destination buffer
-+ * @buffer_size: The maximum number of bytes to read
-+ * @offset: The offset into the 'file' to read from.
-+ *
-+ * Note the destination buffer needs to be fully mapped in userspace or the read
-+ * will fault.
-+ *
-+ * Return:
-+ * * The number of bytes read or:
-+ * * -EBADF - the file descriptor did not have an attached reader
-+ * * -EFAULT - memory access fault
-+ * * -EAGAIN - if the file is set to nonblocking reads with O_NONBLOCK and there
-+ * is no data available
-+ *
-+ * Note: The number of bytes read will always be a multiple of the size of an
-+ * entry.
-+ */
-+static ssize_t reader_read(struct file *const filp,
-+ char __user *const buffer,
-+ size_t const buffer_size,
-+ loff_t *const offset)
-+{
-+ struct reader *const reader = filp->private_data;
-+ struct reader_changes *changes;
-+ ssize_t ret;
-+
-+ if (!reader)
-+ return -EBADF;
-+
-+ if (buffer_size < sizeof(struct kbase_kinstr_jm_atom_state_change))
-+ return -ENOBUFS;
-+
-+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE
-+ if (!access_ok(buffer, buffer_size))
-+ return -EIO;
-+#else
-+ if (!access_ok(VERIFY_WRITE, buffer, buffer_size))
-+ return -EIO;
-+#endif
-+
-+ changes = &reader->changes;
-+
-+ mutex_lock(&changes->consumer);
-+ if (!reader_changes_count_locked(changes)) {
-+ if (filp->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ goto exit;
-+ }
-+
-+ if (wait_event_interruptible(
-+ reader->wait_queue,
-+ !!reader_changes_count_locked(changes))) {
-+ ret = -EINTR;
-+ goto exit;
-+ }
-+ }
-+
-+ ret = reader_changes_copy_to_user(changes, buffer, buffer_size);
-+
-+exit:
-+ mutex_unlock(&changes->consumer);
-+ return ret;
-+}
-+
-+/**
-+ * reader_poll() - Handles a poll call on the reader file descriptor
-+ * @file: The file that the poll was performed on
-+ * @wait: The poll table
-+ *
-+ * The results of the poll will be unreliable if there is no mapped memory as
-+ * there is no circular buffer to push atom state changes into.
-+ *
-+ * Return:
-+ * * 0 - no data ready
-+ * * POLLIN - state changes have been buffered
-+ * * -EBADF - the file descriptor did not have an attached reader
-+ * * -EINVAL - the IO control arguments were invalid
-+ */
-+static __poll_t reader_poll(struct file *const file,
-+ struct poll_table_struct *const wait)
-+{
-+ struct reader *reader;
-+ struct reader_changes *changes;
-+
-+ if (unlikely(!file || !wait))
-+ return -EINVAL;
-+
-+ reader = file->private_data;
-+ if (unlikely(!reader))
-+ return -EBADF;
-+
-+ changes = &reader->changes;
-+
-+ if (reader_changes_count(changes) >= changes->threshold)
-+ return POLLIN;
-+
-+ poll_wait(file, &reader->wait_queue, wait);
-+
-+ return (reader_changes_count(changes) > 0) ? POLLIN : 0;
-+}
-+
-+/* The file operations virtual function table */
-+static const struct file_operations file_operations = {
-+ .owner = THIS_MODULE,
-+ .llseek = no_llseek,
-+ .read = reader_read,
-+ .poll = reader_poll,
-+ .release = reader_release
-+};
-+
-+/* The maximum amount of readers that can be created on a context. */
-+static const size_t kbase_kinstr_jm_readers_max = 16;
-+
-+/**
-+ * kbasep_kinstr_jm_release() - Invoked when the reference count is dropped
-+ * @ref: the context reference count
-+ */
-+static void kbase_kinstr_jm_release(struct kref *const ref)
-+{
-+ struct kbase_kinstr_jm *const ctx =
-+ container_of(ref, struct kbase_kinstr_jm, refcount);
-+
-+ kfree(ctx);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_ref_get() - Reference counts the instrumentation context
-+ * @ctx: the context to reference count
-+ * Return: the reference counted context
-+ */
-+static struct kbase_kinstr_jm *
-+kbase_kinstr_jm_ref_get(struct kbase_kinstr_jm *const ctx)
-+{
-+ if (likely(ctx))
-+ kref_get(&ctx->refcount);
-+ return ctx;
-+}
-+
-+/**
-+ * kbase_kinstr_jm_ref_put() - Dereferences the instrumentation context
-+ * @ctx: the context to lower the reference count on
-+ */
-+static void kbase_kinstr_jm_ref_put(struct kbase_kinstr_jm *const ctx)
-+{
-+ if (likely(ctx))
-+ kref_put(&ctx->refcount, kbase_kinstr_jm_release);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_readers_add() - Adds a reader to the list of readers
-+ * @ctx: the instrumentation context
-+ * @reader: the reader to add
-+ *
-+ * Return:
-+ * 0 - success
-+ * -ENOMEM - too many readers already added.
-+ */
-+static int kbase_kinstr_jm_readers_add(struct kbase_kinstr_jm *const ctx,
-+ struct reader *const reader)
-+{
-+ struct hlist_bl_head *const readers = &ctx->readers;
-+ struct hlist_bl_node *node;
-+ struct reader *temp;
-+ size_t count = 0;
-+
-+ hlist_bl_lock(readers);
-+
-+ hlist_bl_for_each_entry_rcu(temp, node, readers, node)
-+ ++count;
-+
-+ if (kbase_kinstr_jm_readers_max < count) {
-+ hlist_bl_unlock(readers);
-+ return -ENOMEM;
-+ }
-+
-+ hlist_bl_add_head_rcu(&reader->node, readers);
-+
-+ hlist_bl_unlock(readers);
-+
-+ static_branch_inc(&basep_kinstr_jm_reader_static_key);
-+
-+ return 0;
-+}
-+
-+/**
-+ * readers_del() - Deletes a reader from the list of readers
-+ * @ctx: the instrumentation context
-+ * @reader: the reader to delete
-+ */
-+static void kbase_kinstr_jm_readers_del(struct kbase_kinstr_jm *const ctx,
-+ struct reader *const reader)
-+{
-+ struct hlist_bl_head *const readers = &ctx->readers;
-+
-+ hlist_bl_lock(readers);
-+ hlist_bl_del_rcu(&reader->node);
-+ hlist_bl_unlock(readers);
-+
-+ static_branch_dec(&basep_kinstr_jm_reader_static_key);
-+}
-+
-+int kbase_kinstr_jm_get_fd(struct kbase_kinstr_jm *const ctx,
-+ union kbase_kinstr_jm_fd *jm_fd_arg)
-+{
-+ struct kbase_kinstr_jm_fd_in const *in;
-+ struct reader *reader;
-+ size_t const change_size = sizeof(struct
-+ kbase_kinstr_jm_atom_state_change);
-+ int status;
-+ int fd;
-+ int i;
-+
-+ if (!ctx || !jm_fd_arg)
-+ return -EINVAL;
-+
-+ in = &jm_fd_arg->in;
-+
-+ if (!is_power_of_2(in->count))
-+ return -EINVAL;
-+
-+ for (i = 0; i < sizeof(in->padding); ++i)
-+ if (in->padding[i])
-+ return -EINVAL;
-+
-+ status = reader_init(&reader, ctx, in->count);
-+ if (status < 0)
-+ return status;
-+
-+ jm_fd_arg->out.version = KBASE_KINSTR_JM_VERSION;
-+ jm_fd_arg->out.size = change_size;
-+ memset(&jm_fd_arg->out.padding, 0, sizeof(jm_fd_arg->out.padding));
-+
-+ fd = anon_inode_getfd("[mali_kinstr_jm]", &file_operations, reader,
-+ O_CLOEXEC);
-+ if (fd < 0)
-+ reader_term(reader);
-+
-+ return fd;
-+}
-+
-+int kbase_kinstr_jm_init(struct kbase_kinstr_jm **const out_ctx)
-+{
-+ struct kbase_kinstr_jm *ctx = NULL;
-+
-+ if (!out_ctx)
-+ return -EINVAL;
-+
-+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-+ if (!ctx)
-+ return -ENOMEM;
-+
-+ INIT_HLIST_BL_HEAD(&ctx->readers);
-+ kref_init(&ctx->refcount);
-+
-+ *out_ctx = ctx;
-+
-+ return 0;
-+}
-+
-+void kbase_kinstr_jm_term(struct kbase_kinstr_jm *const ctx)
-+{
-+ kbase_kinstr_jm_ref_put(ctx);
-+}
-+
-+void kbasep_kinstr_jm_atom_state(
-+ struct kbase_jd_atom *const katom,
-+ const enum kbase_kinstr_jm_reader_atom_state state)
-+{
-+ struct kbase_context *const kctx = katom->kctx;
-+ struct kbase_kinstr_jm *const ctx = kctx->kinstr_jm;
-+ const u8 id = kbase_jd_atom_id(kctx, katom);
-+ struct kbase_kinstr_jm_atom_state_change change = {
-+ .timestamp = ktime_get_raw_ns(), .atom = id, .state = state
-+ };
-+ struct reader *reader;
-+ struct hlist_bl_node *node;
-+
-+ WARN(KBASE_KINSTR_JM_READER_ATOM_STATE_COUNT < state || 0 > state,
-+ PR_ "unsupported katom (%u) state (%i)", id, state);
-+
-+ switch (state) {
-+ case KBASE_KINSTR_JM_READER_ATOM_STATE_START:
-+ change.data.start.slot = katom->slot_nr;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ rcu_read_lock();
-+ hlist_bl_for_each_entry_rcu(reader, node, &ctx->readers, node)
-+ reader_changes_push(
-+ &reader->changes, &change, &reader->wait_queue);
-+ rcu_read_unlock();
-+}
-+
-+KBASE_EXPORT_TEST_API(kbasep_kinstr_jm_atom_state);
-+
-+void kbasep_kinstr_jm_atom_hw_submit(struct kbase_jd_atom *const katom)
-+{
-+ struct kbase_context *const kctx = katom->kctx;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ const int slot = katom->slot_nr;
-+ struct kbase_jd_atom *const submitted = kbase_gpu_inspect(kbdev, slot, 0);
-+
-+ BUILD_BUG_ON(SLOT_RB_SIZE != 2);
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ if (WARN_ON(slot < 0 || slot >= GPU_MAX_JOB_SLOTS))
-+ return;
-+ if (WARN_ON(!submitted))
-+ return;
-+
-+ if (submitted == katom)
-+ kbase_kinstr_jm_atom_state_start(katom);
-+}
-+
-+void kbasep_kinstr_jm_atom_hw_release(struct kbase_jd_atom *const katom)
-+{
-+ struct kbase_context *const kctx = katom->kctx;
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ const int slot = katom->slot_nr;
-+ struct kbase_jd_atom *const submitted = kbase_gpu_inspect(kbdev, slot, 0);
-+ struct kbase_jd_atom *const queued = kbase_gpu_inspect(kbdev, slot, 1);
-+
-+ BUILD_BUG_ON(SLOT_RB_SIZE != 2);
-+
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ if (WARN_ON(slot < 0 || slot >= GPU_MAX_JOB_SLOTS))
-+ return;
-+ if (WARN_ON(!submitted))
-+ return;
-+ if (WARN_ON((submitted != katom) && (queued != katom)))
-+ return;
-+
-+ if (queued == katom)
-+ return;
-+
-+ if (katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED)
-+ kbase_kinstr_jm_atom_state_stop(katom);
-+ if (queued && queued->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED)
-+ kbase_kinstr_jm_atom_state_start(queued);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_kinstr_jm.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_kinstr_jm.h
-new file mode 100644
-index 0000000..2c904e5
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_kinstr_jm.h
-@@ -0,0 +1,275 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * mali_kbase_kinstr_jm.h
-+ * Kernel driver public interface to job manager atom tracing. This API provides
-+ * a method to get the atom state changes into user space.
-+ *
-+ * The flow of operation is:
-+ *
-+ * | kernel | user |
-+ * | ----------------------------------- | ----------------------------------- |
-+ * | Initialize API with | |
-+ * | kbase_kinstr_jm_init() | |
-+ * | | |
-+ * | Kernel code injects states with | |
-+ * | kbase_kinstr_jm_atom_state_*() APIs | |
-+ * | | Call ioctl() to get file descriptor |
-+ * | | via KBASE_IOCTL_KINSTR_JM_FD |
-+ * | Allocates a reader attached to FD | |
-+ * | Allocates circular buffer and | |
-+ * | patches, via ASM goto, the | |
-+ * | kbase_kinstr_jm_atom_state_*() | |
-+ * | | loop: |
-+ * | | Call poll() on FD for POLLIN |
-+ * | When threshold of changes is hit, | |
-+ * | the poll is interrupted with | |
-+ * | POLLIN. If circular buffer is | |
-+ * | full then store the missed count | |
-+ * | and interrupt poll | Call read() to get data from |
-+ * | | circular buffer via the fd |
-+ * | Kernel advances tail of circular | |
-+ * | buffer | |
-+ * | | Close file descriptor |
-+ * | Deallocates circular buffer | |
-+ * | | |
-+ * | Terminate API with | |
-+ * | kbase_kinstr_jm_term() | |
-+ *
-+ * All tracepoints are guarded on a static key. The static key is activated when
-+ * a user space reader gets created. This means that there is negligible cost
-+ * inserting the tracepoints into code when there are no readers.
-+ */
-+
-+#ifndef _KBASE_KINSTR_JM_H_
-+#define _KBASE_KINSTR_JM_H_
-+
-+#include <uapi/gpu/arm/midgard/mali_kbase_kinstr_jm_reader.h>
-+
-+#ifdef __KERNEL__
-+#include <linux/version.h>
-+#include <linux/static_key.h>
-+#else
-+/* empty wrapper macros for userspace */
-+#define static_branch_unlikely(key) (1)
-+#define KERNEL_VERSION(a, b, c) (0)
-+#define LINUX_VERSION_CODE (1)
-+#endif /* __KERNEL__ */
-+
-+/* Forward declarations */
-+struct kbase_context;
-+struct kbase_kinstr_jm;
-+struct kbase_jd_atom;
-+union kbase_kinstr_jm_fd;
-+
-+/**
-+ * kbase_kinstr_jm_init() - Initialise an instrumentation job manager context.
-+ * @ctx: Non-NULL pointer to where the pointer to the created context will
-+ * be stored on success.
-+ *
-+ * Return: 0 on success, else error code.
-+ */
-+int kbase_kinstr_jm_init(struct kbase_kinstr_jm **ctx);
-+
-+/**
-+ * kbase_kinstr_jm_term() - Terminate an instrumentation job manager context.
-+ * @ctx: Pointer to context to be terminated.
-+ */
-+void kbase_kinstr_jm_term(struct kbase_kinstr_jm *ctx);
-+
-+/**
-+ * kbase_kinstr_jm_get_fd() - Retrieves a file descriptor that can be used to
-+ * read the atom state changes from userspace
-+ *
-+ * @ctx: Pointer to the initialized context
-+ * @jm_fd_arg: Pointer to the union containing the in/out params
-+ * Return: -1 on failure, valid file descriptor on success
-+ */
-+int kbase_kinstr_jm_get_fd(struct kbase_kinstr_jm *const ctx,
-+ union kbase_kinstr_jm_fd *jm_fd_arg);
-+
-+/**
-+ * kbasep_kinstr_jm_atom_state() - Signifies that an atom has changed state
-+ * @atom: The atom that has changed state
-+ * @state: The new state of the atom
-+ *
-+ * This performs the actual storage of the state ready for user space to
-+ * read the data. It is only called when the static key is enabled from
-+ * kbase_kinstr_jm_atom_state(). There is almost never a need to invoke this
-+ * function directly.
-+ */
-+void kbasep_kinstr_jm_atom_state(
-+ struct kbase_jd_atom *const atom,
-+ const enum kbase_kinstr_jm_reader_atom_state state);
-+
-+/* Allows ASM goto patching to reduce tracing overhead. This is
-+ * incremented/decremented when readers are created and terminated. This really
-+ * shouldn't be changed externally, but if you do, make sure you use
-+ * a static_key_inc()/static_key_dec() pair.
-+ */
-+extern struct static_key_false basep_kinstr_jm_reader_static_key;
-+
-+/**
-+ * kbase_kinstr_jm_atom_state() - Signifies that an atom has changed state
-+ * @atom: The atom that has changed state
-+ * @state: The new state of the atom
-+ *
-+ * This uses a static key to reduce overhead when tracing is disabled
-+ */
-+static inline void kbase_kinstr_jm_atom_state(
-+ struct kbase_jd_atom *const atom,
-+ const enum kbase_kinstr_jm_reader_atom_state state)
-+{
-+ if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key))
-+ kbasep_kinstr_jm_atom_state(atom, state);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_atom_state_queue() - Signifies that an atom has entered a
-+ * hardware or software queue.
-+ * @atom: The atom that has changed state
-+ */
-+static inline void kbase_kinstr_jm_atom_state_queue(
-+ struct kbase_jd_atom *const atom)
-+{
-+ kbase_kinstr_jm_atom_state(
-+ atom, KBASE_KINSTR_JM_READER_ATOM_STATE_QUEUE);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_atom_state_start() - Signifies that work has started on an
-+ * atom
-+ * @atom: The atom that has changed state
-+ */
-+static inline void kbase_kinstr_jm_atom_state_start(
-+ struct kbase_jd_atom *const atom)
-+{
-+ kbase_kinstr_jm_atom_state(
-+ atom, KBASE_KINSTR_JM_READER_ATOM_STATE_START);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_atom_state_stop() - Signifies that work has stopped on an
-+ * atom
-+ * @atom: The atom that has changed state
-+ */
-+static inline void kbase_kinstr_jm_atom_state_stop(
-+ struct kbase_jd_atom *const atom)
-+{
-+ kbase_kinstr_jm_atom_state(
-+ atom, KBASE_KINSTR_JM_READER_ATOM_STATE_STOP);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_atom_state_complete() - Signifies that all work has completed
-+ * on an atom
-+ * @atom: The atom that has changed state
-+ */
-+static inline void kbase_kinstr_jm_atom_state_complete(
-+ struct kbase_jd_atom *const atom)
-+{
-+ kbase_kinstr_jm_atom_state(
-+ atom, KBASE_KINSTR_JM_READER_ATOM_STATE_COMPLETE);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_atom_queue() - A software *or* hardware atom is queued for
-+ * execution
-+ * @atom: The atom that has changed state
-+ */
-+static inline void kbase_kinstr_jm_atom_queue(struct kbase_jd_atom *const atom)
-+{
-+ kbase_kinstr_jm_atom_state_queue(atom);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_atom_complete() - A software *or* hardware atom is fully
-+ * completed
-+ * @atom: The atom that has changed state
-+ */
-+static inline void kbase_kinstr_jm_atom_complete(
-+ struct kbase_jd_atom *const atom)
-+{
-+ kbase_kinstr_jm_atom_state_complete(atom);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_atom_sw_start() - A software atom has started work
-+ * @atom: The atom that has changed state
-+ */
-+static inline void kbase_kinstr_jm_atom_sw_start(
-+ struct kbase_jd_atom *const atom)
-+{
-+ kbase_kinstr_jm_atom_state_start(atom);
-+}
-+
-+/**
-+ * kbase_kinstr_jm_atom_sw_stop() - A software atom has stopped work
-+ * @atom: The atom that has changed state
-+ */
-+static inline void kbase_kinstr_jm_atom_sw_stop(
-+ struct kbase_jd_atom *const atom)
-+{
-+ kbase_kinstr_jm_atom_state_stop(atom);
-+}
-+
-+/**
-+ * kbasep_kinstr_jm_atom_hw_submit() - A hardware atom has been submitted
-+ * @atom: The atom that has been submitted
-+ *
-+ * This private implementation should not be called directly, it is protected
-+ * by a static key in kbase_kinstr_jm_atom_hw_submit(). Use that instead.
-+ */
-+void kbasep_kinstr_jm_atom_hw_submit(struct kbase_jd_atom *const atom);
-+
-+/**
-+ * kbase_kinstr_jm_atom_hw_submit() - A hardware atom has been submitted
-+ * @atom: The atom that has been submitted
-+ */
-+static inline void kbase_kinstr_jm_atom_hw_submit(
-+ struct kbase_jd_atom *const atom)
-+{
-+ if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key))
-+ kbasep_kinstr_jm_atom_hw_submit(atom);
-+}
-+
-+/**
-+ * kbasep_kinstr_jm_atom_hw_release() - A hardware atom has been released
-+ * @atom: The atom that has been released
-+ *
-+ * This private implementation should not be called directly, it is protected
-+ * by a static key in kbase_kinstr_jm_atom_hw_release(). Use that instead.
-+ */
-+void kbasep_kinstr_jm_atom_hw_release(struct kbase_jd_atom *const atom);
-+
-+/**
-+ * kbase_kinstr_jm_atom_hw_release() - A hardware atom has been released
-+ * @atom: The atom that has been released
-+ */
-+static inline void kbase_kinstr_jm_atom_hw_release(
-+ struct kbase_jd_atom *const atom)
-+{
-+ if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key))
-+ kbasep_kinstr_jm_atom_hw_release(atom);
-+}
-+
-+#endif /* _KBASE_KINSTR_JM_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_linux.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_linux.h
-index 003ac9e..1d8d196 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_linux.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_linux.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2014, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_linux.h
-- * Base kernel APIs, Linux implementation.
-+ * DOC: Base kernel APIs, Linux implementation.
- */
-
- #ifndef _KBASE_LINUX_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.c
-index 4a1004b..a68e4ea 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-@@ -29,7 +28,7 @@
- #include <linux/compat.h>
- #include <linux/version.h>
- #include <linux/log2.h>
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- #include <linux/of_platform.h>
- #endif
-
-@@ -43,6 +42,7 @@
- #include <mali_kbase_mem_pool_group.h>
- #include <mmu/mali_kbase_mmu.h>
- #include <mali_kbase_config_defaults.h>
-+#include <mali_kbase_trace_gpu_mem.h>
-
- /*
- * Alignment of objects allocated by the GPU inside a just-in-time memory
-@@ -89,7 +89,7 @@ static size_t kbase_get_num_cpu_va_bits(struct kbase_context *kctx)
- #error "Unknown CPU VA width for this architecture"
- #endif
-
--#ifdef CONFIG_64BIT
-+#if IS_ENABLED(CONFIG_64BIT)
- if (kbase_ctx_flag(kctx, KCTX_COMPAT))
- cpu_va_bits = 32;
- #endif
-@@ -98,27 +98,34 @@ static size_t kbase_get_num_cpu_va_bits(struct kbase_context *kctx)
- }
-
- /* This function finds out which RB tree the given pfn from the GPU VA belongs
-- * to based on the memory zone the pfn refers to */
-+ * to based on the memory zone the pfn refers to
-+ */
- static struct rb_root *kbase_gpu_va_to_rbtree(struct kbase_context *kctx,
- u64 gpu_pfn)
- {
- struct rb_root *rbtree = NULL;
-+ struct kbase_reg_zone *exec_va_zone =
-+ kbase_ctx_reg_zone_get(kctx, KBASE_REG_ZONE_EXEC_VA);
-
- /* The gpu_pfn can only be greater than the starting pfn of the EXEC_VA
- * zone if this has been initialized.
- */
-- if (gpu_pfn >= kctx->exec_va_start)
-+ if (gpu_pfn >= exec_va_zone->base_pfn)
- rbtree = &kctx->reg_rbtree_exec;
- else {
- u64 same_va_end;
-
--#ifdef CONFIG_64BIT
-- if (kbase_ctx_flag(kctx, KCTX_COMPAT))
-+#if IS_ENABLED(CONFIG_64BIT)
-+ if (kbase_ctx_flag(kctx, KCTX_COMPAT)) {
- #endif /* CONFIG_64BIT */
- same_va_end = KBASE_REG_ZONE_CUSTOM_VA_BASE;
--#ifdef CONFIG_64BIT
-- else
-- same_va_end = kctx->same_va_end;
-+#if IS_ENABLED(CONFIG_64BIT)
-+ } else {
-+ struct kbase_reg_zone *same_va_zone =
-+ kbase_ctx_reg_zone_get(kctx,
-+ KBASE_REG_ZONE_SAME_VA);
-+ same_va_end = kbase_reg_zone_end_pfn(same_va_zone);
-+ }
- #endif /* CONFIG_64BIT */
-
- if (gpu_pfn >= same_va_end)
-@@ -228,7 +235,7 @@ struct kbase_va_region *kbase_region_tracker_find_region_enclosing_address(
- u64 gpu_pfn = gpu_addr >> PAGE_SHIFT;
- struct rb_root *rbtree = NULL;
-
-- KBASE_DEBUG_ASSERT(NULL != kctx);
-+ KBASE_DEBUG_ASSERT(kctx != NULL);
-
- lockdep_assert_held(&kctx->reg_lock);
-
-@@ -288,7 +295,8 @@ static struct kbase_va_region *kbase_region_tracker_find_region_meeting_reqs(
- struct rb_root *rbtree = NULL;
-
- /* Note that this search is a linear search, as we do not have a target
-- address in mind, so does not benefit from the rbtree search */
-+ * address in mind, so does not benefit from the rbtree search
-+ */
- rbtree = reg_reqs->rbtree;
-
- for (rbnode = rb_first(rbtree); rbnode; rbnode = rb_next(rbnode)) {
-@@ -303,7 +311,8 @@ static struct kbase_va_region *kbase_region_tracker_find_region_meeting_reqs(
- * (start_pfn + align_mask) & ~(align_mask)
- *
- * Otherwise, it aligns to n*align + offset, for the
-- * lowest value n that makes this still >start_pfn */
-+ * lowest value n that makes this still >start_pfn
-+ */
- start_pfn += align_mask;
- start_pfn -= (start_pfn - align_offset) & (align_mask);
-
-@@ -341,7 +350,8 @@ static struct kbase_va_region *kbase_region_tracker_find_region_meeting_reqs(
- }
-
- /**
-- * @brief Remove a region object from the global list.
-+ * Remove a region object from the global list.
-+ * @reg: Region object to remove
- *
- * The region reg is removed, possibly by merging with other free and
- * compatible adjacent regions. It must be called with the context
-@@ -367,8 +377,9 @@ int kbase_remove_va_region(struct kbase_va_region *reg)
- if (rbprev) {
- prev = rb_entry(rbprev, struct kbase_va_region, rblink);
- if (prev->flags & KBASE_REG_FREE) {
-- /* We're compatible with the previous VMA,
-- * merge with it */
-+ /* We're compatible with the previous VMA, merge with
-+ * it
-+ */
- WARN_ON((prev->flags & KBASE_REG_ZONE_MASK) !=
- (reg->flags & KBASE_REG_ZONE_MASK));
- prev->nr_pages += reg->nr_pages;
-@@ -511,8 +522,8 @@ int kbase_add_va_region(struct kbase_context *kctx,
- int gpu_pc_bits =
- kbdev->gpu_props.props.core_props.log2_program_counter_size;
-
-- KBASE_DEBUG_ASSERT(NULL != kctx);
-- KBASE_DEBUG_ASSERT(NULL != reg);
-+ KBASE_DEBUG_ASSERT(kctx != NULL);
-+ KBASE_DEBUG_ASSERT(reg != NULL);
-
- lockdep_assert_held(&kctx->reg_lock);
-
-@@ -614,13 +625,15 @@ int kbase_add_va_region_rbtree(struct kbase_device *kbdev,
- size_t align_offset = align;
- size_t align_mask = align - 1;
-
-+#if !MALI_USE_CSF
- if ((reg->flags & KBASE_REG_TILER_ALIGN_TOP)) {
- WARN(align > 1, "%s with align %lx might not be honored for KBASE_REG_TILER_ALIGN_TOP memory",
- __func__,
- (unsigned long)align);
-- align_mask = reg->extent - 1;
-- align_offset = reg->extent - reg->initial_commit;
-+ align_mask = reg->extension - 1;
-+ align_offset = reg->extension - reg->initial_commit;
- }
-+#endif /* !MALI_USE_CSF */
-
- tmp = kbase_region_tracker_find_region_meeting_reqs(reg,
- nr_pages, align_offset, align_mask,
-@@ -643,7 +656,7 @@ exit:
- return err;
- }
-
--/**
-+/*
- * @brief Initialize the internal region tracker data structure.
- */
- static void kbase_region_tracker_ds_init(struct kbase_context *kctx,
-@@ -698,6 +711,9 @@ void kbase_region_tracker_term(struct kbase_context *kctx)
- kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_same);
- kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_custom);
- kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_exec);
-+#if MALI_USE_CSF
-+ WARN_ON(!list_empty(&kctx->csf.event_pages_head));
-+#endif
- kbase_gpu_vm_unlock(kctx);
- }
-
-@@ -720,23 +736,26 @@ int kbase_region_tracker_init(struct kbase_context *kctx)
- u64 custom_va_size = KBASE_REG_ZONE_CUSTOM_VA_SIZE;
- u64 gpu_va_limit = (1ULL << kctx->kbdev->gpu_props.mmu.va_bits) >> PAGE_SHIFT;
- u64 same_va_pages;
-+ u64 same_va_base = 1u;
- int err;
-
- /* Take the lock as kbase_free_alloced_region requires it */
- kbase_gpu_vm_lock(kctx);
-
-- same_va_pages = (1ULL << (same_va_bits - PAGE_SHIFT)) - 1;
-+ same_va_pages = (1ULL << (same_va_bits - PAGE_SHIFT)) - same_va_base;
- /* all have SAME_VA */
-- same_va_reg = kbase_alloc_free_region(&kctx->reg_rbtree_same, 1,
-- same_va_pages,
-- KBASE_REG_ZONE_SAME_VA);
-+ same_va_reg =
-+ kbase_alloc_free_region(&kctx->reg_rbtree_same, same_va_base,
-+ same_va_pages, KBASE_REG_ZONE_SAME_VA);
-
- if (!same_va_reg) {
- err = -ENOMEM;
- goto fail_unlock;
- }
-+ kbase_ctx_reg_zone_init(kctx, KBASE_REG_ZONE_SAME_VA, same_va_base,
-+ same_va_pages);
-
--#ifdef CONFIG_64BIT
-+#if IS_ENABLED(CONFIG_64BIT)
- /* 32-bit clients have custom VA zones */
- if (kbase_ctx_flag(kctx, KCTX_COMPAT)) {
- #endif
-@@ -760,19 +779,28 @@ int kbase_region_tracker_init(struct kbase_context *kctx)
- err = -ENOMEM;
- goto fail_free_same_va;
- }
--#ifdef CONFIG_64BIT
-+ kbase_ctx_reg_zone_init(kctx, KBASE_REG_ZONE_CUSTOM_VA,
-+ KBASE_REG_ZONE_CUSTOM_VA_BASE,
-+ custom_va_size);
-+#if IS_ENABLED(CONFIG_64BIT)
- } else {
- custom_va_size = 0;
- }
- #endif
-+ /* EXEC_VA zone's codepaths are slightly easier when its base_pfn is
-+ * initially U64_MAX
-+ */
-+ kbase_ctx_reg_zone_init(kctx, KBASE_REG_ZONE_EXEC_VA, U64_MAX, 0u);
-+ /* Other zones are 0: kbase_create_context() uses vzalloc */
-
- kbase_region_tracker_ds_init(kctx, same_va_reg, custom_va_reg);
-
-- kctx->same_va_end = same_va_pages + 1;
-- kctx->gpu_va_end = kctx->same_va_end + custom_va_size;
-- kctx->exec_va_start = U64_MAX;
-+ kctx->gpu_va_end = same_va_base + same_va_pages + custom_va_size;
- kctx->jit_va = false;
-
-+#if MALI_USE_CSF
-+ INIT_LIST_HEAD(&kctx->csf.event_pages_head);
-+#endif
-
- kbase_gpu_vm_unlock(kctx);
- return 0;
-@@ -784,44 +812,147 @@ fail_unlock:
- return err;
- }
-
--#ifdef CONFIG_64BIT
-+static bool kbase_has_exec_va_zone_locked(struct kbase_context *kctx)
-+{
-+ struct kbase_reg_zone *exec_va_zone;
-+
-+ lockdep_assert_held(&kctx->reg_lock);
-+ exec_va_zone = kbase_ctx_reg_zone_get(kctx, KBASE_REG_ZONE_EXEC_VA);
-+
-+ return (exec_va_zone->base_pfn != U64_MAX);
-+}
-+
-+bool kbase_has_exec_va_zone(struct kbase_context *kctx)
-+{
-+ bool has_exec_va_zone;
-+
-+ kbase_gpu_vm_lock(kctx);
-+ has_exec_va_zone = kbase_has_exec_va_zone_locked(kctx);
-+ kbase_gpu_vm_unlock(kctx);
-+
-+ return has_exec_va_zone;
-+}
-+
-+/**
-+ * Determine if any allocations have been made on a context's region tracker
-+ * @kctx: KBase context
-+ *
-+ * Check the context to determine if any allocations have been made yet from
-+ * any of its zones. This check should be done before resizing a zone, e.g. to
-+ * make space to add a second zone.
-+ *
-+ * Whilst a zone without allocations can be resized whilst other zones have
-+ * allocations, we still check all of @kctx 's zones anyway: this is a stronger
-+ * guarantee and should be adhered to when creating new zones anyway.
-+ *
-+ * Allocations from kbdev zones are not counted.
-+ *
-+ * Return: true if any allocs exist on any zone, false otherwise
-+ */
-+static bool kbase_region_tracker_has_allocs(struct kbase_context *kctx)
-+{
-+ unsigned int zone_idx;
-+
-+ lockdep_assert_held(&kctx->reg_lock);
-+
-+ for (zone_idx = 0; zone_idx < KBASE_REG_ZONE_MAX; ++zone_idx) {
-+ struct kbase_reg_zone *zone;
-+ struct kbase_va_region *reg;
-+ u64 zone_base_addr;
-+ unsigned long zone_bits = KBASE_REG_ZONE(zone_idx);
-+ unsigned long reg_zone;
-+
-+ zone = kbase_ctx_reg_zone_get(kctx, zone_bits);
-+ zone_base_addr = zone->base_pfn << PAGE_SHIFT;
-+
-+ reg = kbase_region_tracker_find_region_base_address(
-+ kctx, zone_base_addr);
-+
-+ if (!zone->va_size_pages) {
-+ WARN(reg,
-+ "Should not have found a region that starts at 0x%.16llx for zone 0x%lx",
-+ (unsigned long long)zone_base_addr, zone_bits);
-+ continue;
-+ }
-+
-+ if (WARN(!reg,
-+ "There should always be a region that starts at 0x%.16llx for zone 0x%lx, couldn't find it",
-+ (unsigned long long)zone_base_addr, zone_bits))
-+ return true; /* Safest return value */
-+
-+ reg_zone = reg->flags & KBASE_REG_ZONE_MASK;
-+ if (WARN(reg_zone != zone_bits,
-+ "The region that starts at 0x%.16llx should be in zone 0x%lx but was found in the wrong zone 0x%lx",
-+ (unsigned long long)zone_base_addr, zone_bits,
-+ reg_zone))
-+ return true; /* Safest return value */
-+
-+ /* Unless the region is completely free, of the same size as
-+ * the original zone, then it has allocs
-+ */
-+ if ((!(reg->flags & KBASE_REG_FREE)) ||
-+ (reg->nr_pages != zone->va_size_pages))
-+ return true;
-+ }
-+
-+ /* All zones are the same size as originally made, so there are no
-+ * allocs
-+ */
-+ return false;
-+}
-+
-+#if IS_ENABLED(CONFIG_64BIT)
- static int kbase_region_tracker_init_jit_64(struct kbase_context *kctx,
- u64 jit_va_pages)
- {
-- struct kbase_va_region *same_va;
-+ struct kbase_va_region *same_va_reg;
-+ struct kbase_reg_zone *same_va_zone;
-+ u64 same_va_zone_base_addr;
-+ const unsigned long same_va_zone_bits = KBASE_REG_ZONE_SAME_VA;
- struct kbase_va_region *custom_va_reg;
-+ u64 jit_va_start;
-
- lockdep_assert_held(&kctx->reg_lock);
-
-- /* First verify that a JIT_VA zone has not been created already. */
-- if (kctx->jit_va)
-- return -EINVAL;
--
- /*
-- * Modify the same VA free region after creation. Be careful to ensure
-- * that allocations haven't been made as they could cause an overlap
-- * to happen with existing same VA allocations and the custom VA zone.
-+ * Modify the same VA free region after creation. The caller has
-+ * ensured that allocations haven't been made, as any allocations could
-+ * cause an overlap to happen with existing same VA allocations and the
-+ * custom VA zone.
- */
-- same_va = kbase_region_tracker_find_region_base_address(kctx,
-- PAGE_SIZE);
-- if (!same_va)
-+ same_va_zone = kbase_ctx_reg_zone_get(kctx, same_va_zone_bits);
-+ same_va_zone_base_addr = same_va_zone->base_pfn << PAGE_SHIFT;
-+
-+ same_va_reg = kbase_region_tracker_find_region_base_address(
-+ kctx, same_va_zone_base_addr);
-+ if (WARN(!same_va_reg,
-+ "Already found a free region at the start of every zone, but now cannot find any region for zone base 0x%.16llx zone 0x%lx",
-+ (unsigned long long)same_va_zone_base_addr, same_va_zone_bits))
- return -ENOMEM;
-
-- if (same_va->nr_pages < jit_va_pages || kctx->same_va_end < jit_va_pages)
-+ /* kbase_region_tracker_has_allocs() in the caller has already ensured
-+ * that all of the zones have no allocs, so no need to check that again
-+ * on same_va_reg
-+ */
-+ WARN_ON((!(same_va_reg->flags & KBASE_REG_FREE)) ||
-+ same_va_reg->nr_pages != same_va_zone->va_size_pages);
-+
-+ if (same_va_reg->nr_pages < jit_va_pages ||
-+ same_va_zone->va_size_pages < jit_va_pages)
- return -ENOMEM;
-
- /* It's safe to adjust the same VA zone now */
-- same_va->nr_pages -= jit_va_pages;
-- kctx->same_va_end -= jit_va_pages;
-+ same_va_reg->nr_pages -= jit_va_pages;
-+ same_va_zone->va_size_pages -= jit_va_pages;
-+ jit_va_start = kbase_reg_zone_end_pfn(same_va_zone);
-
- /*
- * Create a custom VA zone at the end of the VA for allocations which
- * JIT can use so it doesn't have to allocate VA from the kernel.
- */
-- custom_va_reg = kbase_alloc_free_region(&kctx->reg_rbtree_custom,
-- kctx->same_va_end,
-- jit_va_pages,
-- KBASE_REG_ZONE_CUSTOM_VA);
-+ custom_va_reg =
-+ kbase_alloc_free_region(&kctx->reg_rbtree_custom, jit_va_start,
-+ jit_va_pages, KBASE_REG_ZONE_CUSTOM_VA);
-
- /*
- * The context will be destroyed if we fail here so no point
-@@ -829,6 +960,11 @@ static int kbase_region_tracker_init_jit_64(struct kbase_context *kctx,
- */
- if (!custom_va_reg)
- return -ENOMEM;
-+ /* Since this is 64-bit, the custom zone will not have been
-+ * initialized, so initialize it now
-+ */
-+ kbase_ctx_reg_zone_init(kctx, KBASE_REG_ZONE_CUSTOM_VA, jit_va_start,
-+ jit_va_pages);
-
- kbase_region_tracker_insert(custom_va_reg);
- return 0;
-@@ -847,16 +983,34 @@ int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages,
- if (group_id < 0 || group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)
- return -EINVAL;
-
--#if MALI_JIT_PRESSURE_LIMIT
- if (phys_pages_limit > jit_va_pages)
--#else
-- if (phys_pages_limit != jit_va_pages)
--#endif /* MALI_JIT_PRESSURE_LIMIT */
- return -EINVAL;
-
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (phys_pages_limit != jit_va_pages)
-+ kbase_ctx_flag_set(kctx, KCTX_JPL_ENABLED);
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-+
- kbase_gpu_vm_lock(kctx);
-
--#ifdef CONFIG_64BIT
-+ /* Verify that a JIT_VA zone has not been created already. */
-+ if (kctx->jit_va) {
-+ err = -EINVAL;
-+ goto exit_unlock;
-+ }
-+
-+ /* If in 64-bit, we always lookup the SAME_VA zone. To ensure it has no
-+ * allocs, we can ensure there are no allocs anywhere.
-+ *
-+ * This check is also useful in 32-bit, just to make sure init of the
-+ * zone is always done before any allocs.
-+ */
-+ if (kbase_region_tracker_has_allocs(kctx)) {
-+ err = -ENOMEM;
-+ goto exit_unlock;
-+ }
-+
-+#if IS_ENABLED(CONFIG_64BIT)
- if (!kbase_ctx_flag(kctx, KCTX_COMPAT))
- err = kbase_region_tracker_init_jit_64(kctx, jit_va_pages);
- #endif
-@@ -870,13 +1024,14 @@ int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages,
- kctx->trim_level = trim_level;
- kctx->jit_va = true;
- kctx->jit_group_id = group_id;
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- kctx->jit_phys_pages_limit = phys_pages_limit;
- dev_dbg(kctx->kbdev->dev, "phys_pages_limit set to %llu\n",
- phys_pages_limit);
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
- }
-
-+exit_unlock:
- kbase_gpu_vm_unlock(kctx);
-
- return err;
-@@ -884,24 +1039,33 @@ int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages,
-
- int kbase_region_tracker_init_exec(struct kbase_context *kctx, u64 exec_va_pages)
- {
-- struct kbase_va_region *shrinking_va_reg;
- struct kbase_va_region *exec_va_reg;
-- u64 exec_va_start, exec_va_base_addr;
-+ struct kbase_reg_zone *exec_va_zone;
-+ struct kbase_reg_zone *target_zone;
-+ struct kbase_va_region *target_reg;
-+ u64 target_zone_base_addr;
-+ unsigned long target_zone_bits;
-+ u64 exec_va_start;
- int err;
-
-- /* The EXEC_VA zone shall be created by making space at the end of the
-- * address space. Firstly, verify that the number of EXEC_VA pages
-- * requested by the client is reasonable and then make sure that it is
-- * not greater than the address space itself before calculating the base
-- * address of the new zone.
-+ /* The EXEC_VA zone shall be created by making space either:
-+ * - for 64-bit clients, at the end of the process's address space
-+ * - for 32-bit clients, in the CUSTOM zone
-+ *
-+ * Firstly, verify that the number of EXEC_VA pages requested by the
-+ * client is reasonable and then make sure that it is not greater than
-+ * the address space itself before calculating the base address of the
-+ * new zone.
- */
- if (exec_va_pages == 0 || exec_va_pages > KBASE_REG_ZONE_EXEC_VA_MAX_PAGES)
- return -EINVAL;
-
- kbase_gpu_vm_lock(kctx);
-
-- /* First verify that a JIT_VA zone has not been created already. */
-- if (kctx->jit_va) {
-+ /* Verify that we've not already created a EXEC_VA zone, and that the
-+ * EXEC_VA zone must come before JIT's CUSTOM_VA.
-+ */
-+ if (kbase_has_exec_va_zone_locked(kctx) || kctx->jit_va) {
- err = -EPERM;
- goto exit_unlock;
- }
-@@ -911,28 +1075,50 @@ int kbase_region_tracker_init_exec(struct kbase_context *kctx, u64 exec_va_pages
- goto exit_unlock;
- }
-
-- exec_va_start = kctx->gpu_va_end - exec_va_pages;
-- exec_va_base_addr = exec_va_start << PAGE_SHIFT;
--
-- shrinking_va_reg = kbase_region_tracker_find_region_enclosing_address(kctx,
-- exec_va_base_addr);
-- if (!shrinking_va_reg) {
-+ /* Verify no allocations have already been made */
-+ if (kbase_region_tracker_has_allocs(kctx)) {
- err = -ENOMEM;
- goto exit_unlock;
- }
-
-- /* Make sure that the EXEC_VA region is still uninitialized */
-- if ((shrinking_va_reg->flags & KBASE_REG_ZONE_MASK) ==
-- KBASE_REG_ZONE_EXEC_VA) {
-- err = -EPERM;
-+#if IS_ENABLED(CONFIG_64BIT)
-+ if (kbase_ctx_flag(kctx, KCTX_COMPAT)) {
-+#endif
-+ /* 32-bit client: take from CUSTOM_VA zone */
-+ target_zone_bits = KBASE_REG_ZONE_CUSTOM_VA;
-+#if IS_ENABLED(CONFIG_64BIT)
-+ } else {
-+ /* 64-bit client: take from SAME_VA zone */
-+ target_zone_bits = KBASE_REG_ZONE_SAME_VA;
-+ }
-+#endif
-+ target_zone = kbase_ctx_reg_zone_get(kctx, target_zone_bits);
-+ target_zone_base_addr = target_zone->base_pfn << PAGE_SHIFT;
-+
-+ target_reg = kbase_region_tracker_find_region_base_address(
-+ kctx, target_zone_base_addr);
-+ if (WARN(!target_reg,
-+ "Already found a free region at the start of every zone, but now cannot find any region for zone base 0x%.16llx zone 0x%lx",
-+ (unsigned long long)target_zone_base_addr, target_zone_bits)) {
-+ err = -ENOMEM;
- goto exit_unlock;
- }
-+ /* kbase_region_tracker_has_allocs() above has already ensured that all
-+ * of the zones have no allocs, so no need to check that again on
-+ * target_reg
-+ */
-+ WARN_ON((!(target_reg->flags & KBASE_REG_FREE)) ||
-+ target_reg->nr_pages != target_zone->va_size_pages);
-
-- if (shrinking_va_reg->nr_pages <= exec_va_pages) {
-+ if (target_reg->nr_pages <= exec_va_pages ||
-+ target_zone->va_size_pages <= exec_va_pages) {
- err = -ENOMEM;
- goto exit_unlock;
- }
-
-+ /* Taken from the end of the target zone */
-+ exec_va_start = kbase_reg_zone_end_pfn(target_zone) - exec_va_pages;
-+
- exec_va_reg = kbase_alloc_free_region(&kctx->reg_rbtree_exec,
- exec_va_start,
- exec_va_pages,
-@@ -941,13 +1127,17 @@ int kbase_region_tracker_init_exec(struct kbase_context *kctx, u64 exec_va_pages
- err = -ENOMEM;
- goto exit_unlock;
- }
-+ /* Update EXEC_VA zone
-+ *
-+ * not using kbase_ctx_reg_zone_init() - it was already initialized
-+ */
-+ exec_va_zone = kbase_ctx_reg_zone_get(kctx, KBASE_REG_ZONE_EXEC_VA);
-+ exec_va_zone->base_pfn = exec_va_start;
-+ exec_va_zone->va_size_pages = exec_va_pages;
-
-- shrinking_va_reg->nr_pages -= exec_va_pages;
--#ifdef CONFIG_64BIT
-- if (!kbase_ctx_flag(kctx, KCTX_COMPAT))
-- kctx->same_va_end -= exec_va_pages;
--#endif
-- kctx->exec_va_start = exec_va_start;
-+ /* Update target zone and corresponding region */
-+ target_reg->nr_pages -= exec_va_pages;
-+ target_zone->va_size_pages -= exec_va_pages;
-
- kbase_region_tracker_insert(exec_va_reg);
- err = 0;
-@@ -957,12 +1147,40 @@ exit_unlock:
- return err;
- }
-
-+#if MALI_USE_CSF
-+void kbase_mcu_shared_interface_region_tracker_term(struct kbase_device *kbdev)
-+{
-+ kbase_region_tracker_term_rbtree(&kbdev->csf.shared_reg_rbtree);
-+}
-+
-+int kbase_mcu_shared_interface_region_tracker_init(struct kbase_device *kbdev)
-+{
-+ struct kbase_va_region *shared_reg;
-+ u64 shared_reg_start_pfn;
-+ u64 shared_reg_size;
-+
-+ shared_reg_start_pfn = KBASE_REG_ZONE_MCU_SHARED_BASE;
-+ shared_reg_size = KBASE_REG_ZONE_MCU_SHARED_SIZE;
-+
-+ kbdev->csf.shared_reg_rbtree = RB_ROOT;
-+
-+ shared_reg = kbase_alloc_free_region(&kbdev->csf.shared_reg_rbtree,
-+ shared_reg_start_pfn,
-+ shared_reg_size,
-+ KBASE_REG_ZONE_MCU_SHARED);
-+ if (!shared_reg)
-+ return -ENOMEM;
-+
-+ kbase_region_tracker_insert(shared_reg);
-+ return 0;
-+}
-+#endif
-
- int kbase_mem_init(struct kbase_device *kbdev)
- {
- int err = 0;
- struct kbasep_mem_device *memdev;
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- struct device_node *mgm_node = NULL;
- #endif
-
-@@ -976,6 +1194,12 @@ int kbase_mem_init(struct kbase_device *kbdev)
- /* Initialize memory usage */
- atomic_set(&memdev->used_pages, 0);
-
-+ spin_lock_init(&kbdev->gpu_mem_usage_lock);
-+ kbdev->total_gpu_pages = 0;
-+ kbdev->process_root = RB_ROOT;
-+ kbdev->dma_buf_root = RB_ROOT;
-+ mutex_init(&kbdev->dma_buf_lock);
-+
- #ifdef IR_THRESHOLD
- atomic_set(&memdev->ir_threshold, IR_THRESHOLD);
- #else
-@@ -984,7 +1208,7 @@ int kbase_mem_init(struct kbase_device *kbdev)
-
- kbdev->mgm_dev = &kbase_native_mgm_dev;
-
--#ifdef CONFIG_OF
-+#if IS_ENABLED(CONFIG_OF)
- /* Check to see whether or not a platform-specific memory group manager
- * is configured and available.
- */
-@@ -1053,13 +1277,22 @@ void kbase_mem_term(struct kbase_device *kbdev)
-
- kbase_mem_pool_group_term(&kbdev->mem_pools);
-
-+ WARN_ON(kbdev->total_gpu_pages);
-+ WARN_ON(!RB_EMPTY_ROOT(&kbdev->process_root));
-+ WARN_ON(!RB_EMPTY_ROOT(&kbdev->dma_buf_root));
-+ mutex_destroy(&kbdev->dma_buf_lock);
-+
- if (kbdev->mgm_dev)
- module_put(kbdev->mgm_dev->owner);
- }
- KBASE_EXPORT_TEST_API(kbase_mem_term);
-
- /**
-- * @brief Allocate a free region object.
-+ * Allocate a free region object.
-+ * @rbtree: Backlink to the red-black tree of memory regions.
-+ * @start_pfn: The Page Frame Number in GPU virtual address space.
-+ * @nr_pages: The size of the region in pages.
-+ * @zone: KBASE_REG_ZONE_CUSTOM_VA or KBASE_REG_ZONE_SAME_VA
- *
- * The allocated object is not part of any list yet, and is flagged as
- * KBASE_REG_FREE. No mapping is allocated yet.
-@@ -1132,7 +1365,8 @@ static struct kbase_context *kbase_reg_flags_to_kctx(
- }
-
- /**
-- * @brief Free a region object.
-+ * Free a region object.
-+ * @reg: Region
- *
- * The described region must be freed of any mapping.
- *
-@@ -1143,6 +1377,13 @@ static struct kbase_context *kbase_reg_flags_to_kctx(
- */
- void kbase_free_alloced_region(struct kbase_va_region *reg)
- {
-+#if MALI_USE_CSF
-+ if ((reg->flags & KBASE_REG_ZONE_MASK) ==
-+ KBASE_REG_ZONE_MCU_SHARED) {
-+ kfree(reg);
-+ return;
-+ }
-+#endif
- if (!(reg->flags & KBASE_REG_FREE)) {
- struct kbase_context *kctx = kbase_reg_flags_to_kctx(reg);
-
-@@ -1152,8 +1393,12 @@ void kbase_free_alloced_region(struct kbase_va_region *reg)
- if (WARN_ON(kbase_is_region_invalid(reg)))
- return;
-
-- dev_dbg(kctx->kbdev->dev, "Freeing memory region %p\n",
-+ dev_dbg(kctx->kbdev->dev, "Freeing memory region %pK\n",
- (void *)reg);
-+#if MALI_USE_CSF
-+ if (reg->flags & KBASE_REG_CSF_EVENT)
-+ kbase_unlink_event_mem_page(kctx, reg);
-+#endif
-
- mutex_lock(&kctx->jit_evict_lock);
-
-@@ -1233,8 +1478,8 @@ int kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, u64
- else
- attr = KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_WRITE_ALLOC);
-
-- KBASE_DEBUG_ASSERT(NULL != kctx);
-- KBASE_DEBUG_ASSERT(NULL != reg);
-+ KBASE_DEBUG_ASSERT(kctx != NULL);
-+ KBASE_DEBUG_ASSERT(reg != NULL);
-
- err = kbase_add_va_region(kctx, reg, addr, nr_pages, align);
- if (err)
-@@ -1260,7 +1505,9 @@ int kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, u64
- if (err)
- goto bad_insert;
-
-- kbase_mem_phy_alloc_gpu_mapped(alloc->imported.alias.aliased[i].alloc);
-+ /* Note: mapping count is tracked at alias
-+ * creation time
-+ */
- } else {
- err = kbase_mmu_insert_single_page(kctx,
- reg->start_pfn + i * stride,
-@@ -1319,13 +1566,6 @@ bad_insert:
- reg->start_pfn, reg->nr_pages,
- kctx->as_nr);
-
-- if (alloc->type == KBASE_MEM_TYPE_ALIAS) {
-- KBASE_DEBUG_ASSERT(alloc->imported.alias.aliased);
-- while (i--)
-- if (alloc->imported.alias.aliased[i].alloc)
-- kbase_mem_phy_alloc_gpu_unmapped(alloc->imported.alias.aliased[i].alloc);
-- }
--
- kbase_remove_va_region(reg);
-
- return err;
-@@ -1339,7 +1579,6 @@ static void kbase_jd_user_buf_unmap(struct kbase_context *kctx,
- int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg)
- {
- int err = 0;
-- size_t i;
-
- if (reg->start_pfn == 0)
- return 0;
-@@ -1364,10 +1603,9 @@ int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg)
- /* Update tracking, and other cleanup, depending on memory type. */
- switch (reg->gpu_alloc->type) {
- case KBASE_MEM_TYPE_ALIAS:
-- KBASE_DEBUG_ASSERT(reg->gpu_alloc->imported.alias.aliased);
-- for (i = 0; i < reg->gpu_alloc->imported.alias.nents; i++)
-- if (reg->gpu_alloc->imported.alias.aliased[i].alloc)
-- kbase_mem_phy_alloc_gpu_unmapped(reg->gpu_alloc->imported.alias.aliased[i].alloc);
-+ /* We mark the source allocs as unmapped from the GPU when
-+ * putting reg's allocs
-+ */
- break;
- case KBASE_MEM_TYPE_IMPORTED_USER_BUF: {
- struct kbase_alloc_import_user_buf *user_buf =
-@@ -1404,7 +1642,7 @@ static struct kbase_cpu_mapping *kbasep_find_enclosing_cpu_mapping(
- unsigned long map_start;
- size_t map_size;
-
-- lockdep_assert_held(¤t->mm->mmap_sem);
-+ lockdep_assert_held(kbase_mem_get_process_mmap_lock());
-
- if ((uintptr_t) uaddr + size < (uintptr_t) uaddr) /* overflow check */
- return NULL;
-@@ -1676,9 +1914,9 @@ int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *re
- {
- int err;
-
-- KBASE_DEBUG_ASSERT(NULL != kctx);
-- KBASE_DEBUG_ASSERT(NULL != reg);
-- dev_dbg(kctx->kbdev->dev, "%s %p in kctx %p\n",
-+ KBASE_DEBUG_ASSERT(kctx != NULL);
-+ KBASE_DEBUG_ASSERT(reg != NULL);
-+ dev_dbg(kctx->kbdev->dev, "%s %pK in kctx %pK\n",
- __func__, (void *)reg, (void *)kctx);
- lockdep_assert_held(&kctx->reg_lock);
-
-@@ -1724,7 +1962,9 @@ int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *re
- KBASE_EXPORT_TEST_API(kbase_mem_free_region);
-
- /**
-- * @brief Free the region from the GPU and unregister it.
-+ * Free the region from the GPU and unregister it.
-+ * @kctx: KBase context
-+ * @gpu_addr: GPU address to free
- *
- * This function implements the free operation on a memory segment.
- * It will loudly fail if called with outstanding mappings.
-@@ -1735,7 +1975,7 @@ int kbase_mem_free(struct kbase_context *kctx, u64 gpu_addr)
- struct kbase_va_region *reg;
-
- KBASE_DEBUG_ASSERT(kctx != NULL);
-- dev_dbg(kctx->kbdev->dev, "%s 0x%llx in kctx %p\n",
-+ dev_dbg(kctx->kbdev->dev, "%s 0x%llx in kctx %pK\n",
- __func__, gpu_addr, (void *)kctx);
-
- if ((gpu_addr & ~PAGE_MASK) && (gpu_addr >= PAGE_SIZE)) {
-@@ -1743,7 +1983,7 @@ int kbase_mem_free(struct kbase_context *kctx, u64 gpu_addr)
- return -EINVAL;
- }
-
-- if (0 == gpu_addr) {
-+ if (gpu_addr == 0) {
- dev_warn(kctx->kbdev->dev, "gpu_addr 0 is reserved for the ringbuffer and it's an error to try to free it using kbase_mem_free\n");
- return -EINVAL;
- }
-@@ -1796,7 +2036,7 @@ KBASE_EXPORT_TEST_API(kbase_mem_free);
- int kbase_update_region_flags(struct kbase_context *kctx,
- struct kbase_va_region *reg, unsigned long flags)
- {
-- KBASE_DEBUG_ASSERT(NULL != reg);
-+ KBASE_DEBUG_ASSERT(reg != NULL);
- KBASE_DEBUG_ASSERT((flags & ~((1ul << BASE_MEM_FLAGS_NR_BITS) - 1)) == 0);
-
- reg->flags |= kbase_cache_enabled(flags, reg->nr_pages);
-@@ -1835,9 +2075,25 @@ int kbase_update_region_flags(struct kbase_context *kctx,
- reg->flags |= KBASE_REG_SHARE_IN;
- }
-
-+#if !MALI_USE_CSF
- if (flags & BASE_MEM_TILER_ALIGN_TOP)
- reg->flags |= KBASE_REG_TILER_ALIGN_TOP;
-+#endif /* !MALI_USE_CSF */
-+
-+#if MALI_USE_CSF
-+ if (flags & BASE_MEM_CSF_EVENT) {
-+ reg->flags |= KBASE_REG_CSF_EVENT;
-+ reg->flags |= KBASE_REG_PERMANENT_KERNEL_MAPPING;
-
-+ if (!(reg->flags & KBASE_REG_SHARE_BOTH)) {
-+ /* On non coherent platforms need to map as uncached on
-+ * both sides.
-+ */
-+ reg->flags &= ~KBASE_REG_CPU_CACHED;
-+ reg->flags &= ~KBASE_REG_GPU_CACHED;
-+ }
-+ }
-+#endif
-
- /* Set up default MEMATTR usage */
- if (!(reg->flags & KBASE_REG_GPU_CACHED)) {
-@@ -1851,6 +2107,13 @@ int kbase_update_region_flags(struct kbase_context *kctx,
- "Can't allocate GPU uncached memory due to MMU in Legacy Mode\n");
- return -EINVAL;
- }
-+#if MALI_USE_CSF
-+ } else if (reg->flags & KBASE_REG_CSF_EVENT) {
-+ WARN_ON(!(reg->flags & KBASE_REG_SHARE_BOTH));
-+
-+ reg->flags |=
-+ KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_SHARED);
-+#endif
- } else if (kctx->kbdev->system_coherency == COHERENCY_ACE &&
- (reg->flags & KBASE_REG_SHARE_BOTH)) {
- reg->flags |=
-@@ -1905,7 +2168,8 @@ int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc *alloc,
- &kctx->kbdev->memdev.used_pages);
-
- /* Increase mm counters before we allocate pages so that this
-- * allocation is visible to the OOM killer */
-+ * allocation is visible to the OOM killer
-+ */
- kbase_process_page_usage_inc(kctx, nr_pages_requested);
-
- tp = alloc->pages + alloc->nents;
-@@ -2033,6 +2297,9 @@ no_new_partial:
- (u64)new_page_count);
-
- alloc->nents += nr_pages_requested;
-+
-+ kbase_trace_gpu_mem_usage_inc(kctx->kbdev, kctx, nr_pages_requested);
-+
- done:
- return 0;
-
-@@ -2209,6 +2476,9 @@ struct tagged_addr *kbase_alloc_phy_pages_helper_locked(
- (u64)new_page_count);
-
- alloc->nents += nr_pages_requested;
-+
-+ kbase_trace_gpu_mem_usage_inc(kctx->kbdev, kctx, nr_pages_requested);
-+
- done:
- return new_pages;
-
-@@ -2303,7 +2573,7 @@ int kbase_free_phy_pages_helper(
- }
-
- /* early out if nothing to do */
-- if (0 == nr_pages_to_free)
-+ if (nr_pages_to_free == 0)
- return 0;
-
- start_free = alloc->pages + alloc->nents - nr_pages_to_free;
-@@ -2374,6 +2644,8 @@ int kbase_free_phy_pages_helper(
- kbdev,
- kctx->id,
- (u64)new_page_count);
-+
-+ kbase_trace_gpu_mem_usage_dec(kctx->kbdev, kctx, freed);
- }
-
- return 0;
-@@ -2496,9 +2768,19 @@ void kbase_free_phy_pages_helper_locked(struct kbase_mem_phy_alloc *alloc,
- kbdev,
- kctx->id,
- (u64)new_page_count);
-+
-+ kbase_trace_gpu_mem_usage_dec(kctx->kbdev, kctx, freed);
- }
- }
-+KBASE_EXPORT_TEST_API(kbase_free_phy_pages_helper_locked);
-
-+#if MALI_USE_CSF
-+/**
-+ * kbase_jd_user_buf_unpin_pages - Release the pinned pages of a user buffer.
-+ * @alloc: The allocation for the imported user buffer.
-+ */
-+static void kbase_jd_user_buf_unpin_pages(struct kbase_mem_phy_alloc *alloc);
-+#endif
-
- void kbase_mem_kref_free(struct kref *kref)
- {
-@@ -2540,8 +2822,10 @@ void kbase_mem_kref_free(struct kref *kref)
- aliased = alloc->imported.alias.aliased;
- if (aliased) {
- for (i = 0; i < alloc->imported.alias.nents; i++)
-- if (aliased[i].alloc)
-+ if (aliased[i].alloc) {
-+ kbase_mem_phy_alloc_gpu_unmapped(aliased[i].alloc);
- kbase_mem_phy_alloc_put(aliased[i].alloc);
-+ }
- vfree(aliased);
- }
- break;
-@@ -2558,12 +2842,17 @@ void kbase_mem_kref_free(struct kref *kref)
- alloc->imported.umm.dma_attachment,
- alloc->imported.umm.sgt,
- DMA_BIDIRECTIONAL);
-+ kbase_remove_dma_buf_usage(alloc->imported.umm.kctx,
-+ alloc);
- }
- dma_buf_detach(alloc->imported.umm.dma_buf,
- alloc->imported.umm.dma_attachment);
- dma_buf_put(alloc->imported.umm.dma_buf);
- break;
- case KBASE_MEM_TYPE_IMPORTED_USER_BUF:
-+#if MALI_USE_CSF
-+ kbase_jd_user_buf_unpin_pages(alloc);
-+#endif
- if (alloc->imported.user_buf.mm)
- mmdrop(alloc->imported.user_buf.mm);
- if (alloc->properties & KBASE_MEM_PHY_ALLOC_LARGE)
-@@ -2587,7 +2876,7 @@ KBASE_EXPORT_TEST_API(kbase_mem_kref_free);
-
- int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size)
- {
-- KBASE_DEBUG_ASSERT(NULL != reg);
-+ KBASE_DEBUG_ASSERT(reg != NULL);
- KBASE_DEBUG_ASSERT(vsize > 0);
-
- /* validate user provided arguments */
-@@ -2600,7 +2889,7 @@ int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size
- if ((size_t) vsize > ((size_t) -1 / sizeof(*reg->cpu_alloc->pages)))
- goto out_term;
-
-- KBASE_DEBUG_ASSERT(0 != vsize);
-+ KBASE_DEBUG_ASSERT(vsize != 0);
-
- if (kbase_alloc_phy_pages_helper(reg->cpu_alloc, size) != 0)
- goto out_term;
-@@ -2643,22 +2932,37 @@ bool kbase_check_alloc_flags(unsigned long flags)
- /* GPU executable memory cannot:
- * - Be written by the GPU
- * - Be grown on GPU page fault
-- * - Have the top of its initial commit aligned to 'extent' */
-+ */
-+ if ((flags & BASE_MEM_PROT_GPU_EX) && (flags &
-+ (BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF)))
-+ return false;
-+
-+#if !MALI_USE_CSF
-+ /* GPU executable memory also cannot have the top of its initial
-+ * commit aligned to 'extension'
-+ */
- if ((flags & BASE_MEM_PROT_GPU_EX) && (flags &
-- (BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF |
-- BASE_MEM_TILER_ALIGN_TOP)))
-+ BASE_MEM_TILER_ALIGN_TOP))
- return false;
-+#endif /* !MALI_USE_CSF */
-
- /* To have an allocation lie within a 4GB chunk is required only for
-- * TLS memory, which will never be used to contain executable code
-- * and also used for Tiler heap.
-+ * TLS memory, which will never be used to contain executable code.
- */
- if ((flags & BASE_MEM_GPU_VA_SAME_4GB_PAGE) && (flags &
-- (BASE_MEM_PROT_GPU_EX | BASE_MEM_TILER_ALIGN_TOP)))
-+ BASE_MEM_PROT_GPU_EX))
- return false;
-
-+#if !MALI_USE_CSF
-+ /* TLS memory should also not be used for tiler heap */
-+ if ((flags & BASE_MEM_GPU_VA_SAME_4GB_PAGE) && (flags &
-+ BASE_MEM_TILER_ALIGN_TOP))
-+ return false;
-+#endif /* !MALI_USE_CSF */
-+
- /* GPU should have at least read or write access otherwise there is no
-- reason for allocating. */
-+ * reason for allocating.
-+ */
- if ((flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR)) == 0)
- return false;
-
-@@ -2666,14 +2970,15 @@ bool kbase_check_alloc_flags(unsigned long flags)
- if ((flags & BASE_MEM_IMPORT_SHARED) == BASE_MEM_IMPORT_SHARED)
- return false;
-
-- /* BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP is only valid for imported
-- * memory */
-+ /* BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP is only valid for imported memory
-+ */
- if ((flags & BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP) ==
- BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP)
- return false;
-
- /* Should not combine BASE_MEM_COHERENT_LOCAL with
-- * BASE_MEM_COHERENT_SYSTEM */
-+ * BASE_MEM_COHERENT_SYSTEM
-+ */
- if ((flags & (BASE_MEM_COHERENT_LOCAL | BASE_MEM_COHERENT_SYSTEM)) ==
- (BASE_MEM_COHERENT_LOCAL | BASE_MEM_COHERENT_SYSTEM))
- return false;
-@@ -2699,12 +3004,15 @@ bool kbase_check_import_flags(unsigned long flags)
- if (flags & BASE_MEM_GROW_ON_GPF)
- return false;
-
-+#if !MALI_USE_CSF
- /* Imported memory cannot be aligned to the end of its initial commit */
- if (flags & BASE_MEM_TILER_ALIGN_TOP)
- return false;
-+#endif /* !MALI_USE_CSF */
-
- /* GPU should have at least read or write access otherwise there is no
-- reason for importing. */
-+ * reason for importing.
-+ */
- if ((flags & (BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR)) == 0)
- return false;
-
-@@ -2716,19 +3024,19 @@ bool kbase_check_import_flags(unsigned long flags)
- }
-
- int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags,
-- u64 va_pages, u64 commit_pages, u64 large_extent)
-+ u64 va_pages, u64 commit_pages, u64 large_extension)
- {
- struct device *dev = kctx->kbdev->dev;
- int gpu_pc_bits = kctx->kbdev->gpu_props.props.core_props.log2_program_counter_size;
- u64 gpu_pc_pages_max = 1ULL << gpu_pc_bits >> PAGE_SHIFT;
- struct kbase_va_region test_reg;
-
-- /* kbase_va_region's extent member can be of variable size, so check against that type */
-- test_reg.extent = large_extent;
-+ /* kbase_va_region's extension member can be of variable size, so check against that type */
-+ test_reg.extension = large_extension;
-
- #define KBASE_MSG_PRE "GPU allocation attempted with "
-
-- if (0 == va_pages) {
-+ if (va_pages == 0) {
- dev_warn(dev, KBASE_MSG_PRE "0 va_pages!");
- return -EINVAL;
- }
-@@ -2740,7 +3048,8 @@ int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags,
- }
-
- /* Note: commit_pages is checked against va_pages during
-- * kbase_alloc_phy_pages() */
-+ * kbase_alloc_phy_pages()
-+ */
-
- /* Limit GPU executable allocs to GPU PC size */
- if ((flags & BASE_MEM_PROT_GPU_EX) && (va_pages > gpu_pc_pages_max)) {
-@@ -2751,47 +3060,73 @@ int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags,
- return -EINVAL;
- }
-
-- if ((flags & (BASE_MEM_GROW_ON_GPF | BASE_MEM_TILER_ALIGN_TOP)) &&
-- test_reg.extent == 0) {
-- dev_warn(dev, KBASE_MSG_PRE "BASE_MEM_GROW_ON_GPF or BASE_MEM_TILER_ALIGN_TOP but extent == 0\n");
-+ if ((flags & BASE_MEM_GROW_ON_GPF) && (test_reg.extension == 0)) {
-+ dev_warn(dev, KBASE_MSG_PRE
-+ "BASE_MEM_GROW_ON_GPF but extension == 0\n");
-+ return -EINVAL;
-+ }
-+
-+#if !MALI_USE_CSF
-+ if ((flags & BASE_MEM_TILER_ALIGN_TOP) && (test_reg.extension == 0)) {
-+ dev_warn(dev, KBASE_MSG_PRE
-+ "BASE_MEM_TILER_ALIGN_TOP but extension == 0\n");
- return -EINVAL;
- }
-
- if (!(flags & (BASE_MEM_GROW_ON_GPF | BASE_MEM_TILER_ALIGN_TOP)) &&
-- test_reg.extent != 0) {
-- dev_warn(dev, KBASE_MSG_PRE "neither BASE_MEM_GROW_ON_GPF nor BASE_MEM_TILER_ALIGN_TOP set but extent != 0\n");
-+ test_reg.extension != 0) {
-+ dev_warn(
-+ dev, KBASE_MSG_PRE
-+ "neither BASE_MEM_GROW_ON_GPF nor BASE_MEM_TILER_ALIGN_TOP set but extension != 0\n");
-+ return -EINVAL;
-+ }
-+#else
-+ if (!(flags & BASE_MEM_GROW_ON_GPF) && test_reg.extension != 0) {
-+ dev_warn(dev, KBASE_MSG_PRE
-+ "BASE_MEM_GROW_ON_GPF not set but extension != 0\n");
- return -EINVAL;
- }
-+#endif /* !MALI_USE_CSF */
-
-+#if !MALI_USE_CSF
- /* BASE_MEM_TILER_ALIGN_TOP memory has a number of restrictions */
- if (flags & BASE_MEM_TILER_ALIGN_TOP) {
- #define KBASE_MSG_PRE_FLAG KBASE_MSG_PRE "BASE_MEM_TILER_ALIGN_TOP and "
-- unsigned long small_extent;
--
-- if (large_extent > BASE_MEM_TILER_ALIGN_TOP_EXTENT_MAX_PAGES) {
-- dev_warn(dev, KBASE_MSG_PRE_FLAG "extent==%lld pages exceeds limit %lld",
-- (unsigned long long)large_extent,
-- BASE_MEM_TILER_ALIGN_TOP_EXTENT_MAX_PAGES);
-+ unsigned long small_extension;
-+
-+ if (large_extension >
-+ BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES) {
-+ dev_warn(dev,
-+ KBASE_MSG_PRE_FLAG
-+ "extension==%lld pages exceeds limit %lld",
-+ (unsigned long long)large_extension,
-+ BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES);
- return -EINVAL;
- }
- /* For use with is_power_of_2, which takes unsigned long, so
-- * must ensure e.g. on 32-bit kernel it'll fit in that type */
-- small_extent = (unsigned long)large_extent;
-+ * must ensure e.g. on 32-bit kernel it'll fit in that type
-+ */
-+ small_extension = (unsigned long)large_extension;
-
-- if (!is_power_of_2(small_extent)) {
-- dev_warn(dev, KBASE_MSG_PRE_FLAG "extent==%ld not a non-zero power of 2",
-- small_extent);
-+ if (!is_power_of_2(small_extension)) {
-+ dev_warn(dev,
-+ KBASE_MSG_PRE_FLAG
-+ "extension==%ld not a non-zero power of 2",
-+ small_extension);
- return -EINVAL;
- }
-
-- if (commit_pages > large_extent) {
-- dev_warn(dev, KBASE_MSG_PRE_FLAG "commit_pages==%ld exceeds extent==%ld",
-- (unsigned long)commit_pages,
-- (unsigned long)large_extent);
-+ if (commit_pages > large_extension) {
-+ dev_warn(dev,
-+ KBASE_MSG_PRE_FLAG
-+ "commit_pages==%ld exceeds extension==%ld",
-+ (unsigned long)commit_pages,
-+ (unsigned long)large_extension);
- return -EINVAL;
- }
- #undef KBASE_MSG_PRE_FLAG
- }
-+#endif /* !MALI_USE_CSF */
-
- if ((flags & BASE_MEM_GPU_VA_SAME_4GB_PAGE) &&
- (va_pages > (BASE_MEM_PFN_MASK_4GB + 1))) {
-@@ -2805,7 +3140,8 @@ int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags,
- }
-
- /**
-- * @brief Acquire the per-context region list lock
-+ * Acquire the per-context region list lock
-+ * @kctx: KBase context
- */
- void kbase_gpu_vm_lock(struct kbase_context *kctx)
- {
-@@ -2816,7 +3152,8 @@ void kbase_gpu_vm_lock(struct kbase_context *kctx)
- KBASE_EXPORT_TEST_API(kbase_gpu_vm_lock);
-
- /**
-- * @brief Release the per-context region list lock
-+ * Release the per-context region list lock
-+ * @kctx: KBase context
- */
- void kbase_gpu_vm_unlock(struct kbase_context *kctx)
- {
-@@ -2826,7 +3163,7 @@ void kbase_gpu_vm_unlock(struct kbase_context *kctx)
-
- KBASE_EXPORT_TEST_API(kbase_gpu_vm_unlock);
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- struct kbase_jit_debugfs_data {
- int (*func)(struct kbase_jit_debugfs_data *);
- struct mutex lock;
-@@ -2879,7 +3216,7 @@ static ssize_t kbase_jit_debugfs_common_read(struct file *file,
- }
-
- size = scnprintf(data->buffer, sizeof(data->buffer),
-- "%llu,%llu,%llu", data->active_value,
-+ "%llu,%llu,%llu\n", data->active_value,
- data->pool_value, data->destroy_value);
- }
-
-@@ -2983,19 +3320,23 @@ static int kbase_jit_debugfs_phys_get(struct kbase_jit_debugfs_data *data)
- KBASE_JIT_DEBUGFS_DECLARE(kbase_jit_debugfs_phys_fops,
- kbase_jit_debugfs_phys_get);
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- static int kbase_jit_debugfs_used_get(struct kbase_jit_debugfs_data *data)
- {
- struct kbase_context *kctx = data->kctx;
- struct kbase_va_region *reg;
-
-+#if !MALI_USE_CSF
- mutex_lock(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
- mutex_lock(&kctx->jit_evict_lock);
- list_for_each_entry(reg, &kctx->jit_active_head, jit_node) {
- data->active_value += reg->used_pages;
- }
- mutex_unlock(&kctx->jit_evict_lock);
-+#if !MALI_USE_CSF
- mutex_unlock(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
-
- return 0;
- }
-@@ -3012,7 +3353,9 @@ static int kbase_jit_debugfs_trim_get(struct kbase_jit_debugfs_data *data)
- struct kbase_context *kctx = data->kctx;
- struct kbase_va_region *reg;
-
-+#if !MALI_USE_CSF
- mutex_lock(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
- kbase_gpu_vm_lock(kctx);
- mutex_lock(&kctx->jit_evict_lock);
- list_for_each_entry(reg, &kctx->jit_active_head, jit_node) {
-@@ -3031,14 +3374,16 @@ static int kbase_jit_debugfs_trim_get(struct kbase_jit_debugfs_data *data)
- }
- mutex_unlock(&kctx->jit_evict_lock);
- kbase_gpu_vm_unlock(kctx);
-+#if !MALI_USE_CSF
- mutex_unlock(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
-
- return 0;
- }
-
- KBASE_JIT_DEBUGFS_DECLARE(kbase_jit_debugfs_trim_fops,
- kbase_jit_debugfs_trim_get);
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- void kbase_jit_debugfs_init(struct kbase_context *kctx)
- {
-@@ -3078,7 +3423,7 @@ void kbase_jit_debugfs_init(struct kbase_context *kctx)
- */
- debugfs_create_file("mem_jit_phys", mode, kctx->kctx_dentry,
- kctx, &kbase_jit_debugfs_phys_fops);
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /*
- * Debugfs entry for getting the number of pages used
- * by JIT allocations for estimating the physical pressure
-@@ -3093,7 +3438,7 @@ void kbase_jit_debugfs_init(struct kbase_context *kctx)
- */
- debugfs_create_file("mem_jit_trim", mode, kctx->kctx_dentry,
- kctx, &kbase_jit_debugfs_trim_fops);
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
- }
- #endif /* CONFIG_DEBUG_FS */
-
-@@ -3138,8 +3483,13 @@ int kbase_jit_init(struct kbase_context *kctx)
- INIT_LIST_HEAD(&kctx->jit_destroy_head);
- INIT_WORK(&kctx->jit_work, kbase_jit_destroy_worker);
-
-+#if MALI_USE_CSF
-+ INIT_LIST_HEAD(&kctx->csf.kcpu_queues.jit_cmds_head);
-+ INIT_LIST_HEAD(&kctx->csf.kcpu_queues.jit_blocked_queues);
-+#else /* !MALI_USE_CSF */
- INIT_LIST_HEAD(&kctx->jctx.jit_atoms_head);
- INIT_LIST_HEAD(&kctx->jctx.jit_pending_alloc);
-+#endif /* MALI_USE_CSF */
- mutex_unlock(&kctx->jit_evict_lock);
-
- kctx->jit_max_allocations = 0;
-@@ -3153,25 +3503,29 @@ int kbase_jit_init(struct kbase_context *kctx)
- * allocation and also, if BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP is set, meets
- * the alignment requirements.
- */
--static bool meet_size_and_tiler_align_top_requirements(struct kbase_context *kctx,
-- struct kbase_va_region *walker, const struct base_jit_alloc_info *info)
-+static bool meet_size_and_tiler_align_top_requirements(
-+ const struct kbase_va_region *walker,
-+ const struct base_jit_alloc_info *info)
- {
- bool meet_reqs = true;
-
- if (walker->nr_pages != info->va_pages)
- meet_reqs = false;
-- else if (info->flags & BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP) {
-- size_t align = info->extent;
-+
-+#if !MALI_USE_CSF
-+ if (meet_reqs && (info->flags & BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP)) {
-+ size_t align = info->extension;
- size_t align_mask = align - 1;
-
- if ((walker->start_pfn + info->commit_pages) & align_mask)
- meet_reqs = false;
- }
-+#endif /* !MALI_USE_CSF */
-
- return meet_reqs;
- }
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /* Function will guarantee *@freed will not exceed @pages_needed
- */
- static int kbase_mem_jit_trim_pages_from_region(struct kbase_context *kctx,
-@@ -3185,7 +3539,9 @@ static int kbase_mem_jit_trim_pages_from_region(struct kbase_context *kctx,
- size_t to_free = 0u;
- size_t max_allowed_pages = old_pages;
-
-+#if !MALI_USE_CSF
- lockdep_assert_held(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
- lockdep_assert_held(&kctx->reg_lock);
-
- /* Is this a JIT allocation that has been reported on? */
-@@ -3213,20 +3569,20 @@ static int kbase_mem_jit_trim_pages_from_region(struct kbase_context *kctx,
- KBASE_GPU_ALLOCATED_OBJECT_ALIGN_BYTES);
- } else if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) {
- /* The GPU could report being ready to write to the next
-- * 'extent' sized chunk, but didn't actually write to it, so we
-- * can report up to 'extent' size pages more than the backed
-+ * 'extension' sized chunk, but didn't actually write to it, so we
-+ * can report up to 'extension' size pages more than the backed
- * size.
- *
- * Note, this is allowed to exceed reg->nr_pages.
- */
-- max_allowed_pages += reg->extent;
-+ max_allowed_pages += reg->extension;
-
- /* Also note that in these GPUs, the GPU may make a large (>1
- * page) initial allocation but not actually write out to all
- * of it. Hence it might report that a much higher amount of
- * memory was used than actually was written to. This does not
- * result in a real warning because on growing this memory we
-- * round up the size of the allocation up to an 'extent' sized
-+ * round up the size of the allocation up to an 'extension' sized
- * chunk, hence automatically bringing the backed size up to
- * the reported size.
- */
-@@ -3308,8 +3664,12 @@ static size_t kbase_mem_jit_trim_pages(struct kbase_context *kctx,
- struct kbase_va_region *reg, *tmp;
- size_t total_freed = 0;
-
-- kbase_gpu_vm_lock(kctx);
-- mutex_lock(&kctx->jit_evict_lock);
-+#if !MALI_USE_CSF
-+ lockdep_assert_held(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
-+ lockdep_assert_held(&kctx->reg_lock);
-+ lockdep_assert_held(&kctx->jit_evict_lock);
-+
- list_for_each_entry_safe(reg, tmp, &kctx->jit_active_head, jit_node) {
- int err;
- size_t freed = 0u;
-@@ -3328,18 +3688,17 @@ static size_t kbase_mem_jit_trim_pages(struct kbase_context *kctx,
- if (!pages_needed)
- break;
- }
-- mutex_unlock(&kctx->jit_evict_lock);
-- kbase_gpu_vm_unlock(kctx);
-
- trace_mali_jit_trim(total_freed);
-
- return total_freed;
- }
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- static int kbase_jit_grow(struct kbase_context *kctx,
-- const struct base_jit_alloc_info *info,
-- struct kbase_va_region *reg)
-+ const struct base_jit_alloc_info *info,
-+ struct kbase_va_region *reg,
-+ struct kbase_sub_alloc **prealloc_sas)
- {
- size_t delta;
- size_t pages_required;
-@@ -3347,15 +3706,13 @@ static int kbase_jit_grow(struct kbase_context *kctx,
- struct kbase_mem_pool *pool;
- int ret = -ENOMEM;
- struct tagged_addr *gpu_pages;
-- struct kbase_sub_alloc *prealloc_sas[2] = { NULL, NULL };
-- int i;
-
- if (info->commit_pages > reg->nr_pages) {
- /* Attempted to grow larger than maximum size */
- return -EINVAL;
- }
-
-- kbase_gpu_vm_lock(kctx);
-+ lockdep_assert_held(&kctx->reg_lock);
-
- /* Make the physical backing no longer reclaimable */
- if (!kbase_mem_evictable_unmake(reg->gpu_alloc))
-@@ -3372,14 +3729,6 @@ static int kbase_jit_grow(struct kbase_context *kctx,
- pages_required = delta;
-
- #ifdef CONFIG_MALI_2MB_ALLOC
-- /* Preallocate memory for the sub-allocation structs */
-- for (i = 0; i != ARRAY_SIZE(prealloc_sas); ++i) {
-- prealloc_sas[i] = kmalloc(sizeof(*prealloc_sas[i]),
-- GFP_KERNEL);
-- if (!prealloc_sas[i])
-- goto update_failed;
-- }
--
- if (pages_required >= (SZ_2M / SZ_4K)) {
- pool = &kctx->mem_pools.large[kctx->jit_group_id];
- /* Round up to number of 2 MB pages required */
-@@ -3405,15 +3754,18 @@ static int kbase_jit_grow(struct kbase_context *kctx,
- */
- while (kbase_mem_pool_size(pool) < pages_required) {
- int pool_delta = pages_required - kbase_mem_pool_size(pool);
-+ int ret;
-
- kbase_mem_pool_unlock(pool);
- spin_unlock(&kctx->mem_partials_lock);
-+
- kbase_gpu_vm_unlock(kctx);
-+ ret = kbase_mem_pool_grow(pool, pool_delta);
-+ kbase_gpu_vm_lock(kctx);
-
-- if (kbase_mem_pool_grow(pool, pool_delta))
-- goto update_failed_unlocked;
-+ if (ret)
-+ goto update_failed;
-
-- kbase_gpu_vm_lock(kctx);
- spin_lock(&kctx->mem_partials_lock);
- kbase_mem_pool_lock(pool);
- }
-@@ -3456,14 +3808,9 @@ done:
-
- /* Update attributes of JIT allocation taken from the pool */
- reg->initial_commit = info->commit_pages;
-- reg->extent = info->extent;
-+ reg->extension = info->extension;
-
- update_failed:
-- kbase_gpu_vm_unlock(kctx);
--update_failed_unlocked:
-- for (i = 0; i != ARRAY_SIZE(prealloc_sas); ++i)
-- kfree(prealloc_sas[i]);
--
- return ret;
- }
-
-@@ -3492,9 +3839,9 @@ static void trace_jit_stats(struct kbase_context *kctx,
- max_allocations, alloc_count, va_pages, ph_pages);
- }
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /**
-- * get_jit_backed_pressure() - calculate the physical backing of all JIT
-+ * get_jit_phys_backing() - calculate the physical backing of all JIT
- * allocations
- *
- * @kctx: Pointer to the kbase context whose active JIT allocations will be
-@@ -3502,83 +3849,50 @@ static void trace_jit_stats(struct kbase_context *kctx,
- *
- * Return: number of pages that are committed by JIT allocations
- */
--static size_t get_jit_backed_pressure(struct kbase_context *kctx)
-+static size_t get_jit_phys_backing(struct kbase_context *kctx)
- {
-- size_t backed_pressure = 0;
-- int jit_id;
--
-- lockdep_assert_held(&kctx->jctx.lock);
-+ struct kbase_va_region *walker;
-+ size_t backing = 0;
-
-- kbase_gpu_vm_lock(kctx);
-- for (jit_id = 0; jit_id <= BASE_JIT_ALLOC_COUNT; jit_id++) {
-- struct kbase_va_region *reg = kctx->jit_alloc[jit_id];
-+ lockdep_assert_held(&kctx->jit_evict_lock);
-
-- if (reg && (reg != KBASE_RESERVED_REG_JIT_ALLOC)) {
-- /* If region has no report, be pessimistic */
-- if (reg->used_pages == reg->nr_pages) {
-- backed_pressure += reg->nr_pages;
-- } else {
-- backed_pressure +=
-- kbase_reg_current_backed_size(reg);
-- }
-- }
-+ list_for_each_entry(walker, &kctx->jit_active_head, jit_node) {
-+ backing += kbase_reg_current_backed_size(walker);
- }
-- kbase_gpu_vm_unlock(kctx);
-
-- return backed_pressure;
-+ return backing;
- }
-
--/**
-- * jit_trim_necessary_pages() - calculate and trim the least pages possible to
-- * satisfy a new JIT allocation
-- *
-- * @kctx: Pointer to the kbase context
-- * @info: Pointer to JIT allocation information for the new allocation
-- *
-- * Before allocating a new just-in-time memory region or reusing a previous
-- * one, ensure that the total JIT physical page usage also will not exceed the
-- * pressure limit.
-- *
-- * If there are no reported-on allocations, then we already guarantee this will
-- * be the case - because our current pressure then only comes from the va_pages
-- * of each JIT region, hence JIT physical page usage is guaranteed to be
-- * bounded by this.
-- *
-- * However as soon as JIT allocations become "reported on", the pressure is
-- * lowered to allow new JIT regions to be allocated. It is after such a point
-- * that the total JIT physical page usage could (either now or in the future on
-- * a grow-on-GPU-page-fault) exceed the pressure limit, but only on newly
-- * allocated JIT regions. Hence, trim any "reported on" regions.
-- *
-- * Any pages freed will go into the pool and be allocated from there in
-- * kbase_mem_alloc().
-- */
--static void jit_trim_necessary_pages(struct kbase_context *kctx,
-- const struct base_jit_alloc_info *info)
-+void kbase_jit_trim_necessary_pages(struct kbase_context *kctx,
-+ size_t needed_pages)
- {
-- size_t backed_pressure = 0;
-- size_t needed_pages = 0;
-+ size_t jit_backing = 0;
-+ size_t pages_to_trim = 0;
-
-- backed_pressure = get_jit_backed_pressure(kctx);
-+#if !MALI_USE_CSF
-+ lockdep_assert_held(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
-+ lockdep_assert_held(&kctx->reg_lock);
-+ lockdep_assert_held(&kctx->jit_evict_lock);
-+
-+ jit_backing = get_jit_phys_backing(kctx);
-
- /* It is possible that this is the case - if this is the first
- * allocation after "ignore_pressure_limit" allocation.
- */
-- if (backed_pressure > kctx->jit_phys_pages_limit) {
-- needed_pages +=
-- (backed_pressure - kctx->jit_phys_pages_limit)
-- + info->va_pages;
-+ if (jit_backing > kctx->jit_phys_pages_limit) {
-+ pages_to_trim += (jit_backing - kctx->jit_phys_pages_limit) +
-+ needed_pages;
- } else {
-- size_t backed_diff =
-- kctx->jit_phys_pages_limit - backed_pressure;
-+ size_t backed_diff = kctx->jit_phys_pages_limit - jit_backing;
-
-- if (info->va_pages > backed_diff)
-- needed_pages += info->va_pages - backed_diff;
-+ if (needed_pages > backed_diff)
-+ pages_to_trim += needed_pages - backed_diff;
- }
-
-- if (needed_pages) {
-- size_t trimmed_pages = kbase_mem_jit_trim_pages(kctx,
-- needed_pages);
-+ if (pages_to_trim) {
-+ size_t trimmed_pages =
-+ kbase_mem_jit_trim_pages(kctx, pages_to_trim);
-
- /* This should never happen - we already asserted that
- * we are not violating JIT pressure limit in earlier
-@@ -3586,10 +3900,10 @@ static void jit_trim_necessary_pages(struct kbase_context *kctx,
- * must have enough unused pages to satisfy the new
- * allocation
- */
-- WARN_ON(trimmed_pages < needed_pages);
-+ WARN_ON(trimmed_pages < pages_to_trim);
- }
- }
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- /**
- * jit_allow_allocate() - check whether basic conditions are satisfied to allow
-@@ -3606,10 +3920,14 @@ static bool jit_allow_allocate(struct kbase_context *kctx,
- const struct base_jit_alloc_info *info,
- bool ignore_pressure_limit)
- {
-+#if MALI_USE_CSF
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+#else
- lockdep_assert_held(&kctx->jctx.lock);
-+#endif
-
--#if MALI_JIT_PRESSURE_LIMIT
-- if (likely(!ignore_pressure_limit) &&
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (!ignore_pressure_limit &&
- ((kctx->jit_phys_pages_limit <= kctx->jit_current_phys_pressure) ||
- (info->va_pages > (kctx->jit_phys_pages_limit - kctx->jit_current_phys_pressure)))) {
- dev_dbg(kctx->kbdev->dev,
-@@ -3618,7 +3936,7 @@ static bool jit_allow_allocate(struct kbase_context *kctx,
- kctx->jit_phys_pages_limit);
- return false;
- }
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- if (kctx->jit_current_allocations >= kctx->jit_max_allocations) {
- /* Too many current allocations */
-@@ -3644,123 +3962,156 @@ static bool jit_allow_allocate(struct kbase_context *kctx,
- return true;
- }
-
-+static struct kbase_va_region *
-+find_reasonable_region(const struct base_jit_alloc_info *info,
-+ struct list_head *pool_head, bool ignore_usage_id)
-+{
-+ struct kbase_va_region *closest_reg = NULL;
-+ struct kbase_va_region *walker;
-+ size_t current_diff = SIZE_MAX;
-+
-+ list_for_each_entry(walker, pool_head, jit_node) {
-+ if ((ignore_usage_id ||
-+ walker->jit_usage_id == info->usage_id) &&
-+ walker->jit_bin_id == info->bin_id &&
-+ meet_size_and_tiler_align_top_requirements(walker, info)) {
-+ size_t min_size, max_size, diff;
-+
-+ /*
-+ * The JIT allocations VA requirements have been met,
-+ * it's suitable but other allocations might be a
-+ * better fit.
-+ */
-+ min_size = min_t(size_t, walker->gpu_alloc->nents,
-+ info->commit_pages);
-+ max_size = max_t(size_t, walker->gpu_alloc->nents,
-+ info->commit_pages);
-+ diff = max_size - min_size;
-+
-+ if (current_diff > diff) {
-+ current_diff = diff;
-+ closest_reg = walker;
-+ }
-+
-+ /* The allocation is an exact match */
-+ if (current_diff == 0)
-+ break;
-+ }
-+ }
-+
-+ return closest_reg;
-+}
-+
- struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx,
- const struct base_jit_alloc_info *info,
- bool ignore_pressure_limit)
- {
- struct kbase_va_region *reg = NULL;
-+ struct kbase_sub_alloc *prealloc_sas[2] = { NULL, NULL };
-+ int i;
-
-+#if MALI_USE_CSF
-+ lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
-+#else
- lockdep_assert_held(&kctx->jctx.lock);
-+#endif
-
- if (!jit_allow_allocate(kctx, info, ignore_pressure_limit))
- return NULL;
-
--#if MALI_JIT_PRESSURE_LIMIT
-- if (!ignore_pressure_limit)
-- jit_trim_necessary_pages(kctx, info);
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#ifdef CONFIG_MALI_2MB_ALLOC
-+ /* Preallocate memory for the sub-allocation structs */
-+ for (i = 0; i != ARRAY_SIZE(prealloc_sas); ++i) {
-+ prealloc_sas[i] = kmalloc(sizeof(*prealloc_sas[i]), GFP_KERNEL);
-+ if (!prealloc_sas[i])
-+ goto end;
-+ }
-+#endif
-
-+ kbase_gpu_vm_lock(kctx);
- mutex_lock(&kctx->jit_evict_lock);
-
- /*
- * Scan the pool for an existing allocation which meets our
- * requirements and remove it.
- */
-- if (info->usage_id != 0) {
-+ if (info->usage_id != 0)
- /* First scan for an allocation with the same usage ID */
-- struct kbase_va_region *walker;
-- size_t current_diff = SIZE_MAX;
--
-- list_for_each_entry(walker, &kctx->jit_pool_head, jit_node) {
--
-- if (walker->jit_usage_id == info->usage_id &&
-- walker->jit_bin_id == info->bin_id &&
-- meet_size_and_tiler_align_top_requirements(
-- kctx, walker, info)) {
-- size_t min_size, max_size, diff;
--
-- /*
-- * The JIT allocations VA requirements have been
-- * met, it's suitable but other allocations
-- * might be a better fit.
-- */
-- min_size = min_t(size_t,
-- walker->gpu_alloc->nents,
-- info->commit_pages);
-- max_size = max_t(size_t,
-- walker->gpu_alloc->nents,
-- info->commit_pages);
-- diff = max_size - min_size;
--
-- if (current_diff > diff) {
-- current_diff = diff;
-- reg = walker;
-- }
--
-- /* The allocation is an exact match */
-- if (current_diff == 0)
-- break;
-- }
-- }
-- }
-+ reg = find_reasonable_region(info, &kctx->jit_pool_head, false);
-
-- if (!reg) {
-+ if (!reg)
- /* No allocation with the same usage ID, or usage IDs not in
- * use. Search for an allocation we can reuse.
- */
-- struct kbase_va_region *walker;
-- size_t current_diff = SIZE_MAX;
--
-- list_for_each_entry(walker, &kctx->jit_pool_head, jit_node) {
--
-- if (walker->jit_bin_id == info->bin_id &&
-- meet_size_and_tiler_align_top_requirements(
-- kctx, walker, info)) {
-- size_t min_size, max_size, diff;
--
-- /*
-- * The JIT allocations VA requirements have been
-- * met, it's suitable but other allocations
-- * might be a better fit.
-- */
-- min_size = min_t(size_t,
-- walker->gpu_alloc->nents,
-- info->commit_pages);
-- max_size = max_t(size_t,
-- walker->gpu_alloc->nents,
-- info->commit_pages);
-- diff = max_size - min_size;
--
-- if (current_diff > diff) {
-- current_diff = diff;
-- reg = walker;
-- }
--
-- /* The allocation is an exact match, so stop
-- * looking.
-- */
-- if (current_diff == 0)
-- break;
-- }
-- }
-- }
-+ reg = find_reasonable_region(info, &kctx->jit_pool_head, true);
-
- if (reg) {
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ size_t needed_pages = 0;
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-+ int ret;
-+
- /*
- * Remove the found region from the pool and add it to the
- * active list.
- */
- list_move(®->jit_node, &kctx->jit_active_head);
-
-+ WARN_ON(reg->gpu_alloc->evicted);
-+
- /*
- * Remove the allocation from the eviction list as it's no
- * longer eligible for eviction. This must be done before
- * dropping the jit_evict_lock
- */
- list_del_init(®->gpu_alloc->evict_node);
-+
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (!ignore_pressure_limit) {
-+ if (info->commit_pages > reg->gpu_alloc->nents)
-+ needed_pages = info->commit_pages -
-+ reg->gpu_alloc->nents;
-+
-+ /* Update early the recycled JIT region's estimate of
-+ * used_pages to ensure it doesn't get trimmed
-+ * undesirably. This is needed as the recycled JIT
-+ * region has been added to the active list but the
-+ * number of used pages for it would be zero, so it
-+ * could get trimmed instead of other allocations only
-+ * to be regrown later resulting in a breach of the JIT
-+ * physical pressure limit.
-+ * Also that trimming would disturb the accounting of
-+ * physical pages, i.e. the VM stats, as the number of
-+ * backing pages would have changed when the call to
-+ * kbase_mem_evictable_unmark_reclaim is made.
-+ *
-+ * The second call to update pressure at the end of
-+ * this function would effectively be a nop.
-+ */
-+ kbase_jit_report_update_pressure(
-+ kctx, reg, info->va_pages,
-+ KBASE_JIT_REPORT_ON_ALLOC_OR_FREE);
-+
-+ kbase_jit_request_phys_increase_locked(kctx,
-+ needed_pages);
-+ }
-+#endif
- mutex_unlock(&kctx->jit_evict_lock);
-
-- if (kbase_jit_grow(kctx, info, reg) < 0) {
-+ /* kbase_jit_grow() can release & reacquire 'kctx->reg_lock',
-+ * so any state protected by that lock might need to be
-+ * re-evaluated if more code is added here in future.
-+ */
-+ ret = kbase_jit_grow(kctx, info, reg, prealloc_sas);
-+
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (!ignore_pressure_limit)
-+ kbase_jit_done_phys_increase(kctx, needed_pages);
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-+
-+ kbase_gpu_vm_unlock(kctx);
-+
-+ if (ret < 0) {
- /*
- * An update to an allocation from the pool failed,
- * chances are slim a new allocation would fair any
-@@ -3770,10 +4121,21 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx,
- dev_dbg(kctx->kbdev->dev,
- "JIT allocation resize failed: va_pages 0x%llx, commit_pages 0x%llx\n",
- info->va_pages, info->commit_pages);
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ /* Undo the early change made to the recycled JIT
-+ * region's estimate of used_pages.
-+ */
-+ if (!ignore_pressure_limit) {
-+ kbase_jit_report_update_pressure(
-+ kctx, reg, 0,
-+ KBASE_JIT_REPORT_ON_ALLOC_OR_FREE);
-+ }
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
- mutex_lock(&kctx->jit_evict_lock);
- list_move(®->jit_node, &kctx->jit_pool_head);
- mutex_unlock(&kctx->jit_evict_lock);
-- return NULL;
-+ reg = NULL;
-+ goto end;
- }
- } else {
- /* No suitable JIT allocation was found so create a new one */
-@@ -3783,15 +4145,28 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx,
- BASEP_MEM_NO_USER_FREE;
- u64 gpu_addr;
-
-- mutex_unlock(&kctx->jit_evict_lock);
--
-+#if !MALI_USE_CSF
- if (info->flags & BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP)
- flags |= BASE_MEM_TILER_ALIGN_TOP;
-+#endif /* !MALI_USE_CSF */
-
- flags |= base_mem_group_id_set(kctx->jit_group_id);
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (!ignore_pressure_limit) {
-+ flags |= BASEP_MEM_PERFORM_JIT_TRIM;
-+ /* The corresponding call to 'done_phys_increase' would
-+ * be made inside the kbase_mem_alloc().
-+ */
-+ kbase_jit_request_phys_increase_locked(
-+ kctx, info->commit_pages);
-+ }
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-+
-+ mutex_unlock(&kctx->jit_evict_lock);
-+ kbase_gpu_vm_unlock(kctx);
-
- reg = kbase_mem_alloc(kctx, info->va_pages, info->commit_pages,
-- info->extent, &flags, &gpu_addr);
-+ info->extension, &flags, &gpu_addr);
- if (!reg) {
- /* Most likely not enough GPU virtual space left for
- * the new JIT allocation.
-@@ -3799,12 +4174,22 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx,
- dev_dbg(kctx->kbdev->dev,
- "Failed to allocate JIT memory: va_pages 0x%llx, commit_pages 0x%llx\n",
- info->va_pages, info->commit_pages);
-- return NULL;
-+ goto end;
- }
-
-- mutex_lock(&kctx->jit_evict_lock);
-- list_add(®->jit_node, &kctx->jit_active_head);
-- mutex_unlock(&kctx->jit_evict_lock);
-+ if (!ignore_pressure_limit) {
-+ /* Due to enforcing of pressure limit, kbase_mem_alloc
-+ * was instructed to perform the trimming which in turn
-+ * would have ensured that the new JIT allocation is
-+ * already in the jit_active_head list, so nothing to
-+ * do here.
-+ */
-+ WARN_ON(list_empty(®->jit_node));
-+ } else {
-+ mutex_lock(&kctx->jit_evict_lock);
-+ list_add(®->jit_node, &kctx->jit_active_head);
-+ mutex_unlock(&kctx->jit_evict_lock);
-+ }
- }
-
- trace_mali_jit_alloc(reg, info->id);
-@@ -3816,13 +4201,18 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx,
-
- reg->jit_usage_id = info->usage_id;
- reg->jit_bin_id = info->bin_id;
--#if MALI_JIT_PRESSURE_LIMIT
-+ reg->flags |= KBASE_REG_ACTIVE_JIT_ALLOC;
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- if (info->flags & BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE)
- reg->flags = reg->flags | KBASE_REG_HEAP_INFO_IS_SIZE;
- reg->heap_info_gpu_addr = info->heap_info_gpu_addr;
- kbase_jit_report_update_pressure(kctx, reg, info->va_pages,
- KBASE_JIT_REPORT_ON_ALLOC_OR_FREE);
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-+
-+end:
-+ for (i = 0; i != ARRAY_SIZE(prealloc_sas); ++i)
-+ kfree(prealloc_sas[i]);
-
- return reg;
- }
-@@ -3844,15 +4234,18 @@ void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg)
- div_u64(old_pages * (100 - kctx->trim_level), 100));
- u64 delta = old_pages - new_size;
-
-- if (delta)
-+ if (delta) {
-+ mutex_lock(&kctx->reg_lock);
- kbase_mem_shrink(kctx, reg, old_pages - delta);
-+ mutex_unlock(&kctx->reg_lock);
-+ }
- }
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- reg->heap_info_gpu_addr = 0;
- kbase_jit_report_update_pressure(kctx, reg, 0,
- KBASE_JIT_REPORT_ON_ALLOC_OR_FREE);
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- kctx->jit_current_allocations--;
- kctx->jit_current_allocations_per_bin[reg->jit_bin_id]--;
-@@ -3863,6 +4256,7 @@ void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg)
-
- kbase_gpu_vm_lock(kctx);
- reg->flags |= KBASE_REG_DONT_NEED;
-+ reg->flags &= ~KBASE_REG_ACTIVE_JIT_ALLOC;
- kbase_mem_shrink_cpu_mapping(kctx, reg, 0, reg->gpu_alloc->nents);
- kbase_gpu_vm_unlock(kctx);
-
-@@ -3875,6 +4269,7 @@ void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg)
- /* This allocation can't already be on a list. */
- WARN_ON(!list_empty(®->gpu_alloc->evict_node));
- list_add(®->gpu_alloc->evict_node, &kctx->evict_list);
-+ atomic_add(reg->gpu_alloc->nents, &kctx->evict_nents);
-
- list_move(®->jit_node, &kctx->jit_pool_head);
-
-@@ -3962,6 +4357,9 @@ void kbase_jit_term(struct kbase_context *kctx)
- kbase_mem_free_region(kctx, walker);
- mutex_lock(&kctx->jit_evict_lock);
- }
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ WARN_ON(kctx->jit_phys_pages_to_be_allocated);
-+#endif
- mutex_unlock(&kctx->jit_evict_lock);
- kbase_gpu_vm_unlock(kctx);
-
-@@ -3972,7 +4370,7 @@ void kbase_jit_term(struct kbase_context *kctx)
- cancel_work_sync(&kctx->jit_work);
- }
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- void kbase_trace_jit_report_gpu_mem_trace_enabled(struct kbase_context *kctx,
- struct kbase_va_region *reg, unsigned int flags)
- {
-@@ -4015,16 +4413,18 @@ void kbase_trace_jit_report_gpu_mem_trace_enabled(struct kbase_context *kctx,
- out:
- return;
- }
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- void kbase_jit_report_update_pressure(struct kbase_context *kctx,
- struct kbase_va_region *reg, u64 new_used_pages,
- unsigned int flags)
- {
- u64 diff;
-
-+#if !MALI_USE_CSF
- lockdep_assert_held(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
-
- trace_mali_jit_report_pressure(reg, new_used_pages,
- kctx->jit_current_phys_pressure + new_used_pages -
-@@ -4053,19 +4453,22 @@ void kbase_jit_report_update_pressure(struct kbase_context *kctx,
- }
-
- }
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
--bool kbase_has_exec_va_zone(struct kbase_context *kctx)
-+#if MALI_USE_CSF
-+static void kbase_jd_user_buf_unpin_pages(struct kbase_mem_phy_alloc *alloc)
- {
-- bool has_exec_va_zone;
-+ if (alloc->nents) {
-+ struct page **pages = alloc->imported.user_buf.pages;
-+ long i;
-
-- kbase_gpu_vm_lock(kctx);
-- has_exec_va_zone = (kctx->exec_va_start != U64_MAX);
-- kbase_gpu_vm_unlock(kctx);
-+ WARN_ON(alloc->nents != alloc->imported.user_buf.nr_pages);
-
-- return has_exec_va_zone;
-+ for (i = 0; i < alloc->nents; i++)
-+ put_page(pages[i]);
-+ }
- }
--
-+#endif
-
- int kbase_jd_user_buf_pin_pages(struct kbase_context *kctx,
- struct kbase_va_region *reg)
-@@ -4090,7 +4493,7 @@ int kbase_jd_user_buf_pin_pages(struct kbase_context *kctx,
- if (WARN_ON(reg->gpu_alloc->imported.user_buf.mm != current->mm))
- return -EINVAL;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
-+#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE
- pinned_pages = get_user_pages(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
-@@ -4102,24 +4505,30 @@ KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE
- reg->flags & KBASE_REG_GPU_WR,
- 0, pages, NULL);
- #endif
--#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
-+#elif KERNEL_VERSION(4, 9, 0) > LINUX_VERSION_CODE
- pinned_pages = get_user_pages_remote(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
- reg->flags & KBASE_REG_GPU_WR,
- 0, pages, NULL);
--#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
-+#elif KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE
- pinned_pages = get_user_pages_remote(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
- pages, NULL);
--#else
-+#elif KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE
- pinned_pages = get_user_pages_remote(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
- pages, NULL, NULL);
-+#else
-+ pinned_pages = get_user_pages_remote(mm,
-+ address,
-+ alloc->imported.user_buf.nr_pages,
-+ reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
-+ pages, NULL, NULL);
- #endif
-
- if (pinned_pages <= 0)
-@@ -4232,12 +4641,16 @@ static void kbase_jd_user_buf_unmap(struct kbase_context *kctx,
- DMA_BIDIRECTIONAL);
- if (writeable)
- set_page_dirty_lock(pages[i]);
-+#if !MALI_USE_CSF
- put_page(pages[i]);
- pages[i] = NULL;
-+#endif
-
- size -= local_size;
- }
-+#if !MALI_USE_CSF
- alloc->nents = 0;
-+#endif
- }
-
- int kbase_mem_copy_to_pinned_user_pages(struct page **dest_pages,
-@@ -4296,7 +4709,8 @@ struct kbase_mem_phy_alloc *kbase_map_external_resource(
- goto exit;
-
- reg->gpu_alloc->imported.user_buf.current_mapping_usage_count++;
-- if (1 == reg->gpu_alloc->imported.user_buf.current_mapping_usage_count) {
-+ if (reg->gpu_alloc->imported.user_buf
-+ .current_mapping_usage_count == 1) {
- err = kbase_jd_user_buf_map(kctx, reg);
- if (err) {
- reg->gpu_alloc->imported.user_buf.current_mapping_usage_count--;
-@@ -4331,7 +4745,7 @@ void kbase_unmap_external_resource(struct kbase_context *kctx,
- case KBASE_MEM_TYPE_IMPORTED_USER_BUF: {
- alloc->imported.user_buf.current_mapping_usage_count--;
-
-- if (0 == alloc->imported.user_buf.current_mapping_usage_count) {
-+ if (alloc->imported.user_buf.current_mapping_usage_count == 0) {
- bool writeable = true;
-
- if (!kbase_is_region_invalid_or_free(reg) &&
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h
-index 6e921ec..e9ac809 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_mem.h
-- * Base kernel memory APIs
-+ * DOC: Base kernel memory APIs
- */
-
- #ifndef _KBASE_MEM_H_
-@@ -35,7 +31,7 @@
- #endif
-
- #include <linux/kref.h>
--#include "mali_base_kernel.h"
-+#include <uapi/gpu/arm/midgard/mali_base_kernel.h>
- #include <mali_kbase_hw.h>
- #include "mali_kbase_pm.h"
- #include "mali_kbase_defs.h"
-@@ -48,10 +44,13 @@ static inline void kbase_process_page_usage_inc(struct kbase_context *kctx,
- /* Part of the workaround for uTLB invalid pages is to ensure we grow/shrink tmem by 4 pages at a time */
- #define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_8316 (2) /* round to 4 pages */
-
--/* Part of the workaround for PRLAM-9630 requires us to grow/shrink memory by 8 pages.
--The MMU reads in 8 page table entries from memory at a time, if we have more than one page fault within the same 8 pages and
--page tables are updated accordingly, the MMU does not re-read the page table entries from memory for the subsequent page table
--updates and generates duplicate page faults as the page table information used by the MMU is not valid. */
-+/* Part of the workaround for PRLAM-9630 requires us to grow/shrink memory by
-+ * 8 pages. The MMU reads in 8 page table entries from memory at a time, if we
-+ * have more than one page fault within the same 8 pages and page tables are
-+ * updated accordingly, the MMU does not re-read the page table entries from
-+ * memory for the subsequent page table updates and generates duplicate page
-+ * faults as the page table information used by the MMU is not valid.
-+ */
- #define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_9630 (3) /* round to 8 pages */
-
- #define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2 (0) /* round to 1 page */
-@@ -60,7 +59,8 @@ updates and generates duplicate page faults as the page table information used b
- #define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2)
- #define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_HW_ISSUE_8316 (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_8316)
- #define KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_HW_ISSUE_9630 (1u << KBASEP_TMEM_GROWABLE_BLOCKSIZE_PAGES_LOG2_HW_ISSUE_9630)
--/**
-+
-+/*
- * A CPU mapping
- */
- struct kbase_cpu_mapping {
-@@ -81,16 +81,15 @@ enum kbase_memory_type {
- };
-
- /* internal structure, mirroring base_mem_aliasing_info,
-- * but with alloc instead of a gpu va (handle) */
-+ * but with alloc instead of a gpu va (handle)
-+ */
- struct kbase_aliased {
- struct kbase_mem_phy_alloc *alloc; /* NULL for special, non-NULL for native */
- u64 offset; /* in pages */
- u64 length; /* in pages */
- };
-
--/**
-- * @brief Physical pages tracking object properties
-- */
-+/* Physical pages tracking object properties */
- #define KBASE_MEM_PHY_ALLOC_ACCESSED_CACHED (1u << 0)
- #define KBASE_MEM_PHY_ALLOC_LARGE (1u << 1)
-
-@@ -105,7 +104,13 @@ struct kbase_aliased {
- * updated as part of the change.
- *
- * @kref: number of users of this alloc
-- * @gpu_mappings: count number of times mapped on the GPU
-+ * @gpu_mappings: count number of times mapped on the GPU. Indicates the number
-+ * of references there are to the physical pages from different
-+ * GPU VA regions.
-+ * @kernel_mappings: count number of times mapped on the CPU, specifically in
-+ * the kernel. Indicates the number of references there are
-+ * to the physical pages to prevent flag changes or shrink
-+ * while maps are still held.
- * @nents: 0..N
- * @pages: N elements, only 0..nents are valid
- * @mappings: List of CPU mappings of this physical memory allocation.
-@@ -128,6 +133,7 @@ struct kbase_aliased {
- struct kbase_mem_phy_alloc {
- struct kref kref;
- atomic_t gpu_mappings;
-+ atomic_t kernel_mappings;
- size_t nents;
- struct tagged_addr *pages;
- struct list_head mappings;
-@@ -141,6 +147,7 @@ struct kbase_mem_phy_alloc {
-
- union {
- struct {
-+ struct kbase_context *kctx;
- struct dma_buf *dma_buf;
- struct dma_buf_attachment *dma_attachment;
- unsigned int current_mapping_usage_count;
-@@ -210,12 +217,36 @@ static inline void kbase_mem_phy_alloc_gpu_unmapped(struct kbase_mem_phy_alloc *
- KBASE_DEBUG_ASSERT(alloc);
- /* we only track mappings of NATIVE buffers */
- if (alloc->type == KBASE_MEM_TYPE_NATIVE)
-- if (0 > atomic_dec_return(&alloc->gpu_mappings)) {
-+ if (atomic_dec_return(&alloc->gpu_mappings) < 0) {
- pr_err("Mismatched %s:\n", __func__);
- dump_stack();
- }
- }
-
-+/**
-+ * kbase_mem_phy_alloc_kernel_mapped - Increment kernel_mappings
-+ * counter for a memory region to prevent commit and flag changes
-+ *
-+ * @alloc: Pointer to physical pages tracking object
-+ */
-+static inline void
-+kbase_mem_phy_alloc_kernel_mapped(struct kbase_mem_phy_alloc *alloc)
-+{
-+ atomic_inc(&alloc->kernel_mappings);
-+}
-+
-+/**
-+ * kbase_mem_phy_alloc_kernel_unmapped - Decrement kernel_mappings
-+ * counter for a memory region to allow commit and flag changes
-+ *
-+ * @alloc: Pointer to physical pages tracking object
-+ */
-+static inline void
-+kbase_mem_phy_alloc_kernel_unmapped(struct kbase_mem_phy_alloc *alloc)
-+{
-+ WARN_ON(atomic_dec_return(&alloc->kernel_mappings) < 0);
-+}
-+
- /**
- * kbase_mem_is_imported - Indicate whether a memory type is imported
- *
-@@ -248,7 +279,7 @@ static inline struct kbase_mem_phy_alloc *kbase_mem_phy_alloc_put(struct kbase_m
- }
-
- /**
-- * A GPU memory region, and attributes for CPU mappings.
-+ * struct kbase_va_region - A GPU memory region, and attributes for CPU mappings
- *
- * @rblink: Node in a red-black tree of memory regions within the same zone of
- * the GPU's virtual address space.
-@@ -262,13 +293,31 @@ static inline struct kbase_mem_phy_alloc *kbase_mem_phy_alloc_put(struct kbase_m
- * @threshold_pages: If non-zero and the amount of memory committed to a region
- * that can grow on page fault exceeds this number of pages
- * then the driver switches to incremental rendering.
-- * @extent: Number of pages allocated on page fault.
-+ * @flags: Flags
-+ * @extension: Number of pages allocated on page fault.
- * @cpu_alloc: The physical memory we mmap to the CPU when mapping this region.
- * @gpu_alloc: The physical memory we mmap to the GPU when mapping this region.
- * @jit_node: Links to neighboring regions in the just-in-time memory pool.
- * @jit_usage_id: The last just-in-time memory usage ID for this region.
- * @jit_bin_id: The just-in-time memory bin this region came from.
- * @va_refcnt: Number of users of this region. Protected by reg_lock.
-+ * @heap_info_gpu_addr: Pointer to an object in GPU memory defining an end of
-+ * an allocated region
-+ * The object can be one of:
-+ * - u32 value defining the size of the region
-+ * - u64 pointer first unused byte in the region
-+ * The interpretation of the object depends on
-+ * BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE flag in
-+ * jit_info_flags - if it is set, the heap info object
-+ * should be interpreted as size.
-+ * @used_pages: The current estimate of the number of pages used, which in
-+ * normal use is either:
-+ * - the initial estimate == va_pages
-+ * - the actual pages used, as found by a JIT usage report
-+ * Note that since the value is calculated from GPU memory after a
-+ * JIT usage report, at any point in time it is allowed to take a
-+ * random value that is no greater than va_pages (e.g. it may be
-+ * greater than gpu_alloc->nents)
- */
- struct kbase_va_region {
- struct rb_node rblink;
-@@ -308,8 +357,13 @@ struct kbase_va_region {
- #define KBASE_REG_SHARE_BOTH (1ul << 10)
-
- /* Space for 4 different zones */
--#define KBASE_REG_ZONE_MASK (3ul << 11)
--#define KBASE_REG_ZONE(x) (((x) & 3) << 11)
-+#define KBASE_REG_ZONE_MASK ((KBASE_REG_ZONE_MAX - 1ul) << 11)
-+#define KBASE_REG_ZONE(x) (((x) & (KBASE_REG_ZONE_MAX - 1ul)) << 11)
-+#define KBASE_REG_ZONE_IDX(x) (((x) & KBASE_REG_ZONE_MASK) >> 11)
-+
-+#if ((KBASE_REG_ZONE_MAX - 1) & 0x3) != (KBASE_REG_ZONE_MAX - 1)
-+#error KBASE_REG_ZONE_MAX too large for allocation of KBASE_REG_<...> bits
-+#endif
-
- /* GPU read access */
- #define KBASE_REG_GPU_RD (1ul<<13)
-@@ -328,14 +382,29 @@ struct kbase_va_region {
- /* Imported buffer is padded? */
- #define KBASE_REG_IMPORT_PAD (1ul << 21)
-
-+#if MALI_USE_CSF
-+/* CSF event memory */
-+#define KBASE_REG_CSF_EVENT (1ul << 22)
-+#else
- /* Bit 22 is reserved.
- *
-- * Do not remove, use the next unreserved bit for new flags */
-+ * Do not remove, use the next unreserved bit for new flags
-+ */
- #define KBASE_REG_RESERVED_BIT_22 (1ul << 22)
-+#endif
-
--/* The top of the initial commit is aligned to extent pages.
-- * Extent must be a power of 2 */
-+#if !MALI_USE_CSF
-+/* The top of the initial commit is aligned to extension pages.
-+ * Extent must be a power of 2
-+ */
- #define KBASE_REG_TILER_ALIGN_TOP (1ul << 23)
-+#else
-+/* Bit 23 is reserved.
-+ *
-+ * Do not remove, use the next unreserved bit for new flags
-+ */
-+#define KBASE_REG_RESERVED_BIT_23 (1ul << 23)
-+#endif /* !MALI_USE_CSF */
-
- /* Whilst this flag is set the GPU allocation is not supposed to be freed by
- * user space. The flag will remain set for the lifetime of JIT allocations.
-@@ -367,6 +436,9 @@ struct kbase_va_region {
- */
- #define KBASE_REG_HEAP_INFO_IS_SIZE (1ul << 27)
-
-+/* Allocation is actively used for JIT memory */
-+#define KBASE_REG_ACTIVE_JIT_ALLOC (1ul << 28)
-+
- #define KBASE_REG_ZONE_SAME_VA KBASE_REG_ZONE(0)
-
- /* only used with 32-bit clients */
-@@ -390,15 +462,21 @@ struct kbase_va_region {
- #define KBASE_REG_ZONE_EXEC_VA KBASE_REG_ZONE(2)
- #define KBASE_REG_ZONE_EXEC_VA_MAX_PAGES ((1ULL << 32) >> PAGE_SHIFT) /* 4 GB */
-
-+#if MALI_USE_CSF
-+#define KBASE_REG_ZONE_MCU_SHARED KBASE_REG_ZONE(3)
-+#define KBASE_REG_ZONE_MCU_SHARED_BASE (0x04000000ULL >> PAGE_SHIFT)
-+#define KBASE_REG_ZONE_MCU_SHARED_SIZE (((0x08000000ULL) >> PAGE_SHIFT) - \
-+ KBASE_REG_ZONE_MCU_SHARED_BASE)
-+#endif
-
- unsigned long flags;
-- size_t extent;
-+ size_t extension;
- struct kbase_mem_phy_alloc *cpu_alloc;
- struct kbase_mem_phy_alloc *gpu_alloc;
- struct list_head jit_node;
- u16 jit_usage_id;
- u8 jit_bin_id;
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /* Pointer to an object in GPU memory defining an end of an allocated
- * region
- *
-@@ -423,7 +501,7 @@ struct kbase_va_region {
- * gpu_alloc->nents)
- */
- size_t used_pages;
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- int va_refcnt;
- };
-@@ -471,7 +549,7 @@ static inline struct kbase_va_region *kbase_va_region_alloc_get(
- WARN_ON(!region->va_refcnt);
-
- /* non-atomic as kctx->reg_lock is held */
-- dev_dbg(kctx->kbdev->dev, "va_refcnt %d before get %p\n",
-+ dev_dbg(kctx->kbdev->dev, "va_refcnt %d before get %pK\n",
- region->va_refcnt, (void *)region);
- region->va_refcnt++;
-
-@@ -488,7 +566,7 @@ static inline struct kbase_va_region *kbase_va_region_alloc_put(
-
- /* non-atomic as kctx->reg_lock is held */
- region->va_refcnt--;
-- dev_dbg(kctx->kbdev->dev, "va_refcnt %d after put %p\n",
-+ dev_dbg(kctx->kbdev->dev, "va_refcnt %d after put %pK\n",
- region->va_refcnt, (void *)region);
- if (!region->va_refcnt)
- kbase_region_refcnt_free(region);
-@@ -580,6 +658,7 @@ static inline struct kbase_mem_phy_alloc *kbase_alloc_create(
-
- kref_init(&alloc->kref);
- atomic_set(&alloc->gpu_mappings, 0);
-+ atomic_set(&alloc->kernel_mappings, 0);
- alloc->nents = 0;
- alloc->pages = (void *)(alloc + 1);
- INIT_LIST_HEAD(&alloc->mappings);
-@@ -1019,7 +1098,9 @@ struct kbase_va_region *kbase_find_region_enclosing_address(
- struct rb_root *rbtree, u64 gpu_addr);
-
- /**
-- * @brief Check that a pointer is actually a valid region.
-+ * Check that a pointer is actually a valid region.
-+ * @kctx: kbase context containing the region
-+ * @gpu_addr: pointer to check
- *
- * Must be called with context lock held.
- */
-@@ -1048,7 +1129,7 @@ bool kbase_check_import_flags(unsigned long flags);
- * @flags: The flags passed from user space
- * @va_pages: The size of the requested region, in pages.
- * @commit_pages: Number of pages to commit initially.
-- * @extent: Number of pages to grow by on GPU page fault and/or alignment
-+ * @extension: Number of pages to grow by on GPU page fault and/or alignment
- * (depending on flags)
- *
- * Makes checks on the size parameters passed in from user space for a memory
-@@ -1057,7 +1138,7 @@ bool kbase_check_import_flags(unsigned long flags);
- * Return: 0 if sizes are valid for these flags, negative error code otherwise
- */
- int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags,
-- u64 va_pages, u64 commit_pages, u64 extent);
-+ u64 va_pages, u64 commit_pages, u64 extension);
-
- /**
- * kbase_update_region_flags - Convert user space flags to kernel region flags
-@@ -1080,14 +1161,21 @@ void kbase_gpu_vm_unlock(struct kbase_context *kctx);
- int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size);
-
- /**
-- * @brief Register region and map it on the GPU.
-+ * Register region and map it on the GPU.
-+ * @kctx: kbase context containing the region
-+ * @reg: the region to add
-+ * @addr: the address to insert the region at
-+ * @nr_pages: the number of pages in the region
-+ * @align: the minimum alignment in pages
- *
- * Call kbase_add_va_region() and map the region on the GPU.
- */
- int kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, u64 addr, size_t nr_pages, size_t align);
-
- /**
-- * @brief Remove the region from the GPU and unregister it.
-+ * Remove the region from the GPU and unregister it.
-+ * @kctx: KBase context
-+ * @reg: The region to remove
- *
- * Must be called with context lock held.
- */
-@@ -1136,20 +1224,23 @@ void kbase_mmu_disable_as(struct kbase_device *kbdev, int as_nr);
-
- void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat);
-
--/** Dump the MMU tables to a buffer
-+/**
-+ * kbase_mmu_dump() - Dump the MMU tables to a buffer.
- *
-- * This function allocates a buffer (of @c nr_pages pages) to hold a dump of the MMU tables and fills it. If the
-- * buffer is too small then the return value will be NULL.
-+ * This function allocates a buffer (of @c nr_pages pages) to hold a dump
-+ * of the MMU tables and fills it. If the buffer is too small
-+ * then the return value will be NULL.
- *
- * The GPU vm lock must be held when calling this function.
- *
-- * The buffer returned should be freed with @ref vfree when it is no longer required.
-+ * The buffer returned should be freed with @ref vfree when it is no longer
-+ * required.
- *
-- * @param[in] kctx The kbase context to dump
-- * @param[in] nr_pages The number of pages to allocate for the buffer.
-+ * @kctx: The kbase context to dump
-+ * @nr_pages: The number of pages to allocate for the buffer.
- *
-- * @return The address of the buffer containing the MMU dump or NULL on error (including if the @c nr_pages is too
-- * small)
-+ * Return: The address of the buffer containing the MMU dump or NULL on error
-+ * (including if the @c nr_pages is too small)
- */
- void *kbase_mmu_dump(struct kbase_context *kctx, int nr_pages);
-
-@@ -1174,25 +1265,27 @@ void kbase_os_mem_map_lock(struct kbase_context *kctx);
- void kbase_os_mem_map_unlock(struct kbase_context *kctx);
-
- /**
-- * @brief Update the memory allocation counters for the current process
-+ * kbasep_os_process_page_usage_update() - Update the memory allocation
-+ * counters for the current process.
- *
-- * OS specific call to updates the current memory allocation counters for the current process with
-- * the supplied delta.
-+ * OS specific call to updates the current memory allocation counters
-+ * for the current process with the supplied delta.
- *
-- * @param[in] kctx The kbase context
-- * @param[in] pages The desired delta to apply to the memory usage counters.
-+ * @kctx: The kbase context
-+ * @pages: The desired delta to apply to the memory usage counters.
- */
-
- void kbasep_os_process_page_usage_update(struct kbase_context *kctx, int pages);
-
- /**
-- * @brief Add to the memory allocation counters for the current process
-+ * kbase_process_page_usage_inc() - Add to the memory allocation counters for
-+ * the current process
- *
-- * OS specific call to add to the current memory allocation counters for the current process by
-- * the supplied amount.
-+ * OS specific call to add to the current memory allocation counters for
-+ * the current process by the supplied amount.
- *
-- * @param[in] kctx The kernel base context used for the allocation.
-- * @param[in] pages The desired delta to apply to the memory usage counters.
-+ * @kctx: The kernel base context used for the allocation.
-+ * @pages: The desired delta to apply to the memory usage counters.
- */
-
- static inline void kbase_process_page_usage_inc(struct kbase_context *kctx, int pages)
-@@ -1201,13 +1294,14 @@ static inline void kbase_process_page_usage_inc(struct kbase_context *kctx, int
- }
-
- /**
-- * @brief Subtract from the memory allocation counters for the current process
-+ * kbase_process_page_usage_dec() - Subtract from the memory allocation
-+ * counters for the current process.
- *
-- * OS specific call to subtract from the current memory allocation counters for the current process by
-- * the supplied amount.
-+ * OS specific call to subtract from the current memory allocation counters
-+ * for the current process by the supplied amount.
- *
-- * @param[in] kctx The kernel base context used for the allocation.
-- * @param[in] pages The desired delta to apply to the memory usage counters.
-+ * @kctx: The kernel base context used for the allocation.
-+ * @pages: The desired delta to apply to the memory usage counters.
- */
-
- static inline void kbase_process_page_usage_dec(struct kbase_context *kctx, int pages)
-@@ -1332,15 +1426,15 @@ struct tagged_addr *kbase_alloc_phy_pages_helper_locked(
- struct kbase_sub_alloc **prealloc_sa);
-
- /**
--* @brief Free physical pages.
--*
--* Frees \a nr_pages and updates the alloc object.
--*
--* @param[in] alloc allocation object to free pages from
--* @param[in] nr_pages_to_free number of physical pages to free
--*
--* Return: 0 on success, otherwise a negative error code
--*/
-+ * kbase_free_phy_pages_helper() - Free physical pages.
-+ *
-+ * Frees \a nr_pages and updates the alloc object.
-+ *
-+ * @alloc: allocation object to free pages from
-+ * @nr_pages_to_free: number of physical pages to free
-+ *
-+ * Return: 0 on success, otherwise a negative error code
-+ */
- int kbase_free_phy_pages_helper(struct kbase_mem_phy_alloc *alloc, size_t nr_pages_to_free);
-
- /**
-@@ -1370,7 +1464,8 @@ static inline void kbase_set_dma_addr(struct page *p, dma_addr_t dma_addr)
- /* on 32-bit ARM with LPAE dma_addr_t becomes larger, but the
- * private field stays the same. So we have to be clever and
- * use the fact that we only store DMA addresses of whole pages,
-- * so the low bits should be zero */
-+ * so the low bits should be zero
-+ */
- KBASE_DEBUG_ASSERT(!(dma_addr & (PAGE_SIZE - 1)));
- set_page_private(p, dma_addr >> PAGE_SHIFT);
- } else {
-@@ -1392,26 +1487,11 @@ static inline void kbase_clear_dma_addr(struct page *p)
- }
-
- /**
-- * @brief Process a page fault.
-- *
-- * @param[in] data work_struct passed by queue_work()
-- */
--void page_fault_worker(struct work_struct *data);
--
--/**
-- * @brief Process a bus fault.
-- *
-- * @param[in] data work_struct passed by queue_work()
-- */
--void bus_fault_worker(struct work_struct *data);
--
--/**
-- * @brief Flush MMU workqueues.
-+ * kbase_flush_mmu_wqs() - Flush MMU workqueues.
-+ * @kbdev: Device pointer.
- *
- * This function will cause any outstanding page or bus faults to be processed.
- * It should be called prior to powering off the GPU.
-- *
-- * @param[in] kbdev Device pointer
- */
- void kbase_flush_mmu_wqs(struct kbase_device *kbdev);
-
-@@ -1437,7 +1517,7 @@ void kbase_sync_single_for_device(struct kbase_device *kbdev, dma_addr_t handle,
- void kbase_sync_single_for_cpu(struct kbase_device *kbdev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir);
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- /**
- * kbase_jit_debugfs_init - Add per context debugfs entry for JIT.
- * @kctx: kbase context
-@@ -1497,7 +1577,7 @@ bool kbase_jit_evict(struct kbase_context *kctx);
- */
- void kbase_jit_term(struct kbase_context *kctx);
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /**
- * kbase_trace_jit_report_gpu_mem_trace_enabled - variant of
- * kbase_trace_jit_report_gpu_mem() that should only be called once the
-@@ -1508,7 +1588,7 @@ void kbase_jit_term(struct kbase_context *kctx);
- */
- void kbase_trace_jit_report_gpu_mem_trace_enabled(struct kbase_context *kctx,
- struct kbase_va_region *reg, unsigned int flags);
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- /**
- * kbase_trace_jit_report_gpu_mem - Trace information about the GPU memory used
-@@ -1530,7 +1610,7 @@ void kbase_trace_jit_report_gpu_mem_trace_enabled(struct kbase_context *kctx,
- * been included. Also gives no opportunity for the compiler to mess up
- * inlining it.
- */
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- #define kbase_trace_jit_report_gpu_mem(kctx, reg, flags) \
- do { \
- if (trace_mali_jit_report_gpu_mem_enabled()) \
-@@ -1540,9 +1620,9 @@ void kbase_trace_jit_report_gpu_mem_trace_enabled(struct kbase_context *kctx,
- #else
- #define kbase_trace_jit_report_gpu_mem(kctx, reg, flags) \
- CSTD_NOP(kctx, reg, flags)
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /**
- * kbase_jit_report_update_pressure - safely update the JIT physical page
- * pressure and JIT region's estimate of used_pages
-@@ -1562,7 +1642,127 @@ void kbase_trace_jit_report_gpu_mem_trace_enabled(struct kbase_context *kctx,
- void kbase_jit_report_update_pressure(struct kbase_context *kctx,
- struct kbase_va_region *reg, u64 new_used_pages,
- unsigned int flags);
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+
-+/**
-+ * jit_trim_necessary_pages() - calculate and trim the least pages possible to
-+ * satisfy a new JIT allocation
-+ *
-+ * @kctx: Pointer to the kbase context
-+ * @needed_pages: Number of JIT physical pages by which trimming is requested.
-+ * The actual number of pages trimmed could differ.
-+ *
-+ * Before allocating a new just-in-time memory region or reusing a previous
-+ * one, ensure that the total JIT physical page usage also will not exceed the
-+ * pressure limit.
-+ *
-+ * If there are no reported-on allocations, then we already guarantee this will
-+ * be the case - because our current pressure then only comes from the va_pages
-+ * of each JIT region, hence JIT physical page usage is guaranteed to be
-+ * bounded by this.
-+ *
-+ * However as soon as JIT allocations become "reported on", the pressure is
-+ * lowered to allow new JIT regions to be allocated. It is after such a point
-+ * that the total JIT physical page usage could (either now or in the future on
-+ * a grow-on-GPU-page-fault) exceed the pressure limit, but only on newly
-+ * allocated JIT regions. Hence, trim any "reported on" regions.
-+ *
-+ * Any pages freed will go into the pool and be allocated from there in
-+ * kbase_mem_alloc().
-+ */
-+void kbase_jit_trim_necessary_pages(struct kbase_context *kctx,
-+ size_t needed_pages);
-+
-+/*
-+ * Same as kbase_jit_request_phys_increase(), except that Caller is supposed
-+ * to take jit_evict_lock also on @kctx before calling this function.
-+ */
-+static inline void
-+kbase_jit_request_phys_increase_locked(struct kbase_context *kctx,
-+ size_t needed_pages)
-+{
-+#if !MALI_USE_CSF
-+ lockdep_assert_held(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
-+ lockdep_assert_held(&kctx->reg_lock);
-+ lockdep_assert_held(&kctx->jit_evict_lock);
-+
-+ kctx->jit_phys_pages_to_be_allocated += needed_pages;
-+
-+ kbase_jit_trim_necessary_pages(kctx,
-+ kctx->jit_phys_pages_to_be_allocated);
-+}
-+
-+/**
-+ * kbase_jit_request_phys_increase() - Increment the backing pages count and do
-+ * the required trimming before allocating pages for a JIT allocation.
-+ *
-+ * @kctx: Pointer to the kbase context
-+ * @needed_pages: Number of pages to be allocated for the JIT allocation.
-+ *
-+ * This function needs to be called before allocating backing pages for a
-+ * just-in-time memory region. The backing pages are currently allocated when,
-+ *
-+ * - A new JIT region is created.
-+ * - An old JIT region is reused from the cached pool.
-+ * - GPU page fault occurs for the active JIT region.
-+ * - Backing is grown for the JIT region through the commit ioctl.
-+ *
-+ * This function would ensure that the total JIT physical page usage does not
-+ * exceed the pressure limit even when the backing pages get allocated
-+ * simultaneously for multiple JIT allocations from different threads.
-+ *
-+ * There should be a matching call to kbase_jit_done_phys_increase(), after
-+ * the pages have been allocated and accounted against the active JIT
-+ * allocation.
-+ *
-+ * Caller is supposed to take reg_lock on @kctx before calling this function.
-+ */
-+static inline void kbase_jit_request_phys_increase(struct kbase_context *kctx,
-+ size_t needed_pages)
-+{
-+#if !MALI_USE_CSF
-+ lockdep_assert_held(&kctx->jctx.lock);
-+#endif /* !MALI_USE_CSF */
-+ lockdep_assert_held(&kctx->reg_lock);
-+
-+ mutex_lock(&kctx->jit_evict_lock);
-+ kbase_jit_request_phys_increase_locked(kctx, needed_pages);
-+ mutex_unlock(&kctx->jit_evict_lock);
-+}
-+
-+/**
-+ * kbase_jit_done_phys_increase() - Decrement the backing pages count after the
-+ * allocation of pages for a JIT allocation.
-+ *
-+ * @kctx: Pointer to the kbase context
-+ * @needed_pages: Number of pages that were allocated for the JIT allocation.
-+ *
-+ * This function should be called after backing pages have been allocated and
-+ * accounted against the active JIT allocation.
-+ * The call should be made when the following have been satisfied:
-+ * when the allocation is on the jit_active_head.
-+ * when additional needed_pages have been allocated.
-+ * kctx->reg_lock was held during the above and has not yet been unlocked.
-+ * Failure to call this function before unlocking the kctx->reg_lock when
-+ * either the above have changed may result in over-accounting the memory.
-+ * This ensures kbase_jit_trim_necessary_pages() gets a consistent count of
-+ * the memory.
-+ *
-+ * A matching call to kbase_jit_request_phys_increase() should have been made,
-+ * before the allocation of backing pages.
-+ *
-+ * Caller is supposed to take reg_lock on @kctx before calling this function.
-+ */
-+static inline void kbase_jit_done_phys_increase(struct kbase_context *kctx,
-+ size_t needed_pages)
-+{
-+ lockdep_assert_held(&kctx->reg_lock);
-+
-+ WARN_ON(kctx->jit_phys_pages_to_be_allocated < needed_pages);
-+
-+ kctx->jit_phys_pages_to_be_allocated -= needed_pages;
-+}
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- /**
- * kbase_has_exec_va_zone - EXEC_VA zone predicate
-@@ -1693,6 +1893,63 @@ static inline void kbase_mem_pool_unlock(struct kbase_mem_pool *pool)
- */
- void kbase_mem_evictable_mark_reclaim(struct kbase_mem_phy_alloc *alloc);
-
-+#if MALI_USE_CSF
-+/**
-+ * kbase_link_event_mem_page - Add the new event memory region to the per
-+ * context list of event pages.
-+ * @kctx: Pointer to kbase context
-+ * @reg: Pointer to the region allocated for event memory.
-+ *
-+ * The region being linked shouldn't have been marked as free and should
-+ * have KBASE_REG_CSF_EVENT flag set for it.
-+ */
-+static inline void kbase_link_event_mem_page(struct kbase_context *kctx,
-+ struct kbase_va_region *reg)
-+{
-+ lockdep_assert_held(&kctx->reg_lock);
-+
-+ WARN_ON(reg->flags & KBASE_REG_FREE);
-+ WARN_ON(!(reg->flags & KBASE_REG_CSF_EVENT));
-+
-+ list_add(®->link, &kctx->csf.event_pages_head);
-+}
-+
-+/**
-+ * kbase_unlink_event_mem_page - Remove the event memory region from the per
-+ * context list of event pages.
-+ * @kctx: Pointer to kbase context
-+ * @reg: Pointer to the region allocated for event memory.
-+ *
-+ * The region being un-linked shouldn't have been marked as free and should
-+ * have KBASE_REG_CSF_EVENT flag set for it.
-+ */
-+static inline void kbase_unlink_event_mem_page(struct kbase_context *kctx,
-+ struct kbase_va_region *reg)
-+{
-+ lockdep_assert_held(&kctx->reg_lock);
-+
-+ WARN_ON(reg->flags & KBASE_REG_FREE);
-+ WARN_ON(!(reg->flags & KBASE_REG_CSF_EVENT));
-+
-+ list_del(®->link);
-+}
-+
-+/**
-+ * kbase_mcu_shared_interface_region_tracker_init - Initialize the rb tree to
-+ * manage the shared interface segment of MCU firmware address space.
-+ * @kbdev: Pointer to the kbase device
-+ *
-+ * Returns zero on success or negative error number on failure.
-+ */
-+int kbase_mcu_shared_interface_region_tracker_init(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_mcu_shared_interface_region_tracker_term - Teardown the rb tree
-+ * managing the shared interface segment of MCU firmware address space.
-+ * @kbdev: Pointer to the kbase device
-+ */
-+void kbase_mcu_shared_interface_region_tracker_term(struct kbase_device *kbdev);
-+#endif
-
- /**
- * kbase_mem_umm_map - Map dma-buf
-@@ -1742,7 +1999,6 @@ void kbase_mem_umm_unmap(struct kbase_context *kctx,
- int kbase_mem_do_sync_imported(struct kbase_context *kctx,
- struct kbase_va_region *reg, enum kbase_sync_type sync_fn);
-
--
- /**
- * kbase_mem_copy_to_pinned_user_pages - Memcpy from source input page to
- * an unaligned address at a given offset from the start of a target page.
-@@ -1768,4 +2024,76 @@ int kbase_mem_copy_to_pinned_user_pages(struct page **dest_pages,
- void *src_page, size_t *to_copy, unsigned int nr_pages,
- unsigned int *target_page_nr, size_t offset);
-
-+/**
-+ * kbase_ctx_reg_zone_end_pfn - return the end Page Frame Number of @zone
-+ * @zone: zone to query
-+ *
-+ * Return: The end of the zone corresponding to @zone
-+ */
-+static inline u64 kbase_reg_zone_end_pfn(struct kbase_reg_zone *zone)
-+{
-+ return zone->base_pfn + zone->va_size_pages;
-+}
-+
-+/**
-+ * kbase_ctx_reg_zone_init - initialize a zone in @kctx
-+ * @kctx: Pointer to kbase context
-+ * @zone_bits: A KBASE_REG_ZONE_<...> to initialize
-+ * @base_pfn: Page Frame Number in GPU virtual address space for the start of
-+ * the Zone
-+ * @va_size_pages: Size of the Zone in pages
-+ */
-+static inline void kbase_ctx_reg_zone_init(struct kbase_context *kctx,
-+ unsigned long zone_bits,
-+ u64 base_pfn, u64 va_size_pages)
-+{
-+ struct kbase_reg_zone *zone;
-+
-+ lockdep_assert_held(&kctx->reg_lock);
-+ WARN_ON((zone_bits & KBASE_REG_ZONE_MASK) != zone_bits);
-+
-+ zone = &kctx->reg_zone[KBASE_REG_ZONE_IDX(zone_bits)];
-+ *zone = (struct kbase_reg_zone){
-+ .base_pfn = base_pfn, .va_size_pages = va_size_pages,
-+ };
-+}
-+
-+/**
-+ * kbase_ctx_reg_zone_get_nolock - get a zone from @kctx where the caller does
-+ * not have @kctx 's region lock
-+ * @kctx: Pointer to kbase context
-+ * @zone_bits: A KBASE_REG_ZONE_<...> to retrieve
-+ *
-+ * This should only be used in performance-critical paths where the code is
-+ * resilient to a race with the zone changing.
-+ *
-+ * Return: The zone corresponding to @zone_bits
-+ */
-+static inline struct kbase_reg_zone *
-+kbase_ctx_reg_zone_get_nolock(struct kbase_context *kctx,
-+ unsigned long zone_bits)
-+{
-+ WARN_ON((zone_bits & KBASE_REG_ZONE_MASK) != zone_bits);
-+
-+ return &kctx->reg_zone[KBASE_REG_ZONE_IDX(zone_bits)];
-+}
-+
-+/**
-+ * kbase_ctx_reg_zone_get - get a zone from @kctx
-+ * @kctx: Pointer to kbase context
-+ * @zone_bits: A KBASE_REG_ZONE_<...> to retrieve
-+ *
-+ * The get is not refcounted - there is no corresponding 'put' operation
-+ *
-+ * Return: The zone corresponding to @zone_bits
-+ */
-+static inline struct kbase_reg_zone *
-+kbase_ctx_reg_zone_get(struct kbase_context *kctx, unsigned long zone_bits)
-+{
-+ lockdep_assert_held(&kctx->reg_lock);
-+ WARN_ON((zone_bits & KBASE_REG_ZONE_MASK) != zone_bits);
-+
-+ return &kctx->reg_zone[KBASE_REG_ZONE_IDX(zone_bits)];
-+}
-+
- #endif /* _KBASE_MEM_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
-index b669f2a..21302c1 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_mem_linux.c
-- * Base kernel memory APIs, Linux implementation.
-+ * DOC: Base kernel memory APIs, Linux implementation.
- */
-
- #include <linux/compat.h>
-@@ -35,10 +31,9 @@
- #include <linux/fs.h>
- #include <linux/version.h>
- #include <linux/dma-mapping.h>
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) && \
-- (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
-+#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE)
- #include <linux/dma-attrs.h>
--#endif /* LINUX_VERSION_CODE >= 3.5.0 && < 4.8.0 */
-+#endif /* LINUX_VERSION_CODE < 4.8.0 */
- #include <linux/dma-buf.h>
- #include <linux/shrinker.h>
- #include <linux/cache.h>
-@@ -47,8 +42,11 @@
- #include <mali_kbase.h>
- #include <mali_kbase_mem_linux.h>
- #include <tl/mali_kbase_tracepoints.h>
--#include <mali_kbase_ioctl.h>
-+#include <uapi/gpu/arm/midgard/mali_kbase_ioctl.h>
- #include <mmu/mali_kbase_mmu.h>
-+#include <mali_kbase_caps.h>
-+#include <mali_kbase_trace_gpu_mem.h>
-+#include <mali_kbase_reset_gpu.h>
-
- #if ((KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE) || \
- (KERNEL_VERSION(5, 0, 0) > LINUX_VERSION_CODE))
-@@ -87,6 +85,12 @@
-
- #define IR_THRESHOLD_STEPS (256u)
-
-+#if MALI_USE_CSF
-+static int kbase_csf_cpu_mmap_user_reg_page(struct kbase_context *kctx,
-+ struct vm_area_struct *vma);
-+static int kbase_csf_cpu_mmap_user_io_pages(struct kbase_context *kctx,
-+ struct vm_area_struct *vma);
-+#endif
-
- static int kbase_vmap_phy_pages(struct kbase_context *kctx,
- struct kbase_va_region *reg, u64 offset_bytes, size_t size,
-@@ -107,6 +111,25 @@ static int kbase_mem_shrink_gpu_mapping(struct kbase_context *kctx,
- static struct kbase_va_region *kbase_find_event_mem_region(
- struct kbase_context *kctx, u64 gpu_addr)
- {
-+#if MALI_USE_CSF
-+ u64 gpu_pfn = gpu_addr >> PAGE_SHIFT;
-+ struct kbase_va_region *reg;
-+
-+ lockdep_assert_held(&kctx->reg_lock);
-+
-+ list_for_each_entry(reg, &kctx->csf.event_pages_head, link) {
-+ if ((reg->start_pfn <= gpu_pfn) &&
-+ (gpu_pfn < (reg->start_pfn + reg->nr_pages))) {
-+ if (WARN_ON(reg->flags & KBASE_REG_FREE))
-+ return NULL;
-+
-+ if (WARN_ON(!(reg->flags & KBASE_REG_CSF_EVENT)))
-+ return NULL;
-+
-+ return reg;
-+ }
-+ }
-+#endif
-
- return NULL;
- }
-@@ -269,8 +292,8 @@ void kbase_phy_alloc_mapping_put(struct kbase_context *kctx,
- }
-
- struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
-- u64 va_pages, u64 commit_pages, u64 extent, u64 *flags,
-- u64 *gpu_va)
-+ u64 va_pages, u64 commit_pages,
-+ u64 extension, u64 *flags, u64 *gpu_va)
- {
- int zone;
- struct kbase_va_region *reg;
-@@ -282,15 +305,20 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
- KBASE_DEBUG_ASSERT(gpu_va);
-
- dev = kctx->kbdev->dev;
-- dev_dbg(dev, "Allocating %lld va_pages, %lld commit_pages, %lld extent, 0x%llX flags\n",
-- va_pages, commit_pages, extent, *flags);
-+ dev_dbg(dev,
-+ "Allocating %lld va_pages, %lld commit_pages, %lld extension, 0x%llX flags\n",
-+ va_pages, commit_pages, extension, *flags);
-
-+#if MALI_USE_CSF
-+ *gpu_va = 0; /* return 0 on failure */
-+#else
- if (!(*flags & BASE_MEM_FLAG_MAP_FIXED))
- *gpu_va = 0; /* return 0 on failure */
- else
- dev_err(dev,
- "Keeping requested GPU VA of 0x%llx\n",
- (unsigned long long)*gpu_va);
-+#endif
-
- if (!kbase_check_alloc_flags(*flags)) {
- dev_warn(dev,
-@@ -299,7 +327,7 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
- goto bad_flags;
- }
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
- if (unlikely(kbase_ctx_flag(kctx, KCTX_INFINITE_CACHE))) {
- /* Mask coherency flags if infinite cache is enabled to prevent
- * the skipping of syncs from BASE side.
-@@ -325,7 +353,8 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
- *flags &= ~BASE_MEM_COHERENT_SYSTEM;
- }
-
-- if (kbase_check_alloc_sizes(kctx, *flags, va_pages, commit_pages, extent))
-+ if (kbase_check_alloc_sizes(kctx, *flags, va_pages, commit_pages,
-+ extension))
- goto bad_sizes;
-
- #ifdef CONFIG_MALI_MEMORY_FULLY_BACKED
-@@ -363,6 +392,15 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
- goto prepare_failed;
- }
-
-+ if (unlikely(reg->cpu_alloc != reg->gpu_alloc))
-+ *flags |= BASE_MEM_KERNEL_SYNC;
-+
-+ /* make sure base knows if the memory is actually cached or not */
-+ if (reg->flags & KBASE_REG_CPU_CACHED)
-+ *flags |= BASE_MEM_CACHED_CPU;
-+ else
-+ *flags &= ~BASE_MEM_CACHED_CPU;
-+
- if (*flags & BASE_MEM_GROW_ON_GPF) {
- unsigned int const ir_threshold = atomic_read(
- &kctx->kbdev->memdev.ir_threshold);
-@@ -372,12 +410,17 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
- } else
- reg->threshold_pages = 0;
-
-- if (*flags & (BASE_MEM_GROW_ON_GPF|BASE_MEM_TILER_ALIGN_TOP)) {
-- /* kbase_check_alloc_sizes() already checks extent is valid for
-- * assigning to reg->extent */
-- reg->extent = extent;
-+ if (*flags & BASE_MEM_GROW_ON_GPF) {
-+ /* kbase_check_alloc_sizes() already checks extension is valid for
-+ * assigning to reg->extension
-+ */
-+ reg->extension = extension;
-+#if !MALI_USE_CSF
-+ } else if (*flags & BASE_MEM_TILER_ALIGN_TOP) {
-+ reg->extension = extension;
-+#endif /* !MALI_USE_CSF */
- } else {
-- reg->extent = 0;
-+ reg->extension = 0;
- }
-
- if (kbase_alloc_phy_pages(reg, va_pages, commit_pages) != 0) {
-@@ -404,7 +447,6 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
- }
- }
-
--
- /* mmap needed to setup VA? */
- if (*flags & BASE_MEM_SAME_VA) {
- unsigned long cookie, cookie_nr;
-@@ -436,6 +478,17 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
- *gpu_va = reg->start_pfn << PAGE_SHIFT;
- }
-
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (*flags & BASEP_MEM_PERFORM_JIT_TRIM) {
-+ kbase_jit_done_phys_increase(kctx, commit_pages);
-+
-+ mutex_lock(&kctx->jit_evict_lock);
-+ WARN_ON(!list_empty(®->jit_node));
-+ list_add(®->jit_node, &kctx->jit_active_head);
-+ mutex_unlock(&kctx->jit_evict_lock);
-+ }
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-+
- kbase_gpu_vm_unlock(kctx);
- return reg;
-
-@@ -443,6 +496,13 @@ no_mmap:
- no_cookie:
- no_kern_mapping:
- no_mem:
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (*flags & BASEP_MEM_PERFORM_JIT_TRIM) {
-+ kbase_gpu_vm_lock(kctx);
-+ kbase_jit_done_phys_increase(kctx, commit_pages);
-+ kbase_gpu_vm_unlock(kctx);
-+ }
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
- kbase_mem_phy_alloc_put(reg->cpu_alloc);
- kbase_mem_phy_alloc_put(reg->gpu_alloc);
- invalid_flags:
-@@ -511,21 +571,36 @@ int kbase_mem_query(struct kbase_context *kctx,
- *out |= BASE_MEM_COHERENT_SYSTEM;
- if (KBASE_REG_SHARE_IN & reg->flags)
- *out |= BASE_MEM_COHERENT_LOCAL;
-- if (kctx->api_version >= KBASE_API_VERSION(11, 2)) {
-- /* Prior to 11.2, these were known about by user-side
-- * but we did not return them. Returning some of these
-- * caused certain clients that were not expecting them
-- * to fail, so we omit all of them as a special-case
-- * for compatibility reasons */
-+ if (mali_kbase_supports_mem_grow_on_gpf(kctx->api_version)) {
-+ /* Prior to this version, this was known about by
-+ * user-side but we did not return them. Returning
-+ * it caused certain clients that were not expecting
-+ * it to fail, so we omit it as a special-case for
-+ * compatibility reasons
-+ */
- if (KBASE_REG_PF_GROW & reg->flags)
- *out |= BASE_MEM_GROW_ON_GPF;
-+ }
-+ if (mali_kbase_supports_mem_protected(kctx->api_version)) {
-+ /* Prior to this version, this was known about by
-+ * user-side but we did not return them. Returning
-+ * it caused certain clients that were not expecting
-+ * it to fail, so we omit it as a special-case for
-+ * compatibility reasons
-+ */
- if (KBASE_REG_PROTECTED & reg->flags)
- *out |= BASE_MEM_PROTECTED;
- }
-+#if !MALI_USE_CSF
- if (KBASE_REG_TILER_ALIGN_TOP & reg->flags)
- *out |= BASE_MEM_TILER_ALIGN_TOP;
-+#endif /* !MALI_USE_CSF */
- if (!(KBASE_REG_GPU_CACHED & reg->flags))
- *out |= BASE_MEM_UNCACHED_GPU;
-+#if MALI_USE_CSF
-+ if (KBASE_REG_CSF_EVENT & reg->flags)
-+ *out |= BASE_MEM_CSF_EVENT;
-+#endif
- if (KBASE_REG_GPU_VA_SAME_4GB_PAGE & reg->flags)
- *out |= BASE_MEM_GPU_VA_SAME_4GB_PAGE;
-
-@@ -561,18 +636,17 @@ unsigned long kbase_mem_evictable_reclaim_count_objects(struct shrinker *s,
- struct shrink_control *sc)
- {
- struct kbase_context *kctx;
-- struct kbase_mem_phy_alloc *alloc;
-- unsigned long pages = 0;
-
- kctx = container_of(s, struct kbase_context, reclaim);
-
-- mutex_lock(&kctx->jit_evict_lock);
--
-- list_for_each_entry(alloc, &kctx->evict_list, evict_node)
-- pages += alloc->nents;
-+ WARN((sc->gfp_mask & __GFP_ATOMIC),
-+ "Shrinkers cannot be called for GFP_ATOMIC allocations. Check kernel mm for problems. gfp_mask==%x\n",
-+ sc->gfp_mask);
-+ WARN(in_atomic(),
-+ "Shrinker called whilst in atomic context. The caller must switch to using GFP_ATOMIC or similar. gfp_mask==%x\n",
-+ sc->gfp_mask);
-
-- mutex_unlock(&kctx->jit_evict_lock);
-- return pages;
-+ return atomic_read(&kctx->evict_nents);
- }
-
- /**
-@@ -604,6 +678,7 @@ unsigned long kbase_mem_evictable_reclaim_scan_objects(struct shrinker *s,
- unsigned long freed = 0;
-
- kctx = container_of(s, struct kbase_context, reclaim);
-+
- mutex_lock(&kctx->jit_evict_lock);
-
- list_for_each_entry_safe(alloc, tmp, &kctx->evict_list, evict_node) {
-@@ -630,6 +705,7 @@ unsigned long kbase_mem_evictable_reclaim_scan_objects(struct shrinker *s,
-
- kbase_free_phy_pages_helper(alloc, alloc->evicted);
- freed += alloc->evicted;
-+ WARN_ON(atomic_sub_return(alloc->evicted, &kctx->evict_nents) < 0);
- list_del_init(&alloc->evict_node);
-
- /*
-@@ -648,35 +724,20 @@ out_unlock:
- return freed;
- }
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
--static int kbase_mem_evictable_reclaim_shrink(struct shrinker *s,
-- struct shrink_control *sc)
--{
-- if (sc->nr_to_scan == 0)
-- return kbase_mem_evictable_reclaim_count_objects(s, sc);
--
-- return kbase_mem_evictable_reclaim_scan_objects(s, sc);
--}
--#endif
--
- int kbase_mem_evictable_init(struct kbase_context *kctx)
- {
- INIT_LIST_HEAD(&kctx->evict_list);
- mutex_init(&kctx->jit_evict_lock);
-
-- /* Register shrinker */
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
-- kctx->reclaim.shrink = kbase_mem_evictable_reclaim_shrink;
--#else
-+ atomic_set(&kctx->evict_nents, 0);
-+
- kctx->reclaim.count_objects = kbase_mem_evictable_reclaim_count_objects;
- kctx->reclaim.scan_objects = kbase_mem_evictable_reclaim_scan_objects;
--#endif
- kctx->reclaim.seeks = DEFAULT_SEEKS;
- /* Kernel versions prior to 3.1 :
-- * struct shrinker does not define batch */
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
-+ * struct shrinker does not define batch
-+ */
- kctx->reclaim.batch = 0;
--#endif
- register_shrinker(&kctx->reclaim);
- return 0;
- }
-@@ -705,6 +766,7 @@ void kbase_mem_evictable_mark_reclaim(struct kbase_mem_phy_alloc *alloc)
- kbdev,
- kctx->id,
- (u64)new_page_count);
-+ kbase_trace_gpu_mem_usage_dec(kbdev, kctx, alloc->nents);
- }
-
- /**
-@@ -731,6 +793,7 @@ void kbase_mem_evictable_unmark_reclaim(struct kbase_mem_phy_alloc *alloc)
- kbdev,
- kctx->id,
- (u64)new_page_count);
-+ kbase_trace_gpu_mem_usage_inc(kbdev, kctx, alloc->nents);
- }
-
- int kbase_mem_evictable_make(struct kbase_mem_phy_alloc *gpu_alloc)
-@@ -751,6 +814,7 @@ int kbase_mem_evictable_make(struct kbase_mem_phy_alloc *gpu_alloc)
- * can reclaim it.
- */
- list_add(&gpu_alloc->evict_node, &kctx->evict_list);
-+ atomic_add(gpu_alloc->nents, &kctx->evict_nents);
- mutex_unlock(&kctx->jit_evict_lock);
- kbase_mem_evictable_mark_reclaim(gpu_alloc);
-
-@@ -770,6 +834,7 @@ bool kbase_mem_evictable_unmake(struct kbase_mem_phy_alloc *gpu_alloc)
- * First remove the allocation from the eviction list as it's no
- * longer eligible for eviction.
- */
-+ WARN_ON(atomic_sub_return(gpu_alloc->nents, &kctx->evict_nents) < 0);
- list_del_init(&gpu_alloc->evict_node);
- mutex_unlock(&kctx->jit_evict_lock);
-
-@@ -840,7 +905,7 @@ int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned in
- real_flags |= KBASE_REG_SHARE_IN;
-
- /* now we can lock down the context, and find the region */
-- down_write(¤t->mm->mmap_sem);
-+ down_write(kbase_mem_get_process_mmap_lock());
- kbase_gpu_vm_lock(kctx);
-
- /* Validate the region */
-@@ -852,10 +917,18 @@ int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned in
- prev_needed = (KBASE_REG_DONT_NEED & reg->flags) == KBASE_REG_DONT_NEED;
- new_needed = (BASE_MEM_DONT_NEED & flags) == BASE_MEM_DONT_NEED;
- if (prev_needed != new_needed) {
-- /* Aliased allocations can't be made ephemeral */
-+ /* Aliased allocations can't be shrunk as the code doesn't
-+ * support looking up:
-+ * - all physical pages assigned to different GPU VAs
-+ * - CPU mappings for the physical pages at different vm_pgoff
-+ * (==GPU VA) locations.
-+ */
- if (atomic_read(®->cpu_alloc->gpu_mappings) > 1)
- goto out_unlock;
-
-+ if (atomic_read(®->cpu_alloc->kernel_mappings) > 0)
-+ goto out_unlock;
-+
- if (new_needed) {
- /* Only native allocations can be marked not needed */
- if (reg->cpu_alloc->type != KBASE_MEM_TYPE_NATIVE) {
-@@ -938,7 +1011,7 @@ int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned in
-
- out_unlock:
- kbase_gpu_vm_unlock(kctx);
-- up_write(¤t->mm->mmap_sem);
-+ up_write(kbase_mem_get_process_mmap_lock());
- out:
- return ret;
- }
-@@ -1029,7 +1102,7 @@ int kbase_mem_do_sync_imported(struct kbase_context *kctx,
- dir);
- #endif /* KBASE_MEM_ION_SYNC_WORKAROUND */
- break;
-- };
-+ }
-
- if (unlikely(ret))
- dev_warn(kctx->kbdev->dev,
-@@ -1056,6 +1129,8 @@ static void kbase_mem_umm_unmap_attachment(struct kbase_context *kctx,
- alloc->imported.umm.sgt, DMA_BIDIRECTIONAL);
- alloc->imported.umm.sgt = NULL;
-
-+ kbase_remove_dma_buf_usage(kctx, alloc);
-+
- memset(pa, 0xff, sizeof(*pa) * alloc->nents);
- alloc->nents = 0;
- }
-@@ -1123,6 +1198,7 @@ static int kbase_mem_umm_map_attachment(struct kbase_context *kctx,
-
- /* Update nents as we now have pages to map */
- alloc->nents = count;
-+ kbase_add_dma_buf_usage(kctx, alloc);
-
- return 0;
-
-@@ -1327,7 +1403,7 @@ static struct kbase_va_region *kbase_mem_from_umm(struct kbase_context *kctx,
- if (*flags & BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP)
- need_sync = true;
-
--#ifdef CONFIG_64BIT
-+#if IS_ENABLED(CONFIG_64BIT)
- if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) {
- /*
- * 64-bit tasks require us to reserve VA on the CPU that we use
-@@ -1383,7 +1459,8 @@ static struct kbase_va_region *kbase_mem_from_umm(struct kbase_context *kctx,
- reg->gpu_alloc->imported.umm.dma_attachment = dma_attachment;
- reg->gpu_alloc->imported.umm.current_mapping_usage_count = 0;
- reg->gpu_alloc->imported.umm.need_sync = need_sync;
-- reg->extent = 0;
-+ reg->gpu_alloc->imported.umm.kctx = kctx;
-+ reg->extension = 0;
-
- if (!IS_ENABLED(CONFIG_MALI_DMA_BUF_MAP_ON_DEMAND)) {
- int err;
-@@ -1436,6 +1513,7 @@ static struct kbase_va_region *kbase_mem_from_user_buffer(
- u32 cache_line_alignment = kbase_get_cache_line_alignment(kctx->kbdev);
- struct kbase_alloc_import_user_buf *user_buf;
- struct page **pages = NULL;
-+ int write;
-
- /* Flag supported only for dma-buf imported memory */
- if (*flags & BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP)
-@@ -1478,7 +1556,7 @@ static struct kbase_va_region *kbase_mem_from_user_buffer(
- if (*flags & BASE_MEM_IMPORT_SHARED)
- shared_zone = true;
-
--#ifdef CONFIG_64BIT
-+#if IS_ENABLED(CONFIG_64BIT)
- if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) {
- /*
- * 64-bit tasks require us to reserve VA on the CPU that we use
-@@ -1547,33 +1625,33 @@ static struct kbase_va_region *kbase_mem_from_user_buffer(
- *flags |= KBASE_MEM_IMPORT_HAVE_PAGES;
- }
-
-- down_read(¤t->mm->mmap_sem);
-+ down_read(kbase_mem_get_process_mmap_lock());
-+
-+ write = reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR);
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
-+#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE
- faulted_pages = get_user_pages(current, current->mm, address, *va_pages,
- #if KERNEL_VERSION(4, 4, 168) <= LINUX_VERSION_CODE && \
- KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE
-- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
-- pages, NULL);
-+ write ? FOLL_WRITE : 0, pages, NULL);
- #else
-- reg->flags & KBASE_REG_GPU_WR, 0, pages, NULL);
-+ write, 0, pages, NULL);
- #endif
--#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
-+#elif KERNEL_VERSION(4, 9, 0) > LINUX_VERSION_CODE
- faulted_pages = get_user_pages(address, *va_pages,
-- reg->flags & KBASE_REG_GPU_WR, 0, pages, NULL);
-+ write, 0, pages, NULL);
- #else
- faulted_pages = get_user_pages(address, *va_pages,
-- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
-- pages, NULL);
-+ write ? FOLL_WRITE : 0, pages, NULL);
- #endif
-
-- up_read(¤t->mm->mmap_sem);
-+ up_read(kbase_mem_get_process_mmap_lock());
-
- if (faulted_pages != *va_pages)
- goto fault_mismatch;
-
- reg->gpu_alloc->nents = 0;
-- reg->extent = 0;
-+ reg->extension = 0;
-
- if (pages) {
- struct device *dev = kctx->kbdev->dev;
-@@ -1672,10 +1750,11 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride,
- /* calculate the number of pages this alias will cover */
- *num_pages = nents * stride;
-
--#ifdef CONFIG_64BIT
-+#if IS_ENABLED(CONFIG_64BIT)
- if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) {
- /* 64-bit tasks must MMAP anyway, but not expose this address to
-- * clients */
-+ * clients
-+ */
- *flags |= BASE_MEM_NEED_MMAP;
- reg = kbase_alloc_free_region(&kctx->reg_rbtree_same, 0,
- *num_pages,
-@@ -1721,7 +1800,8 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride,
- goto bad_handle; /* must be > 0 */
- if (ai[i].length > stride)
- goto bad_handle; /* can't be larger than the
-- stride */
-+ * stride
-+ */
- reg->gpu_alloc->imported.alias.aliased[i].length = ai[i].length;
- } else {
- struct kbase_va_region *aliasing_reg;
-@@ -1736,6 +1816,15 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride,
- goto bad_handle; /* Not found/already free */
- if (aliasing_reg->flags & KBASE_REG_DONT_NEED)
- goto bad_handle; /* Ephemeral region */
-+ if (aliasing_reg->flags & KBASE_REG_NO_USER_FREE)
-+ goto bad_handle; /* JIT regions can't be
-+ * aliased. NO_USER_FREE flag
-+ * covers the entire lifetime
-+ * of JIT regions. The other
-+ * types of regions covered
-+ * by this flag also shall
-+ * not be aliased.
-+ */
- if (!(aliasing_reg->flags & KBASE_REG_GPU_CACHED))
- goto bad_handle; /* GPU uncached memory */
- if (!aliasing_reg->gpu_alloc)
-@@ -1743,16 +1832,18 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride,
- if (aliasing_reg->gpu_alloc->type != KBASE_MEM_TYPE_NATIVE)
- goto bad_handle; /* Not a native alloc */
- if (coherent != ((aliasing_reg->flags & KBASE_REG_SHARE_BOTH) != 0))
-- goto bad_handle;
-- /* Non-coherent memory cannot alias
-- coherent memory, and vice versa.*/
-+ goto bad_handle; /* Non-coherent memory cannot
-+ * alias coherent memory, and
-+ * vice versa.
-+ */
-
- /* check size against stride */
- if (!ai[i].length)
- goto bad_handle; /* must be > 0 */
- if (ai[i].length > stride)
- goto bad_handle; /* can't be larger than the
-- stride */
-+ * stride
-+ */
-
- alloc = aliasing_reg->gpu_alloc;
-
-@@ -1765,10 +1856,22 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride,
- reg->gpu_alloc->imported.alias.aliased[i].alloc = kbase_mem_phy_alloc_get(alloc);
- reg->gpu_alloc->imported.alias.aliased[i].length = ai[i].length;
- reg->gpu_alloc->imported.alias.aliased[i].offset = ai[i].offset;
-+
-+ /* Ensure the underlying alloc is marked as being
-+ * mapped at >1 different GPU VA immediately, even
-+ * though mapping might not happen until later.
-+ *
-+ * Otherwise, we would (incorrectly) allow shrinking of
-+ * the source region (aliasing_reg) and so freeing the
-+ * physical pages (without freeing the entire alloc)
-+ * whilst we still hold an implicit reference on those
-+ * physical pages.
-+ */
-+ kbase_mem_phy_alloc_gpu_mapped(alloc);
- }
- }
-
--#ifdef CONFIG_64BIT
-+#if IS_ENABLED(CONFIG_64BIT)
- if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) {
- /* Bind to a cookie */
- if (bitmap_empty(kctx->cookies, BITS_PER_LONG)) {
-@@ -1803,11 +1906,15 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride,
-
- return gpu_va;
-
--#ifdef CONFIG_64BIT
-+#if IS_ENABLED(CONFIG_64BIT)
- no_cookie:
- #endif
- no_mmap:
- bad_handle:
-+ /* Marking the source allocs as not being mapped on the GPU and putting
-+ * them is handled by putting reg's allocs, so no rollback of those
-+ * actions is done here.
-+ */
- kbase_gpu_vm_unlock(kctx);
- no_aliased_array:
- invalid_flags:
-@@ -1887,7 +1994,7 @@ int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type,
- sizeof(user_buffer))) {
- reg = NULL;
- } else {
--#ifdef CONFIG_COMPAT
-+#if IS_ENABLED(CONFIG_COMPAT)
- if (kbase_ctx_flag(kctx, KCTX_COMPAT))
- uptr = compat_ptr(user_buffer.ptr);
- else
-@@ -2024,7 +2131,7 @@ static int kbase_mem_shrink_gpu_mapping(struct kbase_context *const kctx,
- int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages)
- {
- u64 old_pages;
-- u64 delta;
-+ u64 delta = 0;
- int res = -EINVAL;
- struct kbase_va_region *reg;
- bool read_locked = false;
-@@ -2037,7 +2144,7 @@ int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages)
- return -EINVAL;
- }
-
-- down_write(¤t->mm->mmap_sem);
-+ down_write(kbase_mem_get_process_mmap_lock());
- kbase_gpu_vm_lock(kctx);
-
- /* Validate the region */
-@@ -2054,13 +2161,27 @@ int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages)
- if (0 == (reg->flags & KBASE_REG_GROWABLE))
- goto out_unlock;
-
-+ if (reg->flags & KBASE_REG_ACTIVE_JIT_ALLOC)
-+ goto out_unlock;
-+
- /* Would overflow the VA region */
- if (new_pages > reg->nr_pages)
- goto out_unlock;
-
-- /* can't be mapped more than once on the GPU */
-+ /* Can't shrink when physical pages are mapped to different GPU
-+ * VAs. The code doesn't support looking up:
-+ * - all physical pages assigned to different GPU VAs
-+ * - CPU mappings for the physical pages at different vm_pgoff
-+ * (==GPU VA) locations.
-+ *
-+ * Note that for Native allocs mapped at multiple GPU VAs, growth of
-+ * such allocs is not a supported use-case.
-+ */
- if (atomic_read(®->gpu_alloc->gpu_mappings) > 1)
- goto out_unlock;
-+
-+ if (atomic_read(®->cpu_alloc->kernel_mappings) > 0)
-+ goto out_unlock;
- /* can't grow regions which are ephemeral */
- if (reg->flags & KBASE_REG_DONT_NEED)
- goto out_unlock;
-@@ -2085,7 +2206,7 @@ int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages)
- * No update to the mm so downgrade the writer lock to a read
- * lock so other readers aren't blocked after this point.
- */
-- downgrade_write(¤t->mm->mmap_sem);
-+ downgrade_write(kbase_mem_get_process_mmap_lock());
- read_locked = true;
-
- /* Allocate some more pages */
-@@ -2127,9 +2248,9 @@ int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages)
- out_unlock:
- kbase_gpu_vm_unlock(kctx);
- if (read_locked)
-- up_read(¤t->mm->mmap_sem);
-+ up_read(kbase_mem_get_process_mmap_lock());
- else
-- up_write(¤t->mm->mmap_sem);
-+ up_write(kbase_mem_get_process_mmap_lock());
-
- return res;
- }
-@@ -2360,11 +2481,7 @@ static int kbase_cpu_mmap(struct kbase_context *kctx,
- * See MIDBASE-1057
- */
-
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
- vma->vm_flags |= VM_DONTCOPY | VM_DONTDUMP | VM_DONTEXPAND | VM_IO;
--#else
-- vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO;
--#endif
- vma->vm_ops = &kbase_vm_ops;
- vma->vm_private_data = map;
-
-@@ -2510,16 +2627,14 @@ out:
-
- void kbase_os_mem_map_lock(struct kbase_context *kctx)
- {
-- struct mm_struct *mm = current->mm;
- (void)kctx;
-- down_read(&mm->mmap_sem);
-+ down_read(kbase_mem_get_process_mmap_lock());
- }
-
- void kbase_os_mem_map_unlock(struct kbase_context *kctx)
- {
-- struct mm_struct *mm = current->mm;
- (void)kctx;
-- up_read(&mm->mmap_sem);
-+ up_read(kbase_mem_get_process_mmap_lock());
- }
-
- static int kbasep_reg_mmap(struct kbase_context *kctx,
-@@ -2547,7 +2662,8 @@ static int kbasep_reg_mmap(struct kbase_context *kctx,
- /* incorrect mmap size */
- /* leave the cookie for a potential later
- * mapping, or to be reclaimed later when the
-- * context is freed */
-+ * context is freed
-+ */
- err = -ENOMEM;
- goto out;
- }
-@@ -2576,6 +2692,11 @@ static int kbasep_reg_mmap(struct kbase_context *kctx,
- kctx->pending_regions[cookie] = NULL;
- bitmap_set(kctx->cookies, cookie, 1);
-
-+#if MALI_USE_CSF
-+ if (reg->flags & KBASE_REG_CSF_EVENT)
-+ kbase_link_event_mem_page(kctx, reg);
-+#endif
-+
- /*
- * Overwrite the offset with the region start_pfn, so we effectively
- * map from offset 0 in the region. However subtract the aligned
-@@ -2595,7 +2716,7 @@ int kbase_context_mmap(struct kbase_context *const kctx,
- {
- struct kbase_va_region *reg = NULL;
- void *kaddr = NULL;
-- size_t nr_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-+ size_t nr_pages = vma_pages(vma);
- int err = 0;
- int free_on_close = 0;
- struct device *dev = kctx->kbdev->dev;
-@@ -2608,7 +2729,7 @@ int kbase_context_mmap(struct kbase_context *const kctx,
- if (!(vma->vm_flags & VM_WRITE))
- vma->vm_flags &= ~VM_MAYWRITE;
-
-- if (0 == nr_pages) {
-+ if (nr_pages == 0) {
- err = -EINVAL;
- goto out;
- }
-@@ -2629,7 +2750,8 @@ int kbase_context_mmap(struct kbase_context *const kctx,
- /* if not the MTP, verify that the MTP has been mapped */
- rcu_read_lock();
- /* catches both when the special page isn't present or
-- * when we've forked */
-+ * when we've forked
-+ */
- if (rcu_dereference(kctx->process_mm) != current->mm) {
- err = -EINVAL;
- rcu_read_unlock();
-@@ -2646,16 +2768,30 @@ int kbase_context_mmap(struct kbase_context *const kctx,
- case PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE):
- /* MMU dump */
- err = kbase_mmu_dump_mmap(kctx, vma, ®, &kaddr);
-- if (0 != err)
-+ if (err != 0)
- goto out_unlock;
- /* free the region on munmap */
- free_on_close = 1;
- break;
-+#if MALI_USE_CSF
-+ case PFN_DOWN(BASEP_MEM_CSF_USER_REG_PAGE_HANDLE):
-+ kbase_gpu_vm_unlock(kctx);
-+ err = kbase_csf_cpu_mmap_user_reg_page(kctx, vma);
-+ goto out;
-+ case PFN_DOWN(BASEP_MEM_CSF_USER_IO_PAGES_HANDLE) ...
-+ PFN_DOWN(BASE_MEM_COOKIE_BASE) - 1: {
-+ kbase_gpu_vm_unlock(kctx);
-+ mutex_lock(&kctx->csf.lock);
-+ err = kbase_csf_cpu_mmap_user_io_pages(kctx, vma);
-+ mutex_unlock(&kctx->csf.lock);
-+ goto out;
-+ }
-+#endif
- case PFN_DOWN(BASE_MEM_COOKIE_BASE) ...
- PFN_DOWN(BASE_MEM_FIRST_FREE_ADDRESS) - 1: {
- err = kbasep_reg_mmap(kctx, vma, ®, &nr_pages,
- &aligned_offset);
-- if (0 != err)
-+ if (err != 0)
- goto out_unlock;
- /* free the region on munmap */
- free_on_close = 1;
-@@ -2728,8 +2864,21 @@ int kbase_context_mmap(struct kbase_context *const kctx,
-
- if (vma->vm_pgoff == PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE)) {
- /* MMU dump - userspace should now have a reference on
-- * the pages, so we can now free the kernel mapping */
-+ * the pages, so we can now free the kernel mapping
-+ */
- vfree(kaddr);
-+ /* CPU mapping of GPU allocations have GPU VA as the vm_pgoff
-+ * and that is used to shrink the mapping when the commit size
-+ * is reduced. So vm_pgoff for CPU mapping created to get the
-+ * snapshot of GPU page tables shall not match with any GPU VA.
-+ * That can be ensured by setting vm_pgoff as vma->vm_start
-+ * because,
-+ * - GPU VA of any SAME_VA allocation cannot match with
-+ * vma->vm_start, as CPU VAs are unique.
-+ * - GPU VA of CUSTOM_VA allocations are outside the CPU
-+ * virtual address space.
-+ */
-+ vma->vm_pgoff = PFN_DOWN(vma->vm_start);
- }
-
- out_unlock:
-@@ -2824,8 +2973,8 @@ static int kbase_vmap_phy_pages(struct kbase_context *kctx,
-
- /* Note: enforcing a RO prot_request onto prot is not done, since:
- * - CPU-arch-specific integration required
-- * - kbase_vmap() requires no access checks to be made/enforced */
--
-+ * - kbase_vmap() requires no access checks to be made/enforced
-+ */
- cpu_addr = vmap(pages, page_count, VM_MAP, prot);
-
- kfree(pages);
-@@ -2846,6 +2995,7 @@ static int kbase_vmap_phy_pages(struct kbase_context *kctx,
- if (map->sync_needed)
- kbase_sync_mem_regions(kctx, map, KBASE_SYNC_TO_CPU);
-
-+ kbase_mem_phy_alloc_kernel_mapped(reg->cpu_alloc);
- return 0;
- }
-
-@@ -2901,7 +3051,8 @@ void *kbase_vmap(struct kbase_context *kctx, u64 gpu_addr, size_t size,
- * be made.
- *
- * As mentioned in kbase_vmap_prot() this means that a kernel-side
-- * CPU-RO mapping is not enforced to allow this to work */
-+ * CPU-RO mapping is not enforced to allow this to work
-+ */
- return kbase_vmap_prot(kctx, gpu_addr, size, 0u, map);
- }
- KBASE_EXPORT_TEST_API(kbase_vmap);
-@@ -2915,6 +3066,7 @@ static void kbase_vunmap_phy_pages(struct kbase_context *kctx,
- if (map->sync_needed)
- kbase_sync_mem_regions(kctx, map, KBASE_SYNC_TO_DEVICE);
-
-+ kbase_mem_phy_alloc_kernel_unmapped(map->cpu_alloc);
- map->offset_in_page = 0;
- map->cpu_pages = NULL;
- map->gpu_pages = NULL;
-@@ -2933,7 +3085,7 @@ KBASE_EXPORT_TEST_API(kbase_vunmap);
-
- static void kbasep_add_mm_counter(struct mm_struct *mm, int member, long value)
- {
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
-+#if (KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE)
- /* To avoid the build breakage due to an unexported kernel symbol
- * 'mm_trace_rss_stat' from later kernels, i.e. from V4.19.0 onwards,
- * we inline here the equivalent of 'add_mm_counter()' from linux
-@@ -3017,14 +3169,319 @@ static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_
-
- /* no real access */
- vma->vm_flags &= ~(VM_READ | VM_MAYREAD | VM_WRITE | VM_MAYWRITE | VM_EXEC | VM_MAYEXEC);
--#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
- vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
-+ vma->vm_ops = &kbase_vm_special_ops;
-+ vma->vm_private_data = kctx;
-+
-+ return 0;
-+}
-+
-+#if MALI_USE_CSF
-+static unsigned long get_queue_doorbell_pfn(struct kbase_device *kbdev,
-+ struct kbase_queue *queue)
-+{
-+ lockdep_assert_held(&kbdev->csf.reg_lock);
-+
-+ /* Return the real Hw doorbell page if queue has been
-+ * assigned one, otherwise a dummy page. Always return the
-+ * dummy page in no mali builds.
-+ */
-+ if (queue->doorbell_nr == KBASEP_USER_DB_NR_INVALID)
-+ return PFN_DOWN(as_phys_addr_t(kbdev->csf.dummy_db_page));
-+ return (PFN_DOWN(kbdev->reg_start + CSF_HW_DOORBELL_PAGE_OFFSET +
-+ (u64)queue->doorbell_nr * CSF_HW_DOORBELL_PAGE_SIZE));
-+}
-+
-+static void kbase_csf_user_io_pages_vm_open(struct vm_area_struct *vma)
-+{
-+ WARN(1, "Unexpected attempt to clone private vma\n");
-+ vma->vm_private_data = NULL;
-+}
-+
-+static void kbase_csf_user_io_pages_vm_close(struct vm_area_struct *vma)
-+{
-+ struct kbase_queue *queue = vma->vm_private_data;
-+ struct kbase_context *kctx;
-+ struct kbase_device *kbdev;
-+ int err;
-+ bool reset_prevented = false;
-+
-+ if (WARN_ON(!queue))
-+ return;
-+
-+ kctx = queue->kctx;
-+ kbdev = kctx->kbdev;
-+
-+ err = kbase_reset_gpu_prevent_and_wait(kbdev);
-+ if (err)
-+ dev_warn(
-+ kbdev->dev,
-+ "Unsuccessful GPU reset detected when unbinding queue (csi_index=%d), attempting to unbind regardless",
-+ queue->csi_index);
-+ else
-+ reset_prevented = true;
-+
-+ mutex_lock(&kctx->csf.lock);
-+ kbase_csf_queue_unbind(queue);
-+ mutex_unlock(&kctx->csf.lock);
-+
-+ if (reset_prevented)
-+ kbase_reset_gpu_allow(kbdev);
-+
-+ /* Now as the vma is closed, drop the reference on mali device file */
-+ fput(kctx->filp);
-+}
-+
-+#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE)
-+static vm_fault_t kbase_csf_user_io_pages_vm_fault(struct vm_area_struct *vma,
-+ struct vm_fault *vmf)
-+{
- #else
-- vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO;
-+static vm_fault_t kbase_csf_user_io_pages_vm_fault(struct vm_fault *vmf)
-+{
-+ struct vm_area_struct *vma = vmf->vma;
- #endif
-- vma->vm_ops = &kbase_vm_special_ops;
-+ struct kbase_queue *queue = vma->vm_private_data;
-+ unsigned long doorbell_cpu_addr, input_cpu_addr, output_cpu_addr;
-+ unsigned long doorbell_page_pfn, input_page_pfn, output_page_pfn;
-+ pgprot_t doorbell_pgprot, input_page_pgprot, output_page_pgprot;
-+ size_t nr_pages = PFN_DOWN(vma->vm_end - vma->vm_start);
-+ vm_fault_t ret;
-+ struct kbase_device *kbdev;
-+ struct memory_group_manager_device *mgm_dev;
-+
-+ /* Few sanity checks up front */
-+ if ((nr_pages != BASEP_QUEUE_NR_MMAP_USER_PAGES) ||
-+ (vma->vm_pgoff != queue->db_file_offset))
-+ return VM_FAULT_SIGBUS;
-+
-+ mutex_lock(&queue->kctx->csf.lock);
-+ kbdev = queue->kctx->kbdev;
-+ mgm_dev = kbdev->mgm_dev;
-+
-+ /* Always map the doorbell page as uncached */
-+ doorbell_pgprot = pgprot_device(vma->vm_page_prot);
-+
-+#if ((KERNEL_VERSION(4, 4, 147) >= LINUX_VERSION_CODE) || \
-+ ((KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE) && \
-+ (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE)))
-+ vma->vm_page_prot = doorbell_pgprot;
-+ input_page_pgprot = doorbell_pgprot;
-+ output_page_pgprot = doorbell_pgprot;
-+#else
-+ if (kbdev->system_coherency == COHERENCY_NONE) {
-+ input_page_pgprot = pgprot_writecombine(vma->vm_page_prot);
-+ output_page_pgprot = pgprot_writecombine(vma->vm_page_prot);
-+ } else {
-+ input_page_pgprot = vma->vm_page_prot;
-+ output_page_pgprot = vma->vm_page_prot;
-+ }
-+#endif
-+
-+ doorbell_cpu_addr = vma->vm_start;
-+
-+#if KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE
-+ if ((unsigned long)vmf->virtual_address == doorbell_cpu_addr) {
-+#else
-+ if (vmf->address == doorbell_cpu_addr) {
-+#endif
-+ mutex_lock(&kbdev->csf.reg_lock);
-+ doorbell_page_pfn = get_queue_doorbell_pfn(kbdev, queue);
-+ ret = mgm_dev->ops.mgm_vmf_insert_pfn_prot(mgm_dev,
-+ KBASE_MEM_GROUP_CSF_IO, vma, doorbell_cpu_addr,
-+ doorbell_page_pfn, doorbell_pgprot);
-+ mutex_unlock(&kbdev->csf.reg_lock);
-+ } else {
-+ /* Map the Input page */
-+ input_cpu_addr = doorbell_cpu_addr + PAGE_SIZE;
-+ input_page_pfn = PFN_DOWN(as_phys_addr_t(queue->phys[0]));
-+ ret = mgm_dev->ops.mgm_vmf_insert_pfn_prot(mgm_dev,
-+ KBASE_MEM_GROUP_CSF_IO, vma, input_cpu_addr,
-+ input_page_pfn, input_page_pgprot);
-+ if (ret != VM_FAULT_NOPAGE)
-+ goto exit;
-+
-+ /* Map the Output page */
-+ output_cpu_addr = input_cpu_addr + PAGE_SIZE;
-+ output_page_pfn = PFN_DOWN(as_phys_addr_t(queue->phys[1]));
-+ ret = mgm_dev->ops.mgm_vmf_insert_pfn_prot(mgm_dev,
-+ KBASE_MEM_GROUP_CSF_IO, vma, output_cpu_addr,
-+ output_page_pfn, output_page_pgprot);
-+ }
-+
-+exit:
-+ mutex_unlock(&queue->kctx->csf.lock);
-+ return ret;
-+}
-+
-+static const struct vm_operations_struct kbase_csf_user_io_pages_vm_ops = {
-+ .open = kbase_csf_user_io_pages_vm_open,
-+ .close = kbase_csf_user_io_pages_vm_close,
-+ .fault = kbase_csf_user_io_pages_vm_fault
-+};
-+
-+/* Program the client process's page table entries to map the pair of
-+ * input/output pages & Hw doorbell page. The caller should have validated that
-+ * vma->vm_pgoff maps to the range of csf cookies.
-+ */
-+static int kbase_csf_cpu_mmap_user_io_pages(struct kbase_context *kctx,
-+ struct vm_area_struct *vma)
-+{
-+ unsigned long cookie =
-+ vma->vm_pgoff - PFN_DOWN(BASEP_MEM_CSF_USER_IO_PAGES_HANDLE);
-+ size_t nr_pages = vma_pages(vma);
-+ struct kbase_queue *queue;
-+ int err = 0;
-+
-+ lockdep_assert_held(&kctx->csf.lock);
-+
-+ queue = kctx->csf.user_pages_info[cookie];
-+
-+ /* Looks like the bind has been aborted */
-+ if (!queue)
-+ return -EINVAL;
-+
-+ if (WARN_ON(test_bit(cookie, kctx->csf.cookies)))
-+ return -EINVAL;
-+
-+ /* no need for the cookie anymore */
-+ kctx->csf.user_pages_info[cookie] = NULL;
-+ bitmap_set(kctx->csf.cookies, cookie, 1);
-+
-+ /* Reset the handle to avoid (re)freeing the cookie (which can
-+ * now get re-assigned) on unbind.
-+ */
-+ queue->handle = BASEP_MEM_INVALID_HANDLE;
-+
-+ if (nr_pages != BASEP_QUEUE_NR_MMAP_USER_PAGES) {
-+ err = -EINVAL;
-+ goto map_failed;
-+ }
-+
-+ err = kbase_csf_alloc_command_stream_user_pages(kctx, queue);
-+ if (err)
-+ goto map_failed;
-+
-+ vma->vm_flags |= VM_DONTCOPY | VM_DONTDUMP | VM_DONTEXPAND | VM_IO;
-+ /* TODO use VM_MIXEDMAP, since it is more appropriate as both types of
-+ * memory with and without "struct page" backing are being inserted here.
-+ * Hw Doorbell pages comes from the device register area so kernel does
-+ * not use "struct page" for them.
-+ */
-+ vma->vm_flags |= VM_PFNMAP;
-+
-+ vma->vm_ops = &kbase_csf_user_io_pages_vm_ops;
-+ vma->vm_private_data = queue;
-+
-+ /* Make vma point to the special internal file, but don't drop the
-+ * reference on mali device file (that would be done later when the
-+ * vma is closed).
-+ */
-+ vma->vm_file = kctx->kbdev->csf.db_filp;
-+ get_file(vma->vm_file);
-+ /* Also adjust the vm_pgoff */
-+ vma->vm_pgoff = queue->db_file_offset;
-+
-+ return 0;
-+
-+map_failed:
-+ /* The queue cannot have got to KBASE_CSF_QUEUE_BOUND state if we
-+ * reached here, so safe to use a variant of unbind that only works on
-+ * stopped queues
-+ *
-+ * This is so we don't enter the CSF scheduler from this path.
-+ */
-+ kbase_csf_queue_unbind_stopped(queue);
-+
-+ return err;
-+}
-+
-+static void kbase_csf_user_reg_vm_close(struct vm_area_struct *vma)
-+{
-+ struct kbase_context *kctx = vma->vm_private_data;
-+
-+ WARN_ON(!kctx->csf.user_reg_vma);
-+
-+ kctx->csf.user_reg_vma = NULL;
-+}
-+
-+#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE)
-+static vm_fault_t kbase_csf_user_reg_vm_fault(struct vm_area_struct *vma,
-+ struct vm_fault *vmf)
-+{
-+#else
-+static vm_fault_t kbase_csf_user_reg_vm_fault(struct vm_fault *vmf)
-+{
-+ struct vm_area_struct *vma = vmf->vma;
-+#endif
-+ struct kbase_context *kctx = vma->vm_private_data;
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ struct memory_group_manager_device *mgm_dev = kbdev->mgm_dev;
-+ unsigned long pfn = PFN_DOWN(kbdev->reg_start + USER_BASE);
-+ size_t nr_pages = PFN_DOWN(vma->vm_end - vma->vm_start);
-+ vm_fault_t ret = VM_FAULT_SIGBUS;
-+
-+ /* Few sanity checks up front */
-+ if (WARN_ON(nr_pages != 1) ||
-+ WARN_ON(vma != kctx->csf.user_reg_vma) ||
-+ WARN_ON(vma->vm_pgoff !=
-+ PFN_DOWN(BASEP_MEM_CSF_USER_REG_PAGE_HANDLE)))
-+ return VM_FAULT_SIGBUS;
-+
-+ mutex_lock(&kbdev->pm.lock);
-+
-+ /* Don't map in the actual register page if GPU is powered down.
-+ * Always map in the dummy page in no mali builds.
-+ */
-+ if (!kbdev->pm.backend.gpu_powered)
-+ pfn = PFN_DOWN(as_phys_addr_t(kbdev->csf.dummy_user_reg_page));
-+
-+ ret = mgm_dev->ops.mgm_vmf_insert_pfn_prot(mgm_dev,
-+ KBASE_MEM_GROUP_CSF_FW, vma,
-+ vma->vm_start, pfn,
-+ vma->vm_page_prot);
-+
-+ mutex_unlock(&kbdev->pm.lock);
-+
-+ return ret;
-+}
-+
-+static const struct vm_operations_struct kbase_csf_user_reg_vm_ops = {
-+ .close = kbase_csf_user_reg_vm_close,
-+ .fault = kbase_csf_user_reg_vm_fault
-+};
-+
-+static int kbase_csf_cpu_mmap_user_reg_page(struct kbase_context *kctx,
-+ struct vm_area_struct *vma)
-+{
-+ size_t nr_pages = PFN_DOWN(vma->vm_end - vma->vm_start);
-+
-+ /* Few sanity checks */
-+ if (kctx->csf.user_reg_vma)
-+ return -EBUSY;
-+
-+ if (nr_pages != 1)
-+ return -EINVAL;
-+
-+ if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))
-+ return -EPERM;
-+
-+ /* Map uncached */
-+ vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
-+
-+ vma->vm_flags |= VM_DONTCOPY | VM_DONTDUMP | VM_DONTEXPAND | VM_IO;
-+
-+ /* User register page comes from the device register area so
-+ * "struct page" isn't available for it.
-+ */
-+ vma->vm_flags |= VM_PFNMAP;
-+
-+ kctx->csf.user_reg_vma = vma;
-+
-+ vma->vm_ops = &kbase_csf_user_reg_vm_ops;
- vma->vm_private_data = kctx;
-
- return 0;
- }
-
-+#endif /* MALI_USE_CSF */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h
-index cd094b3..36159c1 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010, 2012-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010, 2012-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,21 +17,16 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_mem_linux.h
- * Base kernel memory APIs, Linux implementation.
- */
-
- #ifndef _KBASE_MEM_LINUX_H_
- #define _KBASE_MEM_LINUX_H_
-
--/** A HWC dump mapping */
-+/* A HWC dump mapping */
- struct kbase_hwc_dma_mapping {
- void *cpu_va;
- dma_addr_t dma_pa;
-@@ -43,7 +39,7 @@ struct kbase_hwc_dma_mapping {
- * @kctx: The kernel context
- * @va_pages: The number of pages of virtual address space to reserve
- * @commit_pages: The number of physical pages to allocate upfront
-- * @extent: The number of extra pages to allocate on each GPU fault which
-+ * @extension: The number of extra pages to allocate on each GPU fault which
- * grows the region.
- * @flags: bitmask of BASE_MEM_* flags to convey special requirements &
- * properties for the new allocation.
-@@ -53,8 +49,8 @@ struct kbase_hwc_dma_mapping {
- * Return: 0 on success or error code
- */
- struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
-- u64 va_pages, u64 commit_pages, u64 extent, u64 *flags,
-- u64 *gpu_va);
-+ u64 va_pages, u64 commit_pages,
-+ u64 extension, u64 *flags, u64 *gpu_va);
-
- /**
- * kbase_mem_query - Query properties of a GPU memory region
-@@ -194,8 +190,8 @@ int kbase_mem_grow_gpu_mapping(struct kbase_context *kctx,
- * Take the provided region and make all the physical pages within it
- * reclaimable by the kernel, updating the per-process VM stats as well.
- * Remove any CPU mappings (as these can't be removed in the shrinker callback
-- * as mmap_sem might already be taken) but leave the GPU mapping intact as
-- * and until the shrinker reclaims the allocation.
-+ * as mmap_sem/mmap_lock might already be taken) but leave the GPU mapping
-+ * intact as and until the shrinker reclaims the allocation.
- *
- * Note: Must be called with the region lock of the containing context.
- */
-@@ -461,4 +457,18 @@ static inline vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma,
- }
- #endif
-
-+/**
-+ * kbase_mem_get_process_mmap_lock - Return the mmap lock for the current process
-+ *
-+ * Return: the mmap lock for the current process
-+ */
-+static inline struct rw_semaphore *kbase_mem_get_process_mmap_lock(void)
-+{
-+#if KERNEL_VERSION(5, 8, 0) > LINUX_VERSION_CODE
-+ return ¤t->mm->mmap_sem;
-+#else /* KERNEL_VERSION(5, 8, 0) > LINUX_VERSION_CODE */
-+ return ¤t->mm->mmap_lock;
-+#endif /* KERNEL_VERSION(5, 8, 0) > LINUX_VERSION_CODE */
-+}
-+
- #endif /* _KBASE_MEM_LINUX_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h
-index 7011603..3f260bf 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_lowlevel.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2014,2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2014, 2016-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #ifndef _KBASE_MEM_LOWLEVEL_H
- #define _KBASE_MEM_LOWLEVEL_H
-
-@@ -31,9 +28,7 @@
-
- #include <linux/dma-mapping.h>
-
--/**
-- * @brief Flags for kbase_phy_allocator_pages_alloc
-- */
-+/* Flags for kbase_phy_allocator_pages_alloc */
- #define KBASE_PHY_PAGES_FLAG_DEFAULT (0) /** Default allocation flag */
- #define KBASE_PHY_PAGES_FLAG_CLEAR (1 << 0) /** Clear the pages after allocation */
- #define KBASE_PHY_PAGES_FLAG_POISON (1 << 1) /** Fill the memory with a poison value */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool.c
-index 0723e32..a11da82 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2015-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
-@@ -154,20 +153,12 @@ static void kbase_mem_pool_spill(struct kbase_mem_pool *next_pool,
- struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool)
- {
- struct page *p;
-- gfp_t gfp;
-+ gfp_t gfp = GFP_HIGHUSER | __GFP_ZERO;
- struct kbase_device *const kbdev = pool->kbdev;
- struct device *const dev = kbdev->dev;
- dma_addr_t dma_addr;
- int i;
-
--#if defined(CONFIG_ARM) && !defined(CONFIG_HAVE_DMA_ATTRS) && \
-- LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
-- /* DMA cache sync fails for HIGHMEM before 3.5 on ARM */
-- gfp = GFP_USER | __GFP_ZERO;
--#else
-- gfp = GFP_HIGHUSER | __GFP_ZERO;
--#endif
--
- /* don't warn on higher order failures */
- if (pool->order)
- gfp |= __GFP_NOWARN;
-@@ -318,7 +309,7 @@ void kbase_mem_pool_set_max_size(struct kbase_mem_pool *pool, size_t max_size)
-
- kbase_mem_pool_unlock(pool);
- }
--
-+KBASE_EXPORT_TEST_API(kbase_mem_pool_set_max_size);
-
- static unsigned long kbase_mem_pool_reclaim_count_objects(struct shrinker *s,
- struct shrink_control *sc)
-@@ -364,17 +355,6 @@ static unsigned long kbase_mem_pool_reclaim_scan_objects(struct shrinker *s,
- return freed;
- }
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
--static int kbase_mem_pool_reclaim_shrink(struct shrinker *s,
-- struct shrink_control *sc)
--{
-- if (sc->nr_to_scan == 0)
-- return kbase_mem_pool_reclaim_count_objects(s, sc);
--
-- return kbase_mem_pool_reclaim_scan_objects(s, sc);
--}
--#endif
--
- int kbase_mem_pool_init(struct kbase_mem_pool *pool,
- const struct kbase_mem_pool_config *config,
- unsigned int order,
-@@ -398,19 +378,13 @@ int kbase_mem_pool_init(struct kbase_mem_pool *pool,
- spin_lock_init(&pool->pool_lock);
- INIT_LIST_HEAD(&pool->page_list);
-
-- /* Register shrinker */
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
-- pool->reclaim.shrink = kbase_mem_pool_reclaim_shrink;
--#else
- pool->reclaim.count_objects = kbase_mem_pool_reclaim_count_objects;
- pool->reclaim.scan_objects = kbase_mem_pool_reclaim_scan_objects;
--#endif
- pool->reclaim.seeks = DEFAULT_SEEKS;
- /* Kernel versions prior to 3.1 :
-- * struct shrinker does not define batch */
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
-+ * struct shrinker does not define batch
-+ */
- pool->reclaim.batch = 0;
--#endif
- register_shrinker(&pool->reclaim);
-
- pool_dbg(pool, "initialized\n");
-@@ -830,8 +804,8 @@ void kbase_mem_pool_free_pages_locked(struct kbase_mem_pool *pool,
- nr_to_pool = kbase_mem_pool_capacity(pool);
- nr_to_pool = min(nr_pages, nr_to_pool);
-
-- kbase_mem_pool_add_array_locked(pool, nr_pages, pages, false,
-- dirty);
-+ kbase_mem_pool_add_array_locked(pool, nr_to_pool, pages, false,
-+ dirty);
-
- i += nr_to_pool;
- }
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_debugfs.c
-index 5879fdf..cfb43b0 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_debugfs.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_debugfs.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/debugfs.h>
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_debugfs.h
-index 2932945..207b585 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_debugfs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_debugfs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_MEM_POOL_DEBUGFS_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_group.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_group.c
-index aa25548..8d7bb4d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_group.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_group.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_group.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_group.h
-index 0484f59..38fd4ca 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_group.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_pool_group.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_MEM_POOL_GROUP_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c
-index 5752d4a..ea8e34b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2017, 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2017, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,23 +17,23 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <mali_kbase.h>
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-
--/** Show callback for the @c mem_profile debugfs file.
-+/**
-+ * Show callback for the @c mem_profile debugfs file.
- *
- * This function is called to get the contents of the @c mem_profile debugfs
- * file. This is a report of current memory usage and distribution in userspace.
- *
-- * @param sfile The debugfs entry
-- * @param data Data associated with the entry
-+ * @sfile: The debugfs entry
-+ * @data: Data associated with the entry
- *
-- * @return 0 if it successfully prints data in debugfs entry file, non-zero otherwise
-+ * Return: 0 if it successfully prints data in debugfs entry file, non-zero
-+ * otherwise
- */
- static int kbasep_mem_profile_seq_show(struct seq_file *sfile, void *data)
- {
-@@ -71,6 +72,11 @@ static const struct file_operations kbasep_mem_profile_debugfs_fops = {
- int kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data,
- size_t size)
- {
-+#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
-+ const mode_t mode = 0444;
-+#else
-+ const mode_t mode = 0400;
-+#endif
- int err = 0;
-
- if (IS_ERR_OR_NULL(kctx->kctx_dentry)) /* not initialized */
-@@ -84,7 +90,7 @@ int kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data,
- if (!kbase_ctx_flag(kctx, KCTX_MEM_PROFILE_INITIALIZED)) {
- if (IS_ERR_OR_NULL(kctx->kctx_dentry)) {
- err = -ENOMEM;
-- } else if (!debugfs_create_file("mem_profile", 0444,
-+ } else if (!debugfs_create_file("mem_profile", mode,
- kctx->kctx_dentry, kctx,
- &kbasep_mem_profile_debugfs_fops)) {
- err = -EAGAIN;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h
-index 1462247..093a65e 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2016, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,14 +17,9 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_mem_profile_debugfs.h
- * Header file for mem profiles entries in debugfs
- *
- */
-@@ -35,12 +31,17 @@
- #include <linux/seq_file.h>
-
- /**
-- * @brief Remove entry from Mali memory profile debugfs
-+ * Remove entry from Mali memory profile debugfs
-+ * @kctx: The context whose debugfs file @p data should be removed from
- */
- void kbasep_mem_profile_debugfs_remove(struct kbase_context *kctx);
-
- /**
-- * @brief Insert @p data to the debugfs file so it can be read by userspace
-+ * Insert @p data to the debugfs file so it can be read by userspace
-+ * @kctx: The context whose debugfs file @p data should be inserted to
-+ * @data: A NULL-terminated string to be inserted to the debugfs file,
-+ * without the trailing new line character
-+ * @size: The length of the @p data string
- *
- * The function takes ownership of @p data and frees it later when new data
- * is inserted.
-@@ -48,10 +49,6 @@ void kbasep_mem_profile_debugfs_remove(struct kbase_context *kctx);
- * If the debugfs entry corresponding to the @p kctx doesn't exist,
- * an attempt will be made to create it.
- *
-- * @param kctx The context whose debugfs file @p data should be inserted to
-- * @param data A NULL-terminated string to be inserted to the debugfs file,
-- * without the trailing new line character
-- * @param size The length of the @p data string
- * @return 0 if @p data inserted correctly
- * -EAGAIN in case of error
- * @post @ref mem_profile_initialized will be set to @c true
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h
-index d55cc85..3184a98 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_profile_debugfs_buf_size.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2017-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,9 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-- * @file mali_kbase_mem_profile_debugfs_buf_size.h
- * Header file for the size of the buffer to accumulate the histogram report text in
- */
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mipe_gen_header.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mipe_gen_header.h
-index ec52122..f0b385e 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mipe_gen_header.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mipe_gen_header.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* THIS FILE IS AUTOGENERATED BY mali_trace_generator.py.
-@@ -40,14 +39,14 @@
- * defined. See documentation below:
- */
-
--/**
-+/*
- * The name of the variable where the result BLOB will be stored.
- */
- #if !defined(MIPE_HEADER_BLOB_VAR_NAME)
- #error "MIPE_HEADER_BLOB_VAR_NAME must be defined!"
- #endif
-
--/**
-+/*
- * A compiler attribute for the BLOB variable.
- *
- * e.g. __attribute__((section("my_section")))
-@@ -58,6 +57,17 @@
- #define MIPE_HEADER_BLOB_VAR_ATTRIBUTE
- #endif
-
-+/**
-+ * A compiler attribute for packing structures
-+ *
-+ * e.g. __packed
-+ *
-+ * Default value is __attribute__((__packed__))
-+ */
-+#if !defined(MIPE_HEADER_PACKED_ATTRIBUTE)
-+#define MIPE_HEADER_PACKED_ATTRIBUTE __attribute__((__packed__))
-+#endif
-+
- /**
- * MIPE stream id.
- *
-@@ -67,7 +77,7 @@
- #error "MIPE_HEADER_STREAM_ID must be defined!"
- #endif
-
--/**
-+/*
- * MIPE packet class.
- *
- * See enum tl_packet_class.
-@@ -76,10 +86,11 @@
- #error "MIPE_HEADER_PKT_CLASS must be defined!"
- #endif
-
--/**
-+/*
- * The list of tracepoints to process.
- *
- * It should be defined as follows:
-+ *
- * #define MIPE_HEADER_TRACEPOINT_LIST \
- * TRACEPOINT_DESC(FIRST_TRACEPOINT, "Some description", "@II", "first_arg,second_arg") \
- * TRACEPOINT_DESC(SECOND_TRACEPOINT, "Some description", "@II", "first_arg,second_arg") \
-@@ -94,17 +105,18 @@
- #error "MIPE_HEADER_TRACEPOINT_LIST must be defined!"
- #endif
-
--/**
-+/*
- * The number of entries in MIPE_HEADER_TRACEPOINT_LIST.
- */
- #if !defined(MIPE_HEADER_TRACEPOINT_LIST_SIZE)
- #error "MIPE_HEADER_TRACEPOINT_LIST_SIZE must be defined!"
- #endif
-
--/**
-+/*
- * The list of enums to process.
- *
- * It should be defined as follows:
-+ *
- * #define MIPE_HEADER_ENUM_LIST \
- * ENUM_DESC(enum_arg_name, enum_value) \
- * ENUM_DESC(enum_arg_name, enum_value) \
-@@ -117,7 +129,7 @@
- */
- #if defined(MIPE_HEADER_ENUM_LIST)
-
--/**
-+/*
- * Tracepoint message ID used for enums declaration.
- */
- #if !defined(MIPE_HEADER_ENUM_MSG_ID)
-@@ -149,7 +161,7 @@ const struct
- char _arg_types[sizeof(arg_types)]; \
- u32 _size_arg_names; \
- char _arg_names[sizeof(arg_names)]; \
-- } __attribute__ ((__packed__)) __ ## name;
-+ } MIPE_HEADER_PACKED_ATTRIBUTE __ ## name;
-
- #define ENUM_DESC(arg_name, value) \
- struct { \
-@@ -159,13 +171,13 @@ const struct
- u32 _value; \
- u32 _value_str_len; \
- char _value_str[sizeof(#value)]; \
-- } __attribute__ ((__packed__)) __ ## arg_name ## _ ## value;
-+ } MIPE_HEADER_PACKED_ATTRIBUTE __ ## arg_name ## _ ## value;
-
- MIPE_HEADER_TRACEPOINT_LIST
- MIPE_HEADER_ENUM_LIST
- #undef TRACEPOINT_DESC
- #undef ENUM_DESC
--} __attribute__((packed)) MIPE_HEADER_BLOB_VAR_NAME MIPE_HEADER_BLOB_VAR_ATTRIBUTE = {
-+} MIPE_HEADER_PACKED_ATTRIBUTE MIPE_HEADER_BLOB_VAR_NAME MIPE_HEADER_BLOB_VAR_ATTRIBUTE = {
- ._mipe_w0 = MIPE_PACKET_HEADER_W0(
- TL_PACKET_FAMILY_TL,
- MIPE_HEADER_PKT_CLASS,
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mipe_proto.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mipe_proto.h
-index 54667cf..c35ee61 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mipe_proto.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_mipe_proto.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* THIS FILE IS AUTOGENERATED BY mali_trace_generator.py.
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_native_mgm.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_native_mgm.c
-index 38ae46e..4554bee 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_native_mgm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_native_mgm.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/gfp.h>
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_native_mgm.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_native_mgm.h
-index 431b1f4..1eae2fc 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_native_mgm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_native_mgm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_NATIVE_MGM_H_
-@@ -25,7 +24,7 @@
-
- #include <linux/memory_group_manager.h>
-
--/**
-+/*
- * kbase_native_mgm_dev - Native memory group manager device
- *
- * An implementation of the memory group manager interface that is intended for
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c
-index fbb090e..bf525ed 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_platform_fake.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2014, 2016-2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2014, 2016-2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/errno.h>
-@@ -26,7 +25,6 @@
- #include <linux/platform_device.h>
- #include <linux/string.h>
-
--
- /*
- * This file is included only for type definitions and functions belonging to
- * specific platform folders. Do not add dependencies with symbols that are
-@@ -41,14 +39,13 @@ static struct platform_device *mali_device;
-
- #ifndef CONFIG_OF
- /**
-- * @brief Convert data in struct kbase_io_resources struct to Linux-specific resources
-+ * Convert data in struct kbase_io_resources struct to Linux-specific resources
-+ * @io_resources: Input IO resource data
-+ * @linux_resources: Pointer to output array of Linux resource structures
- *
- * Function converts data in struct kbase_io_resources struct to an array of Linux resource structures. Note that function
- * assumes that size of linux_resource array is at least PLATFORM_CONFIG_RESOURCE_COUNT.
- * Resources are put in fixed order: I/O memory region, job IRQ, MMU IRQ, GPU IRQ.
-- *
-- * @param[in] io_resource Input IO resource data
-- * @param[out] linux_resources Pointer to output array of Linux resource structures
- */
- static void kbasep_config_parse_io_resources(const struct kbase_io_resources *io_resources, struct resource *const linux_resources)
- {
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_pm.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_pm.c
-index b9ed8c3..de100dd 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_pm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_pm.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,15 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_pm.c
-- * Base kernel power management APIs
-+ * DOC: Base kernel power management APIs
- */
-
- #include <mali_kbase.h>
-@@ -33,12 +29,14 @@
- #include <mali_kbase_hwcnt_context.h>
-
- #include <mali_kbase_pm.h>
--#include <mali_kbase_pm_internal.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- #include <arbiter/mali_kbase_arbiter_pm.h>
- #endif /* CONFIG_MALI_ARBITER_SUPPORT */
-
-+#include <backend/gpu/mali_kbase_clk_rate_trace_mgr.h>
-+
- int kbase_pm_powerup(struct kbase_device *kbdev, unsigned int flags)
- {
- return kbase_hwaccess_pm_powerup(kbdev, flags);
-@@ -66,14 +64,14 @@ int kbase_pm_context_active_handle_suspend(struct kbase_device *kbdev,
- kbase_pm_lock(kbdev);
-
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
-- if (kbase_arbiter_pm_ctx_active_handle_suspend(kbdev, suspend_handler))
-+ if (kbase_arbiter_pm_ctx_active_handle_suspend(kbdev,
-+ suspend_handler)) {
-+ kbase_pm_unlock(kbdev);
- return 1;
-+ }
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
-
-- if (kbase_pm_is_suspending(kbdev) ||
-- kbase_pm_is_gpu_lost(kbdev)) {
--#else
- if (kbase_pm_is_suspending(kbdev)) {
--#endif /* CONFIG_MALI_ARBITER_SUPPORT */
- switch (suspend_handler) {
- case KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE:
- if (kbdev->pm.active_count != 0)
-@@ -101,6 +99,7 @@ int kbase_pm_context_active_handle_suspend(struct kbase_device *kbdev,
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
- kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_REF_EVENT);
- #endif /* CONFIG_MALI_ARBITER_SUPPORT */
-+ kbase_clk_rate_trace_manager_gpu_active(kbdev);
- }
-
- kbase_pm_unlock(kbdev);
-@@ -128,6 +127,7 @@ void kbase_pm_context_idle(struct kbase_device *kbdev)
- if (c == 0) {
- /* Last context has gone idle */
- kbase_hwaccess_pm_gpu_idle(kbdev);
-+ kbase_clk_rate_trace_manager_gpu_idle(kbdev);
-
- /* Wake up anyone waiting for this to become 0 (e.g. suspend).
- * The waiters must synchronize with us by locking the pm.lock
-@@ -171,6 +171,7 @@ void kbase_pm_driver_suspend(struct kbase_device *kbdev)
- unsigned long flags;
-
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbdev->js_data.runpool_irq.submit_allowed = 0;
- kbase_disjoint_state_up(kbdev);
- for (i = 0; i < kbdev->gpu_props.num_job_slots; i++)
- kbase_job_slot_softstop(kbdev, i, NULL);
-@@ -184,9 +185,14 @@ void kbase_pm_driver_suspend(struct kbase_device *kbdev)
- * all pm references
- */
-
-+#if !MALI_USE_CSF
- /* Suspend job scheduler and associated components, so that it releases all
-- * the PM active count references */
-+ * the PM active count references
-+ */
- kbasep_js_suspend(kbdev);
-+#else
-+ kbase_csf_scheduler_pm_suspend(kbdev);
-+#endif
-
- /* Wait for the active count to reach zero. This is not the same as
- * waiting for a power down, since not all policies power down when this
-@@ -221,14 +227,16 @@ void kbase_pm_driver_resume(struct kbase_device *kbdev, bool arb_gpu_start)
-
- /* Initial active call, to power on the GPU/cores if needed */
- #ifdef CONFIG_MALI_ARBITER_SUPPORT
-- (void)kbase_pm_context_active_handle_suspend(kbdev,
-- (arb_gpu_start ?
-- KBASE_PM_SUSPEND_HANDLER_VM_GPU_GRANTED :
-- KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE));
-+ if (kbase_pm_context_active_handle_suspend(kbdev,
-+ (arb_gpu_start ?
-+ KBASE_PM_SUSPEND_HANDLER_VM_GPU_GRANTED :
-+ KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE)))
-+ return;
- #else
- kbase_pm_context_active(kbdev);
- #endif
-
-+#if !MALI_USE_CSF
- /* Resume any blocked atoms (which may cause contexts to be scheduled in
- * and dependent atoms to run)
- */
-@@ -238,6 +246,9 @@ void kbase_pm_driver_resume(struct kbase_device *kbdev, bool arb_gpu_start)
- * atoms
- */
- kbasep_js_resume(kbdev);
-+#else
-+ kbase_csf_scheduler_pm_resume(kbdev);
-+#endif
-
- /* Matching idle call, to power off the GPU/cores if we didn't actually
- * need it and the policy doesn't want it on
-@@ -245,9 +256,15 @@ void kbase_pm_driver_resume(struct kbase_device *kbdev, bool arb_gpu_start)
- kbase_pm_context_idle(kbdev);
-
- /* Re-enable GPU hardware counters */
-+#if MALI_USE_CSF
-+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
-+ kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx);
-+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
-+#else
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+#endif
-
- /* Resume vinstr */
- kbase_vinstr_resume(kbdev->vinstr_ctx);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_pm.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_pm.h
-index 257f959..980a8d1 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_pm.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_pm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,14 +17,9 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @file mali_kbase_pm.h
- * Power management API definitions
- */
-
-@@ -35,6 +31,13 @@
- #define PM_ENABLE_IRQS 0x01
- #define PM_HW_ISSUES_DETECT 0x02
-
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+/* In the case that the GPU was granted by the Arbiter, it will have
-+ * already been reset. The following flag ensures it is not reset
-+ * twice.
-+ */
-+#define PM_NO_RESET 0x04
-+#endif
-
- /** Initialize the power management framework.
- *
-@@ -59,12 +62,12 @@ int kbase_pm_powerup(struct kbase_device *kbdev, unsigned int flags);
-
- /**
- * Halt the power management framework.
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ *
- * Should ensure that no new interrupts are generated,
- * but allow any currently running interrupt handlers to complete successfully.
- * The GPU is forced off by the time this function returns, regardless of
- * whether or not the active power policy asks for the GPU to be powered off.
-- *
-- * @param kbdev The kbase device structure for the device (must be a valid pointer)
- */
- void kbase_pm_halt(struct kbase_device *kbdev);
-
-@@ -154,6 +157,7 @@ void kbase_pm_context_idle(struct kbase_device *kbdev);
- /**
- * Suspend the GPU and prevent any further register accesses to it from Kernel
- * threads.
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- *
- * This is called in response to an OS suspend event, and calls into the various
- * kbase components to complete the suspend.
-@@ -161,21 +165,18 @@ void kbase_pm_context_idle(struct kbase_device *kbdev);
- * @note the mechanisms used here rely on all user-space threads being frozen
- * by the OS before we suspend. Otherwise, an IOCTL could occur that powers up
- * the GPU e.g. via atom submission.
-- *
-- * @param kbdev The kbase device structure for the device (must be a valid pointer)
- */
- void kbase_pm_suspend(struct kbase_device *kbdev);
-
- /**
- * Resume the GPU, allow register accesses to it, and resume running atoms on
- * the GPU.
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- *
- * This is called in response to an OS resume event, and calls into the various
- * kbase components to complete the resume.
- *
- * Also called when using VM arbiter, when GPU access has been granted.
-- *
-- * @param kbdev The kbase device structure for the device (must be a valid pointer)
- */
- void kbase_pm_resume(struct kbase_device *kbdev);
-
-@@ -192,8 +193,7 @@ void kbase_pm_vsync_callback(int buffer_updated, void *data);
-
- /**
- * kbase_pm_driver_suspend() - Put GPU and driver in suspend state
-- * @param kbdev The kbase device structure for the device
-- * (must be a valid pointer)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
- *
- * Suspend the GPU and prevent any further register accesses to it from Kernel
- * threads.
-@@ -212,8 +212,8 @@ void kbase_pm_driver_suspend(struct kbase_device *kbdev);
-
- /**
- * kbase_pm_driver_resume() - Put GPU and driver in resume
-- * @param kbdev The kbase device structure for the device
-- * (must be a valid pointer)
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer)
-+ * @arb_gpu_start: Arbiter has notified we can use GPU
- *
- * Resume the GPU, allow register accesses to it, and resume running atoms on
- * the GPU.
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_regs_history_debugfs.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_regs_history_debugfs.c
-index 1d114a6..1e807d7 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_regs_history_debugfs.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_regs_history_debugfs.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2016, 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2016, 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,18 +17,130 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase.h"
--
- #include "mali_kbase_regs_history_debugfs.h"
-
--#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_NO_MALI)
-+#if defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_NO_MALI)
-
- #include <linux/debugfs.h>
-
-+/**
-+ * kbase_io_history_resize - resize the register access history buffer.
-+ *
-+ * @h: Pointer to a valid register history to resize
-+ * @new_size: Number of accesses the buffer could hold
-+ *
-+ * A successful resize will clear all recent register accesses.
-+ * If resizing fails for any reason (e.g., could not allocate memory, invalid
-+ * buffer size) then the original buffer will be kept intact.
-+ *
-+ * @return 0 if the buffer was resized, failure otherwise
-+ */
-+static int kbase_io_history_resize(struct kbase_io_history *h, u16 new_size)
-+{
-+ struct kbase_io_access *old_buf;
-+ struct kbase_io_access *new_buf;
-+ unsigned long flags;
-+
-+ if (!new_size)
-+ goto out_err; /* The new size must not be 0 */
-+
-+ new_buf = vmalloc(new_size * sizeof(*h->buf));
-+ if (!new_buf)
-+ goto out_err;
-+
-+ spin_lock_irqsave(&h->lock, flags);
-+
-+ old_buf = h->buf;
-+
-+ /* Note: we won't bother with copying the old data over. The dumping
-+ * logic wouldn't work properly as it relies on 'count' both as a
-+ * counter and as an index to the buffer which would have changed with
-+ * the new array. This is a corner case that we don't need to support.
-+ */
-+ h->count = 0;
-+ h->size = new_size;
-+ h->buf = new_buf;
-+
-+ spin_unlock_irqrestore(&h->lock, flags);
-+
-+ vfree(old_buf);
-+
-+ return 0;
-+
-+out_err:
-+ return -1;
-+}
-+
-+int kbase_io_history_init(struct kbase_io_history *h, u16 n)
-+{
-+ h->enabled = false;
-+ spin_lock_init(&h->lock);
-+ h->count = 0;
-+ h->size = 0;
-+ h->buf = NULL;
-+ if (kbase_io_history_resize(h, n))
-+ return -1;
-+
-+ return 0;
-+}
-+
-+void kbase_io_history_term(struct kbase_io_history *h)
-+{
-+ vfree(h->buf);
-+ h->buf = NULL;
-+}
-+
-+void kbase_io_history_add(struct kbase_io_history *h,
-+ void __iomem const *addr, u32 value, u8 write)
-+{
-+ struct kbase_io_access *io;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&h->lock, flags);
-+
-+ io = &h->buf[h->count % h->size];
-+ io->addr = (uintptr_t)addr | write;
-+ io->value = value;
-+ ++h->count;
-+ /* If count overflows, move the index by the buffer size so the entire
-+ * buffer will still be dumped later
-+ */
-+ if (unlikely(!h->count))
-+ h->count = h->size;
-+
-+ spin_unlock_irqrestore(&h->lock, flags);
-+}
-+
-+void kbase_io_history_dump(struct kbase_device *kbdev)
-+{
-+ struct kbase_io_history *const h = &kbdev->io_history;
-+ size_t i;
-+ size_t iters;
-+ unsigned long flags;
-+
-+ if (!unlikely(h->enabled))
-+ return;
-+
-+ spin_lock_irqsave(&h->lock, flags);
-+
-+ dev_err(kbdev->dev, "Register IO History:");
-+ iters = (h->size > h->count) ? h->count : h->size;
-+ dev_err(kbdev->dev, "Last %zu register accesses of %zu total:\n", iters,
-+ h->count);
-+ for (i = 0; i < iters; ++i) {
-+ struct kbase_io_access *io =
-+ &h->buf[(h->count - iters + i) % h->size];
-+ char const access = (io->addr & 1) ? 'w' : 'r';
-+
-+ dev_err(kbdev->dev, "%6zu: %c: reg 0x%016lx val %08x\n", i,
-+ access, (unsigned long)(io->addr & ~0x1), io->value);
-+ }
-+
-+ spin_unlock_irqrestore(&h->lock, flags);
-+}
-
- static int regs_history_size_get(void *data, u64 *val)
- {
-@@ -66,7 +179,7 @@ DEFINE_SIMPLE_ATTRIBUTE(regs_history_size_fops,
- static int regs_history_show(struct seq_file *sfile, void *data)
- {
- struct kbase_io_history *const h = sfile->private;
-- u16 i;
-+ size_t i;
- size_t iters;
- unsigned long flags;
-
-@@ -85,8 +198,8 @@ static int regs_history_show(struct seq_file *sfile, void *data)
- &h->buf[(h->count - iters + i) % h->size];
- char const access = (io->addr & 1) ? 'w' : 'r';
-
-- seq_printf(sfile, "%6i: %c: reg 0x%016lx val %08x\n", i, access,
-- (unsigned long)(io->addr & ~0x1), io->value);
-+ seq_printf(sfile, "%6zu: %c: reg 0x%016lx val %08x\n", i,
-+ access, (unsigned long)(io->addr & ~0x1), io->value);
- }
-
- spin_unlock_irqrestore(&h->lock, flags);
-@@ -95,7 +208,6 @@ out:
- return 0;
- }
-
--
- /**
- * regs_history_open - open operation for regs_history debugfs file
- *
-@@ -109,7 +221,6 @@ static int regs_history_open(struct inode *in, struct file *file)
- return single_open(file, ®s_history_show, in->i_private);
- }
-
--
- static const struct file_operations regs_history_fops = {
- .owner = THIS_MODULE,
- .open = ®s_history_open,
-@@ -118,7 +229,6 @@ static const struct file_operations regs_history_fops = {
- .release = single_release,
- };
-
--
- void kbasep_regs_history_debugfs_init(struct kbase_device *kbdev)
- {
- debugfs_create_bool("regs_history_enabled", S_IRUGO | S_IWUSR,
-@@ -131,6 +241,4 @@ void kbasep_regs_history_debugfs_init(struct kbase_device *kbdev)
- kbdev->mali_debugfs_directory, &kbdev->io_history,
- ®s_history_fops);
- }
--
--
--#endif /* CONFIG_DEBUG_FS */
-+#endif /* defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_NO_MALI) */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_regs_history_debugfs.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_regs_history_debugfs.h
-index a0078cb..3b181d3 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_regs_history_debugfs.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_regs_history_debugfs.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2016, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-@@ -37,7 +36,31 @@
-
- struct kbase_device;
-
--#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_MALI_NO_MALI)
-+#if defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_NO_MALI)
-+
-+/**
-+ * kbase_io_history_init - initialize data struct for register access history
-+ *
-+ * @h: The register history to initialize
-+ * @n: The number of register accesses that the buffer could hold
-+ *
-+ * @return 0 if successfully initialized, failure otherwise
-+ */
-+int kbase_io_history_init(struct kbase_io_history *h, u16 n);
-+
-+/**
-+ * kbase_io_history_term - uninit all resources for the register access history
-+ *
-+ * @h: The register history to terminate
-+ */
-+void kbase_io_history_term(struct kbase_io_history *h);
-+
-+/**
-+ * kbase_io_history_dump - print the register history to the kernel ring buffer
-+ *
-+ * @kbdev: Pointer to kbase_device containing the register history to dump
-+ */
-+void kbase_io_history_dump(struct kbase_device *kbdev);
-
- /**
- * kbasep_regs_history_debugfs_init - add debugfs entries for register history
-@@ -46,10 +69,7 @@ struct kbase_device;
- */
- void kbasep_regs_history_debugfs_init(struct kbase_device *kbdev);
-
--#else /* CONFIG_DEBUG_FS */
--
--#define kbasep_regs_history_debugfs_init CSTD_NOP
--
--#endif /* CONFIG_DEBUG_FS */
-+#else /* defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_NO_MALI) */
-+#endif /* defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_NO_MALI) */
-
- #endif /*_KBASE_REGS_HISTORY_DEBUGFS_H*/
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_reset_gpu.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_reset_gpu.h
-index df72eec..292a29c 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_reset_gpu.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_reset_gpu.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,16 +17,142 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_RESET_GPU_H_
- #define _KBASE_RESET_GPU_H_
-
-+/**
-+ * kbase_reset_gpu_prevent_and_wait - Prevent GPU resets from starting whilst
-+ * the current thread is accessing the GPU,
-+ * and wait for any in-flight reset to
-+ * finish.
-+ * @kbdev: Device pointer
-+ *
-+ * This should be used when a potential access to the HW is going to be made
-+ * from a non-atomic context.
-+ *
-+ * It will wait for any in-flight reset to finish before returning. Hence,
-+ * correct lock ordering must be observed with respect to the calling thread
-+ * and the reset worker thread.
-+ *
-+ * This does not synchronize general access to the HW, and so multiple threads
-+ * can prevent GPU reset concurrently, whilst not being serialized. This is
-+ * advantageous as the threads can make this call at points where they do not
-+ * know for sure yet whether they will indeed access the GPU (for example, to
-+ * respect lock ordering), without unnecessarily blocking others.
-+ *
-+ * Threads must still use other synchronization to ensure they access the HW
-+ * consistently, at a point where they are certain it needs to be accessed.
-+ *
-+ * On success, ensure that when access to the GPU by the caller thread has
-+ * finished, that it calls kbase_reset_gpu_allow() again to allow resets to
-+ * happen.
-+ *
-+ * This may return a failure in cases such as a previous failure to reset the
-+ * GPU within a reasonable time. If that happens, the GPU might be
-+ * non-operational and the caller should not attempt any further access.
-+ *
-+ * Note:
-+ * For atomic context, instead check kbase_reset_gpu_is_active().
-+ *
-+ * Return: 0 on success, or negative error code on failure.
-+ */
-+int kbase_reset_gpu_prevent_and_wait(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_reset_gpu_try_prevent - Attempt to prevent GPU resets from starting
-+ * whilst the current thread is accessing the
-+ * GPU, unless a reset is already in progress.
-+ * @kbdev: Device pointer
-+ *
-+ * Similar to kbase_reset_gpu_prevent_and_wait(), but it does not wait for an
-+ * existing reset to complete. This can be used on codepaths that the Reset
-+ * worker waits on, where use of kbase_reset_gpu_prevent_and_wait() would
-+ * otherwise deadlock.
-+ *
-+ * Instead, a reset that is currently happening will cause this function to
-+ * return an error code indicating that, and further resets will not have been
-+ * prevented.
-+ *
-+ * In such cases, the caller must check for -EAGAIN, and take similar actions
-+ * as for handling reset in atomic context. That is, they must cancel any
-+ * actions that depended on reset being prevented, possibly deferring them
-+ * until after the reset.
-+ *
-+ * Otherwise a successful return means that the caller can continue its actions
-+ * safely in the knowledge that reset is prevented, and the reset worker will
-+ * correctly wait instead of deadlocking against this thread.
-+ *
-+ * On success, ensure that when access to the GPU by the caller thread has
-+ * finished, that it calls kbase_reset_gpu_allow() again to allow resets to
-+ * happen.
-+ *
-+ * Refer to kbase_reset_gpu_prevent_and_wait() for more information.
-+ *
-+ * Return: 0 on success. -EAGAIN if a reset is currently happening. Other
-+ * negative error codes on failure.
-+ */
-+int kbase_reset_gpu_try_prevent(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_reset_gpu_allow - Allow GPU resets to happen again after having been
-+ * previously prevented.
-+ * @kbdev: Device pointer
-+ *
-+ * This should be used when a potential access to the HW has finished from a
-+ * non-atomic context.
-+ *
-+ * It must be used from the same thread that originally made a previously call
-+ * to kbase_reset_gpu_prevent_and_wait(). It must not be deferred to another
-+ * thread.
-+ */
-+void kbase_reset_gpu_allow(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_reset_gpu_assert_prevented - Make debugging checks that GPU reset is
-+ * currently prevented by the current
-+ * thread.
-+ * @kbdev: Device pointer
-+ *
-+ * Make debugging checks that the current thread has made a call to
-+ * kbase_reset_gpu_prevent_and_wait(), but has yet to make a subsequent call to
-+ * kbase_reset_gpu_allow().
-+ *
-+ * CONFIG_LOCKDEP is required to prove that reset is indeed
-+ * prevented. Otherwise only limited debugging checks can be made.
-+ */
-+void kbase_reset_gpu_assert_prevented(struct kbase_device *kbdev);
-+
-+/**
-+ * kbase_reset_gpu_assert_failed_or_prevented - Make debugging checks that
-+ * either GPU reset previously
-+ * failed, or is currently
-+ * prevented.
-+ *
-+ * @kbdev: Device pointer
-+ *
-+ * As with kbase_reset_gpu_assert_prevented(), but also allow for paths where
-+ * reset was not prevented due to a failure, yet we still need to execute the
-+ * cleanup code following.
-+ *
-+ * Cleanup code following this call must handle any inconsistent state modified
-+ * by the failed GPU reset, and must timeout any blocking operations instead of
-+ * waiting forever.
-+ */
-+void kbase_reset_gpu_assert_failed_or_prevented(struct kbase_device *kbdev);
-+
-+/**
-+ * Flags for kbase_prepare_to_reset_gpu
-+ */
-+#define RESET_FLAGS_NONE ((unsigned int)0)
-+/* This reset should be treated as an unrecoverable error by HW counter logic */
-+#define RESET_FLAGS_HWC_UNRECOVERABLE_ERROR ((unsigned int)(1 << 0))
-+
- /**
- * kbase_prepare_to_reset_gpu_locked - Prepare for resetting the GPU.
- * @kbdev: Device pointer
-+ * @flags: Bitfield indicating impact of reset (see flag defines)
- *
- * Caller is expected to hold the kbdev->hwaccess_lock.
- *
-@@ -34,18 +161,20 @@
- * - false - Another thread is performing a reset, kbase_reset_gpu should
- * not be called.
- */
--bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev);
-+bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev,
-+ unsigned int flags);
-
- /**
- * kbase_prepare_to_reset_gpu - Prepare for resetting the GPU.
- * @kbdev: Device pointer
-- *
-+ * @flags: Bitfield indicating impact of reset (see flag defines)
-+
- * Return: a boolean which should be interpreted as follows:
- * - true - Prepared for reset, kbase_reset_gpu should be called.
- * - false - Another thread is performing a reset, kbase_reset_gpu should
- * not be called.
- */
--bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev);
-+bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev, unsigned int flags);
-
- /**
- * kbase_reset_gpu - Reset the GPU
-@@ -95,8 +224,13 @@ int kbase_reset_gpu_silent(struct kbase_device *kbdev);
- * kbase_reset_gpu_is_active - Reports if the GPU is being reset
- * @kbdev: Device pointer
- *
-- * Return: True if the GPU is in the process of being reset (or if the reset of
-- * GPU failed, not applicable to Job Manager GPUs).
-+ * Any changes made to the HW when this returns true may be lost, overwritten
-+ * or corrupted.
-+ *
-+ * Note that unless appropriate locks are held when using this function, the
-+ * state could change immediately afterwards.
-+ *
-+ * Return: True if the GPU is in the process of being reset.
- */
- bool kbase_reset_gpu_is_active(struct kbase_device *kbdev);
-
-@@ -126,14 +260,4 @@ int kbase_reset_gpu_init(struct kbase_device *kbdev);
- */
- void kbase_reset_gpu_term(struct kbase_device *kbdev);
-
--/**
-- * kbase_reset_gpu_register_complete_cb - Register the callback function to be
-- * invoked on completion of GPU reset.
-- *
-- * @kbdev: Device pointer
-- * @complete_callback: Pointer to the callback function
-- */
--void kbase_reset_gpu_register_complete_cb(struct kbase_device *kbdev,
-- int (*complete_callback)(struct kbase_device *kbdev));
--
- #endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.c
-index b5c7b12..abbe8d5 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2015, 2018, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,9 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifdef CONFIG_ARM64
-+#if IS_ENABLED(CONFIG_ARM64)
-
- #include <mali_kbase.h>
- #include <mali_kbase_smc.h>
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.h
-index 221eb21..d0086db 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2015 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,16 +17,12 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #ifndef _KBASE_SMC_H_
- #define _KBASE_SMC_H_
-
--#ifdef CONFIG_ARM64
-+#if IS_ENABLED(CONFIG_ARM64)
-
- #include <mali_kbase.h>
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c
-index cbb0c76..bee3513 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #include <mali_kbase.h>
-
- #include <linux/dma-buf.h>
-@@ -30,8 +27,9 @@
- #include <mali_kbase_sync.h>
- #endif
- #include <linux/dma-mapping.h>
--#include <mali_base_kernel.h>
-+#include <uapi/gpu/arm/midgard/mali_base_kernel.h>
- #include <mali_kbase_hwaccess_time.h>
-+#include <mali_kbase_kinstr_jm.h>
- #include <mali_kbase_mem_linux.h>
- #include <tl/mali_kbase_tracepoints.h>
- #include <mali_linux_trace.h>
-@@ -42,10 +40,9 @@
- #include <linux/kernel.h>
- #include <linux/cache.h>
-
-+#if !MALI_USE_CSF
- /**
-- * @file mali_kbase_softjobs.c
-- *
-- * This file implements the logic behind software only jobs that are
-+ * DOC: This file implements the logic behind software only jobs that are
- * executed within the driver rather than being handed over to the GPU.
- */
-
-@@ -136,7 +133,7 @@ static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom)
- void *user_result;
- struct timespec64 ts;
- struct base_dump_cpu_gpu_counters data;
-- u64 system_time;
-+ u64 system_time = 0ULL;
- u64 cycle_counter;
- u64 jc = katom->jc;
- struct kbase_context *kctx = katom->kctx;
-@@ -146,7 +143,11 @@ static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom)
-
- /* Take the PM active reference as late as possible - otherwise, it could
- * delay suspend until we process the atom (which may be at the end of a
-- * long chain of dependencies */
-+ * long chain of dependencies
-+ */
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ atomic_inc(&kctx->kbdev->pm.gpu_users_waiting);
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
- pm_active_err = kbase_pm_context_active_handle_suspend(kctx->kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE);
- if (pm_active_err) {
- struct kbasep_js_device_data *js_devdata = &kctx->kbdev->js_data;
-@@ -164,6 +165,10 @@ static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom)
-
- return pm_active_err;
- }
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ else
-+ atomic_dec(&kctx->kbdev->pm.gpu_users_waiting);
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
-
- kbase_backend_get_gpu_time(kctx->kbdev, &cycle_counter, &system_time,
- &ts);
-@@ -181,7 +186,8 @@ static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom)
- /* GPU_WR access is checked on the range for returning the result to
- * userspace for the following reasons:
- * - security, this is currently how imported user bufs are checked.
-- * - userspace ddk guaranteed to assume region was mapped as GPU_WR */
-+ * - userspace ddk guaranteed to assume region was mapped as GPU_WR
-+ */
- user_result = kbase_vmap_prot(kctx, jc, sizeof(data), KBASE_REG_GPU_WR, &map);
- if (!user_result)
- return 0;
-@@ -292,7 +298,7 @@ static void kbase_fence_debug_check_atom(struct kbase_jd_atom *katom)
-
- if (!kbase_sync_fence_in_info_get(dep, &info)) {
- dev_warn(dev,
-- "\tVictim trigger atom %d fence [%p] %s: %s\n",
-+ "\tVictim trigger atom %d fence [%pK] %s: %s\n",
- kbase_jd_atom_id(kctx, dep),
- info.fence,
- info.name,
-@@ -321,11 +327,11 @@ static void kbase_fence_debug_wait_timeout(struct kbase_jd_atom *katom)
- return;
- }
-
-- dev_warn(dev, "ctx %d_%d: Atom %d still waiting for fence [%p] after %dms\n",
-+ dev_warn(dev, "ctx %d_%d: Atom %d still waiting for fence [%pK] after %dms\n",
- kctx->tgid, kctx->id,
- kbase_jd_atom_id(kctx, katom),
- info.fence, timeout_ms);
-- dev_warn(dev, "\tGuilty fence [%p] %s: %s\n",
-+ dev_warn(dev, "\tGuilty fence [%pK] %s: %s\n",
- info.fence, info.name,
- kbase_sync_status_string(info.status));
-
-@@ -713,14 +719,16 @@ out_unlock:
-
- out_cleanup:
- /* Frees allocated memory for kbase_debug_copy_job struct, including
-- * members, and sets jc to 0 */
-+ * members, and sets jc to 0
-+ */
- kbase_debug_copy_finish(katom);
- kfree(user_buffers);
-
- return ret;
- }
-+#endif /* !MALI_USE_CSF */
-
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
-+#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE
- static void *dma_buf_kmap_page(struct kbase_mem_phy_alloc *gpu_alloc,
- unsigned long page_num, struct page **page)
- {
-@@ -801,16 +809,16 @@ int kbase_mem_copy_from_extres(struct kbase_context *kctx,
- dma_to_copy = min(dma_buf->size,
- (size_t)(buf_data->nr_extres_pages * PAGE_SIZE));
- ret = dma_buf_begin_cpu_access(dma_buf,
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) && !defined(CONFIG_CHROMEOS)
-- 0, dma_to_copy,
-+#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && !defined(CONFIG_CHROMEOS)
-+ 0, dma_to_copy,
- #endif
-- DMA_FROM_DEVICE);
-+ DMA_FROM_DEVICE);
- if (ret)
- goto out_unlock;
-
- for (i = 0; i < dma_to_copy/PAGE_SIZE &&
- target_page_nr < buf_data->nr_pages; i++) {
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
-+#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE
- struct page *pg;
- void *extres_page = dma_buf_kmap_page(gpu_alloc, i, &pg);
- #else
-@@ -822,20 +830,20 @@ int kbase_mem_copy_from_extres(struct kbase_context *kctx,
- buf_data->nr_pages,
- &target_page_nr, offset);
-
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
-+#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE
- kunmap(pg);
- #else
- dma_buf_kunmap(dma_buf, i, extres_page);
- #endif
- if (ret)
-- goto out_unlock;
-+ break;
- }
- }
- dma_buf_end_cpu_access(dma_buf,
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) && !defined(CONFIG_CHROMEOS)
-- 0, dma_to_copy,
-+#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && !defined(CONFIG_CHROMEOS)
-+ 0, dma_to_copy,
- #endif
-- DMA_FROM_DEVICE);
-+ DMA_FROM_DEVICE);
- break;
- }
- default:
-@@ -846,6 +854,7 @@ out_unlock:
- return ret;
- }
-
-+#if !MALI_USE_CSF
- static int kbase_debug_copy(struct kbase_jd_atom *katom)
- {
- struct kbase_debug_copy_buffer *buffers = katom->softjob_data;
-@@ -863,6 +872,7 @@ static int kbase_debug_copy(struct kbase_jd_atom *katom)
-
- return 0;
- }
-+#endif /* !MALI_USE_CSF */
-
- #define KBASEP_JIT_ALLOC_GPU_ADDR_ALIGNMENT ((u32)0x7)
-
-@@ -899,7 +909,7 @@ int kbasep_jit_alloc_validate(struct kbase_context *kctx,
- if (info->flags & ~(BASE_JIT_ALLOC_VALID_FLAGS))
- return -EINVAL;
-
--#if !MALI_JIT_PRESSURE_LIMIT
-+#if !MALI_JIT_PRESSURE_LIMIT_BASE
- /* If just-in-time memory allocation pressure limit feature is disabled,
- * heap_info_gpu_addr must be zeroed-out
- */
-@@ -907,21 +917,19 @@ int kbasep_jit_alloc_validate(struct kbase_context *kctx,
- return -EINVAL;
- #endif
-
-+#if !MALI_USE_CSF
- /* If BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE is set, heap_info_gpu_addr
- * cannot be 0
- */
- if ((info->flags & BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE) &&
- !info->heap_info_gpu_addr)
- return -EINVAL;
-+#endif /* !MALI_USE_CSF */
-
- return 0;
- }
-
--
--#if (KERNEL_VERSION(3, 18, 63) > LINUX_VERSION_CODE)
--#define offsetofend(TYPE, MEMBER) \
-- (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER))
--#endif
-+#if !MALI_USE_CSF
-
- /*
- * Sizes of user data to copy for each just-in-time memory interface version
-@@ -998,10 +1006,10 @@ static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom)
- ret = kbasep_jit_alloc_validate(kctx, info);
- if (ret)
- goto free_info;
-- KBASE_TLSTREAM_TL_ATTRIB_ATOM_JITALLOCINFO(kbdev, katom,
-- info->va_pages, info->commit_pages, info->extent,
-- info->id, info->bin_id, info->max_allocations,
-- info->flags, info->usage_id);
-+ KBASE_TLSTREAM_TL_ATTRIB_ATOM_JITALLOCINFO(
-+ kbdev, katom, info->va_pages, info->commit_pages,
-+ info->extension, info->id, info->bin_id,
-+ info->max_allocations, info->flags, info->usage_id);
- }
-
- katom->jit_blocked = false;
-@@ -1016,7 +1024,7 @@ static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom)
- * though the region is valid it doesn't represent the
- * same thing it used to.
- *
-- * Complete validation of va_pages, commit_pages and extent
-+ * Complete validation of va_pages, commit_pages and extension
- * isn't done here as it will be done during the call to
- * kbase_mem_alloc.
- */
-@@ -1091,14 +1099,19 @@ static int kbase_jit_allocate_process(struct kbase_jd_atom *katom)
- }
- }
-
--#if MALI_JIT_PRESSURE_LIMIT
-- /**
-- * If this is the only JIT_ALLOC atom in-flight then allow it to exceed
-- * the defined pressure limit.
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ /*
-+ * If this is the only JIT_ALLOC atom in-flight or if JIT pressure limit
-+ * is disabled at the context scope, then bypass JIT pressure limit
-+ * logic in kbase_jit_allocate().
- */
-- if (kctx->jit_current_allocations == 0)
-+ if (!kbase_ctx_flag(kctx, KCTX_JPL_ENABLED)
-+ || (kctx->jit_current_allocations == 0)) {
- ignore_pressure_limit = true;
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+ }
-+#else
-+ ignore_pressure_limit = true;
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- for (i = 0, info = katom->softjob_data; i < count; i++, info++) {
- if (kctx->jit_alloc[info->id]) {
-@@ -1215,10 +1228,10 @@ static int kbase_jit_allocate_process(struct kbase_jd_atom *katom)
- MIDGARD_MMU_BOTTOMLEVEL, kctx->jit_group_id);
- #endif
-
-- KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT(kbdev, katom,
-- info->gpu_alloc_addr, new_addr, info->flags,
-- entry_mmu_flags, info->id, info->commit_pages,
-- info->extent, info->va_pages);
-+ KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT(
-+ kbdev, katom, info->gpu_alloc_addr, new_addr,
-+ info->flags, entry_mmu_flags, info->id,
-+ info->commit_pages, info->extension, info->va_pages);
- kbase_vunmap(kctx, &mapping);
-
- kbase_trace_jit_report_gpu_mem(kctx, reg,
-@@ -1358,12 +1371,16 @@ void kbase_jit_retry_pending_alloc(struct kbase_context *kctx)
- list_for_each_safe(i, tmp, &jit_pending_alloc_list) {
- struct kbase_jd_atom *pending_atom = list_entry(i,
- struct kbase_jd_atom, queue);
-+ KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_START(kctx->kbdev, pending_atom);
-+ kbase_kinstr_jm_atom_sw_start(pending_atom);
- if (kbase_jit_allocate_process(pending_atom) == 0) {
- /* Atom has completed */
- INIT_WORK(&pending_atom->work,
- kbasep_jit_finish_worker);
- queue_work(kctx->jctx.job_done_wq, &pending_atom->work);
- }
-+ KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_END(kctx->kbdev, pending_atom);
-+ kbase_kinstr_jm_atom_sw_stop(pending_atom);
- }
- }
-
-@@ -1412,41 +1429,27 @@ static int kbase_ext_res_prepare(struct kbase_jd_atom *katom)
- struct base_external_resource_list *ext_res;
- u64 count = 0;
- size_t copy_size;
-- int ret;
-
- user_ext_res = (__user struct base_external_resource_list *)
- (uintptr_t) katom->jc;
-
- /* Fail the job if there is no info structure */
-- if (!user_ext_res) {
-- ret = -EINVAL;
-- goto fail;
-- }
-+ if (!user_ext_res)
-+ return -EINVAL;
-
-- if (copy_from_user(&count, &user_ext_res->count, sizeof(u64)) != 0) {
-- ret = -EINVAL;
-- goto fail;
-- }
-+ if (copy_from_user(&count, &user_ext_res->count, sizeof(u64)) != 0)
-+ return -EINVAL;
-
- /* Is the number of external resources in range? */
-- if (!count || count > BASE_EXT_RES_COUNT_MAX) {
-- ret = -EINVAL;
-- goto fail;
-- }
-+ if (!count || count > BASE_EXT_RES_COUNT_MAX)
-+ return -EINVAL;
-
- /* Copy the information for safe access and future storage */
- copy_size = sizeof(*ext_res);
- copy_size += sizeof(struct base_external_resource) * (count - 1);
-- ext_res = kzalloc(copy_size, GFP_KERNEL);
-- if (!ext_res) {
-- ret = -ENOMEM;
-- goto fail;
-- }
--
-- if (copy_from_user(ext_res, user_ext_res, copy_size) != 0) {
-- ret = -EINVAL;
-- goto free_info;
-- }
-+ ext_res = memdup_user(user_ext_res, copy_size);
-+ if (IS_ERR(ext_res))
-+ return PTR_ERR(ext_res);
-
- /*
- * Overwrite the count with the first value incase it was changed
-@@ -1457,11 +1460,6 @@ static int kbase_ext_res_prepare(struct kbase_jd_atom *katom)
- katom->softjob_data = ext_res;
-
- return 0;
--
--free_info:
-- kfree(ext_res);
--fail:
-- return ret;
- }
-
- static void kbase_ext_res_process(struct kbase_jd_atom *katom, bool map)
-@@ -1538,6 +1536,7 @@ int kbase_process_soft_job(struct kbase_jd_atom *katom)
- struct kbase_device *kbdev = kctx->kbdev;
-
- KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_START(kbdev, katom);
-+ kbase_kinstr_jm_atom_sw_start(katom);
-
- trace_sysgraph(SGR_SUBMIT, kctx->id,
- kbase_jd_atom_id(kctx, katom));
-@@ -1600,6 +1599,7 @@ int kbase_process_soft_job(struct kbase_jd_atom *katom)
-
- /* Atom is complete */
- KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_END(kbdev, katom);
-+ kbase_kinstr_jm_atom_sw_stop(katom);
- return ret;
- }
-
-@@ -1635,7 +1635,9 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom)
- struct base_fence fence;
- int fd;
-
-- if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence)))
-+ if (copy_from_user(&fence,
-+ (__user void *)(uintptr_t)katom->jc,
-+ sizeof(fence)) != 0)
- return -EINVAL;
-
- fd = kbase_sync_fence_out_create(katom,
-@@ -1644,7 +1646,8 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom)
- return -EINVAL;
-
- fence.basep.fd = fd;
-- if (0 != copy_to_user((__user void *)(uintptr_t) katom->jc, &fence, sizeof(fence))) {
-+ if (copy_to_user((__user void *)(uintptr_t)katom->jc,
-+ &fence, sizeof(fence)) != 0) {
- kbase_sync_fence_out_remove(katom);
- kbase_sync_fence_close_fd(fd);
- fence.basep.fd = -EINVAL;
-@@ -1657,7 +1660,9 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom)
- struct base_fence fence;
- int ret;
-
-- if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence)))
-+ if (copy_from_user(&fence,
-+ (__user void *)(uintptr_t)katom->jc,
-+ sizeof(fence)) != 0)
- return -EINVAL;
-
- /* Get a reference to the fence object */
-@@ -1776,6 +1781,9 @@ void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev)
- if (kbase_process_soft_job(katom_iter) == 0) {
- kbase_finish_soft_job(katom_iter);
- resched |= jd_done_nolock(katom_iter, NULL);
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ atomic_dec(&kbdev->pm.gpu_users_waiting);
-+#endif /* CONFIG_MALI_ARBITER_SUPPORT */
- }
- mutex_unlock(&kctx->jctx.lock);
- }
-@@ -1783,3 +1791,4 @@ void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev)
- if (resched)
- kbase_js_sched_all(kbdev);
- }
-+#endif /* !MALI_USE_CSF */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_strings.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_strings.c
-index 22caa4a..84784be 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_strings.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_strings.c
-@@ -1,11 +1,12 @@
-- /*
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
- *
-- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2016, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,9 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-+
- #include "mali_kbase_strings.h"
-
- #define KBASE_DRV_NAME "mali"
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_strings.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_strings.h
-index d2f1825..c3f94f9 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_strings.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_strings.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2016, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- extern const char kbase_drv_name[];
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync.h
-index 80b54d0..ad05cdf 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2016, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,14 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-- * @file mali_kbase_sync.h
-- *
-- * This file contains our internal "API" for explicit fences.
-+ * DOC: This file contains our internal "API" for explicit fences.
- * It hides the implementation details of the actual explicit fence mechanism
- * used (Android fences or sync file with DMA fences).
- */
-@@ -31,11 +28,12 @@
- #ifndef MALI_KBASE_SYNC_H
- #define MALI_KBASE_SYNC_H
-
-+#include <linux/fdtable.h>
- #include <linux/syscalls.h>
--#ifdef CONFIG_SYNC
-+#if IS_ENABLED(CONFIG_SYNC)
- #include <sync.h>
- #endif
--#ifdef CONFIG_SYNC_FILE
-+#if IS_ENABLED(CONFIG_SYNC_FILE)
- #include "mali_kbase_fence_defs.h"
- #include <linux/sync_file.h>
- #endif
-@@ -72,6 +70,7 @@ struct kbase_sync_fence_info {
- */
- int kbase_sync_fence_stream_create(const char *name, int *const out_fd);
-
-+#if !MALI_USE_CSF
- /**
- * kbase_sync_fence_out_create Create an explicit output fence to specified atom
- * @katom: Atom to assign the new explicit fence to
-@@ -92,6 +91,7 @@ int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int stream_fd);
- * return: 0 on success, < 0 on error
- */
- int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd);
-+#endif /* !MALI_USE_CSF */
-
- /**
- * kbase_sync_fence_validate() - Validate a fd to be a valid fence
-@@ -104,6 +104,7 @@ int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd);
- */
- int kbase_sync_fence_validate(int fd);
-
-+#if !MALI_USE_CSF
- /**
- * kbase_sync_fence_out_trigger - Signal explicit output fence attached on katom
- * @katom: Atom with an explicit fence to signal
-@@ -154,6 +155,7 @@ void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom);
- * This will also release the corresponding reference.
- */
- void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom);
-+#endif /* !MALI_USE_CSF */
-
- /**
- * kbase_sync_fence_close_fd() - Close a file descriptor representing a fence
-@@ -161,13 +163,16 @@ void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom);
- */
- static inline void kbase_sync_fence_close_fd(int fd)
- {
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
-+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE
-+ close_fd(fd);
-+#elif KERNEL_VERSION(4, 17, 0) <= LINUX_VERSION_CODE
- ksys_close(fd);
- #else
- sys_close(fd);
- #endif
- }
-
-+#if !MALI_USE_CSF
- /**
- * kbase_sync_fence_in_info_get() - Retrieves information about input fence
- * @katom: Atom to get fence information from
-@@ -187,6 +192,7 @@ int kbase_sync_fence_in_info_get(struct kbase_jd_atom *katom,
- */
- int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom,
- struct kbase_sync_fence_info *info);
-+#endif /* !MALI_USE_CSF */
-
- #if defined(CONFIG_SYNC_FILE)
- #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
-@@ -207,6 +213,7 @@ void kbase_sync_fence_info_get(struct dma_fence *fence,
- const char *kbase_sync_status_string(int status);
-
-
-+#if !MALI_USE_CSF
- /*
- * Internal worker used to continue processing of atom.
- */
-@@ -219,5 +226,6 @@ void kbase_sync_fence_wait_worker(struct work_struct *data);
- */
- void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom);
- #endif
-+#endif /* !MALI_USE_CSF */
-
- #endif /* MALI_KBASE_SYNC_H */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_android.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_android.c
-index 75940fb..8af2584 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_android.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_android.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -50,15 +49,6 @@ struct mali_sync_pt {
- int result;
- };
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
--/* For backwards compatibility with kernels before 3.17. After 3.17
-- * sync_pt_parent is included in the kernel. */
--static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt)
--{
-- return pt->parent;
--}
--#endif
--
- static struct mali_sync_timeline *to_mali_sync_timeline(
- struct sync_timeline *timeline)
- {
-@@ -196,6 +186,7 @@ int kbase_sync_fence_stream_create(const char *name, int *const out_fd)
- return 0;
- }
-
-+#if !MALI_USE_CSF
- /* Allocates a sync point within the timeline.
- *
- * The timeline must be the one allocated by kbase_sync_timeline_alloc
-@@ -225,10 +216,6 @@ int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int tl_fd)
- struct sync_timeline *tl;
- struct sync_pt *pt;
- struct sync_fence *fence;
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
-- struct files_struct *files;
-- struct fdtable *fdt;
--#endif
- int fd;
- struct file *tl_file;
-
-@@ -259,29 +246,11 @@ int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int tl_fd)
- /* from here the fence owns the sync_pt */
-
- /* create a fd representing the fence */
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
- fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
- if (fd < 0) {
- sync_fence_put(fence);
- goto out;
- }
--#else
-- fd = get_unused_fd();
-- if (fd < 0) {
-- sync_fence_put(fence);
-- goto out;
-- }
--
-- files = current->files;
-- spin_lock(&files->file_lock);
-- fdt = files_fdtable(files);
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
-- __set_close_on_exec(fd, fdt);
--#else
-- FD_SET(fd, fdt->close_on_exec);
--#endif
-- spin_unlock(&files->file_lock);
--#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) */
-
- /* bind fence to the new fd */
- sync_fence_install(fence, fd);
-@@ -289,7 +258,8 @@ int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int tl_fd)
- katom->fence = sync_fence_fdget(fd);
- if (katom->fence == NULL) {
- /* The only way the fence can be NULL is if userspace closed it
-- * for us, so we don't need to clear it up */
-+ * for us, so we don't need to clear it up
-+ */
- fd = -EINVAL;
- goto out;
- }
-@@ -305,6 +275,7 @@ int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd)
- katom->fence = sync_fence_fdget(fd);
- return katom->fence ? 0 : -ENOENT;
- }
-+#endif /* !MALI_USE_CSF */
-
- int kbase_sync_fence_validate(int fd)
- {
-@@ -318,6 +289,7 @@ int kbase_sync_fence_validate(int fd)
- return 0;
- }
-
-+#if !MALI_USE_CSF
- /* Returns true if the specified timeline is allocated by Mali */
- static int kbase_sync_timeline_is_ours(struct sync_timeline *timeline)
- {
-@@ -376,22 +348,14 @@ kbase_sync_fence_out_trigger(struct kbase_jd_atom *katom, int result)
- if (!katom->fence)
- return BASE_JD_EVENT_JOB_CANCELLED;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
-- if (!list_is_singular(&katom->fence->pt_list_head)) {
--#else
- if (katom->fence->num_fences != 1) {
--#endif
- /* Not exactly one item in the list - so it didn't (directly)
-- * come from us */
-+ * come from us
-+ */
- return BASE_JD_EVENT_JOB_CANCELLED;
- }
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
-- pt = list_first_entry(&katom->fence->pt_list_head,
-- struct sync_pt, pt_list);
--#else
- pt = container_of(katom->fence->cbs[0].sync_pt, struct sync_pt, base);
--#endif
- timeline = sync_pt_parent(pt);
-
- if (!kbase_sync_timeline_is_ours(timeline)) {
-@@ -413,11 +377,7 @@ static inline int kbase_fence_get_status(struct sync_fence *fence)
- if (!fence)
- return -ENOENT;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
-- return fence->status;
--#else
- return atomic_read(&fence->status);
--#endif
- }
-
- static void kbase_fence_wait_callback(struct sync_fence *fence,
-@@ -461,7 +421,8 @@ int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom)
- if (ret < 0) {
- katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
- /* We should cause the dependent jobs in the bag to be failed,
-- * to do this we schedule the work queue to complete this job */
-+ * to do this we schedule the work queue to complete this job
-+ */
- INIT_WORK(&katom->work, kbase_sync_fence_wait_worker);
- queue_work(katom->kctx->jctx.job_done_wq, &katom->work);
- }
-@@ -473,7 +434,8 @@ void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom)
- {
- if (sync_fence_cancel_async(katom->fence, &katom->sync_waiter) != 0) {
- /* The wait wasn't cancelled - leave the cleanup for
-- * kbase_fence_wait_callback */
-+ * kbase_fence_wait_callback
-+ */
- return;
- }
-
-@@ -540,3 +502,4 @@ void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom)
- sync_fence_wait(katom->fence, 1);
- }
- #endif
-+#endif /* !MALI_USE_CSF */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_common.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_common.c
-index 2e1ede5..5ee7fc3 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_common.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_common.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2016, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-- * @file mali_kbase_sync_common.c
-+ * @file
- *
- * Common code for our explicit fence functionality
- */
-@@ -30,6 +29,7 @@
- #include "mali_kbase.h"
- #include "mali_kbase_sync.h"
-
-+#if !MALI_USE_CSF
- void kbase_sync_fence_wait_worker(struct work_struct *data)
- {
- struct kbase_jd_atom *katom;
-@@ -37,6 +37,7 @@ void kbase_sync_fence_wait_worker(struct work_struct *data)
- katom = container_of(data, struct kbase_jd_atom, work);
- kbase_soft_event_wait_callback(katom);
- }
-+#endif /* !MALI_USE_CSF */
-
- const char *kbase_sync_status_string(int status)
- {
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_file.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_file.c
-index 0679c48..25670c4 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_file.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_sync_file.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2012-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -59,9 +58,10 @@ int kbase_sync_fence_stream_create(const char *name, int *const out_fd)
- return 0;
- }
-
-+#if !MALI_USE_CSF
- int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int stream_fd)
- {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence;
- #else
- struct dma_fence *fence;
-@@ -106,7 +106,7 @@ int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int stream_fd)
-
- int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd)
- {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence = sync_file_get_fence(fd);
- #else
- struct dma_fence *fence = sync_file_get_fence(fd);
-@@ -119,10 +119,11 @@ int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd)
-
- return 0;
- }
-+#endif /* !MALI_USE_CSF */
-
- int kbase_sync_fence_validate(int fd)
- {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence = sync_file_get_fence(fd);
- #else
- struct dma_fence *fence = sync_file_get_fence(fd);
-@@ -136,6 +137,7 @@ int kbase_sync_fence_validate(int fd)
- return 0; /* valid */
- }
-
-+#if !MALI_USE_CSF
- enum base_jd_event_code
- kbase_sync_fence_out_trigger(struct kbase_jd_atom *katom, int result)
- {
-@@ -157,7 +159,7 @@ kbase_sync_fence_out_trigger(struct kbase_jd_atom *katom, int result)
- return (result != 0) ? BASE_JD_EVENT_JOB_CANCELLED : BASE_JD_EVENT_DONE;
- }
-
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- static void kbase_fence_wait_callback(struct fence *fence,
- struct fence_cb *cb)
- #else
-@@ -175,7 +177,7 @@ static void kbase_fence_wait_callback(struct dma_fence *fence,
- #if (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE || \
- (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE && \
- KERNEL_VERSION(4, 9, 68) <= LINUX_VERSION_CODE))
-- if (dma_fence_is_signaled(kcb->fence) && kcb->fence->error)
-+ if (dma_fence_is_signaled(kcb->fence) && kcb->fence->error < 0)
- #else
- if (dma_fence_is_signaled(kcb->fence) && kcb->fence->status < 0)
- #endif
-@@ -200,7 +202,7 @@ static void kbase_fence_wait_callback(struct dma_fence *fence,
- int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom)
- {
- int err;
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence;
- #else
- struct dma_fence *fence;
-@@ -233,8 +235,8 @@ int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom)
- katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
-
- /* We should cause the dependent jobs in the bag to be failed,
-- * to do this we schedule the work queue to complete this job */
--
-+ * to do this we schedule the work queue to complete this job
-+ */
- INIT_WORK(&katom->work, kbase_sync_fence_wait_worker);
- queue_work(katom->kctx->jctx.job_done_wq, &katom->work);
- }
-@@ -246,7 +248,8 @@ void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom)
- {
- if (!kbase_fence_free_callbacks(katom)) {
- /* The wait wasn't cancelled -
-- * leave the cleanup for kbase_fence_wait_callback */
-+ * leave the cleanup for kbase_fence_wait_callback
-+ */
- return;
- }
-
-@@ -273,6 +276,7 @@ void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom)
- kbase_fence_free_callbacks(katom);
- kbase_fence_in_remove(katom);
- }
-+#endif /* !MALI_USE_CSF */
-
- #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- void kbase_sync_fence_info_get(struct fence *fence,
-@@ -317,10 +321,11 @@ void kbase_sync_fence_info_get(struct dma_fence *fence,
- #endif
- }
-
-+#if !MALI_USE_CSF
- int kbase_sync_fence_in_info_get(struct kbase_jd_atom *katom,
- struct kbase_sync_fence_info *info)
- {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence;
- #else
- struct dma_fence *fence;
-@@ -340,7 +345,7 @@ int kbase_sync_fence_in_info_get(struct kbase_jd_atom *katom,
- int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom,
- struct kbase_sync_fence_info *info)
- {
--#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
- struct fence *fence;
- #else
- struct dma_fence *fence;
-@@ -364,3 +369,4 @@ void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom)
- /* Not implemented */
- }
- #endif
-+#endif /* !MALI_USE_CSF*/
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_trace_gpu_mem.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_trace_gpu_mem.c
-new file mode 100644
-index 0000000..3088c41
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_trace_gpu_mem.c
-@@ -0,0 +1,221 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <mali_kbase_mem_linux.h>
-+#include <mali_kbase_defs.h>
-+#include <mali_kbase_trace_gpu_mem.h>
-+
-+/**
-+ * struct kbase_dma_buf - Object instantiated when a dma-buf imported allocation
-+ * is mapped to GPU for the first time within a process.
-+ * Another instantiation is done for the case when that
-+ * allocation is mapped for the first time to GPU.
-+ *
-+ * @dma_buf: Reference to dma_buf been imported.
-+ * @dma_buf_node: Link node to maintain a rb_tree of kbase_dma_buf.
-+ * @import_count: The number of times the dma_buf was imported.
-+ */
-+struct kbase_dma_buf {
-+ struct dma_buf *dma_buf;
-+ struct rb_node dma_buf_node;
-+ u32 import_count;
-+};
-+
-+/**
-+ * kbase_delete_dma_buf_mapping - Delete a dma buffer mapping.
-+ *
-+ * @kctx: Pointer to kbase context.
-+ * @dma_buf: Pointer to a dma buffer mapping.
-+ * @tree: Pointer to root of rb_tree containing the dma_buf's mapped.
-+ *
-+ * when we un-map any dma mapping we need to remove them from rb_tree,
-+ * rb_tree is maintained at kbase_device level and kbase_process level
-+ * by passing the root of kbase_device or kbase_process we can remove
-+ * the node from the tree.
-+ */
-+static bool kbase_delete_dma_buf_mapping(struct kbase_context *kctx,
-+ struct dma_buf *dma_buf,
-+ struct rb_root *tree)
-+{
-+ struct kbase_dma_buf *buf_node = NULL;
-+ struct rb_node *node = tree->rb_node;
-+ bool mapping_removed = false;
-+
-+ lockdep_assert_held(&kctx->kbdev->dma_buf_lock);
-+
-+ while (node) {
-+ buf_node = rb_entry(node, struct kbase_dma_buf, dma_buf_node);
-+
-+ if (dma_buf == buf_node->dma_buf) {
-+ WARN_ON(!buf_node->import_count);
-+
-+ buf_node->import_count--;
-+
-+ if (!buf_node->import_count) {
-+ rb_erase(&buf_node->dma_buf_node, tree);
-+ kfree(buf_node);
-+ mapping_removed = true;
-+ }
-+
-+ break;
-+ }
-+
-+ if (dma_buf < buf_node->dma_buf)
-+ node = node->rb_left;
-+ else
-+ node = node->rb_right;
-+ }
-+
-+ WARN_ON(!buf_node);
-+ return mapping_removed;
-+}
-+
-+/**
-+ * kbase_capture_dma_buf_mapping - capture a dma buffer mapping.
-+ *
-+ * @kctx: Pointer to kbase context.
-+ * @dma_buf: Pointer to a dma buffer mapping.
-+ * @root: Pointer to root of rb_tree containing the dma_buf's.
-+ *
-+ * We maintain a kbase_device level and kbase_process level rb_tree
-+ * of all unique dma_buf's mapped to gpu memory. So when attach any
-+ * dma_buf add it the rb_tree's. To add the unique mapping we need
-+ * check if the mapping is not a duplicate and then add them.
-+ */
-+static bool kbase_capture_dma_buf_mapping(struct kbase_context *kctx,
-+ struct dma_buf *dma_buf,
-+ struct rb_root *root)
-+{
-+ struct kbase_dma_buf *buf_node = NULL;
-+ struct rb_node *node = root->rb_node;
-+ bool unique_buf_imported = true;
-+
-+ lockdep_assert_held(&kctx->kbdev->dma_buf_lock);
-+
-+ while (node) {
-+ buf_node = rb_entry(node, struct kbase_dma_buf, dma_buf_node);
-+
-+ if (dma_buf == buf_node->dma_buf) {
-+ unique_buf_imported = false;
-+ break;
-+ }
-+
-+ if (dma_buf < buf_node->dma_buf)
-+ node = node->rb_left;
-+ else
-+ node = node->rb_right;
-+ }
-+
-+ if (unique_buf_imported) {
-+ struct kbase_dma_buf *new_buf_node =
-+ kzalloc(sizeof(*new_buf_node), GFP_KERNEL);
-+
-+ if (new_buf_node == NULL) {
-+ dev_err(kctx->kbdev->dev, "Error allocating memory for kbase_dma_buf\n");
-+ /* Dont account for it if we fail to allocate memory */
-+ unique_buf_imported = false;
-+ } else {
-+ struct rb_node **new = &(root->rb_node), *parent = NULL;
-+
-+ new_buf_node->dma_buf = dma_buf;
-+ new_buf_node->import_count = 1;
-+ while (*new) {
-+ struct kbase_dma_buf *new_node;
-+
-+ parent = *new;
-+ new_node = rb_entry(parent, struct kbase_dma_buf,
-+ dma_buf_node);
-+ if (dma_buf < new_node->dma_buf)
-+ new = &(*new)->rb_left;
-+ else
-+ new = &(*new)->rb_right;
-+ }
-+ rb_link_node(&new_buf_node->dma_buf_node, parent, new);
-+ rb_insert_color(&new_buf_node->dma_buf_node, root);
-+ }
-+ } else if (!WARN_ON(!buf_node)) {
-+ buf_node->import_count++;
-+ }
-+
-+ return unique_buf_imported;
-+}
-+
-+void kbase_remove_dma_buf_usage(struct kbase_context *kctx,
-+ struct kbase_mem_phy_alloc *alloc)
-+{
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ bool dev_mapping_removed, prcs_mapping_removed;
-+
-+ mutex_lock(&kbdev->dma_buf_lock);
-+
-+ dev_mapping_removed = kbase_delete_dma_buf_mapping(
-+ kctx, alloc->imported.umm.dma_buf, &kbdev->dma_buf_root);
-+
-+ prcs_mapping_removed = kbase_delete_dma_buf_mapping(
-+ kctx, alloc->imported.umm.dma_buf, &kctx->kprcs->dma_buf_root);
-+
-+ WARN_ON(dev_mapping_removed && !prcs_mapping_removed);
-+
-+ spin_lock(&kbdev->gpu_mem_usage_lock);
-+ if (dev_mapping_removed)
-+ kbdev->total_gpu_pages -= alloc->nents;
-+
-+ if (prcs_mapping_removed)
-+ kctx->kprcs->total_gpu_pages -= alloc->nents;
-+
-+ if (dev_mapping_removed || prcs_mapping_removed)
-+ kbase_trace_gpu_mem_usage(kbdev, kctx);
-+ spin_unlock(&kbdev->gpu_mem_usage_lock);
-+
-+ mutex_unlock(&kbdev->dma_buf_lock);
-+}
-+
-+void kbase_add_dma_buf_usage(struct kbase_context *kctx,
-+ struct kbase_mem_phy_alloc *alloc)
-+{
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ bool unique_dev_dmabuf, unique_prcs_dmabuf;
-+
-+ mutex_lock(&kbdev->dma_buf_lock);
-+
-+ /* add dma_buf to device and process. */
-+ unique_dev_dmabuf = kbase_capture_dma_buf_mapping(
-+ kctx, alloc->imported.umm.dma_buf, &kbdev->dma_buf_root);
-+
-+ unique_prcs_dmabuf = kbase_capture_dma_buf_mapping(
-+ kctx, alloc->imported.umm.dma_buf, &kctx->kprcs->dma_buf_root);
-+
-+ WARN_ON(unique_dev_dmabuf && !unique_prcs_dmabuf);
-+
-+ spin_lock(&kbdev->gpu_mem_usage_lock);
-+ if (unique_dev_dmabuf)
-+ kbdev->total_gpu_pages += alloc->nents;
-+
-+ if (unique_prcs_dmabuf)
-+ kctx->kprcs->total_gpu_pages += alloc->nents;
-+
-+ if (unique_prcs_dmabuf || unique_dev_dmabuf)
-+ kbase_trace_gpu_mem_usage(kbdev, kctx);
-+ spin_unlock(&kbdev->gpu_mem_usage_lock);
-+
-+ mutex_unlock(&kbdev->dma_buf_lock);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_trace_gpu_mem.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_trace_gpu_mem.h
-new file mode 100644
-index 0000000..fd871fc
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_trace_gpu_mem.h
-@@ -0,0 +1,100 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KBASE_TRACE_GPU_MEM_H_
-+#define _KBASE_TRACE_GPU_MEM_H_
-+
-+#if IS_ENABLED(CONFIG_TRACE_GPU_MEM)
-+#include <trace/events/gpu_mem.h>
-+#endif
-+
-+#define DEVICE_TGID ((u32) 0U)
-+
-+static void kbase_trace_gpu_mem_usage(struct kbase_device *kbdev,
-+ struct kbase_context *kctx)
-+{
-+#if IS_ENABLED(CONFIG_TRACE_GPU_MEM)
-+ lockdep_assert_held(&kbdev->gpu_mem_usage_lock);
-+
-+ trace_gpu_mem_total(kbdev->id, DEVICE_TGID,
-+ kbdev->total_gpu_pages << PAGE_SHIFT);
-+
-+ if (likely(kctx))
-+ trace_gpu_mem_total(kbdev->id, kctx->kprcs->tgid,
-+ kctx->kprcs->total_gpu_pages << PAGE_SHIFT);
-+#endif
-+}
-+
-+static inline void kbase_trace_gpu_mem_usage_dec(struct kbase_device *kbdev,
-+ struct kbase_context *kctx, size_t pages)
-+{
-+ spin_lock(&kbdev->gpu_mem_usage_lock);
-+
-+ if (likely(kctx))
-+ kctx->kprcs->total_gpu_pages -= pages;
-+
-+ kbdev->total_gpu_pages -= pages;
-+
-+ kbase_trace_gpu_mem_usage(kbdev, kctx);
-+
-+ spin_unlock(&kbdev->gpu_mem_usage_lock);
-+}
-+
-+static inline void kbase_trace_gpu_mem_usage_inc(struct kbase_device *kbdev,
-+ struct kbase_context *kctx, size_t pages)
-+{
-+ spin_lock(&kbdev->gpu_mem_usage_lock);
-+
-+ if (likely(kctx))
-+ kctx->kprcs->total_gpu_pages += pages;
-+
-+ kbdev->total_gpu_pages += pages;
-+
-+ kbase_trace_gpu_mem_usage(kbdev, kctx);
-+
-+ spin_unlock(&kbdev->gpu_mem_usage_lock);
-+}
-+
-+/**
-+ * kbase_remove_dma_buf_usage - Remove a dma-buf entry captured.
-+ *
-+ * @kctx: Pointer to the kbase context
-+ * @alloc: Pointer to the alloc to unmap
-+ *
-+ * Remove reference to dma buf been unmapped from kbase_device level
-+ * rb_tree and Kbase_process level dma buf rb_tree.
-+ */
-+void kbase_remove_dma_buf_usage(struct kbase_context *kctx,
-+ struct kbase_mem_phy_alloc *alloc);
-+
-+/**
-+ * kbase_add_dma_buf_usage - Add a dma-buf entry captured.
-+ *
-+ * @kctx: Pointer to the kbase context
-+ * @alloc: Pointer to the alloc to map in
-+ *
-+ * Add reference to dma buf been mapped to kbase_device level
-+ * rb_tree and Kbase_process level dma buf rb_tree.
-+ */
-+void kbase_add_dma_buf_usage(struct kbase_context *kctx,
-+ struct kbase_mem_phy_alloc *alloc);
-+
-+#endif /* _KBASE_TRACE_GPU_MEM_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_utility.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_utility.h
-index 8d4f044..2dad49b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_utility.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_utility.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2013, 2015, 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2013, 2015, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #ifndef _KBASE_UTILITY_H
- #define _KBASE_UTILITY_H
-
-@@ -32,7 +29,7 @@
- static inline void kbase_timer_setup(struct timer_list *timer,
- void (*callback)(struct timer_list *timer))
- {
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
-+#if KERNEL_VERSION(4, 14, 0) > LINUX_VERSION_CODE
- setup_timer(timer, (void (*)(unsigned long)) callback,
- (unsigned long) timer);
- #else
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_vinstr.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_vinstr.c
-index d96b565..64405af 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_vinstr.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_vinstr.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,16 +17,14 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase_vinstr.h"
- #include "mali_kbase_hwcnt_virtualizer.h"
- #include "mali_kbase_hwcnt_types.h"
--#include "mali_kbase_hwcnt_reader.h"
-+#include <uapi/gpu/arm/midgard/mali_kbase_hwcnt_reader.h>
- #include "mali_kbase_hwcnt_gpu.h"
--#include "mali_kbase_ioctl.h"
-+#include <uapi/gpu/arm/midgard/mali_kbase_ioctl.h>
- #include "mali_malisw.h"
- #include "mali_kbase_debug.h"
-
-@@ -33,6 +32,7 @@
- #include <linux/fcntl.h>
- #include <linux/fs.h>
- #include <linux/hrtimer.h>
-+#include <linux/log2.h>
- #include <linux/mm.h>
- #include <linux/mutex.h>
- #include <linux/poll.h>
-@@ -53,6 +53,10 @@
- * counters.
- * @hvirt: Hardware counter virtualizer used by vinstr.
- * @metadata: Hardware counter metadata provided by virtualizer.
-+ * @metadata_user: API compatible hardware counter metadata provided by vinstr.
-+ * For compatibility with the user driver interface, this
-+ * contains a "truncated" version of the HWCNT metadata limited
-+ * to 64 entries per block. NULL when not required.
- * @lock: Lock protecting all vinstr state.
- * @suspend_count: Suspend reference count. If non-zero, timer and worker are
- * prevented from being re-scheduled.
-@@ -64,6 +68,7 @@
- struct kbase_vinstr_context {
- struct kbase_hwcnt_virtualizer *hvirt;
- const struct kbase_hwcnt_metadata *metadata;
-+ const struct kbase_hwcnt_metadata *metadata_user;
- struct mutex lock;
- size_t suspend_count;
- size_t client_count;
-@@ -83,6 +88,7 @@ struct kbase_vinstr_context {
- * @next_dump_time_ns: Time in ns when this client's next periodic dump must
- * occur. If 0, not a periodic client.
- * @enable_map: Counters enable map.
-+ * @tmp_buf: Temporary buffer to use before handing dump to client.
- * @dump_bufs: Array of dump buffers allocated by this client.
- * @dump_bufs_meta: Metadata of dump buffers.
- * @meta_idx: Index of metadata being accessed by userspace.
-@@ -97,6 +103,7 @@ struct kbase_vinstr_client {
- u64 next_dump_time_ns;
- u32 dump_interval_ns;
- struct kbase_hwcnt_enable_map enable_map;
-+ struct kbase_hwcnt_dump_buffer tmp_buf;
- struct kbase_hwcnt_dump_buffer_array dump_bufs;
- struct kbase_hwcnt_reader_metadata *dump_bufs_meta;
- atomic_t meta_idx;
-@@ -182,8 +189,10 @@ static int kbasep_vinstr_client_dump(
- u64 ts_end_ns;
- unsigned int write_idx;
- unsigned int read_idx;
-+ struct kbase_hwcnt_dump_buffer *tmp_buf;
- struct kbase_hwcnt_dump_buffer *dump_buf;
- struct kbase_hwcnt_reader_metadata *meta;
-+ u8 clk_cnt;
-
- WARN_ON(!vcli);
- lockdep_assert_held(&vcli->vctx->lock);
-@@ -198,23 +207,42 @@ static int kbasep_vinstr_client_dump(
-
- dump_buf = &vcli->dump_bufs.bufs[write_idx];
- meta = &vcli->dump_bufs_meta[write_idx];
-+ tmp_buf = &vcli->tmp_buf;
-
- errcode = kbase_hwcnt_virtualizer_client_dump(
-- vcli->hvcli, &ts_start_ns, &ts_end_ns, dump_buf);
-+ vcli->hvcli, &ts_start_ns, &ts_end_ns, tmp_buf);
- if (errcode)
- return errcode;
-
- /* Patch the dump buf headers, to hide the counters that other hwcnt
- * clients are using.
- */
-- kbase_hwcnt_gpu_patch_dump_headers(dump_buf, &vcli->enable_map);
-+ kbase_hwcnt_gpu_patch_dump_headers(tmp_buf, &vcli->enable_map);
-+
-+ /* Copy the temp buffer to the userspace visible buffer. The strict
-+ * variant will explicitly zero any non-enabled counters to ensure
-+ * nothing except exactly what the user asked for is made visible.
-+ *
-+ * If the metadata in vinstr (vctx->metadata_user) is not NULL, it means
-+ * vinstr has the truncated metadata, so do a narrow copy since
-+ * virtualizer has a bigger buffer but user only needs part of it.
-+ * otherwise we do a full copy.
-+ */
-+ if (vcli->vctx->metadata_user)
-+ kbase_hwcnt_dump_buffer_copy_strict_narrow(dump_buf, tmp_buf,
-+ &vcli->enable_map);
-+ else
-+ kbase_hwcnt_dump_buffer_copy_strict(dump_buf, tmp_buf,
-+ &vcli->enable_map);
-
-- /* Zero all non-enabled counters (current values are undefined) */
-- kbase_hwcnt_dump_buffer_zero_non_enabled(dump_buf, &vcli->enable_map);
-+ clk_cnt = vcli->vctx->metadata->clk_cnt;
-
- meta->timestamp = ts_end_ns;
- meta->event_id = event_id;
- meta->buffer_idx = write_idx;
-+ meta->cycles.top = (clk_cnt > 0) ? dump_buf->clk_cnt_buf[0] : 0;
-+ meta->cycles.shader_cores =
-+ (clk_cnt > 1) ? dump_buf->clk_cnt_buf[1] : 0;
-
- /* Notify client. Make sure all changes to memory are visible. */
- wmb();
-@@ -345,11 +373,7 @@ static enum hrtimer_restart kbasep_vinstr_dump_timer(struct hrtimer *timer)
- * cancelled, and the worker itself won't reschedule this timer if
- * suspend_count != 0.
- */
--#if KERNEL_VERSION(3, 16, 0) > LINUX_VERSION_CODE
-- queue_work(system_wq, &vctx->dump_work);
--#else
-- queue_work(system_highpri_wq, &vctx->dump_work);
--#endif
-+ kbase_hwcnt_virtualizer_queue_work(vctx->hvirt, &vctx->dump_work);
- return HRTIMER_NORESTART;
- }
-
-@@ -365,6 +389,7 @@ static void kbasep_vinstr_client_destroy(struct kbase_vinstr_client *vcli)
- kbase_hwcnt_virtualizer_client_destroy(vcli->hvcli);
- kfree(vcli->dump_bufs_meta);
- kbase_hwcnt_dump_buffer_array_free(&vcli->dump_bufs);
-+ kbase_hwcnt_dump_buffer_free(&vcli->tmp_buf);
- kbase_hwcnt_enable_map_free(&vcli->enable_map);
- kfree(vcli);
- }
-@@ -374,7 +399,7 @@ static void kbasep_vinstr_client_destroy(struct kbase_vinstr_client *vcli)
- * the vinstr context.
- * @vctx: Non-NULL pointer to vinstr context.
- * @setup: Non-NULL pointer to hardware counter ioctl setup structure.
-- * setup->buffer_count must not be 0.
-+ * setup->buffer_count must not be 0 and must be a power of 2.
- * @out_vcli: Non-NULL pointer to where created client will be stored on
- * success.
- *
-@@ -392,6 +417,7 @@ static int kbasep_vinstr_client_create(
- WARN_ON(!vctx);
- WARN_ON(!setup);
- WARN_ON(setup->buffer_count == 0);
-+ WARN_ON(!is_power_of_2(setup->buffer_count));
-
- vcli = kzalloc(sizeof(*vcli), GFP_KERNEL);
- if (!vcli)
-@@ -404,14 +430,36 @@ static int kbasep_vinstr_client_create(
- if (errcode)
- goto error;
-
-- phys_em.jm_bm = setup->jm_bm;
-+ phys_em.fe_bm = setup->fe_bm;
- phys_em.shader_bm = setup->shader_bm;
- phys_em.tiler_bm = setup->tiler_bm;
- phys_em.mmu_l2_bm = setup->mmu_l2_bm;
- kbase_hwcnt_gpu_enable_map_from_physical(&vcli->enable_map, &phys_em);
-
-- errcode = kbase_hwcnt_dump_buffer_array_alloc(
-- vctx->metadata, setup->buffer_count, &vcli->dump_bufs);
-+ /* Use virtualizer's metadata to alloc tmp buffer which interacts with
-+ * the HWC virtualizer.
-+ */
-+ errcode = kbase_hwcnt_dump_buffer_alloc(vctx->metadata, &vcli->tmp_buf);
-+ if (errcode)
-+ goto error;
-+
-+ /* Enable all the available clk_enable_map. */
-+ vcli->enable_map.clk_enable_map = (1ull << vctx->metadata->clk_cnt) - 1;
-+
-+ if (vctx->metadata_user)
-+ /* Use vinstr's truncated metadata to alloc dump buffers which
-+ * interact with clients.
-+ */
-+ errcode =
-+ kbase_hwcnt_dump_buffer_array_alloc(vctx->metadata_user,
-+ setup->buffer_count,
-+ &vcli->dump_bufs);
-+ else
-+ /* Use metadata from virtualizer to allocate dump buffers if
-+ * vinstr doesn't have the truncated metadata.
-+ */
-+ errcode = kbase_hwcnt_dump_buffer_array_alloc(
-+ vctx->metadata, setup->buffer_count, &vcli->dump_bufs);
- if (errcode)
- goto error;
-
-@@ -439,6 +487,7 @@ int kbase_vinstr_init(
- struct kbase_hwcnt_virtualizer *hvirt,
- struct kbase_vinstr_context **out_vctx)
- {
-+ int errcode;
- struct kbase_vinstr_context *vctx;
- const struct kbase_hwcnt_metadata *metadata;
-
-@@ -455,6 +504,11 @@ int kbase_vinstr_init(
-
- vctx->hvirt = hvirt;
- vctx->metadata = metadata;
-+ vctx->metadata_user = NULL;
-+ errcode = kbase_hwcnt_gpu_metadata_create_truncate_64(
-+ &vctx->metadata_user, metadata);
-+ if (errcode)
-+ goto err_metadata_create;
-
- mutex_init(&vctx->lock);
- INIT_LIST_HEAD(&vctx->clients);
-@@ -464,6 +518,11 @@ int kbase_vinstr_init(
-
- *out_vctx = vctx;
- return 0;
-+
-+err_metadata_create:
-+ kfree(vctx);
-+
-+ return errcode;
- }
-
- void kbase_vinstr_term(struct kbase_vinstr_context *vctx)
-@@ -484,6 +543,9 @@ void kbase_vinstr_term(struct kbase_vinstr_context *vctx)
- }
- }
-
-+ if (vctx->metadata_user)
-+ kbase_hwcnt_metadata_destroy(vctx->metadata_user);
-+
- WARN_ON(vctx->client_count != 0);
- kfree(vctx);
- }
-@@ -543,11 +605,8 @@ void kbase_vinstr_resume(struct kbase_vinstr_context *vctx)
- }
-
- if (has_periodic_clients)
--#if KERNEL_VERSION(3, 16, 0) > LINUX_VERSION_CODE
-- queue_work(system_wq, &vctx->dump_work);
--#else
-- queue_work(system_highpri_wq, &vctx->dump_work);
--#endif
-+ kbase_hwcnt_virtualizer_queue_work(
-+ vctx->hvirt, &vctx->dump_work);
- }
- }
-
-@@ -564,7 +623,8 @@ int kbase_vinstr_hwcnt_reader_setup(
-
- if (!vctx || !setup ||
- (setup->buffer_count == 0) ||
-- (setup->buffer_count > MAX_BUFFER_COUNT))
-+ (setup->buffer_count > MAX_BUFFER_COUNT) ||
-+ !is_power_of_2(setup->buffer_count))
- return -EINVAL;
-
- errcode = kbasep_vinstr_client_create(vctx, setup, &vcli);
-@@ -675,26 +735,31 @@ static long kbasep_vinstr_hwcnt_reader_ioctl_get_buffer(
- unsigned int idx = meta_idx % cli->dump_bufs.buf_cnt;
-
- struct kbase_hwcnt_reader_metadata *meta = &cli->dump_bufs_meta[idx];
-+ const size_t meta_size = sizeof(struct kbase_hwcnt_reader_metadata);
-+ const size_t min_size = min(size, meta_size);
-
- /* Metadata sanity check. */
- WARN_ON(idx != meta->buffer_idx);
-
-- if (sizeof(struct kbase_hwcnt_reader_metadata) != size)
-- return -EINVAL;
--
- /* Check if there is any buffer available. */
-- if (atomic_read(&cli->write_idx) == meta_idx)
-+ if (unlikely(atomic_read(&cli->write_idx) == meta_idx))
- return -EAGAIN;
-
- /* Check if previously taken buffer was put back. */
-- if (atomic_read(&cli->read_idx) != meta_idx)
-+ if (unlikely(atomic_read(&cli->read_idx) != meta_idx))
- return -EBUSY;
-
-+ /* Clear user buffer to zero. */
-+ if (unlikely(meta_size < size && clear_user(buffer, size)))
-+ return -EFAULT;
-+
- /* Copy next available buffer's metadata to user. */
-- if (copy_to_user(buffer, meta, size))
-+ if (unlikely(copy_to_user(buffer, meta, min_size)))
- return -EFAULT;
-
-- atomic_inc(&cli->meta_idx);
-+ /* Compare exchange meta idx to protect against concurrent getters */
-+ if (meta_idx != atomic_cmpxchg(&cli->meta_idx, meta_idx, meta_idx + 1))
-+ return -EBUSY;
-
- return 0;
- }
-@@ -715,24 +780,68 @@ static long kbasep_vinstr_hwcnt_reader_ioctl_put_buffer(
- unsigned int read_idx = atomic_read(&cli->read_idx);
- unsigned int idx = read_idx % cli->dump_bufs.buf_cnt;
-
-- struct kbase_hwcnt_reader_metadata meta;
--
-- if (sizeof(struct kbase_hwcnt_reader_metadata) != size)
-- return -EINVAL;
-+ struct kbase_hwcnt_reader_metadata *meta;
-+ const size_t meta_size = sizeof(struct kbase_hwcnt_reader_metadata);
-+ const size_t max_size = max(size, meta_size);
-+ int ret = 0;
-+ u8 stack_kbuf[64];
-+ u8 *kbuf = NULL;
-+ size_t i;
-
- /* Check if any buffer was taken. */
-- if (atomic_read(&cli->meta_idx) == read_idx)
-+ if (unlikely(atomic_read(&cli->meta_idx) == read_idx))
- return -EPERM;
-
-+ if (likely(max_size <= sizeof(stack_kbuf))) {
-+ /* Use stack buffer when the size is small enough. */
-+ if (unlikely(meta_size > size))
-+ memset(stack_kbuf, 0, sizeof(stack_kbuf));
-+ kbuf = stack_kbuf;
-+ } else {
-+ kbuf = kzalloc(max_size, GFP_KERNEL);
-+ if (unlikely(!kbuf))
-+ return -ENOMEM;
-+ }
-+
-+ /*
-+ * Copy user buffer to zero cleared kernel buffer which has enough
-+ * space for both user buffer and kernel metadata.
-+ */
-+ if (unlikely(copy_from_user(kbuf, buffer, size))) {
-+ ret = -EFAULT;
-+ goto out;
-+ }
-+
-+ /*
-+ * Make sure any "extra" data passed from userspace is zero.
-+ * It's meaningful only in case meta_size < size.
-+ */
-+ for (i = meta_size; i < size; i++) {
-+ /* Check if user data beyond meta size is zero. */
-+ if (unlikely(kbuf[i] != 0)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ }
-+
- /* Check if correct buffer is put back. */
-- if (copy_from_user(&meta, buffer, size))
-- return -EFAULT;
-- if (idx != meta.buffer_idx)
-- return -EINVAL;
-+ meta = (struct kbase_hwcnt_reader_metadata *)kbuf;
-+ if (unlikely(idx != meta->buffer_idx)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-
-- atomic_inc(&cli->read_idx);
-+ /* Compare exchange read idx to protect against concurrent putters */
-+ if (read_idx !=
-+ atomic_cmpxchg(&cli->read_idx, read_idx, read_idx + 1)) {
-+ ret = -EPERM;
-+ goto out;
-+ }
-
-- return 0;
-+out:
-+ if (unlikely(kbuf != stack_kbuf))
-+ kfree(kbuf);
-+ return ret;
- }
-
- /**
-@@ -760,11 +869,8 @@ static long kbasep_vinstr_hwcnt_reader_ioctl_set_interval(
- * worker is already queued.
- */
- if ((interval != 0) && (cli->vctx->suspend_count == 0))
--#if KERNEL_VERSION(3, 16, 0) > LINUX_VERSION_CODE
-- queue_work(system_wq, &cli->vctx->dump_work);
--#else
-- queue_work(system_highpri_wq, &cli->vctx->dump_work);
--#endif
-+ kbase_hwcnt_virtualizer_queue_work(cli->vctx->hvirt,
-+ &cli->vctx->dump_work);
-
- mutex_unlock(&cli->vctx->lock);
-
-@@ -813,26 +919,58 @@ static long kbasep_vinstr_hwcnt_reader_ioctl_get_hwver(
- struct kbase_vinstr_client *cli,
- u32 __user *hwver)
- {
-- u32 ver = 0;
-+ u32 ver = 5;
- const enum kbase_hwcnt_gpu_group_type type =
- kbase_hwcnt_metadata_group_type(cli->vctx->metadata, 0);
-
-- switch (type) {
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V4:
-- ver = 4;
-- break;
-- case KBASE_HWCNT_GPU_GROUP_TYPE_V5:
-- ver = 5;
-- break;
-- default:
-- WARN_ON(true);
-- }
--
-- if (ver != 0) {
-- return put_user(ver, hwver);
-- } else {
-+ if (WARN_ON(type != KBASE_HWCNT_GPU_GROUP_TYPE_V5))
- return -EINVAL;
-+
-+ return put_user(ver, hwver);
-+}
-+
-+/**
-+ * The hwcnt reader's ioctl command - get API version.
-+ * @cli: The non-NULL pointer to the client
-+ * @arg: Command's argument.
-+ * @size: Size of arg.
-+ *
-+ * @return 0 on success, else error code.
-+ */
-+static long kbasep_vinstr_hwcnt_reader_ioctl_get_api_version(
-+ struct kbase_vinstr_client *cli, unsigned long arg, size_t size)
-+{
-+ long ret = -EINVAL;
-+
-+ if (size == sizeof(u32)) {
-+ ret = put_user(HWCNT_READER_API, (u32 __user *)arg);
-+ } else if (size == sizeof(struct kbase_hwcnt_reader_api_version)) {
-+ u8 clk_cnt = cli->vctx->metadata->clk_cnt;
-+ unsigned long bytes = 0;
-+ struct kbase_hwcnt_reader_api_version api_version = {
-+ .version = HWCNT_READER_API,
-+ .features = KBASE_HWCNT_READER_API_VERSION_NO_FEATURE,
-+ };
-+
-+ if (clk_cnt > 0)
-+ api_version.features |=
-+ KBASE_HWCNT_READER_API_VERSION_FEATURE_CYCLES_TOP;
-+ if (clk_cnt > 1)
-+ api_version.features |=
-+ KBASE_HWCNT_READER_API_VERSION_FEATURE_CYCLES_SHADER_CORES;
-+
-+ bytes = copy_to_user(
-+ (void __user *)arg, &api_version, sizeof(api_version));
-+
-+ /* copy_to_user returns zero in case of success.
-+ * If it fails, it returns the number of bytes that could NOT be copied
-+ */
-+ if (bytes == 0)
-+ ret = 0;
-+ else
-+ ret = -EFAULT;
- }
-+ return ret;
- }
-
- /**
-@@ -858,42 +996,48 @@ static long kbasep_vinstr_hwcnt_reader_ioctl(
- if (!cli)
- return -EINVAL;
-
-- switch (cmd) {
-- case KBASE_HWCNT_READER_GET_API_VERSION:
-- rcode = put_user(HWCNT_READER_API, (u32 __user *)arg);
-+ switch (_IOC_NR(cmd)) {
-+ case _IOC_NR(KBASE_HWCNT_READER_GET_API_VERSION):
-+ rcode = kbasep_vinstr_hwcnt_reader_ioctl_get_api_version(
-+ cli, arg, _IOC_SIZE(cmd));
- break;
-- case KBASE_HWCNT_READER_GET_HWVER:
-+ case _IOC_NR(KBASE_HWCNT_READER_GET_HWVER):
- rcode = kbasep_vinstr_hwcnt_reader_ioctl_get_hwver(
- cli, (u32 __user *)arg);
- break;
-- case KBASE_HWCNT_READER_GET_BUFFER_SIZE:
-- rcode = put_user(
-- (u32)cli->vctx->metadata->dump_buf_bytes,
-- (u32 __user *)arg);
-+ case _IOC_NR(KBASE_HWCNT_READER_GET_BUFFER_SIZE):
-+ if (cli->vctx->metadata_user)
-+ rcode = put_user(
-+ (u32)cli->vctx->metadata_user->dump_buf_bytes,
-+ (u32 __user *)arg);
-+ else
-+ rcode = put_user(
-+ (u32)cli->vctx->metadata->dump_buf_bytes,
-+ (u32 __user *)arg);
- break;
-- case KBASE_HWCNT_READER_DUMP:
-+ case _IOC_NR(KBASE_HWCNT_READER_DUMP):
- rcode = kbasep_vinstr_hwcnt_reader_ioctl_dump(cli);
- break;
-- case KBASE_HWCNT_READER_CLEAR:
-+ case _IOC_NR(KBASE_HWCNT_READER_CLEAR):
- rcode = kbasep_vinstr_hwcnt_reader_ioctl_clear(cli);
- break;
-- case KBASE_HWCNT_READER_GET_BUFFER:
-+ case _IOC_NR(KBASE_HWCNT_READER_GET_BUFFER):
- rcode = kbasep_vinstr_hwcnt_reader_ioctl_get_buffer(
- cli, (void __user *)arg, _IOC_SIZE(cmd));
- break;
-- case KBASE_HWCNT_READER_PUT_BUFFER:
-+ case _IOC_NR(KBASE_HWCNT_READER_PUT_BUFFER):
- rcode = kbasep_vinstr_hwcnt_reader_ioctl_put_buffer(
- cli, (void __user *)arg, _IOC_SIZE(cmd));
- break;
-- case KBASE_HWCNT_READER_SET_INTERVAL:
-+ case _IOC_NR(KBASE_HWCNT_READER_SET_INTERVAL):
- rcode = kbasep_vinstr_hwcnt_reader_ioctl_set_interval(
- cli, (u32)arg);
- break;
-- case KBASE_HWCNT_READER_ENABLE_EVENT:
-+ case _IOC_NR(KBASE_HWCNT_READER_ENABLE_EVENT):
- rcode = kbasep_vinstr_hwcnt_reader_ioctl_enable_event(
- cli, (enum base_hwcnt_reader_event)arg);
- break;
-- case KBASE_HWCNT_READER_DISABLE_EVENT:
-+ case _IOC_NR(KBASE_HWCNT_READER_DISABLE_EVENT):
- rcode = kbasep_vinstr_hwcnt_reader_ioctl_disable_event(
- cli, (enum base_hwcnt_reader_event)arg);
- break;
-@@ -955,7 +1099,16 @@ static int kbasep_vinstr_hwcnt_reader_mmap(
- return -EINVAL;
-
- vm_size = vma->vm_end - vma->vm_start;
-- size = cli->dump_bufs.buf_cnt * cli->vctx->metadata->dump_buf_bytes;
-+
-+ /* The mapping is allowed to span the entirety of the page allocation,
-+ * not just the chunk where the dump buffers are allocated.
-+ * This accommodates the corner case where the combined size of the
-+ * dump buffers is smaller than a single page.
-+ * This does not pose a security risk as the pages are zeroed on
-+ * allocation, and anything out of bounds of the dump buffers is never
-+ * written to.
-+ */
-+ size = (1ull << cli->dump_bufs.page_order) * PAGE_SIZE;
-
- if (vma->vm_pgoff > (size >> PAGE_SHIFT))
- return -EINVAL;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_vinstr.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_vinstr.h
-index 81d315f..6747ec7 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_vinstr.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_vinstr.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2015-2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_linux_trace.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_linux_trace.h
-index f618755..2a243dd 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_linux_trace.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_linux_trace.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2011-2016, 2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2016, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #undef TRACE_SYSTEM
-@@ -31,7 +30,7 @@
- #if defined(CONFIG_MALI_GATOR_SUPPORT)
- #define MALI_JOB_SLOTS_EVENT_CHANGED
-
--/**
-+/*
- * mali_job_slots_event - Reports change of job slot status.
- * @gpu_id: Kbase device id
- * @event_id: ORed together bitfields representing a type of event,
-@@ -181,6 +180,23 @@ TRACE_EVENT(mali_total_alloc_pages_change,
- __print_symbolic(KBASE_MMU_FAULT_STATUS_ACCESS(status), \
- KBASE_MMU_FAULT_ACCESS_SYMBOLIC_STRINGS)
-
-+#if MALI_USE_CSF
-+#define KBASE_MMU_FAULT_CODE_VALID(code) \
-+ ((code >= 0xC0 && code <= 0xEB) && \
-+ (!(code >= 0xC5 && code <= 0xC7)) && \
-+ (!(code >= 0xCC && code <= 0xD8)) && \
-+ (!(code >= 0xDC && code <= 0xDF)) && \
-+ (!(code >= 0xE1 && code <= 0xE3)))
-+#define KBASE_MMU_FAULT_CODE_SYMBOLIC_STRINGS _ENSURE_PARENTHESIS(\
-+ {0xC0, "TRANSLATION_FAULT_" }, \
-+ {0xC4, "TRANSLATION_FAULT_" }, \
-+ {0xC8, "PERMISSION_FAULT_" }, \
-+ {0xD0, "TRANSTAB_BUS_FAULT_" }, \
-+ {0xD8, "ACCESS_FLAG_" }, \
-+ {0xE0, "ADDRESS_SIZE_FAULT_IN" }, \
-+ {0xE4, "ADDRESS_SIZE_FAULT_OUT" }, \
-+ {0xE8, "MEMORY_ATTRIBUTES_FAULT_" })
-+#else /* MALI_USE_CSF */
- #define KBASE_MMU_FAULT_CODE_VALID(code) \
- ((code >= 0xC0 && code <= 0xEF) && \
- (!(code >= 0xC5 && code <= 0xC6)) && \
-@@ -197,6 +213,7 @@ TRACE_EVENT(mali_total_alloc_pages_change,
- {0xE4, "ADDRESS_SIZE_FAULT_OUT" }, \
- {0xE8, "MEMORY_ATTRIBUTES_FAULT_" }, \
- {0xEC, "MEMORY_ATTRIBUTES_NONCACHEABLE_" })
-+#endif /* MALI_USE_CSF */
- #endif /* __TRACE_MALI_MMU_HELPERS */
-
- /* trace_mali_mmu_page_fault_grow
-@@ -288,7 +305,8 @@ DEFINE_EVENT_PRINT(mali_jit_softjob_template, mali_jit_free,
- TP_printk("start=0x%llx va_pages=0x%zx backed_size=0x%zx",
- __entry->start_addr, __entry->nr_pages, __entry->backed_pages));
-
--#if MALI_JIT_PRESSURE_LIMIT
-+#if !MALI_USE_CSF
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /* trace_mali_jit_report
- *
- * Tracepoint about the GPU data structure read to form a just-in-time memory
-@@ -326,13 +344,11 @@ TRACE_EVENT(mali_jit_report,
- ),
- __entry->read_val, __entry->used_pages)
- );
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-+#endif /* !MALI_USE_CSF */
-
--#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE)
- TRACE_DEFINE_ENUM(KBASE_JIT_REPORT_ON_ALLOC_OR_FREE);
--#endif
--
--#if MALI_JIT_PRESSURE_LIMIT
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
- /* trace_mali_jit_report_pressure
- *
- * Tracepoint about change in physical memory pressure, due to the information
-@@ -366,14 +382,13 @@ TRACE_EVENT(mali_jit_report_pressure,
- { KBASE_JIT_REPORT_ON_ALLOC_OR_FREE,
- "HAPPENED_ON_ALLOC_OR_FREE" }))
- );
--#endif /* MALI_JIT_PRESSURE_LIMIT */
-+#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
-
- #ifndef __TRACE_SYSGRAPH_ENUM
- #define __TRACE_SYSGRAPH_ENUM
- /* Enum of sysgraph message IDs */
- enum sysgraph_msg {
- SGR_ARRIVE,
-- SGR_DEP_RES,
- SGR_SUBMIT,
- SGR_COMPLETE,
- SGR_POST,
-@@ -401,7 +416,7 @@ TRACE_EVENT(sysgraph,
- __entry->message = message;
- __entry->atom_id = atom_id;
- ),
-- TP_printk("msg=%u proc_id=%u, param1=%d\n", __entry->message,
-+ TP_printk("msg=%u proc_id=%u, param1=%d", __entry->message,
- __entry->proc_id, __entry->atom_id)
- );
-
-@@ -427,7 +442,7 @@ TRACE_EVENT(sysgraph_gpu,
- __entry->atom_id = atom_id;
- __entry->js = js;
- ),
-- TP_printk("msg=%u proc_id=%u, param1=%d, param2=%d\n",
-+ TP_printk("msg=%u proc_id=%u, param1=%d, param2=%d",
- __entry->message, __entry->proc_id,
- __entry->atom_id, __entry->js)
- );
-@@ -516,7 +531,7 @@ TRACE_EVENT(mali_jit_trim,
- TP_printk("freed_pages=%zu", __entry->freed_pages)
- );
-
--#include "mali_kbase_debug_linux_ktrace.h"
-+#include "debug/mali_kbase_debug_linux_ktrace.h"
-
- #endif /* _TRACE_MALI_H */
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_malisw.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_malisw.h
-index 3a4db10..c0649f2 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_malisw.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_malisw.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2015, 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2015, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-@@ -28,26 +27,11 @@
- #define _MALISW_H_
-
- #include <linux/version.h>
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
--#define U8_MAX ((u8)~0U)
--#define S8_MAX ((s8)(U8_MAX>>1))
--#define S8_MIN ((s8)(-S8_MAX - 1))
--#define U16_MAX ((u16)~0U)
--#define S16_MAX ((s16)(U16_MAX>>1))
--#define S16_MIN ((s16)(-S16_MAX - 1))
--#define U32_MAX ((u32)~0U)
--#define S32_MAX ((s32)(U32_MAX>>1))
--#define S32_MIN ((s32)(-S32_MAX - 1))
--#define U64_MAX ((u64)~0ULL)
--#define S64_MAX ((s64)(U64_MAX>>1))
--#define S64_MIN ((s64)(-S64_MAX - 1))
--#endif /* LINUX_VERSION_CODE */
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
--#define SIZE_MAX (~(size_t)0)
--#endif /* LINUX_VERSION_CODE */
-
- /**
- * MIN - Return the lesser of two values.
-+ * @x: value1
-+ * @y: value2
- *
- * As a macro it may evaluate its arguments more than once.
- * Refer to MAX macro for more details
-@@ -55,7 +39,9 @@
- #define MIN(x, y) ((x) < (y) ? (x) : (y))
-
- /**
-- * MAX - Return the greater of two values.
-+ * MAX - Return the greater of two values.
-+ * @x: value1
-+ * @y: value2
- *
- * As a macro it may evaluate its arguments more than once.
- * If called on the same two arguments as MIN it is guaranteed to return
-@@ -67,24 +53,27 @@
- #define MAX(x, y) ((x) < (y) ? (y) : (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.
-+ * Function-like macro for suppressing unused variable warnings.
-+ * @x: unused variable
-+ *
-+ * 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.
-+ * Function-like macro for use where "no behavior" is desired.
-+ * @...: no-op
-+ *
-+ * 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 stringizing a single level macro.
-+ * @x: macro's value
-+ *
- * @code
- * #define MY_MACRO 32
- * CSTD_STR1( MY_MACRO )
-@@ -94,10 +83,11 @@
- #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.
-+ * Function-like macro for stringizing a macro's value.
-+ * @x: 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 )
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_power_gpu_frequency_trace.c
-similarity index 67%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu.h
-rename to dvalin/kernel/drivers/gpu/arm/midgard/mali_power_gpu_frequency_trace.c
-index 9516e56..1db3abe 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_power_gpu_frequency_trace.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,16 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifndef _KBASE_GPU_H_
--#define _KBASE_GPU_H_
--
--#include "mali_kbase_gpu_regmap.h"
--#include "mali_kbase_gpu_fault.h"
--#include "mali_kbase_gpu_coherency.h"
--#include "mali_kbase_gpu_id.h"
--
--#endif /* _KBASE_GPU_H_ */
-+/* Create the trace point if not configured in kernel */
-+#ifndef CONFIG_TRACE_POWER_GPU_FREQUENCY
-+#define CREATE_TRACE_POINTS
-+#include "mali_power_gpu_frequency_trace.h"
-+#endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_power_gpu_frequency_trace.h b/dvalin/kernel/drivers/gpu/arm/midgard/mali_power_gpu_frequency_trace.h
-new file mode 100644
-index 0000000..ea18fcd
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_power_gpu_frequency_trace.h
-@@ -0,0 +1,68 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _TRACE_POWER_GPU_FREQUENCY_MALI
-+#define _TRACE_POWER_GPU_FREQUENCY_MALI
-+#endif
-+
-+#undef TRACE_SYSTEM
-+#define TRACE_SYSTEM power
-+#undef TRACE_INCLUDE_FILE
-+#define TRACE_INCLUDE_FILE mali_power_gpu_frequency_trace
-+#undef TRACE_INCLUDE_PATH
-+#define TRACE_INCLUDE_PATH .
-+
-+#if !defined(_TRACE_POWER_GPU_FREQUENCY_H) || defined(TRACE_HEADER_MULTI_READ)
-+#define _TRACE_POWER_GPU_FREQUENCY_H
-+
-+#include <linux/tracepoint.h>
-+
-+DECLARE_EVENT_CLASS(gpu,
-+
-+ TP_PROTO(unsigned int state, unsigned int gpu_id),
-+
-+ TP_ARGS(state, gpu_id),
-+
-+ TP_STRUCT__entry(
-+ __field( u32, state )
-+ __field( u32, gpu_id )
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->state = state;
-+ __entry->gpu_id = gpu_id;
-+ ),
-+
-+ TP_printk("state=%lu gpu_id=%lu", (unsigned long)__entry->state,
-+ (unsigned long)__entry->gpu_id)
-+);
-+
-+DEFINE_EVENT(gpu, gpu_frequency,
-+
-+ TP_PROTO(unsigned int frequency, unsigned int gpu_id),
-+
-+ TP_ARGS(frequency, gpu_id)
-+);
-+
-+#endif /* _TRACE_POWER_GPU_FREQUENCY_H */
-+
-+/* This part must be outside protection */
-+#include <trace/define_trace.h>
-diff --git a/dvalin/kernel/drivers/base/protected_memory_allocator/Kconfig b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/Kbuild
-similarity index 61%
-rename from dvalin/kernel/drivers/base/protected_memory_allocator/Kconfig
-rename to dvalin/kernel/drivers/gpu/arm/midgard/mmu/Kbuild
-index 7b42d6c..7f2bb26 100644
---- a/dvalin/kernel/drivers/base/protected_memory_allocator/Kconfig
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,14 +16,15 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
-+mali_kbase-y += \
-+ mmu/mali_kbase_mmu.o \
-+ mmu/mali_kbase_mmu_hw_direct.o \
-+ mmu/mali_kbase_mmu_mode_aarch64.o
-
--config MALI_PROTECTED_MEMORY_ALLOCATOR
-- tristate "MALI_PROTECTED_MEMORY_ALLOCATOR"
-- help
-- This option enables an example implementation of a protected memory allocator
-- for allocation and release of pages of secure memory intended to be used
-- by the firmware of Mali GPU device drivers.
-+ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
-+ mali_kbase-y += mmu/backend/mali_kbase_mmu_csf.o
-+else
-+ mali_kbase-y += mmu/backend/mali_kbase_mmu_jm.o
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/backend/mali_kbase_mmu_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/backend/mali_kbase_mmu_csf.c
-new file mode 100644
-index 0000000..05253ae
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/backend/mali_kbase_mmu_csf.c
-@@ -0,0 +1,565 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/**
-+ * DOC: Base kernel MMU management specific for CSF GPU.
-+ */
-+
-+#include <mali_kbase.h>
-+#include <gpu/mali_kbase_gpu_fault.h>
-+#include <mali_kbase_ctx_sched.h>
-+#include <mali_kbase_reset_gpu.h>
-+#include <mali_kbase_as_fault_debugfs.h>
-+#include <mmu/mali_kbase_mmu_internal.h>
-+
-+void kbase_mmu_get_as_setup(struct kbase_mmu_table *mmut,
-+ struct kbase_mmu_setup * const setup)
-+{
-+ /* Set up the required caching policies at the correct indices
-+ * in the memattr register.
-+ */
-+ setup->memattr =
-+ (AS_MEMATTR_IMPL_DEF_CACHE_POLICY <<
-+ (AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY * 8)) |
-+ (AS_MEMATTR_FORCE_TO_CACHE_ALL <<
-+ (AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL * 8)) |
-+ (AS_MEMATTR_WRITE_ALLOC <<
-+ (AS_MEMATTR_INDEX_WRITE_ALLOC * 8)) |
-+ (AS_MEMATTR_AARCH64_OUTER_IMPL_DEF <<
-+ (AS_MEMATTR_INDEX_OUTER_IMPL_DEF * 8)) |
-+ (AS_MEMATTR_AARCH64_OUTER_WA <<
-+ (AS_MEMATTR_INDEX_OUTER_WA * 8)) |
-+ (AS_MEMATTR_AARCH64_NON_CACHEABLE <<
-+ (AS_MEMATTR_INDEX_NON_CACHEABLE * 8)) |
-+ (AS_MEMATTR_AARCH64_SHARED <<
-+ (AS_MEMATTR_INDEX_SHARED * 8));
-+
-+ setup->transtab = (u64)mmut->pgd & AS_TRANSTAB_BASE_MASK;
-+ setup->transcfg = AS_TRANSCFG_ADRMODE_AARCH64_4K;
-+}
-+
-+/**
-+ * submit_work_pagefault() - Submit a work for MMU page fault.
-+ *
-+ * @kbdev: Kbase device pointer
-+ * @as_nr: Faulty address space
-+ * @fault: Data relating to the fault
-+ *
-+ * This function submits a work for reporting the details of MMU fault.
-+ */
-+static void submit_work_pagefault(struct kbase_device *kbdev, u32 as_nr,
-+ struct kbase_fault *fault)
-+{
-+ unsigned long flags;
-+ struct kbase_as *const as = &kbdev->as[as_nr];
-+ struct kbase_context *kctx;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kctx = kbase_ctx_sched_as_to_ctx_nolock(kbdev, as_nr);
-+
-+ if (kctx) {
-+ kbase_ctx_sched_retain_ctx_refcount(kctx);
-+
-+ as->pf_data = (struct kbase_fault) {
-+ .status = fault->status,
-+ .addr = fault->addr,
-+ };
-+
-+ /*
-+ * A page fault work item could already be pending for the
-+ * context's address space, when the page fault occurs for
-+ * MCU's address space.
-+ */
-+ if (!queue_work(as->pf_wq, &as->work_pagefault))
-+ kbase_ctx_sched_release_ctx(kctx);
-+ else {
-+ dev_dbg(kbdev->dev,
-+ "Page fault is already pending for as %u\n",
-+ as_nr);
-+ atomic_inc(&kbdev->faults_pending);
-+ }
-+ }
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+}
-+
-+void kbase_mmu_report_mcu_as_fault_and_reset(struct kbase_device *kbdev,
-+ struct kbase_fault *fault)
-+{
-+ /* decode the fault status */
-+ u32 exception_type = fault->status & 0xFF;
-+ u32 access_type = (fault->status >> 8) & 0x3;
-+ u32 source_id = (fault->status >> 16);
-+ int as_no;
-+
-+ /* terminal fault, print info about the fault */
-+ dev_err(kbdev->dev,
-+ "Unexpected Page fault in firmware address space at VA 0x%016llX\n"
-+ "raw fault status: 0x%X\n"
-+ "exception type 0x%X: %s\n"
-+ "access type 0x%X: %s\n"
-+ "source id 0x%X\n",
-+ fault->addr,
-+ fault->status,
-+ exception_type, kbase_gpu_exception_name(exception_type),
-+ access_type, kbase_gpu_access_type_name(fault->status),
-+ source_id);
-+
-+ /* Report MMU fault for all address spaces (except MCU_AS_NR) */
-+ for (as_no = 1; as_no < kbdev->nr_hw_address_spaces; as_no++)
-+ submit_work_pagefault(kbdev, as_no, fault);
-+
-+ /* GPU reset is required to recover */
-+ if (kbase_prepare_to_reset_gpu(kbdev,
-+ RESET_FLAGS_HWC_UNRECOVERABLE_ERROR))
-+ kbase_reset_gpu(kbdev);
-+}
-+KBASE_EXPORT_TEST_API(kbase_mmu_report_mcu_as_fault_and_reset);
-+
-+void kbase_gpu_report_bus_fault_and_kill(struct kbase_context *kctx,
-+ struct kbase_as *as, struct kbase_fault *fault)
-+{
-+ struct kbase_device *kbdev = kctx->kbdev;
-+ u32 const status = fault->status;
-+ int exception_type = (status & GPU_FAULTSTATUS_EXCEPTION_TYPE_MASK) >>
-+ GPU_FAULTSTATUS_EXCEPTION_TYPE_SHIFT;
-+ int access_type = (status & GPU_FAULTSTATUS_ACCESS_TYPE_MASK) >>
-+ GPU_FAULTSTATUS_ACCESS_TYPE_SHIFT;
-+ int source_id = (status & GPU_FAULTSTATUS_SOURCE_ID_MASK) >>
-+ GPU_FAULTSTATUS_SOURCE_ID_SHIFT;
-+ const char *addr_valid = (status & GPU_FAULTSTATUS_ADDR_VALID_FLAG) ?
-+ "true" : "false";
-+ int as_no = as->number;
-+ unsigned long flags;
-+
-+ /* terminal fault, print info about the fault */
-+ dev_err(kbdev->dev,
-+ "GPU bus fault in AS%d at VA 0x%016llX\n"
-+ "VA_VALID: %s\n"
-+ "raw fault status: 0x%X\n"
-+ "exception type 0x%X: %s\n"
-+ "access type 0x%X: %s\n"
-+ "source id 0x%X\n"
-+ "pid: %d\n",
-+ as_no, fault->addr,
-+ addr_valid,
-+ status,
-+ exception_type, kbase_gpu_exception_name(exception_type),
-+ access_type, kbase_gpu_access_type_name(access_type),
-+ source_id,
-+ kctx->pid);
-+
-+ /* AS transaction begin */
-+ mutex_lock(&kbdev->mmu_hw_mutex);
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_mmu_disable(kctx);
-+ kbase_ctx_flag_set(kctx, KCTX_AS_DISABLED_ON_FAULT);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ mutex_unlock(&kbdev->mmu_hw_mutex);
-+
-+ /* Switching to UNMAPPED mode above would have enabled the firmware to
-+ * recover from the fault (if the memory access was made by firmware)
-+ * and it can then respond to CSG termination requests to be sent now.
-+ * All GPU command queue groups associated with the context would be
-+ * affected as they use the same GPU address space.
-+ */
-+ kbase_csf_ctx_handle_fault(kctx, fault);
-+
-+ /* Now clear the GPU fault */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-+ GPU_COMMAND_CLEAR_FAULT);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+}
-+
-+/*
-+ * The caller must ensure it's retained the ctx to prevent it from being
-+ * scheduled out whilst it's being worked on.
-+ */
-+void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx,
-+ struct kbase_as *as, const char *reason_str,
-+ struct kbase_fault *fault)
-+{
-+ unsigned long flags;
-+ unsigned int exception_type;
-+ unsigned int access_type;
-+ unsigned int source_id;
-+ int as_no;
-+ struct kbase_device *kbdev;
-+ const u32 status = fault->status;
-+
-+ as_no = as->number;
-+ kbdev = kctx->kbdev;
-+
-+ /* Make sure the context was active */
-+ if (WARN_ON(atomic_read(&kctx->refcount) <= 0))
-+ return;
-+
-+ /* decode the fault status */
-+ exception_type = AS_FAULTSTATUS_EXCEPTION_TYPE_GET(status);
-+ access_type = AS_FAULTSTATUS_ACCESS_TYPE_GET(status);
-+ source_id = AS_FAULTSTATUS_SOURCE_ID_GET(status);
-+
-+ /* terminal fault, print info about the fault */
-+ dev_err(kbdev->dev,
-+ "Unhandled Page fault in AS%d at VA 0x%016llX\n"
-+ "Reason: %s\n"
-+ "raw fault status: 0x%X\n"
-+ "exception type 0x%X: %s\n"
-+ "access type 0x%X: %s\n"
-+ "source id 0x%X\n"
-+ "pid: %d\n",
-+ as_no, fault->addr,
-+ reason_str,
-+ status,
-+ exception_type, kbase_gpu_exception_name(exception_type),
-+ access_type, kbase_gpu_access_type_name(status),
-+ source_id,
-+ kctx->pid);
-+
-+ /* AS transaction begin */
-+ mutex_lock(&kbdev->mmu_hw_mutex);
-+
-+ /* switch to UNMAPPED mode,
-+ * will abort all jobs and stop any hw counter dumping
-+ */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_mmu_disable(kctx);
-+ kbase_ctx_flag_set(kctx, KCTX_AS_DISABLED_ON_FAULT);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ mutex_unlock(&kbdev->mmu_hw_mutex);
-+ /* AS transaction end */
-+
-+ /* Switching to UNMAPPED mode above would have enabled the firmware to
-+ * recover from the fault (if the memory access was made by firmware)
-+ * and it can then respond to CSG termination requests to be sent now.
-+ * All GPU command queue groups associated with the context would be
-+ * affected as they use the same GPU address space.
-+ */
-+ kbase_csf_ctx_handle_fault(kctx, fault);
-+
-+ /* Clear down the fault */
-+ kbase_mmu_hw_clear_fault(kbdev, as,
-+ KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED);
-+ kbase_mmu_hw_enable_fault(kbdev, as,
-+ KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED);
-+}
-+
-+/**
-+ * kbase_mmu_interrupt_process() - Process a bus or page fault.
-+ * @kbdev: The kbase_device the fault happened on
-+ * @kctx: The kbase_context for the faulting address space if one was
-+ * found.
-+ * @as: The address space that has the fault
-+ * @fault: Data relating to the fault
-+ *
-+ * This function will process a fault on a specific address space
-+ */
-+static void kbase_mmu_interrupt_process(struct kbase_device *kbdev,
-+ struct kbase_context *kctx, struct kbase_as *as,
-+ struct kbase_fault *fault)
-+{
-+ lockdep_assert_held(&kbdev->hwaccess_lock);
-+
-+ if (!kctx) {
-+ dev_warn(kbdev->dev, "%s in AS%d at 0x%016llx with no context present! Spurious IRQ or SW Design Error?\n",
-+ kbase_as_has_bus_fault(as, fault) ?
-+ "Bus error" : "Page fault",
-+ as->number, fault->addr);
-+
-+ /* Since no ctx was found, the MMU must be disabled. */
-+ WARN_ON(as->current_setup.transtab);
-+
-+ if (kbase_as_has_bus_fault(as, fault))
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-+ GPU_COMMAND_CLEAR_FAULT);
-+ else if (kbase_as_has_page_fault(as, fault)) {
-+ kbase_mmu_hw_clear_fault(kbdev, as,
-+ KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED);
-+ kbase_mmu_hw_enable_fault(kbdev, as,
-+ KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED);
-+ }
-+
-+ return;
-+ }
-+
-+ if (kbase_as_has_bus_fault(as, fault)) {
-+ /*
-+ * We need to switch to UNMAPPED mode - but we do this in a
-+ * worker so that we can sleep
-+ */
-+ WARN_ON(!queue_work(as->pf_wq, &as->work_busfault));
-+ atomic_inc(&kbdev->faults_pending);
-+ } else {
-+ WARN_ON(!queue_work(as->pf_wq, &as->work_pagefault));
-+ atomic_inc(&kbdev->faults_pending);
-+ }
-+}
-+
-+int kbase_mmu_bus_fault_interrupt(struct kbase_device *kbdev,
-+ u32 status, u32 as_nr)
-+{
-+ struct kbase_context *kctx;
-+ unsigned long flags;
-+ struct kbase_as *as;
-+ struct kbase_fault *fault;
-+
-+ if (WARN_ON(as_nr == MCU_AS_NR))
-+ return -EINVAL;
-+
-+ if (WARN_ON(as_nr >= BASE_MAX_NR_AS))
-+ return -EINVAL;
-+
-+ as = &kbdev->as[as_nr];
-+ fault = &as->bf_data;
-+ fault->status = status;
-+ fault->addr = (u64) kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(GPU_FAULTADDRESS_HI)) << 32;
-+ fault->addr |= kbase_reg_read(kbdev,
-+ GPU_CONTROL_REG(GPU_FAULTADDRESS_LO));
-+ fault->protected_mode = false;
-+
-+ /* report the fault to debugfs */
-+ kbase_as_fault_debugfs_new(kbdev, as_nr);
-+
-+ kctx = kbase_ctx_sched_as_to_ctx_refcount(kbdev, as_nr);
-+
-+ /* Process the bus fault interrupt for this address space */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_mmu_interrupt_process(kbdev, kctx, as, fault);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ return 0;
-+}
-+
-+void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat)
-+{
-+ const int num_as = 16;
-+ const int pf_shift = 0;
-+ const unsigned long as_bit_mask = (1UL << num_as) - 1;
-+ unsigned long flags;
-+ u32 new_mask;
-+ u32 tmp;
-+ u32 pf_bits = ((irq_stat >> pf_shift) & as_bit_mask);
-+
-+ /* remember current mask */
-+ spin_lock_irqsave(&kbdev->mmu_mask_change, flags);
-+ new_mask = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK));
-+ /* mask interrupts for now */
-+ kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), 0);
-+ spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags);
-+
-+ while (pf_bits) {
-+ struct kbase_context *kctx;
-+ int as_no = ffs(pf_bits) - 1;
-+ struct kbase_as *as = &kbdev->as[as_no];
-+ struct kbase_fault *fault = &as->pf_data;
-+
-+ /* find faulting address */
-+ fault->addr = kbase_reg_read(kbdev, MMU_AS_REG(as_no,
-+ AS_FAULTADDRESS_HI));
-+ fault->addr <<= 32;
-+ fault->addr |= kbase_reg_read(kbdev, MMU_AS_REG(as_no,
-+ AS_FAULTADDRESS_LO));
-+
-+ /* Mark the fault protected or not */
-+ fault->protected_mode = false;
-+
-+ /* report the fault to debugfs */
-+ kbase_as_fault_debugfs_new(kbdev, as_no);
-+
-+ /* record the fault status */
-+ fault->status = kbase_reg_read(kbdev, MMU_AS_REG(as_no,
-+ AS_FAULTSTATUS));
-+
-+ fault->extra_addr = kbase_reg_read(kbdev,
-+ MMU_AS_REG(as_no, AS_FAULTEXTRA_HI));
-+ fault->extra_addr <<= 32;
-+ fault->extra_addr |= kbase_reg_read(kbdev,
-+ MMU_AS_REG(as_no, AS_FAULTEXTRA_LO));
-+
-+ /* Mark page fault as handled */
-+ pf_bits &= ~(1UL << as_no);
-+
-+ /* remove the queued PF from the mask */
-+ new_mask &= ~MMU_PAGE_FAULT(as_no);
-+
-+ if (as_no == MCU_AS_NR) {
-+ kbase_mmu_report_mcu_as_fault_and_reset(kbdev, fault);
-+ /* Pointless to handle remaining faults */
-+ break;
-+ }
-+
-+ /*
-+ * Refcount the kctx - it shouldn't disappear anyway, since
-+ * Page faults _should_ only occur whilst GPU commands are
-+ * executing, and a command causing the Page fault shouldn't
-+ * complete until the MMU is updated.
-+ * Reference is released at the end of bottom half of page
-+ * fault handling.
-+ */
-+ kctx = kbase_ctx_sched_as_to_ctx_refcount(kbdev, as_no);
-+
-+ /* Process the interrupt for this address space */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_mmu_interrupt_process(kbdev, kctx, as, fault);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+ }
-+
-+ /* reenable interrupts */
-+ spin_lock_irqsave(&kbdev->mmu_mask_change, flags);
-+ tmp = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK));
-+ new_mask |= tmp;
-+ kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), new_mask);
-+ spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags);
-+}
-+
-+int kbase_mmu_switch_to_ir(struct kbase_context *const kctx,
-+ struct kbase_va_region *const reg)
-+{
-+ /* Can't soft-stop the provoking job */
-+ return -EPERM;
-+}
-+
-+/**
-+ * kbase_mmu_gpu_fault_worker() - Process a GPU fault for the device.
-+ *
-+ * @data: work_struct passed by queue_work()
-+ *
-+ * Report a GPU fatal error for all GPU command queue groups that are
-+ * using the address space and terminate them.
-+ */
-+static void kbase_mmu_gpu_fault_worker(struct work_struct *data)
-+{
-+ struct kbase_as *const faulting_as = container_of(data, struct kbase_as,
-+ work_gpufault);
-+ const u32 as_nr = faulting_as->number;
-+ struct kbase_device *const kbdev = container_of(faulting_as, struct
-+ kbase_device, as[as_nr]);
-+ struct kbase_fault *fault;
-+ struct kbase_context *kctx;
-+ u32 status;
-+ u64 address;
-+ u32 as_valid;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ fault = &faulting_as->gf_data;
-+ status = fault->status;
-+ as_valid = status & GPU_FAULTSTATUS_JASID_VALID_FLAG;
-+ address = fault->addr;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ dev_warn(kbdev->dev,
-+ "GPU Fault 0x%08x (%s) in AS%u at 0x%016llx\n"
-+ "ASID_VALID: %s, ADDRESS_VALID: %s\n",
-+ status,
-+ kbase_gpu_exception_name(
-+ GPU_FAULTSTATUS_EXCEPTION_TYPE_GET(status)),
-+ as_nr, address,
-+ as_valid ? "true" : "false",
-+ status & GPU_FAULTSTATUS_ADDR_VALID_FLAG ? "true" : "false");
-+
-+ kctx = kbase_ctx_sched_as_to_ctx(kbdev, as_nr);
-+ kbase_csf_ctx_handle_fault(kctx, fault);
-+ kbase_ctx_sched_release_ctx_lock(kctx);
-+
-+ atomic_dec(&kbdev->faults_pending);
-+
-+ /* A work for GPU fault is complete.
-+ * Till reaching here, no further GPU fault will be reported.
-+ * Now clear the GPU fault to allow next GPU fault interrupt report.
-+ */
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
-+ GPU_COMMAND_CLEAR_FAULT);
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+}
-+
-+/**
-+ * submit_work_gpufault() - Submit a work for GPU fault.
-+ *
-+ * @kbdev: Kbase device pointer
-+ * @status: GPU fault status
-+ * @as_nr: Faulty address space
-+ * @address: GPU fault address
-+ *
-+ * This function submits a work for reporting the details of GPU fault.
-+ */
-+static void submit_work_gpufault(struct kbase_device *kbdev, u32 status,
-+ u32 as_nr, u64 address)
-+{
-+ unsigned long flags;
-+ struct kbase_as *const as = &kbdev->as[as_nr];
-+ struct kbase_context *kctx;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ kctx = kbase_ctx_sched_as_to_ctx_nolock(kbdev, as_nr);
-+
-+ if (kctx) {
-+ kbase_ctx_sched_retain_ctx_refcount(kctx);
-+
-+ as->gf_data = (struct kbase_fault) {
-+ .status = status,
-+ .addr = address,
-+ };
-+
-+ if (WARN_ON(!queue_work(as->pf_wq, &as->work_gpufault)))
-+ kbase_ctx_sched_release_ctx(kctx);
-+ else
-+ atomic_inc(&kbdev->faults_pending);
-+ }
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+}
-+
-+void kbase_mmu_gpu_fault_interrupt(struct kbase_device *kbdev, u32 status,
-+ u32 as_nr, u64 address, bool as_valid)
-+{
-+ if (!as_valid || (as_nr == MCU_AS_NR)) {
-+ int as;
-+
-+ /* Report GPU fault for all contexts (except MCU_AS_NR) in case either
-+ * the address space is invalid or it's MCU address space.
-+ */
-+ for (as = 1; as < kbdev->nr_hw_address_spaces; as++)
-+ submit_work_gpufault(kbdev, status, as, address);
-+ } else
-+ submit_work_gpufault(kbdev, status, as_nr, address);
-+}
-+KBASE_EXPORT_TEST_API(kbase_mmu_gpu_fault_interrupt);
-+
-+int kbase_mmu_as_init(struct kbase_device *kbdev, int i)
-+{
-+ kbdev->as[i].number = i;
-+ kbdev->as[i].bf_data.addr = 0ULL;
-+ kbdev->as[i].pf_data.addr = 0ULL;
-+ kbdev->as[i].gf_data.addr = 0ULL;
-+
-+ kbdev->as[i].pf_wq = alloc_workqueue("mali_mmu%d", 0, 1, i);
-+ if (!kbdev->as[i].pf_wq)
-+ return -ENOMEM;
-+
-+ INIT_WORK(&kbdev->as[i].work_pagefault, kbase_mmu_page_fault_worker);
-+ INIT_WORK(&kbdev->as[i].work_busfault, kbase_mmu_bus_fault_worker);
-+ INIT_WORK(&kbdev->as[i].work_gpufault, kbase_mmu_gpu_fault_worker);
-+
-+ return 0;
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/backend/mali_kbase_mmu_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/backend/mali_kbase_mmu_jm.c
-index 2d8fb51..01ca419 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/backend/mali_kbase_mmu_jm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/backend/mali_kbase_mmu_jm.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,21 +17,18 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-- * Base kernel MMU management specific for Job Manager GPU.
-+ * DOC: Base kernel MMU management specific for Job Manager GPU.
- */
-
- #include <mali_kbase.h>
- #include <gpu/mali_kbase_gpu_fault.h>
- #include <mali_kbase_hwaccess_jm.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
-+#include <device/mali_kbase_device.h>
- #include <mali_kbase_as_fault_debugfs.h>
--#include "../mali_kbase_mmu_internal.h"
--#include "mali_kbase_device_internal.h"
-+#include <mmu/mali_kbase_mmu_internal.h>
-
- void kbase_mmu_get_as_setup(struct kbase_mmu_table *mmut,
- struct kbase_mmu_setup * const setup)
-@@ -98,7 +96,7 @@ void kbase_gpu_report_bus_fault_and_kill(struct kbase_context *kctx,
- KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED);
- }
-
--/**
-+/*
- * The caller must ensure it's retained the ctx to prevent it from being
- * scheduled out whilst it's being worked on.
- */
-@@ -145,6 +143,7 @@ void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx,
- kctx->pid);
-
- /* hardware counters dump fault handling */
-+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- if ((kbdev->hwcnt.kctx) && (kbdev->hwcnt.kctx->as_nr == as_no) &&
- (kbdev->hwcnt.backend.state ==
- KBASE_INSTR_STATE_DUMPING)) {
-@@ -153,6 +152,7 @@ void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx,
- kbdev->hwcnt.addr_bytes)))
- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_FAULT;
- }
-+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
-
- /* Stop the kctx from submitting more jobs and cause it to be scheduled
- * out/rescheduled - this will occur on releasing the context's refcount
-@@ -187,14 +187,26 @@ void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx,
- KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED);
- }
-
--void kbase_mmu_interrupt_process(struct kbase_device *kbdev,
-+/**
-+ * kbase_mmu_interrupt_process() - Process a bus or page fault.
-+ * @kbdev: The kbase_device the fault happened on
-+ * @kctx: The kbase_context for the faulting address space if one was
-+ * found.
-+ * @as: The address space that has the fault
-+ * @fault: Data relating to the fault
-+ *
-+ * This function will process a fault on a specific address space
-+ */
-+static void kbase_mmu_interrupt_process(struct kbase_device *kbdev,
- struct kbase_context *kctx, struct kbase_as *as,
- struct kbase_fault *fault)
- {
-+ unsigned long flags;
-+
- lockdep_assert_held(&kbdev->hwaccess_lock);
-
- dev_dbg(kbdev->dev,
-- "Entering %s kctx %p, as %p\n",
-+ "Entering %s kctx %pK, as %pK\n",
- __func__, (void *)kctx, (void *)as);
-
- if (!kctx) {
-@@ -228,11 +240,13 @@ void kbase_mmu_interrupt_process(struct kbase_device *kbdev,
- * hw counters dumping in progress, signal the
- * other thread that it failed
- */
-+ spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- if ((kbdev->hwcnt.kctx == kctx) &&
- (kbdev->hwcnt.backend.state ==
- KBASE_INSTR_STATE_DUMPING))
- kbdev->hwcnt.backend.state =
- KBASE_INSTR_STATE_FAULT;
-+ spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
-
- /*
- * Stop the kctx from submitting more jobs and cause it
-@@ -241,14 +255,10 @@ void kbase_mmu_interrupt_process(struct kbase_device *kbdev,
- */
- kbasep_js_clear_submit_allowed(js_devdata, kctx);
-
-- if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU))
-- dev_warn(kbdev->dev,
-- "Bus error in AS%d at VA=0x%016llx, IPA=0x%016llx\n",
-- as->number, fault->addr,
-- fault->extra_addr);
-- else
-- dev_warn(kbdev->dev, "Bus error in AS%d at 0x%016llx\n",
-- as->number, fault->addr);
-+ dev_warn(kbdev->dev,
-+ "Bus error in AS%d at VA=0x%016llx, IPA=0x%016llx\n",
-+ as->number, fault->addr,
-+ fault->extra_addr);
-
- /*
- * We need to switch to UNMAPPED mode - but we do this in a
-@@ -262,7 +272,7 @@ void kbase_mmu_interrupt_process(struct kbase_device *kbdev,
- }
-
- dev_dbg(kbdev->dev,
-- "Leaving %s kctx %p, as %p\n",
-+ "Leaving %s kctx %pK, as %pK\n",
- __func__, (void *)kctx, (void *)as);
- }
-
-@@ -296,7 +306,6 @@ void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat)
- unsigned long flags;
- u32 new_mask;
- u32 tmp, bf_bits, pf_bits;
-- bool gpu_lost = false;
-
- dev_dbg(kbdev->dev, "Entering %s irq_stat %u\n",
- __func__, irq_stat);
-@@ -362,22 +371,11 @@ void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat)
- /* record the fault status */
- fault->status = kbase_reg_read(kbdev, MMU_AS_REG(as_no,
- AS_FAULTSTATUS));
--
-- if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) {
-- fault->extra_addr = kbase_reg_read(kbdev,
-- MMU_AS_REG(as_no, AS_FAULTEXTRA_HI));
-- fault->extra_addr <<= 32;
-- fault->extra_addr |= kbase_reg_read(kbdev,
-- MMU_AS_REG(as_no, AS_FAULTEXTRA_LO));
-- }
--
-- /* check if we still have GPU */
-- gpu_lost = kbase_is_gpu_lost(kbdev);
-- if (gpu_lost) {
-- if (kctx)
-- kbasep_js_runpool_release_ctx(kbdev, kctx);
-- return;
-- }
-+ fault->extra_addr = kbase_reg_read(kbdev,
-+ MMU_AS_REG(as_no, AS_FAULTEXTRA_HI));
-+ fault->extra_addr <<= 32;
-+ fault->extra_addr |= kbase_reg_read(kbdev,
-+ MMU_AS_REG(as_no, AS_FAULTEXTRA_LO));
-
- if (kbase_as_has_bus_fault(as, fault)) {
- /* Mark bus fault as handled.
-@@ -418,7 +416,23 @@ int kbase_mmu_switch_to_ir(struct kbase_context *const kctx,
- struct kbase_va_region *const reg)
- {
- dev_dbg(kctx->kbdev->dev,
-- "Switching to incremental rendering for region %p\n",
-+ "Switching to incremental rendering for region %pK\n",
- (void *)reg);
- return kbase_job_slot_softstop_start_rp(kctx, reg);
- }
-+
-+int kbase_mmu_as_init(struct kbase_device *kbdev, int i)
-+{
-+ kbdev->as[i].number = i;
-+ kbdev->as[i].bf_data.addr = 0ULL;
-+ kbdev->as[i].pf_data.addr = 0ULL;
-+
-+ kbdev->as[i].pf_wq = alloc_workqueue("mali_mmu%d", 0, 1, i);
-+ if (!kbdev->as[i].pf_wq)
-+ return -ENOMEM;
-+
-+ INIT_WORK(&kbdev->as[i].work_pagefault, kbase_mmu_page_fault_worker);
-+ INIT_WORK(&kbdev->as[i].work_busfault, kbase_mmu_bus_fault_worker);
-+
-+ return 0;
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.c b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.c
-index c2c7c4b..41ee07f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,13 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-- * @file mali_kbase_mmu.c
-- * Base kernel MMU management.
-+ * DOC: Base kernel MMU management.
- */
-
- #include <linux/kernel.h>
-@@ -31,20 +29,20 @@
- #include <gpu/mali_kbase_gpu_fault.h>
- #include <gpu/mali_kbase_gpu_regmap.h>
- #include <tl/mali_kbase_tracepoints.h>
--#include <mali_kbase_instr_defs.h>
-+#include <backend/gpu/mali_kbase_instr_defs.h>
- #include <mali_kbase_ctx_sched.h>
- #include <mali_kbase_debug.h>
- #include <mali_kbase_defs.h>
- #include <mali_kbase_hw.h>
- #include <mmu/mali_kbase_mmu_hw.h>
--#include <mali_kbase_hwaccess_jm.h>
--#include <mali_kbase_hwaccess_time.h>
- #include <mali_kbase_mem.h>
- #include <mali_kbase_reset_gpu.h>
- #include <mmu/mali_kbase_mmu.h>
- #include <mmu/mali_kbase_mmu_internal.h>
- #include <mali_kbase_cs_experimental.h>
-+#include <device/mali_kbase_device.h>
-
-+#include <mali_kbase_trace_gpu_mem.h>
- #define KBASE_MMU_PAGE_ENTRIES 512
-
- /**
-@@ -82,21 +80,20 @@ static void kbase_mmu_flush_invalidate_no_ctx(struct kbase_device *kbdev,
- u64 vpfn, size_t nr, bool sync, int as_nr);
-
- /**
-- * kbase_mmu_sync_pgd - sync page directory to memory
-+ * kbase_mmu_sync_pgd() - sync page directory to memory when needed.
- * @kbdev: Device pointer.
- * @handle: Address of DMA region.
- * @size: Size of the region to sync.
- *
- * This should be called after each page directory update.
- */
--
- static void kbase_mmu_sync_pgd(struct kbase_device *kbdev,
- dma_addr_t handle, size_t size)
- {
-- /* If page table is not coherent then ensure the gpu can read
-+ /* In non-coherent system, ensure the GPU can read
- * the pages from memory
- */
-- if (kbdev->system_coherency != COHERENCY_ACE)
-+ if (kbdev->system_coherency == COHERENCY_NONE)
- dma_sync_single_for_device(kbdev->dev, handle, size,
- DMA_TO_DEVICE);
- }
-@@ -117,7 +114,7 @@ static int kbase_mmu_update_pages_no_flush(struct kbase_context *kctx, u64 vpfn,
- /**
- * reg_grow_calc_extra_pages() - Calculate the number of backed pages to add to
- * a region on a GPU page fault
-- *
-+ * @kbdev: KBase device
- * @reg: The region that will be backed with more pages
- * @fault_rel_pfn: PFN of the fault relative to the start of the region
- *
-@@ -133,23 +130,32 @@ static int kbase_mmu_update_pages_no_flush(struct kbase_context *kctx, u64 vpfn,
- static size_t reg_grow_calc_extra_pages(struct kbase_device *kbdev,
- struct kbase_va_region *reg, size_t fault_rel_pfn)
- {
-- size_t multiple = reg->extent;
-+ size_t multiple = reg->extension;
- size_t reg_current_size = kbase_reg_current_backed_size(reg);
- size_t minimum_extra = fault_rel_pfn - reg_current_size + 1;
- size_t remainder;
-
- if (!multiple) {
-- dev_warn(kbdev->dev,
-- "VA Region 0x%llx extent was 0, allocator needs to set this properly for KBASE_REG_PF_GROW\n",
-+ dev_warn(
-+ kbdev->dev,
-+ "VA Region 0x%llx extension was 0, allocator needs to set this properly for KBASE_REG_PF_GROW\n",
- ((unsigned long long)reg->start_pfn) << PAGE_SHIFT);
- return minimum_extra;
- }
-
- /* Calculate the remainder to subtract from minimum_extra to make it
-- * the desired (rounded down) multiple of the extent.
-+ * the desired (rounded down) multiple of the extension.
- * Depending on reg's flags, the base used for calculating multiples is
- * different
- */
-+
-+ /* multiple is based from the current backed size, even if the
-+ * current backed size/pfn for end of committed memory are not
-+ * themselves aligned to multiple
-+ */
-+ remainder = minimum_extra % multiple;
-+
-+#if !MALI_USE_CSF
- if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) {
- /* multiple is based from the top of the initial commit, which
- * has been allocated in such a way that (start_pfn +
-@@ -175,13 +181,8 @@ static size_t reg_grow_calc_extra_pages(struct kbase_device *kbdev,
-
- remainder = pages_after_initial % multiple;
- }
-- } else {
-- /* multiple is based from the current backed size, even if the
-- * current backed size/pfn for end of committed memory are not
-- * themselves aligned to multiple
-- */
-- remainder = minimum_extra % multiple;
- }
-+#endif /* !MALI_USE_CSF */
-
- if (remainder == 0)
- return minimum_extra;
-@@ -522,10 +523,15 @@ static bool page_fault_try_alloc(struct kbase_context *kctx,
- static void release_ctx(struct kbase_device *kbdev,
- struct kbase_context *kctx)
- {
-+#if MALI_USE_CSF
-+ CSTD_UNUSED(kbdev);
-+ kbase_ctx_sched_release_ctx_lock(kctx);
-+#else /* MALI_USE_CSF */
- kbasep_js_runpool_release_ctx(kbdev, kctx);
-+#endif /* MALI_USE_CSF */
- }
-
--void page_fault_worker(struct work_struct *data)
-+void kbase_mmu_page_fault_worker(struct work_struct *data)
- {
- u64 fault_pfn;
- u32 fault_status;
-@@ -544,7 +550,9 @@ void page_fault_worker(struct work_struct *data)
- struct kbase_sub_alloc *prealloc_sas[2] = { NULL, NULL };
- int i;
- size_t current_backed_size;
--
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ size_t pages_trimmed = 0;
-+#endif
-
- faulting_as = container_of(data, struct kbase_as, work_pagefault);
- fault = &faulting_as->pf_data;
-@@ -553,7 +561,7 @@ void page_fault_worker(struct work_struct *data)
-
- kbdev = container_of(faulting_as, struct kbase_device, as[as_no]);
- dev_dbg(kbdev->dev,
-- "Entering %s %p, fault_pfn %lld, as_no %d\n",
-+ "Entering %s %pK, fault_pfn %lld, as_no %d\n",
- __func__, (void *)data, fault_pfn, as_no);
-
- /* Grab the context that was already refcounted in kbase_mmu_interrupt()
-@@ -568,6 +576,21 @@ void page_fault_worker(struct work_struct *data)
-
- KBASE_DEBUG_ASSERT(kctx->kbdev == kbdev);
-
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+#if !MALI_USE_CSF
-+ mutex_lock(&kctx->jctx.lock);
-+#endif
-+#endif
-+
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ /* check if we still have GPU */
-+ if (unlikely(kbase_is_gpu_removed(kbdev))) {
-+ dev_dbg(kbdev->dev,
-+ "%s: GPU has been removed\n", __func__);
-+ goto fault_done;
-+ }
-+#endif
-+
- if (unlikely(fault->protected_mode)) {
- kbase_mmu_report_fault_and_kill(kctx, faulting_as,
- "Protected mode fault", fault);
-@@ -611,21 +634,13 @@ void page_fault_worker(struct work_struct *data)
- goto fault_done;
-
- case AS_FAULTSTATUS_EXCEPTION_CODE_ADDRESS_SIZE_FAULT:
-- if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU))
-- kbase_mmu_report_fault_and_kill(kctx, faulting_as,
-- "Address size fault", fault);
-- else
-- kbase_mmu_report_fault_and_kill(kctx, faulting_as,
-- "Unknown fault code", fault);
-+ kbase_mmu_report_fault_and_kill(kctx, faulting_as,
-+ "Address size fault", fault);
- goto fault_done;
-
- case AS_FAULTSTATUS_EXCEPTION_CODE_MEMORY_ATTRIBUTES_FAULT:
-- if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU))
-- kbase_mmu_report_fault_and_kill(kctx, faulting_as,
-- "Memory attributes fault", fault);
-- else
-- kbase_mmu_report_fault_and_kill(kctx, faulting_as,
-- "Unknown fault code", fault);
-+ kbase_mmu_report_fault_and_kill(kctx, faulting_as,
-+ "Memory attributes fault", fault);
- goto fault_done;
-
- default:
-@@ -691,6 +706,10 @@ page_fault_retry:
- goto fault_done;
- }
-
-+ if (AS_FAULTSTATUS_ACCESS_TYPE_GET(fault_status) ==
-+ AS_FAULTSTATUS_ACCESS_TYPE_READ)
-+ dev_warn(kbdev->dev, "Grow on pagefault while reading");
-+
- /* find the size we need to grow it by
- * we know the result fit in a size_t due to
- * kbase_region_tracker_find_region_enclosing_address
-@@ -758,6 +777,13 @@ page_fault_retry:
-
- pages_to_grow = 0;
-
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if ((region->flags & KBASE_REG_ACTIVE_JIT_ALLOC) && !pages_trimmed) {
-+ kbase_jit_request_phys_increase(kctx, new_pages);
-+ pages_trimmed = new_pages;
-+ }
-+#endif
-+
- spin_lock(&kctx->mem_partials_lock);
- grown = page_fault_try_alloc(kctx, region, new_pages, &pages_to_grow,
- &grow_2mb_pool, prealloc_sas);
-@@ -818,7 +844,7 @@ page_fault_retry:
-
- if (kbase_mmu_switch_to_ir(kctx, region) >= 0) {
- dev_dbg(kctx->kbdev->dev,
-- "Get region %p for IR\n",
-+ "Get region %pK for IR\n",
- (void *)region);
- kbase_va_region_alloc_get(kctx, region);
- }
-@@ -872,6 +898,13 @@ page_fault_retry:
- }
- }
- #endif
-+
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (pages_trimmed) {
-+ kbase_jit_done_phys_increase(kctx, pages_trimmed);
-+ pages_trimmed = 0;
-+ }
-+#endif
- kbase_gpu_vm_unlock(kctx);
- } else {
- int ret = -ENOMEM;
-@@ -918,6 +951,17 @@ page_fault_retry:
- }
-
- fault_done:
-+#if MALI_JIT_PRESSURE_LIMIT_BASE
-+ if (pages_trimmed) {
-+ kbase_gpu_vm_lock(kctx);
-+ kbase_jit_done_phys_increase(kctx, pages_trimmed);
-+ kbase_gpu_vm_unlock(kctx);
-+ }
-+#if !MALI_USE_CSF
-+ mutex_unlock(&kctx->jctx.lock);
-+#endif
-+#endif
-+
- for (i = 0; i != ARRAY_SIZE(prealloc_sas); ++i)
- kfree(prealloc_sas[i]);
-
-@@ -928,7 +972,7 @@ fault_done:
- release_ctx(kbdev, kctx);
-
- atomic_dec(&kbdev->faults_pending);
-- dev_dbg(kbdev->dev, "Leaving page_fault_worker %p\n", (void *)data);
-+ dev_dbg(kbdev->dev, "Leaving page_fault_worker %pK\n", (void *)data);
- }
-
- static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev,
-@@ -938,7 +982,11 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev,
- int i;
- struct page *p;
-
-+#ifdef CONFIG_MALI_2MB_ALLOC
-+ p = kbase_mem_pool_alloc(&kbdev->mem_pools.large[mmut->group_id]);
-+#else /* CONFIG_MALI_2MB_ALLOC */
- p = kbase_mem_pool_alloc(&kbdev->mem_pools.small[mmut->group_id]);
-+#endif /* CONFIG_MALI_2MB_ALLOC */
- if (!p)
- return 0;
-
-@@ -964,6 +1012,8 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev,
-
- atomic_add(1, &kbdev->memdev.used_pages);
-
-+ kbase_trace_gpu_mem_usage_inc(kbdev, mmut->kctx, 1);
-+
- for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++)
- kbdev->mmu_mode->entry_invalidate(&page[i]);
-
-@@ -973,8 +1023,12 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev,
- return page_to_phys(p);
-
- alloc_free:
-- kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id], p,
-- false);
-+
-+#ifdef CONFIG_MALI_2MB_ALLOC
-+ kbase_mem_pool_free(&kbdev->mem_pools.large[mmut->group_id], p, false);
-+#else /* CONFIG_MALI_2MB_ALLOC */
-+ kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id], p, false);
-+#endif /* CONFIG_MALI_2MB_ALLOC */
-
- return 0;
- }
-@@ -1200,7 +1254,11 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn,
- */
- mutex_unlock(&kctx->mmu.mmu_lock);
- err = kbase_mem_pool_grow(
-+#ifdef CONFIG_MALI_2MB_ALLOC
-+ &kbdev->mem_pools.large[
-+#else
- &kbdev->mem_pools.small[
-+#endif
- kctx->mmu.group_id],
- MIDGARD_MMU_BOTTOMLEVEL);
- mutex_lock(&kctx->mmu.mmu_lock);
-@@ -1279,7 +1337,11 @@ static inline void cleanup_empty_pte(struct kbase_device *kbdev,
-
- tmp_pgd = kbdev->mmu_mode->pte_to_phy_addr(*pte);
- tmp_p = phys_to_page(tmp_pgd);
-+#ifdef CONFIG_MALI_2MB_ALLOC
-+ kbase_mem_pool_free(&kbdev->mem_pools.large[mmut->group_id],
-+#else
- kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id],
-+#endif
- tmp_p, false);
-
- /* If the MMU tables belong to a context then we accounted the memory
-@@ -1290,6 +1352,8 @@ static inline void cleanup_empty_pte(struct kbase_device *kbdev,
- atomic_sub(1, &mmut->kctx->used_pages);
- }
- atomic_sub(1, &kbdev->memdev.used_pages);
-+
-+ kbase_trace_gpu_mem_usage_dec(kbdev, mmut->kctx, 1);
- }
-
- u64 kbase_mmu_create_ate(struct kbase_device *const kbdev,
-@@ -1361,7 +1425,11 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev,
- */
- mutex_unlock(&mmut->mmu_lock);
- err = kbase_mem_pool_grow(
-+#ifdef CONFIG_MALI_2MB_ALLOC
-+ &kbdev->mem_pools.large[mmut->group_id],
-+#else
- &kbdev->mem_pools.small[mmut->group_id],
-+#endif
- cur_level);
- mutex_lock(&mmut->mmu_lock);
- } while (!err);
-@@ -1509,7 +1577,7 @@ static void kbase_mmu_flush_invalidate_noretain(struct kbase_context *kctx,
- */
- dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issuing GPU soft-reset to recover\n");
-
-- if (kbase_prepare_to_reset_gpu_locked(kbdev))
-+ if (kbase_prepare_to_reset_gpu_locked(kbdev, RESET_FLAGS_NONE))
- kbase_reset_gpu_locked(kbdev);
- }
- }
-@@ -1522,10 +1590,29 @@ static void kbase_mmu_flush_invalidate_as(struct kbase_device *kbdev,
- {
- int err;
- u32 op;
-+ bool gpu_powered;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
-+ gpu_powered = kbdev->pm.backend.gpu_powered;
-+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-+
-+ /* GPU is off so there's no need to perform flush/invalidate.
-+ * But even if GPU is not actually powered down, after gpu_powered flag
-+ * was set to false, it is still safe to skip the flush/invalidate.
-+ * The TLB invalidation will anyways be performed due to AS_COMMAND_UPDATE
-+ * which is sent when address spaces are restored after gpu_powered flag
-+ * is set to true. Flushing of L2 cache is certainly not required as L2
-+ * cache is definitely off if gpu_powered is false.
-+ */
-+ if (!gpu_powered)
-+ return;
-
- if (kbase_pm_context_active_handle_suspend(kbdev,
- KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) {
-- /* GPU is off so there's no need to perform flush/invalidate */
-+ /* GPU has just been powered off due to system suspend.
-+ * So again, no need to perform flush/invalidate.
-+ */
- return;
- }
-
-@@ -1544,9 +1631,10 @@ static void kbase_mmu_flush_invalidate_as(struct kbase_device *kbdev,
- /* Flush failed to complete, assume the GPU has hung and
- * perform a reset to recover
- */
-- dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issueing GPU soft-reset to recover\n");
-+ dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issuing GPU soft-reset to recover\n");
-
-- if (kbase_prepare_to_reset_gpu(kbdev))
-+ if (kbase_prepare_to_reset_gpu(
-+ kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR))
- kbase_reset_gpu(kbdev);
- }
-
-@@ -1577,9 +1665,13 @@ static void kbase_mmu_flush_invalidate(struct kbase_context *kctx,
- return;
-
- kbdev = kctx->kbdev;
-+#if !MALI_USE_CSF
- mutex_lock(&kbdev->js_data.queue_mutex);
- ctx_is_in_runpool = kbase_ctx_sched_inc_refcount(kctx);
- mutex_unlock(&kbdev->js_data.queue_mutex);
-+#else
-+ ctx_is_in_runpool = kbase_ctx_sched_inc_refcount_if_as_valid(kctx);
-+#endif /* !MALI_USE_CSF */
-
- if (ctx_is_in_runpool) {
- KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID);
-@@ -1621,6 +1713,7 @@ void kbase_mmu_disable(struct kbase_context *kctx)
- KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID);
-
- lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
-+ lockdep_assert_held(&kctx->kbdev->mmu_hw_mutex);
-
- /*
- * The address space is being disabled, drain all knowledge of it out
-@@ -1832,7 +1925,11 @@ static int kbase_mmu_update_pages_no_flush(struct kbase_context *kctx, u64 vpfn,
- */
- mutex_unlock(&kctx->mmu.mmu_lock);
- err = kbase_mem_pool_grow(
-+#ifdef CONFIG_MALI_2MB_ALLOC
-+ &kbdev->mem_pools.large[
-+#else
- &kbdev->mem_pools.small[
-+#endif
- kctx->mmu.group_id],
- MIDGARD_MMU_BOTTOMLEVEL);
- mutex_lock(&kctx->mmu.mmu_lock);
-@@ -1927,8 +2024,11 @@ static void mmu_teardown_level(struct kbase_device *kbdev,
- }
-
- p = pfn_to_page(PFN_DOWN(pgd));
--
-+#ifdef CONFIG_MALI_2MB_ALLOC
-+ kbase_mem_pool_free(&kbdev->mem_pools.large[mmut->group_id],
-+#else
- kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id],
-+#endif
- p, true);
-
- atomic_sub(1, &kbdev->memdev.used_pages);
-@@ -1940,6 +2040,8 @@ static void mmu_teardown_level(struct kbase_device *kbdev,
- kbase_process_page_usage_dec(mmut->kctx, 1);
- atomic_sub(1, &mmut->kctx->used_pages);
- }
-+
-+ kbase_trace_gpu_mem_usage_dec(kbdev, mmut->kctx, 1);
- }
-
- int kbase_mmu_init(struct kbase_device *const kbdev,
-@@ -1969,7 +2071,11 @@ int kbase_mmu_init(struct kbase_device *const kbdev,
- int err;
-
- err = kbase_mem_pool_grow(
-+#ifdef CONFIG_MALI_2MB_ALLOC
-+ &kbdev->mem_pools.large[mmut->group_id],
-+#else
- &kbdev->mem_pools.small[mmut->group_id],
-+#endif
- MIDGARD_MMU_BOTTOMLEVEL);
- if (err) {
- kbase_mmu_term(kbdev, mmut);
-@@ -2000,6 +2106,11 @@ void kbase_mmu_term(struct kbase_device *kbdev, struct kbase_mmu_table *mmut)
- mutex_destroy(&mmut->mmu_lock);
- }
-
-+void kbase_mmu_as_term(struct kbase_device *kbdev, int i)
-+{
-+ destroy_workqueue(kbdev->as[i].pf_wq);
-+}
-+
- static size_t kbasep_mmu_dump_level(struct kbase_context *kctx, phys_addr_t pgd,
- int level, char ** const buffer, size_t *size_left)
- {
-@@ -2140,7 +2251,7 @@ fail_free:
- }
- KBASE_EXPORT_TEST_API(kbase_mmu_dump);
-
--void bus_fault_worker(struct work_struct *data)
-+void kbase_mmu_bus_fault_worker(struct work_struct *data)
- {
- struct kbase_as *faulting_as;
- int as_no;
-@@ -2168,6 +2279,17 @@ void bus_fault_worker(struct work_struct *data)
- return;
- }
-
-+#ifdef CONFIG_MALI_ARBITER_SUPPORT
-+ /* check if we still have GPU */
-+ if (unlikely(kbase_is_gpu_removed(kbdev))) {
-+ dev_dbg(kbdev->dev,
-+ "%s: GPU has been removed\n", __func__);
-+ release_ctx(kbdev, kctx);
-+ atomic_dec(&kbdev->faults_pending);
-+ return;
-+ }
-+#endif
-+
- if (unlikely(fault->protected_mode)) {
- kbase_mmu_report_fault_and_kill(kctx, faulting_as,
- "Permission failure", fault);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.h b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.h
-index c9e27b1..a2d1a8e 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,13 +17,35 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_MMU_H_
- #define _KBASE_MMU_H_
-
-+/**
-+ * kbase_mmu_as_init() - Initialising GPU address space object.
-+ *
-+ * This is called from device probe to initialise an address space object
-+ * of the device.
-+ *
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer).
-+ * @i: Array index of address space object.
-+ *
-+ * Return: 0 on success and non-zero value on failure.
-+ */
-+int kbase_mmu_as_init(struct kbase_device *kbdev, int i);
-+
-+/**
-+ * kbase_mmu_as_term() - Terminate address space object.
-+ *
-+ * This is called upon device termination to destroy
-+ * the address space object of the device.
-+ *
-+ * @kbdev: The kbase device structure for the device (must be a valid pointer).
-+ * @i: Array index of address space object.
-+ */
-+void kbase_mmu_as_term(struct kbase_device *kbdev, int i);
-+
- /**
- * kbase_mmu_init - Initialise an object representing GPU page tables
- *
-@@ -115,4 +138,18 @@ int kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn,
- int kbase_mmu_bus_fault_interrupt(struct kbase_device *kbdev, u32 status,
- u32 as_nr);
-
-+/**
-+ * kbase_mmu_gpu_fault_interrupt() - Report a GPU fault.
-+ * @kbdev: Kbase device pointer
-+ * @status: GPU fault status
-+ * @as_nr: Faulty address space
-+ * @address: GPU fault address
-+ * @as_valid: true if address space is valid
-+ *
-+ * This function builds GPU fault information to submit a work
-+ * for reporting the details of the fault.
-+ */
-+void kbase_mmu_gpu_fault_interrupt(struct kbase_device *kbdev, u32 status,
-+ u32 as_nr, u64 address, bool as_valid);
-+
- #endif /* _KBASE_MMU_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_hw.h b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_hw.h
-index e6eef86..d1f1ff2 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_hw.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_hw.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2015, 2018-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2015, 2018-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-@@ -39,6 +38,11 @@ struct kbase_context;
-
- /**
- * enum kbase_mmu_fault_type - MMU fault type descriptor.
-+ * @KBASE_MMU_FAULT_TYPE_UNKNOWN: unknown fault
-+ * @KBASE_MMU_FAULT_TYPE_PAGE: page fault
-+ * @KBASE_MMU_FAULT_TYPE_BUS: nus fault
-+ * @KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED: page_unexpected fault
-+ * @KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED: bus_unexpected fault
- */
- enum kbase_mmu_fault_type {
- KBASE_MMU_FAULT_TYPE_UNKNOWN = 0,
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_hw_direct.c b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_hw_direct.c
-index f22e73e..a99b988 100755
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_hw_direct.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_hw_direct.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/bitops.h>
-@@ -25,8 +24,7 @@
- #include <mali_kbase_mem.h>
- #include <mmu/mali_kbase_mmu_hw.h>
- #include <tl/mali_kbase_tracepoints.h>
--#include <backend/gpu/mali_kbase_device_internal.h>
--#include <mali_kbase_as_fault_debugfs.h>
-+#include <device/mali_kbase_device.h>
-
- /**
- * lock_region() - Generate lockaddr to lock memory region in MMU
-@@ -126,38 +124,33 @@ void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as)
- struct kbase_mmu_setup *current_setup = &as->current_setup;
- u64 transcfg = 0;
-
-- if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_AARCH64_MMU)) {
-- transcfg = current_setup->transcfg;
-+ transcfg = current_setup->transcfg;
-
-- /* Set flag AS_TRANSCFG_PTW_MEMATTR_WRITE_BACK
-- * Clear PTW_MEMATTR bits
-- */
-- transcfg &= ~AS_TRANSCFG_PTW_MEMATTR_MASK;
-- /* Enable correct PTW_MEMATTR bits */
-- transcfg |= AS_TRANSCFG_PTW_MEMATTR_WRITE_BACK;
-- /* Ensure page-tables reads use read-allocate cache-policy in
-- * the L2
-- */
-- transcfg |= AS_TRANSCFG_R_ALLOCATE;
--
-- if (kbdev->system_coherency == COHERENCY_ACE) {
-- /* Set flag AS_TRANSCFG_PTW_SH_OS (outer shareable)
-- * Clear PTW_SH bits
-- */
-- transcfg = (transcfg & ~AS_TRANSCFG_PTW_SH_MASK);
-- /* Enable correct PTW_SH bits */
-- transcfg = (transcfg | AS_TRANSCFG_PTW_SH_OS);
-- }
-+ /* Set flag AS_TRANSCFG_PTW_MEMATTR_WRITE_BACK
-+ * Clear PTW_MEMATTR bits
-+ */
-+ transcfg &= ~AS_TRANSCFG_PTW_MEMATTR_MASK;
-+ /* Enable correct PTW_MEMATTR bits */
-+ transcfg |= AS_TRANSCFG_PTW_MEMATTR_WRITE_BACK;
-+ /* Ensure page-tables reads use read-allocate cache-policy in
-+ * the L2
-+ */
-+ transcfg |= AS_TRANSCFG_R_ALLOCATE;
-
-- kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSCFG_LO),
-- transcfg);
-- kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSCFG_HI),
-- (transcfg >> 32) & 0xFFFFFFFFUL);
-- } else {
-- if (kbdev->system_coherency == COHERENCY_ACE)
-- current_setup->transtab |= AS_TRANSTAB_LPAE_SHARE_OUTER;
-+ if (kbdev->system_coherency != COHERENCY_NONE) {
-+ /* Set flag AS_TRANSCFG_PTW_SH_OS (outer shareable)
-+ * Clear PTW_SH bits
-+ */
-+ transcfg = (transcfg & ~AS_TRANSCFG_PTW_SH_MASK);
-+ /* Enable correct PTW_SH bits */
-+ transcfg = (transcfg | AS_TRANSCFG_PTW_SH_OS);
- }
-
-+ kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSCFG_LO),
-+ transcfg);
-+ kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSCFG_HI),
-+ (transcfg >> 32) & 0xFFFFFFFFUL);
-+
- kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSTAB_LO),
- current_setup->transtab & 0xFFFFFFFFUL);
- kbase_reg_write(kbdev, MMU_AS_REG(as->number, AS_TRANSTAB_HI),
-@@ -230,10 +223,11 @@ void kbase_mmu_hw_clear_fault(struct kbase_device *kbdev, struct kbase_as *as,
-
- /* Clear the page (and bus fault IRQ as well in case one occurred) */
- pf_bf_mask = MMU_PAGE_FAULT(as->number);
-+#if !MALI_USE_CSF
- if (type == KBASE_MMU_FAULT_TYPE_BUS ||
- type == KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED)
- pf_bf_mask |= MMU_BUS_ERROR(as->number);
--
-+#endif
- kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_CLEAR), pf_bf_mask);
-
- unlock:
-@@ -261,10 +255,11 @@ void kbase_mmu_hw_enable_fault(struct kbase_device *kbdev, struct kbase_as *as,
- irq_mask = kbase_reg_read(kbdev, MMU_REG(MMU_IRQ_MASK)) |
- MMU_PAGE_FAULT(as->number);
-
-+#if !MALI_USE_CSF
- if (type == KBASE_MMU_FAULT_TYPE_BUS ||
- type == KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED)
- irq_mask |= MMU_BUS_ERROR(as->number);
--
-+#endif
- kbase_reg_write(kbdev, MMU_REG(MMU_IRQ_MASK), irq_mask);
-
- unlock:
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_internal.h b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_internal.h
-index 28bd341..b8cd55f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_internal.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_internal.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KBASE_MMU_INTERNAL_H_
-@@ -26,6 +25,15 @@
- void kbase_mmu_get_as_setup(struct kbase_mmu_table *mmut,
- struct kbase_mmu_setup * const setup);
-
-+/**
-+ * kbase_mmu_report_mcu_as_fault_and_reset - Report page fault for all
-+ * address spaces and reset the GPU.
-+ * @kbdev: The kbase_device the fault happened on
-+ * @fault: Data relating to the fault
-+ */
-+void kbase_mmu_report_mcu_as_fault_and_reset(struct kbase_device *kbdev,
-+ struct kbase_fault *fault);
-+
- void kbase_gpu_report_bus_fault_and_kill(struct kbase_context *kctx,
- struct kbase_as *as, struct kbase_fault *fault);
-
-@@ -33,24 +41,11 @@ void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx,
- struct kbase_as *as, const char *reason_str,
- struct kbase_fault *fault);
-
--/**
-- * kbase_mmu_interrupt_process - Process a bus or page fault.
-- * @kbdev The kbase_device the fault happened on
-- * @kctx The kbase_context for the faulting address space if one was found.
-- * @as The address space that has the fault
-- * @fault Data relating to the fault
-- *
-- * This function will process a fault on a specific address space
-- */
--void kbase_mmu_interrupt_process(struct kbase_device *kbdev,
-- struct kbase_context *kctx, struct kbase_as *as,
-- struct kbase_fault *fault);
--
- /**
- * kbase_mmu_switch_to_ir() - Switch to incremental rendering if possible
-- * @kctx The kbase_context for the faulting address space.
-- * @reg Reference of a growable GPU memory region in the same context.
-- * Takes ownership of the reference if successful.
-+ * @kctx: kbase_context for the faulting address space.
-+ * @reg: of a growable GPU memory region in the same context.
-+ * Takes ownership of the reference if successful.
- *
- * Used to switch to incremental rendering if we have nearly run out of
- * virtual address space in a growable memory region.
-@@ -60,4 +55,18 @@ void kbase_mmu_interrupt_process(struct kbase_device *kbdev,
- int kbase_mmu_switch_to_ir(struct kbase_context *kctx,
- struct kbase_va_region *reg);
-
-+/**
-+ * kbase_mmu_page_fault_worker() - Process a page fault.
-+ *
-+ * @data: work_struct passed by queue_work()
-+ */
-+void kbase_mmu_page_fault_worker(struct work_struct *data);
-+
-+/**
-+ * kbase_mmu_bus_fault_worker() - Process a bus fault.
-+ *
-+ * @data: work_struct passed by queue_work()
-+ */
-+void kbase_mmu_bus_fault_worker(struct work_struct *data);
-+
- #endif /* _KBASE_MMU_INTERNAL_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_mode_aarch64.c b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_mode_aarch64.c
-index 02493e9..16b928d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_mode_aarch64.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_mode_aarch64.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2014, 2016-2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2014, 2016-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase.h"
-@@ -48,25 +47,7 @@
- */
- static inline void page_table_entry_set(u64 *pte, u64 phy)
- {
--#if KERNEL_VERSION(3, 18, 13) <= LINUX_VERSION_CODE
- WRITE_ONCE(*pte, phy);
--#else
--#ifdef CONFIG_64BIT
-- barrier();
-- *pte = phy;
-- barrier();
--#elif defined(CONFIG_ARM)
-- barrier();
-- asm volatile("ldrd r0, [%1]\n\t"
-- "strd r0, %0\n\t"
-- : "=m" (*pte)
-- : "r" (&phy)
-- : "r0", "r1");
-- barrier();
--#else
--#error "64-bit atomic write must be implemented for your architecture"
--#endif
--#endif
- }
-
- static void mmu_update(struct kbase_device *kbdev, struct kbase_mmu_table *mmut,
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_mode_lpae.c b/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_mode_lpae.c
-deleted file mode 100644
-index 91a2d7a..0000000
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mmu/mali_kbase_mmu_mode_lpae.c
-+++ /dev/null
-@@ -1,215 +0,0 @@
--/*
-- *
-- * (C) COPYRIGHT 2010-2019 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- */
--
--
--#include "mali_kbase.h"
--#include <gpu/mali_kbase_gpu_regmap.h>
--#include "mali_kbase_defs.h"
--
--#define ENTRY_TYPE_MASK 3ULL
--#define ENTRY_IS_ATE 1ULL
--#define ENTRY_IS_INVAL 2ULL
--#define ENTRY_IS_PTE 3ULL
--
--#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)
--
--/* Helper Function to perform assignment of page table entries, to
-- * ensure the use of strd, which is required on LPAE systems.
-- */
--static inline void page_table_entry_set(u64 *pte, u64 phy)
--{
--#if KERNEL_VERSION(3, 18, 13) <= LINUX_VERSION_CODE
-- WRITE_ONCE(*pte, phy);
--#else
--#ifdef CONFIG_64BIT
-- barrier();
-- *pte = phy;
-- barrier();
--#elif defined(CONFIG_ARM)
-- barrier();
-- asm volatile("ldrd r0, [%1]\n\t"
-- "strd r0, %0\n\t"
-- : "=m" (*pte)
-- : "r" (&phy)
-- : "r0", "r1");
-- barrier();
--#else
--#error "64-bit atomic write must be implemented for your architecture"
--#endif
--#endif
--}
--
--static void mmu_get_as_setup(struct kbase_mmu_table *mmut,
-- struct kbase_mmu_setup * const setup)
--{
-- /* Set up the required caching policies at the correct indices
-- * in the memattr register.
-- */
-- setup->memattr =
-- (AS_MEMATTR_LPAE_IMPL_DEF_CACHE_POLICY <<
-- (AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY * 8)) |
-- (AS_MEMATTR_LPAE_FORCE_TO_CACHE_ALL <<
-- (AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL * 8)) |
-- (AS_MEMATTR_LPAE_WRITE_ALLOC <<
-- (AS_MEMATTR_INDEX_WRITE_ALLOC * 8)) |
-- (AS_MEMATTR_LPAE_OUTER_IMPL_DEF <<
-- (AS_MEMATTR_INDEX_OUTER_IMPL_DEF * 8)) |
-- (AS_MEMATTR_LPAE_OUTER_WA <<
-- (AS_MEMATTR_INDEX_OUTER_WA * 8)) |
-- 0; /* The other indices are unused for now */
--
-- setup->transtab = ((u64)mmut->pgd &
-- ((0xFFFFFFFFULL << 32) | AS_TRANSTAB_LPAE_ADDR_SPACE_MASK)) |
-- AS_TRANSTAB_LPAE_ADRMODE_TABLE |
-- AS_TRANSTAB_LPAE_READ_INNER;
--
-- setup->transcfg = 0;
--}
--
--static void mmu_update(struct kbase_device *kbdev,
-- struct kbase_mmu_table *mmut,
-- int as_nr)
--{
-- struct kbase_as *as;
-- struct kbase_mmu_setup *current_setup;
--
-- if (WARN_ON(as_nr == KBASEP_AS_NR_INVALID))
-- return;
--
-- as = &kbdev->as[as_nr];
-- current_setup = &as->current_setup;
--
-- mmu_get_as_setup(mmut, current_setup);
--
-- /* Apply the address space setting */
-- kbase_mmu_hw_configure(kbdev, as);
--}
--
--static void mmu_disable_as(struct kbase_device *kbdev, int as_nr)
--{
-- struct kbase_as * const as = &kbdev->as[as_nr];
-- struct kbase_mmu_setup * const current_setup = &as->current_setup;
--
-- current_setup->transtab = AS_TRANSTAB_LPAE_ADRMODE_UNMAPPED;
--
-- /* Apply the address space setting */
-- kbase_mmu_hw_configure(kbdev, as);
--}
--
--static phys_addr_t pte_to_phy_addr(u64 entry)
--{
-- if (!(entry & 1))
-- return 0;
--
-- return entry & ~0xFFF;
--}
--
--static int ate_is_valid(u64 ate, int const level)
--{
-- return ((ate & ENTRY_TYPE_MASK) == ENTRY_IS_ATE);
--}
--
--static int pte_is_valid(u64 pte, int const level)
--{
-- return ((pte & ENTRY_TYPE_MASK) == ENTRY_IS_PTE);
--}
--
--/*
-- * Map KBASE_REG flags to MMU flags
-- */
--static u64 get_mmu_flags(unsigned long flags)
--{
-- u64 mmu_flags;
-- unsigned long memattr_idx;
--
-- memattr_idx = KBASE_REG_MEMATTR_VALUE(flags);
-- if (WARN(memattr_idx == AS_MEMATTR_INDEX_NON_CACHEABLE,
-- "Legacy Mode MMU cannot honor GPU non-cachable memory, will use default instead\n"))
-- memattr_idx = AS_MEMATTR_INDEX_DEFAULT;
-- /* store mem_attr index as 4:2, noting that:
-- * - macro called above ensures 3 bits already
-- * - all AS_MEMATTR_INDEX_<...> macros only use 3 bits
-- */
-- mmu_flags = memattr_idx << 2;
--
-- /* write perm if requested */
-- mmu_flags |= (flags & KBASE_REG_GPU_WR) ? ENTRY_WR_BIT : 0;
-- /* read perm if requested */
-- mmu_flags |= (flags & KBASE_REG_GPU_RD) ? ENTRY_RD_BIT : 0;
-- /* nx if requested */
-- mmu_flags |= (flags & KBASE_REG_GPU_NX) ? ENTRY_NX_BIT : 0;
--
-- if (flags & KBASE_REG_SHARE_BOTH) {
-- /* inner and outer shareable */
-- mmu_flags |= SHARE_BOTH_BITS;
-- } else if (flags & KBASE_REG_SHARE_IN) {
-- /* inner shareable coherency */
-- mmu_flags |= SHARE_INNER_BITS;
-- }
--
-- return mmu_flags;
--}
--
--static void entry_set_ate(u64 *entry,
-- struct tagged_addr phy,
-- unsigned long flags,
-- int const level)
--{
-- page_table_entry_set(entry, as_phys_addr_t(phy) | get_mmu_flags(flags) |
-- ENTRY_IS_ATE);
--}
--
--static void entry_set_pte(u64 *entry, phys_addr_t phy)
--{
-- page_table_entry_set(entry, (phy & ~0xFFF) | ENTRY_IS_PTE);
--}
--
--static void entry_invalidate(u64 *entry)
--{
-- page_table_entry_set(entry, ENTRY_IS_INVAL);
--}
--
--static struct kbase_mmu_mode const lpae_mode = {
-- .update = mmu_update,
-- .get_as_setup = mmu_get_as_setup,
-- .disable_as = mmu_disable_as,
-- .pte_to_phy_addr = pte_to_phy_addr,
-- .ate_is_valid = ate_is_valid,
-- .pte_is_valid = pte_is_valid,
-- .entry_set_ate = entry_set_ate,
-- .entry_set_pte = entry_set_pte,
-- .entry_invalidate = entry_invalidate,
-- .flags = 0
--};
--
--struct kbase_mmu_mode const *kbase_mmu_mode_get_lpae(void)
--{
-- return &lpae_mode;
--}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/Kconfig b/dvalin/kernel/drivers/gpu/arm/midgard/platform/Kconfig
-index ef9fb96..5f0118d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/Kconfig
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/Kconfig
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012-2013, 2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2013, 2017, 2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,11 +16,7 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
--#
--
--
-
- # Add your platform specific Kconfig file here
- #
-@@ -27,4 +24,3 @@
- #
- # Where xxx is the platform name is the name set in MALI_PLATFORM_NAME
- #
--
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/Kbuild
-old mode 100644
-new mode 100755
-index 0a82eaf..4f3fc0d
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2017, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,8 +16,6 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/Kbuild.rej b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/Kbuild.rej
-new file mode 100644
-index 0000000..dbc2029
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/Kbuild.rej
-@@ -0,0 +1,17 @@
-+--- drivers/gpu/arm/midgard/platform/devicetree/Kbuild
-++++ drivers/gpu/arm/midgard/platform/devicetree/Kbuild
-+@@ -16,10 +17,10 @@
-+ # along with this program; if not, you can access it online at
-+ # http://www.gnu.org/licenses/gpl-2.0.html.
-+ #
-+-# SPDX-License-Identifier: GPL-2.0
-+-#
-+ #
-+
-+ mali_kbase-y += \
-+- $(MALI_PLATFORM_DIR)/mali_kbase_config_devicetree.o \
-+- $(MALI_PLATFORM_DIR)/mali_kbase_runtime_pm.o
-++ platform/$(MALI_PLATFORM_DIR)/mali_kbase_config_devicetree.o \
-++ platform/$(MALI_PLATFORM_DIR)/mali_kbase_config_platform.o \
-++ platform/$(MALI_PLATFORM_DIR)/mali_kbase_runtime_pm.o \
-++ platform/$(MALI_PLATFORM_DIR)/mali_kbase_clk_rate_trace.o
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_clk_rate_trace.c b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_clk_rate_trace.c
-new file mode 100644
-index 0000000..4bcd585
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_clk_rate_trace.c
-@@ -0,0 +1,105 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2015, 2017-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <mali_kbase_defs.h>
-+#include <linux/clk.h>
-+#include "mali_kbase_config_platform.h"
-+
-+#if MALI_USE_CSF
-+#include <asm/arch_timer.h>
-+#endif
-+
-+static void *enumerate_gpu_clk(struct kbase_device *kbdev,
-+ unsigned int index)
-+{
-+ if (index >= kbdev->nr_clocks)
-+ return NULL;
-+
-+#if MALI_USE_CSF
-+ if (of_machine_is_compatible("arm,juno"))
-+ WARN_ON(kbdev->nr_clocks != 1);
-+#endif
-+
-+ return kbdev->clocks[index];
-+}
-+
-+static unsigned long get_gpu_clk_rate(struct kbase_device *kbdev,
-+ void *gpu_clk_handle)
-+{
-+#if MALI_USE_CSF
-+ /* On Juno fpga platforms, the GPU clock rate is reported as 600 MHZ at
-+ * the boot time. Then after the first call to kbase_devfreq_target()
-+ * the clock rate is reported as 450 MHZ and the frequency does not
-+ * change after that. But the actual frequency at which GPU operates
-+ * is always 50 MHz, which is equal to the frequency of system counter
-+ * and HW counters also increment at the same rate.
-+ * DVFS, which is a client of kbase_ipa_control, needs normalization of
-+ * GPU_ACTIVE counter to calculate the time for which GPU has been busy.
-+ * So for the correct normalization need to return the system counter
-+ * frequency value.
-+ * This is a reasonable workaround as the frequency value remains same
-+ * throughout. It can be removed after GPUCORE-25693.
-+ */
-+ if (of_machine_is_compatible("arm,juno"))
-+ return arch_timer_get_cntfrq();
-+#endif
-+
-+ return clk_get_rate((struct clk *)gpu_clk_handle);
-+}
-+
-+static int gpu_clk_notifier_register(struct kbase_device *kbdev,
-+ void *gpu_clk_handle, struct notifier_block *nb)
-+{
-+ compiletime_assert(offsetof(struct clk_notifier_data, clk) ==
-+ offsetof(struct kbase_gpu_clk_notifier_data, gpu_clk_handle),
-+ "mismatch in the offset of clk member");
-+
-+ compiletime_assert(sizeof(((struct clk_notifier_data *)0)->clk) ==
-+ sizeof(((struct kbase_gpu_clk_notifier_data *)0)->gpu_clk_handle),
-+ "mismatch in the size of clk member");
-+
-+#if MALI_USE_CSF
-+ /* Frequency is fixed on Juno platforms */
-+ if (of_machine_is_compatible("arm,juno"))
-+ return 0;
-+#endif
-+
-+ return clk_notifier_register((struct clk *)gpu_clk_handle, nb);
-+}
-+
-+static void gpu_clk_notifier_unregister(struct kbase_device *kbdev,
-+ void *gpu_clk_handle, struct notifier_block *nb)
-+{
-+#if MALI_USE_CSF
-+ if (of_machine_is_compatible("arm,juno"))
-+ return;
-+#endif
-+
-+ clk_notifier_unregister((struct clk *)gpu_clk_handle, nb);
-+}
-+
-+struct kbase_clk_rate_trace_op_conf clk_rate_trace_ops = {
-+ .get_gpu_clk_rate = get_gpu_clk_rate,
-+ .enumerate_gpu_clk = enumerate_gpu_clk,
-+ .gpu_clk_notifier_register = gpu_clk_notifier_register,
-+ .gpu_clk_notifier_unregister = gpu_clk_notifier_unregister,
-+};
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_devicetree.c b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_devicetree.c
-old mode 100644
-new mode 100755
-index 55a50c4..d729ffb
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_devicetree.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_devicetree.c
-@@ -1,20 +1,28 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
-- * mali_kbase_config_devicetree.c
- *
-- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
-+ * (C) COPYRIGHT 2015, 2017, 2020-2021 ARM Limited. All rights reserved.
- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-+ * This program is 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 license.
- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
- *
- */
-
-+#include <mali_kbase.h>
-+#include <mali_kbase_config.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+
- #ifdef CONFIG_DEVFREQ_THERMAL
- #include <linux/version.h>
- #include <linux/devfreq_cooling.h>
-@@ -82,3 +90,14 @@ void kbase_platform_unregister(void)
- {
- }
- #endif
-+
-+#ifdef CONFIG_MALI_MIDGARD_DVFS
-+#if MALI_USE_CSF
-+int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation)
-+#else
-+int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, u32 util_cl_share[2])
-+#endif
-+{
-+ return 1;
-+}
-+#endif /* CONFIG_MALI_MIDGARD_DVFS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.c b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.c
-new file mode 100644
-index 0000000..63aa33f
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.c
-@@ -0,0 +1,43 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <mali_kbase.h>
-+#include <mali_kbase_defs.h>
-+#include <mali_kbase_config.h>
-+#include "mali_kbase_config_platform.h"
-+#include <device/mali_kbase_device.h>
-+#include <mali_kbase_hwaccess_time.h>
-+#include <gpu/mali_kbase_gpu_regmap.h>
-+
-+#include <linux/kthread.h>
-+#include <linux/timer.h>
-+#include <linux/jiffies.h>
-+#include <linux/wait.h>
-+#include <linux/delay.h>
-+#include <linux/gcd.h>
-+#include <asm/arch_timer.h>
-+
-+struct kbase_platform_funcs_conf platform_funcs = {
-+ .platform_init_func = NULL,
-+ .platform_term_func = NULL,
-+ .platform_late_init_func = NULL,
-+ .platform_late_term_func = NULL,
-+};
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h
-old mode 100644
-new mode 100755
-index 233a18e..6cb3b53
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h
-@@ -1,45 +1,22 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
-- * mali_kbase_config_platform.h
- *
-- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
-+ * (C) COPYRIGHT 2014-2017, 2020-2021 ARM Limited. All rights reserved.
- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-+ * This program is 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 license.
- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
- *
-- */
--
--/**
-- * 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
-- */
--#define GPU_FREQ_KHZ_MAX (750000)
--/**
-- * Minimum frequency GPU will be clocked at. Given in kHz.
-- * This must be specified as there is no default value.
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * Attached value: number in kHz
-- * Default value: NA
-- */
--#define GPU_FREQ_KHZ_MIN (100000)
--
--/**
-- * CPU_SPEED_FUNC - A pointer to a function that calculates the CPU clock
-- *
-- * CPU clock speed of the platform is in MHz - see kbase_cpu_clk_speed_func
-- * for the function prototype.
-- *
-- * Attached value: A kbase_cpu_clk_speed_func.
-- * Default Value: NA
- */
- #define CPU_SPEED_FUNC (NULL)
-
-@@ -81,7 +58,12 @@ extern struct devfreq_cooling_ops t83x_model_ops;
- #else
- #define POWER_MODEL_CALLBACKS (NULL)
- #endif
-+
-+#define CLK_RATE_TRACE_OPS (&clk_rate_trace_ops)
-+
- extern struct kbase_pm_callback_conf pm_callbacks;
-+extern struct kbase_clk_rate_trace_op_conf clk_rate_trace_ops;
-+extern struct kbase_platform_funcs_conf platform_funcs;
-
- void mali_dev_freeze(void);
- void mali_dev_restore(void);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h.rej b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h.rej
-new file mode 100644
-index 0000000..277acaa
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h.rej
-@@ -0,0 +1,42 @@
-+--- drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h
-++++ drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_config_platform.h
-+@@ -1,11 +1,12 @@
-++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+ /*
-+ *
-+- * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
-++ * (C) COPYRIGHT 2014-2017, 2020-2021 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.
-++ * of such GNU license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+@@ -16,8 +17,6 @@
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+- * SPDX-License-Identifier: GPL-2.0
-+- *
-+ */
-+
-+ /**
-+@@ -34,10 +33,13 @@
-+ * Attached value: pointer to @ref kbase_platform_funcs_conf
-+ * Default value: See @ref kbase_platform_funcs_conf
-+ */
-+-#define PLATFORM_FUNCS (NULL)
-++#define PLATFORM_FUNCS (&platform_funcs)
-+
-+-extern struct kbase_pm_callback_conf pm_callbacks;
-++#define CLK_RATE_TRACE_OPS (&clk_rate_trace_ops)
-+
-++extern struct kbase_pm_callback_conf pm_callbacks;
-++extern struct kbase_clk_rate_trace_op_conf clk_rate_trace_ops;
-++extern struct kbase_platform_funcs_conf platform_funcs;
-+ /**
-+ * Autosuspend delay
-+ *
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_runtime_pm.c b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_runtime_pm.c
-old mode 100644
-new mode 100755
-index ee18718..4a0b72c
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_runtime_pm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/devicetree/mali_kbase_runtime_pm.c
-@@ -1,21 +1,24 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
-- * mali_kbase_runtime_pm.c
- *
-- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
-+ * (C) COPYRIGHT 2015-2021 ARM Limited. All rights reserved.
- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-+ * This program is 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 license.
- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
- *
- */
-
--//#define DEBUG
- #include <mali_kbase.h>
- #include <mali_kbase_defs.h>
- #include <linux/pm_runtime.h>
-@@ -25,6 +28,7 @@
- #include <linux/delay.h>
- #include <linux/io.h>
- #include <backend/gpu/mali_kbase_device_internal.h>
-+
- #include "mali_kbase_config_platform.h"
- #include "mali_scaling.h"
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/Kbuild
-index 6780e4c..b547366 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012-2013, 2016-2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2013, 2016-2017, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,10 +16,8 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- mali_kbase-y += \
-- $(MALI_PLATFORM_DIR)/mali_kbase_config_vexpress.o \
-- mali_kbase_platform_fake.o
-+ platform/$(MALI_PLATFORM_DIR)/mali_kbase_config_vexpress.o \
-+ mali_kbase_platform_fake.o
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h
-index fac3cd5..d8682db 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_platform.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c
-index d165ce2..ff1ee65 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_config_vexpress.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,18 +17,16 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #include <linux/ioport.h>
- #include <mali_kbase.h>
- #include <mali_kbase_defs.h>
- #include <mali_kbase_config.h>
- #include "mali_kbase_config_platform.h"
-
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+
- #ifndef CONFIG_OF
- static struct kbase_io_resources io_resources = {
- .job_irq_number = 68,
-@@ -67,3 +66,14 @@ struct kbase_platform_config *kbase_get_platform_config(void)
- {
- return &versatile_platform_config;
- }
-+
-+#ifdef CONFIG_MALI_MIDGARD_DVFS
-+#if MALI_USE_CSF
-+int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation)
-+#else
-+int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, u32 util_cl_share[2])
-+#endif
-+{
-+ return 1;
-+}
-+#endif /* CONFIG_MALI_MIDGARD_DVFS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild
-index 51b408e..b547366 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2013-2014, 2016-2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2013, 2016-2017, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,10 +16,8 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- mali_kbase-y += \
-- $(MALI_PLATFORM_DIR)/mali_kbase_config_vexpress.o \
-- mali_kbase_platform_fake.o
-+ platform/$(MALI_PLATFORM_DIR)/mali_kbase_config_vexpress.o \
-+ mali_kbase_platform_fake.o
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h
-index fac3cd5..d8682db 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c
-index efca0a5..fee6a36 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2014, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2014, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/ioport.h>
-@@ -25,6 +24,8 @@
- #include <mali_kbase_defs.h>
- #include <mali_kbase_config.h>
-
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+
- #ifndef CONFIG_OF
- static struct kbase_io_resources io_resources = {
- .job_irq_number = 68,
-@@ -63,3 +64,14 @@ struct kbase_platform_config *kbase_get_platform_config(void)
- {
- return &versatile_platform_config;
- }
-+
-+#ifdef CONFIG_MALI_MIDGARD_DVFS
-+#if MALI_USE_CSF
-+int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation)
-+#else
-+int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, u32 util_cl_share[2])
-+#endif
-+{
-+ return 1;
-+}
-+#endif /* CONFIG_MALI_MIDGARD_DVFS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild
-index e07709c..bb92c47 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2012-2013, 2016-2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2012-2013, 2016-2017, 2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,11 +16,9 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
- mali_kbase-y += \
-- $(MALI_PLATFORM_DIR)/mali_kbase_config_vexpress.o \
-- $(MALI_PLATFORM_DIR)/mali_kbase_cpu_vexpress.o \
-- mali_kbase_platform_fake.o
-+ platform/$(MALI_PLATFORM_DIR)/mali_kbase_config_vexpress.o \
-+ platform/$(MALI_PLATFORM_DIR)/mali_kbase_cpu_vexpress.o \
-+ mali_kbase_platform_fake.o
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h
-index fac3cd5..d8682db 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014-2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /**
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c
-index b6714b9..f6fb9aa 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2011-2014, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2011-2014, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,17 +17,15 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- #include <linux/ioport.h>
- #include <mali_kbase.h>
- #include <mali_kbase_defs.h>
- #include <mali_kbase_config.h>
-
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-+
- #ifndef CONFIG_OF
- static struct kbase_io_resources io_resources = {
- .job_irq_number = 75,
-@@ -65,3 +64,14 @@ struct kbase_platform_config *kbase_get_platform_config(void)
- {
- return &versatile_platform_config;
- }
-+
-+#ifdef CONFIG_MALI_MIDGARD_DVFS
-+#if MALI_USE_CSF
-+int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation)
-+#else
-+int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, u32 util_cl_share[2])
-+#endif
-+{
-+ return 1;
-+}
-+#endif /* CONFIG_MALI_MIDGARD_DVFS */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/protected_mode_switcher.h b/dvalin/kernel/drivers/gpu/arm/midgard/protected_mode_switcher.h
-index 8778d81..9dd9253 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/protected_mode_switcher.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/protected_mode_switcher.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _PROTECTED_MODE_SWITCH_H_
-@@ -28,35 +27,23 @@ struct protected_mode_device;
- /**
- * struct protected_mode_ops - Callbacks for protected mode switch operations
- *
-- * @protected_mode_enable: Callback to enable protected mode for device
-+ * @protected_mode_enable: Callback to enable protected mode for device, and
-+ * reset device
-+ * Returns 0 on success, non-zero on error
- * @protected_mode_disable: Callback to disable protected mode for device
-+ * Returns 0 on success, non-zero on error
- */
- struct protected_mode_ops {
-- /**
-- * protected_mode_enable() - Enable protected mode on device
-- * @dev: The struct device
-- *
-- * Return: 0 on success, non-zero on error
-- */
- int (*protected_mode_enable)(
- struct protected_mode_device *protected_dev);
--
-- /**
-- * protected_mode_disable() - Disable protected mode on device, and
-- * reset device
-- * @dev: The struct device
-- *
-- * Return: 0 on success, non-zero on error
-- */
- int (*protected_mode_disable)(
- struct protected_mode_device *protected_dev);
- };
-
- /**
- * struct protected_mode_device - Device structure for protected mode devices
-- *
-- * @ops - Callbacks associated with this device
-- * @data - Pointer to device private data
-+ * @ops: Callbacks associated with this device
-+ * @data: Pointer to device private data
- *
- * This structure should be registered with the platform device using
- * platform_set_drvdata().
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/tests/Kbuild
-index df16a77..ee3de7b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2017, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,9 +16,15 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
-+ccflags-y += -I$(src)/include \
-+ -I$(src)
-+
-+subdir-ccflags-y += -I$(src)/include \
-+ -I$(src)
-+
- obj-$(CONFIG_MALI_KUTF) += kutf/
--obj-$(CONFIG_MALI_IRQ_LATENCY) += mali_kutf_irq_test/
-+obj-$(CONFIG_MALI_KUTF_IRQ_TEST) += mali_kutf_irq_test/
-+obj-$(CONFIG_MALI_KUTF_CLK_RATE_TRACE) += mali_kutf_clk_rate_trace/kernel/
-+
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/Kconfig b/dvalin/kernel/drivers/gpu/arm/midgard/tests/Kconfig
-index fa91aea..a86e1ce 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/Kconfig
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/Kconfig
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2017, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,9 +16,42 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
--source "drivers/gpu/arm/midgard/tests/kutf/Kconfig"
--source "drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kconfig"
-+menuconfig MALI_KUTF
-+ bool "Build Mali Kernel Unit Test Framework modules"
-+ depends on MALI_MIDGARD && MALI_DEBUG
-+ default y if MALI_DEBUG
-+ help
-+ This option will build the Mali testing framework modules.
-+
-+ Modules:
-+ - kutf.ko
-+ - kutf_test.ko
-+
-+config MALI_KUTF_IRQ_TEST
-+ bool "Build Mali KUTF IRQ test module"
-+ depends on MALI_KUTF
-+ default y
-+ help
-+ This option will build the IRQ latency measurement test module.
-+ It can determine the latency of the Mali GPU IRQ on your system.
-+
-+ Modules:
-+ - mali_kutf_irq_test.ko
-+
-+config MALI_KUTF_CLK_RATE_TRACE
-+ bool "Build Mali KUTF Clock rate trace test module"
-+ depends on MALI_KUTF
-+ default y
-+ help
-+ This option will build the clock rate trace portal test module.
-+ It can test the clocks integration into the platform and exercise some
-+ basic trace test in the system.
-+
-+ Modules:
-+ - mali_kutf_clk_rate_trace_test_portal.ko
-+
-+
-+comment "Enable MALI_DEBUG for KUTF modules support"
-+ depends on MALI_MIDGARD && !MALI_DEBUG && MALI_KUTF
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/Mconfig b/dvalin/kernel/drivers/gpu/arm/midgard/tests/Mconfig
-index be3fedb..167facd 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/Mconfig
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/Mconfig
-@@ -1,38 +1,61 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2018-2021 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.
-+# of such GNU license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# 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.
- #
-
--config UNIT_TEST_KERNEL_MODULES
-- bool
-- default y if UNIT_TEST_CODE && BUILD_KERNEL_MODULES
-- default n
--
--config BUILD_IPA_TESTS
-- bool
-- default y if UNIT_TEST_KERNEL_MODULES && MALI_DEVFREQ
-- default n
--
--config BUILD_IPA_UNIT_TESTS
-- bool
-- default y if NO_MALI && BUILD_IPA_TESTS
-- default n
--
--config BUILD_CSF_TESTS
-- bool
-- default y if UNIT_TEST_KERNEL_MODULES && GPU_HAS_CSF
-- default n
--
--config BUILD_ARBIF_TESTS
-- bool
-- default y if UNIT_TEST_KERNEL_MODULES && MALI_ARBITER_SUPPORT
-- default n
-+menuconfig MALI_KUTF
-+ bool "Build Mali Kernel Unit Test Framework modules"
-+ depends on MALI_MIDGARD && MALI_DEBUG
-+ default y if BACKEND_KERNEL && MALI_DEBUG
-+ help
-+ This option will build the Mali testing framework modules.
-+
-+ Modules:
-+ - kutf.ko
-+ - kutf_test.ko
-+
-+config MALI_KUTF_IRQ_TEST
-+ bool "Build Mali KUTF IRQ test module"
-+ depends on MALI_KUTF
-+ default y
-+ help
-+ This option will build the IRQ latency measurement test module.
-+ It can determine the latency of the Mali GPU IRQ on your system.
-+
-+ Modules:
-+ - mali_kutf_irq_test.ko
-
-+config MALI_KUTF_CLK_RATE_TRACE
-+ bool "Build Mali KUTF Clock rate trace test module"
-+ depends on MALI_KUTF
-+ default y
-+ help
-+ This option will build the clock rate trace portal test module.
-+ It can test the clocks integration into the platform and exercise some
-+ basic trace test in the system.
-+
-+ Modules:
-+ - mali_kutf_clk_rate_trace_test_portal.ko
-+
-+
-+# Enable MALI_DEBUG for KUTF modules support
-+
-+config UNIT_TEST_KERNEL_MODULES
-+ bool
-+ default y if UNIT_TEST_CODE && BACKEND_KERNEL
-+ default n
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/build.bp b/dvalin/kernel/drivers/gpu/arm/midgard/tests/build.bp
-new file mode 100644
-index 0000000..9d6137d
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/build.bp
-@@ -0,0 +1,40 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+bob_defaults {
-+ name: "kernel_test_includes",
-+ local_include_dirs: [
-+ "include",
-+ "./../../",
-+ "./../",
-+ "./"
-+ ],
-+}
-+
-+bob_defaults {
-+ name: "kernel_test_configs",
-+ mali_kutf: {
-+ kbuild_options: ["CONFIG_MALI_KUTF=y"],
-+ },
-+ unit_test_kernel_modules: {
-+ kbuild_options: ["CONFIG_UNIT_TEST_KERNEL_MODULES=y"],
-+ },
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_helpers.h b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_helpers.h
-index 15e168c..c4c713c 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_helpers.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_helpers.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KERNEL_UTF_HELPERS_H_
-@@ -33,6 +32,14 @@
-
- #include <kutf/kutf_suite.h>
-
-+/**
-+ * kutf_helper_pending_input() - Check any pending lines sent by user space
-+ * @context: KUTF context
-+ *
-+ * Return: true if there are pending lines, otherwise false
-+ */
-+bool kutf_helper_pending_input(struct kutf_context *context);
-+
- /**
- * kutf_helper_input_dequeue() - Dequeue a line sent by user space
- * @context: KUTF context
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_helpers_user.h b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_helpers_user.h
-index 3b1300e..e147cbb 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_helpers_user.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_helpers_user.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KERNEL_UTF_HELPERS_USER_H_
-@@ -63,7 +62,8 @@ struct kutf_helper_named_val {
- * unrecoverable)
- *
- * Positive values indicate correct access but invalid parsing (can be
-- * recovered from assuming data in the future is correct) */
-+ * recovered from assuming data in the future is correct)
-+ */
- enum kutf_helper_err {
- /* No error - must be zero */
- KUTF_HELPER_ERR_NONE = 0,
-@@ -71,14 +71,16 @@ enum kutf_helper_err {
- KUTF_HELPER_ERR_INVALID_NAME,
- /* Named value parsing of string or u64 type encountered extra
- * characters after the value (after the last digit for a u64 type or
-- * after the string end delimiter for string type) */
-+ * after the string end delimiter for string type)
-+ */
- KUTF_HELPER_ERR_CHARS_AFTER_VAL,
- /* Named value parsing of string type couldn't find the string end
- * delimiter.
- *
- * This cannot be encountered when the NAME="value" message exceeds the
- * textbuf's maximum line length, because such messages are not checked
-- * for an end string delimiter */
-+ * for an end string delimiter
-+ */
- KUTF_HELPER_ERR_NO_END_DELIMITER,
- /* Named value didn't parse as any of the known types */
- KUTF_HELPER_ERR_INVALID_VALUE,
-@@ -122,7 +124,8 @@ int kutf_helper_max_str_len_for_kern(const char *val_name, int kern_buf_sz);
- *
- * Any failure will be logged on the suite's current test fixture
- *
-- * Returns 0 on success, non-zero on failure */
-+ * Returns 0 on success, non-zero on failure
-+ */
- int kutf_helper_send_named_str(struct kutf_context *context,
- const char *val_name, const char *val_str);
-
-@@ -138,7 +141,8 @@ int kutf_helper_send_named_str(struct kutf_context *context,
- *
- * Returns 0 on success. Negative value on failure to receive from the 'run'
- * file, positive value indicates an enum kutf_helper_err value for correct
-- * reception of data but invalid parsing */
-+ * reception of data but invalid parsing
-+ */
- int kutf_helper_receive_named_val(
- struct kutf_context *context,
- struct kutf_helper_named_val *named_val);
-@@ -165,7 +169,8 @@ int kutf_helper_receive_named_val(
- * - return value will be 0 to indicate success
- *
- * The rationale behind this is that we'd prefer to continue the rest of the
-- * test with failures propagated, rather than hitting a timeout */
-+ * test with failures propagated, rather than hitting a timeout
-+ */
- int kutf_helper_receive_check_val(
- struct kutf_helper_named_val *named_val,
- struct kutf_context *context,
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_mem.h b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_mem.h
-index 988559d..5d4d96e 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_mem.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_mem.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KERNEL_UTF_MEM_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_resultset.h b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_resultset.h
-index 49ebeb4..2fb1a47 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_resultset.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_resultset.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KERNEL_UTF_RESULTSET_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_suite.h b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_suite.h
-index 8d75f50..b9c333b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_suite.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_suite.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KERNEL_UTF_SUITE_H_
-@@ -264,9 +263,10 @@ struct kutf_suite {
- struct list_head test_list;
- };
-
--/* ============================================================================
-- Application functions
--============================================================================ */
-+/** ===========================================================================
-+ * Application functions
-+ * ============================================================================
-+ */
-
- /**
- * kutf_create_application() - Create an in kernel test application.
-@@ -284,9 +284,10 @@ struct kutf_application *kutf_create_application(const char *name);
- */
- void kutf_destroy_application(struct kutf_application *app);
-
--/* ============================================================================
-- Suite functions
--============================================================================ */
-+/**============================================================================
-+ * Suite functions
-+ * ============================================================================
-+ */
-
- /**
- * kutf_create_suite() - Create a kernel test suite.
-@@ -416,10 +417,10 @@ void kutf_add_test_with_filters_and_data(
- unsigned int filters,
- union kutf_callback_data test_data);
-
--
--/* ============================================================================
-- Test functions
--============================================================================ */
-+/** ===========================================================================
-+ * Test functions
-+ * ============================================================================
-+ */
- /**
- * kutf_test_log_result_external() - Log a result which has been created
- * externally into a in a standard form
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_utils.h b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_utils.h
-index 25b8285..18dcc3d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_utils.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/include/kutf/kutf_utils.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _KERNEL_UTF_UTILS_H_
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Kbuild
-index 2531d41..c4790bc 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2017, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,12 +16,16 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
--#
--
--ccflags-y += -I$(src)/../include
-
--obj-$(CONFIG_MALI_KUTF) += kutf.o
-+ifeq ($(CONFIG_MALI_KUTF),y)
-+obj-m += kutf.o
-
--kutf-y := kutf_mem.o kutf_resultset.o kutf_suite.o kutf_utils.o kutf_helpers.o kutf_helpers_user.o
-+kutf-y := \
-+ kutf_mem.o \
-+ kutf_resultset.o \
-+ kutf_suite.o \
-+ kutf_utils.o \
-+ kutf_helpers.o \
-+ kutf_helpers_user.o
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/build.bp b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/build.bp
-index 32eab14..89edae9 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/build.bp
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/build.bp
-@@ -1,23 +1,30 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018-2021 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.
-+ * of such GNU license.
- *
-- * 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 program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
- *
- */
-
- bob_kernel_module {
- name: "kutf",
- defaults: [
-- "kernel_defaults",
-- "kutf_includes",
-+ "mali_kbase_shared_config_defaults",
-+ "kernel_test_configs",
-+ "kernel_test_includes",
- ],
- srcs: [
- "Kbuild",
-@@ -28,9 +35,8 @@ bob_kernel_module {
- "kutf_suite.c",
- "kutf_utils.c",
- ],
-- kbuild_options: ["CONFIG_MALI_KUTF=m"],
- enabled: false,
-- base_build_kutf: {
-+ mali_kutf: {
- enabled: true,
- },
- }
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_helpers.c b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_helpers.c
-index cab5add..c075428 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_helpers.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_helpers.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* Kernel UTF test helpers */
-@@ -29,10 +28,11 @@
- #include <linux/preempt.h>
- #include <linux/wait.h>
- #include <linux/uaccess.h>
-+#include <linux/export.h>
-
- static DEFINE_SPINLOCK(kutf_input_lock);
-
--static bool pending_input(struct kutf_context *context)
-+bool kutf_helper_pending_input(struct kutf_context *context)
- {
- bool input_pending;
-
-@@ -44,6 +44,7 @@ static bool pending_input(struct kutf_context *context)
-
- return input_pending;
- }
-+EXPORT_SYMBOL(kutf_helper_pending_input);
-
- char *kutf_helper_input_dequeue(struct kutf_context *context, size_t *str_size)
- {
-@@ -59,7 +60,7 @@ char *kutf_helper_input_dequeue(struct kutf_context *context, size_t *str_size)
- spin_unlock(&kutf_input_lock);
-
- err = wait_event_interruptible(context->userdata.input_waitq,
-- pending_input(context));
-+ kutf_helper_pending_input(context));
-
- if (err)
- return ERR_PTR(-EINTR);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_helpers_user.c b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_helpers_user.c
-index 108fa82..a8b59f7 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_helpers_user.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_helpers_user.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* Kernel UTF test helpers that mirror those for kutf-userside */
-@@ -42,7 +41,8 @@ static const char *get_val_type_name(enum kutf_helper_valtype valtype)
- * a) "<0 comparison on unsigned type" warning - if we did both upper
- * and lower bound check
- * b) incorrect range checking if it was a signed type - if we did
-- * upper bound check only */
-+ * upper bound check only
-+ */
- unsigned int type_idx = (unsigned int)valtype;
-
- if (type_idx >= (unsigned int)KUTF_HELPER_VALTYPE_COUNT)
-@@ -54,7 +54,8 @@ static const char *get_val_type_name(enum kutf_helper_valtype valtype)
- /* Check up to str_len chars of val_str to see if it's a valid value name:
- *
- * - Has between 1 and KUTF_HELPER_MAX_VAL_NAME_LEN characters before the \0 terminator
-- * - And, each char is in the character set [A-Z0-9_] */
-+ * - And, each char is in the character set [A-Z0-9_]
-+ */
- static int validate_val_name(const char *val_str, int str_len)
- {
- int i = 0;
-@@ -87,7 +88,8 @@ static int validate_val_name(const char *val_str, int str_len)
- * e.g. "str"
- *
- * That is, before any '\\', '\n' or '"' characters. This is so we don't have
-- * to escape the string */
-+ * to escape the string
-+ */
- static int find_quoted_string_valid_len(const char *str)
- {
- char *ptr;
-@@ -207,7 +209,8 @@ int kutf_helper_send_named_str(struct kutf_context *context,
- str_buf_sz = val_name_len + start_delim_len + val_str_len + end_delim_len + 1;
-
- /* Using kmalloc() here instead of mempool since we know we need to free
-- * before we return */
-+ * before we return
-+ */
- str_buf = kmalloc(str_buf_sz, GFP_KERNEL);
- if (!str_buf) {
- errmsg = kutf_dsprintf(&context->fixture_pool,
-@@ -218,7 +221,8 @@ int kutf_helper_send_named_str(struct kutf_context *context,
- copy_ptr = str_buf;
-
- /* Manually copy each string component instead of snprintf because
-- * val_str may need to end early, and less error path handling */
-+ * val_str may need to end early, and less error path handling
-+ */
-
- /* name */
- memcpy(copy_ptr, val_name, val_name_len);
-@@ -331,7 +335,8 @@ int kutf_helper_receive_named_val(
- /* possibly a number value - strtoull will parse it */
- err = kstrtoull(recv_str, 0, &u64val);
- /* unlike userspace can't get an end ptr, but if kstrtoull()
-- * reads characters after the number it'll report -EINVAL */
-+ * reads characters after the number it'll report -EINVAL
-+ */
- if (!err) {
- int len_remain = strnlen(recv_str, recv_sz);
-
-@@ -399,7 +404,8 @@ int kutf_helper_receive_check_val(
- goto out_fail_and_fixup;
- }
-
-- if (strcmp(named_val->val_name, expect_val_name) != 0) {
-+ if (named_val->val_name != NULL &&
-+ strcmp(named_val->val_name, expect_val_name) != 0) {
- const char *msg = kutf_dsprintf(&context->fixture_pool,
- "Expecting to receive value named '%s' but got '%s'",
- expect_val_name, named_val->val_name);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_mem.c b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_mem.c
-index fd98bea..716970a 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_mem.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_mem.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* Kernel UTF memory management functions */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_resultset.c b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_resultset.c
-index 94ecfa4..c7572bd 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_resultset.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_resultset.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* Kernel UTF result management functions */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_suite.c b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_suite.c
-index 3f15669..6745299 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_suite.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_suite.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014, 2017-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2017-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,11 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* Kernel UTF suite, test and fixture management including user to kernel
-- * interaction */
-+ * interaction
-+ */
-
- #include <linux/list.h>
- #include <linux/slab.h>
-@@ -598,7 +598,7 @@ static int create_fixture_variant(struct kutf_test_function *test_func,
- goto fail_file;
- }
-
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
-+#if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE
- tmp = debugfs_create_file_unsafe(
- #else
- tmp = debugfs_create_file(
-@@ -634,7 +634,7 @@ static void kutf_remove_test_variant(struct kutf_test_fixture *test_fix)
- kfree(test_fix);
- }
-
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0)
-+#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE
- /* Adapting to the upstream debugfs_create_x32() change */
- static int ktufp_u32_get(void *data, u64 *val)
- {
-@@ -679,7 +679,7 @@ void kutf_add_test_with_filters_and_data(
- }
-
- test_func->filters = filters;
--#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0)
-+#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE
- tmp = debugfs_create_file_unsafe("filters", S_IROTH, test_func->dir,
- &test_func->filters, &kutfp_fops_x32_ro);
- #else
-@@ -692,12 +692,17 @@ void kutf_add_test_with_filters_and_data(
- }
-
- test_func->test_id = id;
-+#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE
-+ debugfs_create_u32("test_id", S_IROTH, test_func->dir,
-+ &test_func->test_id);
-+#else
- tmp = debugfs_create_u32("test_id", S_IROTH, test_func->dir,
- &test_func->test_id);
- if (!tmp) {
- pr_err("Failed to create debugfs file \"test_id\" when adding test %s\n", name);
- goto fail_file;
- }
-+#endif
-
- for (i = 0; i < suite->fixture_variants; i++) {
- if (create_fixture_variant(test_func, i)) {
-@@ -1153,7 +1158,7 @@ void kutf_test_abort(struct kutf_context *context)
- }
- EXPORT_SYMBOL(kutf_test_abort);
-
--#ifdef CONFIG_DEBUG_FS
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-
- /**
- * init_kutf_core() - Module entry point.
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_utils.c b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_utils.c
-index 7f5ac51..c0fb3ba 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_utils.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/kutf/kutf_utils.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2014, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /* Kernel UTF utility functions */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/Kbuild
-new file mode 100644
-index 0000000..027bc27
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/Kbuild
-@@ -0,0 +1,25 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2020-2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+ifeq ($(CONFIG_MALI_KUTF_CLK_RATE_TRACE),y)
-+obj-m += mali_kutf_clk_rate_trace_test_portal.o
-+
-+mali_kutf_clk_rate_trace_test_portal-y := mali_kutf_clk_rate_trace_test.o
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/build.bp b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/build.bp
-new file mode 100644
-index 0000000..225ad69
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/build.bp
-@@ -0,0 +1,43 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+bob_kernel_module {
-+ name: "mali_kutf_clk_rate_trace_test_portal",
-+ defaults: [
-+ "mali_kbase_shared_config_defaults",
-+ "kernel_test_configs",
-+ "kernel_test_includes",
-+ ],
-+ srcs: [
-+ "Kbuild",
-+ "mali_kutf_clk_rate_trace_test.c",
-+ "../mali_kutf_clk_rate_trace_test.h",
-+ ],
-+ extra_symbols: [
-+ "mali_kbase",
-+ "kutf",
-+ ],
-+ enabled: false,
-+ mali_kutf_clk_rate_trace: {
-+ kbuild_options: ["CONFIG_MALI_KUTF_CLK_RATE_TRACE=y"],
-+ enabled: true,
-+ },
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c
-new file mode 100644
-index 0000000..f9410a5
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c
-@@ -0,0 +1,957 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <linux/fdtable.h>
-+#include <linux/module.h>
-+
-+#include <linux/delay.h>
-+#include <linux/mutex.h>
-+#include <linux/ktime.h>
-+#include <linux/version.h>
-+#if (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE)
-+#include <linux/sched/task.h>
-+#else
-+#include <linux/sched.h>
-+#endif
-+#include "mali_kbase.h"
-+#include "backend/gpu/mali_kbase_irq_internal.h"
-+#include "backend/gpu/mali_kbase_pm_internal.h"
-+#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
-+
-+#include <kutf/kutf_suite.h>
-+#include <kutf/kutf_utils.h>
-+#include <kutf/kutf_helpers.h>
-+#include <kutf/kutf_helpers_user.h>
-+
-+#include "../mali_kutf_clk_rate_trace_test.h"
-+
-+#define MINOR_FOR_FIRST_KBASE_DEV (-1)
-+
-+/* KUTF test application pointer for this test */
-+struct kutf_application *kutf_app;
-+
-+enum portal_server_state {
-+ PORTAL_STATE_NO_CLK,
-+ PORTAL_STATE_LIVE,
-+ PORTAL_STATE_CLOSING,
-+};
-+
-+/**
-+ * struct clk_trace_snapshot - Trace info data on a clock.
-+ * @previous_rate: Snapshot start point clock rate.
-+ * @current_rate: End point clock rate. It becomes the start rate of the
-+ * next trace snapshot.
-+ * @rate_up_cnt: Count in the snapshot duration when the clock trace
-+ * write is a rate of higher value than the last.
-+ * @rate_down_cnt: Count in the snapshot duration when the clock trace write
-+ * is a rate of lower value than the last.
-+ */
-+struct clk_trace_snapshot {
-+ unsigned long previous_rate;
-+ unsigned long current_rate;
-+ u32 rate_up_cnt;
-+ u32 rate_down_cnt;
-+};
-+
-+/**
-+ * struct kutf_clk_rate_trace_fixture_data - Fixture data for the test.
-+ * @kbdev: kbase device for the GPU.
-+ * @listener: Clock rate change listener structure.
-+ * @invoke_notify: When true, invoke notify command is being executed.
-+ * @snapshot: Clock trace update snapshot data array. A snapshot
-+ * for each clock contains info accumulated beteen two
-+ * GET_TRACE_SNAPSHOT requests.
-+ * @nclks: Number of clocks visible to the trace portal.
-+ * @pm_ctx_cnt: Net count of PM (Power Management) context INC/DEC
-+ * PM_CTX_CNT requests made to the portal. On change from
-+ * 0 to 1 (INC), or, 1 to 0 (DEC), a PM context action is
-+ * triggered.
-+ * @total_update_cnt: Total number of received trace write callbacks.
-+ * @server_state: Portal server operational state.
-+ * @result_msg: Message for the test result.
-+ * @test_status: Portal test reslt status.
-+ */
-+struct kutf_clk_rate_trace_fixture_data {
-+ struct kbase_device *kbdev;
-+ struct kbase_clk_rate_listener listener;
-+ bool invoke_notify;
-+ struct clk_trace_snapshot snapshot[BASE_MAX_NR_CLOCKS_REGULATORS];
-+ unsigned int nclks;
-+ unsigned int pm_ctx_cnt;
-+ unsigned int total_update_cnt;
-+ enum portal_server_state server_state;
-+ char const *result_msg;
-+ enum kutf_result_status test_status;
-+};
-+
-+struct clk_trace_portal_input {
-+ struct kutf_helper_named_val cmd_input;
-+ enum kbasep_clk_rate_trace_req portal_cmd;
-+ int named_val_err;
-+};
-+
-+struct kbasep_cmd_name_pair {
-+ enum kbasep_clk_rate_trace_req cmd;
-+ const char *name;
-+};
-+
-+struct kbasep_cmd_name_pair kbasep_portal_cmd_name_map[] = {
-+ { PORTAL_CMD_GET_PLATFORM, GET_PLATFORM },
-+ { PORTAL_CMD_GET_CLK_RATE_MGR, GET_CLK_RATE_MGR },
-+ { PORTAL_CMD_GET_CLK_RATE_TRACE, GET_CLK_RATE_TRACE },
-+ { PORTAL_CMD_GET_TRACE_SNAPSHOT, GET_TRACE_SNAPSHOT },
-+ { PORTAL_CMD_INC_PM_CTX_CNT, INC_PM_CTX_CNT },
-+ { PORTAL_CMD_DEC_PM_CTX_CNT, DEC_PM_CTX_CNT },
-+ { PORTAL_CMD_CLOSE_PORTAL, CLOSE_PORTAL },
-+ { PORTAL_CMD_INVOKE_NOTIFY_42KHZ, INVOKE_NOTIFY_42KHZ },
-+};
-+
-+/* Global pointer for the kutf_portal_trace_write() to use. When
-+ * this pointer is engaged, new requests for create fixture will fail
-+ * hence limiting the use of the portal at any time to a singleton.
-+ */
-+struct kutf_clk_rate_trace_fixture_data *g_ptr_portal_data;
-+
-+#define PORTAL_MSG_LEN (KUTF_MAX_LINE_LENGTH - MAX_REPLY_NAME_LEN)
-+static char portal_msg_buf[PORTAL_MSG_LEN];
-+
-+static void kutf_portal_trace_write(
-+ struct kbase_clk_rate_listener *listener,
-+ u32 index, u32 new_rate)
-+{
-+ struct clk_trace_snapshot *snapshot;
-+ struct kutf_clk_rate_trace_fixture_data *data;
-+
-+ if (listener == NULL) {
-+ pr_err("%s - index: %u, new_rate: %u, listener is NULL\n",
-+ __func__, index, new_rate);
-+ return;
-+ }
-+
-+ data = container_of(listener, struct kutf_clk_rate_trace_fixture_data,
-+ listener);
-+
-+ lockdep_assert_held(&data->kbdev->pm.clk_rtm.lock);
-+
-+ if (WARN_ON(g_ptr_portal_data == NULL))
-+ return;
-+ if (WARN_ON(index >= g_ptr_portal_data->nclks))
-+ return;
-+
-+ /* This callback is triggered by invoke notify command, skipping */
-+ if (data->invoke_notify)
-+ return;
-+
-+ snapshot = &g_ptr_portal_data->snapshot[index];
-+ if (new_rate > snapshot->current_rate)
-+ snapshot->rate_up_cnt++;
-+ else
-+ snapshot->rate_down_cnt++;
-+ snapshot->current_rate = new_rate;
-+ g_ptr_portal_data->total_update_cnt++;
-+}
-+
-+static void kutf_set_pm_ctx_active(struct kutf_context *context)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+
-+ if (WARN_ON(data->pm_ctx_cnt != 1))
-+ return;
-+
-+ kbase_pm_context_active(data->kbdev);
-+ kbase_pm_wait_for_desired_state(data->kbdev);
-+#if !MALI_USE_CSF
-+ kbase_pm_request_gpu_cycle_counter(data->kbdev);
-+#endif
-+}
-+
-+static void kutf_set_pm_ctx_idle(struct kutf_context *context)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+
-+ if (WARN_ON(data->pm_ctx_cnt > 0))
-+ return;
-+#if !MALI_USE_CSF
-+ kbase_pm_release_gpu_cycle_counter(data->kbdev);
-+#endif
-+ kbase_pm_context_idle(data->kbdev);
-+}
-+
-+static char const *kutf_clk_trace_do_change_pm_ctx(struct kutf_context *context,
-+ struct clk_trace_portal_input *cmd)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+ int seq = cmd->cmd_input.u.val_u64 & 0xFF;
-+ const unsigned int cnt = data->pm_ctx_cnt;
-+ const enum kbasep_clk_rate_trace_req req = cmd->portal_cmd;
-+ char const *errmsg = NULL;
-+
-+ WARN_ON(req != PORTAL_CMD_INC_PM_CTX_CNT &&
-+ req != PORTAL_CMD_DEC_PM_CTX_CNT);
-+
-+ if (req == PORTAL_CMD_INC_PM_CTX_CNT && cnt < UINT_MAX) {
-+ data->pm_ctx_cnt++;
-+ if (data->pm_ctx_cnt == 1)
-+ kutf_set_pm_ctx_active(context);
-+ }
-+
-+ if (req == PORTAL_CMD_DEC_PM_CTX_CNT && cnt > 0) {
-+ data->pm_ctx_cnt--;
-+ if (data->pm_ctx_cnt == 0)
-+ kutf_set_pm_ctx_idle(context);
-+ }
-+
-+ /* Skip the length check, no chance of overflow for two ints */
-+ snprintf(portal_msg_buf, PORTAL_MSG_LEN,
-+ "{SEQ:%d, PM_CTX_CNT:%u}", seq, data->pm_ctx_cnt);
-+
-+ if (kutf_helper_send_named_str(context, "ACK", portal_msg_buf)) {
-+ pr_warn("Error in sending ack for adjusting pm_ctx_cnt\n");
-+ errmsg = kutf_dsprintf(&context->fixture_pool,
-+ "Error in sending ack for adjusting pm_ctx_cnt");
-+ }
-+
-+ return errmsg;
-+}
-+
-+static char const *kutf_clk_trace_do_get_rate(struct kutf_context *context,
-+ struct clk_trace_portal_input *cmd)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+ struct kbase_device *kbdev = data->kbdev;
-+ int seq = cmd->cmd_input.u.val_u64 & 0xFF;
-+ unsigned long rate;
-+ bool idle;
-+ int ret;
-+ int i;
-+ char const *errmsg = NULL;
-+
-+ WARN_ON((cmd->portal_cmd != PORTAL_CMD_GET_CLK_RATE_MGR) &&
-+ (cmd->portal_cmd != PORTAL_CMD_GET_CLK_RATE_TRACE));
-+
-+ ret = snprintf(portal_msg_buf, PORTAL_MSG_LEN,
-+ "{SEQ:%d, RATE:[", seq);
-+
-+ for (i = 0; i < data->nclks; i++) {
-+ spin_lock(&kbdev->pm.clk_rtm.lock);
-+ if (cmd->portal_cmd == PORTAL_CMD_GET_CLK_RATE_MGR)
-+ rate = kbdev->pm.clk_rtm.clks[i]->clock_val;
-+ else
-+ rate = data->snapshot[i].current_rate;
-+ idle = kbdev->pm.clk_rtm.gpu_idle;
-+ spin_unlock(&kbdev->pm.clk_rtm.lock);
-+
-+ if ((i + 1) == data->nclks)
-+ ret += snprintf(portal_msg_buf + ret,
-+ PORTAL_MSG_LEN - ret, "0x%lx], GPU_IDLE:%d}",
-+ rate, idle);
-+ else
-+ ret += snprintf(portal_msg_buf + ret,
-+ PORTAL_MSG_LEN - ret, "0x%lx, ", rate);
-+
-+ if (ret >= PORTAL_MSG_LEN) {
-+ pr_warn("Message buf overflow with rate array data\n");
-+ return kutf_dsprintf(&context->fixture_pool,
-+ "Message buf overflow with rate array data");
-+ }
-+ }
-+
-+ if (kutf_helper_send_named_str(context, "ACK", portal_msg_buf)) {
-+ pr_warn("Error in sending back rate array\n");
-+ errmsg = kutf_dsprintf(&context->fixture_pool,
-+ "Error in sending rate array");
-+ }
-+
-+ return errmsg;
-+}
-+
-+/**
-+ * kutf_clk_trace_do_get_snapshot() - Send back the current snapshot
-+ * @context: KUTF context
-+ * @cmd: The decoded portal input request
-+ *
-+ * The accumulated clock rate trace information is kept inside as an snapshot
-+ * record. A user request of getting the snapshot marks the closure of the
-+ * current snapshot record, and the start of the next one. The response
-+ * message contains the current snapshot record, with each clock's
-+ * data sequentially placed inside (array marker) [ ].
-+ */
-+static char const *kutf_clk_trace_do_get_snapshot(struct kutf_context *context,
-+ struct clk_trace_portal_input *cmd)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+ struct clk_trace_snapshot snapshot;
-+ int seq = cmd->cmd_input.u.val_u64 & 0xFF;
-+ int ret;
-+ int i;
-+ char const *fmt;
-+ char const *errmsg = NULL;
-+
-+ WARN_ON(cmd->portal_cmd != PORTAL_CMD_GET_TRACE_SNAPSHOT);
-+
-+ ret = snprintf(portal_msg_buf, PORTAL_MSG_LEN,
-+ "{SEQ:%d, SNAPSHOT_ARRAY:[", seq);
-+
-+ for (i = 0; i < data->nclks; i++) {
-+ spin_lock(&data->kbdev->pm.clk_rtm.lock);
-+ /* copy out the snapshot of the clock */
-+ snapshot = data->snapshot[i];
-+ /* Set the next snapshot start condition */
-+ data->snapshot[i].previous_rate = snapshot.current_rate;
-+ data->snapshot[i].rate_up_cnt = 0;
-+ data->snapshot[i].rate_down_cnt = 0;
-+ spin_unlock(&data->kbdev->pm.clk_rtm.lock);
-+
-+ /* Check i corresponding to the last clock */
-+ if ((i + 1) == data->nclks)
-+ fmt = "(0x%lx, 0x%lx, %u, %u)]}";
-+ else
-+ fmt = "(0x%lx, 0x%lx, %u, %u), ";
-+ ret += snprintf(portal_msg_buf + ret, PORTAL_MSG_LEN - ret,
-+ fmt, snapshot.previous_rate, snapshot.current_rate,
-+ snapshot.rate_up_cnt, snapshot.rate_down_cnt);
-+ if (ret >= PORTAL_MSG_LEN) {
-+ pr_warn("Message buf overflow with snapshot data\n");
-+ return kutf_dsprintf(&context->fixture_pool,
-+ "Message buf overflow with snapshot data");
-+ }
-+ }
-+
-+ if (kutf_helper_send_named_str(context, "ACK", portal_msg_buf)) {
-+ pr_warn("Error in sending back snapshot array\n");
-+ errmsg = kutf_dsprintf(&context->fixture_pool,
-+ "Error in sending snapshot array");
-+ }
-+
-+ return errmsg;
-+}
-+
-+/**
-+ * kutf_clk_trace_do_invoke_notify_42k() - Invokes the stored notification callback
-+ * @context: KUTF context
-+ * @cmd: The decoded portal input request
-+ *
-+ * Invokes frequency change notification callbacks with a fake
-+ * GPU frequency 42 kHz for the top clock domain.
-+ */
-+static char const *kutf_clk_trace_do_invoke_notify_42k(
-+ struct kutf_context *context,
-+ struct clk_trace_portal_input *cmd)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+ int seq = cmd->cmd_input.u.val_u64 & 0xFF;
-+ const unsigned long new_rate_hz = 42000;
-+ int ret;
-+ char const *errmsg = NULL;
-+ struct kbase_clk_rate_trace_manager *clk_rtm = &data->kbdev->pm.clk_rtm;
-+
-+ WARN_ON(cmd->portal_cmd != PORTAL_CMD_INVOKE_NOTIFY_42KHZ);
-+
-+ spin_lock(&clk_rtm->lock);
-+
-+ data->invoke_notify = true;
-+ kbase_clk_rate_trace_manager_notify_all(
-+ clk_rtm, 0, new_rate_hz);
-+ data->invoke_notify = false;
-+
-+ spin_unlock(&clk_rtm->lock);
-+
-+ ret = snprintf(portal_msg_buf, PORTAL_MSG_LEN,
-+ "{SEQ:%d, HZ:%lu}", seq, new_rate_hz);
-+
-+ if (ret >= PORTAL_MSG_LEN) {
-+ pr_warn("Message buf overflow with invoked data\n");
-+ return kutf_dsprintf(&context->fixture_pool,
-+ "Message buf overflow with invoked data");
-+ }
-+
-+ if (kutf_helper_send_named_str(context, "ACK", portal_msg_buf)) {
-+ pr_warn("Error in sending ack for " INVOKE_NOTIFY_42KHZ "request\n");
-+ errmsg = kutf_dsprintf(&context->fixture_pool,
-+ "Error in sending ack for " INVOKE_NOTIFY_42KHZ "request");
-+ }
-+
-+ return errmsg;
-+}
-+
-+static char const *kutf_clk_trace_do_close_portal(struct kutf_context *context,
-+ struct clk_trace_portal_input *cmd)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+ int seq = cmd->cmd_input.u.val_u64 & 0xFF;
-+ char const *errmsg = NULL;
-+
-+ WARN_ON(cmd->portal_cmd != PORTAL_CMD_CLOSE_PORTAL);
-+
-+ data->server_state = PORTAL_STATE_CLOSING;
-+
-+ /* Skip the length check, no chance of overflow for two ints */
-+ snprintf(portal_msg_buf, PORTAL_MSG_LEN,
-+ "{SEQ:%d, PM_CTX_CNT:%u}", seq, data->pm_ctx_cnt);
-+
-+ if (kutf_helper_send_named_str(context, "ACK", portal_msg_buf)) {
-+ pr_warn("Error in sending ack for " CLOSE_PORTAL "reuquest\n");
-+ errmsg = kutf_dsprintf(&context->fixture_pool,
-+ "Error in sending ack for " CLOSE_PORTAL "reuquest");
-+ }
-+
-+ return errmsg;
-+}
-+
-+/**
-+ * kutf_clk_trace_do_get_platform() - Gets platform information
-+ * @context: KUTF context
-+ * @cmd: The decoded portal input request
-+ *
-+ * Checks the gpu node in the device tree to see if arbitration is enabled
-+ * If so determines device tree whether platform is PV or PTM
-+ *
-+ * Return: A string to indicate the platform (PV/PTM/GPU/UNKNOWN)
-+ */
-+static char const *kutf_clk_trace_do_get_platform(
-+ struct kutf_context *context,
-+ struct clk_trace_portal_input *cmd)
-+{
-+ int seq = cmd->cmd_input.u.val_u64 & 0xFF;
-+ char const *errmsg = NULL;
-+ const void *arbiter_if_node = NULL;
-+ const void *power_node = NULL;
-+ const char *platform = "GPU";
-+#if defined(CONFIG_MALI_ARBITER_SUPPORT) && defined(CONFIG_OF)
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+
-+ arbiter_if_node =
-+ of_get_property(data->kbdev->dev->of_node, "arbiter_if", NULL);
-+#endif
-+ if (arbiter_if_node) {
-+ power_node = of_find_compatible_node(NULL, NULL,
-+ "arm,mali-gpu-power");
-+ if (power_node) {
-+ platform = "PV";
-+ } else {
-+ power_node = of_find_compatible_node(NULL, NULL,
-+ "arm,mali-ptm");
-+ if (power_node)
-+ platform = "PTM";
-+ else
-+ platform = "UNKNOWN";
-+ }
-+ } else {
-+ platform = "GPU";
-+ }
-+
-+ pr_debug("%s - platform is %s\n", __func__, platform);
-+ snprintf(portal_msg_buf, PORTAL_MSG_LEN,
-+ "{SEQ:%d, PLATFORM:%s}", seq, platform);
-+
-+ WARN_ON(cmd->portal_cmd != PORTAL_CMD_GET_PLATFORM);
-+
-+ if (kutf_helper_send_named_str(context, "ACK", portal_msg_buf)) {
-+ pr_warn("Error in sending ack for " CLOSE_PORTAL "reuquest\n");
-+ errmsg = kutf_dsprintf(&context->fixture_pool,
-+ "Error in sending ack for " GET_PLATFORM "request");
-+ }
-+
-+ return errmsg;
-+}
-+
-+static bool kutf_clk_trace_dequeue_portal_cmd(struct kutf_context *context,
-+ struct clk_trace_portal_input *cmd)
-+{
-+ int i;
-+ int err = kutf_helper_receive_named_val(context, &cmd->cmd_input);
-+
-+ cmd->named_val_err = err;
-+ if (err == KUTF_HELPER_ERR_NONE &&
-+ cmd->cmd_input.type == KUTF_HELPER_VALTYPE_U64) {
-+ /* All portal request commands are of format (named u64):
-+ * CMD_NAME=1234
-+ * where, 1234 is a (variable) sequence number tag.
-+ */
-+ for (i = 0; i < PORTAL_TOTAL_CMDS; i++) {
-+ if (strcmp(cmd->cmd_input.val_name,
-+ kbasep_portal_cmd_name_map[i].name))
-+ continue;
-+
-+ cmd->portal_cmd = kbasep_portal_cmd_name_map[i].cmd;
-+ return true;
-+ }
-+ }
-+
-+ cmd->portal_cmd = PORTAL_CMD_INVALID;
-+ return false;
-+}
-+
-+static void kutf_clk_trace_flag_result(struct kutf_context *context,
-+ enum kutf_result_status result, char const *msg)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+
-+ if (result > data->test_status) {
-+ data->test_status = result;
-+ if (msg)
-+ data->result_msg = msg;
-+ if (data->server_state == PORTAL_STATE_LIVE &&
-+ result > KUTF_RESULT_WARN) {
-+ data->server_state = PORTAL_STATE_CLOSING;
-+ }
-+ }
-+}
-+
-+static bool kutf_clk_trace_process_portal_cmd(struct kutf_context *context,
-+ struct clk_trace_portal_input *cmd)
-+{
-+ char const *errmsg = NULL;
-+
-+ BUILD_BUG_ON(ARRAY_SIZE(kbasep_portal_cmd_name_map) !=
-+ PORTAL_TOTAL_CMDS);
-+ WARN_ON(cmd->portal_cmd == PORTAL_CMD_INVALID);
-+
-+ switch (cmd->portal_cmd) {
-+ case PORTAL_CMD_GET_PLATFORM:
-+ errmsg = kutf_clk_trace_do_get_platform(context, cmd);
-+ break;
-+ case PORTAL_CMD_GET_CLK_RATE_MGR:
-+ /* Fall through */
-+ case PORTAL_CMD_GET_CLK_RATE_TRACE:
-+ errmsg = kutf_clk_trace_do_get_rate(context, cmd);
-+ break;
-+ case PORTAL_CMD_GET_TRACE_SNAPSHOT:
-+ errmsg = kutf_clk_trace_do_get_snapshot(context, cmd);
-+ break;
-+ case PORTAL_CMD_INC_PM_CTX_CNT:
-+ /* Fall through */
-+ case PORTAL_CMD_DEC_PM_CTX_CNT:
-+ errmsg = kutf_clk_trace_do_change_pm_ctx(context, cmd);
-+ break;
-+ case PORTAL_CMD_CLOSE_PORTAL:
-+ errmsg = kutf_clk_trace_do_close_portal(context, cmd);
-+ break;
-+ case PORTAL_CMD_INVOKE_NOTIFY_42KHZ:
-+ errmsg = kutf_clk_trace_do_invoke_notify_42k(context, cmd);
-+ break;
-+ default:
-+ pr_warn("Don't know how to handle portal_cmd: %d, abort session.\n",
-+ cmd->portal_cmd);
-+ errmsg = kutf_dsprintf(&context->fixture_pool,
-+ "Don't know how to handle portal_cmd: %d",
-+ cmd->portal_cmd);
-+ break;
-+ }
-+
-+ if (errmsg)
-+ kutf_clk_trace_flag_result(context, KUTF_RESULT_FAIL, errmsg);
-+
-+ return (errmsg == NULL);
-+}
-+
-+/**
-+ * kutf_clk_trace_do_nack_response() - respond a NACK to erroneous input
-+ * @context: KUTF context
-+ * @cmd: The erroneous input request
-+ *
-+ * This function deal with an erroneous input request, and respond with
-+ * a proper 'NACK' message.
-+ */
-+static int kutf_clk_trace_do_nack_response(struct kutf_context *context,
-+ struct clk_trace_portal_input *cmd)
-+{
-+ int seq;
-+ int err;
-+ char const *errmsg = NULL;
-+
-+ WARN_ON(cmd->portal_cmd != PORTAL_CMD_INVALID);
-+
-+ if (cmd->named_val_err == KUTF_HELPER_ERR_NONE &&
-+ cmd->cmd_input.type == KUTF_HELPER_VALTYPE_U64) {
-+ /* Keep seq number as % 256 */
-+ seq = cmd->cmd_input.u.val_u64 & 255;
-+ snprintf(portal_msg_buf, PORTAL_MSG_LEN,
-+ "{SEQ:%d, MSG: Unknown command '%s'.}", seq,
-+ cmd->cmd_input.val_name);
-+ err = kutf_helper_send_named_str(context, "NACK",
-+ portal_msg_buf);
-+ } else
-+ err = kutf_helper_send_named_str(context, "NACK",
-+ "Wrong portal cmd format (Ref example: CMD_NAME=0X16)");
-+
-+ if (err) {
-+ errmsg = kutf_dsprintf(&context->fixture_pool,
-+ "Failed to send portal NACK response");
-+ kutf_clk_trace_flag_result(context, KUTF_RESULT_FAIL, errmsg);
-+ }
-+
-+ return err;
-+}
-+
-+/**
-+ * kutf_clk_trace_barebone_check() - Sanity test on the clock tracing
-+ * @context: KUTF context
-+ *
-+ * This function carries out some basic test on the tracing operation:
-+ * 1). GPU idle on test start, trace rate should be 0 (low power state)
-+ * 2). Make sure GPU is powered up, the trace rate should match
-+ * that from the clcok manager's internal recorded rate
-+ * 3). If the GPU active transition occurs following 2), there
-+ * must be rate change event from tracing.
-+ */
-+void kutf_clk_trace_barebone_check(struct kutf_context *context)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+ struct kbase_device *kbdev = data->kbdev;
-+ bool fail = false;
-+ bool idle[2] = { false };
-+ char const *msg = NULL;
-+ int i;
-+
-+ /* Check consistency if gpu happens to be idle */
-+ spin_lock(&kbdev->pm.clk_rtm.lock);
-+ idle[0] = kbdev->pm.clk_rtm.gpu_idle;
-+ if (kbdev->pm.clk_rtm.gpu_idle) {
-+ for (i = 0; i < data->nclks; i++) {
-+ if (data->snapshot[i].current_rate) {
-+ /* Idle should have a rate 0 */
-+ fail = true;
-+ break;
-+ }
-+ }
-+ }
-+ spin_unlock(&kbdev->pm.clk_rtm.lock);
-+ if (fail) {
-+ msg = kutf_dsprintf(&context->fixture_pool,
-+ "GPU Idle not yielding 0-rate");
-+ pr_err("Trace did not see idle rate\n");
-+ } else {
-+ /* Make local PM active if not done so yet */
-+ if (data->pm_ctx_cnt == 0) {
-+ /* Ensure the GPU is powered */
-+ data->pm_ctx_cnt++;
-+ kutf_set_pm_ctx_active(context);
-+ }
-+ /* Checking the rate is consistent */
-+ spin_lock(&kbdev->pm.clk_rtm.lock);
-+ idle[1] = kbdev->pm.clk_rtm.gpu_idle;
-+ for (i = 0; i < data->nclks; i++) {
-+ /* Rate match between the manager and the trace */
-+ if (kbdev->pm.clk_rtm.clks[i]->clock_val !=
-+ data->snapshot[i].current_rate) {
-+ fail = true;
-+ break;
-+ }
-+ }
-+ spin_unlock(&kbdev->pm.clk_rtm.lock);
-+
-+ if (idle[1]) {
-+ msg = kutf_dsprintf(&context->fixture_pool,
-+ "GPU still idle after set_pm_ctx_active");
-+ pr_err("GPU still idle after set_pm_ctx_active\n");
-+ }
-+
-+ if (!msg && fail) {
-+ msg = kutf_dsprintf(&context->fixture_pool,
-+ "Trace rate not matching Clk manager's read");
-+ pr_err("Trace rate not matching Clk manager's read\n");
-+ }
-+ }
-+
-+ if (!msg && idle[0] && !idle[1] && !data->total_update_cnt) {
-+ msg = kutf_dsprintf(&context->fixture_pool,
-+ "Trace update did not occur");
-+ pr_err("Trace update did not occur\n");
-+ }
-+ if (msg)
-+ kutf_clk_trace_flag_result(context, KUTF_RESULT_FAIL, msg);
-+ else if (!data->total_update_cnt) {
-+ msg = kutf_dsprintf(&context->fixture_pool,
-+ "No trace update seen during the test!");
-+ kutf_clk_trace_flag_result(context, KUTF_RESULT_WARN, msg);
-+ }
-+}
-+
-+static bool kutf_clk_trace_end_of_stream(struct clk_trace_portal_input *cmd)
-+{
-+ return (cmd->named_val_err == -EBUSY);
-+}
-+
-+void kutf_clk_trace_no_clks_dummy(struct kutf_context *context)
-+{
-+ struct clk_trace_portal_input cmd;
-+ unsigned long timeout = jiffies + HZ * 2;
-+ bool has_cmd;
-+
-+ while (time_before(jiffies, timeout)) {
-+ if (kutf_helper_pending_input(context)) {
-+ has_cmd = kutf_clk_trace_dequeue_portal_cmd(context,
-+ &cmd);
-+ if (!has_cmd && kutf_clk_trace_end_of_stream(&cmd))
-+ break;
-+
-+ kutf_helper_send_named_str(context, "NACK",
-+ "Fatal! No clocks visible, aborting");
-+ }
-+ msleep(20);
-+ }
-+
-+ kutf_clk_trace_flag_result(context, KUTF_RESULT_FATAL,
-+ "No clocks visble to the portal");
-+}
-+
-+/**
-+ * mali_kutf_clk_rate_trace_test_portal() - Service portal input
-+ * @context: KUTF context
-+ *
-+ * The test portal operates on input requests. If the input request is one
-+ * of the recognized portal commands, it handles it accordingly. Otherwise
-+ * a negative response 'NACK' is returned. The portal service terminates
-+ * when a 'CLOSE_PORTAL' request is received, or due to an internal error.
-+ * Both case would result in the server_state transitioned to CLOSING.
-+ *
-+ * If the portal is closed on request, a sanity test on the clock rate
-+ * trace operation is undertaken via function:
-+ * kutf_clk_trace_barebone_check();
-+ */
-+static void mali_kutf_clk_rate_trace_test_portal(struct kutf_context *context)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+ struct clk_trace_portal_input new_cmd;
-+
-+ pr_debug("Test portal service start\n");
-+
-+ while (data->server_state == PORTAL_STATE_LIVE) {
-+ if (kutf_clk_trace_dequeue_portal_cmd(context, &new_cmd))
-+ kutf_clk_trace_process_portal_cmd(context, &new_cmd);
-+ else if (kutf_clk_trace_end_of_stream(&new_cmd))
-+ /* Dequeue on portal input, end of stream */
-+ data->server_state = PORTAL_STATE_CLOSING;
-+ else
-+ kutf_clk_trace_do_nack_response(context, &new_cmd);
-+ }
-+
-+ /* Closing, exhausting all the pending inputs with NACKs. */
-+ if (data->server_state == PORTAL_STATE_CLOSING) {
-+ while (kutf_helper_pending_input(context) &&
-+ (kutf_clk_trace_dequeue_portal_cmd(context, &new_cmd) ||
-+ !kutf_clk_trace_end_of_stream(&new_cmd))) {
-+ kutf_helper_send_named_str(context, "NACK",
-+ "Portal closing down");
-+ }
-+ }
-+
-+ /* If no portal error, do a barebone test here irrespective
-+ * whatever the portal live session has been testing, which
-+ * is entirely driven by the user-side via portal requests.
-+ */
-+ if (data->test_status <= KUTF_RESULT_WARN) {
-+ if (data->server_state != PORTAL_STATE_NO_CLK)
-+ kutf_clk_trace_barebone_check(context);
-+ else {
-+ /* No clocks case, NACK 2-sec for the fatal situation */
-+ kutf_clk_trace_no_clks_dummy(context);
-+ }
-+ }
-+
-+ /* If we have changed pm_ctx count, drop it back */
-+ if (data->pm_ctx_cnt) {
-+ /* Although we count on portal requests, it only has material
-+ * impact when from 0 -> 1. So the reverse is a simple one off.
-+ */
-+ data->pm_ctx_cnt = 0;
-+ kutf_set_pm_ctx_idle(context);
-+ }
-+
-+ /* Finally log the test result line */
-+ if (data->test_status < KUTF_RESULT_WARN)
-+ kutf_test_pass(context, data->result_msg);
-+ else if (data->test_status == KUTF_RESULT_WARN)
-+ kutf_test_warn(context, data->result_msg);
-+ else if (data->test_status == KUTF_RESULT_FATAL)
-+ kutf_test_fatal(context, data->result_msg);
-+ else
-+ kutf_test_fail(context, data->result_msg);
-+
-+ pr_debug("Test end\n");
-+}
-+
-+/**
-+ * mali_kutf_clk_rate_trace_create_fixture() - Creates the fixture data
-+ * required for mali_kutf_clk_rate_trace_test_portal.
-+ * @context: KUTF context.
-+ *
-+ * Return: Fixture data created on success or NULL on failure
-+ */
-+static void *mali_kutf_clk_rate_trace_create_fixture(
-+ struct kutf_context *context)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data;
-+ struct kbase_device *kbdev;
-+ unsigned long rate;
-+ int i;
-+
-+ /* Acquire the kbase device */
-+ pr_debug("Finding device\n");
-+ kbdev = kbase_find_device(MINOR_FOR_FIRST_KBASE_DEV);
-+ if (kbdev == NULL) {
-+ kutf_test_fail(context, "Failed to find kbase device");
-+ return NULL;
-+ }
-+
-+ pr_debug("Creating fixture\n");
-+ data = kutf_mempool_alloc(&context->fixture_pool,
-+ sizeof(struct kutf_clk_rate_trace_fixture_data));
-+ if (!data)
-+ return NULL;
-+
-+ *data = (const struct kutf_clk_rate_trace_fixture_data) { 0 };
-+ pr_debug("Hooking up the test portal to kbdev clk rate trace\n");
-+ spin_lock(&kbdev->pm.clk_rtm.lock);
-+
-+ if (g_ptr_portal_data != NULL) {
-+ pr_warn("Test portal is already in use, run aborted\n");
-+ kutf_test_fail(context, "Portal allows single session only");
-+ spin_unlock(&kbdev->pm.clk_rtm.lock);
-+ return NULL;
-+ }
-+
-+ for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) {
-+ if (kbdev->pm.clk_rtm.clks[i]) {
-+ data->nclks++;
-+ if (kbdev->pm.clk_rtm.gpu_idle)
-+ rate = 0;
-+ else
-+ rate = kbdev->pm.clk_rtm.clks[i]->clock_val;
-+ data->snapshot[i].previous_rate = rate;
-+ data->snapshot[i].current_rate = rate;
-+ }
-+ }
-+
-+ spin_unlock(&kbdev->pm.clk_rtm.lock);
-+
-+ if (data->nclks) {
-+ /* Subscribe this test server portal */
-+ data->listener.notify = kutf_portal_trace_write;
-+ data->invoke_notify = false;
-+
-+ kbase_clk_rate_trace_manager_subscribe(
-+ &kbdev->pm.clk_rtm, &data->listener);
-+ /* Update the kutf_server_portal fixture_data pointer */
-+ g_ptr_portal_data = data;
-+ }
-+
-+ data->kbdev = kbdev;
-+ data->result_msg = NULL;
-+ data->test_status = KUTF_RESULT_PASS;
-+
-+ if (data->nclks == 0) {
-+ data->server_state = PORTAL_STATE_NO_CLK;
-+ pr_debug("Kbdev has no clocks for rate trace");
-+ } else
-+ data->server_state = PORTAL_STATE_LIVE;
-+
-+ pr_debug("Created fixture\n");
-+
-+ return data;
-+}
-+
-+/**
-+ * Destroy fixture data previously created by
-+ * mali_kutf_clk_rate_trace_create_fixture.
-+ *
-+ * @context: KUTF context.
-+ */
-+static void mali_kutf_clk_rate_trace_remove_fixture(
-+ struct kutf_context *context)
-+{
-+ struct kutf_clk_rate_trace_fixture_data *data = context->fixture;
-+ struct kbase_device *kbdev = data->kbdev;
-+
-+ if (data->nclks) {
-+ /* Clean up the portal trace write arrangement */
-+ g_ptr_portal_data = NULL;
-+
-+ kbase_clk_rate_trace_manager_unsubscribe(
-+ &kbdev->pm.clk_rtm, &data->listener);
-+ }
-+ pr_debug("Destroying fixture\n");
-+ kbase_release_device(kbdev);
-+ pr_debug("Destroyed fixture\n");
-+}
-+
-+/**
-+ * mali_kutf_clk_rate_trace_test_module_init() - Entry point for test mdoule.
-+ */
-+int mali_kutf_clk_rate_trace_test_module_init(void)
-+{
-+ struct kutf_suite *suite;
-+ unsigned int filters;
-+ union kutf_callback_data suite_data = { 0 };
-+
-+ pr_debug("Creating app\n");
-+
-+ g_ptr_portal_data = NULL;
-+ kutf_app = kutf_create_application(CLK_RATE_TRACE_APP_NAME);
-+
-+ if (!kutf_app) {
-+ pr_warn("Creation of app " CLK_RATE_TRACE_APP_NAME
-+ " failed!\n");
-+ return -ENOMEM;
-+ }
-+
-+ pr_debug("Create suite %s\n", CLK_RATE_TRACE_SUITE_NAME);
-+ suite = kutf_create_suite_with_filters_and_data(
-+ kutf_app, CLK_RATE_TRACE_SUITE_NAME, 1,
-+ mali_kutf_clk_rate_trace_create_fixture,
-+ mali_kutf_clk_rate_trace_remove_fixture,
-+ KUTF_F_TEST_GENERIC,
-+ suite_data);
-+
-+ if (!suite) {
-+ pr_warn("Creation of suite %s failed!\n",
-+ CLK_RATE_TRACE_SUITE_NAME);
-+ kutf_destroy_application(kutf_app);
-+ return -ENOMEM;
-+ }
-+
-+ filters = suite->suite_default_flags;
-+ kutf_add_test_with_filters(
-+ suite, 0x0, CLK_RATE_TRACE_PORTAL,
-+ mali_kutf_clk_rate_trace_test_portal,
-+ filters);
-+
-+ pr_debug("Init complete\n");
-+ return 0;
-+}
-+
-+/**
-+ * mali_kutf_clk_rate_trace_test_module_exit() - Module exit point for this
-+ * test.
-+ */
-+void mali_kutf_clk_rate_trace_test_module_exit(void)
-+{
-+ pr_debug("Exit start\n");
-+ kutf_destroy_application(kutf_app);
-+ pr_debug("Exit complete\n");
-+}
-+
-+
-+module_init(mali_kutf_clk_rate_trace_test_module_init);
-+module_exit(mali_kutf_clk_rate_trace_test_module_exit);
-+
-+MODULE_LICENSE("GPL");
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/mali_kutf_clk_rate_trace_test.h b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/mali_kutf_clk_rate_trace_test.h
-new file mode 100644
-index 0000000..f37efa8
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_clk_rate_trace/mali_kutf_clk_rate_trace_test.h
-@@ -0,0 +1,151 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _KUTF_CLK_RATE_TRACE_TEST_H_
-+#define _KUTF_CLK_RATE_TRACE_TEST_H_
-+
-+#define CLK_RATE_TRACE_APP_NAME "clk_rate_trace"
-+#define CLK_RATE_TRACE_SUITE_NAME "rate_trace"
-+#define CLK_RATE_TRACE_PORTAL "portal"
-+
-+/**
-+ * enum kbasep_clk_rate_trace_req - request command to the clock rate trace
-+ * service portal.
-+ *
-+ * @PORTAL_CMD_GET_PLATFORM: Request the platform that the tests are
-+ * to be run on.
-+ * @PORTAL_CMD_GET_CLK_RATE_MGR: Request the clock trace manager internal
-+ * data record. On a positive acknowledgement
-+ * the prevailing clock rates and the GPU idle
-+ * condition flag are returned.
-+ * @PORTAL_CMD_GET_CLK_RATE_TRACE: Request the clock trace portal to return its
-+ * data record. On a positive acknowledgement
-+ * the last trace recorded clock rates and the
-+ * GPU idle condition flag are returned.
-+ * @PORTAL_CMD_GET_TRACE_SNAPSHOT: Request the clock trace portal to return its
-+ * current snapshot data record. On a positive
-+ * acknowledgement the snapshot array matching
-+ * the number of clocks are returned. It also
-+ * starts a fresh snapshot inside the clock
-+ * trace portal.
-+ * @PORTAL_CMD_INC_PM_CTX_CNT: Request the clock trace portal to increase
-+ * its internal PM_CTX_COUNT. If this increase
-+ * yielded a count of 0 -> 1 change, the portal
-+ * will initiate a PM_CTX_ACTIVE call to the
-+ * Kbase power management. Futher increase
-+ * requests will limit to only affect the
-+ * portal internal count value.
-+ * @PORTAL_CMD_DEC_PM_CTX_CNT: Request the clock trace portal to decrease
-+ * its internal PM_CTX_COUNT. If this decrease
-+ * yielded a count of 1 -> 0 change, the portal
-+ * will initiate a PM_CTX_IDLE call to the
-+ * Kbase power management.
-+ * @PORTAL_CMD_CLOSE_PORTAL: Inform the clock trace portal service the
-+ * client has completed its session. The portal
-+ * will start the close down action. If no
-+ * error has occurred during the dynamic
-+ * interactive session, an inherent basic test
-+ * carrying out some sanity check on the clock
-+ * trace is undertaken.
-+ * @PORTAL_CMD_INVOKE_NOTIFY_42KHZ: Invokes all clock rate trace manager callbacks
-+ * for the top clock domain with a new GPU frequency
-+ * set to 42 kHZ.
-+ * @PORTAL_CMD_INVALID: Valid commands termination marker. Must be
-+ * the highest enumeration value, as it
-+ * represents valid command array size.
-+ * @PORTAL_TOTAL_CMDS: Alias of PORTAL_CMD_INVALID.
-+ */
-+/* PORTAL_CMD_INVALID must be the last one, serving the size */
-+enum kbasep_clk_rate_trace_req {
-+ PORTAL_CMD_GET_PLATFORM,
-+ PORTAL_CMD_GET_CLK_RATE_MGR,
-+ PORTAL_CMD_GET_CLK_RATE_TRACE,
-+ PORTAL_CMD_GET_TRACE_SNAPSHOT,
-+ PORTAL_CMD_INC_PM_CTX_CNT,
-+ PORTAL_CMD_DEC_PM_CTX_CNT,
-+ PORTAL_CMD_CLOSE_PORTAL,
-+ PORTAL_CMD_INVOKE_NOTIFY_42KHZ,
-+ PORTAL_CMD_INVALID,
-+ PORTAL_TOTAL_CMDS = PORTAL_CMD_INVALID,
-+};
-+
-+/**
-+ * Portal service request command names. The portal request consists of a kutf
-+ * named u64-value. For those above enumerated PORTAL_CMD, the names defined
-+ * here are used to mark the name and then followed with a sequence number
-+ * value. Example (manual script here for illustration):
-+ * exec 5<>run # open the portal kutf run as fd-5
-+ * echo GET_CLK_RATE_MGR=1 >&5 # send the cmd and sequence number 1
-+ * head -n 1 <&5 # read back the 1-line server reseponse
-+ * ACK="{SEQ:1, RATE:[0x1ad27480], GPU_IDLE:1}" # response string
-+ * echo GET_TRACE_SNAPSHOT=1 >&5 # send the cmd and sequence number 1
-+ * head -n 1 <&5 # read back the 1-line server reseponse
-+ * ACK="{SEQ:1, SNAPSHOT_ARRAY:[(0x0, 0x1ad27480, 1, 0)]}"
-+ * echo CLOSE_PORTAL=1 >&5 # close the portal
-+ * cat <&5 # read back all the response lines
-+ * ACK="{SEQ:1, PM_CTX_CNT:0}" # response to close command
-+ * KUTF_RESULT_PASS:(explicit pass) # internal sanity test passed.
-+ * exec 5>&- # close the service portal fd.
-+ *
-+ * Expected request command return format:
-+ * GET_CLK_RATE_MGR: ACK="{SEQ:12, RATE:[1080, 1280], GPU_IDLE:1}"
-+ * Note, the above contains 2-clock with rates in [], GPU idle
-+ * GET_CLK_RATE_TRACE: ACK="{SEQ:6, RATE:[0x1ad27480], GPU_IDLE:0}"
-+ * Note, 1-clock with rate in [], GPU not idle
-+ * GET_TRACE_SNAPSHOT: ACK="{SEQ:8, SNAPSHOT_ARRAY:[(0x0, 0x1ad27480, 1, 0)]}"
-+ * Note, 1-clock, (start_rate : 0, last_rate : 0x1ad27480,
-+ * trace_rate_up_count: 1, trace_rate_down_count : 0)
-+ * For the specific sample case here, there is a single rate_trace event
-+ * that yielded a rate increase change. No rate drop event recorded in the
-+ * reporting snapshot duration.
-+ * INC_PM_CTX_CNT: ACK="{SEQ:1, PM_CTX_CNT:1}"
-+ * Note, after the increment, M_CTX_CNT is 1. (i.e. 0 -> 1)
-+ * DEC_PM_CTX_CNT: ACK="{SEQ:3, PM_CTX_CNT:0}"
-+ * Note, after the decrement, PM_CTX_CNT is 0. (i.e. 1 -> 0)
-+ * CLOSE_PORTAL: ACK="{SEQ:1, PM_CTX_CNT:1}"
-+ * Note, at the close, PM_CTX_CNT is 1. The PM_CTX_CNT will internally be
-+ * dropped down to 0 as part of the portal close clean up.
-+ */
-+#define GET_PLATFORM "GET_PLATFORM"
-+#define GET_CLK_RATE_MGR "GET_CLK_RATE_MGR"
-+#define GET_CLK_RATE_TRACE "GET_CLK_RATE_TRACE"
-+#define GET_TRACE_SNAPSHOT "GET_TRACE_SNAPSHOT"
-+#define INC_PM_CTX_CNT "INC_PM_CTX_CNT"
-+#define DEC_PM_CTX_CNT "DEC_PM_CTX_CNT"
-+#define CLOSE_PORTAL "CLOSE_PORTAL"
-+#define INVOKE_NOTIFY_42KHZ "INVOKE_NOTIFY_42KHZ"
-+
-+/**
-+ * Portal service response tag names. The response consists of a kutf
-+ * named string-value. In case of a 'NACK' (negative acknowledgement), it
-+ * can be one of the two formats:
-+ * 1. NACK="{SEQ:2, MSG:xyzed}" # NACK on command with sequence tag-2.
-+ * Note, the portal has received a valid name and valid sequence number
-+ * but can't carry-out the request, reason in the MSG field.
-+ * 2. NACK="Failing-message"
-+ * Note, unable to parse a valid name or valid sequence number,
-+ * or some internal error condition. Reason in the quoted string.
-+ */
-+#define ACK "ACK"
-+#define NACK "NACK"
-+#define MAX_REPLY_NAME_LEN 32
-+
-+#endif /* _KUTF_CLK_RATE_TRACE_TEST_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kbuild
-index ca8c512..213d6d5 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- #
--# (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2017, 2020-2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,12 +16,10 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
- #
--#
--
--ccflags-y += -I$(src)/../include -I$(src)/../../../ -I$(src)/../../ -I$(src)/../../backend/gpu -I$(srctree)/drivers/staging/android
-
--obj-$(CONFIG_MALI_IRQ_LATENCY) += mali_kutf_irq_test.o
-+ifeq ($(CONFIG_MALI_KUTF_IRQ_TEST),y)
-+obj-m += mali_kutf_irq_test.o
-
- mali_kutf_irq_test-y := mali_kutf_irq_test_main.o
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kconfig b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kconfig
-deleted file mode 100644
-index 4a3863a..0000000
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Kconfig
-+++ /dev/null
-@@ -1,29 +0,0 @@
--#
--# (C) COPYRIGHT 2017 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.
--#
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--# GNU General Public License for more details.
--#
--# You should have received a copy of the GNU General Public License
--# along with this program; if not, you can access it online at
--# http://www.gnu.org/licenses/gpl-2.0.html.
--#
--# SPDX-License-Identifier: GPL-2.0
--#
--#
--
--config MALI_IRQ_LATENCY
-- tristate "Mali GPU IRQ latency measurement"
-- depends on MALI_MIDGARD && MALI_DEBUG && MALI_KUTF
-- default m
-- help
-- This option will build a test module mali_kutf_irq_test that
-- can determine the latency of the Mali GPU IRQ on your system.
-- Choosing M here will generate a single module called mali_kutf_irq_test.
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Makefile b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Makefile
-deleted file mode 100644
-index bc4d654..0000000
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/Makefile
-+++ /dev/null
-@@ -1,51 +0,0 @@
--#
--# (C) COPYRIGHT 2015, 2017-2018, 2020 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.
--#
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--# GNU General Public License for more details.
--#
--# You should have received a copy of the GNU General Public License
--# along with this program; if not, you can access it online at
--# http://www.gnu.org/licenses/gpl-2.0.html.
--#
--# SPDX-License-Identifier: GPL-2.0
--#
--#
--
--# linux build system bootstrap for out-of-tree module
--
--# default to building for the host
--ARCH ?= $(shell uname -m)
--
--ifeq ($(KDIR),)
--$(error Must specify KDIR to point to the kernel to target))
--endif
--
--TEST_CCFLAGS := \
-- -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \
-- -DMALI_CUSTOMER_RELEASE=$(MALI_CUSTOMER_RELEASE) \
-- -DMALI_USE_CSF=$(MALI_USE_CSF) \
-- $(SCONS_CFLAGS) \
-- -I$(CURDIR)/../include \
-- -I$(CURDIR)/../../../../../../include \
-- -I$(CURDIR)/../../../ \
-- -I$(CURDIR)/../../ \
-- -I$(CURDIR)/../../backend/gpu \
-- -I$(CURDIR)/../../debug \
-- -I$(CURDIR)/../../debug/backend \
-- -I$(CURDIR)/ \
-- -I$(srctree)/drivers/staging/android \
-- -I$(srctree)/include/linux
--
--all:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) $(SCONS_CONFIGS) EXTRA_CFLAGS="$(TEST_CCFLAGS)" KBUILD_EXTRA_SYMBOLS="$(CURDIR)/../kutf/Module.symvers $(CURDIR)/../../Module.symvers" modules
--
--clean:
-- $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/build.bp b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/build.bp
-index 90efdcf..155875b 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/build.bp
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/build.bp
-@@ -1,15 +1,21 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2018-2021 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.
-+ * of such GNU license.
- *
-- * 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 program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
- *
- */
-
-@@ -17,6 +23,7 @@ bob_kernel_module {
- name: "mali_kutf_irq_test",
- defaults: [
- "mali_kbase_shared_config_defaults",
-+ "kernel_test_configs",
- "kernel_test_includes",
- ],
- srcs: [
-@@ -28,8 +35,8 @@ bob_kernel_module {
- "kutf",
- ],
- enabled: false,
-- base_build_kutf: {
-+ mali_kutf_irq_test: {
-+ kbuild_options: ["CONFIG_MALI_KUTF_IRQ_TEST=y"],
- enabled: true,
-- kbuild_options: ["CONFIG_MALI_IRQ_LATENCY=m"],
- },
- }
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c
-index 26b442a..fdc5437 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2016-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2016-2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include <linux/module.h>
-@@ -25,8 +24,8 @@
- #include <linux/interrupt.h>
-
- #include "mali_kbase.h"
--#include <midgard/backend/gpu/mali_kbase_device_internal.h>
--#include <midgard/backend/gpu/mali_kbase_pm_internal.h>
-+#include <device/mali_kbase_device.h>
-+#include <backend/gpu/mali_kbase_pm_internal.h>
-
- #include <kutf/kutf_suite.h>
- #include <kutf/kutf_utils.h>
-@@ -242,7 +241,7 @@ int mali_kutf_irq_test_main_init(void)
-
- irq_app = kutf_create_application("irq");
-
-- if (NULL == irq_app) {
-+ if (irq_app == NULL) {
- pr_warn("Creation of test application failed!\n");
- return -ENOMEM;
- }
-@@ -251,7 +250,7 @@ int mali_kutf_irq_test_main_init(void)
- 1, mali_kutf_irq_default_create_fixture,
- mali_kutf_irq_default_remove_fixture);
-
-- if (NULL == suite) {
-+ if (suite == NULL) {
- pr_warn("Creation of test suite failed!\n");
- kutf_destroy_application(irq_app);
- return -ENOMEM;
-diff --git a/dvalin/kernel/drivers/base/memory_group_manager/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/thirdparty/Kbuild
-similarity index 82%
-rename from dvalin/kernel/drivers/base/memory_group_manager/Kbuild
-rename to dvalin/kernel/drivers/gpu/arm/midgard/thirdparty/Kbuild
-index a049bed..c723f3a 100644
---- a/dvalin/kernel/drivers/base/memory_group_manager/Kbuild
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/thirdparty/Kbuild
-@@ -1,10 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0
- #
--# (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+# (C) COPYRIGHT 2021 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.
-+# of such GNU license.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -15,8 +16,6 @@
- # along with this program; if not, you can access it online at
- # http://www.gnu.org/licenses/gpl-2.0.html.
- #
--# SPDX-License-Identifier: GPL-2.0
--#
- #
-
--obj-$(CONFIG_MALI_MEMORY_GROUP_MANAGER) := memory_group_manager.o
-\ No newline at end of file
-+mali_kbase-y += thirdparty/mali_kbase_mmap.o
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/thirdparty/mali_kbase_mmap.c b/dvalin/kernel/drivers/gpu/arm/midgard/thirdparty/mali_kbase_mmap.c
-index f266d8e..de1199a 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/thirdparty/mali_kbase_mmap.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/thirdparty/mali_kbase_mmap.c
-@@ -1,24 +1,4 @@
- /*
-- *
-- * (C) COPYRIGHT 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.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, you can access it online at
-- * http://www.gnu.org/licenses/gpl-2.0.html.
-- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
-- *//*
- * 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
-@@ -30,7 +10,7 @@
- */
-
- #include "linux/mman.h"
--#include "../mali_kbase.h"
-+#include <mali_kbase.h>
-
- /* mali_kbase_mmap.c
- *
-@@ -209,7 +189,8 @@ check_current:
- return -ENOMEM;
- if (gap_start <= high_limit && gap_end - gap_start >= length) {
- /* We found a suitable gap. Clip it with the original
-- * high_limit. */
-+ * high_limit.
-+ */
- if (gap_end > info->high_limit)
- gap_end = info->high_limit;
-
-@@ -270,19 +251,38 @@ unsigned long kbase_context_get_unmapped_area(struct kbase_context *const kctx,
- bool is_same_4gb_page = false;
- unsigned long ret;
-
-+ /* the 'nolock' form is used here:
-+ * - the base_pfn of the SAME_VA zone does not change
-+ * - in normal use, va_size_pages is constant once the first allocation
-+ * begins
-+ *
-+ * However, in abnormal use this function could be processing whilst
-+ * another new zone is being setup in a different thread (e.g. to
-+ * borrow part of the SAME_VA zone). In the worst case, this path may
-+ * witness a higher SAME_VA end_pfn than the code setting up the new
-+ * zone.
-+ *
-+ * This is safe because once we reach the main allocation functions,
-+ * we'll see the updated SAME_VA end_pfn and will determine that there
-+ * is no free region at the address found originally by too large a
-+ * same_va_end_addr here, and will fail the allocation gracefully.
-+ */
-+ struct kbase_reg_zone *zone =
-+ kbase_ctx_reg_zone_get_nolock(kctx, KBASE_REG_ZONE_SAME_VA);
-+ u64 same_va_end_addr = kbase_reg_zone_end_pfn(zone) << PAGE_SHIFT;
-+
- /* err on fixed address */
- if ((flags & MAP_FIXED) || addr)
- return -EINVAL;
-
--#ifdef CONFIG_64BIT
-+#if IS_ENABLED(CONFIG_64BIT)
- /* too big? */
- if (len > TASK_SIZE - SZ_2M)
- return -ENOMEM;
-
- if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) {
--
-- high_limit = min_t(unsigned long, mm->mmap_base,
-- (kctx->same_va_end << PAGE_SHIFT));
-+ high_limit =
-+ min_t(unsigned long, mm->mmap_base, same_va_end_addr);
-
- /* If there's enough (> 33 bits) of GPU VA space, align
- * to 2MB boundaries.
-@@ -317,19 +317,25 @@ unsigned long kbase_context_get_unmapped_area(struct kbase_context *const kctx,
- align_mask = align_offset - 1;
- is_shader_code = true;
- }
-+#if !MALI_USE_CSF
- } else if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) {
-- unsigned long extent_bytes =
-- (unsigned long)(reg->extent << PAGE_SHIFT);
-+ unsigned long extension_bytes =
-+ (unsigned long)(reg->extension
-+ << PAGE_SHIFT);
- /* kbase_check_alloc_sizes() already satisfies
- * these checks, but they're here to avoid
- * maintenance hazards due to the assumptions
-- * involved */
-- WARN_ON(reg->extent > (ULONG_MAX >> PAGE_SHIFT));
-+ * involved
-+ */
-+ WARN_ON(reg->extension >
-+ (ULONG_MAX >> PAGE_SHIFT));
- WARN_ON(reg->initial_commit > (ULONG_MAX >> PAGE_SHIFT));
-- WARN_ON(!is_power_of_2(extent_bytes));
-- align_mask = extent_bytes - 1;
-+ WARN_ON(!is_power_of_2(extension_bytes));
-+ align_mask = extension_bytes - 1;
- align_offset =
-- extent_bytes - (reg->initial_commit << PAGE_SHIFT);
-+ extension_bytes -
-+ (reg->initial_commit << PAGE_SHIFT);
-+#endif /* !MALI_USE_CSF */
- } else if (reg->flags & KBASE_REG_GPU_VA_SAME_4GB_PAGE) {
- is_same_4gb_page = true;
- }
-@@ -352,11 +358,10 @@ unsigned long kbase_context_get_unmapped_area(struct kbase_context *const kctx,
- is_same_4gb_page);
-
- if (IS_ERR_VALUE(ret) && high_limit == mm->mmap_base &&
-- high_limit < (kctx->same_va_end << PAGE_SHIFT)) {
-+ high_limit < same_va_end_addr) {
- /* Retry above mmap_base */
- info.low_limit = mm->mmap_base;
-- info.high_limit = min_t(u64, TASK_SIZE,
-- (kctx->same_va_end << PAGE_SHIFT));
-+ info.high_limit = min_t(u64, TASK_SIZE, same_va_end_addr);
-
- ret = kbase_unmapped_area_topdown(&info, is_shader_code,
- is_same_4gb_page);
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/Kbuild b/dvalin/kernel/drivers/gpu/arm/midgard/tl/Kbuild
-new file mode 100644
-index 0000000..4344850
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/Kbuild
-@@ -0,0 +1,32 @@
-+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+#
-+# (C) COPYRIGHT 2021 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 license.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, you can access it online at
-+# http://www.gnu.org/licenses/gpl-2.0.html.
-+#
-+#
-+
-+mali_kbase-y += \
-+ tl/mali_kbase_timeline.o \
-+ tl/mali_kbase_timeline_io.o \
-+ tl/mali_kbase_tlstream.o \
-+ tl/mali_kbase_tracepoints.o
-+
-+
-+ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
-+ mali_kbase-y += tl/backend/mali_kbase_timeline_csf.o
-+else
-+ mali_kbase-y += tl/backend/mali_kbase_timeline_jm.o
-+endif
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/backend/mali_kbase_timeline_csf.c b/dvalin/kernel/drivers/gpu/arm/midgard/tl/backend/mali_kbase_timeline_csf.c
-new file mode 100644
-index 0000000..a2868da
---- /dev/null
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/backend/mali_kbase_timeline_csf.c
-@@ -0,0 +1,171 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#include <tl/mali_kbase_tracepoints.h>
-+#include <tl/mali_kbase_timeline.h>
-+#include <tl/mali_kbase_timeline_priv.h>
-+
-+#include <mali_kbase.h>
-+
-+void kbase_create_timeline_objects(struct kbase_device *kbdev)
-+{
-+ unsigned int as_nr;
-+ unsigned int slot_i;
-+ struct kbase_context *kctx;
-+ struct kbase_timeline *timeline = kbdev->timeline;
-+ struct kbase_tlstream *summary =
-+ &kbdev->timeline->streams[TL_STREAM_TYPE_OBJ_SUMMARY];
-+
-+ /* Summarize the Address Space objects. */
-+ for (as_nr = 0; as_nr < kbdev->nr_hw_address_spaces; as_nr++)
-+ __kbase_tlstream_tl_new_as(summary, &kbdev->as[as_nr], as_nr);
-+
-+ /* Create Legacy GPU object to track in AOM for dumping */
-+ __kbase_tlstream_tl_new_gpu(summary,
-+ kbdev,
-+ kbdev->gpu_props.props.raw_props.gpu_id,
-+ kbdev->gpu_props.num_cores);
-+
-+
-+ for (as_nr = 0; as_nr < kbdev->nr_hw_address_spaces; as_nr++)
-+ __kbase_tlstream_tl_lifelink_as_gpu(summary,
-+ &kbdev->as[as_nr],
-+ kbdev);
-+
-+ /* Trace the creation of a new kbase device and set its properties. */
-+ __kbase_tlstream_tl_kbase_new_device(summary,
-+ kbdev->gpu_props.props.raw_props.gpu_id,
-+ kbdev->gpu_props.num_cores, kbdev->csf.global_iface.group_num,
-+ kbdev->nr_hw_address_spaces);
-+
-+ /* Lock the context list, to ensure no changes to the list are made
-+ * while we're summarizing the contexts and their contents.
-+ */
-+ mutex_lock(&timeline->tl_kctx_list_lock);
-+
-+ /* Hold the scheduler lock while we emit the current state
-+ * We also need to continue holding the lock until after the first body
-+ * stream tracepoints are emitted to ensure we don't change the
-+ * scheduler until after then
-+ */
-+ mutex_lock(&kbdev->csf.scheduler.lock);
-+
-+ for (slot_i = 0; slot_i < kbdev->csf.global_iface.group_num; slot_i++) {
-+
-+ struct kbase_queue_group *group =
-+ kbdev->csf.scheduler.csg_slots[slot_i].resident_group;
-+
-+ if (group)
-+ __kbase_tlstream_tl_kbase_device_program_csg(summary,
-+ kbdev->gpu_props.props.raw_props.gpu_id,
-+ group->handle, slot_i);
-+ }
-+
-+ /* Reset body stream buffers while holding the kctx lock.
-+ * As we are holding the lock, we can guarantee that no kctx creation or
-+ * deletion tracepoints can be fired from outside of this function by
-+ * some other thread.
-+ */
-+ kbase_timeline_streams_body_reset(timeline);
-+
-+ mutex_unlock(&kbdev->csf.scheduler.lock);
-+
-+ /* For each context in the device... */
-+ list_for_each_entry(kctx, &timeline->tl_kctx_list, tl_kctx_list_node) {
-+ size_t i;
-+ struct kbase_tlstream *body =
-+ &timeline->streams[TL_STREAM_TYPE_OBJ];
-+
-+ /* Lock the context's KCPU queues, to ensure no KCPU-queue
-+ * related actions can occur in this context from now on.
-+ */
-+ mutex_lock(&kctx->csf.kcpu_queues.lock);
-+
-+ /* Acquire the MMU lock, to ensure we don't get a concurrent
-+ * address space assignment while summarizing this context's
-+ * address space.
-+ */
-+ mutex_lock(&kbdev->mmu_hw_mutex);
-+
-+ /* Trace the context itself into the body stream, not the
-+ * summary stream.
-+ * We place this in the body to ensure it is ordered after any
-+ * other tracepoints related to the contents of the context that
-+ * might have been fired before acquiring all of the per-context
-+ * locks.
-+ * This ensures that those tracepoints will not actually affect
-+ * the object model state, as they reference a context that
-+ * hasn't been traced yet. They may, however, cause benign
-+ * errors to be emitted.
-+ */
-+ __kbase_tlstream_tl_kbase_new_ctx(body, kctx->id,
-+ kbdev->gpu_props.props.raw_props.gpu_id);
-+
-+ /* Also trace with the legacy AOM tracepoint for dumping */
-+ __kbase_tlstream_tl_new_ctx(body,
-+ kctx,
-+ kctx->id,
-+ (u32)(kctx->tgid));
-+
-+ /* Trace the currently assigned address space */
-+ if (kctx->as_nr != KBASEP_AS_NR_INVALID)
-+ __kbase_tlstream_tl_kbase_ctx_assign_as(body, kctx->id,
-+ kctx->as_nr);
-+
-+
-+ /* Trace all KCPU queues in the context into the body stream.
-+ * As we acquired the KCPU lock after resetting the body stream,
-+ * it's possible that some KCPU-related events for this context
-+ * occurred between that reset and now.
-+ * These will cause errors to be emitted when parsing the
-+ * timeline, but they will not affect the correctness of the
-+ * object model.
-+ */
-+ for (i = 0; i < KBASEP_MAX_KCPU_QUEUES; i++) {
-+ const struct kbase_kcpu_command_queue *kcpu_queue =
-+ kctx->csf.kcpu_queues.array[i];
-+
-+ if (kcpu_queue)
-+ __kbase_tlstream_tl_kbase_new_kcpuqueue(
-+ body, kcpu_queue, kcpu_queue->kctx->id,
-+ kcpu_queue->num_pending_cmds);
-+ }
-+
-+ mutex_unlock(&kbdev->mmu_hw_mutex);
-+ mutex_unlock(&kctx->csf.kcpu_queues.lock);
-+
-+ /* Now that all per-context locks for this context have been
-+ * released, any per-context tracepoints that are fired from
-+ * any other threads will go into the body stream after
-+ * everything that was just summarised into the body stream in
-+ * this iteration of the loop, so will start to correctly update
-+ * the object model state.
-+ */
-+ }
-+
-+ mutex_unlock(&timeline->tl_kctx_list_lock);
-+
-+ /* Static object are placed into summary packet that needs to be
-+ * transmitted first. Flush all streams to make it available to
-+ * user space.
-+ */
-+ kbase_timeline_streams_flush(timeline);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/backend/mali_kbase_timeline_jm.c b/dvalin/kernel/drivers/gpu/arm/midgard/tl/backend/mali_kbase_timeline_jm.c
-index c368ac7..9ba89f5 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/backend/mali_kbase_timeline_jm.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/backend/mali_kbase_timeline_jm.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,13 +17,11 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#include "../mali_kbase_tracepoints.h"
--#include "../mali_kbase_timeline.h"
--#include "../mali_kbase_timeline_priv.h"
-+#include <tl/mali_kbase_tracepoints.h>
-+#include <tl/mali_kbase_timeline.h>
-+#include <tl/mali_kbase_timeline_priv.h>
-
- #include <mali_kbase.h>
-
-@@ -66,16 +65,16 @@ void kbase_create_timeline_objects(struct kbase_device *kbdev)
- /* Lock the context list, to ensure no changes to the list are made
- * while we're summarizing the contexts and their contents.
- */
-- mutex_lock(&kbdev->kctx_list_lock);
-+ mutex_lock(&timeline->tl_kctx_list_lock);
-
- /* For each context in the device... */
-- list_for_each_entry(kctx, &kbdev->kctx_list, kctx_list_link) {
-+ list_for_each_entry(kctx, &timeline->tl_kctx_list, tl_kctx_list_node) {
- /* Summarize the context itself */
- __kbase_tlstream_tl_new_ctx(summary,
- kctx,
- kctx->id,
- (u32)(kctx->tgid));
-- };
-+ }
-
- /* Reset body stream buffers while holding the kctx lock.
- * This ensures we can't fire both summary and normal tracepoints for
-@@ -87,11 +86,11 @@ void kbase_create_timeline_objects(struct kbase_device *kbdev)
- */
- kbase_timeline_streams_body_reset(timeline);
-
-- mutex_unlock(&kbdev->kctx_list_lock);
-+ mutex_unlock(&timeline->tl_kctx_list_lock);
-
- /* Static object are placed into summary packet that needs to be
- * transmitted first. Flush all streams to make it available to
- * user space.
- */
- kbase_timeline_streams_flush(timeline);
--}
-\ No newline at end of file
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline.c b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline.c
-index 88fba83..09818a5 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase_timeline.h"
-@@ -109,11 +108,14 @@ int kbase_timeline_init(struct kbase_timeline **timeline,
- {
- enum tl_stream_type i;
- struct kbase_timeline *result;
-+#if MALI_USE_CSF
-+ struct kbase_tlstream *csffw_stream;
-+#endif
-
- if (!timeline || !timeline_flags)
- return -EINVAL;
-
-- result = kzalloc(sizeof(*result), GFP_KERNEL);
-+ result = vzalloc(sizeof(*result));
- if (!result)
- return -ENOMEM;
-
-@@ -125,12 +127,20 @@ int kbase_timeline_init(struct kbase_timeline **timeline,
- kbase_tlstream_init(&result->streams[i], i,
- &result->event_queue);
-
-+ /* Initialize the kctx list */
-+ mutex_init(&result->tl_kctx_list_lock);
-+ INIT_LIST_HEAD(&result->tl_kctx_list);
-+
- /* Initialize autoflush timer. */
- atomic_set(&result->autoflush_timer_active, 0);
- kbase_timer_setup(&result->autoflush_timer,
- kbasep_timeline_autoflush_timer_callback);
- result->timeline_flags = timeline_flags;
-
-+#if MALI_USE_CSF
-+ csffw_stream = &result->streams[TL_STREAM_TYPE_CSFFW];
-+ kbase_csf_tl_reader_init(&result->csf_tl_reader, csffw_stream);
-+#endif
-
- *timeline = result;
- return 0;
-@@ -143,11 +153,16 @@ void kbase_timeline_term(struct kbase_timeline *timeline)
- if (!timeline)
- return;
-
-+#if MALI_USE_CSF
-+ kbase_csf_tl_reader_term(&timeline->csf_tl_reader);
-+#endif
-+
-+ WARN_ON(!list_empty(&timeline->tl_kctx_list));
-
- for (i = (enum tl_stream_type)0; i < TL_STREAM_TYPE_COUNT; i++)
- kbase_tlstream_term(&timeline->streams[i]);
-
-- kfree(timeline);
-+ vfree(timeline);
- }
-
- #ifdef CONFIG_MALI_DEVFREQ
-@@ -162,11 +177,7 @@ static void kbase_tlstream_current_devfreq_target(struct kbase_device *kbdev)
- unsigned long cur_freq = 0;
-
- mutex_lock(&devfreq->lock);
--#if KERNEL_VERSION(4, 3, 0) > LINUX_VERSION_CODE
-- cur_freq = kbdev->current_nominal_freq;
--#else
- cur_freq = devfreq->last_status.current_frequency;
--#endif
- KBASE_TLSTREAM_AUX_DEVFREQ_TARGET(kbdev, (u64)cur_freq);
- mutex_unlock(&devfreq->lock);
- }
-@@ -175,13 +186,24 @@ static void kbase_tlstream_current_devfreq_target(struct kbase_device *kbdev)
-
- int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags)
- {
-- int ret;
-+ int ret = 0;
- u32 timeline_flags = TLSTREAM_ENABLED | flags;
- struct kbase_timeline *timeline = kbdev->timeline;
-
- if (!atomic_cmpxchg(timeline->timeline_flags, 0, timeline_flags)) {
- int rcode;
-
-+#if MALI_USE_CSF
-+ if (flags & BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS) {
-+ ret = kbase_csf_tl_reader_start(
-+ &timeline->csf_tl_reader, kbdev);
-+ if (ret)
-+ {
-+ atomic_set(timeline->timeline_flags, 0);
-+ return ret;
-+ }
-+ }
-+#endif
- ret = anon_inode_getfd(
- "[mali_tlstream]",
- &kbasep_tlstream_fops,
-@@ -189,6 +211,9 @@ int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags)
- O_RDONLY | O_CLOEXEC);
- if (ret < 0) {
- atomic_set(timeline->timeline_flags, 0);
-+#if MALI_USE_CSF
-+ kbase_csf_tl_reader_stop(&timeline->csf_tl_reader);
-+#endif
- return ret;
- }
-
-@@ -206,6 +231,7 @@ int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags)
- jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL));
- CSTD_UNUSED(rcode);
-
-+#if !MALI_USE_CSF
- /* If job dumping is enabled, readjust the software event's
- * timeout as the default value of 3 seconds is often
- * insufficient.
-@@ -216,6 +242,7 @@ int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags)
- atomic_set(&kbdev->js_data.soft_job_timeout_ms,
- 1800000);
- }
-+#endif /* !MALI_USE_CSF */
-
- /* Summary stream was cleared during acquire.
- * Create static timeline objects that will be
-@@ -235,15 +262,30 @@ int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags)
- ret = -EBUSY;
- }
-
-+ if (ret >= 0)
-+ timeline->last_acquire_time = ktime_get();
-+
- return ret;
- }
-
--void kbase_timeline_streams_flush(struct kbase_timeline *timeline)
-+int kbase_timeline_streams_flush(struct kbase_timeline *timeline)
- {
- enum tl_stream_type stype;
-+ bool has_bytes = false;
-+ size_t nbytes = 0;
-+#if MALI_USE_CSF
-+ int ret = kbase_csf_tl_reader_flush_buffer(&timeline->csf_tl_reader);
-+
-+ if (ret > 0)
-+ has_bytes = true;
-+#endif
-
-- for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++)
-- kbase_tlstream_flush_stream(&timeline->streams[stype]);
-+ for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) {
-+ nbytes = kbase_tlstream_flush_stream(&timeline->streams[stype]);
-+ if (nbytes > 0)
-+ has_bytes = true;
-+ }
-+ return has_bytes ? 0 : -EIO;
- }
-
- void kbase_timeline_streams_body_reset(struct kbase_timeline *timeline)
-@@ -252,6 +294,78 @@ void kbase_timeline_streams_body_reset(struct kbase_timeline *timeline)
- &timeline->streams[TL_STREAM_TYPE_OBJ]);
- kbase_tlstream_reset(
- &timeline->streams[TL_STREAM_TYPE_AUX]);
-+#if MALI_USE_CSF
-+ kbase_tlstream_reset(
-+ &timeline->streams[TL_STREAM_TYPE_CSFFW]);
-+#endif
-+}
-+
-+void kbase_timeline_pre_kbase_context_destroy(struct kbase_context *kctx)
-+{
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ struct kbase_timeline *timeline = kbdev->timeline;
-+
-+ /* Remove the context from the list to ensure we don't try and
-+ * summarize a context that is being destroyed.
-+ *
-+ * It's unsafe to try and summarize a context being destroyed as the
-+ * locks we might normally attempt to acquire, and the data structures
-+ * we would normally attempt to traverse could already be destroyed.
-+ *
-+ * In the case where the tlstream is acquired between this pre destroy
-+ * call and the post destroy call, we will get a context destroy
-+ * tracepoint without the corresponding context create tracepoint,
-+ * but this will not affect the correctness of the object model.
-+ */
-+ mutex_lock(&timeline->tl_kctx_list_lock);
-+ list_del_init(&kctx->tl_kctx_list_node);
-+ mutex_unlock(&timeline->tl_kctx_list_lock);
-+}
-+
-+void kbase_timeline_post_kbase_context_create(struct kbase_context *kctx)
-+{
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+ struct kbase_timeline *timeline = kbdev->timeline;
-+
-+ /* On context create, add the context to the list to ensure it is
-+ * summarized when timeline is acquired
-+ */
-+ mutex_lock(&timeline->tl_kctx_list_lock);
-+
-+ list_add(&kctx->tl_kctx_list_node, &timeline->tl_kctx_list);
-+
-+ /* Fire the tracepoints with the lock held to ensure the tracepoints
-+ * are either fired before or after the summarization,
-+ * never in parallel with it. If fired in parallel, we could get
-+ * duplicate creation tracepoints.
-+ */
-+#if MALI_USE_CSF
-+ KBASE_TLSTREAM_TL_KBASE_NEW_CTX(
-+ kbdev, kctx->id, kbdev->gpu_props.props.raw_props.gpu_id);
-+#endif
-+ /* Trace with the AOM tracepoint even in CSF for dumping */
-+ KBASE_TLSTREAM_TL_NEW_CTX(kbdev, kctx, kctx->id, 0);
-+
-+ mutex_unlock(&timeline->tl_kctx_list_lock);
-+}
-+
-+void kbase_timeline_post_kbase_context_destroy(struct kbase_context *kctx)
-+{
-+ struct kbase_device *const kbdev = kctx->kbdev;
-+
-+ /* Trace with the AOM tracepoint even in CSF for dumping */
-+ KBASE_TLSTREAM_TL_DEL_CTX(kbdev, kctx);
-+#if MALI_USE_CSF
-+ KBASE_TLSTREAM_TL_KBASE_DEL_CTX(kbdev, kctx->id);
-+#endif
-+
-+ /* Flush the timeline stream, so the user can see the termination
-+ * tracepoints being fired.
-+ * The "if" statement below is for optimization. It is safe to call
-+ * kbase_timeline_streams_flush when timeline is disabled.
-+ */
-+ if (atomic_read(&kbdev->timeline_flags) != 0)
-+ kbase_timeline_streams_flush(kbdev->timeline);
- }
-
- #if MALI_UNIT_TEST
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline.h b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline.h
-index cd48411..63926eb 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #if !defined(_KBASE_TIMELINE_H)
-@@ -70,8 +69,10 @@ int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags);
- * @timeline: Timeline instance
- *
- * Function will flush pending data in all timeline streams.
-+ *
-+ * Return: Zero on success, errno on failure.
- */
--void kbase_timeline_streams_flush(struct kbase_timeline *timeline);
-+int kbase_timeline_streams_flush(struct kbase_timeline *timeline);
-
- /**
- * kbase_timeline_streams_body_reset - reset timeline body streams.
-@@ -81,33 +82,31 @@ void kbase_timeline_streams_flush(struct kbase_timeline *timeline);
- */
- void kbase_timeline_streams_body_reset(struct kbase_timeline *timeline);
-
--#if MALI_UNIT_TEST
- /**
-- * kbase_timeline_test - start timeline stream data generator
-- * @kbdev: Kernel common context
-- * @tpw_count: Number of trace point writers in each context
-- * @msg_delay: Time delay in milliseconds between trace points written by one
-- * writer
-- * @msg_count: Number of trace points written by one writer
-- * @aux_msg: If non-zero aux messages will be included
-+ * kbase_timeline_post_kbase_context_create - Inform timeline that a new KBase
-+ * Context has been created.
-+ * @kctx: KBase Context
-+ */
-+void kbase_timeline_post_kbase_context_create(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_timeline_pre_kbase_context_destroy - Inform timeline that a KBase
-+ * Context is about to be destroyed.
-+ * @kctx: KBase Context
-+ */
-+void kbase_timeline_pre_kbase_context_destroy(struct kbase_context *kctx);
-+
-+/**
-+ * kbase_timeline_post_kbase_context_destroy - Inform timeline that a KBase
-+ * Context has been destroyed.
-+ * @kctx: KBase Context
- *
-- * This test starts a requested number of asynchronous writers in both IRQ and
-- * thread context. Each writer will generate required number of test
-- * tracepoints (tracepoints with embedded information about writer that
-- * should be verified by user space reader). Tracepoints will be emitted in
-- * all timeline body streams. If aux_msg is non-zero writer will also
-- * generate not testable tracepoints (tracepoints without information about
-- * writer). These tracepoints are used to check correctness of remaining
-- * timeline message generating functions. Writer will wait requested time
-- * between generating another set of messages. This call blocks until all
-- * writers finish.
-+ * Should be called immediately before the memory is freed, and the context ID
-+ * and kbdev pointer should still be valid.
- */
--void kbase_timeline_test(
-- struct kbase_device *kbdev,
-- unsigned int tpw_count,
-- unsigned int msg_delay,
-- unsigned int msg_count,
-- int aux_msg);
-+void kbase_timeline_post_kbase_context_destroy(struct kbase_context *kctx);
-+
-+#if MALI_UNIT_TEST
-
- /**
- * kbase_timeline_stats - read timeline stream statistics
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline_io.c b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline_io.c
-index cdde928..eff30a0 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline_io.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline_io.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,35 +17,38 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase_timeline_priv.h"
- #include "mali_kbase_tlstream.h"
- #include "mali_kbase_tracepoints.h"
-+#include "mali_kbase_timeline.h"
-
-+#include <linux/delay.h>
- #include <linux/poll.h>
-
- /* The timeline stream file operations functions. */
--static ssize_t kbasep_timeline_io_read(
-- struct file *filp,
-- char __user *buffer,
-- size_t size,
-- loff_t *f_pos);
--static unsigned int kbasep_timeline_io_poll(struct file *filp, poll_table *wait);
-+static ssize_t kbasep_timeline_io_read(struct file *filp, char __user *buffer,
-+ size_t size, loff_t *f_pos);
-+static unsigned int kbasep_timeline_io_poll(struct file *filp,
-+ poll_table *wait);
- static int kbasep_timeline_io_release(struct inode *inode, struct file *filp);
-+static int kbasep_timeline_io_fsync(struct file *filp, loff_t start, loff_t end,
-+ int datasync);
-
- /* The timeline stream file operations structure. */
- const struct file_operations kbasep_tlstream_fops = {
- .owner = THIS_MODULE,
- .release = kbasep_timeline_io_release,
-- .read = kbasep_timeline_io_read,
-- .poll = kbasep_timeline_io_poll,
-+ .read = kbasep_timeline_io_read,
-+ .poll = kbasep_timeline_io_poll,
-+ .fsync = kbasep_timeline_io_fsync,
- };
-
- /**
-- * kbasep_timeline_io_packet_pending - check timeline streams for pending packets
-+ * kbasep_timeline_io_packet_pending - check timeline streams for pending
-+ * packets
-+ *
- * @timeline: Timeline instance
- * @ready_stream: Pointer to variable where stream will be placed
- * @rb_idx_raw: Pointer to variable where read buffer index will be placed
-@@ -56,10 +60,10 @@ const struct file_operations kbasep_tlstream_fops = {
- *
- * Return: non-zero if any of timeline streams has at last one packet ready
- */
--static int kbasep_timeline_io_packet_pending(
-- struct kbase_timeline *timeline,
-- struct kbase_tlstream **ready_stream,
-- unsigned int *rb_idx_raw)
-+static int
-+kbasep_timeline_io_packet_pending(struct kbase_timeline *timeline,
-+ struct kbase_tlstream **ready_stream,
-+ unsigned int *rb_idx_raw)
- {
- enum tl_stream_type i;
-
-@@ -78,12 +82,28 @@ static int kbasep_timeline_io_packet_pending(
- *ready_stream = stream;
- return 1;
- }
--
- }
-
- return 0;
- }
-
-+/**
-+ * kbasep_timeline_has_header_data() - check timeline headers for pending
-+ * packets
-+ *
-+ * @timeline: Timeline instance
-+ *
-+ * Return: non-zero if any of timeline headers has at last one packet ready.
-+ */
-+static int kbasep_timeline_has_header_data(struct kbase_timeline *timeline)
-+{
-+ return timeline->obj_header_btc || timeline->aux_header_btc
-+#if MALI_USE_CSF
-+ || timeline->csf_tl_reader.tl_header.btc
-+#endif
-+ ;
-+}
-+
- /**
- * copy_stream_header() - copy timeline stream header.
- *
-@@ -97,11 +117,9 @@ static int kbasep_timeline_io_packet_pending(
- *
- * Returns: 0 if success, -1 otherwise.
- */
--static inline int copy_stream_header(
-- char __user *buffer, size_t size, ssize_t *copy_len,
-- const char *hdr,
-- size_t hdr_size,
-- size_t *hdr_btc)
-+static inline int copy_stream_header(char __user *buffer, size_t size,
-+ ssize_t *copy_len, const char *hdr,
-+ size_t hdr_size, size_t *hdr_btc)
- {
- const size_t offset = hdr_size - *hdr_btc;
- const size_t copy_size = MIN(size - *copy_len, *hdr_btc);
-@@ -123,6 +141,7 @@ static inline int copy_stream_header(
-
- /**
- * kbasep_timeline_copy_header - copy timeline headers to the user
-+ *
- * @timeline: Timeline instance
- * @buffer: Pointer to the buffer provided by user
- * @size: Maximum amount of data that can be stored in the buffer
-@@ -135,29 +154,30 @@ static inline int copy_stream_header(
- *
- * Returns: 0 if success, -1 if copy_to_user has failed.
- */
--static inline int kbasep_timeline_copy_headers(
-- struct kbase_timeline *timeline,
-- char __user *buffer,
-- size_t size,
-- ssize_t *copy_len)
-+static inline int kbasep_timeline_copy_headers(struct kbase_timeline *timeline,
-+ char __user *buffer, size_t size,
-+ ssize_t *copy_len)
- {
-- if (copy_stream_header(buffer, size, copy_len,
-- obj_desc_header,
-- obj_desc_header_size,
-- &timeline->obj_header_btc))
-+ if (copy_stream_header(buffer, size, copy_len, obj_desc_header,
-+ obj_desc_header_size, &timeline->obj_header_btc))
- return -1;
-
-+ if (copy_stream_header(buffer, size, copy_len, aux_desc_header,
-+ aux_desc_header_size, &timeline->aux_header_btc))
-+ return -1;
-+#if MALI_USE_CSF
- if (copy_stream_header(buffer, size, copy_len,
-- aux_desc_header,
-- aux_desc_header_size,
-- &timeline->aux_header_btc))
-+ timeline->csf_tl_reader.tl_header.data,
-+ timeline->csf_tl_reader.tl_header.size,
-+ &timeline->csf_tl_reader.tl_header.btc))
- return -1;
-+#endif
- return 0;
- }
-
--
- /**
- * kbasep_timeline_io_read - copy data from streams to buffer provided by user
-+ *
- * @filp: Pointer to file structure
- * @buffer: Pointer to the buffer provided by user
- * @size: Maximum amount of data that can be stored in the buffer
-@@ -165,11 +185,8 @@ static inline int kbasep_timeline_copy_headers(
- *
- * Return: number of bytes stored in the buffer
- */
--static ssize_t kbasep_timeline_io_read(
-- struct file *filp,
-- char __user *buffer,
-- size_t size,
-- loff_t *f_pos)
-+static ssize_t kbasep_timeline_io_read(struct file *filp, char __user *buffer,
-+ size_t size, loff_t *f_pos)
- {
- ssize_t copy_len = 0;
- struct kbase_timeline *timeline;
-@@ -180,25 +197,25 @@ static ssize_t kbasep_timeline_io_read(
- if (WARN_ON(!filp->private_data))
- return -EFAULT;
-
-- timeline = (struct kbase_timeline *) filp->private_data;
-+ timeline = (struct kbase_timeline *)filp->private_data;
-
- if (!buffer)
- return -EINVAL;
-
-- if ((*f_pos < 0) || (size < PACKET_SIZE))
-+ if (*f_pos < 0)
- return -EINVAL;
-
- mutex_lock(&timeline->reader_lock);
-
- while (copy_len < size) {
- struct kbase_tlstream *stream = NULL;
-- unsigned int rb_idx_raw = 0;
-- unsigned int wb_idx_raw;
-- unsigned int rb_idx;
-- size_t rb_size;
-+ unsigned int rb_idx_raw = 0;
-+ unsigned int wb_idx_raw;
-+ unsigned int rb_idx;
-+ size_t rb_size;
-
-- if (kbasep_timeline_copy_headers(
-- timeline, buffer, size, ©_len)) {
-+ if (kbasep_timeline_copy_headers(timeline, buffer, size,
-+ ©_len)) {
- copy_len = -EFAULT;
- break;
- }
-@@ -210,17 +227,13 @@ static ssize_t kbasep_timeline_io_read(
- */
- if (copy_len > 0) {
- if (!kbasep_timeline_io_packet_pending(
-- timeline,
-- &stream,
-- &rb_idx_raw))
-+ timeline, &stream, &rb_idx_raw))
- break;
- } else {
- if (wait_event_interruptible(
-- timeline->event_queue,
-- kbasep_timeline_io_packet_pending(
-- timeline,
-- &stream,
-- &rb_idx_raw))) {
-+ timeline->event_queue,
-+ kbasep_timeline_io_packet_pending(
-+ timeline, &stream, &rb_idx_raw))) {
- copy_len = -ERESTARTSYS;
- break;
- }
-@@ -238,10 +251,8 @@ static ssize_t kbasep_timeline_io_read(
- rb_size = atomic_read(&stream->buffer[rb_idx].size);
- if (rb_size > size - copy_len)
- break;
-- if (copy_to_user(
-- &buffer[copy_len],
-- stream->buffer[rb_idx].data,
-- rb_size)) {
-+ if (copy_to_user(&buffer[copy_len], stream->buffer[rb_idx].data,
-+ rb_size)) {
- copy_len = -EFAULT;
- break;
- }
-@@ -283,7 +294,7 @@ static ssize_t kbasep_timeline_io_read(
- static unsigned int kbasep_timeline_io_poll(struct file *filp, poll_table *wait)
- {
- struct kbase_tlstream *stream;
-- unsigned int rb_idx;
-+ unsigned int rb_idx;
- struct kbase_timeline *timeline;
-
- KBASE_DEBUG_ASSERT(filp);
-@@ -292,7 +303,11 @@ static unsigned int kbasep_timeline_io_poll(struct file *filp, poll_table *wait)
- if (WARN_ON(!filp->private_data))
- return -EFAULT;
-
-- timeline = (struct kbase_timeline *) filp->private_data;
-+ timeline = (struct kbase_timeline *)filp->private_data;
-+
-+ /* If there are header bytes to copy, read will not block */
-+ if (kbasep_timeline_has_header_data(timeline))
-+ return POLLIN;
-
- poll_wait(filp, &timeline->event_queue, wait);
- if (kbasep_timeline_io_packet_pending(timeline, &stream, &rb_idx))
-@@ -310,6 +325,8 @@ static unsigned int kbasep_timeline_io_poll(struct file *filp, poll_table *wait)
- static int kbasep_timeline_io_release(struct inode *inode, struct file *filp)
- {
- struct kbase_timeline *timeline;
-+ ktime_t elapsed_time;
-+ s64 elapsed_time_ms, time_to_sleep;
-
- KBASE_DEBUG_ASSERT(inode);
- KBASE_DEBUG_ASSERT(filp);
-@@ -317,8 +334,23 @@ static int kbasep_timeline_io_release(struct inode *inode, struct file *filp)
-
- CSTD_UNUSED(inode);
-
-- timeline = (struct kbase_timeline *) filp->private_data;
-+ timeline = (struct kbase_timeline *)filp->private_data;
-+
-+ /* Get the amount of time passed since the timeline was acquired and ensure
-+ * we sleep for long enough such that it has been at least
-+ * TIMELINE_HYSTERESIS_TIMEOUT_MS amount of time between acquire and release.
-+ * This prevents userspace from spamming acquire and release too quickly.
-+ */
-+ elapsed_time = ktime_sub(ktime_get(), timeline->last_acquire_time);
-+ elapsed_time_ms = ktime_to_ms(elapsed_time);
-+ time_to_sleep = MIN(TIMELINE_HYSTERESIS_TIMEOUT_MS,
-+ TIMELINE_HYSTERESIS_TIMEOUT_MS - elapsed_time_ms);
-+ if (time_to_sleep > 0)
-+ msleep(time_to_sleep);
-
-+#if MALI_USE_CSF
-+ kbase_csf_tl_reader_stop(&timeline->csf_tl_reader);
-+#endif
-
- /* Stop autoflush timer before releasing access to streams. */
- atomic_set(&timeline->autoflush_timer_active, 0);
-@@ -327,3 +359,20 @@ static int kbasep_timeline_io_release(struct inode *inode, struct file *filp)
- atomic_set(timeline->timeline_flags, 0);
- return 0;
- }
-+
-+static int kbasep_timeline_io_fsync(struct file *filp, loff_t start, loff_t end,
-+ int datasync)
-+{
-+ struct kbase_timeline *timeline;
-+
-+ CSTD_UNUSED(start);
-+ CSTD_UNUSED(end);
-+ CSTD_UNUSED(datasync);
-+
-+ if (WARN_ON(!filp->private_data))
-+ return -EFAULT;
-+
-+ timeline = (struct kbase_timeline *)filp->private_data;
-+
-+ return kbase_timeline_streams_flush(timeline);
-+}
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline_priv.h b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline_priv.h
-index 3596584..bf2c385 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline_priv.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_timeline_priv.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #if !defined(_KBASE_TIMELINE_PRIV_H)
-@@ -26,14 +25,25 @@
- #include <mali_kbase.h>
- #include "mali_kbase_tlstream.h"
-
-+#if MALI_USE_CSF
-+#include "csf/mali_kbase_csf_tl_reader.h"
-+#include "csf/mali_kbase_csf_trace_buffer.h"
-+#endif
-
- #include <linux/timer.h>
- #include <linux/atomic.h>
- #include <linux/mutex.h>
-
-+/* The minimum amount of time timeline must be acquired for before release is
-+ * allowed, to prevent DoS attacks.
-+ */
-+#define TIMELINE_HYSTERESIS_TIMEOUT_MS ((s64)500)
-+
- /**
- * struct kbase_timeline - timeline state structure
- * @streams: The timeline streams generated by kernel
-+ * @tl_kctx_list: List of contexts for timeline.
-+ * @tl_kctx_list_lock: Lock to protect @tl_kctx_list.
- * @autoflush_timer: Autoflush timer
- * @autoflush_timer_active: If non-zero autoflush timer is active
- * @reader_lock: Reader lock. Only one reader is allowed to
-@@ -44,9 +54,13 @@
- * otherwise. See kbase_timeline_io_acquire().
- * @obj_header_btc: Remaining bytes to copy for the object stream header
- * @aux_header_btc: Remaining bytes to copy for the aux stream header
-+ * @last_acquire_time: The time at which timeline was last acquired.
-+ * @csf_tl_reader: CSFFW timeline reader
- */
- struct kbase_timeline {
- struct kbase_tlstream streams[TL_STREAM_TYPE_COUNT];
-+ struct list_head tl_kctx_list;
-+ struct mutex tl_kctx_list_lock;
- struct timer_list autoflush_timer;
- atomic_t autoflush_timer_active;
- struct mutex reader_lock;
-@@ -57,6 +71,10 @@ struct kbase_timeline {
- atomic_t *timeline_flags;
- size_t obj_header_btc;
- size_t aux_header_btc;
-+ ktime_t last_acquire_time;
-+#if MALI_USE_CSF
-+ struct kbase_csf_tl_reader csf_tl_reader;
-+#endif
- };
-
- extern const struct file_operations kbasep_tlstream_fops;
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tl_serialize.h b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tl_serialize.h
-index 3e37827..30d120d 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tl_serialize.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tl_serialize.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #if !defined(_KBASE_TL_SERIALIZE_H)
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tlstream.c b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tlstream.c
-index bec4be7..0275bad 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tlstream.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tlstream.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #include "mali_kbase_tlstream.h"
-@@ -57,20 +56,19 @@ static void kbasep_packet_header_setup(
- * @numbered: non-zero if the stream is numbered
- *
- * Function updates mutable part of packet header in the given buffer.
-- * Note that value of data_size must not including size of the header.
-+ * Note that value of data_size must not include size of the header.
- */
- static void kbasep_packet_header_update(
- char *buffer,
- size_t data_size,
- int numbered)
- {
-- u32 word0;
- u32 word1 = MIPE_PACKET_HEADER_W1((u32)data_size, !!numbered);
-
- KBASE_DEBUG_ASSERT(buffer);
-- CSTD_UNUSED(word0);
-
-- memcpy(&buffer[sizeof(word0)], &word1, sizeof(word1));
-+ /* we copy the contents of word1 to its respective position in the buffer */
-+ memcpy(&buffer[sizeof(u32)], &word1, sizeof(word1));
- }
-
- /**
-@@ -131,6 +129,14 @@ static const struct {
- TL_PACKET_TYPE_BODY,
- TL_STREAM_ID_KERNEL,
- },
-+#if MALI_USE_CSF
-+ {
-+ TL_PACKET_FAMILY_TL,
-+ TL_PACKET_CLASS_OBJ,
-+ TL_PACKET_TYPE_BODY,
-+ TL_STREAM_ID_CSFFW,
-+ },
-+#endif
- };
-
- void kbase_tlstream_init(
-@@ -141,12 +147,12 @@ void kbase_tlstream_init(
- unsigned int i;
-
- KBASE_DEBUG_ASSERT(stream);
-- KBASE_DEBUG_ASSERT(TL_STREAM_TYPE_COUNT > stream_type);
-+ KBASE_DEBUG_ASSERT(stream_type < TL_STREAM_TYPE_COUNT);
-
- spin_lock_init(&stream->lock);
-
- /* All packets carrying tracepoints shall be numbered. */
-- if (TL_PACKET_TYPE_BODY == tl_stream_cfg[stream_type].pkt_type)
-+ if (tl_stream_cfg[stream_type].pkt_type == TL_PACKET_TYPE_BODY)
- stream->numbered = 1;
- else
- stream->numbered = 0;
-@@ -209,7 +215,8 @@ static size_t kbasep_tlstream_msgbuf_submit(
-
- /* Increasing write buffer index will expose this packet to the reader.
- * As stream->lock is not taken on reader side we must make sure memory
-- * is updated correctly before this will happen. */
-+ * is updated correctly before this will happen.
-+ */
- smp_wmb();
- atomic_inc(&stream->wbi);
-
-@@ -243,7 +250,7 @@ char *kbase_tlstream_msgbuf_acquire(
- wb_size = atomic_read(&stream->buffer[wb_idx].size);
-
- /* Select next buffer if data will not fit into current one. */
-- if (PACKET_SIZE < wb_size + msg_size) {
-+ if (wb_size + msg_size > PACKET_SIZE) {
- wb_size = kbasep_tlstream_msgbuf_submit(
- stream, wb_idx_raw, wb_size);
- wb_idx = (wb_idx_raw + 1) % PACKET_COUNT;
-@@ -269,7 +276,7 @@ void kbase_tlstream_msgbuf_release(
- spin_unlock_irqrestore(&stream->lock, flags);
- }
-
--void kbase_tlstream_flush_stream(
-+size_t kbase_tlstream_flush_stream(
- struct kbase_tlstream *stream)
- {
- unsigned long flags;
-@@ -278,6 +285,7 @@ void kbase_tlstream_flush_stream(
- size_t wb_size;
- size_t min_size = PACKET_HEADER_SIZE;
-
-+
- if (stream->numbered)
- min_size += PACKET_NUMBER_SIZE;
-
-@@ -292,7 +300,14 @@ void kbase_tlstream_flush_stream(
- stream, wb_idx_raw, wb_size);
- wb_idx = (wb_idx_raw + 1) % PACKET_COUNT;
- atomic_set(&stream->buffer[wb_idx].size, wb_size);
-+ } else {
-+ /* we return that there is no bytes to be read.*/
-+ /* Timeline io fsync will use this info the decide whether
-+ * fsync should return an error
-+ */
-+ wb_size = 0;
- }
-+
- spin_unlock_irqrestore(&stream->lock, flags);
-+ return wb_size;
- }
--
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tlstream.h b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tlstream.h
-index 427bb09..6660cf5 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tlstream.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tlstream.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #if !defined(_KBASE_TLSTREAM_H)
-@@ -44,6 +43,8 @@
- * struct kbase_tlstream - timeline stream structure
- * @lock: Message order lock
- * @buffer: Array of buffers
-+ * @buffer.size: Number of bytes in buffer
-+ * @buffer.data: Buffer's data
- * @wbi: Write buffer index
- * @rbi: Read buffer index
- * @numbered: If non-zero stream's packets are sequentially numbered
-@@ -76,8 +77,8 @@ struct kbase_tlstream {
- spinlock_t lock;
-
- struct {
-- atomic_t size; /* number of bytes in buffer */
-- char data[PACKET_SIZE]; /* buffer's data */
-+ atomic_t size;
-+ char data[PACKET_SIZE];
- } buffer[PACKET_COUNT];
-
- atomic_t wbi;
-@@ -97,6 +98,9 @@ enum tl_stream_type {
- TL_STREAM_TYPE_OBJ_SUMMARY = TL_STREAM_TYPE_FIRST,
- TL_STREAM_TYPE_OBJ,
- TL_STREAM_TYPE_AUX,
-+#if MALI_USE_CSF
-+ TL_STREAM_TYPE_CSFFW,
-+#endif
- TL_STREAM_TYPE_COUNT
- };
-
-@@ -159,8 +163,10 @@ void kbase_tlstream_msgbuf_release(struct kbase_tlstream *stream,
- * @stream: Pointer to the stream structure
- *
- * Flush pending data in the timeline stream.
-+ *
-+ * Return: Number of bytes available flushed and available to be read
-+ *
- */
--void kbase_tlstream_flush_stream(struct kbase_tlstream *stream);
-+size_t kbase_tlstream_flush_stream(struct kbase_tlstream *stream);
-
- #endif /* _KBASE_TLSTREAM_H */
--
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tracepoints.c b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tracepoints.c
-index e445a3a..2c0de01 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tracepoints.c
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tracepoints.c
-@@ -1,11 +1,12 @@
-+// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -66,10 +65,11 @@ enum tl_msg_id_obj {
- KBASE_TL_EVENT_ATOM_SOFTSTOP_ISSUE,
- KBASE_TL_EVENT_ATOM_SOFTJOB_START,
- KBASE_TL_EVENT_ATOM_SOFTJOB_END,
-- KBASE_TL_EVENT_ARB_GRANTED,
-- KBASE_TL_EVENT_ARB_STARTED,
-- KBASE_TL_EVENT_ARB_STOP_REQUESTED,
-- KBASE_TL_EVENT_ARB_STOPPED,
-+ KBASE_TL_ARBITER_GRANTED,
-+ KBASE_TL_ARBITER_STARTED,
-+ KBASE_TL_ARBITER_STOP_REQUESTED,
-+ KBASE_TL_ARBITER_STOPPED,
-+ KBASE_TL_ARBITER_REQUESTED,
- KBASE_JD_GPU_SOFT_RESET,
- KBASE_TL_KBASE_NEW_DEVICE,
- KBASE_TL_KBASE_DEVICE_PROGRAM_CSG,
-@@ -82,18 +82,13 @@ enum tl_msg_id_obj {
- KBASE_TL_KBASE_DEL_KCPUQUEUE,
- KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_SIGNAL,
- KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT,
-- KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_WAIT,
-- KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_WAIT,
-- KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_WAIT,
-- KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_SET,
-- KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_SET,
-- KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_SET,
-- KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_DEBUGCOPY,
-- KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_DEBUGCOPY,
-- KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_DEBUGCOPY,
-+ KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT,
-+ KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET,
- KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT,
- KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT,
- KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE,
-+ KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER,
-+ KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND,
- KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC,
- KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_ALLOC,
- KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_ALLOC,
-@@ -107,8 +102,6 @@ enum tl_msg_id_obj {
- KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START,
- KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END,
- KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET,
-- KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_START,
-- KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_END,
- KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START,
- KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END,
- KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_START,
-@@ -123,8 +116,11 @@ enum tl_msg_id_obj {
- KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_FREE_END,
- KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END,
- KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_FREE_END,
-- KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_ERRORBARRIER,
-+ KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER,
-+ KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START,
-+ KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END,
- KBASE_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW,
-+ KBASE_TL_KBASE_CSFFW_RESET,
- KBASE_OBJ_MSG_COUNT,
- };
-
-@@ -139,6 +135,7 @@ enum tl_msg_id_aux {
- KBASE_AUX_PROTECTED_LEAVE_START,
- KBASE_AUX_PROTECTED_LEAVE_END,
- KBASE_AUX_JIT_STATS,
-+ KBASE_AUX_TILER_HEAP_STATS,
- KBASE_AUX_EVENT_JOB_SLOT,
- KBASE_AUX_MSG_COUNT,
- };
-@@ -276,22 +273,26 @@ enum tl_msg_id_aux {
- "atom soft job has completed", \
- "@p", \
- "atom") \
-- TRACEPOINT_DESC(KBASE_TL_EVENT_ARB_GRANTED, \
-+ TRACEPOINT_DESC(KBASE_TL_ARBITER_GRANTED, \
- "Arbiter has granted gpu access", \
- "@p", \
- "gpu") \
-- TRACEPOINT_DESC(KBASE_TL_EVENT_ARB_STARTED, \
-+ TRACEPOINT_DESC(KBASE_TL_ARBITER_STARTED, \
- "Driver is running again and able to process jobs", \
- "@p", \
- "gpu") \
-- TRACEPOINT_DESC(KBASE_TL_EVENT_ARB_STOP_REQUESTED, \
-+ TRACEPOINT_DESC(KBASE_TL_ARBITER_STOP_REQUESTED, \
- "Arbiter has requested driver to stop using gpu", \
- "@p", \
- "gpu") \
-- TRACEPOINT_DESC(KBASE_TL_EVENT_ARB_STOPPED, \
-+ TRACEPOINT_DESC(KBASE_TL_ARBITER_STOPPED, \
- "Driver has stopped using gpu", \
- "@p", \
- "gpu") \
-+ TRACEPOINT_DESC(KBASE_TL_ARBITER_REQUESTED, \
-+ "Driver has requested the arbiter for gpu access", \
-+ "@p", \
-+ "gpu") \
- TRACEPOINT_DESC(KBASE_JD_GPU_SOFT_RESET, \
- "gpu soft reset", \
- "@p", \
-@@ -340,42 +341,14 @@ enum tl_msg_id_aux {
- "KCPU Queue enqueues Wait on Fence", \
- "@pp", \
- "kcpu_queue,fence") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_WAIT, \
-- "Begin array of KCPU Queue enqueues Wait on Cross Queue Sync Object", \
-- "@p", \
-- "kcpu_queue") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_WAIT, \
-- "Array item of KCPU Queue enqueues Wait on Cross Queue Sync Object", \
-- "@pLI", \
-- "kcpu_queue,cqs_obj_gpu_addr,cqs_obj_compare_value") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_WAIT, \
-- "End array of KCPU Queue enqueues Wait on Cross Queue Sync Object", \
-- "@p", \
-- "kcpu_queue") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_SET, \
-- "Begin array of KCPU Queue enqueues Set on Cross Queue Sync Object", \
-- "@p", \
-- "kcpu_queue") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_SET, \
-- "Array item of KCPU Queue enqueues Set on Cross Queue Sync Object", \
-+ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT, \
-+ "KCPU Queue enqueues Wait on Cross Queue Sync Object", \
-+ "@pLII", \
-+ "kcpu_queue,cqs_obj_gpu_addr,cqs_obj_compare_value,cqs_obj_inherit_error") \
-+ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET, \
-+ "KCPU Queue enqueues Set on Cross Queue Sync Object", \
- "@pL", \
- "kcpu_queue,cqs_obj_gpu_addr") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_SET, \
-- "End array of KCPU Queue enqueues Set on Cross Queue Sync Object", \
-- "@p", \
-- "kcpu_queue") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_DEBUGCOPY, \
-- "Begin array of KCPU Queue enqueues Debug Copy", \
-- "@p", \
-- "kcpu_queue") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_DEBUGCOPY, \
-- "Array item of KCPU Queue enqueues Debug Copy", \
-- "@pL", \
-- "kcpu_queue,debugcopy_dst_size") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_DEBUGCOPY, \
-- "End array of KCPU Queue enqueues Debug Copy", \
-- "@p", \
-- "kcpu_queue") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT, \
- "KCPU Queue enqueues Map Import", \
- "@pL", \
-@@ -388,6 +361,14 @@ enum tl_msg_id_aux {
- "KCPU Queue enqueues Unmap Import ignoring reference count", \
- "@pL", \
- "kcpu_queue,map_import_buf_gpu_addr") \
-+ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER, \
-+ "KCPU Queue enqueues Error Barrier", \
-+ "@p", \
-+ "kcpu_queue") \
-+ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND, \
-+ "KCPU Queue enqueues Group Suspend", \
-+ "@ppI", \
-+ "kcpu_queue,group_suspend_buf,gpu_cmdq_grp_handle") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC, \
- "Begin array of KCPU Queue enqueues JIT Alloc", \
- "@p", \
-@@ -418,60 +399,52 @@ enum tl_msg_id_aux {
- "kcpu_queue") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END, \
- "KCPU Queue ends a Signal on Fence", \
-- "@p", \
-- "kcpu_queue") \
-+ "@pI", \
-+ "kcpu_queue,execute_error") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_START, \
- "KCPU Queue starts a Wait on Fence", \
- "@p", \
- "kcpu_queue") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_END, \
- "KCPU Queue ends a Wait on Fence", \
-- "@p", \
-- "kcpu_queue") \
-+ "@pI", \
-+ "kcpu_queue,execute_error") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START, \
- "KCPU Queue starts a Wait on an array of Cross Queue Sync Objects", \
- "@p", \
- "kcpu_queue") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END, \
- "KCPU Queue ends a Wait on an array of Cross Queue Sync Objects", \
-- "@p", \
-- "kcpu_queue") \
-+ "@pI", \
-+ "kcpu_queue,execute_error") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET, \
- "KCPU Queue executes a Set on an array of Cross Queue Sync Objects", \
-- "@p", \
-- "kcpu_queue") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_START, \
-- "KCPU Queue starts an array of Debug Copys", \
-- "@p", \
-- "kcpu_queue") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_END, \
-- "KCPU Queue ends an array of Debug Copys", \
-- "@p", \
-- "kcpu_queue") \
-+ "@pI", \
-+ "kcpu_queue,execute_error") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START, \
- "KCPU Queue starts a Map Import", \
- "@p", \
- "kcpu_queue") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END, \
- "KCPU Queue ends a Map Import", \
-- "@p", \
-- "kcpu_queue") \
-+ "@pI", \
-+ "kcpu_queue,execute_error") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_START, \
- "KCPU Queue starts an Unmap Import", \
- "@p", \
- "kcpu_queue") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_END, \
- "KCPU Queue ends an Unmap Import", \
-- "@p", \
-- "kcpu_queue") \
-+ "@pI", \
-+ "kcpu_queue,execute_error") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_START, \
- "KCPU Queue starts an Unmap Import ignoring reference count", \
- "@p", \
- "kcpu_queue") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_END, \
- "KCPU Queue ends an Unmap Import ignoring reference count", \
-- "@p", \
-- "kcpu_queue") \
-+ "@pI", \
-+ "kcpu_queue,execute_error") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_START, \
- "KCPU Queue starts an array of JIT Allocs", \
- "@p", \
-@@ -482,8 +455,8 @@ enum tl_msg_id_aux {
- "kcpu_queue") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_ALLOC_END, \
- "Array item of KCPU Queue ends an array of JIT Allocs", \
-- "@pLL", \
-- "kcpu_queue,jit_alloc_gpu_alloc_addr,jit_alloc_mmu_flags") \
-+ "@pILL", \
-+ "kcpu_queue,execute_error,jit_alloc_gpu_alloc_addr,jit_alloc_mmu_flags") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_ALLOC_END, \
- "End array of KCPU Queue ends an array of JIT Allocs", \
- "@p", \
-@@ -498,20 +471,32 @@ enum tl_msg_id_aux {
- "kcpu_queue") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END, \
- "Array item of KCPU Queue ends an array of JIT Frees", \
-- "@pL", \
-- "kcpu_queue,jit_free_pages_used") \
-+ "@pIL", \
-+ "kcpu_queue,execute_error,jit_free_pages_used") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_FREE_END, \
- "End array of KCPU Queue ends an array of JIT Frees", \
- "@p", \
- "kcpu_queue") \
-- TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_ERRORBARRIER, \
-+ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER, \
- "KCPU Queue executes an Error Barrier", \
- "@p", \
- "kcpu_queue") \
-+ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START, \
-+ "KCPU Queue starts a group suspend", \
-+ "@p", \
-+ "kcpu_queue") \
-+ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END, \
-+ "KCPU Queue ends a group suspend", \
-+ "@pI", \
-+ "kcpu_queue,execute_error") \
- TRACEPOINT_DESC(KBASE_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW, \
- "An overflow has happened with the CSFFW Timeline stream", \
- "@LL", \
- "csffw_timestamp,csffw_cycle") \
-+ TRACEPOINT_DESC(KBASE_TL_KBASE_CSFFW_RESET, \
-+ "A reset has happened with the CSFFW", \
-+ "@L", \
-+ "csffw_cycle") \
-
- #define MIPE_HEADER_BLOB_VAR_NAME __obj_desc_header
- #define MIPE_HEADER_STREAM_ID TL_STREAM_ID_KERNEL
-@@ -561,6 +546,10 @@ const size_t obj_desc_header_size = sizeof(__obj_desc_header);
- "per-bin JIT statistics", \
- "@IIIIII", \
- "ctx_nr,bid,max_allocs,allocs,va_pages,ph_pages") \
-+ TRACEPOINT_DESC(KBASE_AUX_TILER_HEAP_STATS, \
-+ "Tiler Heap statistics", \
-+ "@ILIIIIIII", \
-+ "ctx_nr,heap_id,va_pages,ph_pages,max_chunks,chunk_size,chunk_count,target_in_flight,nr_in_flight") \
- TRACEPOINT_DESC(KBASE_AUX_EVENT_JOB_SLOT, \
- "event on a given job slot", \
- "@pIII", \
-@@ -1493,11 +1482,33 @@ void __kbase_tlstream_tl_event_atom_softjob_end(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_event_arb_granted(
-+void __kbase_tlstream_tl_arbiter_granted(
-+ struct kbase_tlstream *stream,
-+ const void *gpu)
-+{
-+ const u32 msg_id = KBASE_TL_ARBITER_GRANTED;
-+ const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-+ + sizeof(gpu)
-+ ;
-+ char *buffer;
-+ unsigned long acq_flags;
-+ size_t pos = 0;
-+
-+ buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
-+
-+ pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-+ pos = kbasep_serialize_timestamp(buffer, pos);
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &gpu, sizeof(gpu));
-+
-+ kbase_tlstream_msgbuf_release(stream, acq_flags);
-+}
-+
-+void __kbase_tlstream_tl_arbiter_started(
- struct kbase_tlstream *stream,
- const void *gpu)
- {
-- const u32 msg_id = KBASE_TL_EVENT_ARB_GRANTED;
-+ const u32 msg_id = KBASE_TL_ARBITER_STARTED;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(gpu)
- ;
-@@ -1515,11 +1526,11 @@ void __kbase_tlstream_tl_event_arb_granted(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_event_arb_started(
-+void __kbase_tlstream_tl_arbiter_stop_requested(
- struct kbase_tlstream *stream,
- const void *gpu)
- {
-- const u32 msg_id = KBASE_TL_EVENT_ARB_STARTED;
-+ const u32 msg_id = KBASE_TL_ARBITER_STOP_REQUESTED;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(gpu)
- ;
-@@ -1537,11 +1548,11 @@ void __kbase_tlstream_tl_event_arb_started(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_event_arb_stop_requested(
-+void __kbase_tlstream_tl_arbiter_stopped(
- struct kbase_tlstream *stream,
- const void *gpu)
- {
-- const u32 msg_id = KBASE_TL_EVENT_ARB_STOP_REQUESTED;
-+ const u32 msg_id = KBASE_TL_ARBITER_STOPPED;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(gpu)
- ;
-@@ -1559,11 +1570,11 @@ void __kbase_tlstream_tl_event_arb_stop_requested(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_event_arb_stopped(
-+void __kbase_tlstream_tl_arbiter_requested(
- struct kbase_tlstream *stream,
- const void *gpu)
- {
-- const u32 msg_id = KBASE_TL_EVENT_ARB_STOPPED;
-+ const u32 msg_id = KBASE_TL_ARBITER_REQUESTED;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(gpu)
- ;
-@@ -1837,6 +1848,60 @@ void __kbase_tlstream_aux_jit_stats(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
-+void __kbase_tlstream_aux_tiler_heap_stats(
-+ struct kbase_tlstream *stream,
-+ u32 ctx_nr,
-+ u64 heap_id,
-+ u32 va_pages,
-+ u32 ph_pages,
-+ u32 max_chunks,
-+ u32 chunk_size,
-+ u32 chunk_count,
-+ u32 target_in_flight,
-+ u32 nr_in_flight)
-+{
-+ const u32 msg_id = KBASE_AUX_TILER_HEAP_STATS;
-+ const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-+ + sizeof(ctx_nr)
-+ + sizeof(heap_id)
-+ + sizeof(va_pages)
-+ + sizeof(ph_pages)
-+ + sizeof(max_chunks)
-+ + sizeof(chunk_size)
-+ + sizeof(chunk_count)
-+ + sizeof(target_in_flight)
-+ + sizeof(nr_in_flight)
-+ ;
-+ char *buffer;
-+ unsigned long acq_flags;
-+ size_t pos = 0;
-+
-+ buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
-+
-+ pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-+ pos = kbasep_serialize_timestamp(buffer, pos);
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &ctx_nr, sizeof(ctx_nr));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &heap_id, sizeof(heap_id));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &va_pages, sizeof(va_pages));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &ph_pages, sizeof(ph_pages));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &max_chunks, sizeof(max_chunks));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &chunk_size, sizeof(chunk_size));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &chunk_count, sizeof(chunk_count));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &target_in_flight, sizeof(target_in_flight));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &nr_in_flight, sizeof(nr_in_flight));
-+
-+ kbase_tlstream_msgbuf_release(stream, acq_flags);
-+}
-+
- void __kbase_tlstream_aux_event_job_slot(
- struct kbase_tlstream *stream,
- const void *ctx,
-@@ -2161,39 +2226,19 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_wait(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_cqs_wait(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
--{
-- const u32 msg_id = KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_WAIT;
-- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-- + sizeof(kcpu_queue)
-- ;
-- char *buffer;
-- unsigned long acq_flags;
-- size_t pos = 0;
--
-- buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
--
-- pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-- pos = kbasep_serialize_timestamp(buffer, pos);
-- pos = kbasep_serialize_bytes(buffer,
-- pos, &kcpu_queue, sizeof(kcpu_queue));
--
-- kbase_tlstream_msgbuf_release(stream, acq_flags);
--}
--
--void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_cqs_wait(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_cqs_wait(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
- u64 cqs_obj_gpu_addr,
-- u32 cqs_obj_compare_value)
-+ u32 cqs_obj_compare_value,
-+ u32 cqs_obj_inherit_error)
- {
-- const u32 msg_id = KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_WAIT;
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
- + sizeof(cqs_obj_gpu_addr)
- + sizeof(cqs_obj_compare_value)
-+ + sizeof(cqs_obj_inherit_error)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2209,60 +2254,18 @@ void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_cqs_wait(
- pos, &cqs_obj_gpu_addr, sizeof(cqs_obj_gpu_addr));
- pos = kbasep_serialize_bytes(buffer,
- pos, &cqs_obj_compare_value, sizeof(cqs_obj_compare_value));
--
-- kbase_tlstream_msgbuf_release(stream, acq_flags);
--}
--
--void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_cqs_wait(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
--{
-- const u32 msg_id = KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_WAIT;
-- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-- + sizeof(kcpu_queue)
-- ;
-- char *buffer;
-- unsigned long acq_flags;
-- size_t pos = 0;
--
-- buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
--
-- pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-- pos = kbasep_serialize_timestamp(buffer, pos);
-- pos = kbasep_serialize_bytes(buffer,
-- pos, &kcpu_queue, sizeof(kcpu_queue));
--
-- kbase_tlstream_msgbuf_release(stream, acq_flags);
--}
--
--void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_cqs_set(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
--{
-- const u32 msg_id = KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_SET;
-- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-- + sizeof(kcpu_queue)
-- ;
-- char *buffer;
-- unsigned long acq_flags;
-- size_t pos = 0;
--
-- buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
--
-- pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
-- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos, &cqs_obj_inherit_error, sizeof(cqs_obj_inherit_error));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_cqs_set(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_cqs_set(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
- u64 cqs_obj_gpu_addr)
- {
-- const u32 msg_id = KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_SET;
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
- + sizeof(cqs_obj_gpu_addr)
-@@ -2283,13 +2286,15 @@ void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_cqs_set(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_cqs_set(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_map_import(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
-+ const void *kcpu_queue,
-+ u64 map_import_buf_gpu_addr)
- {
-- const u32 msg_id = KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_SET;
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(map_import_buf_gpu_addr)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2301,41 +2306,21 @@ void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_cqs_set(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
--
-- kbase_tlstream_msgbuf_release(stream, acq_flags);
--}
--
--void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_debugcopy(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
--{
-- const u32 msg_id = KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_DEBUGCOPY;
-- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-- + sizeof(kcpu_queue)
-- ;
-- char *buffer;
-- unsigned long acq_flags;
-- size_t pos = 0;
--
-- buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
--
-- pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
-- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos, &map_import_buf_gpu_addr, sizeof(map_import_buf_gpu_addr));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_debugcopy(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
-- u64 debugcopy_dst_size)
-+ u64 map_import_buf_gpu_addr)
- {
-- const u32 msg_id = KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_DEBUGCOPY;
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-- + sizeof(debugcopy_dst_size)
-+ + sizeof(map_import_buf_gpu_addr)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2348,39 +2333,17 @@ void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_debugcopy(
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
- pos = kbasep_serialize_bytes(buffer,
-- pos, &debugcopy_dst_size, sizeof(debugcopy_dst_size));
--
-- kbase_tlstream_msgbuf_release(stream, acq_flags);
--}
--
--void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_debugcopy(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
--{
-- const u32 msg_id = KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_DEBUGCOPY;
-- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-- + sizeof(kcpu_queue)
-- ;
-- char *buffer;
-- unsigned long acq_flags;
-- size_t pos = 0;
--
-- buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
--
-- pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-- pos = kbasep_serialize_timestamp(buffer, pos);
-- pos = kbasep_serialize_bytes(buffer,
-- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos, &map_import_buf_gpu_addr, sizeof(map_import_buf_gpu_addr));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_map_import(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import_force(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
- u64 map_import_buf_gpu_addr)
- {
-- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT;
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
- + sizeof(map_import_buf_gpu_addr)
-@@ -2401,15 +2364,13 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_map_import(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_error_barrier(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue,
-- u64 map_import_buf_gpu_addr)
-+ const void *kcpu_queue)
- {
-- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT;
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-- + sizeof(map_import_buf_gpu_addr)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2421,21 +2382,21 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-- pos = kbasep_serialize_bytes(buffer,
-- pos, &map_import_buf_gpu_addr, sizeof(map_import_buf_gpu_addr));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import_force(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_group_suspend(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
-- u64 map_import_buf_gpu_addr)
-+ const void *group_suspend_buf,
-+ u32 gpu_cmdq_grp_handle)
- {
-- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE;
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-- + sizeof(map_import_buf_gpu_addr)
-+ + sizeof(group_suspend_buf)
-+ + sizeof(gpu_cmdq_grp_handle)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2448,7 +2409,9 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import_force(
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
- pos = kbasep_serialize_bytes(buffer,
-- pos, &map_import_buf_gpu_addr, sizeof(map_import_buf_gpu_addr));
-+ pos, &group_suspend_buf, sizeof(group_suspend_buf));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &gpu_cmdq_grp_handle, sizeof(gpu_cmdq_grp_handle));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-@@ -2649,11 +2612,13 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_signal_start(
-
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_signal_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
-+ const void *kcpu_queue,
-+ u32 execute_error)
- {
- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2665,6 +2630,8 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_signal_end(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &execute_error, sizeof(execute_error));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-@@ -2693,11 +2660,13 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_wait_start(
-
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_wait_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
-+ const void *kcpu_queue,
-+ u32 execute_error)
- {
- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_END;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2709,6 +2678,8 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_wait_end(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &execute_error, sizeof(execute_error));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-@@ -2737,11 +2708,13 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_wait_start(
-
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_wait_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
-+ const void *kcpu_queue,
-+ u32 execute_error)
- {
- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2753,17 +2726,21 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_wait_end(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &execute_error, sizeof(execute_error));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_set(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
-+ const void *kcpu_queue,
-+ u32 execute_error)
- {
- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2775,50 +2752,8 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_set(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
--
-- kbase_tlstream_msgbuf_release(stream, acq_flags);
--}
--
--void __kbase_tlstream_tl_kbase_kcpuqueue_execute_debugcopy_start(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
--{
-- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_START;
-- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-- + sizeof(kcpu_queue)
-- ;
-- char *buffer;
-- unsigned long acq_flags;
-- size_t pos = 0;
--
-- buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
--
-- pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-- pos = kbasep_serialize_timestamp(buffer, pos);
-- pos = kbasep_serialize_bytes(buffer,
-- pos, &kcpu_queue, sizeof(kcpu_queue));
--
-- kbase_tlstream_msgbuf_release(stream, acq_flags);
--}
--
--void __kbase_tlstream_tl_kbase_kcpuqueue_execute_debugcopy_end(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
--{
-- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_END;
-- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-- + sizeof(kcpu_queue)
-- ;
-- char *buffer;
-- unsigned long acq_flags;
-- size_t pos = 0;
--
-- buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
--
-- pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
-- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos, &execute_error, sizeof(execute_error));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-@@ -2847,11 +2782,13 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_map_import_start(
-
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_map_import_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
-+ const void *kcpu_queue,
-+ u32 execute_error)
- {
- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2863,6 +2800,8 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_map_import_end(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &execute_error, sizeof(execute_error));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-@@ -2891,11 +2830,13 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_start(
-
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
-+ const void *kcpu_queue,
-+ u32 execute_error)
- {
- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_END;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2907,6 +2848,8 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_end(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &execute_error, sizeof(execute_error));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-@@ -2935,11 +2878,13 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_force_start(
-
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_force_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue)
-+ const void *kcpu_queue,
-+ u32 execute_error)
- {
- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_END;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -2951,6 +2896,8 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_force_end(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &execute_error, sizeof(execute_error));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-@@ -3002,12 +2949,14 @@ void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_execute_jit_alloc_end(
- void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_execute_jit_alloc_end(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
-+ u32 execute_error,
- u64 jit_alloc_gpu_alloc_addr,
- u64 jit_alloc_mmu_flags)
- {
- const u32 msg_id = KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_ALLOC_END;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- + sizeof(jit_alloc_gpu_alloc_addr)
- + sizeof(jit_alloc_mmu_flags)
- ;
-@@ -3021,6 +2970,8 @@ void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_execute_jit_alloc_end(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &execute_error, sizeof(execute_error));
- pos = kbasep_serialize_bytes(buffer,
- pos, &jit_alloc_gpu_alloc_addr, sizeof(jit_alloc_gpu_alloc_addr));
- pos = kbasep_serialize_bytes(buffer,
-@@ -3098,11 +3049,13 @@ void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_execute_jit_free_end(
- void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_execute_jit_free_end(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
-+ u32 execute_error,
- u64 jit_free_pages_used)
- {
- const u32 msg_id = KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- + sizeof(jit_free_pages_used)
- ;
- char *buffer;
-@@ -3115,6 +3068,8 @@ void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_execute_jit_free_end(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &execute_error, sizeof(execute_error));
- pos = kbasep_serialize_bytes(buffer,
- pos, &jit_free_pages_used, sizeof(jit_free_pages_used));
-
-@@ -3143,13 +3098,59 @@ void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_execute_jit_free_end(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
--void __kbase_tlstream_tl_kbase_kcpuqueue_execute_errorbarrier(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_execute_error_barrier(
-+ struct kbase_tlstream *stream,
-+ const void *kcpu_queue)
-+{
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER;
-+ const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-+ + sizeof(kcpu_queue)
-+ ;
-+ char *buffer;
-+ unsigned long acq_flags;
-+ size_t pos = 0;
-+
-+ buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
-+
-+ pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-+ pos = kbasep_serialize_timestamp(buffer, pos);
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &kcpu_queue, sizeof(kcpu_queue));
-+
-+ kbase_tlstream_msgbuf_release(stream, acq_flags);
-+}
-+
-+void __kbase_tlstream_tl_kbase_kcpuqueue_execute_group_suspend_start(
- struct kbase_tlstream *stream,
- const void *kcpu_queue)
- {
-- const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_ERRORBARRIER;
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START;
-+ const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-+ + sizeof(kcpu_queue)
-+ ;
-+ char *buffer;
-+ unsigned long acq_flags;
-+ size_t pos = 0;
-+
-+ buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
-+
-+ pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-+ pos = kbasep_serialize_timestamp(buffer, pos);
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &kcpu_queue, sizeof(kcpu_queue));
-+
-+ kbase_tlstream_msgbuf_release(stream, acq_flags);
-+}
-+
-+void __kbase_tlstream_tl_kbase_kcpuqueue_execute_group_suspend_end(
-+ struct kbase_tlstream *stream,
-+ const void *kcpu_queue,
-+ u32 execute_error)
-+{
-+ const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END;
- const size_t msg_size = sizeof(msg_id) + sizeof(u64)
- + sizeof(kcpu_queue)
-+ + sizeof(execute_error)
- ;
- char *buffer;
- unsigned long acq_flags;
-@@ -3161,6 +3162,8 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_errorbarrier(
- pos = kbasep_serialize_timestamp(buffer, pos);
- pos = kbasep_serialize_bytes(buffer,
- pos, &kcpu_queue, sizeof(kcpu_queue));
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &execute_error, sizeof(execute_error));
-
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-@@ -3191,4 +3194,26 @@ void __kbase_tlstream_tl_kbase_csffw_tlstream_overflow(
- kbase_tlstream_msgbuf_release(stream, acq_flags);
- }
-
-+void __kbase_tlstream_tl_kbase_csffw_reset(
-+ struct kbase_tlstream *stream,
-+ u64 csffw_cycle)
-+{
-+ const u32 msg_id = KBASE_TL_KBASE_CSFFW_RESET;
-+ const size_t msg_size = sizeof(msg_id) + sizeof(u64)
-+ + sizeof(csffw_cycle)
-+ ;
-+ char *buffer;
-+ unsigned long acq_flags;
-+ size_t pos = 0;
-+
-+ buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
-+
-+ pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
-+ pos = kbasep_serialize_timestamp(buffer, pos);
-+ pos = kbasep_serialize_bytes(buffer,
-+ pos, &csffw_cycle, sizeof(csffw_cycle));
-+
-+ kbase_tlstream_msgbuf_release(stream, acq_flags);
-+}
-+
- /* clang-format on */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tracepoints.h b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tracepoints.h
-index 7ea8ba8..887a1aa 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tracepoints.h
-+++ b/dvalin/kernel/drivers/gpu/arm/midgard/tl/mali_kbase_tracepoints.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- /*
-@@ -226,16 +225,19 @@ void __kbase_tlstream_tl_event_atom_softjob_start(
- void __kbase_tlstream_tl_event_atom_softjob_end(
- struct kbase_tlstream *stream,
- const void *atom);
--void __kbase_tlstream_tl_event_arb_granted(
-+void __kbase_tlstream_tl_arbiter_granted(
-+ struct kbase_tlstream *stream,
-+ const void *gpu);
-+void __kbase_tlstream_tl_arbiter_started(
- struct kbase_tlstream *stream,
- const void *gpu);
--void __kbase_tlstream_tl_event_arb_started(
-+void __kbase_tlstream_tl_arbiter_stop_requested(
- struct kbase_tlstream *stream,
- const void *gpu);
--void __kbase_tlstream_tl_event_arb_stop_requested(
-+void __kbase_tlstream_tl_arbiter_stopped(
- struct kbase_tlstream *stream,
- const void *gpu);
--void __kbase_tlstream_tl_event_arb_stopped(
-+void __kbase_tlstream_tl_arbiter_requested(
- struct kbase_tlstream *stream,
- const void *gpu);
- void __kbase_tlstream_jd_gpu_soft_reset(
-@@ -277,6 +279,17 @@ void __kbase_tlstream_aux_jit_stats(
- u32 allocs,
- u32 va_pages,
- u32 ph_pages);
-+void __kbase_tlstream_aux_tiler_heap_stats(
-+ struct kbase_tlstream *stream,
-+ u32 ctx_nr,
-+ u64 heap_id,
-+ u32 va_pages,
-+ u32 ph_pages,
-+ u32 max_chunks,
-+ u32 chunk_size,
-+ u32 chunk_count,
-+ u32 target_in_flight,
-+ u32 nr_in_flight);
- void __kbase_tlstream_aux_event_job_slot(
- struct kbase_tlstream *stream,
- const void *ctx,
-@@ -328,37 +341,16 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_wait(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
- const void *fence);
--void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_cqs_wait(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
--void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_cqs_wait(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_cqs_wait(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
- u64 cqs_obj_gpu_addr,
-- u32 cqs_obj_compare_value);
--void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_cqs_wait(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
--void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_cqs_set(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
--void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_cqs_set(
-+ u32 cqs_obj_compare_value,
-+ u32 cqs_obj_inherit_error);
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_cqs_set(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
- u64 cqs_obj_gpu_addr);
--void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_cqs_set(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
--void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_debugcopy(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
--void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_debugcopy(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue,
-- u64 debugcopy_dst_size);
--void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_debugcopy(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
- void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_map_import(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
-@@ -371,6 +363,14 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import_force(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
- u64 map_import_buf_gpu_addr);
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_error_barrier(
-+ struct kbase_tlstream *stream,
-+ const void *kcpu_queue);
-+void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_group_suspend(
-+ struct kbase_tlstream *stream,
-+ const void *kcpu_queue,
-+ const void *group_suspend_buf,
-+ u32 gpu_cmdq_grp_handle);
- void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_jit_alloc(
- struct kbase_tlstream *stream,
- const void *kcpu_queue);
-@@ -404,46 +404,47 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_signal_start(
- const void *kcpu_queue);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_signal_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
-+ const void *kcpu_queue,
-+ u32 execute_error);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_wait_start(
- struct kbase_tlstream *stream,
- const void *kcpu_queue);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_wait_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
-+ const void *kcpu_queue,
-+ u32 execute_error);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_wait_start(
- struct kbase_tlstream *stream,
- const void *kcpu_queue);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_wait_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
-+ const void *kcpu_queue,
-+ u32 execute_error);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_set(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
--void __kbase_tlstream_tl_kbase_kcpuqueue_execute_debugcopy_start(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
--void __kbase_tlstream_tl_kbase_kcpuqueue_execute_debugcopy_end(
-- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
-+ const void *kcpu_queue,
-+ u32 execute_error);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_map_import_start(
- struct kbase_tlstream *stream,
- const void *kcpu_queue);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_map_import_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
-+ const void *kcpu_queue,
-+ u32 execute_error);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_start(
- struct kbase_tlstream *stream,
- const void *kcpu_queue);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
-+ const void *kcpu_queue,
-+ u32 execute_error);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_force_start(
- struct kbase_tlstream *stream,
- const void *kcpu_queue);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_force_end(
- struct kbase_tlstream *stream,
-- const void *kcpu_queue);
-+ const void *kcpu_queue,
-+ u32 execute_error);
- void __kbase_tlstream_tl_kbase_kcpuqueue_execute_jit_alloc_start(
- struct kbase_tlstream *stream,
- const void *kcpu_queue);
-@@ -453,6 +454,7 @@ void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_execute_jit_alloc_end(
- void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_execute_jit_alloc_end(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
-+ u32 execute_error,
- u64 jit_alloc_gpu_alloc_addr,
- u64 jit_alloc_mmu_flags);
- void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_execute_jit_alloc_end(
-@@ -467,17 +469,28 @@ void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_execute_jit_free_end(
- void __kbase_tlstream_tl_kbase_array_item_kcpuqueue_execute_jit_free_end(
- struct kbase_tlstream *stream,
- const void *kcpu_queue,
-+ u32 execute_error,
- u64 jit_free_pages_used);
- void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_execute_jit_free_end(
- struct kbase_tlstream *stream,
- const void *kcpu_queue);
--void __kbase_tlstream_tl_kbase_kcpuqueue_execute_errorbarrier(
-+void __kbase_tlstream_tl_kbase_kcpuqueue_execute_error_barrier(
-+ struct kbase_tlstream *stream,
-+ const void *kcpu_queue);
-+void __kbase_tlstream_tl_kbase_kcpuqueue_execute_group_suspend_start(
- struct kbase_tlstream *stream,
- const void *kcpu_queue);
-+void __kbase_tlstream_tl_kbase_kcpuqueue_execute_group_suspend_end(
-+ struct kbase_tlstream *stream,
-+ const void *kcpu_queue,
-+ u32 execute_error);
- void __kbase_tlstream_tl_kbase_csffw_tlstream_overflow(
- struct kbase_tlstream *stream,
- u64 csffw_timestamp,
- u64 csffw_cycle);
-+void __kbase_tlstream_tl_kbase_csffw_reset(
-+ struct kbase_tlstream *stream,
-+ u64 csffw_cycle);
-
- struct kbase_tlstream;
-
-@@ -1215,77 +1228,96 @@ struct kbase_tlstream;
- } while (0)
-
- /**
-- * KBASE_TLSTREAM_TL_EVENT_ARB_GRANTED -
-+ * KBASE_TLSTREAM_TL_ARBITER_GRANTED -
- * Arbiter has granted gpu access
- *
- * @kbdev: Kbase device
- * @gpu: Name of the GPU object
- */
--#define KBASE_TLSTREAM_TL_EVENT_ARB_GRANTED( \
-+#define KBASE_TLSTREAM_TL_ARBITER_GRANTED( \
- kbdev, \
- gpu \
- ) \
- do { \
- int enabled = atomic_read(&kbdev->timeline_flags); \
- if (enabled & TLSTREAM_ENABLED) \
-- __kbase_tlstream_tl_event_arb_granted( \
-+ __kbase_tlstream_tl_arbiter_granted( \
- __TL_DISPATCH_STREAM(kbdev, obj), \
- gpu); \
- } while (0)
-
- /**
-- * KBASE_TLSTREAM_TL_EVENT_ARB_STARTED -
-+ * KBASE_TLSTREAM_TL_ARBITER_STARTED -
- * Driver is running again and able to process jobs
- *
- * @kbdev: Kbase device
- * @gpu: Name of the GPU object
- */
--#define KBASE_TLSTREAM_TL_EVENT_ARB_STARTED( \
-+#define KBASE_TLSTREAM_TL_ARBITER_STARTED( \
- kbdev, \
- gpu \
- ) \
- do { \
- int enabled = atomic_read(&kbdev->timeline_flags); \
- if (enabled & TLSTREAM_ENABLED) \
-- __kbase_tlstream_tl_event_arb_started( \
-+ __kbase_tlstream_tl_arbiter_started( \
- __TL_DISPATCH_STREAM(kbdev, obj), \
- gpu); \
- } while (0)
-
- /**
-- * KBASE_TLSTREAM_TL_EVENT_ARB_STOP_REQUESTED -
-+ * KBASE_TLSTREAM_TL_ARBITER_STOP_REQUESTED -
- * Arbiter has requested driver to stop using gpu
- *
- * @kbdev: Kbase device
- * @gpu: Name of the GPU object
- */
--#define KBASE_TLSTREAM_TL_EVENT_ARB_STOP_REQUESTED( \
-+#define KBASE_TLSTREAM_TL_ARBITER_STOP_REQUESTED( \
- kbdev, \
- gpu \
- ) \
- do { \
- int enabled = atomic_read(&kbdev->timeline_flags); \
- if (enabled & TLSTREAM_ENABLED) \
-- __kbase_tlstream_tl_event_arb_stop_requested( \
-+ __kbase_tlstream_tl_arbiter_stop_requested( \
- __TL_DISPATCH_STREAM(kbdev, obj), \
- gpu); \
- } while (0)
-
- /**
-- * KBASE_TLSTREAM_TL_EVENT_ARB_STOPPED -
-+ * KBASE_TLSTREAM_TL_ARBITER_STOPPED -
- * Driver has stopped using gpu
- *
- * @kbdev: Kbase device
- * @gpu: Name of the GPU object
- */
--#define KBASE_TLSTREAM_TL_EVENT_ARB_STOPPED( \
-+#define KBASE_TLSTREAM_TL_ARBITER_STOPPED( \
- kbdev, \
- gpu \
- ) \
- do { \
- int enabled = atomic_read(&kbdev->timeline_flags); \
- if (enabled & TLSTREAM_ENABLED) \
-- __kbase_tlstream_tl_event_arb_stopped( \
-+ __kbase_tlstream_tl_arbiter_stopped( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ gpu); \
-+ } while (0)
-+
-+/**
-+ * KBASE_TLSTREAM_TL_ARBITER_REQUESTED -
-+ * Driver has requested the arbiter for gpu access
-+ *
-+ * @kbdev: Kbase device
-+ * @gpu: Name of the GPU object
-+ */
-+#define KBASE_TLSTREAM_TL_ARBITER_REQUESTED( \
-+ kbdev, \
-+ gpu \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & TLSTREAM_ENABLED) \
-+ __kbase_tlstream_tl_arbiter_requested( \
- __TL_DISPATCH_STREAM(kbdev, obj), \
- gpu); \
- } while (0)
-@@ -1499,6 +1531,42 @@ struct kbase_tlstream;
- ctx_nr, bid, max_allocs, allocs, va_pages, ph_pages); \
- } while (0)
-
-+/**
-+ * KBASE_TLSTREAM_AUX_TILER_HEAP_STATS -
-+ * Tiler Heap statistics
-+ *
-+ * @kbdev: Kbase device
-+ * @ctx_nr: Kernel context number
-+ * @heap_id: Unique id used to represent a heap under a context
-+ * @va_pages: Number of virtual pages allocated in this bin
-+ * @ph_pages: Number of physical pages allocated in this bin
-+ * @max_chunks: The maximum number of chunks that the heap should be allowed to use
-+ * @chunk_size: Size of each chunk in tiler heap, in bytes
-+ * @chunk_count: The number of chunks currently allocated in the tiler heap
-+ * @target_in_flight: Number of render-passes that the driver should attempt
-+ * to keep in flight for which allocation of new chunks is allowed
-+ * @nr_in_flight: Number of render-passes that are in flight
-+ */
-+#define KBASE_TLSTREAM_AUX_TILER_HEAP_STATS( \
-+ kbdev, \
-+ ctx_nr, \
-+ heap_id, \
-+ va_pages, \
-+ ph_pages, \
-+ max_chunks, \
-+ chunk_size, \
-+ chunk_count, \
-+ target_in_flight, \
-+ nr_in_flight \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & TLSTREAM_ENABLED) \
-+ __kbase_tlstream_aux_tiler_heap_stats( \
-+ __TL_DISPATCH_STREAM(kbdev, aux), \
-+ ctx_nr, heap_id, va_pages, ph_pages, max_chunks, chunk_size, chunk_count, target_in_flight, nr_in_flight); \
-+ } while (0)
-+
- /**
- * KBASE_TLSTREAM_AUX_EVENT_JOB_SLOT -
- * event on a given job slot
-@@ -1534,6 +1602,22 @@ struct kbase_tlstream;
- * @kbase_device_max_num_csgs: The max number of CSGs the physical hardware supports
- * @kbase_device_as_count: The number of address spaces the physical hardware has available
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_NEW_DEVICE( \
-+ kbdev, \
-+ kbase_device_id, \
-+ kbase_device_gpu_core_count, \
-+ kbase_device_max_num_csgs, \
-+ kbase_device_as_count \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_new_device( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kbase_device_id, kbase_device_gpu_core_count, kbase_device_max_num_csgs, kbase_device_as_count); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_NEW_DEVICE( \
- kbdev, \
- kbase_device_id, \
-@@ -1542,6 +1626,7 @@ struct kbase_tlstream;
- kbase_device_as_count \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_DEVICE_PROGRAM_CSG -
-@@ -1552,6 +1637,21 @@ struct kbase_tlstream;
- * @gpu_cmdq_grp_handle: GPU Command Queue Group handle which will match userspace
- * @kbase_device_csg_slot_index: The index of the slot in the scheduler being programmed
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_DEVICE_PROGRAM_CSG( \
-+ kbdev, \
-+ kbase_device_id, \
-+ gpu_cmdq_grp_handle, \
-+ kbase_device_csg_slot_index \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_device_program_csg( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kbase_device_id, gpu_cmdq_grp_handle, kbase_device_csg_slot_index); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_DEVICE_PROGRAM_CSG( \
- kbdev, \
- kbase_device_id, \
-@@ -1559,6 +1659,7 @@ struct kbase_tlstream;
- kbase_device_csg_slot_index \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_DEVICE_DEPROGRAM_CSG -
-@@ -1568,12 +1669,27 @@ struct kbase_tlstream;
- * @kbase_device_id: The id of the physical hardware
- * @kbase_device_csg_slot_index: The index of the slot in the scheduler being programmed
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_DEVICE_DEPROGRAM_CSG( \
-+ kbdev, \
-+ kbase_device_id, \
-+ kbase_device_csg_slot_index \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_device_deprogram_csg( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kbase_device_id, kbase_device_csg_slot_index); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_DEVICE_DEPROGRAM_CSG( \
- kbdev, \
- kbase_device_id, \
- kbase_device_csg_slot_index \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_NEW_CTX -
-@@ -1583,12 +1699,27 @@ struct kbase_tlstream;
- * @kernel_ctx_id: Unique ID for the KBase Context
- * @kbase_device_id: The id of the physical hardware
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_NEW_CTX( \
-+ kbdev, \
-+ kernel_ctx_id, \
-+ kbase_device_id \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_new_ctx( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kernel_ctx_id, kbase_device_id); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_NEW_CTX( \
- kbdev, \
- kernel_ctx_id, \
- kbase_device_id \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_DEL_CTX -
-@@ -1597,11 +1728,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kernel_ctx_id: Unique ID for the KBase Context
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_DEL_CTX( \
-+ kbdev, \
-+ kernel_ctx_id \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_del_ctx( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kernel_ctx_id); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_DEL_CTX( \
- kbdev, \
- kernel_ctx_id \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_CTX_ASSIGN_AS -
-@@ -1611,12 +1756,27 @@ struct kbase_tlstream;
- * @kernel_ctx_id: Unique ID for the KBase Context
- * @kbase_device_as_index: The index of the device address space being assigned
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_CTX_ASSIGN_AS( \
-+ kbdev, \
-+ kernel_ctx_id, \
-+ kbase_device_as_index \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_ctx_assign_as( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kernel_ctx_id, kbase_device_as_index); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_CTX_ASSIGN_AS( \
- kbdev, \
- kernel_ctx_id, \
- kbase_device_as_index \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_CTX_UNASSIGN_AS -
-@@ -1625,11 +1785,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kernel_ctx_id: Unique ID for the KBase Context
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_CTX_UNASSIGN_AS( \
-+ kbdev, \
-+ kernel_ctx_id \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_ctx_unassign_as( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kernel_ctx_id); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_CTX_UNASSIGN_AS( \
- kbdev, \
- kernel_ctx_id \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_NEW_KCPUQUEUE -
-@@ -1641,6 +1815,21 @@ struct kbase_tlstream;
- * @kcpuq_num_pending_cmds: Number of commands already enqueued
- * in the KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_NEW_KCPUQUEUE( \
-+ kbdev, \
-+ kcpu_queue, \
-+ kernel_ctx_id, \
-+ kcpuq_num_pending_cmds \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_new_kcpuqueue( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, kernel_ctx_id, kcpuq_num_pending_cmds); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_NEW_KCPUQUEUE( \
- kbdev, \
- kcpu_queue, \
-@@ -1648,6 +1837,7 @@ struct kbase_tlstream;
- kcpuq_num_pending_cmds \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_DEL_KCPUQUEUE -
-@@ -1656,11 +1846,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_DEL_KCPUQUEUE( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_del_kcpuqueue( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_DEL_KCPUQUEUE( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_SIGNAL -
-@@ -1670,12 +1874,27 @@ struct kbase_tlstream;
- * @kcpu_queue: KCPU queue
- * @fence: Fence object handle
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_SIGNAL( \
-+ kbdev, \
-+ kcpu_queue, \
-+ fence \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_signal( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, fence); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_SIGNAL( \
- kbdev, \
- kcpu_queue, \
- fence \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT -
-@@ -1685,183 +1904,244 @@ struct kbase_tlstream;
- * @kcpu_queue: KCPU queue
- * @fence: Fence object handle
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT( \
- kbdev, \
- kcpu_queue, \
- fence \
- ) \
-- do { } while (0)
--
--/**
-- * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_WAIT -
-- * Begin array of KCPU Queue enqueues Wait on Cross Queue Sync Object
-- *
-- * @kbdev: Kbase device
-- * @kcpu_queue: KCPU queue
-- */
--#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_WAIT( \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_wait( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, fence); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ fence \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
-- * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_WAIT -
-- * Array item of KCPU Queue enqueues Wait on Cross Queue Sync Object
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT -
-+ * KCPU Queue enqueues Wait on Cross Queue Sync Object
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-- * @cqs_obj_gpu_addr: CQS Object GPU ptr
-+ * @cqs_obj_gpu_addr: CQS Object GPU pointer
- * @cqs_obj_compare_value: Semaphore value that should be exceeded
- * for the WAIT to pass
-+ * @cqs_obj_inherit_error: Indicates the error state should be inherited into the queue or not
- */
--#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_WAIT( \
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT( \
-+ kbdev, \
-+ kcpu_queue, \
-+ cqs_obj_gpu_addr, \
-+ cqs_obj_compare_value, \
-+ cqs_obj_inherit_error \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_cqs_wait( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, cqs_obj_gpu_addr, cqs_obj_compare_value, cqs_obj_inherit_error); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT( \
- kbdev, \
- kcpu_queue, \
- cqs_obj_gpu_addr, \
-- cqs_obj_compare_value \
-+ cqs_obj_compare_value, \
-+ cqs_obj_inherit_error \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
-- * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_WAIT -
-- * End array of KCPU Queue enqueues Wait on Cross Queue Sync Object
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET -
-+ * KCPU Queue enqueues Set on Cross Queue Sync Object
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @cqs_obj_gpu_addr: CQS Object GPU pointer
- */
--#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_WAIT( \
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ cqs_obj_gpu_addr \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_cqs_set( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, cqs_obj_gpu_addr); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET( \
-+ kbdev, \
-+ kcpu_queue, \
-+ cqs_obj_gpu_addr \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
-- * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_SET -
-- * Begin array of KCPU Queue enqueues Set on Cross Queue Sync Object
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT -
-+ * KCPU Queue enqueues Map Import
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @map_import_buf_gpu_addr: Map import buffer GPU pointer
- */
--#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_CQS_SET( \
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ map_import_buf_gpu_addr \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_map_import( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, map_import_buf_gpu_addr); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT( \
-+ kbdev, \
-+ kcpu_queue, \
-+ map_import_buf_gpu_addr \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
-- * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_SET -
-- * Array item of KCPU Queue enqueues Set on Cross Queue Sync Object
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT -
-+ * KCPU Queue enqueues Unmap Import
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-- * @cqs_obj_gpu_addr: CQS Object GPU ptr
-+ * @map_import_buf_gpu_addr: Map import buffer GPU pointer
- */
--#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_CQS_SET( \
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT( \
- kbdev, \
- kcpu_queue, \
-- cqs_obj_gpu_addr \
-+ map_import_buf_gpu_addr \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, map_import_buf_gpu_addr); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT( \
-+ kbdev, \
-+ kcpu_queue, \
-+ map_import_buf_gpu_addr \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
-- * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_SET -
-- * End array of KCPU Queue enqueues Set on Cross Queue Sync Object
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE -
-+ * KCPU Queue enqueues Unmap Import ignoring reference count
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @map_import_buf_gpu_addr: Map import buffer GPU pointer
- */
--#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_CQS_SET( \
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ map_import_buf_gpu_addr \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import_force( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, map_import_buf_gpu_addr); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE( \
-+ kbdev, \
-+ kcpu_queue, \
-+ map_import_buf_gpu_addr \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
-- * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_DEBUGCOPY -
-- * Begin array of KCPU Queue enqueues Debug Copy
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER -
-+ * KCPU Queue enqueues Error Barrier
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
--#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_DEBUGCOPY( \
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_error_barrier( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
-- * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_DEBUGCOPY -
-- * Array item of KCPU Queue enqueues Debug Copy
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND -
-+ * KCPU Queue enqueues Group Suspend
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-- * @debugcopy_dst_size: Debug Copy destination size
-- */
--#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_DEBUGCOPY( \
-- kbdev, \
-- kcpu_queue, \
-- debugcopy_dst_size \
-- ) \
-- do { } while (0)
--
--/**
-- * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_DEBUGCOPY -
-- * End array of KCPU Queue enqueues Debug Copy
-- *
-- * @kbdev: Kbase device
-- * @kcpu_queue: KCPU queue
-- */
--#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_DEBUGCOPY( \
-- kbdev, \
-- kcpu_queue \
-- ) \
-- do { } while (0)
--
--/**
-- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT -
-- * KCPU Queue enqueues Map Import
-- *
-- * @kbdev: Kbase device
-- * @kcpu_queue: KCPU queue
-- * @map_import_buf_gpu_addr: Map import buffer GPU ptr
-- */
--#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT( \
-- kbdev, \
-- kcpu_queue, \
-- map_import_buf_gpu_addr \
-- ) \
-- do { } while (0)
--
--/**
-- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT -
-- * KCPU Queue enqueues Unmap Import
-- *
-- * @kbdev: Kbase device
-- * @kcpu_queue: KCPU queue
-- * @map_import_buf_gpu_addr: Map import buffer GPU ptr
-+ * @group_suspend_buf: Pointer to the suspend buffer structure
-+ * @gpu_cmdq_grp_handle: GPU Command Queue Group handle which will match userspace
- */
--#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT( \
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND( \
- kbdev, \
- kcpu_queue, \
-- map_import_buf_gpu_addr \
-+ group_suspend_buf, \
-+ gpu_cmdq_grp_handle \
- ) \
-- do { } while (0)
--
--/**
-- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE -
-- * KCPU Queue enqueues Unmap Import ignoring reference count
-- *
-- * @kbdev: Kbase device
-- * @kcpu_queue: KCPU queue
-- * @map_import_buf_gpu_addr: Map import buffer GPU ptr
-- */
--#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE( \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_group_suspend( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, group_suspend_buf, gpu_cmdq_grp_handle); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND( \
- kbdev, \
- kcpu_queue, \
-- map_import_buf_gpu_addr \
-+ group_suspend_buf, \
-+ gpu_cmdq_grp_handle \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC -
-@@ -1870,11 +2150,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_jit_alloc( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_ALLOC -
-@@ -1902,6 +2196,28 @@ struct kbase_tlstream;
- * reused. The kernel should attempt to use a previous allocation with the same
- * usage_id
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \
-+ kbdev, \
-+ kcpu_queue, \
-+ jit_alloc_gpu_alloc_addr_dest, \
-+ jit_alloc_va_pages, \
-+ jit_alloc_commit_pages, \
-+ jit_alloc_extent, \
-+ jit_alloc_jit_id, \
-+ jit_alloc_bin_id, \
-+ jit_alloc_max_allocations, \
-+ jit_alloc_flags, \
-+ jit_alloc_usage_id \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_jit_alloc( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, jit_alloc_gpu_alloc_addr_dest, jit_alloc_va_pages, jit_alloc_commit_pages, jit_alloc_extent, jit_alloc_jit_id, jit_alloc_bin_id, jit_alloc_max_allocations, jit_alloc_flags, jit_alloc_usage_id); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \
- kbdev, \
- kcpu_queue, \
-@@ -1916,6 +2232,7 @@ struct kbase_tlstream;
- jit_alloc_usage_id \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_ALLOC -
-@@ -1924,11 +2241,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_jit_alloc( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_FREE -
-@@ -1937,11 +2268,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_FREE( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_jit_free( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_FREE( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_FREE -
-@@ -1952,12 +2297,27 @@ struct kbase_tlstream;
- * @jit_alloc_jit_id: Unique ID provided by the caller, this is used
- * to pair allocation and free requests. Zero is not a valid value
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_FREE( \
-+ kbdev, \
-+ kcpu_queue, \
-+ jit_alloc_jit_id \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_item_kcpuqueue_enqueue_jit_free( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, jit_alloc_jit_id); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_FREE( \
- kbdev, \
- kcpu_queue, \
- jit_alloc_jit_id \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_FREE -
-@@ -1966,11 +2326,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_FREE( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_jit_free( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_FREE( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START -
-@@ -1979,11 +2353,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_signal_start( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END -
-@@ -1991,12 +2379,29 @@ struct kbase_tlstream;
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ execute_error \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_signal_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_START -
-@@ -2005,11 +2410,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_START( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_wait_start( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_START( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_END -
-@@ -2017,12 +2436,29 @@ struct kbase_tlstream;
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_END( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ execute_error \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_wait_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START -
-@@ -2031,11 +2467,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_wait_start( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END -
-@@ -2043,12 +2493,29 @@ struct kbase_tlstream;
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ execute_error \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_wait_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET -
-@@ -2056,51 +2523,56 @@ struct kbase_tlstream;
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ execute_error \
- ) \
-- do { } while (0)
--
--/**
-- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_START -
-- * KCPU Queue starts an array of Debug Copys
-- *
-- * @kbdev: Kbase device
-- * @kcpu_queue: KCPU queue
-- */
--#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_START( \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_cqs_set( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ execute_error \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
-- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_END -
-- * KCPU Queue ends an array of Debug Copys
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START -
-+ * KCPU Queue starts a Map Import
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
--#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_DEBUGCOPY_END( \
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START( \
- kbdev, \
- kcpu_queue \
- ) \
-- do { } while (0)
--
--/**
-- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START -
-- * KCPU Queue starts a Map Import
-- *
-- * @kbdev: Kbase device
-- * @kcpu_queue: KCPU queue
-- */
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_map_import_start( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END -
-@@ -2108,12 +2580,29 @@ struct kbase_tlstream;
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ execute_error \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_map_import_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_START -
-@@ -2122,11 +2611,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_START( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_start( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_START( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_END -
-@@ -2134,12 +2637,29 @@ struct kbase_tlstream;
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_END( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ execute_error \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_START -
-@@ -2148,11 +2668,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_START( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_force_start( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_START( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_END -
-@@ -2160,12 +2694,29 @@ struct kbase_tlstream;
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_END( \
- kbdev, \
-- kcpu_queue \
-+ kcpu_queue, \
-+ execute_error \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_unmap_import_force_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_START -
-@@ -2174,11 +2725,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_START( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_jit_alloc_start( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_START( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_ALLOC_END -
-@@ -2187,11 +2752,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_execute_jit_alloc_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_ALLOC_END -
-@@ -2199,16 +2778,35 @@ struct kbase_tlstream;
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
- * @jit_alloc_gpu_alloc_addr: The JIT allocated GPU virtual address
- * @jit_alloc_mmu_flags: The MMU flags for the JIT allocation
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \
- kbdev, \
- kcpu_queue, \
-+ execute_error, \
-+ jit_alloc_gpu_alloc_addr, \
-+ jit_alloc_mmu_flags \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_item_kcpuqueue_execute_jit_alloc_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error, jit_alloc_gpu_alloc_addr, jit_alloc_mmu_flags); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error, \
- jit_alloc_gpu_alloc_addr, \
- jit_alloc_mmu_flags \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_ALLOC_END -
-@@ -2217,11 +2815,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_end_kcpuqueue_execute_jit_alloc_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_START -
-@@ -2230,11 +2842,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_START( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_jit_free_start( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_START( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_FREE_END -
-@@ -2243,11 +2869,25 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_FREE_END( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_execute_jit_free_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_FREE_END( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END -
-@@ -2255,15 +2895,33 @@ struct kbase_tlstream;
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
- * @jit_free_pages_used: The actual number of pages used by the JIT
- * allocation
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error, \
-+ jit_free_pages_used \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_item_kcpuqueue_execute_jit_free_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error, jit_free_pages_used); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END( \
- kbdev, \
- kcpu_queue, \
-+ execute_error, \
- jit_free_pages_used \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_FREE_END -
-@@ -2272,24 +2930,109 @@ struct kbase_tlstream;
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_FREE_END( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_array_end_kcpuqueue_execute_jit_free_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
- #define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_FREE_END( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
-- * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_ERRORBARRIER -
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER -
- * KCPU Queue executes an Error Barrier
- *
- * @kbdev: Kbase device
- * @kcpu_queue: KCPU queue
- */
--#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_ERRORBARRIER( \
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_error_barrier( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { } while (0)
-+#endif /* MALI_USE_CSF */
-+
-+/**
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START -
-+ * KCPU Queue starts a group suspend
-+ *
-+ * @kbdev: Kbase device
-+ * @kcpu_queue: KCPU queue
-+ */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START( \
-+ kbdev, \
-+ kcpu_queue \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_group_suspend_start( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START( \
- kbdev, \
- kcpu_queue \
- ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-+
-+/**
-+ * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END -
-+ * KCPU Queue ends a group suspend
-+ *
-+ * @kbdev: Kbase device
-+ * @kcpu_queue: KCPU queue
-+ * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero
-+ */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_kcpuqueue_execute_group_suspend_end( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ kcpu_queue, execute_error); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END( \
-+ kbdev, \
-+ kcpu_queue, \
-+ execute_error \
-+ ) \
-+ do { } while (0)
-+#endif /* MALI_USE_CSF */
-
- /**
- * KBASE_TLSTREAM_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW -
-@@ -2299,12 +3042,54 @@ struct kbase_tlstream;
- * @csffw_timestamp: Timestamp of a CSFFW event
- * @csffw_cycle: Cycle number of a CSFFW event
- */
-+#if MALI_USE_CSF
- #define KBASE_TLSTREAM_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW( \
- kbdev, \
- csffw_timestamp, \
- csffw_cycle \
- ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_csffw_tlstream_overflow( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ csffw_timestamp, csffw_cycle); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW( \
-+ kbdev, \
-+ csffw_timestamp, \
-+ csffw_cycle \
-+ ) \
-+ do { } while (0)
-+#endif /* MALI_USE_CSF */
-+
-+/**
-+ * KBASE_TLSTREAM_TL_KBASE_CSFFW_RESET -
-+ * A reset has happened with the CSFFW
-+ *
-+ * @kbdev: Kbase device
-+ * @csffw_cycle: Cycle number of a CSFFW event
-+ */
-+#if MALI_USE_CSF
-+#define KBASE_TLSTREAM_TL_KBASE_CSFFW_RESET( \
-+ kbdev, \
-+ csffw_cycle \
-+ ) \
-+ do { \
-+ int enabled = atomic_read(&kbdev->timeline_flags); \
-+ if (enabled & BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS) \
-+ __kbase_tlstream_tl_kbase_csffw_reset( \
-+ __TL_DISPATCH_STREAM(kbdev, obj), \
-+ csffw_cycle); \
-+ } while (0)
-+#else
-+#define KBASE_TLSTREAM_TL_KBASE_CSFFW_RESET( \
-+ kbdev, \
-+ csffw_cycle \
-+ ) \
- do { } while (0)
-+#endif /* MALI_USE_CSF */
-
-
- /* Gator tracepoints are hooked into TLSTREAM interface.
-diff --git a/dvalin/kernel/include/linux/dma-buf-test-exporter.h b/dvalin/kernel/include/linux/dma-buf-test-exporter.h
-index 95bc6f8..5a310f6 100644
---- a/dvalin/kernel/include/linux/dma-buf-test-exporter.h
-+++ b/dvalin/kernel/include/linux/dma-buf-test-exporter.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2012-2013, 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2012-2013, 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,8 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
- #ifndef _LINUX_DMA_BUF_TEST_EXPORTER_H_
- #define _LINUX_DMA_BUF_TEST_EXPORTER_H_
-
-diff --git a/dvalin/kernel/include/linux/memory_group_manager.h b/dvalin/kernel/include/linux/memory_group_manager.h
-index b1ac253..c0e808b 100644
---- a/dvalin/kernel/include/linux/memory_group_manager.h
-+++ b/dvalin/kernel/include/linux/memory_group_manager.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _MEMORY_GROUP_MANAGER_H_
-diff --git a/dvalin/kernel/include/linux/priority_control_manager.h b/dvalin/kernel/include/linux/priority_control_manager.h
-new file mode 100644
-index 0000000..002e78b
---- /dev/null
-+++ b/dvalin/kernel/include/linux/priority_control_manager.h
-@@ -0,0 +1,77 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _PRIORITY_CONTROL_MANAGER_H_
-+#define _PRIORITY_CONTROL_MANAGER_H_
-+
-+#include <linux/mm.h>
-+#include <linux/of.h>
-+#include <linux/version.h>
-+
-+struct priority_control_manager_device;
-+
-+/**
-+ * struct priority_control_manager_ops - Callbacks for priority control manager operations
-+ *
-+ * @pcm_scheduler_priority_check: Callback to check if scheduling priority level can be requested
-+ */
-+struct priority_control_manager_ops {
-+ /**
-+ * pcm_scheduler_priority_check: This function can be used to check what priority its work
-+ * would be treated as based on the requested_priority value.
-+ *
-+ * @pcm_dev: The priority control manager through which the request is
-+ * being made.
-+ * @task: The task struct of the process requesting the priority check.
-+ * @requested_priority: The priority level being requested.
-+ *
-+ * The returned value will be:
-+ * The same as requested_priority if the process has permission to use requested_priority
-+ * A lower priority value if the process does not have permission to use requested_priority
-+ *
-+ * requested_priority has the following value range:
-+ * 0-3 : Priority level, 0 being highest and 3 being lowest
-+ *
-+ * Return: The priority that would actually be given, could be lower than requested_priority
-+ */
-+ int (*pcm_scheduler_priority_check)(
-+ struct priority_control_manager_device *pcm_dev,
-+ struct task_struct *task, int requested_priority);
-+};
-+
-+/**
-+ * struct priority_control_manager_device - Device structure for priority
-+ * control manager
-+ *
-+ * @ops: Callbacks associated with this device
-+ * @data: Pointer to device private data
-+ * @owner: Pointer to the module owner
-+ *
-+ * This structure should be registered with the platform device using
-+ * platform_set_drvdata().
-+ */
-+struct priority_control_manager_device {
-+ struct priority_control_manager_ops ops;
-+ void *data;
-+ struct module *owner;
-+};
-+
-+#endif /* _PRIORITY_CONTROL_MANAGER_H_ */
-diff --git a/dvalin/kernel/include/linux/protected_memory_allocator.h b/dvalin/kernel/include/linux/protected_memory_allocator.h
-index 3b9205b..1e05bb8 100644
---- a/dvalin/kernel/include/linux/protected_memory_allocator.h
-+++ b/dvalin/kernel/include/linux/protected_memory_allocator.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _PROTECTED_MEMORY_ALLOCATOR_H_
-diff --git a/dvalin/kernel/include/linux/protected_mode_switcher.h b/dvalin/kernel/include/linux/protected_mode_switcher.h
-index 8778d81..1a3c5f7 100644
---- a/dvalin/kernel/include/linux/protected_mode_switcher.h
-+++ b/dvalin/kernel/include/linux/protected_mode_switcher.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,8 +17,6 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
- #ifndef _PROTECTED_MODE_SWITCH_H_
-diff --git a/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_base_csf_kernel.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_base_csf_kernel.h
-new file mode 100644
-index 0000000..72572e5
---- /dev/null
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_base_csf_kernel.h
-@@ -0,0 +1,765 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _UAPI_BASE_CSF_KERNEL_H_
-+#define _UAPI_BASE_CSF_KERNEL_H_
-+
-+#include <linux/types.h>
-+
-+/* Memory allocation, access/hint flags.
-+ *
-+ * See base_mem_alloc_flags.
-+ */
-+
-+/* IN */
-+/* Read access CPU side
-+ */
-+#define BASE_MEM_PROT_CPU_RD ((base_mem_alloc_flags)1 << 0)
-+
-+/* Write access CPU side
-+ */
-+#define BASE_MEM_PROT_CPU_WR ((base_mem_alloc_flags)1 << 1)
-+
-+/* Read access GPU side
-+ */
-+#define BASE_MEM_PROT_GPU_RD ((base_mem_alloc_flags)1 << 2)
-+
-+/* Write access GPU side
-+ */
-+#define BASE_MEM_PROT_GPU_WR ((base_mem_alloc_flags)1 << 3)
-+
-+/* Execute allowed on the GPU side
-+ */
-+#define BASE_MEM_PROT_GPU_EX ((base_mem_alloc_flags)1 << 4)
-+
-+/* Will be permanently mapped in kernel space.
-+ * Flag is only allowed on allocations originating from kbase.
-+ */
-+#define BASEP_MEM_PERMANENT_KERNEL_MAPPING ((base_mem_alloc_flags)1 << 5)
-+
-+/* The allocation will completely reside within the same 4GB chunk in the GPU
-+ * virtual space.
-+ * Since this flag is primarily required only for the TLS memory which will
-+ * not be used to contain executable code and also not used for Tiler heap,
-+ * it can't be used along with BASE_MEM_PROT_GPU_EX and TILER_ALIGN_TOP flags.
-+ */
-+#define BASE_MEM_GPU_VA_SAME_4GB_PAGE ((base_mem_alloc_flags)1 << 6)
-+
-+/* Userspace is not allowed to free this memory.
-+ * Flag is only allowed on allocations originating from kbase.
-+ */
-+#define BASEP_MEM_NO_USER_FREE ((base_mem_alloc_flags)1 << 7)
-+
-+#define BASE_MEM_RESERVED_BIT_8 ((base_mem_alloc_flags)1 << 8)
-+
-+/* Grow backing store on GPU Page Fault
-+ */
-+#define BASE_MEM_GROW_ON_GPF ((base_mem_alloc_flags)1 << 9)
-+
-+/* Page coherence Outer shareable, if available
-+ */
-+#define BASE_MEM_COHERENT_SYSTEM ((base_mem_alloc_flags)1 << 10)
-+
-+/* Page coherence Inner shareable
-+ */
-+#define BASE_MEM_COHERENT_LOCAL ((base_mem_alloc_flags)1 << 11)
-+
-+/* IN/OUT */
-+/* Should be cached on the CPU, returned if actually cached
-+ */
-+#define BASE_MEM_CACHED_CPU ((base_mem_alloc_flags)1 << 12)
-+
-+/* IN/OUT */
-+/* Must have same VA on both the GPU and the CPU
-+ */
-+#define BASE_MEM_SAME_VA ((base_mem_alloc_flags)1 << 13)
-+
-+/* OUT */
-+/* Must call mmap to acquire a GPU address for the alloc
-+ */
-+#define BASE_MEM_NEED_MMAP ((base_mem_alloc_flags)1 << 14)
-+
-+/* IN */
-+/* Page coherence Outer shareable, required.
-+ */
-+#define BASE_MEM_COHERENT_SYSTEM_REQUIRED ((base_mem_alloc_flags)1 << 15)
-+
-+/* Protected memory
-+ */
-+#define BASE_MEM_PROTECTED ((base_mem_alloc_flags)1 << 16)
-+
-+/* Not needed physical memory
-+ */
-+#define BASE_MEM_DONT_NEED ((base_mem_alloc_flags)1 << 17)
-+
-+/* Must use shared CPU/GPU zone (SAME_VA zone) but doesn't require the
-+ * addresses to be the same
-+ */
-+#define BASE_MEM_IMPORT_SHARED ((base_mem_alloc_flags)1 << 18)
-+
-+/* CSF event memory
-+ *
-+ * If Outer shareable coherence is not specified or not available, then on
-+ * allocation kbase will automatically use the uncached GPU mapping.
-+ * There is no need for the client to specify BASE_MEM_UNCACHED_GPU
-+ * themselves when allocating memory with the BASE_MEM_CSF_EVENT flag.
-+ *
-+ * This memory requires a permanent mapping
-+ *
-+ * See also kbase_reg_needs_kernel_mapping()
-+ */
-+#define BASE_MEM_CSF_EVENT ((base_mem_alloc_flags)1 << 19)
-+
-+#define BASE_MEM_RESERVED_BIT_20 ((base_mem_alloc_flags)1 << 20)
-+
-+/* Should be uncached on the GPU, will work only for GPUs using AARCH64 mmu
-+ * mode. Some components within the GPU might only be able to access memory
-+ * that is GPU cacheable. Refer to the specific GPU implementation for more
-+ * details. The 3 shareability flags will be ignored for GPU uncached memory.
-+ * If used while importing USER_BUFFER type memory, then the import will fail
-+ * if the memory is not aligned to GPU and CPU cache line width.
-+ */
-+#define BASE_MEM_UNCACHED_GPU ((base_mem_alloc_flags)1 << 21)
-+
-+/*
-+ * Bits [22:25] for group_id (0~15).
-+ *
-+ * base_mem_group_id_set() should be used to pack a memory group ID into a
-+ * base_mem_alloc_flags value instead of accessing the bits directly.
-+ * base_mem_group_id_get() should be used to extract the memory group ID from
-+ * a base_mem_alloc_flags value.
-+ */
-+#define BASEP_MEM_GROUP_ID_SHIFT 22
-+#define BASE_MEM_GROUP_ID_MASK \
-+ ((base_mem_alloc_flags)0xF << BASEP_MEM_GROUP_ID_SHIFT)
-+
-+/* Must do CPU cache maintenance when imported memory is mapped/unmapped
-+ * on GPU. Currently applicable to dma-buf type only.
-+ */
-+#define BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP ((base_mem_alloc_flags)1 << 26)
-+
-+/* OUT */
-+/* Kernel side cache sync ops required */
-+#define BASE_MEM_KERNEL_SYNC ((base_mem_alloc_flags)1 << 28)
-+
-+/* 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 29
-+
-+/* A mask of all the flags which are only valid for allocations within kbase,
-+ * and may not be passed from user space.
-+ */
-+#define BASEP_MEM_FLAGS_KERNEL_ONLY \
-+ (BASEP_MEM_PERMANENT_KERNEL_MAPPING | BASEP_MEM_NO_USER_FREE)
-+
-+/* A mask for all output bits, excluding IN/OUT bits.
-+ */
-+#define BASE_MEM_FLAGS_OUTPUT_MASK BASE_MEM_NEED_MMAP
-+
-+/* A mask for all input bits, including IN/OUT bits.
-+ */
-+#define BASE_MEM_FLAGS_INPUT_MASK \
-+ (((1 << BASE_MEM_FLAGS_NR_BITS) - 1) & ~BASE_MEM_FLAGS_OUTPUT_MASK)
-+
-+/* A mask of all currently reserved flags
-+ */
-+#define BASE_MEM_FLAGS_RESERVED \
-+ BASE_MEM_RESERVED_BIT_8 | BASE_MEM_RESERVED_BIT_20
-+
-+#define BASEP_MEM_INVALID_HANDLE (0ull << 12)
-+#define BASE_MEM_MMU_DUMP_HANDLE (1ull << 12)
-+#define BASE_MEM_TRACE_BUFFER_HANDLE (2ull << 12)
-+#define BASE_MEM_MAP_TRACKING_HANDLE (3ull << 12)
-+#define BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE (4ull << 12)
-+/* reserved handles ..-47<<PAGE_SHIFT> for future special handles */
-+#define BASEP_MEM_CSF_USER_REG_PAGE_HANDLE (47ul << 12)
-+#define BASEP_MEM_CSF_USER_IO_PAGES_HANDLE (48ul << 12)
-+#define BASE_MEM_COOKIE_BASE (64ul << 12)
-+#define BASE_MEM_FIRST_FREE_ADDRESS ((BITS_PER_LONG << 12) + \
-+ BASE_MEM_COOKIE_BASE)
-+
-+#define KBASE_CSF_NUM_USER_IO_PAGES_HANDLE \
-+ ((BASE_MEM_COOKIE_BASE - BASEP_MEM_CSF_USER_IO_PAGES_HANDLE) >> \
-+ LOCAL_PAGE_SHIFT)
-+
-+/**
-+ * Valid set of just-in-time memory allocation flags
-+ */
-+#define BASE_JIT_ALLOC_VALID_FLAGS ((__u8)0)
-+
-+/* Flags to pass to ::base_context_init.
-+ * Flags can be ORed together to enable multiple things.
-+ *
-+ * These share the same space as BASEP_CONTEXT_FLAG_*, and so must
-+ * not collide with them.
-+ */
-+typedef __u32 base_context_create_flags;
-+
-+/* No flags set */
-+#define BASE_CONTEXT_CREATE_FLAG_NONE ((base_context_create_flags)0)
-+
-+/* Base context is embedded in a cctx object (flag used for CINSTR
-+ * software counter macros)
-+ */
-+#define BASE_CONTEXT_CCTX_EMBEDDED ((base_context_create_flags)1 << 0)
-+
-+/* Base context is a 'System Monitor' context for Hardware counters.
-+ *
-+ * One important side effect of this is that job submission is disabled.
-+ */
-+#define BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED \
-+ ((base_context_create_flags)1 << 1)
-+
-+/* Base context creates a CSF event notification thread.
-+ *
-+ * The creation of a CSF event notification thread is conditional but
-+ * mandatory for the handling of CSF events.
-+ */
-+#define BASE_CONTEXT_CSF_EVENT_THREAD ((base_context_create_flags)1 << 2)
-+
-+/* Bit-shift used to encode a memory group ID in base_context_create_flags
-+ */
-+#define BASEP_CONTEXT_MMU_GROUP_ID_SHIFT (3)
-+
-+/* Bitmask used to encode a memory group ID in base_context_create_flags
-+ */
-+#define BASEP_CONTEXT_MMU_GROUP_ID_MASK \
-+ ((base_context_create_flags)0xF << BASEP_CONTEXT_MMU_GROUP_ID_SHIFT)
-+
-+/* Bitpattern describing the base_context_create_flags that can be
-+ * passed to the kernel
-+ */
-+#define BASEP_CONTEXT_CREATE_KERNEL_FLAGS \
-+ (BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED | \
-+ BASEP_CONTEXT_MMU_GROUP_ID_MASK)
-+
-+/* Bitpattern describing the ::base_context_create_flags that can be
-+ * passed to base_context_init()
-+ */
-+#define BASEP_CONTEXT_CREATE_ALLOWED_FLAGS \
-+ (BASE_CONTEXT_CCTX_EMBEDDED | \
-+ BASE_CONTEXT_CSF_EVENT_THREAD | \
-+ BASEP_CONTEXT_CREATE_KERNEL_FLAGS)
-+
-+/* Enable additional tracepoints for latency measurements (TL_ATOM_READY,
-+ * TL_ATOM_DONE, TL_ATOM_PRIO_CHANGE, TL_ATOM_EVENT_POST)
-+ */
-+#define BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS (1 << 0)
-+
-+/* Indicate that job dumping is enabled. This could affect certain timers
-+ * to account for the performance impact.
-+ */
-+#define BASE_TLSTREAM_JOB_DUMPING_ENABLED (1 << 1)
-+
-+/* Enable KBase tracepoints for CSF builds */
-+#define BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS (1 << 2)
-+
-+/* Enable additional CSF Firmware side tracepoints */
-+#define BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS (1 << 3)
-+
-+#define BASE_TLSTREAM_FLAGS_MASK (BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS | \
-+ BASE_TLSTREAM_JOB_DUMPING_ENABLED | \
-+ BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS | \
-+ BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS)
-+
-+/* Number of pages mapped into the process address space for a bound GPU
-+ * command queue. A pair of input/output pages and a Hw doorbell page
-+ * are mapped to enable direct submission of commands to Hw.
-+ */
-+#define BASEP_QUEUE_NR_MMAP_USER_PAGES ((size_t)3)
-+
-+#define BASE_QUEUE_MAX_PRIORITY (15U)
-+
-+/* CQS Sync object is an array of __u32 event_mem[2], error field index is 1 */
-+#define BASEP_EVENT_VAL_INDEX (0U)
-+#define BASEP_EVENT_ERR_INDEX (1U)
-+
-+/* The upper limit for number of objects that could be waited/set per command.
-+ * This limit is now enforced as internally the error inherit inputs are
-+ * converted to 32-bit flags in a __u32 variable occupying a previously padding
-+ * field.
-+ */
-+#define BASEP_KCPU_CQS_MAX_NUM_OBJS ((size_t)32)
-+
-+#if MALI_UNIT_TEST
-+/**
-+ * enum base_kcpu_command_type - Kernel CPU queue command type.
-+ * @BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL: fence_signal,
-+ * @BASE_KCPU_COMMAND_TYPE_FENCE_WAIT: fence_wait,
-+ * @BASE_KCPU_COMMAND_TYPE_CQS_WAIT: cqs_wait,
-+ * @BASE_KCPU_COMMAND_TYPE_CQS_SET: cqs_set,
-+ * @BASE_KCPU_COMMAND_TYPE_CQS_WAIT_OPERATION: cqs_wait_operation,
-+ * @BASE_KCPU_COMMAND_TYPE_CQS_SET_OPERATION: cqs_set_operation,
-+ * @BASE_KCPU_COMMAND_TYPE_MAP_IMPORT: map_import,
-+ * @BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT: unmap_import,
-+ * @BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT_FORCE: unmap_import_force,
-+ * @BASE_KCPU_COMMAND_TYPE_JIT_ALLOC: jit_alloc,
-+ * @BASE_KCPU_COMMAND_TYPE_JIT_FREE: jit_free,
-+ * @BASE_KCPU_COMMAND_TYPE_GROUP_SUSPEND: group_suspend,
-+ * @BASE_KCPU_COMMAND_TYPE_ERROR_BARRIER: error_barrier,
-+ * @BASE_KCPU_COMMAND_TYPE_SAMPLE_TIME: sample_time,
-+ */
-+enum base_kcpu_command_type {
-+ BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL,
-+ BASE_KCPU_COMMAND_TYPE_FENCE_WAIT,
-+ BASE_KCPU_COMMAND_TYPE_CQS_WAIT,
-+ BASE_KCPU_COMMAND_TYPE_CQS_SET,
-+ BASE_KCPU_COMMAND_TYPE_CQS_WAIT_OPERATION,
-+ BASE_KCPU_COMMAND_TYPE_CQS_SET_OPERATION,
-+ BASE_KCPU_COMMAND_TYPE_MAP_IMPORT,
-+ BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT,
-+ BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT_FORCE,
-+ BASE_KCPU_COMMAND_TYPE_JIT_ALLOC,
-+ BASE_KCPU_COMMAND_TYPE_JIT_FREE,
-+ BASE_KCPU_COMMAND_TYPE_GROUP_SUSPEND,
-+ BASE_KCPU_COMMAND_TYPE_ERROR_BARRIER,
-+ BASE_KCPU_COMMAND_TYPE_SAMPLE_TIME,
-+};
-+#else
-+/**
-+ * enum base_kcpu_command_type - Kernel CPU queue command type.
-+ * @BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL: fence_signal,
-+ * @BASE_KCPU_COMMAND_TYPE_FENCE_WAIT: fence_wait,
-+ * @BASE_KCPU_COMMAND_TYPE_CQS_WAIT: cqs_wait,
-+ * @BASE_KCPU_COMMAND_TYPE_CQS_SET: cqs_set,
-+ * @BASE_KCPU_COMMAND_TYPE_CQS_WAIT_OPERATION: cqs_wait_operation,
-+ * @BASE_KCPU_COMMAND_TYPE_CQS_SET_OPERATION: cqs_set_operation,
-+ * @BASE_KCPU_COMMAND_TYPE_MAP_IMPORT: map_import,
-+ * @BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT: unmap_import,
-+ * @BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT_FORCE: unmap_import_force,
-+ * @BASE_KCPU_COMMAND_TYPE_JIT_ALLOC: jit_alloc,
-+ * @BASE_KCPU_COMMAND_TYPE_JIT_FREE: jit_free,
-+ * @BASE_KCPU_COMMAND_TYPE_GROUP_SUSPEND: group_suspend,
-+ * @BASE_KCPU_COMMAND_TYPE_ERROR_BARRIER: error_barrier,
-+ */
-+enum base_kcpu_command_type {
-+ BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL,
-+ BASE_KCPU_COMMAND_TYPE_FENCE_WAIT,
-+ BASE_KCPU_COMMAND_TYPE_CQS_WAIT,
-+ BASE_KCPU_COMMAND_TYPE_CQS_SET,
-+ BASE_KCPU_COMMAND_TYPE_CQS_WAIT_OPERATION,
-+ BASE_KCPU_COMMAND_TYPE_CQS_SET_OPERATION,
-+ BASE_KCPU_COMMAND_TYPE_MAP_IMPORT,
-+ BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT,
-+ BASE_KCPU_COMMAND_TYPE_UNMAP_IMPORT_FORCE,
-+ BASE_KCPU_COMMAND_TYPE_JIT_ALLOC,
-+ BASE_KCPU_COMMAND_TYPE_JIT_FREE,
-+ BASE_KCPU_COMMAND_TYPE_GROUP_SUSPEND,
-+ BASE_KCPU_COMMAND_TYPE_ERROR_BARRIER,
-+};
-+#endif /* MALI_UNIT_TEST */
-+
-+/**
-+ * enum base_queue_group_priority - Priority of a GPU Command Queue Group.
-+ * @BASE_QUEUE_GROUP_PRIORITY_HIGH: GPU Command Queue Group is of high
-+ * priority.
-+ * @BASE_QUEUE_GROUP_PRIORITY_MEDIUM: GPU Command Queue Group is of medium
-+ * priority.
-+ * @BASE_QUEUE_GROUP_PRIORITY_LOW: GPU Command Queue Group is of low
-+ * priority.
-+ * @BASE_QUEUE_GROUP_PRIORITY_REALTIME: GPU Command Queue Group is of real-time
-+ * priority.
-+ * @BASE_QUEUE_GROUP_PRIORITY_COUNT: Number of GPU Command Queue Group
-+ * priority levels.
-+ *
-+ * Currently this is in order of highest to lowest, but if new levels are added
-+ * then those new levels may be out of order to preserve the ABI compatibility
-+ * with previous releases. At that point, ensure assignment to
-+ * the 'priority' member in &kbase_queue_group is updated to ensure it remains
-+ * a linear ordering.
-+ *
-+ * There should be no gaps in the enum, otherwise use of
-+ * BASE_QUEUE_GROUP_PRIORITY_COUNT in kbase must be updated.
-+ */
-+enum base_queue_group_priority {
-+ BASE_QUEUE_GROUP_PRIORITY_HIGH = 0,
-+ BASE_QUEUE_GROUP_PRIORITY_MEDIUM,
-+ BASE_QUEUE_GROUP_PRIORITY_LOW,
-+ BASE_QUEUE_GROUP_PRIORITY_REALTIME,
-+ BASE_QUEUE_GROUP_PRIORITY_COUNT
-+};
-+
-+struct base_kcpu_command_fence_info {
-+ __u64 fence;
-+};
-+
-+struct base_cqs_wait_info {
-+ __u64 addr;
-+ __u32 val;
-+ __u32 padding;
-+};
-+
-+struct base_kcpu_command_cqs_wait_info {
-+ __u64 objs;
-+ __u32 nr_objs;
-+ __u32 inherit_err_flags;
-+};
-+
-+struct base_cqs_set {
-+ __u64 addr;
-+};
-+
-+struct base_kcpu_command_cqs_set_info {
-+ __u64 objs;
-+ __u32 nr_objs;
-+ __u32 padding;
-+};
-+
-+/**
-+ * basep_cqs_data_type - Enumeration of CQS Data Types
-+ *
-+ * @BASEP_CQS_DATA_TYPE_U32: The Data Type of a CQS Object's value
-+ * is an unsigned 32-bit integer
-+ * @BASEP_CQS_DATA_TYPE_U64: The Data Type of a CQS Object's value
-+ * is an unsigned 64-bit integer
-+ */
-+typedef enum PACKED {
-+ BASEP_CQS_DATA_TYPE_U32 = 0,
-+ BASEP_CQS_DATA_TYPE_U64 = 1,
-+} basep_cqs_data_type;
-+
-+/**
-+ * basep_cqs_wait_operation_op - Enumeration of CQS Object Wait
-+ * Operation conditions
-+ *
-+ * @BASEP_CQS_WAIT_OPERATION_LE: CQS Wait Operation indicating that a
-+ * wait will be satisfied when a CQS Object's
-+ * value is Less than or Equal to
-+ * the Wait Operation value
-+ * @BASEP_CQS_WAIT_OPERATION_GT: CQS Wait Operation indicating that a
-+ * wait will be satisfied when a CQS Object's
-+ * value is Greater than the Wait Operation value
-+ */
-+typedef enum {
-+ BASEP_CQS_WAIT_OPERATION_LE = 0,
-+ BASEP_CQS_WAIT_OPERATION_GT = 1,
-+} basep_cqs_wait_operation_op;
-+
-+struct base_cqs_wait_operation_info {
-+ __u64 addr;
-+ __u64 val;
-+ __u8 operation;
-+ __u8 data_type;
-+ __u8 padding[6];
-+};
-+
-+/**
-+ * struct base_kcpu_command_cqs_wait_operation_info - structure which contains information
-+ * about the Timeline CQS wait objects
-+ *
-+ * @objs: An array of Timeline CQS waits.
-+ * @nr_objs: Number of Timeline CQS waits in the array.
-+ * @inherit_err_flags: Bit-pattern for the CQSs in the array who's error field
-+ * to be served as the source for importing into the
-+ * queue's error-state.
-+ */
-+struct base_kcpu_command_cqs_wait_operation_info {
-+ __u64 objs;
-+ __u32 nr_objs;
-+ __u32 inherit_err_flags;
-+};
-+
-+/**
-+ * basep_cqs_set_operation_op - Enumeration of CQS Set Operations
-+ *
-+ * @BASEP_CQS_SET_OPERATION_ADD: CQS Set operation for adding a value
-+ * to a synchronization object
-+ * @BASEP_CQS_SET_OPERATION_SET: CQS Set operation for setting the value
-+ * of a synchronization object
-+ */
-+typedef enum {
-+ BASEP_CQS_SET_OPERATION_ADD = 0,
-+ BASEP_CQS_SET_OPERATION_SET = 1,
-+} basep_cqs_set_operation_op;
-+
-+struct base_cqs_set_operation_info {
-+ __u64 addr;
-+ __u64 val;
-+ __u8 operation;
-+ __u8 data_type;
-+ __u8 padding[6];
-+};
-+
-+/**
-+ * struct base_kcpu_command_cqs_set_operation_info - structure which contains information
-+ * about the Timeline CQS set objects
-+ *
-+ * @objs: An array of Timeline CQS sets.
-+ * @nr_objs: Number of Timeline CQS sets in the array.
-+ * @padding: Structure padding, unused bytes.
-+ */
-+struct base_kcpu_command_cqs_set_operation_info {
-+ __u64 objs;
-+ __u32 nr_objs;
-+ __u32 padding;
-+};
-+
-+/**
-+ * struct base_kcpu_command_import_info - structure which contains information
-+ * about the imported buffer.
-+ *
-+ * @handle: Address of imported user buffer.
-+ */
-+struct base_kcpu_command_import_info {
-+ __u64 handle;
-+};
-+
-+/**
-+ * struct base_kcpu_command_jit_alloc_info - structure which contains
-+ * information about jit memory allocation.
-+ *
-+ * @info: An array of elements of the
-+ * struct base_jit_alloc_info type.
-+ * @count: The number of elements in the info array.
-+ * @padding: Padding to a multiple of 64 bits.
-+ */
-+struct base_kcpu_command_jit_alloc_info {
-+ __u64 info;
-+ __u8 count;
-+ __u8 padding[7];
-+};
-+
-+/**
-+ * struct base_kcpu_command_jit_free_info - structure which contains
-+ * information about jit memory which is to be freed.
-+ *
-+ * @ids: An array containing the JIT IDs to free.
-+ * @count: The number of elements in the ids array.
-+ * @padding: Padding to a multiple of 64 bits.
-+ */
-+struct base_kcpu_command_jit_free_info {
-+ __u64 ids;
-+ __u8 count;
-+ __u8 padding[7];
-+};
-+
-+/**
-+ * struct base_kcpu_command_group_suspend_info - structure which contains
-+ * suspend buffer data captured for a suspended queue group.
-+ *
-+ * @buffer: Pointer to an array of elements of the type char.
-+ * @size: Number of elements in the @buffer array.
-+ * @group_handle: Handle to the mapping of CSG.
-+ * @padding: padding to a multiple of 64 bits.
-+ */
-+struct base_kcpu_command_group_suspend_info {
-+ __u64 buffer;
-+ __u32 size;
-+ __u8 group_handle;
-+ __u8 padding[3];
-+};
-+
-+#if MALI_UNIT_TEST
-+struct base_kcpu_command_sample_time_info {
-+ __u64 time;
-+};
-+#endif /* MALI_UNIT_TEST */
-+
-+/**
-+ * struct base_kcpu_command - kcpu command.
-+ * @type: type of the kcpu command, one enum base_kcpu_command_type
-+ * @padding: padding to a multiple of 64 bits
-+ * @info: structure which contains information about the kcpu command;
-+ * actual type is determined by @p type
-+ * @info.fence: Fence
-+ * @info.cqs_wait: CQS wait
-+ * @info.cqs_set: CQS set
-+ * @info.import: import
-+ * @info.jit_alloc: jit allocation
-+ * @info.jit_free: jit deallocation
-+ * @info.suspend_buf_copy: suspend buffer copy
-+ * @info.sample_time: sample time
-+ * @info.padding: padding
-+ */
-+struct base_kcpu_command {
-+ __u8 type;
-+ __u8 padding[sizeof(__u64) - sizeof(__u8)];
-+ union {
-+ struct base_kcpu_command_fence_info fence;
-+ struct base_kcpu_command_cqs_wait_info cqs_wait;
-+ struct base_kcpu_command_cqs_set_info cqs_set;
-+ struct base_kcpu_command_cqs_wait_operation_info cqs_wait_operation;
-+ struct base_kcpu_command_cqs_set_operation_info cqs_set_operation;
-+ struct base_kcpu_command_import_info import;
-+ struct base_kcpu_command_jit_alloc_info jit_alloc;
-+ struct base_kcpu_command_jit_free_info jit_free;
-+ struct base_kcpu_command_group_suspend_info suspend_buf_copy;
-+#if MALI_UNIT_TEST
-+ struct base_kcpu_command_sample_time_info sample_time;
-+#endif /* MALI_UNIT_TEST */
-+ __u64 padding[2]; /* No sub-struct should be larger */
-+ } info;
-+};
-+
-+/**
-+ * struct basep_cs_stream_control - CSI capabilities.
-+ *
-+ * @features: Features of this stream
-+ * @padding: Padding to a multiple of 64 bits.
-+ */
-+struct basep_cs_stream_control {
-+ __u32 features;
-+ __u32 padding;
-+};
-+
-+/**
-+ * struct basep_cs_group_control - CSG interface capabilities.
-+ *
-+ * @features: Features of this group
-+ * @stream_num: Number of streams in this group
-+ * @suspend_size: Size in bytes of the suspend buffer for this group
-+ * @padding: Padding to a multiple of 64 bits.
-+ */
-+struct basep_cs_group_control {
-+ __u32 features;
-+ __u32 stream_num;
-+ __u32 suspend_size;
-+ __u32 padding;
-+};
-+
-+/**
-+ * struct base_gpu_queue_group_error_fatal_payload - Unrecoverable fault
-+ * error information associated with GPU command queue group.
-+ *
-+ * @sideband: Additional information of the unrecoverable fault.
-+ * @status: Unrecoverable fault information.
-+ * This consists of exception type (least significant byte) and
-+ * data (remaining bytes). One example of exception type is
-+ * CS_INVALID_INSTRUCTION (0x49).
-+ * @padding: Padding to make multiple of 64bits
-+ */
-+struct base_gpu_queue_group_error_fatal_payload {
-+ __u64 sideband;
-+ __u32 status;
-+ __u32 padding;
-+};
-+
-+/**
-+ * struct base_gpu_queue_error_fatal_payload - Unrecoverable fault
-+ * error information related to GPU command queue.
-+ *
-+ * @sideband: Additional information about this unrecoverable fault.
-+ * @status: Unrecoverable fault information.
-+ * This consists of exception type (least significant byte) and
-+ * data (remaining bytes). One example of exception type is
-+ * CS_INVALID_INSTRUCTION (0x49).
-+ * @csi_index: Index of the CSF interface the queue is bound to.
-+ * @padding: Padding to make multiple of 64bits
-+ */
-+struct base_gpu_queue_error_fatal_payload {
-+ __u64 sideband;
-+ __u32 status;
-+ __u8 csi_index;
-+ __u8 padding[3];
-+};
-+
-+/**
-+ * enum base_gpu_queue_group_error_type - GPU Fatal error type.
-+ *
-+ * @BASE_GPU_QUEUE_GROUP_ERROR_FATAL: Fatal error associated with GPU
-+ * command queue group.
-+ * @BASE_GPU_QUEUE_GROUP_QUEUE_ERROR_FATAL: Fatal error associated with GPU
-+ * command queue.
-+ * @BASE_GPU_QUEUE_GROUP_ERROR_TIMEOUT: Fatal error associated with
-+ * progress timeout.
-+ * @BASE_GPU_QUEUE_GROUP_ERROR_TILER_HEAP_OOM: Fatal error due to running out
-+ * of tiler heap memory.
-+ * @BASE_GPU_QUEUE_GROUP_ERROR_FATAL_COUNT: The number of fatal error types
-+ *
-+ * This type is used for &struct_base_gpu_queue_group_error.error_type.
-+ */
-+enum base_gpu_queue_group_error_type {
-+ BASE_GPU_QUEUE_GROUP_ERROR_FATAL = 0,
-+ BASE_GPU_QUEUE_GROUP_QUEUE_ERROR_FATAL,
-+ BASE_GPU_QUEUE_GROUP_ERROR_TIMEOUT,
-+ BASE_GPU_QUEUE_GROUP_ERROR_TILER_HEAP_OOM,
-+ BASE_GPU_QUEUE_GROUP_ERROR_FATAL_COUNT
-+};
-+
-+/**
-+ * struct base_gpu_queue_group_error - Unrecoverable fault information
-+ * @error_type: Error type of @base_gpu_queue_group_error_type
-+ * indicating which field in union payload is filled
-+ * @padding: Unused bytes for 64bit boundary
-+ * @payload: Input Payload
-+ * @payload.fatal_group: Unrecoverable fault error associated with
-+ * GPU command queue group
-+ * @payload.fatal_queue: Unrecoverable fault error associated with command queue
-+ */
-+struct base_gpu_queue_group_error {
-+ __u8 error_type;
-+ __u8 padding[7];
-+ union {
-+ struct base_gpu_queue_group_error_fatal_payload fatal_group;
-+ struct base_gpu_queue_error_fatal_payload fatal_queue;
-+ } payload;
-+};
-+
-+/**
-+ * enum base_csf_notification_type - Notification type
-+ *
-+ * @BASE_CSF_NOTIFICATION_EVENT: Notification with kernel event
-+ * @BASE_CSF_NOTIFICATION_GPU_QUEUE_GROUP_ERROR: Notification with GPU fatal
-+ * error
-+ * @BASE_CSF_NOTIFICATION_CPU_QUEUE_DUMP: Notification with dumping cpu
-+ * queue
-+ * @BASE_CSF_NOTIFICATION_COUNT: The number of notification type
-+ *
-+ * This type is used for &struct_base_csf_notification.type.
-+ */
-+enum base_csf_notification_type {
-+ BASE_CSF_NOTIFICATION_EVENT = 0,
-+ BASE_CSF_NOTIFICATION_GPU_QUEUE_GROUP_ERROR,
-+ BASE_CSF_NOTIFICATION_CPU_QUEUE_DUMP,
-+ BASE_CSF_NOTIFICATION_COUNT
-+};
-+
-+/**
-+ * struct base_csf_notification - Event or error notification
-+ *
-+ * @type: Notification type of @base_csf_notification_type
-+ * @padding: Padding for 64bit boundary
-+ * @payload: Input Payload
-+ * @payload.align: To fit the struct into a 64-byte cache line
-+ * @payload.csg_error: CSG error
-+ * @payload.csg_error.handle: Handle of GPU command queue group associated with
-+ * fatal error
-+ * @payload.csg_error.padding: Padding
-+ * @payload.csg_error.error: Unrecoverable fault error
-+ *
-+ */
-+struct base_csf_notification {
-+ __u8 type;
-+ __u8 padding[7];
-+ union {
-+ struct {
-+ __u8 handle;
-+ __u8 padding[7];
-+ struct base_gpu_queue_group_error error;
-+ } csg_error;
-+
-+ __u8 align[56];
-+ } payload;
-+};
-+
-+#endif /* _UAPI_BASE_CSF_KERNEL_H_ */
-diff --git a/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_gpu_csf_control_registers.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_gpu_csf_control_registers.h
-new file mode 100644
-index 0000000..b62a8b0
---- /dev/null
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_gpu_csf_control_registers.h
-@@ -0,0 +1,32 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * This header was autogenerated, it should not be edited.
-+ */
-+
-+#ifndef _UAPI_GPU_CSF_CONTROL_REGISTERS_H_
-+#define _UAPI_GPU_CSF_CONTROL_REGISTERS_H_
-+
-+/* GPU_REGISTERS register offsets */
-+#define GPU_CONTROL_MCU 0x3000 /* () MCU control registers */
-+
-+#endif /* _UAPI_GPU_CSF_CONTROL_REGISTERS_H_ */
-diff --git a/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_gpu_csf_registers.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_gpu_csf_registers.h
-new file mode 100644
-index 0000000..06cc4c2
---- /dev/null
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_gpu_csf_registers.h
-@@ -0,0 +1,1488 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2018-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * This header was autogenerated, it should not be edited.
-+ */
-+
-+#ifndef _UAPI_GPU_CSF_REGISTERS_H_
-+#define _UAPI_GPU_CSF_REGISTERS_H_
-+
-+/*
-+ * Begin register sets
-+ */
-+
-+/* DOORBELLS base address */
-+#define DOORBELLS_BASE 0x0080000
-+#define DOORBELLS_REG(r) (DOORBELLS_BASE + (r))
-+
-+/* CS_KERNEL_INPUT_BLOCK base address */
-+#define CS_KERNEL_INPUT_BLOCK_BASE 0x0000
-+#define CS_KERNEL_INPUT_BLOCK_REG(r) (CS_KERNEL_INPUT_BLOCK_BASE + (r))
-+
-+/* CS_KERNEL_OUTPUT_BLOCK base address */
-+#define CS_KERNEL_OUTPUT_BLOCK_BASE 0x0000
-+#define CS_KERNEL_OUTPUT_BLOCK_REG(r) (CS_KERNEL_OUTPUT_BLOCK_BASE + (r))
-+
-+/* CS_USER_INPUT_BLOCK base address */
-+#define CS_USER_INPUT_BLOCK_BASE 0x0000
-+#define CS_USER_INPUT_BLOCK_REG(r) (CS_USER_INPUT_BLOCK_BASE + (r))
-+
-+/* CS_USER_OUTPUT_BLOCK base address */
-+#define CS_USER_OUTPUT_BLOCK_BASE 0x0000
-+#define CS_USER_OUTPUT_BLOCK_REG(r) (CS_USER_OUTPUT_BLOCK_BASE + (r))
-+
-+/* CSG_INPUT_BLOCK base address */
-+#define CSG_INPUT_BLOCK_BASE 0x0000
-+#define CSG_INPUT_BLOCK_REG(r) (CSG_INPUT_BLOCK_BASE + (r))
-+
-+/* CSG_OUTPUT_BLOCK base address */
-+#define CSG_OUTPUT_BLOCK_BASE 0x0000
-+#define CSG_OUTPUT_BLOCK_REG(r) (CSG_OUTPUT_BLOCK_BASE + (r))
-+
-+/* GLB_CONTROL_BLOCK base address */
-+#define GLB_CONTROL_BLOCK_BASE 0x04000000
-+#define GLB_CONTROL_BLOCK_REG(r) (GLB_CONTROL_BLOCK_BASE + (r))
-+
-+/* GLB_INPUT_BLOCK base address */
-+#define GLB_INPUT_BLOCK_BASE 0x0000
-+#define GLB_INPUT_BLOCK_REG(r) (GLB_INPUT_BLOCK_BASE + (r))
-+
-+/* GLB_OUTPUT_BLOCK base address */
-+#define GLB_OUTPUT_BLOCK_BASE 0x0000
-+#define GLB_OUTPUT_BLOCK_REG(r) (GLB_OUTPUT_BLOCK_BASE + (r))
-+
-+/* USER base address */
-+#define USER_BASE 0x0010000
-+#define USER_REG(r) (USER_BASE + (r))
-+
-+/* End register sets */
-+
-+/*
-+ * Begin register offsets
-+ */
-+
-+/* DOORBELLS register offsets */
-+#define DOORBELL_0 0x0000 /* () Doorbell 0 register */
-+#define DOORBELL(n) (DOORBELL_0 + (n)*65536)
-+#define DOORBELL_REG(n, r) (DOORBELL(n) + DOORBELL_BLOCK_REG(r))
-+#define DOORBELL_COUNT 1024
-+
-+/* DOORBELL_BLOCK register offsets */
-+#define DB_BLK_DOORBELL 0x0000 /* (WO) Doorbell request */
-+
-+/* CS_KERNEL_INPUT_BLOCK register offsets */
-+#define CS_REQ 0x0000 /* () CS request flags */
-+#define CS_CONFIG 0x0004 /* () CS configuration */
-+#define CS_ACK_IRQ_MASK 0x000C /* () Command steam interrupt mask */
-+#define CS_BASE_LO 0x0010 /* () Base pointer for the ring buffer, low word */
-+#define CS_BASE_HI 0x0014 /* () Base pointer for the ring buffer, high word */
-+#define CS_SIZE 0x0018 /* () Size of the ring buffer */
-+#define CS_TILER_HEAP_START_LO 0x0020 /* () Pointer to heap start, low word */
-+#define CS_TILER_HEAP_START_HI 0x0024 /* () Pointer to heap start, high word */
-+#define CS_TILER_HEAP_END_LO 0x0028 /* () Tiler heap descriptor address, low word */
-+#define CS_TILER_HEAP_END_HI 0x002C /* () Tiler heap descriptor address, high word */
-+#define CS_USER_INPUT_LO 0x0030 /* () CS user mode input page address, low word */
-+#define CS_USER_INPUT_HI 0x0034 /* () CS user mode input page address, high word */
-+#define CS_USER_OUTPUT_LO 0x0038 /* () CS user mode input page address, low word */
-+#define CS_USER_OUTPUT_HI 0x003C /* () CS user mode input page address, high word */
-+#define CS_INSTR_CONFIG 0x0040 /* () Instrumentation buffer configuration */
-+#define CS_INSTR_BUFFER_SIZE 0x0044 /* () Instrumentation buffer size */
-+#define CS_INSTR_BUFFER_BASE_LO 0x0048 /* () Instrumentation buffer base pointer, low word */
-+#define CS_INSTR_BUFFER_BASE_HI 0x004C /* () Instrumentation buffer base pointer, high word */
-+#define CS_INSTR_BUFFER_OFFSET_POINTER_LO 0x0050 /* () Instrumentation buffer pointer to insert offset, low word */
-+#define CS_INSTR_BUFFER_OFFSET_POINTER_HI 0x0054 /* () Instrumentation buffer pointer to insert offset, high word */
-+
-+/* CS_KERNEL_OUTPUT_BLOCK register offsets */
-+#define CS_ACK 0x0000 /* () CS acknowledge flags */
-+#define CS_STATUS_CMD_PTR_LO 0x0040 /* () Program pointer current value, low word */
-+#define CS_STATUS_CMD_PTR_HI 0x0044 /* () Program pointer current value, high word */
-+#define CS_STATUS_WAIT 0x0048 /* () Wait condition status register */
-+#define CS_STATUS_REQ_RESOURCE 0x004C /* () Indicates the resources requested by the CS */
-+#define CS_STATUS_WAIT_SYNC_POINTER_LO 0x0050 /* () Sync object pointer, low word */
-+#define CS_STATUS_WAIT_SYNC_POINTER_HI 0x0054 /* () Sync object pointer, high word */
-+#define CS_STATUS_WAIT_SYNC_VALUE 0x0058 /* () Sync object test value */
-+#define CS_STATUS_SCOREBOARDS 0x005C /* () Scoreboard status */
-+#define CS_STATUS_BLOCKED_REASON 0x0060 /* () Blocked reason */
-+#define CS_FAULT 0x0080 /* () Recoverable fault information */
-+#define CS_FATAL 0x0084 /* () Unrecoverable fault information */
-+#define CS_FAULT_INFO_LO 0x0088 /* () Additional information about a recoverable fault, low word */
-+#define CS_FAULT_INFO_HI 0x008C /* () Additional information about a recoverable fault, high word */
-+#define CS_FATAL_INFO_LO 0x0090 /* () Additional information about a non-recoverable fault, low word */
-+#define CS_FATAL_INFO_HI 0x0094 /* () Additional information about a non-recoverable fault, high word */
-+#define CS_HEAP_VT_START 0x00C0 /* () Number of vertex/tiling operations started */
-+#define CS_HEAP_VT_END 0x00C4 /* () Number of vertex/tiling operations completed */
-+#define CS_HEAP_FRAG_END 0x00CC /* () Number of fragment completed */
-+#define CS_HEAP_ADDRESS_LO 0x00D0 /* () Heap address, low word */
-+#define CS_HEAP_ADDRESS_HI 0x00D4 /* () Heap address, high word */
-+
-+/* CS_USER_INPUT_BLOCK register offsets */
-+#define CS_INSERT_LO 0x0000 /* () Current insert offset for ring buffer, low word */
-+#define CS_INSERT_HI 0x0004 /* () Current insert offset for ring buffer, high word */
-+#define CS_EXTRACT_INIT_LO 0x0008 /* () Initial extract offset for ring buffer, low word */
-+#define CS_EXTRACT_INIT_HI 0x000C /* () Initial extract offset for ring buffer, high word */
-+
-+/* CS_USER_OUTPUT_BLOCK register offsets */
-+#define CS_EXTRACT_LO 0x0000 /* () Current extract offset for ring buffer, low word */
-+#define CS_EXTRACT_HI 0x0004 /* () Current extract offset for ring buffer, high word */
-+#define CS_ACTIVE 0x0008 /* () Initial extract offset when the CS is started */
-+
-+/* CSG_INPUT_BLOCK register offsets */
-+#define CSG_REQ 0x0000 /* () CSG request */
-+#define CSG_ACK_IRQ_MASK 0x0004 /* () Global acknowledge interrupt mask */
-+#define CSG_DB_REQ 0x0008 /* () Global doorbell request */
-+#define CSG_IRQ_ACK 0x000C /* () CS IRQ acknowledge */
-+#define CSG_ALLOW_COMPUTE_LO 0x0020 /* () Allowed compute endpoints, low word */
-+#define CSG_ALLOW_COMPUTE_HI 0x0024 /* () Allowed compute endpoints, high word */
-+#define CSG_ALLOW_FRAGMENT_LO 0x0028 /* () Allowed fragment endpoints, low word */
-+#define CSG_ALLOW_FRAGMENT_HI 0x002C /* () Allowed fragment endpoints, high word */
-+#define CSG_ALLOW_OTHER 0x0030 /* () Allowed other endpoints */
-+#define CSG_EP_REQ 0x0034 /* () Maximum number of endpoints allowed */
-+#define CSG_SUSPEND_BUF_LO 0x0040 /* () Normal mode suspend buffer, low word */
-+#define CSG_SUSPEND_BUF_HI 0x0044 /* () Normal mode suspend buffer, high word */
-+#define CSG_PROTM_SUSPEND_BUF_LO 0x0048 /* () Protected mode suspend buffer, low word */
-+#define CSG_PROTM_SUSPEND_BUF_HI 0x004C /* () Protected mode suspend buffer, high word */
-+#define CSG_CONFIG 0x0050 /* () CSG configuration options */
-+#define CSG_ITER_TRACE_CONFIG 0x0054 /* () CSG trace configuration */
-+
-+/* CSG_OUTPUT_BLOCK register offsets */
-+#define CSG_ACK 0x0000 /* () CSG acknowledge flags */
-+#define CSG_DB_ACK 0x0008 /* () CS kernel doorbell acknowledge flags */
-+#define CSG_IRQ_REQ 0x000C /* () CS interrupt request flags */
-+#define CSG_STATUS_EP_CURRENT 0x0010 /* () Endpoint allocation status register */
-+#define CSG_STATUS_EP_REQ 0x0014 /* () Endpoint request status register */
-+#define CSG_RESOURCE_DEP 0x001C /* () Current resource dependencies */
-+
-+/* GLB_CONTROL_BLOCK register offsets */
-+#define GLB_VERSION 0x0000 /* () Global interface version */
-+#define GLB_FEATURES 0x0004 /* () Global interface features */
-+#define GLB_INPUT_VA 0x0008 /* () Address of GLB_INPUT_BLOCK */
-+#define GLB_OUTPUT_VA 0x000C /* () Address of GLB_OUTPUT_BLOCK */
-+#define GLB_GROUP_NUM 0x0010 /* () Number of CSG interfaces */
-+#define GLB_GROUP_STRIDE 0x0014 /* () Stride between CSG interfaces */
-+#define GLB_PRFCNT_SIZE 0x0018 /* () Size of CSF performance counters */
-+#define GLB_INSTR_FEATURES \
-+ 0x001C /* () TRACE_POINT instrumentation. (csf >= 1.1.0) */
-+#define GROUP_CONTROL_0 0x1000 /* () CSG control and capabilities */
-+#define GROUP_CONTROL(n) (GROUP_CONTROL_0 + (n)*256)
-+#define GROUP_CONTROL_REG(n, r) (GROUP_CONTROL(n) + GROUP_CONTROL_BLOCK_REG(r))
-+#define GROUP_CONTROL_COUNT 16
-+
-+/* STREAM_CONTROL_BLOCK register offsets */
-+#define STREAM_FEATURES 0x0000 /* () CSI features */
-+#define STREAM_INPUT_VA 0x0004 /* () Address of CS_KERNEL_INPUT_BLOCK */
-+#define STREAM_OUTPUT_VA 0x0008 /* () Address of CS_KERNEL_OUTPUT_BLOCK */
-+
-+/* GROUP_CONTROL_BLOCK register offsets */
-+#define GROUP_FEATURES 0x0000 /* () CSG interface features */
-+#define GROUP_INPUT_VA 0x0004 /* () Address of CSG_INPUT_BLOCK */
-+#define GROUP_OUTPUT_VA 0x0008 /* () Address of CSG_OUTPUT_BLOCK */
-+#define GROUP_SUSPEND_SIZE 0x000C /* () Size of CSG suspend buffer */
-+#define GROUP_PROTM_SUSPEND_SIZE 0x0010 /* () Size of CSG protected-mode suspend buffer */
-+#define GROUP_STREAM_NUM 0x0014 /* () Number of CS interfaces */
-+#define GROUP_STREAM_STRIDE 0x0018 /* () Stride between CS interfaces */
-+#define STREAM_CONTROL_0 0x0040 /* () CS control and capabilities */
-+#define STREAM_CONTROL(n) (STREAM_CONTROL_0 + (n)*12)
-+#define STREAM_CONTROL_REG(n, r) (STREAM_CONTROL(n) + STREAM_CONTROL_BLOCK_REG(r))
-+#define STREAM_CONTROL_COUNT 16
-+
-+/* GLB_INPUT_BLOCK register offsets */
-+#define GLB_REQ 0x0000 /* () Global request */
-+#define GLB_ACK_IRQ_MASK 0x0004 /* () Global acknowledge interrupt mask */
-+#define GLB_DB_REQ 0x0008 /* () Global doorbell request */
-+#define GLB_PROGRESS_TIMER 0x0010 /* () Global progress timeout */
-+#define GLB_PWROFF_TIMER 0x0014 /* () Global shader core power off timer */
-+#define GLB_ALLOC_EN_LO 0x0018 /* () Global shader core allocation enable mask, low word */
-+#define GLB_ALLOC_EN_HI 0x001C /* () Global shader core allocation enable mask, high word */
-+#define GLB_PROTM_COHERENCY 0x0020 /* () Configure COHERENCY_ENABLE register value to use in protected mode execution */
-+
-+#define GLB_PRFCNT_JASID 0x0024 /* () Performance counter address space */
-+#define GLB_PRFCNT_BASE_LO 0x0028 /* () Performance counter buffer address, low word */
-+#define GLB_PRFCNT_BASE_HI 0x002C /* () Performance counter buffer address, high word */
-+#define GLB_PRFCNT_EXTRACT 0x0030 /* () Performance counter buffer extract index */
-+#define GLB_PRFCNT_CONFIG 0x0040 /* () Performance counter configuration */
-+#define GLB_PRFCNT_CSG_SELECT 0x0044 /* () CSG performance counting enable */
-+#define GLB_PRFCNT_FW_EN 0x0048 /* () Performance counter enable for firmware */
-+#define GLB_PRFCNT_CSG_EN 0x004C /* () Performance counter enable for CSG */
-+#define GLB_PRFCNT_CSF_EN 0x0050 /* () Performance counter enable for CSF */
-+#define GLB_PRFCNT_SHADER_EN 0x0054 /* () Performance counter enable for shader cores */
-+#define GLB_PRFCNT_TILER_EN 0x0058 /* () Performance counter enable for tiler */
-+#define GLB_PRFCNT_MMU_L2_EN 0x005C /* () Performance counter enable for MMU/L2 cache */
-+
-+#define GLB_DEBUG_FWUTF_DESTROY 0x0FE0 /* () Test fixture destroy function address */
-+#define GLB_DEBUG_FWUTF_TEST 0x0FE4 /* () Test index */
-+#define GLB_DEBUG_FWUTF_FIXTURE 0x0FE8 /* () Test fixture index */
-+#define GLB_DEBUG_FWUTF_CREATE 0x0FEC /* () Test fixture create function address */
-+#define GLB_DEBUG_ACK_IRQ_MASK 0x0FF8 /* () Global debug acknowledge interrupt mask */
-+#define GLB_DEBUG_REQ 0x0FFC /* () Global debug request */
-+
-+/* GLB_OUTPUT_BLOCK register offsets */
-+#define GLB_ACK 0x0000 /* () Global acknowledge */
-+#define GLB_DB_ACK 0x0008 /* () Global doorbell acknowledge */
-+#define GLB_HALT_STATUS 0x0010 /* () Global halt status */
-+#define GLB_PRFCNT_STATUS 0x0014 /* () Performance counter status */
-+#define GLB_PRFCNT_INSERT 0x0018 /* () Performance counter buffer insert index */
-+#define GLB_DEBUG_FWUTF_RESULT 0x0FE0 /* () Firmware debug test result */
-+#define GLB_DEBUG_ACK 0x0FFC /* () Global debug acknowledge */
-+
-+/* USER register offsets */
-+#define LATEST_FLUSH 0x0000 /* () Flush ID of latest clean-and-invalidate operation */
-+
-+/* End register offsets */
-+
-+/* CS_KERNEL_INPUT_BLOCK register set definitions */
-+/* GLB_VERSION register */
-+#define GLB_VERSION_PATCH_SHIFT (0)
-+#define GLB_VERSION_MINOR_SHIFT (16)
-+#define GLB_VERSION_MAJOR_SHIFT (24)
-+
-+/* CS_REQ register */
-+#define CS_REQ_STATE_SHIFT 0
-+#define CS_REQ_STATE_MASK (0x7 << CS_REQ_STATE_SHIFT)
-+#define CS_REQ_STATE_GET(reg_val) (((reg_val)&CS_REQ_STATE_MASK) >> CS_REQ_STATE_SHIFT)
-+#define CS_REQ_STATE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_STATE_MASK) | (((value) << CS_REQ_STATE_SHIFT) & CS_REQ_STATE_MASK))
-+/* CS_REQ_STATE values */
-+#define CS_REQ_STATE_STOP 0x0
-+#define CS_REQ_STATE_START 0x1
-+/* End of CS_REQ_STATE values */
-+#define CS_REQ_EXTRACT_EVENT_SHIFT 4
-+#define CS_REQ_EXTRACT_EVENT_MASK (0x1 << CS_REQ_EXTRACT_EVENT_SHIFT)
-+#define CS_REQ_EXTRACT_EVENT_GET(reg_val) (((reg_val)&CS_REQ_EXTRACT_EVENT_MASK) >> CS_REQ_EXTRACT_EVENT_SHIFT)
-+#define CS_REQ_EXTRACT_EVENT_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_EXTRACT_EVENT_MASK) | (((value) << CS_REQ_EXTRACT_EVENT_SHIFT) & CS_REQ_EXTRACT_EVENT_MASK))
-+
-+#define CS_REQ_IDLE_SYNC_WAIT_SHIFT 8
-+#define CS_REQ_IDLE_SYNC_WAIT_MASK (0x1 << CS_REQ_IDLE_SYNC_WAIT_SHIFT)
-+#define CS_REQ_IDLE_SYNC_WAIT_GET(reg_val) (((reg_val)&CS_REQ_IDLE_SYNC_WAIT_MASK) >> CS_REQ_IDLE_SYNC_WAIT_SHIFT)
-+#define CS_REQ_IDLE_SYNC_WAIT_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_IDLE_SYNC_WAIT_MASK) | \
-+ (((value) << CS_REQ_IDLE_SYNC_WAIT_SHIFT) & CS_REQ_IDLE_SYNC_WAIT_MASK))
-+#define CS_REQ_IDLE_PROTM_PEND_SHIFT 9
-+#define CS_REQ_IDLE_PROTM_PEND_MASK (0x1 << CS_REQ_IDLE_PROTM_PEND_SHIFT)
-+#define CS_REQ_IDLE_PROTM_PEND_GET(reg_val) (((reg_val)&CS_REQ_IDLE_PROTM_PEND_MASK) >> CS_REQ_IDLE_PROTM_PEND_SHIFT)
-+#define CS_REQ_IDLE_PROTM_PEND_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_IDLE_PROTM_PEND_MASK) | \
-+ (((value) << CS_REQ_IDLE_PROTM_PEND_SHIFT) & CS_REQ_IDLE_PROTM_PEND_MASK))
-+#define CS_REQ_IDLE_EMPTY_SHIFT 10
-+#define CS_REQ_IDLE_EMPTY_MASK (0x1 << CS_REQ_IDLE_EMPTY_SHIFT)
-+#define CS_REQ_IDLE_EMPTY_GET(reg_val) (((reg_val)&CS_REQ_IDLE_EMPTY_MASK) >> CS_REQ_IDLE_EMPTY_SHIFT)
-+#define CS_REQ_IDLE_EMPTY_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_IDLE_EMPTY_MASK) | (((value) << CS_REQ_IDLE_EMPTY_SHIFT) & CS_REQ_IDLE_EMPTY_MASK))
-+#define CS_REQ_IDLE_RESOURCE_REQ_SHIFT 11
-+#define CS_REQ_IDLE_RESOURCE_REQ_MASK (0x1 << CS_REQ_IDLE_RESOURCE_REQ_SHIFT)
-+#define CS_REQ_IDLE_RESOURCE_REQ_GET(reg_val) \
-+ (((reg_val)&CS_REQ_IDLE_RESOURCE_REQ_MASK) >> CS_REQ_IDLE_RESOURCE_REQ_SHIFT)
-+#define CS_REQ_IDLE_RESOURCE_REQ_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_IDLE_RESOURCE_REQ_MASK) | \
-+ (((value) << CS_REQ_IDLE_RESOURCE_REQ_SHIFT) & CS_REQ_IDLE_RESOURCE_REQ_MASK))
-+#define CS_REQ_TILER_OOM_SHIFT 26
-+#define CS_REQ_TILER_OOM_MASK (0x1 << CS_REQ_TILER_OOM_SHIFT)
-+#define CS_REQ_TILER_OOM_GET(reg_val) (((reg_val)&CS_REQ_TILER_OOM_MASK) >> CS_REQ_TILER_OOM_SHIFT)
-+#define CS_REQ_TILER_OOM_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_TILER_OOM_MASK) | (((value) << CS_REQ_TILER_OOM_SHIFT) & CS_REQ_TILER_OOM_MASK))
-+#define CS_REQ_PROTM_PEND_SHIFT 27
-+#define CS_REQ_PROTM_PEND_MASK (0x1 << CS_REQ_PROTM_PEND_SHIFT)
-+#define CS_REQ_PROTM_PEND_GET(reg_val) (((reg_val)&CS_REQ_PROTM_PEND_MASK) >> CS_REQ_PROTM_PEND_SHIFT)
-+#define CS_REQ_PROTM_PEND_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_PROTM_PEND_MASK) | (((value) << CS_REQ_PROTM_PEND_SHIFT) & CS_REQ_PROTM_PEND_MASK))
-+#define CS_REQ_FATAL_SHIFT 30
-+#define CS_REQ_FATAL_MASK (0x1 << CS_REQ_FATAL_SHIFT)
-+#define CS_REQ_FATAL_GET(reg_val) (((reg_val)&CS_REQ_FATAL_MASK) >> CS_REQ_FATAL_SHIFT)
-+#define CS_REQ_FATAL_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_FATAL_MASK) | (((value) << CS_REQ_FATAL_SHIFT) & CS_REQ_FATAL_MASK))
-+#define CS_REQ_FAULT_SHIFT 31
-+#define CS_REQ_FAULT_MASK (0x1 << CS_REQ_FAULT_SHIFT)
-+#define CS_REQ_FAULT_GET(reg_val) (((reg_val)&CS_REQ_FAULT_MASK) >> CS_REQ_FAULT_SHIFT)
-+#define CS_REQ_FAULT_SET(reg_val, value) \
-+ (((reg_val) & ~CS_REQ_FAULT_MASK) | (((value) << CS_REQ_FAULT_SHIFT) & CS_REQ_FAULT_MASK))
-+
-+/* CS_CONFIG register */
-+#define CS_CONFIG_PRIORITY_SHIFT 0
-+#define CS_CONFIG_PRIORITY_MASK (0xF << CS_CONFIG_PRIORITY_SHIFT)
-+#define CS_CONFIG_PRIORITY_GET(reg_val) (((reg_val)&CS_CONFIG_PRIORITY_MASK) >> CS_CONFIG_PRIORITY_SHIFT)
-+#define CS_CONFIG_PRIORITY_SET(reg_val, value) \
-+ (((reg_val) & ~CS_CONFIG_PRIORITY_MASK) | (((value) << CS_CONFIG_PRIORITY_SHIFT) & CS_CONFIG_PRIORITY_MASK))
-+#define CS_CONFIG_USER_DOORBELL_SHIFT 8
-+#define CS_CONFIG_USER_DOORBELL_MASK (0xFF << CS_CONFIG_USER_DOORBELL_SHIFT)
-+#define CS_CONFIG_USER_DOORBELL_GET(reg_val) (((reg_val)&CS_CONFIG_USER_DOORBELL_MASK) >> CS_CONFIG_USER_DOORBELL_SHIFT)
-+#define CS_CONFIG_USER_DOORBELL_SET(reg_val, value) \
-+ (((reg_val) & ~CS_CONFIG_USER_DOORBELL_MASK) | \
-+ (((value) << CS_CONFIG_USER_DOORBELL_SHIFT) & CS_CONFIG_USER_DOORBELL_MASK))
-+
-+/* CS_ACK_IRQ_MASK register */
-+#define CS_ACK_IRQ_MASK_STATE_SHIFT 0
-+#define CS_ACK_IRQ_MASK_STATE_MASK (0x7 << CS_ACK_IRQ_MASK_STATE_SHIFT)
-+#define CS_ACK_IRQ_MASK_STATE_GET(reg_val) (((reg_val)&CS_ACK_IRQ_MASK_STATE_MASK) >> CS_ACK_IRQ_MASK_STATE_SHIFT)
-+#define CS_ACK_IRQ_MASK_STATE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_IRQ_MASK_STATE_MASK) | \
-+ (((value) << CS_ACK_IRQ_MASK_STATE_SHIFT) & CS_ACK_IRQ_MASK_STATE_MASK))
-+/* CS_ACK_IRQ_MASK_STATE values */
-+#define CS_ACK_IRQ_MASK_STATE_DISABLED 0x0
-+#define CS_ACK_IRQ_MASK_STATE_ENABLED 0x7
-+/* End of CS_ACK_IRQ_MASK_STATE values */
-+#define CS_ACK_IRQ_MASK_EXTRACT_EVENT_SHIFT 4
-+#define CS_ACK_IRQ_MASK_EXTRACT_EVENT_MASK (0x1 << CS_ACK_IRQ_MASK_EXTRACT_EVENT_SHIFT)
-+#define CS_ACK_IRQ_MASK_EXTRACT_EVENT_GET(reg_val) \
-+ (((reg_val)&CS_ACK_IRQ_MASK_EXTRACT_EVENT_MASK) >> CS_ACK_IRQ_MASK_EXTRACT_EVENT_SHIFT)
-+#define CS_ACK_IRQ_MASK_EXTRACT_EVENT_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_IRQ_MASK_EXTRACT_EVENT_MASK) | \
-+ (((value) << CS_ACK_IRQ_MASK_EXTRACT_EVENT_SHIFT) & CS_ACK_IRQ_MASK_EXTRACT_EVENT_MASK))
-+#define CS_ACK_IRQ_MASK_TILER_OOM_SHIFT 26
-+#define CS_ACK_IRQ_MASK_TILER_OOM_MASK (0x1 << CS_ACK_IRQ_MASK_TILER_OOM_SHIFT)
-+#define CS_ACK_IRQ_MASK_TILER_OOM_GET(reg_val) \
-+ (((reg_val)&CS_ACK_IRQ_MASK_TILER_OOM_MASK) >> CS_ACK_IRQ_MASK_TILER_OOM_SHIFT)
-+#define CS_ACK_IRQ_MASK_TILER_OOM_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_IRQ_MASK_TILER_OOM_MASK) | \
-+ (((value) << CS_ACK_IRQ_MASK_TILER_OOM_SHIFT) & CS_ACK_IRQ_MASK_TILER_OOM_MASK))
-+#define CS_ACK_IRQ_MASK_PROTM_PEND_SHIFT 27
-+#define CS_ACK_IRQ_MASK_PROTM_PEND_MASK (0x1 << CS_ACK_IRQ_MASK_PROTM_PEND_SHIFT)
-+#define CS_ACK_IRQ_MASK_PROTM_PEND_GET(reg_val) \
-+ (((reg_val)&CS_ACK_IRQ_MASK_PROTM_PEND_MASK) >> CS_ACK_IRQ_MASK_PROTM_PEND_SHIFT)
-+#define CS_ACK_IRQ_MASK_PROTM_PEND_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_IRQ_MASK_PROTM_PEND_MASK) | \
-+ (((value) << CS_ACK_IRQ_MASK_PROTM_PEND_SHIFT) & CS_ACK_IRQ_MASK_PROTM_PEND_MASK))
-+#define CS_ACK_IRQ_MASK_FATAL_SHIFT 30
-+#define CS_ACK_IRQ_MASK_FATAL_MASK (0x1 << CS_ACK_IRQ_MASK_FATAL_SHIFT)
-+#define CS_ACK_IRQ_MASK_FATAL_GET(reg_val) (((reg_val)&CS_ACK_IRQ_MASK_FATAL_MASK) >> CS_ACK_IRQ_MASK_FATAL_SHIFT)
-+#define CS_ACK_IRQ_MASK_FATAL_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_IRQ_MASK_FATAL_MASK) | \
-+ (((value) << CS_ACK_IRQ_MASK_FATAL_SHIFT) & CS_ACK_IRQ_MASK_FATAL_MASK))
-+#define CS_ACK_IRQ_MASK_FAULT_SHIFT 31
-+#define CS_ACK_IRQ_MASK_FAULT_MASK (0x1 << CS_ACK_IRQ_MASK_FAULT_SHIFT)
-+#define CS_ACK_IRQ_MASK_FAULT_GET(reg_val) (((reg_val)&CS_ACK_IRQ_MASK_FAULT_MASK) >> CS_ACK_IRQ_MASK_FAULT_SHIFT)
-+#define CS_ACK_IRQ_MASK_FAULT_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_IRQ_MASK_FAULT_MASK) | \
-+ (((value) << CS_ACK_IRQ_MASK_FAULT_SHIFT) & CS_ACK_IRQ_MASK_FAULT_MASK))
-+
-+/* CS_BASE register */
-+#define CS_BASE_POINTER_SHIFT 0
-+#define CS_BASE_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_BASE_POINTER_SHIFT)
-+#define CS_BASE_POINTER_GET(reg_val) (((reg_val)&CS_BASE_POINTER_MASK) >> CS_BASE_POINTER_SHIFT)
-+#define CS_BASE_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_BASE_POINTER_MASK) | (((value) << CS_BASE_POINTER_SHIFT) & CS_BASE_POINTER_MASK))
-+
-+/* CS_SIZE register */
-+#define CS_SIZE_SIZE_SHIFT 0
-+#define CS_SIZE_SIZE_MASK (0xFFFFFFFF << CS_SIZE_SIZE_SHIFT)
-+#define CS_SIZE_SIZE_GET(reg_val) (((reg_val)&CS_SIZE_SIZE_MASK) >> CS_SIZE_SIZE_SHIFT)
-+#define CS_SIZE_SIZE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_SIZE_SIZE_MASK) | (((value) << CS_SIZE_SIZE_SHIFT) & CS_SIZE_SIZE_MASK))
-+
-+/* CS_TILER_HEAP_START register */
-+#define CS_TILER_HEAP_START_POINTER_SHIFT 0
-+#define CS_TILER_HEAP_START_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_TILER_HEAP_START_POINTER_SHIFT)
-+#define CS_TILER_HEAP_START_POINTER_GET(reg_val) \
-+ (((reg_val)&CS_TILER_HEAP_START_POINTER_MASK) >> CS_TILER_HEAP_START_POINTER_SHIFT)
-+#define CS_TILER_HEAP_START_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_TILER_HEAP_START_POINTER_MASK) | \
-+ (((value) << CS_TILER_HEAP_START_POINTER_SHIFT) & CS_TILER_HEAP_START_POINTER_MASK))
-+/* HeapChunkPointer nested in CS_TILER_HEAP_START_POINTER */
-+/* End of HeapChunkPointer nested in CS_TILER_HEAP_START_POINTER */
-+
-+/* CS_TILER_HEAP_END register */
-+#define CS_TILER_HEAP_END_POINTER_SHIFT 0
-+#define CS_TILER_HEAP_END_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_TILER_HEAP_END_POINTER_SHIFT)
-+#define CS_TILER_HEAP_END_POINTER_GET(reg_val) \
-+ (((reg_val)&CS_TILER_HEAP_END_POINTER_MASK) >> CS_TILER_HEAP_END_POINTER_SHIFT)
-+#define CS_TILER_HEAP_END_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_TILER_HEAP_END_POINTER_MASK) | \
-+ (((value) << CS_TILER_HEAP_END_POINTER_SHIFT) & CS_TILER_HEAP_END_POINTER_MASK))
-+/* HeapChunkPointer nested in CS_TILER_HEAP_END_POINTER */
-+/* End of HeapChunkPointer nested in CS_TILER_HEAP_END_POINTER */
-+
-+/* CS_USER_INPUT register */
-+#define CS_USER_INPUT_POINTER_SHIFT 0
-+#define CS_USER_INPUT_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_USER_INPUT_POINTER_SHIFT)
-+#define CS_USER_INPUT_POINTER_GET(reg_val) (((reg_val)&CS_USER_INPUT_POINTER_MASK) >> CS_USER_INPUT_POINTER_SHIFT)
-+#define CS_USER_INPUT_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_USER_INPUT_POINTER_MASK) | \
-+ (((value) << CS_USER_INPUT_POINTER_SHIFT) & CS_USER_INPUT_POINTER_MASK))
-+
-+/* CS_USER_OUTPUT register */
-+#define CS_USER_OUTPUT_POINTER_SHIFT 0
-+#define CS_USER_OUTPUT_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_USER_OUTPUT_POINTER_SHIFT)
-+#define CS_USER_OUTPUT_POINTER_GET(reg_val) (((reg_val)&CS_USER_OUTPUT_POINTER_MASK) >> CS_USER_OUTPUT_POINTER_SHIFT)
-+#define CS_USER_OUTPUT_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_USER_OUTPUT_POINTER_MASK) | \
-+ (((value) << CS_USER_OUTPUT_POINTER_SHIFT) & CS_USER_OUTPUT_POINTER_MASK))
-+
-+/* CS_INSTR_CONFIG register */
-+#define CS_INSTR_CONFIG_JASID_SHIFT (0)
-+#define CS_INSTR_CONFIG_JASID_MASK ((u32)0xF << CS_INSTR_CONFIG_JASID_SHIFT)
-+#define CS_INSTR_CONFIG_JASID_GET(reg_val) (((reg_val)&CS_INSTR_CONFIG_JASID_MASK) >> CS_INSTR_CONFIG_JASID_SHIFT)
-+#define CS_INSTR_CONFIG_JASID_SET(reg_val, value) \
-+ (((reg_val) & ~CS_INSTR_CONFIG_JASID_MASK) | \
-+ (((value) << CS_INSTR_CONFIG_JASID_SHIFT) & CS_INSTR_CONFIG_JASID_MASK))
-+#define CS_INSTR_CONFIG_EVENT_SIZE_SHIFT (4)
-+#define CS_INSTR_CONFIG_EVENT_SIZE_MASK ((u32)0xF << CS_INSTR_CONFIG_EVENT_SIZE_SHIFT)
-+#define CS_INSTR_CONFIG_EVENT_SIZE_GET(reg_val) \
-+ (((reg_val)&CS_INSTR_CONFIG_EVENT_SIZE_MASK) >> CS_INSTR_CONFIG_EVENT_SIZE_SHIFT)
-+#define CS_INSTR_CONFIG_EVENT_SIZE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_INSTR_CONFIG_EVENT_SIZE_MASK) | \
-+ (((value) << CS_INSTR_CONFIG_EVENT_SIZE_SHIFT) & CS_INSTR_CONFIG_EVENT_SIZE_MASK))
-+#define CS_INSTR_CONFIG_EVENT_STATE_SHIFT (16)
-+#define CS_INSTR_CONFIG_EVENT_STATE_MASK ((u32)0xFF << CS_INSTR_CONFIG_EVENT_STATE_SHIFT)
-+#define CS_INSTR_CONFIG_EVENT_STATE_GET(reg_val) \
-+ (((reg_val)&CS_INSTR_CONFIG_EVENT_STATE_MASK) >> CS_INSTR_CONFIG_EVENT_STATE_SHIFT)
-+#define CS_INSTR_CONFIG_EVENT_STATE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_INSTR_CONFIG_EVENT_STATE_MASK) | \
-+ (((value) << CS_INSTR_CONFIG_EVENT_STATE_SHIFT) & CS_INSTR_CONFIG_EVENT_STATE_MASK))
-+
-+/* CS_INSTR_BUFFER_SIZE register */
-+#define CS_INSTR_BUFFER_SIZE_SIZE_SHIFT (0)
-+#define CS_INSTR_BUFFER_SIZE_SIZE_MASK ((u32)0xFFFFFFFF << CS_INSTR_BUFFER_SIZE_SIZE_SHIFT)
-+#define CS_INSTR_BUFFER_SIZE_SIZE_GET(reg_val) \
-+ (((reg_val)&CS_INSTR_BUFFER_SIZE_SIZE_MASK) >> CS_INSTR_BUFFER_SIZE_SIZE_SHIFT)
-+#define CS_INSTR_BUFFER_SIZE_SIZE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_INSTR_BUFFER_SIZE_SIZE_MASK) | \
-+ (((value) << CS_INSTR_BUFFER_SIZE_SIZE_SHIFT) & CS_INSTR_BUFFER_SIZE_SIZE_MASK))
-+
-+/* CS_INSTR_BUFFER_BASE register */
-+#define CS_INSTR_BUFFER_BASE_POINTER_SHIFT (0)
-+#define CS_INSTR_BUFFER_BASE_POINTER_MASK ((u64)0xFFFFFFFFFFFFFFFF << CS_INSTR_BUFFER_BASE_POINTER_SHIFT)
-+#define CS_INSTR_BUFFER_BASE_POINTER_GET(reg_val) \
-+ (((reg_val)&CS_INSTR_BUFFER_BASE_POINTER_MASK) >> CS_INSTR_BUFFER_BASE_POINTER_SHIFT)
-+#define CS_INSTR_BUFFER_BASE_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_INSTR_BUFFER_BASE_POINTER_MASK) | \
-+ (((value) << CS_INSTR_BUFFER_BASE_POINTER_SHIFT) & CS_INSTR_BUFFER_BASE_POINTER_MASK))
-+
-+/* CS_INSTR_BUFFER_OFFSET_POINTER register */
-+#define CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SHIFT (0)
-+#define CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_MASK \
-+ ((u64)0xFFFFFFFFFFFFFFFF) << CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SHIFT)
-+#define CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_GET(reg_val) \
-+ (((reg_val)&CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_MASK) >> CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SHIFT)
-+#define CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_MASK) | \
-+ (((value) << CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SHIFT) & CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_MASK))
-+
-+/* End of CS_KERNEL_INPUT_BLOCK register set definitions */
-+
-+/* CS_KERNEL_OUTPUT_BLOCK register set definitions */
-+
-+/* CS_ACK register */
-+#define CS_ACK_STATE_SHIFT 0
-+#define CS_ACK_STATE_MASK (0x7 << CS_ACK_STATE_SHIFT)
-+#define CS_ACK_STATE_GET(reg_val) (((reg_val)&CS_ACK_STATE_MASK) >> CS_ACK_STATE_SHIFT)
-+#define CS_ACK_STATE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_STATE_MASK) | (((value) << CS_ACK_STATE_SHIFT) & CS_ACK_STATE_MASK))
-+/* CS_ACK_STATE values */
-+#define CS_ACK_STATE_STOP 0x0
-+#define CS_ACK_STATE_START 0x1
-+/* End of CS_ACK_STATE values */
-+#define CS_ACK_EXTRACT_EVENT_SHIFT 4
-+#define CS_ACK_EXTRACT_EVENT_MASK (0x1 << CS_ACK_EXTRACT_EVENT_SHIFT)
-+#define CS_ACK_EXTRACT_EVENT_GET(reg_val) (((reg_val)&CS_ACK_EXTRACT_EVENT_MASK) >> CS_ACK_EXTRACT_EVENT_SHIFT)
-+#define CS_ACK_EXTRACT_EVENT_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_EXTRACT_EVENT_MASK) | (((value) << CS_ACK_EXTRACT_EVENT_SHIFT) & CS_ACK_EXTRACT_EVENT_MASK))
-+#define CS_ACK_TILER_OOM_SHIFT 26
-+#define CS_ACK_TILER_OOM_MASK (0x1 << CS_ACK_TILER_OOM_SHIFT)
-+#define CS_ACK_TILER_OOM_GET(reg_val) (((reg_val)&CS_ACK_TILER_OOM_MASK) >> CS_ACK_TILER_OOM_SHIFT)
-+#define CS_ACK_TILER_OOM_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_TILER_OOM_MASK) | (((value) << CS_ACK_TILER_OOM_SHIFT) & CS_ACK_TILER_OOM_MASK))
-+#define CS_ACK_PROTM_PEND_SHIFT 27
-+#define CS_ACK_PROTM_PEND_MASK (0x1 << CS_ACK_PROTM_PEND_SHIFT)
-+#define CS_ACK_PROTM_PEND_GET(reg_val) (((reg_val)&CS_ACK_PROTM_PEND_MASK) >> CS_ACK_PROTM_PEND_SHIFT)
-+#define CS_ACK_PROTM_PEND_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_PROTM_PEND_MASK) | (((value) << CS_ACK_PROTM_PEND_SHIFT) & CS_ACK_PROTM_PEND_MASK))
-+#define CS_ACK_FATAL_SHIFT 30
-+#define CS_ACK_FATAL_MASK (0x1 << CS_ACK_FATAL_SHIFT)
-+#define CS_ACK_FATAL_GET(reg_val) (((reg_val)&CS_ACK_FATAL_MASK) >> CS_ACK_FATAL_SHIFT)
-+#define CS_ACK_FATAL_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_FATAL_MASK) | (((value) << CS_ACK_FATAL_SHIFT) & CS_ACK_FATAL_MASK))
-+#define CS_ACK_FAULT_SHIFT 31
-+#define CS_ACK_FAULT_MASK (0x1 << CS_ACK_FAULT_SHIFT)
-+#define CS_ACK_FAULT_GET(reg_val) (((reg_val)&CS_ACK_FAULT_MASK) >> CS_ACK_FAULT_SHIFT)
-+#define CS_ACK_FAULT_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACK_FAULT_MASK) | (((value) << CS_ACK_FAULT_SHIFT) & CS_ACK_FAULT_MASK))
-+
-+/* CS_STATUS_CMD_PTR register */
-+#define CS_STATUS_CMD_PTR_POINTER_SHIFT 0
-+#define CS_STATUS_CMD_PTR_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_STATUS_CMD_PTR_POINTER_SHIFT)
-+#define CS_STATUS_CMD_PTR_POINTER_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_CMD_PTR_POINTER_MASK) >> CS_STATUS_CMD_PTR_POINTER_SHIFT)
-+#define CS_STATUS_CMD_PTR_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_CMD_PTR_POINTER_MASK) | \
-+ (((value) << CS_STATUS_CMD_PTR_POINTER_SHIFT) & CS_STATUS_CMD_PTR_POINTER_MASK))
-+
-+/* CS_STATUS_WAIT register */
-+#define CS_STATUS_WAIT_SB_MASK_SHIFT 0
-+#define CS_STATUS_WAIT_SB_MASK_MASK (0xFFFF << CS_STATUS_WAIT_SB_MASK_SHIFT)
-+#define CS_STATUS_WAIT_SB_MASK_GET(reg_val) (((reg_val)&CS_STATUS_WAIT_SB_MASK_MASK) >> CS_STATUS_WAIT_SB_MASK_SHIFT)
-+#define CS_STATUS_WAIT_SB_MASK_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_WAIT_SB_MASK_MASK) | \
-+ (((value) << CS_STATUS_WAIT_SB_MASK_SHIFT) & CS_STATUS_WAIT_SB_MASK_MASK))
-+#define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_SHIFT 24
-+#define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_MASK (0xF << CS_STATUS_WAIT_SYNC_WAIT_CONDITION_SHIFT)
-+#define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_WAIT_SYNC_WAIT_CONDITION_MASK) >> CS_STATUS_WAIT_SYNC_WAIT_CONDITION_SHIFT)
-+#define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_WAIT_SYNC_WAIT_CONDITION_MASK) | \
-+ (((value) << CS_STATUS_WAIT_SYNC_WAIT_CONDITION_SHIFT) & CS_STATUS_WAIT_SYNC_WAIT_CONDITION_MASK))
-+/* CS_STATUS_WAIT_SYNC_WAIT_CONDITION values */
-+#define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_LE 0x0
-+#define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GT 0x1
-+/* End of CS_STATUS_WAIT_SYNC_WAIT_CONDITION values */
-+#define CS_STATUS_WAIT_PROGRESS_WAIT_SHIFT 28
-+#define CS_STATUS_WAIT_PROGRESS_WAIT_MASK (0x1 << CS_STATUS_WAIT_PROGRESS_WAIT_SHIFT)
-+#define CS_STATUS_WAIT_PROGRESS_WAIT_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_WAIT_PROGRESS_WAIT_MASK) >> CS_STATUS_WAIT_PROGRESS_WAIT_SHIFT)
-+#define CS_STATUS_WAIT_PROGRESS_WAIT_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_WAIT_PROGRESS_WAIT_MASK) | \
-+ (((value) << CS_STATUS_WAIT_PROGRESS_WAIT_SHIFT) & CS_STATUS_WAIT_PROGRESS_WAIT_MASK))
-+#define CS_STATUS_WAIT_PROTM_PEND_SHIFT 29
-+#define CS_STATUS_WAIT_PROTM_PEND_MASK (0x1 << CS_STATUS_WAIT_PROTM_PEND_SHIFT)
-+#define CS_STATUS_WAIT_PROTM_PEND_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_WAIT_PROTM_PEND_MASK) >> CS_STATUS_WAIT_PROTM_PEND_SHIFT)
-+#define CS_STATUS_WAIT_PROTM_PEND_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_WAIT_PROTM_PEND_MASK) | \
-+ (((value) << CS_STATUS_WAIT_PROTM_PEND_SHIFT) & CS_STATUS_WAIT_PROTM_PEND_MASK))
-+#define CS_STATUS_WAIT_SYNC_WAIT_SHIFT 31
-+#define CS_STATUS_WAIT_SYNC_WAIT_MASK (0x1 << CS_STATUS_WAIT_SYNC_WAIT_SHIFT)
-+#define CS_STATUS_WAIT_SYNC_WAIT_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_WAIT_SYNC_WAIT_MASK) >> CS_STATUS_WAIT_SYNC_WAIT_SHIFT)
-+#define CS_STATUS_WAIT_SYNC_WAIT_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_WAIT_SYNC_WAIT_MASK) | \
-+ (((value) << CS_STATUS_WAIT_SYNC_WAIT_SHIFT) & CS_STATUS_WAIT_SYNC_WAIT_MASK))
-+
-+/* CS_STATUS_REQ_RESOURCE register */
-+#define CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_SHIFT 0
-+#define CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_MASK (0x1 << CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_SHIFT)
-+#define CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_MASK) >> CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_SHIFT)
-+#define CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_MASK) | \
-+ (((value) << CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_SHIFT) & CS_STATUS_REQ_RESOURCE_COMPUTE_RESOURCES_MASK))
-+#define CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_SHIFT 1
-+#define CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_MASK (0x1 << CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_SHIFT)
-+#define CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_MASK) >> CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_SHIFT)
-+#define CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_MASK) | \
-+ (((value) << CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_SHIFT) & CS_STATUS_REQ_RESOURCE_FRAGMENT_RESOURCES_MASK))
-+#define CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_SHIFT 2
-+#define CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_MASK (0x1 << CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_SHIFT)
-+#define CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_MASK) >> CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_SHIFT)
-+#define CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_MASK) | \
-+ (((value) << CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_SHIFT) & CS_STATUS_REQ_RESOURCE_TILER_RESOURCES_MASK))
-+#define CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_SHIFT 3
-+#define CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_MASK (0x1 << CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_SHIFT)
-+#define CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_MASK) >> CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_SHIFT)
-+#define CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_MASK) | \
-+ (((value) << CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_SHIFT) & CS_STATUS_REQ_RESOURCE_IDVS_RESOURCES_MASK))
-+
-+/* CS_STATUS_WAIT_SYNC_POINTER register */
-+#define CS_STATUS_WAIT_SYNC_POINTER_POINTER_SHIFT 0
-+#define CS_STATUS_WAIT_SYNC_POINTER_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_STATUS_WAIT_SYNC_POINTER_POINTER_SHIFT)
-+#define CS_STATUS_WAIT_SYNC_POINTER_POINTER_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_WAIT_SYNC_POINTER_POINTER_MASK) >> CS_STATUS_WAIT_SYNC_POINTER_POINTER_SHIFT)
-+#define CS_STATUS_WAIT_SYNC_POINTER_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_WAIT_SYNC_POINTER_POINTER_MASK) | \
-+ (((value) << CS_STATUS_WAIT_SYNC_POINTER_POINTER_SHIFT) & CS_STATUS_WAIT_SYNC_POINTER_POINTER_MASK))
-+
-+/* CS_STATUS_WAIT_SYNC_VALUE register */
-+#define CS_STATUS_WAIT_SYNC_VALUE_VALUE_SHIFT 0
-+#define CS_STATUS_WAIT_SYNC_VALUE_VALUE_MASK (0xFFFFFFFF << CS_STATUS_WAIT_SYNC_VALUE_VALUE_SHIFT)
-+#define CS_STATUS_WAIT_SYNC_VALUE_VALUE_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_WAIT_SYNC_VALUE_VALUE_MASK) >> CS_STATUS_WAIT_SYNC_VALUE_VALUE_SHIFT)
-+#define CS_STATUS_WAIT_SYNC_VALUE_VALUE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_WAIT_SYNC_VALUE_VALUE_MASK) | \
-+ (((value) << CS_STATUS_WAIT_SYNC_VALUE_VALUE_SHIFT) & CS_STATUS_WAIT_SYNC_VALUE_VALUE_MASK))
-+
-+/* CS_STATUS_SCOREBOARDS register */
-+#define CS_STATUS_SCOREBOARDS_NONZERO_SHIFT (0)
-+#define CS_STATUS_SCOREBOARDS_NONZERO_MASK \
-+ ((0xFFFF) << CS_STATUS_SCOREBOARDS_NONZERO_SHIFT)
-+#define CS_STATUS_SCOREBOARDS_NONZERO_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_SCOREBOARDS_NONZERO_MASK) >> \
-+ CS_STATUS_SCOREBOARDS_NONZERO_SHIFT)
-+#define CS_STATUS_SCOREBOARDS_NONZERO_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_SCOREBOARDS_NONZERO_MASK) | \
-+ (((value) << CS_STATUS_SCOREBOARDS_NONZERO_SHIFT) & \
-+ CS_STATUS_SCOREBOARDS_NONZERO_MASK))
-+
-+/* CS_STATUS_BLOCKED_REASON register */
-+#define CS_STATUS_BLOCKED_REASON_REASON_SHIFT (0)
-+#define CS_STATUS_BLOCKED_REASON_REASON_MASK \
-+ ((0xF) << CS_STATUS_BLOCKED_REASON_REASON_SHIFT)
-+#define CS_STATUS_BLOCKED_REASON_REASON_GET(reg_val) \
-+ (((reg_val)&CS_STATUS_BLOCKED_REASON_REASON_MASK) >> \
-+ CS_STATUS_BLOCKED_REASON_REASON_SHIFT)
-+#define CS_STATUS_BLOCKED_REASON_REASON_SET(reg_val, value) \
-+ (((reg_val) & ~CS_STATUS_BLOCKED_REASON_REASON_MASK) | \
-+ (((value) << CS_STATUS_BLOCKED_REASON_REASON_SHIFT) & \
-+ CS_STATUS_BLOCKED_REASON_REASON_MASK))
-+/* CS_STATUS_BLOCKED_REASON_reason values */
-+#define CS_STATUS_BLOCKED_REASON_REASON_UNBLOCKED 0x0
-+#define CS_STATUS_BLOCKED_REASON_REASON_WAIT 0x1
-+#define CS_STATUS_BLOCKED_REASON_REASON_PROGRESS_WAIT 0x2
-+#define CS_STATUS_BLOCKED_REASON_REASON_SYNC_WAIT 0x3
-+#define CS_STATUS_BLOCKED_REASON_REASON_DEFERRED 0x4
-+#define CS_STATUS_BLOCKED_REASON_REASON_RESOURCE 0x5
-+#define CS_STATUS_BLOCKED_REASON_REASON_FLUSH 0x6
-+/* End of CS_STATUS_BLOCKED_REASON_reason values */
-+
-+/* CS_FAULT register */
-+#define CS_FAULT_EXCEPTION_TYPE_SHIFT 0
-+#define CS_FAULT_EXCEPTION_TYPE_MASK (0xFF << CS_FAULT_EXCEPTION_TYPE_SHIFT)
-+#define CS_FAULT_EXCEPTION_TYPE_GET(reg_val) (((reg_val)&CS_FAULT_EXCEPTION_TYPE_MASK) >> CS_FAULT_EXCEPTION_TYPE_SHIFT)
-+#define CS_FAULT_EXCEPTION_TYPE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_FAULT_EXCEPTION_TYPE_MASK) | \
-+ (((value) << CS_FAULT_EXCEPTION_TYPE_SHIFT) & CS_FAULT_EXCEPTION_TYPE_MASK))
-+/* CS_FAULT_EXCEPTION_TYPE values */
-+#define CS_FAULT_EXCEPTION_TYPE_CS_RESOURCE_TERMINATED 0x0F
-+#define CS_FAULT_EXCEPTION_TYPE_CS_INHERIT_FAULT 0x4B
-+#define CS_FAULT_EXCEPTION_TYPE_INSTR_INVALID_PC 0x50
-+#define CS_FAULT_EXCEPTION_TYPE_INSTR_INVALID_ENC 0x51
-+#define CS_FAULT_EXCEPTION_TYPE_INSTR_BARRIER_FAULT 0x55
-+#define CS_FAULT_EXCEPTION_TYPE_DATA_INVALID_FAULT 0x58
-+#define CS_FAULT_EXCEPTION_TYPE_TILE_RANGE_FAULT 0x59
-+#define CS_FAULT_EXCEPTION_TYPE_ADDR_RANGE_FAULT 0x5A
-+#define CS_FAULT_EXCEPTION_TYPE_IMPRECISE_FAULT 0x5B
-+#define CS_FAULT_EXCEPTION_TYPE_RESOURCE_EVICTION_TIMEOUT 0x69
-+/* End of CS_FAULT_EXCEPTION_TYPE values */
-+#define CS_FAULT_EXCEPTION_DATA_SHIFT 8
-+#define CS_FAULT_EXCEPTION_DATA_MASK (0xFFFFFF << CS_FAULT_EXCEPTION_DATA_SHIFT)
-+#define CS_FAULT_EXCEPTION_DATA_GET(reg_val) (((reg_val)&CS_FAULT_EXCEPTION_DATA_MASK) >> CS_FAULT_EXCEPTION_DATA_SHIFT)
-+#define CS_FAULT_EXCEPTION_DATA_SET(reg_val, value) \
-+ (((reg_val) & ~CS_FAULT_EXCEPTION_DATA_MASK) | \
-+ (((value) << CS_FAULT_EXCEPTION_DATA_SHIFT) & CS_FAULT_EXCEPTION_DATA_MASK))
-+
-+/* CS_FATAL register */
-+#define CS_FATAL_EXCEPTION_TYPE_SHIFT 0
-+#define CS_FATAL_EXCEPTION_TYPE_MASK (0xFF << CS_FATAL_EXCEPTION_TYPE_SHIFT)
-+#define CS_FATAL_EXCEPTION_TYPE_GET(reg_val) (((reg_val)&CS_FATAL_EXCEPTION_TYPE_MASK) >> CS_FATAL_EXCEPTION_TYPE_SHIFT)
-+#define CS_FATAL_EXCEPTION_TYPE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_FATAL_EXCEPTION_TYPE_MASK) | \
-+ (((value) << CS_FATAL_EXCEPTION_TYPE_SHIFT) & CS_FATAL_EXCEPTION_TYPE_MASK))
-+/* CS_FATAL_EXCEPTION_TYPE values */
-+#define CS_FATAL_EXCEPTION_TYPE_CS_CONFIG_FAULT 0x40
-+#define CS_FATAL_EXCEPTION_TYPE_CS_ENDPOINT_FAULT 0x44
-+#define CS_FATAL_EXCEPTION_TYPE_CS_BUS_FAULT 0x48
-+#define CS_FATAL_EXCEPTION_TYPE_CS_INVALID_INSTRUCTION 0x49
-+#define CS_FATAL_EXCEPTION_TYPE_CS_CALL_STACK_OVERFLOW 0x4A
-+#define CS_FATAL_EXCEPTION_TYPE_FIRMWARE_INTERNAL_ERROR 0x68
-+/* End of CS_FATAL_EXCEPTION_TYPE values */
-+#define CS_FATAL_EXCEPTION_DATA_SHIFT 8
-+#define CS_FATAL_EXCEPTION_DATA_MASK (0xFFFFFF << CS_FATAL_EXCEPTION_DATA_SHIFT)
-+#define CS_FATAL_EXCEPTION_DATA_GET(reg_val) (((reg_val)&CS_FATAL_EXCEPTION_DATA_MASK) >> CS_FATAL_EXCEPTION_DATA_SHIFT)
-+#define CS_FATAL_EXCEPTION_DATA_SET(reg_val, value) \
-+ (((reg_val) & ~CS_FATAL_EXCEPTION_DATA_MASK) | \
-+ (((value) << CS_FATAL_EXCEPTION_DATA_SHIFT) & CS_FATAL_EXCEPTION_DATA_MASK))
-+
-+/* CS_FAULT_INFO register */
-+#define CS_FAULT_INFO_EXCEPTION_DATA_SHIFT 0
-+#define CS_FAULT_INFO_EXCEPTION_DATA_MASK (0xFFFFFFFFFFFFFFFF << CS_FAULT_INFO_EXCEPTION_DATA_SHIFT)
-+#define CS_FAULT_INFO_EXCEPTION_DATA_GET(reg_val) \
-+ (((reg_val)&CS_FAULT_INFO_EXCEPTION_DATA_MASK) >> CS_FAULT_INFO_EXCEPTION_DATA_SHIFT)
-+#define CS_FAULT_INFO_EXCEPTION_DATA_SET(reg_val, value) \
-+ (((reg_val) & ~CS_FAULT_INFO_EXCEPTION_DATA_MASK) | \
-+ (((value) << CS_FAULT_INFO_EXCEPTION_DATA_SHIFT) & CS_FAULT_INFO_EXCEPTION_DATA_MASK))
-+
-+/* CS_FATAL_INFO register */
-+#define CS_FATAL_INFO_EXCEPTION_DATA_SHIFT 0
-+#define CS_FATAL_INFO_EXCEPTION_DATA_MASK (0xFFFFFFFFFFFFFFFF << CS_FATAL_INFO_EXCEPTION_DATA_SHIFT)
-+#define CS_FATAL_INFO_EXCEPTION_DATA_GET(reg_val) \
-+ (((reg_val)&CS_FATAL_INFO_EXCEPTION_DATA_MASK) >> CS_FATAL_INFO_EXCEPTION_DATA_SHIFT)
-+#define CS_FATAL_INFO_EXCEPTION_DATA_SET(reg_val, value) \
-+ (((reg_val) & ~CS_FATAL_INFO_EXCEPTION_DATA_MASK) | \
-+ (((value) << CS_FATAL_INFO_EXCEPTION_DATA_SHIFT) & CS_FATAL_INFO_EXCEPTION_DATA_MASK))
-+
-+/* CS_HEAP_VT_START register */
-+#define CS_HEAP_VT_START_VALUE_SHIFT 0
-+#define CS_HEAP_VT_START_VALUE_MASK (0xFFFFFFFF << CS_HEAP_VT_START_VALUE_SHIFT)
-+#define CS_HEAP_VT_START_VALUE_GET(reg_val) (((reg_val)&CS_HEAP_VT_START_VALUE_MASK) >> CS_HEAP_VT_START_VALUE_SHIFT)
-+#define CS_HEAP_VT_START_VALUE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_HEAP_VT_START_VALUE_MASK) | \
-+ (((value) << CS_HEAP_VT_START_VALUE_SHIFT) & CS_HEAP_VT_START_VALUE_MASK))
-+
-+/* CS_HEAP_VT_END register */
-+#define CS_HEAP_VT_END_VALUE_SHIFT 0
-+#define CS_HEAP_VT_END_VALUE_MASK (0xFFFFFFFF << CS_HEAP_VT_END_VALUE_SHIFT)
-+#define CS_HEAP_VT_END_VALUE_GET(reg_val) (((reg_val)&CS_HEAP_VT_END_VALUE_MASK) >> CS_HEAP_VT_END_VALUE_SHIFT)
-+#define CS_HEAP_VT_END_VALUE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_HEAP_VT_END_VALUE_MASK) | (((value) << CS_HEAP_VT_END_VALUE_SHIFT) & CS_HEAP_VT_END_VALUE_MASK))
-+
-+/* CS_HEAP_FRAG_END register */
-+#define CS_HEAP_FRAG_END_VALUE_SHIFT 0
-+#define CS_HEAP_FRAG_END_VALUE_MASK (0xFFFFFFFF << CS_HEAP_FRAG_END_VALUE_SHIFT)
-+#define CS_HEAP_FRAG_END_VALUE_GET(reg_val) (((reg_val)&CS_HEAP_FRAG_END_VALUE_MASK) >> CS_HEAP_FRAG_END_VALUE_SHIFT)
-+#define CS_HEAP_FRAG_END_VALUE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_HEAP_FRAG_END_VALUE_MASK) | \
-+ (((value) << CS_HEAP_FRAG_END_VALUE_SHIFT) & CS_HEAP_FRAG_END_VALUE_MASK))
-+
-+/* CS_HEAP_ADDRESS register */
-+#define CS_HEAP_ADDRESS_POINTER_SHIFT 0
-+#define CS_HEAP_ADDRESS_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_HEAP_ADDRESS_POINTER_SHIFT)
-+#define CS_HEAP_ADDRESS_POINTER_GET(reg_val) (((reg_val)&CS_HEAP_ADDRESS_POINTER_MASK) >> CS_HEAP_ADDRESS_POINTER_SHIFT)
-+#define CS_HEAP_ADDRESS_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CS_HEAP_ADDRESS_POINTER_MASK) | \
-+ (((value) << CS_HEAP_ADDRESS_POINTER_SHIFT) & CS_HEAP_ADDRESS_POINTER_MASK))
-+/* End of CS_KERNEL_OUTPUT_BLOCK register set definitions */
-+
-+/* CS_USER_INPUT_BLOCK register set definitions */
-+
-+/* CS_INSERT register */
-+#define CS_INSERT_VALUE_SHIFT 0
-+#define CS_INSERT_VALUE_MASK (0xFFFFFFFFFFFFFFFF << CS_INSERT_VALUE_SHIFT)
-+#define CS_INSERT_VALUE_GET(reg_val) (((reg_val)&CS_INSERT_VALUE_MASK) >> CS_INSERT_VALUE_SHIFT)
-+#define CS_INSERT_VALUE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_INSERT_VALUE_MASK) | (((value) << CS_INSERT_VALUE_SHIFT) & CS_INSERT_VALUE_MASK))
-+
-+/* CS_EXTRACT_INIT register */
-+#define CS_EXTRACT_INIT_VALUE_SHIFT 0
-+#define CS_EXTRACT_INIT_VALUE_MASK (0xFFFFFFFFFFFFFFFF << CS_EXTRACT_INIT_VALUE_SHIFT)
-+#define CS_EXTRACT_INIT_VALUE_GET(reg_val) (((reg_val)&CS_EXTRACT_INIT_VALUE_MASK) >> CS_EXTRACT_INIT_VALUE_SHIFT)
-+#define CS_EXTRACT_INIT_VALUE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_EXTRACT_INIT_VALUE_MASK) | \
-+ (((value) << CS_EXTRACT_INIT_VALUE_SHIFT) & CS_EXTRACT_INIT_VALUE_MASK))
-+/* End of CS_USER_INPUT_BLOCK register set definitions */
-+
-+/* CS_USER_OUTPUT_BLOCK register set definitions */
-+
-+/* CS_EXTRACT register */
-+#define CS_EXTRACT_VALUE_SHIFT 0
-+#define CS_EXTRACT_VALUE_MASK (0xFFFFFFFFFFFFFFFF << CS_EXTRACT_VALUE_SHIFT)
-+#define CS_EXTRACT_VALUE_GET(reg_val) (((reg_val)&CS_EXTRACT_VALUE_MASK) >> CS_EXTRACT_VALUE_SHIFT)
-+#define CS_EXTRACT_VALUE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_EXTRACT_VALUE_MASK) | (((value) << CS_EXTRACT_VALUE_SHIFT) & CS_EXTRACT_VALUE_MASK))
-+
-+/* CS_ACTIVE register */
-+#define CS_ACTIVE_HW_ACTIVE_SHIFT 0
-+#define CS_ACTIVE_HW_ACTIVE_MASK (0x1 << CS_ACTIVE_HW_ACTIVE_SHIFT)
-+#define CS_ACTIVE_HW_ACTIVE_GET(reg_val) (((reg_val)&CS_ACTIVE_HW_ACTIVE_MASK) >> CS_ACTIVE_HW_ACTIVE_SHIFT)
-+#define CS_ACTIVE_HW_ACTIVE_SET(reg_val, value) \
-+ (((reg_val) & ~CS_ACTIVE_HW_ACTIVE_MASK) | (((value) << CS_ACTIVE_HW_ACTIVE_SHIFT) & CS_ACTIVE_HW_ACTIVE_MASK))
-+/* End of CS_USER_OUTPUT_BLOCK register set definitions */
-+
-+/* CSG_INPUT_BLOCK register set definitions */
-+
-+/* CSG_REQ register */
-+#define CSG_REQ_STATE_SHIFT 0
-+#define CSG_REQ_STATE_MASK (0x7 << CSG_REQ_STATE_SHIFT)
-+#define CSG_REQ_STATE_GET(reg_val) (((reg_val)&CSG_REQ_STATE_MASK) >> CSG_REQ_STATE_SHIFT)
-+#define CSG_REQ_STATE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_REQ_STATE_MASK) | (((value) << CSG_REQ_STATE_SHIFT) & CSG_REQ_STATE_MASK))
-+/* CSG_REQ_STATE values */
-+#define CSG_REQ_STATE_TERMINATE 0x0
-+#define CSG_REQ_STATE_START 0x1
-+#define CSG_REQ_STATE_SUSPEND 0x2
-+#define CSG_REQ_STATE_RESUME 0x3
-+/* End of CSG_REQ_STATE values */
-+#define CSG_REQ_EP_CFG_SHIFT 4
-+#define CSG_REQ_EP_CFG_MASK (0x1 << CSG_REQ_EP_CFG_SHIFT)
-+#define CSG_REQ_EP_CFG_GET(reg_val) (((reg_val)&CSG_REQ_EP_CFG_MASK) >> CSG_REQ_EP_CFG_SHIFT)
-+#define CSG_REQ_EP_CFG_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_REQ_EP_CFG_MASK) | (((value) << CSG_REQ_EP_CFG_SHIFT) & CSG_REQ_EP_CFG_MASK))
-+#define CSG_REQ_STATUS_UPDATE_SHIFT 5
-+#define CSG_REQ_STATUS_UPDATE_MASK (0x1 << CSG_REQ_STATUS_UPDATE_SHIFT)
-+#define CSG_REQ_STATUS_UPDATE_GET(reg_val) (((reg_val)&CSG_REQ_STATUS_UPDATE_MASK) >> CSG_REQ_STATUS_UPDATE_SHIFT)
-+#define CSG_REQ_STATUS_UPDATE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_REQ_STATUS_UPDATE_MASK) | \
-+ (((value) << CSG_REQ_STATUS_UPDATE_SHIFT) & CSG_REQ_STATUS_UPDATE_MASK))
-+#define CSG_REQ_SYNC_UPDATE_SHIFT 28
-+#define CSG_REQ_SYNC_UPDATE_MASK (0x1 << CSG_REQ_SYNC_UPDATE_SHIFT)
-+#define CSG_REQ_SYNC_UPDATE_GET(reg_val) (((reg_val)&CSG_REQ_SYNC_UPDATE_MASK) >> CSG_REQ_SYNC_UPDATE_SHIFT)
-+#define CSG_REQ_SYNC_UPDATE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_REQ_SYNC_UPDATE_MASK) | (((value) << CSG_REQ_SYNC_UPDATE_SHIFT) & CSG_REQ_SYNC_UPDATE_MASK))
-+#define CSG_REQ_IDLE_SHIFT 29
-+#define CSG_REQ_IDLE_MASK (0x1 << CSG_REQ_IDLE_SHIFT)
-+#define CSG_REQ_IDLE_GET(reg_val) (((reg_val)&CSG_REQ_IDLE_MASK) >> CSG_REQ_IDLE_SHIFT)
-+#define CSG_REQ_IDLE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_REQ_IDLE_MASK) | (((value) << CSG_REQ_IDLE_SHIFT) & CSG_REQ_IDLE_MASK))
-+#define CSG_REQ_DOORBELL_SHIFT 30
-+#define CSG_REQ_DOORBELL_MASK (0x1 << CSG_REQ_DOORBELL_SHIFT)
-+#define CSG_REQ_DOORBELL_GET(reg_val) (((reg_val)&CSG_REQ_DOORBELL_MASK) >> CSG_REQ_DOORBELL_SHIFT)
-+#define CSG_REQ_DOORBELL_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_REQ_DOORBELL_MASK) | (((value) << CSG_REQ_DOORBELL_SHIFT) & CSG_REQ_DOORBELL_MASK))
-+#define CSG_REQ_PROGRESS_TIMER_EVENT_SHIFT 31
-+#define CSG_REQ_PROGRESS_TIMER_EVENT_MASK (0x1 << CSG_REQ_PROGRESS_TIMER_EVENT_SHIFT)
-+#define CSG_REQ_PROGRESS_TIMER_EVENT_GET(reg_val) \
-+ (((reg_val)&CSG_REQ_PROGRESS_TIMER_EVENT_MASK) >> CSG_REQ_PROGRESS_TIMER_EVENT_SHIFT)
-+#define CSG_REQ_PROGRESS_TIMER_EVENT_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_REQ_PROGRESS_TIMER_EVENT_MASK) | \
-+ (((value) << CSG_REQ_PROGRESS_TIMER_EVENT_SHIFT) & CSG_REQ_PROGRESS_TIMER_EVENT_MASK))
-+
-+/* CSG_ACK_IRQ_MASK register */
-+#define CSG_ACK_IRQ_MASK_STATE_SHIFT 0
-+#define CSG_ACK_IRQ_MASK_STATE_MASK (0x7 << CSG_ACK_IRQ_MASK_STATE_SHIFT)
-+#define CSG_ACK_IRQ_MASK_STATE_GET(reg_val) (((reg_val)&CSG_ACK_IRQ_MASK_STATE_MASK) >> CSG_ACK_IRQ_MASK_STATE_SHIFT)
-+#define CSG_ACK_IRQ_MASK_STATE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_IRQ_MASK_STATE_MASK) | \
-+ (((value) << CSG_ACK_IRQ_MASK_STATE_SHIFT) & CSG_ACK_IRQ_MASK_STATE_MASK))
-+/* CSG_ACK_IRQ_MASK_STATE values */
-+#define CSG_ACK_IRQ_MASK_STATE_DISABLED 0x0
-+#define CSG_ACK_IRQ_MASK_STATE_ENABLED 0x7
-+/* End of CSG_ACK_IRQ_MASK_STATE values */
-+#define CSG_ACK_IRQ_MASK_EP_CFG_SHIFT 4
-+#define CSG_ACK_IRQ_MASK_EP_CFG_MASK (0x1 << CSG_ACK_IRQ_MASK_EP_CFG_SHIFT)
-+#define CSG_ACK_IRQ_MASK_EP_CFG_GET(reg_val) (((reg_val)&CSG_ACK_IRQ_MASK_EP_CFG_MASK) >> CSG_ACK_IRQ_MASK_EP_CFG_SHIFT)
-+#define CSG_ACK_IRQ_MASK_EP_CFG_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_IRQ_MASK_EP_CFG_MASK) | \
-+ (((value) << CSG_ACK_IRQ_MASK_EP_CFG_SHIFT) & CSG_ACK_IRQ_MASK_EP_CFG_MASK))
-+#define CSG_ACK_IRQ_MASK_STATUS_UPDATE_SHIFT 5
-+#define CSG_ACK_IRQ_MASK_STATUS_UPDATE_MASK (0x1 << CSG_ACK_IRQ_MASK_STATUS_UPDATE_SHIFT)
-+#define CSG_ACK_IRQ_MASK_STATUS_UPDATE_GET(reg_val) \
-+ (((reg_val)&CSG_ACK_IRQ_MASK_STATUS_UPDATE_MASK) >> CSG_ACK_IRQ_MASK_STATUS_UPDATE_SHIFT)
-+#define CSG_ACK_IRQ_MASK_STATUS_UPDATE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_IRQ_MASK_STATUS_UPDATE_MASK) | \
-+ (((value) << CSG_ACK_IRQ_MASK_STATUS_UPDATE_SHIFT) & CSG_ACK_IRQ_MASK_STATUS_UPDATE_MASK))
-+#define CSG_ACK_IRQ_MASK_SYNC_UPDATE_SHIFT 28
-+#define CSG_ACK_IRQ_MASK_SYNC_UPDATE_MASK (0x1 << CSG_ACK_IRQ_MASK_SYNC_UPDATE_SHIFT)
-+#define CSG_ACK_IRQ_MASK_SYNC_UPDATE_GET(reg_val) \
-+ (((reg_val)&CSG_ACK_IRQ_MASK_SYNC_UPDATE_MASK) >> CSG_ACK_IRQ_MASK_SYNC_UPDATE_SHIFT)
-+#define CSG_ACK_IRQ_MASK_SYNC_UPDATE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_IRQ_MASK_SYNC_UPDATE_MASK) | \
-+ (((value) << CSG_ACK_IRQ_MASK_SYNC_UPDATE_SHIFT) & CSG_ACK_IRQ_MASK_SYNC_UPDATE_MASK))
-+#define CSG_ACK_IRQ_MASK_IDLE_SHIFT 29
-+#define CSG_ACK_IRQ_MASK_IDLE_MASK (0x1 << CSG_ACK_IRQ_MASK_IDLE_SHIFT)
-+#define CSG_ACK_IRQ_MASK_IDLE_GET(reg_val) (((reg_val)&CSG_ACK_IRQ_MASK_IDLE_MASK) >> CSG_ACK_IRQ_MASK_IDLE_SHIFT)
-+#define CSG_ACK_IRQ_MASK_IDLE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_IRQ_MASK_IDLE_MASK) | \
-+ (((value) << CSG_ACK_IRQ_MASK_IDLE_SHIFT) & CSG_ACK_IRQ_MASK_IDLE_MASK))
-+#define CSG_ACK_IRQ_MASK_DOORBELL_SHIFT 30
-+#define CSG_ACK_IRQ_MASK_DOORBELL_MASK (0x1 << CSG_ACK_IRQ_MASK_DOORBELL_SHIFT)
-+#define CSG_ACK_IRQ_MASK_DOORBELL_GET(reg_val) \
-+ (((reg_val)&CSG_ACK_IRQ_MASK_DOORBELL_MASK) >> CSG_ACK_IRQ_MASK_DOORBELL_SHIFT)
-+#define CSG_ACK_IRQ_MASK_DOORBELL_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_IRQ_MASK_DOORBELL_MASK) | \
-+ (((value) << CSG_ACK_IRQ_MASK_DOORBELL_SHIFT) & CSG_ACK_IRQ_MASK_DOORBELL_MASK))
-+#define CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_SHIFT 31
-+#define CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_MASK (0x1 << CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_SHIFT)
-+#define CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_GET(reg_val) \
-+ (((reg_val)&CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_MASK) >> CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_SHIFT)
-+#define CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_MASK) | \
-+ (((value) << CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_SHIFT) & CSG_ACK_IRQ_MASK_PROGRESS_TIMER_EVENT_MASK))
-+
-+/* CSG_EP_REQ register */
-+#define CSG_EP_REQ_COMPUTE_EP_SHIFT 0
-+#define CSG_EP_REQ_COMPUTE_EP_MASK (0xFF << CSG_EP_REQ_COMPUTE_EP_SHIFT)
-+#define CSG_EP_REQ_COMPUTE_EP_GET(reg_val) (((reg_val)&CSG_EP_REQ_COMPUTE_EP_MASK) >> CSG_EP_REQ_COMPUTE_EP_SHIFT)
-+#define CSG_EP_REQ_COMPUTE_EP_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_EP_REQ_COMPUTE_EP_MASK) | \
-+ (((value) << CSG_EP_REQ_COMPUTE_EP_SHIFT) & CSG_EP_REQ_COMPUTE_EP_MASK))
-+#define CSG_EP_REQ_FRAGMENT_EP_SHIFT 8
-+#define CSG_EP_REQ_FRAGMENT_EP_MASK (0xFF << CSG_EP_REQ_FRAGMENT_EP_SHIFT)
-+#define CSG_EP_REQ_FRAGMENT_EP_GET(reg_val) (((reg_val)&CSG_EP_REQ_FRAGMENT_EP_MASK) >> CSG_EP_REQ_FRAGMENT_EP_SHIFT)
-+#define CSG_EP_REQ_FRAGMENT_EP_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_EP_REQ_FRAGMENT_EP_MASK) | \
-+ (((value) << CSG_EP_REQ_FRAGMENT_EP_SHIFT) & CSG_EP_REQ_FRAGMENT_EP_MASK))
-+#define CSG_EP_REQ_TILER_EP_SHIFT 16
-+#define CSG_EP_REQ_TILER_EP_MASK (0xF << CSG_EP_REQ_TILER_EP_SHIFT)
-+#define CSG_EP_REQ_TILER_EP_GET(reg_val) (((reg_val)&CSG_EP_REQ_TILER_EP_MASK) >> CSG_EP_REQ_TILER_EP_SHIFT)
-+#define CSG_EP_REQ_TILER_EP_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_EP_REQ_TILER_EP_MASK) | (((value) << CSG_EP_REQ_TILER_EP_SHIFT) & CSG_EP_REQ_TILER_EP_MASK))
-+#define CSG_EP_REQ_EXCLUSIVE_COMPUTE_SHIFT 20
-+#define CSG_EP_REQ_EXCLUSIVE_COMPUTE_MASK (0x1 << CSG_EP_REQ_EXCLUSIVE_COMPUTE_SHIFT)
-+#define CSG_EP_REQ_EXCLUSIVE_COMPUTE_GET(reg_val) \
-+ (((reg_val)&CSG_EP_REQ_EXCLUSIVE_COMPUTE_MASK) >> CSG_EP_REQ_EXCLUSIVE_COMPUTE_SHIFT)
-+#define CSG_EP_REQ_EXCLUSIVE_COMPUTE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_EP_REQ_EXCLUSIVE_COMPUTE_MASK) | \
-+ (((value) << CSG_EP_REQ_EXCLUSIVE_COMPUTE_SHIFT) & CSG_EP_REQ_EXCLUSIVE_COMPUTE_MASK))
-+#define CSG_EP_REQ_EXCLUSIVE_FRAGMENT_SHIFT 21
-+#define CSG_EP_REQ_EXCLUSIVE_FRAGMENT_MASK (0x1 << CSG_EP_REQ_EXCLUSIVE_FRAGMENT_SHIFT)
-+#define CSG_EP_REQ_EXCLUSIVE_FRAGMENT_GET(reg_val) \
-+ (((reg_val)&CSG_EP_REQ_EXCLUSIVE_FRAGMENT_MASK) >> CSG_EP_REQ_EXCLUSIVE_FRAGMENT_SHIFT)
-+#define CSG_EP_REQ_EXCLUSIVE_FRAGMENT_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_EP_REQ_EXCLUSIVE_FRAGMENT_MASK) | \
-+ (((value) << CSG_EP_REQ_EXCLUSIVE_FRAGMENT_SHIFT) & CSG_EP_REQ_EXCLUSIVE_FRAGMENT_MASK))
-+#define CSG_EP_REQ_PRIORITY_SHIFT 28
-+#define CSG_EP_REQ_PRIORITY_MASK (0xF << CSG_EP_REQ_PRIORITY_SHIFT)
-+#define CSG_EP_REQ_PRIORITY_GET(reg_val) (((reg_val)&CSG_EP_REQ_PRIORITY_MASK) >> CSG_EP_REQ_PRIORITY_SHIFT)
-+#define CSG_EP_REQ_PRIORITY_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_EP_REQ_PRIORITY_MASK) | (((value) << CSG_EP_REQ_PRIORITY_SHIFT) & CSG_EP_REQ_PRIORITY_MASK))
-+
-+/* CSG_SUSPEND_BUF register */
-+#define CSG_SUSPEND_BUF_POINTER_SHIFT 0
-+#define CSG_SUSPEND_BUF_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CSG_SUSPEND_BUF_POINTER_SHIFT)
-+#define CSG_SUSPEND_BUF_POINTER_GET(reg_val) (((reg_val)&CSG_SUSPEND_BUF_POINTER_MASK) >> CSG_SUSPEND_BUF_POINTER_SHIFT)
-+#define CSG_SUSPEND_BUF_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_SUSPEND_BUF_POINTER_MASK) | \
-+ (((value) << CSG_SUSPEND_BUF_POINTER_SHIFT) & CSG_SUSPEND_BUF_POINTER_MASK))
-+
-+/* CSG_PROTM_SUSPEND_BUF register */
-+#define CSG_PROTM_SUSPEND_BUF_POINTER_SHIFT 0
-+#define CSG_PROTM_SUSPEND_BUF_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CSG_PROTM_SUSPEND_BUF_POINTER_SHIFT)
-+#define CSG_PROTM_SUSPEND_BUF_POINTER_GET(reg_val) \
-+ (((reg_val)&CSG_PROTM_SUSPEND_BUF_POINTER_MASK) >> CSG_PROTM_SUSPEND_BUF_POINTER_SHIFT)
-+#define CSG_PROTM_SUSPEND_BUF_POINTER_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_PROTM_SUSPEND_BUF_POINTER_MASK) | \
-+ (((value) << CSG_PROTM_SUSPEND_BUF_POINTER_SHIFT) & CSG_PROTM_SUSPEND_BUF_POINTER_MASK))
-+
-+/* End of CSG_INPUT_BLOCK register set definitions */
-+
-+/* CSG_OUTPUT_BLOCK register set definitions */
-+
-+/* CSG_ACK register */
-+#define CSG_ACK_STATE_SHIFT 0
-+#define CSG_ACK_STATE_MASK (0x7 << CSG_ACK_STATE_SHIFT)
-+#define CSG_ACK_STATE_GET(reg_val) (((reg_val)&CSG_ACK_STATE_MASK) >> CSG_ACK_STATE_SHIFT)
-+#define CSG_ACK_STATE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_STATE_MASK) | (((value) << CSG_ACK_STATE_SHIFT) & CSG_ACK_STATE_MASK))
-+/* CSG_ACK_STATE values */
-+#define CSG_ACK_STATE_TERMINATE 0x0
-+#define CSG_ACK_STATE_START 0x1
-+#define CSG_ACK_STATE_SUSPEND 0x2
-+#define CSG_ACK_STATE_RESUME 0x3
-+/* End of CSG_ACK_STATE values */
-+#define CSG_ACK_EP_CFG_SHIFT 4
-+#define CSG_ACK_EP_CFG_MASK (0x1 << CSG_ACK_EP_CFG_SHIFT)
-+#define CSG_ACK_EP_CFG_GET(reg_val) (((reg_val)&CSG_ACK_EP_CFG_MASK) >> CSG_ACK_EP_CFG_SHIFT)
-+#define CSG_ACK_EP_CFG_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_EP_CFG_MASK) | (((value) << CSG_ACK_EP_CFG_SHIFT) & CSG_ACK_EP_CFG_MASK))
-+#define CSG_ACK_STATUS_UPDATE_SHIFT 5
-+#define CSG_ACK_STATUS_UPDATE_MASK (0x1 << CSG_ACK_STATUS_UPDATE_SHIFT)
-+#define CSG_ACK_STATUS_UPDATE_GET(reg_val) (((reg_val)&CSG_ACK_STATUS_UPDATE_MASK) >> CSG_ACK_STATUS_UPDATE_SHIFT)
-+#define CSG_ACK_STATUS_UPDATE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_STATUS_UPDATE_MASK) | \
-+ (((value) << CSG_ACK_STATUS_UPDATE_SHIFT) & CSG_ACK_STATUS_UPDATE_MASK))
-+#define CSG_ACK_SYNC_UPDATE_SHIFT 28
-+#define CSG_ACK_SYNC_UPDATE_MASK (0x1 << CSG_ACK_SYNC_UPDATE_SHIFT)
-+#define CSG_ACK_SYNC_UPDATE_GET(reg_val) (((reg_val)&CSG_ACK_SYNC_UPDATE_MASK) >> CSG_ACK_SYNC_UPDATE_SHIFT)
-+#define CSG_ACK_SYNC_UPDATE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_SYNC_UPDATE_MASK) | (((value) << CSG_ACK_SYNC_UPDATE_SHIFT) & CSG_ACK_SYNC_UPDATE_MASK))
-+#define CSG_ACK_IDLE_SHIFT 29
-+#define CSG_ACK_IDLE_MASK (0x1 << CSG_ACK_IDLE_SHIFT)
-+#define CSG_ACK_IDLE_GET(reg_val) (((reg_val)&CSG_ACK_IDLE_MASK) >> CSG_ACK_IDLE_SHIFT)
-+#define CSG_ACK_IDLE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_IDLE_MASK) | (((value) << CSG_ACK_IDLE_SHIFT) & CSG_ACK_IDLE_MASK))
-+#define CSG_ACK_DOORBELL_SHIFT 30
-+#define CSG_ACK_DOORBELL_MASK (0x1 << CSG_ACK_DOORBELL_SHIFT)
-+#define CSG_ACK_DOORBELL_GET(reg_val) (((reg_val)&CSG_ACK_DOORBELL_MASK) >> CSG_ACK_DOORBELL_SHIFT)
-+#define CSG_ACK_DOORBELL_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_DOORBELL_MASK) | (((value) << CSG_ACK_DOORBELL_SHIFT) & CSG_ACK_DOORBELL_MASK))
-+#define CSG_ACK_PROGRESS_TIMER_EVENT_SHIFT 31
-+#define CSG_ACK_PROGRESS_TIMER_EVENT_MASK (0x1 << CSG_ACK_PROGRESS_TIMER_EVENT_SHIFT)
-+#define CSG_ACK_PROGRESS_TIMER_EVENT_GET(reg_val) \
-+ (((reg_val)&CSG_ACK_PROGRESS_TIMER_EVENT_MASK) >> CSG_ACK_PROGRESS_TIMER_EVENT_SHIFT)
-+#define CSG_ACK_PROGRESS_TIMER_EVENT_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_ACK_PROGRESS_TIMER_EVENT_MASK) | \
-+ (((value) << CSG_ACK_PROGRESS_TIMER_EVENT_SHIFT) & CSG_ACK_PROGRESS_TIMER_EVENT_MASK))
-+
-+/* CSG_STATUS_EP_CURRENT register */
-+#define CSG_STATUS_EP_CURRENT_COMPUTE_EP_SHIFT 0
-+#define CSG_STATUS_EP_CURRENT_COMPUTE_EP_MASK (0xFF << CSG_STATUS_EP_CURRENT_COMPUTE_EP_SHIFT)
-+#define CSG_STATUS_EP_CURRENT_COMPUTE_EP_GET(reg_val) \
-+ (((reg_val)&CSG_STATUS_EP_CURRENT_COMPUTE_EP_MASK) >> CSG_STATUS_EP_CURRENT_COMPUTE_EP_SHIFT)
-+#define CSG_STATUS_EP_CURRENT_COMPUTE_EP_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_STATUS_EP_CURRENT_COMPUTE_EP_MASK) | \
-+ (((value) << CSG_STATUS_EP_CURRENT_COMPUTE_EP_SHIFT) & CSG_STATUS_EP_CURRENT_COMPUTE_EP_MASK))
-+#define CSG_STATUS_EP_CURRENT_FRAGMENT_EP_SHIFT 8
-+#define CSG_STATUS_EP_CURRENT_FRAGMENT_EP_MASK (0xFF << CSG_STATUS_EP_CURRENT_FRAGMENT_EP_SHIFT)
-+#define CSG_STATUS_EP_CURRENT_FRAGMENT_EP_GET(reg_val) \
-+ (((reg_val)&CSG_STATUS_EP_CURRENT_FRAGMENT_EP_MASK) >> CSG_STATUS_EP_CURRENT_FRAGMENT_EP_SHIFT)
-+#define CSG_STATUS_EP_CURRENT_FRAGMENT_EP_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_STATUS_EP_CURRENT_FRAGMENT_EP_MASK) | \
-+ (((value) << CSG_STATUS_EP_CURRENT_FRAGMENT_EP_SHIFT) & CSG_STATUS_EP_CURRENT_FRAGMENT_EP_MASK))
-+#define CSG_STATUS_EP_CURRENT_TILER_EP_SHIFT 16
-+#define CSG_STATUS_EP_CURRENT_TILER_EP_MASK (0xF << CSG_STATUS_EP_CURRENT_TILER_EP_SHIFT)
-+#define CSG_STATUS_EP_CURRENT_TILER_EP_GET(reg_val) \
-+ (((reg_val)&CSG_STATUS_EP_CURRENT_TILER_EP_MASK) >> CSG_STATUS_EP_CURRENT_TILER_EP_SHIFT)
-+#define CSG_STATUS_EP_CURRENT_TILER_EP_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_STATUS_EP_CURRENT_TILER_EP_MASK) | \
-+ (((value) << CSG_STATUS_EP_CURRENT_TILER_EP_SHIFT) & CSG_STATUS_EP_CURRENT_TILER_EP_MASK))
-+
-+/* CSG_STATUS_EP_REQ register */
-+#define CSG_STATUS_EP_REQ_COMPUTE_EP_SHIFT 0
-+#define CSG_STATUS_EP_REQ_COMPUTE_EP_MASK (0xFF << CSG_STATUS_EP_REQ_COMPUTE_EP_SHIFT)
-+#define CSG_STATUS_EP_REQ_COMPUTE_EP_GET(reg_val) \
-+ (((reg_val)&CSG_STATUS_EP_REQ_COMPUTE_EP_MASK) >> CSG_STATUS_EP_REQ_COMPUTE_EP_SHIFT)
-+#define CSG_STATUS_EP_REQ_COMPUTE_EP_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_STATUS_EP_REQ_COMPUTE_EP_MASK) | \
-+ (((value) << CSG_STATUS_EP_REQ_COMPUTE_EP_SHIFT) & CSG_STATUS_EP_REQ_COMPUTE_EP_MASK))
-+#define CSG_STATUS_EP_REQ_FRAGMENT_EP_SHIFT 8
-+#define CSG_STATUS_EP_REQ_FRAGMENT_EP_MASK (0xFF << CSG_STATUS_EP_REQ_FRAGMENT_EP_SHIFT)
-+#define CSG_STATUS_EP_REQ_FRAGMENT_EP_GET(reg_val) \
-+ (((reg_val)&CSG_STATUS_EP_REQ_FRAGMENT_EP_MASK) >> CSG_STATUS_EP_REQ_FRAGMENT_EP_SHIFT)
-+#define CSG_STATUS_EP_REQ_FRAGMENT_EP_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_STATUS_EP_REQ_FRAGMENT_EP_MASK) | \
-+ (((value) << CSG_STATUS_EP_REQ_FRAGMENT_EP_SHIFT) & CSG_STATUS_EP_REQ_FRAGMENT_EP_MASK))
-+#define CSG_STATUS_EP_REQ_TILER_EP_SHIFT 16
-+#define CSG_STATUS_EP_REQ_TILER_EP_MASK (0xF << CSG_STATUS_EP_REQ_TILER_EP_SHIFT)
-+#define CSG_STATUS_EP_REQ_TILER_EP_GET(reg_val) \
-+ (((reg_val)&CSG_STATUS_EP_REQ_TILER_EP_MASK) >> CSG_STATUS_EP_REQ_TILER_EP_SHIFT)
-+#define CSG_STATUS_EP_REQ_TILER_EP_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_STATUS_EP_REQ_TILER_EP_MASK) | \
-+ (((value) << CSG_STATUS_EP_REQ_TILER_EP_SHIFT) & CSG_STATUS_EP_REQ_TILER_EP_MASK))
-+#define CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_SHIFT 20
-+#define CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_MASK (0x1 << CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_SHIFT)
-+#define CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_GET(reg_val) \
-+ (((reg_val)&CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_MASK) >> CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_SHIFT)
-+#define CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_MASK) | \
-+ (((value) << CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_SHIFT) & CSG_STATUS_EP_REQ_EXCLUSIVE_COMPUTE_MASK))
-+#define CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_SHIFT 21
-+#define CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_MASK (0x1 << CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_SHIFT)
-+#define CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_GET(reg_val) \
-+ (((reg_val)&CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_MASK) >> CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_SHIFT)
-+#define CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_MASK) | \
-+ (((value) << CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_SHIFT) & CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_MASK))
-+
-+/* End of CSG_OUTPUT_BLOCK register set definitions */
-+
-+/* STREAM_CONTROL_BLOCK register set definitions */
-+
-+/* STREAM_FEATURES register */
-+#define STREAM_FEATURES_WORK_REGISTERS_SHIFT 0
-+#define STREAM_FEATURES_WORK_REGISTERS_MASK (0xFF << STREAM_FEATURES_WORK_REGISTERS_SHIFT)
-+#define STREAM_FEATURES_WORK_REGISTERS_GET(reg_val) \
-+ (((reg_val)&STREAM_FEATURES_WORK_REGISTERS_MASK) >> STREAM_FEATURES_WORK_REGISTERS_SHIFT)
-+#define STREAM_FEATURES_WORK_REGISTERS_SET(reg_val, value) \
-+ (((reg_val) & ~STREAM_FEATURES_WORK_REGISTERS_MASK) | \
-+ (((value) << STREAM_FEATURES_WORK_REGISTERS_SHIFT) & STREAM_FEATURES_WORK_REGISTERS_MASK))
-+#define STREAM_FEATURES_SCOREBOARDS_SHIFT 8
-+#define STREAM_FEATURES_SCOREBOARDS_MASK (0xFF << STREAM_FEATURES_SCOREBOARDS_SHIFT)
-+#define STREAM_FEATURES_SCOREBOARDS_GET(reg_val) \
-+ (((reg_val)&STREAM_FEATURES_SCOREBOARDS_MASK) >> STREAM_FEATURES_SCOREBOARDS_SHIFT)
-+#define STREAM_FEATURES_SCOREBOARDS_SET(reg_val, value) \
-+ (((reg_val) & ~STREAM_FEATURES_SCOREBOARDS_MASK) | \
-+ (((value) << STREAM_FEATURES_SCOREBOARDS_SHIFT) & STREAM_FEATURES_SCOREBOARDS_MASK))
-+#define STREAM_FEATURES_COMPUTE_SHIFT 16
-+#define STREAM_FEATURES_COMPUTE_MASK (0x1 << STREAM_FEATURES_COMPUTE_SHIFT)
-+#define STREAM_FEATURES_COMPUTE_GET(reg_val) (((reg_val)&STREAM_FEATURES_COMPUTE_MASK) >> STREAM_FEATURES_COMPUTE_SHIFT)
-+#define STREAM_FEATURES_COMPUTE_SET(reg_val, value) \
-+ (((reg_val) & ~STREAM_FEATURES_COMPUTE_MASK) | \
-+ (((value) << STREAM_FEATURES_COMPUTE_SHIFT) & STREAM_FEATURES_COMPUTE_MASK))
-+#define STREAM_FEATURES_FRAGMENT_SHIFT 17
-+#define STREAM_FEATURES_FRAGMENT_MASK (0x1 << STREAM_FEATURES_FRAGMENT_SHIFT)
-+#define STREAM_FEATURES_FRAGMENT_GET(reg_val) \
-+ (((reg_val)&STREAM_FEATURES_FRAGMENT_MASK) >> STREAM_FEATURES_FRAGMENT_SHIFT)
-+#define STREAM_FEATURES_FRAGMENT_SET(reg_val, value) \
-+ (((reg_val) & ~STREAM_FEATURES_FRAGMENT_MASK) | \
-+ (((value) << STREAM_FEATURES_FRAGMENT_SHIFT) & STREAM_FEATURES_FRAGMENT_MASK))
-+#define STREAM_FEATURES_TILER_SHIFT 18
-+#define STREAM_FEATURES_TILER_MASK (0x1 << STREAM_FEATURES_TILER_SHIFT)
-+#define STREAM_FEATURES_TILER_GET(reg_val) (((reg_val)&STREAM_FEATURES_TILER_MASK) >> STREAM_FEATURES_TILER_SHIFT)
-+#define STREAM_FEATURES_TILER_SET(reg_val, value) \
-+ (((reg_val) & ~STREAM_FEATURES_TILER_MASK) | \
-+ (((value) << STREAM_FEATURES_TILER_SHIFT) & STREAM_FEATURES_TILER_MASK))
-+
-+/* STREAM_INPUT_VA register */
-+#define STREAM_INPUT_VA_VALUE_SHIFT 0
-+#define STREAM_INPUT_VA_VALUE_MASK (0xFFFFFFFF << STREAM_INPUT_VA_VALUE_SHIFT)
-+#define STREAM_INPUT_VA_VALUE_GET(reg_val) (((reg_val)&STREAM_INPUT_VA_VALUE_MASK) >> STREAM_INPUT_VA_VALUE_SHIFT)
-+#define STREAM_INPUT_VA_VALUE_SET(reg_val, value) \
-+ (((reg_val) & ~STREAM_INPUT_VA_VALUE_MASK) | \
-+ (((value) << STREAM_INPUT_VA_VALUE_SHIFT) & STREAM_INPUT_VA_VALUE_MASK))
-+
-+/* STREAM_OUTPUT_VA register */
-+#define STREAM_OUTPUT_VA_VALUE_SHIFT 0
-+#define STREAM_OUTPUT_VA_VALUE_MASK (0xFFFFFFFF << STREAM_OUTPUT_VA_VALUE_SHIFT)
-+#define STREAM_OUTPUT_VA_VALUE_GET(reg_val) (((reg_val)&STREAM_OUTPUT_VA_VALUE_MASK) >> STREAM_OUTPUT_VA_VALUE_SHIFT)
-+#define STREAM_OUTPUT_VA_VALUE_SET(reg_val, value) \
-+ (((reg_val) & ~STREAM_OUTPUT_VA_VALUE_MASK) | \
-+ (((value) << STREAM_OUTPUT_VA_VALUE_SHIFT) & STREAM_OUTPUT_VA_VALUE_MASK))
-+/* End of STREAM_CONTROL_BLOCK register set definitions */
-+
-+/* GLB_INPUT_BLOCK register set definitions */
-+
-+/* GLB_REQ register */
-+#define GLB_REQ_HALT_SHIFT 0
-+#define GLB_REQ_HALT_MASK (0x1 << GLB_REQ_HALT_SHIFT)
-+#define GLB_REQ_HALT_GET(reg_val) (((reg_val)&GLB_REQ_HALT_MASK) >> GLB_REQ_HALT_SHIFT)
-+#define GLB_REQ_HALT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_HALT_MASK) | (((value) << GLB_REQ_HALT_SHIFT) & GLB_REQ_HALT_MASK))
-+#define GLB_REQ_CFG_PROGRESS_TIMER_SHIFT 1
-+#define GLB_REQ_CFG_PROGRESS_TIMER_MASK (0x1 << GLB_REQ_CFG_PROGRESS_TIMER_SHIFT)
-+#define GLB_REQ_CFG_PROGRESS_TIMER_GET(reg_val) \
-+ (((reg_val)&GLB_REQ_CFG_PROGRESS_TIMER_MASK) >> GLB_REQ_CFG_PROGRESS_TIMER_SHIFT)
-+#define GLB_REQ_CFG_PROGRESS_TIMER_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_CFG_PROGRESS_TIMER_MASK) | \
-+ (((value) << GLB_REQ_CFG_PROGRESS_TIMER_SHIFT) & GLB_REQ_CFG_PROGRESS_TIMER_MASK))
-+#define GLB_REQ_CFG_ALLOC_EN_SHIFT 2
-+#define GLB_REQ_CFG_ALLOC_EN_MASK (0x1 << GLB_REQ_CFG_ALLOC_EN_SHIFT)
-+#define GLB_REQ_CFG_ALLOC_EN_GET(reg_val) (((reg_val)&GLB_REQ_CFG_ALLOC_EN_MASK) >> GLB_REQ_CFG_ALLOC_EN_SHIFT)
-+#define GLB_REQ_CFG_ALLOC_EN_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_CFG_ALLOC_EN_MASK) | (((value) << GLB_REQ_CFG_ALLOC_EN_SHIFT) & GLB_REQ_CFG_ALLOC_EN_MASK))
-+#define GLB_REQ_CFG_PWROFF_TIMER_SHIFT 3
-+#define GLB_REQ_CFG_PWROFF_TIMER_MASK (0x1 << GLB_REQ_CFG_PWROFF_TIMER_SHIFT)
-+#define GLB_REQ_CFG_PWROFF_TIMER_GET(reg_val) \
-+ (((reg_val)&GLB_REQ_CFG_PWROFF_TIMER_MASK) >> GLB_REQ_CFG_PWROFF_TIMER_SHIFT)
-+#define GLB_REQ_CFG_PWROFF_TIMER_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_CFG_PWROFF_TIMER_MASK) | \
-+ (((value) << GLB_REQ_CFG_PWROFF_TIMER_SHIFT) & GLB_REQ_CFG_PWROFF_TIMER_MASK))
-+#define GLB_REQ_PROTM_ENTER_SHIFT 4
-+#define GLB_REQ_PROTM_ENTER_MASK (0x1 << GLB_REQ_PROTM_ENTER_SHIFT)
-+#define GLB_REQ_PROTM_ENTER_GET(reg_val) (((reg_val)&GLB_REQ_PROTM_ENTER_MASK) >> GLB_REQ_PROTM_ENTER_SHIFT)
-+#define GLB_REQ_PROTM_ENTER_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_PROTM_ENTER_MASK) | (((value) << GLB_REQ_PROTM_ENTER_SHIFT) & GLB_REQ_PROTM_ENTER_MASK))
-+#define GLB_REQ_PRFCNT_ENABLE_SHIFT 5
-+#define GLB_REQ_PRFCNT_ENABLE_MASK (0x1 << GLB_REQ_PRFCNT_ENABLE_SHIFT)
-+#define GLB_REQ_PRFCNT_ENABLE_GET(reg_val) (((reg_val)&GLB_REQ_PRFCNT_ENABLE_MASK) >> GLB_REQ_PRFCNT_ENABLE_SHIFT)
-+#define GLB_REQ_PRFCNT_ENABLE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_PRFCNT_ENABLE_MASK) | \
-+ (((value) << GLB_REQ_PRFCNT_ENABLE_SHIFT) & GLB_REQ_PRFCNT_ENABLE_MASK))
-+#define GLB_REQ_PRFCNT_SAMPLE_SHIFT 6
-+#define GLB_REQ_PRFCNT_SAMPLE_MASK (0x1 << GLB_REQ_PRFCNT_SAMPLE_SHIFT)
-+#define GLB_REQ_PRFCNT_SAMPLE_GET(reg_val) (((reg_val)&GLB_REQ_PRFCNT_SAMPLE_MASK) >> GLB_REQ_PRFCNT_SAMPLE_SHIFT)
-+#define GLB_REQ_PRFCNT_SAMPLE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_PRFCNT_SAMPLE_MASK) | \
-+ (((value) << GLB_REQ_PRFCNT_SAMPLE_SHIFT) & GLB_REQ_PRFCNT_SAMPLE_MASK))
-+#define GLB_REQ_COUNTER_ENABLE_SHIFT 7
-+#define GLB_REQ_COUNTER_ENABLE_MASK (0x1 << GLB_REQ_COUNTER_ENABLE_SHIFT)
-+#define GLB_REQ_COUNTER_ENABLE_GET(reg_val) (((reg_val)&GLB_REQ_COUNTER_ENABLE_MASK) >> GLB_REQ_COUNTER_ENABLE_SHIFT)
-+#define GLB_REQ_COUNTER_ENABLE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_COUNTER_ENABLE_MASK) | \
-+ (((value) << GLB_REQ_COUNTER_ENABLE_SHIFT) & GLB_REQ_COUNTER_ENABLE_MASK))
-+#define GLB_REQ_PING_SHIFT 8
-+#define GLB_REQ_PING_MASK (0x1 << GLB_REQ_PING_SHIFT)
-+#define GLB_REQ_PING_GET(reg_val) (((reg_val)&GLB_REQ_PING_MASK) >> GLB_REQ_PING_SHIFT)
-+#define GLB_REQ_PING_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_PING_MASK) | (((value) << GLB_REQ_PING_SHIFT) & GLB_REQ_PING_MASK))
-+#define GLB_REQ_FIRMWARE_CONFIG_UPDATE_SHIFT 9
-+#define GLB_REQ_FIRMWARE_CONFIG_UPDATE_MASK \
-+ (0x1 << GLB_REQ_FIRMWARE_CONFIG_UPDATE_SHIFT)
-+#define GLB_REQ_FIRMWARE_CONFIG_UPDATE_GET(reg_val) \
-+ (((reg_val)&GLB_REQ_FIRMWARE_CONFIG_UPDATE_MASK) >> \
-+ GLB_REQ_FIRMWARE_CONFIG_UPDATE_SHIFT)
-+#define GLB_REQ_FIRMWARE_CONFIG_UPDATE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_FIRMWARE_CONFIG_UPDATE_MASK) | \
-+ (((value) << GLB_REQ_FIRMWARE_CONFIG_UPDATE_SHIFT) & \
-+ GLB_REQ_FIRMWARE_CONFIG_UPDATE_MASK))
-+#define GLB_REQ_INACTIVE_COMPUTE_SHIFT 20
-+#define GLB_REQ_INACTIVE_COMPUTE_MASK (0x1 << GLB_REQ_INACTIVE_COMPUTE_SHIFT)
-+#define GLB_REQ_INACTIVE_COMPUTE_GET(reg_val) \
-+ (((reg_val)&GLB_REQ_INACTIVE_COMPUTE_MASK) >> GLB_REQ_INACTIVE_COMPUTE_SHIFT)
-+#define GLB_REQ_INACTIVE_COMPUTE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_INACTIVE_COMPUTE_MASK) | \
-+ (((value) << GLB_REQ_INACTIVE_COMPUTE_SHIFT) & GLB_REQ_INACTIVE_COMPUTE_MASK))
-+#define GLB_REQ_INACTIVE_FRAGMENT_SHIFT 21
-+#define GLB_REQ_INACTIVE_FRAGMENT_MASK (0x1 << GLB_REQ_INACTIVE_FRAGMENT_SHIFT)
-+#define GLB_REQ_INACTIVE_FRAGMENT_GET(reg_val) \
-+ (((reg_val)&GLB_REQ_INACTIVE_FRAGMENT_MASK) >> GLB_REQ_INACTIVE_FRAGMENT_SHIFT)
-+#define GLB_REQ_INACTIVE_FRAGMENT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_INACTIVE_FRAGMENT_MASK) | \
-+ (((value) << GLB_REQ_INACTIVE_FRAGMENT_SHIFT) & GLB_REQ_INACTIVE_FRAGMENT_MASK))
-+#define GLB_REQ_INACTIVE_TILER_SHIFT 22
-+#define GLB_REQ_INACTIVE_TILER_MASK (0x1 << GLB_REQ_INACTIVE_TILER_SHIFT)
-+#define GLB_REQ_INACTIVE_TILER_GET(reg_val) (((reg_val)&GLB_REQ_INACTIVE_TILER_MASK) >> GLB_REQ_INACTIVE_TILER_SHIFT)
-+#define GLB_REQ_INACTIVE_TILER_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_INACTIVE_TILER_MASK) | \
-+ (((value) << GLB_REQ_INACTIVE_TILER_SHIFT) & GLB_REQ_INACTIVE_TILER_MASK))
-+#define GLB_REQ_PROTM_EXIT_SHIFT 23
-+#define GLB_REQ_PROTM_EXIT_MASK (0x1 << GLB_REQ_PROTM_EXIT_SHIFT)
-+#define GLB_REQ_PROTM_EXIT_GET(reg_val) (((reg_val)&GLB_REQ_PROTM_EXIT_MASK) >> GLB_REQ_PROTM_EXIT_SHIFT)
-+#define GLB_REQ_PROTM_EXIT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_PROTM_EXIT_MASK) | (((value) << GLB_REQ_PROTM_EXIT_SHIFT) & GLB_REQ_PROTM_EXIT_MASK))
-+#define GLB_REQ_PRFCNT_THRESHOLD_SHIFT 24
-+#define GLB_REQ_PRFCNT_THRESHOLD_MASK (0x1 << GLB_REQ_PRFCNT_THRESHOLD_SHIFT)
-+#define GLB_REQ_PRFCNT_THRESHOLD_GET(reg_val) \
-+ (((reg_val)&GLB_REQ_PRFCNT_THRESHOLD_MASK) >> \
-+ GLB_REQ_PRFCNT_THRESHOLD_SHIFT)
-+#define GLB_REQ_PRFCNT_THRESHOLD_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_PRFCNT_THRESHOLD_MASK) | \
-+ (((value) << GLB_REQ_PRFCNT_THRESHOLD_SHIFT) & \
-+ GLB_REQ_PRFCNT_THRESHOLD_MASK))
-+#define GLB_REQ_PRFCNT_OVERFLOW_SHIFT 25
-+#define GLB_REQ_PRFCNT_OVERFLOW_MASK (0x1 << GLB_REQ_PRFCNT_OVERFLOW_SHIFT)
-+#define GLB_REQ_PRFCNT_OVERFLOW_GET(reg_val) \
-+ (((reg_val)&GLB_REQ_PRFCNT_OVERFLOW_MASK) >> \
-+ GLB_REQ_PRFCNT_OVERFLOW_SHIFT)
-+#define GLB_REQ_PRFCNT_OVERFLOW_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_PRFCNT_OVERFLOW_MASK) | \
-+ (((value) << GLB_REQ_PRFCNT_OVERFLOW_SHIFT) & \
-+ GLB_REQ_PRFCNT_OVERFLOW_MASK))
-+#define GLB_REQ_DEBUG_CSF_REQ_SHIFT 30
-+#define GLB_REQ_DEBUG_CSF_REQ_MASK (0x1 << GLB_REQ_DEBUG_CSF_REQ_SHIFT)
-+#define GLB_REQ_DEBUG_CSF_REQ_GET(reg_val) (((reg_val)&GLB_REQ_DEBUG_CSF_REQ_MASK) >> GLB_REQ_DEBUG_CSF_REQ_SHIFT)
-+#define GLB_REQ_DEBUG_CSF_REQ_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_DEBUG_CSF_REQ_MASK) | \
-+ (((value) << GLB_REQ_DEBUG_CSF_REQ_SHIFT) & GLB_REQ_DEBUG_CSF_REQ_MASK))
-+#define GLB_REQ_DEBUG_HOST_REQ_SHIFT 31
-+#define GLB_REQ_DEBUG_HOST_REQ_MASK (0x1 << GLB_REQ_DEBUG_HOST_REQ_SHIFT)
-+#define GLB_REQ_DEBUG_HOST_REQ_GET(reg_val) (((reg_val)&GLB_REQ_DEBUG_HOST_REQ_MASK) >> GLB_REQ_DEBUG_HOST_REQ_SHIFT)
-+#define GLB_REQ_DEBUG_HOST_REQ_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_REQ_DEBUG_HOST_REQ_MASK) | \
-+ (((value) << GLB_REQ_DEBUG_HOST_REQ_SHIFT) & GLB_REQ_DEBUG_HOST_REQ_MASK))
-+
-+/* GLB_ACK_IRQ_MASK register */
-+#define GLB_ACK_IRQ_MASK_HALT_SHIFT 0
-+#define GLB_ACK_IRQ_MASK_HALT_MASK (0x1 << GLB_ACK_IRQ_MASK_HALT_SHIFT)
-+#define GLB_ACK_IRQ_MASK_HALT_GET(reg_val) (((reg_val)&GLB_ACK_IRQ_MASK_HALT_MASK) >> GLB_ACK_IRQ_MASK_HALT_SHIFT)
-+#define GLB_ACK_IRQ_MASK_HALT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_HALT_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_HALT_SHIFT) & GLB_ACK_IRQ_MASK_HALT_MASK))
-+#define GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_SHIFT 1
-+#define GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_MASK (0x1 << GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_SHIFT)
-+#define GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_MASK) >> GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_SHIFT)
-+#define GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_SHIFT) & GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_MASK))
-+#define GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_SHIFT 2
-+#define GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_MASK (0x1 << GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_SHIFT)
-+#define GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_MASK) >> GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_SHIFT)
-+#define GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_SHIFT) & GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_MASK))
-+#define GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_SHIFT 3
-+#define GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_MASK (0x1 << GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_SHIFT)
-+#define GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_MASK) >> GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_SHIFT)
-+#define GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_SHIFT) & GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_MASK))
-+#define GLB_ACK_IRQ_MASK_PROTM_ENTER_SHIFT 4
-+#define GLB_ACK_IRQ_MASK_PROTM_ENTER_MASK (0x1 << GLB_ACK_IRQ_MASK_PROTM_ENTER_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PROTM_ENTER_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_PROTM_ENTER_MASK) >> GLB_ACK_IRQ_MASK_PROTM_ENTER_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PROTM_ENTER_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_PROTM_ENTER_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_PROTM_ENTER_SHIFT) & GLB_ACK_IRQ_MASK_PROTM_ENTER_MASK))
-+#define GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_SHIFT 5
-+#define GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK (0x1 << GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK) >> GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_SHIFT) & GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK))
-+#define GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_SHIFT 6
-+#define GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK (0x1 << GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK) >> GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_SHIFT) & GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK))
-+#define GLB_ACK_IRQ_MASK_COUNTER_ENABLE_SHIFT 7
-+#define GLB_ACK_IRQ_MASK_COUNTER_ENABLE_MASK (0x1 << GLB_ACK_IRQ_MASK_COUNTER_ENABLE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_COUNTER_ENABLE_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_COUNTER_ENABLE_MASK) >> GLB_ACK_IRQ_MASK_COUNTER_ENABLE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_COUNTER_ENABLE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_COUNTER_ENABLE_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_COUNTER_ENABLE_SHIFT) & GLB_ACK_IRQ_MASK_COUNTER_ENABLE_MASK))
-+#define GLB_ACK_IRQ_MASK_PING_SHIFT 8
-+#define GLB_ACK_IRQ_MASK_PING_MASK (0x1 << GLB_ACK_IRQ_MASK_PING_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PING_GET(reg_val) (((reg_val)&GLB_ACK_IRQ_MASK_PING_MASK) >> GLB_ACK_IRQ_MASK_PING_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PING_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_PING_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_PING_SHIFT) & GLB_ACK_IRQ_MASK_PING_MASK))
-+#define GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_SHIFT 9
-+#define GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK \
-+ (0x1 << GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK) >> \
-+ GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_SHIFT) & \
-+ GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK))
-+#define GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_SHIFT 20
-+#define GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_MASK (0x1 << GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_MASK) >> GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_SHIFT)
-+#define GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_SHIFT) & GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_MASK))
-+#define GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_SHIFT 21
-+#define GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_MASK (0x1 << GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_SHIFT)
-+#define GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_MASK) >> GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_SHIFT)
-+#define GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_SHIFT) & GLB_ACK_IRQ_MASK_INACTIVE_FRAGMENT_MASK))
-+#define GLB_ACK_IRQ_MASK_INACTIVE_TILER_SHIFT 22
-+#define GLB_ACK_IRQ_MASK_INACTIVE_TILER_MASK (0x1 << GLB_ACK_IRQ_MASK_INACTIVE_TILER_SHIFT)
-+#define GLB_ACK_IRQ_MASK_INACTIVE_TILER_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_INACTIVE_TILER_MASK) >> GLB_ACK_IRQ_MASK_INACTIVE_TILER_SHIFT)
-+#define GLB_ACK_IRQ_MASK_INACTIVE_TILER_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_INACTIVE_TILER_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_INACTIVE_TILER_SHIFT) & GLB_ACK_IRQ_MASK_INACTIVE_TILER_MASK))
-+#define GLB_ACK_IRQ_MASK_PROTM_EXIT_SHIFT 23
-+#define GLB_ACK_IRQ_MASK_PROTM_EXIT_MASK (0x1 << GLB_ACK_IRQ_MASK_PROTM_EXIT_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PROTM_EXIT_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_PROTM_EXIT_MASK) >> GLB_ACK_IRQ_MASK_PROTM_EXIT_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PROTM_EXIT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_PROTM_EXIT_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_PROTM_EXIT_SHIFT) & GLB_ACK_IRQ_MASK_PROTM_EXIT_MASK))
-+#define GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_SHIFT 24
-+#define GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK \
-+ (0x1 << GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK) >> \
-+ GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_SHIFT) & \
-+ GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK))
-+#define GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_SHIFT 25
-+#define GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK \
-+ (0x1 << GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK) >> \
-+ GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_SHIFT)
-+#define GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_SHIFT) & \
-+ GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK))
-+#define GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_SHIFT 30
-+#define GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_MASK (0x1 << GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_SHIFT)
-+#define GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_MASK) >> GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_SHIFT)
-+#define GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_SHIFT) & GLB_ACK_IRQ_MASK_DEBUG_CSF_REQ_MASK))
-+#define GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_SHIFT 31
-+#define GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_MASK (0x1 << GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_SHIFT)
-+#define GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_MASK) >> GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_SHIFT)
-+#define GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_MASK) | \
-+ (((value) << GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_SHIFT) & GLB_ACK_IRQ_MASK_DEBUG_HOST_REQ_MASK))
-+
-+/* GLB_PROGRESS_TIMER register */
-+#define GLB_PROGRESS_TIMER_TIMEOUT_SHIFT 0
-+#define GLB_PROGRESS_TIMER_TIMEOUT_MASK (0xFFFFFFFF << GLB_PROGRESS_TIMER_TIMEOUT_SHIFT)
-+#define GLB_PROGRESS_TIMER_TIMEOUT_GET(reg_val) \
-+ (((reg_val)&GLB_PROGRESS_TIMER_TIMEOUT_MASK) >> GLB_PROGRESS_TIMER_TIMEOUT_SHIFT)
-+#define GLB_PROGRESS_TIMER_TIMEOUT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_PROGRESS_TIMER_TIMEOUT_MASK) | \
-+ (((value) << GLB_PROGRESS_TIMER_TIMEOUT_SHIFT) & GLB_PROGRESS_TIMER_TIMEOUT_MASK))
-+
-+/* GLB_PWROFF_TIMER register */
-+#define GLB_PWROFF_TIMER_TIMEOUT_SHIFT 0
-+#define GLB_PWROFF_TIMER_TIMEOUT_MASK (0x7FFFFFFF << GLB_PWROFF_TIMER_TIMEOUT_SHIFT)
-+#define GLB_PWROFF_TIMER_TIMEOUT_GET(reg_val) \
-+ (((reg_val)&GLB_PWROFF_TIMER_TIMEOUT_MASK) >> GLB_PWROFF_TIMER_TIMEOUT_SHIFT)
-+#define GLB_PWROFF_TIMER_TIMEOUT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_PWROFF_TIMER_TIMEOUT_MASK) | \
-+ (((value) << GLB_PWROFF_TIMER_TIMEOUT_SHIFT) & GLB_PWROFF_TIMER_TIMEOUT_MASK))
-+#define GLB_PWROFF_TIMER_TIMER_SOURCE_SHIFT 31
-+#define GLB_PWROFF_TIMER_TIMER_SOURCE_MASK (0x1 << GLB_PWROFF_TIMER_TIMER_SOURCE_SHIFT)
-+#define GLB_PWROFF_TIMER_TIMER_SOURCE_GET(reg_val) \
-+ (((reg_val)&GLB_PWROFF_TIMER_TIMER_SOURCE_MASK) >> GLB_PWROFF_TIMER_TIMER_SOURCE_SHIFT)
-+#define GLB_PWROFF_TIMER_TIMER_SOURCE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_PWROFF_TIMER_TIMER_SOURCE_MASK) | \
-+ (((value) << GLB_PWROFF_TIMER_TIMER_SOURCE_SHIFT) & GLB_PWROFF_TIMER_TIMER_SOURCE_MASK))
-+/* GLB_PWROFF_TIMER_TIMER_SOURCE values */
-+#define GLB_PWROFF_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP 0x0
-+#define GLB_PWROFF_TIMER_TIMER_SOURCE_GPU_COUNTER 0x1
-+/* End of GLB_PWROFF_TIMER_TIMER_SOURCE values */
-+
-+/* GLB_ALLOC_EN register */
-+#define GLB_ALLOC_EN_MASK_SHIFT 0
-+#define GLB_ALLOC_EN_MASK_MASK (0xFFFFFFFFFFFFFFFF << GLB_ALLOC_EN_MASK_SHIFT)
-+#define GLB_ALLOC_EN_MASK_GET(reg_val) (((reg_val)&GLB_ALLOC_EN_MASK_MASK) >> GLB_ALLOC_EN_MASK_SHIFT)
-+#define GLB_ALLOC_EN_MASK_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ALLOC_EN_MASK_MASK) | (((value) << GLB_ALLOC_EN_MASK_SHIFT) & GLB_ALLOC_EN_MASK_MASK))
-+
-+/* GLB_PROTM_COHERENCY register */
-+#define GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_SHIFT 0
-+#define GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_MASK \
-+ (0xFFFFFFFF << GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_SHIFT)
-+#define GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_GET(reg_val) \
-+ (((reg_val)&GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_MASK) >> \
-+ GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_SHIFT)
-+#define GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_MASK) | \
-+ (((value) << GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_SHIFT) & \
-+ GLB_PROTM_COHERENCY_L2_CACHE_PROTOCOL_SELECT_MASK))
-+/* End of GLB_INPUT_BLOCK register set definitions */
-+
-+/* GLB_OUTPUT_BLOCK register set definitions */
-+
-+/* GLB_ACK register */
-+#define GLB_ACK_CFG_PROGRESS_TIMER_SHIFT 1
-+#define GLB_ACK_CFG_PROGRESS_TIMER_MASK (0x1 << GLB_ACK_CFG_PROGRESS_TIMER_SHIFT)
-+#define GLB_ACK_CFG_PROGRESS_TIMER_GET(reg_val) \
-+ (((reg_val)&GLB_ACK_CFG_PROGRESS_TIMER_MASK) >> GLB_ACK_CFG_PROGRESS_TIMER_SHIFT)
-+#define GLB_ACK_CFG_PROGRESS_TIMER_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_CFG_PROGRESS_TIMER_MASK) | \
-+ (((value) << GLB_ACK_CFG_PROGRESS_TIMER_SHIFT) & GLB_ACK_CFG_PROGRESS_TIMER_MASK))
-+#define GLB_ACK_CFG_ALLOC_EN_SHIFT 2
-+#define GLB_ACK_CFG_ALLOC_EN_MASK (0x1 << GLB_ACK_CFG_ALLOC_EN_SHIFT)
-+#define GLB_ACK_CFG_ALLOC_EN_GET(reg_val) (((reg_val)&GLB_ACK_CFG_ALLOC_EN_MASK) >> GLB_ACK_CFG_ALLOC_EN_SHIFT)
-+#define GLB_ACK_CFG_ALLOC_EN_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_ACK_CFG_ALLOC_EN_MASK) | (((value) << GLB_ACK_CFG_ALLOC_EN_SHIFT) & GLB_ACK_CFG_ALLOC_EN_MASK))
-+/* End of GLB_OUTPUT_BLOCK register set definitions */
-+
-+/* The following register and fields are for headers before 10.x.7/11.x.4 */
-+#define GLB_REQ_IDLE_ENABLE_SHIFT (10)
-+#define GLB_REQ_REQ_IDLE_ENABLE (1 << GLB_REQ_IDLE_ENABLE_SHIFT)
-+#define GLB_REQ_REQ_IDLE_DISABLE (0 << GLB_REQ_IDLE_ENABLE_SHIFT)
-+#define GLB_REQ_IDLE_ENABLE_MASK (0x1 << GLB_REQ_IDLE_ENABLE_SHIFT)
-+#define GLB_REQ_IDLE_DISABLE_MASK (0x1 << GLB_REQ_IDLE_ENABLE_SHIFT)
-+#define GLB_REQ_IDLE_EVENT_SHIFT (26)
-+#define GLB_REQ_IDLE_EVENT_MASK (0x1 << GLB_REQ_IDLE_EVENT_SHIFT)
-+#define GLB_ACK_IDLE_ENABLE_SHIFT (10)
-+#define GLB_ACK_ACK_IDLE_ENABLE (1 << GLB_ACK_IDLE_ENABLE_SHIFT)
-+#define GLB_ACK_ACK_IDLE_DISABLE (0 << GLB_ACK_IDLE_ENABLE_SHIFT)
-+#define GLB_ACK_IDLE_ENABLE_MASK (0x1 << GLB_ACK_IDLE_ENABLE_SHIFT)
-+#define GLB_ACK_IDLE_EVENT_SHIFT (26)
-+#define GLB_ACK_IDLE_EVENT_MASK (0x1 << GLB_REQ_IDLE_EVENT_SHIFT)
-+
-+#define GLB_ACK_IRQ_MASK_IDLE_EVENT_SHIFT (26)
-+#define GLB_ACK_IRQ_MASK_IDLE_EVENT_MASK (0x1 << GLB_ACK_IRQ_MASK_IDLE_EVENT_SHIFT)
-+
-+#define GLB_IDLE_TIMER (0x0080)
-+/* GLB_IDLE_TIMER register */
-+#define GLB_IDLE_TIMER_TIMEOUT_SHIFT (0)
-+#define GLB_IDLE_TIMER_TIMEOUT_MASK ((0x7FFFFFFF) << GLB_IDLE_TIMER_TIMEOUT_SHIFT)
-+#define GLB_IDLE_TIMER_TIMEOUT_GET(reg_val) (((reg_val)&GLB_IDLE_TIMER_TIMEOUT_MASK) >> GLB_IDLE_TIMER_TIMEOUT_SHIFT)
-+#define GLB_IDLE_TIMER_TIMEOUT_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_IDLE_TIMER_TIMEOUT_MASK) | \
-+ (((value) << GLB_IDLE_TIMER_TIMEOUT_SHIFT) & GLB_IDLE_TIMER_TIMEOUT_MASK))
-+#define GLB_IDLE_TIMER_TIMER_SOURCE_SHIFT (31)
-+#define GLB_IDLE_TIMER_TIMER_SOURCE_MASK ((0x1) << GLB_IDLE_TIMER_TIMER_SOURCE_SHIFT)
-+#define GLB_IDLE_TIMER_TIMER_SOURCE_GET(reg_val) \
-+ (((reg_val)&GLB_IDLE_TIMER_TIMER_SOURCE_MASK) >> GLB_IDLE_TIMER_TIMER_SOURCE_SHIFT)
-+#define GLB_IDLE_TIMER_TIMER_SOURCE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_IDLE_TIMER_TIMER_SOURCE_MASK) | \
-+ (((value) << GLB_IDLE_TIMER_TIMER_SOURCE_SHIFT) & GLB_IDLE_TIMER_TIMER_SOURCE_MASK))
-+/* GLB_IDLE_TIMER_TIMER_SOURCE values */
-+#define GLB_IDLE_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP 0x0
-+#define GLB_IDLE_TIMER_TIMER_SOURCE_GPU_COUNTER 0x1
-+/* End of GLB_IDLE_TIMER_TIMER_SOURCE values */
-+
-+/* GLB_INSTR_FEATURES register */
-+#define GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_SHIFT (0)
-+#define GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_MASK ((u32)0xF << GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_SHIFT)
-+#define GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_GET(reg_val) \
-+ (((reg_val)&GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_MASK) >> GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_SHIFT)
-+#define GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_MASK) | \
-+ (((value) << GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_SHIFT) & GLB_INSTR_FEATURES_OFFSET_UPDATE_RATE_MASK))
-+#define GLB_INSTR_FEATURES_EVENT_SIZE_MAX_SHIFT (4)
-+#define GLB_INSTR_FEATURES_EVENT_SIZE_MAX_MASK ((u32)0xF << GLB_INSTR_FEATURES_EVENT_SIZE_MAX_SHIFT)
-+#define GLB_INSTR_FEATURES_EVENT_SIZE_MAX_GET(reg_val) \
-+ (((reg_val)&GLB_INSTR_FEATURES_EVENT_SIZE_MAX_MASK) >> GLB_INSTR_FEATURES_EVENT_SIZE_MAX_SHIFT)
-+#define GLB_INSTR_FEATURES_EVENT_SIZE_MAX_SET(reg_val, value) \
-+ (((reg_val) & ~GLB_INSTR_FEATURES_EVENT_SIZE_MAX_MASK) | \
-+ (((value) << GLB_INSTR_FEATURES_EVENT_SIZE_MAX_SHIFT) & GLB_INSTR_FEATURES_EVENT_SIZE_MAX_MASK))
-+
-+#define CSG_STATUS_STATE (0x0018) /* CSG state status register */
-+/* CSG_STATUS_STATE register */
-+#define CSG_STATUS_STATE_IDLE_SHIFT (0)
-+#define CSG_STATUS_STATE_IDLE_MASK ((0x1) << CSG_STATUS_STATE_IDLE_SHIFT)
-+#define CSG_STATUS_STATE_IDLE_GET(reg_val) \
-+ (((reg_val)&CSG_STATUS_STATE_IDLE_MASK) >> CSG_STATUS_STATE_IDLE_SHIFT)
-+#define CSG_STATUS_STATE_IDLE_SET(reg_val, value) \
-+ (((reg_val) & ~CSG_STATUS_STATE_IDLE_MASK) | \
-+ (((value) << CSG_STATUS_STATE_IDLE_SHIFT) & CSG_STATUS_STATE_IDLE_MASK))
-+
-+#endif /* _UAPI_GPU_CSF_REGISTERS_H_ */
-diff --git a/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_kbase_csf_ioctl.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_kbase_csf_ioctl.h
-new file mode 100644
-index 0000000..d2d7ce2
---- /dev/null
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/csf/mali_kbase_csf_ioctl.h
-@@ -0,0 +1,433 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _UAPI_KBASE_CSF_IOCTL_H_
-+#define _UAPI_KBASE_CSF_IOCTL_H_
-+
-+#include <asm-generic/ioctl.h>
-+#include <linux/types.h>
-+
-+/*
-+ * 1.0:
-+ * - CSF IOCTL header separated from JM
-+ * 1.1:
-+ * - Add a new priority level BASE_QUEUE_GROUP_PRIORITY_REALTIME
-+ * - Add ioctl 54: This controls the priority setting.
-+ * 1.2:
-+ * - Add new CSF GPU_FEATURES register into the property structure
-+ * returned by KBASE_IOCTL_GET_GPUPROPS
-+ * 1.3:
-+ * - Add __u32 group_uid member to
-+ * &struct_kbase_ioctl_cs_queue_group_create.out
-+ * 1.4:
-+ * - Replace padding in kbase_ioctl_cs_get_glb_iface with
-+ * instr_features member of same size
-+ * 1.5:
-+ * - Add ioctl 40: kbase_ioctl_cs_queue_register_ex, this is a new
-+ * queue registration call with extended format for supporting CS
-+ * trace configurations with CSF trace_command.
-+ */
-+
-+#define BASE_UK_VERSION_MAJOR 1
-+#define BASE_UK_VERSION_MINOR 5
-+
-+/**
-+ * struct kbase_ioctl_version_check - Check version compatibility between
-+ * kernel and userspace
-+ *
-+ * @major: Major version number
-+ * @minor: Minor version number
-+ */
-+struct kbase_ioctl_version_check {
-+ __u16 major;
-+ __u16 minor;
-+};
-+
-+#define KBASE_IOCTL_VERSION_CHECK_RESERVED \
-+ _IOWR(KBASE_IOCTL_TYPE, 0, struct kbase_ioctl_version_check)
-+
-+
-+/**
-+ * struct kbase_ioctl_cs_queue_register - Register a GPU command queue with the
-+ * base back-end
-+ *
-+ * @buffer_gpu_addr: GPU address of the buffer backing the queue
-+ * @buffer_size: Size of the buffer in bytes
-+ * @priority: Priority of the queue within a group when run within a process
-+ * @padding: Currently unused, must be zero
-+ *
-+ * @Note: There is an identical sub-section in kbase_ioctl_cs_queue_register_ex.
-+ * Any change of this struct should also be mirrored to the latter.
-+ */
-+struct kbase_ioctl_cs_queue_register {
-+ __u64 buffer_gpu_addr;
-+ __u32 buffer_size;
-+ __u8 priority;
-+ __u8 padding[3];
-+};
-+
-+#define KBASE_IOCTL_CS_QUEUE_REGISTER \
-+ _IOW(KBASE_IOCTL_TYPE, 36, struct kbase_ioctl_cs_queue_register)
-+
-+/**
-+ * struct kbase_ioctl_cs_queue_kick - Kick the GPU command queue group scheduler
-+ * to notify that a queue has been updated
-+ *
-+ * @buffer_gpu_addr: GPU address of the buffer backing the queue
-+ */
-+struct kbase_ioctl_cs_queue_kick {
-+ __u64 buffer_gpu_addr;
-+};
-+
-+#define KBASE_IOCTL_CS_QUEUE_KICK \
-+ _IOW(KBASE_IOCTL_TYPE, 37, struct kbase_ioctl_cs_queue_kick)
-+
-+/**
-+ * union kbase_ioctl_cs_queue_bind - Bind a GPU command queue to a group
-+ *
-+ * @in: Input parameters
-+ * @in.buffer_gpu_addr: GPU address of the buffer backing the queue
-+ * @in.group_handle: Handle of the group to which the queue should be bound
-+ * @in.csi_index: Index of the CSF interface the queue should be bound to
-+ * @in.padding: Currently unused, must be zero
-+ * @out: Output parameters
-+ * @out.mmap_handle: Handle to be used for creating the mapping of CS
-+ * input/output pages
-+ */
-+union kbase_ioctl_cs_queue_bind {
-+ struct {
-+ __u64 buffer_gpu_addr;
-+ __u8 group_handle;
-+ __u8 csi_index;
-+ __u8 padding[6];
-+ } in;
-+ struct {
-+ __u64 mmap_handle;
-+ } out;
-+};
-+
-+#define KBASE_IOCTL_CS_QUEUE_BIND \
-+ _IOWR(KBASE_IOCTL_TYPE, 39, union kbase_ioctl_cs_queue_bind)
-+
-+/**
-+ * struct kbase_ioctl_cs_queue_register_ex - Register a GPU command queue with the
-+ * base back-end in extended format,
-+ * involving trace buffer configuration
-+ *
-+ * @buffer_gpu_addr: GPU address of the buffer backing the queue
-+ * @buffer_size: Size of the buffer in bytes
-+ * @priority: Priority of the queue within a group when run within a process
-+ * @padding: Currently unused, must be zero
-+ * @ex_offset_var_addr: GPU address of the trace buffer write offset variable
-+ * @ex_buffer_base: Trace buffer GPU base address for the queue
-+ * @ex_buffer_size: Size of the trace buffer in bytes
-+ * @ex_event_size: Trace event write size, in log2 designation
-+ * @ex_event_state: Trace event states configuration
-+ * @ex_padding: Currently unused, must be zero
-+ *
-+ * @Note: There is an identical sub-section at the start of this struct to that
-+ * of @ref kbase_ioctl_cs_queue_register. Any change of this sub-section
-+ * must also be mirrored to the latter. Following the said sub-section,
-+ * the remaining fields forms the extension, marked with ex_*.
-+ */
-+struct kbase_ioctl_cs_queue_register_ex {
-+ __u64 buffer_gpu_addr;
-+ __u32 buffer_size;
-+ __u8 priority;
-+ __u8 padding[3];
-+ __u64 ex_offset_var_addr;
-+ __u64 ex_buffer_base;
-+ __u32 ex_buffer_size;
-+ __u8 ex_event_size;
-+ __u8 ex_event_state;
-+ __u8 ex_padding[2];
-+};
-+
-+#define KBASE_IOCTL_CS_QUEUE_REGISTER_EX \
-+ _IOW(KBASE_IOCTL_TYPE, 40, struct kbase_ioctl_cs_queue_register_ex)
-+
-+/**
-+ * struct kbase_ioctl_cs_queue_terminate - Terminate a GPU command queue
-+ *
-+ * @buffer_gpu_addr: GPU address of the buffer backing the queue
-+ */
-+struct kbase_ioctl_cs_queue_terminate {
-+ __u64 buffer_gpu_addr;
-+};
-+
-+#define KBASE_IOCTL_CS_QUEUE_TERMINATE \
-+ _IOW(KBASE_IOCTL_TYPE, 41, struct kbase_ioctl_cs_queue_terminate)
-+
-+/**
-+ * union kbase_ioctl_cs_queue_group_create - Create a GPU command queue group
-+ * @in: Input parameters
-+ * @in.tiler_mask: Mask of tiler endpoints the group is allowed to use.
-+ * @in.fragment_mask: Mask of fragment endpoints the group is allowed to use.
-+ * @in.compute_mask: Mask of compute endpoints the group is allowed to use.
-+ * @in.cs_min: Minimum number of CSs required.
-+ * @in.priority: Queue group's priority within a process.
-+ * @in.tiler_max: Maximum number of tiler endpoints the group is allowed
-+ * to use.
-+ * @in.fragment_max: Maximum number of fragment endpoints the group is
-+ * allowed to use.
-+ * @in.compute_max: Maximum number of compute endpoints the group is allowed
-+ * to use.
-+ * @in.padding: Currently unused, must be zero
-+ * @out: Output parameters
-+ * @out.group_handle: Handle of a newly created queue group.
-+ * @out.padding: Currently unused, must be zero
-+ * @out.group_uid: UID of the queue group available to base.
-+ */
-+union kbase_ioctl_cs_queue_group_create {
-+ struct {
-+ __u64 tiler_mask;
-+ __u64 fragment_mask;
-+ __u64 compute_mask;
-+ __u8 cs_min;
-+ __u8 priority;
-+ __u8 tiler_max;
-+ __u8 fragment_max;
-+ __u8 compute_max;
-+ __u8 padding[3];
-+
-+ } in;
-+ struct {
-+ __u8 group_handle;
-+ __u8 padding[3];
-+ __u32 group_uid;
-+ } out;
-+};
-+
-+#define KBASE_IOCTL_CS_QUEUE_GROUP_CREATE \
-+ _IOWR(KBASE_IOCTL_TYPE, 42, union kbase_ioctl_cs_queue_group_create)
-+
-+/**
-+ * struct kbase_ioctl_cs_queue_group_term - Terminate a GPU command queue group
-+ *
-+ * @group_handle: Handle of the queue group to be terminated
-+ * @padding: Padding to round up to a multiple of 8 bytes, must be zero
-+ */
-+struct kbase_ioctl_cs_queue_group_term {
-+ __u8 group_handle;
-+ __u8 padding[7];
-+};
-+
-+#define KBASE_IOCTL_CS_QUEUE_GROUP_TERMINATE \
-+ _IOW(KBASE_IOCTL_TYPE, 43, struct kbase_ioctl_cs_queue_group_term)
-+
-+#define KBASE_IOCTL_CS_EVENT_SIGNAL \
-+ _IO(KBASE_IOCTL_TYPE, 44)
-+
-+typedef __u8 base_kcpu_queue_id; /* We support up to 256 active KCPU queues */
-+
-+/**
-+ * struct kbase_ioctl_kcpu_queue_new - Create a KCPU command queue
-+ *
-+ * @id: ID of the new command queue returned by the kernel
-+ * @padding: Padding to round up to a multiple of 8 bytes, must be zero
-+ */
-+struct kbase_ioctl_kcpu_queue_new {
-+ base_kcpu_queue_id id;
-+ __u8 padding[7];
-+};
-+
-+#define KBASE_IOCTL_KCPU_QUEUE_CREATE \
-+ _IOR(KBASE_IOCTL_TYPE, 45, struct kbase_ioctl_kcpu_queue_new)
-+
-+/**
-+ * struct kbase_ioctl_kcpu_queue_delete - Destroy a KCPU command queue
-+ *
-+ * @id: ID of the command queue to be destroyed
-+ * @padding: Padding to round up to a multiple of 8 bytes, must be zero
-+ */
-+struct kbase_ioctl_kcpu_queue_delete {
-+ base_kcpu_queue_id id;
-+ __u8 padding[7];
-+};
-+
-+#define KBASE_IOCTL_KCPU_QUEUE_DELETE \
-+ _IOW(KBASE_IOCTL_TYPE, 46, struct kbase_ioctl_kcpu_queue_delete)
-+
-+/**
-+ * struct kbase_ioctl_kcpu_queue_enqueue - Enqueue commands into the KCPU queue
-+ *
-+ * @addr: Memory address of an array of struct base_kcpu_queue_command
-+ * @nr_commands: Number of commands in the array
-+ * @id: kcpu queue identifier, returned by KBASE_IOCTL_KCPU_QUEUE_CREATE ioctl
-+ * @padding: Padding to round up to a multiple of 8 bytes, must be zero
-+ */
-+struct kbase_ioctl_kcpu_queue_enqueue {
-+ __u64 addr;
-+ __u32 nr_commands;
-+ base_kcpu_queue_id id;
-+ __u8 padding[3];
-+};
-+
-+#define KBASE_IOCTL_KCPU_QUEUE_ENQUEUE \
-+ _IOW(KBASE_IOCTL_TYPE, 47, struct kbase_ioctl_kcpu_queue_enqueue)
-+
-+/**
-+ * union kbase_ioctl_cs_tiler_heap_init - Initialize chunked tiler memory heap
-+ * @in: Input parameters
-+ * @in.chunk_size: Size of each chunk.
-+ * @in.initial_chunks: Initial number of chunks that heap will be created with.
-+ * @in.max_chunks: Maximum number of chunks that the heap is allowed to use.
-+ * @in.target_in_flight: Number of render-passes that the driver should attempt to
-+ * keep in flight for which allocation of new chunks is
-+ * allowed.
-+ * @in.group_id: Group ID to be used for physical allocations.
-+ * @in.padding: Padding
-+ * @out: Output parameters
-+ * @out.gpu_heap_va: GPU VA (virtual address) of Heap context that was set up
-+ * for the heap.
-+ * @out.first_chunk_va: GPU VA of the first chunk allocated for the heap,
-+ * actually points to the header of heap chunk and not to
-+ * the low address of free memory in the chunk.
-+ */
-+union kbase_ioctl_cs_tiler_heap_init {
-+ struct {
-+ __u32 chunk_size;
-+ __u32 initial_chunks;
-+ __u32 max_chunks;
-+ __u16 target_in_flight;
-+ __u8 group_id;
-+ __u8 padding;
-+ } in;
-+ struct {
-+ __u64 gpu_heap_va;
-+ __u64 first_chunk_va;
-+ } out;
-+};
-+
-+#define KBASE_IOCTL_CS_TILER_HEAP_INIT \
-+ _IOWR(KBASE_IOCTL_TYPE, 48, union kbase_ioctl_cs_tiler_heap_init)
-+
-+/**
-+ * struct kbase_ioctl_cs_tiler_heap_term - Terminate a chunked tiler heap
-+ * instance
-+ *
-+ * @gpu_heap_va: GPU VA of Heap context that was set up for the heap.
-+ */
-+struct kbase_ioctl_cs_tiler_heap_term {
-+ __u64 gpu_heap_va;
-+};
-+
-+#define KBASE_IOCTL_CS_TILER_HEAP_TERM \
-+ _IOW(KBASE_IOCTL_TYPE, 49, struct kbase_ioctl_cs_tiler_heap_term)
-+
-+/**
-+ * union kbase_ioctl_cs_get_glb_iface - Request the global control block
-+ * of CSF interface capabilities
-+ *
-+ * @in: Input parameters
-+ * @in.max_group_num: The maximum number of groups to be read. Can be 0, in
-+ * which case groups_ptr is unused.
-+ * @in.max_total_stream _num: The maximum number of CSs to be read. Can be 0, in
-+ * which case streams_ptr is unused.
-+ * @in.groups_ptr: Pointer where to store all the group data (sequentially).
-+ * @in.streams_ptr: Pointer where to store all the CS data (sequentially).
-+ * @out: Output parameters
-+ * @out.glb_version: Global interface version.
-+ * @out.features: Bit mask of features (e.g. whether certain types of job
-+ * can be suspended).
-+ * @out.group_num: Number of CSGs supported.
-+ * @out.prfcnt_size: Size of CSF performance counters, in bytes. Bits 31:16
-+ * hold the size of firmware performance counter data
-+ * and 15:0 hold the size of hardware performance counter
-+ * data.
-+ * @out.total_stream_num: Total number of CSs, summed across all groups.
-+ * @out.instr_features: Instrumentation features. Bits 7:4 hold the maximum
-+ * size of events. Bits 3:0 hold the offset update rate.
-+ * (csf >= 1.1.0)
-+ *
-+ */
-+union kbase_ioctl_cs_get_glb_iface {
-+ struct {
-+ __u32 max_group_num;
-+ __u32 max_total_stream_num;
-+ __u64 groups_ptr;
-+ __u64 streams_ptr;
-+ } in;
-+ struct {
-+ __u32 glb_version;
-+ __u32 features;
-+ __u32 group_num;
-+ __u32 prfcnt_size;
-+ __u32 total_stream_num;
-+ __u32 instr_features;
-+ } out;
-+};
-+
-+#define KBASE_IOCTL_CS_GET_GLB_IFACE \
-+ _IOWR(KBASE_IOCTL_TYPE, 51, union kbase_ioctl_cs_get_glb_iface)
-+
-+struct kbase_ioctl_cs_cpu_queue_info {
-+ __u64 buffer;
-+ __u64 size;
-+};
-+
-+#define KBASE_IOCTL_VERSION_CHECK \
-+ _IOWR(KBASE_IOCTL_TYPE, 52, struct kbase_ioctl_version_check)
-+
-+#define KBASE_IOCTL_CS_CPU_QUEUE_DUMP \
-+ _IOW(KBASE_IOCTL_TYPE, 53, struct kbase_ioctl_cs_cpu_queue_info)
-+
-+/***************
-+ * test ioctls *
-+ ***************/
-+#if MALI_UNIT_TEST
-+/* These ioctls are purely for test purposes and are not used in the production
-+ * driver, they therefore may change without notice
-+ */
-+
-+/**
-+ * struct kbase_ioctl_cs_event_memory_write - Write an event memory address
-+ * @cpu_addr: Memory address to write
-+ * @value: Value to write
-+ * @padding: Currently unused, must be zero
-+ */
-+struct kbase_ioctl_cs_event_memory_write {
-+ __u64 cpu_addr;
-+ __u8 value;
-+ __u8 padding[7];
-+};
-+
-+/**
-+ * union kbase_ioctl_cs_event_memory_read - Read an event memory address
-+ * @in: Input parameters
-+ * @in.cpu_addr: Memory address to read
-+ * @out: Output parameters
-+ * @out.value: Value read
-+ * @out.padding: Currently unused, must be zero
-+ */
-+union kbase_ioctl_cs_event_memory_read {
-+ struct {
-+ __u64 cpu_addr;
-+ } in;
-+ struct {
-+ __u8 value;
-+ __u8 padding[7];
-+ } out;
-+};
-+
-+#endif /* MALI_UNIT_TEST */
-+
-+#endif /* _UAPI_KBASE_CSF_IOCTL_H_ */
-diff --git a/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_csf.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_csf.h
-new file mode 100644
-index 0000000..2041739
---- /dev/null
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_csf.h
-@@ -0,0 +1,335 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2019-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _UAPI_KBASE_GPU_REGMAP_CSF_H_
-+#define _UAPI_KBASE_GPU_REGMAP_CSF_H_
-+
-+#include <linux/types.h>
-+
-+#if !MALI_USE_CSF && defined(__KERNEL__)
-+#error "Cannot be compiled with JM"
-+#endif
-+
-+/* IPA control registers */
-+
-+#define IPA_CONTROL_BASE 0x40000
-+#define IPA_CONTROL_REG(r) (IPA_CONTROL_BASE+(r))
-+#define COMMAND 0x000 /* (WO) Command register */
-+#define STATUS 0x004 /* (RO) Status register */
-+#define TIMER 0x008 /* (RW) Timer control register */
-+
-+#define SELECT_CSHW_LO 0x010 /* (RW) Counter select for CS hardware, low word */
-+#define SELECT_CSHW_HI 0x014 /* (RW) Counter select for CS hardware, high word */
-+#define SELECT_MEMSYS_LO 0x018 /* (RW) Counter select for Memory system, low word */
-+#define SELECT_MEMSYS_HI 0x01C /* (RW) Counter select for Memory system, high word */
-+#define SELECT_TILER_LO 0x020 /* (RW) Counter select for Tiler cores, low word */
-+#define SELECT_TILER_HI 0x024 /* (RW) Counter select for Tiler cores, high word */
-+#define SELECT_SHADER_LO 0x028 /* (RW) Counter select for Shader cores, low word */
-+#define SELECT_SHADER_HI 0x02C /* (RW) Counter select for Shader cores, high word */
-+
-+/* Accumulated counter values for CS hardware */
-+#define VALUE_CSHW_BASE 0x100
-+#define VALUE_CSHW_REG_LO(n) (VALUE_CSHW_BASE + ((n) << 3)) /* (RO) Counter value #n, low word */
-+#define VALUE_CSHW_REG_HI(n) (VALUE_CSHW_BASE + ((n) << 3) + 4) /* (RO) Counter value #n, high word */
-+
-+/* Accumulated counter values for memory system */
-+#define VALUE_MEMSYS_BASE 0x140
-+#define VALUE_MEMSYS_REG_LO(n) (VALUE_MEMSYS_BASE + ((n) << 3)) /* (RO) Counter value #n, low word */
-+#define VALUE_MEMSYS_REG_HI(n) (VALUE_MEMSYS_BASE + ((n) << 3) + 4) /* (RO) Counter value #n, high word */
-+
-+#define VALUE_TILER_BASE 0x180
-+#define VALUE_TILER_REG_LO(n) (VALUE_TILER_BASE + ((n) << 3)) /* (RO) Counter value #n, low word */
-+#define VALUE_TILER_REG_HI(n) (VALUE_TILER_BASE + ((n) << 3) + 4) /* (RO) Counter value #n, high word */
-+
-+#define VALUE_SHADER_BASE 0x1C0
-+#define VALUE_SHADER_REG_LO(n) (VALUE_SHADER_BASE + ((n) << 3)) /* (RO) Counter value #n, low word */
-+#define VALUE_SHADER_REG_HI(n) (VALUE_SHADER_BASE + ((n) << 3) + 4) /* (RO) Counter value #n, high word */
-+
-+#include "../../csf/mali_gpu_csf_control_registers.h"
-+
-+/* Set to implementation defined, outer caching */
-+#define AS_MEMATTR_AARCH64_OUTER_IMPL_DEF 0x88ull
-+/* Set to write back memory, outer caching */
-+#define AS_MEMATTR_AARCH64_OUTER_WA 0x8Dull
-+/* Set to inner non-cacheable, outer-non-cacheable
-+ * Setting defined by the alloc bits is ignored, but set to a valid encoding:
-+ * - no-alloc on read
-+ * - no alloc on write
-+ */
-+#define AS_MEMATTR_AARCH64_NON_CACHEABLE 0x4Cull
-+/* Set to shared memory, that is inner cacheable on ACE and inner or outer
-+ * shared, otherwise inner non-cacheable.
-+ * Outer cacheable if inner or outer shared, otherwise outer non-cacheable.
-+ */
-+#define AS_MEMATTR_AARCH64_SHARED 0x8ull
-+
-+/* Symbols for default MEMATTR to use
-+ * Default is - HW implementation defined caching
-+ */
-+#define AS_MEMATTR_INDEX_DEFAULT 0
-+#define AS_MEMATTR_INDEX_DEFAULT_ACE 3
-+
-+/* HW implementation defined caching */
-+#define AS_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY 0
-+/* Force cache on */
-+#define AS_MEMATTR_INDEX_FORCE_TO_CACHE_ALL 1
-+/* Write-alloc */
-+#define AS_MEMATTR_INDEX_WRITE_ALLOC 2
-+/* Outer coherent, inner implementation defined policy */
-+#define AS_MEMATTR_INDEX_OUTER_IMPL_DEF 3
-+/* Outer coherent, write alloc inner */
-+#define AS_MEMATTR_INDEX_OUTER_WA 4
-+/* Normal memory, inner non-cacheable, outer non-cacheable (ARMv8 mode only) */
-+#define AS_MEMATTR_INDEX_NON_CACHEABLE 5
-+/* Normal memory, shared between MCU and Host */
-+#define AS_MEMATTR_INDEX_SHARED 6
-+
-+/* Configuration bits for the CSF. */
-+#define CSF_CONFIG 0xF00
-+
-+/* CSF_CONFIG register */
-+#define CSF_CONFIG_FORCE_COHERENCY_FEATURES_SHIFT 2
-+
-+/* GPU control registers */
-+#define CORE_FEATURES 0x008 /* () Shader Core Features */
-+#define MCU_CONTROL 0x700
-+#define MCU_STATUS 0x704
-+
-+#define MCU_CNTRL_ENABLE (1 << 0)
-+#define MCU_CNTRL_AUTO (1 << 1)
-+#define MCU_CNTRL_DISABLE (0)
-+
-+#define MCU_STATUS_HALTED (1 << 1)
-+
-+#define PRFCNT_BASE_LO 0x060 /* (RW) Performance counter memory
-+ * region base address, low word
-+ */
-+#define PRFCNT_BASE_HI 0x064 /* (RW) Performance counter memory
-+ * region base address, high word
-+ */
-+#define PRFCNT_CONFIG 0x068 /* (RW) Performance counter
-+ * configuration
-+ */
-+
-+#define PRFCNT_CSHW_EN 0x06C /* (RW) Performance counter
-+ * enable for CS Hardware
-+ */
-+
-+#define PRFCNT_SHADER_EN 0x070 /* (RW) Performance counter enable
-+ * flags for shader cores
-+ */
-+#define PRFCNT_TILER_EN 0x074 /* (RW) Performance counter enable
-+ * flags for tiler
-+ */
-+#define PRFCNT_MMU_L2_EN 0x07C /* (RW) Performance counter enable
-+ * flags for MMU/L2 cache
-+ */
-+
-+/* JOB IRQ flags */
-+#define JOB_IRQ_GLOBAL_IF (1 << 31) /* Global interface interrupt received */
-+
-+/* GPU_COMMAND codes */
-+#define GPU_COMMAND_CODE_NOP 0x00 /* No operation, nothing happens */
-+#define GPU_COMMAND_CODE_RESET 0x01 /* Reset the GPU */
-+#define GPU_COMMAND_CODE_PRFCNT 0x02 /* Clear or sample performance counters */
-+#define GPU_COMMAND_CODE_TIME 0x03 /* Configure time sources */
-+#define GPU_COMMAND_CODE_FLUSH_CACHES 0x04 /* Flush caches */
-+#define GPU_COMMAND_CODE_SET_PROTECTED_MODE 0x05 /* Places the GPU in protected mode */
-+#define GPU_COMMAND_CODE_FINISH_HALT 0x06 /* Halt CSF */
-+#define GPU_COMMAND_CODE_CLEAR_FAULT 0x07 /* Clear GPU_FAULTSTATUS and GPU_FAULTADDRESS, TODX */
-+
-+/* GPU_COMMAND_RESET payloads */
-+
-+/* This will leave the state of active jobs UNDEFINED, but will leave the external bus in a defined and idle state.
-+ * Power domains will remain powered on.
-+ */
-+#define GPU_COMMAND_RESET_PAYLOAD_FAST_RESET 0x00
-+
-+/* This will leave the state of active CSs UNDEFINED, but will leave the external bus in a defined and
-+ * idle state.
-+ */
-+#define GPU_COMMAND_RESET_PAYLOAD_SOFT_RESET 0x01
-+
-+/* This reset will leave the state of currently active streams UNDEFINED, will likely lose data, and may leave
-+ * the system bus in an inconsistent state. Use only as a last resort when nothing else works.
-+ */
-+#define GPU_COMMAND_RESET_PAYLOAD_HARD_RESET 0x02
-+
-+/* GPU_COMMAND_PRFCNT payloads */
-+#define GPU_COMMAND_PRFCNT_PAYLOAD_SAMPLE 0x01 /* Sample performance counters */
-+#define GPU_COMMAND_PRFCNT_PAYLOAD_CLEAR 0x02 /* Clear performance counters */
-+
-+/* GPU_COMMAND_TIME payloads */
-+#define GPU_COMMAND_TIME_DISABLE 0x00 /* Disable cycle counter */
-+#define GPU_COMMAND_TIME_ENABLE 0x01 /* Enable cycle counter */
-+
-+/* GPU_COMMAND_FLUSH_CACHES payloads */
-+#define GPU_COMMAND_FLUSH_PAYLOAD_NONE 0x00 /* No flush */
-+#define GPU_COMMAND_FLUSH_PAYLOAD_CLEAN 0x01 /* Clean the caches */
-+#define GPU_COMMAND_FLUSH_PAYLOAD_INVALIDATE 0x02 /* Invalidate the caches */
-+#define GPU_COMMAND_FLUSH_PAYLOAD_CLEAN_INVALIDATE 0x03 /* Clean and invalidate the caches */
-+
-+/* GPU_COMMAND command + payload */
-+#define GPU_COMMAND_CODE_PAYLOAD(opcode, payload) \
-+ ((__u32)opcode | ((__u32)payload << 8))
-+
-+/* Final GPU_COMMAND form */
-+/* No operation, nothing happens */
-+#define GPU_COMMAND_NOP \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_NOP, 0)
-+
-+/* Stop all external bus interfaces, and then reset the entire GPU. */
-+#define GPU_COMMAND_SOFT_RESET \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_RESET, GPU_COMMAND_RESET_PAYLOAD_SOFT_RESET)
-+
-+/* Immediately reset the entire GPU. */
-+#define GPU_COMMAND_HARD_RESET \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_RESET, GPU_COMMAND_RESET_PAYLOAD_HARD_RESET)
-+
-+/* Clear all performance counters, setting them all to zero. */
-+#define GPU_COMMAND_PRFCNT_CLEAR \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_PRFCNT, GPU_COMMAND_PRFCNT_PAYLOAD_CLEAR)
-+
-+/* Sample all performance counters, writing them out to memory */
-+#define GPU_COMMAND_PRFCNT_SAMPLE \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_PRFCNT, GPU_COMMAND_PRFCNT_PAYLOAD_SAMPLE)
-+
-+/* Starts the cycle counter, and system timestamp propagation */
-+#define GPU_COMMAND_CYCLE_COUNT_START \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_TIME, GPU_COMMAND_TIME_ENABLE)
-+
-+/* Stops the cycle counter, and system timestamp propagation */
-+#define GPU_COMMAND_CYCLE_COUNT_STOP \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_TIME, GPU_COMMAND_TIME_DISABLE)
-+
-+/* Clean all caches */
-+#define GPU_COMMAND_CLEAN_CACHES \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FLUSH_CACHES, GPU_COMMAND_FLUSH_PAYLOAD_CLEAN)
-+
-+/* Clean and invalidate all caches */
-+#define GPU_COMMAND_CLEAN_INV_CACHES \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FLUSH_CACHES, GPU_COMMAND_FLUSH_PAYLOAD_CLEAN_INVALIDATE)
-+
-+/* Places the GPU in protected mode */
-+#define GPU_COMMAND_SET_PROTECTED_MODE \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_SET_PROTECTED_MODE, 0)
-+
-+/* Halt CSF */
-+#define GPU_COMMAND_FINISH_HALT \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FINISH_HALT, 0)
-+
-+/* Clear GPU faults */
-+#define GPU_COMMAND_CLEAR_FAULT \
-+ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_CLEAR_FAULT, 0)
-+
-+/* End Command Values */
-+
-+/* GPU_FAULTSTATUS register */
-+#define GPU_FAULTSTATUS_EXCEPTION_TYPE_SHIFT 0
-+#define GPU_FAULTSTATUS_EXCEPTION_TYPE_MASK (0xFFul)
-+#define GPU_FAULTSTATUS_EXCEPTION_TYPE_GET(reg_val) \
-+ (((reg_val)&GPU_FAULTSTATUS_EXCEPTION_TYPE_MASK) \
-+ >> GPU_FAULTSTATUS_EXCEPTION_TYPE_SHIFT)
-+#define GPU_FAULTSTATUS_ACCESS_TYPE_SHIFT 8
-+#define GPU_FAULTSTATUS_ACCESS_TYPE_MASK \
-+ (0x3ul << GPU_FAULTSTATUS_ACCESS_TYPE_SHIFT)
-+
-+#define GPU_FAULTSTATUS_ADDR_VALID_SHIFT 10
-+#define GPU_FAULTSTATUS_ADDR_VALID_FLAG \
-+ (1ul << GPU_FAULTSTATUS_ADDR_VALID_SHIFT)
-+
-+#define GPU_FAULTSTATUS_JASID_VALID_SHIFT 11
-+#define GPU_FAULTSTATUS_JASID_VALID_FLAG \
-+ (1ul << GPU_FAULTSTATUS_JASID_VALID_SHIFT)
-+
-+#define GPU_FAULTSTATUS_JASID_SHIFT 12
-+#define GPU_FAULTSTATUS_JASID_MASK (0xF << GPU_FAULTSTATUS_JASID_SHIFT)
-+#define GPU_FAULTSTATUS_JASID_GET(reg_val) \
-+ (((reg_val)&GPU_FAULTSTATUS_JASID_MASK) >> GPU_FAULTSTATUS_JASID_SHIFT)
-+#define GPU_FAULTSTATUS_JASID_SET(reg_val, value) \
-+ (((reg_val) & ~GPU_FAULTSTATUS_JASID_MASK) | \
-+ (((value) << GPU_FAULTSTATUS_JASID_SHIFT) & GPU_FAULTSTATUS_JASID_MASK))
-+
-+#define GPU_FAULTSTATUS_SOURCE_ID_SHIFT 16
-+#define GPU_FAULTSTATUS_SOURCE_ID_MASK \
-+ (0xFFFFul << GPU_FAULTSTATUS_SOURCE_ID_SHIFT)
-+/* End GPU_FAULTSTATUS register */
-+
-+/* GPU_FAULTSTATUS_ACCESS_TYPE values */
-+#define GPU_FAULTSTATUS_ACCESS_TYPE_ATOMIC 0x0
-+#define GPU_FAULTSTATUS_ACCESS_TYPE_EXECUTE 0x1
-+#define GPU_FAULTSTATUS_ACCESS_TYPE_READ 0x2
-+#define GPU_FAULTSTATUS_ACCESS_TYPE_WRITE 0x3
-+/* End of GPU_FAULTSTATUS_ACCESS_TYPE values */
-+
-+/* Implementation-dependent exception codes used to indicate CSG
-+ * and CS errors that are not specified in the specs.
-+ */
-+#define GPU_EXCEPTION_TYPE_SW_FAULT_0 ((__u8)0x70)
-+#define GPU_EXCEPTION_TYPE_SW_FAULT_1 ((__u8)0x71)
-+#define GPU_EXCEPTION_TYPE_SW_FAULT_2 ((__u8)0x72)
-+
-+/* GPU_FAULTSTATUS_EXCEPTION_TYPE values */
-+#define GPU_FAULTSTATUS_EXCEPTION_TYPE_OK 0x00
-+#define GPU_FAULTSTATUS_EXCEPTION_TYPE_GPU_BUS_FAULT 0x80
-+#define GPU_FAULTSTATUS_EXCEPTION_TYPE_GPU_SHAREABILITY_FAULT 0x88
-+#define GPU_FAULTSTATUS_EXCEPTION_TYPE_SYSTEM_SHAREABILITY_FAULT 0x89
-+#define GPU_FAULTSTATUS_EXCEPTION_TYPE_GPU_CACHEABILITY_FAULT 0x8A
-+/* End of GPU_FAULTSTATUS_EXCEPTION_TYPE values */
-+
-+#define GPU_FAULTSTATUS_ADDRESS_VALID_SHIFT GPU_U(10)
-+#define GPU_FAULTSTATUS_ADDRESS_VALID_MASK (GPU_U(0x1) << GPU_FAULTSTATUS_ADDRESS_VALID_SHIFT)
-+#define GPU_FAULTSTATUS_ADDRESS_VALID_GET(reg_val) \
-+ (((reg_val)&GPU_FAULTSTATUS_ADDRESS_VALID_MASK) >> GPU_FAULTSTATUS_ADDRESS_VALID_SHIFT)
-+#define GPU_FAULTSTATUS_ADDRESS_VALID_SET(reg_val, value) \
-+ (((reg_val) & ~GPU_FAULTSTATUS_ADDRESS_VALID_MASK) | \
-+ (((value) << GPU_FAULTSTATUS_ADDRESS_VALID_SHIFT) & GPU_FAULTSTATUS_ADDRESS_VALID_MASK))
-+
-+/* IRQ flags */
-+#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */
-+#define GPU_PROTECTED_FAULT (1 << 1) /* A GPU fault has occurred in protected mode */
-+#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. */
-+#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */
-+#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down. */
-+#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */
-+#define DOORBELL_MIRROR (1 << 18) /* Mirrors the doorbell interrupt line to the CPU */
-+#define MCU_STATUS_GPU_IRQ (1 << 19) /* MCU requires attention */
-+
-+/*
-+ * In Debug build,
-+ * GPU_IRQ_REG_COMMON | POWER_CHANGED_SINGLE is used to clear and unmask interupts sources of GPU_IRQ
-+ * by writing it onto GPU_IRQ_CLEAR/MASK registers.
-+ *
-+ * In Release build,
-+ * GPU_IRQ_REG_COMMON is used.
-+ *
-+ * Note:
-+ * CLEAN_CACHES_COMPLETED - Used separately for cache operation.
-+ * DOORBELL_MIRROR - Do not have it included for GPU_IRQ_REG_COMMON
-+ * as it can't be cleared by GPU_IRQ_CLEAR, thus interrupt storm might happen
-+ */
-+#define GPU_IRQ_REG_COMMON (GPU_FAULT | GPU_PROTECTED_FAULT | RESET_COMPLETED \
-+ | POWER_CHANGED_ALL | MCU_STATUS_GPU_IRQ)
-+
-+/* GPU_CONTROL_MCU.GPU_IRQ_RAWSTAT */
-+#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when performance count sample has completed */
-+
-+#endif /* _UAPI_KBASE_GPU_REGMAP_CSF_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_jm.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_jm.h
-similarity index 89%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_jm.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_jm.h
-index 258ff33..1be3541 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_jm.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/backend/mali_kbase_gpu_regmap_jm.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,13 +17,14 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifndef _KBASE_GPU_REGMAP_JM_H_
--#define _KBASE_GPU_REGMAP_JM_H_
-+#ifndef _UAPI_KBASE_GPU_REGMAP_JM_H_
-+#define _UAPI_KBASE_GPU_REGMAP_JM_H_
-
-+#if MALI_USE_CSF && defined(__KERNEL__)
-+#error "Cannot be compiled with CSF"
-+#endif
-
- /* Set to implementation defined, outer caching */
- #define AS_MEMATTR_AARCH64_OUTER_IMPL_DEF 0x88ull
-@@ -136,8 +138,8 @@
- #define JS_AFFINITY_LO 0x10 /* (RO) Core affinity mask for job slot n, low word */
- #define JS_AFFINITY_HI 0x14 /* (RO) Core affinity mask for job slot n, high word */
- #define JS_CONFIG 0x18 /* (RO) Configuration settings for job slot n */
--#define JS_XAFFINITY 0x1C /* (RO) Extended affinity mask for job
-- slot n */
-+/* (RO) Extended affinity mask for job slot n*/
-+#define JS_XAFFINITY 0x1C
-
- #define JS_COMMAND 0x20 /* (WO) Command register for job slot n */
- #define JS_STATUS 0x24 /* (RO) Status register for job slot n */
-@@ -148,8 +150,8 @@
- #define JS_AFFINITY_NEXT_LO 0x50 /* (RW) Next core affinity mask for job slot n, low word */
- #define JS_AFFINITY_NEXT_HI 0x54 /* (RW) Next core affinity mask for job slot n, high word */
- #define JS_CONFIG_NEXT 0x58 /* (RW) Next configuration settings for job slot n */
--#define JS_XAFFINITY_NEXT 0x5C /* (RW) Next extended affinity mask for
-- job slot n */
-+/* (RW) Next extended affinity mask for job slot n */
-+#define JS_XAFFINITY_NEXT 0x5C
-
- #define JS_COMMAND_NEXT 0x60 /* (RW) Next command register for job slot n */
-
-@@ -259,4 +261,27 @@
- #define GPU_COMMAND_CLEAN_INV_CACHES 0x08 /* Clean and invalidate all caches */
- #define GPU_COMMAND_SET_PROTECTED_MODE 0x09 /* Places the GPU in protected mode */
-
--#endif /* _KBASE_GPU_REGMAP_JM_H_ */
-+/* IRQ flags */
-+#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */
-+#define MULTIPLE_GPU_FAULTS (1 << 7) /* More than one GPU Fault occurred. */
-+#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. */
-+#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */
-+#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down. */
-+#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when a performance count sample has completed. */
-+#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */
-+
-+/*
-+ * In Debug build,
-+ * GPU_IRQ_REG_COMMON | POWER_CHANGED_SINGLE is used to clear and enable interupts sources of GPU_IRQ
-+ * by writing it onto GPU_IRQ_CLEAR/MASK registers.
-+ *
-+ * In Release build,
-+ * GPU_IRQ_REG_COMMON is used.
-+ *
-+ * Note:
-+ * CLEAN_CACHES_COMPLETED - Used separately for cache operation.
-+ */
-+#define GPU_IRQ_REG_COMMON (GPU_FAULT | MULTIPLE_GPU_FAULTS | RESET_COMPLETED \
-+ | POWER_CHANGED_ALL | PRFCNT_SAMPLE_COMPLETED)
-+
-+#endif /* _UAPI_KBASE_GPU_REGMAP_JM_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_coherency.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_coherency.h
-similarity index 75%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_coherency.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_coherency.h
-index bb2b161..83d8413 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_coherency.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_coherency.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,16 +17,14 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifndef _KBASE_GPU_COHERENCY_H_
--#define _KBASE_GPU_COHERENCY_H_
-+#ifndef _UAPI_KBASE_GPU_COHERENCY_H_
-+#define _UAPI_KBASE_GPU_COHERENCY_H_
-
- #define COHERENCY_ACE_LITE 0
- #define COHERENCY_ACE 1
- #define COHERENCY_NONE 31
- #define COHERENCY_FEATURE_BIT(x) (1 << (x))
-
--#endif /* _KBASE_GPU_COHERENCY_H_ */
-+#endif /* _UAPI_KBASE_GPU_COHERENCY_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_id.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_id.h
-similarity index 74%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_id.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_id.h
-index 9f3d6b1..d093ce4 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/gpu/mali_kbase_gpu_id.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_id.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,12 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifndef _KBASE_GPU_ID_H_
--#define _KBASE_GPU_ID_H_
-+#ifndef _UAPI_KBASE_GPU_ID_H_
-+#define _UAPI_KBASE_GPU_ID_H_
-+
-+#include <linux/types.h>
-
- /* GPU_ID register */
- #define GPU_ID_VERSION_STATUS_SHIFT 0
-@@ -53,19 +54,21 @@
- GPU_ID2_VERSION_STATUS)
-
- /* Helper macro to create a partial GPU_ID (new format) that defines
-- a product ignoring its version. */
-+ * a product ignoring its version.
-+ */
- #define GPU_ID2_PRODUCT_MAKE(arch_major, arch_minor, arch_rev, product_major) \
-- ((((u32)arch_major) << GPU_ID2_ARCH_MAJOR_SHIFT) | \
-- (((u32)arch_minor) << GPU_ID2_ARCH_MINOR_SHIFT) | \
-- (((u32)arch_rev) << GPU_ID2_ARCH_REV_SHIFT) | \
-- (((u32)product_major) << GPU_ID2_PRODUCT_MAJOR_SHIFT))
-+ ((((__u32)arch_major) << GPU_ID2_ARCH_MAJOR_SHIFT) | \
-+ (((__u32)arch_minor) << GPU_ID2_ARCH_MINOR_SHIFT) | \
-+ (((__u32)arch_rev) << GPU_ID2_ARCH_REV_SHIFT) | \
-+ (((__u32)product_major) << GPU_ID2_PRODUCT_MAJOR_SHIFT))
-
- /* Helper macro to create a partial GPU_ID (new format) that specifies the
-- revision (major, minor, status) of a product */
-+ * revision (major, minor, status) of a product
-+ */
- #define GPU_ID2_VERSION_MAKE(version_major, version_minor, version_status) \
-- ((((u32)version_major) << GPU_ID2_VERSION_MAJOR_SHIFT) | \
-- (((u32)version_minor) << GPU_ID2_VERSION_MINOR_SHIFT) | \
-- (((u32)version_status) << GPU_ID2_VERSION_STATUS_SHIFT))
-+ ((((__u32)version_major) << GPU_ID2_VERSION_MAJOR_SHIFT) | \
-+ (((__u32)version_minor) << GPU_ID2_VERSION_MINOR_SHIFT) | \
-+ (((__u32)version_status) << GPU_ID2_VERSION_STATUS_SHIFT))
-
- /* Helper macro to create a complete GPU_ID (new format) */
- #define GPU_ID2_MAKE(arch_major, arch_minor, arch_rev, product_major, \
-@@ -76,16 +79,18 @@
- version_status))
-
- /* Helper macro to create a partial GPU_ID (new format) that identifies
-- a particular GPU model by its arch_major and product_major. */
-+ * a particular GPU model by its arch_major and product_major.
-+ */
- #define GPU_ID2_MODEL_MAKE(arch_major, product_major) \
-- ((((u32)arch_major) << GPU_ID2_ARCH_MAJOR_SHIFT) | \
-- (((u32)product_major) << GPU_ID2_PRODUCT_MAJOR_SHIFT))
-+ ((((__u32)arch_major) << GPU_ID2_ARCH_MAJOR_SHIFT) | \
-+ (((__u32)product_major) << GPU_ID2_PRODUCT_MAJOR_SHIFT))
-
- /* Strip off the non-relevant bits from a product_id value and make it suitable
-- for comparison against the GPU_ID2_PRODUCT_xxx values which identify a GPU
-- model. */
-+ * for comparison against the GPU_ID2_PRODUCT_xxx values which identify a GPU
-+ * model.
-+ */
- #define GPU_ID2_MODEL_MATCH_VALUE(product_id) \
-- ((((u32)product_id) << GPU_ID2_PRODUCT_MAJOR_SHIFT) & \
-+ ((((__u32)product_id) << GPU_ID2_PRODUCT_MAJOR_SHIFT) & \
- GPU_ID2_PRODUCT_MODEL)
-
- #define GPU_ID2_PRODUCT_TMIX GPU_ID2_MODEL_MAKE(6, 0)
-@@ -98,21 +103,20 @@
- #define GPU_ID2_PRODUCT_TNAX GPU_ID2_MODEL_MAKE(9, 1)
- #define GPU_ID2_PRODUCT_TBEX GPU_ID2_MODEL_MAKE(9, 2)
- #define GPU_ID2_PRODUCT_LBEX GPU_ID2_MODEL_MAKE(9, 4)
-+#define GPU_ID2_PRODUCT_TBAX GPU_ID2_MODEL_MAKE(9, 5)
- #define GPU_ID2_PRODUCT_TDUX GPU_ID2_MODEL_MAKE(10, 1)
- #define GPU_ID2_PRODUCT_TODX GPU_ID2_MODEL_MAKE(10, 2)
- #define GPU_ID2_PRODUCT_TGRX GPU_ID2_MODEL_MAKE(10, 3)
- #define GPU_ID2_PRODUCT_TVAX GPU_ID2_MODEL_MAKE(10, 4)
- #define GPU_ID2_PRODUCT_LODX GPU_ID2_MODEL_MAKE(10, 7)
--#define GPU_ID2_PRODUCT_TTUX GPU_ID2_MODEL_MAKE(11, 2)
--#define GPU_ID2_PRODUCT_LTUX GPU_ID2_MODEL_MAKE(11, 3)
--#define GPU_ID2_PRODUCT_TE2X GPU_ID2_MODEL_MAKE(11, 1)
-
- /* Helper macro to create a GPU_ID assuming valid values for id, major,
-- minor, status */
-+ * minor, status
-+ */
- #define GPU_ID_MAKE(id, major, minor, status) \
-- ((((u32)id) << GPU_ID_VERSION_PRODUCT_ID_SHIFT) | \
-- (((u32)major) << GPU_ID_VERSION_MAJOR_SHIFT) | \
-- (((u32)minor) << GPU_ID_VERSION_MINOR_SHIFT) | \
-- (((u32)status) << GPU_ID_VERSION_STATUS_SHIFT))
-+ ((((__u32)id) << GPU_ID_VERSION_PRODUCT_ID_SHIFT) | \
-+ (((__u32)major) << GPU_ID_VERSION_MAJOR_SHIFT) | \
-+ (((__u32)minor) << GPU_ID_VERSION_MINOR_SHIFT) | \
-+ (((__u32)status) << GPU_ID_VERSION_STATUS_SHIFT))
-
--#endif /* _KBASE_GPU_ID_H_ */
-+#endif /* _UAPI_KBASE_GPU_ID_H_ */
-diff --git a/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_regmap.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_regmap.h
-new file mode 100644
-index 0000000..84fad8d
---- /dev/null
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/gpu/mali_kbase_gpu_regmap.h
-@@ -0,0 +1,434 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+#ifndef _UAPI_KBASE_GPU_REGMAP_H_
-+#define _UAPI_KBASE_GPU_REGMAP_H_
-+
-+#include "mali_kbase_gpu_coherency.h"
-+#include "mali_kbase_gpu_id.h"
-+#if MALI_USE_CSF
-+#include "backend/mali_kbase_gpu_regmap_csf.h"
-+#else
-+#include "backend/mali_kbase_gpu_regmap_jm.h"
-+#endif
-+
-+/* Begin Register Offsets */
-+/* GPU control registers */
-+
-+#define GPU_CONTROL_BASE 0x0000
-+#define GPU_CONTROL_REG(r) (GPU_CONTROL_BASE + (r))
-+#define GPU_ID 0x000 /* (RO) GPU and revision identifier */
-+#define L2_FEATURES 0x004 /* (RO) Level 2 cache features */
-+#define TILER_FEATURES 0x00C /* (RO) Tiler Features */
-+#define MEM_FEATURES 0x010 /* (RO) Memory system features */
-+#define MMU_FEATURES 0x014 /* (RO) MMU features */
-+#define AS_PRESENT 0x018 /* (RO) Address space slots present */
-+#define GPU_IRQ_RAWSTAT 0x020 /* (RW) */
-+#define GPU_IRQ_CLEAR 0x024 /* (WO) */
-+#define GPU_IRQ_MASK 0x028 /* (RW) */
-+#define GPU_IRQ_STATUS 0x02C /* (RO) */
-+
-+#define GPU_COMMAND 0x030 /* (WO) */
-+#define GPU_STATUS 0x034 /* (RO) */
-+
-+#define GPU_DBGEN (1 << 8) /* DBGEN wire status */
-+
-+#define GPU_FAULTSTATUS 0x03C /* (RO) GPU exception type and fault status */
-+#define GPU_FAULTADDRESS_LO 0x040 /* (RO) GPU exception fault address, low word */
-+#define GPU_FAULTADDRESS_HI 0x044 /* (RO) GPU exception fault address, high word */
-+
-+#define L2_CONFIG 0x048 /* (RW) Level 2 cache configuration */
-+
-+#define GROUPS_L2_COHERENT (1 << 0) /* Cores groups are l2 coherent */
-+#define SUPER_L2_COHERENT (1 << 1) /* Shader cores within a core
-+ * supergroup are l2 coherent
-+ */
-+
-+#define PWR_KEY 0x050 /* (WO) Power manager key register */
-+#define PWR_OVERRIDE0 0x054 /* (RW) Power manager override settings */
-+#define PWR_OVERRIDE1 0x058 /* (RW) Power manager override settings */
-+#define GPU_FEATURES_LO 0x060 /* (RO) GPU features, low word */
-+#define GPU_FEATURES_HI 0x064 /* (RO) GPU features, high word */
-+#define PRFCNT_FEATURES 0x068 /* (RO) Performance counter features */
-+#define TIMESTAMP_OFFSET_LO 0x088 /* (RW) Global time stamp offset, low word */
-+#define TIMESTAMP_OFFSET_HI 0x08C /* (RW) Global time stamp offset, high word */
-+#define CYCLE_COUNT_LO 0x090 /* (RO) Cycle counter, low word */
-+#define CYCLE_COUNT_HI 0x094 /* (RO) Cycle counter, high word */
-+#define TIMESTAMP_LO 0x098 /* (RO) Global time stamp counter, low word */
-+#define TIMESTAMP_HI 0x09C /* (RO) Global time stamp counter, high word */
-+
-+#define THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */
-+#define THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */
-+#define THREAD_MAX_BARRIER_SIZE 0x0A8 /* (RO) Maximum threads waiting at a barrier */
-+#define THREAD_FEATURES 0x0AC /* (RO) Thread features */
-+#define THREAD_TLS_ALLOC 0x310 /* (RO) Number of threads per core that TLS must be allocated for */
-+
-+#define TEXTURE_FEATURES_0 0x0B0 /* (RO) Support flags for indexed texture formats 0..31 */
-+#define TEXTURE_FEATURES_1 0x0B4 /* (RO) Support flags for indexed texture formats 32..63 */
-+#define TEXTURE_FEATURES_2 0x0B8 /* (RO) Support flags for indexed texture formats 64..95 */
-+#define TEXTURE_FEATURES_3 0x0BC /* (RO) Support flags for texture order */
-+
-+#define TEXTURE_FEATURES_REG(n) GPU_CONTROL_REG(TEXTURE_FEATURES_0 + ((n) << 2))
-+
-+#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */
-+#define SHADER_PRESENT_HI 0x104 /* (RO) Shader core present bitmap, high word */
-+
-+#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */
-+#define TILER_PRESENT_HI 0x114 /* (RO) Tiler core present bitmap, high word */
-+
-+#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */
-+#define L2_PRESENT_HI 0x124 /* (RO) Level 2 cache present bitmap, high word */
-+
-+#define STACK_PRESENT_LO 0xE00 /* (RO) Core stack present bitmap, low word */
-+#define STACK_PRESENT_HI 0xE04 /* (RO) Core stack present bitmap, high word */
-+
-+#define SHADER_READY_LO 0x140 /* (RO) Shader core ready bitmap, low word */
-+#define SHADER_READY_HI 0x144 /* (RO) Shader core ready bitmap, high word */
-+
-+#define TILER_READY_LO 0x150 /* (RO) Tiler core ready bitmap, low word */
-+#define TILER_READY_HI 0x154 /* (RO) Tiler core ready bitmap, high word */
-+
-+#define L2_READY_LO 0x160 /* (RO) Level 2 cache ready bitmap, low word */
-+#define L2_READY_HI 0x164 /* (RO) Level 2 cache ready bitmap, high word */
-+
-+#define STACK_READY_LO 0xE10 /* (RO) Core stack ready bitmap, low word */
-+#define STACK_READY_HI 0xE14 /* (RO) Core stack ready bitmap, high word */
-+
-+#define SHADER_PWRON_LO 0x180 /* (WO) Shader core power on bitmap, low word */
-+#define SHADER_PWRON_HI 0x184 /* (WO) Shader core power on bitmap, high word */
-+
-+#define TILER_PWRON_LO 0x190 /* (WO) Tiler core power on bitmap, low word */
-+#define TILER_PWRON_HI 0x194 /* (WO) Tiler core power on bitmap, high word */
-+
-+#define L2_PWRON_LO 0x1A0 /* (WO) Level 2 cache power on bitmap, low word */
-+#define L2_PWRON_HI 0x1A4 /* (WO) Level 2 cache power on bitmap, high word */
-+
-+#define STACK_PWRON_LO 0xE20 /* (RO) Core stack power on bitmap, low word */
-+#define STACK_PWRON_HI 0xE24 /* (RO) Core stack power on bitmap, high word */
-+
-+#define SHADER_PWROFF_LO 0x1C0 /* (WO) Shader core power off bitmap, low word */
-+#define SHADER_PWROFF_HI 0x1C4 /* (WO) Shader core power off bitmap, high word */
-+
-+#define TILER_PWROFF_LO 0x1D0 /* (WO) Tiler core power off bitmap, low word */
-+#define TILER_PWROFF_HI 0x1D4 /* (WO) Tiler core power off bitmap, high word */
-+
-+#define L2_PWROFF_LO 0x1E0 /* (WO) Level 2 cache power off bitmap, low word */
-+#define L2_PWROFF_HI 0x1E4 /* (WO) Level 2 cache power off bitmap, high word */
-+
-+#define STACK_PWROFF_LO 0xE30 /* (RO) Core stack power off bitmap, low word */
-+#define STACK_PWROFF_HI 0xE34 /* (RO) Core stack power off bitmap, high word */
-+
-+#define SHADER_PWRTRANS_LO 0x200 /* (RO) Shader core power transition bitmap, low word */
-+#define SHADER_PWRTRANS_HI 0x204 /* (RO) Shader core power transition bitmap, high word */
-+
-+#define TILER_PWRTRANS_LO 0x210 /* (RO) Tiler core power transition bitmap, low word */
-+#define TILER_PWRTRANS_HI 0x214 /* (RO) Tiler core power transition bitmap, high word */
-+
-+#define L2_PWRTRANS_LO 0x220 /* (RO) Level 2 cache power transition bitmap, low word */
-+#define L2_PWRTRANS_HI 0x224 /* (RO) Level 2 cache power transition bitmap, high word */
-+
-+#define ASN_HASH_0 0x02C0 /* (RW) ASN hash function argument 0 */
-+#define ASN_HASH(n) (ASN_HASH_0 + (n)*4)
-+#define ASN_HASH_COUNT 3
-+
-+#define STACK_PWRTRANS_LO 0xE40 /* (RO) Core stack power transition bitmap, low word */
-+#define STACK_PWRTRANS_HI 0xE44 /* (RO) Core stack power transition bitmap, high word */
-+
-+#define SHADER_PWRACTIVE_LO 0x240 /* (RO) Shader core active bitmap, low word */
-+#define SHADER_PWRACTIVE_HI 0x244 /* (RO) Shader core active bitmap, high word */
-+
-+#define TILER_PWRACTIVE_LO 0x250 /* (RO) Tiler core active bitmap, low word */
-+#define TILER_PWRACTIVE_HI 0x254 /* (RO) Tiler core active bitmap, high word */
-+
-+#define L2_PWRACTIVE_LO 0x260 /* (RO) Level 2 cache active bitmap, low word */
-+#define L2_PWRACTIVE_HI 0x264 /* (RO) Level 2 cache active bitmap, high word */
-+
-+#define COHERENCY_FEATURES 0x300 /* (RO) Coherency features present */
-+#define COHERENCY_ENABLE 0x304 /* (RW) Coherency enable */
-+
-+#define SHADER_CONFIG 0xF04 /* (RW) Shader core configuration (implementation-specific) */
-+#define TILER_CONFIG 0xF08 /* (RW) Tiler core configuration (implementation-specific) */
-+#define L2_MMU_CONFIG 0xF0C /* (RW) L2 cache and MMU configuration (implementation-specific) */
-+
-+/* Job control registers */
-+
-+#define JOB_CONTROL_BASE 0x1000
-+
-+#define JOB_CONTROL_REG(r) (JOB_CONTROL_BASE + (r))
-+
-+#define JOB_IRQ_RAWSTAT 0x000 /* Raw interrupt status register */
-+#define JOB_IRQ_CLEAR 0x004 /* Interrupt clear register */
-+#define JOB_IRQ_MASK 0x008 /* Interrupt mask register */
-+#define JOB_IRQ_STATUS 0x00C /* Interrupt status register */
-+
-+/* MMU control registers */
-+
-+#define MEMORY_MANAGEMENT_BASE 0x2000
-+#define MMU_REG(r) (MEMORY_MANAGEMENT_BASE + (r))
-+
-+#define MMU_IRQ_RAWSTAT 0x000 /* (RW) Raw interrupt status register */
-+#define MMU_IRQ_CLEAR 0x004 /* (WO) Interrupt clear register */
-+#define MMU_IRQ_MASK 0x008 /* (RW) Interrupt mask register */
-+#define MMU_IRQ_STATUS 0x00C /* (RO) Interrupt status register */
-+
-+#define MMU_AS0 0x400 /* Configuration registers for address space 0 */
-+#define MMU_AS1 0x440 /* Configuration registers for address space 1 */
-+#define MMU_AS2 0x480 /* Configuration registers for address space 2 */
-+#define MMU_AS3 0x4C0 /* Configuration registers for address space 3 */
-+#define MMU_AS4 0x500 /* Configuration registers for address space 4 */
-+#define MMU_AS5 0x540 /* Configuration registers for address space 5 */
-+#define MMU_AS6 0x580 /* Configuration registers for address space 6 */
-+#define MMU_AS7 0x5C0 /* Configuration registers for address space 7 */
-+#define MMU_AS8 0x600 /* Configuration registers for address space 8 */
-+#define MMU_AS9 0x640 /* Configuration registers for address space 9 */
-+#define MMU_AS10 0x680 /* Configuration registers for address space 10 */
-+#define MMU_AS11 0x6C0 /* Configuration registers for address space 11 */
-+#define MMU_AS12 0x700 /* Configuration registers for address space 12 */
-+#define MMU_AS13 0x740 /* Configuration registers for address space 13 */
-+#define MMU_AS14 0x780 /* Configuration registers for address space 14 */
-+#define MMU_AS15 0x7C0 /* Configuration registers for address space 15 */
-+
-+/* MMU address space control registers */
-+
-+#define MMU_AS_REG(n, r) (MMU_REG(MMU_AS0 + ((n) << 6)) + (r))
-+
-+#define AS_TRANSTAB_LO 0x00 /* (RW) Translation Table Base Address for address space n, low word */
-+#define AS_TRANSTAB_HI 0x04 /* (RW) Translation Table Base Address for address space n, high word */
-+#define AS_MEMATTR_LO 0x08 /* (RW) Memory attributes for address space n, low word. */
-+#define AS_MEMATTR_HI 0x0C /* (RW) Memory attributes for address space n, high word. */
-+#define AS_LOCKADDR_LO 0x10 /* (RW) Lock region address for address space n, low word */
-+#define AS_LOCKADDR_HI 0x14 /* (RW) Lock region address for address space n, high word */
-+#define AS_COMMAND 0x18 /* (WO) MMU command register for address space n */
-+#define AS_FAULTSTATUS 0x1C /* (RO) MMU fault status register for address space n */
-+#define AS_FAULTADDRESS_LO 0x20 /* (RO) Fault Address for address space n, low word */
-+#define AS_FAULTADDRESS_HI 0x24 /* (RO) Fault Address for address space n, high word */
-+#define AS_STATUS 0x28 /* (RO) Status flags for address space n */
-+
-+/* (RW) Translation table configuration for address space n, low word */
-+#define AS_TRANSCFG_LO 0x30
-+/* (RW) Translation table configuration for address space n, high word */
-+#define AS_TRANSCFG_HI 0x34
-+/* (RO) Secondary fault address for address space n, low word */
-+#define AS_FAULTEXTRA_LO 0x38
-+/* (RO) Secondary fault address for address space n, high word */
-+#define AS_FAULTEXTRA_HI 0x3C
-+
-+/* End Register Offsets */
-+
-+#define GPU_IRQ_REG_ALL (GPU_IRQ_REG_COMMON)
-+
-+/*
-+ * MMU_IRQ_RAWSTAT register values. Values are valid also for
-+ * MMU_IRQ_CLEAR, MMU_IRQ_MASK, MMU_IRQ_STATUS registers.
-+ */
-+
-+#define MMU_PAGE_FAULT_FLAGS 16
-+
-+/* Macros returning a bitmask to retrieve page fault or bus error flags from
-+ * MMU registers
-+ */
-+#define MMU_PAGE_FAULT(n) (1UL << (n))
-+#define MMU_BUS_ERROR(n) (1UL << ((n) + MMU_PAGE_FAULT_FLAGS))
-+
-+/*
-+ * Begin AARCH64 MMU TRANSTAB register values
-+ */
-+#define MMU_HW_OUTA_BITS 40
-+#define AS_TRANSTAB_BASE_MASK ((1ULL << MMU_HW_OUTA_BITS) - (1ULL << 4))
-+
-+/*
-+ * Begin MMU STATUS register values
-+ */
-+#define AS_STATUS_AS_ACTIVE 0x01
-+
-+#define AS_FAULTSTATUS_EXCEPTION_CODE_MASK (0x7<<3)
-+#define AS_FAULTSTATUS_EXCEPTION_CODE_TRANSLATION_FAULT (0x0<<3)
-+#define AS_FAULTSTATUS_EXCEPTION_CODE_PERMISSION_FAULT (0x1<<3)
-+#define AS_FAULTSTATUS_EXCEPTION_CODE_TRANSTAB_BUS_FAULT (0x2<<3)
-+#define AS_FAULTSTATUS_EXCEPTION_CODE_ACCESS_FLAG (0x3<<3)
-+#define AS_FAULTSTATUS_EXCEPTION_CODE_ADDRESS_SIZE_FAULT (0x4<<3)
-+#define AS_FAULTSTATUS_EXCEPTION_CODE_MEMORY_ATTRIBUTES_FAULT (0x5<<3)
-+
-+#define AS_FAULTSTATUS_EXCEPTION_TYPE_SHIFT 0
-+#define AS_FAULTSTATUS_EXCEPTION_TYPE_MASK (0xFF << AS_FAULTSTATUS_EXCEPTION_TYPE_SHIFT)
-+#define AS_FAULTSTATUS_EXCEPTION_TYPE_GET(reg_val) \
-+ (((reg_val)&AS_FAULTSTATUS_EXCEPTION_TYPE_MASK) >> AS_FAULTSTATUS_EXCEPTION_TYPE_SHIFT)
-+#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_0 0xC0
-+
-+#define AS_FAULTSTATUS_ACCESS_TYPE_SHIFT 8
-+#define AS_FAULTSTATUS_ACCESS_TYPE_MASK (0x3 << AS_FAULTSTATUS_ACCESS_TYPE_SHIFT)
-+#define AS_FAULTSTATUS_ACCESS_TYPE_GET(reg_val) \
-+ (((reg_val)&AS_FAULTSTATUS_ACCESS_TYPE_MASK) >> AS_FAULTSTATUS_ACCESS_TYPE_SHIFT)
-+
-+#define AS_FAULTSTATUS_ACCESS_TYPE_ATOMIC (0x0)
-+#define AS_FAULTSTATUS_ACCESS_TYPE_EX (0x1)
-+#define AS_FAULTSTATUS_ACCESS_TYPE_READ (0x2)
-+#define AS_FAULTSTATUS_ACCESS_TYPE_WRITE (0x3)
-+
-+#define AS_FAULTSTATUS_SOURCE_ID_SHIFT 16
-+#define AS_FAULTSTATUS_SOURCE_ID_MASK (0xFFFF << AS_FAULTSTATUS_SOURCE_ID_SHIFT)
-+#define AS_FAULTSTATUS_SOURCE_ID_GET(reg_val) \
-+ (((reg_val)&AS_FAULTSTATUS_SOURCE_ID_MASK) >> AS_FAULTSTATUS_SOURCE_ID_SHIFT)
-+
-+#define PRFCNT_FEATURES_COUNTER_BLOCK_SIZE_SHIFT (0)
-+#define PRFCNT_FEATURES_COUNTER_BLOCK_SIZE_MASK \
-+ ((0xFF) << PRFCNT_FEATURES_COUNTER_BLOCK_SIZE_SHIFT)
-+#define PRFCNT_FEATURES_COUNTER_BLOCK_SIZE_GET(reg_val) \
-+ (((reg_val)&PRFCNT_FEATURES_COUNTER_BLOCK_SIZE_MASK) >> \
-+ PRFCNT_FEATURES_COUNTER_BLOCK_SIZE_SHIFT)
-+
-+/*
-+ * Begin MMU TRANSCFG register values
-+ */
-+#define AS_TRANSCFG_ADRMODE_LEGACY 0
-+#define AS_TRANSCFG_ADRMODE_UNMAPPED 1
-+#define AS_TRANSCFG_ADRMODE_IDENTITY 2
-+#define AS_TRANSCFG_ADRMODE_AARCH64_4K 6
-+#define AS_TRANSCFG_ADRMODE_AARCH64_64K 8
-+
-+#define AS_TRANSCFG_ADRMODE_MASK 0xF
-+
-+/*
-+ * Begin TRANSCFG register values
-+ */
-+#define AS_TRANSCFG_PTW_MEMATTR_MASK (3ull << 24)
-+#define AS_TRANSCFG_PTW_MEMATTR_NON_CACHEABLE (1ull << 24)
-+#define AS_TRANSCFG_PTW_MEMATTR_WRITE_BACK (2ull << 24)
-+
-+#define AS_TRANSCFG_PTW_SH_MASK ((3ull << 28))
-+#define AS_TRANSCFG_PTW_SH_OS (2ull << 28)
-+#define AS_TRANSCFG_PTW_SH_IS (3ull << 28)
-+#define AS_TRANSCFG_R_ALLOCATE (1ull << 30)
-+
-+/*
-+ * Begin Command Values
-+ */
-+
-+/* AS_COMMAND register commands */
-+#define AS_COMMAND_NOP 0x00 /* NOP Operation */
-+#define AS_COMMAND_UPDATE 0x01 /* Broadcasts the values in AS_TRANSTAB and ASn_MEMATTR to all MMUs */
-+#define AS_COMMAND_LOCK 0x02 /* Issue a lock region command to all MMUs */
-+#define AS_COMMAND_UNLOCK 0x03 /* Issue a flush region command to all MMUs */
-+/* Flush all L2 caches then issue a flush region command to all MMUs
-+ * (deprecated - only for use with T60x)
-+ */
-+#define AS_COMMAND_FLUSH 0x04
-+/* Flush all L2 caches then issue a flush region command to all MMUs */
-+#define AS_COMMAND_FLUSH_PT 0x04
-+/* Wait for memory accesses to complete, flush all the L1s cache then flush all
-+ * L2 caches then issue a flush region command to all MMUs
-+ */
-+#define AS_COMMAND_FLUSH_MEM 0x05
-+
-+/* GPU_STATUS values */
-+#define GPU_STATUS_PRFCNT_ACTIVE (1 << 2) /* Set if the performance counters are active. */
-+#define GPU_STATUS_CYCLE_COUNT_ACTIVE (1 << 6) /* Set if the cycle counter is active. */
-+#define GPU_STATUS_PROTECTED_MODE_ACTIVE (1 << 7) /* Set if protected mode is active */
-+
-+/* PRFCNT_CONFIG register values */
-+#define PRFCNT_CONFIG_MODE_SHIFT 0 /* Counter mode position. */
-+#define PRFCNT_CONFIG_AS_SHIFT 4 /* Address space bitmap position. */
-+#define PRFCNT_CONFIG_SETSELECT_SHIFT 8 /* Set select position. */
-+
-+/* The performance counters are disabled. */
-+#define PRFCNT_CONFIG_MODE_OFF 0
-+/* The performance counters are enabled, but are only written out when a
-+ * PRFCNT_SAMPLE command is issued using the GPU_COMMAND register.
-+ */
-+#define PRFCNT_CONFIG_MODE_MANUAL 1
-+/* The performance counters are enabled, and are written out each time a tile
-+ * finishes rendering.
-+ */
-+#define PRFCNT_CONFIG_MODE_TILE 2
-+
-+/* AS<n>_MEMATTR values from MMU_MEMATTR_STAGE1: */
-+/* Use GPU implementation-defined caching policy. */
-+#define AS_MEMATTR_IMPL_DEF_CACHE_POLICY 0x88ull
-+/* The attribute set to force all resources to be cached. */
-+#define AS_MEMATTR_FORCE_TO_CACHE_ALL 0x8Full
-+/* Inner write-alloc cache setup, no outer caching */
-+#define AS_MEMATTR_WRITE_ALLOC 0x8Dull
-+
-+/* Use GPU implementation-defined caching policy. */
-+#define AS_MEMATTR_LPAE_IMPL_DEF_CACHE_POLICY 0x48ull
-+/* The attribute set to force all resources to be cached. */
-+#define AS_MEMATTR_LPAE_FORCE_TO_CACHE_ALL 0x4Full
-+/* Inner write-alloc cache setup, no outer caching */
-+#define AS_MEMATTR_LPAE_WRITE_ALLOC 0x4Dull
-+/* Set to implementation defined, outer caching */
-+#define AS_MEMATTR_LPAE_OUTER_IMPL_DEF 0x88ull
-+/* Set to write back memory, outer caching */
-+#define AS_MEMATTR_LPAE_OUTER_WA 0x8Dull
-+/* There is no LPAE support for non-cacheable, since the memory type is always
-+ * write-back.
-+ * Marking this setting as reserved for LPAE
-+ */
-+#define AS_MEMATTR_LPAE_NON_CACHEABLE_RESERVED
-+
-+/* L2_MMU_CONFIG register */
-+#define L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY_SHIFT (23)
-+#define L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY (0x1 << L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY_SHIFT)
-+
-+/* End L2_MMU_CONFIG register */
-+
-+/* THREAD_* registers */
-+
-+/* THREAD_FEATURES IMPLEMENTATION_TECHNOLOGY values */
-+#define IMPLEMENTATION_UNSPECIFIED 0
-+#define IMPLEMENTATION_SILICON 1
-+#define IMPLEMENTATION_FPGA 2
-+#define IMPLEMENTATION_MODEL 3
-+
-+/* Default values when registers are not supported by the implemented hardware */
-+#define THREAD_MT_DEFAULT 256
-+#define THREAD_MWS_DEFAULT 256
-+#define THREAD_MBS_DEFAULT 256
-+#define THREAD_MR_DEFAULT 1024
-+#define THREAD_MTQ_DEFAULT 4
-+#define THREAD_MTGS_DEFAULT 10
-+
-+/* End THREAD_* registers */
-+
-+/* SHADER_CONFIG register */
-+#define SC_LS_ALLOW_ATTR_TYPES (1ul << 16)
-+#define SC_TLS_HASH_ENABLE (1ul << 17)
-+#define SC_LS_ATTR_CHECK_DISABLE (1ul << 18)
-+#define SC_VAR_ALGORITHM (1ul << 29)
-+/* End SHADER_CONFIG register */
-+
-+/* TILER_CONFIG register */
-+#define TC_CLOCK_GATE_OVERRIDE (1ul << 0)
-+/* End TILER_CONFIG register */
-+
-+/* L2_CONFIG register */
-+#define L2_CONFIG_SIZE_SHIFT 16
-+#define L2_CONFIG_SIZE_MASK (0xFFul << L2_CONFIG_SIZE_SHIFT)
-+#define L2_CONFIG_HASH_SHIFT 24
-+#define L2_CONFIG_HASH_MASK (0xFFul << L2_CONFIG_HASH_SHIFT)
-+#define L2_CONFIG_ASN_HASH_ENABLE_SHIFT 24
-+#define L2_CONFIG_ASN_HASH_ENABLE_MASK (1ul << L2_CONFIG_ASN_HASH_ENABLE_SHIFT)
-+/* End L2_CONFIG register */
-+
-+/* IDVS_GROUP register */
-+#define IDVS_GROUP_SIZE_SHIFT (16)
-+#define IDVS_GROUP_MAX_SIZE (0x3F)
-+
-+#endif /* _UAPI_KBASE_GPU_REGMAP_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_base_jm_kernel.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/jm/mali_base_jm_kernel.h
-similarity index 75%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_base_jm_kernel.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/jm/mali_base_jm_kernel.h
-index 879a436..749e1fa 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_base_jm_kernel.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/jm/mali_base_jm_kernel.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2019-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,11 +17,12 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
--#ifndef _BASE_JM_KERNEL_H_
--#define _BASE_JM_KERNEL_H_
-+
-+#ifndef _UAPI_BASE_JM_KERNEL_H_
-+#define _UAPI_BASE_JM_KERNEL_H_
-+
-+#include <linux/types.h>
-
- /* Memory allocation, access/hint flags.
- *
-@@ -80,7 +82,8 @@
- */
- #define BASE_MEM_COHERENT_LOCAL ((base_mem_alloc_flags)1 << 11)
-
--/* Should be cached on the CPU
-+/* IN/OUT */
-+/* Should be cached on the CPU, returned if actually cached
- */
- #define BASE_MEM_CACHED_CPU ((base_mem_alloc_flags)1 << 12)
-
-@@ -120,9 +123,9 @@
- #define BASE_MEM_RESERVED_BIT_19 ((base_mem_alloc_flags)1 << 19)
-
- /**
-- * Memory starting from the end of the initial commit is aligned to 'extent'
-- * pages, where 'extent' must be a power of 2 and no more than
-- * BASE_MEM_TILER_ALIGN_TOP_EXTENT_MAX_PAGES
-+ * Memory starting from the end of the initial commit is aligned to 'extension'
-+ * pages, where 'extension' must be a power of 2 and no more than
-+ * BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES
- */
- #define BASE_MEM_TILER_ALIGN_TOP ((base_mem_alloc_flags)1 << 20)
-
-@@ -155,18 +158,25 @@
- /* Use the GPU VA chosen by the kernel client */
- #define BASE_MEM_FLAG_MAP_FIXED ((base_mem_alloc_flags)1 << 27)
-
-+/* OUT */
-+/* Kernel side cache sync ops required */
-+#define BASE_MEM_KERNEL_SYNC ((base_mem_alloc_flags)1 << 28)
-+
-+/* Force trimming of JIT allocations when creating a new allocation */
-+#define BASEP_MEM_PERFORM_JIT_TRIM ((base_mem_alloc_flags)1 << 29)
-+
- /* 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 28
-+#define BASE_MEM_FLAGS_NR_BITS 30
-
- /* A mask of all the flags which are only valid for allocations within kbase,
- * and may not be passed from user space.
- */
- #define BASEP_MEM_FLAGS_KERNEL_ONLY \
- (BASEP_MEM_PERMANENT_KERNEL_MAPPING | BASEP_MEM_NO_USER_FREE | \
-- BASE_MEM_FLAG_MAP_FIXED)
-+ BASE_MEM_FLAG_MAP_FIXED | BASEP_MEM_PERFORM_JIT_TRIM)
-
- /* A mask for all output bits, excluding IN/OUT bits.
- */
-@@ -192,6 +202,28 @@
- #define BASE_MEM_FIRST_FREE_ADDRESS ((BITS_PER_LONG << 12) + \
- BASE_MEM_COOKIE_BASE)
-
-+/* Similar to BASE_MEM_TILER_ALIGN_TOP, memory starting from the end of the
-+ * initial commit is aligned to 'extension' pages, where 'extension' must be a power
-+ * of 2 and no more than BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES
-+ */
-+#define BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP (1 << 0)
-+
-+/**
-+ * If set, the heap info address points to a __u32 holding the used size in bytes;
-+ * otherwise it points to a __u64 holding the lowest address of unused memory.
-+ */
-+#define BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE (1 << 1)
-+
-+/**
-+ * Valid set of just-in-time memory allocation flags
-+ *
-+ * Note: BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE cannot be set if heap_info_gpu_addr
-+ * in %base_jit_alloc_info is 0 (atom with BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE set
-+ * and heap_info_gpu_addr being 0 will be rejected).
-+ */
-+#define BASE_JIT_ALLOC_VALID_FLAGS \
-+ (BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP | BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE)
-+
- /**
- * typedef base_context_create_flags - Flags to pass to ::base_context_init.
- *
-@@ -200,7 +232,7 @@
- * These share the same space as BASEP_CONTEXT_FLAG_*, and so must
- * not collide with them.
- */
--typedef u32 base_context_create_flags;
-+typedef __u32 base_context_create_flags;
-
- /* No flags set */
- #define BASE_CONTEXT_CREATE_FLAG_NONE ((base_context_create_flags)0)
-@@ -290,7 +322,7 @@ typedef u32 base_context_create_flags;
- * @blob: per-job data array
- */
- struct base_jd_udata {
-- u64 blob[2];
-+ __u64 blob[2];
- };
-
- /**
-@@ -303,7 +335,7 @@ struct base_jd_udata {
- * When the flag is set for a particular dependency to signal that it is an
- * ordering only dependency then errors will not be propagated.
- */
--typedef u8 base_jd_dep_type;
-+typedef __u8 base_jd_dep_type;
-
- #define BASE_JD_DEP_TYPE_INVALID (0) /**< Invalid dependency */
- #define BASE_JD_DEP_TYPE_DATA (1U << 0) /**< Data dependency */
-@@ -319,7 +351,7 @@ typedef u8 base_jd_dep_type;
- * Special case is ::BASE_JD_REQ_DEP, which is used to express complex
- * dependencies, and that doesn't execute anything on the hardware.
- */
--typedef u32 base_jd_core_req;
-+typedef __u32 base_jd_core_req;
-
- /* Requirements that come from the HW */
-
-@@ -551,6 +583,13 @@ typedef u32 base_jd_core_req;
- */
- #define BASE_JD_REQ_END_RENDERPASS ((base_jd_core_req)1 << 19)
-
-+/* SW-only requirement: The atom needs to run on a limited core mask affinity.
-+ *
-+ * If this bit is set then the kbase_context.limited_core_mask will be applied
-+ * to the affinity.
-+ */
-+#define BASE_JD_REQ_LIMITED_CORE_MASK ((base_jd_core_req)1 << 20)
-+
- /* These requirement bits are currently unused in base_jd_core_req
- */
- #define BASEP_JD_REQ_RESERVED \
-@@ -561,7 +600,7 @@ typedef u32 base_jd_core_req;
- BASE_JD_REQ_FS_AFBC | BASE_JD_REQ_PERMON | \
- BASE_JD_REQ_SKIP_CACHE_START | BASE_JD_REQ_SKIP_CACHE_END | \
- BASE_JD_REQ_JOB_SLOT | BASE_JD_REQ_START_RENDERPASS | \
-- BASE_JD_REQ_END_RENDERPASS))
-+ BASE_JD_REQ_END_RENDERPASS | BASE_JD_REQ_LIMITED_CORE_MASK))
-
- /* Mask of all bits in base_jd_core_req that control the type of the atom.
- *
-@@ -606,7 +645,7 @@ enum kbase_jd_atom_state {
- /**
- * typedef base_atom_id - Type big enough to store an atom number in.
- */
--typedef u8 base_atom_id;
-+typedef __u8 base_atom_id;
-
- /**
- * struct base_dependency -
-@@ -669,10 +708,10 @@ struct base_dependency {
- * BASE_JD_REQ_END_RENDERPASS is set in the base_jd_core_req.
- */
- struct base_jd_fragment {
-- u64 norm_read_norm_write;
-- u64 norm_read_forced_write;
-- u64 forced_read_forced_write;
-- u64 forced_read_norm_write;
-+ __u64 norm_read_norm_write;
-+ __u64 norm_read_forced_write;
-+ __u64 forced_read_forced_write;
-+ __u64 forced_read_norm_write;
- };
-
- /**
-@@ -712,7 +751,7 @@ struct base_jd_fragment {
- * the same context. See KBASE_JS_SYSTEM_PRIORITY_MODE and
- * KBASE_JS_PROCESS_LOCAL_PRIORITY_MODE for more details.
- */
--typedef u8 base_jd_prio;
-+typedef __u8 base_jd_prio;
-
- /* Medium atom priority. This is a priority higher than BASE_JD_PRIO_LOW */
- #define BASE_JD_PRIO_MEDIUM ((base_jd_prio)0)
-@@ -722,11 +761,15 @@ typedef u8 base_jd_prio;
- #define BASE_JD_PRIO_HIGH ((base_jd_prio)1)
- /* Low atom priority. */
- #define BASE_JD_PRIO_LOW ((base_jd_prio)2)
-+/* Real-Time atom priority. This is a priority higher than BASE_JD_PRIO_HIGH,
-+ * BASE_JD_PRIO_MEDIUM, and BASE_JD_PRIO_LOW
-+ */
-+#define BASE_JD_PRIO_REALTIME ((base_jd_prio)3)
-
- /* Count of the number of priority levels. This itself is not a valid
- * base_jd_prio setting
- */
--#define BASE_JD_NR_PRIO_LEVELS 3
-+#define BASE_JD_NR_PRIO_LEVELS 4
-
- /**
- * struct base_jd_atom_v2 - Node of a dependency graph used to submit a
-@@ -759,34 +802,82 @@ typedef u8 base_jd_prio;
- * @padding: Unused. Must be zero.
- *
- * This structure has changed since UK 10.2 for which base_jd_core_req was a
-- * u16 value.
-+ * __u16 value.
- *
-- * In UK 10.3 a core_req field of a u32 type was added to the end of the
-- * structure, and the place in the structure previously occupied by u16
-+ * In UK 10.3 a core_req field of a __u32 type was added to the end of the
-+ * structure, and the place in the structure previously occupied by __u16
- * core_req was kept but renamed to compat_core_req.
- *
-- * From UK 11.20 - compat_core_req is now occupied by u8 jit_id[2].
-+ * From UK 11.20 - compat_core_req is now occupied by __u8 jit_id[2].
- * Compatibility with UK 10.x from UK 11.y is not handled because
- * the major version increase prevents this.
- *
- * For UK 11.20 jit_id[2] must be initialized to zero.
- */
- struct base_jd_atom_v2 {
-- u64 jc;
-+ __u64 jc;
- struct base_jd_udata udata;
-- u64 extres_list;
-- u16 nr_extres;
-- u8 jit_id[2];
-+ __u64 extres_list;
-+ __u16 nr_extres;
-+ __u8 jit_id[2];
- struct base_dependency pre_dep[2];
- base_atom_id atom_number;
- base_jd_prio prio;
-- u8 device_nr;
-- u8 jobslot;
-+ __u8 device_nr;
-+ __u8 jobslot;
- base_jd_core_req core_req;
-- u8 renderpass_id;
-- u8 padding[7];
-+ __u8 renderpass_id;
-+ __u8 padding[7];
- };
-
-+/**
-+ * struct base_jd_atom - Same as base_jd_atom_v2, but has an extra seq_nr
-+ * at the beginning.
-+ *
-+ * @seq_nr: Sequence number of logical grouping of atoms.
-+ * @jc: GPU address of a job chain or (if BASE_JD_REQ_END_RENDERPASS
-+ * is set in the base_jd_core_req) the CPU address of a
-+ * base_jd_fragment object.
-+ * @udata: User data.
-+ * @extres_list: List of external resources.
-+ * @nr_extres: Number of external resources or JIT allocations.
-+ * @jit_id: Zero-terminated array of IDs of just-in-time memory
-+ * allocations written to by the atom. When the atom
-+ * completes, the value stored at the
-+ * &struct_base_jit_alloc_info.heap_info_gpu_addr of
-+ * each allocation is read in order to enforce an
-+ * overall physical memory usage limit.
-+ * @pre_dep: Pre-dependencies. One need to use SETTER function to assign
-+ * this field; this is done in order to reduce possibility of
-+ * improper assignment of a dependency field.
-+ * @atom_number: Unique number to identify the atom.
-+ * @prio: Atom priority. Refer to base_jd_prio for more details.
-+ * @device_nr: Core group when BASE_JD_REQ_SPECIFIC_COHERENT_GROUP
-+ * specified.
-+ * @jobslot: Job slot to use when BASE_JD_REQ_JOB_SLOT is specified.
-+ * @core_req: Core requirements.
-+ * @renderpass_id: Renderpass identifier used to associate an atom that has
-+ * BASE_JD_REQ_START_RENDERPASS set in its core requirements
-+ * with an atom that has BASE_JD_REQ_END_RENDERPASS set.
-+ * @padding: Unused. Must be zero.
-+ */
-+typedef struct base_jd_atom {
-+ __u64 seq_nr;
-+ __u64 jc;
-+ struct base_jd_udata udata;
-+ __u64 extres_list;
-+ __u16 nr_extres;
-+ __u8 jit_id[2];
-+ struct base_dependency pre_dep[2];
-+ base_atom_id atom_number;
-+ base_jd_prio prio;
-+ __u8 device_nr;
-+ __u8 jobslot;
-+ base_jd_core_req core_req;
-+ __u8 renderpass_id;
-+ __u8 padding[7];
-+} base_jd_atom;
-+
- /* Job chain event code bits
- * Defines the bits used to create ::base_jd_event_code
- */
-@@ -834,6 +925,109 @@ enum {
- * Such codes are never returned to
- * user-space.
- * @BASE_JD_EVENT_RANGE_KERNEL_ONLY_END: End of kernel-only status codes.
-+ * @BASE_JD_EVENT_DONE: atom has completed successfull
-+ * @BASE_JD_EVENT_JOB_CONFIG_FAULT: Atom dependencies configuration error which
-+ * shall result in a failed atom
-+ * @BASE_JD_EVENT_JOB_POWER_FAULT: The job could not be executed because the
-+ * part of the memory system required to access
-+ * job descriptors was not powered on
-+ * @BASE_JD_EVENT_JOB_READ_FAULT: Reading a job descriptor into the Job
-+ * manager failed
-+ * @BASE_JD_EVENT_JOB_WRITE_FAULT: Writing a job descriptor from the Job
-+ * manager failed
-+ * @BASE_JD_EVENT_JOB_AFFINITY_FAULT: The job could not be executed because the
-+ * specified affinity mask does not intersect
-+ * any available cores
-+ * @BASE_JD_EVENT_JOB_BUS_FAULT: A bus access failed while executing a job
-+ * @BASE_JD_EVENT_INSTR_INVALID_PC: A shader instruction with an illegal program
-+ * counter was executed.
-+ * @BASE_JD_EVENT_INSTR_INVALID_ENC: A shader instruction with an illegal
-+ * encoding was executed.
-+ * @BASE_JD_EVENT_INSTR_TYPE_MISMATCH: A shader instruction was executed where
-+ * the instruction encoding did not match the
-+ * instruction type encoded in the program
-+ * counter.
-+ * @BASE_JD_EVENT_INSTR_OPERAND_FAULT: A shader instruction was executed that
-+ * contained invalid combinations of operands.
-+ * @BASE_JD_EVENT_INSTR_TLS_FAULT: A shader instruction was executed that tried
-+ * to access the thread local storage section
-+ * of another thread.
-+ * @BASE_JD_EVENT_INSTR_ALIGN_FAULT: A shader instruction was executed that
-+ * tried to do an unsupported unaligned memory
-+ * access.
-+ * @BASE_JD_EVENT_INSTR_BARRIER_FAULT: A shader instruction was executed that
-+ * failed to complete an instruction barrier.
-+ * @BASE_JD_EVENT_DATA_INVALID_FAULT: Any data structure read as part of the job
-+ * contains invalid combinations of data.
-+ * @BASE_JD_EVENT_TILE_RANGE_FAULT: Tile or fragment shading was asked to
-+ * process a tile that is entirely outside the
-+ * bounding box of the frame.
-+ * @BASE_JD_EVENT_STATE_FAULT: Matches ADDR_RANGE_FAULT. A virtual address
-+ * has been found that exceeds the virtual
-+ * address range.
-+ * @BASE_JD_EVENT_OUT_OF_MEMORY: The tiler ran out of memory when executing a job.
-+ * @BASE_JD_EVENT_UNKNOWN: If multiple jobs in a job chain fail, only
-+ * the first one the reports an error will set
-+ * and return full error information.
-+ * Subsequent failing jobs will not update the
-+ * error status registers, and may write an
-+ * error status of UNKNOWN.
-+ * @BASE_JD_EVENT_DELAYED_BUS_FAULT: The GPU received a bus fault for access to
-+ * physical memory where the original virtual
-+ * address is no longer available.
-+ * @BASE_JD_EVENT_SHAREABILITY_FAULT: Matches GPU_SHAREABILITY_FAULT. A cache
-+ * has detected that the same line has been
-+ * accessed as both shareable and non-shareable
-+ * memory from inside the GPU.
-+ * @BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL1: A memory access hit an invalid table
-+ * entry at level 1 of the translation table.
-+ * @BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL2: A memory access hit an invalid table
-+ * entry at level 2 of the translation table.
-+ * @BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL3: A memory access hit an invalid table
-+ * entry at level 3 of the translation table.
-+ * @BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL4: A memory access hit an invalid table
-+ * entry at level 4 of the translation table.
-+ * @BASE_JD_EVENT_PERMISSION_FAULT: A memory access could not be allowed due to
-+ * the permission flags set in translation
-+ * table
-+ * @BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL1: A bus fault occurred while reading
-+ * level 0 of the translation tables.
-+ * @BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL2: A bus fault occurred while reading
-+ * level 1 of the translation tables.
-+ * @BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL3: A bus fault occurred while reading
-+ * level 2 of the translation tables.
-+ * @BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL4: A bus fault occurred while reading
-+ * level 3 of the translation tables.
-+ * @BASE_JD_EVENT_ACCESS_FLAG: Matches ACCESS_FLAG_0. A memory access hit a
-+ * translation table entry with the ACCESS_FLAG
-+ * bit set to zero in level 0 of the
-+ * page table, and the DISABLE_AF_FAULT flag
-+ * was not set.
-+ * @BASE_JD_EVENT_MEM_GROWTH_FAILED: raised for JIT_ALLOC atoms that failed to
-+ * grow memory on demand
-+ * @BASE_JD_EVENT_JOB_CANCELLED: raised when this atom was hard-stopped or its
-+ * dependencies failed
-+ * @BASE_JD_EVENT_JOB_INVALID: raised for many reasons, including invalid data
-+ * in the atom which overlaps with
-+ * BASE_JD_EVENT_JOB_CONFIG_FAULT, or if the
-+ * platform doesn't support the feature specified in
-+ * the atom.
-+ * @BASE_JD_EVENT_PM_EVENT: TODO: remove as it's not used
-+ * @BASE_JD_EVENT_TIMED_OUT: TODO: remove as it's not used
-+ * @BASE_JD_EVENT_BAG_INVALID: TODO: remove as it's not used
-+ * @BASE_JD_EVENT_PROGRESS_REPORT: TODO: remove as it's not used
-+ * @BASE_JD_EVENT_BAG_DONE: TODO: remove as it's not used
-+ * @BASE_JD_EVENT_DRV_TERMINATED: this is a special event generated to indicate
-+ * to userspace that the KBase context has been
-+ * destroyed and Base should stop listening for
-+ * further events
-+ * @BASE_JD_EVENT_REMOVED_FROM_NEXT: raised when an atom that was configured in
-+ * the GPU has to be retried (but it has not
-+ * started) due to e.g., GPU reset
-+ * @BASE_JD_EVENT_END_RP_DONE: this is used for incremental rendering to signal
-+ * the completion of a renderpass. This value
-+ * shouldn't be returned to userspace but I haven't
-+ * seen where it is reset back to JD_EVENT_DONE.
- *
- * HW and low-level SW events are represented by event codes.
- * The status of jobs which succeeded are also represented by
-@@ -980,9 +1174,14 @@ struct base_jd_event_v2 {
- * struct base_dump_cpu_gpu_counters - Structure for
- * BASE_JD_REQ_SOFT_DUMP_CPU_GPU_COUNTERS
- * jobs.
-+ * @system_time: gpu timestamp
-+ * @cycle_counter: gpu cycle count
-+ * @sec: cpu time(sec)
-+ * @usec: cpu time(usec)
-+ * @padding: padding
- *
- * This structure is stored into the memory pointed to by the @jc field
-- * of &struct base_jd_atom_v2.
-+ * of &struct base_jd_atom.
- *
- * It must not occupy the same CPU cache line(s) as any neighboring data.
- * This is to avoid cases where access to pages containing the structure
-@@ -991,11 +1190,11 @@ struct base_jd_event_v2 {
- */
-
- struct base_dump_cpu_gpu_counters {
-- u64 system_time;
-- u64 cycle_counter;
-- u64 sec;
-- u32 usec;
-- u8 padding[36];
-+ __u64 system_time;
-+ __u64 cycle_counter;
-+ __u64 sec;
-+ __u32 usec;
-+ __u8 padding[36];
- };
-
--#endif /* _BASE_JM_KERNEL_H_ */
-+#endif /* _UAPI_BASE_JM_KERNEL_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_ioctl.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/jm/mali_kbase_jm_ioctl.h
-similarity index 57%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_ioctl.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/jm/mali_kbase_jm_ioctl.h
-index 408e98e..72d75cb 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/jm/mali_kbase_jm_ioctl.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/jm/mali_kbase_jm_ioctl.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifndef _KBASE_JM_IOCTL_H_
--#define _KBASE_JM_IOCTL_H_
-+#ifndef _UAPI_KBASE_JM_IOCTL_H_
-+#define _UAPI_KBASE_JM_IOCTL_H_
-
- #include <asm-generic/ioctl.h>
- #include <linux/types.h>
-@@ -94,16 +93,58 @@
- * - The above changes are checked for safe values in usual builds
- * 11.21:
- * - v2.0 of mali_trace debugfs file, which now versions the file separately
-+ * 11.22:
-+ * - Added base_jd_atom (v3), which is seq_nr + base_jd_atom_v2.
-+ * KBASE_IOCTL_JOB_SUBMIT supports both in parallel.
-+ * 11.23:
-+ * - Modified KBASE_IOCTL_MEM_COMMIT behavior to reject requests to modify
-+ * the physical memory backing of JIT allocations. This was not supposed
-+ * to be a valid use case, but it was allowed by the previous implementation.
-+ * 11.24:
-+ * - Added a sysfs file 'serialize_jobs' inside a new sub-directory
-+ * 'scheduling'.
-+ * 11.25:
-+ * - Enabled JIT pressure limit in base/kbase by default
-+ * 11.26
-+ * - Added kinstr_jm API
-+ * 11.27
-+ * - Backwards compatible extension to HWC ioctl.
-+ * 11.28:
-+ * - Added kernel side cache ops needed hint
-+ * 11.29:
-+ * - Reserve ioctl 52
-+ * 11.30:
-+ * - Add a new priority level BASE_JD_PRIO_REALTIME
-+ * - Add ioctl 54: This controls the priority setting.
-+ * 11.31:
-+ * - Added BASE_JD_REQ_LIMITED_CORE_MASK.
-+ * - Added ioctl 55: set_limited_core_count.
- */
- #define BASE_UK_VERSION_MAJOR 11
--#define BASE_UK_VERSION_MINOR 21
-+#define BASE_UK_VERSION_MINOR 31
-+
-+/**
-+ * struct kbase_ioctl_version_check - Check version compatibility between
-+ * kernel and userspace
-+ *
-+ * @major: Major version number
-+ * @minor: Minor version number
-+ */
-+struct kbase_ioctl_version_check {
-+ __u16 major;
-+ __u16 minor;
-+};
-+
-+#define KBASE_IOCTL_VERSION_CHECK \
-+ _IOWR(KBASE_IOCTL_TYPE, 0, struct kbase_ioctl_version_check)
-+
-
- /**
- * struct kbase_ioctl_job_submit - Submit jobs/atoms to the kernel
- *
-- * @addr: Memory address of an array of struct base_jd_atom_v2
-+ * @addr: Memory address of an array of struct base_jd_atom_v2 or v3
- * @nr_atoms: Number of entries in the array
-- * @stride: sizeof(struct base_jd_atom_v2)
-+ * @stride: sizeof(struct base_jd_atom_v2) or sizeof(struct base_jd_atom)
- */
- struct kbase_ioctl_job_submit {
- __u64 addr;
-@@ -132,5 +173,51 @@ struct kbase_ioctl_soft_event_update {
- #define KBASE_IOCTL_SOFT_EVENT_UPDATE \
- _IOW(KBASE_IOCTL_TYPE, 28, struct kbase_ioctl_soft_event_update)
-
-+/**
-+ * struct kbase_kinstr_jm_fd_out - Explains the compatibility information for
-+ * the `struct kbase_kinstr_jm_atom_state_change` structure returned from the
-+ * kernel
-+ *
-+ * @size: The size of the `struct kbase_kinstr_jm_atom_state_change`
-+ * @version: Represents a breaking change in the
-+ * `struct kbase_kinstr_jm_atom_state_change`
-+ * @padding: Explicit padding to get the structure up to 64bits. See
-+ * https://www.kernel.org/doc/Documentation/ioctl/botching-up-ioctls.rst
-+ *
-+ * The `struct kbase_kinstr_jm_atom_state_change` may have extra members at the
-+ * end of the structure that older user space might not understand. If the
-+ * `version` is the same, the structure is still compatible with newer kernels.
-+ * The `size` can be used to cast the opaque memory returned from the kernel.
-+ */
-+struct kbase_kinstr_jm_fd_out {
-+ __u16 size;
-+ __u8 version;
-+ __u8 padding[5];
-+};
-+
-+/**
-+ * struct kbase_kinstr_jm_fd_in - Options when creating the file descriptor
-+ *
-+ * @count: Number of atom states that can be stored in the kernel circular
-+ * buffer. Must be a power of two
-+ * @padding: Explicit padding to get the structure up to 64bits. See
-+ * https://www.kernel.org/doc/Documentation/ioctl/botching-up-ioctls.rst
-+ */
-+struct kbase_kinstr_jm_fd_in {
-+ __u16 count;
-+ __u8 padding[6];
-+};
-+
-+union kbase_kinstr_jm_fd {
-+ struct kbase_kinstr_jm_fd_in in;
-+ struct kbase_kinstr_jm_fd_out out;
-+};
-+
-+#define KBASE_IOCTL_KINSTR_JM_FD \
-+ _IOWR(KBASE_IOCTL_TYPE, 51, union kbase_kinstr_jm_fd)
-+
-+
-+#define KBASE_IOCTL_VERSION_CHECK_RESERVED \
-+ _IOWR(KBASE_IOCTL_TYPE, 52, struct kbase_ioctl_version_check)
-
--#endif /* _KBASE_JM_IOCTL_H_ */
-+#endif /* _UAPI_KBASE_JM_IOCTL_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_kernel.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_base_kernel.h
-similarity index 72%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/mali_base_kernel.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/mali_base_kernel.h
-index 1e2744d..a46c41f 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_kernel.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_base_kernel.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,48 +17,52 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /*
- * Base structures shared with the kernel.
- */
-
--#ifndef _BASE_KERNEL_H_
--#define _BASE_KERNEL_H_
-+#ifndef _UAPI_BASE_KERNEL_H_
-+#define _UAPI_BASE_KERNEL_H_
-+
-+#include <linux/types.h>
-
- struct base_mem_handle {
- struct {
-- u64 handle;
-+ __u64 handle;
- } basep;
- };
-
- #include "mali_base_mem_priv.h"
--#include "gpu/mali_kbase_gpu_coherency.h"
- #include "gpu/mali_kbase_gpu_id.h"
-+#include "gpu/mali_kbase_gpu_coherency.h"
-
- #define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 4
-
- #define BASE_MAX_COHERENT_GROUPS 16
-
--#if defined CDBG_ASSERT
-+#if defined(CDBG_ASSERT)
- #define LOCAL_ASSERT CDBG_ASSERT
--#elif defined KBASE_DEBUG_ASSERT
-+#elif defined(KBASE_DEBUG_ASSERT)
- #define LOCAL_ASSERT KBASE_DEBUG_ASSERT
- #else
-+#if defined(__KERNEL__)
- #error assert macro not defined!
-+#else
-+#define LOCAL_ASSERT(...) ((void)#__VA_ARGS__)
-+#endif
- #endif
-
- #if defined(PAGE_MASK) && defined(PAGE_SHIFT)
- #define LOCAL_PAGE_SHIFT PAGE_SHIFT
- #define LOCAL_PAGE_LSB ~PAGE_MASK
- #else
--#include <osu/mali_osu.h>
-+#ifndef OSU_CONFIG_CPU_PAGE_SIZE_LOG2
-+#define OSU_CONFIG_CPU_PAGE_SIZE_LOG2 12
-+#endif
-
--#if defined OSU_CONFIG_CPU_PAGE_SIZE_LOG2
-+#if defined(OSU_CONFIG_CPU_PAGE_SIZE_LOG2)
- #define LOCAL_PAGE_SHIFT OSU_CONFIG_CPU_PAGE_SIZE_LOG2
- #define LOCAL_PAGE_LSB ((1ul << OSU_CONFIG_CPU_PAGE_SIZE_LOG2) - 1)
- #else
-@@ -85,7 +90,7 @@ struct base_mem_handle {
- * 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;
-+typedef __u32 base_mem_alloc_flags;
-
- /* A mask for all the flags which are modifiable via the base_mem_set_flags
- * interface.
-@@ -121,7 +126,7 @@ typedef u32 base_mem_alloc_flags;
- */
- enum base_mem_import_type {
- BASE_MEM_IMPORT_TYPE_INVALID = 0,
-- /**
-+ /*
- * Import type with value 1 is deprecated.
- */
- BASE_MEM_IMPORT_TYPE_UMM = 2,
-@@ -138,8 +143,8 @@ enum base_mem_import_type {
- */
-
- struct base_mem_import_user_buffer {
-- u64 ptr;
-- u64 length;
-+ __u64 ptr;
-+ __u64 length;
- };
-
- /* Mask to detect 4GB boundary alignment */
-@@ -147,15 +152,15 @@ struct base_mem_import_user_buffer {
- /* Mask to detect 4GB boundary (in page units) alignment */
- #define BASE_MEM_PFN_MASK_4GB (BASE_MEM_MASK_4GB >> LOCAL_PAGE_SHIFT)
-
--/* Limit on the 'extent' parameter for an allocation with the
-+/* Limit on the 'extension' parameter for an allocation with the
- * BASE_MEM_TILER_ALIGN_TOP flag set
- *
- * This is the same as the maximum limit for a Buffer Descriptor's chunk size
- */
--#define BASE_MEM_TILER_ALIGN_TOP_EXTENT_MAX_PAGES_LOG2 \
-- (21u - (LOCAL_PAGE_SHIFT))
--#define BASE_MEM_TILER_ALIGN_TOP_EXTENT_MAX_PAGES \
-- (1ull << (BASE_MEM_TILER_ALIGN_TOP_EXTENT_MAX_PAGES_LOG2))
-+#define BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES_LOG2 \
-+ (21u - (LOCAL_PAGE_SHIFT))
-+#define BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES \
-+ (1ull << (BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES_LOG2))
-
- /* Bit mask of cookies used for for memory allocation setup */
- #define KBASE_COOKIE_MASK ~1UL /* bit 0 is reserved */
-@@ -163,7 +168,7 @@ struct base_mem_import_user_buffer {
- /* Maximum size allowed in a single KBASE_IOCTL_MEM_ALLOC call */
- #define KBASE_MEM_ALLOC_MAX_SIZE ((8ull << 30) >> PAGE_SHIFT) /* 8 GB */
-
--/**
-+/*
- * struct base_fence - Cross-device synchronisation fence.
- *
- * A fence is used to signal when the GPU has finished accessing a resource that
-@@ -200,8 +205,8 @@ struct base_fence {
- */
- struct base_mem_aliasing_info {
- struct base_mem_handle handle;
-- u64 offset;
-- u64 length;
-+ __u64 offset;
-+ __u64 length;
- };
-
- /* Maximum percentage of just-in-time memory allocation trimming to perform
-@@ -213,28 +218,6 @@ struct base_mem_aliasing_info {
- */
- #define BASE_JIT_ALLOC_COUNT (255)
-
--/* Similar to BASE_MEM_TILER_ALIGN_TOP, memory starting from the end of the
-- * initial commit is aligned to 'extent' pages, where 'extent' must be a power
-- * of 2 and no more than BASE_MEM_TILER_ALIGN_TOP_EXTENT_MAX_PAGES
-- */
--#define BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP (1 << 0)
--
--/**
-- * If set, the heap info address points to a u32 holding the used size in bytes;
-- * otherwise it points to a u64 holding the lowest address of unused memory.
-- */
--#define BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE (1 << 1)
--
--/**
-- * Valid set of just-in-time memory allocation flags
-- *
-- * Note: BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE cannot be set if heap_info_gpu_addr
-- * in %base_jit_alloc_info is 0 (atom with BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE set
-- * and heap_info_gpu_addr being 0 will be rejected).
-- */
--#define BASE_JIT_ALLOC_VALID_FLAGS \
-- (BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP | BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE)
--
- /* base_jit_alloc_info in use for kernel driver versions 10.2 to early 11.5
- *
- * jit_version is 1
-@@ -245,11 +228,11 @@ struct base_mem_aliasing_info {
- * An array of structures was not supported
- */
- struct base_jit_alloc_info_10_2 {
-- u64 gpu_alloc_addr;
-- u64 va_pages;
-- u64 commit_pages;
-- u64 extent;
-- u8 id;
-+ __u64 gpu_alloc_addr;
-+ __u64 va_pages;
-+ __u64 commit_pages;
-+ __u64 extension;
-+ __u8 id;
- };
-
- /* base_jit_alloc_info introduced by kernel driver version 11.5, and in use up
-@@ -272,16 +255,16 @@ struct base_jit_alloc_info_10_2 {
- * 11.10: Arrays of this structure are supported
- */
- struct base_jit_alloc_info_11_5 {
-- u64 gpu_alloc_addr;
-- u64 va_pages;
-- u64 commit_pages;
-- u64 extent;
-- u8 id;
-- u8 bin_id;
-- u8 max_allocations;
-- u8 flags;
-- u8 padding[2];
-- u16 usage_id;
-+ __u64 gpu_alloc_addr;
-+ __u64 va_pages;
-+ __u64 commit_pages;
-+ __u64 extension;
-+ __u8 id;
-+ __u8 bin_id;
-+ __u8 max_allocations;
-+ __u8 flags;
-+ __u8 padding[2];
-+ __u16 usage_id;
- };
-
- /**
-@@ -292,7 +275,7 @@ struct base_jit_alloc_info_11_5 {
- * @va_pages: The minimum number of virtual pages required.
- * @commit_pages: The minimum number of physical pages which
- * should back the allocation.
-- * @extent: Granularity of physical pages to grow the
-+ * @extension: Granularity of physical pages to grow the
- * allocation by during a fault.
- * @id: Unique ID provided by the caller, this is used
- * to pair allocation and free requests.
-@@ -327,17 +310,17 @@ struct base_jit_alloc_info_11_5 {
- * 11.20: added @heap_info_gpu_addr
- */
- struct base_jit_alloc_info {
-- u64 gpu_alloc_addr;
-- u64 va_pages;
-- u64 commit_pages;
-- u64 extent;
-- u8 id;
-- u8 bin_id;
-- u8 max_allocations;
-- u8 flags;
-- u8 padding[2];
-- u16 usage_id;
-- u64 heap_info_gpu_addr;
-+ __u64 gpu_alloc_addr;
-+ __u64 va_pages;
-+ __u64 commit_pages;
-+ __u64 extension;
-+ __u8 id;
-+ __u8 bin_id;
-+ __u8 max_allocations;
-+ __u8 flags;
-+ __u8 padding[2];
-+ __u16 usage_id;
-+ __u64 heap_info_gpu_addr;
- };
-
- enum base_external_resource_access {
-@@ -346,7 +329,7 @@ enum base_external_resource_access {
- };
-
- struct base_external_resource {
-- u64 ext_resource;
-+ __u64 ext_resource;
- };
-
-
-@@ -364,13 +347,13 @@ struct base_external_resource {
- * sized at allocation time.
- */
- struct base_external_resource_list {
-- u64 count;
-+ __u64 count;
- struct base_external_resource ext_res[1];
- };
-
- struct base_jd_debug_copy_buffer {
-- u64 address;
-- u64 size;
-+ __u64 address;
-+ __u64 size;
- struct base_external_resource extres;
- };
-
-@@ -482,7 +465,7 @@ struct base_jd_debug_copy_buffer {
- * population count, since faulty cores may be disabled during production,
- * producing a non-contiguous mask.
- *
-- * The memory requirements for this algorithm can be determined either by a u64
-+ * The memory requirements for this algorithm can be determined either by a __u64
- * population count on the L2_PRESENT mask (a LUT helper already is
- * required for the above), or simple assumption that there can be no more than
- * 16 coherent groups, since core groups are typically 4 cores.
-@@ -491,165 +474,170 @@ struct base_jd_debug_copy_buffer {
- #define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 4
-
- #define BASE_MAX_COHERENT_GROUPS 16
--
-+/**
-+ * struct mali_base_gpu_core_props - GPU core props info
-+ * @product_id: Pro specific value.
-+ * @version_status: 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).
-+ * @minor_revision: Minor release number of the GPU. "P" part of an "RnPn"
-+ * release number.
-+ * 8 bit values (0-255).
-+ * @major_revision: Major release number of the GPU. "R" part of an "RnPn"
-+ * release number.
-+ * 4 bit values (0-15).
-+ * @padding: padding to allign to 8-byte
-+ * @gpu_freq_khz_max: The maximum GPU frequency. Reported to applications by
-+ * clGetDeviceInfo()
-+ * @log2_program_counter_size: Size of the shader program counter, in bits.
-+ * @texture_features: 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.
-+ * @gpu_available_memory_size: 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.
-+ * @num_exec_engines: The number of execution engines.
-+ */
- struct mali_base_gpu_core_props {
-- /**
-- * Product specific value.
-- */
-- u32 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;
--
-- /* The maximum GPU frequency. Reported to applications by
-- * clGetDeviceInfo()
-- */
-- u32 gpu_freq_khz_max;
--
-- /**
-- * 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;
--
-- /**
-- * The number of execution engines.
-- */
-- u8 num_exec_engines;
-+ __u32 product_id;
-+ __u16 version_status;
-+ __u16 minor_revision;
-+ __u16 major_revision;
-+ __u16 padding;
-+ __u32 gpu_freq_khz_max;
-+ __u32 log2_program_counter_size;
-+ __u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS];
-+ __u64 gpu_available_memory_size;
-+ __u8 num_exec_engines;
- };
-
--/**
-- *
-+/*
- * 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];
-+ __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_tiler_props {
-- u32 bin_size_bytes; /* Max is 4*2^15 */
-- u32 max_active_levels; /* Max is 2^15 */
-+ __u32 bin_size_bytes; /* Max is 4*2^15 */
-+ __u32 max_active_levels; /* Max is 2^15 */
- };
-
- /**
-- * GPU threading system details.
-+ * struct mali_base_gpu_thread_props - GPU threading system details.
-+ * @max_threads: Max. number of threads per core
-+ * @max_workgroup_size: Max. number of threads per workgroup
-+ * @max_barrier_size: Max. number of threads that can synchronize on a
-+ * simple barrier
-+ * @max_registers: Total size [1..65535] of the register file available
-+ * per core.
-+ * @max_task_queue: Max. tasks [1..255] which may be sent to a core
-+ * before it becomes blocked.
-+ * @max_thread_group_split: Max. allowed value [1..15] of the Thread Group Split
-+ * field.
-+ * @impl_tech: 0 = Not specified, 1 = Silicon, 2 = FPGA,
-+ * 3 = SW Model/Emulation
-+ * @padding: padding to allign to 8-byte
-+ * @tls_alloc: Number of threads per core that TLS must be
-+ * allocated for
- */
- struct mali_base_gpu_thread_props {
-- u32 max_threads; /* Max. number of threads per core */
-- u32 max_workgroup_size; /* Max. number of threads per workgroup */
-- u32 max_barrier_size; /* Max. number of threads that can synchronize on a simple barrier */
-- 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; /* 0 = Not specified, 1 = Silicon, 2 = FPGA, 3 = SW Model/Emulation */
-- u8 padding[3];
-- u32 tls_alloc; /* Number of threads per core that TLS must
-- * be allocated for
-- */
-+ __u32 max_threads;
-+ __u32 max_workgroup_size;
-+ __u32 max_barrier_size;
-+ __u16 max_registers;
-+ __u8 max_task_queue;
-+ __u8 max_thread_group_split;
-+ __u8 impl_tech;
-+ __u8 padding[3];
-+ __u32 tls_alloc;
- };
-
- /**
- * struct mali_base_gpu_coherent_group - descriptor for a coherent group
-+ * @core_mask: Core restriction mask required for the group
-+ * @num_cores: Number of cores in the group
-+ * @padding: padding to allign to 8-byte
- *
- * \c core_mask exposes all cores in that coherent group, and \c num_cores
-- * provides a cached population-count for that mask.
-+ * 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 Power policy.
-+ * the application, depending on the Kernel Power policy.
- *
-- * @note if u64s must be 8-byte aligned, then this structure has 32-bits of wastage.
-+ * @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];
-+ __u64 core_mask;
-+ __u16 num_cores;
-+ __u16 padding[3];
- };
-
- /**
- * struct mali_base_gpu_coherent_group_info - Coherency group information
-+ * @num_groups: Number of coherent groups in the GPU.
-+ * @num_core_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.
-+ * @coherency: Coherency features of the memory, accessed by gpu_mem_features
-+ * methods
-+ * @padding: padding to allign to 8-byte
-+ * @group: Descriptors of coherent groups
- *
- * 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
-+ * 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 gpu_mem_features
-- * methods
-- */
-- u32 coherency;
--
-- u32 padding;
--
-- /**
-- * Descriptors of coherent groups
-- */
-+ __u32 num_groups;
-+ __u32 num_core_groups;
-+ __u32 coherency;
-+ __u32 padding;
- struct mali_base_gpu_coherent_group group[BASE_MAX_COHERENT_GROUPS];
- };
-
- /**
- * struct gpu_raw_gpu_props - A complete description of the GPU's Hardware
- * Configuration Discovery registers.
-+ * @shader_present: Shader core present bitmap
-+ * @tiler_present: Tiler core present bitmap
-+ * @l2_present: Level 2 cache present bitmap
-+ * @stack_present: Core stack present bitmap
-+ * @l2_features: L2 features
-+ * @core_features: Core features
-+ * @mem_features: Mem features
-+ * @mmu_features: Mmu features
-+ * @as_present: Bitmap of address spaces present
-+ * @js_present: Job slots present
-+ * @js_features: Array of job slot features.
-+ * @tiler_features: Tiler features
-+ * @texture_features: TEXTURE_FEATURES_x registers, as exposed by the GPU
-+ * @gpu_id: GPU and revision identifier
-+ * @thread_max_threads: Maximum number of threads per core
-+ * @thread_max_workgroup_size: Maximum number of threads per workgroup
-+ * @thread_max_barrier_size: Maximum number of threads per barrier
-+ * @thread_features: Thread features
-+ * @coherency_mode: Note: This is the _selected_ coherency mode rather than the
-+ * available modes as exposed in the coherency_features register
-+ * @thread_tls_alloc: Number of threads per core that TLS must be allocated for
-+ * @gpu_features: GPU features
- *
- * The information is presented inefficiently for access. For frequent access,
- * the values should be better expressed in an unpacked form in the
-@@ -664,62 +652,69 @@ struct mali_base_gpu_coherent_group_info {
- *
- */
- struct gpu_raw_gpu_props {
-- u64 shader_present;
-- u64 tiler_present;
-- u64 l2_present;
-- u64 stack_present;
-+ __u64 shader_present;
-+ __u64 tiler_present;
-+ __u64 l2_present;
-+ __u64 stack_present;
-+ __u32 l2_features;
-+ __u32 core_features;
-+ __u32 mem_features;
-+ __u32 mmu_features;
-
-- u32 l2_features;
-- u32 core_features;
-- u32 mem_features;
-- u32 mmu_features;
-+ __u32 as_present;
-
-- u32 as_present;
-+ __u32 js_present;
-+ __u32 js_features[GPU_MAX_JOB_SLOTS];
-+ __u32 tiler_features;
-+ __u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS];
-
-- u32 js_present;
-- u32 js_features[GPU_MAX_JOB_SLOTS];
-- u32 tiler_features;
-- u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS];
-+ __u32 gpu_id;
-
-- u32 gpu_id;
--
-- u32 thread_max_threads;
-- u32 thread_max_workgroup_size;
-- u32 thread_max_barrier_size;
-- u32 thread_features;
-+ __u32 thread_max_threads;
-+ __u32 thread_max_workgroup_size;
-+ __u32 thread_max_barrier_size;
-+ __u32 thread_features;
-
- /*
- * Note: This is the _selected_ coherency mode rather than the
- * available modes as exposed in the coherency_features register.
- */
-- u32 coherency_mode;
-+ __u32 coherency_mode;
-
-- u32 thread_tls_alloc;
-+ __u32 thread_tls_alloc;
-+ __u64 gpu_features;
- };
-
- /**
- * struct base_gpu_props - Return structure for base_get_gpu_props().
-+ * @core_props: Core props.
-+ * @l2_props: L2 props.
-+ * @unused_1: Keep for backwards compatibility.
-+ * @tiler_props: Tiler props.
-+ * @thread_props: Thread props.
-+ * @raw_props: This member is large, likely to be 128 bytes.
-+ * @coherency_info: This must be last member of the structure.
- *
- * NOTE: the raw_props member in this data structure contains the register
- * values from which the value of the other members are derived. The derived
- * members exist to allow for efficient access and/or shielding the details
- * of the layout of the registers.
-- *
-- * @unused_1: Keep for backwards compatibility.
-- * @raw_props: This member is large, likely to be 128 bytes.
-- * @coherency_info: This must be last member of the structure.
-- */
-+ * */
- struct base_gpu_props {
- struct mali_base_gpu_core_props core_props;
- struct mali_base_gpu_l2_cache_props l2_props;
-- u64 unused_1;
-+ __u64 unused_1;
- struct mali_base_gpu_tiler_props tiler_props;
- struct mali_base_gpu_thread_props thread_props;
- struct gpu_raw_gpu_props raw_props;
- struct mali_base_gpu_coherent_group_info coherency_info;
- };
-
-+#if MALI_USE_CSF
-+#include "csf/mali_base_csf_kernel.h"
-+#else
- #include "jm/mali_base_jm_kernel.h"
-+#endif
-
- /**
- * base_mem_group_id_get() - Get group ID from flags
-@@ -730,7 +725,7 @@ struct base_gpu_props {
- *
- * Return: group ID(0~15) extracted from the parameter
- */
--static inline int base_mem_group_id_get(base_mem_alloc_flags flags)
-+static __inline__ int base_mem_group_id_get(base_mem_alloc_flags flags)
- {
- LOCAL_ASSERT((flags & ~BASE_MEM_FLAGS_INPUT_MASK) == 0);
- return (int)((flags & BASE_MEM_GROUP_ID_MASK) >>
-@@ -749,10 +744,12 @@ static inline int base_mem_group_id_get(base_mem_alloc_flags flags)
- * The return value can be combined with other flags against base_mem_alloc
- * to identify a specific memory group.
- */
--static inline base_mem_alloc_flags base_mem_group_id_set(int id)
-+static __inline__ base_mem_alloc_flags base_mem_group_id_set(int id)
- {
-- LOCAL_ASSERT(id >= 0);
-- LOCAL_ASSERT(id < BASE_MEM_GROUP_COUNT);
-+ if ((id < 0) || (id >= BASE_MEM_GROUP_COUNT)) {
-+ /* Set to default value when id is out of range. */
-+ id = BASE_MEM_GROUP_DEFAULT;
-+ }
-
- return ((base_mem_alloc_flags)id << BASEP_MEM_GROUP_ID_SHIFT) &
- BASE_MEM_GROUP_ID_MASK;
-@@ -768,7 +765,7 @@ static inline base_mem_alloc_flags base_mem_group_id_set(int id)
- *
- * Return: Bitmask of flags to pass to base_context_init.
- */
--static inline base_context_create_flags base_context_mmu_group_id_set(
-+static __inline__ base_context_create_flags base_context_mmu_group_id_set(
- int const group_id)
- {
- LOCAL_ASSERT(group_id >= 0);
-@@ -788,7 +785,7 @@ static inline base_context_create_flags base_context_mmu_group_id_set(
- *
- * Return: Physical memory group ID. Valid range is 0..(BASE_MEM_GROUP_COUNT-1).
- */
--static inline int base_context_mmu_group_id_get(
-+static __inline__ int base_context_mmu_group_id_get(
- base_context_create_flags const flags)
- {
- LOCAL_ASSERT(flags == (flags & BASEP_CONTEXT_CREATE_ALLOWED_FLAGS));
-@@ -820,4 +817,10 @@ static inline int base_context_mmu_group_id_get(
- BASE_TIMEINFO_KERNEL_SOURCE_FLAG | \
- BASE_TIMEINFO_USER_SOURCE_FLAG)
-
--#endif /* _BASE_KERNEL_H_ */
-+/* Maximum number of source allocations allowed to create an alias allocation.
-+ * This needs to be 4096 * 6 to allow cube map arrays with up to 4096 array
-+ * layers, since each cube map in the array will have 6 faces.
-+ */
-+#define BASE_MEM_ALIAS_MAX_ENTS ((size_t)24576)
-+
-+#endif /* _UAPI_BASE_KERNEL_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_mem_priv.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_base_mem_priv.h
-similarity index 80%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/mali_base_mem_priv.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/mali_base_mem_priv.h
-index 844a025..304a334 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_base_mem_priv.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_base_mem_priv.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010-2015, 2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010-2015, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,14 +17,14 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
-+#ifndef _UAPI_BASE_MEM_PRIV_H_
-+#define _UAPI_BASE_MEM_PRIV_H_
-
-+#include <linux/types.h>
-
--#ifndef _BASE_MEM_PRIV_H_
--#define _BASE_MEM_PRIV_H_
-+#include "mali_base_kernel.h"
-
- #define BASE_SYNCSET_OP_MSYNC (1U << 0)
- #define BASE_SYNCSET_OP_CSYNC (1U << 1)
-@@ -48,10 +49,10 @@
- */
- struct basep_syncset {
- struct base_mem_handle mem_handle;
-- u64 user_addr;
-- u64 size;
-- u8 type;
-- u8 padding[7];
-+ __u64 user_addr;
-+ __u64 size;
-+ __u8 type;
-+ __u8 padding[7];
- };
-
--#endif
-+#endif /* _UAPI_BASE_MEM_PRIV_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_reader.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_hwcnt_reader.h
-similarity index 52%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_reader.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_hwcnt_reader.h
-index 10706b8..9baaec1 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_hwcnt_reader.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_hwcnt_reader.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2015 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2015, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,38 +17,59 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifndef _KBASE_HWCNT_READER_H_
--#define _KBASE_HWCNT_READER_H_
-+#ifndef _UAPI_KBASE_HWCNT_READER_H_
-+#define _UAPI_KBASE_HWCNT_READER_H_
-+
-+#include <stddef.h>
-+#include <linux/types.h>
-
- /* The ids of ioctl commands. */
- #define KBASE_HWCNT_READER 0xBE
--#define KBASE_HWCNT_READER_GET_HWVER _IOR(KBASE_HWCNT_READER, 0x00, u32)
--#define KBASE_HWCNT_READER_GET_BUFFER_SIZE _IOR(KBASE_HWCNT_READER, 0x01, u32)
--#define KBASE_HWCNT_READER_DUMP _IOW(KBASE_HWCNT_READER, 0x10, u32)
--#define KBASE_HWCNT_READER_CLEAR _IOW(KBASE_HWCNT_READER, 0x11, u32)
--#define KBASE_HWCNT_READER_GET_BUFFER _IOR(KBASE_HWCNT_READER, 0x20,\
-+#define KBASE_HWCNT_READER_GET_HWVER _IOR(KBASE_HWCNT_READER, 0x00, __u32)
-+#define KBASE_HWCNT_READER_GET_BUFFER_SIZE _IOR(KBASE_HWCNT_READER, 0x01, __u32)
-+#define KBASE_HWCNT_READER_DUMP _IOW(KBASE_HWCNT_READER, 0x10, __u32)
-+#define KBASE_HWCNT_READER_CLEAR _IOW(KBASE_HWCNT_READER, 0x11, __u32)
-+#define KBASE_HWCNT_READER_GET_BUFFER _IOC(_IOC_READ, KBASE_HWCNT_READER, 0x20,\
-+ offsetof(struct kbase_hwcnt_reader_metadata, cycles))
-+#define KBASE_HWCNT_READER_GET_BUFFER_WITH_CYCLES _IOR(KBASE_HWCNT_READER, 0x20,\
- struct kbase_hwcnt_reader_metadata)
--#define KBASE_HWCNT_READER_PUT_BUFFER _IOW(KBASE_HWCNT_READER, 0x21,\
-+#define KBASE_HWCNT_READER_PUT_BUFFER _IOC(_IOC_WRITE, KBASE_HWCNT_READER, 0x21,\
-+ offsetof(struct kbase_hwcnt_reader_metadata, cycles))
-+#define KBASE_HWCNT_READER_PUT_BUFFER_WITH_CYCLES _IOW(KBASE_HWCNT_READER, 0x21,\
- struct kbase_hwcnt_reader_metadata)
--#define KBASE_HWCNT_READER_SET_INTERVAL _IOW(KBASE_HWCNT_READER, 0x30, u32)
--#define KBASE_HWCNT_READER_ENABLE_EVENT _IOW(KBASE_HWCNT_READER, 0x40, u32)
--#define KBASE_HWCNT_READER_DISABLE_EVENT _IOW(KBASE_HWCNT_READER, 0x41, u32)
--#define KBASE_HWCNT_READER_GET_API_VERSION _IOW(KBASE_HWCNT_READER, 0xFF, u32)
-+#define KBASE_HWCNT_READER_SET_INTERVAL _IOW(KBASE_HWCNT_READER, 0x30, __u32)
-+#define KBASE_HWCNT_READER_ENABLE_EVENT _IOW(KBASE_HWCNT_READER, 0x40, __u32)
-+#define KBASE_HWCNT_READER_DISABLE_EVENT _IOW(KBASE_HWCNT_READER, 0x41, __u32)
-+#define KBASE_HWCNT_READER_GET_API_VERSION _IOW(KBASE_HWCNT_READER, 0xFF, __u32)
-+#define KBASE_HWCNT_READER_GET_API_VERSION_WITH_FEATURES \
-+ _IOW(KBASE_HWCNT_READER, 0xFF, \
-+ struct kbase_hwcnt_reader_api_version)
-+
-+/**
-+ * struct kbase_hwcnt_reader_metadata_cycles - GPU clock cycles
-+ * @top: the number of cycles associated with the main clock for the
-+ * GPU
-+ * @shader_cores: the cycles that have elapsed on the GPU shader cores
-+ */
-+struct kbase_hwcnt_reader_metadata_cycles {
-+ __u64 top;
-+ __u64 shader_cores;
-+};
-
- /**
- * struct kbase_hwcnt_reader_metadata - hwcnt reader sample buffer metadata
- * @timestamp: time when sample was collected
- * @event_id: id of an event that triggered sample collection
- * @buffer_idx: position in sampling area where sample buffer was stored
-+ * @cycles: the GPU cycles that occurred since the last sample
- */
- struct kbase_hwcnt_reader_metadata {
-- u64 timestamp;
-- u32 event_id;
-- u32 buffer_idx;
-+ __u64 timestamp;
-+ __u32 event_id;
-+ __u32 buffer_idx;
-+ struct kbase_hwcnt_reader_metadata_cycles cycles;
- };
-
- /**
-@@ -63,9 +85,21 @@ enum base_hwcnt_reader_event {
- BASE_HWCNT_READER_EVENT_PERIODIC,
- BASE_HWCNT_READER_EVENT_PREJOB,
- BASE_HWCNT_READER_EVENT_POSTJOB,
--
- BASE_HWCNT_READER_EVENT_COUNT
- };
-
--#endif /* _KBASE_HWCNT_READER_H_ */
-+#define KBASE_HWCNT_READER_API_VERSION_NO_FEATURE (0)
-+#define KBASE_HWCNT_READER_API_VERSION_FEATURE_CYCLES_TOP (1 << 0)
-+#define KBASE_HWCNT_READER_API_VERSION_FEATURE_CYCLES_SHADER_CORES (1 << 1)
-+/**
-+ * struct kbase_hwcnt_reader_api_version - hwcnt reader API version
-+ * @version: API version
-+ * @features: available features in this API version
-+ */
-+struct kbase_hwcnt_reader_api_version {
-+ __u32 version;
-+ __u32 features;
-+};
-+
-+#endif /* _UAPI_KBASE_HWCNT_READER_H_ */
-
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ioctl.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_ioctl.h
-similarity index 83%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ioctl.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_ioctl.h
-index 977b194..29ff32a 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_ioctl.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_ioctl.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2017-2020 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2017-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,12 +17,10 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--#ifndef _KBASE_IOCTL_H_
--#define _KBASE_IOCTL_H_
-+#ifndef _UAPI_KBASE_IOCTL_H_
-+#define _UAPI_KBASE_IOCTL_H_
-
- #ifdef __cpluscplus
- extern "C" {
-@@ -30,24 +29,14 @@ extern "C" {
- #include <asm-generic/ioctl.h>
- #include <linux/types.h>
-
-+#if MALI_USE_CSF
-+#include "csf/mali_kbase_csf_ioctl.h"
-+#else
- #include "jm/mali_kbase_jm_ioctl.h"
-+#endif /* MALI_USE_CSF */
-
- #define KBASE_IOCTL_TYPE 0x80
-
--/**
-- * struct kbase_ioctl_version_check - Check version compatibility with kernel
-- *
-- * @major: Major version number
-- * @minor: Minor version number
-- */
--struct kbase_ioctl_version_check {
-- __u16 major;
-- __u16 minor;
--};
--
--#define KBASE_IOCTL_VERSION_CHECK \
-- _IOWR(KBASE_IOCTL_TYPE, 0, struct kbase_ioctl_version_check)
--
- /**
- * struct kbase_ioctl_set_flags - Set kernel context creation flags
- *
-@@ -75,16 +64,16 @@ struct kbase_ioctl_set_flags {
- * @flags may be used in the future to request a different format for the
- * buffer. With @flags == 0 the following format is used.
- *
-- * The buffer will be filled with pairs of values, a u32 key identifying the
-+ * The buffer will be filled with pairs of values, a __u32 key identifying the
- * property followed by the value. The size of the value is identified using
- * the bottom bits of the key. The value then immediately followed the key and
- * is tightly packed (there is no padding). All keys and values are
- * little-endian.
- *
-- * 00 = u8
-- * 01 = u16
-- * 10 = u32
-- * 11 = u64
-+ * 00 = __u8
-+ * 01 = __u16
-+ * 10 = __u32
-+ * 11 = __u64
- */
- struct kbase_ioctl_get_gpuprops {
- __u64 buffer;
-@@ -97,22 +86,20 @@ struct kbase_ioctl_get_gpuprops {
-
- /**
- * union kbase_ioctl_mem_alloc - Allocate memory on the GPU
-- *
-- * @va_pages: The number of pages of virtual address space to reserve
-- * @commit_pages: The number of physical pages to allocate
-- * @extent: The number of extra pages to allocate on each GPU fault which grows
-- * the region
-- * @flags: Flags
-- * @gpu_va: The GPU virtual address which is allocated
-- *
- * @in: Input parameters
-+ * @in.va_pages: The number of pages of virtual address space to reserve
-+ * @in.commit_pages: The number of physical pages to allocate
-+ * @in.extension: The number of extra pages to allocate on each GPU fault which grows the region
-+ * @in.flags: Flags
- * @out: Output parameters
-+ * @out.flags: Flags
-+ * @out.gpu_va: The GPU virtual address which is allocated
- */
- union kbase_ioctl_mem_alloc {
- struct {
- __u64 va_pages;
- __u64 commit_pages;
-- __u64 extent;
-+ __u64 extension;
- __u64 flags;
- } in;
- struct {
-@@ -126,14 +113,13 @@ union kbase_ioctl_mem_alloc {
-
- /**
- * struct kbase_ioctl_mem_query - Query properties of a GPU memory region
-- * @gpu_addr: A GPU address contained within the region
-- * @query: The type of query
-- * @value: The result of the query
-- *
-- * Use a %KBASE_MEM_QUERY_xxx flag as input for @query.
-- *
- * @in: Input parameters
-+ * @in.gpu_addr: A GPU address contained within the region
-+ * @in.query: The type of query
- * @out: Output parameters
-+ * @out.value: The result of the query
-+ *
-+ * Use a %KBASE_MEM_QUERY_xxx flag as input for @query.
- */
- union kbase_ioctl_mem_query {
- struct {
-@@ -148,9 +134,9 @@ union kbase_ioctl_mem_query {
- #define KBASE_IOCTL_MEM_QUERY \
- _IOWR(KBASE_IOCTL_TYPE, 6, union kbase_ioctl_mem_query)
-
--#define KBASE_MEM_QUERY_COMMIT_SIZE ((u64)1)
--#define KBASE_MEM_QUERY_VA_SIZE ((u64)2)
--#define KBASE_MEM_QUERY_FLAGS ((u64)3)
-+#define KBASE_MEM_QUERY_COMMIT_SIZE ((__u64)1)
-+#define KBASE_MEM_QUERY_VA_SIZE ((__u64)2)
-+#define KBASE_MEM_QUERY_FLAGS ((__u64)3)
-
- /**
- * struct kbase_ioctl_mem_free - Free a memory region
-@@ -166,7 +152,7 @@ struct kbase_ioctl_mem_free {
- /**
- * struct kbase_ioctl_hwcnt_reader_setup - Setup HWC dumper/reader
- * @buffer_count: requested number of dumping buffers
-- * @jm_bm: counters selection bitmask (JM)
-+ * @fe_bm: counters selection bitmask (Front end)
- * @shader_bm: counters selection bitmask (Shader)
- * @tiler_bm: counters selection bitmask (Tiler)
- * @mmu_l2_bm: counters selection bitmask (MMU_L2)
-@@ -175,7 +161,7 @@ struct kbase_ioctl_mem_free {
- */
- struct kbase_ioctl_hwcnt_reader_setup {
- __u32 buffer_count;
-- __u32 jm_bm;
-+ __u32 fe_bm;
- __u32 shader_bm;
- __u32 tiler_bm;
- __u32 mmu_l2_bm;
-@@ -187,14 +173,14 @@ struct kbase_ioctl_hwcnt_reader_setup {
- /**
- * struct kbase_ioctl_hwcnt_enable - Enable hardware counter collection
- * @dump_buffer: GPU address to write counters to
-- * @jm_bm: counters selection bitmask (JM)
-+ * @fe_bm: counters selection bitmask (Front end)
- * @shader_bm: counters selection bitmask (Shader)
- * @tiler_bm: counters selection bitmask (Tiler)
- * @mmu_l2_bm: counters selection bitmask (MMU_L2)
- */
- struct kbase_ioctl_hwcnt_enable {
- __u64 dump_buffer;
-- __u32 jm_bm;
-+ __u32 fe_bm;
- __u32 shader_bm;
- __u32 tiler_bm;
- __u32 mmu_l2_bm;
-@@ -353,13 +339,12 @@ struct kbase_ioctl_mem_sync {
- /**
- * union kbase_ioctl_mem_find_cpu_offset - Find the offset of a CPU pointer
- *
-- * @gpu_addr: The GPU address of the memory region
-- * @cpu_addr: The CPU address to locate
-- * @size: A size in bytes to validate is contained within the region
-- * @offset: The offset from the start of the memory region to @cpu_addr
-- *
- * @in: Input parameters
-+ * @in.gpu_addr: The GPU address of the memory region
-+ * @in.cpu_addr: The CPU address to locate
-+ * @in.size: A size in bytes to validate is contained within the region
- * @out: Output parameters
-+ * @out.offset: The offset from the start of the memory region to @cpu_addr
- */
- union kbase_ioctl_mem_find_cpu_offset {
- struct {
-@@ -424,15 +409,15 @@ struct kbase_ioctl_mem_commit {
-
- /**
- * union kbase_ioctl_mem_alias - Create an alias of memory regions
-- * @flags: Flags, see BASE_MEM_xxx
-- * @stride: Bytes between start of each memory region
-- * @nents: The number of regions to pack together into the alias
-- * @aliasing_info: Pointer to an array of struct base_mem_aliasing_info
-- * @gpu_va: Address of the new alias
-- * @va_pages: Size of the new alias
-- *
- * @in: Input parameters
-+ * @in.flags: Flags, see BASE_MEM_xxx
-+ * @in.stride: Bytes between start of each memory region
-+ * @in.nents: The number of regions to pack together into the alias
-+ * @in.aliasing_info: Pointer to an array of struct base_mem_aliasing_info
- * @out: Output parameters
-+ * @out.flags: Flags, see BASE_MEM_xxx
-+ * @out.gpu_va: Address of the new alias
-+ * @out.va_pages: Size of the new alias
- */
- union kbase_ioctl_mem_alias {
- struct {
-@@ -453,15 +438,15 @@ union kbase_ioctl_mem_alias {
-
- /**
- * union kbase_ioctl_mem_import - Import memory for use by the GPU
-- * @flags: Flags, see BASE_MEM_xxx
-- * @phandle: Handle to the external memory
-- * @type: Type of external memory, see base_mem_import_type
-- * @padding: Amount of extra VA pages to append to the imported buffer
-- * @gpu_va: Address of the new alias
-- * @va_pages: Size of the new alias
-- *
- * @in: Input parameters
-+ * @in.flags: Flags, see BASE_MEM_xxx
-+ * @in.phandle: Handle to the external memory
-+ * @in.type: Type of external memory, see base_mem_import_type
-+ * @in.padding: Amount of extra VA pages to append to the imported buffer
- * @out: Output parameters
-+ * @out.flags: Flags, see BASE_MEM_xxx
-+ * @out.gpu_va: Address of the new alias
-+ * @out.va_pages: Size of the new alias
- */
- union kbase_ioctl_mem_import {
- struct {
-@@ -544,7 +529,7 @@ struct kbase_ioctl_mem_profile_add {
- /**
- * struct kbase_ioctl_sticky_resource_map - Permanently map an external resource
- * @count: Number of resources
-- * @address: Array of u64 GPU addresses of the external resources to map
-+ * @address: Array of __u64 GPU addresses of the external resources to map
- */
- struct kbase_ioctl_sticky_resource_map {
- __u64 count;
-@@ -558,7 +543,7 @@ struct kbase_ioctl_sticky_resource_map {
- * struct kbase_ioctl_sticky_resource_map - Unmap a resource mapped which was
- * previously permanently mapped
- * @count: Number of resources
-- * @address: Array of u64 GPU addresses of the external resources to unmap
-+ * @address: Array of __u64 GPU addresses of the external resources to unmap
- */
- struct kbase_ioctl_sticky_resource_unmap {
- __u64 count;
-@@ -574,15 +559,13 @@ struct kbase_ioctl_sticky_resource_unmap {
- * the given gpu address and
- * the offset of that address
- * into the region
-- *
-- * @gpu_addr: GPU virtual address
-- * @size: Size in bytes within the region
-- * @start: Address of the beginning of the memory region enclosing @gpu_addr
-- * for the length of @offset bytes
-- * @offset: The offset from the start of the memory region to @gpu_addr
-- *
- * @in: Input parameters
-+ * @in.gpu_addr: GPU virtual address
-+ * @in.size: Size in bytes within the region
- * @out: Output parameters
-+ * @out.start: Address of the beginning of the memory region enclosing @gpu_addr
-+ * for the length of @offset bytes
-+ * @out.offset: The offset from the start of the memory region to @gpu_addr
- */
- union kbase_ioctl_mem_find_gpu_start_and_offset {
- struct {
-@@ -598,7 +581,6 @@ union kbase_ioctl_mem_find_gpu_start_and_offset {
- #define KBASE_IOCTL_MEM_FIND_GPU_START_AND_OFFSET \
- _IOWR(KBASE_IOCTL_TYPE, 31, union kbase_ioctl_mem_find_gpu_start_and_offset)
-
--
- #define KBASE_IOCTL_CINSTR_GWT_START \
- _IO(KBASE_IOCTL_TYPE, 33)
-
-@@ -607,14 +589,15 @@ union kbase_ioctl_mem_find_gpu_start_and_offset {
-
- /**
- * union kbase_ioctl_gwt_dump - Used to collect all GPU write fault addresses.
-- * @addr_buffer: Address of buffer to hold addresses of gpu modified areas.
-- * @size_buffer: Address of buffer to hold size of modified areas (in pages)
-- * @len: Number of addresses the buffers can hold.
-- * @more_data_available: Status indicating if more addresses are available.
-- * @no_of_addr_collected: Number of addresses collected into addr_buffer.
-- *
- * @in: Input parameters
-+ * @in.addr_buffer: Address of buffer to hold addresses of gpu modified areas.
-+ * @in.size_buffer: Address of buffer to hold size of modified areas (in pages)
-+ * @in.len: Number of addresses the buffers can hold.
-+ * @in.padding: padding
- * @out: Output parameters
-+ * @out.no_of_addr_collected: Number of addresses collected into addr_buffer.
-+ * @out.more_data_available: Status indicating if more addresses are available.
-+ * @out.padding: padding
- *
- * This structure is used when performing a call to dump GPU write fault
- * addresses.
-@@ -652,18 +635,15 @@ struct kbase_ioctl_mem_exec_init {
- /**
- * union kbase_ioctl_get_cpu_gpu_timeinfo - Request zero or more types of
- * cpu/gpu time (counter values)
-- *
-- * @request_flags: Bit-flags indicating the requested types.
-- * @paddings: Unused, size alignment matching the out.
-- * @sec: Integer field of the monotonic time, unit in seconds.
-- * @nsec: Fractional sec of the monotonic time, in nano-seconds.
-- * @padding: Unused, for u64 alignment
-- * @timestamp: System wide timestamp (counter) value.
-- * @cycle_counter: GPU cycle counter value.
-- *
- * @in: Input parameters
-+ * @in.request_flags: Bit-flags indicating the requested types.
-+ * @in.paddings: Unused, size alignment matching the out.
- * @out: Output parameters
-- *
-+ * @out.sec: Integer field of the monotonic time, unit in seconds.
-+ * @out.nsec: Fractional sec of the monotonic time, in nano-seconds.
-+ * @out.padding: Unused, for __u64 alignment
-+ * @out.timestamp: System wide timestamp (counter) value.
-+ * @out.cycle_counter: GPU cycle counter value.
- */
- union kbase_ioctl_get_cpu_gpu_timeinfo {
- struct {
-@@ -682,6 +662,31 @@ union kbase_ioctl_get_cpu_gpu_timeinfo {
- #define KBASE_IOCTL_GET_CPU_GPU_TIMEINFO \
- _IOWR(KBASE_IOCTL_TYPE, 50, union kbase_ioctl_get_cpu_gpu_timeinfo)
-
-+/**
-+ * struct kbase_ioctl_context_priority_check - Check the max possible priority
-+ * @priority: Input priority & output priority
-+ */
-+
-+struct kbase_ioctl_context_priority_check {
-+ __u8 priority;
-+};
-+
-+#define KBASE_IOCTL_CONTEXT_PRIORITY_CHECK \
-+ _IOWR(KBASE_IOCTL_TYPE, 54, struct kbase_ioctl_context_priority_check)
-+
-+/**
-+ * struct kbase_ioctl_set_limited_core_count - Set the limited core count.
-+ *
-+ * @max_core_count: Maximum core count
-+ */
-+struct kbase_ioctl_set_limited_core_count {
-+ __u8 max_core_count;
-+};
-+
-+#define KBASE_IOCTL_SET_LIMITED_CORE_COUNT \
-+ _IOW(KBASE_IOCTL_TYPE, 55, struct kbase_ioctl_set_limited_core_count)
-+
-+
- /***************
- * test ioctls *
- ***************/
-@@ -692,23 +697,6 @@ union kbase_ioctl_get_cpu_gpu_timeinfo {
-
- #define KBASE_IOCTL_TEST_TYPE (KBASE_IOCTL_TYPE + 1)
-
--/**
-- * struct kbase_ioctl_tlstream_test - Start a timeline stream test
-- *
-- * @tpw_count: number of trace point writers in each context
-- * @msg_delay: time delay between tracepoints from one writer in milliseconds
-- * @msg_count: number of trace points written by one writer
-- * @aux_msg: if non-zero aux messages will be included
-- */
--struct kbase_ioctl_tlstream_test {
-- __u32 tpw_count;
-- __u32 msg_delay;
-- __u32 msg_count;
-- __u32 aux_msg;
--};
--
--#define KBASE_IOCTL_TLSTREAM_TEST \
-- _IOW(KBASE_IOCTL_TEST_TYPE, 1, struct kbase_ioctl_tlstream_test)
-
- /**
- * struct kbase_ioctl_tlstream_stats - Read tlstream stats for test purposes
-@@ -836,13 +824,13 @@ struct kbase_ioctl_tlstream_stats {
- #define KBASE_GPUPROP_TEXTURE_FEATURES_3 80
- #define KBASE_GPUPROP_RAW_TEXTURE_FEATURES_3 81
-
--#define KBASE_GPUPROP_NUM_EXEC_ENGINES 82
-+#define KBASE_GPUPROP_NUM_EXEC_ENGINES 82
-
- #define KBASE_GPUPROP_RAW_THREAD_TLS_ALLOC 83
- #define KBASE_GPUPROP_TLS_ALLOC 84
--
-+#define KBASE_GPUPROP_RAW_GPU_FEATURES 85
- #ifdef __cpluscplus
- }
- #endif
-
--#endif
-+#endif /* _UAPI_KBASE_IOCTL_H_ */
-diff --git a/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_kinstr_jm_reader.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_kinstr_jm_reader.h
-new file mode 100644
-index 0000000..72e1b9d
---- /dev/null
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_kbase_kinstr_jm_reader.h
-@@ -0,0 +1,69 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-+/*
-+ *
-+ * (C) COPYRIGHT 2020-2021 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 license.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, you can access it online at
-+ * http://www.gnu.org/licenses/gpl-2.0.html.
-+ *
-+ */
-+
-+/*
-+ * mali_kbase_kinstr_jm_reader.h
-+ * Provides an ioctl API to read kernel atom state changes. The flow of the
-+ * API is:
-+ * 1. Obtain the file descriptor with ``KBASE_IOCTL_KINSTR_JM_FD``
-+ * 2. Determine the buffer structure layout via the above ioctl's returned
-+ * size and version fields in ``struct kbase_kinstr_jm_fd_out``
-+ * 4. Poll the file descriptor for ``POLLIN``
-+ * 5. Get data with read() on the fd
-+ * 6. Use the structure version to understand how to read the data from the
-+ * buffer
-+ * 7. Repeat 4-6
-+ * 8. Close the file descriptor
-+ */
-+
-+#ifndef _UAPI_KBASE_KINSTR_JM_READER_H_
-+#define _UAPI_KBASE_KINSTR_JM_READER_H_
-+
-+/**
-+ * enum kbase_kinstr_jm_reader_atom_state - Determines the work state of an atom
-+ * @KBASE_KINSTR_JM_READER_ATOM_STATE_QUEUE: Signifies that an atom has
-+ * entered a hardware queue
-+ * @KBASE_KINSTR_JM_READER_ATOM_STATE_START: Signifies that work has started
-+ * on an atom
-+ * @KBASE_KINSTR_JM_READER_ATOM_STATE_STOP: Signifies that work has stopped
-+ * on an atom
-+ * @KBASE_KINSTR_JM_READER_ATOM_STATE_COMPLETE: Signifies that work has
-+ * completed on an atom
-+ * @KBASE_KINSTR_JM_READER_ATOM_STATE_COUNT: The number of state enumerations
-+ *
-+ * We can add new states to the end of this if they do not break the existing
-+ * state machine. Old user mode code can gracefully ignore states they do not
-+ * understand.
-+ *
-+ * If we need to make a breaking change to the state machine, we can do that by
-+ * changing the version reported by KBASE_IOCTL_KINSTR_JM_FD. This will
-+ * mean that old user mode code will fail to understand the new state field in
-+ * the structure and gracefully not use the state change API.
-+ */
-+enum kbase_kinstr_jm_reader_atom_state {
-+ KBASE_KINSTR_JM_READER_ATOM_STATE_QUEUE,
-+ KBASE_KINSTR_JM_READER_ATOM_STATE_START,
-+ KBASE_KINSTR_JM_READER_ATOM_STATE_STOP,
-+ KBASE_KINSTR_JM_READER_ATOM_STATE_COMPLETE,
-+ KBASE_KINSTR_JM_READER_ATOM_STATE_COUNT
-+};
-+
-+#endif /* _UAPI_KBASE_KINSTR_JM_READER_H_ */
-diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_uk.h b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_uk.h
-similarity index 69%
-rename from dvalin/kernel/drivers/gpu/arm/midgard/mali_uk.h
-rename to dvalin/kernel/include/uapi/gpu/arm/midgard/mali_uk.h
-index 701f390..fcb6cb8 100644
---- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_uk.h
-+++ b/dvalin/kernel/include/uapi/gpu/arm/midgard/mali_uk.h
-@@ -1,11 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
- /*
- *
-- * (C) COPYRIGHT 2010, 2012-2015, 2018 ARM Limited. All rights reserved.
-+ * (C) COPYRIGHT 2010, 2012-2015, 2018, 2020-2021 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.
-+ * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-@@ -16,32 +17,22 @@
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
-- * SPDX-License-Identifier: GPL-2.0
-- *
- */
-
--
--
- /**
-- * @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_
-+#ifndef _UAPI_UK_H_
-+#define _UAPI_UK_H_
-
- #ifdef __cplusplus
- extern "C" {
--#endif /* __cplusplus */
--
--/**
-- * @addtogroup base_api
-- * @{
-- */
-+#endif /* __cplusplus */
-
- /**
-- * @defgroup uk_api User-Kernel Interface API
-+ * DOC: 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.
-@@ -51,12 +42,16 @@ extern "C" {
- *
- * 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
-+ * enum uk_client_id - These are identifiers for kernel-side drivers
-+ * implementing a UK interface, aka UKK clients.
-+ * @UK_CLIENT_MALI_T600_BASE: Value used to identify the Base driver UK client.
-+ * @UK_CLIENT_COUNT: The number of uk clients supported. This must be
-+ * the last member of the enum
-+ *
-+ * 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
-@@ -65,20 +60,11 @@ extern "C" {
- *
- */
- 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
- };
-
--/** @} end group uk_api */
--
--/** @} *//* end group base_api */
--
- #ifdef __cplusplus
- }
--#endif /* __cplusplus */
--#endif /* _UK_H_ */
-+#endif /* __cplusplus */
-+#endif /* _UAPI_UK_H_ */
---
-2.29.0
-