summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
diff options
context:
space:
mode:
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;