diff options
Diffstat (limited to 'mali_kbase/platform')
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_dvfs_governor.c | 19 | ||||
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_sscd.c | 98 | ||||
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_sysfs.c | 5 | ||||
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_trace.h | 24 |
4 files changed, 144 insertions, 2 deletions
diff --git a/mali_kbase/platform/pixel/pixel_gpu_dvfs_governor.c b/mali_kbase/platform/pixel/pixel_gpu_dvfs_governor.c index a4d4a61..28d4073 100644 --- a/mali_kbase/platform/pixel/pixel_gpu_dvfs_governor.c +++ b/mali_kbase/platform/pixel/pixel_gpu_dvfs_governor.c @@ -7,11 +7,13 @@ /* Mali core includes */ #include <mali_kbase.h> +#include <trace/events/power.h> /* Pixel integration includes */ #include "mali_kbase_config_platform.h" #include "pixel_gpu_control.h" #include "pixel_gpu_dvfs.h" +#include "pixel_gpu_trace.h" /** * gpu_dvfs_governor_basic() - The evaluation function for &GPU_DVFS_GOVERNOR_BASIC. @@ -165,11 +167,24 @@ int gpu_dvfs_governor_get_next_level(struct kbase_device *kbdev, struct gpu_dvfs_utlization *util_stats) { struct pixel_context *pc = kbdev->platform_context; - int level; + int level, ret; lockdep_assert_held(&pc->dvfs.lock); level = governors[pc->dvfs.governor.curr].evaluate(kbdev, util_stats); - return clamp(level, pc->dvfs.level_scaling_max, pc->dvfs.level_scaling_min); + if (level != pc->dvfs.level) { + trace_clock_set_rate("gpu_gov_rec", pc->dvfs.table[level].clk[GPU_DVFS_CLK_SHADERS], + raw_smp_processor_id()); + } + + ret = clamp(level, pc->dvfs.level_scaling_max, pc->dvfs.level_scaling_min); + if (ret != level) { + trace_gpu_gov_rec_violate(pc->dvfs.table[level].clk[GPU_DVFS_CLK_SHADERS], + pc->dvfs.table[ret].clk[GPU_DVFS_CLK_SHADERS], + pc->dvfs.table[pc->dvfs.level_scaling_min].clk[GPU_DVFS_CLK_SHADERS], + pc->dvfs.table[pc->dvfs.level_scaling_max].clk[GPU_DVFS_CLK_SHADERS]); + } + + return ret; } /** diff --git a/mali_kbase/platform/pixel/pixel_gpu_sscd.c b/mali_kbase/platform/pixel/pixel_gpu_sscd.c index 75f3c2a..b48d8c7 100644 --- a/mali_kbase/platform/pixel/pixel_gpu_sscd.c +++ b/mali_kbase/platform/pixel/pixel_gpu_sscd.c @@ -8,7 +8,9 @@ /* Mali core includes */ #include <mali_kbase.h> #include <csf/mali_kbase_csf_trace_buffer.h> +#include <csf/mali_kbase_csf_firmware.h> #include <csf/mali_kbase_csf_firmware_cfg.h> +#include <csf/mali_kbase_csf_firmware_core_dump.h> /* Pixel integration includes */ #include "mali_kbase_config_platform.h" @@ -53,6 +55,7 @@ enum PDC_STATUS = 0x8, KTRACE = 0x9, CONTEXTS = 0xA, + FW_CORE_DUMP = 0xB, NUM_SEGMENTS } sscd_segs; @@ -356,6 +359,88 @@ static int get_and_init_contexts(struct kbase_device *kbdev, } #endif +struct pixel_fw_core_dump { + char magic[4]; + u32 reserved; + char git_sha[BUILD_INFO_GIT_SHA_LEN]; + char core_dump[]; +}; + +static void get_and_init_fw_core_dump(struct kbase_device *kbdev, struct sscd_segment *seg) +{ + const size_t core_dump_size = get_fw_core_dump_size(kbdev); + + int i; + struct pixel_fw_core_dump *fw_core_dump; + struct kbase_csf_firmware_interface *interface; + struct page *page; + u32 *p; + size_t size; + size_t write_size; + + if (core_dump_size == -1) + { + dev_err(kbdev->dev, "pixel: failed to get firmware core dump size"); + } + + seg->size = sizeof(struct pixel_fw_core_dump) + core_dump_size; + seg->addr = kzalloc(seg->size, GFP_KERNEL); + + if (seg->addr == NULL) { + seg->size = 0; + dev_err(kbdev->dev, "pixel: failed to allocate for firmware core dump buffer"); + return; + } + + fw_core_dump = (struct pixel_fw_core_dump *) seg->addr; + + strncpy(fw_core_dump->magic, "fwcd", 4); + memcpy(fw_core_dump->git_sha, fw_git_sha, BUILD_INFO_GIT_SHA_LEN); + + // Dumping ELF header + { + struct fw_core_dump_data private = {.kbdev = kbdev}; + struct seq_file m = {.private = &private, .buf = fw_core_dump->core_dump, .size = core_dump_size}; + fw_core_dump_write_elf_header(&m); + size = m.count; + if (unlikely(m.count >= m.size)) + dev_warn(kbdev->dev, "firmware core dump header may be larger than buffer size"); + } + + // Dumping pages + list_for_each_entry(interface, &kbdev->csf.firmware_interfaces, node) { + /* Skip memory sections that cannot be read or are protected. */ + if ((interface->flags & CSF_FIRMWARE_ENTRY_PROTECTED) || + (interface->flags & CSF_FIRMWARE_ENTRY_READ) == 0) + continue; + + for(i = 0; i < interface->num_pages; i++) + { + page = as_page(interface->phys[i]); + write_size = size < core_dump_size ? min(core_dump_size - size, (size_t) FW_PAGE_SIZE) : 0; + if (write_size) + { + p = kmap_atomic(page); + memcpy(fw_core_dump->core_dump + size, p, write_size); + kunmap_atomic(p); + } + size += FW_PAGE_SIZE; + + if (size < FW_PAGE_SIZE) + break; + } + } + + if (unlikely(size != core_dump_size)) + { + dev_err(kbdev->dev, "firmware core dump size and buffer size are different"); + kfree(seg->addr); + seg->addr = NULL; + seg->size = 0; + } + + return; +} /* * Stub pending FW support */ @@ -493,6 +578,9 @@ void gpu_sscd_dump(struct kbase_device *kbdev, const char* reason) unsigned long flags, current_ts = jiffies; struct pixel_gpu_pdc_status pdc_status; static unsigned long last_hang_sscd_ts; +#if MALI_USE_CSF + int fwcd_err; +#endif if (!strcmp(reason, "GPU hang")) { /* GPU hang - avoid multiple coredumps for the same hang until @@ -515,6 +603,12 @@ void gpu_sscd_dump(struct kbase_device *kbdev, const char* reason) return; } +#if MALI_USE_CSF + fwcd_err = fw_core_dump_create(kbdev); + if (fwcd_err) + dev_err(kbdev->dev, "pixel: failed to create firmware core dump"); +#endif + ec = segments_init(kbdev, segs); if (ec != 0) { dev_err(kbdev->dev, @@ -554,7 +648,11 @@ void gpu_sscd_dump(struct kbase_device *kbdev, const char* reason) dev_err(kbdev->dev, "could not collect active contexts: rc: %i", ec); } + + if (!fwcd_err) + get_and_init_fw_core_dump(kbdev, &segs[FW_CORE_DUMP]); #endif + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); /* Acquire the pm lock to prevent modifications to the rail state log */ diff --git a/mali_kbase/platform/pixel/pixel_gpu_sysfs.c b/mali_kbase/platform/pixel/pixel_gpu_sysfs.c index c816460..f6164f9 100644 --- a/mali_kbase/platform/pixel/pixel_gpu_sysfs.c +++ b/mali_kbase/platform/pixel/pixel_gpu_sysfs.c @@ -7,6 +7,7 @@ /* Mali core includes */ #include <mali_kbase.h> +#include <trace/events/power.h> /* Pixel integration includes */ #include "mali_kbase_config_platform.h" @@ -445,6 +446,8 @@ static ssize_t hint_max_freq_store(struct device *dev, struct device_attribute * if (level < 0) return -EINVAL; + trace_clock_set_rate("gpu_hint_max", clock, raw_smp_processor_id()); + mutex_lock(&pc->dvfs.lock); gpu_dvfs_update_level_lock(kbdev, GPU_DVFS_LEVEL_LOCK_HINT, -1, level); gpu_dvfs_select_level(kbdev); @@ -489,6 +492,8 @@ static ssize_t hint_min_freq_store(struct device *dev, struct device_attribute * if (level < 0) return -EINVAL; + trace_clock_set_rate("gpu_hint_min", clock, raw_smp_processor_id()); + mutex_lock(&pc->dvfs.lock); gpu_dvfs_update_level_lock(kbdev, GPU_DVFS_LEVEL_LOCK_HINT, level, -1); gpu_dvfs_select_level(kbdev); diff --git a/mali_kbase/platform/pixel/pixel_gpu_trace.h b/mali_kbase/platform/pixel/pixel_gpu_trace.h index 1165e75..6c30f1b 100644 --- a/mali_kbase/platform/pixel/pixel_gpu_trace.h +++ b/mali_kbase/platform/pixel/pixel_gpu_trace.h @@ -45,6 +45,30 @@ TRACE_EVENT(gpu_power_state, ) ); +TRACE_EVENT(gpu_gov_rec_violate, + TP_PROTO(unsigned int recfreq, unsigned int retfreq, + unsigned int minlvfreq, unsigned int maxlvfreq), + TP_ARGS(recfreq, retfreq, minlvfreq, maxlvfreq), + TP_STRUCT__entry( + __field(unsigned int, recfreq) + __field(unsigned int, retfreq) + __field(unsigned int, minlvfreq) + __field(unsigned int, maxlvfreq) + ), + TP_fast_assign( + __entry->recfreq = recfreq; + __entry->retfreq = retfreq; + __entry->minlvfreq = minlvfreq; + __entry->maxlvfreq = maxlvfreq; + ), + TP_printk("rec=%u ret=%u min=%u max=%u", + __entry->recfreq, + __entry->retfreq, + __entry->minlvfreq, + __entry->maxlvfreq + ) +); + #endif /* _TRACE_PIXEL_GPU_H */ /* This part must be outside protection */ |