From: Ben Skeggs <[email protected]>

- move suspend/resume paths to HW-specific code
- allow (future) RM paths to be based on nv50_instmem

Signed-off-by: Ben Skeggs <[email protected]>
---
 .../drm/nouveau/include/nvkm/subdev/instmem.h |  2 +
 .../drm/nouveau/nvkm/subdev/instmem/base.c    | 40 ++++++-----------
 .../drm/nouveau/nvkm/subdev/instmem/gk20a.c   |  2 +
 .../drm/nouveau/nvkm/subdev/instmem/nv04.c    | 45 +++++++++++++++++++
 .../drm/nouveau/nvkm/subdev/instmem/nv50.c    | 27 +++++++++--
 .../drm/nouveau/nvkm/subdev/instmem/priv.h    | 10 +++++
 6 files changed, 96 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h 
b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
index 92a36ddfc29f..7d93c742ee59 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
@@ -8,6 +8,8 @@ struct nvkm_instmem {
        const struct nvkm_instmem_func *func;
        struct nvkm_subdev subdev;
 
+       bool suspend;
+
        spinlock_t lock;
        struct list_head list;
        struct list_head boot;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
index 24886eabe8dc..a2cd3330efc6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
@@ -28,7 +28,7 @@
 /******************************************************************************
  * instmem object base implementation
  *****************************************************************************/
-static void
+void
 nvkm_instobj_load(struct nvkm_instobj *iobj)
 {
        struct nvkm_memory *memory = &iobj->memory;
@@ -48,7 +48,7 @@ nvkm_instobj_load(struct nvkm_instobj *iobj)
        iobj->suspend = NULL;
 }
 
-static int
+int
 nvkm_instobj_save(struct nvkm_instobj *iobj)
 {
        struct nvkm_memory *memory = &iobj->memory;
@@ -179,24 +179,14 @@ static int
 nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend)
 {
        struct nvkm_instmem *imem = nvkm_instmem(subdev);
-       struct nvkm_instobj *iobj;
+       int ret;
 
        if (suspend) {
-               list_for_each_entry(iobj, &imem->list, head) {
-                       if (iobj->preserve) {
-                               int ret = nvkm_instobj_save(iobj);
-                               if (ret)
-                                       return ret;
-                       }
-               }
-
-               nvkm_bar_bar2_fini(subdev->device);
+               ret = imem->func->suspend(imem);
+               if (ret)
+                       return ret;
 
-               list_for_each_entry(iobj, &imem->boot, head) {
-                       int ret = nvkm_instobj_save(iobj);
-                       if (ret)
-                               return ret;
-               }
+               imem->suspend = true;
        }
 
        if (imem->func->fini)
@@ -209,20 +199,16 @@ static int
 nvkm_instmem_init(struct nvkm_subdev *subdev)
 {
        struct nvkm_instmem *imem = nvkm_instmem(subdev);
-       struct nvkm_instobj *iobj;
 
-       list_for_each_entry(iobj, &imem->boot, head) {
-               if (iobj->suspend)
-                       nvkm_instobj_load(iobj);
-       }
+       if (imem->suspend) {
+               if (imem->func->resume)
+                       imem->func->resume(imem);
 
-       nvkm_bar_bar2_init(subdev->device);
-
-       list_for_each_entry(iobj, &imem->list, head) {
-               if (iobj->suspend)
-                       nvkm_instobj_load(iobj);
+               imem->suspend = false;
+               return 0;
        }
 
+       nvkm_bar_bar2_init(subdev->device);
        return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
index a4ac94a2ab57..1b811d6972a1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
@@ -564,6 +564,8 @@ gk20a_instmem_dtor(struct nvkm_instmem *base)
 static const struct nvkm_instmem_func
 gk20a_instmem = {
        .dtor = gk20a_instmem_dtor,
+       .suspend = nv04_instmem_suspend,
+       .resume = nv04_instmem_resume,
        .memory_new = gk20a_instobj_new,
        .zero = false,
 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
index 25603b01d6f8..e5320ef849bf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
@@ -25,6 +25,7 @@
 #include "priv.h"
 
 #include <core/ramht.h>
+#include <subdev/bar.h>
 
 struct nv04_instmem {
        struct nvkm_instmem base;
@@ -154,6 +155,48 @@ nv04_instmem_wr32(struct nvkm_instmem *imem, u32 addr, u32 
data)
        nvkm_wr32(imem->subdev.device, 0x700000 + addr, data);
 }
 
+void
+nv04_instmem_resume(struct nvkm_instmem *imem)
+{
+       struct nvkm_instobj *iobj;
+
+       list_for_each_entry(iobj, &imem->boot, head) {
+               if (iobj->suspend)
+                       nvkm_instobj_load(iobj);
+       }
+
+       nvkm_bar_bar2_init(imem->subdev.device);
+
+       list_for_each_entry(iobj, &imem->list, head) {
+               if (iobj->suspend)
+                       nvkm_instobj_load(iobj);
+       }
+}
+
+int
+nv04_instmem_suspend(struct nvkm_instmem *imem)
+{
+       struct nvkm_instobj *iobj;
+
+       list_for_each_entry(iobj, &imem->list, head) {
+               if (iobj->preserve) {
+                       int ret = nvkm_instobj_save(iobj);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       nvkm_bar_bar2_fini(imem->subdev.device);
+
+       list_for_each_entry(iobj, &imem->boot, head) {
+               int ret = nvkm_instobj_save(iobj);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int
 nv04_instmem_oneinit(struct nvkm_instmem *base)
 {
@@ -210,6 +253,8 @@ static const struct nvkm_instmem_func
 nv04_instmem = {
        .dtor = nv04_instmem_dtor,
        .oneinit = nv04_instmem_oneinit,
+       .suspend = nv04_instmem_suspend,
+       .resume = nv04_instmem_resume,
        .rd32 = nv04_instmem_rd32,
        .wr32 = nv04_instmem_wr32,
        .memory_new = nv04_instobj_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
index 4b2d7465d22f..6649e30d7cd7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
@@ -27,6 +27,7 @@
 #include <core/memory.h>
 #include <subdev/bar.h>
 #include <subdev/fb.h>
+#include <subdev/gsp.h>
 #include <subdev/mmu.h>
 
 struct nv50_instmem {
@@ -394,24 +395,44 @@ nv50_instmem_fini(struct nvkm_instmem *base)
        nv50_instmem(base)->addr = ~0ULL;
 }
 
+static void *
+nv50_instmem_dtor(struct nvkm_instmem *base)
+{
+       return nv50_instmem(base);
+}
+
 static const struct nvkm_instmem_func
 nv50_instmem = {
+       .dtor = nv50_instmem_dtor,
        .fini = nv50_instmem_fini,
+       .suspend = nv04_instmem_suspend,
+       .resume = nv04_instmem_resume,
        .memory_new = nv50_instobj_new,
        .memory_wrap = nv50_instobj_wrap,
        .zero = false,
 };
 
 int
-nv50_instmem_new(struct nvkm_device *device, enum nvkm_subdev_type type, int 
inst,
-                struct nvkm_instmem **pimem)
+nv50_instmem_new_(const struct nvkm_instmem_func *func,
+                 struct nvkm_device *device, enum nvkm_subdev_type type, int 
inst,
+                 struct nvkm_instmem **pimem)
 {
        struct nv50_instmem *imem;
 
        if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL)))
                return -ENOMEM;
-       nvkm_instmem_ctor(&nv50_instmem, device, type, inst, &imem->base);
+       nvkm_instmem_ctor(func, device, type, inst, &imem->base);
        INIT_LIST_HEAD(&imem->lru);
        *pimem = &imem->base;
        return 0;
 }
+
+int
+nv50_instmem_new(struct nvkm_device *device, enum nvkm_subdev_type type, int 
inst,
+                struct nvkm_instmem **pimem)
+{
+       if (nvkm_gsp_rm(device->gsp))
+               return -ENODEV;
+
+       return nv50_instmem_new_(&nv50_instmem, device, type, inst, pimem);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h 
b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
index 390ca00ab567..95a83358aa7d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
@@ -7,6 +7,8 @@
 struct nvkm_instmem_func {
        void *(*dtor)(struct nvkm_instmem *);
        int (*oneinit)(struct nvkm_instmem *);
+       int (*suspend)(struct nvkm_instmem *);
+       void (*resume)(struct nvkm_instmem *);
        void (*fini)(struct nvkm_instmem *);
        u32  (*rd32)(struct nvkm_instmem *, u32 addr);
        void (*wr32)(struct nvkm_instmem *, u32 addr, u32 data);
@@ -16,10 +18,16 @@ struct nvkm_instmem_func {
        bool zero;
 };
 
+int nv50_instmem_new_(const struct nvkm_instmem_func *, struct nvkm_device *,
+                     enum nvkm_subdev_type, int, struct nvkm_instmem **);
+
 void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *,
                       enum nvkm_subdev_type, int, struct nvkm_instmem *);
 void nvkm_instmem_boot(struct nvkm_instmem *);
 
+int nv04_instmem_suspend(struct nvkm_instmem *);
+void nv04_instmem_resume(struct nvkm_instmem *);
+
 #include <core/memory.h>
 
 struct nvkm_instobj {
@@ -32,4 +40,6 @@ struct nvkm_instobj {
 void nvkm_instobj_ctor(const struct nvkm_memory_func *func,
                       struct nvkm_instmem *, struct nvkm_instobj *);
 void nvkm_instobj_dtor(struct nvkm_instmem *, struct nvkm_instobj *);
+int nvkm_instobj_save(struct nvkm_instobj *);
+void nvkm_instobj_load(struct nvkm_instobj *);
 #endif
-- 
2.41.0

Reply via email to