summaryrefslogtreecommitdiff
path: root/mali_kbase/backend/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'mali_kbase/backend/gpu')
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_gpu.c7
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_jm_hw.c107
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_js_backend.c20
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_backend.c84
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_driver.c28
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_internal.h21
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.