@@ -157,6 +157,17 @@ u32 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
return buffer->offset;
}
+void etnaviv_buffer_end(struct etnaviv_gpu *gpu)
+{
+ struct etnaviv_gem_object *buffer = to_etnaviv_bo(gpu->buffer);
+
+ /* Replace the last WAIT with an END */
+ buffer->offset -= 4;
+
+ CMD_END(buffer);
+ mb();
+}
+
void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
struct etnaviv_gem_submit *submit)
{
@@ -111,6 +111,7 @@ struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
uintptr_t ptr, uint32_t size, uint32_t flags, uint32_t *handle);
u32 etnaviv_buffer_init(struct etnaviv_gpu *gpu);
+void etnaviv_buffer_end(struct etnaviv_gpu *gpu);
void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
struct etnaviv_gem_submit *submit);
bool etnaviv_cmd_validate_one(struct etnaviv_gpu *gpu,
@@ -942,6 +942,35 @@ static int etnaviv_gpu_suspend(struct etnaviv_gpu *gpu)
{
int ret;
+ if (gpu->buffer) {
+ unsigned long timeout;
+
+ /* Replace the last WAIT with END */
+ etnaviv_buffer_end(gpu);
+
+ /*
+ * We know that only the FE is busy here, this should
+ * happen quickly (as the WAIT is only 200 cycles). If
+ * we fail, just warn and continue.
+ */
+ timeout = jiffies + msecs_to_jiffies(100);
+ do {
+ u32 idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
+
+ if ((idle & gpu->idle_mask) == gpu->idle_mask)
+ break;
+
+ if (time_is_before_jiffies(timeout)) {
+ dev_warn(gpu->dev,
+ "timed out waiting for idle: idle=0x%x\n",
+ idle);
+ break;
+ }
+
+ udelay(5);
+ } while (1);
+ }
+
ret = disable_axi(gpu);
if (ret)
return ret;