From 0a96099691c8cd1ac0744ef30b6846869dc2b566 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 21 Jul 2020 11:34:07 +1000 Subject: drm/nouveau/kms/nv50-: implement proper push buffer control logic We had a, what was supposed to be temporary, hack in the KMS code where we'd completely drain an EVO/NVD channel's push buffer when wrapping to the start again, instead of treating it as a ring buffer. Let's fix that, finally. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c | 4 +++- drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c | 4 +++- drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c | 4 +++- drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c | 4 +++- drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c | 4 +++- 9 files changed, 21 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nvkm') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h index e55054b7329f..9cf2cfe2010c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h @@ -21,6 +21,8 @@ struct nv50_disp_chan { struct nvkm_memory *memory; u64 push; + + u32 suspend_put; }; struct nv50_disp_chan_func { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c index d162b9cf4eac..689e3cdd959a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c @@ -182,6 +182,8 @@ gf119_disp_core_fini(struct nv50_disp_chan *chan) nvkm_error(subdev, "core fini: %08x\n", nvkm_rd32(device, 0x610490)); } + + chan->suspend_put = nvkm_rd32(device, 0x640000); } static int @@ -195,7 +197,7 @@ gf119_disp_core_init(struct nv50_disp_chan *chan) nvkm_wr32(device, 0x610498, 0x00010000); nvkm_wr32(device, 0x61049c, 0x00000001); nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, 0x00000000); + nvkm_wr32(device, 0x640000, chan->suspend_put); nvkm_wr32(device, 0x610490, 0x01000013); /* wait for it to go inactive */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c index 5b7f993c73c7..1b435beef3bf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c @@ -36,7 +36,7 @@ gp102_disp_core_init(struct nv50_disp_chan *chan) nvkm_wr32(device, 0x611498, 0x00010000); nvkm_wr32(device, 0x61149c, 0x00000001); nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, 0x00000000); + nvkm_wr32(device, 0x640000, chan->suspend_put); nvkm_wr32(device, 0x610490, 0x01000013); /* wait for it to go inactive */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c index 4592d0e69fec..e20a48f201f6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c @@ -167,6 +167,7 @@ gv100_disp_core_fini(struct nv50_disp_chan *chan) nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000000); gv100_disp_core_idle(chan); nvkm_mask(device, 0x6104e0, 0x00000002, 0x00000000); + chan->suspend_put = nvkm_rd32(device, 0x680000); } static int @@ -181,7 +182,7 @@ gv100_disp_core_init(struct nv50_disp_chan *chan) nvkm_wr32(device, 0x610b2c, 0x00000040); nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x680000, 0x00000000); + nvkm_wr32(device, 0x680000, chan->suspend_put); nvkm_wr32(device, 0x6104e0, 0x00000013); return gv100_disp_core_idle(chan); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c index 55db9a22b4be..660310b27f9c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c @@ -179,6 +179,8 @@ nv50_disp_core_fini(struct nv50_disp_chan *chan) nvkm_error(subdev, "core fini: %08x\n", nvkm_rd32(device, 0x610200)); } + + chan->suspend_put = nvkm_rd32(device, 0x640000); } static int @@ -198,7 +200,7 @@ nv50_disp_core_init(struct nv50_disp_chan *chan) nvkm_wr32(device, 0x610208, 0x00010000); nvkm_wr32(device, 0x61020c, 0x00000000); nvkm_mask(device, 0x610200, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, 0x00000000); + nvkm_wr32(device, 0x640000, chan->suspend_put); nvkm_wr32(device, 0x610200, 0x01000013); /* wait for it to go inactive */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c index edf7dd0d931d..76425e8586da 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c @@ -53,6 +53,8 @@ gf119_disp_dmac_fini(struct nv50_disp_chan *chan) nvkm_error(subdev, "ch %d fini: %08x\n", user, nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); } + + chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); } static int @@ -68,7 +70,7 @@ gf119_disp_dmac_init(struct nv50_disp_chan *chan) nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000); nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001); nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); /* wait for it to go inactive */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c index f21a433199aa..da258df268d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c @@ -38,7 +38,7 @@ gp102_disp_dmac_init(struct nv50_disp_chan *chan) nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000); nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001); nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); /* wait for it to go inactive */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c index eac0e42da354..fdb624ac6b87 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c @@ -50,10 +50,12 @@ void gv100_disp_dmac_fini(struct nv50_disp_chan *chan) { struct nvkm_device *device = chan->disp->base.engine.subdev.device; + const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; const u32 coff = chan->chid.ctrl * 0x04; nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000000); gv100_disp_dmac_idle(chan); nvkm_mask(device, 0x6104e0 + coff, 0x00000002, 0x00000000); + chan->suspend_put = nvkm_rd32(device, 0x690000 + uoff); } int @@ -71,7 +73,7 @@ gv100_disp_dmac_init(struct nv50_disp_chan *chan) nvkm_wr32(device, 0x610b2c + poff, 0x00000040); nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x690000 + uoff, 0x00000000); + nvkm_wr32(device, 0x690000 + uoff, chan->suspend_put); nvkm_wr32(device, 0x6104e0 + coff, 0x00000013); return gv100_disp_dmac_idle(chan); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c index 9e8a9d7a9b68..d0a7da96d62b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c @@ -94,6 +94,8 @@ nv50_disp_dmac_fini(struct nv50_disp_chan *chan) nvkm_error(subdev, "ch %d fini timeout, %08x\n", user, nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); } + + chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); } static int @@ -109,7 +111,7 @@ nv50_disp_dmac_init(struct nv50_disp_chan *chan) nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000); nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl); nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013); /* wait for it to go inactive */ -- cgit