diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c index 6bf0dad46919..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; @@ -99,9 +100,9 @@ static void * nv04_instobj_dtor(struct nvkm_memory *memory) { struct nv04_instobj *iobj = nv04_instobj(memory); - mutex_lock(&iobj->imem->base.subdev.mutex); + mutex_lock(&iobj->imem->base.mutex); nvkm_mm_free(&iobj->imem->heap, &iobj->node); - mutex_unlock(&iobj->imem->base.subdev.mutex); + mutex_unlock(&iobj->imem->base.mutex); nvkm_instobj_dtor(&iobj->imem->base, &iobj->base); return iobj; } @@ -132,10 +133,9 @@ nv04_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, iobj->base.memory.ptrs = &nv04_instobj_ptrs; iobj->imem = imem; - mutex_lock(&imem->base.subdev.mutex); - ret = nvkm_mm_head(&imem->heap, 0, 1, size, size, - align ? align : 1, &iobj->node); - mutex_unlock(&imem->base.subdev.mutex); + mutex_lock(&imem->base.mutex); + ret = nvkm_mm_head(&imem->heap, 0, 1, size, size, align ? align : 1, &iobj->node); + mutex_unlock(&imem->base.mutex); return ret; } @@ -155,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) { @@ -211,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, @@ -218,14 +262,14 @@ nv04_instmem = { }; int -nv04_instmem_new(struct nvkm_device *device, int index, +nv04_instmem_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_instmem **pimem) { struct nv04_instmem *imem; if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL))) return -ENOMEM; - nvkm_instmem_ctor(&nv04_instmem, device, index, &imem->base); + nvkm_instmem_ctor(&nv04_instmem, device, type, inst, &imem->base); *pimem = &imem->base; return 0; } |
