diff options
Diffstat (limited to 'drm/nouveau/nvkm/engine/gr/gk104.c')
-rw-r--r-- | drm/nouveau/nvkm/engine/gr/gk104.c | 34 |
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) { |