[PATCH 29/48] staging: etnaviv: fix runtime resume

Lucas Stach l.stach at pengutronix.de
Fri Sep 25 04:57:41 PDT 2015


From: Russell King <rmk+kernel at arm.linux.org.uk>

When resuming a core, especially if it has been powered down by a PM
domain, we need to re-initialise the clock control register, and
perform a reload of the context.

This is important where we have a GPU with multiple execution states,
where we must select the appropriate execution state prior to
processing any further GPU operations from userspace.

Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 38 ++++++++++++++++++++++++++---------
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c b/drivers/staging/etnaviv/etnaviv_gpu.c
index 2a6560be4c51..7b618ed69201 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -1078,7 +1078,7 @@ static int etnaviv_gpu_clk_disable(struct etnaviv_gpu *gpu)
 	return 0;
 }
 
-static int etnaviv_gpu_suspend(struct etnaviv_gpu *gpu)
+static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
 {
 	if (gpu->buffer) {
 		unsigned long timeout;
@@ -1112,6 +1112,29 @@ static int etnaviv_gpu_suspend(struct etnaviv_gpu *gpu)
 	return etnaviv_gpu_clk_disable(gpu);
 }
 
+static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)
+{
+	struct drm_device *drm = gpu->drm;
+	u32 clock;
+	int ret;
+
+	ret = mutex_lock_killable(&drm->struct_mutex);
+	if (ret)
+		return ret;
+
+	clock = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
+		VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
+
+	etnaviv_gpu_load_clock(gpu, clock);
+	etnaviv_gpu_hw_init(gpu);
+
+	gpu->switch_context = true;
+
+	mutex_unlock(&drm->struct_mutex);
+
+	return 0;
+}
+
 static int etnaviv_gpu_bind(struct device *dev, struct device *master,
 	void *data)
 {
@@ -1161,7 +1184,7 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
 	pm_runtime_get_sync(gpu->dev);
 	pm_runtime_put_sync_suspend(gpu->dev);
 #else
-	etnaviv_gpu_suspend(gpu);
+	etnaviv_gpu_hw_suspend(gpu);
 #endif
 
 	if (gpu->buffer) {
@@ -1292,17 +1315,16 @@ static int etnaviv_gpu_rpm_suspend(struct device *dev)
 	if (idle != mask)
 		return -EBUSY;
 
-	return etnaviv_gpu_suspend(gpu);
+	return etnaviv_gpu_hw_suspend(gpu);
 }
 
 static int etnaviv_gpu_rpm_resume(struct device *dev)
 {
 	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
-	struct drm_device *drm = gpu->drm;
 	int ret;
 
 	/* We must never runtime-PM resume holding struct_mutex */
-	if (drm && WARN_ON_ONCE(mutex_is_locked(&drm->struct_mutex)))
+	if (gpu->drm && WARN_ON_ONCE(mutex_is_locked(&gpu->drm->struct_mutex)))
 		return -EDEADLK;
 
 	ret = etnaviv_gpu_clk_enable(gpu);
@@ -1310,14 +1332,12 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
 		return ret;
 
 	/* Re-initialise the basic hardware state */
-	if (drm && gpu->buffer) {
-		ret = mutex_lock_killable(&drm->struct_mutex);
+	if (gpu->drm && gpu->buffer) {
+		ret = etnaviv_gpu_hw_resume(gpu);
 		if (ret) {
 			etnaviv_gpu_clk_disable(gpu);
 			return ret;
 		}
-		etnaviv_gpu_hw_init(gpu);
-		mutex_unlock(&drm->struct_mutex);
 	}
 
 	return 0;
-- 
2.5.1



More information about the dri-devel mailing list