summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mali_kbase/Kbuild45
-rw-r--r--mali_kbase/backend/gpu/Kbuild6
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_devfreq.c149
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_hw.c52
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_rb.c53
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_ca.c5
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.c129
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.h55
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_defs.h5
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_driver.c27
-rw-r--r--mali_kbase/ipa/Kbuild9
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa.c495
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa.h81
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa_debugfs.c237
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa_debugfs.h50
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa_generic.c217
-rw-r--r--mali_kbase/ipa/mali_kbase_ipa_simple.c205
-rw-r--r--mali_kbase/mali_base_hwconfig_features.h1
-rw-r--r--mali_kbase/mali_base_hwconfig_issues.h48
-rw-r--r--mali_kbase/mali_base_kernel.h2
-rw-r--r--mali_kbase/mali_kbase.h2
-rw-r--r--mali_kbase/mali_kbase_config_defaults.h10
-rw-r--r--mali_kbase/mali_kbase_core_linux.c98
-rw-r--r--mali_kbase/mali_kbase_defs.h34
-rw-r--r--mali_kbase/mali_kbase_device.c2
-rw-r--r--mali_kbase/mali_kbase_gator_api.c2
-rw-r--r--mali_kbase/mali_kbase_gator_hwcnt_names.h3
-rw-r--r--mali_kbase/mali_kbase_gator_hwcnt_names_tsix.h20
-rw-r--r--mali_kbase/mali_kbase_gpu_id.h11
-rw-r--r--mali_kbase/mali_kbase_gpuprops.c2
-rw-r--r--mali_kbase/mali_kbase_gpuprops.h2
-rw-r--r--mali_kbase/mali_kbase_gpuprops_types.h7
-rw-r--r--mali_kbase/mali_kbase_hw.c35
-rw-r--r--mali_kbase/mali_kbase_jd.c2
-rw-r--r--mali_kbase/mali_kbase_js.c9
-rw-r--r--mali_kbase/mali_kbase_js.h67
-rw-r--r--mali_kbase/mali_kbase_js_defs.h10
-rw-r--r--mali_kbase/mali_kbase_mem.h2
-rw-r--r--mali_kbase/mali_kbase_mem_linux.c2
-rw-r--r--mali_kbase/mali_kbase_mem_linux.h2
-rw-r--r--mali_kbase/mali_kbase_softjobs.c13
-rw-r--r--mali_kbase/mali_kbase_tlstream.c2
-rw-r--r--mali_kbase/mali_kbase_tlstream.h2
-rw-r--r--mali_kbase/mali_kbase_uku.h2
-rw-r--r--mali_kbase/mali_midg_regmap.h3
-rw-r--r--mali_kbase/platform/Kbuild21
-rw-r--r--mali_kbase/platform/devicetree/Kbuild12
-rw-r--r--mali_kbase/platform/juno_soc/Kbuild10
-rw-r--r--mali_kbase/platform/juno_soc/juno_mali_opp.c84
-rw-r--r--mali_kbase/platform/vexpress/Kbuild8
-rw-r--r--mali_kbase/platform/vexpress_1xv7_a57/Kbuild4
-rw-r--r--mali_kbase/platform/vexpress_6xvirtex7_10mhz/Kbuild8
52 files changed, 1600 insertions, 762 deletions
diff --git a/mali_kbase/Kbuild b/mali_kbase/Kbuild
index d9df906..3e78928 100644
--- a/mali_kbase/Kbuild
+++ b/mali_kbase/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2012,2014 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@@ -15,7 +15,7 @@
# Driver version string which is returned to userspace via an ioctl
-MALI_RELEASE_NAME ?= "r4p0-01rel0"
+MALI_RELEASE_NAME ?= "r5p0-01rel0"
# Paths required for build
KBASE_PATH = $(src)
@@ -163,47 +163,24 @@ ifeq ($(CONFIG_MALI_PLATFORM_FAKE),y)
platform/vexpress_6xvirtex7_10mhz/mali_kbase_cpu_vexpress.c
ccflags-y += -I$(src)/platform/vexpress_6xvirtex7_10mhz
endif
-
- ifeq ($(CONFIG_MALI_PLATFORM_A7_KIPLING),y)
- SRC += platform/a7_kipling/mali_kbase_config_a7_kipling.c \
- platform/a7_kipling/mali_kbase_cpu_a7_kipling.c
- ccflags-y += -I$(src)/platform/a7_kipling
- endif
-
- ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y)
- # remove begin and end quotes from the Kconfig string type
- platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME))
- MALI_PLATFORM_THIRDPARTY_DIR := platform/$(platform_name)
- ccflags-y += -I$(src)/$(MALI_PLATFORM_THIRDPARTY_DIR)
- ifeq ($(CONFIG_MALI_MIDGARD),m)
- include $(src)/platform/$(platform_name)/Kbuild
- else ifeq ($(CONFIG_MALI_MIDGARD),y)
- obj-$(CONFIG_MALI_MIDGARD) += platform/
- endif
- endif
endif # CONFIG_MALI_PLATFORM_FAKE=y
-ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y)
-# remove begin and end quotes from the Kconfig string type
-platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME))
-MALI_PLATFORM_THIRDPARTY_DIR := platform/$(platform_name)
-ccflags-y += -I$(src)/$(MALI_PLATFORM_THIRDPARTY_DIR)
-ifeq ($(CONFIG_MALI_MIDGARD),m)
-include $(src)/platform/$(platform_name)/Kbuild
-else ifeq ($(CONFIG_MALI_MIDGARD),y)
-obj-$(CONFIG_MALI_MIDGARD) += platform/
-endif
-endif
-
# Tell the Linux build system from which .o file to create the kernel module
obj-$(CONFIG_MALI_MIDGARD) += mali_kbase.o
# Tell the Linux build system to enable building of our .c files
mali_kbase-y := $(SRC:.c=.o)
+ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y)
+ # Kconfig passes in the name with quotes for in-tree builds - remove them.
+ platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME))
+ MALI_PLATFORM_THIRDPARTY_DIR := platform/$(platform_name)
+ ccflags-y += -I$(src)/$(MALI_PLATFORM_THIRDPARTY_DIR)
+ include $(src)/$(MALI_PLATFORM_THIRDPARTY_DIR)/Kbuild
+endif
+
ifeq ($(CONFIG_DEVFREQ_THERMAL),y)
-include $(src)/ipa/Kbuild
-mali_kbase-y += $(IPA:.c=.o)
+ include $(src)/ipa/Kbuild
endif
mali_kbase-$(CONFIG_MALI_DMA_FENCE) += mali_kbase_dma_fence.o
diff --git a/mali_kbase/backend/gpu/Kbuild b/mali_kbase/backend/gpu/Kbuild
index df4e796..5f700e9 100644
--- a/mali_kbase/backend/gpu/Kbuild
+++ b/mali_kbase/backend/gpu/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2014 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2014,2017 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@@ -46,7 +46,9 @@ BACKEND += \
endif
ifeq ($(CONFIG_MALI_DEVFREQ),y)
-BACKEND += backend/gpu/mali_kbase_devfreq.c
+BACKEND += \
+ backend/gpu/mali_kbase_devfreq.c \
+ backend/gpu/mali_kbase_pm_ca_devfreq.c
endif
ifeq ($(CONFIG_MALI_NO_MALI),y)
diff --git a/mali_kbase/backend/gpu/mali_kbase_devfreq.c b/mali_kbase/backend/gpu/mali_kbase_devfreq.c
index 28b4f1d..574eb3e 100644
--- a/mali_kbase/backend/gpu/mali_kbase_devfreq.c
+++ b/mali_kbase/backend/gpu/mali_kbase_devfreq.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -20,6 +20,7 @@
#include <mali_kbase_config_defaults.h>
#include <backend/gpu/mali_kbase_pm_internal.h>
+#include <linux/of.h>
#include <linux/clk.h>
#include <linux/devfreq.h>
#ifdef CONFIG_DEVFREQ_THERMAL
@@ -41,15 +42,47 @@
#define dev_pm_opp_find_freq_ceil opp_find_freq_ceil
#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
+ *
+ * Return: Real target frequency
+ *
+ * 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.
+ */
+static unsigned long opp_translate(struct kbase_device *kbdev,
+ unsigned long freq, u64 *core_mask)
+{
+ int i;
+
+ for (i = 0; i < kbdev->num_opps; i++) {
+ if (kbdev->opp_table[i].opp_freq == freq) {
+ *core_mask = kbdev->opp_table[i].core_mask;
+ return kbdev->opp_table[i].real_freq;
+ }
+ }
+
+ /* Failed to find OPP - return all cores enabled & nominal frequency */
+ *core_mask = kbdev->gpu_props.props.raw_props.shader_present;
+
+ return freq;
+}
static int
kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
{
struct kbase_device *kbdev = dev_get_drvdata(dev);
struct dev_pm_opp *opp;
+ unsigned long nominal_freq;
unsigned long freq = 0;
unsigned long voltage;
int err;
+ u64 core_mask;
freq = *target_freq;
@@ -62,14 +95,17 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
return PTR_ERR(opp);
}
+ nominal_freq = freq;
+
/*
* Only update if there is a change of frequency
*/
- if (kbdev->current_freq == freq) {
- *target_freq = freq;
+ if (kbdev->current_nominal_freq == nominal_freq) {
+ *target_freq = nominal_freq;
return 0;
}
+ freq = opp_translate(kbdev, nominal_freq, &core_mask);
#ifdef CONFIG_REGULATOR
if (kbdev->regulator && kbdev->current_voltage != voltage
&& kbdev->current_freq < freq) {
@@ -99,11 +135,17 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
}
#endif
- *target_freq = freq;
+ if (kbdev->pm.backend.ca_current_policy->id ==
+ KBASE_PM_CA_POLICY_ID_DEVFREQ)
+ kbase_devfreq_set_core_mask(kbdev, core_mask);
+
+ *target_freq = nominal_freq;
kbdev->current_voltage = voltage;
+ kbdev->current_nominal_freq = nominal_freq;
kbdev->current_freq = freq;
+ kbdev->current_core_mask = core_mask;
- KBASE_TLSTREAM_AUX_DEVFREQ_TARGET((u64)freq);
+ KBASE_TLSTREAM_AUX_DEVFREQ_TARGET((u64)nominal_freq);
kbase_pm_reset_dvfs_utilisation(kbdev);
@@ -115,7 +157,7 @@ kbase_devfreq_cur_freq(struct device *dev, unsigned long *freq)
{
struct kbase_device *kbdev = dev_get_drvdata(dev);
- *freq = kbdev->current_freq;
+ *freq = kbdev->current_nominal_freq;
return 0;
}
@@ -125,7 +167,7 @@ kbase_devfreq_status(struct device *dev, struct devfreq_dev_status *stat)
{
struct kbase_device *kbdev = dev_get_drvdata(dev);
- stat->current_frequency = kbdev->current_freq;
+ stat->current_frequency = kbdev->current_nominal_freq;
kbase_pm_get_dvfs_utilisation(kbdev,
&stat->total_time, &stat->busy_time);
@@ -189,15 +231,92 @@ static void kbase_devfreq_exit(struct device *dev)
kbase_devfreq_term_freq_table(kbdev);
}
+static int kbase_devfreq_init_core_mask_table(struct kbase_device *kbdev)
+{
+ struct device_node *opp_node = of_parse_phandle(kbdev->dev->of_node,
+ "operating-points-v2", 0);
+ struct device_node *node;
+ int i = 0;
+ int count;
+
+ if (!opp_node)
+ return 0;
+ if (!of_device_is_compatible(opp_node, "operating-points-v2-mali"))
+ return 0;
+
+ count = dev_pm_opp_get_opp_count(kbdev->dev);
+ kbdev->opp_table = kmalloc_array(count,
+ sizeof(struct kbase_devfreq_opp), GFP_KERNEL);
+ if (!kbdev->opp_table)
+ return -ENOMEM;
+
+ for_each_available_child_of_node(opp_node, node) {
+ u64 core_mask;
+ u64 opp_freq, real_freq;
+ const void *core_count_p;
+
+ if (of_property_read_u64(node, "opp-hz", &opp_freq)) {
+ dev_warn(kbdev->dev, "OPP is missing required opp-hz property\n");
+ continue;
+ }
+ if (of_property_read_u64(node, "opp-hz-real", &real_freq))
+ real_freq = opp_freq;
+ if (of_property_read_u64(node, "opp-core-mask", &core_mask))
+ core_mask =
+ kbdev->gpu_props.props.raw_props.shader_present;
+ core_count_p = of_get_property(node, "opp-core-count", NULL);
+ if (core_count_p) {
+ u64 remaining_core_mask =
+ kbdev->gpu_props.props.raw_props.shader_present;
+ int core_count = be32_to_cpup(core_count_p);
+
+ core_mask = 0;
+
+ for (; core_count > 0; core_count--) {
+ int core = ffs(remaining_core_mask);
+
+ if (!core) {
+ dev_err(kbdev->dev, "OPP has more cores than GPU\n");
+ return -ENODEV;
+ }
+
+ core_mask |= (1ull << (core-1));
+ remaining_core_mask &= ~(1ull << (core-1));
+ }
+ }
+
+ if (!core_mask) {
+ dev_err(kbdev->dev, "OPP has invalid core mask of 0\n");
+ return -ENODEV;
+ }
+
+ kbdev->opp_table[i].opp_freq = opp_freq;
+ kbdev->opp_table[i].real_freq = real_freq;
+ kbdev->opp_table[i].core_mask = core_mask;
+
+ dev_info(kbdev->dev, "OPP %d : opp_freq=%llu real_freq=%llu core_mask=%llx\n",
+ i, opp_freq, real_freq, core_mask);
+
+ i++;
+ }
+
+ kbdev->num_opps = i;
+
+ return 0;
+}
+
int kbase_devfreq_init(struct kbase_device *kbdev)
{
struct devfreq_dev_profile *dp;
int err;
- if (!kbdev->clock)
+ if (!kbdev->clock) {
+ dev_err(kbdev->dev, "Clock not available for devfreq\n");
return -ENODEV;
+ }
kbdev->current_freq = clk_get_rate(kbdev->clock);
+ kbdev->current_nominal_freq = kbdev->current_freq;
dp = &kbdev->devfreq_profile;
@@ -211,6 +330,10 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
if (kbase_devfreq_init_freq_table(kbdev, dp))
return -EFAULT;
+ err = kbase_devfreq_init_core_mask_table(kbdev);
+ if (err)
+ return err;
+
kbdev->devfreq = devfreq_add_device(kbdev->dev, dp,
"simple_ondemand", NULL);
if (IS_ERR(kbdev->devfreq)) {
@@ -218,6 +341,10 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
return PTR_ERR(kbdev->devfreq);
}
+ /* devfreq_add_device only copies a few of kbdev->dev's fields, so
+ * 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);
if (err) {
dev_err(kbdev->dev,
@@ -226,7 +353,7 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
}
#ifdef CONFIG_DEVFREQ_THERMAL
- err = kbase_ipa_model_init(kbdev);
+ err = kbase_ipa_init(kbdev);
if (err) {
dev_err(kbdev->dev, "IPA initialization failed\n");
goto cooling_failed;
@@ -270,7 +397,7 @@ void kbase_devfreq_term(struct kbase_device *kbdev)
if (kbdev->devfreq_cooling)
devfreq_cooling_unregister(kbdev->devfreq_cooling);
- kbase_ipa_model_term(kbdev);
+ kbase_ipa_term(kbdev);
#endif
devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq);
@@ -280,4 +407,6 @@ void kbase_devfreq_term(struct kbase_device *kbdev)
dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err);
else
kbdev->devfreq = NULL;
+
+ kfree(kbdev->opp_table);
}
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_hw.c b/mali_kbase/backend/gpu/mali_kbase_jm_hw.c
index 7856378..ef7497d 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_hw.c
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_hw.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -129,8 +129,7 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
/* Write an approximate start timestamp.
* It's approximate because there might be a job in the HEAD register.
- * In such cases, we'll try to make a better approximation in the IRQ
- * handler (up to the KBASE_JS_IRQ_THROTTLE_TIME_US). */
+ */
katom->start_timestamp = ktime_get();
/* GO ! */
@@ -184,9 +183,9 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
* Update the start_timestamp of the job currently in the HEAD, based on the
* fact that we got an IRQ for the previous set of completed jobs.
*
- * The estimate also takes into account the %KBASE_JS_IRQ_THROTTLE_TIME_US and
- * the time the job was submitted, to work out the best estimate (which might
- * still result in an over-estimate to the calculated time spent)
+ * The estimate also takes into account the time the job was submitted, to
+ * work out the best estimate (which might still result in an over-estimate to
+ * the calculated time spent)
*/
static void kbasep_job_slot_update_head_start_timestamp(
struct kbase_device *kbdev,
@@ -195,25 +194,20 @@ static void kbasep_job_slot_update_head_start_timestamp(
{
if (kbase_backend_nr_atoms_on_slot(kbdev, js) > 0) {
struct kbase_jd_atom *katom;
- ktime_t new_timestamp;
ktime_t timestamp_diff;
/* The atom in the HEAD */
katom = kbase_gpu_inspect(kbdev, js, 0);
KBASE_DEBUG_ASSERT(katom != NULL);
- /* Account for any IRQ Throttle time - makes an overestimate of
- * the time spent by the job */
- new_timestamp = ktime_sub_ns(end_timestamp,
- KBASE_JS_IRQ_THROTTLE_TIME_US * 1000);
- timestamp_diff = ktime_sub(new_timestamp,
- katom->start_timestamp);
+ timestamp_diff = ktime_sub(end_timestamp,
+ katom->start_timestamp);
if (ktime_to_ns(timestamp_diff) >= 0) {
/* Only update the timestamp if it's a better estimate
* than what's currently stored. This is because our
* estimate that accounts for the throttle time may be
* too much of an overestimate */
- katom->start_timestamp = new_timestamp;
+ katom->start_timestamp = end_timestamp;
}
}
}
@@ -250,16 +244,6 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done)
memset(&kbdev->slot_submit_count_irq[0], 0,
sizeof(kbdev->slot_submit_count_irq));
- /* write irq throttle register, this will prevent irqs from occurring
- * until the given number of gpu clock cycles have passed */
- {
- int irq_throttle_cycles =
- atomic_read(&kbdev->irq_throttle_cycles);
-
- kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_THROTTLE),
- irq_throttle_cycles, NULL);
- }
-
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
while (done) {
@@ -1139,10 +1123,9 @@ static void kbase_debug_dump_registers(struct kbase_device *kbdev)
dev_err(kbdev->dev, " GPU_IRQ_RAWSTAT=0x%08x GPU_STATUS=0x%08x",
kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT), NULL),
kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS), NULL));
- dev_err(kbdev->dev, " JOB_IRQ_RAWSTAT=0x%08x JOB_IRQ_JS_STATE=0x%08x JOB_IRQ_THROTTLE=0x%08x",
+ dev_err(kbdev->dev, " JOB_IRQ_RAWSTAT=0x%08x JOB_IRQ_JS_STATE=0x%08x",
kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT), NULL),
- kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_JS_STATE), NULL),
- kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_THROTTLE), NULL));
+ kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_JS_STATE), NULL));
for (i = 0; i < 3; i++) {
dev_err(kbdev->dev, " JS%d_STATUS=0x%08x JS%d_HEAD_LO=0x%08x",
i, kbase_reg_read(kbdev, JOB_SLOT_REG(i, JS_STATUS),
@@ -1163,6 +1146,9 @@ static void kbase_debug_dump_registers(struct kbase_device *kbdev)
dev_err(kbdev->dev, " SHADER_CONFIG=0x%08x L2_MMU_CONFIG=0x%08x",
kbase_reg_read(kbdev, GPU_CONTROL_REG(SHADER_CONFIG), NULL),
kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), NULL));
+ dev_err(kbdev->dev, " TILER_CONFIG=0x%08x JM_CONFIG=0x%08x",
+ kbase_reg_read(kbdev, GPU_CONTROL_REG(TILER_CONFIG), NULL),
+ kbase_reg_read(kbdev, GPU_CONTROL_REG(JM_CONFIG), NULL));
}
static void kbasep_reset_timeout_worker(struct work_struct *data)
@@ -1264,15 +1250,16 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
if (!silent)
kbase_debug_dump_registers(kbdev);
- /* Reset the GPU */
- kbase_pm_init_hw(kbdev, 0);
-
/* Complete any jobs that were still on the GPU */
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ kbdev->protected_mode = false;
kbase_backend_reset(kbdev, &end_timestamp);
kbase_pm_metrics_update(kbdev, NULL);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+ /* Reset the GPU */
+ kbase_pm_init_hw(kbdev, 0);
+
mutex_unlock(&kbdev->pm.lock);
mutex_lock(&js_devdata->runpool_mutex);
@@ -1326,6 +1313,11 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
kbase_js_sched_all(kbdev);
}
+ /* Process any pending slot updates */
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ kbase_backend_slot_update(kbdev);
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+
kbase_pm_context_idle(kbdev);
/* Release vinstr */
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_rb.c b/mali_kbase/backend/gpu/mali_kbase_jm_rb.c
index d4ed3d4..418ae1f 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_rb.c
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_rb.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -692,6 +692,7 @@ static void kbase_gpu_release_atom(struct kbase_device *kbdev,
}
katom->gpu_rb_state = KBASE_ATOM_GPU_RB_WAITING_BLOCKED;
+ katom->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK;
}
static void kbase_gpu_mark_atom_for_return(struct kbase_device *kbdev,
@@ -1003,21 +1004,13 @@ static int kbase_jm_exit_protected_mode(struct kbase_device *kbdev,
/* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
case KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT:
- if (kbase_reset_gpu_active(kbdev))
- return -EAGAIN;
-
- kbdev->protected_mode_transition = false;
- kbdev->protected_mode = false;
- KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_END(kbdev);
- /* protected mode sanity checks */
- KBASE_DEBUG_ASSERT_MSG(
- kbase_jd_katom_is_protected(katom[idx]) == kbase_gpu_in_protected_mode(kbdev),
- "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)",
- kbase_jd_katom_is_protected(katom[idx]), kbase_gpu_in_protected_mode(kbdev));
- KBASE_DEBUG_ASSERT_MSG(
- (kbase_jd_katom_is_protected(katom[idx]) && js == 0) ||
- !kbase_jd_katom_is_protected(katom[idx]),
- "Protected atom on JS%d not supported", js);
+ /* A GPU reset is issued when exiting protected mode. Once the
+ * reset is done all atoms' state will also be reset. For this
+ * reason, if the atom is still in this state we can safely
+ * say that the reset has not completed i.e., we have not
+ * finished exiting protected mode yet.
+ */
+ return -EAGAIN;
}
return 0;
@@ -1297,6 +1290,18 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js,
lockdep_assert_held(&kbdev->hwaccess_lock);
+ /*
+ * When a hard-stop is followed close after a soft-stop, the completion
+ * code may be set to STOPPED, even though the job is terminated
+ */
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TMIX_8438)) {
+ if (completion_code == BASE_JD_EVENT_STOPPED &&
+ (katom->atom_flags &
+ KBASE_KATOM_FLAG_BEEN_HARD_STOPPED)) {
+ completion_code = BASE_JD_EVENT_TERMINATED;
+ }
+ }
+
if ((kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_6787) || (katom->core_req &
BASE_JD_REQ_SKIP_CACHE_END)) &&
completion_code != BASE_JD_EVENT_DONE &&
@@ -1492,6 +1497,9 @@ void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp)
lockdep_assert_held(&kbdev->hwaccess_lock);
+ /* Reset should always take the GPU out of protected mode */
+ WARN_ON(kbase_gpu_in_protected_mode(kbdev));
+
for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) {
int atom_idx = 0;
int idx;
@@ -1505,7 +1513,19 @@ void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp)
break;
if (katom->protected_state.exit ==
KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT)
+ {
KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_END(kbdev);
+
+ /* protected mode sanity checks */
+ KBASE_DEBUG_ASSERT_MSG(
+ kbase_jd_katom_is_protected(katom) == kbase_gpu_in_protected_mode(kbdev),
+ "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)",
+ kbase_jd_katom_is_protected(katom), kbase_gpu_in_protected_mode(kbdev));
+ KBASE_DEBUG_ASSERT_MSG(
+ (kbase_jd_katom_is_protected(katom) && js == 0) ||
+ !kbase_jd_katom_is_protected(katom),
+ "Protected atom on JS%d not supported", js);
+ }
if (katom->gpu_rb_state < KBASE_ATOM_GPU_RB_SUBMITTED)
keep_in_jm_rb = true;
@@ -1539,7 +1559,6 @@ void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp)
}
kbdev->protected_mode_transition = false;
- kbdev->protected_mode = false;
}
static inline void kbase_gpu_stop_atom(struct kbase_device *kbdev,
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_ca.c b/mali_kbase/backend/gpu/mali_kbase_pm_ca.c
index e8cd8cb..85890f1 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_ca.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_ca.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2013-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2013-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -25,6 +25,9 @@
static const struct kbase_pm_ca_policy *const policy_list[] = {
&kbase_pm_ca_fixed_policy_ops,
+#ifdef CONFIG_MALI_DEVFREQ
+ &kbase_pm_ca_devfreq_policy_ops,
+#endif
#if !MALI_CUSTOMER_RELEASE
&kbase_pm_ca_random_policy_ops
#endif
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.c b/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.c
new file mode 100644
index 0000000..66bf660
--- /dev/null
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.c
@@ -0,0 +1,129 @@
+/*
+ *
+ * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * 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.
+ *
+ */
+
+
+
+/*
+ * A core availability policy implementing core mask selection from devfreq OPPs
+ *
+ */
+
+#include <mali_kbase.h>
+#include <mali_kbase_pm.h>
+#include <backend/gpu/mali_kbase_pm_internal.h>
+#include <linux/version.h>
+
+void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask)
+{
+ struct kbasep_pm_ca_policy_devfreq *data =
+ &kbdev->pm.backend.ca_policy_data.devfreq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+
+ data->cores_desired = core_mask;
+
+ /* Disable any cores that are now unwanted */
+ data->cores_enabled &= data->cores_desired;
+
+ kbdev->pm.backend.ca_in_transition = true;
+
+ /* If there are no cores to be powered off then power on desired cores
+ */
+ if (!(data->cores_used & ~data->cores_desired)) {
+ data->cores_enabled = data->cores_desired;
+ kbdev->pm.backend.ca_in_transition = false;
+ }
+
+ kbase_pm_update_cores_state_nolock(kbdev);
+
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+
+ dev_dbg(kbdev->dev, "Devfreq policy : new core mask=%llX %llX\n",
+ data->cores_desired, data->cores_enabled);
+}
+
+static void devfreq_init(struct kbase_device *kbdev)
+{
+ struct kbasep_pm_ca_policy_devfreq *data =
+ &kbdev->pm.backend.ca_policy_data.devfreq;
+
+ if (kbdev->current_core_mask) {
+ data->cores_enabled = kbdev->current_core_mask;
+ data->cores_desired = kbdev->current_core_mask;
+ } else {
+ data->cores_enabled =
+ kbdev->gpu_props.props.raw_props.shader_present;
+ data->cores_desired =
+ kbdev->gpu_props.props.raw_props.shader_present;
+ }
+ data->cores_used = 0;
+ kbdev->pm.backend.ca_in_transition = false;
+}
+
+static void devfreq_term(struct kbase_device *kbdev)
+{
+}
+
+static u64 devfreq_get_core_mask(struct kbase_device *kbdev)
+{
+ return kbdev->pm.backend.ca_policy_data.devfreq.cores_enabled;
+}
+
+static void devfreq_update_core_status(struct kbase_device *kbdev,
+ u64 cores_ready,
+ u64 cores_transitioning)
+{
+ struct kbasep_pm_ca_policy_devfreq *data =
+ &kbdev->pm.backend.ca_policy_data.devfreq;
+
+ lockdep_assert_held(&kbdev->hwaccess_lock);
+
+ data->cores_used = cores_ready | cores_transitioning;
+
+ /* If in desired state then clear transition flag */
+ if (data->cores_enabled == data->cores_desired)
+ kbdev->pm.backend.ca_in_transition = false;
+
+ /* If all undesired cores are now off then power on desired cores.
+ * The direct comparison against cores_enabled limits potential
+ * recursion to one level */
+ if (!(data->cores_used & ~data->cores_desired) &&
+ data->cores_enabled != data->cores_desired) {
+ data->cores_enabled = data->cores_desired;
+
+ kbase_pm_update_cores_state_nolock(kbdev);
+
+ kbdev->pm.backend.ca_in_transition = false;
+ }
+}
+
+/*
+ * The struct kbase_pm_ca_policy structure for the devfreq core availability
+ * policy.
+ *
+ * This is the static structure that defines the devfreq core availability power
+ * policy's callback and name.
+ */
+const struct kbase_pm_ca_policy kbase_pm_ca_devfreq_policy_ops = {
+ "devfreq", /* name */
+ devfreq_init, /* init */
+ devfreq_term, /* term */
+ devfreq_get_core_mask, /* get_core_mask */
+ devfreq_update_core_status, /* update_core_status */
+ 0u, /* flags */
+ KBASE_PM_CA_POLICY_ID_DEVFREQ, /* id */
+};
+
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.h b/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.h
new file mode 100644
index 0000000..7ab3cd4
--- /dev/null
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_ca_devfreq.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * 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.
+ *
+ */
+
+
+
+/*
+ * A core availability policy for use with devfreq, where core masks are
+ * associated with OPPs.
+ */
+
+#ifndef MALI_KBASE_PM_CA_DEVFREQ_H
+#define MALI_KBASE_PM_CA_DEVFREQ_H
+
+/**
+ * struct kbasep_pm_ca_policy_devfreq - Private structure for devfreq ca policy
+ *
+ * This contains data that is private to the devfreq core availability
+ * policy.
+ *
+ * @cores_desired: Cores that the policy wants to be available
+ * @cores_enabled: Cores that the policy is currently returning as available
+ * @cores_used: Cores currently powered or transitioning
+ */
+struct kbasep_pm_ca_policy_devfreq {
+ u64 cores_desired;
+ u64 cores_enabled;
+ u64 cores_used;
+};
+
+extern const struct kbase_pm_ca_policy kbase_pm_ca_devfreq_policy_ops;
+
+/**
+ * kbase_devfreq_set_core_mask - Set core mask for policy to use
+ * @kbdev: Device pointer
+ * @core_mask: New core mask
+ *
+ * The new core mask will have immediate effect if the GPU is powered, or will
+ * take effect when it is next powered on.
+ */
+void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask);
+
+#endif /* MALI_KBASE_PM_CA_DEVFREQ_H */
+
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_defs.h b/mali_kbase/backend/gpu/mali_kbase_pm_defs.h
index 632ef12..352744e 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-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -23,6 +23,7 @@
#define _KBASE_PM_HWACCESS_DEFS_H_
#include "mali_kbase_pm_ca_fixed.h"
+#include "mali_kbase_pm_ca_devfreq.h"
#if !MALI_CUSTOMER_RELEASE
#include "mali_kbase_pm_ca_random.h"
#endif
@@ -131,6 +132,7 @@ union kbase_pm_policy_data {
union kbase_pm_ca_policy_data {
struct kbasep_pm_ca_policy_fixed fixed;
+ struct kbasep_pm_ca_policy_devfreq devfreq;
#if !MALI_CUSTOMER_RELEASE
struct kbasep_pm_ca_policy_random random;
#endif
@@ -410,6 +412,7 @@ struct kbase_pm_policy {
enum kbase_pm_ca_policy_id {
KBASE_PM_CA_POLICY_ID_FIXED = 1,
+ KBASE_PM_CA_POLICY_ID_DEVFREQ,
KBASE_PM_CA_POLICY_ID_RANDOM
};
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_driver.c b/mali_kbase/backend/gpu/mali_kbase_pm_driver.c
index 55763a8..ac63aa5 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_driver.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_driver.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -1223,6 +1223,10 @@ static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev)
kbdev->hw_quirks_sc |= SC_LS_ALLOW_ATTR_TYPES;
}
+ if (!kbdev->hw_quirks_sc)
+ kbdev->hw_quirks_sc = kbase_reg_read(kbdev,
+ GPU_CONTROL_REG(SHADER_CONFIG), NULL);
+
kbdev->hw_quirks_tiler = kbase_reg_read(kbdev,
GPU_CONTROL_REG(TILER_CONFIG), NULL);
@@ -1251,7 +1255,7 @@ static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev)
kbdev->hw_quirks_mmu |= L2_MMU_CONFIG_ALLOW_SNOOP_DISPARITY;
}
- kbdev->hw_quirks_jm = JM_CONFIG_UNUSED;
+ kbdev->hw_quirks_jm = 0;
/* Only for T86x/T88x-based products after r2p0 */
if (prod_id >= 0x860 && prod_id <= 0x880 && major >= 2) {
@@ -1273,7 +1277,7 @@ static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev)
}
/* Aggregate to one integer. */
- kbdev->hw_quirks_jm = (jm_values[0] ?
+ kbdev->hw_quirks_jm |= (jm_values[0] ?
JM_TIMESTAMP_OVERRIDE : 0);
kbdev->hw_quirks_jm |= (jm_values[1] ?
JM_CLOCK_GATE_OVERRIDE : 0);
@@ -1296,12 +1300,16 @@ static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev)
*/
if (coherency_features ==
COHERENCY_FEATURE_BIT(COHERENCY_ACE)) {
- kbdev->hw_quirks_jm =
+ kbdev->hw_quirks_jm |=
(COHERENCY_ACE_LITE | COHERENCY_ACE) <<
JM_FORCE_COHERENCY_FEATURES_SHIFT;
}
}
+ if (!kbdev->hw_quirks_jm)
+ kbdev->hw_quirks_jm = kbase_reg_read(kbdev,
+ GPU_CONTROL_REG(JM_CONFIG), NULL);
+
#ifdef CONFIG_MALI_CORESTACK
#define MANUAL_POWER_CONTROL ((u32)(1 << 8))
kbdev->hw_quirks_jm |= MANUAL_POWER_CONTROL;
@@ -1310,9 +1318,8 @@ static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev)
static void kbase_pm_hw_issues_apply(struct kbase_device *kbdev)
{
- if (kbdev->hw_quirks_sc)
- kbase_reg_write(kbdev, GPU_CONTROL_REG(SHADER_CONFIG),
- kbdev->hw_quirks_sc, NULL);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(SHADER_CONFIG),
+ kbdev->hw_quirks_sc, NULL);
kbase_reg_write(kbdev, GPU_CONTROL_REG(TILER_CONFIG),
kbdev->hw_quirks_tiler, NULL);
@@ -1320,10 +1327,8 @@ static void kbase_pm_hw_issues_apply(struct kbase_device *kbdev)
kbase_reg_write(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG),
kbdev->hw_quirks_mmu, NULL);
-
- if (kbdev->hw_quirks_jm != JM_CONFIG_UNUSED)
- kbase_reg_write(kbdev, GPU_CONTROL_REG(JM_CONFIG),
- kbdev->hw_quirks_jm, NULL);
+ kbase_reg_write(kbdev, GPU_CONTROL_REG(JM_CONFIG),
+ kbdev->hw_quirks_jm, NULL);
}
diff --git a/mali_kbase/ipa/Kbuild b/mali_kbase/ipa/Kbuild
index 7551f9e..b3f8761 100644
--- a/mali_kbase/ipa/Kbuild
+++ b/mali_kbase/ipa/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@@ -13,7 +13,8 @@
#
+mali_kbase-y += \
+ ipa/mali_kbase_ipa_simple.o \
+ ipa/mali_kbase_ipa.o
-IPA = \
- ipa/mali_kbase_ipa_generic.c \
- ipa/mali_kbase_ipa.c
+mali_kbase-$(CONFIG_DEBUG_FS) += ipa/mali_kbase_ipa_debugfs.o
diff --git a/mali_kbase/ipa/mali_kbase_ipa.c b/mali_kbase/ipa/mali_kbase_ipa.c
index dd0f1d6..d289ea8 100644
--- a/mali_kbase/ipa/mali_kbase_ipa.c
+++ b/mali_kbase/ipa/mali_kbase_ipa.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -14,25 +14,57 @@
*/
-#include <linux/sysfs.h>
#include <linux/thermal.h>
#include <linux/devfreq_cooling.h>
#include <linux/of.h>
#include "mali_kbase.h"
+#include "mali_kbase_ipa.h"
+#include "mali_kbase_ipa_debugfs.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
+#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"
+
+int kbase_ipa_model_recalculate(struct kbase_ipa_model *model)
+{
+ int err = 0;
+
+ lockdep_assert_held(&model->kbdev->ipa.lock);
+
+ if (model->ops->recalculate) {
+ err = model->ops->recalculate(model);
+ if (err) {
+ dev_err(model->kbdev->dev,
+ "recalculation of power model %s returned error %d\n",
+ model->ops->name, err);
+ }
+ }
+
+ return err;
+}
int kbase_ipa_model_ops_register(struct kbase_device *kbdev,
struct kbase_ipa_model_ops *new_model_ops)
{
struct kbase_ipa_model *new_model;
+ lockdep_assert_held(&kbdev->ipa.lock);
+
new_model = kzalloc(sizeof(struct kbase_ipa_model), GFP_KERNEL);
if (!new_model)
return -ENOMEM;
- INIT_LIST_HEAD(&new_model->link);
+
new_model->kbdev = kbdev;
new_model->ops = new_model_ops;
- list_add(&new_model->link, &kbdev->ipa_power_models);
+ list_add(&new_model->link, &kbdev->ipa.power_models);
return 0;
}
@@ -41,8 +73,10 @@ static int kbase_ipa_internal_models_append_list(struct kbase_device *kbdev)
{
int err;
- /* Always have the generic IPA */
- err = kbase_ipa_model_ops_register(kbdev, &kbase_generic_ipa_model_ops);
+ INIT_LIST_HEAD(&kbdev->ipa.power_models);
+
+ /* Always have the simple IPA model */
+ err = kbase_ipa_model_ops_register(kbdev, &kbase_simple_ipa_model_ops);
if (err)
return err;
@@ -56,7 +90,9 @@ struct kbase_ipa_model *kbase_ipa_get_model(struct kbase_device *kbdev,
/* Search registered power models first */
struct list_head *it;
- list_for_each(it, &kbdev->ipa_power_models) {
+ lockdep_assert_held(&kbdev->ipa.lock);
+
+ list_for_each(it, &kbdev->ipa.power_models) {
struct kbase_ipa_model *model =
list_entry(it,
struct kbase_ipa_model,
@@ -70,17 +106,13 @@ struct kbase_ipa_model *kbase_ipa_get_model(struct kbase_device *kbdev,
void kbase_ipa_model_use_fallback_locked(struct kbase_device *kbdev)
{
- lockdep_assert_held(&kbdev->hwaccess_lock);
- if (kbdev->ipa_current_model != kbdev->ipa_fallback_model)
- kbdev->ipa_current_model = kbdev->ipa_fallback_model;
+ atomic_set(&kbdev->ipa_use_configured_model, false);
}
void kbase_ipa_model_use_configured_locked(struct kbase_device *kbdev)
{
- lockdep_assert_held(&kbdev->hwaccess_lock);
- if (kbdev->ipa_current_model != kbdev->ipa_configured_model)
- kbdev->ipa_current_model = kbdev->ipa_configured_model;
+ atomic_set(&kbdev->ipa_use_configured_model, true);
}
const char *kbase_ipa_model_name_from_id(u32 gpu_id)
@@ -91,41 +123,218 @@ const char *kbase_ipa_model_name_from_id(u32 gpu_id)
if (GPU_ID_IS_NEW_FORMAT(prod_id)) {
switch (GPU_ID2_MODEL_MATCH_VALUE(prod_id)) {
case GPU_ID2_PRODUCT_TMIX:
- return "generic_ipa_model";
+ return KBASE_IPA_FALLBACK_MODEL_NAME;
default:
- return "generic_ipa_model";
+ return KBASE_IPA_FALLBACK_MODEL_NAME;
}
}
- return "generic_ipa_model";
+ return KBASE_IPA_FALLBACK_MODEL_NAME;
+}
+
+static struct device_node *get_model_dt_node(struct kbase_ipa_model *model)
+{
+ struct device_node *model_dt_node;
+ char compat_string[64];
+
+ snprintf(compat_string, sizeof(compat_string), "arm,%s",
+ model->ops->name);
+
+ model_dt_node = of_find_compatible_node(model->kbdev->dev->of_node,
+ NULL, compat_string);
+ if (!model_dt_node) {
+ dev_warn(model->kbdev->dev,
+ "Couldn't find power_model DT node matching \'%s\'\n",
+ compat_string);
+ }
+
+ return model_dt_node;
+}
+
+int kbase_ipa_model_add_param_u32_def(struct kbase_ipa_model *model,
+ const char *name, u32 *addr,
+ bool has_default, u32 default_value)
+{
+ int err;
+ struct device_node *model_dt_node = get_model_dt_node(model);
+
+ err = of_property_read_u32(model_dt_node, name, addr);
+
+ if (err && !has_default) {
+ dev_err(model->kbdev->dev,
+ "No DT entry or default found for %s.%s, err = %d\n",
+ model->ops->name, name, err);
+ goto exit;
+ } else if (err && has_default) {
+ *addr = default_value;
+ dev_dbg(model->kbdev->dev, "%s.%s = %u (default)\n",
+ model->ops->name, name, *addr);
+ err = 0;
+ } else /* !err */ {
+ dev_dbg(model->kbdev->dev, "%s.%s = %u (DT)\n",
+ model->ops->name, name, *addr);
+ }
+
+ err = kbase_ipa_model_param_add(model, name, addr, sizeof(u32),
+ PARAM_TYPE_U32);
+exit:
+ return err;
+}
+
+int kbase_ipa_model_add_param_s32_array(struct kbase_ipa_model *model,
+ const char *name, s32 *addr,
+ size_t num_elems)
+{
+ int err, i;
+ struct device_node *model_dt_node = get_model_dt_node(model);
+
+ err = of_property_read_u32_array(model_dt_node, name, addr, num_elems);
+
+ if (err) {
+ dev_err(model->kbdev->dev,
+ "No DT entry found for %s.%s, err = %d\n",
+ model->ops->name, name, err);
+ goto exit;
+ } else {
+ for (i = 0; i < num_elems; ++i)
+ dev_dbg(model->kbdev->dev, "%s.%s[%u] = %d (DT)\n",
+ model->ops->name, name, i, *(addr + i));
+ }
+
+ /* Create a unique debugfs entry for each element */
+ for (i = 0; i < num_elems; ++i) {
+ char elem_name[32];
+
+ snprintf(elem_name, sizeof(elem_name), "%s.%d", name, i);
+ err = kbase_ipa_model_param_add(model, elem_name, &addr[i],
+ sizeof(s32), PARAM_TYPE_S32);
+ if (err)
+ goto exit;
+ }
+exit:
+ return err;
+}
+
+int kbase_ipa_model_add_param_string(struct kbase_ipa_model *model,
+ const char *name, char *addr,
+ size_t len)
+{
+ int err;
+ struct device_node *model_dt_node = get_model_dt_node(model);
+ const char *string_prop_value;
+
+ err = of_property_read_string(model_dt_node, name,
+ &string_prop_value);
+ if (err) {
+ dev_err(model->kbdev->dev,
+ "No DT entry found for %s.%s, err = %d\n",
+ model->ops->name, name, err);
+ goto exit;
+ } else {
+ strncpy(addr, string_prop_value, len);
+ dev_dbg(model->kbdev->dev, "%s.%s = \'%s\' (DT)\n",
+ model->ops->name, name, string_prop_value);
+ }
+
+ err = kbase_ipa_model_param_add(model, name, addr, len,
+ PARAM_TYPE_STRING);
+exit:
+ return err;
}
-int kbase_ipa_model_init(struct kbase_device *kbdev)
+static void term_model(struct kbase_ipa_model *model)
+{
+ if (!model)
+ return;
+
+ lockdep_assert_held(&model->kbdev->ipa.lock);
+
+ if (model->ops->term)
+ model->ops->term(model);
+
+ kbase_ipa_model_param_free_all(model);
+}
+
+static struct kbase_ipa_model *init_model(struct kbase_device *kbdev,
+ const char *model_name)
+{
+ struct kbase_ipa_model *model;
+ int err;
+
+ lockdep_assert_held(&kbdev->ipa.lock);
+
+ model = kbase_ipa_get_model(kbdev, model_name);
+ if (!model) {
+ dev_err(kbdev->dev, "power model \'%s\' not found\n",
+ model_name);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&model->params);
+
+ err = model->ops->init(model);
+ if (err) {
+ dev_err(kbdev->dev,
+ "init of power model \'%s\' returned error %d\n",
+ model_name, err);
+ term_model(model);
+ return NULL;
+ }
+
+ err = kbase_ipa_model_recalculate(model);
+ if (err) {
+ term_model(model);
+ return NULL;
+ }
+
+ return model;
+}
+
+static void kbase_ipa_term_locked(struct kbase_device *kbdev)
+{
+ lockdep_assert_held(&kbdev->ipa.lock);
+
+ /* Clean up the models */
+ if (kbdev->ipa.configured_model != kbdev->ipa.fallback_model)
+ term_model(kbdev->ipa.configured_model);
+ term_model(kbdev->ipa.fallback_model);
+
+ /* Clean up the list */
+ if (!list_empty(&kbdev->ipa.power_models)) {
+ struct kbase_ipa_model *model_p, *model_n;
+
+ list_for_each_entry_safe(model_p, model_n, &kbdev->ipa.power_models, link) {
+ list_del(&model_p->link);
+ kfree(model_p);
+ }
+ }
+}
+
+int kbase_ipa_init(struct kbase_device *kbdev)
{
const char *model_name;
struct kbase_ipa_model *default_model = NULL;
- struct kbase_ipa_model *model = NULL;
int err;
+ mutex_init(&kbdev->ipa.lock);
+ /*
+ * Lock during init to avoid warnings from lockdep_assert_held (there
+ * shouldn't be any concurrent access yet).
+ */
+ mutex_lock(&kbdev->ipa.lock);
+
/* Add default ones to the list */
err = kbase_ipa_internal_models_append_list(kbdev);
- default_model = kbase_ipa_get_model(kbdev, "generic_ipa_model");
- /* The generic_ipa_model 'MUST' always be present.*/
+ /* The simple IPA model must *always* be present.*/
+ default_model = init_model(kbdev, KBASE_IPA_FALLBACK_MODEL_NAME);
if (!default_model) {
err = -EINVAL;
goto end;
}
- err = default_model->ops->init(default_model);
- if (err) {
- dev_err(kbdev->dev,
- "failed to init default generic power model err %d\n",
- err);
- goto end;
- }
- kbdev->ipa_fallback_model = default_model;
+ kbdev->ipa.fallback_model = default_model;
err = of_property_read_string(kbdev->dev->of_node,
"ipa-model",
&model_name);
@@ -137,63 +346,43 @@ int kbase_ipa_model_init(struct kbase_device *kbdev)
model_name = kbase_ipa_model_name_from_id(gpu_id);
}
- if (strcmp("generic_ipa_model", model_name) != 0) {
-
- model = kbase_ipa_get_model(kbdev, model_name);
- kbdev->ipa_configured_model = model;
-
- if (model) {
- kbdev->ipa_current_model = model;
- err = model->ops->init(model);
+ if (strcmp(KBASE_IPA_FALLBACK_MODEL_NAME, model_name) != 0) {
+ kbdev->ipa.configured_model = init_model(kbdev, model_name);
+ if (!kbdev->ipa.configured_model) {
+ err = -EINVAL;
goto end;
}
- dev_err(kbdev->dev,
- "Failed to find IPA model matching: %s\n",
- model_name);
- err = -EINVAL;
} else {
-
- kbdev->ipa_current_model = default_model;
- kbdev->ipa_configured_model = default_model;
- dev_dbg(kbdev->dev, "Using generic-ipa-model by default\n");
+ kbdev->ipa.configured_model = default_model;
err = 0;
}
+
+ kbase_ipa_model_use_configured_locked(kbdev);
+
end:
if (err)
- kbase_ipa_model_term(kbdev);
-
+ kbase_ipa_term_locked(kbdev);
+ else
+ dev_info(kbdev->dev,
+ "Using configured power model %s, and fallback %s\n",
+ kbdev->ipa.fallback_model->ops->name,
+ kbdev->ipa.configured_model->ops->name);
+
+ mutex_unlock(&kbdev->ipa.lock);
return err;
}
-void kbase_ipa_model_term(struct kbase_device *kbdev)
+void kbase_ipa_term(struct kbase_device *kbdev)
{
- /* Clean up the models */
- struct kbase_ipa_model *model = kbdev->ipa_configured_model;
-
- if (model) {
- if (model->ops->term)
- model->ops->term(model);
- /* Always terminate the default model,
- * unless it was the configured model */
- if (model != kbdev->ipa_fallback_model)
- kbdev->ipa_fallback_model->ops->term(model);
- }
- /* Clean up the list */
- if (!list_empty(&kbdev->ipa_power_models)) {
- struct kbase_ipa_model *model_p, *model_n;
-
- list_for_each_entry_safe(model_p, model_n, &kbdev->ipa_power_models, link) {
- list_del(&model_p->link);
- kfree(model_p);
- }
- }
-
+ mutex_lock(&kbdev->ipa.lock);
+ kbase_ipa_term_locked(kbdev);
+ mutex_unlock(&kbdev->ipa.lock);
}
/**
- * kbase_scale_power() - Scale a model-specific power coefficient to an OPP
- * @c: Model coefficient, in pW/(Hz V^2). Should be in range
- * 0 < c < 2^16 to prevent overflow.
+ * kbase_scale_dynamic_power() - Scale a dynamic power coefficient to an OPP
+ * @c: Dynamic model coefficient, in pW/(Hz V^2). Should be in range
+ * 0 < c < 2^26 to prevent overflow.
* @freq: Frequency, in Hz. Range: 2^23 < freq < 2^30 (~8MHz to ~1GHz)
* @voltage: Voltage, in mV. Range: 2^9 < voltage < 2^13 (~0.5V to ~8V)
*
@@ -204,9 +393,9 @@ void kbase_ipa_model_term(struct kbase_device *kbdev)
*
* Return: Power consumption, in mW. Range: 0 < p < 2^13 (0W to ~8W)
*/
-static inline unsigned long kbase_scale_power(const unsigned long c,
- const unsigned long freq,
- const unsigned long voltage)
+static inline unsigned long kbase_scale_dynamic_power(const unsigned long c,
+ const unsigned long freq,
+ const unsigned long voltage)
{
/* Range: 2^8 < v2 < 2^16 m(V^2) */
const unsigned long v2 = (voltage * voltage) / 1000;
@@ -220,38 +409,89 @@ static inline unsigned long kbase_scale_power(const unsigned long c,
/* Range: 2^1 < v2f < 2^16 MHz V^2 */
const unsigned long v2f = v2f_big / 1000;
- /* Range (working backwards from next line): 0 < v2fc < 2^23 uW */
- const unsigned long v2fc = c * v2f;
+ /* Range (working backwards from next line): 0 < v2fc < 2^23 uW.
+ * Must be < 2^42 to avoid overflowing the return value. */
+ const u64 v2fc = (u64) c * (u64) v2f;
/* Range: 0 < v2fc / 1000 < 2^13 mW */
return v2fc / 1000;
}
+/**
+ * kbase_scale_static_power() - Scale a static power coefficient to an OPP
+ * @c: Static model coefficient, in uW/V^3. Should be in range
+ * 0 < c < 2^32 to prevent overflow.
+ * @voltage: Voltage, in mV. Range: 2^9 < voltage < 2^13 (~0.5V to ~8V)
+ *
+ * Return: Power consumption, in mW. Range: 0 < p < 2^13 (0W to ~8W)
+ */
+unsigned long kbase_scale_static_power(const unsigned long c,
+ const unsigned long voltage)
+{
+ /* Range: 2^8 < v2 < 2^16 m(V^2) */
+ const unsigned long v2 = (voltage * voltage) / 1000;
+
+ /* Range: 2^17 < v3_big < 2^29 m(V^2) mV */
+ const unsigned long v3_big = v2 * voltage;
+
+ /* Range: 2^7 < v3 < 2^19 m(V^3) */
+ const unsigned long v3 = v3_big / 1000;
+
+ /*
+ * Range (working backwards from next line): 0 < v3c_big < 2^33 nW.
+ * The result should be < 2^52 to avoid overflowing the return value.
+ */
+ const u64 v3c_big = (u64) c * (u64) v3;
+
+ /* Range: 0 < v3c_big / 1000000 < 2^13 mW */
+ return v3c_big / 1000000;
+}
+
+static struct kbase_ipa_model *get_current_model(struct kbase_device *kbdev)
+{
+ lockdep_assert_held(&kbdev->ipa.lock);
+
+ if (atomic_read(&kbdev->ipa_use_configured_model))
+ return kbdev->ipa.configured_model;
+ else
+ return kbdev->ipa.fallback_model;
+}
+
#ifdef CONFIG_MALI_PWRSOFT_765
static unsigned long kbase_get_static_power(struct devfreq *df,
unsigned long voltage)
#else
static unsigned long kbase_get_static_power(unsigned long voltage)
-
#endif
{
struct kbase_ipa_model *model;
+ unsigned long power_coeff = 0, power = 0;
#ifdef CONFIG_MALI_PWRSOFT_765
struct kbase_device *kbdev = dev_get_drvdata(&df->dev);
#else
struct kbase_device *kbdev = kbase_find_device(-1);
#endif
- /* We make sure that the model we access is the correct one */
- model = ACCESS_ONCE(kbdev->ipa_current_model);
+ mutex_lock(&kbdev->ipa.lock);
+
+ model = get_current_model(kbdev);
+
+ if (model) {
+ power_coeff = model->ops->get_static_power(model);
+ power = kbase_scale_static_power(power_coeff, voltage);
+ } else {
+ dev_err(kbdev->dev, "%s: No current IPA model set", __func__);
+ }
+
+ kbdev->ipa.last_static_power_coeff = power_coeff;
+
+ mutex_unlock(&kbdev->ipa.lock);
#ifndef CONFIG_MALI_PWRSOFT_765
kbase_release_device(kbdev);
#endif
- if (model)
- return model->ops->get_static_power(model, voltage);
- return 0;
+ return power;
}
#ifdef CONFIG_MALI_PWRSOFT_765
@@ -264,43 +504,83 @@ static unsigned long kbase_get_dynamic_power(unsigned long freq,
#endif
{
struct kbase_ipa_model *model;
+ unsigned long power_coeff = 0, power = 0;
#ifdef CONFIG_MALI_PWRSOFT_765
struct kbase_device *kbdev = dev_get_drvdata(&df->dev);
#else
struct kbase_device *kbdev = kbase_find_device(-1);
#endif
- /* We make sure that the model we access is the correct one */
- model = ACCESS_ONCE(kbdev->ipa_current_model);
+ mutex_lock(&kbdev->ipa.lock);
-#ifndef CONFIG_MALI_PWRSOFT_765
- kbase_release_device(kbdev);
-#endif
+ model = get_current_model(kbdev);
if (model) {
- const unsigned long c = model->ops->get_dynamic_power(model);
-
- return kbase_scale_power(c, freq, voltage);
+ power_coeff = model->ops->get_dynamic_power(model);
+ power = kbase_scale_dynamic_power(power_coeff, freq, voltage);
+ } else {
+ dev_err(kbdev->dev, "%s: No current IPA model set", __func__);
}
- return 0;
+ kbdev->ipa.last_model_dyn_power_coeff = power_coeff;
+
+ mutex_unlock(&kbdev->ipa.lock);
+
+#ifndef CONFIG_MALI_PWRSOFT_765
+ kbase_release_device(kbdev);
+#endif
+
+ return power;
}
-#ifdef CONFIG_MALI_PWRSOFT_765
unsigned long kbase_power_to_state(struct devfreq *df, u32 target_power)
{
- struct kbase_ipa_model *model;
struct kbase_device *kbdev = dev_get_drvdata(&df->dev);
+ struct device *dev = df->dev.parent;
+ unsigned long i, state = -1;
+ unsigned long dyn_coeff, static_coeff;
- /* We make sure that the model we access is the correct one */
- model = ACCESS_ONCE(kbdev->ipa_current_model);
+ mutex_lock(&kbdev->ipa.lock);
- if (model && model->ops->power_to_state)
- return model->ops->power_to_state(model, target_power);
+ dyn_coeff = kbdev->ipa.last_model_dyn_power_coeff;
+ static_coeff = kbdev->ipa.last_static_power_coeff;
- return 0;
+ mutex_unlock(&kbdev->ipa.lock);
+
+ /* OPPs are sorted from highest frequency to lowest */
+ for (i = 0; i < df->profile->max_state - 1; i++) {
+ struct dev_pm_opp *opp;
+ unsigned int freq;
+ unsigned long dyn_power, static_power, voltage;
+
+ freq = df->profile->freq_table[i]; /* Hz */
+
+ rcu_read_lock();
+ opp = dev_pm_opp_find_freq_exact(dev, freq, true);
+ /* Allow unavailable frequencies too in case we can enable a
+ * higher one. */
+ if (PTR_ERR(opp) == -ERANGE)
+ opp = dev_pm_opp_find_freq_exact(dev, freq, false);
+
+ if (IS_ERR(opp)) {
+ rcu_read_unlock();
+ return PTR_ERR(opp);
+ }
+
+ voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */
+ rcu_read_unlock();
+
+ dyn_power = kbase_scale_dynamic_power(dyn_coeff, freq, voltage);
+ static_power = kbase_scale_static_power(static_coeff, voltage);
+
+ if (target_power >= dyn_power + static_power)
+ break;
+ }
+ state = i;
+
+ return state;
}
-#endif
+KBASE_EXPORT_TEST_API(kbase_power_to_state);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
struct devfreq_cooling_ops power_model_ops = {
@@ -309,6 +589,9 @@ struct devfreq_cooling_power power_model_ops = {
#endif
.get_static_power = &kbase_get_static_power,
.get_dynamic_power = &kbase_get_dynamic_power,
+#ifdef CONFIG_MALI_PWRSOFT_765
+ .power2state = &kbase_power_to_state,
+#endif
};
unsigned long kbase_ipa_dynamic_power(struct kbase_device *kbdev,
@@ -323,5 +606,17 @@ unsigned long kbase_ipa_dynamic_power(struct kbase_device *kbdev,
return kbase_get_dynamic_power(freq, voltage);
#endif
}
-
KBASE_EXPORT_TEST_API(kbase_ipa_dynamic_power);
+
+unsigned long kbase_ipa_static_power(struct kbase_device *kbdev,
+ unsigned long voltage)
+{
+#ifdef CONFIG_MALI_PWRSOFT_765
+ struct devfreq *df = kbdev->devfreq;
+
+ return kbase_get_static_power(df, voltage);
+#else
+ return kbase_get_static_power(voltage);
+#endif
+}
+KBASE_EXPORT_TEST_API(kbase_ipa_static_power);
diff --git a/mali_kbase/ipa/mali_kbase_ipa.h b/mali_kbase/ipa/mali_kbase_ipa.h
index 67e0270..540d34a 100644
--- a/mali_kbase/ipa/mali_kbase_ipa.h
+++ b/mali_kbase/ipa/mali_kbase_ipa.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -23,53 +23,92 @@ struct kbase_ipa_model {
struct kbase_device *kbdev;
void *model_data;
struct kbase_ipa_model_ops *ops;
+ struct list_head params;
};
+int kbase_ipa_model_add_param_u32_def(struct kbase_ipa_model *model,
+ const char *name, u32 *addr,
+ bool has_default, u32 default_value);
+
+int kbase_ipa_model_add_param_s32_array(struct kbase_ipa_model *model,
+ const char *name, s32 *addr,
+ size_t num_elems);
+
+int kbase_ipa_model_add_param_string(struct kbase_ipa_model *model,
+ const char *name, char *addr,
+ size_t len);
+
+#define kbase_ipa_model_add_param_u32(MODEL, NAME, ADDR) \
+ kbase_ipa_model_add_param_u32_def((MODEL), (NAME), (ADDR), \
+ false, 0)
+
struct kbase_ipa_model_ops {
char *name;
- /* The init and term ops on the default model are always called.
- * However, all the other models are only invoked if the model
+ /* The init, recalculate and term ops on the default model are always
+ * called. However, all the other models are only invoked if the model
* is selected in the device tree. Otherwise they are never
- * initialized. Additional resources can be acquired by models
- * in init(), however they must be terminated in the term().
+ * initialized. Additional resources can be acquired by models in
+ * init(), however they must be terminated in the term().
*/
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. */
+ int (*recalculate)(struct kbase_ipa_model *model);
void (*term)(struct kbase_ipa_model *model);
/* get_dynamic_power() - return a coefficient with units pW/(Hz V^2),
* which is scaled by the IPA framework according to the current OPP's
* frequency and voltage. */
unsigned long (*get_dynamic_power)(struct kbase_ipa_model *model);
- /* get_static_power() - return an estimate of the current static power
- * consumption, in mW, based on the current OPP's voltage, in mV. */
- unsigned long (*get_static_power)(struct kbase_ipa_model *model,
- unsigned long voltage);
- unsigned long (*power_to_state)(struct kbase_ipa_model *model,
- unsigned long power);
+ /* get_static_power() - return a coefficient with units uW/(V^3),
+ * which is scaled by the IPA framework according to the current OPP's
+ * voltage. */
+ unsigned long (*get_static_power)(struct kbase_ipa_model *model);
};
/* Models can be registered only in the platform's platform_init_func call */
int kbase_ipa_model_ops_register(struct kbase_device *kbdev,
struct kbase_ipa_model_ops *new_model_ops);
-int kbase_ipa_model_init(struct kbase_device *kbdev);
-void kbase_ipa_model_term(struct kbase_device *kbdev);
+int kbase_ipa_init(struct kbase_device *kbdev);
+void kbase_ipa_term(struct kbase_device *kbdev);
void kbase_ipa_model_use_fallback_locked(struct kbase_device *kbdev);
void kbase_ipa_model_use_configured_locked(struct kbase_device *kbdev);
+int kbase_ipa_model_recalculate(struct kbase_ipa_model *model);
-extern struct kbase_ipa_model_ops kbase_generic_ipa_model_ops;
+extern struct kbase_ipa_model_ops kbase_simple_ipa_model_ops;
/**
- * kbase_ipa_dynamic_power - calculate power
- * @kbdev: kbase device
- * @freq: frequency in Hz
- * @voltage: voltage in mV
+ * kbase_ipa_dynamic_power() - Calculate dynamic power component
+ * @kbdev: Pointer to kbase device.
+ * @freq: Frequency, in Hz.
+ * @voltage: Voltage, in mV.
*
- * Return: returns power consumption
+ * Return: Dynamic power consumption, in mW.
*/
unsigned long kbase_ipa_dynamic_power(struct kbase_device *kbdev,
- unsigned long freq,
- unsigned long voltage);
+ unsigned long freq,
+ unsigned long voltage);
+
+/**
+ * kbase_ipa_static_power() - Calculate static power component
+ * @kbdev: Pointer to kbase device.
+ * @voltage: Voltage, in mV.
+ *
+ * Return: Static power consumption, in mW.
+ */
+unsigned long kbase_ipa_static_power(struct kbase_device *kbdev,
+ unsigned long voltage);
+/**
+ * kbase_power_to_state() - Find the OPP which consumes target_power
+ * @df: Pointer to devfreq device.
+ * @target_power: Maximum power consumption, in mW.
+ *
+ * Return: The index of the most performant OPP whose power consumption is less
+ * than target_power.
+ */
+unsigned long kbase_power_to_state(struct devfreq *df, u32 target_power);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
extern struct devfreq_cooling_ops power_model_ops;
diff --git a/mali_kbase/ipa/mali_kbase_ipa_debugfs.c b/mali_kbase/ipa/mali_kbase_ipa_debugfs.c
new file mode 100644
index 0000000..78bdcef
--- /dev/null
+++ b/mali_kbase/ipa/mali_kbase_ipa_debugfs.c
@@ -0,0 +1,237 @@
+/*
+ *
+ * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+
+#include "mali_kbase.h"
+#include "mali_kbase_ipa.h"
+#include "mali_kbase_ipa_debugfs.h"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
+#define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE
+#endif
+
+struct kbase_ipa_model_param {
+ char *name;
+ union {
+ void *voidp;
+ u32 *u32p;
+ s32 *s32p;
+ char *str;
+ } addr;
+ size_t size;
+ enum kbase_ipa_model_param_type type;
+ struct kbase_ipa_model *model;
+ struct list_head link;
+};
+
+static int param_int_get(void *data, u64 *val)
+{
+ struct kbase_ipa_model_param *param = data;
+
+ mutex_lock(&param->model->kbdev->ipa.lock);
+ if (param->type == PARAM_TYPE_S32)
+ *(s64 *) val = *param->addr.s32p;
+ else
+ *val = *param->addr.u32p;
+ mutex_unlock(&param->model->kbdev->ipa.lock);
+
+ return 0;
+}
+
+static int param_int_set(void *data, u64 val)
+{
+ struct kbase_ipa_model_param *param = data;
+ struct kbase_ipa_model *model = param->model;
+ s64 sval = (s64) val;
+ int err = 0;
+
+ switch (param->type) {
+ case PARAM_TYPE_U32:
+ if (sval < 0 || val > U32_MAX)
+ return -ERANGE;
+ break;
+ case PARAM_TYPE_S32:
+ if (sval < S32_MIN || sval > S32_MAX)
+ return -ERANGE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mutex_lock(&param->model->kbdev->ipa.lock);
+ *param->addr.u32p = val;
+ err = kbase_ipa_model_recalculate(model);
+ mutex_unlock(&param->model->kbdev->ipa.lock);
+
+ return err;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_u32, param_int_get, param_int_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_s32, param_int_get, param_int_set, "%lld\n");
+
+static ssize_t param_string_get(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct kbase_ipa_model_param *param = file->private_data;
+ ssize_t ret;
+ size_t len;
+
+ mutex_lock(&param->model->kbdev->ipa.lock);
+ len = strnlen(param->addr.str, param->size - 1) + 1;
+ ret = simple_read_from_buffer(user_buf, count, ppos,
+ param->addr.str, len);
+ mutex_unlock(&param->model->kbdev->ipa.lock);
+
+ return ret;
+}
+
+static ssize_t param_string_set(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct kbase_ipa_model_param *param = file->private_data;
+ struct kbase_ipa_model *model = param->model;
+ ssize_t ret = count;
+ size_t buf_size;
+ int err;
+
+ mutex_lock(&model->kbdev->ipa.lock);
+
+ if (count > param->size) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ buf_size = min(param->size - 1, count);
+ if (copy_from_user(param->addr.str, user_buf, buf_size)) {
+ ret = -EFAULT;
+ goto end;
+ }
+
+ param->addr.str[buf_size] = '\0';
+
+ err = kbase_ipa_model_recalculate(model);
+ if (err < 0)
+ ret = err;
+
+end:
+ mutex_unlock(&model->kbdev->ipa.lock);
+
+ return ret;
+}
+
+static const struct file_operations fops_string = {
+ .read = param_string_get,
+ .write = param_string_set,
+ .open = simple_open,
+ .llseek = default_llseek,
+};
+
+int kbase_ipa_model_param_add(struct kbase_ipa_model *model, const char *name,
+ void *addr, size_t size,
+ enum kbase_ipa_model_param_type type)
+{
+ struct kbase_ipa_model_param *param;
+
+ param = kzalloc(sizeof(*param), GFP_KERNEL);
+
+ if (!param)
+ return -ENOMEM;
+
+ /* 'name' is stack-allocated for array elements, so copy it into
+ * heap-allocated storage */
+ param->name = kstrdup(name, GFP_KERNEL);
+ param->addr.voidp = addr;
+ param->size = size;
+ param->type = type;
+ param->model = model;
+
+ list_add(&param->link, &model->params);
+
+ return 0;
+}
+
+void kbase_ipa_model_param_free_all(struct kbase_ipa_model *model)
+{
+ struct kbase_ipa_model_param *param_p, *param_n;
+
+ list_for_each_entry_safe(param_p, param_n, &model->params, link) {
+ list_del(&param_p->link);
+ kfree(param_p->name);
+ kfree(param_p);
+ }
+}
+
+static void kbase_ipa_model_debugfs_init(struct kbase_ipa_model *model)
+{
+ struct list_head *it;
+ struct dentry *dir;
+
+ lockdep_assert_held(&model->kbdev->ipa.lock);
+
+ dir = debugfs_create_dir(model->ops->name,
+ model->kbdev->mali_debugfs_directory);
+
+ if (!dir) {
+ dev_err(model->kbdev->dev,
+ "Couldn't create mali debugfs %s directory",
+ model->ops->name);
+ return;
+ }
+
+ list_for_each(it, &model->params) {
+ struct kbase_ipa_model_param *param =
+ list_entry(it,
+ struct kbase_ipa_model_param,
+ link);
+ const struct file_operations *fops = NULL;
+
+ switch (param->type) {
+ case PARAM_TYPE_S32:
+ fops = &fops_s32;
+ break;
+ case PARAM_TYPE_U32:
+ fops = &fops_u32;
+ break;
+ case PARAM_TYPE_STRING:
+ fops = &fops_string;
+ break;
+ }
+
+ if (unlikely(!fops)) {
+ dev_err(model->kbdev->dev,
+ "Type not set for %s parameter %s\n",
+ model->ops->name, param->name);
+ } else {
+ debugfs_create_file(param->name, S_IRUGO | S_IWUSR,
+ dir, param, fops);
+ }
+ }
+}
+
+void kbase_ipa_debugfs_init(struct kbase_device *kbdev)
+{
+ mutex_lock(&kbdev->ipa.lock);
+
+ if (kbdev->ipa.configured_model != kbdev->ipa.fallback_model)
+ kbase_ipa_model_debugfs_init(kbdev->ipa.configured_model);
+ kbase_ipa_model_debugfs_init(kbdev->ipa.fallback_model);
+
+ mutex_unlock(&kbdev->ipa.lock);
+}
diff --git a/mali_kbase/ipa/mali_kbase_ipa_debugfs.h b/mali_kbase/ipa/mali_kbase_ipa_debugfs.h
new file mode 100644
index 0000000..d7fc908
--- /dev/null
+++ b/mali_kbase/ipa/mali_kbase_ipa_debugfs.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#ifndef _KBASE_IPA_DEBUGFS_H_
+#define _KBASE_IPA_DEBUGFS_H_
+
+enum kbase_ipa_model_param_type {
+ PARAM_TYPE_S32 = 1,
+ PARAM_TYPE_U32,
+ PARAM_TYPE_STRING,
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+void kbase_ipa_debugfs_init(struct kbase_device *kbdev);
+int kbase_ipa_model_param_add(struct kbase_ipa_model *model, const char *name,
+ void *addr, size_t size,
+ enum kbase_ipa_model_param_type type);
+void kbase_ipa_model_param_free_all(struct kbase_ipa_model *model);
+
+#else /* CONFIG_DEBUG_FS */
+
+static inline int kbase_ipa_model_param_add(struct kbase_ipa_model *model,
+ const char *name, void *addr,
+ size_t size,
+ enum kbase_ipa_model_param_type type)
+{
+ return 0;
+}
+
+static inline void kbase_ipa_model_param_free_all(struct kbase_ipa_model *model)
+{ }
+
+#endif /* CONFIG_DEBUG_FS */
+
+#endif /* _KBASE_IPA_DEBUGFS_H_ */
diff --git a/mali_kbase/ipa/mali_kbase_ipa_generic.c b/mali_kbase/ipa/mali_kbase_ipa_generic.c
deleted file mode 100644
index 18fb2b2..0000000
--- a/mali_kbase/ipa/mali_kbase_ipa_generic.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- *
- * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
- *
- * This program is free software and is provided to you under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation, and any use by you of this program is subject to the terms
- * of such GNU licence.
- *
- * A copy of the licence is included with the program, and can also be obtained
- * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-
-
-#include <linux/thermal.h>
-#ifdef CONFIG_DEVFREQ_THERMAL
-#include <linux/devfreq_cooling.h>
-#endif
-#include <linux/of.h>
-
-#include "mali_kbase.h"
-#include "mali_kbase_defs.h"
-
-/*
- * This model is primarily designed for the Juno platform. It may not be
- * suitable for other platforms. The additional resources in this model
- * should preferably be minimal, as this model is rarely used when a dynamic
- * model is available.
- */
-
-/**
- * struct kbase_ipa_model_generic_data - IPA context per device
- * @dynamic_coefficient: dynamic coefficient of the model
- * @static_coefficient: static coefficient of the model
- * @ts: ts of the model
- * @gpu_tz: thermal zone device
- * @ipa_lock: protects the entire IPA context
- */
-
-struct kbase_ipa_model_generic_data {
- u32 dynamic_coefficient;
- u32 static_coefficient;
- s32 ts[4];
- struct thermal_zone_device *gpu_tz;
- struct mutex ipa_lock;
-};
-#define FALLBACK_STATIC_TEMPERATURE 55000
-
-static unsigned long model_static_power(struct kbase_ipa_model *model,
- unsigned long voltage)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
- unsigned long temperature;
-#else
- int temperature;
-#endif
- unsigned long temp;
- unsigned long temp_squared, temp_cubed, temp_scaling_factor;
- const unsigned long voltage_cubed = (voltage * voltage * voltage) >> 10;
- struct kbase_ipa_model_generic_data *model_data =
- (struct kbase_ipa_model_generic_data *) model->model_data;
- struct thermal_zone_device *gpu_tz = model_data->gpu_tz;
-
- if (gpu_tz) {
- int ret;
-
- ret = gpu_tz->ops->get_temp(gpu_tz, &temperature);
- if (ret) {
- pr_warn_ratelimited("Error reading temperature for gpu thermal zone: %d\n",
- ret);
- temperature = FALLBACK_STATIC_TEMPERATURE;
- }
- } else {
- temperature = FALLBACK_STATIC_TEMPERATURE;
- }
-
- /* Calculate the temperature scaling factor. To be applied to the
- * voltage scaled power.
- */
- temp = temperature / 1000;
- temp_squared = temp * temp;
- temp_cubed = temp_squared * temp;
- temp_scaling_factor =
- (model_data->ts[3] * temp_cubed)
- + (model_data->ts[2] * temp_squared)
- + (model_data->ts[1] * temp)
- + model_data->ts[0];
-
- return (((model_data->static_coefficient * voltage_cubed) >> 20)
- * temp_scaling_factor)
- / 1000000;
-}
-
-static unsigned long model_dynamic_power(struct kbase_ipa_model *model)
-{
- struct kbase_ipa_model_generic_data *model_data =
- (struct kbase_ipa_model_generic_data *) model->model_data;
-
- return model_data->dynamic_coefficient;
-}
-
-static int kbase_generic_power_model_init(struct kbase_ipa_model *model)
-{
- struct kbase_device *kbdev = model->kbdev;
- struct device_node *power_model_node;
- const char *tz_name;
- u32 static_power, dynamic_power;
- u32 voltage, voltage_squared, voltage_cubed, frequency;
- struct kbase_ipa_model_generic_data *model_data;
- int err;
-
- model_data = kzalloc(sizeof(struct kbase_ipa_model_generic_data),
- GFP_KERNEL);
-
- if (!model_data)
- return -ENOMEM;
-
- power_model_node = of_get_child_by_name(kbdev->dev->of_node,
- "power_model");
- if (!power_model_node) {
- dev_err(kbdev->dev, "could not find power_model node\n");
- err = -ENODEV;
- goto error;
- }
- if (!of_device_is_compatible(power_model_node,
- "arm,mali-simple-power-model")) {
- dev_err(kbdev->dev, "power_model incompatible with simple power model\n");
- err = -ENODEV;
- goto error;
- }
-
- err = of_property_read_string(power_model_node, "thermal-zone",
- &tz_name);
- if (err) {
- dev_err(kbdev->dev, "thermal zone in power_model not available\n");
- goto error;
- }
-
- model_data->gpu_tz = thermal_zone_get_zone_by_name(tz_name);
- if (IS_ERR(model_data->gpu_tz)) {
- pr_warn_ratelimited("Error getting gpu thermal zone (%ld), not yet ready?\n",
- PTR_ERR(model_data->gpu_tz));
- model_data->gpu_tz = NULL;
- err = -EPROBE_DEFER;
- goto error;
- }
-
- err = of_property_read_u32(power_model_node, "static-power",
- &static_power);
- if (err) {
- dev_err(kbdev->dev, "static-power in power_model not available\n");
- goto error;
- }
-
- err = of_property_read_u32(power_model_node, "dynamic-power",
- &dynamic_power);
- if (err) {
- dev_err(kbdev->dev, "dynamic-power in power_model not available\n");
- goto error;
- }
-
- err = of_property_read_u32(power_model_node, "voltage",
- &voltage);
- if (err) {
- dev_err(kbdev->dev, "voltage in power_model not available\n");
- goto error;
- }
-
- err = of_property_read_u32(power_model_node, "frequency",
- &frequency);
- if (err) {
- dev_err(kbdev->dev, "frequency in power_model not available\n");
- goto error;
- }
- voltage_squared = (voltage * voltage) / 1000;
- voltage_cubed = voltage * voltage * voltage;
- model_data->static_coefficient =
- (static_power << 20) / (voltage_cubed >> 10);
- model_data->dynamic_coefficient =
- (((dynamic_power * 1000) / voltage_squared) * 1000) / frequency;
-
- err = of_property_read_u32_array(power_model_node,
- "ts",
- (u32 *)model_data->ts,
- 4);
- if (err) {
- dev_err(kbdev->dev, "ts in power_model not available\n");
- goto error;
- }
-
- model->model_data = (void *) model_data;
-
- return 0;
-error:
- kfree(model_data);
- return err;
-}
-
-static void kbase_generic_power_model_term(struct kbase_ipa_model *model)
-{
- struct kbase_ipa_model_generic_data *model_data =
- (struct kbase_ipa_model_generic_data *)model->model_data;
-
- kfree(model_data);
-}
-
-struct kbase_ipa_model_ops kbase_generic_ipa_model_ops = {
- .name = "generic_ipa_model",
- .init = &kbase_generic_power_model_init,
- .term = &kbase_generic_power_model_term,
- .get_dynamic_power = &model_dynamic_power,
- .get_static_power = &model_static_power,
- .power_to_state = NULL
-};
diff --git a/mali_kbase/ipa/mali_kbase_ipa_simple.c b/mali_kbase/ipa/mali_kbase_ipa_simple.c
new file mode 100644
index 0000000..f8d46e1
--- /dev/null
+++ b/mali_kbase/ipa/mali_kbase_ipa_simple.c
@@ -0,0 +1,205 @@
+/*
+ *
+ * (C) COPYRIGHT 2016-2017 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+
+#include <linux/thermal.h>
+#ifdef CONFIG_DEVFREQ_THERMAL
+#include <linux/devfreq_cooling.h>
+#endif
+#include <linux/of.h>
+
+#include "mali_kbase.h"
+#include "mali_kbase_defs.h"
+
+/*
+ * This model is primarily designed for the Juno platform. It may not be
+ * suitable for other platforms. The additional resources in this model
+ * should preferably be minimal, as this model is rarely used when a dynamic
+ * model is available.
+ */
+
+/**
+ * struct kbase_ipa_model_simple_data - IPA context per device
+ * @dynamic_coefficient: dynamic coefficient of the model
+ * @static_coefficient: static coefficient of the model
+ * @ts: Thermal scaling coefficients of the model
+ * @tz_name: Thermal zone name
+ * @gpu_tz: thermal zone device
+ */
+
+struct kbase_ipa_model_simple_data {
+ u32 dynamic_coefficient;
+ u32 static_coefficient;
+ s32 ts[4];
+ char tz_name[16];
+ struct thermal_zone_device *gpu_tz;
+};
+#define FALLBACK_STATIC_TEMPERATURE 55000
+
+/**
+ * calculate_temp_scaling_factor() - Calculate temperature scaling coefficient
+ * @ts: Signed coefficients, in order t^0 to t^3, with units Deg^-N
+ * @t: Temperature, in mDeg C. Range: -2^17 < t < 2^17
+ *
+ * Scale the temperature according to a cubic polynomial whose coefficients are
+ * provided in the device tree. The result is used to scale the static power
+ * coefficient, where 1000000 means no change.
+ *
+ * Return: Temperature scaling factor. Approx range 0 < ret < 10,000,000.
+ */
+static u32 calculate_temp_scaling_factor(s32 ts[4], s64 t)
+{
+ /* Range: -2^24 < t2 < 2^24 m(Deg^2) */
+ const s64 t2 = (t * t) / 1000;
+
+ /* Range: -2^31 < t3 < 2^31 m(Deg^3) */
+ const s64 t3 = (t * t2) / 1000;
+
+ /*
+ * Sum the parts. t^[1-3] are in m(Deg^N), but the coefficients are in
+ * Deg^-N, so we need to multiply the last coefficient by 1000.
+ * Range: -2^63 < res_big < 2^63
+ */
+ const s64 res_big = ts[3] * t3 /* +/- 2^62 */
+ + ts[2] * t2 /* +/- 2^55 */
+ + ts[1] * t /* +/- 2^48 */
+ + ts[0] * 1000; /* +/- 2^41 */
+
+ /* Range: -2^60 < res_unclamped < 2^60 */
+ s64 res_unclamped = res_big / 1000;
+
+ /* Clamp to range of 0x to 10x the static power */
+ return clamp(res_unclamped, (s64) 0, (s64) 10000000);
+}
+
+static unsigned long model_static_power(struct kbase_ipa_model *model)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
+ unsigned long temp;
+#else
+ int temp;
+#endif
+ u32 temp_scaling_factor;
+ struct kbase_ipa_model_simple_data *model_data =
+ (struct kbase_ipa_model_simple_data *) model->model_data;
+ struct thermal_zone_device *gpu_tz = model_data->gpu_tz;
+
+ if (gpu_tz) {
+ int ret;
+
+ ret = gpu_tz->ops->get_temp(gpu_tz, &temp);
+ if (ret) {
+ pr_warn_ratelimited("Error reading temperature for gpu thermal zone: %d\n",
+ ret);
+ temp = FALLBACK_STATIC_TEMPERATURE;
+ }
+ } else {
+ temp = FALLBACK_STATIC_TEMPERATURE;
+ }
+
+ temp_scaling_factor = calculate_temp_scaling_factor(model_data->ts,
+ temp);
+
+ return (model_data->static_coefficient * temp_scaling_factor) / 1000000;
+}
+
+static unsigned long model_dynamic_power(struct kbase_ipa_model *model)
+{
+ struct kbase_ipa_model_simple_data *model_data =
+ (struct kbase_ipa_model_simple_data *) model->model_data;
+
+ return model_data->dynamic_coefficient;
+}
+
+static int add_params(struct kbase_ipa_model *model)
+{
+ int err = 0;
+ struct kbase_ipa_model_simple_data *model_data =
+ (struct kbase_ipa_model_simple_data *)model->model_data;
+
+ err = kbase_ipa_model_add_param_u32(model, "static-coefficient",
+ &model_data->static_coefficient);
+ if (err)
+ goto end;
+
+ err = kbase_ipa_model_add_param_u32(model, "dynamic-coefficient",
+ &model_data->dynamic_coefficient);
+ if (err)
+ goto end;
+
+ err = kbase_ipa_model_add_param_s32_array(model, "ts",
+ model_data->ts, 4);
+ if (err)
+ goto end;
+
+ err = kbase_ipa_model_add_param_string(model, "thermal-zone",
+ model_data->tz_name,
+ sizeof(model_data->tz_name));
+
+end:
+ return err;
+}
+
+static int kbase_simple_power_model_init(struct kbase_ipa_model *model)
+{
+ int err;
+ struct kbase_ipa_model_simple_data *model_data;
+
+ model_data = kzalloc(sizeof(struct kbase_ipa_model_simple_data),
+ GFP_KERNEL);
+ if (!model_data)
+ return -ENOMEM;
+
+ model->model_data = (void *) model_data;
+
+ err = add_params(model);
+
+ return err;
+}
+
+static int kbase_simple_power_model_recalculate(struct kbase_ipa_model *model)
+{
+ struct kbase_ipa_model_simple_data *model_data =
+ (struct kbase_ipa_model_simple_data *)model->model_data;
+
+ model_data->gpu_tz = thermal_zone_get_zone_by_name(model_data->tz_name);
+ if (IS_ERR(model_data->gpu_tz)) {
+ pr_warn_ratelimited("Error %ld getting thermal zone \'%s\', not yet ready?\n",
+ PTR_ERR(model_data->gpu_tz),
+ model_data->tz_name);
+ model_data->gpu_tz = NULL;
+ return -EPROBE_DEFER;
+ }
+
+ return 0;
+}
+
+static void kbase_simple_power_model_term(struct kbase_ipa_model *model)
+{
+ struct kbase_ipa_model_simple_data *model_data =
+ (struct kbase_ipa_model_simple_data *)model->model_data;
+
+ kfree(model_data);
+}
+
+struct kbase_ipa_model_ops kbase_simple_ipa_model_ops = {
+ .name = "mali-simple-power-model",
+ .init = &kbase_simple_power_model_init,
+ .recalculate = &kbase_simple_power_model_recalculate,
+ .term = &kbase_simple_power_model_term,
+ .get_dynamic_power = &model_dynamic_power,
+ .get_static_power = &model_static_power,
+};
diff --git a/mali_kbase/mali_base_hwconfig_features.h b/mali_kbase/mali_base_hwconfig_features.h
index 239582e..8ee19fc 100644
--- a/mali_kbase/mali_base_hwconfig_features.h
+++ b/mali_kbase/mali_base_hwconfig_features.h
@@ -246,4 +246,5 @@ static const enum base_hw_feature base_hw_features_tSIx[] = {
BASE_HW_FEATURE_END
};
+
#endif /* _BASE_HWCONFIG_FEATURES_H_ */
diff --git a/mali_kbase/mali_base_hwconfig_issues.h b/mali_kbase/mali_base_hwconfig_issues.h
index e1e43a1..53f3804 100644
--- a/mali_kbase/mali_base_hwconfig_issues.h
+++ b/mali_kbase/mali_base_hwconfig_issues.h
@@ -116,6 +116,8 @@ enum base_hw_issue {
BASE_HW_ISSUE_TMIX_8463,
BASE_HW_ISSUE_TMIX_8456,
GPUCORE_1619,
+ BASE_HW_ISSUE_TSIX_1116,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -185,6 +187,7 @@ static const enum base_hw_issue base_hw_issues_t60x_r0p0_15dev0[] = {
BASE_HW_ISSUE_T76X_1909,
BASE_HW_ISSUE_T76X_3964,
GPUCORE_1619,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -224,6 +227,7 @@ static const enum base_hw_issue base_hw_issues_t60x_r0p0_eac[] = {
BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_T76X_1909,
BASE_HW_ISSUE_T76X_3964,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -261,6 +265,7 @@ static const enum base_hw_issue base_hw_issues_t60x_r0p1[] = {
BASE_HW_ISSUE_T76X_1909,
BASE_HW_ISSUE_T76X_1963,
BASE_HW_ISSUE_T76X_3964,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -294,6 +299,7 @@ static const enum base_hw_issue base_hw_issues_t62x_r0p1[] = {
BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_T76X_1909,
BASE_HW_ISSUE_T76X_1963,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -318,6 +324,7 @@ static const enum base_hw_issue base_hw_issues_t62x_r1p0[] = {
BASE_HW_ISSUE_T76X_1909,
BASE_HW_ISSUE_T76X_1963,
BASE_HW_ISSUE_T76X_3964,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -339,6 +346,7 @@ static const enum base_hw_issue base_hw_issues_t62x_r1p1[] = {
BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_T76X_1909,
BASE_HW_ISSUE_T76X_1963,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -366,6 +374,7 @@ static const enum base_hw_issue base_hw_issues_t76x_r0p0[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -393,6 +402,7 @@ static const enum base_hw_issue base_hw_issues_t76x_r0p1[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -418,6 +428,7 @@ static const enum base_hw_issue base_hw_issues_t76x_r0p1_50rel0[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -445,6 +456,7 @@ static const enum base_hw_issue base_hw_issues_t76x_r0p2[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -470,6 +482,7 @@ static const enum base_hw_issue base_hw_issues_t76x_r0p3[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -492,6 +505,7 @@ static const enum base_hw_issue base_hw_issues_t76x_r1p0[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -511,6 +525,7 @@ static const enum base_hw_issue base_hw_issues_t72x_r0p0[] = {
BASE_HW_ISSUE_T76X_1909,
BASE_HW_ISSUE_T76X_1963,
BASE_HW_ISSUE_T76X_3964,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -531,6 +546,7 @@ static const enum base_hw_issue base_hw_issues_t72x_r1p0[] = {
BASE_HW_ISSUE_T76X_1909,
BASE_HW_ISSUE_T76X_1963,
BASE_HW_ISSUE_T76X_3964,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -551,6 +567,7 @@ static const enum base_hw_issue base_hw_issues_t72x_r1p1[] = {
BASE_HW_ISSUE_T76X_1909,
BASE_HW_ISSUE_T76X_1963,
BASE_HW_ISSUE_T76X_3964,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -645,6 +662,7 @@ static const enum base_hw_issue base_hw_issues_tFRx_r0p1[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -665,6 +683,7 @@ static const enum base_hw_issue base_hw_issues_tFRx_r0p2[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -683,6 +702,7 @@ static const enum base_hw_issue base_hw_issues_tFRx_r1p0[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -701,6 +721,7 @@ static const enum base_hw_issue base_hw_issues_tFRx_r2p0[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -736,6 +757,7 @@ static const enum base_hw_issue base_hw_issues_t86x_r0p2[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -754,6 +776,7 @@ static const enum base_hw_issue base_hw_issues_t86x_r1p0[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -772,6 +795,7 @@ static const enum base_hw_issue base_hw_issues_t86x_r2p0[] = {
BASE_HW_ISSUE_T76X_3966,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -806,6 +830,7 @@ static const enum base_hw_issue base_hw_issues_t83x_r0p1[] = {
BASE_HW_ISSUE_T76X_3960,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -825,6 +850,7 @@ static const enum base_hw_issue base_hw_issues_t83x_r1p0[] = {
BASE_HW_ISSUE_T76X_3960,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -840,6 +866,7 @@ static const enum base_hw_issue base_hw_issues_model_t83x[] = {
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
GPUCORE_1619,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -861,6 +888,7 @@ static const enum base_hw_issue base_hw_issues_t82x_r0p0[] = {
BASE_HW_ISSUE_T76X_3964,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -881,6 +909,7 @@ static const enum base_hw_issue base_hw_issues_t82x_r0p1[] = {
BASE_HW_ISSUE_T76X_3960,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -900,6 +929,7 @@ static const enum base_hw_issue base_hw_issues_t82x_r1p0[] = {
BASE_HW_ISSUE_T76X_3960,
BASE_HW_ISSUE_T76X_3979,
BASE_HW_ISSUE_TMIX_7891,
+ BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_END
};
@@ -983,6 +1013,21 @@ static const enum base_hw_issue base_hw_issues_model_tHEx[] = {
static const enum base_hw_issue base_hw_issues_tSIx_r0p0[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TMIX_8133,
+ BASE_HW_ISSUE_TSIX_1116,
+ BASE_HW_ISSUE_END
+};
+
+static const enum base_hw_issue base_hw_issues_tSIx_r0p1[] = {
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_TMIX_8133,
+ BASE_HW_ISSUE_TSIX_1116,
+ BASE_HW_ISSUE_END
+};
+
+static const enum base_hw_issue base_hw_issues_tSIx_r1p0[] = {
+ BASE_HW_ISSUE_9435,
+ BASE_HW_ISSUE_TMIX_8133,
+ BASE_HW_ISSUE_TSIX_1116,
BASE_HW_ISSUE_END
};
@@ -990,7 +1035,10 @@ static const enum base_hw_issue base_hw_issues_model_tSIx[] = {
BASE_HW_ISSUE_5736,
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TMIX_8133,
+ BASE_HW_ISSUE_TSIX_1116,
BASE_HW_ISSUE_END
};
+
+
#endif /* _BASE_HWCONFIG_ISSUES_H_ */
diff --git a/mali_kbase/mali_base_kernel.h b/mali_kbase/mali_base_kernel.h
index 0d2ac95..0c80e03 100644
--- a/mali_kbase/mali_base_kernel.h
+++ b/mali_kbase/mali_base_kernel.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase.h b/mali_kbase/mali_kbase.h
index b5a771f..2289f80 100644
--- a/mali_kbase/mali_kbase.h
+++ b/mali_kbase/mali_kbase.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_config_defaults.h b/mali_kbase/mali_kbase_config_defaults.h
index f982aa5..f6eeac8 100644
--- a/mali_kbase/mali_kbase_config_defaults.h
+++ b/mali_kbase/mali_kbase_config_defaults.h
@@ -29,16 +29,6 @@
#include <mali_kbase_config_platform.h>
/**
- * Irq throttle. It is the minimum desired time in between two
- * consecutive gpu interrupts (given in 'us'). The irq throttle
- * gpu register will be configured after this, taking into
- * account the configured max frequency.
- *
- * Attached value: number in micro seconds
- */
-#define DEFAULT_IRQ_THROTTLE_TIME_US 20
-
-/**
* Boolean indicating whether the driver is configured to be secure at
* a potential loss of performance.
*
diff --git a/mali_kbase/mali_kbase_core_linux.c b/mali_kbase/mali_kbase_core_linux.c
index 4e95633..e335c0d 100644
--- a/mali_kbase/mali_kbase_core_linux.c
+++ b/mali_kbase/mali_kbase_core_linux.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -23,6 +23,9 @@
#include <mali_kbase_mem_linux.h>
#ifdef CONFIG_MALI_DEVFREQ
#include <backend/gpu/mali_kbase_devfreq.h>
+#ifdef CONFIG_DEVFREQ_THERMAL
+#include <ipa/mali_kbase_ipa_debugfs.h>
+#endif /* CONFIG_DEVFREQ_THERMAL */
#endif /* CONFIG_MALI_DEVFREQ */
#ifdef CONFIG_MALI_NO_MALI
#include "mali_kbase_model_linux.h"
@@ -250,9 +253,9 @@ enum {
inited_vinstr = (1u << 8),
inited_job_fault = (1u << 10),
- inited_misc_register = (1u << 11),
- inited_get_device = (1u << 12),
- inited_sysfs_group = (1u << 13),
+ inited_sysfs_group = (1u << 11),
+ inited_misc_register = (1u << 12),
+ inited_get_device = (1u << 13),
inited_dev_list = (1u << 14),
inited_debugfs = (1u << 15),
inited_gpu_device = (1u << 16),
@@ -3324,7 +3327,8 @@ if (kbdev->clock != NULL) {
static void power_control_term(struct kbase_device *kbdev)
{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || \
+ defined(LSK_OPPV2_BACKPORT)
dev_pm_opp_of_remove_table(kbdev->dev);
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
of_free_opp_table(kbdev->dev);
@@ -3381,6 +3385,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_##type##_quirks, type##_quirks_get,\
MAKE_QUIRK_ACCESSORS(sc);
MAKE_QUIRK_ACCESSORS(tiler);
MAKE_QUIRK_ACCESSORS(mmu);
+MAKE_QUIRK_ACCESSORS(jm);
#endif /* KBASE_GPU_RESET_EN */
@@ -3464,6 +3469,8 @@ static int kbase_device_debugfs_init(struct kbase_device *kbdev)
kbasep_gpu_memory_debugfs_init(kbdev);
kbase_as_fault_debugfs_init(kbdev);
#if KBASE_GPU_RESET_EN
+ /* fops_* variables created by invocations of macro
+ * MAKE_QUIRK_ACCESSORS() above. */
debugfs_create_file("quirks_sc", 0644,
kbdev->mali_debugfs_directory, kbdev,
&fops_sc_quirks);
@@ -3473,6 +3480,9 @@ static int kbase_device_debugfs_init(struct kbase_device *kbdev)
debugfs_create_file("quirks_mmu", 0644,
kbdev->mali_debugfs_directory, kbdev,
&fops_mmu_quirks);
+ debugfs_create_file("quirks_jm", 0644,
+ kbdev->mali_debugfs_directory, kbdev,
+ &fops_jm_quirks);
#endif /* KBASE_GPU_RESET_EN */
#ifndef CONFIG_MALI_COH_USER
@@ -3499,6 +3509,13 @@ static int kbase_device_debugfs_init(struct kbase_device *kbdev)
kbasep_trace_timeline_debugfs_init(kbdev);
#endif /* CONFIG_MALI_TRACE_TIMELINE */
+#ifdef CONFIG_MALI_DEVFREQ
+#ifdef CONFIG_DEVFREQ_THERMAL
+ if (kbdev->inited_subsys & inited_devfreq)
+ kbase_ipa_debugfs_init(kbdev);
+#endif /* CONFIG_DEVFREQ_THERMAL */
+#endif /* CONFIG_MALI_DEVFREQ */
+
#ifdef CONFIG_DEBUG_FS
debugfs_create_file("serialize_jobs", S_IRUGO | S_IWUSR,
kbdev->mali_debugfs_directory, kbdev,
@@ -3639,10 +3656,6 @@ static int kbase_platform_device_remove(struct platform_device *pdev)
}
#endif
- if (kbdev->inited_subsys & inited_sysfs_group) {
- sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group);
- kbdev->inited_subsys &= ~inited_sysfs_group;
- }
if (kbdev->inited_subsys & inited_dev_list) {
dev_list = kbase_dev_list_get();
@@ -3656,6 +3669,11 @@ static int kbase_platform_device_remove(struct platform_device *pdev)
kbdev->inited_subsys &= ~inited_misc_register;
}
+ if (kbdev->inited_subsys & inited_sysfs_group) {
+ sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group);
+ kbdev->inited_subsys &= ~inited_sysfs_group;
+ }
+
if (kbdev->inited_subsys & inited_get_device) {
put_device(kbdev->dev);
kbdev->inited_subsys &= ~inited_get_device;
@@ -3788,7 +3806,7 @@ static int kbase_platform_device_probe(struct platform_device *pdev)
dev_set_drvdata(kbdev->dev, kbdev);
#ifdef CONFIG_DEVFREQ_THERMAL
- INIT_LIST_HEAD(&kbdev->ipa_power_models);
+ INIT_LIST_HEAD(&kbdev->ipa.power_models);
#endif
#ifdef CONFIG_MALI_NO_MALI
@@ -3851,8 +3869,6 @@ static int kbase_platform_device_probe(struct platform_device *pdev)
core_props->gpu_freq_khz_min = GPU_FREQ_KHZ_MIN;
core_props->gpu_freq_khz_max = GPU_FREQ_KHZ_MAX;
- kbdev->gpu_props.irq_throttle_time_us = DEFAULT_IRQ_THROTTLE_TIME_US;
-
err = kbase_device_init(kbdev);
if (err) {
dev_err(kbdev->dev, "Device initialization failed (%d)\n", err);
@@ -3919,12 +3935,10 @@ static int kbase_platform_device_probe(struct platform_device *pdev)
#ifdef CONFIG_MALI_DEVFREQ
err = kbase_devfreq_init(kbdev);
- if (err) {
- dev_err(kbdev->dev, "Devfreq initialization failed\n");
- kbase_platform_device_remove(pdev);
- return err;
- }
- kbdev->inited_subsys |= inited_devfreq;
+ if (!err)
+ kbdev->inited_subsys |= inited_devfreq;
+ else
+ dev_err(kbdev->dev, "Continuing without devfreq\n");
#endif /* CONFIG_MALI_DEVFREQ */
kbdev->vinstr_ctx = kbase_vinstr_init(kbdev);
@@ -3962,23 +3976,35 @@ static int kbase_platform_device_probe(struct platform_device *pdev)
kbdev->mdev.parent = get_device(kbdev->dev);
kbdev->inited_subsys |= inited_get_device;
- err = misc_register(&kbdev->mdev);
+ /* This needs to happen before registering the device with misc_register(),
+ * otherwise it causes a race condition between registering the device and a
+ * uevent event being generated for userspace, causing udev rules to run
+ * which might expect certain sysfs attributes present. As a result of the
+ * race condition we avoid, some Mali sysfs entries may have appeared to
+ * udev to not exist.
+
+ * For more information, see
+ * https://www.kernel.org/doc/Documentation/driver-model/device.txt, the
+ * paragraph that starts with "Word of warning", currently the second-last
+ * paragraph.
+ */
+ err = sysfs_create_group(&kbdev->dev->kobj, &kbase_attr_group);
if (err) {
- dev_err(kbdev->dev, "Misc device registration failed for %s\n",
- kbdev->devname);
+ dev_err(&pdev->dev, "SysFS group creation failed\n");
kbase_platform_device_remove(pdev);
return err;
}
- kbdev->inited_subsys |= inited_misc_register;
-
+ kbdev->inited_subsys |= inited_sysfs_group;
- err = sysfs_create_group(&kbdev->dev->kobj, &kbase_attr_group);
+ err = misc_register(&kbdev->mdev);
if (err) {
- dev_err(&pdev->dev, "SysFS group creation failed\n");
+ dev_err(kbdev->dev, "Misc device registration failed for %s\n",
+ kbdev->devname);
kbase_platform_device_remove(pdev);
return err;
}
- kbdev->inited_subsys |= inited_sysfs_group;
+ kbdev->inited_subsys |= inited_misc_register;
+
#ifdef CONFIG_MALI_FPGA_BUS_LOGGER
err = bl_core_client_register(kbdev->devname,
@@ -4021,9 +4047,10 @@ static int kbase_device_suspend(struct device *dev)
if (!kbdev)
return -ENODEV;
-#if defined(CONFIG_PM_DEVFREQ) && \
+#if defined(CONFIG_MALI_DEVFREQ) && \
(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
- devfreq_suspend_device(kbdev->devfreq);
+ if (kbdev->inited_subsys & inited_devfreq)
+ devfreq_suspend_device(kbdev->devfreq);
#endif
kbase_pm_suspend(kbdev);
@@ -4048,9 +4075,10 @@ static int kbase_device_resume(struct device *dev)
kbase_pm_resume(kbdev);
-#if defined(CONFIG_PM_DEVFREQ) && \
+#if defined(CONFIG_MALI_DEVFREQ) && \
(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
- devfreq_resume_device(kbdev->devfreq);
+ if (kbdev->inited_subsys & inited_devfreq)
+ devfreq_resume_device(kbdev->devfreq);
#endif
return 0;
}
@@ -4074,9 +4102,10 @@ static int kbase_device_runtime_suspend(struct device *dev)
if (!kbdev)
return -ENODEV;
-#if defined(CONFIG_PM_DEVFREQ) && \
+#if defined(CONFIG_MALI_DEVFREQ) && \
(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
- devfreq_suspend_device(kbdev->devfreq);
+ if (kbdev->inited_subsys & inited_devfreq)
+ devfreq_suspend_device(kbdev->devfreq);
#endif
if (kbdev->pm.backend.callback_power_runtime_off) {
@@ -4111,9 +4140,10 @@ static int kbase_device_runtime_resume(struct device *dev)
dev_dbg(dev, "runtime resume\n");
}
-#if defined(CONFIG_PM_DEVFREQ) && \
+#if defined(CONFIG_MALI_DEVFREQ) && \
(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
- devfreq_resume_device(kbdev->devfreq);
+ if (kbdev->inited_subsys & inited_devfreq)
+ devfreq_resume_device(kbdev->devfreq);
#endif
return ret;
diff --git a/mali_kbase/mali_kbase_defs.h b/mali_kbase/mali_kbase_defs.h
index 290d460..73f849c 100644
--- a/mali_kbase/mali_kbase_defs.h
+++ b/mali_kbase/mali_kbase_defs.h
@@ -945,6 +945,18 @@ struct kbase_mem_pool {
struct kbase_mem_pool *next_pool;
};
+/**
+ * struct kbase_devfreq_opp - Lookup table for converting between nominal OPP
+ * frequency, and real frequency and core mask
+ * @opp_freq: Nominal OPP frequency
+ * @real_freq: Real GPU frequency
+ * @core_mask: Shader core mask
+ */
+struct kbase_devfreq_opp {
+ u64 opp_freq;
+ u64 real_freq;
+ u64 core_mask;
+};
#define DEVNAME_SIZE 16
@@ -1067,9 +1079,6 @@ struct kbase_device {
struct kbase_vinstr_context *vinstr_ctx;
- /*value to be written to the irq_throttle register each time an irq is served */
- atomic_t irq_throttle_cycles;
-
#if KBASE_TRACE_ENABLE
spinlock_t trace_lock;
u16 trace_first_out;
@@ -1092,17 +1101,28 @@ struct kbase_device {
struct devfreq_dev_profile devfreq_profile;
struct devfreq *devfreq;
unsigned long current_freq;
+ unsigned long current_nominal_freq;
unsigned long current_voltage;
+ u64 current_core_mask;
+ struct kbase_devfreq_opp *opp_table;
+ int num_opps;
#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
- struct list_head ipa_power_models;
- struct kbase_ipa_model *ipa_current_model;
- struct kbase_ipa_model *ipa_configured_model;
- struct kbase_ipa_model *ipa_fallback_model;
+ /* Current IPA model - true for configured model, false for fallback */
+ atomic_t ipa_use_configured_model;
+ struct {
+ /* Access to this struct must be with ipa.lock held */
+ struct mutex lock;
+ unsigned long last_model_dyn_power_coeff;
+ unsigned long last_static_power_coeff;
+ struct list_head power_models;
+ struct kbase_ipa_model *configured_model;
+ struct kbase_ipa_model *fallback_model;
+ } ipa;
#endif
#endif
diff --git a/mali_kbase/mali_kbase_device.c b/mali_kbase/mali_kbase_device.c
index 7484eec..e53f876 100644
--- a/mali_kbase/mali_kbase_device.c
+++ b/mali_kbase/mali_kbase_device.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_gator_api.c b/mali_kbase/mali_kbase_gator_api.c
index 7c3c5f3..860e101 100644
--- a/mali_kbase/mali_kbase_gator_api.c
+++ b/mali_kbase/mali_kbase_gator_api.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_gator_hwcnt_names.h b/mali_kbase/mali_kbase_gator_hwcnt_names.h
index ce8e424..e4003f6 100644
--- a/mali_kbase/mali_kbase_gator_hwcnt_names.h
+++ b/mali_kbase/mali_kbase_gator_hwcnt_names.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -2162,4 +2162,5 @@ static const char * const hardware_counters_mali_t88x[] = {
#include "mali_kbase_gator_hwcnt_names_tsix.h"
+
#endif
diff --git a/mali_kbase/mali_kbase_gator_hwcnt_names_tsix.h b/mali_kbase/mali_kbase_gator_hwcnt_names_tsix.h
index 7ff7009..be09c45 100644
--- a/mali_kbase/mali_kbase_gator_hwcnt_names_tsix.h
+++ b/mali_kbase/mali_kbase_gator_hwcnt_names_tsix.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -191,15 +191,15 @@ static const char * const hardware_counters_mali_tSIx[] = {
"TSIx_ARITH_INSTR_DOUBLE",
"TSIx_ARITH_INSTR_MSG",
"TSIx_ARITH_INSTR_MSG_ONLY",
- "TSIx_TEX_INSTR",
- "TSIx_TEX_INSTR_MIPMAP",
- "TSIx_TEX_INSTR_COMPRESSED",
- "TSIx_TEX_INSTR_3D",
- "TSIx_TEX_INSTR_TRILINEAR",
- "TSIx_TEX_COORD_ISSUE",
- "TSIx_TEX_COORD_STALL",
- "TSIx_TEX_STARVE_CACHE",
- "TSIx_TEX_STARVE_FILTER",
+ "TSIx_TEX_MSGI_NUM_QUADS",
+ "TSIx_TEX_DFCH_NUM_PASSES",
+ "TSIx_TEX_DFCH_NUM_PASSES_MISS",
+ "TSIx_TEX_DFCH_NUM_PASSES_MIP_MAP",
+ "TSIx_TEX_TIDX_NUM_SPLIT_MIP_MAP",
+ "TSIx_TEX_TFCH_NUM_LINES_FETCHED",
+ "TSIx_TEX_TFCH_NUM_LINES_FETCHED_BLOCK_COMPRESSED",
+ "TSIx_TEX_TFCH_NUM_OPERATIONS",
+ "TSIx_TEX_FILT_NUM_OPERATIONS",
"TSIx_LS_MEM_READ_FULL",
"TSIx_LS_MEM_READ_SHORT",
"TSIx_LS_MEM_WRITE_FULL",
diff --git a/mali_kbase/mali_kbase_gpu_id.h b/mali_kbase/mali_kbase_gpu_id.h
index 5c2367f..60b4371 100644
--- a/mali_kbase/mali_kbase_gpu_id.h
+++ b/mali_kbase/mali_kbase_gpu_id.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -58,6 +58,9 @@
#define GPU_ID2_ARCH_MINOR (0xF << GPU_ID2_ARCH_MINOR_SHIFT)
#define GPU_ID2_ARCH_MAJOR (0xF << GPU_ID2_ARCH_MAJOR_SHIFT)
#define GPU_ID2_PRODUCT_MODEL (GPU_ID2_ARCH_MAJOR | GPU_ID2_PRODUCT_MAJOR)
+#define GPU_ID2_VERSION (GPU_ID2_VERSION_MAJOR | \
+ GPU_ID2_VERSION_MINOR | \
+ GPU_ID2_VERSION_STATUS)
/* Helper macro to create a partial GPU_ID (new format) that defines
a product ignoring its version. */
@@ -95,9 +98,9 @@
(((product_id) << GPU_ID2_PRODUCT_MAJOR_SHIFT) & \
GPU_ID2_PRODUCT_MODEL)
-#define GPU_ID2_PRODUCT_TMIX GPU_ID2_MODEL_MAKE(6, 0)
-#define GPU_ID2_PRODUCT_THEX GPU_ID2_MODEL_MAKE(6, 1)
-#define GPU_ID2_PRODUCT_TSIX GPU_ID2_MODEL_MAKE(7, 0)
+#define GPU_ID2_PRODUCT_TMIX GPU_ID2_MODEL_MAKE(6u, 0)
+#define GPU_ID2_PRODUCT_THEX GPU_ID2_MODEL_MAKE(6u, 1)
+#define GPU_ID2_PRODUCT_TSIX GPU_ID2_MODEL_MAKE(7u, 0)
/* Values for GPU_ID_VERSION_STATUS field for PRODUCT_ID GPU_ID_PI_T60X */
#define GPU_ID_S_15DEV0 0x1
diff --git a/mali_kbase/mali_kbase_gpuprops.c b/mali_kbase/mali_kbase_gpuprops.c
index ceba27c..fc65223 100644
--- a/mali_kbase/mali_kbase_gpuprops.c
+++ b/mali_kbase/mali_kbase_gpuprops.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_gpuprops.h b/mali_kbase/mali_kbase_gpuprops.h
index f3c95cc..44b5e9e 100644
--- a/mali_kbase/mali_kbase_gpuprops.h
+++ b/mali_kbase/mali_kbase_gpuprops.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-2015, 2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_gpuprops_types.h b/mali_kbase/mali_kbase_gpuprops_types.h
index 920cf77..b06e511 100644
--- a/mali_kbase/mali_kbase_gpuprops_types.h
+++ b/mali_kbase/mali_kbase_gpuprops_types.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -82,11 +82,6 @@ struct kbase_gpu_props {
struct kbase_gpu_mem_props mem;
struct kbase_gpu_mmu_props mmu;
- /**
- * Implementation specific irq throttle value (us), should be adjusted during integration.
- */
- int irq_throttle_time_us;
-
/* Properties shared with userspace */
base_gpu_props props;
};
diff --git a/mali_kbase/mali_kbase_hw.c b/mali_kbase/mali_kbase_hw.c
index 51a31fb..89fe0d8 100644
--- a/mali_kbase/mali_kbase_hw.c
+++ b/mali_kbase/mali_kbase_hw.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2012-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -109,16 +109,33 @@ int kbase_hw_set_issues_mask(struct kbase_device *kbdev)
issues = base_hw_issues_tMIx_r0p0;
break;
default:
- if ((gpu_id & GPU_ID2_PRODUCT_MODEL) ==
- GPU_ID2_PRODUCT_TMIX) {
+ switch (gpu_id & GPU_ID2_PRODUCT_MODEL) {
+ case GPU_ID2_PRODUCT_TMIX:
issues = base_hw_issues_tMIx_r0p0;
- } else if ((gpu_id & GPU_ID2_PRODUCT_MODEL) ==
- GPU_ID2_PRODUCT_THEX) {
+ break;
+ case GPU_ID2_PRODUCT_THEX:
issues = base_hw_issues_tHEx_r0p0;
- } else if ((gpu_id & GPU_ID2_PRODUCT_MODEL) ==
- GPU_ID2_PRODUCT_TSIX) {
- issues = base_hw_issues_tSIx_r0p0;
- } else {
+ break;
+ case GPU_ID2_PRODUCT_TSIX:
+ switch (gpu_id & (GPU_ID2_VERSION_MAJOR |
+ GPU_ID2_VERSION_MINOR)) {
+ case GPU_ID2_VERSION_MAKE(0, 0, 0):
+ issues = base_hw_issues_tSIx_r0p0;
+ break;
+ case GPU_ID2_VERSION_MAKE(0, 1, 0):
+ issues = base_hw_issues_tSIx_r0p1;
+ break;
+ case GPU_ID2_VERSION_MAKE(1, 0, 0):
+ issues = base_hw_issues_tSIx_r1p0;
+ break;
+ default:
+ dev_err(kbdev->dev,
+ "Unknown GPU ID %x",
+ gpu_id);
+ return -EINVAL;
+ }
+ break;
+ default:
dev_err(kbdev->dev,
"Unknown GPU ID %x", gpu_id);
return -EINVAL;
diff --git a/mali_kbase/mali_kbase_jd.c b/mali_kbase/mali_kbase_jd.c
index 596b047..c2a5571 100644
--- a/mali_kbase/mali_kbase_jd.c
+++ b/mali_kbase/mali_kbase_jd.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_js.c b/mali_kbase/mali_kbase_js.c
index 3a675a1..d75dcba 100644
--- a/mali_kbase/mali_kbase_js.c
+++ b/mali_kbase/mali_kbase_js.c
@@ -577,15 +577,6 @@ int kbasep_js_devdata_init(struct kbase_device * const kbdev)
dev_dbg(kbdev->dev, "Note: The JS tick timer (if coded) will still be run, but do nothing.");
#endif
- /* setup the number of irq throttle cycles base on given time */
- {
- int time_us = kbdev->gpu_props.irq_throttle_time_us;
- int cycles = kbasep_js_convert_us_to_gpu_ticks_max_freq(kbdev,
- time_us);
-
- atomic_set(&kbdev->irq_throttle_cycles, cycles);
- }
-
/* Clear the AS data, including setting NULL pointers */
memset(&jsdd->runpool_irq.per_as_data[0], 0,
sizeof(jsdd->runpool_irq.per_as_data));
diff --git a/mali_kbase/mali_kbase_js.h b/mali_kbase/mali_kbase_js.h
index 76172f7..d092fff 100644
--- a/mali_kbase/mali_kbase_js.h
+++ b/mali_kbase/mali_kbase_js.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -851,71 +851,6 @@ static inline struct kbase_context *kbasep_js_runpool_lookup_ctx_noretain(struct
return found_kctx;
}
-/**
- * This will provide a conversion from time (us) to ticks of the gpu clock
- * based on the minimum available gpu frequency.
- * This is usually good to compute best/worst case (where the use of current
- * frequency is not valid due to DVFS).
- * e.g.: when you need the number of cycles to guarantee you won't wait for
- * longer than 'us' time (you might have a shorter wait).
- */
-static inline u32 kbasep_js_convert_us_to_gpu_ticks_min_freq(struct kbase_device *kbdev, u32 us)
-{
- u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_min;
-
- KBASE_DEBUG_ASSERT(0 != gpu_freq);
- return us * (gpu_freq / 1000);
-}
-
-/**
- * This will provide a conversion from time (us) to ticks of the gpu clock
- * based on the maximum available gpu frequency.
- * This is usually good to compute best/worst case (where the use of current
- * frequency is not valid due to DVFS).
- * e.g.: When you need the number of cycles to guarantee you'll wait at least
- * 'us' amount of time (but you might wait longer).
- */
-static inline u32 kbasep_js_convert_us_to_gpu_ticks_max_freq(struct kbase_device *kbdev, u32 us)
-{
- u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_max;
-
- KBASE_DEBUG_ASSERT(0 != gpu_freq);
- return us * (u32) (gpu_freq / 1000);
-}
-
-/**
- * This will provide a conversion from ticks of the gpu clock to time (us)
- * based on the minimum available gpu frequency.
- * This is usually good to compute best/worst case (where the use of current
- * frequency is not valid due to DVFS).
- * e.g.: When you need to know the worst-case wait that 'ticks' cycles will
- * take (you guarantee that you won't wait any longer than this, but it may
- * be shorter).
- */
-static inline u32 kbasep_js_convert_gpu_ticks_to_us_min_freq(struct kbase_device *kbdev, u32 ticks)
-{
- u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_min;
-
- KBASE_DEBUG_ASSERT(0 != gpu_freq);
- return ticks / gpu_freq * 1000;
-}
-
-/**
- * This will provide a conversion from ticks of the gpu clock to time (us)
- * based on the maximum available gpu frequency.
- * This is usually good to compute best/worst case (where the use of current
- * frequency is not valid due to DVFS).
- * e.g.: When you need to know the best-case wait for 'tick' cycles (you
- * guarantee to be waiting for at least this long, but it may be longer).
- */
-static inline u32 kbasep_js_convert_gpu_ticks_to_us_max_freq(struct kbase_device *kbdev, u32 ticks)
-{
- u32 gpu_freq = kbdev->gpu_props.props.core_props.gpu_freq_khz_max;
-
- KBASE_DEBUG_ASSERT(0 != gpu_freq);
- return ticks / gpu_freq * 1000;
-}
-
/*
* The following locking conditions are made on the caller:
* - The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex.
diff --git a/mali_kbase/mali_kbase_js_defs.h b/mali_kbase/mali_kbase_js_defs.h
index 119344c..6f5feba 100644
--- a/mali_kbase/mali_kbase_js_defs.h
+++ b/mali_kbase/mali_kbase_js_defs.h
@@ -67,16 +67,6 @@ typedef void (*kbasep_js_ctx_job_cb)(struct kbase_device *kbdev, struct kbase_jd
#define KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ 2
/**
- * @brief the IRQ_THROTTLE time in microseconds
- *
- * This will be converted via the GPU's clock frequency into a cycle-count.
- *
- * @note we can make an estimate of the GPU's frequency by periodically
- * sampling its CYCLE_COUNT register
- */
-#define KBASE_JS_IRQ_THROTTLE_TIME_US 20
-
-/**
* @brief Context attributes
*
* Each context attribute can be thought of as a boolean value that caches some
diff --git a/mali_kbase/mali_kbase_mem.h b/mali_kbase/mali_kbase_mem.h
index fb4ca4d..eefb4a2 100644
--- a/mali_kbase/mali_kbase_mem.h
+++ b/mali_kbase/mali_kbase_mem.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_mem_linux.c b/mali_kbase/mali_kbase_mem_linux.c
index 503a5ec..0b3a7da 100644
--- a/mali_kbase/mali_kbase_mem_linux.c
+++ b/mali_kbase/mali_kbase_mem_linux.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_mem_linux.h b/mali_kbase/mali_kbase_mem_linux.h
index 2053a47..97e0bec 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-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010, 2012-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_softjobs.c b/mali_kbase/mali_kbase_softjobs.c
index 2997e6f..8a9a47d 100644
--- a/mali_kbase/mali_kbase_softjobs.c
+++ b/mali_kbase/mali_kbase_softjobs.c
@@ -423,13 +423,22 @@ static void kbase_fence_debug_wait_timeout(struct kbase_jd_atom *katom)
{
struct kbase_context *kctx = katom->kctx;
struct device *dev = katom->kctx->kbdev->dev;
- struct sync_fence *fence = katom->fence;
+ struct sync_fence *fence;
int timeout_ms = atomic_read(&kctx->kbdev->js_data.soft_job_timeout_ms);
- int status = kbase_fence_get_status(fence);
+ int status;
unsigned long lflags;
spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags);
+ fence = katom->fence;
+ if (!fence) {
+ /* Fence must have signaled just after timeout. */
+ spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags);
+ return;
+ }
+
+ status = kbase_fence_get_status(fence);
+
dev_warn(dev, "ctx %d_%d: Atom %d still waiting for fence [%p] after %dms\n",
kctx->tgid, kctx->id,
kbase_jd_atom_id(kctx, katom),
diff --git a/mali_kbase/mali_kbase_tlstream.c b/mali_kbase/mali_kbase_tlstream.c
index 408b9d9..aa7850a 100644
--- a/mali_kbase/mali_kbase_tlstream.c
+++ b/mali_kbase/mali_kbase_tlstream.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_tlstream.h b/mali_kbase/mali_kbase_tlstream.h
index 7349ab2..69e188e 100644
--- a/mali_kbase/mali_kbase_tlstream.h
+++ b/mali_kbase/mali_kbase_tlstream.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2015-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_kbase_uku.h b/mali_kbase/mali_kbase_uku.h
index baa9296..3f2cb15 100644
--- a/mali_kbase/mali_kbase_uku.h
+++ b/mali_kbase/mali_kbase_uku.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2008-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2008-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
diff --git a/mali_kbase/mali_midg_regmap.h b/mali_kbase/mali_midg_regmap.h
index 2d8231d..7d7b7bc 100644
--- a/mali_kbase/mali_midg_regmap.h
+++ b/mali_kbase/mali_midg_regmap.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2017 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -605,7 +605,6 @@
#define JM_FORCE_COHERENCY_FEATURES_SHIFT (2)
#define JM_IDVS_GROUP_SIZE_SHIFT (16)
#define JM_MAX_IDVS_GROUP_SIZE (0x3F)
-#define JM_CONFIG_UNUSED (1ul << 31)
/* End JM_CONFIG register */
diff --git a/mali_kbase/platform/Kbuild b/mali_kbase/platform/Kbuild
deleted file mode 100644
index 558657b..0000000
--- a/mali_kbase/platform/Kbuild
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
-#
-# This program is free software and is provided to you under the terms of the
-# GNU General Public License version 2 as published by the Free Software
-# Foundation, and any use by you of this program is subject to the terms
-# of such GNU licence.
-#
-# 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.
-#
-#
-
-
-
-ifeq ($(CONFIG_MALI_PLATFORM_THIRDPARTY),y)
-# remove begin and end quotes from the Kconfig string type
- platform_name := $(shell echo $(CONFIG_MALI_PLATFORM_THIRDPARTY_NAME))
- obj-y += $(platform_name)/
-endif
diff --git a/mali_kbase/platform/devicetree/Kbuild b/mali_kbase/platform/devicetree/Kbuild
index b5a49f3..e888a42 100644
--- a/mali_kbase/platform/devicetree/Kbuild
+++ b/mali_kbase/platform/devicetree/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2012-2016 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@@ -13,10 +13,6 @@
#
-ifeq ($(CONFIG_MALI_MIDGARD),y)
-obj-y += mali_kbase_runtime_pm.c
-obj-y += mali_kbase_config_devicetree.c
-else ifeq ($(CONFIG_MALI_MIDGARD),m)
-SRC += platform/devicetree/mali_kbase_runtime_pm.c
-SRC += platform/devicetree/mali_kbase_config_devicetree.c
-endif
+mali_kbase-y += \
+ $(MALI_PLATFORM_THIRDPARTY_DIR)/mali_kbase_config_devicetree.o \
+ $(MALI_PLATFORM_THIRDPARTY_DIR)/mali_kbase_runtime_pm.o
diff --git a/mali_kbase/platform/juno_soc/Kbuild b/mali_kbase/platform/juno_soc/Kbuild
index 0449442..5e1ce63 100644
--- a/mali_kbase/platform/juno_soc/Kbuild
+++ b/mali_kbase/platform/juno_soc/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2013-2014, 2016 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2013-2016 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@@ -13,10 +13,4 @@
#
-obj-y += mali_kbase_config_juno_soc.o
-
-ifeq (($CONFIG_MALI_MIDGARD),y)
-obj-m += juno_mali_opp.o
-else ifeq ($(CONFIG_MALI_MIDGARD),m)
-SRC += platform/juno_soc/mali_kbase_config_juno_soc.c
-endif
+mali_kbase-y += $(MALI_PLATFORM_THIRDPARTY_DIR)/mali_kbase_config_juno_soc.o
diff --git a/mali_kbase/platform/juno_soc/juno_mali_opp.c b/mali_kbase/platform/juno_soc/juno_mali_opp.c
deleted file mode 100644
index ccfd8cc..0000000
--- a/mali_kbase/platform/juno_soc/juno_mali_opp.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *
- * (C) COPYRIGHT 2014 ARM Limited. All rights reserved.
- *
- * This program is free software and is provided to you under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation, and any use by you of this program is subject to the terms
- * of such GNU licence.
- *
- * A copy of the licence is included with the program, and can also be obtained
- * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-
-
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/scpi_protocol.h>
-#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_add opp_add
-#endif /* Linux >= 3.13 */
-
-
-static int init_juno_opps_from_scpi(struct device *dev)
-{
- struct scpi_opp *sopp;
- int i;
-
- /* Hard coded for Juno. 2 is GPU domain */
- sopp = scpi_dvfs_get_opps(2);
- if (IS_ERR_OR_NULL(sopp))
- return PTR_ERR(sopp);
-
- for (i = 0; i < sopp->count; i++) {
- struct scpi_opp_entry *e = &sopp->opp[i];
-
- dev_info(dev, "Mali OPP from SCPI: %u Hz @ %u mV\n",
- e->freq_hz, e->volt_mv);
-
- dev_pm_opp_add(dev, e->freq_hz, e->volt_mv * 1000);
- }
-
- return 0;
-}
-
-static int juno_setup_opps(void)
-{
- struct device_node *np;
- struct platform_device *pdev;
- int err;
-
- np = of_find_node_by_name(NULL, "gpu");
- if (!np) {
- pr_err("Failed to find DT entry for Mali\n");
- return -EFAULT;
- }
-
- pdev = of_find_device_by_node(np);
- if (!pdev) {
- pr_err("Failed to find device for Mali\n");
- of_node_put(np);
- return -EFAULT;
- }
-
- err = init_juno_opps_from_scpi(&pdev->dev);
-
- of_node_put(np);
-
- return err;
-}
-
-module_init(juno_setup_opps);
-MODULE_LICENSE("GPL");
diff --git a/mali_kbase/platform/vexpress/Kbuild b/mali_kbase/platform/vexpress/Kbuild
index 084a156..1caa293 100644
--- a/mali_kbase/platform/vexpress/Kbuild
+++ b/mali_kbase/platform/vexpress/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2012-2013, 2016 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@@ -13,6 +13,6 @@
#
-
-obj-y += mali_kbase_config_vexpress.o
-obj-y += mali_kbase_cpu_vexpress.o
+mali_kbase-y += \
+ $(MALI_PLATFORM_THIRDPARTY_DIR)/mali_kbase_config_vexpress.o \
+ $(MALI_PLATFORM_THIRDPARTY_DIR)/mali_kbase_cpu_vexpress.o
diff --git a/mali_kbase/platform/vexpress_1xv7_a57/Kbuild b/mali_kbase/platform/vexpress_1xv7_a57/Kbuild
index d9bfabc..7efe8fa 100644
--- a/mali_kbase/platform/vexpress_1xv7_a57/Kbuild
+++ b/mali_kbase/platform/vexpress_1xv7_a57/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2013 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2013-2014, 2016 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@@ -13,4 +13,4 @@
#
-obj-y += mali_kbase_config_vexpress.o
+mali_kbase-y += $(MALI_PLATFORM_THIRDPARTY_DIR)/mali_kbase_config_vexpress.o
diff --git a/mali_kbase/platform/vexpress_6xvirtex7_10mhz/Kbuild b/mali_kbase/platform/vexpress_6xvirtex7_10mhz/Kbuild
index 0cb41ce..1caa293 100644
--- a/mali_kbase/platform/vexpress_6xvirtex7_10mhz/Kbuild
+++ b/mali_kbase/platform/vexpress_6xvirtex7_10mhz/Kbuild
@@ -1,5 +1,5 @@
#
-# (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
+# (C) COPYRIGHT 2012-2013, 2016 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@@ -13,6 +13,6 @@
#
-
-obj-y += mali_kbase_config_vexpress.o
-obj-y += mali_kbase_cpu_vexpress.o
+mali_kbase-y += \
+ $(MALI_PLATFORM_THIRDPARTY_DIR)/mali_kbase_config_vexpress.o \
+ $(MALI_PLATFORM_THIRDPARTY_DIR)/mali_kbase_cpu_vexpress.o