From: Ben Skeggs <bskeggs@redhat.com>
Date: Wed, 1 Nov 2017 03:56:19 +1000
Subject: drm/nouveau/imem: separate pre-BAR2-bootstrap objects from the rest
Git-commit: b00b8430468d2922c5ea9a0557c7a36136df98c2
Patch-mainline: v4.15-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166
These will require slow-path access during suspend/resume.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h | 1
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c | 27 ++++++++++++++++++
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c | 1
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h | 1
4 files changed, 30 insertions(+)
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
@@ -9,6 +9,7 @@ struct nvkm_instmem {
spinlock_t lock;
struct list_head list;
+ struct list_head boot;
u32 reserved;
struct nvkm_memory *vbios;
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
@@ -129,6 +129,21 @@ nvkm_instmem_wr32(struct nvkm_instmem *i
return imem->func->wr32(imem, addr, data);
}
+void
+nvkm_instmem_boot(struct nvkm_instmem *imem)
+{
+ /* Separate bootstrapped objects from normal list, as we need
+ * to make sure they're accessed with the slowpath on suspend
+ * and resume.
+ */
+ struct nvkm_instobj *iobj, *itmp;
+ spin_lock(&imem->lock);
+ list_for_each_entry_safe(iobj, itmp, &imem->list, head) {
+ list_move_tail(&iobj->head, &imem->boot);
+ }
+ spin_unlock(&imem->lock);
+}
+
static int
nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend)
{
@@ -141,6 +156,12 @@ nvkm_instmem_fini(struct nvkm_subdev *su
if (ret)
return ret;
}
+
+ list_for_each_entry(iobj, &imem->boot, head) {
+ int ret = nvkm_instobj_save(iobj);
+ if (ret)
+ return ret;
+ }
}
if (imem->func->fini)
@@ -155,6 +176,11 @@ nvkm_instmem_init(struct nvkm_subdev *su
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);
+ }
+
list_for_each_entry(iobj, &imem->list, head) {
if (iobj->suspend)
nvkm_instobj_load(iobj);
@@ -198,4 +224,5 @@ nvkm_instmem_ctor(const struct nvkm_inst
imem->func = func;
spin_lock_init(&imem->lock);
INIT_LIST_HEAD(&imem->list);
+ INIT_LIST_HEAD(&imem->boot);
}
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
@@ -271,6 +271,7 @@ nv50_instobj_boot(struct nvkm_memory *me
}
nv50_instobj_kmap(iobj, vmm);
+ nvkm_instmem_boot(imem);
mutex_unlock(&imem->subdev.mutex);
}
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
@@ -16,6 +16,7 @@ struct nvkm_instmem_func {
void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *,
int index, struct nvkm_instmem *);
+void nvkm_instmem_boot(struct nvkm_instmem *);
#include <core/memory.h>