summaryrefslogtreecommitdiff
path: root/drm/nouveau/nvkm/engine/gr/gk104.c
diff options
context:
space:
mode:
Diffstat (limited to 'drm/nouveau/nvkm/engine/gr/gk104.c')
-rw-r--r--drm/nouveau/nvkm/engine/gr/gk104.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/drm/nouveau/nvkm/engine/gr/gk104.c b/drm/nouveau/nvkm/engine/gr/gk104.c
index abf54928a..56f8d53e6 100644
--- a/drm/nouveau/nvkm/engine/gr/gk104.c
+++ b/drm/nouveau/nvkm/engine/gr/gk104.c
@@ -177,6 +177,40 @@ gk104_gr_pack_mmio[] = {
* PGRAPH engine/subdev functions
******************************************************************************/
+/**
+ * Wait until GR goes idle. GR is considered idle if it is disabled by the
+ * MC (0x200) register, or GR is not busy and a context switch is not in
+ * progress.
+ */
+int
+gk104_gr_wait_idle(struct gf100_gr *gr)
+{
+ struct nvkm_subdev *subdev = &gr->base.engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ unsigned long end_jiffies = jiffies + msecs_to_jiffies(2000);
+ bool gr_enabled, ctxsw_active, gr_busy;
+
+ do {
+ /*
+ * required to make sure FIFO_ENGINE_STATUS (0x2640) is
+ * up-to-date
+ */
+ nvkm_rd32(device, 0x400700);
+
+ gr_enabled = nvkm_rd32(device, 0x200) & 0x1000;
+ ctxsw_active = nvkm_rd32(device, 0x2640) & 0x8000;
+ gr_busy = nvkm_rd32(device, 0x40060c) & 0x1;
+
+ if (!gr_enabled || (!gr_busy && !ctxsw_active))
+ return 0;
+ } while (time_before(jiffies, end_jiffies));
+
+ nvkm_error(subdev,
+ "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n",
+ gr_enabled, ctxsw_active, gr_busy);
+ return -EAGAIN;
+}
+
int
gk104_gr_init(struct gf100_gr *gr)
{