diff options
Diffstat (limited to 'mali_kbase/backend/gpu')
-rw-r--r-- | mali_kbase/backend/gpu/mali_kbase_gpu.c | 7 | ||||
-rw-r--r-- | mali_kbase/backend/gpu/mali_kbase_jm_hw.c | 107 | ||||
-rw-r--r-- | mali_kbase/backend/gpu/mali_kbase_js_backend.c | 20 | ||||
-rw-r--r-- | mali_kbase/backend/gpu/mali_kbase_pm_backend.c | 84 | ||||
-rw-r--r-- | mali_kbase/backend/gpu/mali_kbase_pm_driver.c | 28 | ||||
-rw-r--r-- | mali_kbase/backend/gpu/mali_kbase_pm_internal.h | 21 |
6 files changed, 128 insertions, 139 deletions
diff --git a/mali_kbase/backend/gpu/mali_kbase_gpu.c b/mali_kbase/backend/gpu/mali_kbase_gpu.c index 3b78100..6bceba1 100644 --- a/mali_kbase/backend/gpu/mali_kbase_gpu.c +++ b/mali_kbase/backend/gpu/mali_kbase_gpu.c @@ -34,6 +34,10 @@ int kbase_backend_early_init(struct kbase_device *kbdev) if (err) return err; + err = kbase_pm_runtime_init(kbdev); + if (err) + goto fail_runtime_pm; + /* Ensure we can access the GPU registers */ kbase_pm_register_access_enable(kbdev); @@ -56,6 +60,8 @@ int kbase_backend_early_init(struct kbase_device *kbdev) fail_pm: kbase_release_interrupts(kbdev); fail_interrupts: + kbase_pm_runtime_term(kbdev); +fail_runtime_pm: kbasep_platform_device_term(kbdev); return err; @@ -65,6 +71,7 @@ void kbase_backend_early_term(struct kbase_device *kbdev) { kbase_hwaccess_pm_term(kbdev); kbase_release_interrupts(kbdev); + kbase_pm_runtime_term(kbdev); kbasep_platform_device_term(kbdev); } diff --git a/mali_kbase/backend/gpu/mali_kbase_jm_hw.c b/mali_kbase/backend/gpu/mali_kbase_jm_hw.c index be88ec8..0a2a0b7 100644 --- a/mali_kbase/backend/gpu/mali_kbase_jm_hw.c +++ b/mali_kbase/backend/gpu/mali_kbase_jm_hw.c @@ -235,10 +235,8 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done) int i; u32 count = 0; ktime_t end_timestamp = ktime_get(); - struct kbasep_js_device_data *js_devdata; KBASE_DEBUG_ASSERT(kbdev); - js_devdata = &kbdev->js_data; KBASE_TRACE_ADD(kbdev, JM_IRQ, NULL, NULL, 0, done); @@ -756,92 +754,43 @@ void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx, } } -struct zap_reset_data { - /* The stages are: - * 1. The timer has never been called - * 2. The zap has timed out, all slots are soft-stopped - the GPU reset - * will happen. The GPU has been reset when - * kbdev->hwaccess.backend.reset_waitq is signalled - * - * (-1 - The timer has been cancelled) - */ - int stage; - struct kbase_device *kbdev; - struct hrtimer timer; - spinlock_t lock; /* protects updates to stage member */ -}; - -static enum hrtimer_restart zap_timeout_callback(struct hrtimer *timer) -{ - struct zap_reset_data *reset_data = container_of(timer, - struct zap_reset_data, timer); - struct kbase_device *kbdev = reset_data->kbdev; - unsigned long flags; - - spin_lock_irqsave(&reset_data->lock, flags); - - if (reset_data->stage == -1) - goto out; - -#if KBASE_GPU_RESET_EN - if (kbase_prepare_to_reset_gpu(kbdev)) { - dev_err(kbdev->dev, "Issueing GPU soft-reset because jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n", - ZAP_TIMEOUT); - kbase_reset_gpu(kbdev); - } -#endif /* KBASE_GPU_RESET_EN */ - reset_data->stage = 2; - - out: - spin_unlock_irqrestore(&reset_data->lock, flags); - - return HRTIMER_NORESTART; -} - void kbase_jm_wait_for_zero_jobs(struct kbase_context *kctx) { struct kbase_device *kbdev = kctx->kbdev; - struct zap_reset_data reset_data; - unsigned long flags; - - hrtimer_init_on_stack(&reset_data.timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - reset_data.timer.function = zap_timeout_callback; + unsigned long timeout = msecs_to_jiffies(ZAP_TIMEOUT); - spin_lock_init(&reset_data.lock); + timeout = wait_event_timeout(kctx->jctx.zero_jobs_wait, + kctx->jctx.job_nr == 0, timeout); - reset_data.kbdev = kbdev; - reset_data.stage = 1; + if (timeout != 0) + timeout = wait_event_timeout( + kctx->jctx.sched_info.ctx.is_scheduled_wait, + !kbase_ctx_flag(kctx, KCTX_SCHEDULED), + timeout); - hrtimer_start(&reset_data.timer, HR_TIMER_DELAY_MSEC(ZAP_TIMEOUT), - HRTIMER_MODE_REL); + /* Neither wait timed out; all done! */ + if (timeout != 0) + goto exit; - /* Wait for all jobs to finish, and for the context to be not-scheduled - * (due to kbase_job_zap_context(), we also guarentee it's not in the JS - * policy queue either */ - wait_event(kctx->jctx.zero_jobs_wait, kctx->jctx.job_nr == 0); - wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, - !kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - - spin_lock_irqsave(&reset_data.lock, flags); - if (reset_data.stage == 1) { - /* The timer hasn't run yet - so cancel it */ - reset_data.stage = -1; +#if KBASE_GPU_RESET_EN + if (kbase_prepare_to_reset_gpu(kbdev)) { + dev_err(kbdev->dev, + "Issueing GPU soft-reset because jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n", + ZAP_TIMEOUT); + kbase_reset_gpu(kbdev); } - spin_unlock_irqrestore(&reset_data.lock, flags); - hrtimer_cancel(&reset_data.timer); - - if (reset_data.stage == 2) { - /* The reset has already started. - * Wait for the reset to complete - */ - wait_event(kbdev->hwaccess.backend.reset_wait, - atomic_read(&kbdev->hwaccess.backend.reset_gpu) - == KBASE_RESET_GPU_NOT_PENDING); - } - destroy_hrtimer_on_stack(&reset_data.timer); + /* Wait for the reset to complete */ + wait_event(kbdev->hwaccess.backend.reset_wait, + atomic_read(&kbdev->hwaccess.backend.reset_gpu) + == KBASE_RESET_GPU_NOT_PENDING); +#else + dev_warn(kbdev->dev, + "Jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n", + ZAP_TIMEOUT); +#endif +exit: dev_dbg(kbdev->dev, "Zap: Finished Context %p", kctx); /* Ensure that the signallers of the waitqs have finished */ @@ -874,8 +823,6 @@ int kbase_job_slot_init(struct kbase_device *kbdev) if (NULL == kbdev->hwaccess.backend.reset_workq) return -EINVAL; - KBASE_DEBUG_ASSERT(0 == - object_is_on_stack(&kbdev->hwaccess.backend.reset_work)); INIT_WORK(&kbdev->hwaccess.backend.reset_work, kbasep_reset_timeout_worker); diff --git a/mali_kbase/backend/gpu/mali_kbase_js_backend.c b/mali_kbase/backend/gpu/mali_kbase_js_backend.c index a8c1af2..63d048f 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-2016 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2017 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -26,14 +26,6 @@ #include <backend/gpu/mali_kbase_js_internal.h> /* - * Define for when dumping is enabled. - * This should not be based on the instrumentation level as whether dumping is - * enabled for a particular level is down to the integrator. However this is - * being used for now as otherwise the cinstr headers would be needed. - */ -#define CINSTR_DUMPING_ENABLED (2 == MALI_INSTRUMENTATION_LEVEL) - -/* * Hold the runpool_mutex for this */ static inline bool timer_callback_should_run(struct kbase_device *kbdev) @@ -119,7 +111,7 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer) if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_5736)) { u32 ticks = atom->ticks++; -#if !CINSTR_DUMPING_ENABLED +#ifndef CONFIG_MALI_JOB_DUMP u32 soft_stop_ticks, hard_stop_ticks, gpu_reset_ticks; if (atom->core_req & BASE_JD_REQ_ONLY_COMPUTE) { @@ -209,8 +201,8 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer) */ reset_needed = true; } -#else /* !CINSTR_DUMPING_ENABLED */ - /* NOTE: During CINSTR_DUMPING_ENABLED, we use +#else /* !CONFIG_MALI_JOB_DUMP */ + /* NOTE: During CONFIG_MALI_JOB_DUMP, we use * the alternate timeouts, which makes the hard- * stop and GPU reset timeout much longer. We * also ensure that we don't soft-stop at all. @@ -219,7 +211,7 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer) /* Job has been scheduled for at least * js_devdata->soft_stop_ticks. We do * not soft-stop during - * CINSTR_DUMPING_ENABLED, however. + * CONFIG_MALI_JOB_DUMP, however. */ dev_dbg(kbdev->dev, "Soft-stop"); } else if (ticks == @@ -248,7 +240,7 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer) */ reset_needed = true; } -#endif /* !CINSTR_DUMPING_ENABLED */ +#endif /* !CONFIG_MALI_JOB_DUMP */ } } } diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_backend.c b/mali_kbase/backend/gpu/mali_kbase_pm_backend.c index c88b80a..a871eae 100644 --- a/mali_kbase/backend/gpu/mali_kbase_pm_backend.c +++ b/mali_kbase/backend/gpu/mali_kbase_pm_backend.c @@ -32,6 +32,57 @@ static void kbase_pm_gpu_poweroff_wait_wq(struct work_struct *data); +int kbase_pm_runtime_init(struct kbase_device *kbdev) +{ + struct kbase_pm_callback_conf *callbacks; + + callbacks = (struct kbase_pm_callback_conf *)POWER_MANAGEMENT_CALLBACKS; + if (callbacks) { + kbdev->pm.backend.callback_power_on = + callbacks->power_on_callback; + kbdev->pm.backend.callback_power_off = + callbacks->power_off_callback; + kbdev->pm.backend.callback_power_suspend = + callbacks->power_suspend_callback; + kbdev->pm.backend.callback_power_resume = + callbacks->power_resume_callback; + kbdev->pm.callback_power_runtime_init = + callbacks->power_runtime_init_callback; + kbdev->pm.callback_power_runtime_term = + callbacks->power_runtime_term_callback; + kbdev->pm.backend.callback_power_runtime_on = + callbacks->power_runtime_on_callback; + kbdev->pm.backend.callback_power_runtime_off = + callbacks->power_runtime_off_callback; + kbdev->pm.backend.callback_power_runtime_idle = + callbacks->power_runtime_idle_callback; + + if (callbacks->power_runtime_init_callback) + return callbacks->power_runtime_init_callback(kbdev); + else + return 0; + } + + kbdev->pm.backend.callback_power_on = NULL; + kbdev->pm.backend.callback_power_off = NULL; + kbdev->pm.backend.callback_power_suspend = NULL; + kbdev->pm.backend.callback_power_resume = NULL; + kbdev->pm.callback_power_runtime_init = NULL; + kbdev->pm.callback_power_runtime_term = NULL; + kbdev->pm.backend.callback_power_runtime_on = NULL; + kbdev->pm.backend.callback_power_runtime_off = NULL; + kbdev->pm.backend.callback_power_runtime_idle = NULL; + + return 0; +} + +void kbase_pm_runtime_term(struct kbase_device *kbdev) +{ + if (kbdev->pm.callback_power_runtime_term) { + kbdev->pm.callback_power_runtime_term(kbdev); + } +} + void kbase_pm_register_access_enable(struct kbase_device *kbdev) { struct kbase_pm_callback_conf *callbacks; @@ -59,7 +110,6 @@ void kbase_pm_register_access_disable(struct kbase_device *kbdev) int kbase_hwaccess_pm_init(struct kbase_device *kbdev) { int ret = 0; - struct kbase_pm_callback_conf *callbacks; KBASE_DEBUG_ASSERT(kbdev != NULL); @@ -81,38 +131,6 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev) kbdev->pm.backend.gpu_in_desired_state = true; init_waitqueue_head(&kbdev->pm.backend.gpu_in_desired_state_wait); - callbacks = (struct kbase_pm_callback_conf *)POWER_MANAGEMENT_CALLBACKS; - if (callbacks) { - kbdev->pm.backend.callback_power_on = - callbacks->power_on_callback; - kbdev->pm.backend.callback_power_off = - callbacks->power_off_callback; - kbdev->pm.backend.callback_power_suspend = - callbacks->power_suspend_callback; - kbdev->pm.backend.callback_power_resume = - callbacks->power_resume_callback; - kbdev->pm.callback_power_runtime_init = - callbacks->power_runtime_init_callback; - kbdev->pm.callback_power_runtime_term = - callbacks->power_runtime_term_callback; - kbdev->pm.backend.callback_power_runtime_on = - callbacks->power_runtime_on_callback; - kbdev->pm.backend.callback_power_runtime_off = - callbacks->power_runtime_off_callback; - kbdev->pm.backend.callback_power_runtime_idle = - callbacks->power_runtime_idle_callback; - } else { - kbdev->pm.backend.callback_power_on = NULL; - kbdev->pm.backend.callback_power_off = NULL; - kbdev->pm.backend.callback_power_suspend = NULL; - kbdev->pm.backend.callback_power_resume = NULL; - kbdev->pm.callback_power_runtime_init = NULL; - kbdev->pm.callback_power_runtime_term = NULL; - kbdev->pm.backend.callback_power_runtime_on = NULL; - kbdev->pm.backend.callback_power_runtime_off = NULL; - kbdev->pm.backend.callback_power_runtime_idle = NULL; - } - /* Initialise the metrics subsystem */ ret = kbasep_pm_metrics_init(kbdev); if (ret) diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_driver.c b/mali_kbase/backend/gpu/mali_kbase_pm_driver.c index cbc258c..26802e4 100644 --- a/mali_kbase/backend/gpu/mali_kbase_pm_driver.c +++ b/mali_kbase/backend/gpu/mali_kbase_pm_driver.c @@ -304,10 +304,8 @@ u64 kbase_pm_get_present_cores(struct kbase_device *kbdev, return kbdev->gpu_props.props.raw_props.shader_present; case KBASE_PM_CORE_TILER: return kbdev->gpu_props.props.raw_props.tiler_present; -#ifdef CONFIG_MALI_CORESTACK case KBASE_PM_CORE_STACK: return kbdev->gpu_props.props.raw_props.stack_present; -#endif /* CONFIG_MALI_CORESTACK */ default: break; } @@ -585,7 +583,7 @@ u64 kbase_pm_core_stack_mask(u64 cores) if (test_bit(i, (unsigned long *)&cores)) { /* Every core which ID >= 16 is filled to stacks 4-7 * instead of 0-3 */ - size_t const stack_num = (i > 16) ? + size_t const stack_num = (i >= 16) ? (i % NUM_CORES_PER_STACK) + 4 : (i % NUM_CORES_PER_STACK); set_bit(stack_num, (unsigned long *)&stack_mask); @@ -1229,15 +1227,25 @@ static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev) kbdev->hw_quirks_mmu = kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG), NULL); - /* Limit read ID width for AXI */ - kbdev->hw_quirks_mmu &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_READS); - kbdev->hw_quirks_mmu |= (DEFAULT_ARID_LIMIT & 0x3) << + + /* Limit read & write ID width for AXI */ + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_3BIT_EXT_RW_L2_MMU_CONFIG)) { + kbdev->hw_quirks_mmu &= ~(L2_MMU_CONFIG_3BIT_LIMIT_EXTERNAL_READS); + kbdev->hw_quirks_mmu |= (DEFAULT_3BIT_ARID_LIMIT & 0x7) << + L2_MMU_CONFIG_3BIT_LIMIT_EXTERNAL_READS_SHIFT; + + kbdev->hw_quirks_mmu &= ~(L2_MMU_CONFIG_3BIT_LIMIT_EXTERNAL_WRITES); + kbdev->hw_quirks_mmu |= (DEFAULT_3BIT_AWID_LIMIT & 0x7) << + L2_MMU_CONFIG_3BIT_LIMIT_EXTERNAL_WRITES_SHIFT; + } else { + kbdev->hw_quirks_mmu &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_READS); + kbdev->hw_quirks_mmu |= (DEFAULT_ARID_LIMIT & 0x3) << L2_MMU_CONFIG_LIMIT_EXTERNAL_READS_SHIFT; - /* Limit write ID width for AXI */ - kbdev->hw_quirks_mmu &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES); - kbdev->hw_quirks_mmu |= (DEFAULT_AWID_LIMIT & 0x3) << + kbdev->hw_quirks_mmu &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES); + kbdev->hw_quirks_mmu |= (DEFAULT_AWID_LIMIT & 0x3) << L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES_SHIFT; + } if (kbdev->system_coherency == COHERENCY_ACE) { /* Allow memory configuration disparity to be ignored, we @@ -1297,6 +1305,8 @@ static void kbase_pm_hw_issues_detect(struct kbase_device *kbdev) } } + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_TLS_HASHING)) + kbdev->hw_quirks_sc |= SC_TLS_HASH_ENABLE; if (!kbdev->hw_quirks_jm) kbdev->hw_quirks_jm = kbase_reg_read(kbdev, diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_internal.h b/mali_kbase/backend/gpu/mali_kbase_pm_internal.h index 6804f45..7b77823 100644 --- a/mali_kbase/backend/gpu/mali_kbase_pm_internal.h +++ b/mali_kbase/backend/gpu/mali_kbase_pm_internal.h @@ -411,14 +411,29 @@ void kbase_pm_release_gpu_cycle_counter_nolock(struct kbase_device *kbdev); void kbase_pm_wait_for_poweroff_complete(struct kbase_device *kbdev); /** + * kbase_pm_runtime_init - Initialize runtime-pm for Mali GPU platform device + * + * Setup the power management callbacks and initialize/enable the runtime-pm + * for the Mali GPU platform device, using the callback function. This must be + * called before the kbase_pm_register_access_enable() function. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +int kbase_pm_runtime_init(struct kbase_device *kbdev); + +/** + * kbase_pm_runtime_term - Disable runtime-pm for Mali GPU platform device + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + */ +void kbase_pm_runtime_term(struct kbase_device *kbdev); + +/** * kbase_pm_register_access_enable - Enable access to GPU registers * * Enables access to the GPU registers before power management has powered up * the GPU with kbase_pm_powerup(). * - * Access to registers should be done using kbase_os_reg_read()/write() at this - * stage, not kbase_reg_read()/write(). - * * This results in the power management callbacks provided in the driver * configuration to get called to turn on power and/or clocks to the GPU. See * kbase_pm_callback_conf. |