diff options
author | Sidath Senanayake <sidaths@google.com> | 2021-08-19 21:56:16 +0100 |
---|---|---|
committer | Sidath Senanayake <sidaths@google.com> | 2021-08-19 23:35:54 +0100 |
commit | 24cf981f70b9258d0a63e3df75008dcd0e88e60b (patch) | |
tree | 1d262e31167882774c3fe9c84a0730e332830d07 | |
parent | 5f5610c2d0250e36bf8ce6e15e9281a843053524 (diff) | |
download | gpu-24cf981f70b9258d0a63e3df75008dcd0e88e60b.tar.gz |
mali_kbase: platform: power: Explicitly track GPU power state
Store the view of GPU power state within the GPU platform integration
itself rather than relying on querying PMU registers.
Test: run cts-dev --include-filter "CtsDeqpTestCases dEQP-VK.protected_memory.*"
Test: Repro steps for race condition from b/196269975#comment71
Test: Ensure inter-frame power off working
Bug: 196269975
Bug: 196300136
Signed-off-by: Sidath Senanayake <sidaths@google.com>
Change-Id: I86f9472b0a43139f28d78cd858608f054910b7ed
-rw-r--r-- | mali_kbase/platform/pixel/mali_kbase_config_platform.h | 25 | ||||
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_power.c | 46 | ||||
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_trace.h | 23 |
3 files changed, 51 insertions, 43 deletions
diff --git a/mali_kbase/platform/pixel/mali_kbase_config_platform.h b/mali_kbase/platform/pixel/mali_kbase_config_platform.h index 8c7611a..f75fc39 100644 --- a/mali_kbase/platform/pixel/mali_kbase_config_platform.h +++ b/mali_kbase/platform/pixel/mali_kbase_config_platform.h @@ -106,6 +106,25 @@ extern struct protected_mode_ops pixel_protected_ops; #define OF_DATA_NUM_MAX 128 #define CPU_FREQ_MAX INT_MAX +enum gpu_power_state { + /* Mali GPUs have a hierarchy of power domains, which must be powered up + * in order and powered down in reverse order. Individual architectures + * and implementations may not allow each domain to be powered up or + * down independently of the others. + * + * The power state can thus be defined as the highest-level domain that + * is currently powered on. + * + * GLOBAL: The frontend (JM, CSF), including registers. + * COREGROUP: The L2 and AXI interface, Tiler, and MMU. + * STACKS: The shader cores. + */ + GPU_POWER_LEVEL_OFF = 0, + GPU_POWER_LEVEL_GLOBAL = 1, + GPU_POWER_LEVEL_COREGROUP = 2, + GPU_POWER_LEVEL_STACKS = 3, +}; + /** * enum gpu_pm_domain - Power domains on the GPU. * @@ -202,10 +221,10 @@ struct gpu_dvfs_metrics_uid_stats; * * @kbdev: The &struct kbase_device for the GPU. * - * @pm.lock: &struct mutex used to control access to the power down sequence. + * @pm.lock: &struct mutex used to control accesses to &state. + * @pm.state: Holds the current power state of the GPU. * @pm.domain_devs Virtual pm domain devices. * @pm.domain_links Links from pm domain devices to the real device. - * @pm.state_lost: Stores whether the TOP domain has been powered off and state lost. * @pm.domain: The power domain the GPU is in. * @pm.status_reg_offset: Register offset to the G3D status in the PMU. Set via DT. * @pm.status_local_power_mask: Mask to extract power status of the GPU. Set via DT. @@ -277,11 +296,11 @@ struct pixel_context { struct { struct mutex lock; + enum gpu_power_state state; struct device *domain_devs[GPU_PM_DOMAIN_COUNT]; struct device_link *domain_links[GPU_PM_DOMAIN_COUNT]; - bool state_lost; struct exynos_pm_domain *domain; unsigned int status_reg_offset; unsigned int status_local_power_mask; diff --git a/mali_kbase/platform/pixel/pixel_gpu_power.c b/mali_kbase/platform/pixel/pixel_gpu_power.c index e117054..53a9ff0 100644 --- a/mali_kbase/platform/pixel/pixel_gpu_power.c +++ b/mali_kbase/platform/pixel/pixel_gpu_power.c @@ -44,16 +44,18 @@ static const char * const GPU_PM_DOMAIN_NAMES[GPU_PM_DOMAIN_COUNT] = { * * @kbdev: The &struct kbase_device for the GPU. * - * Powers off the CORES domain and issues trace points and events. Also powers on TOP and cancels + * Powers on the CORES domain and issues trace points and events. Also powers on TOP and cancels * any pending suspend operations on it. * - * Context: Process context. + * Context: Process context. Requires the caller to hold the PM lock. */ static void gpu_pm_power_on_cores(struct kbase_device *kbdev) { struct pixel_context *pc = kbdev->platform_context; u64 start_ns = ktime_get_ns(); + lockdep_assert_held(&pc->pm.lock); + pm_runtime_get_sync(pc->pm.domain_devs[GPU_PM_DOMAIN_TOP]); pm_runtime_get_sync(pc->pm.domain_devs[GPU_PM_DOMAIN_CORES]); @@ -62,10 +64,13 @@ static void gpu_pm_power_on_cores(struct kbase_device *kbdev) #ifdef CONFIG_MALI_MIDGARD_DVFS gpu_dvfs_event_power_on(kbdev); #endif + #if IS_ENABLED(CONFIG_GOOGLE_BCL) if (pc->pm.bcl_dev) google_init_gpu_ratio(pc->pm.bcl_dev); #endif + + pc->pm.state = GPU_POWER_LEVEL_STACKS; } /** @@ -74,11 +79,8 @@ static void gpu_pm_power_on_cores(struct kbase_device *kbdev) * @kbdev: The &struct kbase_device for the GPU. * * Powers off the CORES domain and issues trace points and events. Also marks the TOP domain for - * delayed suspend. - * - * While the GPU power on sequence occurs only due to incoming GPU work, the power down sequence is - * more complex in that it can be triggered by more than one event. In order to avoid races between - * these power down triggers, we use the PM lock to ensure correct behaviour. + * delayed suspend. If the we have already performed these operations without an intervening call to + * &gpu_pm_power_on_cores, then we take no action. * * Context: Process context. Takes and releases the PM lock. */ @@ -89,8 +91,7 @@ static void gpu_pm_power_off_cores(struct kbase_device *kbdev) mutex_lock(&pc->pm.lock); - if (gpu_pm_get_power_state(kbdev)) { - + if (pc->pm.state > GPU_POWER_LEVEL_GLOBAL) { pm_runtime_put_sync(pc->pm.domain_devs[GPU_PM_DOMAIN_CORES]); pm_runtime_mark_last_busy(pc->pm.domain_devs[GPU_PM_DOMAIN_TOP]); @@ -101,6 +102,9 @@ static void gpu_pm_power_off_cores(struct kbase_device *kbdev) #ifdef CONFIG_MALI_MIDGARD_DVFS gpu_dvfs_event_power_off(kbdev); #endif + + /* We won't reach GPU_POWER_LEVEL_OFF until the autosuspend completes */ + pc->pm.state = GPU_POWER_LEVEL_GLOBAL; } mutex_unlock(&pc->pm.lock); @@ -125,15 +129,19 @@ static void gpu_pm_power_off_cores(struct kbase_device *kbdev) static int gpu_pm_callback_power_on(struct kbase_device *kbdev) { struct pixel_context *pc = kbdev->platform_context; - int ret = (pc->pm.state_lost ? 1 : 0); + int ret; dev_dbg(kbdev->dev, "%s\n", __func__); - if (pc->pm.state_lost) - pc->pm.state_lost = false; + mutex_lock(&pc->pm.lock); + + /* If the GPU is currently off, then state was lost */ + ret = (pc->pm.state == GPU_POWER_LEVEL_OFF); gpu_pm_power_on_cores(kbdev); + mutex_unlock(&pc->pm.lock); + return ret; } @@ -184,16 +192,9 @@ static void gpu_pm_callback_power_off(struct kbase_device *kbdev) */ static void gpu_pm_callback_power_suspend(struct kbase_device *kbdev) { - struct pixel_context *pc = kbdev->platform_context; - dev_dbg(kbdev->dev, "%s\n", __func__); - if (pc->pm.state_lost) - return; - gpu_pm_power_off_cores(kbdev); - - pc->pm.state_lost = true; } #ifdef KBASE_PM_RUNTIME @@ -216,9 +217,12 @@ static int gpu_pm_callback_power_runtime_suspend(struct device *dev) dev_dbg(kbdev->dev, "%s\n", __func__); - WARN_ON(pc->pm.state_lost); + mutex_lock(&pc->pm.lock); + + WARN_ON(pc->pm.state > GPU_POWER_LEVEL_GLOBAL); + pc->pm.state = GPU_POWER_LEVEL_OFF; - pc->pm.state_lost = true; + mutex_unlock(&pc->pm.lock); #ifdef CONFIG_MALI_MIDGARD_DVFS kbase_pm_metrics_stop(kbdev); diff --git a/mali_kbase/platform/pixel/pixel_gpu_trace.h b/mali_kbase/platform/pixel/pixel_gpu_trace.h index ef7cc88..775adde 100644 --- a/mali_kbase/platform/pixel/pixel_gpu_trace.h +++ b/mali_kbase/platform/pixel/pixel_gpu_trace.h @@ -6,25 +6,6 @@ #ifndef _PIXEL_GPU_TRACE_H_ #define _PIXEL_GPU_TRACE_H_ -enum gpu_power_state { - /* Mali GPUs have a hierarchy of power domains, which must be powered up - * in order and powered down in reverse order. Individual architectures - * and implementations may not allow each domain to be powered up or - * down independently of the others. - * - * The power state can thus be defined as the highest-level domain that - * is currently powered on. - * - * GLOBAL: The frontend (JM, CSF), including registers. - * COREGROUP: The L2 and AXI interface, Tiler, and MMU. - * STACKS: The shader cores. - */ - GPU_POWER_LEVEL_OFF = 0, - GPU_POWER_LEVEL_GLOBAL = 1, - GPU_POWER_LEVEL_COREGROUP = 2, - GPU_POWER_LEVEL_STACKS = 3, -}; - #endif /* _PIXEL_GPU_TRACE_H_ */ #undef TRACE_SYSTEM @@ -33,8 +14,12 @@ enum gpu_power_state { #if !defined(_TRACE_PIXEL_GPU_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_PIXEL_GPU_H +/* Linux includes */ #include <linux/tracepoint.h> +/* Pixel integration includes */ +#include "mali_kbase_config_platform.h" + #define GPU_POWER_STATE_SYMBOLIC_STRINGS \ {GPU_POWER_LEVEL_STACKS, "STACKS"}, \ {GPU_POWER_LEVEL_COREGROUP, "COREGROUP"}, \ |