summaryrefslogtreecommitdiff
path: root/mali_kbase/backend
diff options
context:
space:
mode:
authorSidath Senanayake <sidaths@google.com>2016-11-09 14:14:45 +0100
committerSidath Senanayake <sidaths@google.com>2016-11-09 14:14:45 +0100
commit192bd796c27ac6eb9443af4b7e027294316f7c5b (patch)
treeaf0b7bd546062b6bbc6c32af91009f0f185fe6f4 /mali_kbase/backend
parent823a760515e356dfef47c691d827d8ba795ce2a4 (diff)
downloadgpu-192bd796c27ac6eb9443af4b7e027294316f7c5b.tar.gz
Mali Bifrost DDK r1p0 KMD
Provenance: 9f8289b33 (collaborate/EAC/b_r1p0) BX304L01B-BU-00000-r1p0-01rel0 BX304L06A-BU-00000-r1p0-01rel0 BX304X07X-BU-00000-r1p0-01bet0 Signed-off-by: Sidath Senanayake <sidaths@google.com> Change-Id: I1559e84ef1f3853e66978a6c12307e766b31e30f
Diffstat (limited to 'mali_kbase/backend')
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c1
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_devfreq.c4
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_gpu.c1
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_instr_backend.c66
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_instr_defs.h6
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_defs.h9
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_hw.c231
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_internal.h4
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_rb.c257
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_js_affinity.c21
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_js_affinity.h10
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_js_backend.c22
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_mmu_hw_direct.c5
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_backend.c1
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c5
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_defs.h5
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_demand.c5
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_driver.c152
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_policy.c61
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_power_model_simple.c15
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_power_model_simple.h6
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_time.c9
22 files changed, 509 insertions, 387 deletions
diff --git a/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c b/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c
index 2f3c41a..c686253 100644
--- a/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_cache_policy_backend.c
@@ -16,7 +16,6 @@
#include "backend/gpu/mali_kbase_cache_policy_backend.h"
-#include <backend/gpu/mali_kbase_pm_internal.h>
#include <backend/gpu/mali_kbase_device_internal.h>
void kbase_cache_set_coherency_mode(struct kbase_device *kbdev,
diff --git a/mali_kbase/backend/gpu/mali_kbase_devfreq.c b/mali_kbase/backend/gpu/mali_kbase_devfreq.c
index 531c432..032ca4b 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-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 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
@@ -133,10 +133,12 @@ kbase_devfreq_status(struct device *dev, struct devfreq_dev_status *stat)
stat->private_data = NULL;
#ifdef CONFIG_DEVFREQ_THERMAL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
if (kbdev->devfreq_cooling)
memcpy(&kbdev->devfreq_cooling->last_status, stat,
sizeof(*stat));
#endif
+#endif
return 0;
}
diff --git a/mali_kbase/backend/gpu/mali_kbase_gpu.c b/mali_kbase/backend/gpu/mali_kbase_gpu.c
index 033caf9..d578fd7 100644
--- a/mali_kbase/backend/gpu/mali_kbase_gpu.c
+++ b/mali_kbase/backend/gpu/mali_kbase_gpu.c
@@ -20,7 +20,6 @@
* Register-based HW access backend APIs
*/
#include <mali_kbase.h>
-#include <mali_kbase_hwaccess_jm.h>
#include <mali_kbase_hwaccess_backend.h>
#include <backend/gpu/mali_kbase_irq_internal.h>
#include <backend/gpu/mali_kbase_jm_internal.h>
diff --git a/mali_kbase/backend/gpu/mali_kbase_instr_backend.c b/mali_kbase/backend/gpu/mali_kbase_instr_backend.c
index 4e70b34..3f06a10 100644
--- a/mali_kbase/backend/gpu/mali_kbase_instr_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_instr_backend.c
@@ -22,8 +22,8 @@
*/
#include <mali_kbase.h>
-#include <mali_kbase_config_defaults.h>
#include <mali_midg_regmap.h>
+#include <mali_kbase_hwaccess_instr.h>
#include <backend/gpu/mali_kbase_device_internal.h>
#include <backend/gpu/mali_kbase_pm_internal.h>
#include <backend/gpu/mali_kbase_instr_internal.h>
@@ -41,14 +41,6 @@ static void kbasep_instr_hwcnt_cacheclean(struct kbase_device *kbdev)
u32 irq_mask;
spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- /* Wait for any reset to complete */
- while (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_RESETTING) {
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
- wait_event(kbdev->hwcnt.backend.cache_clean_wait,
- kbdev->hwcnt.backend.state !=
- KBASE_INSTR_STATE_RESETTING);
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- }
KBASE_DEBUG_ASSERT(kbdev->hwcnt.backend.state ==
KBASE_INSTR_STATE_REQUEST_CLEAN);
@@ -75,19 +67,14 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
{
unsigned long flags, pm_flags;
int err = -EINVAL;
- struct kbasep_js_device_data *js_devdata;
u32 irq_mask;
int ret;
u64 shader_cores_needed;
u32 prfcnt_config;
- KBASE_DEBUG_ASSERT(NULL == kbdev->hwcnt.suspended_kctx);
-
shader_cores_needed = kbase_pm_get_present_cores(kbdev,
KBASE_PM_CORE_SHADER);
- js_devdata = &kbdev->js_data;
-
/* alignment failure */
if ((setup->dump_buffer == 0ULL) || (setup->dump_buffer & (2048 - 1)))
goto out_err;
@@ -102,14 +89,6 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_RESETTING) {
- /* GPU is being reset */
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
- wait_event(kbdev->hwcnt.backend.wait,
- kbdev->hwcnt.backend.triggered != 0);
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- }
-
if (kbdev->hwcnt.backend.state != KBASE_INSTR_STATE_DISABLED) {
/* Instrumentation is already enabled */
spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
@@ -127,10 +106,6 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
kbdev->hwcnt.kctx = kctx;
/* Remember the dump address so we can reprogram it later */
kbdev->hwcnt.addr = setup->dump_buffer;
- /* Remember all the settings for suspend/resume */
- if (&kbdev->hwcnt.suspended_state != setup)
- memcpy(&kbdev->hwcnt.suspended_state, setup,
- sizeof(kbdev->hwcnt.suspended_state));
/* Request the clean */
kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_REQUEST_CLEAN;
@@ -199,14 +174,6 @@ int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev,
spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_RESETTING) {
- /* GPU is being reset */
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
- wait_event(kbdev->hwcnt.backend.wait,
- kbdev->hwcnt.backend.triggered != 0);
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- }
-
kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE;
kbdev->hwcnt.backend.triggered = 1;
wake_up(&kbdev->hwcnt.backend.wait);
@@ -373,15 +340,11 @@ void kbasep_cache_clean_worker(struct work_struct *data)
spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
/* Wait for our condition, and any reset to complete */
- while (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_RESETTING ||
- kbdev->hwcnt.backend.state ==
- KBASE_INSTR_STATE_CLEANING) {
+ while (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_CLEANING) {
spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
wait_event(kbdev->hwcnt.backend.cache_clean_wait,
- (kbdev->hwcnt.backend.state !=
- KBASE_INSTR_STATE_RESETTING &&
kbdev->hwcnt.backend.state !=
- KBASE_INSTR_STATE_CLEANING));
+ KBASE_INSTR_STATE_CLEANING);
spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
}
KBASE_DEBUG_ASSERT(kbdev->hwcnt.backend.state ==
@@ -414,9 +377,6 @@ void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev)
&kbdev->hwcnt.backend.cache_clean_work);
KBASE_DEBUG_ASSERT(ret);
}
- /* NOTE: In the state KBASE_INSTR_STATE_RESETTING, We're in a reset,
- * and the instrumentation state hasn't been restored yet -
- * kbasep_reset_timeout_worker() will do the rest of the work */
spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
}
@@ -444,10 +404,6 @@ void kbase_clean_caches_done(struct kbase_device *kbdev)
kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_CLEANED;
wake_up(&kbdev->hwcnt.backend.cache_clean_wait);
}
- /* NOTE: In the state KBASE_INSTR_STATE_RESETTING, We're in a
- * reset, and the instrumentation state hasn't been restored yet
- * - kbasep_reset_timeout_worker() will do the rest of the work
- */
spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
}
@@ -465,14 +421,6 @@ int kbase_instr_hwcnt_wait_for_dump(struct kbase_context *kctx)
spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_RESETTING) {
- /* GPU is being reset */
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
- wait_event(kbdev->hwcnt.backend.wait,
- kbdev->hwcnt.backend.triggered != 0);
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- }
-
if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_FAULT) {
err = -EINVAL;
kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE;
@@ -496,14 +444,6 @@ int kbase_instr_hwcnt_clear(struct kbase_context *kctx)
spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_RESETTING) {
- /* GPU is being reset */
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
- wait_event(kbdev->hwcnt.backend.wait,
- kbdev->hwcnt.backend.triggered != 0);
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- }
-
/* Check it's the context previously set up and we're not already
* dumping */
if (kbdev->hwcnt.kctx != kctx || kbdev->hwcnt.backend.state !=
diff --git a/mali_kbase/backend/gpu/mali_kbase_instr_defs.h b/mali_kbase/backend/gpu/mali_kbase_instr_defs.h
index 23bd80a..4794672 100644
--- a/mali_kbase/backend/gpu/mali_kbase_instr_defs.h
+++ b/mali_kbase/backend/gpu/mali_kbase_instr_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 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
@@ -39,10 +39,6 @@ enum kbase_instr_state {
/* Cache clean completed, and either a) a dump is complete, or
* b) instrumentation can now be setup. */
KBASE_INSTR_STATE_CLEANED,
- /* kbasep_reset_timeout_worker() has started (but not compelted) a
- * reset. This generally indicates the current action should be aborted,
- * and kbasep_reset_timeout_worker() will handle the cleanup */
- KBASE_INSTR_STATE_RESETTING,
/* An error has occured during DUMPING (page fault). */
KBASE_INSTR_STATE_FAULT
};
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_defs.h b/mali_kbase/backend/gpu/mali_kbase_jm_defs.h
index 8ccc440..83d4778 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_defs.h
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_defs.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 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
@@ -71,6 +71,7 @@ struct slot_rb {
* @reset_work: Work item for performing the reset
* @reset_wait: Wait event signalled when the reset is complete
* @reset_timer: Timeout for soft-stops before the reset
+ * @timeouts_updated: Have timeout values just been updated?
*
* The kbasep_js_device_data::runpool_irq::lock (a spinlock) must be held when
* accessing this structure
@@ -97,11 +98,15 @@ struct kbase_backend_data {
/* The GPU reset process is currently occuring (timeout has expired or
* kbasep_try_reset_gpu_early was called) */
#define KBASE_RESET_GPU_HAPPENING 3
-
+/* Reset the GPU silently, used when resetting the GPU as part of normal
+ * behavior (e.g. when exiting protected mode). */
+#define KBASE_RESET_GPU_SILENT 4
struct workqueue_struct *reset_workq;
struct work_struct reset_work;
wait_queue_head_t reset_wait;
struct hrtimer reset_timer;
+
+ bool timeouts_updated;
};
/**
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_hw.c b/mali_kbase/backend/gpu/mali_kbase_jm_hw.c
index 6577175..00900a9 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_hw.c
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_hw.c
@@ -26,8 +26,8 @@
#include <mali_kbase_gator.h>
#endif
#include <mali_kbase_tlstream.h>
+#include <mali_kbase_vinstr.h>
#include <mali_kbase_hw.h>
-#include <mali_kbase_config_defaults.h>
#include <mali_kbase_hwaccess_jm.h>
#include <backend/gpu/mali_kbase_device_internal.h>
#include <backend/gpu/mali_kbase_irq_internal.h>
@@ -82,19 +82,30 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
/* start MMU, medium priority, cache clean/flush on end, clean/flush on
* start */
cfg = kctx->as_nr;
+
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_REDUCTION))
cfg |= JS_CONFIG_ENABLE_FLUSH_REDUCTION;
#ifndef CONFIG_MALI_COH_GPU
- cfg |= JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE;
- cfg |= JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE;
-#endif
+ if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_START))
+ cfg |= JS_CONFIG_START_FLUSH_NO_ACTION;
+ else
+ cfg |= JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE;
+
+ if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_END))
+ cfg |= JS_CONFIG_END_FLUSH_NO_ACTION;
+ else
+ cfg |= JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE;
+#endif /* CONFIG_MALI_COH_GPU */
+
+ if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_10649) ||
+ !kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_3982))
+ cfg |= JS_CONFIG_START_MMU;
- cfg |= JS_CONFIG_START_MMU;
cfg |= JS_CONFIG_THREAD_PRI(8);
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_MODE) &&
- (katom->atom_flags & KBASE_KATOM_FLAG_SECURE))
+ (katom->atom_flags & KBASE_KATOM_FLAG_PROTECTED))
cfg |= JS_CONFIG_DISABLE_DESCRIPTOR_WR_BK;
if (kbase_hw_has_feature(kbdev,
@@ -465,7 +476,7 @@ static bool kbasep_soft_stop_allowed(struct kbase_device *kbdev,
{
bool soft_stops_allowed = true;
- if (kbase_jd_katom_is_secure(katom)) {
+ if (kbase_jd_katom_is_protected(katom)) {
soft_stops_allowed = false;
} else if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) {
if ((katom->core_req & BASE_JD_REQ_T) != 0)
@@ -475,7 +486,7 @@ static bool kbasep_soft_stop_allowed(struct kbase_device *kbdev,
}
static bool kbasep_hard_stop_allowed(struct kbase_device *kbdev,
- u16 core_reqs)
+ base_jd_core_req core_reqs)
{
bool hard_stops_allowed = true;
@@ -489,7 +500,7 @@ static bool kbasep_hard_stop_allowed(struct kbase_device *kbdev,
void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev,
int js,
u32 action,
- u16 core_reqs,
+ base_jd_core_req core_reqs,
struct kbase_jd_atom *target_katom)
{
struct kbase_context *kctx = target_katom->kctx;
@@ -734,7 +745,6 @@ void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx,
struct kbase_jd_atom *target_katom)
{
struct kbase_device *kbdev;
- struct kbasep_js_device_data *js_devdata;
int js = target_katom->slot_nr;
int priority = target_katom->sched_priority;
int i;
@@ -742,7 +752,6 @@ void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx,
KBASE_DEBUG_ASSERT(kctx != NULL);
kbdev = kctx->kbdev;
KBASE_DEBUG_ASSERT(kbdev != NULL);
- js_devdata = &kbdev->js_data;
lockdep_assert_held(&kbdev->js_data.runpool_irq.lock);
@@ -1074,7 +1083,7 @@ void kbase_job_slot_hardstop(struct kbase_context *kctx, int js,
* state when the soft/hard-stop action is complete
*/
void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action,
- u16 core_reqs, struct kbase_jd_atom *target_katom)
+ base_jd_core_req core_reqs, struct kbase_jd_atom *target_katom)
{
u32 hw_action = action & JS_COMMAND_MASK;
@@ -1151,26 +1160,6 @@ static void kbase_debug_dump_registers(struct kbase_device *kbdev)
kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), NULL));
}
-static void kbasep_save_hwcnt_setup(struct kbase_device *kbdev,
- struct kbase_context *kctx,
- struct kbase_uk_hwcnt_setup *hwcnt_setup)
-{
- hwcnt_setup->dump_buffer =
- kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO), kctx) &
- 0xffffffff;
- hwcnt_setup->dump_buffer |= (u64)
- kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI), kctx) <<
- 32;
- hwcnt_setup->jm_bm =
- kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN), kctx);
- hwcnt_setup->shader_bm =
- kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN), kctx);
- hwcnt_setup->tiler_bm =
- kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN), kctx);
- hwcnt_setup->mmu_l2_bm =
- kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN), kctx);
-}
-
static void kbasep_reset_timeout_worker(struct work_struct *data)
{
unsigned long flags, mmu_flags;
@@ -1178,10 +1167,8 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
int i;
ktime_t end_timestamp = ktime_get();
struct kbasep_js_device_data *js_devdata;
- struct kbase_uk_hwcnt_setup hwcnt_setup = { {0} };
- enum kbase_instr_state bckp_state;
bool try_schedule = false;
- bool restore_hwc = false;
+ bool silent = false;
KBASE_DEBUG_ASSERT(data);
@@ -1191,8 +1178,16 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
KBASE_DEBUG_ASSERT(kbdev);
js_devdata = &kbdev->js_data;
+ if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) ==
+ KBASE_RESET_GPU_SILENT)
+ silent = true;
+
KBASE_TRACE_ADD(kbdev, JM_BEGIN_RESET_WORKER, NULL, NULL, 0u, 0);
+ /* Suspend vinstr.
+ * This call will block until vinstr is suspended. */
+ kbase_vinstr_suspend(kbdev->vinstr_ctx);
+
/* Make sure the timer has completed - this cannot be done from
* interrupt context, so this cannot be done within
* kbasep_try_reset_gpu_early. */
@@ -1242,39 +1237,14 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
* assume that anything that is still left on the GPU is stuck there and
* we'll kill it when we reset the GPU */
- dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)",
+ if (!silent)
+ dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)",
RESET_TIMEOUT);
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
-
- if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_RESETTING) {
- /* the same interrupt handler preempted itself */
- /* GPU is being reset */
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
- wait_event(kbdev->hwcnt.backend.wait,
- kbdev->hwcnt.backend.triggered != 0);
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- }
- /* Save the HW counters setup */
- if (kbdev->hwcnt.kctx != NULL) {
- struct kbase_context *kctx = kbdev->hwcnt.kctx;
-
- if (kctx->jctx.sched_info.ctx.is_scheduled) {
- kbasep_save_hwcnt_setup(kbdev, kctx, &hwcnt_setup);
-
- restore_hwc = true;
- }
- }
-
/* Output the state of some interesting registers to help in the
* debugging of GPU resets */
- kbase_debug_dump_registers(kbdev);
-
- bckp_state = kbdev->hwcnt.backend.state;
- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_RESETTING;
- kbdev->hwcnt.backend.triggered = 0;
-
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
+ if (!silent)
+ kbase_debug_dump_registers(kbdev);
/* Reset the GPU */
kbase_pm_init_hw(kbdev, 0);
@@ -1314,112 +1284,14 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
kbase_disjoint_state_down(kbdev);
wake_up(&kbdev->hwaccess.backend.reset_wait);
- dev_err(kbdev->dev, "Reset complete");
+ if (!silent)
+ dev_err(kbdev->dev, "Reset complete");
if (js_devdata->nr_contexts_pullable > 0 && !kbdev->poweroff_pending)
try_schedule = true;
mutex_unlock(&js_devdata->runpool_mutex);
- spin_lock_irqsave(&kbdev->hwcnt.lock, flags);
- /* Restore the HW counters setup */
- if (restore_hwc) {
- struct kbase_context *kctx = kbdev->hwcnt.kctx;
- u32 prfcnt_config = kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT;
-
-#ifdef CONFIG_MALI_PRFCNT_SET_SECONDARY
- u32 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id;
- u32 product_id = (gpu_id & GPU_ID_VERSION_PRODUCT_ID)
- >> GPU_ID_VERSION_PRODUCT_ID_SHIFT;
- int arch_v6 = GPU_ID_IS_NEW_FORMAT(product_id);
-
- if (arch_v6)
- prfcnt_config |= 1 << PRFCNT_CONFIG_SETSELECT_SHIFT;
-#endif
-
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG),
- prfcnt_config | PRFCNT_CONFIG_MODE_OFF, kctx);
-
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_LO),
- hwcnt_setup.dump_buffer & 0xFFFFFFFF, kctx);
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_BASE_HI),
- hwcnt_setup.dump_buffer >> 32, kctx);
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_JM_EN),
- hwcnt_setup.jm_bm, kctx);
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_SHADER_EN),
- hwcnt_setup.shader_bm, kctx);
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_MMU_L2_EN),
- hwcnt_setup.mmu_l2_bm, kctx);
-
- /* Due to PRLAM-8186 we need to disable the Tiler before we
- * enable the HW counter dump. */
- if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186))
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN),
- 0, kctx);
- else
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN),
- hwcnt_setup.tiler_bm, kctx);
-
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_CONFIG),
- prfcnt_config | PRFCNT_CONFIG_MODE_MANUAL,
- kctx);
-
- /* If HW has PRLAM-8186 we can now re-enable the tiler HW
- * counters dump */
- if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8186))
- kbase_reg_write(kbdev, GPU_CONTROL_REG(PRFCNT_TILER_EN),
- hwcnt_setup.tiler_bm, kctx);
- }
- kbdev->hwcnt.backend.state = bckp_state;
- switch (kbdev->hwcnt.backend.state) {
- /* Cases for waking kbasep_cache_clean_worker worker */
- case KBASE_INSTR_STATE_CLEANED:
- /* Cache-clean IRQ occurred, but we reset:
- * Wakeup incase the waiter saw RESETTING */
- case KBASE_INSTR_STATE_REQUEST_CLEAN:
- /* After a clean was requested, but before the regs were
- * written:
- * Wakeup incase the waiter saw RESETTING */
- wake_up(&kbdev->hwcnt.backend.cache_clean_wait);
- break;
- case KBASE_INSTR_STATE_CLEANING:
- /* Either:
- * 1) We've not got the Cache-clean IRQ yet: it was lost, or:
- * 2) We got it whilst resetting: it was voluntarily lost
- *
- * So, move to the next state and wakeup: */
- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_CLEANED;
- wake_up(&kbdev->hwcnt.backend.cache_clean_wait);
- break;
-
- /* Cases for waking anyone else */
- case KBASE_INSTR_STATE_DUMPING:
- /* If dumping, abort the dump, because we may've lost the IRQ */
- kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE;
- kbdev->hwcnt.backend.triggered = 1;
- wake_up(&kbdev->hwcnt.backend.wait);
- break;
- case KBASE_INSTR_STATE_DISABLED:
- case KBASE_INSTR_STATE_IDLE:
- case KBASE_INSTR_STATE_FAULT:
- /* Every other reason: wakeup in that state */
- kbdev->hwcnt.backend.triggered = 1;
- wake_up(&kbdev->hwcnt.backend.wait);
- break;
-
- /* Unhandled cases */
- case KBASE_INSTR_STATE_RESETTING:
- default:
- BUG();
- break;
- }
- spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags);
-
- /* Resume the vinstr core */
- kbase_vinstr_hwc_resume(kbdev->vinstr_ctx);
-
- /* Note: counter dumping may now resume */
-
mutex_lock(&kbdev->pm.lock);
/* Find out what cores are required now */
@@ -1439,6 +1311,10 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
}
kbase_pm_context_idle(kbdev);
+
+ /* Release vinstr */
+ kbase_vinstr_resume(kbdev->vinstr_ctx);
+
KBASE_TRACE_ADD(kbdev, JM_END_RESET_WORKER, NULL, NULL, 0u, 0);
}
@@ -1520,7 +1396,7 @@ static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev)
*
* Return:
* The function returns a boolean which should be interpreted as follows:
- * true - Prepared for reset, kbase_reset_gpu should be called.
+ * true - Prepared for reset, kbase_reset_gpu_locked should be called.
* false - Another thread is performing a reset, kbase_reset_gpu should
* not be called.
*/
@@ -1614,4 +1490,29 @@ void kbase_reset_gpu_locked(struct kbase_device *kbdev)
/* Try resetting early */
kbasep_try_reset_gpu_early_locked(kbdev);
}
+
+void kbase_reset_gpu_silent(struct kbase_device *kbdev)
+{
+ if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu,
+ KBASE_RESET_GPU_NOT_PENDING,
+ KBASE_RESET_GPU_SILENT) !=
+ KBASE_RESET_GPU_NOT_PENDING) {
+ /* Some other thread is already resetting the GPU */
+ return;
+ }
+
+ kbase_disjoint_state_up(kbdev);
+
+ queue_work(kbdev->hwaccess.backend.reset_workq,
+ &kbdev->hwaccess.backend.reset_work);
+}
+
+bool kbase_reset_gpu_active(struct kbase_device *kbdev)
+{
+ if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) ==
+ KBASE_RESET_GPU_NOT_PENDING)
+ return false;
+
+ return true;
+}
#endif /* KBASE_GPU_RESET_EN */
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_internal.h b/mali_kbase/backend/gpu/mali_kbase_jm_internal.h
index eb068d4..8f1e561 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_internal.h
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_internal.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-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
@@ -96,7 +96,7 @@ void kbase_job_hw_submit(struct kbase_device *kbdev,
void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev,
int js,
u32 action,
- u16 core_reqs,
+ base_jd_core_req core_reqs,
struct kbase_jd_atom *target_katom);
/**
diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_rb.c b/mali_kbase/backend/gpu/mali_kbase_jm_rb.c
index af6cddc..da7c4df 100644
--- a/mali_kbase/backend/gpu/mali_kbase_jm_rb.c
+++ b/mali_kbase/backend/gpu/mali_kbase_jm_rb.c
@@ -24,11 +24,11 @@
#include <mali_kbase_hwaccess_jm.h>
#include <mali_kbase_jm.h>
#include <mali_kbase_js.h>
+#include <mali_kbase_tlstream.h>
#include <mali_kbase_10969_workaround.h>
#include <backend/gpu/mali_kbase_device_internal.h>
#include <backend/gpu/mali_kbase_jm_internal.h>
#include <backend/gpu/mali_kbase_js_affinity.h>
-#include <backend/gpu/mali_kbase_js_internal.h>
#include <backend/gpu/mali_kbase_pm_internal.h>
/* Return whether the specified ringbuffer is empty. HW access lock must be
@@ -592,7 +592,7 @@ static void kbase_gpu_release_atom(struct kbase_device *kbdev,
case KBASE_ATOM_GPU_RB_READY:
/* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */
- case KBASE_ATOM_GPU_RB_WAITING_SECURE_MODE:
+ case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_ENTRY:
/* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */
case KBASE_ATOM_GPU_RB_WAITING_AFFINITY:
@@ -603,6 +603,9 @@ static void kbase_gpu_release_atom(struct kbase_device *kbdev,
case KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE:
break;
+ case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_EXIT:
+ /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */
+
case KBASE_ATOM_GPU_RB_WAITING_BLOCKED:
/* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */
@@ -654,53 +657,145 @@ static inline bool kbase_gpu_rmu_workaround(struct kbase_device *kbdev, int js)
return true;
}
-static bool kbase_gpu_in_secure_mode(struct kbase_device *kbdev)
+static inline bool kbase_gpu_in_protected_mode(struct kbase_device *kbdev)
{
- return kbdev->secure_mode;
+ return kbdev->protected_mode;
}
-static int kbase_gpu_secure_mode_enable(struct kbase_device *kbdev)
+static int kbase_gpu_protected_mode_enter(struct kbase_device *kbdev)
{
int err = -EINVAL;
lockdep_assert_held(&kbdev->js_data.runpool_irq.lock);
- WARN_ONCE(!kbdev->secure_ops,
- "Cannot enable secure mode: secure callbacks not specified.\n");
+ WARN_ONCE(!kbdev->protected_ops,
+ "Cannot enter protected mode: protected callbacks not specified.\n");
- if (kbdev->secure_ops) {
- /* Switch GPU to secure mode */
- err = kbdev->secure_ops->secure_mode_enable(kbdev);
+ if (kbdev->protected_ops) {
+ /* Switch GPU to protected mode */
+ err = kbdev->protected_ops->protected_mode_enter(kbdev);
if (err)
- dev_warn(kbdev->dev, "Failed to enable secure mode: %d\n", err);
+ dev_warn(kbdev->dev, "Failed to enable protected mode: %d\n",
+ err);
else
- kbdev->secure_mode = true;
+ kbdev->protected_mode = true;
}
return err;
}
-static int kbase_gpu_secure_mode_disable(struct kbase_device *kbdev)
+static int kbase_gpu_protected_mode_reset(struct kbase_device *kbdev)
{
- int err = -EINVAL;
-
lockdep_assert_held(&kbdev->js_data.runpool_irq.lock);
- WARN_ONCE(!kbdev->secure_ops,
- "Cannot disable secure mode: secure callbacks not specified.\n");
+ WARN_ONCE(!kbdev->protected_ops,
+ "Cannot exit protected mode: protected callbacks not specified.\n");
- if (kbdev->secure_ops) {
- /* Switch GPU to non-secure mode */
- err = kbdev->secure_ops->secure_mode_disable(kbdev);
+ if (!kbdev->protected_ops)
+ return -EINVAL;
- if (err)
- dev_warn(kbdev->dev, "Failed to disable secure mode: %d\n", err);
- else
- kbdev->secure_mode = false;
+ kbdev->protected_mode_transition = true;
+ kbase_reset_gpu_silent(kbdev);
+
+ return 0;
+}
+
+static int kbase_jm_exit_protected_mode(struct kbase_device *kbdev,
+ struct kbase_jd_atom **katom, int idx, int js)
+{
+ int err = 0;
+
+ switch (katom[idx]->exit_protected_state) {
+ case KBASE_ATOM_EXIT_PROTECTED_CHECK:
+ /*
+ * If the atom ahead of this one hasn't got to being
+ * submitted yet then bail.
+ */
+ if (idx == 1 &&
+ (katom[0]->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED &&
+ katom[0]->gpu_rb_state != KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB))
+ return -EAGAIN;
+
+ /* If we're not exiting protected mode then we're done here. */
+ if (!(kbase_gpu_in_protected_mode(kbdev) &&
+ !kbase_jd_katom_is_protected(katom[idx])))
+ return 0;
+
+ /*
+ * If there is a transition in progress, or work still
+ * on the GPU try again later.
+ */
+ if (kbdev->protected_mode_transition ||
+ kbase_gpu_atoms_submitted_any(kbdev))
+ return -EAGAIN;
+
+ /*
+ * Exiting protected mode requires a reset, but first the L2
+ * needs to be powered down to ensure it's not active when the
+ * reset is issued.
+ */
+ katom[idx]->exit_protected_state =
+ KBASE_ATOM_EXIT_PROTECTED_IDLE_L2;
+
+ /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
+
+ case KBASE_ATOM_EXIT_PROTECTED_IDLE_L2:
+ if (kbase_pm_get_active_cores(kbdev, KBASE_PM_CORE_L2) ||
+ kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_L2)) {
+ /*
+ * The L2 is still powered, wait for all the users to
+ * finish with it before doing the actual reset.
+ */
+ return -EAGAIN;
+ }
+ katom[idx]->exit_protected_state =
+ KBASE_ATOM_EXIT_PROTECTED_RESET;
+
+ /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
+
+ case KBASE_ATOM_EXIT_PROTECTED_RESET:
+ /* Issue the reset to the GPU */
+ err = kbase_gpu_protected_mode_reset(kbdev);
+ if (err) {
+ /* Failed to exit protected mode, fail atom */
+ katom[idx]->event_code = BASE_JD_EVENT_JOB_INVALID;
+ kbase_gpu_mark_atom_for_return(kbdev, katom[idx]);
+ /* Only return if head atom or previous atom
+ * already removed - as atoms must be returned
+ * in order */
+ if (idx == 0 || katom[0]->gpu_rb_state ==
+ KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) {
+ kbase_gpu_dequeue_atom(kbdev, js, NULL);
+ kbase_jm_return_atom_to_js(kbdev, katom[idx]);
+ }
+
+ kbase_vinstr_resume(kbdev->vinstr_ctx);
+
+ return -EINVAL;
+ }
+
+ katom[idx]->exit_protected_state =
+ KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT;
+
+ /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
+
+ case KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT:
+ if (kbase_reset_gpu_active(kbdev))
+ return -EAGAIN;
+
+ /* 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);
}
- return err;
+ return 0;
}
void kbase_gpu_slot_update(struct kbase_device *kbdev)
@@ -719,6 +814,7 @@ void kbase_gpu_slot_update(struct kbase_device *kbdev)
for (idx = 0; idx < SLOT_RB_SIZE; idx++) {
bool cores_ready;
+ int ret;
if (!katom[idx])
continue;
@@ -735,11 +831,29 @@ void kbase_gpu_slot_update(struct kbase_device *kbdev)
break;
katom[idx]->gpu_rb_state =
- KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE;
+ KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_EXIT;
+
+ /* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
+
+ case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_EXIT:
+ /*
+ * Exiting protected mode must be done before
+ * the references on the cores are taken as
+ * a power down the L2 is required which
+ * can't happen after the references for this
+ * atom are taken.
+ */
+ ret = kbase_jm_exit_protected_mode(kbdev,
+ katom, idx, js);
+ if (ret)
+ break;
+
+ katom[idx]->gpu_rb_state =
+ KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE;
/* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
- case KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE:
+ case KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE:
if (katom[idx]->will_fail_event_code) {
kbase_gpu_mark_atom_for_return(kbdev,
katom[idx]);
@@ -785,11 +899,12 @@ void kbase_gpu_slot_update(struct kbase_device *kbdev)
break;
katom[idx]->gpu_rb_state =
- KBASE_ATOM_GPU_RB_WAITING_SECURE_MODE;
+ KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_ENTRY;
/* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
- case KBASE_ATOM_GPU_RB_WAITING_SECURE_MODE:
+ case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_ENTRY:
+
/* Only submit if head atom or previous atom
* already submitted */
if (idx == 1 &&
@@ -797,7 +912,15 @@ void kbase_gpu_slot_update(struct kbase_device *kbdev)
katom[0]->gpu_rb_state != KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB))
break;
- if (kbase_gpu_in_secure_mode(kbdev) != kbase_jd_katom_is_secure(katom[idx])) {
+ /*
+ * If the GPU is transitioning protected mode
+ * then bail now and we'll be called when the
+ * new state has settled.
+ */
+ if (kbdev->protected_mode_transition)
+ break;
+
+ if (!kbase_gpu_in_protected_mode(kbdev) && kbase_jd_katom_is_protected(katom[idx])) {
int err = 0;
/* Not in correct mode, take action */
@@ -811,16 +934,26 @@ void kbase_gpu_slot_update(struct kbase_device *kbdev)
*/
break;
}
-
- /* No jobs running, so we can switch GPU mode right now */
- if (kbase_jd_katom_is_secure(katom[idx])) {
- err = kbase_gpu_secure_mode_enable(kbdev);
- } else {
- err = kbase_gpu_secure_mode_disable(kbdev);
+ if (kbase_vinstr_try_suspend(kbdev->vinstr_ctx) < 0) {
+ /*
+ * We can't switch now because
+ * the vinstr core state switch
+ * is not done yet.
+ */
+ break;
}
+ /* Once reaching this point GPU must be
+ * switched to protected mode or vinstr
+ * re-enabled. */
+ /* No jobs running, so we can switch GPU mode right now */
+ err = kbase_gpu_protected_mode_enter(kbdev);
if (err) {
- /* Failed to switch secure mode, fail atom */
+ /*
+ * Failed to switch into protected mode, resume
+ * vinstr core and fail atom.
+ */
+ kbase_vinstr_resume(kbdev->vinstr_ctx);
katom[idx]->event_code = BASE_JD_EVENT_JOB_INVALID;
kbase_gpu_mark_atom_for_return(kbdev, katom[idx]);
/* Only return if head atom or previous atom
@@ -835,17 +968,18 @@ void kbase_gpu_slot_update(struct kbase_device *kbdev)
}
}
- /* Secure mode sanity checks */
+ /* Protected mode sanity checks */
KBASE_DEBUG_ASSERT_MSG(
- kbase_jd_katom_is_secure(katom[idx]) == kbase_gpu_in_secure_mode(kbdev),
- "Secure mode of atom (%d) doesn't match secure mode of GPU (%d)",
- kbase_jd_katom_is_secure(katom[idx]), kbase_gpu_in_secure_mode(kbdev));
+ 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));
katom[idx]->gpu_rb_state =
KBASE_ATOM_GPU_RB_READY;
/* ***FALLTHROUGH: TRANSITION TO HIGHER STATE*** */
case KBASE_ATOM_GPU_RB_READY:
+
/* Only submit if head atom or previous atom
* already submitted */
if (idx == 1 &&
@@ -966,8 +1100,16 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, int js,
}
katom = kbase_gpu_dequeue_atom(kbdev, js, end_timestamp);
-
kbase_timeline_job_slot_done(kbdev, katom->kctx, katom, js, 0);
+ kbase_tlstream_tl_nret_atom_lpu(
+ katom,
+ &kbdev->gpu_props.props.raw_props.js_features[
+ katom->slot_nr]);
+ kbase_tlstream_tl_nret_atom_as(katom, &kbdev->as[kctx->as_nr]);
+ kbase_tlstream_tl_nret_ctx_lpu(
+ kctx,
+ &kbdev->gpu_props.props.raw_props.js_features[
+ katom->slot_nr]);
if (completion_code == BASE_JD_EVENT_STOPPED) {
struct kbase_jd_atom *next_katom = kbase_gpu_inspect(kbdev, js,
@@ -1120,13 +1262,34 @@ void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp)
for (idx = 0; idx < 2; idx++) {
struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev,
js, 0);
+ bool keep_in_jm_rb = false;
- if (katom) {
- kbase_gpu_release_atom(kbdev, katom, NULL);
- kbase_gpu_dequeue_atom(kbdev, js, NULL);
- katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
- kbase_jm_complete(kbdev, katom, end_timestamp);
+ if (!katom)
+ continue;
+
+ if (katom->gpu_rb_state < KBASE_ATOM_GPU_RB_SUBMITTED)
+ keep_in_jm_rb = true;
+
+ kbase_gpu_release_atom(kbdev, katom, NULL);
+
+ /*
+ * If the atom wasn't on HW when the reset was issued
+ * then leave it in the RB and next time we're kicked
+ * it will be processed again from the starting state.
+ */
+ if (keep_in_jm_rb) {
+ katom->coreref_state = KBASE_ATOM_COREREF_STATE_NO_CORES_REQUESTED;
+ katom->exit_protected_state = KBASE_ATOM_EXIT_PROTECTED_CHECK;
+ continue;
}
+
+ /*
+ * The atom was on the HW when the reset was issued
+ * all we can do is fail the atom.
+ */
+ kbase_gpu_dequeue_atom(kbdev, js, NULL);
+ katom->event_code = BASE_JD_EVENT_JOB_CANCELLED;
+ kbase_jm_complete(kbdev, katom, end_timestamp);
}
}
}
diff --git a/mali_kbase/backend/gpu/mali_kbase_js_affinity.c b/mali_kbase/backend/gpu/mali_kbase_js_affinity.c
index 5459281..d665420 100644
--- a/mali_kbase/backend/gpu/mali_kbase_js_affinity.c
+++ b/mali_kbase/backend/gpu/mali_kbase_js_affinity.c
@@ -23,6 +23,7 @@
#include <mali_kbase.h>
#include "mali_kbase_js_affinity.h"
+#include "mali_kbase_hw.h"
#include <backend/gpu/mali_kbase_pm_internal.h>
@@ -114,9 +115,14 @@ bool kbase_js_choose_affinity(u64 * const affinity,
if ((core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) ==
BASE_JD_REQ_T) {
spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags);
- /* Tiler only job, bit 0 needed to enable tiler but no shader
- * cores required */
- *affinity = 1;
+ /* If the hardware supports XAFFINITY then we'll only enable
+ * the tiler (which is the default so this is a no-op),
+ * otherwise enable shader core 0. */
+ if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_XAFFINITY))
+ *affinity = 1;
+ else
+ *affinity = 0;
+
return true;
}
@@ -172,9 +178,12 @@ bool kbase_js_choose_affinity(u64 * const affinity,
if (*affinity == 0)
return false;
- /* Enable core 0 if tiler required */
- if (core_req & BASE_JD_REQ_T)
- *affinity = *affinity | 1;
+ /* Enable core 0 if tiler required for hardware without XAFFINITY
+ * support (notes above) */
+ if (core_req & BASE_JD_REQ_T) {
+ if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_XAFFINITY))
+ *affinity = *affinity | 1;
+ }
return true;
}
diff --git a/mali_kbase/backend/gpu/mali_kbase_js_affinity.h b/mali_kbase/backend/gpu/mali_kbase_js_affinity.h
index 3026e6a..fbffa3b 100644
--- a/mali_kbase/backend/gpu/mali_kbase_js_affinity.h
+++ b/mali_kbase/backend/gpu/mali_kbase_js_affinity.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-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
@@ -24,14 +24,6 @@
#ifndef _KBASE_JS_AFFINITY_H_
#define _KBASE_JS_AFFINITY_H_
-#ifdef CONFIG_MALI_DEBUG_SHADER_SPLIT_FS
-/* Import the external affinity mask variables */
-extern u64 mali_js0_affinity_mask;
-extern u64 mali_js1_affinity_mask;
-extern u64 mali_js2_affinity_mask;
-#endif /* CONFIG_MALI_DEBUG_SHADER_SPLIT_FS */
-
-
/**
* kbase_js_can_run_job_on_slot_no_lock - Decide whether it is possible to
* submit a job to a particular job slot in the current status
diff --git a/mali_kbase/backend/gpu/mali_kbase_js_backend.c b/mali_kbase/backend/gpu/mali_kbase_js_backend.c
index 1e9a7e4..a23deb4 100644
--- a/mali_kbase/backend/gpu/mali_kbase_js_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_js_backend.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 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
@@ -138,6 +138,17 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer)
js_devdata->gpu_reset_ticks_ss;
}
+ /* If timeouts have been changed then ensure
+ * that atom tick count is not greater than the
+ * new soft_stop timeout. This ensures that
+ * atoms do not miss any of the timeouts due to
+ * races between this worker and the thread
+ * changing the timeouts. */
+ if (backend->timeouts_updated &&
+ ticks > soft_stop_ticks)
+ ticks = atom->sched_info.cfs.ticks =
+ soft_stop_ticks;
+
/* Job is Soft-Stoppable */
if (ticks == soft_stop_ticks) {
int disjoint_threshold =
@@ -257,6 +268,8 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer)
HR_TIMER_DELAY_NSEC(js_devdata->scheduling_period_ns),
HRTIMER_MODE_REL);
+ backend->timeouts_updated = false;
+
spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
return HRTIMER_NORESTART;
@@ -335,3 +348,10 @@ void kbase_backend_timer_resume(struct kbase_device *kbdev)
kbase_backend_ctx_count_changed(kbdev);
}
+void kbase_backend_timeouts_changed(struct kbase_device *kbdev)
+{
+ struct kbase_backend_data *backend = &kbdev->hwaccess.backend;
+
+ backend->timeouts_updated = true;
+}
+
diff --git a/mali_kbase/backend/gpu/mali_kbase_mmu_hw_direct.c b/mali_kbase/backend/gpu/mali_kbase_mmu_hw_direct.c
index c6c7b89..4a3572d 100644
--- a/mali_kbase/backend/gpu/mali_kbase_mmu_hw_direct.c
+++ b/mali_kbase/backend/gpu/mali_kbase_mmu_hw_direct.c
@@ -21,8 +21,8 @@
#include <mali_kbase_mem.h>
#include <mali_kbase_mmu_hw.h>
#include <mali_kbase_tlstream.h>
-#include <backend/gpu/mali_kbase_mmu_hw_direct.h>
#include <backend/gpu/mali_kbase_device_internal.h>
+#include <mali_kbase_as_fault_debugfs.h>
static inline u64 lock_region(struct kbase_device *kbdev, u64 pfn,
u32 num_pages)
@@ -152,6 +152,9 @@ void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat)
AS_FAULTADDRESS_LO),
kctx);
+ /* report the fault to debugfs */
+ kbase_as_fault_debugfs_new(kbdev, as_no);
+
/* record the fault status */
as->fault_status = kbase_reg_read(kbdev,
MMU_AS_REG(as_no,
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_backend.c b/mali_kbase/backend/gpu/mali_kbase_pm_backend.c
index 5805efe..711e44c 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_backend.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_backend.c
@@ -168,6 +168,7 @@ bool kbase_pm_do_poweroff(struct kbase_device *kbdev, bool is_suspend)
/* Force all cores off */
kbdev->pm.backend.desired_shader_state = 0;
+ kbdev->pm.backend.desired_tiler_state = 0;
/* Force all cores to be unavailable, in the situation where
* transitions are in progress for some cores but not others,
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c b/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c
index 4873911..f891fa2 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_coarse_demand.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2012-2015 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
@@ -35,7 +35,8 @@ static u64 coarse_demand_get_core_mask(struct kbase_device *kbdev)
static bool coarse_demand_get_core_active(struct kbase_device *kbdev)
{
if (0 == kbdev->pm.active_count && !(kbdev->shader_needed_bitmap |
- kbdev->shader_inuse_bitmap))
+ kbdev->shader_inuse_bitmap) && !kbdev->tiler_needed_cnt
+ && !kbdev->tiler_inuse_cnt)
return false;
return true;
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_defs.h b/mali_kbase/backend/gpu/mali_kbase_pm_defs.h
index 6eb1b1c..e8f96fe 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_defs.h
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_defs.h
@@ -192,12 +192,14 @@ union kbase_pm_ca_policy_data {
* @gpu_poweroff_pending: number of poweroff timer ticks until the GPU is
* powered off
* @shader_poweroff_pending_time: number of poweroff timer ticks until shaders
- * are powered off
+ * and/or timers are powered off
* @gpu_poweroff_timer: Timer for powering off GPU
* @gpu_poweroff_wq: Workqueue to power off GPU on when timer fires
* @gpu_poweroff_work: Workitem used on @gpu_poweroff_wq
* @shader_poweroff_pending: Bit mask of shaders to be powered off on next
* timer callback
+ * @tiler_poweroff_pending: Bit mask of tilers to be powered off on next timer
+ * callback
* @poweroff_timer_needed: true if the poweroff timer is currently required,
* false otherwise
* @poweroff_timer_running: true if the poweroff timer is currently running,
@@ -274,6 +276,7 @@ struct kbase_pm_backend_data {
struct work_struct gpu_poweroff_work;
u64 shader_poweroff_pending;
+ u64 tiler_poweroff_pending;
bool poweroff_timer_needed;
bool poweroff_timer_running;
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_demand.c b/mali_kbase/backend/gpu/mali_kbase_pm_demand.c
index 9dac230..81322fd 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_demand.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_demand.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2010-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-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
@@ -37,7 +37,8 @@ static u64 demand_get_core_mask(struct kbase_device *kbdev)
static bool demand_get_core_active(struct kbase_device *kbdev)
{
if (0 == kbdev->pm.active_count && !(kbdev->shader_needed_bitmap |
- kbdev->shader_inuse_bitmap))
+ kbdev->shader_inuse_bitmap) && !kbdev->tiler_needed_cnt
+ && !kbdev->tiler_inuse_cnt)
return false;
return true;
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_driver.c b/mali_kbase/backend/gpu/mali_kbase_pm_driver.c
index 2c27ad9..046ebcb 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_driver.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_driver.c
@@ -29,7 +29,6 @@
#endif
#include <mali_kbase_tlstream.h>
#include <mali_kbase_pm.h>
-#include <mali_kbase_cache_policy.h>
#include <mali_kbase_config_defaults.h>
#include <mali_kbase_smc.h>
#include <mali_kbase_hwaccess_jm.h>
@@ -510,10 +509,12 @@ KBASE_EXPORT_TEST_API(kbase_pm_transition_core_type);
* @present: The bit mask of present caches
* @cores_powered: A bit mask of cores (or L2 caches) that are desired to
* be powered
+ * @tilers_powered: The bit mask of tilers that are desired to be powered
*
* Return: A bit mask of the caches that should be turned on
*/
-static u64 get_desired_cache_status(u64 present, u64 cores_powered)
+static u64 get_desired_cache_status(u64 present, u64 cores_powered,
+ u64 tilers_powered)
{
u64 desired = 0;
@@ -536,6 +537,10 @@ static u64 get_desired_cache_status(u64 present, u64 cores_powered)
present &= ~bit_mask;
}
+ /* Power up the required L2(s) for the tiler */
+ if (tilers_powered)
+ desired |= 1;
+
return desired;
}
@@ -548,6 +553,7 @@ MOCKABLE(kbase_pm_check_transitions_nolock) (struct kbase_device *kbdev)
bool in_desired_state = true;
u64 desired_l2_state;
u64 cores_powered;
+ u64 tilers_powered;
u64 tiler_available_bitmap;
u64 shader_available_bitmap;
u64 shader_ready_bitmap;
@@ -581,6 +587,10 @@ MOCKABLE(kbase_pm_check_transitions_nolock) (struct kbase_device *kbdev)
cores_powered |= kbdev->pm.backend.desired_shader_state;
+ /* Work out which tilers want to be powered */
+ tilers_powered = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_TILER);
+ tilers_powered |= kbdev->pm.backend.desired_tiler_state;
+
/* If there are l2 cache users registered, keep all l2s powered even if
* all other cores are off. */
if (kbdev->l2_users_count > 0)
@@ -588,17 +598,11 @@ MOCKABLE(kbase_pm_check_transitions_nolock) (struct kbase_device *kbdev)
desired_l2_state = get_desired_cache_status(
kbdev->gpu_props.props.raw_props.l2_present,
- cores_powered);
+ cores_powered, tilers_powered);
/* If any l2 cache is on, then enable l2 #0, for use by job manager */
- if (0 != desired_l2_state) {
+ if (0 != desired_l2_state)
desired_l2_state |= 1;
- /* Also enable tiler if l2 cache is powered */
- kbdev->pm.backend.desired_tiler_state =
- kbdev->gpu_props.props.raw_props.tiler_present;
- } else {
- kbdev->pm.backend.desired_tiler_state = 0;
- }
prev_l2_available_bitmap = kbdev->l2_available_bitmap;
in_desired_state &= kbase_pm_transition_core_type(kbdev,
@@ -1108,9 +1112,9 @@ static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev)
kbdev->hw_quirks_sc |= SC_ENABLE_TEXGRD_FLAGS;
if (!kbase_hw_has_issue(kbdev, GPUCORE_1619)) {
- if (prod_id < 0x760 || prod_id == 0x6956) /* T60x, T62x, T72x */
+ if (prod_id < 0x750 || prod_id == 0x6956) /* T60x, T62x, T72x */
kbdev->hw_quirks_sc |= SC_LS_ATTR_CHECK_DISABLE;
- else if (prod_id >= 0x760 && prod_id <= 0x880) /* T76x, T8xx */
+ else if (prod_id >= 0x750 && prod_id <= 0x880) /* T76x, T8xx */
kbdev->hw_quirks_sc |= SC_LS_ALLOW_ATTR_TYPES;
}
@@ -1233,48 +1237,10 @@ void kbase_pm_cache_snoop_disable(struct kbase_device *kbdev)
}
}
-int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
+static int kbase_pm_reset_do_normal(struct kbase_device *kbdev)
{
- unsigned long irq_flags;
struct kbasep_reset_timeout_data rtdata;
- KBASE_DEBUG_ASSERT(NULL != kbdev);
- lockdep_assert_held(&kbdev->pm.lock);
-
- /* Ensure the clock is on before attempting to access the hardware */
- if (!kbdev->pm.backend.gpu_powered) {
- if (kbdev->pm.backend.callback_power_on)
- kbdev->pm.backend.callback_power_on(kbdev);
-
- spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock,
- irq_flags);
- kbdev->pm.backend.gpu_powered = true;
- spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock,
- irq_flags);
- }
-
- /* Ensure interrupts are off to begin with, this also clears any
- * outstanding interrupts */
- kbase_pm_disable_interrupts(kbdev);
- /* Ensure cache snoops are disabled before reset. */
- kbase_pm_cache_snoop_disable(kbdev);
- /* Prepare for the soft-reset */
- kbdev->pm.backend.reset_done = false;
-
- /* The cores should be made unavailable due to the reset */
- spin_lock_irqsave(&kbdev->pm.power_change_lock, irq_flags);
- if (kbdev->shader_available_bitmap != 0u)
- KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL,
- NULL, 0u, (u32)0u);
- if (kbdev->tiler_available_bitmap != 0u)
- KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER,
- NULL, NULL, 0u, (u32)0u);
- kbdev->shader_available_bitmap = 0u;
- kbdev->tiler_available_bitmap = 0u;
- kbdev->l2_available_bitmap = 0u;
- spin_unlock_irqrestore(&kbdev->pm.power_change_lock, irq_flags);
-
- /* Soft reset the GPU */
KBASE_TRACE_ADD(kbdev, CORE_GPU_SOFT_RESET, NULL, NULL, 0u, 0);
kbase_tlstream_jd_gpu_soft_reset(kbdev);
@@ -1304,7 +1270,7 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
/* GPU has been reset */
hrtimer_cancel(&rtdata.timer);
destroy_hrtimer_on_stack(&rtdata.timer);
- goto out;
+ return 0;
}
/* No interrupt has been received - check if the RAWSTAT register says
@@ -1340,7 +1306,7 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
/* GPU has been reset */
hrtimer_cancel(&rtdata.timer);
destroy_hrtimer_on_stack(&rtdata.timer);
- goto out;
+ return 0;
}
destroy_hrtimer_on_stack(&rtdata.timer);
@@ -1348,10 +1314,75 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
dev_err(kbdev->dev, "Failed to hard-reset the GPU (timed out after %d ms)\n",
RESET_TIMEOUT);
- /* The GPU still hasn't reset, give up */
return -EINVAL;
+}
+
+static int kbase_pm_reset_do_protected(struct kbase_device *kbdev)
+{
+ KBASE_TRACE_ADD(kbdev, CORE_GPU_SOFT_RESET, NULL, NULL, 0u, 0);
+ kbase_tlstream_jd_gpu_soft_reset(kbdev);
-out:
+ return kbdev->protected_ops->protected_mode_reset(kbdev);
+}
+
+int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
+{
+ unsigned long irq_flags;
+ int err;
+ bool resume_vinstr = false;
+
+ KBASE_DEBUG_ASSERT(NULL != kbdev);
+ lockdep_assert_held(&kbdev->pm.lock);
+
+ /* Ensure the clock is on before attempting to access the hardware */
+ if (!kbdev->pm.backend.gpu_powered) {
+ if (kbdev->pm.backend.callback_power_on)
+ kbdev->pm.backend.callback_power_on(kbdev);
+
+ spin_lock_irqsave(&kbdev->pm.backend.gpu_powered_lock,
+ irq_flags);
+ kbdev->pm.backend.gpu_powered = true;
+ spin_unlock_irqrestore(&kbdev->pm.backend.gpu_powered_lock,
+ irq_flags);
+ }
+
+ /* Ensure interrupts are off to begin with, this also clears any
+ * outstanding interrupts */
+ kbase_pm_disable_interrupts(kbdev);
+ /* Ensure cache snoops are disabled before reset. */
+ kbase_pm_cache_snoop_disable(kbdev);
+ /* Prepare for the soft-reset */
+ kbdev->pm.backend.reset_done = false;
+
+ /* The cores should be made unavailable due to the reset */
+ spin_lock_irqsave(&kbdev->pm.power_change_lock, irq_flags);
+ if (kbdev->shader_available_bitmap != 0u)
+ KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL,
+ NULL, 0u, (u32)0u);
+ if (kbdev->tiler_available_bitmap != 0u)
+ KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER,
+ NULL, NULL, 0u, (u32)0u);
+ kbdev->shader_available_bitmap = 0u;
+ kbdev->tiler_available_bitmap = 0u;
+ kbdev->l2_available_bitmap = 0u;
+ spin_unlock_irqrestore(&kbdev->pm.power_change_lock, irq_flags);
+
+ /* Soft reset the GPU */
+ if (kbdev->protected_mode_support &&
+ kbdev->protected_ops->protected_mode_reset)
+ err = kbase_pm_reset_do_protected(kbdev);
+ else
+ err = kbase_pm_reset_do_normal(kbdev);
+
+ spin_lock_irqsave(&kbdev->js_data.runpool_irq.lock, irq_flags);
+ if (kbdev->protected_mode)
+ resume_vinstr = true;
+ kbdev->protected_mode_transition = false;
+ kbdev->protected_mode = false;
+ spin_unlock_irqrestore(&kbdev->js_data.runpool_irq.lock, irq_flags);
+
+ if (err)
+ goto exit;
if (flags & PM_HW_ISSUES_DETECT)
kbase_pm_hw_issues_detect(kbdev);
@@ -1360,12 +1391,12 @@ out:
kbase_cache_set_coherency_mode(kbdev, kbdev->system_coherency);
+ /* Sanity check protected mode was left after reset */
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_MODE)) {
u32 gpu_status = kbase_reg_read(kbdev,
GPU_CONTROL_REG(GPU_STATUS), NULL);
- kbdev->secure_mode = (gpu_status &
- GPU_STATUS_PROTECTED_MODE_ACTIVE) != 0;
+ WARN_ON(gpu_status & GPU_STATUS_PROTECTED_MODE_ACTIVE);
}
/* If cycle counter was in use re-enable it, enable_irqs will only be
@@ -1394,7 +1425,12 @@ out:
if (flags & PM_ENABLE_IRQS)
kbase_pm_enable_interrupts(kbdev);
- return 0;
+exit:
+ /* If GPU is leaving protected mode resume vinstr operation. */
+ if (kbdev->vinstr_ctx && resume_vinstr)
+ kbase_vinstr_resume(kbdev->vinstr_ctx);
+
+ return err;
}
/**
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_policy.c b/mali_kbase/backend/gpu/mali_kbase_pm_policy.c
index ad0e98b..4d00602 100644
--- a/mali_kbase/backend/gpu/mali_kbase_pm_policy.c
+++ b/mali_kbase/backend/gpu/mali_kbase_pm_policy.c
@@ -21,7 +21,6 @@
#include <mali_kbase.h>
#include <mali_midg_regmap.h>
-#include <mali_kbase_gator.h>
#include <mali_kbase_pm.h>
#include <mali_kbase_config_defaults.h>
#include <backend/gpu/mali_kbase_pm_internal.h>
@@ -155,16 +154,22 @@ static inline void kbase_timeline_pm_cores_func(struct kbase_device *kbdev,
static void kbasep_pm_do_poweroff_cores(struct kbase_device *kbdev)
{
u64 prev_shader_state = kbdev->pm.backend.desired_shader_state;
+ u64 prev_tiler_state = kbdev->pm.backend.desired_tiler_state;
lockdep_assert_held(&kbdev->pm.power_change_lock);
kbdev->pm.backend.desired_shader_state &=
~kbdev->pm.backend.shader_poweroff_pending;
+ kbdev->pm.backend.desired_tiler_state &=
+ ~kbdev->pm.backend.tiler_poweroff_pending;
kbdev->pm.backend.shader_poweroff_pending = 0;
+ kbdev->pm.backend.tiler_poweroff_pending = 0;
- if (prev_shader_state != kbdev->pm.backend.desired_shader_state
- || kbdev->pm.backend.ca_in_transition) {
+ if (prev_shader_state != kbdev->pm.backend.desired_shader_state ||
+ prev_tiler_state !=
+ kbdev->pm.backend.desired_tiler_state ||
+ kbdev->pm.backend.ca_in_transition) {
bool cores_are_available;
KBASE_TIMELINE_PM_CHECKTRANS(kbdev,
@@ -202,7 +207,8 @@ kbasep_pm_do_gpu_poweroff_callback(struct hrtimer *timer)
queue_work(kbdev->pm.backend.gpu_poweroff_wq,
&kbdev->pm.backend.gpu_poweroff_work);
- if (kbdev->pm.backend.shader_poweroff_pending) {
+ if (kbdev->pm.backend.shader_poweroff_pending ||
+ kbdev->pm.backend.tiler_poweroff_pending) {
kbdev->pm.backend.shader_poweroff_pending_time--;
KBASE_DEBUG_ASSERT(
@@ -327,6 +333,7 @@ void kbase_pm_cancel_deferred_poweroff(struct kbase_device *kbdev)
kbdev->pm.backend.gpu_poweroff_pending = 0;
kbdev->pm.backend.shader_poweroff_pending = 0;
+ kbdev->pm.backend.tiler_poweroff_pending = 0;
kbdev->pm.backend.shader_poweroff_pending_time = 0;
spin_unlock_irqrestore(&kbdev->pm.power_change_lock, flags);
@@ -381,8 +388,10 @@ void kbase_pm_update_active(struct kbase_device *kbdev)
* when there are contexts active */
KBASE_DEBUG_ASSERT(pm->active_count == 0);
- if (backend->shader_poweroff_pending) {
+ if (backend->shader_poweroff_pending ||
+ backend->tiler_poweroff_pending) {
backend->shader_poweroff_pending = 0;
+ backend->tiler_poweroff_pending = 0;
backend->shader_poweroff_pending_time = 0;
}
@@ -441,6 +450,7 @@ void kbase_pm_update_active(struct kbase_device *kbdev)
void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev)
{
u64 desired_bitmap;
+ u64 desired_tiler_bitmap;
bool cores_are_available;
bool do_poweroff = false;
@@ -453,23 +463,37 @@ void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev)
kbdev->pm.backend.pm_current_policy->get_core_mask(kbdev);
desired_bitmap &= kbase_pm_ca_get_core_mask(kbdev);
- /* Enable core 0 if tiler required, regardless of core availability */
if (kbdev->tiler_needed_cnt > 0 || kbdev->tiler_inuse_cnt > 0)
- desired_bitmap |= 1;
+ desired_tiler_bitmap = 1;
+ else
+ desired_tiler_bitmap = 0;
+
+ if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_XAFFINITY)) {
+ /* Unless XAFFINITY is supported, enable core 0 if tiler
+ * required, regardless of core availability */
+ if (kbdev->tiler_needed_cnt > 0 || kbdev->tiler_inuse_cnt > 0)
+ desired_bitmap |= 1;
+ }
if (kbdev->pm.backend.desired_shader_state != desired_bitmap)
KBASE_TRACE_ADD(kbdev, PM_CORES_CHANGE_DESIRED, NULL, NULL, 0u,
(u32)desired_bitmap);
/* Are any cores being powered on? */
if (~kbdev->pm.backend.desired_shader_state & desired_bitmap ||
+ ~kbdev->pm.backend.desired_tiler_state & desired_tiler_bitmap ||
kbdev->pm.backend.ca_in_transition) {
/* Check if we are powering off any cores before updating shader
* state */
- if (kbdev->pm.backend.desired_shader_state & ~desired_bitmap) {
+ if (kbdev->pm.backend.desired_shader_state & ~desired_bitmap ||
+ kbdev->pm.backend.desired_tiler_state &
+ ~desired_tiler_bitmap) {
/* Start timer to power off cores */
kbdev->pm.backend.shader_poweroff_pending |=
(kbdev->pm.backend.desired_shader_state &
~desired_bitmap);
+ kbdev->pm.backend.tiler_poweroff_pending |=
+ (kbdev->pm.backend.desired_tiler_state &
+ ~desired_tiler_bitmap);
if (kbdev->pm.poweroff_shader_ticks)
kbdev->pm.backend.shader_poweroff_pending_time =
@@ -479,21 +503,28 @@ void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev)
}
kbdev->pm.backend.desired_shader_state = desired_bitmap;
+ kbdev->pm.backend.desired_tiler_state = desired_tiler_bitmap;
/* If any cores are being powered on, transition immediately */
cores_are_available = kbase_pm_check_transitions_nolock(kbdev);
- } else if (kbdev->pm.backend.desired_shader_state & ~desired_bitmap) {
+ } else if (kbdev->pm.backend.desired_shader_state & ~desired_bitmap ||
+ kbdev->pm.backend.desired_tiler_state &
+ ~desired_tiler_bitmap) {
/* Start timer to power off cores */
kbdev->pm.backend.shader_poweroff_pending |=
(kbdev->pm.backend.desired_shader_state &
~desired_bitmap);
+ kbdev->pm.backend.tiler_poweroff_pending |=
+ (kbdev->pm.backend.desired_tiler_state &
+ ~desired_tiler_bitmap);
if (kbdev->pm.poweroff_shader_ticks)
kbdev->pm.backend.shader_poweroff_pending_time =
kbdev->pm.poweroff_shader_ticks;
else
kbasep_pm_do_poweroff_cores(kbdev);
} else if (kbdev->pm.active_count == 0 && desired_bitmap != 0 &&
- kbdev->pm.backend.poweroff_timer_needed) {
+ desired_tiler_bitmap != 0 &&
+ kbdev->pm.backend.poweroff_timer_needed) {
/* If power policy is keeping cores on despite there being no
* active contexts then disable poweroff timer as it isn't
* required.
@@ -504,11 +535,17 @@ void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev)
/* Ensure timer does not power off wanted cores and make sure to power
* off unwanted cores */
- if (kbdev->pm.backend.shader_poweroff_pending != 0) {
+ if (kbdev->pm.backend.shader_poweroff_pending ||
+ kbdev->pm.backend.tiler_poweroff_pending) {
kbdev->pm.backend.shader_poweroff_pending &=
~(kbdev->pm.backend.desired_shader_state &
desired_bitmap);
- if (kbdev->pm.backend.shader_poweroff_pending == 0)
+ kbdev->pm.backend.tiler_poweroff_pending &=
+ ~(kbdev->pm.backend.desired_tiler_state &
+ desired_tiler_bitmap);
+
+ if (!kbdev->pm.backend.shader_poweroff_pending &&
+ !kbdev->pm.backend.tiler_poweroff_pending)
kbdev->pm.backend.shader_poweroff_pending_time = 0;
}
diff --git a/mali_kbase/backend/gpu/mali_kbase_power_model_simple.c b/mali_kbase/backend/gpu/mali_kbase_power_model_simple.c
index cd4f0a2..d965033 100644
--- a/mali_kbase/backend/gpu/mali_kbase_power_model_simple.c
+++ b/mali_kbase/backend/gpu/mali_kbase_power_model_simple.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2011-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
@@ -36,7 +36,12 @@ static struct thermal_zone_device *gpu_tz;
static unsigned long model_static_power(unsigned long voltage)
{
- unsigned long temperature, temp;
+#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;
@@ -85,7 +90,11 @@ static unsigned long model_dynamic_power(unsigned long freq,
return (dynamic_coefficient * v2 * f_mhz) / 1000000; /* mW */
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
struct devfreq_cooling_ops power_model_simple_ops = {
+#else
+struct devfreq_cooling_power power_model_simple_ops = {
+#endif
.get_static_power = model_static_power,
.get_dynamic_power = model_dynamic_power,
};
@@ -150,7 +159,7 @@ int kbase_power_model_simple_init(struct kbase_device *kbdev)
dynamic_coefficient = (((dynamic_power * 1000) / voltage_squared)
* 1000) / frequency;
- if (of_property_read_u32_array(power_model_node, "ts", ts, 4)) {
+ if (of_property_read_u32_array(power_model_node, "ts", (u32 *)ts, 4)) {
dev_err(kbdev->dev, "ts in power_model not available\n");
return -EINVAL;
}
diff --git a/mali_kbase/backend/gpu/mali_kbase_power_model_simple.h b/mali_kbase/backend/gpu/mali_kbase_power_model_simple.h
index d20de1e..9b5e69a 100644
--- a/mali_kbase/backend/gpu/mali_kbase_power_model_simple.h
+++ b/mali_kbase/backend/gpu/mali_kbase_power_model_simple.h
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 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
@@ -38,6 +38,10 @@
*/
int kbase_power_model_simple_init(struct kbase_device *kbdev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
extern struct devfreq_cooling_ops power_model_simple_ops;
+#else
+extern struct devfreq_cooling_power power_model_simple_ops;
+#endif
#endif /* _BASE_POWER_MODEL_SIMPLE_H_ */
diff --git a/mali_kbase/backend/gpu/mali_kbase_time.c b/mali_kbase/backend/gpu/mali_kbase_time.c
index 4bcde85..d992989 100644
--- a/mali_kbase/backend/gpu/mali_kbase_time.c
+++ b/mali_kbase/backend/gpu/mali_kbase_time.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 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
@@ -74,9 +74,10 @@ void kbase_wait_write_flush(struct kbase_context *kctx)
{
u32 base_count = 0;
- /* A suspend won't happen here, because we're in a syscall from a
- * userspace thread */
-
+ /*
+ * The caller must be holding onto the kctx or the call is from
+ * userspace.
+ */
kbase_pm_context_active(kctx->kbdev);
kbase_pm_request_gpu_cycle_counter(kctx->kbdev);