diff options
author | Sidath Senanayake <sidaths@google.com> | 2021-08-24 13:16:38 +0100 |
---|---|---|
committer | Sidath Senanayake <sidaths@google.com> | 2021-08-24 16:40:56 +0000 |
commit | c32bd52783def2625b1ad47c54fbdcd72cfa58f9 (patch) | |
tree | 413efc5238e65e517a0a34861a46ac395f7fc2f3 | |
parent | 853ae2836fd7eebed41348d7a5198bcbc89ac496 (diff) | |
download | gpu-android-gs-raviole-5.10-android12-d1.tar.gz |
mali_kbase: platform: power: Only take lock for domain updatesandroid-12.0.0_r0.9android-12.0.0_r0.8android-12.0.0_r0.17android-12.0.0_r0.16android-gs-raviole-5.10-android12-d1
Only take the Pixel Context power management lock when actively
changing the power state of GPU domains.
Bug: 197417527
Signed-off-by: Sidath Senanayake <sidaths@google.com>
Change-Id: If1557150b448d2e980448161b4f96100004f4dc3
-rw-r--r-- | mali_kbase/platform/pixel/mali_kbase_config_platform.h | 37 | ||||
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_power.c | 61 |
2 files changed, 56 insertions, 42 deletions
diff --git a/mali_kbase/platform/pixel/mali_kbase_config_platform.h b/mali_kbase/platform/pixel/mali_kbase_config_platform.h index f75fc39..87df05d 100644 --- a/mali_kbase/platform/pixel/mali_kbase_config_platform.h +++ b/mali_kbase/platform/pixel/mali_kbase_config_platform.h @@ -107,22 +107,23 @@ extern struct protected_mode_ops pixel_protected_ops; #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, + /* + * 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, }; /** @@ -221,7 +222,9 @@ struct gpu_dvfs_metrics_uid_stats; * * @kbdev: The &struct kbase_device for the GPU. * - * @pm.lock: &struct mutex used to control accesses to &state. + * @pm.lock: &struct mutex used to ensure serialization of calls to kernel power + * management functions on the GPU power domain devices held in + * &pm.domain_devs. * @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. diff --git a/mali_kbase/platform/pixel/pixel_gpu_power.c b/mali_kbase/platform/pixel/pixel_gpu_power.c index 53a9ff0..33ea438 100644 --- a/mali_kbase/platform/pixel/pixel_gpu_power.c +++ b/mali_kbase/platform/pixel/pixel_gpu_power.c @@ -47,18 +47,34 @@ static const char * const GPU_PM_DOMAIN_NAMES[GPU_PM_DOMAIN_COUNT] = { * 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. Requires the caller to hold the PM lock. + * Context: Process context. Takes and releases PM lock. + * + * Return: If GPU state has been lost, 1 is returned. Otherwise 0 is returned. */ -static void gpu_pm_power_on_cores(struct kbase_device *kbdev) +static int gpu_pm_power_on_cores(struct kbase_device *kbdev) { + int ret; struct pixel_context *pc = kbdev->platform_context; u64 start_ns = ktime_get_ns(); - lockdep_assert_held(&pc->pm.lock); + mutex_lock(&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]); + /* + * We determine whether GPU state was lost by detecting whether the GPU state reached + * GPU_POWER_LEVEL_OFF before we entered this function. The GPU state is set to be + * GPU_POWER_LEVEL_OFF in the gpu_pm_callback_power_runtime_suspend callback which is run + * when autosuspend for TOP is triggered. + * + * As such, GPU state is only checked at this point in the code (and not at the start) as it + * is after pm_runtime_get_sync() on the TOP domain has been called. If there was an + * autosuspend in progress for TOP, then the call to pm_runtime_get_sync() would have + * blocked until it completed ensuring that the value of pc->pm.state is up-to-date. + */ + ret = (pc->pm.state == GPU_POWER_LEVEL_OFF); + trace_gpu_power_state(ktime_get_ns() - start_ns, GPU_POWER_LEVEL_GLOBAL, GPU_POWER_LEVEL_STACKS); #ifdef CONFIG_MALI_MIDGARD_DVFS @@ -71,6 +87,10 @@ static void gpu_pm_power_on_cores(struct kbase_device *kbdev) #endif pc->pm.state = GPU_POWER_LEVEL_STACKS; + + mutex_unlock(&pc->pm.lock); + + return ret; } /** @@ -79,8 +99,12 @@ 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. If the we have already performed these operations without an intervening call to - * &gpu_pm_power_on_cores, then we take no action. + * delayed suspend. Complete power down of all GPU domains will only occur after this delayed + * suspend, and the kernel notifies of this change via the &gpu_pm_callback_power_runtime_suspend + * callback. + * + * Note: 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. */ @@ -93,6 +117,7 @@ static void gpu_pm_power_off_cores(struct kbase_device *kbdev) if (pc->pm.state > GPU_POWER_LEVEL_GLOBAL) { pm_runtime_put_sync(pc->pm.domain_devs[GPU_PM_DOMAIN_CORES]); + pc->pm.state = GPU_POWER_LEVEL_GLOBAL; pm_runtime_mark_last_busy(pc->pm.domain_devs[GPU_PM_DOMAIN_TOP]); pm_runtime_put_autosuspend(pc->pm.domain_devs[GPU_PM_DOMAIN_TOP]); @@ -102,9 +127,6 @@ 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); @@ -128,21 +150,9 @@ 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; - dev_dbg(kbdev->dev, "%s\n", __func__); - 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; + return gpu_pm_power_on_cores(kbdev); } /** @@ -208,6 +218,11 @@ static void gpu_pm_callback_power_suspend(struct kbase_device *kbdev) * the TOP domain of GPU is about to enter runtime suspend. At this point we take the opportunity * to store that state will be lost and disable DVFS metrics gathering. * + * Note: This function doesn't take the PM lock prior to updating GPU state as it doesn't explicitly + * attempt to update GPU power domain state. The caller of this function (or another function + * further up the callstack) will hold &power.lock for the TOP domain's &struct device and + * that is sufficient for ensuring serialization of the GPU power state. + * * Return: Always returns 0. */ static int gpu_pm_callback_power_runtime_suspend(struct device *dev) @@ -217,13 +232,9 @@ static int gpu_pm_callback_power_runtime_suspend(struct device *dev) dev_dbg(kbdev->dev, "%s\n", __func__); - mutex_lock(&pc->pm.lock); - WARN_ON(pc->pm.state > GPU_POWER_LEVEL_GLOBAL); pc->pm.state = GPU_POWER_LEVEL_OFF; - mutex_unlock(&pc->pm.lock); - #ifdef CONFIG_MALI_MIDGARD_DVFS kbase_pm_metrics_stop(kbdev); #endif |