diff options
author | Jérôme Glisse <jglisse@redhat.com> | 2017-08-10 13:42:02 -0400 |
---|---|---|
committer | Jérôme Glisse <jglisse@redhat.com> | 2017-08-29 10:34:59 -0400 |
commit | 89d00fdb42239f470b1f312a6c6ac2693ab75a77 (patch) | |
tree | 1da98dbb45299aabfbdcdd0a820d8bcbdc217fe7 /drivers/gpu | |
parent | 91a96fcb30e78e0e400943c4ed6ad98733edb927 (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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvkm/core/mm.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/mm.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c | 28 |
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) { |