summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2016-03-17 19:17:16 +0000
committerRussell King <rmk+kernel@armlinux.org.uk>2016-08-08 11:03:33 +0100
commitb20b8d4bc709977bf6c66fd08f3539535eaaf182 (patch)
tree21a3d5be7fca43a5385d496c21cab47ce1f7a3e0 /drivers/gpu/drm/etnaviv/etnaviv_gpu.c
parenta09a4e88711b1a8bb8cb1bb825cb85a1941795c2 (diff)
drm: etnaviv: try harder to reset the GPU at probe timedrm-etnaviv-devel
Try harder to reset the GPU at probe time by allowing the GPU to enter runtime PM even if it indicates that it is busy. Where platforms implement PM domains, this allows the GPU domain to be power cycled, which can recover a hung GPU. This can't be done in normal operation as we need to drop the mutex, and dropping the mutex will permit GPU submissions which will keep the GPU from idling. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/gpu/drm/etnaviv/etnaviv_gpu.c')
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index 8948ab07ff36..57aa177ac348 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -599,7 +599,7 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
{
- int ret, i;
+ int ret, i, try;
struct iommu_domain *iommu;
enum etnaviv_iommu_version version;
bool mmuv2;
@@ -642,7 +642,20 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
gpu->memory_base = dma_mask - SZ_2G + 1;
}
- ret = etnaviv_hw_reset(gpu);
+ for (try = 0; try < 2; try++) {
+ ret = etnaviv_hw_reset(gpu);
+ if (ret == 0)
+ break;
+
+ dev_warn(gpu->dev, "GPU failed to reset, trying to power cycle\n");
+ gpu->force_rpm_idle = true;
+ pm_runtime_put_sync(gpu->dev);
+ msleep(100);
+ ret = pm_runtime_get_sync(gpu->dev);
+ gpu->force_rpm_idle = false;
+ if (ret)
+ break;
+ }
if (ret)
goto fail;
@@ -1798,6 +1811,11 @@ static int __maybe_unused etnaviv_gpu_rpm_suspend(struct device *dev)
{
struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+ if (gpu->force_rpm_idle) {
+ etnaviv_gpu_clk_disable(gpu);
+ return 0;
+ }
+
/* If we have outstanding fences, we're not idle */
if (gpu->completed_fence != gpu->active_fence)
return -EBUSY;