diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2023-09-19 06:21:19 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2023-10-31 15:08:12 +1000 |
commit | 624c6f78cc8d9d1a87eeb4d905f231ea128f4a4f (patch) | |
tree | c28118b7f3fc249ad6734457998ea202524790d4 /drivers/gpu/drm | |
parent | a25a5d560dada2d2edec1891bf1a89c12d9808ad (diff) | |
download | linux-stable-624c6f78cc8d9d1a87eeb4d905f231ea128f4a4f.tar.gz linux-stable-624c6f78cc8d9d1a87eeb4d905f231ea128f4a4f.tar.bz2 linux-stable-624c6f78cc8d9d1a87eeb4d905f231ea128f4a4f.zip |
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')
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 |