OSDN Git Service

drm/nouveau/gr/gf100-: expose fecs methods for pausing ctxsw
authorBen Skeggs <bskeggs@redhat.com>
Fri, 1 Feb 2019 03:52:50 +0000 (13:52 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 19 Feb 2019 23:00:00 +0000 (09:00 +1000)
MMU will need access to these.

v2. Apply fix from Rhys Kidd to send correct FECS method for STOP_CTXSW.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h
drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h

index ba1518f..87cc737 100644 (file)
@@ -10,6 +10,8 @@ struct nvkm_gr {
 
 u64 nvkm_gr_units(struct nvkm_gr *);
 int nvkm_gr_tlb_flush(struct nvkm_gr *);
+int nvkm_gr_ctxsw_pause(struct nvkm_device *);
+int nvkm_gr_ctxsw_resume(struct nvkm_device *);
 
 int nv04_gr_new(struct nvkm_device *, int, struct nvkm_gr **);
 int nv10_gr_new(struct nvkm_device *, int, struct nvkm_gr **);
index cd8cf6f..53f6282 100644 (file)
 
 #include <engine/fifo.h>
 
+int
+nvkm_gr_ctxsw_resume(struct nvkm_device *device)
+{
+       struct nvkm_gr *gr = device->gr;
+       if (gr && gr->func->ctxsw.resume)
+               return gr->func->ctxsw.resume(gr);
+       return 0;
+}
+
+int
+nvkm_gr_ctxsw_pause(struct nvkm_device *device)
+{
+       struct nvkm_gr *gr = device->gr;
+       if (gr && gr->func->ctxsw.pause)
+               return gr->func->ctxsw.pause(gr);
+       return 0;
+}
+
 static bool
 nvkm_gr_chsw_load(struct nvkm_engine *engine)
 {
index bfe7400..63802ed 100644 (file)
@@ -715,6 +715,56 @@ gf100_gr_pack_mmio[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
+static int
+gf100_gr_fecs_ctrl_ctxsw(struct gf100_gr *gr, u32 mthd)
+{
+       struct nvkm_device *device = gr->base.engine.subdev.device;
+
+       nvkm_wr32(device, 0x409804, 0xffffffff);
+       nvkm_wr32(device, 0x409840, 0xffffffff);
+       nvkm_wr32(device, 0x409500, 0xffffffff);
+       nvkm_wr32(device, 0x409504, mthd);
+       nvkm_msec(device, 2000,
+               u32 stat = nvkm_rd32(device, 0x409804);
+               if (stat == 0x00000002)
+                       return -EIO;
+               if (stat == 0x00000001)
+                       return 0;
+       );
+
+       return -ETIMEDOUT;
+}
+
+int
+gf100_gr_fecs_start_ctxsw(struct nvkm_gr *base)
+{
+       struct gf100_gr *gr = gf100_gr(base);
+       int ret = 0;
+
+       mutex_lock(&gr->fecs.mutex);
+       if (!--gr->fecs.disable) {
+               if (WARN_ON(ret = gf100_gr_fecs_ctrl_ctxsw(gr, 0x39)))
+                       gr->fecs.disable++;
+       }
+       mutex_unlock(&gr->fecs.mutex);
+       return ret;
+}
+
+int
+gf100_gr_fecs_stop_ctxsw(struct nvkm_gr *base)
+{
+       struct gf100_gr *gr = gf100_gr(base);
+       int ret = 0;
+
+       mutex_lock(&gr->fecs.mutex);
+       if (!gr->fecs.disable++) {
+               if (WARN_ON(ret = gf100_gr_fecs_ctrl_ctxsw(gr, 0x38)))
+                       gr->fecs.disable--;
+       }
+       mutex_unlock(&gr->fecs.mutex);
+       return ret;
+}
+
 int
 gf100_gr_fecs_bind_pointer(struct gf100_gr *gr, u32 inst)
 {
@@ -1891,6 +1941,8 @@ gf100_gr_oneinit(struct nvkm_gr *base)
        if (ret)
                return ret;
 
+       mutex_init(&gr->fecs.mutex);
+
        ret = nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs.falcon);
        if (ret)
                return ret;
@@ -2004,6 +2056,8 @@ gf100_gr_ = {
        .chan_new = gf100_gr_chan_new,
        .object_get = gf100_gr_object_get,
        .chsw_load = gf100_gr_chsw_load,
+       .ctxsw.pause = gf100_gr_fecs_stop_ctxsw,
+       .ctxsw.resume = gf100_gr_fecs_start_ctxsw,
 };
 
 int
index 2c031af..fafdd0b 100644 (file)
@@ -84,6 +84,8 @@ struct gf100_gr {
 
        struct {
                struct nvkm_falcon *falcon;
+               struct mutex mutex;
+               u32 disable;
        } fecs;
 
        struct {
index 66359c2..b8023a6 100644 (file)
@@ -27,6 +27,10 @@ struct nvkm_gr_func {
         */
        u64 (*units)(struct nvkm_gr *);
        bool (*chsw_load)(struct nvkm_gr *);
+       struct {
+               int (*pause)(struct nvkm_gr *);
+               int (*resume)(struct nvkm_gr *);
+       } ctxsw;
        struct nvkm_sclass sclass[];
 };