diff options
author | Sidath Senanayake <sidaths@google.com> | 2016-11-09 14:14:45 +0100 |
---|---|---|
committer | Sidath Senanayake <sidaths@google.com> | 2016-11-09 14:14:45 +0100 |
commit | 192bd796c27ac6eb9443af4b7e027294316f7c5b (patch) | |
tree | af0b7bd546062b6bbc6c32af91009f0f185fe6f4 /mali_kbase/backend/gpu | |
parent | 823a760515e356dfef47c691d827d8ba795ce2a4 (diff) | |
download | gpu-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/gpu')
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); |