diff options
Diffstat (limited to 'drivers/gpu/drm/etnaviv/etnaviv_gpu.c')
-rw-r--r-- | drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 22 |
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; |