summaryrefslogtreecommitdiff
path: root/mali_kbase
diff options
context:
space:
mode:
authorSidath Senanayake <sidaths@google.com>2021-01-29 15:03:53 +0000
committerSidath Senanayake <sidaths@google.com>2021-01-29 15:03:53 +0000
commit9748305a584b9f1f7705303ce6e33a5e8b923e60 (patch)
treea73788e1d912a3202db3a99018002e0858e9a948 /mali_kbase
parent201c8bfb4637601363b6e9283f3bdc510711a226 (diff)
downloadgpu-9748305a584b9f1f7705303ce6e33a5e8b923e60.tar.gz
Mali Valhall DDK r29p0 KMD
Provenance: afaca8da1 (collaborate/EAC/v_r29p0) VX504X08X-BU-00000-r29p0-01eac0 - Valhall Android DDK VX504X08X-BU-60000-r29p0-01eac0 - Valhall Android Document Bundle VX504X08X-DC-11001-r29p0-01eac0 - Valhall Android DDK Software Errata VX504X08X-SW-99006-r29p0-01eac0 - Valhall Android Renderscript AOSP parts Signed-off-by: Sidath Senanayake <sidaths@google.com> Change-Id: Ie0904c9223b7ec9311b848a52d3159ac2b07530e
Diffstat (limited to 'mali_kbase')
-rw-r--r--mali_kbase/Kbuild6
-rw-r--r--mali_kbase/Makefile2
-rw-r--r--mali_kbase/Makefile.kbase3
-rw-r--r--mali_kbase/Mconfig15
-rw-r--r--mali_kbase/arbiter/mali_kbase_arbif.c1
-rw-r--r--mali_kbase/arbiter/mali_kbase_arbif.h2
-rw-r--r--mali_kbase/arbiter/mali_kbase_arbiter_defs.h4
-rw-r--r--mali_kbase/arbiter/mali_kbase_arbiter_interface.h2
-rw-r--r--mali_kbase/arbiter/mali_kbase_arbiter_pm.c22
-rw-r--r--mali_kbase/arbiter/mali_kbase_arbiter_pm.h3
-rw-r--r--mali_kbase/backend/gpu/Kbuild2
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_backend_config.h21
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c1
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.h22
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.c18
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.h21
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_debug_job_fault_backend.c1
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_devfreq.c113
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_devfreq.h37
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_gpuprops_backend.c22
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_instr_backend.c123
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_instr_defs.h24
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_instr_internal.h23
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_irq_internal.h21
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_irq_linux.c16
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_as.c6
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_defs.h30
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_hw.c100
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_internal.h23
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_rb.c95
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_rb.h22
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_js_backend.c31
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_js_internal.h22
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_l2_mmu_config.h3
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_always_on.c8
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_always_on.h23
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_backend.c35
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_ca.c1
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_ca.h21
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.h21
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c8
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.h23
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_defs.h98
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_driver.c317
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_internal.h79
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_l2_states.h21
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_mcu_states.h29
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_metrics.c175
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_policy.c157
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_policy.h21
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_shader_states.h21
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_time.c1
-rw-r--r--mali_kbase/build.bp14
-rw-r--r--mali_kbase/context/backend/mali_kbase_context_csf.c63
-rw-r--r--mali_kbase/context/backend/mali_kbase_context_jm.c68
-rw-r--r--mali_kbase/context/mali_kbase_context.c53
-rw-r--r--mali_kbase/context/mali_kbase_context.h31
-rw-r--r--mali_kbase/context/mali_kbase_context_internal.h18
-rw-r--r--mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.c119
-rw-r--r--mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.h49
-rw-r--r--mali_kbase/csf/mali_base_csf_kernel.h40
-rw-r--r--mali_kbase/csf/mali_gpu_csf_control_registers.h21
-rw-r--r--mali_kbase/csf/mali_gpu_csf_registers.h99
-rw-r--r--mali_kbase/csf/mali_kbase_csf.c459
-rw-r--r--mali_kbase/csf/mali_kbase_csf.h110
-rw-r--r--mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.c1
-rw-r--r--mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.h21
-rw-r--r--mali_kbase/csf/mali_kbase_csf_csg_debugfs.c56
-rw-r--r--mali_kbase/csf/mali_kbase_csf_csg_debugfs.h21
-rw-r--r--mali_kbase/csf/mali_kbase_csf_defs.h192
-rw-r--r--mali_kbase/csf/mali_kbase_csf_firmware.c192
-rw-r--r--mali_kbase/csf/mali_kbase_csf_firmware.h105
-rw-r--r--mali_kbase/csf/mali_kbase_csf_firmware_cfg.c1
-rw-r--r--mali_kbase/csf/mali_kbase_csf_firmware_cfg.h21
-rw-r--r--mali_kbase/csf/mali_kbase_csf_firmware_no_mali.c143
-rw-r--r--mali_kbase/csf/mali_kbase_csf_heap_context_alloc.c3
-rw-r--r--mali_kbase/csf/mali_kbase_csf_heap_context_alloc.h21
-rw-r--r--mali_kbase/csf/mali_kbase_csf_ioctl.h31
-rw-r--r--mali_kbase/csf/mali_kbase_csf_kcpu.c127
-rw-r--r--mali_kbase/csf/mali_kbase_csf_kcpu.h25
-rw-r--r--mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.c2
-rw-r--r--mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.h21
-rw-r--r--mali_kbase/csf/mali_kbase_csf_protected_memory.c3
-rw-r--r--mali_kbase/csf/mali_kbase_csf_protected_memory.h21
-rw-r--r--mali_kbase/csf/mali_kbase_csf_reset_gpu.c350
-rw-r--r--mali_kbase/csf/mali_kbase_csf_scheduler.c742
-rw-r--r--mali_kbase/csf/mali_kbase_csf_scheduler.h63
-rw-r--r--mali_kbase/csf/mali_kbase_csf_tiler_heap.c25
-rw-r--r--mali_kbase/csf/mali_kbase_csf_tiler_heap.h21
-rw-r--r--mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.c1
-rw-r--r--mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.h21
-rw-r--r--mali_kbase/csf/mali_kbase_csf_tiler_heap_def.h24
-rw-r--r--mali_kbase/csf/mali_kbase_csf_timeout.c1
-rw-r--r--mali_kbase/csf/mali_kbase_csf_timeout.h21
-rw-r--r--mali_kbase/csf/mali_kbase_csf_tl_reader.c3
-rw-r--r--mali_kbase/csf/mali_kbase_csf_tl_reader.h23
-rw-r--r--mali_kbase/csf/mali_kbase_csf_trace_buffer.c3
-rw-r--r--mali_kbase/csf/mali_kbase_csf_trace_buffer.h21
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_csf.h61
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_jm.h21
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.c88
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.h86
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_csf.h93
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_jm.h49
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.c44
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.h21
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_csf.h67
-rw-r--r--mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_jm.h21
-rw-r--r--mali_kbase/debug/mali_kbase_debug_ktrace.c11
-rw-r--r--mali_kbase/debug/mali_kbase_debug_ktrace.h21
-rw-r--r--mali_kbase/debug/mali_kbase_debug_ktrace_codes.h30
-rw-r--r--mali_kbase/debug/mali_kbase_debug_ktrace_defs.h44
-rw-r--r--mali_kbase/debug/mali_kbase_debug_ktrace_internal.h21
-rw-r--r--mali_kbase/debug/mali_kbase_debug_linux_ktrace.h27
-rw-r--r--mali_kbase/device/backend/mali_kbase_device_csf.c21
-rw-r--r--mali_kbase/device/backend/mali_kbase_device_hw_csf.c20
-rw-r--r--mali_kbase/device/backend/mali_kbase_device_jm.c7
-rw-r--r--mali_kbase/device/mali_kbase_device.c94
-rw-r--r--mali_kbase/device/mali_kbase_device.h21
-rw-r--r--mali_kbase/device/mali_kbase_device_internal.h30
-rw-r--r--mali_kbase/gpu/backend/mali_kbase_gpu_fault_csf.c1
-rw-r--r--mali_kbase/gpu/backend/mali_kbase_gpu_fault_jm.c1
-rw-r--r--mali_kbase/gpu/backend/mali_kbase_gpu_regmap_csf.h29
-rw-r--r--mali_kbase/gpu/backend/mali_kbase_gpu_regmap_jm.h29
-rw-r--r--mali_kbase/gpu/mali_kbase_gpu.c4
-rw-r--r--mali_kbase/gpu/mali_kbase_gpu.h21
-rw-r--r--mali_kbase/gpu/mali_kbase_gpu_coherency.h21
-rw-r--r--mali_kbase/gpu/mali_kbase_gpu_fault.h21
-rw-r--r--mali_kbase/gpu/mali_kbase_gpu_id.h38
-rw-r--r--mali_kbase/gpu/mali_kbase_gpu_regmap.h48
-rw-r--r--mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.c360
-rw-r--r--mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.h108
-rw-r--r--mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.c7
-rw-r--r--mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.h34
-rw-r--r--mali_kbase/ipa/backend/mali_kbase_ipa_counter_csf.c140
-rw-r--r--mali_kbase/ipa/backend/mali_kbase_ipa_counter_jm.c3
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa.c224
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa.h71
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa_debugfs.c6
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa_debugfs.h21
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa_simple.c47
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa_simple.h21
-rw-r--r--mali_kbase/jm/mali_base_jm_kernel.h28
-rw-r--r--mali_kbase/jm/mali_kbase_jm_defs.h25
-rw-r--r--mali_kbase/jm/mali_kbase_jm_ioctl.h32
-rw-r--r--mali_kbase/jm/mali_kbase_jm_js.h35
-rw-r--r--mali_kbase/jm/mali_kbase_js_defs.h71
-rw-r--r--mali_kbase/mali_base_hwconfig_features.h23
-rw-r--r--mali_kbase/mali_base_hwconfig_issues.h27
-rw-r--r--mali_kbase/mali_base_kernel.h25
-rw-r--r--mali_kbase/mali_base_mem_priv.h23
-rw-r--r--mali_kbase/mali_kbase.h31
-rw-r--r--mali_kbase/mali_kbase_as_fault_debugfs.c3
-rw-r--r--mali_kbase/mali_kbase_as_fault_debugfs.h21
-rw-r--r--mali_kbase/mali_kbase_bits.h14
-rw-r--r--mali_kbase/mali_kbase_cache_policy.c5
-rw-r--r--mali_kbase/mali_kbase_cache_policy.h23
-rw-r--r--mali_kbase/mali_kbase_caps.h22
-rw-r--r--mali_kbase/mali_kbase_ccswe.c5
-rw-r--r--mali_kbase/mali_kbase_ccswe.h21
-rw-r--r--mali_kbase/mali_kbase_config.c5
-rw-r--r--mali_kbase/mali_kbase_config.h23
-rw-r--r--mali_kbase/mali_kbase_config_defaults.h21
-rw-r--r--mali_kbase/mali_kbase_core_linux.c376
-rw-r--r--mali_kbase/mali_kbase_cs_experimental.h13
-rw-r--r--mali_kbase/mali_kbase_ctx_sched.c68
-rw-r--r--mali_kbase/mali_kbase_ctx_sched.h57
-rw-r--r--mali_kbase/mali_kbase_debug.c5
-rw-r--r--mali_kbase/mali_kbase_debug.h23
-rw-r--r--mali_kbase/mali_kbase_debug_job_fault.c22
-rw-r--r--mali_kbase/mali_kbase_debug_job_fault.h24
-rw-r--r--mali_kbase/mali_kbase_debug_mem_view.c20
-rw-r--r--mali_kbase/mali_kbase_debug_mem_view.h21
-rw-r--r--mali_kbase/mali_kbase_debugfs_helper.c71
-rw-r--r--mali_kbase/mali_kbase_debugfs_helper.h44
-rw-r--r--mali_kbase/mali_kbase_defs.h118
-rw-r--r--mali_kbase/mali_kbase_disjoint_events.c1
-rw-r--r--mali_kbase/mali_kbase_dma_fence.c15
-rw-r--r--mali_kbase/mali_kbase_dma_fence.h25
-rw-r--r--mali_kbase/mali_kbase_dummy_job_wa.c1
-rw-r--r--mali_kbase/mali_kbase_dummy_job_wa.h21
-rw-r--r--mali_kbase/mali_kbase_dvfs_debugfs.c8
-rw-r--r--mali_kbase/mali_kbase_dvfs_debugfs.h21
-rw-r--r--mali_kbase/mali_kbase_event.c8
-rw-r--r--mali_kbase/mali_kbase_fence.c7
-rw-r--r--mali_kbase/mali_kbase_fence.h29
-rw-r--r--mali_kbase/mali_kbase_fence_defs.h25
-rw-r--r--mali_kbase/mali_kbase_fence_ops.c11
-rw-r--r--mali_kbase/mali_kbase_gator.h21
-rw-r--r--mali_kbase/mali_kbase_gpu_memory_debugfs.c6
-rw-r--r--mali_kbase/mali_kbase_gpu_memory_debugfs.h23
-rw-r--r--mali_kbase/mali_kbase_gpuprops.c97
-rw-r--r--mali_kbase/mali_kbase_gpuprops.h15
-rw-r--r--mali_kbase/mali_kbase_gpuprops_types.h25
-rw-r--r--mali_kbase/mali_kbase_gwt.c1
-rw-r--r--mali_kbase/mali_kbase_gwt.h21
-rw-r--r--mali_kbase/mali_kbase_hw.c15
-rw-r--r--mali_kbase/mali_kbase_hw.h23
-rw-r--r--mali_kbase/mali_kbase_hwaccess_backend.h22
-rw-r--r--mali_kbase/mali_kbase_hwaccess_defs.h21
-rw-r--r--mali_kbase/mali_kbase_hwaccess_gpuprops.h14
-rw-r--r--mali_kbase/mali_kbase_hwaccess_instr.h23
-rw-r--r--mali_kbase/mali_kbase_hwaccess_jm.h22
-rw-r--r--mali_kbase/mali_kbase_hwaccess_pm.h21
-rw-r--r--mali_kbase/mali_kbase_hwaccess_time.h22
-rw-r--r--mali_kbase/mali_kbase_hwcnt.c73
-rw-r--r--mali_kbase/mali_kbase_hwcnt_accumulator.h21
-rw-r--r--mali_kbase/mali_kbase_hwcnt_backend.h50
-rw-r--r--mali_kbase/mali_kbase_hwcnt_backend_csf.c1882
-rw-r--r--mali_kbase/mali_kbase_hwcnt_backend_csf.h184
-rw-r--r--mali_kbase/mali_kbase_hwcnt_backend_csf_if.h280
-rw-r--r--mali_kbase/mali_kbase_hwcnt_backend_csf_if_fw.c771
-rw-r--r--mali_kbase/mali_kbase_hwcnt_backend_csf_if_fw.h70
-rw-r--r--mali_kbase/mali_kbase_hwcnt_backend_jm.c101
-rw-r--r--mali_kbase/mali_kbase_hwcnt_backend_jm.h21
-rw-r--r--mali_kbase/mali_kbase_hwcnt_context.h60
-rw-r--r--mali_kbase/mali_kbase_hwcnt_gpu.c206
-rw-r--r--mali_kbase/mali_kbase_hwcnt_gpu.h131
-rw-r--r--mali_kbase/mali_kbase_hwcnt_legacy.c1
-rw-r--r--mali_kbase/mali_kbase_hwcnt_legacy.h21
-rw-r--r--mali_kbase/mali_kbase_hwcnt_reader.h21
-rw-r--r--mali_kbase/mali_kbase_hwcnt_types.c19
-rw-r--r--mali_kbase/mali_kbase_hwcnt_types.h22
-rw-r--r--mali_kbase/mali_kbase_hwcnt_virtualizer.c22
-rw-r--r--mali_kbase/mali_kbase_hwcnt_virtualizer.h37
-rw-r--r--mali_kbase/mali_kbase_ioctl.h37
-rw-r--r--mali_kbase/mali_kbase_jd.c91
-rw-r--r--mali_kbase/mali_kbase_jd_debugfs.c34
-rw-r--r--mali_kbase/mali_kbase_jd_debugfs.h21
-rw-r--r--mali_kbase/mali_kbase_jm.c2
-rw-r--r--mali_kbase/mali_kbase_jm.h21
-rw-r--r--mali_kbase/mali_kbase_js.c208
-rw-r--r--mali_kbase/mali_kbase_js.h23
-rw-r--r--mali_kbase/mali_kbase_js_ctx_attr.c11
-rw-r--r--mali_kbase/mali_kbase_js_ctx_attr.h23
-rw-r--r--mali_kbase/mali_kbase_kinstr_jm.c7
-rw-r--r--mali_kbase/mali_kbase_kinstr_jm.h28
-rw-r--r--mali_kbase/mali_kbase_kinstr_jm_reader.h21
-rw-r--r--mali_kbase/mali_kbase_linux.h23
-rw-r--r--mali_kbase/mali_kbase_mem.c99
-rw-r--r--mali_kbase/mali_kbase_mem.h49
-rw-r--r--mali_kbase/mali_kbase_mem_linux.c162
-rw-r--r--mali_kbase/mali_kbase_mem_linux.h29
-rw-r--r--mali_kbase/mali_kbase_mem_lowlevel.h23
-rw-r--r--mali_kbase/mali_kbase_mem_pool.c34
-rw-r--r--mali_kbase/mali_kbase_mem_pool_debugfs.c3
-rw-r--r--mali_kbase/mali_kbase_mem_pool_debugfs.h21
-rw-r--r--mali_kbase/mali_kbase_mem_pool_group.c3
-rw-r--r--mali_kbase/mali_kbase_mem_pool_group.h21
-rw-r--r--mali_kbase/mali_kbase_mem_profile_debugfs.c1
-rw-r--r--mali_kbase/mali_kbase_mem_profile_debugfs.h23
-rw-r--r--mali_kbase/mali_kbase_mem_profile_debugfs_buf_size.h21
-rw-r--r--mali_kbase/mali_kbase_mipe_gen_header.h38
-rw-r--r--mali_kbase/mali_kbase_mipe_proto.h21
-rw-r--r--mali_kbase/mali_kbase_native_mgm.c3
-rw-r--r--mali_kbase/mali_kbase_native_mgm.h21
-rw-r--r--mali_kbase/mali_kbase_platform_fake.c3
-rw-r--r--mali_kbase/mali_kbase_pm.c6
-rw-r--r--mali_kbase/mali_kbase_pm.h23
-rw-r--r--mali_kbase/mali_kbase_regs_history_debugfs.c1
-rw-r--r--mali_kbase/mali_kbase_regs_history_debugfs.h21
-rw-r--r--mali_kbase/mali_kbase_reset_gpu.h150
-rw-r--r--mali_kbase/mali_kbase_smc.c1
-rw-r--r--mali_kbase/mali_kbase_smc.h23
-rw-r--r--mali_kbase/mali_kbase_softjobs.c46
-rw-r--r--mali_kbase/mali_kbase_strings.c6
-rw-r--r--mali_kbase/mali_kbase_strings.h21
-rw-r--r--mali_kbase/mali_kbase_sync.h23
-rw-r--r--mali_kbase/mali_kbase_sync_android.c63
-rw-r--r--mali_kbase/mali_kbase_sync_common.c3
-rw-r--r--mali_kbase/mali_kbase_sync_file.c22
-rw-r--r--mali_kbase/mali_kbase_trace_gpu_mem.c6
-rw-r--r--mali_kbase/mali_kbase_trace_gpu_mem.h25
-rw-r--r--mali_kbase/mali_kbase_utility.h25
-rw-r--r--mali_kbase/mali_kbase_vinstr.c21
-rw-r--r--mali_kbase/mali_kbase_vinstr.h21
-rw-r--r--mali_kbase/mali_linux_trace.h24
-rw-r--r--mali_kbase/mali_malisw.h38
-rw-r--r--mali_kbase/mali_power_gpu_frequency_trace.c1
-rw-r--r--mali_kbase/mali_power_gpu_frequency_trace.h21
-rw-r--r--mali_kbase/mali_uk.h23
-rw-r--r--mali_kbase/mmu/backend/mali_kbase_mmu_csf.c54
-rw-r--r--mali_kbase/mmu/backend/mali_kbase_mmu_jm.c1
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu.c52
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu.h38
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu_hw.h21
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu_hw_direct.c1
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu_internal.h21
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu_mode_aarch64.c21
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu_mode_lpae.c22
-rw-r--r--mali_kbase/platform/Kconfig3
-rw-r--r--mali_kbase/platform/devicetree/mali_kbase_clk_rate_trace.c1
-rw-r--r--mali_kbase/platform/devicetree/mali_kbase_config_devicetree.c3
-rw-r--r--mali_kbase/platform/devicetree/mali_kbase_config_platform.h21
-rw-r--r--mali_kbase/platform/devicetree/mali_kbase_runtime_pm.c3
-rw-r--r--mali_kbase/platform/vexpress/Kbuild2
-rw-r--r--mali_kbase/platform/vexpress/mali_kbase_config_platform.h21
-rw-r--r--mali_kbase/platform/vexpress/mali_kbase_config_vexpress.c5
-rw-r--r--mali_kbase/platform/vexpress_1xv7_a57/Kbuild2
-rw-r--r--mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h21
-rw-r--r--mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c3
-rw-r--r--mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h21
-rw-r--r--mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c5
-rw-r--r--mali_kbase/protected_mode_switcher.h21
-rw-r--r--mali_kbase/tests/Mconfig15
-rw-r--r--mali_kbase/tests/include/kutf/kutf_helpers.h21
-rw-r--r--mali_kbase/tests/include/kutf/kutf_helpers_user.h39
-rw-r--r--mali_kbase/tests/include/kutf/kutf_mem.h21
-rw-r--r--mali_kbase/tests/include/kutf/kutf_resultset.h21
-rw-r--r--mali_kbase/tests/include/kutf/kutf_suite.h43
-rw-r--r--mali_kbase/tests/include/kutf/kutf_utils.h21
-rw-r--r--mali_kbase/tests/kutf/Kbuild2
-rw-r--r--mali_kbase/tests/kutf/Kconfig3
-rw-r--r--mali_kbase/tests/kutf/Makefile2
-rw-r--r--mali_kbase/tests/kutf/build.bp14
-rw-r--r--mali_kbase/tests/kutf/kutf_helpers.c1
-rw-r--r--mali_kbase/tests/kutf/kutf_helpers_user.c24
-rw-r--r--mali_kbase/tests/kutf/kutf_mem.c3
-rw-r--r--mali_kbase/tests/kutf/kutf_resultset.c3
-rw-r--r--mali_kbase/tests/kutf/kutf_suite.c12
-rw-r--r--mali_kbase/tests/kutf/kutf_utils.c3
-rw-r--r--mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/build.bp16
-rw-r--r--mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c1
-rw-r--r--mali_kbase/tests/mali_kutf_clk_rate_trace/mali_kutf_clk_rate_trace_test.h21
-rw-r--r--mali_kbase/tests/mali_kutf_irq_test/Kbuild2
-rw-r--r--mali_kbase/tests/mali_kutf_irq_test/Kconfig2
-rw-r--r--mali_kbase/tests/mali_kutf_irq_test/build.bp14
-rw-r--r--mali_kbase/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c5
-rw-r--r--mali_kbase/thirdparty/mali_kbase_mmap.c6
-rw-r--r--mali_kbase/tl/backend/mali_kbase_timeline_csf.c7
-rw-r--r--mali_kbase/tl/backend/mali_kbase_timeline_jm.c11
-rw-r--r--mali_kbase/tl/mali_kbase_timeline.c83
-rw-r--r--mali_kbase/tl/mali_kbase_timeline.h45
-rw-r--r--mali_kbase/tl/mali_kbase_timeline_io.c1
-rw-r--r--mali_kbase/tl/mali_kbase_timeline_priv.h25
-rw-r--r--mali_kbase/tl/mali_kbase_tl_serialize.h21
-rw-r--r--mali_kbase/tl/mali_kbase_tlstream.c10
-rw-r--r--mali_kbase/tl/mali_kbase_tlstream.h21
-rw-r--r--mali_kbase/tl/mali_kbase_tracepoints.c60
-rw-r--r--mali_kbase/tl/mali_kbase_tracepoints.h68
340 files changed, 13346 insertions, 2864 deletions
diff --git a/mali_kbase/Kbuild b/mali_kbase/Kbuild
index 5b495c9..c8cef84 100644
--- a/mali_kbase/Kbuild
+++ b/mali_kbase/Kbuild
@@ -21,7 +21,7 @@
# Driver version string which is returned to userspace via an ioctl
-MALI_RELEASE_NAME ?= "r28p0-01eac0"
+MALI_RELEASE_NAME ?= "r29p0-01eac0"
# Paths required for build
@@ -91,7 +91,6 @@ SRC := \
mali_kbase_config.c \
mali_kbase_vinstr.c \
mali_kbase_hwcnt.c \
- mali_kbase_hwcnt_backend_jm.c \
mali_kbase_hwcnt_gpu.c \
mali_kbase_hwcnt_legacy.c \
mali_kbase_hwcnt_types.c \
@@ -128,6 +127,8 @@ SRC := \
ifeq ($(MALI_USE_CSF),1)
SRC += \
+ mali_kbase_hwcnt_backend_csf.c \
+ mali_kbase_hwcnt_backend_csf_if_fw.c \
debug/backend/mali_kbase_debug_ktrace_csf.c \
device/backend/mali_kbase_device_csf.c \
device/backend/mali_kbase_device_hw_csf.c \
@@ -137,6 +138,7 @@ ifeq ($(MALI_USE_CSF),1)
context/backend/mali_kbase_context_csf.c
else
SRC += \
+ mali_kbase_hwcnt_backend_jm.c \
mali_kbase_dummy_job_wa.c \
mali_kbase_debug_job_fault.c \
mali_kbase_event.c \
diff --git a/mali_kbase/Makefile b/mali_kbase/Makefile
index 53a1209..45fb434 100644
--- a/mali_kbase/Makefile
+++ b/mali_kbase/Makefile
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2010-2019 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2010-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
diff --git a/mali_kbase/Makefile.kbase b/mali_kbase/Makefile.kbase
index 6b0f81e..74a9763 100644
--- a/mali_kbase/Makefile.kbase
+++ b/mali_kbase/Makefile.kbase
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2010, 2013, 2018 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2010, 2013, 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
@@ -20,4 +20,3 @@
#
EXTRA_CFLAGS += -I$(ROOT) -I$(KBASE_PATH) -I$(KBASE_PATH)/platform_$(PLATFORM)
-
diff --git a/mali_kbase/Mconfig b/mali_kbase/Mconfig
index a70c76c..d7a5569 100644
--- a/mali_kbase/Mconfig
+++ b/mali_kbase/Mconfig
@@ -1,17 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
#
# (C) COPYRIGHT 2012-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.
#
-# 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"
diff --git a/mali_kbase/arbiter/mali_kbase_arbif.c b/mali_kbase/arbiter/mali_kbase_arbif.c
index 3bfc62d..8e03466 100644
--- a/mali_kbase/arbiter/mali_kbase_arbif.c
+++ b/mali_kbase/arbiter/mali_kbase_arbif.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/arbiter/mali_kbase_arbif.h b/mali_kbase/arbiter/mali_kbase_arbif.h
index e7e9de7..ff082ef 100644
--- a/mali_kbase/arbiter/mali_kbase_arbif.h
+++ b/mali_kbase/arbiter/mali_kbase_arbif.h
@@ -19,7 +19,6 @@
* SPDX-License-Identifier: GPL-2.0
*
*//* SPDX-License-Identifier: GPL-2.0 */
-
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -38,7 +37,6 @@
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
- *
*/
/**
diff --git a/mali_kbase/arbiter/mali_kbase_arbiter_defs.h b/mali_kbase/arbiter/mali_kbase_arbiter_defs.h
index 1f53cbf..071d5ee 100644
--- a/mali_kbase/arbiter/mali_kbase_arbiter_defs.h
+++ b/mali_kbase/arbiter/mali_kbase_arbiter_defs.h
@@ -19,7 +19,6 @@
* SPDX-License-Identifier: GPL-2.0
*
*//* SPDX-License-Identifier: GPL-2.0 */
-
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -38,7 +37,6 @@
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
- *
*/
/**
@@ -66,7 +64,6 @@
* @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
*/
struct kbase_arbiter_vm_state {
struct kbase_device *kbdev;
@@ -78,7 +75,6 @@ struct kbase_arbiter_vm_state {
struct work_struct vm_resume_work;
bool vm_arb_starting;
bool vm_arb_stopping;
- int vm_arb_users_waiting;
};
/**
diff --git a/mali_kbase/arbiter/mali_kbase_arbiter_interface.h b/mali_kbase/arbiter/mali_kbase_arbiter_interface.h
index 5d5d8a7..59a51d9 100644
--- a/mali_kbase/arbiter/mali_kbase_arbiter_interface.h
+++ b/mali_kbase/arbiter/mali_kbase_arbiter_interface.h
@@ -19,7 +19,6 @@
* SPDX-License-Identifier: GPL-2.0
*
*//* SPDX-License-Identifier: GPL-2.0 */
-
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -38,7 +37,6 @@
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
- *
*/
/**
diff --git a/mali_kbase/arbiter/mali_kbase_arbiter_pm.c b/mali_kbase/arbiter/mali_kbase_arbiter_pm.c
index 1fc432b..f3893b6 100644
--- a/mali_kbase/arbiter/mali_kbase_arbiter_pm.c
+++ b/mali_kbase/arbiter/mali_kbase_arbiter_pm.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -29,10 +28,7 @@
#include <mali_kbase.h>
#include <mali_kbase_pm.h>
-#include <mali_kbase_hwaccess_jm.h>
#include <mali_kbase_irq_internal.h>
-#include <mali_kbase_hwcnt_context.h>
-#include <mali_kbase_pm_internal.h>
#include <tl/mali_kbase_tracepoints.h>
static void kbase_arbiter_pm_vm_wait_gpu_assignment(struct kbase_device *kbdev);
@@ -131,6 +127,9 @@ static void kbase_arbiter_pm_vm_set_state(struct kbase_device *kbdev,
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);
}
@@ -193,6 +192,7 @@ 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__);
}
@@ -231,7 +231,7 @@ int kbase_arbiter_pm_early_init(struct kbase_device *kbdev)
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);
kbdev->pm.arb_vm_state = arb_vm_state;
err = kbase_arbif_init(kbdev);
@@ -312,7 +312,7 @@ 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);
@@ -623,7 +623,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);
@@ -656,8 +658,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_ARBITER_STARTED(kbdev, kbdev);
- /* FALL THROUGH */
case KBASE_VM_STATE_IDLE:
kbase_arbiter_pm_vm_set_state(kbdev,
KBASE_VM_STATE_ACTIVE);
@@ -799,7 +799,7 @@ int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev,
}
/* 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);
@@ -807,7 +807,7 @@ 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);
}
diff --git a/mali_kbase/arbiter/mali_kbase_arbiter_pm.h b/mali_kbase/arbiter/mali_kbase_arbiter_pm.h
index 3c49eb1..b029c62 100644
--- a/mali_kbase/arbiter/mali_kbase_arbiter_pm.h
+++ b/mali_kbase/arbiter/mali_kbase_arbiter_pm.h
@@ -19,7 +19,6 @@
* SPDX-License-Identifier: GPL-2.0
*
*//* SPDX-License-Identifier: GPL-2.0 */
-
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -38,8 +37,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/mali_kbase/backend/gpu/Kbuild b/mali_kbase/backend/gpu/Kbuild
index 5dc8c01..b95e795 100644
--- a/mali_kbase/backend/gpu/Kbuild
+++ b/mali_kbase/backend/gpu/Kbuild
@@ -23,7 +23,6 @@ BACKEND += \
backend/gpu/mali_kbase_cache_policy_backend.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 \
@@ -40,6 +39,7 @@ ifeq ($(MALI_USE_CSF),1)
# empty
else
BACKEND += \
+ backend/gpu/mali_kbase_instr_backend.c \
backend/gpu/mali_kbase_jm_as.c \
backend/gpu/mali_kbase_debug_job_fault_backend.c \
backend/gpu/mali_kbase_jm_hw.c \
diff --git a/mali_kbase/backend/gpu/mali_kbase_backend_config.h b/mali_kbase/backend/gpu/mali_kbase_backend_config.h
index 4a61f96..1e9fbcb 100644
--- a/mali_kbase/backend/gpu/mali_kbase_backend_config.h
+++ b/mali_kbase/backend/gpu/mali_kbase_backend_config.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
/*
diff --git a/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c b/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c
index 4e07a3f..b58518a 100644
--- a/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2016, 2018, 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.h b/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.h
index f78ada7..1d63098 100644
--- a/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.h
+++ b/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015-2016 ARM Limited. All rights reserved.
+ * (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
@@ -18,9 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-2016, 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 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_CACHE_POLICY_BACKEND_H_
#define _KBASE_CACHE_POLICY_BACKEND_H_
diff --git a/mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.c b/mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.c
index 187d7d6..8d82295 100644
--- a/mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.c
+++ b/mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -127,13 +128,15 @@ int kbase_clk_rate_trace_manager_init(struct kbase_device *kbdev)
unsigned int i;
int ret = 0;
- /* Return early if no callbacks provided for clock rate tracing */
- if (!callbacks)
- return 0;
-
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++) {
@@ -151,10 +154,12 @@ int kbase_clk_rate_trace_manager_init(struct kbase_device *kbdev)
/* Activate clock rate trace manager if at least one GPU clock was
* enumerated.
*/
- if (i)
+ if (i) {
WRITE_ONCE(clk_rtm->clk_rate_trace_ops, callbacks);
- else
+ } else {
dev_info(kbdev->dev, "No clock(s) available for rate tracing");
+ WRITE_ONCE(clk_rtm->clk_rate_trace_ops, NULL);
+ }
return 0;
@@ -284,4 +289,3 @@ void kbase_clk_rate_trace_manager_notify_all(
}
}
KBASE_EXPORT_TEST_API(kbase_clk_rate_trace_manager_notify_all);
-
diff --git a/mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.h b/mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.h
index dcafb26..2e65b6a 100644
--- a/mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.h
+++ b/mali_kbase/backend/gpu/mali_kbase_clk_rate_trace_mgr.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
diff --git a/mali_kbase/backend/gpu/mali_kbase_debug_job_fault_backend.c b/mali_kbase/backend/gpu/mali_kbase_debug_job_fault_backend.c
index 3aadcb0..7a5bfb8 100644
--- a/mali_kbase/backend/gpu/mali_kbase_debug_job_fault_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_debug_job_fault_backend.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2012-2015, 2018-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/backend/gpu/mali_kbase_devfreq.c b/mali_kbase/backend/gpu/mali_kbase_devfreq.c
index 2806f05..2f9015d 100644
--- a/mali_kbase/backend/gpu/mali_kbase_devfreq.c
+++ b/mali_kbase/backend/gpu/mali_kbase_devfreq.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
@@ -32,35 +33,48 @@
#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 +96,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 +123,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,7 +146,8 @@ 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
/* Regulators and clocks work in pairs: every clock has a regulator,
@@ -238,6 +258,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 +273,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 +288,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
@@ -359,7 +383,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.
@@ -493,11 +517,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,12 +576,9 @@ 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);
@@ -569,12 +588,10 @@ void kbase_devfreq_enqueue_work(struct kbase_device *kbdev,
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,15 +601,12 @@ 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
}
int kbase_devfreq_init(struct kbase_device *kbdev)
@@ -657,7 +671,8 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
}
/* 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);
diff --git a/mali_kbase/backend/gpu/mali_kbase_devfreq.h b/mali_kbase/backend/gpu/mali_kbase_devfreq.h
index 8c976b2..ab731b9 100644
--- a/mali_kbase/backend/gpu/mali_kbase_devfreq.h
+++ b/mali_kbase/backend/gpu/mali_kbase_devfreq.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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 _BASE_DEVFREQ_H_
@@ -43,4 +62,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/mali_kbase/backend/gpu/mali_kbase_gpuprops_backend.c b/mali_kbase/backend/gpu/mali_kbase_gpuprops_backend.c
index 60ae020..7e92ffe 100644
--- a/mali_kbase/backend/gpu/mali_kbase_gpuprops_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_gpuprops_backend.c
@@ -42,11 +42,19 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev,
registers.l2_features = kbase_reg_read(kbdev,
GPU_CONTROL_REG(L2_FEATURES));
#if !MALI_USE_CSF
+ /* TGOx */
registers.core_features = kbase_reg_read(kbdev,
GPU_CONTROL_REG(CORE_FEATURES));
#else /* !MALI_USE_CSF */
- registers.core_features = 0;
-#endif /* !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));
+ else
+ registers.core_features = 0;
+#endif /* MALI_USE_CSF */
registers.tiler_features = kbase_reg_read(kbdev,
GPU_CONTROL_REG(TILER_FEATURES));
registers.mem_features = kbase_reg_read(kbdev,
@@ -105,6 +113,16 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev,
registers.stack_present_hi = kbase_reg_read(kbdev,
GPU_CONTROL_REG(STACK_PRESENT_HI));
+ 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;
diff --git a/mali_kbase/backend/gpu/mali_kbase_instr_backend.c b/mali_kbase/backend/gpu/mali_kbase_instr_backend.c
index 7c5001e..f366265 100644
--- a/mali_kbase/backend/gpu/mali_kbase_instr_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_instr_backend.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
@@ -20,8 +21,6 @@
*
*/
-
-
/*
* GPU backend instrumentation APIs.
*/
@@ -39,9 +38,7 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
{
unsigned long flags;
int err = -EINVAL;
-#if !MALI_USE_CSF
u32 irq_mask;
-#endif
u32 prfcnt_config;
lockdep_assert_held(&kbdev->hwaccess_lock);
@@ -58,12 +55,10 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
goto out_err;
}
-#if !MALI_USE_CSF
/* 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 |
PRFCNT_SAMPLE_COMPLETED);
-#endif
/* In use, this context is the owner */
kbdev->hwcnt.kctx = kctx;
@@ -82,29 +77,6 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
prfcnt_config |= enable->counter_set << PRFCNT_CONFIG_SETSELECT_SHIFT;
#endif
-#if MALI_USE_CSF
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_CONFIG),
- prfcnt_config | PRFCNT_CONFIG_MODE_OFF);
-
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_BASE_LO),
- enable->dump_buffer & 0xFFFFFFFF);
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_BASE_HI),
- enable->dump_buffer >> 32);
-
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_CSHW_EN),
- enable->fe_bm);
-
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_SHADER_EN),
- enable->shader_bm);
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_MMU_L2_EN),
- enable->mmu_l2_bm);
-
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_TILER_EN),
- enable->tiler_bm);
-
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_CONFIG),
- prfcnt_config | PRFCNT_CONFIG_MODE_MANUAL);
-#else
kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG),
prfcnt_config | PRFCNT_CONFIG_MODE_OFF);
@@ -126,7 +98,6 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG),
prfcnt_config | PRFCNT_CONFIG_MODE_MANUAL);
-#endif
spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
@@ -148,9 +119,7 @@ int kbase_instr_hwcnt_disable_internal(struct kbase_context *kctx)
{
unsigned long flags, pm_flags;
int err = -EINVAL;
-#if !MALI_USE_CSF
u32 irq_mask;
-#endif
struct kbase_device *kbdev = kctx->kbdev;
while (1) {
@@ -185,10 +154,6 @@ int kbase_instr_hwcnt_disable_internal(struct kbase_context *kctx)
kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DISABLED;
kbdev->hwcnt.backend.triggered = 0;
-#if MALI_USE_CSF
- /* Disable the counters */
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_CONFIG), 0);
-#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),
@@ -196,7 +161,6 @@ int kbase_instr_hwcnt_disable_internal(struct kbase_context *kctx)
/* Disable the counters */
kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG), 0);
-#endif
kbdev->hwcnt.kctx = NULL;
kbdev->hwcnt.addr = 0ULL;
@@ -228,7 +192,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;
}
@@ -238,32 +203,18 @@ int kbase_instr_hwcnt_request_dump(struct kbase_context *kctx)
*/
kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DUMPING;
-
-#if MALI_USE_CSF
- /* Reconfigure the dump address */
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_BASE_LO),
- kbdev->hwcnt.addr & 0xFFFFFFFF);
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(PRFCNT_BASE_HI),
- kbdev->hwcnt.addr >> 32);
-#else
/* Reconfigure the dump address */
kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO),
kbdev->hwcnt.addr & 0xFFFFFFFF);
kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI),
kbdev->hwcnt.addr >> 32);
-#endif
/* Start dumping */
KBASE_KTRACE_ADD(kbdev, CORE_GPU_PRFCNT_SAMPLE, NULL,
kbdev->hwcnt.addr);
-#if MALI_USE_CSF
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(GPU_COMMAND),
- GPU_COMMAND_PRFCNT_SAMPLE);
-#else
kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
GPU_COMMAND_PRFCNT_SAMPLE);
-#endif
dev_dbg(kbdev->dev, "HW counters dumping done for context %p", kctx);
@@ -272,10 +223,6 @@ int kbase_instr_hwcnt_request_dump(struct kbase_context *kctx)
unlock:
spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
-#if MALI_USE_CSF
- tasklet_schedule(&kbdev->hwcnt.backend.csf_hwc_irq_poll_tasklet);
-#endif
-
return err;
}
KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_request_dump);
@@ -304,53 +251,6 @@ bool kbase_instr_hwcnt_dump_complete(struct kbase_context *kctx,
}
KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_complete);
-#if MALI_USE_CSF
-/**
- * kbasep_hwcnt_irq_poll_tasklet - tasklet to poll MCU IRQ status register
- *
- * @data: tasklet parameter which pointer to kbdev
- *
- * This tasklet poll GPU_IRQ_STATUS register in GPU_CONTROL_MCU page to check
- * PRFCNT_SAMPLE_COMPLETED bit.
- *
- * Tasklet is needed here since work_queue is too slow and cuased some test
- * cases timeout, the poll_count variable is introduced to avoid infinite
- * loop in unexpected cases, the poll_count is 1 or 2 in normal case, 128
- * should be big enough to exit the tasklet in abnormal cases.
- *
- * Return: void
- */
-static void kbasep_hwcnt_irq_poll_tasklet(unsigned long int data)
-{
- struct kbase_device *kbdev = (struct kbase_device *)data;
- unsigned long flags, pm_flags;
- u32 mcu_gpu_irq_raw_status = 0;
- u32 poll_count = 0;
-
- while (1) {
- spin_lock_irqsave(&kbdev->hwaccess_lock, pm_flags);
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- mcu_gpu_irq_raw_status = kbase_reg_read(kbdev,
- GPU_CONTROL_MCU_REG(GPU_IRQ_RAWSTAT));
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags);
- if (mcu_gpu_irq_raw_status & PRFCNT_SAMPLE_COMPLETED) {
- kbase_reg_write(kbdev,
- GPU_CONTROL_MCU_REG(GPU_IRQ_CLEAR),
- PRFCNT_SAMPLE_COMPLETED);
- kbase_instr_hwcnt_sample_done(kbdev);
- break;
- } else if (poll_count++ > 128) {
- dev_err(kbdev->dev,
- "Err: HWC dump timeout, count: %u", poll_count);
- /* Still call sample_done to unblock waiting thread */
- kbase_instr_hwcnt_sample_done(kbdev);
- break;
- }
- }
-}
-#endif
-
void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev)
{
unsigned long flags;
@@ -406,20 +306,16 @@ 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;
/* Clear the counters */
KBASE_KTRACE_ADD(kbdev, CORE_GPU_PRFCNT_CLEAR, NULL, 0);
-#if MALI_USE_CSF
- kbase_reg_write(kbdev, GPU_CONTROL_MCU_REG(GPU_COMMAND),
- GPU_COMMAND_PRFCNT_CLEAR);
-#else
kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND),
GPU_COMMAND_PRFCNT_CLEAR);
-#endif
err = 0;
@@ -437,11 +333,6 @@ int kbase_instr_backend_init(struct kbase_device *kbdev)
init_waitqueue_head(&kbdev->hwcnt.backend.wait);
-#if MALI_USE_CSF
- tasklet_init(&kbdev->hwcnt.backend.csf_hwc_irq_poll_tasklet,
- kbasep_hwcnt_irq_poll_tasklet, (unsigned long int)kbdev);
-#endif
-
kbdev->hwcnt.backend.triggered = 0;
#ifdef CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
@@ -460,9 +351,7 @@ int kbase_instr_backend_init(struct kbase_device *kbdev)
void kbase_instr_backend_term(struct kbase_device *kbdev)
{
-#if MALI_USE_CSF
- tasklet_kill(&kbdev->hwcnt.backend.csf_hwc_irq_poll_tasklet);
-#endif
+ (void)kbdev;
}
#ifdef CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS
diff --git a/mali_kbase/backend/gpu/mali_kbase_instr_defs.h b/mali_kbase/backend/gpu/mali_kbase_instr_defs.h
index e4b6280..1344262 100644
--- a/mali_kbase/backend/gpu/mali_kbase_instr_defs.h
+++ b/mali_kbase/backend/gpu/mali_kbase_instr_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2016, 2018, 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 2016, 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 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.
+ *
*/
/*
@@ -52,9 +71,6 @@ struct kbase_instr_backend {
#endif
enum kbase_instr_state state;
-#if MALI_USE_CSF
- struct tasklet_struct csf_hwc_irq_poll_tasklet;
-#endif
};
#endif /* _KBASE_INSTR_DEFS_H_ */
diff --git a/mali_kbase/backend/gpu/mali_kbase_instr_internal.h b/mali_kbase/backend/gpu/mali_kbase_instr_internal.h
index 2254b9f..0716fd4 100644
--- a/mali_kbase/backend/gpu/mali_kbase_instr_internal.h
+++ b/mali_kbase/backend/gpu/mali_kbase_instr_internal.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 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 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 HW access instrumentation APIs
*/
diff --git a/mali_kbase/backend/gpu/mali_kbase_irq_internal.h b/mali_kbase/backend/gpu/mali_kbase_irq_internal.h
index ca3c048..f5ad27b 100644
--- a/mali_kbase/backend/gpu/mali_kbase_irq_internal.h
+++ b/mali_kbase/backend/gpu/mali_kbase_irq_internal.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-2015, 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 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.
+ *
*/
/*
diff --git a/mali_kbase/backend/gpu/mali_kbase_irq_linux.c b/mali_kbase/backend/gpu/mali_kbase_irq_linux.c
index f6cf6a1..07ab5df 100644
--- a/mali_kbase/backend/gpu/mali_kbase_irq_linux.c
+++ b/mali_kbase/backend/gpu/mali_kbase_irq_linux.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2016,2018-2020 ARM Limited. All rights reserved.
@@ -215,20 +216,21 @@ 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);
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_as.c b/mali_kbase/backend/gpu/mali_kbase_jm_as.c
index 9b77589..87c4bd1 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_as.c
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_as.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
@@ -20,7 +21,6 @@
*
*/
-
/*
* Register backend context / address space management
*/
@@ -190,8 +190,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/mali_kbase/backend/gpu/mali_kbase_jm_defs.h b/mali_kbase/backend/gpu/mali_kbase_jm_defs.h
index 7d6c814..c6fad21 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_defs.h
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
/*
@@ -92,13 +111,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/mali_kbase/backend/gpu/mali_kbase_jm_hw.c b/mali_kbase/backend/gpu/mali_kbase_jm_hw.c
index 3658748..d1f2eef 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_hw.c
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_hw.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
@@ -205,7 +206,8 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
affinity = kbase_job_write_affinity(kbdev, katom->core_req, js);
/* 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) &&
@@ -331,7 +333,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;
}
}
@@ -374,9 +377,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);
@@ -388,7 +391,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));
@@ -402,7 +406,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,
@@ -411,18 +416,21 @@ 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))
@@ -483,7 +491,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);
}
}
@@ -585,7 +594,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 */
@@ -1020,6 +1030,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;
@@ -1086,13 +1123,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);
@@ -1113,14 +1152,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 */
@@ -1131,7 +1172,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))
;
@@ -1146,14 +1188,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);
@@ -1192,7 +1236,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);
@@ -1269,7 +1314,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) {
@@ -1362,7 +1408,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,
@@ -1385,7 +1432,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,
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_internal.h b/mali_kbase/backend/gpu/mali_kbase_jm_internal.h
index cd1f979..cfb26ee 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_internal.h
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_internal.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2016, 2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-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 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.
+ *
*/
-
-
/*
* Job Manager backend-specific low-level APIs.
*/
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_rb.c b/mali_kbase/backend/gpu/mali_kbase_jm_rb.c
index afaaef2..cf96a86 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_rb.c
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_rb.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
@@ -20,7 +21,6 @@
*
*/
-
/*
* Register-based HW access backend specific APIs
*/
@@ -40,10 +40,12 @@
#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,
@@ -284,7 +286,8 @@ static void kbase_gpu_release_atom(struct kbase_device *kbdev,
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);
@@ -544,7 +547,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
@@ -570,19 +574,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;
@@ -722,7 +722,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));
@@ -768,8 +769,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);
@@ -912,12 +913,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);
@@ -948,7 +951,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 !=
@@ -964,7 +968,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))
@@ -976,7 +981,8 @@ 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);
@@ -987,7 +993,8 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
/* 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);
@@ -1000,7 +1007,8 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
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);
@@ -1103,7 +1111,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;
}
@@ -1184,7 +1193,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);
@@ -1271,7 +1281,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);
}
@@ -1322,7 +1333,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;
}
@@ -1425,7 +1437,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 &&
@@ -1472,7 +1485,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,
@@ -1481,7 +1495,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),
@@ -1496,7 +1511,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);
@@ -1510,7 +1526,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);
@@ -1529,7 +1546,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;
@@ -1557,7 +1575,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);
@@ -1567,13 +1586,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);
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_rb.h b/mali_kbase/backend/gpu/mali_kbase_jm_rb.h
index c3b9f2d..1633d6e 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_rb.h
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_rb.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,9 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
-
/*
* Register-based HW access backend specific APIs
*/
diff --git a/mali_kbase/backend/gpu/mali_kbase_js_backend.c b/mali_kbase/backend/gpu/mali_kbase_js_backend.c
index 67c51c7..fb38510 100644
--- a/mali_kbase/backend/gpu/mali_kbase_js_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_js_backend.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
@@ -20,7 +21,6 @@
*
*/
-
/*
* Register-based HW access backend specific job scheduler APIs
*/
@@ -48,7 +48,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
@@ -114,7 +115,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++;
@@ -142,7 +144,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;
@@ -172,10 +175,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 |=
@@ -287,11 +291,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);
}
diff --git a/mali_kbase/backend/gpu/mali_kbase_js_internal.h b/mali_kbase/backend/gpu/mali_kbase_js_internal.h
index 6576e55..a48b4ea 100644
--- a/mali_kbase/backend/gpu/mali_kbase_js_internal.h
+++ b/mali_kbase/backend/gpu/mali_kbase_js_internal.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
+ * (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
@@ -18,9 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-2015, 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 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.
+ *
*/
-
/*
* Register-based HW access backend specific job scheduler APIs
*/
diff --git a/mali_kbase/backend/gpu/mali_kbase_l2_mmu_config.h b/mali_kbase/backend/gpu/mali_kbase_l2_mmu_config.h
index 0c779ac..3d277ac 100644
--- a/mali_kbase/backend/gpu/mali_kbase_l2_mmu_config.h
+++ b/mali_kbase/backend/gpu/mali_kbase_l2_mmu_config.h
@@ -20,12 +20,13 @@
*
*//* 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/mali_kbase/backend/gpu/mali_kbase_pm_always_on.c b/mali_kbase/backend/gpu/mali_kbase_pm_always_on.c
index e33fe0b..c694e9a 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_always_on.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_always_on.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2010-2015, 2018-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2015, 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
@@ -20,8 +21,6 @@
*
*/
-
-
/*
* "Always on" power management policy
*/
@@ -62,6 +61,9 @@ const struct kbase_pm_policy kbase_pm_always_on_policy_ops = {
always_on_shaders_needed, /* shaders_needed */
always_on_get_core_active, /* get_core_active */
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/mali_kbase/backend/gpu/mali_kbase_pm_always_on.h b/mali_kbase/backend/gpu/mali_kbase_pm_always_on.h
index e7927cf..332c09d 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_always_on.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_always_on.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2015,2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-2015, 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 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.
+ *
*/
-
-
/*
* "Always on" power management policy
*/
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_backend.c b/mali_kbase/backend/gpu/mali_kbase_pm_backend.c
index bb11d68..1e90c6a 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_backend.c
@@ -1,4 +1,5 @@
- /*
+// SPDX-License-Identifier: GPL-2.0
+/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
*
@@ -20,7 +21,6 @@
*
*/
-
/*
* GPU backend implementation of base kernel power management APIs
*/
@@ -162,6 +162,8 @@ int kbase_hwaccess_pm_init(struct kbase_device *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.
*/
@@ -240,7 +242,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) {
@@ -258,7 +261,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)
@@ -572,7 +576,8 @@ 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);
@@ -598,7 +603,8 @@ int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev,
#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,
@@ -610,7 +616,8 @@ 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
@@ -643,6 +650,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);
@@ -671,6 +680,12 @@ void kbase_hwaccess_pm_term(struct kbase_device *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);
@@ -737,7 +752,8 @@ 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);
@@ -783,6 +799,9 @@ void kbase_pm_handle_gpu_lost(struct kbase_device *kbdev)
ktime_t end_timestamp = ktime_get();
struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
+ if (!kbdev->arb.arb_if)
+ return;
+
mutex_lock(&kbdev->pm.lock);
mutex_lock(&arb_vm_state->vm_state_lock);
if (kbdev->pm.backend.gpu_powered &&
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_ca.c b/mali_kbase/backend/gpu/mali_kbase_pm_ca.c
index 02dfdb0..975f42d 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_ca.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_ca.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2013-2018, 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_ca.h b/mali_kbase/backend/gpu/mali_kbase_pm_ca.h
index 5423e96..af91624 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_ca.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_ca.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-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 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.
+ *
*/
/*
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.h b/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.h
index f67ec65..49a964c 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/*
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c b/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c
index 9eef44a..5317a38 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2012-2016, 2018-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2012-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
@@ -20,8 +21,6 @@
*
*/
-
-
/*
* "Coarse Demand" power management policy
*/
@@ -61,6 +60,9 @@ const struct kbase_pm_policy kbase_pm_coarse_demand_policy_ops = {
coarse_demand_shaders_needed, /* shaders_needed */
coarse_demand_get_core_active, /* get_core_active */
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/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.h b/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.h
index 304e5d7..fe17fd3 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2015,2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-2015, 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 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.
+ *
*/
-
-
/*
* "Coarse Demand" power management policy
*/
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_defs.h b/mali_kbase/backend/gpu/mali_kbase_pm_defs.h
index d7d8f75..2a4f3ac 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_defs.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
/*
@@ -166,21 +185,29 @@ 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.
+ * @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
+#if MALI_USE_CSF
+ /*
+ * The amount of time the GPU has spent in protected mode since
+ * the time_period_start timestamp, measured in units of 256ns.
+ */
+ u32 time_in_protm;
+#else
u32 busy_cl[2];
u32 busy_gl;
#endif
@@ -201,6 +228,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
@@ -212,6 +240,10 @@ struct kbasep_pm_metrics_state {
#if MALI_USE_CSF
/* Handle returned on registering DVFS as a kbase_ipa_control client */
void *ipa_control_client;
+ /* Decide whether to skip GPU_ACTIVE sanity check in DVFS utilisation
+ * calculation
+ */
+ bool skip_gpu_active_sanity_check;
#else
bool gpu_active;
u32 active_cl_ctx[2];
@@ -225,6 +257,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;
@@ -461,6 +494,21 @@ struct kbase_pm_backend_data {
#if MALI_USE_CSF
/* True if the micro-control unit should be powered on */
bool mcu_desired;
+ /* 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.
+ */
+ bool policy_change_clamp_state_to_off;
+ /* CSF Dynamic PM control flags in accordance to the current active PM
+ * policy. This field is updated whenever a new policy is activated.
+ */
+ unsigned int csf_pm_sched_flags;
+ /* 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. This mutex lock is to serialize such
+ * sequence.
+ */
+ struct mutex policy_change_lock;
#endif
bool l2_desired;
bool l2_always_on;
@@ -485,6 +533,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 {
@@ -564,6 +629,15 @@ struct kbase_pm_policy {
bool (*get_core_active)(struct kbase_device *kbdev);
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/mali_kbase/backend/gpu/mali_kbase_pm_driver.c b/mali_kbase/backend/gpu/mali_kbase_pm_driver.c
index 420d5c5..f67e8b3 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_driver.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_driver.c
@@ -32,9 +32,13 @@
#include <mali_kbase_pm.h>
#include <mali_kbase_config_defaults.h>
#include <mali_kbase_smc.h>
-#if !MALI_USE_CSF
+
+#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>
@@ -106,13 +110,13 @@ bool kbase_pm_is_mcu_desired(struct kbase_device *kbdev)
return true;
/* MCU is supposed to be ON, only when scheduler.pm_active_count is
- * non zero. But for always_on policy also MCU needs to be ON.
- * GPUCORE-24926 will add the proper handling for always_on
- * power policy.
+ * 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 &&
- (kbdev->pm.backend.pm_current_policy ==
- &kbase_pm_always_on_policy_ops));
+ kbase_pm_no_mcu_core_pwroff(kbdev) &&
+ !kbdev->pm.backend.policy_change_clamp_state_to_off);
}
#endif
@@ -129,6 +133,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;
}
@@ -260,7 +269,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));
@@ -495,14 +505,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);
}
}
@@ -520,7 +526,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));
@@ -531,13 +538,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);
}
@@ -564,14 +583,33 @@ static const char *kbase_mcu_state_to_string(enum kbase_mcu_state state)
return strings[state];
}
-static inline void kbase_pm_mcu_update_core_mask(struct kbase_device *kbdev)
+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(kbdev->pm.backend.mcu_state != KBASE_MCU_ON);
- kbase_csf_firmware_update_core_mask(kbdev,
- kbdev->pm.backend.shaders_desired_mask);
- kbdev->pm.backend.mcu_state = KBASE_MCU_ON_CORE_MASK_UPDATE_PEND;
+ 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)
@@ -591,11 +629,20 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
}
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;
@@ -607,7 +654,7 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
backend->shaders_desired_mask =
kbase_pm_ca_get_core_mask(kbdev);
kbase_csf_firmware_global_reinit(kbdev,
- backend->shaders_desired_mask);
+ backend->shaders_desired_mask);
backend->mcu_state =
KBASE_MCU_ON_GLB_REINIT_PEND;
}
@@ -616,11 +663,37 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
case KBASE_MCU_ON_GLB_REINIT_PEND:
if (kbase_csf_firmware_global_reinit_complete(kbdev)) {
backend->shaders_avail =
- backend->shaders_desired_mask;
- backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE;
+ 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) {
@@ -632,19 +705,53 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
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 {
- backend->shaders_desired_mask =
- kbase_pm_ca_get_core_mask(kbdev);
- if (unlikely(backend->shaders_avail !=
- backend->shaders_desired_mask))
- kbase_pm_mcu_update_core_mask(kbdev);
+ 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_MASK_UPDATE_PEND:
- if (kbase_csf_firmware_core_mask_updated(kbdev)) {
+ 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;
@@ -669,14 +776,32 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
if (!kbase_pm_is_mcu_desired(kbdev)) {
kbase_csf_firmware_trigger_mcu_halt(kbdev);
backend->mcu_state = KBASE_MCU_ON_PEND_HALT;
- } else if (kbase_pm_is_mcu_desired(kbdev)) {
+ } else
backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE;
- }
break;
case KBASE_MCU_ON_PEND_HALT:
- if (kbase_csf_firmware_mcu_halted(kbdev))
+ 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:
@@ -1701,7 +1826,8 @@ 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. */
+ * 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)
@@ -1759,6 +1885,15 @@ static void kbase_pm_timed_out(struct kbase_device *kbdev)
kbase_reg_read(kbdev, GPU_CONTROL_REG(
L2_PWRTRANS_LO)));
+#if MALI_USE_CSF
+ /* PM timeout probably means hardware counters will stop working.
+ * Put the backend into the unrecoverable error state to cause
+ * current and subsequent counter operations to immediately
+ * fail, avoiding the risk of a hang.
+ */
+ kbase_hwcnt_backend_csf_on_unrecoverable_error(&kbdev->hwcnt_gpu_iface);
+#endif
+
dev_err(kbdev->dev, "Sending reset to GPU - all running jobs will be lost\n");
if (kbase_prepare_to_reset_gpu(kbdev))
kbase_reset_gpu(kbdev);
@@ -1828,7 +1963,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.
@@ -1854,7 +1989,7 @@ 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.
@@ -1908,7 +2043,7 @@ 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 */
@@ -1953,21 +2088,24 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume)
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 {
- struct kbase_arbiter_vm_state *arb_vm_state =
+ 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);
+ /* 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);
+ }
}
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
@@ -2014,7 +2152,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. */
@@ -2038,7 +2176,8 @@ 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;
}
@@ -2119,7 +2258,8 @@ static enum hrtimer_restart kbasep_reset_timeout(struct hrtimer *timer)
rtdata->timed_out = 1;
/* 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;
@@ -2386,11 +2526,13 @@ 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)) {
/* 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);
@@ -2404,33 +2546,40 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev)
}
/* 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 = 0;
- 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 == 0) {
+ /* 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;
}
@@ -2454,7 +2603,7 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
unsigned long irq_flags;
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 */
@@ -2466,7 +2615,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);
@@ -2487,6 +2637,12 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
kbdev->protected_dev);
spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags);
+#if MALI_USE_CSF
+ if (kbdev->protected_mode) {
+ kbase_ipa_control_protm_exited(kbdev);
+ kbase_hwcnt_backend_csf_protm_exited(&kbdev->hwcnt_gpu_iface);
+ }
+#endif
kbdev->protected_mode = false;
spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags);
@@ -2507,7 +2663,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);
@@ -2565,7 +2722,7 @@ kbase_pm_request_gpu_cycle_counter_do_request(struct kbase_device *kbdev)
++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);
@@ -2617,7 +2774,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/mali_kbase/backend/gpu/mali_kbase_pm_internal.h b/mali_kbase/backend/gpu/mali_kbase_pm_internal.h
index 9f02dd4..304ecda 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_internal.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_internal.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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.
+ *
*/
-
-
/*
* Power management API definitions used internally by GPU backend
*/
@@ -492,7 +509,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
@@ -724,6 +742,59 @@ bool kbase_pm_is_l2_desired(struct kbase_device *kbdev);
* 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
/**
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_l2_states.h b/mali_kbase/backend/gpu/mali_kbase_pm_l2_states.h
index 12cb051..90a46fa 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_l2_states.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_l2_states.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/*
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_mcu_states.h b/mali_kbase/backend/gpu/mali_kbase_pm_mcu_states.h
index bc3e6b1..95e68df 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_mcu_states.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_mcu_states.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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.
+ *
*/
/*
@@ -31,10 +50,16 @@ 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_MASK_UPDATE_PEND)
+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/mali_kbase/backend/gpu/mali_kbase_pm_metrics.c b/mali_kbase/backend/gpu/mali_kbase_pm_metrics.c
index dc07412..5c42c0a 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_metrics.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_metrics.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
@@ -20,8 +21,6 @@
*
*/
-
-
/*
* Metrics for power management
*/
@@ -42,13 +41,11 @@
/* 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
-/* CSHW counter block offsets */
-#define GPU_ACTIVE (4)
-
/* To get the GPU_ACTIVE value in nano seconds unit */
#define GPU_ACTIVE_SCALING_FACTOR ((u64)1E9)
#endif
@@ -91,6 +88,7 @@ int kbasep_pm_metrics_init(struct kbase_device *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;
@@ -101,7 +99,7 @@ int kbasep_pm_metrics_init(struct kbase_device *kbdev)
perf_counter.type = KBASE_IPA_CORE_TYPE_CSHW;
/* We need the GPU_ACTIVE counter */
- perf_counter.idx = GPU_ACTIVE;
+ perf_counter.idx = GPU_ACTIVE_CNT_IDX;
err = kbase_ipa_control_register(
kbdev, &perf_counter, NUM_PERF_COUNTERS,
@@ -137,10 +135,18 @@ int kbasep_pm_metrics_init(struct kbase_device *kbdev)
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);
@@ -157,6 +163,7 @@ 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
@@ -172,42 +179,111 @@ KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term);
*/
#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,
- ktime_t now)
+static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev)
{
- ktime_t diff;
int err;
u64 gpu_active_counter;
+ u64 protected_time;
+ ktime_t now;
lockdep_assert_held(&kbdev->pm.backend.metrics.lock);
- diff = ktime_sub(now, kbdev->pm.backend.metrics.time_period_start);
- if (ktime_to_ns(diff) < 0)
- return;
-
- /* TODO: The final parameter to this function is used to obtain the amount of
- * protected-mode time the GPU has spent. This is the subject of a future
- * ticket, and is not yet considered / implemented.
+ /* 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, NULL);
+ &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 {
- u32 ns_time = (u32) (ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT);
+ u64 diff_ns, margin_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;
+
+ /* Use a margin value that is approximately 1% of the time
+ * difference.
+ */
+ margin_ns = diff_ns >> 6;
+
+ /* Calculate time difference in units of 256ns */
+ ns_time = (u32)(diff_ns >> KBASE_PM_TIME_SHIFT);
+
+#ifndef 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) {
+ 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);
+ }
+ }
+#else
+ CSTD_UNUSED(margin_ns);
+#endif
+ /* 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;
- WARN_ON_ONCE(gpu_active_counter > ns_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;
@@ -240,8 +316,8 @@ 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;
@@ -257,13 +333,19 @@ 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
+#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;
@@ -291,7 +373,8 @@ void kbase_pm_get_dvfs_action(struct kbase_device *kbdev)
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);
@@ -303,8 +386,15 @@ void kbase_pm_get_dvfs_action(struct kbase_device *kbdev)
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
}
@@ -327,11 +417,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);
}
@@ -339,11 +438,20 @@ 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);
}
@@ -374,7 +482,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);
@@ -413,8 +522,8 @@ void kbase_pm_metrics_update(struct kbase_device *kbdev, ktime_t *timestamp)
timestamp = &now;
}
- /* 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
+ /* 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);
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_policy.c b/mali_kbase/backend/gpu/mali_kbase_pm_policy.c
index 426e8a4..60eae35 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_policy.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_policy.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
@@ -28,6 +29,11 @@
#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>
+
+#if MALI_USE_CSF && defined CONFIG_MALI_DEBUG
+#include <csf/mali_kbase_csf_firmware.h>
+#endif
static const struct kbase_pm_policy *const all_policy_list[] = {
#ifdef CONFIG_MALI_NO_MALI
@@ -45,11 +51,43 @@ static const struct kbase_pm_policy *const all_policy_list[] = {
#endif /* CONFIG_MALI_NO_MALI */
};
+#if MALI_USE_CSF
+void kbase_pm_policy_init(struct kbase_device *kbdev)
+{
+ unsigned long flags;
+ const struct kbase_pm_policy *default_policy = all_policy_list[0];
+
+#if 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);
+
+ 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 /* MALI_USE_CSF */
void kbase_pm_policy_init(struct kbase_device *kbdev)
{
kbdev->pm.backend.pm_current_policy = all_policy_list[0];
+
+#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)
+ kbdev->pm.backend.pm_current_policy =
+ &kbase_pm_always_on_policy_ops;
+#endif
kbdev->pm.backend.pm_current_policy->init(kbdev);
}
+#endif /* MALI_USE_CSF */
void kbase_pm_policy_term(struct kbase_device *kbdev)
{
@@ -102,7 +140,8 @@ void kbase_pm_update_active(struct kbase_device *kbdev)
}
} 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;
@@ -167,7 +206,8 @@ 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);
@@ -219,20 +259,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);
@@ -253,19 +379,40 @@ void kbase_pm_set_policy(struct kbase_device *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))
+ 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/mali_kbase/backend/gpu/mali_kbase_pm_policy.h b/mali_kbase/backend/gpu/mali_kbase_pm_policy.h
index f103ef0..d566d9b 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_policy.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_policy.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2015, 2018-2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-2015, 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 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.
+ *
*/
/*
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_shader_states.h b/mali_kbase/backend/gpu/mali_kbase_pm_shader_states.h
index 6cafaa1..dafb117 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_shader_states.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_shader_states.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018-2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/*
diff --git a/mali_kbase/backend/gpu/mali_kbase_time.c b/mali_kbase/backend/gpu/mali_kbase_time.c
index e19f53b..557b595 100644
--- a/mali_kbase/backend/gpu/mali_kbase_time.c
+++ b/mali_kbase/backend/gpu/mali_kbase_time.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2016,2018-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/build.bp b/mali_kbase/build.bp
index b8d8310..3afd42b 100644
--- a/mali_kbase/build.bp
+++ b/mali_kbase/build.bp
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
*
* (C) COPYRIGHT 2017-2020 ARM Limited. All rights reserved.
@@ -5,11 +6,16 @@
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the 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.
*
*/
diff --git a/mali_kbase/context/backend/mali_kbase_context_csf.c b/mali_kbase/context/backend/mali_kbase_context_csf.c
index 6476921..da8cfc1 100644
--- a/mali_kbase/context/backend/mali_kbase_context_csf.c
+++ b/mali_kbase/context/backend/mali_kbase_context_csf.c
@@ -32,6 +32,7 @@
#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>
#ifdef CONFIG_DEBUG_FS
#include <csf/mali_kbase_csf_csg_debugfs.h>
@@ -72,24 +73,34 @@ void kbase_context_debugfs_term(struct kbase_context *const 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[] = {
- {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"},
- {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"},
+ { 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(
@@ -133,14 +144,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;
}
@@ -163,9 +183,8 @@ void kbase_destroy_context(struct kbase_context *kctx)
/* Context termination could happen whilst the system suspend of
* the GPU device is ongoing or has completed. It has been seen on
- * Customer side for JM GPUs that a hang could occur if context
- * termination is not blocked until the resume of GPU device.
- * Similar issue can potentially occur on CSF GPUs also.
+ * 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)) {
diff --git a/mali_kbase/context/backend/mali_kbase_context_jm.c b/mali_kbase/context/backend/mali_kbase_context_jm.c
index a8cefb6..d0111be 100644
--- a/mali_kbase/context/backend/mali_kbase_context_jm.c
+++ b/mali_kbase/context/backend/mali_kbase_context_jm.c
@@ -1,7 +1,7 @@
// 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
@@ -35,7 +35,6 @@
#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
#include <mali_kbase_debug_mem_view.h>
@@ -47,14 +46,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
@@ -73,12 +70,7 @@ KBASE_EXPORT_SYMBOL(kbase_context_debugfs_term);
static int kbase_context_kbase_kinstr_jm_init(struct kbase_context *kctx)
{
- int ret = kbase_kinstr_jm_init(&kctx->kinstr_jm);
-
- if (!ret)
- return ret;
-
- return 0;
+ return kbase_kinstr_jm_init(&kctx->kinstr_jm);
}
static void kbase_context_kbase_kinstr_jm_term(struct kbase_context *kctx)
@@ -114,12 +106,27 @@ 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 },
+ { 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 goup initialization failed" },
+ "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,
@@ -134,13 +141,22 @@ static const struct kbase_context_init context_init[] = {
{ kbase_context_kbase_kinstr_jm_init,
kbase_context_kbase_kinstr_jm_term,
"JM instrumentation initialization failed" },
- { kbase_context_kbase_timer_setup, NULL, NULL },
+ { 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, NULL },
+ { kbase_context_submit_check, NULL, "Enabling job submission failed" },
+#ifdef 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" },
};
static void kbase_context_term_partial(
@@ -184,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;
}
@@ -217,19 +242,22 @@ void kbase_destroy_context(struct kbase_context *kctx)
* Customer side that a hang could occur if context termination is
* not blocked until the resume of GPU device.
*/
+#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_info(kbdev->dev,
+ 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/mali_kbase/context/mali_kbase_context.c b/mali_kbase/context/mali_kbase_context.c
index 5de4c6b..9ab254c 100644
--- a/mali_kbase/context/mali_kbase_context.c
+++ b/mali_kbase/context/mali_kbase_context.c
@@ -30,7 +30,6 @@
#include <mali_kbase_mem_linux.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>
@@ -169,22 +168,49 @@ int kbase_context_common_init(struct kbase_context *kctx)
mutex_init(&kctx->legacy_hwcnt_lock);
mutex_lock(&kctx->kbdev->kctx_list_lock);
- list_add(&kctx->kctx_list_link, &kctx->kbdev->kctx_list);
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);
- 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));
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.
@@ -237,24 +263,9 @@ void kbase_context_common_term(struct kbase_context *kctx)
mutex_lock(&kctx->kbdev->kctx_list_lock);
kbase_remove_kctx_from_process(kctx);
-
- KBASE_TLSTREAM_TL_KBASE_DEL_CTX(kctx->kbdev, kctx->id);
-
- KBASE_TLSTREAM_TL_DEL_CTX(kctx->kbdev, kctx);
- list_del(&kctx->kctx_list_link);
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)
diff --git a/mali_kbase/context/mali_kbase_context.h b/mali_kbase/context/mali_kbase_context.h
index e4ed894..895ca4b 100644
--- a/mali_kbase/context/mali_kbase_context.h
+++ b/mali_kbase/context/mali_kbase_context.h
@@ -21,12 +21,21 @@
*//* SPDX-License-Identifier: GPL-2.0 */
/*
*
- * (C) COPYRIGHT 2011-2017, 2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-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.
+ * of such 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.
*
*/
@@ -117,25 +126,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/mali_kbase/context/mali_kbase_context_internal.h b/mali_kbase/context/mali_kbase_context_internal.h
index 818cdbe..5a901d2 100644
--- a/mali_kbase/context/mali_kbase_context_internal.h
+++ b/mali_kbase/context/mali_kbase_context_internal.h
@@ -20,12 +20,23 @@
*
*//* SPDX-License-Identifier: GPL-2.0 */
/*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ *
+ * (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
+ * 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>
@@ -58,3 +69,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/mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.c b/mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.c
index 66ac377..ad14cb5 100644
--- a/mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.c
+++ b/mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -19,6 +20,7 @@
* SPDX-License-Identifier: GPL-2.0
*
*/
+
#include <mali_kbase.h>
#include "mali_kbase_clk_rate_trace_mgr.h"
#include "mali_kbase_csf_ipa_control.h"
@@ -45,14 +47,23 @@
/**
* Default value for the TIMER register of the IPA Control interface,
- * expressed as number of clock cycles.
+ * 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_CLK_CYCLES ((u32)1000)
+#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)100000000)
+#define IPA_INACTIVE_MAX_LOOPS ((unsigned int)8000000)
/**
* Number of bits used to configure a performance counter in SELECT registers.
@@ -76,14 +87,19 @@ struct kbase_ipa_control_listener_data {
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.
+ * 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));
@@ -285,6 +301,15 @@ kbase_ipa_control_rate_change_notify(struct kbase_clk_rate_listener *listener,
}
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);
@@ -499,6 +524,14 @@ int kbase_ipa_control_register(
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++;
}
@@ -528,8 +561,9 @@ int kbase_ipa_control_register(
COMMAND_SAMPLE);
ret = wait_status(kbdev, STATUS_COMMAND_ACTIVE);
if (!ret) {
- kbase_reg_write(kbdev, IPA_CONTROL_REG(TIMER),
- TIMER_DEFAULT_VALUE_CLK_CYCLES);
+ 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",
@@ -680,8 +714,7 @@ int kbase_ipa_control_query(struct kbase_device *kbdev, const void *client,
gpu_ready = kbdev->pm.backend.gpu_ready;
for (i = 0; i < session->num_prfcnts; i++) {
- struct kbase_ipa_control_prfcnt *prfcnt =
- &session->prfcnts[i];
+ struct kbase_ipa_control_prfcnt *prfcnt = &session->prfcnts[i];
calc_prfcnt_delta(kbdev, prfcnt, gpu_ready);
/* Return all the accumulated difference */
@@ -689,14 +722,28 @@ int kbase_ipa_control_query(struct kbase_device *kbdev, const void *client,
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;
- if (protected_time)
- *protected_time = 0;
-
return 0;
}
KBASE_EXPORT_TEST_API(kbase_ipa_control_query);
@@ -774,7 +821,7 @@ void kbase_ipa_control_handle_gpu_power_on(struct kbase_device *kbdev)
/* Re-enable the timer for periodic sampling */
kbase_reg_write(kbdev, IPA_CONTROL_REG(TIMER),
- TIMER_DEFAULT_VALUE_CLK_CYCLES);
+ timer_value(ipa_ctrl->cur_gpu_rate));
spin_unlock(&ipa_ctrl->lock);
}
@@ -832,3 +879,49 @@ void kbase_ipa_control_rate_change_notify_test(struct kbase_device *kbdev,
}
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/mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.h b/mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.h
index ef93ff3..441c2bd 100644
--- a/mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.h
+++ b/mali_kbase/csf/ipa_control/mali_kbase_csf_ipa_control.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
@@ -214,4 +233,32 @@ 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/mali_kbase/csf/mali_base_csf_kernel.h b/mali_kbase/csf/mali_base_csf_kernel.h
index bc356d1..d9ea65e 100644
--- a/mali_kbase/csf/mali_base_csf_kernel.h
+++ b/mali_kbase/csf/mali_base_csf_kernel.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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 _BASE_CSF_KERNEL_H_
@@ -320,14 +339,16 @@ enum base_kcpu_command_type {
/**
* 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_COUNT: Number of GPU Command Queue Group
- * priority levels.
+ * @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
@@ -342,6 +363,7 @@ 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
};
diff --git a/mali_kbase/csf/mali_gpu_csf_control_registers.h b/mali_kbase/csf/mali_gpu_csf_control_registers.h
index 4fff80c..9b8a9bf 100644
--- a/mali_kbase/csf/mali_gpu_csf_control_registers.h
+++ b/mali_kbase/csf/mali_gpu_csf_control_registers.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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.
+ *
*/
/*
diff --git a/mali_kbase/csf/mali_gpu_csf_registers.h b/mali_kbase/csf/mali_gpu_csf_registers.h
index 281c9c2..d06b38d 100644
--- a/mali_kbase/csf/mali_gpu_csf_registers.h
+++ b/mali_kbase/csf/mali_gpu_csf_registers.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/*
@@ -115,6 +134,8 @@
#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 */
@@ -207,6 +228,7 @@
#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 */
@@ -228,6 +250,7 @@
#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 */
@@ -237,6 +260,10 @@
/* 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
@@ -545,6 +572,39 @@
(((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)
@@ -1079,6 +1139,19 @@
#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)
@@ -1182,6 +1255,20 @@
#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) \
@@ -1301,4 +1388,14 @@
#define GLB_IDLE_TIMER_TIMER_SOURCE_GPU_COUNTER 0x1
/* End of GLB_IDLE_TIMER_TIMER_SOURCE values */
+#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 /* _GPU_CSF_REGISTERS_H_ */
diff --git a/mali_kbase/csf/mali_kbase_csf.c b/mali_kbase/csf/mali_kbase_csf.c
index b75cae3..4c6bb06 100644
--- a/mali_kbase/csf/mali_kbase_csf.c
+++ b/mali_kbase/csf/mali_kbase_csf.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -26,11 +27,13 @@
#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 "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)
@@ -55,6 +58,19 @@ struct kbase_csf_event {
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)
{
@@ -502,6 +518,9 @@ int kbase_csf_queue_register(struct kbase_context *kctx,
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);
@@ -523,10 +542,21 @@ static void unbind_queue(struct kbase_context *kctx,
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;
- mutex_lock(&kctx->csf.lock);
+ 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) {
@@ -556,9 +586,9 @@ void kbase_csf_queue_terminate(struct kbase_context *kctx,
kbase_gpu_vm_unlock(kctx);
spin_lock_irqsave(&kctx->csf.event_lock, flags);
- /* Remove any pending command queue fatal from
- * the per-context list.
- */
+ dev_dbg(kctx->kbdev->dev,
+ "Remove any pending command queue fatal from context %p\n",
+ (void *)kctx);
list_del_init(&queue->error.link);
spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
@@ -566,6 +596,8 @@ void kbase_csf_queue_terminate(struct kbase_context *kctx,
}
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)
@@ -680,7 +712,8 @@ void kbase_csf_ring_cs_user_doorbell(struct kbase_device *kbdev,
}
void kbase_csf_ring_cs_kernel_doorbell(struct kbase_device *kbdev,
- int csi_index, int csg_nr)
+ int csi_index, int csg_nr,
+ bool ring_csg_doorbell)
{
struct kbase_csf_cmd_stream_group_info *ginfo;
u32 value;
@@ -700,18 +733,28 @@ void kbase_csf_ring_cs_kernel_doorbell(struct kbase_device *kbdev,
kbase_csf_firmware_csg_input_mask(ginfo, CSG_DB_REQ, value,
1 << csi_index);
- kbase_csf_ring_csg_doorbell(kbdev, csg_nr);
+ 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;
- mutex_lock(&kctx->csf.lock);
+ 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;
@@ -726,8 +769,9 @@ int kbase_csf_queue_kick(struct kbase_context *kctx,
if (!err)
err = kbase_csf_scheduler_queue_start(queue);
-
mutex_unlock(&kctx->csf.lock);
+ kbase_reset_gpu_allow(kbdev);
+
return err;
}
@@ -777,6 +821,7 @@ static void unbind_stopped_queue(struct kbase_context *kctx,
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) {
@@ -800,6 +845,20 @@ void kbase_csf_queue_unbind(struct kbase_queue *queue)
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
*
@@ -1095,7 +1154,8 @@ static int create_queue_group(struct kbase_context *const kctx,
group->tiler_max = create->in.tiler_max;
group->fragment_max = create->in.fragment_max;
group->compute_max = create->in.compute_max;
- group->priority = create->in.priority;
+ 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;
@@ -1282,6 +1342,7 @@ 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 */
@@ -1304,6 +1365,18 @@ 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);
@@ -1313,7 +1386,11 @@ void kbase_csf_queue_group_terminate(struct kbase_context *kctx,
unsigned long flags;
spin_lock_irqsave(&kctx->csf.event_lock, flags);
- /* Remove any pending group fatal error from the per-context list. */
+
+ dev_dbg(kbdev->dev,
+ "Remove any pending group fatal error from context %p\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);
@@ -1324,6 +1401,8 @@ void kbase_csf_queue_group_terminate(struct kbase_context *kctx,
}
mutex_unlock(&kctx->csf.lock);
+ if (reset_prevented)
+ kbase_reset_gpu_allow(kbdev);
if (!group)
return;
@@ -1341,26 +1420,80 @@ int kbase_csf_queue_group_suspend(struct kbase_context *kctx,
struct kbase_suspend_copy_buffer *sus_buf,
u8 group_handle)
{
- int err = -EINVAL;
+ 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;
}
-void kbase_csf_add_fatal_error_to_kctx(
+/**
+ * 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 %p of type %d in context %p\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;
- unsigned long flags;
if (WARN_ON(!group))
return;
@@ -1378,18 +1511,7 @@ void kbase_csf_add_fatal_error_to_kctx(
}
};
- spin_lock_irqsave(&group->kctx->csf.event_lock, flags);
-
- /* If this group has already been in fatal error status,
- * subsequent fatal error on this group should never take place.
- */
- if (!WARN_ON(!list_empty(&group->error_fatal.link))) {
- group->error_fatal.data = error;
- list_add_tail(&group->error_fatal.link,
- &group->kctx->csf.error_list);
- }
-
- spin_unlock_irqrestore(&group->kctx->csf.event_lock, flags);
+ add_error(group->kctx, &group->error_fatal, &error);
}
void kbase_csf_active_queue_groups_reset(struct kbase_device *kbdev,
@@ -1489,6 +1611,8 @@ void kbase_csf_ctx_handle_fault(struct kbase_context *kctx,
int gr;
bool reported = false;
struct base_gpu_queue_group_error err_payload;
+ int err;
+ struct kbase_device *kbdev;
if (WARN_ON(!kctx))
return;
@@ -1496,6 +1620,14 @@ void kbase_csf_ctx_handle_fault(struct kbase_context *kctx,
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 = {
@@ -1514,7 +1646,7 @@ void kbase_csf_ctx_handle_fault(struct kbase_context *kctx,
if (group && group->run_state != KBASE_CSF_GROUP_TERMINATED) {
term_queue_group(group);
- kbase_csf_add_fatal_error_to_kctx(group, &err_payload);
+ kbase_csf_add_group_fatal_error(group, &err_payload);
reported = true;
}
}
@@ -1523,11 +1655,18 @@ void kbase_csf_ctx_handle_fault(struct kbase_context *kctx,
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
@@ -1536,8 +1675,17 @@ void kbase_csf_ctx_term(struct kbase_context *kctx)
*/
kbase_csf_event_wait_remove_all(kctx);
- mutex_lock(&kctx->csf.lock);
+ /* 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.
*/
@@ -1545,19 +1693,39 @@ void kbase_csf_ctx_term(struct kbase_context *kctx)
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++)
+ 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.
@@ -1583,12 +1751,6 @@ void kbase_csf_ctx_term(struct kbase_context *kctx)
mutex_unlock(&kctx->csf.lock);
- /* Wait for the firmware error work item to also finish as it could
- * be affecting this outgoing context also. Proper handling would be
- * added in GPUCORE-25209.
- */
- flush_work(&kctx->kbdev->csf.fw_error_work);
-
kbase_csf_tiler_heap_context_term(kctx);
kbase_csf_kcpu_queue_context_term(kctx);
kbase_csf_scheduler_context_term(kctx);
@@ -1612,6 +1774,9 @@ int kbase_csf_event_wait_add(struct kbase_context *kctx,
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 %p with param %p\n", event,
+ event->param);
spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
err = 0;
@@ -1631,6 +1796,9 @@ void kbase_csf_event_wait_remove(struct kbase_context *kctx,
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 %p with param %p\n",
+ event, event->param);
kfree(event);
break;
}
@@ -1652,6 +1820,8 @@ bool kbase_csf_read_error(struct kbase_context *kctx,
struct kbase_csf_notification, link);
list_del_init(&error_data->link);
*event_data = error_data->data;
+ dev_dbg(kctx->kbdev->dev, "Dequeued error %p in context %p\n",
+ (void *)error_data, (void *)kctx);
} else {
got_event = false;
}
@@ -1668,6 +1838,8 @@ bool kbase_csf_error_pending(struct kbase_context *kctx)
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 %p\n",
+ event_pended ? "An" : "No", (void *)kctx);
spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
return event_pended;
@@ -1678,6 +1850,10 @@ 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 %p\n",
+ notify_gpu ? "with" : "without", (void *)kctx);
+
/* First increment the signal count and wake up event thread.
*/
atomic_set(&kctx->event_count, 1);
@@ -1703,9 +1879,12 @@ void kbase_csf_event_signal(struct kbase_context *kctx, bool notify_gpu)
list_for_each_entry_safe(
event, next_event, &kctx->csf.event_callback_list, link) {
- enum kbase_csf_event_callback_action action =
- event->callback(event->param);
+ enum kbase_csf_event_callback_action action;
+ dev_dbg(kctx->kbdev->dev,
+ "Calling event handler %p with param %p\n",
+ (void *)event, event->param);
+ action = event->callback(event->param);
if (action == KBASE_CSF_EVENT_CALLBACK_REMOVE) {
list_del(&event->link);
kfree(event);
@@ -1725,6 +1904,9 @@ void kbase_csf_event_wait_remove_all(struct kbase_context *kctx)
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 %p with param %p\n",
+ (void *)event, event->param);
kfree(event);
}
@@ -1816,20 +1998,9 @@ static void report_tiler_oom_error(struct kbase_queue_group *group)
.error_type =
BASE_GPU_QUEUE_GROUP_ERROR_TILER_HEAP_OOM,
} } } };
- struct kbase_context *kctx = group->kctx;
- unsigned long flags;
-
- spin_lock_irqsave(&kctx->csf.event_lock, flags);
-
- /* Ignore this error if the previous one hasn't been reported */
- if (!WARN_ON(!list_empty(&group->error_tiler_oom.link))) {
- group->error_tiler_oom.data = error;
- list_add_tail(&group->error_tiler_oom.link,
- &kctx->csf.error_list);
- kbase_event_wakeup(kctx);
- }
- spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
+ add_error(group->kctx, &group->error_tiler_oom, &error);
+ kbase_event_wakeup(group->kctx);
}
/**
@@ -1915,7 +2086,7 @@ static void kbase_queue_oom_event(struct kbase_queue *const queue)
return;
}
- kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, slot_num);
+ kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, slot_num, true);
unlock:
kbase_csf_scheduler_unlock(kbdev);
}
@@ -1934,6 +2105,14 @@ 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);
@@ -1941,6 +2120,7 @@ static void oom_event_worker(struct work_struct *data)
release_queue(queue);
mutex_unlock(&kctx->csf.lock);
+ kbase_reset_gpu_allow(kbdev);
}
/**
@@ -1963,25 +2143,15 @@ static void handle_progress_timer_event(struct kbase_queue_group *const group)
BASE_GPU_QUEUE_GROUP_ERROR_TIMEOUT,
} } } };
struct kbase_context *const kctx = group->kctx;
- unsigned long flags;
kbase_csf_scheduler_spin_lock_assert_held(kctx->kbdev);
- spin_lock_irqsave(&kctx->csf.event_lock, flags);
-
dev_warn(kctx->kbdev->dev,
"Notify the event notification thread, forward progress timeout (%llu cycles)\n",
kbase_csf_timeout_get(kctx->kbdev));
- /* Ignore this error if the previous one hasn't been reported */
- if (!WARN_ON(!list_empty(&group->error_timeout.link))) {
- group->error_timeout.data = error;
- list_add_tail(&group->error_timeout.link,
- &kctx->csf.error_list);
- kbase_event_wakeup(kctx);
- }
-
- spin_unlock_irqrestore(&kctx->csf.event_lock, flags);
+ add_error(kctx, &group->error_timeout, &error);
+ kbase_event_wakeup(kctx);
}
/**
@@ -2011,7 +2181,7 @@ static void protm_event_worker(struct work_struct *data)
*
*/
static void
-handle_fault_event(struct kbase_queue const *const queue,
+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);
@@ -2036,20 +2206,21 @@ handle_fault_event(struct kbase_queue const *const queue,
queue->csi_index, cs_fault_exception_type,
kbase_gpu_exception_name(cs_fault_exception_type),
cs_fault_exception_data, cs_fault_info_exception_data);
+
+ /* TODO GPUCORE-26291: We've'identified an issue with faulted CSIs not
+ * making progress in some cases. Until the issue is resolved,
+ * RESOURCE_EVICTION_TIMEOUT error shall be treated as a fatal error
+ * to give userspace a chance to terminate the group. This is intended
+ * to be a temporary workaround.
+ */
+ if (cs_fault_exception_type ==
+ CS_FAULT_EXCEPTION_TYPE_RESOURCE_EVICTION_TIMEOUT)
+ kbase_csf_add_queue_fatal_error(
+ queue, GPU_EXCEPTION_TYPE_SW_FAULT_2, 0);
}
-/**
- * report_queue_fatal_error - Report queue fatal error to user space
- *
- * @queue: Pointer to queue for which fatal event was received.
- * @cs_fatal: Fault information
- * @cs_fatal_info: Additional fault information
- *
- * If a queue has already been in fatal error status,
- * subsequent fatal error on the queue should never take place.
- */
-static void report_queue_fatal_error(struct kbase_queue *const queue,
- u32 cs_fatal, u64 cs_fatal_info)
+void kbase_csf_add_queue_fatal_error(struct kbase_queue *const queue,
+ u32 cs_fatal, u64 cs_fatal_info)
{
struct base_csf_notification error = {
.type = BASE_CSF_NOTIFICATION_GPU_QUEUE_GROUP_ERROR,
@@ -2070,22 +2241,10 @@ static void report_queue_fatal_error(struct kbase_queue *const queue,
}
}
};
- unsigned long flags;
kbase_csf_scheduler_spin_lock_assert_held(queue->kctx->kbdev);
-
- spin_lock_irqsave(&queue->kctx->csf.event_lock, flags);
-
- /* If a queue has already been in fatal error status,
- * subsequent fatal error on the queue should never take place.
- */
- if (!WARN_ON(!list_empty(&queue->error.link))) {
- queue->error.data = error;
- list_add_tail(&queue->error.link, &queue->kctx->csf.error_list);
- kbase_event_wakeup(queue->kctx);
- }
-
- spin_unlock_irqrestore(&queue->kctx->csf.event_lock, flags);
+ add_error(queue->kctx, &queue->error, &error);
+ kbase_event_wakeup(queue->kctx);
}
/**
@@ -2134,7 +2293,7 @@ handle_fatal_event(struct kbase_queue *const queue,
CS_FATAL_EXCEPTION_TYPE_FIRMWARE_INTERNAL_ERROR)
*fw_error = true;
else
- report_queue_fatal_error(queue, cs_fatal, cs_fatal_info);
+ kbase_csf_add_queue_fatal_error(queue, cs_fatal, cs_fatal_info);
}
/**
@@ -2171,7 +2330,7 @@ static void handle_queue_exception_event(struct kbase_queue *const queue,
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);
+ kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, slot_num, true);
}
if (internal_fw_error)
@@ -2354,7 +2513,7 @@ static void process_csg_interrupts(struct kbase_device *const kbdev,
/* Check if the scheduling tick can be advanced */
if (kbase_csf_scheduler_all_csgs_idle(kbdev) &&
!scheduler->gpu_idle_fw_timer_enabled) {
- mod_delayed_work(scheduler->wq, &scheduler->tick_work, 0);
+ kbase_csf_scheduler_advance_tick_nolock(kbdev);
}
}
@@ -2372,6 +2531,90 @@ static void process_csg_interrupts(struct kbase_device *const kbdev,
process_cs_interrupts(group, ginfo, irqreq, irqack);
}
+static void process_prfcnt_interrupts(struct kbase_device *kbdev, u32 glb_req,
+ u32 glb_ack, unsigned long *flags)
+{
+ 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;
+ kbase_csf_scheduler_spin_unlock(kbdev, *flags);
+
+ dev_dbg(kbdev->dev, "PRFCNT_SAMPLE done interrupt received.");
+
+ kbase_hwcnt_backend_csf_on_prfcnt_sample(
+ &kbdev->hwcnt_gpu_iface);
+
+ kbase_csf_scheduler_spin_lock(kbdev, flags);
+ }
+
+ /* 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;
+ kbase_csf_scheduler_spin_unlock(kbdev, *flags);
+
+ 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);
+ }
+
+ kbase_csf_scheduler_spin_lock(kbdev, flags);
+ }
+
+ /* Process PRFCNT_THRESHOLD interrupt. */
+ if ((glb_req ^ glb_ack) & GLB_REQ_PRFCNT_THRESHOLD_MASK) {
+ kbase_csf_scheduler_spin_unlock(kbdev, *flags);
+ dev_dbg(kbdev->dev, "PRFCNT_THRESHOLD interrupt received.");
+
+ kbase_hwcnt_backend_csf_on_prfcnt_threshold(
+ &kbdev->hwcnt_gpu_iface);
+
+ kbase_csf_scheduler_spin_lock(kbdev, flags);
+
+ /* 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) {
+ kbase_csf_scheduler_spin_unlock(kbdev, *flags);
+ dev_dbg(kbdev->dev, "PRFCNT_OVERFLOW interrupt received.");
+
+ kbase_hwcnt_backend_csf_on_prfcnt_overflow(
+ &kbdev->hwcnt_gpu_iface);
+
+ kbase_csf_scheduler_spin_lock(kbdev, flags);
+ /* 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;
@@ -2409,6 +2652,9 @@ void kbase_csf_interrupt(struct kbase_device *kbdev, u32 val)
scheduler->active_protm_grp = NULL;
KBASE_KTRACE_ADD(kbdev, SCHEDULER_EXIT_PROTM, NULL, 0u);
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 */
@@ -2419,18 +2665,22 @@ void kbase_csf_interrupt(struct kbase_device *kbdev, u32 val)
GLB_REQ_IDLE_EVENT_MASK);
if (!atomic_read(&scheduler->non_idle_offslot_grps)) {
- mod_delayed_work(system_highpri_wq,
- &scheduler->gpu_idle_work, 0);
+ if (kbase_pm_idle_groups_sched_suspendable(kbdev))
+ queue_work(system_highpri_wq,
+ &scheduler->gpu_idle_work);
} else {
/* Advance the scheduling tick to get
* the non-idle suspended groups loaded
* soon.
*/
- mod_delayed_work(scheduler->wq,
- &scheduler->tick_work, 0);
+ kbase_csf_scheduler_advance_tick_nolock(
+ kbdev);
}
}
+ process_prfcnt_interrupts(kbdev, glb_req, glb_ack,
+ &flags);
+
kbase_csf_scheduler_spin_unlock(kbdev, flags);
/* Invoke the MCU state machine as a state transition
@@ -2539,3 +2789,18 @@ int kbase_csf_setup_dummy_user_reg_page(struct kbase_device *kbdev)
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/mali_kbase/csf/mali_kbase_csf.h b/mali_kbase/csf/mali_kbase_csf.h
index 44bc131..7eed90d 100644
--- a/mali_kbase/csf/mali_kbase_csf.h
+++ b/mali_kbase/csf/mali_kbase_csf.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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_
@@ -40,9 +59,6 @@
*/
#define KBASEP_USER_DB_NR_INVALID ((s8)-1)
-/* Waiting timeout for global request completion acknowledgment */
-#define GLB_REQ_WAIT_TIMEOUT_MS (300) /* 300 milliseconds */
-
#define FIRMWARE_PING_INTERVAL_MS (2000) /* 2 seconds */
#define FIRMWARE_IDLE_HYSTERESIS_TIME_MS (10) /* Default 10 milliseconds */
@@ -267,6 +283,16 @@ int kbase_csf_queue_bind(struct kbase_context *kctx,
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.
@@ -350,16 +376,29 @@ int kbase_csf_queue_group_suspend(struct kbase_context *kctx,
struct kbase_suspend_copy_buffer *sus_buf, u8 group_handle);
/**
- * kbase_csf_add_fatal_error_to_kctx - Add a fatal error to per-ctx error list.
+ * 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_fatal_error_to_kctx(
+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_add_queue_fatal_error - Report a fatal queue error to userspace
+ *
+ * @queue: Pointer to queue for which fatal event was received.
+ * @cs_fatal: Fault information
+ * @cs_fatal_info: Additional fault information
+ *
+ * If a queue has already been in fatal error status,
+ * subsequent fatal error on the queue should never take place.
+ */
+void kbase_csf_add_queue_fatal_error(struct kbase_queue *const queue,
+ u32 cs_fatal, u64 cs_fatal_info);
+
+/**
* kbase_csf_interrupt - Handle interrupts issued by CSF firmware.
*
* @kbdev: The kbase device to handle an IRQ for
@@ -448,9 +487,16 @@ void kbase_csf_ring_csg_slots_doorbell(struct kbase_device *kbdev,
* @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);
+ int csi_index, int csg_nr,
+ bool ring_csg_doorbell);
/**
* kbase_csf_ring_cs_user_doorbell - ring the user doorbell allocated for a
@@ -482,4 +528,54 @@ void kbase_csf_ring_cs_user_doorbell(struct kbase_device *kbdev,
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/mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.c b/mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.c
index 3acceeb..166c1b4 100644
--- a/mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.c
+++ b/mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.h b/mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.h
index 71309bf..4ba0b8c 100644
--- a/mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.h
+++ b/mali_kbase/csf/mali_kbase_csf_cpu_queue_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
diff --git a/mali_kbase/csf/mali_kbase_csf_csg_debugfs.c b/mali_kbase/csf/mali_kbase_csf_csg_debugfs.c
index e54c724..86f359a 100644
--- a/mali_kbase/csf/mali_kbase_csf_csg_debugfs.c
+++ b/mali_kbase/csf/mali_kbase_csf_csg_debugfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -29,12 +30,37 @@
#ifdef 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)
+ 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"
@@ -56,6 +82,11 @@ static void kbasep_csf_scheduler_dump_active_queue_cs_status_wait(
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)));
}
/**
@@ -74,6 +105,8 @@ static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file,
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;
@@ -109,6 +142,8 @@ static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file,
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) {
@@ -120,7 +155,8 @@ static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file,
kbasep_csf_scheduler_dump_active_queue_cs_status_wait(
file, wait_status, wait_sync_value,
- wait_sync_live_value, wait_sync_pointer);
+ wait_sync_live_value, wait_sync_pointer,
+ sb_status, blocked_reason);
}
} else {
struct kbase_device const *const kbdev =
@@ -161,6 +197,11 @@ static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file,
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];
@@ -171,7 +212,8 @@ static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file,
kbasep_csf_scheduler_dump_active_queue_cs_status_wait(
file, wait_status, wait_sync_value,
- wait_sync_live_value, wait_sync_pointer);
+ wait_sync_live_value, wait_sync_pointer, sb_status,
+ blocked_reason);
}
seq_puts(file, "\n");
diff --git a/mali_kbase/csf/mali_kbase_csf_csg_debugfs.h b/mali_kbase/csf/mali_kbase_csf_csg_debugfs.h
index c2e99d3..68e9ce0 100644
--- a/mali_kbase/csf/mali_kbase_csf_csg_debugfs.h
+++ b/mali_kbase/csf/mali_kbase_csf_csg_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_
diff --git a/mali_kbase/csf/mali_kbase_csf_defs.h b/mali_kbase/csf/mali_kbase_csf_defs.h
index 3939238..968895f 100644
--- a/mali_kbase/csf/mali_kbase_csf_defs.h
+++ b/mali_kbase/csf/mali_kbase_csf_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
@@ -66,18 +85,36 @@ enum kbase_csf_queue_bind_state {
* 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
- * @KBASE_CSF_RESET_GPU_SILENT: Set when the GPU reset process is occurring,
- * used when resetting the GPU as part of normal behavior (e.g. when exiting
- * protected mode).
+ * (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_SILENT,
+ KBASE_CSF_RESET_GPU_COMMITTED_SILENT,
KBASE_CSF_RESET_GPU_FAILED,
};
@@ -202,6 +239,24 @@ enum kbase_csf_scheduler_state {
};
/**
+ * 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
*
@@ -248,7 +303,7 @@ struct kbase_csf_notification {
* @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.
+ * @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
@@ -267,6 +322,10 @@ struct kbase_csf_notification {
* 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
* @error: GPU command queue fatal information to pass to user space.
*/
struct kbase_queue {
@@ -285,12 +344,14 @@ struct kbase_queue {
u64 base_addr;
u32 size;
u8 priority;
- u8 bind_state;
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;
struct kbase_csf_notification error;
};
@@ -484,14 +545,17 @@ struct kbase_csf_heap_context_allocator {
* @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.
+ * @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;
};
/**
@@ -499,7 +563,7 @@ struct kbase_csf_tiler_heap_context {
* context for a GPU address space.
*
* @runnable_groups: Lists of runnable GPU command queue groups in the kctx,
- * one per queue group priority level.
+ * 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
@@ -517,7 +581,7 @@ struct kbase_csf_tiler_heap_context {
* 'groups_to_schedule' list of scheduler instance.
*/
struct kbase_csf_scheduler_context {
- struct list_head runnable_groups[BASE_QUEUE_GROUP_PRIORITY_COUNT];
+ 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;
@@ -606,21 +670,26 @@ struct kbase_csf_context {
* @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.
+ * @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.
*/
@@ -689,9 +758,12 @@ struct kbase_csf_csg_slot {
* 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_work: Work item that would perform the schedule on tick
- * operation to implement the time slice based
- * scheduling.
+ * @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
@@ -733,6 +805,14 @@ struct kbase_csf_csg_slot {
* 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;
@@ -754,7 +834,8 @@ struct kbase_csf_scheduler {
unsigned long last_schedule;
bool timer_enabled;
struct workqueue_struct *wq;
- struct delayed_work tick_work;
+ struct hrtimer tick_timer;
+ struct work_struct tick_work;
struct delayed_work tock_work;
struct delayed_work ping_work;
struct kbase_context *top_ctx;
@@ -763,11 +844,13 @@ struct kbase_csf_scheduler {
bool tock_pending_request;
struct kbase_queue_group *active_protm_grp;
bool gpu_idle_fw_timer_enabled;
- struct delayed_work gpu_idle_work;
+ struct work_struct gpu_idle_work;
atomic_t non_idle_offslot_grps;
u32 non_idle_scanout_grps;
bool apply_async_protm;
u32 pm_active_count;
+ unsigned int csg_scheduling_period_ms;
+ bool tick_timer_active;
};
/**
@@ -784,18 +867,20 @@ struct kbase_csf_scheduler {
GLB_PROGRESS_TIMER_TIMEOUT_SCALE)
/**
- * Number of GPU cycles per unit of the global poweroff timeout.
+ * Default GLB_PWROFF_TIMER_TIMEOUT value in unit of micro-seconds.
*/
-#define GLB_PWROFF_TIMER_TIMEOUT_SCALE ((u64)1024)
+#define DEFAULT_GLB_PWROFF_TIMEOUT_US (800)
/**
- * Minimum number of GPU cycles for which shader cores must be idle before they
- * are powered off.
- * Value chosen is equivalent to the hysteresis delay used in the shader cores
- * state machine of JM GPUs, which is ~800 micro seconds. It is assumed the GPU
- * is usually clocked at ~500 MHZ.
+ * 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 DEFAULT_GLB_PWROFF_TIMER_TIMEOUT ((u64)800 * 500)
+#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.
@@ -863,14 +948,18 @@ struct kbase_ipa_control_prfcnt {
/**
* struct kbase_ipa_control_session - Session for an IPA Control client
*
- * @prfcnts: Sessions for individual performance counters.
- * @num_prfcnts: Number of performance counters.
- * @active: Status of the session.
+ * @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;
};
/**
@@ -918,6 +1007,7 @@ struct kbase_ipa_control_prfcnt_block {
* @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];
@@ -927,6 +1017,21 @@ struct kbase_ipa_control {
void *rtm_listener_data;
size_t num_active_sessions;
u32 cur_gpu_rate;
+ u64 protm_start;
+};
+
+/**
+ * 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;
};
/**
@@ -1003,6 +1108,11 @@ struct kbase_ipa_control {
* 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
@@ -1011,12 +1121,26 @@ struct kbase_ipa_control {
* @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;
@@ -1043,12 +1167,18 @@ struct kbase_csf_device {
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;
};
/**
diff --git a/mali_kbase/csf/mali_kbase_csf_firmware.c b/mali_kbase/csf/mali_kbase_csf_firmware.c
index e2067d2..22f162f 100644
--- a/mali_kbase/csf/mali_kbase_csf_firmware.c
+++ b/mali_kbase/csf/mali_kbase_csf_firmware.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -33,6 +34,7 @@
#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>
@@ -1232,22 +1234,43 @@ 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 = {
- .status = GPU_EXCEPTION_TYPE_SW_FAULT_1,
- };
+ struct kbase_fault fault;
if (as == MCU_AS_NR)
continue;
- kctx = kbase_ctx_sched_as_to_ctx_refcount(kbdev, as);
- if (!kctx)
+ /* 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);
}
+ /* Internal FW error could mean hardware counters will stop working.
+ * Put the backend into the unrecoverable error state to cause
+ * current and subsequent counter operations to immediately
+ * fail, avoiding the risk of a hang.
+ */
+ kbase_hwcnt_backend_csf_on_unrecoverable_error(&kbdev->hwcnt_gpu_iface);
+
if (kbase_prepare_to_reset_gpu(kbdev))
kbase_reset_gpu(kbdev);
}
@@ -1292,7 +1315,7 @@ static int wait_for_global_request(struct kbase_device *const kbdev,
u32 const req_mask)
{
const long wait_timeout =
- kbase_csf_timeout_in_jiffies(GLB_REQ_WAIT_TIMEOUT_MS);
+ kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
long remaining;
int err = 0;
@@ -1335,23 +1358,25 @@ static void enable_endpoints_global(
set_global_request(global_iface, GLB_REQ_CFG_ALLOC_EN_MASK);
}
-static void enable_shader_poweroff_timer(
- struct kbase_device *const kbdev,
+static void enable_shader_poweroff_timer(struct kbase_device *const kbdev,
const struct kbase_csf_global_iface *const global_iface)
{
- u32 pwroff_reg = 0;
+ u32 pwroff_reg;
- pwroff_reg = GLB_PWROFF_TIMER_TIMEOUT_SET(
- pwroff_reg, DEFAULT_GLB_PWROFF_TIMER_TIMEOUT /
- GLB_PWROFF_TIMER_TIMEOUT_SCALE);
-
- pwroff_reg = GLB_PWROFF_TIMER_TIMER_SOURCE_SET(
- pwroff_reg, GLB_PWROFF_TIMER_TIMER_SOURCE_GPU_COUNTER);
+ 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);
}
@@ -1432,6 +1457,8 @@ static int global_init_on_boot(struct kbase_device *const kbdev)
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);
@@ -1445,6 +1472,8 @@ void kbase_csf_firmware_global_reinit(struct kbase_device *kbdev,
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);
}
@@ -1459,24 +1488,29 @@ bool kbase_csf_firmware_global_reinit_complete(struct kbase_device *kbdev)
return !kbdev->csf.glb_init_request_pending;
}
-void kbase_csf_firmware_update_core_mask(struct kbase_device *kbdev,
- u64 new_core_mask)
+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);
- enable_endpoints_global(&kbdev->csf.global_iface, new_core_mask);
+ 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_mask_updated(struct kbase_device *kbdev)
+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);
+ return global_request_complete(kbdev, GLB_REQ_CFG_ALLOC_EN_MASK |
+ GLB_REQ_CFG_PWROFF_TIMER_MASK);
}
/**
@@ -1608,6 +1642,67 @@ u32 kbase_csf_firmware_set_gpu_idle_hysteresis_time(struct kbase_device *kbdev,
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_init(struct kbase_device *kbdev)
{
const struct firmware *firmware;
@@ -1633,6 +1728,7 @@ int kbase_csf_firmware_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);
@@ -1648,6 +1744,10 @@ int kbase_csf_firmware_init(struct kbase_device *kbdev)
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");
@@ -1790,21 +1890,32 @@ void kbase_csf_firmware_term(struct kbase_device *kbdev)
cancel_work_sync(&kbdev->csf.fw_error_work);
- while (kbase_reset_gpu_is_active(kbdev) && !ret)
- ret = kbase_reset_gpu_wait(kbdev);
+ ret = kbase_reset_gpu_wait(kbdev);
WARN(ret, "failed to wait for GPU reset");
- /* Make sure ongoing transitions have completed */
- kbase_pm_wait_for_desired_state(kbdev);
-
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 (kbdev->pm.backend.mcu_state != KBASE_MCU_OFF) {
+ if (WARN_ON(kbdev->pm.backend.mcu_state != KBASE_MCU_OFF)) {
kbdev->pm.backend.mcu_state = KBASE_MCU_OFF;
stop_csf_firmware(kbdev);
}
@@ -1812,18 +1923,7 @@ void kbase_csf_firmware_term(struct kbase_device *kbdev)
unload_mmu_tables(kbdev);
- 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;
+ kbase_csf_firmware_trace_buffers_term(kbdev);
while (!list_empty(&kbdev->csf.firmware_interfaces)) {
struct firmware_interface *interface;
@@ -1859,18 +1959,21 @@ void kbase_csf_firmware_term(struct kbase_device *kbdev)
kfree(metadata);
}
- kbase_csf_firmware_trace_buffers_term(kbdev);
-
#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);
+
+ 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)
@@ -1976,6 +2079,8 @@ void kbase_csf_enter_protected_mode(struct kbase_device *kbdev)
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_hwcnt_backend_csf_protm_entered(&kbdev->hwcnt_gpu_iface);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
}
}
@@ -2184,7 +2289,8 @@ 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. */
+ * function doesn't try to unmap or free random addresses.
+ */
csf_mapping->phys = NULL;
csf_mapping->cpu_addr = NULL;
csf_mapping->va_reg = NULL;
diff --git a/mali_kbase/csf/mali_kbase_csf_firmware.h b/mali_kbase/csf/mali_kbase_csf_firmware.h
index 3a05062..baee9da 100644
--- a/mali_kbase/csf/mali_kbase_csf_firmware.h
+++ b/mali_kbase/csf/mali_kbase_csf_firmware.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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_
@@ -79,6 +98,9 @@
/* Maximum CSs per csg. */
#define MAX_SUPPORTED_STREAMS_PER_GROUP 32
+/* Waiting timeout for status change acknowledgment, in milliseconds */
+#define CSF_FIRMWARE_TIMEOUT_MS (800) /* Relaxed to 800ms from 100ms */
+
struct kbase_device;
@@ -518,26 +540,32 @@ void kbase_csf_firmware_global_reinit(struct kbase_device *kbdev,
bool kbase_csf_firmware_global_reinit_complete(struct kbase_device *kbdev);
/**
- * kbase_csf_firmware_update_core_mask - Send the Global configuration request
- * to update the mask of enabled shader cores.
+ * 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.
- * @new_core_mask: New mask of the enabled cores.
+ * @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_mask(struct kbase_device *kbdev,
- u64 new_core_mask);
+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_mask_updated - Check the Global configuration
+ * kbase_csf_firmware_core_attr_updated - Check the Global configuration
* request has completed or not, that was sent to update
- * to update the mask of enabled shader cores.
+ * the core attributes.
*
- * Return: true if the Global configuration request to update the mask of
- * enabled shader cores has completed, otherwise false.
+ * 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_mask_updated(struct kbase_device *kbdev);
+bool kbase_csf_firmware_core_attr_updated(struct kbase_device *kbdev);
/**
* Request the global control block of CSF interface capabilities
@@ -713,4 +741,59 @@ u32 kbase_csf_firmware_get_gpu_idle_hysteresis_time(struct kbase_device *kbdev);
*/
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));
+}
+
#endif
diff --git a/mali_kbase/csf/mali_kbase_csf_firmware_cfg.c b/mali_kbase/csf/mali_kbase_csf_firmware_cfg.c
index d282d5c..6a4bfda 100644
--- a/mali_kbase/csf/mali_kbase_csf_firmware_cfg.c
+++ b/mali_kbase/csf/mali_kbase_csf_firmware_cfg.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/csf/mali_kbase_csf_firmware_cfg.h b/mali_kbase/csf/mali_kbase_csf_firmware_cfg.h
index ab4b6eb..542e3b9 100644
--- a/mali_kbase/csf/mali_kbase_csf_firmware_cfg.h
+++ b/mali_kbase/csf/mali_kbase_csf_firmware_cfg.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
diff --git a/mali_kbase/csf/mali_kbase_csf_firmware_no_mali.c b/mali_kbase/csf/mali_kbase_csf_firmware_no_mali.c
index 1891778..d82139a 100644
--- a/mali_kbase/csf/mali_kbase_csf_firmware_no_mali.c
+++ b/mali_kbase/csf/mali_kbase_csf_firmware_no_mali.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -434,22 +435,43 @@ 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 = {
- .status = GPU_EXCEPTION_TYPE_SW_FAULT_1,
- };
+ struct kbase_fault fault;
if (as == MCU_AS_NR)
continue;
- kctx = kbase_ctx_sched_as_to_ctx_refcount(kbdev, as);
- if (!kctx)
+ /* 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);
}
+ /* Internal FW error could mean hardware counters will stop working.
+ * Put the backend into the unrecoverable error state to cause
+ * current and subsequent counter operations to immediately
+ * fail, avoiding the risk of a hang.
+ */
+ kbase_hwcnt_backend_csf_on_unrecoverable_error(&kbdev->hwcnt_gpu_iface);
+
if (kbase_prepare_to_reset_gpu(kbdev))
kbase_reset_gpu(kbdev);
}
@@ -494,7 +516,7 @@ static int wait_for_global_request(struct kbase_device *const kbdev,
u32 const req_mask)
{
const long wait_timeout =
- kbase_csf_timeout_in_jiffies(GLB_REQ_WAIT_TIMEOUT_MS);
+ kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
long remaining;
int err = 0;
@@ -537,21 +559,24 @@ static void enable_endpoints_global(
set_global_request(global_iface, GLB_REQ_CFG_ALLOC_EN_MASK);
}
-static void enable_shader_poweroff_timer(
- const struct kbase_csf_global_iface *const global_iface)
+static void enable_shader_poweroff_timer(struct kbase_device *const kbdev,
+ const struct kbase_csf_global_iface *const global_iface)
{
- u32 pwroff_reg = 0;
-
- pwroff_reg = GLB_PWROFF_TIMER_TIMEOUT_SET(
- pwroff_reg, DEFAULT_GLB_PWROFF_TIMER_TIMEOUT /
- GLB_PWROFF_TIMER_TIMEOUT_SCALE);
+ u32 pwroff_reg;
- pwroff_reg = GLB_PWROFF_TIMER_TIMER_SOURCE_SET(
- pwroff_reg, GLB_PWROFF_TIMER_TIMER_SOURCE_GPU_COUNTER);
+ 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(
@@ -582,7 +607,7 @@ static void global_init(struct kbase_device *const kbdev, u64 core_mask)
/* Update shader core allocation enable mask */
enable_endpoints_global(global_iface, core_mask);
- enable_shader_poweroff_timer(global_iface);
+ enable_shader_poweroff_timer(kbdev, global_iface);
set_timeout_global(global_iface, kbase_csf_timeout_get(kbdev));
@@ -611,6 +636,8 @@ static int global_init_on_boot(struct kbase_device *const kbdev)
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);
@@ -624,6 +651,8 @@ void kbase_csf_firmware_global_reinit(struct kbase_device *kbdev,
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);
}
@@ -638,24 +667,29 @@ bool kbase_csf_firmware_global_reinit_complete(struct kbase_device *kbdev)
return !kbdev->csf.glb_init_request_pending;
}
-void kbase_csf_firmware_update_core_mask(struct kbase_device *kbdev,
- u64 new_core_mask)
+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);
- enable_endpoints_global(&kbdev->csf.global_iface, new_core_mask);
+ 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_mask_updated(struct kbase_device *kbdev)
+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);
+ 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)
@@ -763,6 +797,67 @@ u32 kbase_csf_firmware_set_gpu_idle_hysteresis_time(struct kbase_device *kbdev,
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_init(struct kbase_device *kbdev)
{
int ret;
@@ -782,6 +877,7 @@ int kbase_csf_firmware_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);
@@ -1046,6 +1142,8 @@ static u32 copy_grp_and_stm(
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)
@@ -1197,7 +1295,8 @@ 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. */
+ * function doesn't try to unmap or free random addresses.
+ */
csf_mapping->phys = NULL;
csf_mapping->cpu_addr = NULL;
csf_mapping->va_reg = NULL;
diff --git a/mali_kbase/csf/mali_kbase_csf_heap_context_alloc.c b/mali_kbase/csf/mali_kbase_csf_heap_context_alloc.c
index 087cc85..4dc1ac1 100644
--- a/mali_kbase/csf/mali_kbase_csf_heap_context_alloc.c
+++ b/mali_kbase/csf/mali_kbase_csf_heap_context_alloc.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
diff --git a/mali_kbase/csf/mali_kbase_csf_heap_context_alloc.h b/mali_kbase/csf/mali_kbase_csf_heap_context_alloc.h
index f71ea01..ecb0852 100644
--- a/mali_kbase/csf/mali_kbase_csf_heap_context_alloc.h
+++ b/mali_kbase/csf/mali_kbase_csf_heap_context_alloc.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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>
diff --git a/mali_kbase/csf/mali_kbase_csf_ioctl.h b/mali_kbase/csf/mali_kbase_csf_ioctl.h
index d7db345..0bbc96c 100644
--- a/mali_kbase/csf/mali_kbase_csf_ioctl.h
+++ b/mali_kbase/csf/mali_kbase_csf_ioctl.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_IOCTL_H_
@@ -29,10 +48,16 @@
/*
* 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
*/
#define BASE_UK_VERSION_MAJOR 1
-#define BASE_UK_VERSION_MINOR 0
+#define BASE_UK_VERSION_MINOR 2
/**
* struct kbase_ioctl_version_check - Check version compatibility between
@@ -46,7 +71,6 @@ struct kbase_ioctl_version_check {
__u16 minor;
};
-
#define KBASE_IOCTL_VERSION_CHECK_RESERVED \
_IOWR(KBASE_IOCTL_TYPE, 0, struct kbase_ioctl_version_check)
@@ -341,7 +365,6 @@ struct kbase_ioctl_cs_cpu_queue_info {
#define KBASE_IOCTL_CS_CPU_QUEUE_DUMP \
_IOW(KBASE_IOCTL_TYPE, 53, struct kbase_ioctl_cs_cpu_queue_info)
-
/***************
* test ioctls *
***************/
diff --git a/mali_kbase/csf/mali_kbase_csf_kcpu.c b/mali_kbase/csf/mali_kbase_csf_kcpu.c
index b9c2597..b073d05 100644
--- a/mali_kbase/csf/mali_kbase_csf_kcpu.c
+++ b/mali_kbase/csf/mali_kbase_csf_kcpu.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -576,8 +577,8 @@ static int kbase_csf_queue_group_suspend_prepare(
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;
- int ret = 0;
+ int pinned_pages = 0, ret = 0;
+ struct kbase_va_region *reg;
lockdep_assert_held(&kctx->csf.kcpu_queues.lock);
@@ -604,17 +605,57 @@ static int kbase_csf_queue_group_suspend_prepare(
goto out_clean_sus_buf;
}
- pinned_pages = get_user_pages_fast(page_addr, nr_pages, 1,
- sus_buf->pages);
- if (pinned_pages < 0) {
- ret = pinned_pages;
- goto out_clean_pages;
- }
- if (pinned_pages != nr_pages) {
- ret = -EINVAL;
- goto out_clean_pages;
+ /* 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);
+ 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 =
@@ -622,9 +663,11 @@ static int kbase_csf_queue_group_suspend_prepare(
return ret;
out_clean_pages:
+ kbase_gpu_vm_unlock(kctx);
kfree(sus_buf->pages);
out_clean_sus_buf:
kfree(sus_buf);
+
return ret;
}
@@ -688,6 +731,8 @@ static int kbase_kcpu_cqs_wait_process(struct kbase_device *kbdev,
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) {
@@ -699,10 +744,18 @@ static int kbase_kcpu_cqs_wait_process(struct kbase_device *kbdev,
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)
+ 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,
@@ -813,6 +866,10 @@ static void kbase_kcpu_cqs_set_process(struct kbase_device *kbdev,
/* 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]);
}
}
@@ -872,6 +929,9 @@ static void kbase_csf_fence_wait_callback(struct dma_fence *fence,
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);
}
@@ -888,8 +948,13 @@ static void kbase_kcpu_fence_wait_cancel(
return;
if (kcpu_queue->fence_wait_processed) {
- dma_fence_remove_callback(fence_info->fence,
+ 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 */
@@ -933,6 +998,9 @@ static int kbase_kcpu_fence_wait_process(
&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;
@@ -1003,6 +1071,10 @@ static int kbase_kcpu_fence_signal_process(
"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;
@@ -1112,6 +1184,9 @@ static int delete_queue(struct kbase_context *kctx, u32 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.
*/
@@ -1394,13 +1469,15 @@ static void kcpu_queue_process(struct kbase_kcpu_command_queue *queue,
KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_END(
kbdev, queue);
break;
- case BASE_KCPU_COMMAND_TYPE_GROUP_SUSPEND:
+ 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,
- cmd->info.suspend_buf_copy.sus_buf,
+ queue->kctx, sus_buf,
cmd->info.suspend_buf_copy.group_handle);
if (status)
queue->has_error = true;
@@ -1408,9 +1485,19 @@ static void kcpu_queue_process(struct kbase_kcpu_command_queue *queue,
KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END(
kbdev, queue, status);
- kfree(cmd->info.suspend_buf_copy.sus_buf->pages);
- kfree(cmd->info.suspend_buf_copy.sus_buf);
+ 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_put(sus_buf->cpu_alloc);
+ }
+
+ kfree(sus_buf->pages);
+ kfree(sus_buf);
break;
+ }
default:
dev_warn(kbdev->dev,
"Unrecognized command type\n");
@@ -1798,6 +1885,7 @@ int kbase_csf_kcpu_queue_new(struct kbase_context *kctx,
INIT_LIST_HEAD(&queue->jit_blocked);
queue->has_error = false;
INIT_WORK(&queue->work, kcpu_queue_process_worker);
+ queue->id = idx;
newq->id = idx;
@@ -1806,6 +1894,9 @@ int kbase_csf_kcpu_queue_new(struct kbase_context *kctx,
*/
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);
diff --git a/mali_kbase/csf/mali_kbase_csf_kcpu.h b/mali_kbase/csf/mali_kbase_csf_kcpu.h
index 6c4c2d2..cf506ea 100644
--- a/mali_kbase/csf/mali_kbase_csf_kcpu.h
+++ b/mali_kbase/csf/mali_kbase_csf_kcpu.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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_
@@ -145,12 +164,14 @@ struct kbase_kcpu_command_jit_free_info {
* 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;
};
/**
@@ -201,6 +222,7 @@ struct kbase_kcpu_command {
* 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
@@ -233,6 +255,7 @@ struct kbase_kcpu_command_queue {
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;
diff --git a/mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.c b/mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.c
index 55e3b64..004fc89 100644
--- a/mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.c
+++ b/mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -196,4 +197,3 @@ void kbase_csf_kcpu_debugfs_init(struct kbase_context *kctx)
}
#endif /* CONFIG_DEBUG_FS */
-
diff --git a/mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.h b/mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.h
index 359fe2c..11ee381 100644
--- a/mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.h
+++ b/mali_kbase/csf/mali_kbase_csf_kcpu_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_
diff --git a/mali_kbase/csf/mali_kbase_csf_protected_memory.c b/mali_kbase/csf/mali_kbase_csf_protected_memory.c
index 987cbc2..0ace25a 100644
--- a/mali_kbase/csf/mali_kbase_csf_protected_memory.c
+++ b/mali_kbase/csf/mali_kbase_csf_protected_memory.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
diff --git a/mali_kbase/csf/mali_kbase_csf_protected_memory.h b/mali_kbase/csf/mali_kbase_csf_protected_memory.h
index 2b45991..ba9411d 100644
--- a/mali_kbase/csf/mali_kbase_csf_protected_memory.h
+++ b/mali_kbase/csf/mali_kbase_csf_protected_memory.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_
diff --git a/mali_kbase/csf/mali_kbase_csf_reset_gpu.c b/mali_kbase/csf/mali_kbase_csf_reset_gpu.c
index 4a88ffc..8418320 100644
--- a/mali_kbase/csf/mali_kbase_csf_reset_gpu.c
+++ b/mali_kbase/csf/mali_kbase_csf_reset_gpu.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -29,6 +30,7 @@
#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 */
@@ -38,6 +40,199 @@
#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);
@@ -115,26 +310,33 @@ static void kbase_csf_dump_firmware_trace_buffer(struct kbase_device *kbdev)
}
static int kbase_csf_reset_gpu_now(struct kbase_device *kbdev,
- bool firmware_inited)
+ bool firmware_inited, bool silent)
{
unsigned long flags;
- bool silent = false;
int err;
- if (atomic_read(&kbdev->csf.reset.state) == KBASE_CSF_RESET_GPU_SILENT)
- silent = true;
-
WARN_ON(kbdev->irq_reset_flush);
-
- /* Reset the scheduler state before disabling the interrupts as suspend of active
- * CSG slots would also be done as a part of reset.
+ /* 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);
- /* Disable GPU hardware counters.
- * This call will block until counters are disabled.
+ 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);
@@ -142,7 +344,8 @@ static int kbase_csf_reset_gpu_now(struct kbase_device *kbdev,
spin_lock(&kbdev->mmu_mask_change);
kbase_pm_reset_start_locked(kbdev);
- /* We're about to flush out the IRQs and their bottom halves */
+ 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
@@ -153,15 +356,16 @@ static int kbase_csf_reset_gpu_now(struct kbase_device *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.
+ 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);
- /* Flush out any in-flight work items */
+ dev_dbg(kbdev->dev, "Flush out any in-flight work items\n");
kbase_flush_mmu_wqs(kbdev);
- /* The flush has completed so reset the active indicator */
+ dev_dbg(kbdev->dev,
+ "The flush has completed so reset the active indicator\n");
kbdev->irq_reset_flush = false;
mutex_lock(&kbdev->pm.lock);
@@ -179,17 +383,23 @@ static int kbase_csf_reset_gpu_now(struct kbase_device *kbdev,
}
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbdev->protected_mode = false;
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))
- return err;
+ goto error;
mutex_lock(&kbdev->mmu_hw_mutex);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
@@ -207,7 +417,7 @@ static int kbase_csf_reset_gpu_now(struct kbase_device *kbdev,
mutex_unlock(&kbdev->pm.lock);
if (err)
- return err;
+ goto error;
/* Re-enable GPU hardware counters */
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
@@ -218,6 +428,28 @@ static int kbase_csf_reset_gpu_now(struct kbase_device *kbdev,
dev_err(kbdev->dev, "Reset complete");
return 0;
+error:
+ WARN_ON(!err);
+
+ /* If hardware init failed, we assume hardware counters will
+ * not work and put the backend into the unrecoverable error
+ * state.
+ */
+ 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).
+ */
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx);
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+
+ return err;
}
static void kbase_csf_reset_gpu_worker(struct work_struct *data)
@@ -227,6 +459,13 @@ static void kbase_csf_reset_gpu_worker(struct work_struct *data)
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;
@@ -234,31 +473,24 @@ static void kbase_csf_reset_gpu_worker(struct work_struct *data)
if (!kbase_pm_context_active_handle_suspend(kbdev,
KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) {
- err = kbase_csf_reset_gpu_now(kbdev, firmware_inited);
+ 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);
- if (!err) {
- atomic_set(&kbdev->csf.reset.state,
- KBASE_CSF_RESET_GPU_NOT_PENDING);
- if (likely(firmware_inited))
- kbase_csf_scheduler_enable_tick_timer(kbdev);
- } else {
- dev_err(kbdev->dev, "Reset failed to complete");
- atomic_set(&kbdev->csf.reset.state,
- KBASE_CSF_RESET_GPU_FAILED);
- }
-
- wake_up(&kbdev->csf.reset.wait);
+ /* 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)
{
if (atomic_cmpxchg(&kbdev->csf.reset.state,
KBASE_CSF_RESET_GPU_NOT_PENDING,
- KBASE_CSF_RESET_GPU_HAPPENING) !=
+ KBASE_CSF_RESET_GPU_PREPARED) !=
KBASE_CSF_RESET_GPU_NOT_PENDING) {
/* Some other thread is already resetting the GPU */
return false;
@@ -275,15 +507,21 @@ bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev)
return kbase_prepare_to_reset_gpu(kbdev);
}
-int kbase_reset_gpu(struct kbase_device *kbdev)
+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);
-
- return 0;
}
KBASE_EXPORT_TEST_API(kbase_reset_gpu);
@@ -298,7 +536,7 @@ 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_SILENT) !=
+ KBASE_CSF_RESET_GPU_COMMITTED_SILENT) !=
KBASE_CSF_RESET_GPU_NOT_PENDING) {
/* Some other thread is already resetting the GPU */
return -EAGAIN;
@@ -313,23 +551,42 @@ int kbase_reset_gpu_silent(struct kbase_device *kbdev)
bool kbase_reset_gpu_is_active(struct kbase_device *kbdev)
{
- if (atomic_read(&kbdev->csf.reset.state) ==
- KBASE_CSF_RESET_GPU_NOT_PENDING)
- return false;
+ enum kbase_csf_reset_gpu_state reset_state =
+ atomic_read(&kbdev->csf.reset.state);
- return true;
+ /* 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 = 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);
+ 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");
@@ -352,6 +609,7 @@ int kbase_reset_gpu_init(struct kbase_device *kbdev)
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;
}
diff --git a/mali_kbase/csf/mali_kbase_csf_scheduler.c b/mali_kbase/csf/mali_kbase_csf_scheduler.c
index a78088a..e78b912 100644
--- a/mali_kbase/csf/mali_kbase_csf_scheduler.c
+++ b/mali_kbase/csf/mali_kbase_csf_scheduler.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -35,9 +36,6 @@
/* 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 status change acknowledgment, in milliseconds */
-#define CSF_STATE_WAIT_TIMEOUT_MS (800) /* Relaxed to 800ms from 100ms */
-
/* Waiting timeout for scheduler state change for descheduling a CSG */
#define CSG_SCHED_STOP_TIMEOUT_MS (50)
@@ -51,8 +49,6 @@
/* CSF scheduler time slice value */
#define CSF_SCHEDULER_TIME_TICK_MS (100) /* 100 milliseconds */
-#define CSF_SCHEDULER_TIME_TICK_JIFFIES \
- msecs_to_jiffies(CSF_SCHEDULER_TIME_TICK_MS)
/*
* CSF scheduler time threshold for converting "tock" requests into "tick" if
@@ -81,19 +77,10 @@
/* CS suspended and is wait for a CQS condition */
#define CS_WAIT_SYNC_FLAG (1 << 1)
-/* This is to avoid the immediate power down of GPU when then are no groups
- * left for scheduling. GPUCORE-24250 would add the proper GPU idle detection
- * logic.
- */
-#define GPU_IDLE_POWEROFF_HYSTERESIS_DELAY msecs_to_jiffies((u32)10)
-
-/* This is a workaround before MIDHARC-3065, for avoiding some corner
- * cases where a hang is possible for gpu-queues that happen to be on
- * deferred commands when suspended.
- * The MIDHARC-3065 is scheduled with header 10.x.7/11.x.4.
+/* 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 USE_PRE_MIDHARC_3065_WORKAROUND (1)
+#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);
@@ -112,6 +99,91 @@ static int suspend_active_queue_groups(struct kbase_device *kbdev,
#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);
@@ -333,15 +405,7 @@ static void enable_gpu_idle_fw_timer(struct kbase_device *kbdev)
/* Update the timer_enabled flag requires holding interrupt_lock */
scheduler->gpu_idle_fw_timer_enabled = true;
-
- /* Only send the enable when walkaround is not used, before
- * MIDHARC-3065 is supported. This is for avoiding some
- * corner cases where a hang is possible for gpu-queues that
- * happen to be on some deferred commands when suspended.
- */
-#if (!USE_PRE_MIDHARC_3065_WORKAROUND)
kbase_csf_firmware_enable_gpu_idle_timer(kbdev);
-#endif
spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
}
@@ -356,13 +420,6 @@ static void disable_gpu_idle_fw_timer_locked(struct kbase_device *kbdev)
/* Update of the timer_enabled flag requires holding interrupt_lock */
if (scheduler->gpu_idle_fw_timer_enabled) {
scheduler->gpu_idle_fw_timer_enabled = false;
-
- /* Disable can always be sent, even with build configured
- * to use USE_PRE_MIDHARC_3065_WORKAROUND. There is no adverse
- * side effect for disabling a not yet enabled item with the
- * firmware interface call - it just has no effect (i.e. NOP).
- */
-
kbase_csf_firmware_disable_gpu_idle_timer(kbdev);
}
}
@@ -525,8 +582,7 @@ static int halt_stream_sync(struct kbase_queue *queue)
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(CSF_STATE_WAIT_TIMEOUT_MS);
+ 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)))
@@ -553,7 +609,7 @@ static int halt_stream_sync(struct kbase_queue *queue)
}
remaining =
- kbase_csf_timeout_in_jiffies(CSF_STATE_WAIT_TIMEOUT_MS);
+ kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
}
/* Set state to STOP */
@@ -561,16 +617,32 @@ static int halt_stream_sync(struct kbase_queue *queue)
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);
+ 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);
+ /* Queues that have failed to stop in time shall raise a fatal error
+ * as their group would fail to suspend which could no longer be safely
+ * resumed.
+ */
if (!remaining) {
+ unsigned long flags;
+
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);
+
+ spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, flags);
+ kbase_csf_add_queue_fatal_error(
+ queue, GPU_EXCEPTION_TYPE_SW_FAULT_2, 0);
+ spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock,
+ flags);
+
+ /* 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))
kbase_reset_gpu(kbdev);
}
@@ -654,8 +726,9 @@ retry:
while (group->run_state == KBASE_CSF_GROUP_IDLE) {
mutex_unlock(&scheduler->lock);
remaining = wait_event_timeout(kbdev->csf.event_wait,
- group->run_state != KBASE_CSF_GROUP_IDLE,
- CSF_STATE_WAIT_TIMEOUT_MS);
+ group->run_state !=
+ KBASE_CSF_GROUP_IDLE,
+ kbdev->csf.fw_timeout_ms);
mutex_lock(&scheduler->lock);
if (!remaining) {
dev_warn(kbdev->dev,
@@ -687,9 +760,10 @@ retry:
* 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 * CSF_SCHEDULER_TIME_TICK_MS));
+ 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);
@@ -747,9 +821,11 @@ retry:
/* 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),
- CSF_STATE_WAIT_TIMEOUT_MS);
+ (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,
@@ -769,21 +845,6 @@ retry:
return err;
}
-static int wait_gpu_reset(struct kbase_device *kbdev)
-{
- int ret = 0;
-
- lockdep_assert_held(&kbdev->csf.scheduler.lock);
-
- while (kbase_reset_gpu_is_active(kbdev) && !ret) {
- mutex_unlock(&kbdev->csf.scheduler.lock);
- ret = kbase_reset_gpu_wait(kbdev);
- mutex_lock(&kbdev->csf.scheduler.lock);
- }
-
- return ret;
-}
-
int kbase_csf_scheduler_queue_stop(struct kbase_queue *queue)
{
struct kbase_device *kbdev = queue->kctx->kbdev;
@@ -794,14 +855,13 @@ int kbase_csf_scheduler_queue_stop(struct kbase_queue *queue)
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);
- wait_gpu_reset(kbdev);
-
if (cs_enabled && queue_group_scheduled_locked(group)) {
struct kbase_csf_csg_slot *const csg_slot =
kbdev->csf.scheduler.csg_slots;
@@ -849,7 +909,7 @@ static void program_cs_extract_init(struct kbase_queue *queue)
}
static void program_cs(struct kbase_device *kbdev,
- struct kbase_queue *queue)
+ struct kbase_queue *queue, bool ring_csg_doorbell)
{
struct kbase_queue_group *group = queue->group;
struct kbase_csf_cmd_stream_group_info *ginfo;
@@ -924,7 +984,8 @@ static void program_cs(struct kbase_device *kbdev,
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);
+ kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, group->csg_nr,
+ ring_csg_doorbell);
update_hw_active(queue, true);
}
@@ -936,6 +997,7 @@ int kbase_csf_scheduler_queue_start(struct kbase_queue *queue)
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))
@@ -944,12 +1006,8 @@ int kbase_csf_scheduler_queue_start(struct kbase_queue *queue)
mutex_lock(&kbdev->csf.scheduler.lock);
KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_START, group, queue, group->run_state);
- err = wait_gpu_reset(kbdev);
- if (err) {
- dev_warn(kbdev->dev, "Unsuccessful GPU reset detected when kicking queue (csi_index=%d) of group %d",
- queue->csi_index, group->handle);
- } else if (group->run_state == KBASE_CSF_GROUP_FAULT_EVICTED) {
+ 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)
@@ -977,7 +1035,7 @@ int kbase_csf_scheduler_queue_start(struct kbase_queue *queue)
*/
kbase_csf_ring_cs_user_doorbell(kbdev, queue);
} else
- program_cs(kbdev, queue);
+ program_cs(kbdev, queue, true);
}
queue_delayed_work(system_long_wq,
&kbdev->csf.scheduler.ping_work,
@@ -1101,7 +1159,7 @@ static void halt_csg_slot(struct kbase_queue_group *group, bool suspend)
/* 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(CSF_STATE_WAIT_TIMEOUT_MS);
+ 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,
@@ -1230,6 +1288,13 @@ bool save_slot_cs(struct kbase_csf_cmd_stream_group_info const *const ginfo,
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 {
@@ -1321,7 +1386,7 @@ void insert_group_to_runnable(struct kbase_csf_scheduler *const scheduler,
WARN_ON(group->run_state != KBASE_CSF_GROUP_INACTIVE);
- if (WARN_ON(group->priority >= BASE_QUEUE_GROUP_PRIORITY_COUNT))
+ if (WARN_ON(group->priority >= KBASE_QUEUE_GROUP_PRIORITY_COUNT))
return;
group->run_state = run_state;
@@ -1346,8 +1411,7 @@ void insert_group_to_runnable(struct kbase_csf_scheduler *const scheduler,
scheduler->state == SCHED_SUSPENDED)) {
dev_dbg(kbdev->dev, "Kicking scheduler on first runnable group\n");
/* Fire a scheduling to start the time-slice */
- mod_delayed_work(kbdev->csf.scheduler.wq,
- &kbdev->csf.scheduler.tick_work, 0);
+ enqueue_tick_work(kbdev);
} else
schedule_in_cycle(group, false);
@@ -1404,11 +1468,12 @@ void remove_group_from_runnable(struct kbase_csf_scheduler *const scheduler,
WARN_ON(scheduler->total_runnable_grps == 0);
scheduler->total_runnable_grps--;
- if (!scheduler->total_runnable_grps &&
- scheduler->state != SCHED_SUSPENDED) {
+ if (!scheduler->total_runnable_grps) {
dev_dbg(kctx->kbdev->dev, "Scheduler idle has no runnable groups");
- mod_delayed_work(system_wq, &scheduler->gpu_idle_work,
- GPU_IDLE_POWEROFF_HYSTERESIS_DELAY);
+ 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 |
@@ -1496,13 +1561,38 @@ static void update_offslot_non_idle_cnt_on_grp_suspend(
}
}
-static bool confirm_cs_idle(struct kbase_queue *queue)
+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);
- return (input_addr[CS_INSERT_LO / sizeof(u64)] ==
- output_addr[CS_EXTRACT_LO / sizeof(u64)]);
+ 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)
@@ -1524,51 +1614,53 @@ static void save_csg_slot(struct kbase_queue_group *group)
if (!WARN_ON((state != CSG_ACK_STATE_SUSPEND) &&
(state != CSG_ACK_STATE_TERMINATE))) {
- int i;
+ u32 max_streams = ginfo->stream_num;
+ u32 i;
bool sync_wait = false;
- bool idle = true;
+ bool idle = kbase_csf_firmware_csg_output(ginfo, CSG_STATUS_STATE) &
+ CSG_STATUS_STATE_IDLE_MASK;
#ifdef CONFIG_MALI_NO_MALI
- for (i = 0; i < MAX_SUPPORTED_STREAMS_PER_GROUP; i++)
+ for (i = 0; i < max_streams; i++)
update_hw_active(group->bound_queues[i], false);
#endif
- /* The CSG idle status on suspension will be simplified when
- * MIDHARC_3065 is applied. Prior to it, we will have to
- * evaluate per-CS at the best effort (i.e. in case the
- * CS is executing some deffered instructions, the host
- * has no way to be sure a CS is actually idle). However
- * it is considered that the best effort approach is able to
- * handle the tests from base, where the CS commands are
- * generally simple ones.
- * With the inclusion of support for MIDHARC_3064, the CSG
- * run-state assertion previously in this function and its
- * utility helpers need to be dropped. This is because the
- * suspension actions can be triggered with the idle_worker
- * thread asynchronously to the scheduler ticks.
- */
- for (i = 0; i < MAX_SUPPORTED_STREAMS_PER_GROUP; i++) {
+ for (i = 0; idle && i < max_streams; i++) {
struct kbase_queue *const queue =
- group->bound_queues[i];
+ group->bound_queues[i];
- if (queue && queue->enabled) {
- if (save_slot_cs(ginfo, queue))
- sync_wait = true;
- else if (idle)
- idle = confirm_cs_idle(queue);
+ 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);
}
}
- /* 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 && idle)
- deschedule_idle_wait_group(scheduler, group);
- else if (idle) {
- group->run_state =
- KBASE_CSF_GROUP_SUSPENDED_ON_IDLE;
- dev_dbg(kbdev->dev, "Group-%d suspended: idle\n",
- group->handle);
+ 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;
}
@@ -1623,6 +1715,7 @@ static bool cleanup_csg_slot(struct kbase_queue_group *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);
+ WARN_ON(kctx->mmu_flush_pend_state != KCTX_MMU_FLUSH_NOT_PEND);
kbase_ctx_sched_release_ctx(kctx);
if (unlikely(group->faulted))
as_fault = true;
@@ -1749,6 +1842,7 @@ static void program_csg_slot(struct kbase_queue_group *group, s8 slot,
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
kbase_ctx_sched_retain_ctx(kctx);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+ kbase_mmu_deferred_flush_invalidate(kctx);
mutex_unlock(&kbdev->mmu_hw_mutex);
if (kctx->as_nr == KBASEP_AS_NR_INVALID) {
@@ -1770,7 +1864,7 @@ static void program_csg_slot(struct kbase_queue_group *group, s8 slot,
struct kbase_queue *queue = group->bound_queues[i];
if (queue)
- program_cs(kbdev, queue);
+ program_cs(kbdev, queue, false);
}
@@ -1922,8 +2016,7 @@ static void sched_evict_group(struct kbase_queue_group *group, bool fault,
static int term_group_sync(struct kbase_queue_group *group)
{
struct kbase_device *kbdev = group->kctx->kbdev;
- long remaining =
- kbase_csf_timeout_in_jiffies(CSF_STATE_WAIT_TIMEOUT_MS);
+ long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
int err = 0;
term_csg_slot(group);
@@ -1950,21 +2043,20 @@ void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group)
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;
- bool reset = kbase_reset_gpu_is_active(kbdev);
if (!kbasep_csf_scheduler_group_is_on_slot_locked(group)) {
sched_evict_group(group, false, true);
- } else if (reset || saved_state == SCHED_INACTIVE || force) {
+ } else if (saved_state == SCHED_INACTIVE || force) {
bool as_faulty;
- if (!reset)
- term_group_sync(group);
+ term_group_sync(group);
/* Treat the csg been terminated */
as_faulty = cleanup_csg_slot(group);
/* remove from the scheduler list */
@@ -2049,7 +2141,8 @@ 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 - 1;
+ 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);
@@ -2073,7 +2166,8 @@ static inline void count_active_address_space(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 - 1;
+ 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) {
@@ -2255,11 +2349,13 @@ static void program_suspending_csg_slots(struct kbase_device *kbdev)
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(CSF_STATE_WAIT_TIMEOUT_MS);
+ 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);
@@ -2304,13 +2400,49 @@ static void program_suspending_csg_slots(struct kbase_device *kbdev)
program_vacant_csg_slot(kbdev, (s8)i);
}
} else {
- dev_warn(kbdev->dev, "Timed out waiting for CSG slots to suspend, slot_mask: 0x%*pb\n",
- num_groups, slot_mask);
+ 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 %p on slot %u failed to suspend\n",
+ (void *)group, i);
+
+ /* The group has failed suspension, stop
+ * further examination.
+ */
+ clear_bit(i, slot_mask);
+ set_bit(i, scheduler->csgs_events_enable_mask);
+ }
- if (kbase_prepare_to_reset_gpu(kbdev))
- kbase_reset_gpu(kbdev);
suspend_wait_failed = true;
- break;
}
}
@@ -2318,7 +2450,7 @@ static void program_suspending_csg_slots(struct kbase_device *kbdev)
dev_info(kbdev->dev, "Scheduler evicting slots: 0x%*pb\n",
num_groups, evicted_mask);
- if (unlikely(!suspend_wait_failed)) {
+ if (likely(!suspend_wait_failed)) {
u32 i;
while (scheduler->ngrp_to_schedule &&
@@ -2332,6 +2464,9 @@ static void program_suspending_csg_slots(struct kbase_device *kbdev)
if (WARN_ON(!csg_slot_in_use(kbdev, (int)i)))
break;
}
+ } else {
+ if (kbase_prepare_to_reset_gpu(kbdev))
+ kbase_reset_gpu(kbdev);
}
}
@@ -2342,6 +2477,11 @@ static void suspend_queue_group(struct kbase_queue_group *group)
&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);
@@ -2356,8 +2496,7 @@ 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(CSF_STATE_WAIT_TIMEOUT_MS);
+ long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS) = {0};
u32 i;
@@ -2400,48 +2539,32 @@ static void wait_csg_slots_start(struct kbase_device *kbdev)
}
/**
- * group_on_slot_is_idle() - Check if the queue group resident on a CSG slot
- * is idle.
+ * 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 group's idleness is determined by looping over all the bound command
- * queues and checking their respective CS_STATUS_WAIT register as well as
- * the insert and extract offsets.
- *
- * This function would be simplified in future after the changes under
- * consideration with MIDHARC-3065 are introduced.
+ * 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.
- * @group: Pointer to the resident group on the given slot.
- * @slot: The slot that the given group is resident on.
+ * @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,
- struct kbase_queue_group *group, unsigned long slot)
+ unsigned long slot)
{
struct kbase_csf_cmd_stream_group_info *ginfo =
&kbdev->csf.global_iface.groups[slot];
- u32 i;
+ bool idle = kbase_csf_firmware_csg_output(ginfo, CSG_STATUS_STATE) &
+ CSG_STATUS_STATE_IDLE_MASK;
lockdep_assert_held(&kbdev->csf.scheduler.lock);
- for (i = 0; i < MAX_SUPPORTED_STREAMS_PER_GROUP; i++) {
- struct kbase_queue *queue = group->bound_queues[i];
-
- if (queue && queue->enabled) {
- struct kbase_csf_cmd_stream_info *stream =
- &ginfo->streams[queue->csi_index];
- u32 status = kbase_csf_firmware_cs_output(stream,
- CS_STATUS_WAIT);
- if (!CS_STATUS_WAIT_SYNC_WAIT_GET(status) &&
- !confirm_cs_idle(group->bound_queues[i]))
- return false;
- }
- }
-
- return true;
+ return idle;
}
/**
@@ -2537,8 +2660,7 @@ 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(CSF_STATE_WAIT_TIMEOUT_MS);
+ 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);
@@ -2549,8 +2671,10 @@ static void wait_csg_slots_finish_prio_update(struct kbase_device *kbdev)
* issue, no major consequences are expected as a
* result, so just warn the case.
*/
- dev_warn(kbdev->dev, "Timeout, skipping the update wait: slot mask=0x%lx",
- slot_mask[0]);
+ dev_warn(
+ kbdev->dev,
+ "Timeout on CSG_REQ:EP_CFG, skipping the update wait: slot mask=0x%lx",
+ slot_mask[0]);
}
}
@@ -2562,18 +2686,27 @@ void kbase_csf_scheduler_evict_ctx_slots(struct kbase_device *kbdev,
u32 num_groups = kbdev->csf.global_iface.group_num;
u32 slot;
DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS) = {0};
- DECLARE_BITMAP(terminated_slot_mask, MAX_SUPPORTED_CSGS);
- long remaining =
- kbase_csf_timeout_in_jiffies(DEFAULT_RESET_TIMEOUT_MS);
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);
}
}
@@ -2581,48 +2714,6 @@ void kbase_csf_scheduler_evict_ctx_slots(struct kbase_device *kbdev,
dev_info(kbdev->dev, "Evicting context %d_%d slots: 0x%*pb\n",
kctx->tgid, kctx->id, num_groups, slot_mask);
- bitmap_copy(terminated_slot_mask, slot_mask, MAX_SUPPORTED_CSGS);
- /* Only check for GPU reset once - this thread has the scheduler lock,
- * so even if the return value of kbase_reset_gpu_is_active changes,
- * no reset work would be done anyway until the scheduler lock was
- * released.
- */
- if (!kbase_reset_gpu_is_active(kbdev)) {
- while (remaining
- && !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)
- bitmap_andnot(slot_mask, slot_mask, changed,
- MAX_SUPPORTED_CSGS);
- }
- }
-
- for_each_set_bit(slot, terminated_slot_mask, num_groups) {
- bool as_fault;
-
- group = scheduler->csg_slots[slot].resident_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);
- }
-
- if (!remaining) {
- dev_warn(kbdev->dev, "Timeout on evicting ctx slots: 0x%*pb\n",
- num_groups, slot_mask);
- if (kbase_prepare_to_reset_gpu(kbdev))
- kbase_reset_gpu(kbdev);
- }
-
mutex_unlock(&scheduler->lock);
}
@@ -2861,7 +2952,7 @@ static void scheduler_ctx_scan_groups(struct kbase_device *kbdev,
lockdep_assert_held(&scheduler->lock);
if (WARN_ON(priority < 0) ||
- WARN_ON(priority >= BASE_QUEUE_GROUP_PRIORITY_COUNT))
+ WARN_ON(priority >= KBASE_QUEUE_GROUP_PRIORITY_COUNT))
return;
if (!kctx_as_enabled(kctx))
@@ -3044,15 +3135,17 @@ static void scheduler_update_idle_slots_status(struct kbase_device *kbdev,
/* The groups are aggregated into a single kernel doorbell request */
if (!bitmap_empty(csg_bitmap, num_groups)) {
long wt =
- kbase_csf_timeout_in_jiffies(CSF_STATE_WAIT_TIMEOUT_MS);
+ 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, treat groups as not idle: slot mask=0x%lx",
- csg_bitmap[0]);
+ 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);
@@ -3073,9 +3166,9 @@ static void scheduler_update_idle_slots_status(struct kbase_device *kbdev,
* 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. The idleness of a CSG is determined by looping over all the
- * bound CSs and checking their respective CS_STATUS_WAIT register
- * as well as the insert and extract offset.
+ * 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.
@@ -3108,10 +3201,10 @@ static void scheduler_handle_idle_slots(struct kbase_device *kbdev)
continue;
if (WARN_ON(group->run_state != KBASE_CSF_GROUP_RUNNABLE))
continue;
- if (WARN_ON(group->priority >= BASE_QUEUE_GROUP_PRIORITY_COUNT))
+ if (WARN_ON(group->priority >= KBASE_QUEUE_GROUP_PRIORITY_COUNT))
continue;
- if (group_on_slot_is_idle(kbdev, group, i)) {
+ if (group_on_slot_is_idle(kbdev, i)) {
group->run_state = KBASE_CSF_GROUP_IDLE;
set_bit(i, scheduler->csg_slots_idle_mask);
}
@@ -3166,7 +3259,7 @@ static struct kbase_queue_group *get_tock_top_group(
int i;
lockdep_assert_held(&scheduler->lock);
- for (i = 0; i < BASE_QUEUE_GROUP_PRIORITY_COUNT; ++i) {
+ 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;
@@ -3222,7 +3315,8 @@ static int suspend_active_groups_on_powerdown(struct kbase_device *kbdev,
static bool scheduler_idle_suspendable(struct kbase_device *kbdev)
{
- bool suspendable;
+ bool suspend;
+ unsigned long flags;
struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
lockdep_assert_held(&scheduler->lock);
@@ -3230,32 +3324,39 @@ static bool scheduler_idle_suspendable(struct kbase_device *kbdev)
if (scheduler->state == SCHED_SUSPENDED)
return false;
- if (scheduler->total_runnable_grps) {
-#if USE_PRE_MIDHARC_3065_WORKAROUND
- suspendable = false;
-#else
- unsigned long flags;
+ /* Work around for TTUX, skip scheduler suspend on idle-groups.
+ * ToDo: GPUCORE-26768, or its descendants after root cause
+ * investigation, needs to revert this WA.
+ */
+ if (scheduler->total_runnable_grps &&
+ (kbdev->gpu_props.props.raw_props.gpu_id &
+ GPU_ID2_PRODUCT_MODEL) == GPU_ID2_PRODUCT_TTUX) {
+ dev_dbg(kbdev->dev, "GPU: TTUX, skipping idle suspend");
+ return false;
+ }
- spin_lock_irqsave(&scheduler->interrupt_lock, flags);
+ 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 */
- suspendable = kbase_csf_scheduler_all_csgs_idle(kbdev) &&
- !atomic_read(&scheduler->non_idle_offslot_grps);
+ suspend = kbase_csf_scheduler_all_csgs_idle(kbdev) &&
+ !atomic_read(&scheduler->non_idle_offslot_grps) &&
+ kbase_pm_idle_groups_sched_suspendable(kbdev);
- spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
-#endif
- } else {
- /* No runnables inside the scheduler, can suspend */
- suspendable = true;
- }
+ spin_unlock(&scheduler->interrupt_lock);
+ } else
+ suspend = kbase_pm_no_runnables_sched_suspendable(kbdev);
- return suspendable;
+ 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.work);
+ work, struct kbase_device, csf.scheduler.gpu_idle_work);
struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
mutex_lock(&scheduler->lock);
@@ -3269,12 +3370,12 @@ static void gpu_idle_worker(struct work_struct *work)
if (!ret) {
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 */
- mod_delayed_work(scheduler->wq,
- &scheduler->tick_work, 0);
+ kbase_csf_scheduler_advance_tick(kbdev);
}
}
@@ -3310,7 +3411,7 @@ static int scheduler_prepare(struct kbase_device *kbdev)
bitmap_zero(scheduler->csg_slots_prio_update, MAX_SUPPORTED_CSGS);
/* Scan out to run groups */
- for (i = 0; i < BASE_QUEUE_GROUP_PRIORITY_COUNT; ++i) {
+ for (i = 0; i < KBASE_QUEUE_GROUP_PRIORITY_COUNT; ++i) {
struct kbase_context *kctx;
list_for_each_entry(kctx, &scheduler->runnable_kctxs, csf.link)
@@ -3343,7 +3444,7 @@ static int scheduler_prepare(struct kbase_device *kbdev)
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(CSF_STATE_WAIT_TIMEOUT_MS);
+ long wt = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms);
long remaining;
lockdep_assert_held(&scheduler->lock);
@@ -3387,6 +3488,7 @@ static void schedule_actions(struct kbase_device *kbdev)
struct kbase_queue_group *protm_grp;
int ret;
+ kbase_reset_gpu_assert_prevented(kbdev);
lockdep_assert_held(&scheduler->lock);
ret = kbase_pm_wait_for_desired_state(kbdev);
@@ -3413,6 +3515,7 @@ static void schedule_actions(struct kbase_device *kbdev)
if (protm_grp && scheduler->top_grp == protm_grp) {
dev_dbg(kbdev->dev, "Scheduler keep protm exec: group-%d",
protm_grp->handle);
+ atomic_dec(&scheduler->non_idle_offslot_grps);
} else if (scheduler->top_grp) {
if (protm_grp)
dev_dbg(kbdev->dev, "Scheduler drop protm exec: group-%d",
@@ -3470,13 +3573,16 @@ static void schedule_on_tock(struct work_struct *work)
csf.scheduler.tock_work.work);
struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
- mutex_lock(&scheduler->lock);
-
- if (kbase_reset_gpu_is_active(kbdev) ||
- (scheduler->state == SCHED_SUSPENDED)) {
- mutex_unlock(&scheduler->lock);
+ 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;
@@ -3493,25 +3599,36 @@ static void schedule_on_tock(struct work_struct *work)
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);
+ 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.work);
+ 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);
- if (kbase_reset_gpu_is_active(kbdev) ||
- (scheduler->state == SCHED_SUSPENDED)) {
- mutex_unlock(&scheduler->lock);
- return;
- }
+ WARN_ON(scheduler->tick_timer_active);
+ if (scheduler->state == SCHED_SUSPENDED)
+ goto exit_no_schedule_unlock;
scheduler->state = SCHED_BUSY;
/* Do scheduling stuff */
@@ -3527,17 +3644,23 @@ static void schedule_on_tick(struct work_struct *work)
/* Kicking next scheduling if needed */
if (likely(scheduler_timer_is_enabled_nolock(kbdev)) &&
(scheduler->total_runnable_grps > 0)) {
- mod_delayed_work(scheduler->wq, &scheduler->tick_work,
- CSF_SCHEDULER_TIME_TICK_JIFFIES);
- dev_dbg(kbdev->dev, "scheduling for next tick, num_runnable_groups:%u\n",
+ 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);
+ return;
+
+exit_no_schedule_unlock:
+ mutex_unlock(&scheduler->lock);
+ kbase_reset_gpu_allow(kbdev);
}
int wait_csg_slots_suspend(struct kbase_device *kbdev,
@@ -3618,8 +3741,7 @@ static int suspend_active_queue_groups(struct kbase_device *kbdev,
}
}
- ret = wait_csg_slots_suspend(kbdev, slot_mask,
- CSG_SUSPEND_ON_RESET_WAIT_TIMEOUT_MS);
+ ret = wait_csg_slots_suspend(kbdev, slot_mask, kbdev->reset_timeout_ms);
return ret;
}
@@ -3652,7 +3774,7 @@ static int suspend_active_queue_groups_on_reset(struct kbase_device *kbdev)
*/
kbase_gpu_start_cache_clean(kbdev);
ret2 = kbase_gpu_wait_cache_clean_timeout(kbdev,
- DEFAULT_RESET_TIMEOUT_MS);
+ kbdev->reset_timeout_ms);
if (ret2) {
dev_warn(kbdev->dev, "Timed out waiting for cache clean to complete before reset");
if (!ret)
@@ -3673,8 +3795,9 @@ static void scheduler_inner_reset(struct kbase_device *kbdev)
WARN_ON(csgs_active(kbdev));
/* Cancel any potential queued delayed work(s) */
- cancel_delayed_work_sync(&kbdev->csf.scheduler.gpu_idle_work);
- cancel_delayed_work_sync(&scheduler->tick_work);
+ 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);
@@ -3751,10 +3874,23 @@ static void firmware_aliveness_monitor(struct work_struct *work)
csf.scheduler.ping_work.work);
int err;
- /* Get the scheduler mutex to ensure that reset will not change while
- * this function is being executed as otherwise calling kbase_reset_gpu
- * when reset is already occurring is a programming error.
+ /* 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
@@ -3767,9 +3903,6 @@ static void firmware_aliveness_monitor(struct work_struct *work)
if (kbdev->csf.scheduler.state == SCHED_SUSPENDED)
goto exit;
- if (kbase_reset_gpu_is_active(kbdev))
- goto exit;
-
if (get_nr_active_csgs(kbdev) != 1)
goto exit;
@@ -3787,6 +3920,17 @@ static void firmware_aliveness_monitor(struct work_struct *work)
err = kbase_csf_firmware_ping(kbdev);
if (err) {
+ /* FW not responding means hardware counters will stop working.
+ * Put the backend into the unrecoverable error state to cause
+ * current and subsequent counter operations to immediately
+ * fail, avoiding the risk of a hang.
+ */
+ kbase_hwcnt_backend_csf_on_unrecoverable_error(
+ &kbdev->hwcnt_gpu_iface);
+
+ /* 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))
kbase_reset_gpu(kbdev);
} else if (get_nr_active_csgs(kbdev) == 1) {
@@ -3798,6 +3942,8 @@ static void firmware_aliveness_monitor(struct work_struct *work)
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,
@@ -3806,18 +3952,12 @@ int kbase_csf_scheduler_group_copy_suspend_buf(struct kbase_queue_group *group,
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;
+ int err = 0;
+ kbase_reset_gpu_assert_prevented(kbdev);
lockdep_assert_held(&kctx->csf.lock);
mutex_lock(&scheduler->lock);
- err = wait_gpu_reset(kbdev);
- if (err) {
- dev_warn(kbdev->dev, "Error while waiting for the GPU reset to complete when suspending group %d on slot %d",
- group->handle, group->csg_nr);
- goto exit;
- }
-
if (kbasep_csf_scheduler_group_is_on_slot_locked(group)) {
DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS) = {0};
@@ -3826,7 +3966,7 @@ int kbase_csf_scheduler_group_copy_suspend_buf(struct kbase_queue_group *group,
if (!WARN_ON(scheduler->state == SCHED_SUSPENDED))
suspend_queue_group(group);
err = wait_csg_slots_suspend(kbdev, slot_mask,
- CSF_STATE_WAIT_TIMEOUT_MS);
+ 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);
@@ -3999,6 +4139,13 @@ 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
@@ -4013,6 +4160,7 @@ void kbase_csf_scheduler_group_protm_enter(struct kbase_queue_group *group)
}
mutex_unlock(&scheduler->lock);
+ kbase_reset_gpu_allow(kbdev);
}
/**
@@ -4074,7 +4222,7 @@ int kbase_csf_scheduler_context_init(struct kbase_context *kctx)
int priority;
int err;
- for (priority = 0; priority < BASE_QUEUE_GROUP_PRIORITY_COUNT;
+ for (priority = 0; priority < KBASE_QUEUE_GROUP_PRIORITY_COUNT;
++priority) {
INIT_LIST_HEAD(&kctx->csf.sched.runnable_groups[priority]);
}
@@ -4142,11 +4290,11 @@ int kbase_csf_scheduler_init(struct kbase_device *kbdev)
return -ENOMEM;
}
- INIT_DEFERRABLE_WORK(&scheduler->tick_work, schedule_on_tick);
+ 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(GLB_REQ_WAIT_TIMEOUT_MS >= FIRMWARE_PING_INTERVAL_MS);
+ BUILD_BUG_ON(CSF_FIRMWARE_TIMEOUT_MS >= FIRMWARE_PING_INTERVAL_MS);
mutex_init(&scheduler->lock);
spin_lock_init(&scheduler->interrupt_lock);
@@ -4170,11 +4318,16 @@ int kbase_csf_scheduler_init(struct kbase_device *kbdev)
scheduler->active_protm_grp = NULL;
scheduler->gpu_idle_fw_timer_enabled = false;
scheduler->apply_async_protm = false;
+ scheduler->csg_scheduling_period_ms = CSF_SCHEDULER_TIME_TICK_MS;
scheduler_doorbell_init(kbdev);
- INIT_DEFERRABLE_WORK(&scheduler->gpu_idle_work, gpu_idle_worker);
+ 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;
}
@@ -4183,9 +4336,14 @@ 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));
- cancel_delayed_work_sync(&kbdev->csf.scheduler.gpu_idle_work);
+ 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_delayed_work_sync(&kbdev->csf.scheduler.tick_work);
+ cancel_tick_timer(kbdev);
+ cancel_work_sync(&kbdev->csf.scheduler.tick_work);
cancel_delayed_work_sync(&kbdev->csf.scheduler.tock_work);
destroy_workqueue(kbdev->csf.scheduler.wq);
mutex_destroy(&kbdev->csf.scheduler.lock);
@@ -4217,8 +4375,10 @@ static void scheduler_enable_tick_timer_nolock(struct kbase_device *kbdev)
(scheduler->state != SCHED_SUSPENDED));
if (scheduler->total_runnable_grps > 0) {
- mod_delayed_work(scheduler->wq, &scheduler->tick_work, 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);
}
}
@@ -4252,16 +4412,19 @@ void kbase_csf_scheduler_timer_set_enabled(struct kbase_device *kbdev,
currently_enabled = scheduler_timer_is_enabled_nolock(kbdev);
if (currently_enabled && !enable) {
scheduler->timer_enabled = false;
-
- cancel_delayed_work(&scheduler->tick_work);
+ 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);
}
-
- mutex_unlock(&scheduler->lock);
}
void kbase_csf_scheduler_kick(struct kbase_device *kbdev)
@@ -4274,7 +4437,7 @@ void kbase_csf_scheduler_kick(struct kbase_device *kbdev)
goto out;
if (scheduler->total_runnable_grps > 0) {
- mod_delayed_work(scheduler->wq, &scheduler->tick_work, 0);
+ enqueue_tick_work(kbdev);
dev_dbg(kbdev->dev, "Kicking the scheduler manually\n");
}
@@ -4287,7 +4450,7 @@ 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_delayed_work_sync(&scheduler->tick_work);
+ cancel_work_sync(&scheduler->tick_work);
cancel_delayed_work_sync(&scheduler->tock_work);
mutex_lock(&scheduler->lock);
@@ -4298,6 +4461,7 @@ void kbase_csf_scheduler_pm_suspend(struct kbase_device *kbdev)
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);
}
diff --git a/mali_kbase/csf/mali_kbase_csf_scheduler.h b/mali_kbase/csf/mali_kbase_csf_scheduler.h
index 24103b7..6e42c6e 100644
--- a/mali_kbase/csf/mali_kbase_csf_scheduler.h
+++ b/mali_kbase/csf/mali_kbase_csf_scheduler.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_
@@ -405,4 +424,46 @@ static inline bool kbase_csf_scheduler_all_csgs_idle(struct kbase_device *kbdev)
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) {
+ scheduler->tick_timer_active = false;
+ queue_work(scheduler->wq, &scheduler->tick_work);
+ }
+}
+
+/**
+ * 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);
+}
+
#endif /* _KBASE_CSF_SCHEDULER_H_ */
diff --git a/mali_kbase/csf/mali_kbase_csf_tiler_heap.c b/mali_kbase/csf/mali_kbase_csf_tiler_heap.c
index a3c9826..2da7a7d 100644
--- a/mali_kbase/csf/mali_kbase_csf_tiler_heap.c
+++ b/mali_kbase/csf/mali_kbase_csf_tiler_heap.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -20,6 +21,8 @@
*
*/
+#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"
@@ -337,6 +340,12 @@ static void delete_heap(struct kbase_csf_tiler_heap *heap)
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);
}
@@ -473,11 +482,20 @@ int kbase_csf_tiler_heap_init(struct kbase_context *const kctx,
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);
}
@@ -582,6 +600,13 @@ int kbase_csf_tiler_heap_alloc_new_chunk(struct kbase_context *kctx,
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/mali_kbase/csf/mali_kbase_csf_tiler_heap.h b/mali_kbase/csf/mali_kbase_csf_tiler_heap.h
index d85ac11..13d0564 100644
--- a/mali_kbase/csf/mali_kbase_csf_tiler_heap.h
+++ b/mali_kbase/csf/mali_kbase_csf_tiler_heap.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_
diff --git a/mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.c b/mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.c
index 5d744b8..e38863c 100644
--- a/mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.c
+++ b/mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.h b/mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.h
index 44c580d..c8f37fd 100644
--- a/mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.h
+++ b/mali_kbase/csf/mali_kbase_csf_tiler_heap_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
diff --git a/mali_kbase/csf/mali_kbase_csf_tiler_heap_def.h b/mali_kbase/csf/mali_kbase_csf_tiler_heap_def.h
index 1f9e208..fa94dcb 100644
--- a/mali_kbase/csf/mali_kbase_csf_tiler_heap_def.h
+++ b/mali_kbase/csf/mali_kbase_csf_tiler_heap_def.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
@@ -97,6 +116,8 @@ struct kbase_csf_tiler_heap_chunk {
* @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 {
@@ -107,6 +128,7 @@ struct kbase_csf_tiler_heap {
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/mali_kbase/csf/mali_kbase_csf_timeout.c b/mali_kbase/csf/mali_kbase_csf_timeout.c
index 43b63bd..1396899 100644
--- a/mali_kbase/csf/mali_kbase_csf_timeout.c
+++ b/mali_kbase/csf/mali_kbase_csf_timeout.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/csf/mali_kbase_csf_timeout.h b/mali_kbase/csf/mali_kbase_csf_timeout.h
index dc6f2f2..4ec113d 100644
--- a/mali_kbase/csf/mali_kbase_csf_timeout.h
+++ b/mali_kbase/csf/mali_kbase_csf_timeout.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_
diff --git a/mali_kbase/csf/mali_kbase_csf_tl_reader.c b/mali_kbase/csf/mali_kbase_csf_tl_reader.c
index d5b1649..d7006e6 100644
--- a/mali_kbase/csf/mali_kbase_csf_tl_reader.c
+++ b/mali_kbase/csf/mali_kbase_csf_tl_reader.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -40,7 +41,7 @@
#include "tl/mali_kbase_timeline_priv.h"
#include <linux/debugfs.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0))
+#if (KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE)
#define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE
#endif
#endif
diff --git a/mali_kbase/csf/mali_kbase_csf_tl_reader.h b/mali_kbase/csf/mali_kbase_csf_tl_reader.h
index f5ce9d6..14175b3 100644
--- a/mali_kbase/csf/mali_kbase_csf_tl_reader.h
+++ b/mali_kbase/csf/mali_kbase_csf_tl_reader.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_
@@ -28,7 +47,7 @@
#include <asm/page.h>
/** The number of pages used for CSFFW trace buffer. Can be tweaked. */
-#define KBASE_CSF_TL_BUFFER_NR_PAGES 4
+#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. */
diff --git a/mali_kbase/csf/mali_kbase_csf_trace_buffer.c b/mali_kbase/csf/mali_kbase_csf_trace_buffer.c
index c39c789..8eb0408 100644
--- a/mali_kbase/csf/mali_kbase_csf_trace_buffer.c
+++ b/mali_kbase/csf/mali_kbase_csf_trace_buffer.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -31,7 +32,7 @@
#include <linux/mman.h>
#ifdef CONFIG_DEBUG_FS
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0))
+#if (KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE)
#define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE
#endif
#endif
diff --git a/mali_kbase/csf/mali_kbase_csf_trace_buffer.h b/mali_kbase/csf/mali_kbase_csf_trace_buffer.h
index 2cac55e..887a5e7 100644
--- a/mali_kbase/csf/mali_kbase_csf_trace_buffer.h
+++ b/mali_kbase/csf/mali_kbase_csf_trace_buffer.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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_
diff --git a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_csf.h b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_csf.h
index 32181d7..51ab2f5 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_csf.h
+++ b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_csf.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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.
+ *
*/
/*
@@ -109,6 +128,46 @@ int dummy_array[] = {
KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_START),
KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_STOP),
+ /*
+ * 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
diff --git a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_jm.h b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_jm.h
index b201e49..8e846ad 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_jm.h
+++ b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_codes_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2015,2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-2015, 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 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.
+ *
*/
/*
diff --git a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.c b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.c
index 2ea901b..93a082a 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.c
+++ b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -19,6 +20,7 @@
* 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_csf.h"
@@ -28,30 +30,30 @@
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"), 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 struct kbase_ktrace_backend * const be_msg = &trace_msg->backend;
+ 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->flags & KBASE_KTRACE_FLAG_CSF_GROUP) {
- const s8 slot = be_msg->csg_nr;
+ 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->group_handle, slot), 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->slot_prio), 0);
+ "%u", be_msg->gpu.slot_prio), 0);
/* , */
*written += MAX(snprintf(buffer + *written,
@@ -65,10 +67,24 @@ void kbasep_ktrace_backend_format_msg(struct kbase_ktrace_msg *trace_msg,
}
/* queue parts: csi */
- if (trace_msg->backend.flags & KBASE_KTRACE_FLAG_CSF_QUEUE)
+ 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),
- "%d", be_msg->csi_index), 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
@@ -95,14 +111,14 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
else if (queue)
kctx = queue->kctx;
- /* 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 CSF-specific parts of the message
*
@@ -111,30 +127,66 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
*/
if (queue) {
- trace_msg->backend.flags |= KBASE_KTRACE_FLAG_CSF_QUEUE;
- trace_msg->backend.csi_index = queue->csi_index;
+ 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.flags |= KBASE_KTRACE_FLAG_CSF_GROUP;
+ trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_CSF_GROUP;
- trace_msg->backend.csg_nr = slot;
+ trace_msg->backend.gpu.csg_nr = slot;
if (slot >= 0) {
- struct kbase_csf_csg_slot *csg_slot = &kbdev->csf.scheduler.csg_slots[slot];
+ struct kbase_csf_csg_slot *csg_slot =
+ &kbdev->csf.scheduler.csg_slots[slot];
- trace_msg->backend.slot_prio = csg_slot->priority;
+ 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.group_handle = group->handle;
+ trace_msg->backend.gpu.group_handle = group->handle;
}
- WARN_ON((trace_msg->backend.flags & ~KBASE_KTRACE_FLAG_ALL));
+ 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);
diff --git a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.h b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.h
index 6c539b7..a229333 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.h
+++ b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_csf.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
@@ -44,9 +63,33 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
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)
+ 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 */
@@ -55,12 +98,21 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
CSTD_UNUSED(kbdev);\
CSTD_NOP(code);\
CSTD_UNUSED(group);\
- CSTD_UNUSED(queue); \
+ 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 */
/*
@@ -74,6 +126,9 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
#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) \
@@ -86,6 +141,14 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
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 */
/*
@@ -108,7 +171,7 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
*/
#define KBASE_KTRACE_ADD_CSF_GRP(kbdev, code, group, info_val) \
do { \
- /* capture values that could come from non-pure function calls */ \
+ /* 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, \
@@ -134,7 +197,7 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
*/
#define KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, code, group, queue, info_val) \
do { \
- /* capture values that could come from non-pure function calls */ \
+ /* 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; \
@@ -144,4 +207,17 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev,
__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/mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_csf.h b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_csf.h
index 722b410..426218b 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_csf.h
+++ b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_csf.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
@@ -38,9 +57,15 @@
* 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.
*/
#define KBASE_KTRACE_VERSION_MAJOR 1
-#define KBASE_KTRACE_VERSION_MINOR 1
+#define KBASE_KTRACE_VERSION_MINOR 2
/* indicates if the trace message has valid queue-group related info. */
#define KBASE_KTRACE_FLAG_CSF_GROUP (((kbase_ktrace_flag_t)1) << 0)
@@ -48,37 +73,55 @@
/* 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_GROUP | KBASE_KTRACE_FLAG_CSF_QUEUE | \
+ KBASE_KTRACE_FLAG_CSF_KCPU)
/**
- * struct kbase_ktrace_backend - backend specific part of a trace message
- *
- * @code: Identifies the event, refer to enum kbase_ktrace_code.
- * @flags: indicates information about the trace message itself. Used
- * during dumping of the message.
- * @group_handle: Handle identifying the associated queue group. Only valid
- * when @flags contains KBASE_KTRACE_FLAG_CSF_GROUP.
- * @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.
- * @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.
- * @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 - backend specific part of a trace message
+ *
+ * @code: Identifies the event, refer to enum kbase_ktrace_code.
+ * @flags: indicates information about the trace message itself. Used
+ * during dumping of the message.
+ * @id: ID of the KCPU queue.
+ * @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
+ * @group_handle: Handle identifying the associated queue group. Only valid
+ * when @flags contains KBASE_KTRACE_FLAG_CSF_GROUP.
+ * @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.
+ * @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.
+ * @csi_index: ID of the associated queue's CS HW interface.
+ * Only valid when @flags contains KBASE_KTRACE_FLAG_CSF_QUEUE.
*/
-struct kbase_ktrace_backend {
+
+union kbase_ktrace_backend {
/* Place 64 and 32-bit members together */
/* Pack smaller members together */
- kbase_ktrace_code_t code;
- kbase_ktrace_flag_t flags;
- u8 group_handle;
- s8 csg_nr;
- u8 slot_prio;
- s8 csi_index;
+ 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 */
diff --git a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_jm.h b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_jm.h
index ea8e01a..4b4cefc 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_jm.h
+++ b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_defs_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_JM_H_
@@ -71,7 +90,9 @@
| 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
@@ -86,16 +107,20 @@
* @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 */
diff --git a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.c b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.c
index 1b82128..55e4391 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.c
+++ b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -19,6 +20,7 @@
* 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 +37,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,30 +86,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.flags & ~KBASE_KTRACE_FLAG_ALL));
+ WARN_ON((trace_msg->backend.gpu.flags & ~KBASE_KTRACE_FLAG_ALL));
/* Done */
spin_unlock_irqrestore(&kbdev->ktrace.lock, irqflags);
diff --git a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.h b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.h
index bf258d6..43f5526 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.h
+++ b/mali_kbase/debug/backend/mali_kbase_debug_ktrace_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_JM_H_
diff --git a/mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_csf.h b/mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_csf.h
index d103e57..bb5db30 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_csf.h
+++ b/mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_csf.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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.
+ *
*/
/*
@@ -144,4 +163,50 @@ DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_STOP);
#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/mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_jm.h b/mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_jm.h
index 037b1ed..b0722f9 100644
--- a/mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_jm.h
+++ b/mali_kbase/debug/backend/mali_kbase_debug_linux_ktrace_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014,2018,2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 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 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.
+ *
*/
/*
diff --git a/mali_kbase/debug/mali_kbase_debug_ktrace.c b/mali_kbase/debug/mali_kbase_debug_ktrace.c
index a13c0ba..a38a656 100644
--- a/mali_kbase/debug/mali_kbase_debug_ktrace.c
+++ b/mali_kbase/debug/mali_kbase_debug_ktrace.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -19,6 +20,7 @@
* SPDX-License-Identifier: GPL-2.0
*
*/
+
#include <mali_kbase.h>
#include "debug/mali_kbase_debug_ktrace_internal.h"
@@ -93,7 +95,8 @@ static void kbasep_ktrace_format_msg(struct kbase_ktrace_msg *trace_msg,
(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]), 0);
+ kbasep_ktrace_code_string[trace_msg->backend.gpu.code]),
+ 0);
/* kctx part: */
if (trace_msg->kctx_tgid) {
@@ -171,8 +174,8 @@ void kbasep_ktrace_msg_init(struct kbase_ktrace *ktrace,
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,
@@ -189,7 +192,7 @@ void kbasep_ktrace_add(struct kbase_device *kbdev, enum kbase_ktrace_code code,
/* 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);
diff --git a/mali_kbase/debug/mali_kbase_debug_ktrace.h b/mali_kbase/debug/mali_kbase_debug_ktrace.h
index 7263e0c..71f0fd7 100644
--- a/mali_kbase/debug/mali_kbase_debug_ktrace.h
+++ b/mali_kbase/debug/mali_kbase_debug_ktrace.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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.
+ *
*/
/*
diff --git a/mali_kbase/debug/mali_kbase_debug_ktrace_codes.h b/mali_kbase/debug/mali_kbase_debug_ktrace_codes.h
index dd0ad06..fa842f9 100644
--- a/mali_kbase/debug/mali_kbase_debug_ktrace_codes.h
+++ b/mali_kbase/debug/mali_kbase_debug_ktrace_codes.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2015,2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-2015, 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 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.
+ *
*/
/*
@@ -146,7 +165,14 @@ 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"
diff --git a/mali_kbase/debug/mali_kbase_debug_ktrace_defs.h b/mali_kbase/debug/mali_kbase_debug_ktrace_defs.h
index 3b7db2e..841f11b 100644
--- a/mali_kbase/debug/mali_kbase_debug_ktrace_defs.h
+++ b/mali_kbase/debug/mali_kbase_debug_ktrace_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_H_
@@ -78,12 +97,18 @@ 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
@@ -145,9 +170,9 @@ enum kbase_ktrace_code {
* @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;
@@ -156,8 +181,7 @@ struct kbase_ktrace_msg {
pid_t kctx_tgid;
u32 kctx_id;
u64 info_val;
-
- struct kbase_ktrace_backend backend;
+ union kbase_ktrace_backend backend;
};
struct kbase_ktrace {
diff --git a/mali_kbase/debug/mali_kbase_debug_ktrace_internal.h b/mali_kbase/debug/mali_kbase_debug_ktrace_internal.h
index e450760..02b90ab 100644
--- a/mali_kbase/debug/mali_kbase_debug_ktrace_internal.h
+++ b/mali_kbase/debug/mali_kbase_debug_ktrace_internal.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_INTERNAL_H_
diff --git a/mali_kbase/debug/mali_kbase_debug_linux_ktrace.h b/mali_kbase/debug/mali_kbase_debug_linux_ktrace.h
index a7310eb..86efdc4 100644
--- a/mali_kbase/debug/mali_kbase_debug_linux_ktrace.h
+++ b/mali_kbase/debug/mali_kbase_debug_linux_ktrace.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014,2018,2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 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 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.
+ *
*/
/*
@@ -98,7 +117,13 @@ 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
+DEFINE_MALI_ADD_EVENT(ARB_GPU_LOST);
+DEFINE_MALI_ADD_EVENT(ARB_VM_STATE);
+DEFINE_MALI_ADD_EVENT(ARB_VM_EVT);
+
+#endif
#if MALI_USE_CSF
#include "mali_kbase_debug_linux_ktrace_csf.h"
#else
diff --git a/mali_kbase/device/backend/mali_kbase_device_csf.c b/mali_kbase/device/backend/mali_kbase_device_csf.c
index 7cd3e4a..c70df70 100644
--- a/mali_kbase/device/backend/mali_kbase_device_csf.c
+++ b/mali_kbase/device/backend/mali_kbase_device_csf.c
@@ -129,6 +129,8 @@ static int kbase_backend_late_init(struct kbase_device *kbdev)
init_waitqueue_head(&kbdev->hwaccess.backend.reset_wait);
+ /* kbase_pm_context_idle is called after the boot of firmware */
+
return 0;
fail_update_l2_features:
@@ -146,6 +148,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);
@@ -206,20 +209,26 @@ static const struct kbase_device_init dev_init[] = {
{kbase_clk_rate_trace_manager_init,
kbase_clk_rate_trace_manager_term,
"Clock rate trace manager initialization failed"},
- {kbase_device_hwcnt_backend_jm_init,
- kbase_device_hwcnt_backend_jm_term,
+ {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_device_csf_firmware_init, kbase_device_csf_firmware_term,
+ "Firmware initialization failed"},
+ {kbase_device_hwcnt_backend_csf_metadata_init,
+ kbase_device_hwcnt_backend_csf_metadata_term,
+ "GPU hwcnt backend metadata creation 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"},
- {kbase_device_csf_firmware_init, kbase_device_csf_firmware_term,
- "Firmware initialization failed"},
#ifdef MALI_KBASE_BUILD
{kbase_device_debugfs_init, kbase_device_debugfs_term,
"DebugFS initialization failed"},
diff --git a/mali_kbase/device/backend/mali_kbase_device_hw_csf.c b/mali_kbase/device/backend/mali_kbase_device_hw_csf.c
index ff899be..1ae311a 100644
--- a/mali_kbase/device/backend/mali_kbase_device_hw_csf.c
+++ b/mali_kbase/device/backend/mali_kbase_device_hw_csf.c
@@ -71,6 +71,15 @@ static bool kbase_gpu_fault_interrupt(struct kbase_device *kbdev)
if (!as_valid || (as_nr == MCU_AS_NR)) {
kbase_report_gpu_fault(kbdev, status, as_nr, as_valid);
+ /* MCU bus fault could mean hardware counters will stop
+ * working.
+ * Put the backend into the unrecoverable error state to
+ * cause current and subsequent counter operations to
+ * immediately fail, avoiding the risk of a hang.
+ */
+ kbase_hwcnt_backend_csf_on_unrecoverable_error(
+ &kbdev->hwcnt_gpu_iface);
+
dev_err(kbdev->dev, "GPU bus fault triggering gpu-reset ...\n");
if (kbase_prepare_to_reset_gpu(kbdev))
kbase_reset_gpu(kbdev);
@@ -120,12 +129,21 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val)
} } };
scheduler->active_protm_grp->faulted = true;
- kbase_csf_add_fatal_error_to_kctx(
+ 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);
+ /* Protected fault means we're unlikely to have the counter
+ * operations we might do during reset acknowledged.
+ * Put the backend into the unrecoverable error state to cause
+ * current and subsequent counter operations to immediately
+ * fail, avoiding the risk of a hang.
+ */
+ kbase_hwcnt_backend_csf_on_unrecoverable_error(
+ &kbdev->hwcnt_gpu_iface);
+
if (kbase_prepare_to_reset_gpu(kbdev))
kbase_reset_gpu(kbdev);
}
diff --git a/mali_kbase/device/backend/mali_kbase_device_jm.c b/mali_kbase/device/backend/mali_kbase_device_jm.c
index 2a45a33..0d8de3c 100644
--- a/mali_kbase/device/backend/mali_kbase_device_jm.c
+++ b/mali_kbase/device/backend/mali_kbase_device_jm.c
@@ -96,9 +96,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)
@@ -106,6 +103,9 @@ 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);
+
return 0;
fail_update_l2_features:
@@ -121,6 +121,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);
diff --git a/mali_kbase/device/mali_kbase_device.c b/mali_kbase/device/mali_kbase_device.c
index 76fb33a..6178cc8 100644
--- a/mali_kbase/device/mali_kbase_device.c
+++ b/mali_kbase/device/mali_kbase_device.c
@@ -41,10 +41,14 @@
#include <tl/mali_kbase_timeline.h>
#include "mali_kbase_vinstr.h"
+#if MALI_USE_CSF
+#include <mali_kbase_hwcnt_backend_csf_if_fw.h>
+#endif
#include "mali_kbase_hwcnt_context.h"
#include "mali_kbase_hwcnt_virtualizer.h"
#include "mali_kbase_device.h"
+#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"
@@ -112,6 +116,9 @@ int kbase_device_misc_init(struct kbase_device * const kbdev)
#ifdef CONFIG_ARM64
struct device_node *np = NULL;
#endif /* CONFIG_ARM64 */
+#ifdef CONFIG_OF
+ struct device_node *prio_ctrl_node = NULL;
+#endif
spin_lock_init(&kbdev->mmu_mask_change);
mutex_init(&kbdev->mmu_hw_mutex);
@@ -136,6 +143,34 @@ int kbase_device_misc_init(struct kbase_device * const kbdev)
}
}
#endif /* CONFIG_ARM64 */
+ kbdev->pcm_dev = NULL;
+#ifdef CONFIG_OF
+ /* 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\n");
+ } 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\n");
+ } else {
+ kbdev->pcm_dev = platform_get_drvdata(pdev);
+ if (!kbdev->pcm_dev) {
+ dev_info(kbdev->dev,
+ "Priority control manager is not ready\n");
+ err = -EPROBE_DEFER;
+ }
+ }
+ of_node_put(prio_ctrl_node);
+ }
+#endif /* CONFIG_OF */
+
/* Get the list of workarounds for issues on the current HW
* (identified by the GPU_ID register)
*/
@@ -152,11 +187,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
*/
@@ -179,7 +209,9 @@ int kbase_device_misc_init(struct kbase_device * const kbdev)
if (err)
goto dma_set_mask_failed;
+#if !MALI_USE_CSF
spin_lock_init(&kbdev->hwcnt.lock);
+#endif
err = kbase_ktrace_init(kbdev);
if (err)
@@ -191,9 +223,11 @@ int kbase_device_misc_init(struct kbase_device * const kbdev)
atomic_set(&kbdev->ctx_num, 0);
+#if !MALI_USE_CSF
err = kbase_instr_backend_init(kbdev);
if (err)
goto term_trace;
+#endif
kbdev->pm.dvfs_period = DEFAULT_PM_DVFS_PERIOD;
@@ -210,8 +244,12 @@ int kbase_device_misc_init(struct kbase_device * const kbdev)
spin_lock_init(&kbdev->hwaccess_lock);
return 0;
+
+#if !MALI_USE_CSF
term_trace:
kbase_ktrace_term(kbdev);
+#endif
+
term_as:
kbase_device_all_as_term(kbdev);
dma_set_mask_failed:
@@ -229,7 +267,9 @@ void kbase_device_misc_term(struct kbase_device *kbdev)
kbase_debug_assert_register_hook(NULL, NULL);
#endif
+#if !MALI_USE_CSF
kbase_instr_backend_term(kbdev);
+#endif
kbase_ktrace_term(kbdev);
@@ -253,6 +293,49 @@ void kbase_increment_device_id(void)
kbase_dev_nr++;
}
+#if MALI_USE_CSF
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+void kbase_device_hwcnt_backend_csf_term(struct kbase_device *kbdev)
+{
+ kbase_hwcnt_backend_csf_destroy(&kbdev->hwcnt_gpu_iface);
+}
+
+int kbase_device_hwcnt_backend_csf_metadata_init(struct kbase_device *kbdev)
+{
+ /* For CSF GPUs, HWC metadata needs to query informatoin from CSF
+ * firmware, so the initialization of HWC metadata only can be called
+ * after firmware initialised, but firmware initialization depends on
+ * HWC backend initialization, so we need to separate HWC backend
+ * metadata initialization from HWC backend initialization.
+ */
+ return kbase_hwcnt_backend_csf_metadata_init(&kbdev->hwcnt_gpu_iface);
+}
+
+void kbase_device_hwcnt_backend_csf_metadata_term(struct kbase_device *kbdev)
+{
+ kbase_hwcnt_backend_csf_metadata_term(&kbdev->hwcnt_gpu_iface);
+}
+#else
+
int kbase_device_hwcnt_backend_jm_init(struct kbase_device *kbdev)
{
return kbase_hwcnt_backend_jm_create(kbdev, &kbdev->hwcnt_gpu_iface);
@@ -262,6 +345,7 @@ void kbase_device_hwcnt_backend_jm_term(struct kbase_device *kbdev)
{
kbase_hwcnt_backend_jm_destroy(&kbdev->hwcnt_gpu_iface);
}
+#endif /* MALI_USE_CSF */
int kbase_device_hwcnt_context_init(struct kbase_device *kbdev)
{
diff --git a/mali_kbase/device/mali_kbase_device.h b/mali_kbase/device/mali_kbase_device.h
index 33264bc..32e85fd 100644
--- a/mali_kbase/device/mali_kbase_device.h
+++ b/mali_kbase/device/mali_kbase_device.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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>
diff --git a/mali_kbase/device/mali_kbase_device_internal.h b/mali_kbase/device/mali_kbase_device_internal.h
index 5464458..b07b22c 100644
--- a/mali_kbase/device/mali_kbase_device_internal.h
+++ b/mali_kbase/device/mali_kbase_device_internal.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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>
@@ -43,8 +62,17 @@ 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);
+#if MALI_USE_CSF
+int kbase_device_hwcnt_backend_csf_init(struct kbase_device *kbdev);
+void kbase_device_hwcnt_backend_csf_term(struct kbase_device *kbdev);
+int kbase_device_hwcnt_backend_csf_if_init(struct kbase_device *kbdev);
+void kbase_device_hwcnt_backend_csf_if_term(struct kbase_device *kbdev);
+int kbase_device_hwcnt_backend_csf_metadata_init(struct kbase_device *kbdev);
+void kbase_device_hwcnt_backend_csf_metadata_term(struct kbase_device *kbdev);
+#else
int kbase_device_hwcnt_backend_jm_init(struct kbase_device *kbdev);
void kbase_device_hwcnt_backend_jm_term(struct kbase_device *kbdev);
+#endif
int kbase_device_hwcnt_context_init(struct kbase_device *kbdev);
void kbase_device_hwcnt_context_term(struct kbase_device *kbdev);
diff --git a/mali_kbase/gpu/backend/mali_kbase_gpu_fault_csf.c b/mali_kbase/gpu/backend/mali_kbase_gpu_fault_csf.c
index 8dde2b1..a9f9cb8 100644
--- a/mali_kbase/gpu/backend/mali_kbase_gpu_fault_csf.c
+++ b/mali_kbase/gpu/backend/mali_kbase_gpu_fault_csf.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/gpu/backend/mali_kbase_gpu_fault_jm.c b/mali_kbase/gpu/backend/mali_kbase_gpu_fault_jm.c
index 56f5415..6015062 100644
--- a/mali_kbase/gpu/backend/mali_kbase_gpu_fault_jm.c
+++ b/mali_kbase/gpu/backend/mali_kbase_gpu_fault_jm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/gpu/backend/mali_kbase_gpu_regmap_csf.h b/mali_kbase/gpu/backend/mali_kbase_gpu_regmap_csf.h
index 4a5f97f..04ee612 100644
--- a/mali_kbase/gpu/backend/mali_kbase_gpu_regmap_csf.h
+++ b/mali_kbase/gpu/backend/mali_kbase_gpu_regmap_csf.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_GPU_REGMAP_CSF_H_
@@ -64,8 +83,6 @@
#include "csf/mali_gpu_csf_control_registers.h"
-#define GPU_CONTROL_MCU_REG(r) (GPU_CONTROL_MCU + (r))
-
/* Set to implementation defined, outer caching */
#define AS_MEMATTR_AARCH64_OUTER_IMPL_DEF 0x88ull
@@ -111,6 +128,7 @@
#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
@@ -281,9 +299,12 @@
#define GPU_FAULTSTATUS_ACCESS_TYPE_WRITE 0x3
/* End of GPU_FAULTSTATUS_ACCESS_TYPE values */
-/* TODO: Remove once 10.x.6 headers became available */
+/* 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
diff --git a/mali_kbase/gpu/backend/mali_kbase_gpu_regmap_jm.h b/mali_kbase/gpu/backend/mali_kbase_gpu_regmap_jm.h
index c9c2fbd..57d567b 100644
--- a/mali_kbase/gpu/backend/mali_kbase_gpu_regmap_jm.h
+++ b/mali_kbase/gpu/backend/mali_kbase_gpu_regmap_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_GPU_REGMAP_JM_H_
@@ -139,8 +158,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 */
@@ -151,8 +170,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 */
diff --git a/mali_kbase/gpu/mali_kbase_gpu.c b/mali_kbase/gpu/mali_kbase_gpu.c
index 3128db4..4cc8750 100644
--- a/mali_kbase/gpu/mali_kbase_gpu.c
+++ b/mali_kbase/gpu/mali_kbase_gpu.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -22,6 +23,7 @@
#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/mali_kbase/gpu/mali_kbase_gpu.h b/mali_kbase/gpu/mali_kbase_gpu.h
index 9516e56..0594cd3 100644
--- a/mali_kbase/gpu/mali_kbase_gpu.h
+++ b/mali_kbase/gpu/mali_kbase_gpu.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_GPU_H_
diff --git a/mali_kbase/gpu/mali_kbase_gpu_coherency.h b/mali_kbase/gpu/mali_kbase_gpu_coherency.h
index bb2b161..00991dd 100644
--- a/mali_kbase/gpu/mali_kbase_gpu_coherency.h
+++ b/mali_kbase/gpu/mali_kbase_gpu_coherency.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2015-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 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_GPU_COHERENCY_H_
diff --git a/mali_kbase/gpu/mali_kbase_gpu_fault.h b/mali_kbase/gpu/mali_kbase_gpu_fault.h
index e63c388..a09c3ba 100644
--- a/mali_kbase/gpu/mali_kbase_gpu_fault.h
+++ b/mali_kbase/gpu/mali_kbase_gpu_fault.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_GPU_FAULT_H_
diff --git a/mali_kbase/gpu/mali_kbase_gpu_id.h b/mali_kbase/gpu/mali_kbase_gpu_id.h
index 446b83a..fda52e6 100644
--- a/mali_kbase/gpu/mali_kbase_gpu_id.h
+++ b/mali_kbase/gpu/mali_kbase_gpu_id.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2015-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 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_GPU_ID_H_
@@ -53,7 +72,8 @@
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) | \
@@ -61,7 +81,8 @@
(((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) | \
@@ -76,14 +97,16 @@
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))
/* 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) & \
GPU_ID2_PRODUCT_MODEL)
@@ -108,7 +131,8 @@
#define GPU_ID2_PRODUCT_LTUX GPU_ID2_MODEL_MAKE(11, 3)
/* 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) | \
diff --git a/mali_kbase/gpu/mali_kbase_gpu_regmap.h b/mali_kbase/gpu/mali_kbase_gpu_regmap.h
index acd6baa..8c1e41c 100644
--- a/mali_kbase/gpu/mali_kbase_gpu_regmap.h
+++ b/mali_kbase/gpu/mali_kbase_gpu_regmap.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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_GPU_REGMAP_H_
@@ -66,7 +85,8 @@
#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 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 */
@@ -142,6 +162,10 @@
#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 */
@@ -241,7 +265,8 @@
#define MMU_PAGE_FAULT_FLAGS 16
/* Macros returning a bitmask to retrieve page fault or bus error flags from
- * MMU registers */
+ * MMU registers
+ */
#define MMU_PAGE_FAULT(n) (1UL << (n))
#define MMU_BUS_ERROR(n) (1UL << ((n) + MMU_PAGE_FAULT_FLAGS))
@@ -329,11 +354,16 @@
#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 */
+/* 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. */
@@ -419,6 +449,8 @@
#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 */
diff --git a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.c b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.c
index 2d8f963..b7c861c 100644
--- a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.c
+++ b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -31,6 +32,25 @@
*/
#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;
@@ -47,11 +67,9 @@ static inline s64 kbase_ipa_add_saturate(s64 a, s64 b)
static s64 kbase_ipa_group_energy(s32 coeff, u64 counter_value)
{
- /* Range: 0 < counter_value < 2^27 */
- if (counter_value > U32_MAX)
- counter_value = U32_MAX;
+ /* Range: 0 < counter_value < 2^38 */
- /* Range: -2^49 < ret < 2^49 */
+ /* Range: -2^59 < ret < 2^59 (as -2^21 < coeff < 2^21) */
return counter_value * (s64)coeff;
}
@@ -70,12 +88,18 @@ 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;
- size_t num_counters = model_data->counters_def_num;
+ u32 cnt_idx = 0;
int err;
size_t i;
- perf_counters =
- kcalloc(num_counters, sizeof(*perf_counters), GFP_KERNEL);
+ /* 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,
@@ -83,18 +107,41 @@ kbase_ipa_attach_ipa_control(struct kbase_ipa_counter_model_data *model_data)
return -ENOMEM;
}
- for (i = 0; i < num_counters; ++i) {
+ /* 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->counters_def[i];
+ &model_data->top_level_cntrs_def[i];
- perf_counters[i].type = counter->counter_block_type;
- perf_counters[i].idx = counter->counter_block_offset;
- perf_counters[i].gpu_norm = false;
- perf_counters[i].scaling_factor = 1;
+ 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, num_counters,
- &model_data->ipa_control_cli);
+ 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");
@@ -110,98 +157,87 @@ kbase_ipa_attach_ipa_control(struct kbase_ipa_counter_model_data *model_data)
static void
kbase_ipa_detach_ipa_control(struct kbase_ipa_counter_model_data *model_data)
{
- if (model_data->ipa_control_cli) {
+ if (model_data->ipa_control_client) {
kbase_ipa_control_unregister(model_data->kbdev,
- model_data->ipa_control_cli);
- model_data->ipa_control_cli = NULL;
+ model_data->ipa_control_client);
+ model_data->ipa_control_client = NULL;
}
}
-int kbase_ipa_counter_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp)
+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)
{
- struct kbase_ipa_counter_model_data *model_data =
- (struct kbase_ipa_counter_model_data *)model->model_data;
- s64 energy = 0;
- size_t i;
u64 coeff = 0, coeff_mul = 0;
- u32 active_cycles;
- u64 ret;
-
- /* 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(model->kbdev, model_data->ipa_control_cli,
- model_data->counter_values,
- model_data->counters_def_num, NULL);
- if (WARN_ON(ret))
- return ret;
-
- /* Range: 0 (GPU not used at all), to the max sampling interval, say
- * 1s, * max GPU frequency (GPU 100% utilized).
- * 0 <= active_cycles <= 1 * ~2GHz
- * 0 <= active_cycles < 2^31
- */
- active_cycles = model_data->get_active_cycles(model_data);
-
- /* 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);
+ s64 total_energy = 0;
+ size_t i;
- /* Range of 'energy' is +/- 2^54 * number of IPA groups (~8), so around
- * -2^57 < energy < 2^57
+ /* 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 < model_data->counters_def_num; i++) {
- s32 coeff = model_data->counter_coeffs[i];
- u64 counter_value = model_data->counter_values[i];
+ 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);
- energy = kbase_ipa_add_saturate(energy, group_energy);
- }
+ 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;
+ }
- /* Range: 0 <= coeff < 2^57 */
- if (energy > 0)
- coeff = energy;
+ total_energy =
+ kbase_ipa_add_saturate(total_energy, group_energy);
+ }
- /* Range: 0 <= coeff < 2^57 (because active_cycles >= 1). However, this
- * can be constrained further: Counter values can only be increased by
- * a theoretical maximum of about 64k per clock cycle. Beyond this,
- * we'd have to sample every 1ms to avoid them overflowing at the
- * lowest clock frequency (say 100MHz). Therefore, we can write the
- * range of 'coeff' in terms of active_cycles:
+ /* 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_num_cores
- * coeff <= num_IPA_groups * max_coeff * max_counter * max_num_cores
- * (substitute max_counter = 2^16 * active_cycles)
- * coeff <= num_IPA_groups * max_coeff * 2^16 * active_cycles * max_num_cores
- * coeff <= 2^3 * 2^22 * 2^16 * active_cycles * 2^5
- * coeff <= 2^46 * active_cycles
+ * 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^46
+ * 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^49
+ * Range: 0 <= coeff <= 2^35
*/
coeff = div_u64(coeff * 1000, max(model_data->reference_voltage, 1));
- /* Range: 0 <= coeff <= 2^52 */
+ /* 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^57
+ * Range: 0 <= coeff_mul < 2^43
*/
coeff_mul = coeff * model_data->scaling_factor;
@@ -210,28 +246,133 @@ int kbase_ipa_counter_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp)
* 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^47
+ * 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_common_model_init(
- struct kbase_ipa_model *model,
- const struct kbase_ipa_counter *ipa_counters_def,
- size_t ipa_num_counters,
- kbase_ipa_get_active_cycles_callback get_active_cycles,
- s32 reference_voltage)
+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;
- struct kbase_ipa_counter_model_data *model_data;
- if (!model || !ipa_counters_def || !ipa_num_counters ||
- !get_active_cycles)
+ 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);
@@ -239,22 +380,43 @@ int kbase_ipa_counter_common_model_init(
return -ENOMEM;
model_data->kbdev = model->kbdev;
- model_data->counters_def = ipa_counters_def;
- model_data->counters_def_num = ipa_num_counters;
- model_data->get_active_cycles = get_active_cycles;
+
+ 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;
- for (i = 0; i < model_data->counters_def_num; ++i) {
+ 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->counters_def[i];
+ &model_data->shader_cores_cntrs_def[i];
+
+ *counter_coeffs_p = counter->coeff_default_value;
- model_data->counter_coeffs[i] = counter->coeff_default_value;
err = kbase_ipa_model_add_param_s32(
- model, counter->name, &model_data->counter_coeffs[i], 1,
- false);
+ model, counter->name, counter_coeffs_p, 1, false);
if (err)
goto exit;
+
+ counter_coeffs_p++;
}
model_data->scaling_factor = DEFAULT_SCALING_FACTOR;
diff --git a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.h b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.h
index 064c101..9383dc2 100644
--- a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.h
+++ b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_csf.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
@@ -27,26 +46,25 @@
#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 16
+#define KBASE_IPA_MAX_COUNTER_DEF_NUM 24
struct kbase_ipa_counter_model_data;
-typedef u32 (*kbase_ipa_get_active_cycles_callback)(
- 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_cli: Handle returned on registering IPA counter model as a
+ * @ipa_control_client: Handle returned on registering IPA counter model as a
* client of kbase_ipa_control.
- * @counters_def: Array of description of HW counters used by the IPA
- * counter model.
- * @counters_def_num: Number of elements in the array of HW counters.
- * @get_active_cycles: Callback to return number of active cycles during
- * counter sample period.
+ * @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
@@ -64,12 +82,14 @@ typedef u32 (*kbase_ipa_get_active_cycles_callback)(
*/
struct kbase_ipa_counter_model_data {
struct kbase_device *kbdev;
- void *ipa_control_cli;
- const struct kbase_ipa_counter *counters_def;
- size_t counters_def_num;
- kbase_ipa_get_active_cycles_callback get_active_cycles;
+ 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;
@@ -97,7 +117,7 @@ struct kbase_ipa_counter {
* 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.
+ * 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
@@ -108,31 +128,45 @@ struct kbase_ipa_counter {
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: ipa power model to initialize
- * @ipa_counters_def: Array corresponding to the HW counters used in the
- * IPA counter model, contains the counter index, default
- * value of the coefficient.
- * @ipa_num_counters: number of elements in the array @ipa_counters_def
- * @get_active_cycles: callback to return the number of cycles the GPU was
- * active during the counter sample period.
- * @reference_voltage: voltage, in mV, of the operating point used when
- * deriving the power model coefficients.
- *
- * This initialization function performs initialization steps common
- * for ipa models based on counter values. In each call, the model
- * passes its specific coefficient values per ipa counter group via
- * @ipa_counters_def array.
+ * @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 *ipa_counters_def,
- size_t ipa_num_counters,
- kbase_ipa_get_active_cycles_callback get_active_cycles,
- s32 reference_voltage);
-
+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
diff --git a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.c b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.c
index ef1e526..fe01f78 100644
--- a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.c
+++ b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2017-2020 ARM Limited. All rights reserved.
@@ -273,6 +274,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/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.h b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.h
index 02e735f..0147f18 100644
--- a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.h
+++ b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_common_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2017-2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 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 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_JM_H_
@@ -182,6 +201,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
* @ipa_groups_def: array of ipa groups which sets coefficients for
diff --git a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_csf.c b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_csf.c
index 8cd47a1..1f21a85 100644
--- a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_csf.c
+++ b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_csf.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -24,77 +25,79 @@
#include "mali_kbase.h"
/* CSHW counter block offsets */
-#define GPU_ACTIVE (4)
+#define MESSAGES_RECEIVED (9)
+#define CEU_ACTIVE (40)
/* MEMSYS counter block offsets */
-#define MEMSYS_L2_ANY_LOOKUP (25)
+#define L2_RD_MSG_IN (16)
+#define L2_WR_MSG_IN_STALL (19)
+#define L2_SNP_MSG_IN (20)
+#define L2_ANY_LOOKUP (25)
+#define L2_EXT_READ_BEATS (32)
+#define L2_EXT_AR_CNT_Q3 (36)
+#define L2_EXT_AW_CNT_Q2 (50)
/* SC counter block offsets */
-#define SC_EXEC_INSTR_FMA (27)
-#define SC_EXEC_INSTR_MSG (30)
-#define SC_TEX_FILT_NUM_OPERATIONS (39)
+#define FRAG_FPK_ACTIVE (7)
+#define COMPUTE_ACTIVE (22)
+#define EXEC_CORE_ACTIVE (26)
+#define EXEC_STARVE_ARITH (33)
+#define TEX_FILT_NUM_OPS (39)
+#define BEATS_RD_TEX_EXT (59)
+
+/* Tiler counter block offsets */
+#define PRIM_SAT_CULLED (14)
+
+#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, \
+ }
-/**
- * get_active_cycles() - return the GPU_ACTIVE counter
- * @model_data: Pointer to GPU model data.
- *
- * Return: the number of cycles the GPU was active during the counter sampling
- * period.
- */
-static u32 kbase_csf_get_active_cycles(
- struct kbase_ipa_counter_model_data *model_data)
-{
- size_t i;
+#define CSHW_COUNTER_DEF(cnt_name, coeff, cnt_idx) \
+ COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_CSHW)
- for (i = 0; i < model_data->counters_def_num; ++i) {
- const struct kbase_ipa_counter *counter =
- &model_data->counters_def[i];
+#define MEMSYS_COUNTER_DEF(cnt_name, coeff, cnt_idx) \
+ COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_MEMSYS)
- if (!strcmp(counter->name, "gpu_active"))
- return model_data->counter_values[i];
- }
+#define SC_COUNTER_DEF(cnt_name, coeff, cnt_idx) \
+ COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_SHADER)
- WARN_ON_ONCE(1);
-
- return 0;
-}
+#define TILER_COUNTER_DEF(cnt_name, coeff, cnt_idx) \
+ COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_TILER)
/** Table of description of HW counters used by IPA counter model.
*
* This table provides a description of each performance counter
- * used by the IPA counter model for energy estimation.
+ * used by the top level counter model for energy estimation.
*/
-static const struct kbase_ipa_counter ipa_counters_def_todx[] = {
- {
- .name = "l2_access",
- .coeff_default_value = 599800,
- .counter_block_offset = MEMSYS_L2_ANY_LOOKUP,
- .counter_block_type = KBASE_IPA_CORE_TYPE_MEMSYS,
- },
- {
- .name = "exec_instr_msg",
- .coeff_default_value = 1830200,
- .counter_block_offset = SC_EXEC_INSTR_MSG,
- .counter_block_type = KBASE_IPA_CORE_TYPE_SHADER,
- },
- {
- .name = "exec_instr_fma",
- .coeff_default_value = 407300,
- .counter_block_offset = SC_EXEC_INSTR_FMA,
- .counter_block_type = KBASE_IPA_CORE_TYPE_SHADER,
- },
- {
- .name = "tex_filt_num_operations",
- .coeff_default_value = 224500,
- .counter_block_offset = SC_TEX_FILT_NUM_OPERATIONS,
- .counter_block_type = KBASE_IPA_CORE_TYPE_SHADER,
- },
- {
- .name = "gpu_active",
- .coeff_default_value = 153800,
- .counter_block_offset = GPU_ACTIVE,
- .counter_block_type = KBASE_IPA_CORE_TYPE_CSHW,
- },
+static const struct kbase_ipa_counter ipa_top_level_cntrs_def_todx[] = {
+ CSHW_COUNTER_DEF("messages_received", 925749, MESSAGES_RECEIVED),
+ CSHW_COUNTER_DEF("ceu_active", 25611, CEU_ACTIVE),
+
+ MEMSYS_COUNTER_DEF("l2_ext_read_beats", 3413, L2_EXT_READ_BEATS),
+ MEMSYS_COUNTER_DEF("l2_ext_ar_cnt_q3", 8141, L2_EXT_AR_CNT_Q3),
+ MEMSYS_COUNTER_DEF("l2_rd_msg_in", 3231, L2_RD_MSG_IN),
+ MEMSYS_COUNTER_DEF("l2_ext_aw_cnt_q2", 21714, L2_EXT_AW_CNT_Q2),
+ MEMSYS_COUNTER_DEF("l2_any_lookup", 110567, L2_ANY_LOOKUP),
+ MEMSYS_COUNTER_DEF("l2_wr_msg_in_stall", -370971, L2_WR_MSG_IN_STALL),
+ MEMSYS_COUNTER_DEF("l2_snp_msg_in", 270337, L2_SNP_MSG_IN),
+
+ TILER_COUNTER_DEF("prim_sat_culled", -1094458, PRIM_SAT_CULLED),
+};
+
+ /* This table provides 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("frag_fpk_active", -91312, FRAG_FPK_ACTIVE),
+ SC_COUNTER_DEF("exec_core_active", 485012, EXEC_CORE_ACTIVE),
+ SC_COUNTER_DEF("beats_rd_tex_ext", 174174, BEATS_RD_TEX_EXT),
+ SC_COUNTER_DEF("tex_filt_num_operations", 164419, TEX_FILT_NUM_OPS),
+ SC_COUNTER_DEF("exec_starve_arith", -59107, EXEC_STARVE_ARITH),
+ SC_COUNTER_DEF("compute_active", -277940, COMPUTE_ACTIVE),
};
#define IPA_POWER_MODEL_OPS(gpu, init_token) \
@@ -103,6 +106,7 @@ static const struct kbase_ipa_counter ipa_counters_def_todx[] = {
.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)
@@ -110,13 +114,16 @@ static const struct kbase_ipa_counter ipa_counters_def_todx[] = {
static int kbase_ ## gpu ## _power_model_init(\
struct kbase_ipa_model *model) \
{ \
- BUILD_BUG_ON(ARRAY_SIZE(ipa_counters_def_ ## gpu) > \
- KBASE_IPA_MAX_COUNTER_DEF_NUM); \
+ 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_counters_def_ ## gpu, \
- ARRAY_SIZE(ipa_counters_def_ ## gpu), \
- kbase_csf_get_active_cycles, \
- (reference_voltage)); \
+ 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)
@@ -124,10 +131,9 @@ static const struct kbase_ipa_counter ipa_counters_def_todx[] = {
#define ALIAS_POWER_MODEL(gpu, as_gpu) \
IPA_POWER_MODEL_OPS(gpu, as_gpu)
-/* Currently tBEx energy model is being used, for which reference voltage
- * value is 1000 mV.
+/* Reference voltage value is 750 mV.
*/
-STANDARD_POWER_MODEL(todx, 1000);
+STANDARD_POWER_MODEL(todx, 750);
/* Assuming LODX is an alias of TODX for IPA */
ALIAS_POWER_MODEL(lodx, todx);
diff --git a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_jm.c b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_jm.c
index 6799d8e..233e6d5 100644
--- a/mali_kbase/ipa/backend/mali_kbase_ipa_counter_jm.c
+++ b/mali_kbase/ipa/backend/mali_kbase_ipa_counter_jm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2016-2020 ARM Limited. All rights reserved.
@@ -19,6 +20,7 @@
* SPDX-License-Identifier: GPL-2.0
*
*/
+
#include <linux/thermal.h>
#include "mali_kbase_ipa_counter_common_jm.h"
@@ -455,6 +457,7 @@ static const struct kbase_ipa_group ipa_groups_def_tbax[] = {
.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)
diff --git a/mali_kbase/ipa/mali_kbase_ipa.c b/mali_kbase/ipa/mali_kbase_ipa.c
index 5946e4a..848ea93 100644
--- a/mali_kbase/ipa/mali_kbase_ipa.c
+++ b/mali_kbase/ipa/mali_kbase_ipa.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2016-2020 ARM Limited. All rights reserved.
@@ -19,6 +20,7 @@
* SPDX-License-Identifier: GPL-2.0
*
*/
+
#include <linux/thermal.h>
#include <linux/devfreq_cooling.h>
#include <linux/of.h>
@@ -27,18 +29,20 @@
#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"
+/* 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)
{
int err = 0;
@@ -322,6 +326,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);
@@ -376,7 +382,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 */
@@ -472,8 +479,8 @@ 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 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
@@ -482,8 +489,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);
@@ -499,16 +506,64 @@ 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;
}
-#if defined(CONFIG_MALI_PWRSOFT_765) || \
- LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
+/**
+ * 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)
+{
+#ifndef CONFIG_MALI_NO_MALI
+ 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];
+ }
+#else
+ /* An arbitrary voltage and frequency value can be chosen for testing
+ * in no mali configuration which may not match with any OPP level.
+ */
+ freqs[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL] = nominal_freq;
+ volts[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL] = nominal_voltage;
+
+ freqs[KBASE_IPA_BLOCK_TYPE_SHADER_CORES] = nominal_freq;
+ volts[KBASE_IPA_BLOCK_TYPE_SHADER_CORES] = nominal_voltage;
+#endif
+}
+
+#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)
@@ -518,10 +573,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);
@@ -534,19 +592,34 @@ 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
@@ -558,10 +631,13 @@ int kbase_get_real_power_locked(struct kbase_device *kbdev, u32 *power,
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);
@@ -569,30 +645,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];
+
+ /* 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, voltage);
+ *power += get_static_power_locked(kbdev, model,
+ volts[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL]);
return err;
}
@@ -616,16 +724,40 @@ 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
.get_static_power = &kbase_get_static_power,
.get_dynamic_power = &kbase_get_dynamic_power,
-#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
.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/mali_kbase/ipa/mali_kbase_ipa.h b/mali_kbase/ipa/mali_kbase_ipa.h
index 5f04169..d979540 100644
--- a/mali_kbase/ipa/mali_kbase_ipa.h
+++ b/mali_kbase/ipa/mali_kbase_ipa.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2016-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2016-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 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_H_
@@ -28,6 +47,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
* @model_data: opaque pointer to model specific data, accessed
@@ -89,7 +122,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 +135,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 +151,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);
};
/**
@@ -248,11 +296,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/mali_kbase/ipa/mali_kbase_ipa_debugfs.c b/mali_kbase/ipa/mali_kbase_ipa_debugfs.c
index 267a586..82288fd 100644
--- a/mali_kbase/ipa/mali_kbase_ipa_debugfs.c
+++ b/mali_kbase/ipa/mali_kbase_ipa_debugfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2017-2020 ARM Limited. All rights reserved.
@@ -28,7 +29,7 @@
#include "mali_kbase_ipa.h"
#include "mali_kbase_ipa_debugfs.h"
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0))
+#if (KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE)
#define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE
#endif
@@ -160,7 +161,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/mali_kbase/ipa/mali_kbase_ipa_debugfs.h b/mali_kbase/ipa/mali_kbase_ipa_debugfs.h
index a983d9c..6641f1e 100644
--- a/mali_kbase/ipa/mali_kbase_ipa_debugfs.h
+++ b/mali_kbase/ipa/mali_kbase_ipa_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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_DEBUGFS_H_
diff --git a/mali_kbase/ipa/mali_kbase_ipa_simple.c b/mali_kbase/ipa/mali_kbase_ipa_simple.c
index 852559e..c55daa1 100644
--- a/mali_kbase/ipa/mali_kbase_ipa_simple.c
+++ b/mali_kbase/ipa/mali_kbase_ipa_simple.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2016-2018 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 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
@@ -34,20 +35,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 +56,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 +141,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 +203,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/mali_kbase/ipa/mali_kbase_ipa_simple.h b/mali_kbase/ipa/mali_kbase_ipa_simple.h
index fed67d5..f5f8609 100644
--- a/mali_kbase/ipa/mali_kbase_ipa_simple.h
+++ b/mali_kbase/ipa/mali_kbase_ipa_simple.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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_SIMPLE_H_
diff --git a/mali_kbase/jm/mali_base_jm_kernel.h b/mali_kbase/jm/mali_base_jm_kernel.h
index ddac90a..de317eb 100644
--- a/mali_kbase/jm/mali_base_jm_kernel.h
+++ b/mali_kbase/jm/mali_base_jm_kernel.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,7 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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 _BASE_JM_KERNEL_H_
#define _BASE_JM_KERNEL_H_
@@ -752,11 +772,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
diff --git a/mali_kbase/jm/mali_kbase_jm_defs.h b/mali_kbase/jm/mali_kbase_jm_defs.h
index 22e3fb3..2aeedad 100644
--- a/mali_kbase/jm/mali_kbase_jm_defs.h
+++ b/mali_kbase/jm/mali_kbase_jm_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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) specific to Job Manager Kbase.
* They are placed here to allow the hierarchy of header files to work.
@@ -781,6 +798,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;
@@ -801,6 +819,7 @@ struct kbase_jd_context {
struct list_head jit_atoms_head;
struct list_head jit_pending_alloc;
+ int max_priority;
};
/**
diff --git a/mali_kbase/jm/mali_kbase_jm_ioctl.h b/mali_kbase/jm/mali_kbase_jm_ioctl.h
index 76ac278..7e2515b 100644
--- a/mali_kbase/jm/mali_kbase_jm_ioctl.h
+++ b/mali_kbase/jm/mali_kbase_jm_ioctl.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_JM_IOCTL_H_
@@ -114,9 +133,12 @@
* - 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.
*/
#define BASE_UK_VERSION_MAJOR 11
-#define BASE_UK_VERSION_MINOR 29
+#define BASE_UK_VERSION_MINOR 30
/**
* struct kbase_ioctl_version_check - Check version compatibility between
@@ -133,8 +155,6 @@ struct kbase_ioctl_version_check {
#define KBASE_IOCTL_VERSION_CHECK \
_IOWR(KBASE_IOCTL_TYPE, 0, struct kbase_ioctl_version_check)
-#define KBASE_IOCTL_VERSION_CHECK_RESERVED \
- _IOWR(KBASE_IOCTL_TYPE, 52, struct kbase_ioctl_version_check)
/**
* struct kbase_ioctl_job_submit - Submit jobs/atoms to the kernel
@@ -213,4 +233,8 @@ union kbase_kinstr_jm_fd {
#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_ */
diff --git a/mali_kbase/jm/mali_kbase_jm_js.h b/mali_kbase/jm/mali_kbase_jm_js.h
index 6c222ce..6978b56 100644
--- a/mali_kbase/jm/mali_kbase_jm_js.h
+++ b/mali_kbase/jm/mali_kbase_jm_js.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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.
+ *
*/
/*
@@ -584,7 +603,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
*
@@ -889,4 +907,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/mali_kbase/jm/mali_kbase_js_defs.h b/mali_kbase/jm/mali_kbase_js_defs.h
index 0b48615..7a68f7a 100644
--- a/mali_kbase/jm/mali_kbase_js_defs.h
+++ b/mali_kbase/jm/mali_kbase_js_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,9 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-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 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.
+ *
*/
-
/**
* @file mali_kbase_js.h
* Job Scheduler Type Definitions
@@ -51,7 +69,8 @@ struct kbase_jd_atom;
typedef u32 kbase_context_flags;
/** Callback function run on all of a context's jobs registered with the Job
- * Scheduler */
+ * Scheduler
+ */
typedef void (*kbasep_js_ctx_job_cb)(struct kbase_device *kbdev, struct kbase_jd_atom *katom);
/**
@@ -168,7 +187,8 @@ enum {
* Internal atom priority defines for kbase_jd_atom::sched_prio
*/
enum {
- KBASE_JS_ATOM_SCHED_PRIO_HIGH = 0,
+ KBASE_JS_ATOM_SCHED_PRIO_REALTIME = 0,
+ KBASE_JS_ATOM_SCHED_PRIO_HIGH,
KBASE_JS_ATOM_SCHED_PRIO_MED,
KBASE_JS_ATOM_SCHED_PRIO_LOW,
KBASE_JS_ATOM_SCHED_PRIO_COUNT,
@@ -198,7 +218,8 @@ enum {
*/
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. */
+ * 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
@@ -219,14 +240,17 @@ struct kbasep_js_device_data {
* - 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) */
+ * 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) */
+ * 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
@@ -234,7 +258,8 @@ struct kbasep_js_device_data {
* 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 */
+ * finishes
+ */
s8 slot_affinity_refcount[BASE_JM_MAX_NR_SLOTS][64];
} runpool_irq;
@@ -260,7 +285,9 @@ struct kbasep_js_device_data {
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 */
+ * @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 */
@@ -282,16 +309,19 @@ struct kbasep_js_device_data {
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 */
+ /** 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
+ */
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 */
+ * running
+ */
atomic_t nr_contexts_runnable;
/** Value for JS_SOFT_JOB_TIMEOUT */
@@ -339,9 +369,10 @@ struct kbasep_js_kctx_info {
struct kbase_jsctx {
struct mutex jsctx_mutex; /**< Job Scheduler Context lock */
- /** 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*/
+ /** 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:
@@ -351,7 +382,7 @@ struct kbasep_js_kctx_info {
/**
* 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
@@ -361,13 +392,15 @@ struct kbasep_js_kctx_info {
} ctx;
/* The initalized-flag is placed at the end, to avoid cache-pollution (we should
- * only be using this during init/term paths) */
+ * 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
* 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 */
enum base_jd_event_code event_code;
diff --git a/mali_kbase/mali_base_hwconfig_features.h b/mali_kbase/mali_base_hwconfig_features.h
index c0ce65f..ebbe6bf 100644
--- a/mali_kbase/mali_base_hwconfig_features.h
+++ b/mali_kbase/mali_base_hwconfig_features.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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.
+ *
*/
/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features,
@@ -56,6 +75,7 @@ enum base_hw_feature {
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
};
@@ -480,6 +500,7 @@ static const enum base_hw_feature base_hw_features_tTUx[] = {
BASE_HW_FEATURE_AARCH64_MMU,
BASE_HW_FEATURE_L2_CONFIG,
BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
+ BASE_HW_FEATURE_ASN_HASH,
BASE_HW_FEATURE_END
};
diff --git a/mali_kbase/mali_base_hwconfig_issues.h b/mali_kbase/mali_base_hwconfig_issues.h
index d0a3545..603c8cd 100644
--- a/mali_kbase/mali_base_hwconfig_issues.h
+++ b/mali_kbase/mali_base_hwconfig_issues.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features,
@@ -612,7 +631,6 @@ 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_GPU2019_3212,
BASE_HW_ISSUE_END
};
@@ -621,7 +639,6 @@ static const enum base_hw_issue base_hw_issues_model_tGRx[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
- BASE_HW_ISSUE_GPU2019_3212,
BASE_HW_ISSUE_END
};
@@ -629,7 +646,6 @@ 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_GPU2019_3212,
BASE_HW_ISSUE_END
};
@@ -638,7 +654,6 @@ static const enum base_hw_issue base_hw_issues_model_tVAx[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
- BASE_HW_ISSUE_GPU2019_3212,
BASE_HW_ISSUE_END
};
@@ -646,7 +661,6 @@ static const enum base_hw_issue base_hw_issues_tTUx_r0p0[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
- BASE_HW_ISSUE_GPU2019_3212,
BASE_HW_ISSUE_END
};
@@ -655,7 +669,6 @@ static const enum base_hw_issue base_hw_issues_model_tTUx[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
- BASE_HW_ISSUE_GPU2019_3212,
BASE_HW_ISSUE_END
};
diff --git a/mali_kbase/mali_base_kernel.h b/mali_kbase/mali_base_kernel.h
index aa6fb9f..259922b 100644
--- a/mali_kbase/mali_base_kernel.h
+++ b/mali_kbase/mali_base_kernel.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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 structures shared with the kernel.
*/
@@ -646,7 +663,6 @@ struct gpu_raw_gpu_props {
u64 tiler_present;
u64 l2_present;
u64 stack_present;
-
u32 l2_features;
u32 core_features;
u32 mem_features;
@@ -673,6 +689,7 @@ struct gpu_raw_gpu_props {
u32 coherency_mode;
u32 thread_tls_alloc;
+ u64 gpu_features;
};
/**
diff --git a/mali_kbase/mali_base_mem_priv.h b/mali_kbase/mali_base_mem_priv.h
index 844a025..fe193c0 100644
--- a/mali_kbase/mali_base_mem_priv.h
+++ b/mali_kbase/mali_base_mem_priv.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2015, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-2015, 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 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 _BASE_MEM_PRIV_H_
#define _BASE_MEM_PRIV_H_
diff --git a/mali_kbase/mali_kbase.h b/mali_kbase/mali_kbase.h
index fd176a5..9981991 100644
--- a/mali_kbase/mali_kbase.h
+++ b/mali_kbase/mali_kbase.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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_H_
#define _KBASE_H_
@@ -38,7 +55,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>
@@ -456,7 +473,11 @@ static inline bool kbase_pm_is_gpu_lost(struct kbase_device *kbdev)
static inline void kbase_pm_set_gpu_lost(struct kbase_device *kbdev,
bool gpu_lost)
{
- atomic_set(&kbdev->pm.gpu_lost, (gpu_lost ? 1 : 0));
+ 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
diff --git a/mali_kbase/mali_kbase_as_fault_debugfs.c b/mali_kbase/mali_kbase_as_fault_debugfs.c
index 2e2e394..7851b6d 100644
--- a/mali_kbase/mali_kbase_as_fault_debugfs.c
+++ b/mali_kbase/mali_kbase_as_fault_debugfs.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2016-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2016-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
diff --git a/mali_kbase/mali_kbase_as_fault_debugfs.h b/mali_kbase/mali_kbase_as_fault_debugfs.h
index 496d8b1..19a3e17 100644
--- a/mali_kbase/mali_kbase_as_fault_debugfs.h
+++ b/mali_kbase/mali_kbase_as_fault_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2016, 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 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_AS_FAULT_DEBUG_FS_H
diff --git a/mali_kbase/mali_kbase_bits.h b/mali_kbase/mali_kbase_bits.h
index 2c11093..e1625c6 100644
--- a/mali_kbase/mali_kbase_bits.h
+++ b/mali_kbase/mali_kbase_bits.h
@@ -21,12 +21,22 @@
*//* SPDX-License-Identifier: GPL-2.0 */
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
+ * 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_BITS_H_
diff --git a/mali_kbase/mali_kbase_cache_policy.c b/mali_kbase/mali_kbase_cache_policy.c
index 27a03cf..1cc8738 100644
--- a/mali_kbase/mali_kbase_cache_policy.c
+++ b/mali_kbase/mali_kbase_cache_policy.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2012-2018 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2012-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
@@ -20,8 +21,6 @@
*
*/
-
-
/*
* Cache Policy API.
*/
diff --git a/mali_kbase/mali_kbase_cache_policy.h b/mali_kbase/mali_kbase_cache_policy.h
index 8a1e529..85c328a 100644
--- a/mali_kbase/mali_kbase_cache_policy.h
+++ b/mali_kbase/mali_kbase_cache_policy.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2013, 2015 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-2013, 2015, 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 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.
+ *
*/
-
-
/*
* Cache Policy API.
*/
diff --git a/mali_kbase/mali_kbase_caps.h b/mali_kbase/mali_kbase_caps.h
index b201a60..1901c89 100644
--- a/mali_kbase/mali_kbase_caps.h
+++ b/mali_kbase/mali_kbase_caps.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,9 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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.
+ *
*/
-
/**
* @file mali_kbase_caps.h
*
diff --git a/mali_kbase/mali_kbase_ccswe.c b/mali_kbase/mali_kbase_ccswe.c
index 87d5aaa..c48c4aa 100644
--- a/mali_kbase/mali_kbase_ccswe.c
+++ b/mali_kbase/mali_kbase_ccswe.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -50,7 +51,6 @@ void kbase_ccswe_init(struct kbase_ccswe *self)
spin_lock_init(&self->access);
}
-KBASE_EXPORT_TEST_API(kbase_ccswe_init);
u64 kbase_ccswe_cycle_at(struct kbase_ccswe *self, u64 timestamp_ns)
{
@@ -63,7 +63,6 @@ u64 kbase_ccswe_cycle_at(struct kbase_ccswe *self, u64 timestamp_ns)
return result;
}
-KBASE_EXPORT_TEST_API(kbase_ccswe_cycle_at);
void kbase_ccswe_freq_change(
struct kbase_ccswe *self, u64 timestamp_ns, u32 gpu_freq)
@@ -87,7 +86,6 @@ void kbase_ccswe_freq_change(
exit:
spin_unlock_irqrestore(&self->access, flags);
}
-KBASE_EXPORT_TEST_API(kbase_ccswe_freq_change);
void kbase_ccswe_reset(struct kbase_ccswe *self)
{
@@ -102,4 +100,3 @@ void kbase_ccswe_reset(struct kbase_ccswe *self)
spin_unlock_irqrestore(&self->access, flags);
}
-
diff --git a/mali_kbase/mali_kbase_ccswe.h b/mali_kbase/mali_kbase_ccswe.h
index 3a7cf73..77769f8 100644
--- a/mali_kbase/mali_kbase_ccswe.h
+++ b/mali_kbase/mali_kbase_ccswe.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
diff --git a/mali_kbase/mali_kbase_config.c b/mali_kbase/mali_kbase_config.c
index ce7070d..a4bd10f 100644
--- a/mali_kbase/mali_kbase_config.c
+++ b/mali_kbase/mali_kbase_config.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2011-2015,2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-2015, 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
@@ -20,8 +21,6 @@
*
*/
-
-
#include <mali_kbase.h>
#include <mali_kbase_defs.h>
#include <mali_kbase_config_defaults.h>
diff --git a/mali_kbase/mali_kbase_config.h b/mali_kbase/mali_kbase_config.h
index 57456e2..4ff7f8c 100644
--- a/mali_kbase/mali_kbase_config.h
+++ b/mali_kbase/mali_kbase_config.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2017, 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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.
+ *
*/
-
-
/**
* @file mali_kbase_config.h
* Configuration API and Attributes for KBase
diff --git a/mali_kbase/mali_kbase_config_defaults.h b/mali_kbase/mali_kbase_config_defaults.h
index 48c728e..972ea77 100644
--- a/mali_kbase/mali_kbase_config_defaults.h
+++ b/mali_kbase/mali_kbase_config_defaults.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2013-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2013-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 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.
+ *
*/
/**
diff --git a/mali_kbase/mali_kbase_core_linux.c b/mali_kbase/mali_kbase_core_linux.c
index dcdac19..97cd3cb 100644
--- a/mali_kbase/mali_kbase_core_linux.c
+++ b/mali_kbase/mali_kbase_core_linux.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
@@ -110,12 +111,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>
@@ -144,25 +140,6 @@
#define KBASE_API_MAJ(api_version) ((api_version >> 20) & 0xFFF)
/**
- * mali_kbase_api_version_to_maj_min - convert an api_version to a min/maj pair
- *
- * @api_version: API version to convert
- * @major: Major version number (must not exceed 12 bits)
- * @minor: Major version number (must not exceed 12 bits)
- */
-void mali_kbase_api_version_to_maj_min(unsigned long api_version, u16 *maj, u16 *min)
-{
- if (WARN_ON(!maj))
- return;
-
- if (WARN_ON(!min))
- return;
-
- *maj = KBASE_API_MAJ(api_version);
- *min = KBASE_API_MIN(api_version);
-}
-
-/**
* kbase capabilities table
*/
typedef struct mali_kbase_capability_def {
@@ -434,25 +411,6 @@ static int kbase_api_handshake_dummy(struct kbase_file *kfile,
return -EPERM;
}
-/**
- * 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 struct kbase_device *to_kbase_device(struct device *dev)
{
return dev_get_drvdata(dev);
@@ -530,9 +488,9 @@ 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 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
@@ -1585,52 +1543,80 @@ static int kbasep_ioctl_cs_cpu_queue_dump(struct kbase_context *kctx,
#endif /* MALI_USE_CSF */
-#define KBASE_HANDLE_IOCTL(cmd, function, arg) \
- do { \
- BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_NONE); \
- return function(arg); \
+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 { \
+ 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(&param, uarg, sizeof(param)); \
- if (err) \
- return -EFAULT; \
- return function(arg, &param); \
+#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(&param, uarg, sizeof(param)); \
+ if (err) \
+ return -EFAULT; \
+ ret = function(arg, &param); \
+ 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(&param, 0, sizeof(param)); \
- ret = function(arg, &param); \
- err = copy_to_user(uarg, &param, 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(&param, 0, sizeof(param)); \
+ ret = function(arg, &param); \
+ err = copy_to_user(uarg, &param, 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(&param, uarg, sizeof(param)); \
- if (err) \
- return -EFAULT; \
- ret = function(arg, &param); \
- err = copy_to_user(uarg, &param, 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(&param, uarg, sizeof(param)); \
+ if (err) \
+ return -EFAULT; \
+ ret = function(arg, &param); \
+ err = copy_to_user(uarg, &param, sizeof(param)); \
+ if (err) \
+ return -EFAULT; \
+ dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, \
+ #function); \
+ return ret; \
} while (0)
static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
@@ -2007,6 +1993,12 @@ 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;
}
dev_warn(kbdev->dev, "Unknown ioctl 0x%x nr:%d", cmd, _IOC_NR(cmd));
@@ -2123,7 +2115,8 @@ 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 %p\n",
+ (void *)kctx);
wake_up_interruptible(&kctx->event_queue);
}
@@ -2817,7 +2810,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;
@@ -4374,6 +4368,8 @@ int kbase_device_pm_init(struct kbase_device *kbdev)
}
}
} else {
+ kbdev->arb.arb_if = NULL;
+ kbdev->arb.arb_dev = NULL;
err = power_control_init(kbdev);
}
#else
@@ -4398,7 +4394,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.
@@ -4493,12 +4489,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))
@@ -4510,8 +4500,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:
@@ -4520,20 +4508,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) && \
@@ -4543,8 +4524,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]))
@@ -4555,15 +4534,14 @@ 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
@@ -4765,7 +4743,8 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev)
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);
@@ -4931,6 +4910,149 @@ void buslog_term(struct kbase_device *kbdev)
}
#endif
+#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 ssize_t csg_scheduling_period_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct kbase_device *kbdev;
+ int ret;
+ unsigned int csg_scheduling_period;
+
+ 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;
+}
+
+/**
+ * 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)
+{
+ 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.scheduler.csg_scheduling_period_ms);
+
+ return ret;
+}
+
+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)
+{
+ 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;
+}
+
+/**
+ * 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,
@@ -4958,6 +5080,9 @@ static struct attribute *kbase_attrs[] = {
&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,
@@ -5136,8 +5261,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);
@@ -5165,8 +5293,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);
@@ -5199,8 +5330,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
@@ -5238,8 +5373,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
diff --git a/mali_kbase/mali_kbase_cs_experimental.h b/mali_kbase/mali_kbase_cs_experimental.h
index caba2cd..8a3daa0 100644
--- a/mali_kbase/mali_kbase_cs_experimental.h
+++ b/mali_kbase/mali_kbase_cs_experimental.h
@@ -19,14 +19,23 @@
* 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
+ * 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.
*
*/
diff --git a/mali_kbase/mali_kbase_ctx_sched.c b/mali_kbase/mali_kbase_ctx_sched.c
index 70b498a..953db9e 100644
--- a/mali_kbase/mali_kbase_ctx_sched.c
+++ b/mali_kbase/mali_kbase_ctx_sched.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2017-2020 ARM Limited. All rights reserved.
@@ -44,7 +45,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 */
@@ -259,7 +261,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);
@@ -273,23 +275,35 @@ struct kbase_context *kbase_ctx_sched_as_to_ctx(struct kbase_device *kbdev,
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;
+
if (WARN_ON(kbdev == NULL))
return NULL;
if (WARN_ON(as_nr >= BASE_MAX_NR_AS))
return NULL;
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ lockdep_assert_held(&kbdev->hwaccess_lock);
found_kctx = kbdev->as_to_kctx[as_nr];
if (found_kctx) {
- if (WARN_ON(atomic_read(&found_kctx->refcount) <= 0))
+ if (atomic_read(&found_kctx->refcount) <= 0)
found_kctx = NULL;
}
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-
return found_kctx;
}
@@ -351,3 +365,45 @@ 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_refcount_mmu_flush(struct kbase_context *kctx,
+ bool sync)
+{
+ 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);
+
+ added_ref = kbase_ctx_sched_inc_refcount_nolock(kctx);
+
+ WARN_ON(added_ref &&
+ (kctx->mmu_flush_pend_state != KCTX_MMU_FLUSH_NOT_PEND));
+
+ if (!added_ref && (kctx->as_nr != KBASEP_AS_NR_INVALID)) {
+ enum kbase_ctx_mmu_flush_pending_state new_state =
+ sync ? KCTX_MMU_FLUSH_PEND_SYNC :
+ KCTX_MMU_FLUSH_PEND_NO_SYNC;
+
+ WARN_ON(kctx != kbdev->as_to_kctx[kctx->as_nr]);
+
+ if (kctx->mmu_flush_pend_state != KCTX_MMU_FLUSH_PEND_SYNC)
+ kctx->mmu_flush_pend_state = new_state;
+ }
+
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+ mutex_unlock(&kbdev->mmu_hw_mutex);
+
+ return added_ref;
+}
+#endif
diff --git a/mali_kbase/mali_kbase_ctx_sched.h b/mali_kbase/mali_kbase_ctx_sched.h
index 1affa71..5e5e242 100644
--- a/mali_kbase/mali_kbase_ctx_sched.h
+++ b/mali_kbase/mali_kbase_ctx_sched.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2017-2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 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 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_CTX_SCHED_H_
@@ -168,6 +187,21 @@ 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.
* @kctx: Context to be refcounted
@@ -206,4 +240,25 @@ 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_refcount_mmu_flush - Refcount the context for the MMU flush
+ * operation.
+ *
+ * @kctx: Context to be refcounted.
+ * @sync: Flag passed to the caller function kbase_mmu_flush_invalidate().
+ *
+ * This function takes a reference on the context for the MMU flush operation.
+ * The refcount is taken only if the context is busy/active.
+ * If the context isn't active but has a GPU address space slot assigned to it
+ * then a flag is set to indicate that MMU flush operation is pending, which
+ * will be performed when the context becomes active.
+ *
+ * Return: true if refcount succeeded and the address space slot will not be
+ * reassigned, false if the refcount failed (because the context was inactive)
+ */
+bool kbase_ctx_sched_refcount_mmu_flush(struct kbase_context *kctx,
+ bool sync);
+#endif
+
#endif /* _KBASE_CTX_SCHED_H_ */
diff --git a/mali_kbase/mali_kbase_debug.c b/mali_kbase/mali_kbase_debug.c
index 118f787..82d709d 100644
--- a/mali_kbase/mali_kbase_debug.c
+++ b/mali_kbase/mali_kbase_debug.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2012-2014 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2012-2014, 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
@@ -20,8 +21,6 @@
*
*/
-
-
#include <mali_kbase.h>
static struct kbasep_debug_assert_cb kbasep_debug_assert_registered_cb = {
diff --git a/mali_kbase/mali_kbase_debug.h b/mali_kbase/mali_kbase_debug.h
index 2fdb72d..75e4ed1 100644
--- a/mali_kbase/mali_kbase_debug.h
+++ b/mali_kbase/mali_kbase_debug.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2015, 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-2015, 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 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_H
#define _KBASE_DEBUG_H
diff --git a/mali_kbase/mali_kbase_debug_job_fault.c b/mali_kbase/mali_kbase_debug_job_fault.c
index dbc774d..5a1bc2d 100644
--- a/mali_kbase/mali_kbase_debug_job_fault.c
+++ b/mali_kbase/mali_kbase_debug_job_fault.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2012-2016, 2018-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2012-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
@@ -518,23 +519,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;
}
/*
diff --git a/mali_kbase/mali_kbase_debug_job_fault.h b/mali_kbase/mali_kbase_debug_job_fault.h
index ef69627..c147153 100644
--- a/mali_kbase/mali_kbase_debug_job_fault.h
+++ b/mali_kbase/mali_kbase_debug_job_fault.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2016, 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-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 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_JOB_FAULT_H
@@ -54,8 +73,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/mali_kbase/mali_kbase_debug_mem_view.c b/mali_kbase/mali_kbase_debug_mem_view.c
index 4788137..305007c 100644
--- a/mali_kbase/mali_kbase_debug_mem_view.c
+++ b/mali_kbase/mali_kbase_debug_mem_view.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2013-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2013-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
@@ -32,10 +33,6 @@
#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
-
struct debug_mem_mapping {
struct list_head node;
@@ -179,6 +176,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 +226,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/mali_kbase/mali_kbase_debug_mem_view.h b/mali_kbase/mali_kbase_debug_mem_view.h
index b948b7c..bee7a53 100644
--- a/mali_kbase/mali_kbase_debug_mem_view.h
+++ b/mali_kbase/mali_kbase_debug_mem_view.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2013-2015, 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2013-2015, 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 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_MEM_VIEW_H
diff --git a/mali_kbase/mali_kbase_debugfs_helper.c b/mali_kbase/mali_kbase_debugfs_helper.c
index 37e507b..c48af37 100644
--- a/mali_kbase/mali_kbase_debugfs_helper.c
+++ b/mali_kbase/mali_kbase_debugfs_helper.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -90,6 +91,59 @@ 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)
@@ -100,6 +154,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);
@@ -154,6 +215,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);
diff --git a/mali_kbase/mali_kbase_debugfs_helper.h b/mali_kbase/mali_kbase_debugfs_helper.h
index c3c9efa..c1e1689 100644
--- a/mali_kbase/mali_kbase_debugfs_helper.h
+++ b/mali_kbase/mali_kbase_debugfs_helper.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_DEBUGFS_HELPER_H_
@@ -59,6 +78,29 @@ int kbase_debugfs_helper_set_attr_from_string(
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
* attribute value from an array
*
diff --git a/mali_kbase/mali_kbase_defs.h b/mali_kbase/mali_kbase_defs.h
index ab1f380..b4cca7a 100644
--- a/mali_kbase/mali_kbase_defs.h
+++ b/mali_kbase/mali_kbase_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-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 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.
+ *
*/
-
-
/**
* @file mali_kbase_defs.h
*
@@ -40,7 +57,11 @@
#include <mali_kbase_instr_defs.h>
#include <mali_kbase_pm.h>
#include <mali_kbase_gpuprops_types.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>
@@ -75,8 +96,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
@@ -138,17 +158,22 @@
*/
#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;
@@ -178,11 +203,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;
@@ -429,6 +450,12 @@ struct kbase_pm_device_data {
* The state of the arbiter VM machine
*/
struct kbase_arbiter_vm_state *arb_vm_state;
+
+ /**
+ * Used by virtualization to notify the arbiter that there are users
+ * waiting for the GPU so that it can request and resume the driver.
+ */
+ atomic_t gpu_users_waiting;
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
/**
@@ -882,6 +909,8 @@ struct kbase_process {
* 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
@@ -896,6 +925,7 @@ struct kbase_process {
* @gpu_mem_usage_lock: This spinlock should be held while accounting
* @total_gpu_pages for both native and dma-buf imported
* allocations.
+ * @pcm_dev: The priority control manager device.
*/
struct kbase_device {
u32 hw_quirks_sc;
@@ -964,6 +994,9 @@ 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;
@@ -974,6 +1007,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;
@@ -1007,17 +1041,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
struct thermal_cooling_device *devfreq_cooling;
-#endif
bool ipa_protection_mode_switched;
struct {
/* Access to this struct must be with ipa.lock held */
@@ -1033,6 +1060,10 @@ struct kbase_device {
/* 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 */
@@ -1057,7 +1088,7 @@ 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 */
@@ -1074,8 +1105,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;
@@ -1118,6 +1148,8 @@ struct kbase_device {
u8 l2_size_override;
u8 l2_hash_override;
+ bool l2_hash_values_override;
+ u32 l2_hash_values[ASN_HASH_COUNT];
#if MALI_USE_CSF
/* CSF object for the GPU device. */
@@ -1155,6 +1187,8 @@ struct kbase_device {
/* Pointer to the arbiter device */
struct kbase_arbiter_device arb;
#endif
+ /* Priority Control Manager device */
+ struct priority_control_manager_device *pcm_dev;
};
/**
@@ -1295,6 +1329,30 @@ enum kbase_context_flags {
#endif /* !MALI_JIT_PRESSURE_LIMIT_BASE */
};
+#if MALI_USE_CSF
+/**
+ * enum kbase_ctx_mmu_flush_pending_state - State for the pending mmu flush
+ * operation for a kbase context.
+ *
+ * @KCTX_MMU_FLUSH_NOT_PEND: Set when there is no MMU flush operation pending
+ * for a kbase context or deferred flush operation
+ * is performed.
+ *
+ * @KCTX_MMU_FLUSH_PEND_NO_SYNC: Set when the MMU flush operation is deferred
+ * for a kbase context when it is inactive and
+ * the sync flag passed is 0.
+ *
+ * @KCTX_MMU_FLUSH_PEND_SYNC: Set when the MMU flush operation is deferred
+ * for a kbase context when it is inactive and
+ * the sync flag passed is 1.
+ */
+enum kbase_ctx_mmu_flush_pending_state {
+ KCTX_MMU_FLUSH_NOT_PEND,
+ KCTX_MMU_FLUSH_PEND_NO_SYNC,
+ KCTX_MMU_FLUSH_PEND_SYNC,
+};
+#endif
+
struct kbase_sub_alloc {
struct list_head link;
struct page *page;
@@ -1555,6 +1613,8 @@ struct kbase_sub_alloc {
* @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.
*
* A kernel base context is an entity among which the GPU is scheduled.
* Each context has its own GPU address space.
@@ -1701,6 +1761,16 @@ struct kbase_context {
#if !MALI_USE_CSF
struct kbase_kinstr_jm *kinstr_jm;
#endif
+ struct list_head tl_kctx_list_node;
+
+#if MALI_USE_CSF
+ /* Tracks if the MMU flush operations are pending for the context.
+ * The flush required due to unmap is also tracked.
+ * It is supposed to be in KCTX_MMU_FLUSH_NOT_PEND state whilst a
+ * context is active and shall be updated with mmu_hw_mutex lock held.
+ */
+ enum kbase_ctx_mmu_flush_pending_state mmu_flush_pend_state;
+#endif
};
#ifdef CONFIG_MALI_CINSTR_GWT
diff --git a/mali_kbase/mali_kbase_disjoint_events.c b/mali_kbase/mali_kbase_disjoint_events.c
index b5ac414..ea41565 100644
--- a/mali_kbase/mali_kbase_disjoint_events.c
+++ b/mali_kbase/mali_kbase_disjoint_events.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014, 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mali_kbase_dma_fence.c b/mali_kbase/mali_kbase_dma_fence.c
index 7665d8d..027e530 100644
--- a/mali_kbase/mali_kbase_dma_fence.c
+++ b/mali_kbase/mali_kbase_dma_fence.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2011-2016, 2020 ARM Limited. All rights reserved.
@@ -56,7 +57,7 @@ static int
kbase_dma_fence_lock_reservations(struct kbase_dma_fence_resv_info *info,
struct ww_acquire_ctx *ctx)
{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
struct reservation_object *content_res = NULL;
#else
struct dma_resv *content_res = NULL;
@@ -206,7 +207,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)
@@ -226,7 +227,7 @@ kbase_dma_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
kbase_dma_fence_queue_work(katom);
}
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+#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,
@@ -238,7 +239,7 @@ kbase_dma_fence_add_reservation_callback(struct kbase_jd_atom *katom,
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
@@ -302,7 +303,7 @@ out:
return err;
}
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+#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)
@@ -331,7 +332,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;
@@ -360,7 +361,7 @@ int kbase_dma_fence_wait(struct kbase_jd_atom *katom,
}
for (i = 0; i < info->dma_fence_resv_count; i++) {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+#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];
diff --git a/mali_kbase/mali_kbase_dma_fence.h b/mali_kbase/mali_kbase_dma_fence.h
index f439895..b53ead1 100644
--- a/mali_kbase/mali_kbase_dma_fence.h
+++ b/mali_kbase/mali_kbase_dma_fence.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-2016, 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 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_DMA_FENCE_H_
@@ -44,7 +63,7 @@ struct kbase_context;
* reservation objects.
*/
struct kbase_dma_fence_resv_info {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
struct reservation_object **resv_objs;
#else
struct dma_resv **resv_objs;
@@ -63,7 +82,7 @@ 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 (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+#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);
diff --git a/mali_kbase/mali_kbase_dummy_job_wa.c b/mali_kbase/mali_kbase_dummy_job_wa.c
index a5a7ad7..ac6d953 100644
--- a/mali_kbase/mali_kbase_dummy_job_wa.c
+++ b/mali_kbase/mali_kbase_dummy_job_wa.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mali_kbase_dummy_job_wa.h b/mali_kbase/mali_kbase_dummy_job_wa.h
index e194950..d480291 100644
--- a/mali_kbase/mali_kbase_dummy_job_wa.h
+++ b/mali_kbase/mali_kbase_dummy_job_wa.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_DUMMY_JOB_WORKAROUND_
diff --git a/mali_kbase/mali_kbase_dvfs_debugfs.c b/mali_kbase/mali_kbase_dvfs_debugfs.c
index 438b528..3c7930b 100644
--- a/mali_kbase/mali_kbase_dvfs_debugfs.c
+++ b/mali_kbase/mali_kbase_dvfs_debugfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -38,9 +39,16 @@ static int kbasep_dvfs_utilization_debugfs_show(struct seq_file *file, void *dat
{
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;
}
diff --git a/mali_kbase/mali_kbase_dvfs_debugfs.h b/mali_kbase/mali_kbase_dvfs_debugfs.h
index 4f9e3fc..cd17ac2 100644
--- a/mali_kbase/mali_kbase_dvfs_debugfs.h
+++ b/mali_kbase/mali_kbase_dvfs_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
diff --git a/mali_kbase/mali_kbase_event.c b/mali_kbase/mali_kbase_event.c
index 5adb80f..f00cef2 100644
--- a/mali_kbase/mali_kbase_event.c
+++ b/mali_kbase/mali_kbase_event.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2016,2018-2020 ARM Limited. All rights reserved.
@@ -20,8 +21,6 @@
*
*/
-
-
#include <mali_kbase.h>
#include <mali_kbase_debug.h>
#include <tl/mali_kbase_tracepoints.h>
@@ -154,7 +153,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;
@@ -237,7 +237,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/mali_kbase/mali_kbase_fence.c b/mali_kbase/mali_kbase_fence.c
index 5e04acf..edf1d52 100644
--- a/mali_kbase/mali_kbase_fence.c
+++ b/mali_kbase/mali_kbase_fence.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
@@ -29,7 +30,7 @@
/* Spin lock protecting all Mali fences as fence->lock. */
static DEFINE_SPINLOCK(kbase_fence_lock);
-#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
@@ -37,7 +38,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;
@@ -98,7 +99,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,
diff --git a/mali_kbase/mali_kbase_fence.h b/mali_kbase/mali_kbase_fence.h
index e12f1f9..0705598 100644
--- a/mali_kbase/mali_kbase_fence.h
+++ b/mali_kbase/mali_kbase_fence.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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_FENCE_H_
@@ -35,7 +54,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 +68,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 +85,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);
@@ -169,7 +188,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);
diff --git a/mali_kbase/mali_kbase_fence_defs.h b/mali_kbase/mali_kbase_fence_defs.h
index 3030296..d8f1193 100644
--- a/mali_kbase/mali_kbase_fence_defs.h
+++ b/mali_kbase/mali_kbase_fence_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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_FENCE_DEFS_H_
@@ -30,7 +49,7 @@
#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>
@@ -53,7 +72,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)
diff --git a/mali_kbase/mali_kbase_fence_ops.c b/mali_kbase/mali_kbase_fence_ops.c
index c470374..d0d1672 100644
--- a/mali_kbase/mali_kbase_fence_ops.c
+++ b/mali_kbase/mali_kbase_fence_ops.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -26,7 +27,7 @@
#include <mali_kbase.h>
static const char *
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
+#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)
@@ -36,7 +37,7 @@ kbase_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)
kbase_fence_get_timeline_name(struct fence *fence)
#else
kbase_fence_get_timeline_name(struct dma_fence *fence)
@@ -46,7 +47,7 @@ kbase_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)
kbase_fence_enable_signaling(struct fence *fence)
#else
kbase_fence_enable_signaling(struct dma_fence *fence)
@@ -56,7 +57,7 @@ kbase_fence_enable_signaling(struct dma_fence *fence)
}
static void
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
+#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)
@@ -69,7 +70,7 @@ kbase_fence_fence_value_str(struct dma_fence *fence, char *str, int size)
#endif
}
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
+#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE)
const struct fence_ops kbase_fence_ops = {
.wait = fence_default_wait,
#else
diff --git a/mali_kbase/mali_kbase_gator.h b/mali_kbase/mali_kbase_gator.h
index 6428f08..f1ee3fc 100644
--- a/mali_kbase/mali_kbase_gator.h
+++ b/mali_kbase/mali_kbase_gator.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-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 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.
+ *
*/
/* NB taken from gator */
diff --git a/mali_kbase/mali_kbase_gpu_memory_debugfs.c b/mali_kbase/mali_kbase_gpu_memory_debugfs.c
index 569abd9..84837f4 100644
--- a/mali_kbase/mali_kbase_gpu_memory_debugfs.c
+++ b/mali_kbase/mali_kbase_gpu_memory_debugfs.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2012-2017, 2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2012-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
@@ -54,7 +55,8 @@ static int kbasep_gpu_memory_seq_show(struct seq_file *sfile, void *data)
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 */
+ * opened on this device
+ */
seq_printf(sfile, " %s-0x%p %10u\n",
"kctx",
kctx,
diff --git a/mali_kbase/mali_kbase_gpu_memory_debugfs.h b/mali_kbase/mali_kbase_gpu_memory_debugfs.h
index a45dabb..9b1aaa0 100644
--- a/mali_kbase/mali_kbase_gpu_memory_debugfs.h
+++ b/mali_kbase/mali_kbase_gpu_memory_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2014, 2016, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-2014, 2016, 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 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.
+ *
*/
-
-
/**
* @file mali_kbase_gpu_memory_debugfs.h
* Header file for gpu_memory entry in debugfs
diff --git a/mali_kbase/mali_kbase_gpuprops.c b/mali_kbase/mali_kbase_gpuprops.c
index 81e0395..5eae532 100644
--- a/mali_kbase/mali_kbase_gpuprops.c
+++ b/mali_kbase/mali_kbase_gpuprops.c
@@ -21,8 +21,6 @@
*
*/
-
-
/*
* Base kernel property query APIs
*/
@@ -48,7 +46,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);
@@ -124,8 +122,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, &regdump);
@@ -166,6 +164,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;
}
@@ -217,7 +219,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;
@@ -305,7 +308,7 @@ 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);
+ KBASE_DEBUG_ASSERT(kbdev != NULL);
gpu_props = &kbdev->gpu_props;
raw = &gpu_props->props.raw_props;
@@ -365,13 +368,26 @@ 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");
+
+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.
@@ -380,15 +396,17 @@ 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;
@@ -400,10 +418,41 @@ static bool kbase_read_l2_config_from_dt(struct kbase_device * const kbdev)
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;
+ }
- return false;
+ 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 L2_CONFIG_OVERRIDE_NONE;
}
int kbase_gpuprops_update_l2_features(struct kbase_device *kbdev)
@@ -415,8 +464,15 @@ 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;
+ }
/* Need L2 to get powered to reflect to L2_FEATURES */
kbase_pm_context_active(kbdev);
@@ -440,8 +496,9 @@ int kbase_gpuprops_update_l2_features(struct kbase_device *kbdev)
idle_gpu:
/* Let GPU idle */
kbase_pm_context_idle(kbdev);
- }
+}
+exit:
return err;
}
@@ -521,7 +578,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/mali_kbase/mali_kbase_gpuprops.h b/mali_kbase/mali_kbase_gpuprops.h
index 5eee794..e634922 100644
--- a/mali_kbase/mali_kbase_gpuprops.h
+++ b/mali_kbase/mali_kbase_gpuprops.h
@@ -26,16 +26,19 @@
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the 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.
*
*/
-
-
/**
* @file mali_kbase_gpuprops.h
* Base kernel property query APIs
diff --git a/mali_kbase/mali_kbase_gpuprops_types.h b/mali_kbase/mali_kbase_gpuprops_types.h
index ec6f1c3..d96243d 100644
--- a/mali_kbase/mali_kbase_gpuprops_types.h
+++ b/mali_kbase/mali_kbase_gpuprops_types.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-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 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.
+ *
*/
-
-
/**
* @file mali_kbase_gpuprops_types.h
* Base kernel property query APIs
@@ -60,6 +77,8 @@ 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_gpu_cache_props {
diff --git a/mali_kbase/mali_kbase_gwt.c b/mali_kbase/mali_kbase_gwt.c
index 91dc4db..42ddf9b 100644
--- a/mali_kbase/mali_kbase_gwt.c
+++ b/mali_kbase/mali_kbase_gwt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mali_kbase_gwt.h b/mali_kbase/mali_kbase_gwt.h
index 7e7746e..4510497 100644
--- a/mali_kbase/mali_kbase_gwt.h
+++ b/mali_kbase/mali_kbase_gwt.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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.
+ *
*/
#if !defined(_KBASE_GWT_H)
diff --git a/mali_kbase/mali_kbase_hw.c b/mali_kbase/mali_kbase_hw.c
index 386fb9e..512213c 100644
--- a/mali_kbase/mali_kbase_hw.c
+++ b/mali_kbase/mali_kbase_hw.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2012-2020 ARM Limited. All rights reserved.
@@ -20,8 +21,6 @@
*
*/
-
-
/*
* Run-time work-arounds helpers
*/
@@ -237,7 +236,7 @@ static const enum base_hw_issue *kbase_hw_get_issues_for_new_id(
{U32_MAX, NULL} } },
{GPU_ID2_PRODUCT_LTUX,
- {{GPU_ID2_VERSION_MAKE(3, 0, 0), base_hw_issues_tTUx_r0p0},
+ {{GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTUx_r0p0},
{U32_MAX, NULL} } },
};
@@ -272,8 +271,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
@@ -290,7 +289,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
@@ -343,7 +343,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 {
diff --git a/mali_kbase/mali_kbase_hw.h b/mali_kbase/mali_kbase_hw.h
index f386b16..afc56a6 100644
--- a/mali_kbase/mali_kbase_hw.h
+++ b/mali_kbase/mali_kbase_hw.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-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 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.
+ *
*/
-
-
/**
* @file
* Run-time work-arounds helpers
diff --git a/mali_kbase/mali_kbase_hwaccess_backend.h b/mali_kbase/mali_kbase_hwaccess_backend.h
index 89df251..ce57991 100644
--- a/mali_kbase/mali_kbase_hwaccess_backend.h
+++ b/mali_kbase/mali_kbase_hwaccess_backend.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015, 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,9 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-2015, 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 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.
+ *
*/
-
/*
* HW access backend common APIs
*/
diff --git a/mali_kbase/mali_kbase_hwaccess_defs.h b/mali_kbase/mali_kbase_hwaccess_defs.h
index 3c3dfb0..e21f52d 100644
--- a/mali_kbase/mali_kbase_hwaccess_defs.h
+++ b/mali_kbase/mali_kbase_hwaccess_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2016-2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/**
diff --git a/mali_kbase/mali_kbase_hwaccess_gpuprops.h b/mali_kbase/mali_kbase_hwaccess_gpuprops.h
index 3ae0dbe..edfa02e 100644
--- a/mali_kbase/mali_kbase_hwaccess_gpuprops.h
+++ b/mali_kbase/mali_kbase_hwaccess_gpuprops.h
@@ -26,15 +26,19 @@
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
- * of such GNU licence.
+ * of such 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.
*
*/
-
/**
* Base kernel property query backend APIs
*/
diff --git a/mali_kbase/mali_kbase_hwaccess_instr.h b/mali_kbase/mali_kbase_hwaccess_instr.h
index fd17e55..25a4695 100644
--- a/mali_kbase/mali_kbase_hwaccess_instr.h
+++ b/mali_kbase/mali_kbase_hwaccess_instr.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015, 2017-2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
-
-
/*
* HW Access instrumentation common APIs
*/
diff --git a/mali_kbase/mali_kbase_hwaccess_jm.h b/mali_kbase/mali_kbase_hwaccess_jm.h
index f6ce17e..82236fe 100644
--- a/mali_kbase/mali_kbase_hwaccess_jm.h
+++ b/mali_kbase/mali_kbase_hwaccess_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,9 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
-
/*
* HW access job manager common APIs
*/
diff --git a/mali_kbase/mali_kbase_hwaccess_pm.h b/mali_kbase/mali_kbase_hwaccess_pm.h
index 3e223c6..eb6229e 100644
--- a/mali_kbase/mali_kbase_hwaccess_pm.h
+++ b/mali_kbase/mali_kbase_hwaccess_pm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015, 2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-2015, 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 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.
+ *
*/
/**
diff --git a/mali_kbase/mali_kbase_hwaccess_time.h b/mali_kbase/mali_kbase_hwaccess_time.h
index 94b7551..d982f2a 100644
--- a/mali_kbase/mali_kbase_hwaccess_time.h
+++ b/mali_kbase/mali_kbase_hwaccess_time.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014,2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,9 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014,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 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.
+ *
*/
-
/**
*
*/
diff --git a/mali_kbase/mali_kbase_hwcnt.c b/mali_kbase/mali_kbase_hwcnt.c
index 2708af7..59bbc9d 100644
--- a/mali_kbase/mali_kbase_hwcnt.c
+++ b/mali_kbase/mali_kbase_hwcnt.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018, 2020 ARM Limited. All rights reserved.
@@ -28,9 +29,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 +49,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 +88,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 +117,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 +129,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 +143,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 +151,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 +174,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 +216,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;
@@ -366,8 +386,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);
@@ -609,7 +629,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)
{
@@ -644,7 +663,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)
{
@@ -663,7 +681,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)
{
@@ -692,7 +709,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)
{
@@ -712,7 +728,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)
@@ -720,9 +735,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,
@@ -739,8 +762,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);
@@ -752,7 +775,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,
@@ -768,7 +790,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);
@@ -780,7 +802,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/mali_kbase/mali_kbase_hwcnt_accumulator.h b/mali_kbase/mali_kbase_hwcnt_accumulator.h
index eb82ea4..c3c06b3 100644
--- a/mali_kbase/mali_kbase_hwcnt_accumulator.h
+++ b/mali_kbase/mali_kbase_hwcnt_accumulator.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/**
diff --git a/mali_kbase/mali_kbase_hwcnt_backend.h b/mali_kbase/mali_kbase_hwcnt_backend.h
index 3a921b7..5f3ab08 100644
--- a/mali_kbase/mali_kbase_hwcnt_backend.h
+++ b/mali_kbase/mali_kbase_hwcnt_backend.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/*
@@ -41,12 +60,26 @@ 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.
* @out_backend: Non-NULL pointer to where backend is stored on success.
@@ -171,9 +204,9 @@ 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.
*/
@@ -186,9 +219,10 @@ typedef int (*kbase_hwcnt_backend_dump_get_fn)(
/**
* 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.
@@ -203,8 +237,8 @@ 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_metadata_fn metadata;
kbase_hwcnt_backend_init_fn init;
kbase_hwcnt_backend_term_fn term;
kbase_hwcnt_backend_timestamp_ns_fn timestamp_ns;
diff --git a/mali_kbase/mali_kbase_hwcnt_backend_csf.c b/mali_kbase/mali_kbase_hwcnt_backend_csf.c
new file mode 100644
index 0000000..8560fd7
--- /dev/null
+++ b/mali_kbase/mali_kbase_hwcnt_backend_csf.c
@@ -0,0 +1,1882 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * (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.
+ *
+ * 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_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.
+ * @lock: Spinlock protecting backend and its internal
+ * states.
+ * @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. Functions inside
+ * this interface MUST never be called while
+ * holding the spin lock, as that could cause
+ * deadlocks.
+ * @ring_buf_cnt: Dump buffer count in the ring buffer.
+ * @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.
+ * @gpu_info: GPU information to initialise HWC dump memory
+ * layout.
+ */
+struct kbase_hwcnt_backend_csf_info {
+ struct kbase_hwcnt_backend_csf *backend;
+ spinlock_t lock;
+ 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;
+ size_t dump_bytes;
+ struct kbase_hwcnt_gpu_info gpu_info;
+};
+
+/**
+ * struct kbase_hwcnt_csf_physical_layout - HWC sample memory physical layout
+ * information.
+ * @fe_cnt: FroneEnd 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 signalled 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;
+};
+
+bool kbasep_hwcnt_backend_csf_backend_exists(
+ struct kbase_hwcnt_backend_csf_info *csf_info)
+{
+ WARN_ON(!csf_info);
+ lockdep_assert_held(&csf_info->lock);
+ 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->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 the header is
+ * enabled, the header will be
+ * used when do the samples
+ * delta calculation.
+ *@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_gpu_info *gpu_info,
+ struct kbase_hwcnt_csf_physical_layout *phys_layout)
+{
+ WARN_ON(!gpu_info);
+ WARN_ON(!phys_layout);
+
+ phys_layout->fe_cnt = 1;
+ phys_layout->tiler_cnt = 1;
+ phys_layout->mmu_l2_cnt = gpu_info->l2_count;
+ phys_layout->shader_cnt = fls64(gpu_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 = gpu_info->core_mask;
+
+ phys_layout->headers_per_block = KBASE_HWCNT_V5_HEADERS_PER_BLOCK;
+ phys_layout->counters_per_block = KBASE_HWCNT_V5_COUNTERS_PER_BLOCK;
+ phys_layout->values_per_block = KBASE_HWCNT_V5_VALUES_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->dump_bytes);
+ memset(backend_csf->accum_buf, 0, backend_csf->info->dump_bytes);
+ memset(backend_csf->old_sample_buf, 0, backend_csf->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;
+
+ 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 *
+ backend_csf->info->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->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->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)
+{
+ 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 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 the counters. */
+ 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;
+ 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->dump_bytes;
+ 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 - 1), 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);
+
+ 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 - 1), 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->set_extract_index(
+ backend_csf->info->csf_if->ctx, insert_index_to_stop);
+}
+
+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)
+{
+ lockdep_assert_held(&backend_csf->info->lock);
+
+ 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);
+
+ spin_lock_irqsave(&backend_csf->info->lock, 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_TRANSITIONING_TO_ENABLED &&
+ 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));
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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;
+ spin_unlock_irqrestore(&backend_csf->info->lock, flags);
+
+ /* 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);
+
+ /* 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. */
+ spin_lock_irqsave(&backend_csf->info->lock, 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_TRANSITIONING_TO_ENABLED &&
+ 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));
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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);
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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);
+
+ /* 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);
+
+ spin_lock_irqsave(&backend_csf->info->lock, 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) {
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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)) {
+ spin_unlock_irqrestore(&backend_csf->info->lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&backend_csf->info->lock, flags);
+
+ /* Accumulate everything we possibly can. We grabbed offsets before the
+ * spin lock, so we know it is not possible for a concurrent dump's
+ * insert_to_accumulate to exceed the insert we grabbed.
+ */
+ 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)
+{
+ unsigned long flags;
+ u32 extract_index;
+ u32 insert_index;
+
+ WARN_ON(!csf_info);
+
+ csf_info->csf_if->get_indexes(csf_info->csf_if->ctx, &extract_index,
+ &insert_index);
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+
+ /* Make sure the backend exists and is in the correct state.
+ * A lot of things could have happened to it in the period before we
+ * acquired the lock.
+ */
+ if (kbasep_hwcnt_backend_csf_backend_exists(csf_info) &&
+ (csf_info->backend->enable_state ==
+ KBASE_HWCNT_BACKEND_CSF_ENABLED ||
+ csf_info->backend->enable_state ==
+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) &&
+ csf_info->backend->dump_state ==
+ KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT) {
+ csf_info->backend->insert_index_to_accumulate = insert_index;
+ csf_info->backend->dump_state =
+ KBASE_HWCNT_BACKEND_CSF_DUMP_WORKER_LAUNCHED;
+
+ /* Submit the accumulator task into the work queue. */
+ while (true != queue_work(csf_info->backend->hwc_dump_workq,
+ &csf_info->backend->hwc_dump_work)) {
+ /* Spin until we have guaranteed the work has been
+ * submitted.
+ * Without this there is a potential race where a prior
+ * submission of the work may still technically be on
+ * the queue, even though all of its work is complete.
+ */
+ }
+ }
+
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+}
+
+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;
+}
+
+static int kbasep_hwcnt_backend_csf_dump_enable_impl(
+ struct kbase_hwcnt_backend *backend,
+ const struct kbase_hwcnt_enable_map *enable_map,
+ struct kbase_hwcnt_backend_csf_if_enable *out_enable)
+{
+ unsigned long flags;
+ struct kbase_hwcnt_backend_csf *backend_csf =
+ (struct kbase_hwcnt_backend_csf *)backend;
+ struct kbase_hwcnt_backend_csf_if_enable enable;
+
+ WARN_ON(!out_enable);
+
+ if (!backend_csf || !enable_map ||
+ (enable_map->metadata != backend_csf->info->metadata))
+ return -EINVAL;
+
+ kbasep_hwcnt_backend_csf_get_physical_enable(backend_csf, enable_map,
+ &enable);
+
+ spin_lock_irqsave(&backend_csf->info->lock, flags);
+ /* enable_state should be DISABLED before we transfer it to enabled */
+ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED) {
+ spin_unlock_irqrestore(&backend_csf->info->lock, flags);
+ 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);
+ spin_unlock_irqrestore(&backend_csf->info->lock, flags);
+
+ *out_enable = enable;
+ return 0;
+}
+
+/* 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)
+{
+ int errcode;
+ struct kbase_hwcnt_backend_csf *backend_csf =
+ (struct kbase_hwcnt_backend_csf *)backend;
+ struct kbase_hwcnt_backend_csf_if_enable enable;
+
+ errcode = kbasep_hwcnt_backend_csf_dump_enable_impl(backend, enable_map,
+ &enable);
+ if (errcode)
+ return errcode;
+
+ backend_csf->info->csf_if->dump_enable_nolock(
+ 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;
+ struct kbase_hwcnt_backend_csf *backend_csf =
+ (struct kbase_hwcnt_backend_csf *)backend;
+ struct kbase_hwcnt_backend_csf_if_enable enable;
+
+ errcode = kbasep_hwcnt_backend_csf_dump_enable_impl(backend, enable_map,
+ &enable);
+ if (errcode)
+ return errcode;
+
+ 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;
+}
+
+static void kbasep_hwcnt_backend_csf_wait_enable_transition_complete(
+ struct kbase_hwcnt_backend_csf *backend_csf, unsigned long *lock_flags)
+{
+ lockdep_assert_held(&backend_csf->info->lock);
+
+ while ((backend_csf->enable_state ==
+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) ||
+ (backend_csf->enable_state ==
+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED)) {
+ spin_unlock_irqrestore(&backend_csf->info->lock, *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));
+
+ spin_lock_irqsave(&backend_csf->info->lock, *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);
+
+ spin_lock_irqsave(&backend_csf->info->lock, 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.
+ */
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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));
+
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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);
+
+ if (do_disable)
+ backend_csf->info->csf_if->dump_disable(
+ backend_csf->info->csf_if->ctx);
+
+ spin_lock_irqsave(&backend_csf->info->lock, flags);
+
+ kbasep_hwcnt_backend_csf_wait_enable_transition_complete(backend_csf,
+ &flags);
+
+ switch (backend_csf->enable_state) {
+ case KBASE_HWCNT_BACKEND_CSF_DISABLED:
+ case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED:
+ case KBASE_HWCNT_BACKEND_CSF_ENABLED:
+ case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED:
+ case KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR:
+ WARN_ON(true);
+ break;
+ 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;
+ }
+
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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 - 1), 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;
+
+ spin_lock_irqsave(&backend_csf->info->lock, flags);
+ /* Make sure we are enabled or becoming enabled. */
+ if ((backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) &&
+ (backend_csf->enable_state !=
+ KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED)) {
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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)) {
+ spin_unlock_irqrestore(&backend_csf->info->lock, flags);
+ /* HWC is disabled or another dump is ongoing, or we are on
+ * fault.
+ */
+ return -EIO;
+ }
+
+ /* If we are transitioning to enabled there is 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;
+ spin_unlock_irqrestore(&backend_csf->info->lock, flags);
+ *dump_time_ns = kbasep_hwcnt_backend_csf_timestamp_ns(backend);
+ kbasep_hwcnt_backend_csf_cc_update(backend_csf);
+ return 0;
+ }
+
+ /* 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;
+ }
+ spin_unlock_irqrestore(&backend_csf->info->lock, flags);
+
+ /* 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);
+ }
+
+ 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);
+
+ spin_lock_irqsave(&backend_csf->info->lock, flags);
+ /* Make sure the last dump actually succeeded. */
+ errcode = (backend_csf->dump_state ==
+ KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED) ?
+ 0 :
+ -EIO;
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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);
+
+ if (backend_csf->info->csf_if->ring_buf_free) {
+ 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->gpu_info,
+ &backend_csf->phys_layout);
+
+ backend_csf->accum_buf = kzalloc(csf_info->dump_bytes, GFP_KERNEL);
+ if (!backend_csf->accum_buf)
+ goto err_alloc_acc_buf;
+
+ backend_csf->old_sample_buf = kzalloc(csf_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->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 - 1), 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.
+ */
+ spin_lock_irqsave(&csf_info->lock, 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;
+ }
+ }
+ spin_unlock_irqrestore(&csf_info->lock, 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.
+ */
+ spin_lock_irqsave(&backend_csf->info->lock, flags);
+ backend_csf->info->backend = NULL;
+ spin_unlock_irqrestore(&backend_csf->info->lock, 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;
+
+ spin_lock_init(&info->lock);
+
+#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, unsigned long *lock_flags)
+{
+ bool do_disable = false;
+
+ lockdep_assert_held(&backend_csf->info->lock);
+
+ /* 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) {
+ spin_unlock_irqrestore(&backend_csf->info->lock, *lock_flags);
+ backend_csf->info->csf_if->dump_disable(
+ backend_csf->info->csf_if->ctx);
+ spin_lock_irqsave(&backend_csf->info->lock, *lock_flags);
+ }
+}
+
+static void kbasep_hwcnt_backend_csf_handle_recoverable_error(
+ struct kbase_hwcnt_backend_csf *backend_csf, unsigned long *lock_flags)
+{
+ lockdep_assert_held(&backend_csf->info->lock);
+
+ 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,
+ lock_flags);
+ 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);
+
+ /* Unlock spin lock before we call csf_if disable(). */
+ spin_unlock_irqrestore(&backend_csf->info->lock, *lock_flags);
+
+ backend_csf->info->csf_if->dump_disable(
+ backend_csf->info->csf_if->ctx);
+
+ /* Lock spin lock again to match the spin lock pairs. */
+ spin_lock_irqsave(&backend_csf->info->lock, *lock_flags);
+ return;
+ }
+}
+
+void kbase_hwcnt_backend_csf_protm_entered(
+ 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;
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+ csf_info->fw_in_protected_mode = true;
+
+ /* Early out if the backend does not exist. */
+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ return;
+ }
+
+ backend_csf = csf_info->backend;
+ /* If we are not in REQUESTED state, we don't need to do the dumping. */
+ if (backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_REQUESTED) {
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ return;
+ }
+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT;
+
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ kbase_hwcnt_backend_csf_submit_dump_worker(csf_info);
+}
+
+void kbase_hwcnt_backend_csf_protm_exited(
+ 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;
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+ csf_info->fw_in_protected_mode = false;
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+}
+
+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;
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+ csf_info->unrecoverable_error_happened = true;
+ /* Early out if the backend does not exist. */
+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ return;
+ }
+
+ kbasep_hwcnt_backend_csf_handle_unrecoverable_error(csf_info->backend,
+ &flags);
+
+ spin_unlock_irqrestore(&csf_info->lock, 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;
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+ csf_info->unrecoverable_error_happened = false;
+ /* Early out if the backend does not exist. */
+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
+ spin_unlock_irqrestore(&csf_info->lock, 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, &flags);
+ }
+
+ /* 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);
+ }
+
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+}
+
+void kbase_hwcnt_backend_csf_on_prfcnt_sample(
+ 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;
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+ /* Early out if the backend does not exist. */
+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ 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) {
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ return;
+ }
+ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT;
+
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ kbase_hwcnt_backend_csf_submit_dump_worker(csf_info);
+}
+
+void kbase_hwcnt_backend_csf_on_prfcnt_threshold(
+ 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;
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+ /* Early out if the backend does not exist. */
+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ 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);
+ }
+
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+}
+
+void kbase_hwcnt_backend_csf_on_prfcnt_overflow(
+ 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;
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+ /* Early out if the backend does not exist. */
+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ 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,
+ &flags);
+
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+}
+
+void kbase_hwcnt_backend_csf_on_prfcnt_enable(
+ 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;
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+ /* Early out if the backend does not exist. */
+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ 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, &flags);
+ }
+
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+}
+
+void kbase_hwcnt_backend_csf_on_prfcnt_disable(
+ 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;
+
+ spin_lock_irqsave(&csf_info->lock, flags);
+ /* Early out if the backend does not exist. */
+ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) {
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+ 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, &flags);
+ }
+
+ spin_unlock_irqrestore(&csf_info->lock, flags);
+}
+
+int kbase_hwcnt_backend_csf_metadata_init(
+ struct kbase_hwcnt_backend_interface *iface)
+{
+ int errcode;
+ struct kbase_hwcnt_backend_csf_info *csf_info;
+
+ if (!iface)
+ return -EINVAL;
+
+ csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info;
+
+ WARN_ON(!csf_info->csf_if->get_gpu_info);
+ csf_info->csf_if->get_gpu_info(csf_info->csf_if->ctx,
+ &csf_info->dump_bytes,
+ &csf_info->gpu_info.l2_count,
+ &csf_info->gpu_info.core_mask,
+ &csf_info->gpu_info.clk_cnt);
+
+ /* The clock domain counts should not exceed the number of maximum
+ * number of clock regulators.
+ */
+ if (csf_info->gpu_info.clk_cnt > BASE_MAX_NR_CLOCKS_REGULATORS)
+ return -EIO;
+
+ errcode = kbase_hwcnt_csf_metadata_create(&csf_info->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->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/mali_kbase/mali_kbase_hwcnt_backend_csf.h b/mali_kbase/mali_kbase_hwcnt_backend_csf.h
new file mode 100644
index 0000000..c2b3644
--- /dev/null
+++ b/mali_kbase/mali_kbase_hwcnt_backend_csf.h
@@ -0,0 +1,184 @@
+/*
+ *
+ * (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 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 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 kbdev->hwaccess_lock held.
+ *
+ * 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
+ * to be called when an
+ * unrecoverable error
+ * occurs, such as the
+ * firmware has died or bus
+ * error, this puts us into
+ * the unrecoverable error
+ * state, which we can only
+ * get out of by a reset.
+ * @iface: Non-NULL pointer to HWC backend interface.
+ */
+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/mali_kbase/mali_kbase_hwcnt_backend_csf_if.h b/mali_kbase/mali_kbase_hwcnt_backend_csf_if.h
new file mode 100644
index 0000000..bfc0e3c
--- /dev/null
+++ b/mali_kbase/mali_kbase_hwcnt_backend_csf_if.h
@@ -0,0 +1,280 @@
+/*
+ *
+ * (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 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.
+ *
+ */
+
+/*
+ * 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;
+};
+
+/**
+ * typedef kbase_hwcnt_backend_csf_if_get_gpu_info_fn - Get GPU information
+ * @ctx: Non-NULL pointer to a CSF context.
+ * @dump_size: Non-NULL pointer to where the dump size of performance counter
+ * sample is stored.
+ * @l2_count: Non-NULL pointer to where the MMU L2 cache count is stored.
+ * @core_mask: Non-NULL pointer to where shader core mask is stored.
+ *
+ * @clk_cnt: Non-NULL pointer to where clock domain count in the system is
+ * stored.
+ */
+typedef void (*kbase_hwcnt_backend_csf_if_get_gpu_info_fn)(
+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, size_t *dump_size,
+ size_t *l2_count, u64 *core_mask, u8 *clk_cnt);
+
+/**
+ * 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.
+ * It is set to true when CPU cache needs to be invalidated
+ * before reading the ring buffer contents. And set to false
+ * when CPU cache needs to be flushed after writing to the
+ * ring buffer.
+ *
+ * After HWC sample request is done in GPU side, we need to sync the dump memory
+ * to CPU side to access the HWC data.
+ */
+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.
+ */
+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_enable_nolock_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.
+ *
+ * Exactly the same as kbase_hwcnt_backend_csf_if_dump_enable_fn(), except must
+ * be called in an atomic context with the spinlock documented by the specific
+ * backend interface held.
+ */
+typedef void (*kbase_hwcnt_backend_csf_if_dump_enable_nolock_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.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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_gpu_info interface.
+ * @clk_enable_map: An array of bitfields, each bit specifies an enabled clock
+ * domain.
+ */
+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.
+ * @get_gpu_info: Function ptr to get HWC 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_get_gpu_info_fn get_gpu_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_enable_nolock_fn dump_enable_nolock;
+ 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/mali_kbase/mali_kbase_hwcnt_backend_csf_if_fw.c b/mali_kbase/mali_kbase_hwcnt_backend_csf_if_fw.c
new file mode 100644
index 0000000..21e9853
--- /dev/null
+++ b/mali_kbase/mali_kbase_hwcnt_backend_csf_if_fw.c
@@ -0,0 +1,771 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * (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.
+ *
+ * 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
+ *
+ */
+
+/*
+ * 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 "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"
+#ifdef CONFIG_MALI_NO_MALI
+#include <backend/gpu/mali_kbase_model_dummy.h>
+#endif
+
+/** 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.
+ * @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;
+};
+
+/**
+ * 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.
+ * @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_gpu_info(
+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, size_t *dump_size,
+ size_t *l2_count, u64 *core_mask, u8 *clk_cnt)
+{
+#ifdef CONFIG_MALI_NO_MALI
+ *l2_count = KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS;
+ *core_mask = (1ull << KBASE_DUMMY_MODEL_MAX_SHADER_CORES) - 1;
+ *dump_size = KBASE_DUMMY_MODEL_MAX_NUM_PERF_BLOCKS *
+ KBASE_DUMMY_MODEL_BLOCK_SIZE;
+ *clk_cnt = 1;
+#else
+ 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;
+
+ WARN_ON(!ctx);
+ WARN_ON(!dump_size);
+ WARN_ON(!l2_count);
+ WARN_ON(!core_mask);
+ WARN_ON(!clk_cnt);
+
+ 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;
+ *dump_size = fw_ctx->buf_bytes;
+
+ *l2_count = kbdev->gpu_props.props.l2_props.num_l2_slices;
+ *core_mask = kbdev->gpu_props.props.coherency_info.group[0].core_mask;
+
+ *clk_cnt = fw_ctx->clk_cnt;
+#endif
+}
+
+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);
+
+ /* Get the buffer indexes in the ring buffer. */
+ ring_buf_index_first = buf_index_first & (fw_ring_buf->buf_count - 1);
+ ring_buf_index_last = buf_index_last & (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_nolock(
+ 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)
+{
+ unsigned long flags;
+ 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);
+
+ kbdev = fw_ctx->kbdev;
+ global_iface = &kbdev->csf.global_iface;
+
+ lockdep_assert_held(&kbdev->hwaccess_lock);
+
+ /* Configure */
+ prfcnt_config = fw_ring_buf->buf_count;
+ prfcnt_config |= enable->counter_set << PRFCNT_CONFIG_SETSELECT_SHIFT;
+
+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
+
+ /* 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);
+
+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
+
+ kbasep_hwcnt_backend_csf_if_fw_cc_enable(fw_ctx,
+ enable->clk_enable_map);
+}
+
+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)
+{
+ unsigned long flags;
+ struct kbase_device *kbdev;
+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
+
+ WARN_ON(!ctx);
+ WARN_ON(!ring_buf);
+ WARN_ON(!enable);
+
+ kbdev = fw_ctx->kbdev;
+
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+
+ kbasep_hwcnt_backend_csf_if_fw_dump_enable_nolock(ctx, ring_buf,
+ enable);
+
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+}
+
+static void kbasep_hwcnt_backend_csf_if_fw_dump_disable(
+ struct kbase_hwcnt_backend_csf_if_ctx *ctx)
+{
+ unsigned long flags;
+ 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);
+
+ kbdev = fw_ctx->kbdev;
+ global_iface = &kbdev->csf.global_iface;
+
+ /* Disable the HWC */
+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
+ 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;
+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
+
+ 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)
+{
+ unsigned long flags;
+ 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);
+
+ kbdev = fw_ctx->kbdev;
+ global_iface = &kbdev->csf.global_iface;
+
+ /* Trigger dumping */
+ kbase_csf_scheduler_spin_lock(kbdev, &flags);
+ 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);
+ kbase_csf_scheduler_spin_unlock(kbdev, flags);
+}
+
+static void kbasep_hwcnt_backend_csf_if_fw_get_indexes(
+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 *extract_index,
+ u32 *insert_index)
+{
+ unsigned long flags;
+ 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);
+
+ kbase_csf_scheduler_spin_lock(fw_ctx->kbdev, &flags);
+ *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);
+ kbase_csf_scheduler_spin_unlock(fw_ctx->kbdev, flags);
+}
+
+static void kbasep_hwcnt_backend_csf_if_fw_set_extract_index(
+ struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 extract_idx)
+{
+ unsigned long flags;
+ struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
+ (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
+
+ WARN_ON(!ctx);
+
+ /* Set the raw extract index to release the buffer back to the ring
+ * buffer.
+ */
+ kbase_csf_scheduler_spin_lock(fw_ctx->kbdev, &flags);
+ kbase_csf_firmware_global_input(&fw_ctx->kbdev->csf.global_iface,
+ GLB_PRFCNT_EXTRACT, extract_idx);
+ kbase_csf_scheduler_spin_unlock(fw_ctx->kbdev, flags);
+}
+
+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);
+
+ 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);
+ }
+ }
+}
+
+/**
+ * @brief Destroy a CSF FW interface context.
+ *
+ * @param[in,out] 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->get_gpu_info = kbasep_hwcnt_backend_csf_if_fw_get_gpu_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_enable_nolock =
+ kbasep_hwcnt_backend_csf_if_fw_dump_enable_nolock;
+ 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/mali_kbase/mali_kbase_hwcnt_backend_csf_if_fw.h b/mali_kbase/mali_kbase_hwcnt_backend_csf_if_fw.h
new file mode 100644
index 0000000..b826a50
--- /dev/null
+++ b/mali_kbase/mali_kbase_hwcnt_backend_csf_if_fw.h
@@ -0,0 +1,70 @@
+/*
+ *
+ * (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 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 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/mali_kbase/mali_kbase_hwcnt_backend_jm.c b/mali_kbase/mali_kbase_hwcnt_backend_jm.c
index 7d1334e..a1daaf2 100644
--- a/mali_kbase/mali_kbase_hwcnt_backend_jm.c
+++ b/mali_kbase/mali_kbase_hwcnt_backend_jm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -34,11 +35,7 @@
#endif
#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
-#if MALI_USE_CSF
-#include "mali_kbase_ctx_sched.h"
-#else
#include "backend/gpu/mali_kbase_pm_internal.h"
-#endif
/**
* struct kbase_hwcnt_backend_jm_info - Information used to create an instance
@@ -94,6 +91,47 @@ struct kbase_hwcnt_backend_jm {
};
/**
+ * 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.
+ *
+ * The initialised info struct will only be valid for use while kbdev is valid.
+ */
+int kbase_hwcnt_gpu_info_init(struct kbase_device *kbdev,
+ struct kbase_hwcnt_gpu_info *info)
+{
+ size_t clk;
+
+ if (!kbdev || !info)
+ return -EINVAL;
+
+#ifdef CONFIG_MALI_NO_MALI
+ info->l2_count = KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS;
+ info->core_mask = (1ull << KBASE_DUMMY_MODEL_MAX_SHADER_CORES) - 1;
+#else /* CONFIG_MALI_NO_MALI */
+ {
+ 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;
+ }
+#endif /* CONFIG_MALI_NO_MALI */
+
+ /* 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
@@ -135,10 +173,8 @@ static void kbasep_hwcnt_backend_jm_cc_enable(
if (kbase_hwcnt_clk_enable_map_enabled(
clk_enable_map, KBASE_CLOCK_DOMAIN_TOP)) {
-#if !MALI_USE_CSF
/* turn on the cycle counter */
kbase_pm_request_gpu_cycle_counter_l2_is_on(kbdev);
-#endif
/* Read cycle count for top clock domain. */
kbase_backend_get_gpu_time_norequest(
kbdev, &cycle_count, NULL, NULL);
@@ -191,13 +227,12 @@ static void kbasep_hwcnt_backend_jm_cc_disable(
struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm;
u64 clk_enable_map = backend_jm->clk_enable_map;
-#if !MALI_USE_CSF
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);
}
-#endif
+
if (kbase_hwcnt_clk_enable_map_enabled(
clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) {
@@ -427,9 +462,9 @@ static int kbasep_hwcnt_backend_jm_dump_get(
dst->clk_cnt_buf[clk] = backend_jm->cycle_count_elapsed[clk];
}
- return kbase_hwcnt_gpu_dump_get(
- dst, backend_jm->cpu_dump_va, dst_enable_map,
- backend_jm->pm_core_mask, accumulate);
+ return kbase_hwcnt_jm_dump_get(dst, backend_jm->cpu_dump_va,
+ dst_enable_map, backend_jm->pm_core_mask,
+ accumulate);
}
/**
@@ -497,9 +532,6 @@ static void kbasep_hwcnt_backend_jm_destroy(
return;
if (backend->kctx) {
-#if MALI_USE_CSF
- unsigned long flags;
-#endif
struct kbase_context *kctx = backend->kctx;
struct kbase_device *kbdev = kctx->kbdev;
@@ -510,13 +542,7 @@ static void kbasep_hwcnt_backend_jm_destroy(
kbasep_hwcnt_backend_jm_dump_free(
kctx, backend->gpu_dump_va);
-#if MALI_USE_CSF
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbase_ctx_sched_release_ctx(kctx);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
-#else
kbasep_js_release_privileged_ctx(kbdev, kctx);
-#endif
kbase_destroy_context(kctx);
}
@@ -534,9 +560,6 @@ static int kbasep_hwcnt_backend_jm_create(
const struct kbase_hwcnt_backend_jm_info *info,
struct kbase_hwcnt_backend_jm **out_backend)
{
-#if MALI_USE_CSF
- unsigned long flags;
-#endif
int errcode;
struct kbase_device *kbdev;
struct kbase_hwcnt_backend_jm *backend = NULL;
@@ -557,17 +580,7 @@ static int kbasep_hwcnt_backend_jm_create(
if (!backend->kctx)
goto alloc_error;
-#if MALI_USE_CSF
- kbase_pm_context_active(kbdev);
- mutex_lock(&kbdev->mmu_hw_mutex);
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbase_ctx_sched_retain_ctx(backend->kctx);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
- mutex_unlock(&kbdev->mmu_hw_mutex);
- kbase_pm_context_idle(kbdev);
-#else
kbasep_js_schedule_privileged_ctx(kbdev, backend->kctx);
-#endif
errcode = kbasep_hwcnt_backend_jm_dump_alloc(
info, backend->kctx, &backend->gpu_dump_va);
@@ -597,6 +610,16 @@ error:
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,
@@ -641,7 +664,7 @@ static void kbasep_hwcnt_backend_jm_info_destroy(
if (!info)
return;
- kbase_hwcnt_gpu_metadata_destroy(info->metadata);
+ kbase_hwcnt_jm_metadata_destroy(info->metadata);
kfree(info);
}
@@ -682,10 +705,10 @@ static int kbasep_hwcnt_backend_jm_info_create(
info->counter_set = KBASE_HWCNT_SET_PRIMARY;
#endif
- errcode = kbase_hwcnt_gpu_metadata_create(&hwcnt_gpu_info,
- info->counter_set,
- &info->metadata,
- &info->dump_bytes);
+ errcode = kbase_hwcnt_jm_metadata_create(&hwcnt_gpu_info,
+ info->counter_set,
+ &info->metadata,
+ &info->dump_bytes);
if (errcode)
goto error;
@@ -712,8 +735,8 @@ int kbase_hwcnt_backend_jm_create(
if (errcode)
return errcode;
- iface->metadata = info->metadata;
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;
diff --git a/mali_kbase/mali_kbase_hwcnt_backend_jm.h b/mali_kbase/mali_kbase_hwcnt_backend_jm.h
index f15faeb..b0b24e6 100644
--- a/mali_kbase/mali_kbase_hwcnt_backend_jm.h
+++ b/mali_kbase/mali_kbase_hwcnt_backend_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/**
diff --git a/mali_kbase/mali_kbase_hwcnt_context.h b/mali_kbase/mali_kbase_hwcnt_context.h
index bc50ad1..99d9d1c 100644
--- a/mali_kbase/mali_kbase_hwcnt_context.h
+++ b/mali_kbase/mali_kbase_hwcnt_context.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/**
@@ -28,6 +47,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 +86,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 +104,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 +119,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 +136,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/mali_kbase/mali_kbase_hwcnt_gpu.c b/mali_kbase/mali_kbase_hwcnt_gpu.c
index 1f4953f..9760643 100644
--- a/mali_kbase/mali_kbase_hwcnt_gpu.c
+++ b/mali_kbase/mali_kbase_hwcnt_gpu.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -22,10 +23,9 @@
#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
+
+#include <linux/bug.h>
+#include <linux/err.h>
#define KBASE_HWCNT_V5_BLOCK_TYPE_COUNT 4
#define KBASE_HWCNT_V5_HEADERS_PER_BLOCK 4
@@ -118,17 +118,18 @@ static void kbasep_get_memsys_block_type(u64 *dst,
}
/**
- * 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.
+ * 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,
+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)
{
@@ -139,13 +140,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
@@ -158,7 +159,7 @@ static int kbasep_hwcnt_backend_gpu_metadata_v5_create(
return -EINVAL;
/* One Front End block */
- kbasep_get_fe_block_type(&blks[0].type, counter_set, v5_info->is_csf);
+ 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;
@@ -171,7 +172,7 @@ static int kbasep_hwcnt_backend_gpu_metadata_v5_create(
/* l2_count memsys blks */
kbasep_get_memsys_block_type(&blks[2].type, counter_set);
- blks[2].inst_cnt = v5_info->l2_count;
+ 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;
@@ -191,7 +192,7 @@ 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.
*/
- kbasep_get_sc_block_type(&blks[3].type, counter_set, v5_info->is_csf);
+ 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;
@@ -204,77 +205,34 @@ static int kbasep_hwcnt_backend_gpu_metadata_v5_create(
desc.grp_cnt = 1;
desc.grps = &group;
- desc.clk_cnt = v5_info->clk_cnt;
+ 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.
+ * @v5_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;
-}
-
-int kbase_hwcnt_gpu_info_init(
- struct kbase_device *kbdev,
- struct kbase_hwcnt_gpu_info *info)
-{
- size_t clk;
-
- 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 /* CONFIG_MALI_NO_MALI */
- {
- 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 /* CONFIG_MALI_NO_MALI */
-
-#ifdef MALI_USE_CSF
- info->v5.is_csf = true;
-#else
- info->v5.is_csf = false;
-#endif
-
- /* 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->v5.clk_cnt = clk;
+ WARN_ON(!gpu_info);
- return 0;
+ return (2 + gpu_info->l2_count + fls64(gpu_info->core_mask)) *
+ KBASE_HWCNT_V5_VALUES_PER_BLOCK * KBASE_HWCNT_VALUE_BYTES;
}
-int kbase_hwcnt_gpu_metadata_create(
- const struct kbase_hwcnt_gpu_info *info,
+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)
@@ -283,16 +241,12 @@ 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;
- if (info->type == 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, counter_set, &metadata);
- } else {
- return -EINVAL;
- }
+ 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;
@@ -307,9 +261,38 @@ 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)
@@ -317,7 +300,6 @@ void kbase_hwcnt_gpu_metadata_destroy(
kbase_hwcnt_metadata_destroy(metadata);
}
-KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_metadata_destroy);
static bool is_block_type_shader(
const u64 grp_type,
@@ -338,12 +320,9 @@ static bool is_block_type_shader(
return is_shader;
}
-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, bool accumulate)
{
const struct kbase_hwcnt_metadata *metadata;
const u32 *dump_src;
@@ -402,7 +381,52 @@ int kbase_hwcnt_gpu_dump_get(
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
@@ -558,7 +582,6 @@ 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)
@@ -577,7 +600,6 @@ void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst,
WARN_ON(true);
}
}
-KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_set_to_physical);
void kbase_hwcnt_gpu_enable_map_from_physical(
struct kbase_hwcnt_enable_map *dst,
@@ -649,7 +671,6 @@ void kbase_hwcnt_gpu_enable_map_from_physical(
}
}
}
-KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_enable_map_from_physical);
void kbase_hwcnt_gpu_patch_dump_headers(
struct kbase_hwcnt_dump_buffer *buf,
@@ -683,4 +704,3 @@ void kbase_hwcnt_gpu_patch_dump_headers(
}
}
}
-KBASE_EXPORT_TEST_API(kbase_hwcnt_gpu_patch_dump_headers);
diff --git a/mali_kbase/mali_kbase_hwcnt_gpu.h b/mali_kbase/mali_kbase_hwcnt_gpu.h
index c9039b2..244577d 100644
--- a/mali_kbase/mali_kbase_hwcnt_gpu.h
+++ b/mali_kbase/mali_kbase_hwcnt_gpu.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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_HWCNT_GPU_H_
@@ -30,6 +49,14 @@ 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_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
+
/**
* enum kbase_hwcnt_gpu_group_type - GPU hardware counter group types, used to
* identify metadata groups.
@@ -109,92 +136,110 @@ enum kbase_hwcnt_physical_set {
};
/**
- * struct kbase_hwcnt_gpu_v5_info - Information about hwcnt blocks on v5 GPUs.
+ * 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.
- * @is_csf: Whether CSF is used.
*/
-struct kbase_hwcnt_gpu_v5_info {
+struct kbase_hwcnt_gpu_info {
size_t l2_count;
u64 core_mask;
u8 clk_cnt;
- bool is_csf;
};
/**
- * struct kbase_hwcnt_gpu_info - Tagged union with information about the current
- * GPU's hwcnt blocks.
- * @type: GPU type.
- * @v5: Info filled in if a v5 GPU.
+ * 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
+ * buffer is stored on success.
+ *
+ * Return: 0 on success, else error code.
*/
-struct kbase_hwcnt_gpu_info {
- enum kbase_hwcnt_gpu_group_type type;
- struct kbase_hwcnt_gpu_v5_info v5;
-};
+int kbase_hwcnt_jm_metadata_create(
+ const struct kbase_hwcnt_gpu_info *info,
+ enum kbase_hwcnt_set counter_set,
+ const struct kbase_hwcnt_metadata **out_metadata,
+ size_t *out_dump_bytes);
/**
- * 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.
+ * kbase_hwcnt_jm_metadata_destroy() - Destroy JM GPU hardware counter metadata.
*
- * The initialised info struct will only be valid for use while kbdev is valid.
+ * @metadata: Pointer to metadata to destroy.
*/
-int kbase_hwcnt_gpu_info_init(
- struct kbase_device *kbdev,
- struct kbase_hwcnt_gpu_info *info);
+void kbase_hwcnt_jm_metadata_destroy(
+ const struct kbase_hwcnt_metadata *metadata);
/**
- * 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.
+ * 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.
- * @out_dump_bytes: Non-NULL pointer to where the size of the GPU counter dump
- * buffer is stored on success.
*
* Return: 0 on success, else error code.
*/
-int kbase_hwcnt_gpu_metadata_create(
+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,
- size_t *out_dump_bytes);
+ const struct kbase_hwcnt_metadata **out_metadata);
/**
- * kbase_hwcnt_gpu_metadata_destroy() - Destroy GPU hardware counter 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_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.
+ * @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, 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,
+int kbase_hwcnt_csf_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);
/**
@@ -204,7 +249,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
@@ -231,7 +276,7 @@ void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst,
* @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
@@ -250,7 +295,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/mali_kbase/mali_kbase_hwcnt_legacy.c b/mali_kbase/mali_kbase_hwcnt_legacy.c
index 794ef39..de9b669 100644
--- a/mali_kbase/mali_kbase_hwcnt_legacy.c
+++ b/mali_kbase/mali_kbase_hwcnt_legacy.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018, 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mali_kbase_hwcnt_legacy.h b/mali_kbase/mali_kbase_hwcnt_legacy.h
index 7a610ae..fd0d01e 100644
--- a/mali_kbase/mali_kbase_hwcnt_legacy.h
+++ b/mali_kbase/mali_kbase_hwcnt_legacy.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/**
diff --git a/mali_kbase/mali_kbase_hwcnt_reader.h b/mali_kbase/mali_kbase_hwcnt_reader.h
index 8cd3835..081244c 100644
--- a/mali_kbase/mali_kbase_hwcnt_reader.h
+++ b/mali_kbase/mali_kbase_hwcnt_reader.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2015, 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 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_HWCNT_READER_H_
diff --git a/mali_kbase/mali_kbase_hwcnt_types.c b/mali_kbase/mali_kbase_hwcnt_types.c
index 2b9fe02..f4c0def 100644
--- a/mali_kbase/mali_kbase_hwcnt_types.c
+++ b/mali_kbase/mali_kbase_hwcnt_types.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2018, 2020 ARM Limited. All rights reserved.
@@ -21,7 +22,8 @@
*/
#include "mali_kbase_hwcnt_types.h"
-#include "mali_kbase.h"
+
+#include <linux/slab.h>
/* Minimum alignment of each block of hardware counters */
#define KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT \
@@ -175,13 +177,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,
@@ -205,7 +205,6 @@ int kbase_hwcnt_enable_map_alloc(
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)
{
@@ -216,7 +215,6 @@ void kbase_hwcnt_enable_map_free(struct kbase_hwcnt_enable_map *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,
@@ -243,7 +241,6 @@ int kbase_hwcnt_dump_buffer_alloc(
return 0;
}
-KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_alloc);
void kbase_hwcnt_dump_buffer_free(struct kbase_hwcnt_dump_buffer *dump_buf)
{
@@ -253,7 +250,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,
@@ -309,7 +305,6 @@ int kbase_hwcnt_dump_buffer_array_alloc(
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)
@@ -321,7 +316,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,
@@ -356,7 +350,6 @@ void kbase_hwcnt_dump_buffer_zero(
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)
@@ -369,7 +362,6 @@ void kbase_hwcnt_dump_buffer_zero_strict(
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,
@@ -409,7 +401,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,
@@ -455,7 +446,6 @@ void kbase_hwcnt_dump_buffer_copy(
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,
@@ -502,7 +492,6 @@ void kbase_hwcnt_dump_buffer_copy_strict(
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,
@@ -552,7 +541,6 @@ void kbase_hwcnt_dump_buffer_accumulate(
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,
@@ -601,4 +589,3 @@ void kbase_hwcnt_dump_buffer_accumulate_strict(
dst->clk_cnt_buf[clk] = 0;
}
}
-KBASE_EXPORT_TEST_API(kbase_hwcnt_dump_buffer_accumulate_strict);
diff --git a/mali_kbase/mali_kbase_hwcnt_types.h b/mali_kbase/mali_kbase_hwcnt_types.h
index 3394b12..47f3c0f 100644
--- a/mali_kbase/mali_kbase_hwcnt_types.h
+++ b/mali_kbase/mali_kbase_hwcnt_types.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/**
@@ -85,7 +104,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))
diff --git a/mali_kbase/mali_kbase_hwcnt_virtualizer.c b/mali_kbase/mali_kbase_hwcnt_virtualizer.c
index 917e47c..637ebf5 100644
--- a/mali_kbase/mali_kbase_hwcnt_virtualizer.c
+++ b/mali_kbase/mali_kbase_hwcnt_virtualizer.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
+ * (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
@@ -24,9 +25,6 @@
#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 +85,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 +493,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 +682,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 +714,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 +729,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 +759,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 +779,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/mali_kbase/mali_kbase_hwcnt_virtualizer.h b/mali_kbase/mali_kbase_hwcnt_virtualizer.h
index 8f628c3..d143de2 100644
--- a/mali_kbase/mali_kbase_hwcnt_virtualizer.h
+++ b/mali_kbase/mali_kbase_hwcnt_virtualizer.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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.
+ *
*/
/**
@@ -31,6 +50,7 @@
#define _KBASE_HWCNT_VIRTUALIZER_H_
#include <linux/types.h>
+#include <linux/workqueue.h>
struct kbase_hwcnt_context;
struct kbase_hwcnt_virtualizer;
@@ -142,4 +162,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/mali_kbase/mali_kbase_ioctl.h b/mali_kbase/mali_kbase_ioctl.h
index 1180b3a..b4ee788 100644
--- a/mali_kbase/mali_kbase_ioctl.h
+++ b/mali_kbase/mali_kbase_ioctl.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2017-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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_IOCTL_H_
@@ -672,6 +691,18 @@ 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)
+
/***************
* test ioctls *
***************/
@@ -826,11 +857,11 @@ 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
diff --git a/mali_kbase/mali_kbase_jd.c b/mali_kbase/mali_kbase_jd.c
index a8cdf82..9407146 100644
--- a/mali_kbase/mali_kbase_jd.c
+++ b/mali_kbase/mali_kbase_jd.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
@@ -20,8 +21,6 @@
*
*/
-
-
#include <linux/dma-buf.h>
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
@@ -30,6 +29,7 @@
#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>
@@ -44,13 +44,9 @@
#define beenthere(kctx, f, a...) dev_dbg(kctx->kbdev->dev, "%s:" f, __func__, ##a)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
-/* random32 was renamed to prandom_u32 in 3.8 */
-#define prandom_u32 random32
-#endif
-
/* 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)))
@@ -243,7 +239,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) +
@@ -259,13 +256,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,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
- sizeof(struct reservation_object *),
+ 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 *),
+ sizeof(struct dma_resv *),
#endif
- GFP_KERNEL);
+ GFP_KERNEL);
if (!info.resv_objs) {
err_ret_val = -ENOMEM;
goto early_err_out;
@@ -319,7 +317,7 @@ 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 (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
+#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE)
struct reservation_object *resv;
#else
struct dma_resv *resv;
@@ -336,7 +334,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;
}
@@ -489,7 +487,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;
@@ -498,7 +497,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))
@@ -735,7 +735,8 @@ bool jd_done_nolock(struct kbase_jd_atom *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]);
@@ -793,7 +794,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);
}
}
@@ -809,10 +811,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;
@@ -907,10 +913,11 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
dev_dbg(kbdev->dev, "User did JD submit atom %p\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;
@@ -983,7 +990,8 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
/* Wrong dependency setup. Atom will be sent
* back to user space. Do not record any
- * dependencies. */
+ * dependencies.
+ */
jd_trace_atom_submit(kctx, katom, NULL);
return jd_done_nolock(katom, NULL);
@@ -1069,7 +1077,10 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
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. */
jd_trace_atom_submit(kctx, katom, &katom->sched_priority);
@@ -1535,7 +1546,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);
@@ -1543,7 +1556,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(
@@ -1618,7 +1632,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! */
@@ -1687,10 +1702,10 @@ 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);
KBASE_KTRACE_ADD_JM(kbdev, JD_CANCEL, kctx, katom, katom->jc, 0);
@@ -1761,12 +1776,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;
}
@@ -1802,6 +1820,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/mali_kbase/mali_kbase_jd_debugfs.c b/mali_kbase/mali_kbase_jd_debugfs.c
index 5dd3f00..7b2dade 100644
--- a/mali_kbase/mali_kbase_jd_debugfs.c
+++ b/mali_kbase/mali_kbase_jd_debugfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
@@ -66,42 +67,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 +179,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));
diff --git a/mali_kbase/mali_kbase_jd_debugfs.h b/mali_kbase/mali_kbase_jd_debugfs.h
index 697bdef..c3cee2e 100644
--- a/mali_kbase/mali_kbase_jd_debugfs.h
+++ b/mali_kbase/mali_kbase_jd_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
/**
diff --git a/mali_kbase/mali_kbase_jm.c b/mali_kbase/mali_kbase_jm.c
index 16ae320..d5e64a1 100644
--- a/mali_kbase/mali_kbase_jm.c
+++ b/mali_kbase/mali_kbase_jm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
@@ -20,7 +21,6 @@
*
*/
-
/*
* HW access job manager common APIs
*/
diff --git a/mali_kbase/mali_kbase_jm.h b/mali_kbase/mali_kbase_jm.h
index 132db41..697a3ff 100644
--- a/mali_kbase/mali_kbase_jm.h
+++ b/mali_kbase/mali_kbase_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2013-2014, 2016, 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2013-2014, 2016, 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 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.
+ *
*/
/*
diff --git a/mali_kbase/mali_kbase_js.c b/mali_kbase/mali_kbase_js.c
index 0b0c5bf..0bde5e2 100644
--- a/mali_kbase/mali_kbase_js.c
+++ b/mali_kbase/mali_kbase_js.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (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
@@ -20,8 +21,6 @@
*
*/
-
-
/*
* Job Scheduler Implementation
*/
@@ -37,6 +36,7 @@
#include "mali_kbase_jm.h"
#include "mali_kbase_hwaccess_jm.h"
+#include <linux/priority_control_manager.h>
/*
* Private types
@@ -45,26 +45,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 */
};
@@ -184,7 +188,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_REALTIME;
prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
if (!jsctx_rb_none_to_pull_prio(kctx, js, prio))
return false;
@@ -277,7 +281,7 @@ jsctx_queue_foreach(struct kbase_context *kctx, int js,
{
int prio;
- for (prio = KBASE_JS_ATOM_SCHED_PRIO_HIGH;
+ for (prio = KBASE_JS_ATOM_SCHED_PRIO_REALTIME;
prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++)
jsctx_queue_foreach_prio(kctx, js, prio, callback);
}
@@ -319,7 +323,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 +337,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_REALTIME;
prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
struct kbase_jd_atom *katom;
@@ -448,7 +452,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,7 +536,8 @@ 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);
@@ -595,11 +601,13 @@ 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);
@@ -1020,7 +1028,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 +1039,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 +1048,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 +1059,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 +1068,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 +1077,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 +1088,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 +1107,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;
@@ -1181,7 +1197,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_REALTIME;
prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
if (kctx->atoms_count[prio]) {
new_priority = prio;
@@ -1192,6 +1208,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
@@ -1349,7 +1366,8 @@ bool kbasep_js_add_job(struct kbase_context *kctx,
(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);
@@ -1389,7 +1407,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,17 +1423,20 @@ 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);
- /* 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);
}
}
@@ -1478,7 +1500,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 +1548,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 +1648,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,7 +1660,8 @@ 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 */
+ * from the Run Pool
+ */
dev_dbg(kbdev->dev, "JS: RunPool Remove Context %p 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));
@@ -1662,7 +1688,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 +1729,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,7 +1772,8 @@ 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);
kbase_js_foreach_ctx_job(kctx, &kbase_jd_cancel);
@@ -1798,7 +1827,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)
{
@@ -1867,7 +1897,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 +1957,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 +1971,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 +2000,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;
}
@@ -2059,7 +2094,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 +2107,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 +2153,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 +2175,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 +2187,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 +2202,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_REALTIME;
prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) {
struct kbase_context *kctx, *n;
unsigned long flags;
@@ -2283,7 +2323,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 {
@@ -2472,7 +2513,8 @@ struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, int js)
/* 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);
@@ -2771,13 +2813,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(
@@ -3091,7 +3135,8 @@ 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,
@@ -3412,7 +3457,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(
@@ -3483,7 +3529,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 +3555,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))
@@ -3580,7 +3628,8 @@ 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);
@@ -3655,8 +3704,9 @@ void kbase_js_zap_context(struct kbase_context *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,7 +3717,8 @@ 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);
@@ -3678,18 +3729,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);
/* 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);
@@ -3711,7 +3765,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,
@@ -3758,3 +3813,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/mali_kbase/mali_kbase_js.h b/mali_kbase/mali_kbase_js.h
index 541acd4..3e9719a 100644
--- a/mali_kbase/mali_kbase_js.h
+++ b/mali_kbase/mali_kbase_js.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-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 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.
+ *
*/
-
-
/**
* @file mali_kbase_js.h
* Job Scheduler APIs.
diff --git a/mali_kbase/mali_kbase_js_ctx_attr.c b/mali_kbase/mali_kbase_js_ctx_attr.c
index 141d04a..67c4952 100644
--- a/mali_kbase/mali_kbase_js_ctx_attr.c
+++ b/mali_kbase/mali_kbase_js_ctx_attr.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2012-2016, 2018, 2020 ARM Limited. All rights reserved.
@@ -20,7 +21,6 @@
*
*/
-
#include <mali_kbase.h>
#include <mali_kbase_config.h>
@@ -211,7 +211,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 +252,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/mali_kbase/mali_kbase_js_ctx_attr.h b/mali_kbase/mali_kbase_js_ctx_attr.h
index 25fd397..fa8731a 100644
--- a/mali_kbase/mali_kbase_js_ctx_attr.h
+++ b/mali_kbase/mali_kbase_js_ctx_attr.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2015, 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-2015, 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 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.
+ *
*/
-
-
/**
* @file mali_kbase_js_ctx_attr.h
* Job Scheduler Context Attribute APIs
diff --git a/mali_kbase/mali_kbase_kinstr_jm.c b/mali_kbase/mali_kbase_kinstr_jm.c
index 1e91a7c..98b82f2 100644
--- a/mali_kbase/mali_kbase_kinstr_jm.c
+++ b/mali_kbase/mali_kbase_kinstr_jm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -70,13 +71,7 @@ typedef unsigned int __poll_t;
/* Allows us to perform ASM goto for the tracing
* https://www.kernel.org/doc/Documentation/static-keys.txt
*/
-#if KERNEL_VERSION(4, 3, 0) <= LINUX_VERSION_CODE
DEFINE_STATIC_KEY_FALSE(basep_kinstr_jm_reader_static_key);
-#else
-struct static_key basep_kinstr_jm_reader_static_key = STATIC_KEY_INIT_FALSE;
-#define static_branch_inc(key) static_key_slow_inc(key)
-#define static_branch_dec(key) static_key_slow_dec(key)
-#endif /* KERNEL_VERSION(4 ,3, 0) <= LINUX_VERSION_CODE */
#define KBASE_KINSTR_JM_VERSION 1
diff --git a/mali_kbase/mali_kbase_kinstr_jm.h b/mali_kbase/mali_kbase_kinstr_jm.h
index 555edfe..a276361 100644
--- a/mali_kbase/mali_kbase_kinstr_jm.h
+++ b/mali_kbase/mali_kbase_kinstr_jm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019,2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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.
+ *
*/
/*
@@ -127,14 +146,7 @@ void kbasep_kinstr_jm_atom_state(
* shouldn't be changed externally, but if you do, make sure you use
* a static_key_inc()/static_key_dec() pair.
*/
-#if KERNEL_VERSION(4, 3, 0) <= LINUX_VERSION_CODE
extern struct static_key_false basep_kinstr_jm_reader_static_key;
-#else
-/* Pre-4.3 kernels have a different API for static keys, but work
- * mostly the same with less type safety. */
-extern struct static_key basep_kinstr_jm_reader_static_key;
-#define static_branch_unlikely(key) static_key_false(key)
-#endif /* KERNEL_VERSION(4, 3, 0) <= LINUX_VERSION_CODE */
/**
* kbase_kinstr_jm_atom_state() - Signifies that an atom has changed state
diff --git a/mali_kbase/mali_kbase_kinstr_jm_reader.h b/mali_kbase/mali_kbase_kinstr_jm_reader.h
index e267e6b..1d2c141 100644
--- a/mali_kbase/mali_kbase_kinstr_jm_reader.h
+++ b/mali_kbase/mali_kbase_kinstr_jm_reader.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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.
+ *
*/
/*
diff --git a/mali_kbase/mali_kbase_linux.h b/mali_kbase/mali_kbase_linux.h
index 003ac9e..eb4ce77 100644
--- a/mali_kbase/mali_kbase_linux.h
+++ b/mali_kbase/mali_kbase_linux.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2014 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-2014, 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 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.
+ *
*/
-
-
/**
* @file mali_kbase_linux.h
* Base kernel APIs, Linux implementation.
diff --git a/mali_kbase/mali_kbase_mem.c b/mali_kbase/mali_kbase_mem.c
index 7ec6094..c054205 100644
--- a/mali_kbase/mali_kbase_mem.c
+++ b/mali_kbase/mali_kbase_mem.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
@@ -99,7 +100,8 @@ 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)
{
@@ -229,7 +231,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);
@@ -289,7 +291,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)) {
@@ -304,7 +307,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);
@@ -368,8 +372,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;
@@ -512,8 +517,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);
@@ -1293,8 +1298,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)
@@ -1320,7 +1325,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,
@@ -1379,13 +1386,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;
@@ -1399,7 +1399,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;
@@ -1424,10 +1423,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 =
@@ -1736,8 +1734,8 @@ 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);
+ KBASE_DEBUG_ASSERT(kctx != NULL);
+ KBASE_DEBUG_ASSERT(reg != NULL);
dev_dbg(kctx->kbdev->dev, "%s %p in kctx %p\n",
__func__, (void *)reg, (void *)kctx);
lockdep_assert_held(&kctx->reg_lock);
@@ -1803,7 +1801,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;
}
@@ -1856,7 +1854,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);
@@ -1988,7 +1986,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;
@@ -2392,7 +2391,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;
@@ -2640,8 +2639,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;
@@ -2692,7 +2693,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 */
@@ -2705,7 +2706,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;
@@ -2777,7 +2778,8 @@ bool kbase_check_alloc_flags(unsigned long flags)
#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;
@@ -2785,14 +2787,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;
@@ -2825,7 +2828,8 @@ bool kbase_check_import_flags(unsigned long flags)
#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;
@@ -2849,7 +2853,7 @@ int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags,
#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;
}
@@ -2861,7 +2865,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)) {
@@ -2916,7 +2921,8 @@ int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags,
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 */
+ * 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_extension)) {
@@ -4309,7 +4315,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,
@@ -4321,19 +4327,19 @@ 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);
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
+#elif KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE
pinned_pages = get_user_pages_remote(NULL, mm,
address,
alloc->imported.user_buf.nr_pages,
@@ -4525,7 +4531,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--;
@@ -4560,7 +4567,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/mali_kbase/mali_kbase_mem.h b/mali_kbase/mali_kbase_mem.h
index 7a5cc66..973fb7a 100644
--- a/mali_kbase/mali_kbase_mem.h
+++ b/mali_kbase/mali_kbase_mem.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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.
+ *
*/
-
-
/**
* @file mali_kbase_mem.h
* Base kernel memory APIs
@@ -48,10 +65,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 */
@@ -81,7 +101,8 @@ 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 */
@@ -105,7 +126,9 @@ 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.
* @nents: 0..N
* @pages: N elements, only 0..nents are valid
* @mappings: List of CPU mappings of this physical memory allocation.
@@ -211,7 +234,7 @@ 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();
}
@@ -342,7 +365,8 @@ struct kbase_va_region {
#if !MALI_USE_CSF
/* The top of the initial commit is aligned to extension pages.
- * Extent must be a power of 2 */
+ * Extent must be a power of 2
+ */
#define KBASE_REG_TILER_ALIGN_TOP (1ul << 23)
#else
/* Bit 23 is reserved.
@@ -1400,7 +1424,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 {
diff --git a/mali_kbase/mali_kbase_mem_linux.c b/mali_kbase/mali_kbase_mem_linux.c
index f6d386f..553b8fd 100644
--- a/mali_kbase/mali_kbase_mem_linux.c
+++ b/mali_kbase/mali_kbase_mem_linux.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
@@ -20,8 +21,6 @@
*
*/
-
-
/**
* @file mali_kbase_mem_linux.c
* Base kernel memory APIs, Linux implementation.
@@ -35,10 +34,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>
@@ -51,6 +49,7 @@
#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))
@@ -416,7 +415,8 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx,
if (*flags & BASE_MEM_GROW_ON_GPF) {
/* kbase_check_alloc_sizes() already checks extension is valid for
- * assigning to reg->extension */
+ * assigning to reg->extension
+ */
reg->extension = extension;
#if !MALI_USE_CSF
} else if (*flags & BASE_MEM_TILER_ALIGN_TOP) {
@@ -726,35 +726,18 @@ 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
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;
}
@@ -932,7 +915,12 @@ 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(&reg->cpu_alloc->gpu_mappings) > 1)
goto out_unlock;
@@ -1633,21 +1621,21 @@ static struct kbase_va_region *kbase_mem_from_user_buffer(
down_read(kbase_mem_get_process_mmap_lock());
-#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,
+ reg->flags & KBASE_REG_CPU_WR ? FOLL_WRITE : 0,
pages, NULL);
#else
- reg->flags & KBASE_REG_GPU_WR, 0, pages, NULL);
+ reg->flags & KBASE_REG_CPU_WR, 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);
+ reg->flags & KBASE_REG_CPU_WR, 0, pages, NULL);
#else
faulted_pages = get_user_pages(address, *va_pages,
- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
+ reg->flags & KBASE_REG_CPU_WR ? FOLL_WRITE : 0,
pages, NULL);
#endif
@@ -1759,7 +1747,8 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride,
#ifdef 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,
@@ -1805,7 +1794,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;
@@ -1820,6 +1810,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)
@@ -1827,16 +1826,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;
@@ -1849,6 +1850,18 @@ 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);
}
}
@@ -1892,6 +1905,10 @@ 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:
@@ -2145,7 +2162,15 @@ int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages)
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(&reg->gpu_alloc->gpu_mappings) > 1)
goto out_unlock;
/* can't grow regions which are ephemeral */
@@ -2447,11 +2472,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;
@@ -2632,7 +2653,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;
}
@@ -2698,7 +2720,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;
}
@@ -2719,7 +2741,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();
@@ -2736,7 +2759,7 @@ 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, &reg, &kaddr);
- if (0 != err)
+ if (err != 0)
goto out_unlock;
/* free the region on munmap */
free_on_close = 1;
@@ -2759,7 +2782,7 @@ int kbase_context_mmap(struct kbase_context *const kctx,
PFN_DOWN(BASE_MEM_FIRST_FREE_ADDRESS) - 1: {
err = kbasep_reg_mmap(kctx, vma, &reg, &nr_pages,
&aligned_offset);
- if (0 != err)
+ if (err != 0)
goto out_unlock;
/* free the region on munmap */
free_on_close = 1;
@@ -2832,7 +2855,8 @@ 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
@@ -2940,7 +2964,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);
@@ -3017,7 +3042,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);
@@ -3049,7 +3075,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
@@ -3133,11 +3159,7 @@ 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;
-#else
- vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO;
-#endif
vma->vm_ops = &kbase_vm_special_ops;
vma->vm_private_data = kctx;
@@ -3172,16 +3194,32 @@ 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);
}
@@ -3316,11 +3354,7 @@ static int kbase_csf_cpu_mmap_user_io_pages(struct kbase_context *kctx,
if (err)
goto map_failed;
-#if (KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE)
vma->vm_flags |= VM_DONTCOPY | VM_DONTDUMP | VM_DONTEXPAND | VM_IO;
-#else
- vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO;
-#endif
/* 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
@@ -3343,7 +3377,13 @@ static int kbase_csf_cpu_mmap_user_io_pages(struct kbase_context *kctx,
return 0;
map_failed:
- kbase_csf_queue_unbind(queue);
+ /* 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;
}
diff --git a/mali_kbase/mali_kbase_mem_linux.h b/mali_kbase/mali_kbase_mem_linux.h
index c80d885..c96498f 100644
--- a/mali_kbase/mali_kbase_mem_linux.h
+++ b/mali_kbase/mali_kbase_mem_linux.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010, 2012-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010, 2012-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 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.
+ *
*/
-
-
/**
* @file mali_kbase_mem_linux.h
* Base kernel memory APIs, Linux implementation.
@@ -468,11 +485,11 @@ static inline vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma,
*/
static inline struct rw_semaphore *kbase_mem_get_process_mmap_lock(void)
{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
+#if KERNEL_VERSION(5, 8, 0) > LINUX_VERSION_CODE
return &current->mm->mmap_sem;
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) */
+#else /* KERNEL_VERSION(5, 8, 0) > LINUX_VERSION_CODE */
return &current->mm->mmap_lock;
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0) */
+#endif /* KERNEL_VERSION(5, 8, 0) > LINUX_VERSION_CODE */
}
#endif /* _KBASE_MEM_LINUX_H_ */
diff --git a/mali_kbase/mali_kbase_mem_lowlevel.h b/mali_kbase/mali_kbase_mem_lowlevel.h
index 7011603..96a0b66 100644
--- a/mali_kbase/mali_kbase_mem_lowlevel.h
+++ b/mali_kbase/mali_kbase_mem_lowlevel.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2014,2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-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 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_MEM_LOWLEVEL_H
#define _KBASE_MEM_LOWLEVEL_H
diff --git a/mali_kbase/mali_kbase_mem_pool.c b/mali_kbase/mali_kbase_mem_pool.c
index 0723e32..c075727 100644
--- a/mali_kbase/mali_kbase_mem_pool.c
+++ b/mali_kbase/mali_kbase_mem_pool.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2015-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2015-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
@@ -154,20 +155,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;
@@ -364,17 +357,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 +380,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");
diff --git a/mali_kbase/mali_kbase_mem_pool_debugfs.c b/mali_kbase/mali_kbase_mem_pool_debugfs.c
index 5879fdf..3ed0d1a 100644
--- a/mali_kbase/mali_kbase_mem_pool_debugfs.c
+++ b/mali_kbase/mali_kbase_mem_pool_debugfs.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2014-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-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
diff --git a/mali_kbase/mali_kbase_mem_pool_debugfs.h b/mali_kbase/mali_kbase_mem_pool_debugfs.h
index 2932945..32dd843 100644
--- a/mali_kbase/mali_kbase_mem_pool_debugfs.h
+++ b/mali_kbase/mali_kbase_mem_pool_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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_MEM_POOL_DEBUGFS_H_
diff --git a/mali_kbase/mali_kbase_mem_pool_group.c b/mali_kbase/mali_kbase_mem_pool_group.c
index aa25548..5d6269e 100644
--- a/mali_kbase/mali_kbase_mem_pool_group.c
+++ b/mali_kbase/mali_kbase_mem_pool_group.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
diff --git a/mali_kbase/mali_kbase_mem_pool_group.h b/mali_kbase/mali_kbase_mem_pool_group.h
index 0484f59..4b50155 100644
--- a/mali_kbase/mali_kbase_mem_pool_group.h
+++ b/mali_kbase/mali_kbase_mem_pool_group.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_MEM_POOL_GROUP_H_
diff --git a/mali_kbase/mali_kbase_mem_profile_debugfs.c b/mali_kbase/mali_kbase_mem_profile_debugfs.c
index 85723f8..72b4633 100644
--- a/mali_kbase/mali_kbase_mem_profile_debugfs.c
+++ b/mali_kbase/mali_kbase_mem_profile_debugfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2012-2017, 2019-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mali_kbase_mem_profile_debugfs.h b/mali_kbase/mali_kbase_mem_profile_debugfs.h
index 1462247..04e593f 100644
--- a/mali_kbase/mali_kbase_mem_profile_debugfs.h
+++ b/mali_kbase/mali_kbase_mem_profile_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-2016, 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 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.
+ *
*/
-
-
/**
* @file mali_kbase_mem_profile_debugfs.h
* Header file for mem profiles entries in debugfs
diff --git a/mali_kbase/mali_kbase_mem_profile_debugfs_buf_size.h b/mali_kbase/mali_kbase_mem_profile_debugfs_buf_size.h
index d55cc85..9f530ca 100644
--- a/mali_kbase/mali_kbase_mem_profile_debugfs_buf_size.h
+++ b/mali_kbase/mali_kbase_mem_profile_debugfs_buf_size.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2018-2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 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 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.
+ *
*/
/**
diff --git a/mali_kbase/mali_kbase_mipe_gen_header.h b/mali_kbase/mali_kbase_mipe_gen_header.h
index 72acadf..669f843 100644
--- a/mali_kbase/mali_kbase_mipe_gen_header.h
+++ b/mali_kbase/mali_kbase_mipe_gen_header.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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 FILE IS AUTOGENERATED BY mali_trace_generator.py.
@@ -59,6 +78,17 @@
#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.
*
* See enum tl_stream_id.
@@ -151,7 +181,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 { \
@@ -161,13 +191,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/mali_kbase/mali_kbase_mipe_proto.h b/mali_kbase/mali_kbase_mipe_proto.h
index 54667cf..5202bf6 100644
--- a/mali_kbase/mali_kbase_mipe_proto.h
+++ b/mali_kbase/mali_kbase_mipe_proto.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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 FILE IS AUTOGENERATED BY mali_trace_generator.py.
diff --git a/mali_kbase/mali_kbase_native_mgm.c b/mali_kbase/mali_kbase_native_mgm.c
index 38ae46e..a3417a1 100644
--- a/mali_kbase/mali_kbase_native_mgm.c
+++ b/mali_kbase/mali_kbase_native_mgm.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
diff --git a/mali_kbase/mali_kbase_native_mgm.h b/mali_kbase/mali_kbase_native_mgm.h
index 431b1f4..4d43ea4 100644
--- a/mali_kbase/mali_kbase_native_mgm.h
+++ b/mali_kbase/mali_kbase_native_mgm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_NATIVE_MGM_H_
diff --git a/mali_kbase/mali_kbase_platform_fake.c b/mali_kbase/mali_kbase_platform_fake.c
index fbb090e..c3f85b5 100644
--- a/mali_kbase/mali_kbase_platform_fake.c
+++ b/mali_kbase/mali_kbase_platform_fake.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2011-2014, 2016-2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-2014, 2016-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
diff --git a/mali_kbase/mali_kbase_pm.c b/mali_kbase/mali_kbase_pm.c
index 630ab15..0edf4b6 100644
--- a/mali_kbase/mali_kbase_pm.c
+++ b/mali_kbase/mali_kbase_pm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
@@ -20,8 +21,6 @@
*
*/
-
-
/**
* @file mali_kbase_pm.c
* Base kernel power management APIs
@@ -191,7 +190,8 @@ void kbase_pm_driver_suspend(struct kbase_device *kbdev)
#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);
diff --git a/mali_kbase/mali_kbase_pm.h b/mali_kbase/mali_kbase_pm.h
index 1356518..8cc6625 100644
--- a/mali_kbase/mali_kbase_pm.h
+++ b/mali_kbase/mali_kbase_pm.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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.
+ *
*/
-
-
/**
* @file mali_kbase_pm.h
* Power management API definitions
diff --git a/mali_kbase/mali_kbase_regs_history_debugfs.c b/mali_kbase/mali_kbase_regs_history_debugfs.c
index 640db95..1cc7b29 100644
--- a/mali_kbase/mali_kbase_regs_history_debugfs.c
+++ b/mali_kbase/mali_kbase_regs_history_debugfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014, 2016, 2019-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mali_kbase_regs_history_debugfs.h b/mali_kbase/mali_kbase_regs_history_debugfs.h
index b043bd6..0d5ce9b 100644
--- a/mali_kbase/mali_kbase_regs_history_debugfs.h
+++ b/mali_kbase/mali_kbase_regs_history_debugfs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2016, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 2016, 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 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.
+ *
*/
/**
diff --git a/mali_kbase/mali_kbase_reset_gpu.h b/mali_kbase/mali_kbase_reset_gpu.h
index 61bbb0b..a1b75bf 100644
--- a/mali_kbase/mali_kbase_reset_gpu.h
+++ b/mali_kbase/mali_kbase_reset_gpu.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,12 +18,151 @@
*
* 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 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_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);
+
+/**
* kbase_prepare_to_reset_gpu_locked - Prepare for resetting the GPU.
* @kbdev: Device pointer
*
@@ -95,8 +234,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);
diff --git a/mali_kbase/mali_kbase_smc.c b/mali_kbase/mali_kbase_smc.c
index b5c7b12..e1b884d 100644
--- a/mali_kbase/mali_kbase_smc.c
+++ b/mali_kbase/mali_kbase_smc.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2015, 2018, 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mali_kbase_smc.h b/mali_kbase/mali_kbase_smc.h
index 221eb21..5c384e4 100644
--- a/mali_kbase/mali_kbase_smc.h
+++ b/mali_kbase/mali_kbase_smc.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2015, 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 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_SMC_H_
#define _KBASE_SMC_H_
diff --git a/mali_kbase/mali_kbase_softjobs.c b/mali_kbase/mali_kbase_softjobs.c
index 0dc8c03..77e5b91 100644
--- a/mali_kbase/mali_kbase_softjobs.c
+++ b/mali_kbase/mali_kbase_softjobs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
@@ -20,8 +21,6 @@
*
*/
-
-
#include <mali_kbase.h>
#include <linux/dma-buf.h>
@@ -148,7 +147,8 @@ 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
+ */
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;
@@ -183,7 +183,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;
@@ -715,7 +716,8 @@ 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);
@@ -723,7 +725,7 @@ out_cleanup:
}
#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)
{
@@ -804,16 +806,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
@@ -825,7 +827,7 @@ 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);
@@ -835,10 +837,10 @@ int kbase_mem_copy_from_extres(struct kbase_context *kctx,
}
}
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:
@@ -926,11 +928,6 @@ int kbasep_jit_alloc_validate(struct kbase_context *kctx,
#if !MALI_USE_CSF
-#if (KERNEL_VERSION(3, 18, 63) > LINUX_VERSION_CODE)
-#define offsetofend(TYPE, MEMBER) \
- (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER))
-#endif
-
/*
* Sizes of user data to copy for each just-in-time memory interface version
*
@@ -1654,7 +1651,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,
@@ -1663,7 +1662,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;
@@ -1676,7 +1676,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 */
diff --git a/mali_kbase/mali_kbase_strings.c b/mali_kbase/mali_kbase_strings.c
index 22caa4a..5413dae 100644
--- a/mali_kbase/mali_kbase_strings.c
+++ b/mali_kbase/mali_kbase_strings.c
@@ -1,6 +1,7 @@
- /*
+// SPDX-License-Identifier: GPL-2.0
+/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2016, 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
@@ -19,6 +20,7 @@
* SPDX-License-Identifier: GPL-2.0
*
*/
+
#include "mali_kbase_strings.h"
#define KBASE_DRV_NAME "mali"
diff --git a/mali_kbase/mali_kbase_strings.h b/mali_kbase/mali_kbase_strings.h
index d2f1825..56974a2 100644
--- a/mali_kbase/mali_kbase_strings.h
+++ b/mali_kbase/mali_kbase_strings.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-2016, 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 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.
+ *
*/
extern const char kbase_drv_name[];
diff --git a/mali_kbase/mali_kbase_sync.h b/mali_kbase/mali_kbase_sync.h
index d1921b7..f6426d8 100644
--- a/mali_kbase/mali_kbase_sync.h
+++ b/mali_kbase/mali_kbase_sync.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2016, 2018-2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-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 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.
+ *
*/
/**
@@ -165,7 +184,7 @@ 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(4, 17, 0) <= LINUX_VERSION_CODE
ksys_close(fd);
#else
sys_close(fd);
diff --git a/mali_kbase/mali_kbase_sync_android.c b/mali_kbase/mali_kbase_sync_android.c
index 75940fb..48945f1 100644
--- a/mali_kbase/mali_kbase_sync_android.c
+++ b/mali_kbase/mali_kbase_sync_android.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2012-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
@@ -50,15 +51,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 +188,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 +218,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 +248,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 +260,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 +277,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 +291,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 +350,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 +379,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 +423,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 +436,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 +504,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/mali_kbase/mali_kbase_sync_common.c b/mali_kbase/mali_kbase_sync_common.c
index 866894b..d509769 100644
--- a/mali_kbase/mali_kbase_sync_common.c
+++ b/mali_kbase/mali_kbase_sync_common.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2012-2016, 2018-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2012-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
diff --git a/mali_kbase/mali_kbase_sync_file.c b/mali_kbase/mali_kbase_sync_file.c
index 5020692..2be6699 100644
--- a/mali_kbase/mali_kbase_sync_file.c
+++ b/mali_kbase/mali_kbase_sync_file.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2012-2020 ARM Limited. All rights reserved.
@@ -62,7 +63,7 @@ int kbase_sync_fence_stream_create(const char *name, int *const out_fd)
#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;
@@ -107,7 +108,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);
@@ -124,7 +125,7 @@ int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd)
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);
@@ -160,7 +161,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
@@ -203,7 +204,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;
@@ -236,8 +237,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);
}
@@ -249,7 +250,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;
}
@@ -325,7 +327,7 @@ void kbase_sync_fence_info_get(struct dma_fence *fence,
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;
@@ -345,7 +347,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;
diff --git a/mali_kbase/mali_kbase_trace_gpu_mem.c b/mali_kbase/mali_kbase_trace_gpu_mem.c
index d0e9f0b..5cbe432 100644
--- a/mali_kbase/mali_kbase_trace_gpu_mem.c
+++ b/mali_kbase/mali_kbase_trace_gpu_mem.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
@@ -220,8 +221,3 @@ void kbase_add_dma_buf_usage(struct kbase_context *kctx,
mutex_unlock(&kbdev->dma_buf_lock);
}
-
-#if !defined(CONFIG_TRACE_GPU_MEM) && !MALI_CUSTOMER_RELEASE
-#define CREATE_TRACE_POINTS
-#include "mali_gpu_mem_trace.h"
-#endif
diff --git a/mali_kbase/mali_kbase_trace_gpu_mem.h b/mali_kbase/mali_kbase_trace_gpu_mem.h
index 7e95956..5b25139 100644
--- a/mali_kbase/mali_kbase_trace_gpu_mem.h
+++ b/mali_kbase/mali_kbase_trace_gpu_mem.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
@@ -25,8 +44,6 @@
#ifdef CONFIG_TRACE_GPU_MEM
#include <trace/events/gpu_mem.h>
-#elif !MALI_CUSTOMER_RELEASE
-#include "mali_gpu_mem_trace.h"
#endif
#define DEVICE_TGID ((u32) 0U)
@@ -34,9 +51,9 @@
static void kbase_trace_gpu_mem_usage(struct kbase_device *kbdev,
struct kbase_context *kctx)
{
+#ifdef CONFIG_TRACE_GPU_MEM
lockdep_assert_held(&kbdev->gpu_mem_usage_lock);
-#if defined(CONFIG_TRACE_GPU_MEM) || !MALI_CUSTOMER_RELEASE
trace_gpu_mem_total(kbdev->id, DEVICE_TGID,
kbdev->total_gpu_pages << PAGE_SHIFT);
diff --git a/mali_kbase/mali_kbase_utility.h b/mali_kbase/mali_kbase_utility.h
index 8d4f044..e8e928f 100644
--- a/mali_kbase/mali_kbase_utility.h
+++ b/mali_kbase/mali_kbase_utility.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2013, 2015, 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2012-2013, 2015, 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 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_UTILITY_H
#define _KBASE_UTILITY_H
@@ -32,7 +49,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/mali_kbase/mali_kbase_vinstr.c b/mali_kbase/mali_kbase_vinstr.c
index e0e828c..9b2ec6f 100644
--- a/mali_kbase/mali_kbase_vinstr.c
+++ b/mali_kbase/mali_kbase_vinstr.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved.
@@ -360,11 +361,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;
}
@@ -567,11 +564,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);
}
}
@@ -834,11 +828,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);
diff --git a/mali_kbase/mali_kbase_vinstr.h b/mali_kbase/mali_kbase_vinstr.h
index 81d315f..fafcd5a 100644
--- a/mali_kbase/mali_kbase_vinstr.h
+++ b/mali_kbase/mali_kbase_vinstr.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015-2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2015-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 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.
+ *
*/
/*
diff --git a/mali_kbase/mali_linux_trace.h b/mali_kbase/mali_linux_trace.h
index 4d2c972..e17cf26 100644
--- a/mali_kbase/mali_linux_trace.h
+++ b/mali_kbase/mali_linux_trace.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2016, 2018-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2011-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 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.
+ *
*/
#undef TRACE_SYSTEM
@@ -348,10 +367,7 @@ TRACE_EVENT(mali_jit_report,
#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_BASE
/* trace_mali_jit_report_pressure
*
diff --git a/mali_kbase/mali_malisw.h b/mali_kbase/mali_malisw.h
index 3a4db10..61ff7ae 100644
--- a/mali_kbase/mali_malisw.h
+++ b/mali_kbase/mali_malisw.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015, 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-2015, 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 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.
+ *
*/
/**
@@ -28,23 +47,6 @@
#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.
diff --git a/mali_kbase/mali_power_gpu_frequency_trace.c b/mali_kbase/mali_power_gpu_frequency_trace.c
index b6fb5a0..36fb9cf 100644
--- a/mali_kbase/mali_power_gpu_frequency_trace.c
+++ b/mali_kbase/mali_power_gpu_frequency_trace.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mali_power_gpu_frequency_trace.h b/mali_kbase/mali_power_gpu_frequency_trace.h
index 3b90ae4..b131d62 100644
--- a/mali_kbase/mali_power_gpu_frequency_trace.h
+++ b/mali_kbase/mali_power_gpu_frequency_trace.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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
diff --git a/mali_kbase/mali_uk.h b/mali_kbase/mali_uk.h
index 701f390..9c3e89b 100644
--- a/mali_kbase/mali_uk.h
+++ b/mali_kbase/mali_uk.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010, 2012-2015, 2018 ARM Limited. All rights reserved.
+ * (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
@@ -18,10 +18,27 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010, 2012-2015, 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 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.
+ *
*/
-
-
/**
* @file mali_uk.h
* Types and definitions that are common across OSs for both the user
diff --git a/mali_kbase/mmu/backend/mali_kbase_mmu_csf.c b/mali_kbase/mmu/backend/mali_kbase_mmu_csf.c
index b23d1ff..265e19a 100644
--- a/mali_kbase/mmu/backend/mali_kbase_mmu_csf.c
+++ b/mali_kbase/mmu/backend/mali_kbase_mmu_csf.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -69,17 +70,27 @@ void kbase_mmu_get_as_setup(struct kbase_mmu_table *mmut,
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;
- as->pf_data = (struct kbase_fault) {
- .status = fault->status,
- .addr = fault->addr,
- };
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ kctx = kbase_ctx_sched_as_to_ctx_nolock(kbdev, as_nr);
- if (kbase_ctx_sched_as_to_ctx_refcount(kbdev, as_nr)) {
- WARN_ON(!queue_work(as->pf_wq, &as->work_pagefault));
- atomic_inc(&kbdev->faults_pending);
+ if (kctx) {
+ kbase_ctx_sched_retain_ctx_refcount(kctx);
+
+ as->pf_data = (struct kbase_fault) {
+ .status = fault->status,
+ .addr = fault->addr,
+ };
+
+ if (WARN_ON(!queue_work(as->pf_wq, &as->work_pagefault)))
+ kbase_ctx_sched_release_ctx(kctx);
+ else
+ 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,
@@ -106,8 +117,14 @@ void kbase_mmu_report_mcu_as_fault_and_reset(struct kbase_device *kbdev,
/* Report MMU fault for all address spaces (except MCU_AS_NR) */
for (as_no = 1; as_no < kbdev->nr_hw_address_spaces; as_no++)
- if (kbase_ctx_sched_as_to_ctx(kbdev, as_no))
- submit_work_pagefault(kbdev, as_no, fault);
+ submit_work_pagefault(kbdev, as_no, fault);
+
+ /* MCU AS fault could mean hardware counters will stop working.
+ * Put the backend into the unrecoverable error state to cause
+ * current and subsequent counter operations to immediately
+ * fail, avoiding the risk of a hang.
+ */
+ kbase_hwcnt_backend_csf_on_unrecoverable_error(&kbdev->hwcnt_gpu_iface);
/* GPU reset is required to recover */
if (kbase_prepare_to_reset_gpu(kbdev))
@@ -482,18 +499,25 @@ static void submit_work_gpufault(struct kbase_device *kbdev, u32 status,
{
unsigned long flags;
struct kbase_as *const as = &kbdev->as[as_nr];
+ struct kbase_context *kctx;
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- as->gf_data = (struct kbase_fault) {
+ 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,
- };
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+ };
- if (kbase_ctx_sched_as_to_ctx_refcount(kbdev, as_nr)) {
- WARN_ON(!queue_work(as->pf_wq, &as->work_gpufault));
- atomic_inc(&kbdev->faults_pending);
+ 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,
diff --git a/mali_kbase/mmu/backend/mali_kbase_mmu_jm.c b/mali_kbase/mmu/backend/mali_kbase_mmu_jm.c
index b0187a4..ddb3fd2 100644
--- a/mali_kbase/mmu/backend/mali_kbase_mmu_jm.c
+++ b/mali_kbase/mmu/backend/mali_kbase_mmu_jm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mmu/mali_kbase_mmu.c b/mali_kbase/mmu/mali_kbase_mmu.c
index cb57dc9..402f024 100644
--- a/mali_kbase/mmu/mali_kbase_mmu.c
+++ b/mali_kbase/mmu/mali_kbase_mmu.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
@@ -1616,6 +1617,16 @@ static void kbase_mmu_flush_invalidate_as(struct kbase_device *kbdev,
*/
dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issueing GPU soft-reset to recover\n");
+#if MALI_USE_CSF
+ /* A GPU hang could mean hardware counters will stop working.
+ * Put the backend into the unrecoverable error state to cause
+ * current and subsequent counter operations to immediately
+ * fail, avoiding the risk of a hang.
+ */
+ kbase_hwcnt_backend_csf_on_unrecoverable_error(
+ &kbdev->hwcnt_gpu_iface);
+#endif /* MALI_USE_CSF */
+
if (kbase_prepare_to_reset_gpu(kbdev))
kbase_reset_gpu(kbdev);
}
@@ -1649,10 +1660,10 @@ static void kbase_mmu_flush_invalidate(struct kbase_context *kctx,
kbdev = kctx->kbdev;
#if !MALI_USE_CSF
mutex_lock(&kbdev->js_data.queue_mutex);
-#endif /* !MALI_USE_CSF */
ctx_is_in_runpool = kbase_ctx_sched_inc_refcount(kctx);
-#if !MALI_USE_CSF
mutex_unlock(&kbdev->js_data.queue_mutex);
+#else
+ ctx_is_in_runpool = kbase_ctx_sched_refcount_mmu_flush(kctx, sync);
#endif /* !MALI_USE_CSF */
if (ctx_is_in_runpool) {
@@ -1674,6 +1685,11 @@ void kbase_mmu_update(struct kbase_device *kbdev,
KBASE_DEBUG_ASSERT(as_nr != KBASEP_AS_NR_INVALID);
kbdev->mmu_mode->update(kbdev, mmut, as_nr);
+
+#if MALI_USE_CSF
+ if (mmut->kctx)
+ mmut->kctx->mmu_flush_pend_state = KCTX_MMU_FLUSH_NOT_PEND;
+#endif
}
KBASE_EXPORT_TEST_API(kbase_mmu_update);
@@ -1695,6 +1711,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
@@ -1706,6 +1723,10 @@ void kbase_mmu_disable(struct kbase_context *kctx)
kbase_mmu_flush_invalidate_noretain(kctx, 0, ~0, true);
kctx->kbdev->mmu_mode->disable_as(kctx->kbdev, kctx->as_nr);
+
+#if MALI_USE_CSF
+ kctx->mmu_flush_pend_state = KCTX_MMU_FLUSH_NOT_PEND;
+#endif
}
KBASE_EXPORT_TEST_API(kbase_mmu_disable);
@@ -2295,3 +2316,30 @@ void kbase_flush_mmu_wqs(struct kbase_device *kbdev)
flush_workqueue(as->pf_wq);
}
}
+
+#if MALI_USE_CSF
+void kbase_mmu_deferred_flush_invalidate(struct kbase_context *kctx)
+{
+ struct kbase_device *kbdev = kctx->kbdev;
+
+ lockdep_assert_held(&kbdev->mmu_hw_mutex);
+
+ if (kctx->as_nr == KBASEP_AS_NR_INVALID)
+ return;
+
+ if (kctx->mmu_flush_pend_state == KCTX_MMU_FLUSH_NOT_PEND)
+ return;
+
+ WARN_ON(!atomic_read(&kctx->refcount));
+
+ /* Specify the entire address space as the locked region.
+ * The flush of entire L2 cache and complete TLB invalidation will
+ * anyways happen for the exisiting CSF GPUs, regardless of the locked
+ * range. This may have to be revised later on.
+ */
+ kbase_mmu_flush_invalidate_noretain(kctx, 0, ~0,
+ kctx->mmu_flush_pend_state == KCTX_MMU_FLUSH_PEND_SYNC);
+
+ kctx->mmu_flush_pend_state = KCTX_MMU_FLUSH_NOT_PEND;
+}
+#endif
diff --git a/mali_kbase/mmu/mali_kbase_mmu.h b/mali_kbase/mmu/mali_kbase_mmu.h
index f2613e8..ba525e7 100644
--- a/mali_kbase/mmu/mali_kbase_mmu.h
+++ b/mali_kbase/mmu/mali_kbase_mmu.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_MMU_H_
@@ -153,4 +172,21 @@ int kbase_mmu_bus_fault_interrupt(struct kbase_device *kbdev, u32 status,
void kbase_mmu_gpu_fault_interrupt(struct kbase_device *kbdev, u32 status,
u32 as_nr, u64 address, bool as_valid);
+#if MALI_USE_CSF
+/**
+ * kbase_mmu_deferred_flush_invalidate() - Perform deferred MMU flush
+ * operations for a Kbase context.
+ * @kctx: Pointer to the Kbase context for which MMU flush operations
+ * are pending.
+ *
+ * This function performs the MMU flush operations that are pending for a Kbase
+ * context. The flush operations will be deferred if the context is inactive,
+ * i.e. kctx->refcount is zero which happens when all the queue groups of a
+ * context have gone off CSG slots.
+ * This needs to be called when first queue group of the context is put back
+ * on the CSG slot.
+ */
+void kbase_mmu_deferred_flush_invalidate(struct kbase_context *kctx);
+#endif
+
#endif /* _KBASE_MMU_H_ */
diff --git a/mali_kbase/mmu/mali_kbase_mmu_hw.h b/mali_kbase/mmu/mali_kbase_mmu_hw.h
index e6eef86..bc7561d 100644
--- a/mali_kbase/mmu/mali_kbase_mmu_hw.h
+++ b/mali_kbase/mmu/mali_kbase_mmu_hw.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015, 2018-2019 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-2015, 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 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.
+ *
*/
/**
diff --git a/mali_kbase/mmu/mali_kbase_mmu_hw_direct.c b/mali_kbase/mmu/mali_kbase_mmu_hw_direct.c
index e9eef8b..78d84ad 100644
--- a/mali_kbase/mmu/mali_kbase_mmu_hw_direct.c
+++ b/mali_kbase/mmu/mali_kbase_mmu_hw_direct.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/mmu/mali_kbase_mmu_internal.h b/mali_kbase/mmu/mali_kbase_mmu_internal.h
index 8ecb14d..cc47c91 100644
--- a/mali_kbase/mmu/mali_kbase_mmu_internal.h
+++ b/mali_kbase/mmu/mali_kbase_mmu_internal.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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_MMU_INTERNAL_H_
diff --git a/mali_kbase/mmu/mali_kbase_mmu_mode_aarch64.c b/mali_kbase/mmu/mali_kbase_mmu_mode_aarch64.c
index 02493e9..f705663 100644
--- a/mali_kbase/mmu/mali_kbase_mmu_mode_aarch64.c
+++ b/mali_kbase/mmu/mali_kbase_mmu_mode_aarch64.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2010-2014, 2016-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2014, 2016-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
@@ -48,25 +49,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/mali_kbase/mmu/mali_kbase_mmu_mode_lpae.c b/mali_kbase/mmu/mali_kbase_mmu_mode_lpae.c
index 91a2d7a..b98d64e 100644
--- a/mali_kbase/mmu/mali_kbase_mmu_mode_lpae.c
+++ b/mali_kbase/mmu/mali_kbase_mmu_mode_lpae.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2010-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-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
@@ -20,7 +21,6 @@
*
*/
-
#include "mali_kbase.h"
#include <gpu/mali_kbase_gpu_regmap.h>
#include "mali_kbase_defs.h"
@@ -45,25 +45,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_get_as_setup(struct kbase_mmu_table *mmut,
diff --git a/mali_kbase/platform/Kconfig b/mali_kbase/platform/Kconfig
index ef9fb96..d5477b2 100644
--- a/mali_kbase/platform/Kconfig
+++ b/mali_kbase/platform/Kconfig
@@ -19,12 +19,9 @@
#
#
-
-
# Add your platform specific Kconfig file here
#
# "drivers/gpu/arm/midgard/platform/xxx/Kconfig"
#
# Where xxx is the platform name is the name set in MALI_PLATFORM_NAME
#
-
diff --git a/mali_kbase/platform/devicetree/mali_kbase_clk_rate_trace.c b/mali_kbase/platform/devicetree/mali_kbase_clk_rate_trace.c
index 47933a7..080514c 100644
--- a/mali_kbase/platform/devicetree/mali_kbase_clk_rate_trace.c
+++ b/mali_kbase/platform/devicetree/mali_kbase_clk_rate_trace.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2015, 2017-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/platform/devicetree/mali_kbase_config_devicetree.c b/mali_kbase/platform/devicetree/mali_kbase_config_devicetree.c
index ccefddf..df82806 100644
--- a/mali_kbase/platform/devicetree/mali_kbase_config_devicetree.c
+++ b/mali_kbase/platform/devicetree/mali_kbase_config_devicetree.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2015, 2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2015, 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
diff --git a/mali_kbase/platform/devicetree/mali_kbase_config_platform.h b/mali_kbase/platform/devicetree/mali_kbase_config_platform.h
index 2137b42..f16c9bc 100644
--- a/mali_kbase/platform/devicetree/mali_kbase_config_platform.h
+++ b/mali_kbase/platform/devicetree/mali_kbase_config_platform.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2017, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
/**
diff --git a/mali_kbase/platform/devicetree/mali_kbase_runtime_pm.c b/mali_kbase/platform/devicetree/mali_kbase_runtime_pm.c
index 8772edb..72639b5 100644
--- a/mali_kbase/platform/devicetree/mali_kbase_runtime_pm.c
+++ b/mali_kbase/platform/devicetree/mali_kbase_runtime_pm.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2015, 2017-2019 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2015-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
diff --git a/mali_kbase/platform/vexpress/Kbuild b/mali_kbase/platform/vexpress/Kbuild
index 6780e4c..bcd3167 100644
--- a/mali_kbase/platform/vexpress/Kbuild
+++ b/mali_kbase/platform/vexpress/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2012-2013, 2016-2017 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2012-2013, 2016-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
diff --git a/mali_kbase/platform/vexpress/mali_kbase_config_platform.h b/mali_kbase/platform/vexpress/mali_kbase_config_platform.h
index fac3cd5..a9988ae 100644
--- a/mali_kbase/platform/vexpress/mali_kbase_config_platform.h
+++ b/mali_kbase/platform/vexpress/mali_kbase_config_platform.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
/**
diff --git a/mali_kbase/platform/vexpress/mali_kbase_config_vexpress.c b/mali_kbase/platform/vexpress/mali_kbase_config_vexpress.c
index d165ce2..d02ca3f 100644
--- a/mali_kbase/platform/vexpress/mali_kbase_config_vexpress.c
+++ b/mali_kbase/platform/vexpress/mali_kbase_config_vexpress.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-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
@@ -20,8 +21,6 @@
*
*/
-
-
#include <linux/ioport.h>
#include <mali_kbase.h>
#include <mali_kbase_defs.h>
diff --git a/mali_kbase/platform/vexpress_1xv7_a57/Kbuild b/mali_kbase/platform/vexpress_1xv7_a57/Kbuild
index 51b408e..ae03670 100644
--- a/mali_kbase/platform/vexpress_1xv7_a57/Kbuild
+++ b/mali_kbase/platform/vexpress_1xv7_a57/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2013-2014, 2016-2017 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2013-2014, 2016-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
diff --git a/mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h b/mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h
index fac3cd5..a9988ae 100644
--- a/mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h
+++ b/mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_platform.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
/**
diff --git a/mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c b/mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c
index efca0a5..6d6aaf6 100644
--- a/mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c
+++ b/mali_kbase/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2011-2014, 2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-2014, 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
diff --git a/mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h b/mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h
index fac3cd5..a9988ae 100644
--- a/mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h
+++ b/mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_platform.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014-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 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.
+ *
*/
/**
diff --git a/mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c b/mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c
index b6714b9..c3fbf21 100644
--- a/mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c
+++ b/mali_kbase/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2011-2014, 2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-2014, 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
@@ -20,8 +21,6 @@
*
*/
-
-
#include <linux/ioport.h>
#include <mali_kbase.h>
#include <mali_kbase_defs.h>
diff --git a/mali_kbase/protected_mode_switcher.h b/mali_kbase/protected_mode_switcher.h
index 8778d81..bde31ec 100644
--- a/mali_kbase/protected_mode_switcher.h
+++ b/mali_kbase/protected_mode_switcher.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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 _PROTECTED_MODE_SWITCH_H_
diff --git a/mali_kbase/tests/Mconfig b/mali_kbase/tests/Mconfig
index be3fedb..cdbbaac 100644
--- a/mali_kbase/tests/Mconfig
+++ b/mali_kbase/tests/Mconfig
@@ -1,14 +1,21 @@
+# SPDX-License-Identifier: GPL-2.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.
+# of such 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
diff --git a/mali_kbase/tests/include/kutf/kutf_helpers.h b/mali_kbase/tests/include/kutf/kutf_helpers.h
index 858b9c3..ea87f9c 100644
--- a/mali_kbase/tests/include/kutf/kutf_helpers.h
+++ b/mali_kbase/tests/include/kutf/kutf_helpers.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2017, 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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 _KERNEL_UTF_HELPERS_H_
diff --git a/mali_kbase/tests/include/kutf/kutf_helpers_user.h b/mali_kbase/tests/include/kutf/kutf_helpers_user.h
index 3b1300e..38f36fc 100644
--- a/mali_kbase/tests/include/kutf/kutf_helpers_user.h
+++ b/mali_kbase/tests/include/kutf/kutf_helpers_user.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.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 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 _KERNEL_UTF_HELPERS_USER_H_
@@ -63,7 +82,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 +91,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 +144,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 +161,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 +189,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/mali_kbase/tests/include/kutf/kutf_mem.h b/mali_kbase/tests/include/kutf/kutf_mem.h
index 988559d..8a0e855 100644
--- a/mali_kbase/tests/include/kutf/kutf_mem.h
+++ b/mali_kbase/tests/include/kutf/kutf_mem.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 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 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 _KERNEL_UTF_MEM_H_
diff --git a/mali_kbase/tests/include/kutf/kutf_resultset.h b/mali_kbase/tests/include/kutf/kutf_resultset.h
index 49ebeb4..f21de19 100644
--- a/mali_kbase/tests/include/kutf/kutf_resultset.h
+++ b/mali_kbase/tests/include/kutf/kutf_resultset.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 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 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 _KERNEL_UTF_RESULTSET_H_
diff --git a/mali_kbase/tests/include/kutf/kutf_suite.h b/mali_kbase/tests/include/kutf/kutf_suite.h
index 8d75f50..f4af4fa 100644
--- a/mali_kbase/tests/include/kutf/kutf_suite.h
+++ b/mali_kbase/tests/include/kutf/kutf_suite.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 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 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 _KERNEL_UTF_SUITE_H_
@@ -264,9 +283,10 @@ struct kutf_suite {
struct list_head test_list;
};
-/* ============================================================================
- Application functions
-============================================================================ */
+/** ===========================================================================
+ * Application functions
+ * ============================================================================
+ */
/**
* kutf_create_application() - Create an in kernel test application.
@@ -284,9 +304,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 +437,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/mali_kbase/tests/include/kutf/kutf_utils.h b/mali_kbase/tests/include/kutf/kutf_utils.h
index 25b8285..a60e569 100644
--- a/mali_kbase/tests/include/kutf/kutf_utils.h
+++ b/mali_kbase/tests/include/kutf/kutf_utils.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2014, 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 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 _KERNEL_UTF_UTILS_H_
diff --git a/mali_kbase/tests/kutf/Kbuild b/mali_kbase/tests/kutf/Kbuild
index 2531d41..de68729 100644
--- a/mali_kbase/tests/kutf/Kbuild
+++ b/mali_kbase/tests/kutf/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+# (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
diff --git a/mali_kbase/tests/kutf/Kconfig b/mali_kbase/tests/kutf/Kconfig
index 0cdb474..3d1f92d 100644
--- a/mali_kbase/tests/kutf/Kconfig
+++ b/mali_kbase/tests/kutf/Kconfig
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+# (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
@@ -19,7 +19,6 @@
#
#
-
config MALI_KUTF
tristate "Mali Kernel Unit Test Framework"
default m
diff --git a/mali_kbase/tests/kutf/Makefile b/mali_kbase/tests/kutf/Makefile
index d848e87..b9e070b 100644
--- a/mali_kbase/tests/kutf/Makefile
+++ b/mali_kbase/tests/kutf/Makefile
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2014-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
diff --git a/mali_kbase/tests/kutf/build.bp b/mali_kbase/tests/kutf/build.bp
index 32eab14..707a053 100644
--- a/mali_kbase/tests/kutf/build.bp
+++ b/mali_kbase/tests/kutf/build.bp
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -5,11 +6,16 @@
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the 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.
*
*/
diff --git a/mali_kbase/tests/kutf/kutf_helpers.c b/mali_kbase/tests/kutf/kutf_helpers.c
index 4463b04..13b6353 100644
--- a/mali_kbase/tests/kutf/kutf_helpers.c
+++ b/mali_kbase/tests/kutf/kutf_helpers.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2017, 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/tests/kutf/kutf_helpers_user.c b/mali_kbase/tests/kutf/kutf_helpers_user.c
index 108fa82..00bc9c0 100644
--- a/mali_kbase/tests/kutf/kutf_helpers_user.c
+++ b/mali_kbase/tests/kutf/kutf_helpers_user.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ * (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
@@ -42,7 +43,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 +56,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 +90,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 +211,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 +223,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 +337,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 +406,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/mali_kbase/tests/kutf/kutf_mem.c b/mali_kbase/tests/kutf/kutf_mem.c
index fd98bea..88c2de8 100644
--- a/mali_kbase/tests/kutf/kutf_mem.c
+++ b/mali_kbase/tests/kutf/kutf_mem.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014, 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
diff --git a/mali_kbase/tests/kutf/kutf_resultset.c b/mali_kbase/tests/kutf/kutf_resultset.c
index 94ecfa4..ed6f02a 100644
--- a/mali_kbase/tests/kutf/kutf_resultset.c
+++ b/mali_kbase/tests/kutf/kutf_resultset.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014, 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
diff --git a/mali_kbase/tests/kutf/kutf_suite.c b/mali_kbase/tests/kutf/kutf_suite.c
index 9dc6e2b..382557b 100644
--- a/mali_kbase/tests/kutf/kutf_suite.c
+++ b/mali_kbase/tests/kutf/kutf_suite.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2014, 2017-2020 ARM Limited. All rights reserved.
@@ -21,7 +22,8 @@
*/
/* Kernel UTF suite, test and fixture management including user to kernel
- * interaction */
+ * interaction
+ */
#include <linux/list.h>
#include <linux/slab.h>
@@ -598,7 +600,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 +636,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 +681,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,7 +694,7 @@ void kutf_add_test_with_filters_and_data(
}
test_func->test_id = id;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0)
+#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE
debugfs_create_u32("test_id", S_IROTH, test_func->dir,
&test_func->test_id);
#else
diff --git a/mali_kbase/tests/kutf/kutf_utils.c b/mali_kbase/tests/kutf/kutf_utils.c
index 7f5ac51..7d1de25 100644
--- a/mali_kbase/tests/kutf/kutf_utils.c
+++ b/mali_kbase/tests/kutf/kutf_utils.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2014, 2017 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014, 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
diff --git a/mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/build.bp b/mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/build.bp
index 0cc2904..c16b3de 100644
--- a/mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/build.bp
+++ b/mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/build.bp
@@ -1,14 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
+ *
* (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.
+ * of such 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.
*/
bob_kernel_module {
diff --git a/mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c b/mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c
index d74a278..88dfef4 100644
--- a/mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c
+++ b/mali_kbase/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/tests/mali_kutf_clk_rate_trace/mali_kutf_clk_rate_trace_test.h b/mali_kbase/tests/mali_kutf_clk_rate_trace/mali_kutf_clk_rate_trace_test.h
index f46afd5..0b7b84d 100644
--- a/mali_kbase/tests/mali_kutf_clk_rate_trace/mali_kutf_clk_rate_trace_test.h
+++ b/mali_kbase/tests/mali_kutf_clk_rate_trace/mali_kutf_clk_rate_trace_test.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (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 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_
diff --git a/mali_kbase/tests/mali_kutf_irq_test/Kbuild b/mali_kbase/tests/mali_kutf_irq_test/Kbuild
index ca8c512..a1a4828 100644
--- a/mali_kbase/tests/mali_kutf_irq_test/Kbuild
+++ b/mali_kbase/tests/mali_kutf_irq_test/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+# (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
diff --git a/mali_kbase/tests/mali_kutf_irq_test/Kconfig b/mali_kbase/tests/mali_kutf_irq_test/Kconfig
index 4a3863a..c49ec11 100644
--- a/mali_kbase/tests/mali_kutf_irq_test/Kconfig
+++ b/mali_kbase/tests/mali_kutf_irq_test/Kconfig
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+# (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
diff --git a/mali_kbase/tests/mali_kutf_irq_test/build.bp b/mali_kbase/tests/mali_kutf_irq_test/build.bp
index 90efdcf..58021c8 100644
--- a/mali_kbase/tests/mali_kutf_irq_test/build.bp
+++ b/mali_kbase/tests/mali_kutf_irq_test/build.bp
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
*
* (C) COPYRIGHT 2018-2020 ARM Limited. All rights reserved.
@@ -5,11 +6,16 @@
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the 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.
*
*/
diff --git a/mali_kbase/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c b/mali_kbase/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c
index 5f27c3a..3c22004 100644
--- a/mali_kbase/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c
+++ b/mali_kbase/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2016-2018, 2020 ARM Limited. All rights reserved.
@@ -242,7 +243,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 +252,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/mali_kbase/thirdparty/mali_kbase_mmap.c b/mali_kbase/thirdparty/mali_kbase_mmap.c
index 83a293d..6201cfc 100644
--- a/mali_kbase/thirdparty/mali_kbase_mmap.c
+++ b/mali_kbase/thirdparty/mali_kbase_mmap.c
@@ -209,7 +209,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;
@@ -325,7 +326,8 @@ unsigned long kbase_context_get_unmapped_area(struct kbase_context *const kctx,
/* kbase_check_alloc_sizes() already satisfies
* these checks, but they're here to avoid
* maintenance hazards due to the assumptions
- * involved */
+ * involved
+ */
WARN_ON(reg->extension >
(ULONG_MAX >> PAGE_SHIFT));
WARN_ON(reg->initial_commit > (ULONG_MAX >> PAGE_SHIFT));
diff --git a/mali_kbase/tl/backend/mali_kbase_timeline_csf.c b/mali_kbase/tl/backend/mali_kbase_timeline_csf.c
index abaa6bb..476214d 100644
--- a/mali_kbase/tl/backend/mali_kbase_timeline_csf.c
+++ b/mali_kbase/tl/backend/mali_kbase_timeline_csf.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
@@ -60,7 +61,7 @@ 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);
/* Hold the scheduler lock while we emit the current state
* We also need to continue holding the lock until after the first body
@@ -90,7 +91,7 @@ void kbase_create_timeline_objects(struct kbase_device *kbdev)
mutex_unlock(&kbdev->csf.scheduler.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) {
size_t i;
struct kbase_tlstream *body =
&timeline->streams[TL_STREAM_TYPE_OBJ];
@@ -162,7 +163,7 @@ void kbase_create_timeline_objects(struct kbase_device *kbdev)
*/
};
- 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
diff --git a/mali_kbase/tl/backend/mali_kbase_timeline_jm.c b/mali_kbase/tl/backend/mali_kbase_timeline_jm.c
index c368ac7..4babd1e 100644
--- a/mali_kbase/tl/backend/mali_kbase_timeline_jm.c
+++ b/mali_kbase/tl/backend/mali_kbase_timeline_jm.c
@@ -1,6 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
- * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * (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
@@ -66,10 +67,10 @@ 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,
@@ -87,11 +88,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/mali_kbase/tl/mali_kbase_timeline.c b/mali_kbase/tl/mali_kbase_timeline.c
index 8ebc075..98185e9 100644
--- a/mali_kbase/tl/mali_kbase_timeline.c
+++ b/mali_kbase/tl/mali_kbase_timeline.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
@@ -116,7 +117,7 @@ int kbase_timeline_init(struct kbase_timeline **timeline,
if (!timeline || !timeline_flags)
return -EINVAL;
- result = kzalloc(sizeof(*result), GFP_KERNEL);
+ result = vzalloc(sizeof(*result));
if (!result)
return -ENOMEM;
@@ -128,6 +129,10 @@ 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,
@@ -154,10 +159,12 @@ void kbase_timeline_term(struct kbase_timeline *timeline)
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
@@ -172,11 +179,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);
}
@@ -288,6 +291,74 @@ void kbase_timeline_streams_body_reset(struct kbase_timeline *timeline)
#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
void kbase_timeline_stats(struct kbase_timeline *timeline,
u32 *bytes_collected, u32 *bytes_generated)
diff --git a/mali_kbase/tl/mali_kbase_timeline.h b/mali_kbase/tl/mali_kbase_timeline.h
index cd48411..ea75a69 100644
--- a/mali_kbase/tl/mali_kbase_timeline.h
+++ b/mali_kbase/tl/mali_kbase_timeline.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2015-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 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.
+ *
*/
#if !defined(_KBASE_TIMELINE_H)
@@ -81,6 +100,30 @@ void kbase_timeline_streams_flush(struct kbase_timeline *timeline);
*/
void kbase_timeline_streams_body_reset(struct kbase_timeline *timeline);
+/**
+ * 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
+ *
+ * Should be called immediately before the memory is freed, and the context ID
+ * and kbdev pointer should still be valid.
+ */
+void kbase_timeline_post_kbase_context_destroy(struct kbase_context *kctx);
+
#if MALI_UNIT_TEST
/**
* kbase_timeline_test - start timeline stream data generator
diff --git a/mali_kbase/tl/mali_kbase_timeline_io.c b/mali_kbase/tl/mali_kbase_timeline_io.c
index 724f5fa..a6d02b9 100644
--- a/mali_kbase/tl/mali_kbase_timeline_io.c
+++ b/mali_kbase/tl/mali_kbase_timeline_io.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
diff --git a/mali_kbase/tl/mali_kbase_timeline_priv.h b/mali_kbase/tl/mali_kbase_timeline_priv.h
index 35eec46..d305bb3 100644
--- a/mali_kbase/tl/mali_kbase_timeline_priv.h
+++ b/mali_kbase/tl/mali_kbase_timeline_priv.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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.
+ *
*/
#if !defined(_KBASE_TIMELINE_PRIV_H)
@@ -38,6 +57,8 @@
/**
* 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
@@ -51,6 +72,8 @@
*/
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;
diff --git a/mali_kbase/tl/mali_kbase_tl_serialize.h b/mali_kbase/tl/mali_kbase_tl_serialize.h
index 3e37827..78aee83 100644
--- a/mali_kbase/tl/mali_kbase_tl_serialize.h
+++ b/mali_kbase/tl/mali_kbase_tl_serialize.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* 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 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.
+ *
*/
#if !defined(_KBASE_TL_SERIALIZE_H)
diff --git a/mali_kbase/tl/mali_kbase_tlstream.c b/mali_kbase/tl/mali_kbase_tlstream.c
index f4239cf..b682ecd 100644
--- a/mali_kbase/tl/mali_kbase_tlstream.c
+++ b/mali_kbase/tl/mali_kbase_tlstream.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
@@ -149,12 +150,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;
@@ -217,7 +218,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);
@@ -251,7 +253,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;
diff --git a/mali_kbase/tl/mali_kbase_tlstream.h b/mali_kbase/tl/mali_kbase_tlstream.h
index faf88d6..4ad4ad1 100644
--- a/mali_kbase/tl/mali_kbase_tlstream.h
+++ b/mali_kbase/tl/mali_kbase_tlstream.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2015-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 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.
+ *
*/
#if !defined(_KBASE_TLSTREAM_H)
diff --git a/mali_kbase/tl/mali_kbase_tracepoints.c b/mali_kbase/tl/mali_kbase_tracepoints.c
index 0502c0d..9a2d7db 100644
--- a/mali_kbase/tl/mali_kbase_tracepoints.c
+++ b/mali_kbase/tl/mali_kbase_tracepoints.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
*
* (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
@@ -135,6 +136,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,
};
@@ -541,6 +543,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", \
@@ -1817,6 +1823,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,
diff --git a/mali_kbase/tl/mali_kbase_tracepoints.h b/mali_kbase/tl/mali_kbase_tracepoints.h
index 3cd94e2..844bdf4 100644
--- a/mali_kbase/tl/mali_kbase_tracepoints.h
+++ b/mali_kbase/tl/mali_kbase_tracepoints.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2020 ARM Limited. All rights reserved.
+ * (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
@@ -18,6 +18,25 @@
*
* SPDX-License-Identifier: GPL-2.0
*
+ *//* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * (C) COPYRIGHT 2010-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 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.
+ *
*/
/*
@@ -277,6 +296,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,
@@ -1500,6 +1530,42 @@ struct kbase_tlstream;
} 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
*