From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:20:52 +0000
Subject: [PATCH] add new system file
---
kernel/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c | 147 +++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 130 insertions(+), 17 deletions(-)
diff --git a/kernel/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c b/kernel/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c
index 3b84d74..2687bee 100644
--- a/kernel/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c
+++ b/kernel/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
- * (C) COPYRIGHT 2015-2021 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2015-2022 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
@@ -21,6 +21,7 @@
#include <mali_kbase.h>
#include <mali_kbase_defs.h>
+#include <device/mali_kbase_device.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
@@ -71,18 +72,32 @@
WARN_ON(regulator_disable(kbdev->regulators[i]));
}
#endif
+
}
static int pm_callback_power_on(struct kbase_device *kbdev)
{
int ret = 1; /* Assume GPU has been powered off */
int error;
+ unsigned long flags;
- dev_dbg(kbdev->dev, "pm_callback_power_on %p\n",
- (void *)kbdev->dev->pm_domain);
+ dev_dbg(kbdev->dev, "%s %pK\n", __func__, (void *)kbdev->dev->pm_domain);
+
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ WARN_ON(kbdev->pm.backend.gpu_powered);
+#if MALI_USE_CSF
+ if (likely(kbdev->csf.firmware_inited)) {
+ WARN_ON(!kbdev->pm.active_count);
+ WARN_ON(kbdev->pm.runtime_active);
+ }
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
enable_gpu_power_control(kbdev);
+ CSTD_UNUSED(error);
+#else
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+#ifdef KBASE_PM_RUNTIME
error = pm_runtime_get_sync(kbdev->dev);
if (error == 1) {
/*
@@ -91,30 +106,106 @@
*/
ret = 0;
}
-
dev_dbg(kbdev->dev, "pm_runtime_get_sync returned %d\n", error);
+#else
+ enable_gpu_power_control(kbdev);
+#endif /* KBASE_PM_RUNTIME */
+
+#endif /* MALI_USE_CSF */
return ret;
}
static void pm_callback_power_off(struct kbase_device *kbdev)
{
- dev_dbg(kbdev->dev, "pm_callback_power_off\n");
+ unsigned long flags;
+
+ dev_dbg(kbdev->dev, "%s\n", __func__);
+
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ WARN_ON(kbdev->pm.backend.gpu_powered);
+#if MALI_USE_CSF
+ if (likely(kbdev->csf.firmware_inited)) {
+#ifdef CONFIG_MALI_BIFROST_DEBUG
+ WARN_ON(kbase_csf_scheduler_get_nr_active_csgs(kbdev));
+#endif
+ WARN_ON(kbdev->pm.backend.mcu_state != KBASE_MCU_OFF);
+ }
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+
+ /* Power down the GPU immediately */
+ disable_gpu_power_control(kbdev);
+#else /* MALI_USE_CSF */
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+
+#ifdef KBASE_PM_RUNTIME
+ pm_runtime_mark_last_busy(kbdev->dev);
+ pm_runtime_put_autosuspend(kbdev->dev);
+#else
+ /* Power down the GPU immediately as runtime PM is disabled */
+ disable_gpu_power_control(kbdev);
+#endif
+#endif /* MALI_USE_CSF */
+}
+
+#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME)
+static void pm_callback_runtime_gpu_active(struct kbase_device *kbdev)
+{
+ unsigned long flags;
+ int error;
+
+ lockdep_assert_held(&kbdev->pm.lock);
+
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ WARN_ON(!kbdev->pm.backend.gpu_powered);
+ WARN_ON(!kbdev->pm.active_count);
+ WARN_ON(kbdev->pm.runtime_active);
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+
+ if (pm_runtime_status_suspended(kbdev->dev)) {
+ error = pm_runtime_get_sync(kbdev->dev);
+ dev_dbg(kbdev->dev, "pm_runtime_get_sync returned %d", error);
+ } else {
+ /* Call the async version here, otherwise there could be
+ * a deadlock if the runtime suspend operation is ongoing.
+ * Caller would have taken the kbdev->pm.lock and/or the
+ * scheduler lock, and the runtime suspend callback function
+ * will also try to acquire the same lock(s).
+ */
+ error = pm_runtime_get(kbdev->dev);
+ dev_dbg(kbdev->dev, "pm_runtime_get returned %d", error);
+ }
+
+ kbdev->pm.runtime_active = true;
+}
+
+static void pm_callback_runtime_gpu_idle(struct kbase_device *kbdev)
+{
+ unsigned long flags;
+
+ lockdep_assert_held(&kbdev->pm.lock);
+
+ dev_dbg(kbdev->dev, "%s", __func__);
+
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ WARN_ON(!kbdev->pm.backend.gpu_powered);
+ WARN_ON(kbdev->pm.backend.l2_state != KBASE_L2_OFF);
+ WARN_ON(kbdev->pm.active_count);
+ WARN_ON(!kbdev->pm.runtime_active);
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
pm_runtime_mark_last_busy(kbdev->dev);
pm_runtime_put_autosuspend(kbdev->dev);
-
-#ifndef KBASE_PM_RUNTIME
- disable_gpu_power_control(kbdev);
-#endif
+ kbdev->pm.runtime_active = false;
}
+#endif
#ifdef KBASE_PM_RUNTIME
static int kbase_device_runtime_init(struct kbase_device *kbdev)
{
int ret = 0;
- dev_dbg(kbdev->dev, "kbase_device_runtime_init\n");
+ dev_dbg(kbdev->dev, "%s\n", __func__);
pm_runtime_set_autosuspend_delay(kbdev->dev, AUTO_SUSPEND_DELAY);
pm_runtime_use_autosuspend(kbdev->dev);
@@ -124,7 +215,12 @@
if (!pm_runtime_enabled(kbdev->dev)) {
dev_warn(kbdev->dev, "pm_runtime not enabled");
- ret = -ENOSYS;
+ ret = -EINVAL;
+ } else if (atomic_read(&kbdev->dev->power.usage_count)) {
+ dev_warn(kbdev->dev,
+ "%s: Device runtime usage count unexpectedly non zero %d",
+ __func__, atomic_read(&kbdev->dev->power.usage_count));
+ ret = -EINVAL;
}
return ret;
@@ -132,24 +228,34 @@
static void kbase_device_runtime_disable(struct kbase_device *kbdev)
{
- dev_dbg(kbdev->dev, "kbase_device_runtime_disable\n");
+ dev_dbg(kbdev->dev, "%s\n", __func__);
+
+ if (atomic_read(&kbdev->dev->power.usage_count))
+ dev_warn(kbdev->dev,
+ "%s: Device runtime usage count unexpectedly non zero %d",
+ __func__, atomic_read(&kbdev->dev->power.usage_count));
+
pm_runtime_disable(kbdev->dev);
}
-#endif
+#endif /* KBASE_PM_RUNTIME */
static int pm_callback_runtime_on(struct kbase_device *kbdev)
{
- dev_dbg(kbdev->dev, "pm_callback_runtime_on\n");
+ dev_dbg(kbdev->dev, "%s\n", __func__);
+#if !MALI_USE_CSF
enable_gpu_power_control(kbdev);
+#endif
return 0;
}
static void pm_callback_runtime_off(struct kbase_device *kbdev)
{
- dev_dbg(kbdev->dev, "pm_callback_runtime_off\n");
+ dev_dbg(kbdev->dev, "%s\n", __func__);
+#if !MALI_USE_CSF
disable_gpu_power_control(kbdev);
+#endif
}
static void pm_callback_resume(struct kbase_device *kbdev)
@@ -163,6 +269,7 @@
{
pm_callback_runtime_off(kbdev);
}
+
struct kbase_pm_callback_conf pm_callbacks = {
.power_on_callback = pm_callback_power_on,
@@ -180,6 +287,12 @@
.power_runtime_on_callback = NULL,
.power_runtime_off_callback = NULL,
#endif /* KBASE_PM_RUNTIME */
+
+#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME)
+ .power_runtime_gpu_idle_callback = pm_callback_runtime_gpu_idle,
+ .power_runtime_gpu_active_callback = pm_callback_runtime_gpu_active,
+#else
+ .power_runtime_gpu_idle_callback = NULL,
+ .power_runtime_gpu_active_callback = NULL,
+#endif
};
-
-
--
Gitblit v1.6.2