diff options
-rw-r--r-- | drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 1 |
2 files changed, 21 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; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index 1332802aa831..f36c75ed3470 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -101,6 +101,7 @@ struct etnaviv_gpu { struct mutex lock; struct etnaviv_chip_identity identity; struct etnaviv_file_private *lastctx; + bool force_rpm_idle; bool switch_context; /* 'ring'-buffer: */ |