summaryrefslogtreecommitdiff
path: root/mali_kbase/platform
diff options
context:
space:
mode:
Diffstat (limited to 'mali_kbase/platform')
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_dvfs_governor.c19
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_sscd.c98
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_sysfs.c5
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_trace.h24
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 */