summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJérôme Glisse <jglisse@redhat.com>2017-08-10 13:42:02 -0400
committerJérôme Glisse <jglisse@redhat.com>2017-08-29 10:34:59 -0400
commit89d00fdb42239f470b1f312a6c6ac2693ab75a77 (patch)
tree1da98dbb45299aabfbdcdd0a820d8bcbdc217fe7
parent91a96fcb30e78e0e400943c4ed6ad98733edb927 (diff)
drm/nouveau/core/mm: allow to find nvkm_vma from offset
Need this as we can not lookup regular process vma from page table synchronization callback. Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/mm.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/mm.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c28
4 files changed, 43 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h b/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
index edaad5265d52..95f6a8d71559 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
@@ -14,6 +14,7 @@ struct nvkm_mm_node {
u8 type;
u64 offset;
u64 length;
+ void *data;
};
struct nvkm_mm {
@@ -41,6 +42,7 @@ int nvkm_mm_tail(struct nvkm_mm *, u8 heap, u8 type, u64 size_max,
u64 size_min, u64 align, struct nvkm_mm_node **);
void nvkm_mm_free(struct nvkm_mm *, struct nvkm_mm_node **);
void nvkm_mm_dump(struct nvkm_mm *, const char *);
+struct nvkm_mm_node *nvkm_mm_find(struct nvkm_mm *mm, u64 start, u64 end);
static inline bool
nvkm_mm_contiguous(struct nvkm_mm_node *node)
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
index 069c20940740..40022c496087 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
@@ -54,6 +54,7 @@ void nvkm_vm_map(struct nvkm_vma *, struct nvkm_mem *);
void nvkm_vm_map_at(struct nvkm_vma *, u64 offset, u64 length, struct nvkm_mem *);
void nvkm_vm_unmap(struct nvkm_vma *);
void nvkm_vm_unmap_at(struct nvkm_vma *, u64 offset, u64 length);
+struct nvkm_vma *nvkm_vm_find(struct nvkm_vm *vm, u64 start, u64 end);
int nvkm_vmm_new(struct nvkm_mmu *, u64 addr, u64 size, void *argv, u32 argc,
struct lock_class_key *, struct nvkm_vmm **);
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/mm.c b/drivers/gpu/drm/nouveau/nvkm/core/mm.c
index a38630804139..f66197733bb0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/mm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/mm.c
@@ -207,6 +207,18 @@ nvkm_mm_fix(struct nvkm_mm *mm,
return -ENOSPC;
}
+struct nvkm_mm_node *nvkm_mm_find(struct nvkm_mm *mm, u64 start, u64 end)
+{
+ struct nvkm_mm_node *this;
+
+ list_for_each_entry (this, &mm->nodes, nl_entry) {
+ if (start >= this->offset && (this->offset + this->length) >= end)
+ return this;
+ }
+
+ return NULL;
+}
+
static struct nvkm_mm_node *
region_tail(struct nvkm_mm *mm, struct nvkm_mm_node *a, u64 size)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
index b1afd964d5cc..d16d19386425 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
@@ -297,6 +297,7 @@ nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access,
mutex_unlock(&vm->mutex);
return ret;
}
+ vma->node->data = vma;
fpde = (vma->node->offset >> mmu->func->pgt_bits);
lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits;
@@ -344,6 +345,7 @@ nvkm_vm_get_fix(struct nvkm_vm *vm, u64 offset, u64 size, u32 page_shift,
mutex_unlock(&vm->mutex);
return ret;
}
+ vma->node->data = vma;
fpde = (vma->node->offset >> mmu->func->pgt_bits);
lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits;
@@ -398,6 +400,32 @@ nvkm_vm_put(struct nvkm_vma *vma)
nvkm_vm_ref(NULL, &vma->vm, NULL);
}
+struct nvkm_vma *nvkm_vm_find(struct nvkm_vm *vm, u64 start, u64 end)
+{
+ struct nvkm_vma *vma = NULL;
+ struct nvkm_mm_node *node;
+
+ mutex_lock(&vm->mutex);
+again:
+ node = nvkm_mm_find(&vm->mm, start >> 12, end >> 12);
+ if (node) {
+ vma = node->data;
+ if (vma) {
+ if (vma->refcount <= 0) {
+ start = (node->offset + node->length) << 12;
+ if (start < end)
+ goto again;
+ vma = NULL;
+ } else {
+ vma->refcount++;
+ }
+ }
+ }
+ mutex_unlock(&vm->mutex);
+
+ return vma;
+}
+
int
nvkm_vm_boot(struct nvkm_vm *vm, u64 size)
{