From 192bd796c27ac6eb9443af4b7e027294316f7c5b Mon Sep 17 00:00:00 2001 From: Sidath Senanayake Date: Wed, 9 Nov 2016 14:14:45 +0100 Subject: 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 Change-Id: I1559e84ef1f3853e66978a6c12307e766b31e30f --- mali_kbase/backend/gpu/mali_kbase_jm_hw.c | 231 +++++++++--------------------- 1 file changed, 66 insertions(+), 165 deletions(-) (limited to 'mali_kbase/backend/gpu/mali_kbase_jm_hw.c') 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 #endif #include +#include #include -#include #include #include #include @@ -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 */ -- cgit v1.2.3