summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2023-09-19 06:21:19 +1000
committerDave Airlie <airlied@redhat.com>2023-10-31 15:08:12 +1000
commit624c6f78cc8d9d1a87eeb4d905f231ea128f4a4f (patch)
treec28118b7f3fc249ad6734457998ea202524790d4 /drivers/gpu/drm/nouveau
parenta25a5d560dada2d2edec1891bf1a89c12d9808ad (diff)
drm/nouveau/imem/tu102-: prepare for GSP-RM
- move suspend/resume paths to HW-specific code - allow (future) RM paths to be based on nv50_instmem Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230918202149.4343-15-skeggsb@gmail.com
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c40
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c45
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h10
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