aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/mmu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/mmu')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c234
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c138
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c128
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h15
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c136
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c195
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c174
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h39
8 files changed, 552 insertions, 507 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
index 277b6ec04e24..e04a2296ecd0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
@@ -21,10 +21,10 @@
*
* Authors: Ben Skeggs
*/
-#include <subdev/mmu.h>
-#include <subdev/fb.h>
+#include "priv.h"
#include <core/gpuobj.h>
+#include <subdev/fb.h>
void
nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node)
@@ -32,12 +32,12 @@ nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node)
struct nvkm_vm *vm = vma->vm;
struct nvkm_mmu *mmu = vm->mmu;
struct nvkm_mm_node *r;
- int big = vma->node->type != mmu->spg_shift;
+ int big = vma->node->type != mmu->func->spg_shift;
u32 offset = vma->node->offset + (delta >> 12);
u32 bits = vma->node->type - 12;
- u32 pde = (offset >> mmu->pgt_bits) - vm->fpde;
- u32 pte = (offset & ((1 << mmu->pgt_bits) - 1)) >> bits;
- u32 max = 1 << (mmu->pgt_bits - bits);
+ u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde;
+ u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits;
+ u32 max = 1 << (mmu->func->pgt_bits - bits);
u32 end, len;
delta = 0;
@@ -46,14 +46,14 @@ nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node)
u32 num = r->length >> bits;
while (num) {
- struct nvkm_gpuobj *pgt = vm->pgt[pde].obj[big];
+ struct nvkm_memory *pgt = vm->pgt[pde].mem[big];
end = (pte + num);
if (unlikely(end >= max))
end = max;
len = end - pte;
- mmu->map(vma, pgt, node, pte, len, phys, delta);
+ mmu->func->map(vma, pgt, node, pte, len, phys, delta);
num -= len;
pte += len;
@@ -67,7 +67,7 @@ nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node)
}
}
- mmu->flush(vm);
+ mmu->func->flush(vm);
}
static void
@@ -76,20 +76,20 @@ nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length,
{
struct nvkm_vm *vm = vma->vm;
struct nvkm_mmu *mmu = vm->mmu;
- int big = vma->node->type != mmu->spg_shift;
+ int big = vma->node->type != mmu->func->spg_shift;
u32 offset = vma->node->offset + (delta >> 12);
u32 bits = vma->node->type - 12;
u32 num = length >> vma->node->type;
- u32 pde = (offset >> mmu->pgt_bits) - vm->fpde;
- u32 pte = (offset & ((1 << mmu->pgt_bits) - 1)) >> bits;
- u32 max = 1 << (mmu->pgt_bits - bits);
+ u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde;
+ u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits;
+ u32 max = 1 << (mmu->func->pgt_bits - bits);
unsigned m, sglen;
u32 end, len;
int i;
struct scatterlist *sg;
for_each_sg(mem->sg->sgl, sg, mem->sg->nents, i) {
- struct nvkm_gpuobj *pgt = vm->pgt[pde].obj[big];
+ struct nvkm_memory *pgt = vm->pgt[pde].mem[big];
sglen = sg_dma_len(sg) >> PAGE_SHIFT;
end = pte + sglen;
@@ -100,7 +100,7 @@ nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length,
for (m = 0; m < len; m++) {
dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
- mmu->map_sg(vma, pgt, mem, pte, 1, &addr);
+ mmu->func->map_sg(vma, pgt, mem, pte, 1, &addr);
num--;
pte++;
@@ -115,7 +115,7 @@ nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length,
for (; m < sglen; m++) {
dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
- mmu->map_sg(vma, pgt, mem, pte, 1, &addr);
+ mmu->func->map_sg(vma, pgt, mem, pte, 1, &addr);
num--;
pte++;
if (num == 0)
@@ -125,7 +125,7 @@ nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length,
}
finish:
- mmu->flush(vm);
+ mmu->func->flush(vm);
}
static void
@@ -135,24 +135,24 @@ nvkm_vm_map_sg(struct nvkm_vma *vma, u64 delta, u64 length,
struct nvkm_vm *vm = vma->vm;
struct nvkm_mmu *mmu = vm->mmu;
dma_addr_t *list = mem->pages;
- int big = vma->node->type != mmu->spg_shift;
+ int big = vma->node->type != mmu->func->spg_shift;
u32 offset = vma->node->offset + (delta >> 12);
u32 bits = vma->node->type - 12;
u32 num = length >> vma->node->type;
- u32 pde = (offset >> mmu->pgt_bits) - vm->fpde;
- u32 pte = (offset & ((1 << mmu->pgt_bits) - 1)) >> bits;
- u32 max = 1 << (mmu->pgt_bits - bits);
+ u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde;
+ u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits;
+ u32 max = 1 << (mmu->func->pgt_bits - bits);
u32 end, len;
while (num) {
- struct nvkm_gpuobj *pgt = vm->pgt[pde].obj[big];
+ struct nvkm_memory *pgt = vm->pgt[pde].mem[big];
end = (pte + num);
if (unlikely(end >= max))
end = max;
len = end - pte;
- mmu->map_sg(vma, pgt, mem, pte, len, list);
+ mmu->func->map_sg(vma, pgt, mem, pte, len, list);
num -= len;
pte += len;
@@ -163,7 +163,7 @@ nvkm_vm_map_sg(struct nvkm_vma *vma, u64 delta, u64 length,
}
}
- mmu->flush(vm);
+ mmu->func->flush(vm);
}
void
@@ -183,24 +183,24 @@ nvkm_vm_unmap_at(struct nvkm_vma *vma, u64 delta, u64 length)
{
struct nvkm_vm *vm = vma->vm;
struct nvkm_mmu *mmu = vm->mmu;
- int big = vma->node->type != mmu->spg_shift;
+ int big = vma->node->type != mmu->func->spg_shift;
u32 offset = vma->node->offset + (delta >> 12);
u32 bits = vma->node->type - 12;
u32 num = length >> vma->node->type;
- u32 pde = (offset >> mmu->pgt_bits) - vm->fpde;
- u32 pte = (offset & ((1 << mmu->pgt_bits) - 1)) >> bits;
- u32 max = 1 << (mmu->pgt_bits - bits);
+ u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde;
+ u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits;
+ u32 max = 1 << (mmu->func->pgt_bits - bits);
u32 end, len;
while (num) {
- struct nvkm_gpuobj *pgt = vm->pgt[pde].obj[big];
+ struct nvkm_memory *pgt = vm->pgt[pde].mem[big];
end = (pte + num);
if (unlikely(end >= max))
end = max;
len = end - pte;
- mmu->unmap(pgt, pte, len);
+ mmu->func->unmap(vma, pgt, pte, len);
num -= len;
pte += len;
@@ -210,7 +210,7 @@ nvkm_vm_unmap_at(struct nvkm_vma *vma, u64 delta, u64 length)
}
}
- mmu->flush(vm);
+ mmu->func->flush(vm);
}
void
@@ -225,7 +225,7 @@ nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde)
struct nvkm_mmu *mmu = vm->mmu;
struct nvkm_vm_pgd *vpgd;
struct nvkm_vm_pgt *vpgt;
- struct nvkm_gpuobj *pgt;
+ struct nvkm_memory *pgt;
u32 pde;
for (pde = fpde; pde <= lpde; pde++) {
@@ -233,16 +233,14 @@ nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde)
if (--vpgt->refcount[big])
continue;
- pgt = vpgt->obj[big];
- vpgt->obj[big] = NULL;
+ pgt = vpgt->mem[big];
+ vpgt->mem[big] = NULL;
list_for_each_entry(vpgd, &vm->pgd_list, head) {
- mmu->map_pgt(vpgd->obj, pde, vpgt->obj);
+ mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem);
}
- mutex_unlock(&nv_subdev(mmu)->mutex);
- nvkm_gpuobj_ref(NULL, &pgt);
- mutex_lock(&nv_subdev(mmu)->mutex);
+ nvkm_memory_del(&pgt);
}
}
@@ -252,34 +250,23 @@ nvkm_vm_map_pgt(struct nvkm_vm *vm, u32 pde, u32 type)
struct nvkm_mmu *mmu = vm->mmu;
struct nvkm_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde];
struct nvkm_vm_pgd *vpgd;
- struct nvkm_gpuobj *pgt;
- int big = (type != mmu->spg_shift);
+ int big = (type != mmu->func->spg_shift);
u32 pgt_size;
int ret;
- pgt_size = (1 << (mmu->pgt_bits + 12)) >> type;
+ pgt_size = (1 << (mmu->func->pgt_bits + 12)) >> type;
pgt_size *= 8;
- mutex_unlock(&nv_subdev(mmu)->mutex);
- ret = nvkm_gpuobj_new(nv_object(vm->mmu), NULL, pgt_size, 0x1000,
- NVOBJ_FLAG_ZERO_ALLOC, &pgt);
- mutex_lock(&nv_subdev(mmu)->mutex);
+ ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST,
+ pgt_size, 0x1000, true, &vpgt->mem[big]);
if (unlikely(ret))
return ret;
- /* someone beat us to filling the PDE while we didn't have the lock */
- if (unlikely(vpgt->refcount[big]++)) {
- mutex_unlock(&nv_subdev(mmu)->mutex);
- nvkm_gpuobj_ref(NULL, &pgt);
- mutex_lock(&nv_subdev(mmu)->mutex);
- return 0;
- }
-
- vpgt->obj[big] = pgt;
list_for_each_entry(vpgd, &vm->pgd_list, head) {
- mmu->map_pgt(vpgd->obj, pde, vpgt->obj);
+ mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem);
}
+ vpgt->refcount[big]++;
return 0;
}
@@ -293,20 +280,20 @@ nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access,
u32 fpde, lpde, pde;
int ret;
- mutex_lock(&nv_subdev(mmu)->mutex);
+ mutex_lock(&vm->mutex);
ret = nvkm_mm_head(&vm->mm, 0, page_shift, msize, msize, align,
&vma->node);
if (unlikely(ret != 0)) {
- mutex_unlock(&nv_subdev(mmu)->mutex);
+ mutex_unlock(&vm->mutex);
return ret;
}
- fpde = (vma->node->offset >> mmu->pgt_bits);
- lpde = (vma->node->offset + vma->node->length - 1) >> mmu->pgt_bits;
+ fpde = (vma->node->offset >> mmu->func->pgt_bits);
+ lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits;
for (pde = fpde; pde <= lpde; pde++) {
struct nvkm_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde];
- int big = (vma->node->type != mmu->spg_shift);
+ int big = (vma->node->type != mmu->func->spg_shift);
if (likely(vpgt->refcount[big])) {
vpgt->refcount[big]++;
@@ -318,11 +305,11 @@ nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access,
if (pde != fpde)
nvkm_vm_unmap_pgt(vm, big, fpde, pde - 1);
nvkm_mm_free(&vm->mm, &vma->node);
- mutex_unlock(&nv_subdev(mmu)->mutex);
+ mutex_unlock(&vm->mutex);
return ret;
}
}
- mutex_unlock(&nv_subdev(mmu)->mutex);
+ mutex_unlock(&vm->mutex);
vma->vm = NULL;
nvkm_vm_ref(vm, &vma->vm, NULL);
@@ -334,27 +321,49 @@ nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access,
void
nvkm_vm_put(struct nvkm_vma *vma)
{
- struct nvkm_vm *vm = vma->vm;
- struct nvkm_mmu *mmu = vm->mmu;
+ struct nvkm_mmu *mmu;
+ struct nvkm_vm *vm;
u32 fpde, lpde;
if (unlikely(vma->node == NULL))
return;
- fpde = (vma->node->offset >> mmu->pgt_bits);
- lpde = (vma->node->offset + vma->node->length - 1) >> mmu->pgt_bits;
+ vm = vma->vm;
+ mmu = vm->mmu;
+
+ fpde = (vma->node->offset >> mmu->func->pgt_bits);
+ lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits;
- mutex_lock(&nv_subdev(mmu)->mutex);
- nvkm_vm_unmap_pgt(vm, vma->node->type != mmu->spg_shift, fpde, lpde);
+ mutex_lock(&vm->mutex);
+ nvkm_vm_unmap_pgt(vm, vma->node->type != mmu->func->spg_shift, fpde, lpde);
nvkm_mm_free(&vm->mm, &vma->node);
- mutex_unlock(&nv_subdev(mmu)->mutex);
+ mutex_unlock(&vm->mutex);
nvkm_vm_ref(NULL, &vma->vm, NULL);
}
int
+nvkm_vm_boot(struct nvkm_vm *vm, u64 size)
+{
+ struct nvkm_mmu *mmu = vm->mmu;
+ struct nvkm_memory *pgt;
+ int ret;
+
+ ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST,
+ (size >> mmu->func->spg_shift) * 8, 0x1000, true, &pgt);
+ if (ret == 0) {
+ vm->pgt[0].refcount[0] = 1;
+ vm->pgt[0].mem[0] = pgt;
+ nvkm_memory_boot(pgt, vm);
+ }
+
+ return ret;
+}
+
+int
nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset,
- u32 block, struct nvkm_vm **pvm)
+ u32 block, struct lock_class_key *key, struct nvkm_vm **pvm)
{
+ static struct lock_class_key _key;
struct nvkm_vm *vm;
u64 mm_length = (offset + length) - mm_offset;
int ret;
@@ -363,11 +372,12 @@ nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset,
if (!vm)
return -ENOMEM;
+ __mutex_init(&vm->mutex, "&vm->mutex", key ? key : &_key);
INIT_LIST_HEAD(&vm->pgd_list);
vm->mmu = mmu;
kref_init(&vm->refcount);
- vm->fpde = offset >> (mmu->pgt_bits + 12);
- vm->lpde = (offset + length - 1) >> (mmu->pgt_bits + 12);
+ vm->fpde = offset >> (mmu->func->pgt_bits + 12);
+ vm->lpde = (offset + length - 1) >> (mmu->func->pgt_bits + 12);
vm->pgt = vzalloc((vm->lpde - vm->fpde + 1) * sizeof(*vm->pgt));
if (!vm->pgt) {
@@ -390,10 +400,12 @@ nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset,
int
nvkm_vm_new(struct nvkm_device *device, u64 offset, u64 length, u64 mm_offset,
- struct nvkm_vm **pvm)
+ struct lock_class_key *key, struct nvkm_vm **pvm)
{
- struct nvkm_mmu *mmu = nvkm_mmu(device);
- return mmu->create(mmu, offset, length, mm_offset, pvm);
+ struct nvkm_mmu *mmu = device->mmu;
+ if (!mmu->func->create)
+ return -EINVAL;
+ return mmu->func->create(mmu, offset, length, mm_offset, key, pvm);
}
static int
@@ -410,38 +422,33 @@ nvkm_vm_link(struct nvkm_vm *vm, struct nvkm_gpuobj *pgd)
if (!vpgd)
return -ENOMEM;
- nvkm_gpuobj_ref(pgd, &vpgd->obj);
+ vpgd->obj = pgd;
- mutex_lock(&nv_subdev(mmu)->mutex);
+ mutex_lock(&vm->mutex);
for (i = vm->fpde; i <= vm->lpde; i++)
- mmu->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj);
+ mmu->func->map_pgt(pgd, i, vm->pgt[i - vm->fpde].mem);
list_add(&vpgd->head, &vm->pgd_list);
- mutex_unlock(&nv_subdev(mmu)->mutex);
+ mutex_unlock(&vm->mutex);
return 0;
}
static void
nvkm_vm_unlink(struct nvkm_vm *vm, struct nvkm_gpuobj *mpgd)
{
- struct nvkm_mmu *mmu = vm->mmu;
struct nvkm_vm_pgd *vpgd, *tmp;
- struct nvkm_gpuobj *pgd = NULL;
if (!mpgd)
return;
- mutex_lock(&nv_subdev(mmu)->mutex);
+ mutex_lock(&vm->mutex);
list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
if (vpgd->obj == mpgd) {
- pgd = vpgd->obj;
list_del(&vpgd->head);
kfree(vpgd);
break;
}
}
- mutex_unlock(&nv_subdev(mmu)->mutex);
-
- nvkm_gpuobj_ref(NULL, &pgd);
+ mutex_unlock(&vm->mutex);
}
static void
@@ -478,3 +485,58 @@ nvkm_vm_ref(struct nvkm_vm *ref, struct nvkm_vm **ptr, struct nvkm_gpuobj *pgd)
*ptr = ref;
return 0;
}
+
+static int
+nvkm_mmu_oneinit(struct nvkm_subdev *subdev)
+{
+ struct nvkm_mmu *mmu = nvkm_mmu(subdev);
+ if (mmu->func->oneinit)
+ return mmu->func->oneinit(mmu);
+ return 0;
+}
+
+static int
+nvkm_mmu_init(struct nvkm_subdev *subdev)
+{
+ struct nvkm_mmu *mmu = nvkm_mmu(subdev);
+ if (mmu->func->init)
+ mmu->func->init(mmu);
+ return 0;
+}
+
+static void *
+nvkm_mmu_dtor(struct nvkm_subdev *subdev)
+{
+ struct nvkm_mmu *mmu = nvkm_mmu(subdev);
+ if (mmu->func->dtor)
+ return mmu->func->dtor(mmu);
+ return mmu;
+}
+
+static const struct nvkm_subdev_func
+nvkm_mmu = {
+ .dtor = nvkm_mmu_dtor,
+ .oneinit = nvkm_mmu_oneinit,
+ .init = nvkm_mmu_init,
+};
+
+void
+nvkm_mmu_ctor(const struct nvkm_mmu_func *func, struct nvkm_device *device,
+ int index, struct nvkm_mmu *mmu)
+{
+ nvkm_subdev_ctor(&nvkm_mmu, device, index, 0, &mmu->subdev);
+ mmu->func = func;
+ mmu->limit = func->limit;
+ mmu->dma_bits = func->dma_bits;
+ mmu->lpg_shift = func->lpg_shift;
+}
+
+int
+nvkm_mmu_new_(const struct nvkm_mmu_func *func, struct nvkm_device *device,
+ int index, struct nvkm_mmu **pmmu)
+{
+ if (!(*pmmu = kzalloc(sizeof(**pmmu), GFP_KERNEL)))
+ return -ENOMEM;
+ nvkm_mmu_ctor(func, device, index, *pmmu);
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
index 294cda37f068..7ac507c927bb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
@@ -21,19 +21,14 @@
*
* Authors: Ben Skeggs
*/
-#include <subdev/mmu.h>
-#include <subdev/bar.h>
+#include "priv.h"
+
#include <subdev/fb.h>
#include <subdev/ltc.h>
#include <subdev/timer.h>
#include <core/gpuobj.h>
-struct gf100_mmu_priv {
- struct nvkm_mmu base;
-};
-
-
/* Map from compressed to corresponding uncompressed storage type.
* The value 0xff represents an invalid storage type.
*/
@@ -75,17 +70,19 @@ const u8 gf100_pte_storage_type_map[256] =
static void
-gf100_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 index, struct nvkm_gpuobj *pgt[2])
+gf100_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 index, struct nvkm_memory *pgt[2])
{
u32 pde[2] = { 0, 0 };
if (pgt[0])
- pde[1] = 0x00000001 | (pgt[0]->addr >> 8);
+ pde[1] = 0x00000001 | (nvkm_memory_addr(pgt[0]) >> 8);
if (pgt[1])
- pde[0] = 0x00000001 | (pgt[1]->addr >> 8);
+ pde[0] = 0x00000001 | (nvkm_memory_addr(pgt[1]) >> 8);
- nv_wo32(pgd, (index * 8) + 0, pde[0]);
- nv_wo32(pgd, (index * 8) + 4, pde[1]);
+ nvkm_kmap(pgd);
+ nvkm_wo32(pgd, (index * 8) + 0, pde[0]);
+ nvkm_wo32(pgd, (index * 8) + 4, pde[1]);
+ nvkm_done(pgd);
}
static inline u64
@@ -103,7 +100,7 @@ gf100_vm_addr(struct nvkm_vma *vma, u64 phys, u32 memtype, u32 target)
}
static void
-gf100_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+gf100_vm_map(struct nvkm_vma *vma, struct nvkm_memory *pgt,
struct nvkm_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
{
u64 next = 1 << (vma->node->type - 8);
@@ -112,126 +109,113 @@ gf100_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
pte <<= 3;
if (mem->tag) {
- struct nvkm_ltc *ltc = nvkm_ltc(vma->vm->mmu);
+ struct nvkm_ltc *ltc = vma->vm->mmu->subdev.device->ltc;
u32 tag = mem->tag->offset + (delta >> 17);
phys |= (u64)tag << (32 + 12);
next |= (u64)1 << (32 + 12);
- ltc->tags_clear(ltc, tag, cnt);
+ nvkm_ltc_tags_clear(ltc, tag, cnt);
}
+ nvkm_kmap(pgt);
while (cnt--) {
- nv_wo32(pgt, pte + 0, lower_32_bits(phys));
- nv_wo32(pgt, pte + 4, upper_32_bits(phys));
+ nvkm_wo32(pgt, pte + 0, lower_32_bits(phys));
+ nvkm_wo32(pgt, pte + 4, upper_32_bits(phys));
phys += next;
pte += 8;
}
+ nvkm_done(pgt);
}
static void
-gf100_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+gf100_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
{
u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5;
/* compressed storage types are invalid for system memory */
u32 memtype = gf100_pte_storage_type_map[mem->memtype & 0xff];
+ nvkm_kmap(pgt);
pte <<= 3;
while (cnt--) {
u64 phys = gf100_vm_addr(vma, *list++, memtype, target);
- nv_wo32(pgt, pte + 0, lower_32_bits(phys));
- nv_wo32(pgt, pte + 4, upper_32_bits(phys));
+ nvkm_wo32(pgt, pte + 0, lower_32_bits(phys));
+ nvkm_wo32(pgt, pte + 4, upper_32_bits(phys));
pte += 8;
}
+ nvkm_done(pgt);
}
static void
-gf100_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt)
+gf100_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
{
+ nvkm_kmap(pgt);
pte <<= 3;
while (cnt--) {
- nv_wo32(pgt, pte + 0, 0x00000000);
- nv_wo32(pgt, pte + 4, 0x00000000);
+ nvkm_wo32(pgt, pte + 0, 0x00000000);
+ nvkm_wo32(pgt, pte + 4, 0x00000000);
pte += 8;
}
+ nvkm_done(pgt);
}
static void
gf100_vm_flush(struct nvkm_vm *vm)
{
- struct gf100_mmu_priv *priv = (void *)vm->mmu;
- struct nvkm_bar *bar = nvkm_bar(priv);
+ struct nvkm_mmu *mmu = vm->mmu;
+ struct nvkm_device *device = mmu->subdev.device;
struct nvkm_vm_pgd *vpgd;
u32 type;
- bar->flush(bar);
-
type = 0x00000001; /* PAGE_ALL */
- if (atomic_read(&vm->engref[NVDEV_SUBDEV_BAR]))
+ if (atomic_read(&vm->engref[NVKM_SUBDEV_BAR]))
type |= 0x00000004; /* HUB_ONLY */
- mutex_lock(&nv_subdev(priv)->mutex);
+ mutex_lock(&mmu->subdev.mutex);
list_for_each_entry(vpgd, &vm->pgd_list, head) {
/* looks like maybe a "free flush slots" counter, the
* faster you write to 0x100cbc to more it decreases
*/
- if (!nv_wait_ne(priv, 0x100c80, 0x00ff0000, 0x00000000)) {
- nv_error(priv, "vm timeout 0: 0x%08x %d\n",
- nv_rd32(priv, 0x100c80), type);
- }
+ nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x100c80) & 0x00ff0000)
+ break;
+ );
- nv_wr32(priv, 0x100cb8, vpgd->obj->addr >> 8);
- nv_wr32(priv, 0x100cbc, 0x80000000 | type);
+ nvkm_wr32(device, 0x100cb8, vpgd->obj->addr >> 8);
+ nvkm_wr32(device, 0x100cbc, 0x80000000 | type);
/* wait for flush to be queued? */
- if (!nv_wait(priv, 0x100c80, 0x00008000, 0x00008000)) {
- nv_error(priv, "vm timeout 1: 0x%08x %d\n",
- nv_rd32(priv, 0x100c80), type);
- }
+ nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x100c80) & 0x00008000)
+ break;
+ );
}
- mutex_unlock(&nv_subdev(priv)->mutex);
+ mutex_unlock(&mmu->subdev.mutex);
}
static int
gf100_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset,
- struct nvkm_vm **pvm)
+ struct lock_class_key *key, struct nvkm_vm **pvm)
{
- return nvkm_vm_create(mmu, offset, length, mm_offset, 4096, pvm);
+ return nvkm_vm_create(mmu, offset, length, mm_offset, 4096, key, pvm);
}
-static int
-gf100_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+static const struct nvkm_mmu_func
+gf100_mmu = {
+ .limit = (1ULL << 40),
+ .dma_bits = 40,
+ .pgt_bits = 27 - 12,
+ .spg_shift = 12,
+ .lpg_shift = 17,
+ .create = gf100_vm_create,
+ .map_pgt = gf100_vm_map_pgt,
+ .map = gf100_vm_map,
+ .map_sg = gf100_vm_map_sg,
+ .unmap = gf100_vm_unmap,
+ .flush = gf100_vm_flush,
+};
+
+int
+gf100_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
{
- struct gf100_mmu_priv *priv;
- int ret;
-
- ret = nvkm_mmu_create(parent, engine, oclass, "VM", "vm", &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.limit = 1ULL << 40;
- priv->base.dma_bits = 40;
- priv->base.pgt_bits = 27 - 12;
- priv->base.spg_shift = 12;
- priv->base.lpg_shift = 17;
- priv->base.create = gf100_vm_create;
- priv->base.map_pgt = gf100_vm_map_pgt;
- priv->base.map = gf100_vm_map;
- priv->base.map_sg = gf100_vm_map_sg;
- priv->base.unmap = gf100_vm_unmap;
- priv->base.flush = gf100_vm_flush;
- return 0;
+ return nvkm_mmu_new_(&gf100_mmu, device, index, pmmu);
}
-
-struct nvkm_oclass
-gf100_mmu_oclass = {
- .handle = NV_SUBDEV(MMU, 0xc0),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = gf100_mmu_ctor,
- .dtor = _nvkm_mmu_dtor,
- .init = _nvkm_mmu_init,
- .fini = _nvkm_mmu_fini,
- },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c
index fe93ea2711c9..37927c3fdc3e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c
@@ -23,7 +23,6 @@
*/
#include "nv04.h"
-#include <core/device.h>
#include <core/gpuobj.h>
#define NV04_PDMA_SIZE (128 * 1024 * 1024)
@@ -34,30 +33,34 @@
******************************************************************************/
static void
-nv04_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+nv04_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
{
pte = 0x00008 + (pte * 4);
+ nvkm_kmap(pgt);
while (cnt) {
u32 page = PAGE_SIZE / NV04_PDMA_PAGE;
u32 phys = (u32)*list++;
while (cnt && page--) {
- nv_wo32(pgt, pte, phys | 3);
+ nvkm_wo32(pgt, pte, phys | 3);
phys += NV04_PDMA_PAGE;
pte += 4;
cnt -= 1;
}
}
+ nvkm_done(pgt);
}
static void
-nv04_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt)
+nv04_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
{
pte = 0x00008 + (pte * 4);
+ nvkm_kmap(pgt);
while (cnt--) {
- nv_wo32(pgt, pte, 0x00000000);
+ nvkm_wo32(pgt, pte, 0x00000000);
pte += 4;
}
+ nvkm_done(pgt);
}
static void
@@ -66,86 +69,81 @@ nv04_vm_flush(struct nvkm_vm *vm)
}
/*******************************************************************************
- * VM object
- ******************************************************************************/
-
-int
-nv04_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mmstart,
- struct nvkm_vm **pvm)
-{
- return -EINVAL;
-}
-
-/*******************************************************************************
* MMU subdev
******************************************************************************/
static int
-nv04_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv04_mmu_oneinit(struct nvkm_mmu *base)
{
- struct nv04_mmu_priv *priv;
- struct nvkm_gpuobj *dma;
+ struct nv04_mmu *mmu = nv04_mmu(base);
+ struct nvkm_device *device = mmu->base.subdev.device;
+ struct nvkm_memory *dma;
int ret;
- ret = nvkm_mmu_create(parent, engine, oclass, "PCIGART",
- "pcigart", &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.create = nv04_vm_create;
- priv->base.limit = NV04_PDMA_SIZE;
- priv->base.dma_bits = 32;
- priv->base.pgt_bits = 32 - 12;
- priv->base.spg_shift = 12;
- priv->base.lpg_shift = 12;
- priv->base.map_sg = nv04_vm_map_sg;
- priv->base.unmap = nv04_vm_unmap;
- priv->base.flush = nv04_vm_flush;
-
- ret = nvkm_vm_create(&priv->base, 0, NV04_PDMA_SIZE, 0, 4096,
- &priv->vm);
+ ret = nvkm_vm_create(&mmu->base, 0, NV04_PDMA_SIZE, 0, 4096, NULL,
+ &mmu->vm);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(priv), NULL,
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
(NV04_PDMA_SIZE / NV04_PDMA_PAGE) * 4 + 8,
- 16, NVOBJ_FLAG_ZERO_ALLOC,
- &priv->vm->pgt[0].obj[0]);
- dma = priv->vm->pgt[0].obj[0];
- priv->vm->pgt[0].refcount[0] = 1;
+ 16, true, &dma);
+ mmu->vm->pgt[0].mem[0] = dma;
+ mmu->vm->pgt[0].refcount[0] = 1;
if (ret)
return ret;
- nv_wo32(dma, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */
- nv_wo32(dma, 0x00004, NV04_PDMA_SIZE - 1);
+ nvkm_kmap(dma);
+ nvkm_wo32(dma, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */
+ nvkm_wo32(dma, 0x00004, NV04_PDMA_SIZE - 1);
+ nvkm_done(dma);
return 0;
}
-void
-nv04_mmu_dtor(struct nvkm_object *object)
+void *
+nv04_mmu_dtor(struct nvkm_mmu *base)
{
- struct nv04_mmu_priv *priv = (void *)object;
- if (priv->vm) {
- nvkm_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]);
- nvkm_vm_ref(NULL, &priv->vm, NULL);
+ struct nv04_mmu *mmu = nv04_mmu(base);
+ struct nvkm_device *device = mmu->base.subdev.device;
+ if (mmu->vm) {
+ nvkm_memory_del(&mmu->vm->pgt[0].mem[0]);
+ nvkm_vm_ref(NULL, &mmu->vm, NULL);
}
- if (priv->nullp) {
- pci_free_consistent(nv_device(priv)->pdev, 16 * 1024,
- priv->nullp, priv->null);
+ if (mmu->nullp) {
+ dma_free_coherent(device->dev, 16 * 1024,
+ mmu->nullp, mmu->null);
}
- nvkm_mmu_destroy(&priv->base);
+ return mmu;
+}
+
+int
+nv04_mmu_new_(const struct nvkm_mmu_func *func, struct nvkm_device *device,
+ int index, struct nvkm_mmu **pmmu)
+{
+ struct nv04_mmu *mmu;
+ if (!(mmu = kzalloc(sizeof(*mmu), GFP_KERNEL)))
+ return -ENOMEM;
+ *pmmu = &mmu->base;
+ nvkm_mmu_ctor(func, device, index, &mmu->base);
+ return 0;
}
-struct nvkm_oclass
-nv04_mmu_oclass = {
- .handle = NV_SUBDEV(MMU, 0x04),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv04_mmu_ctor,
- .dtor = nv04_mmu_dtor,
- .init = _nvkm_mmu_init,
- .fini = _nvkm_mmu_fini,
- },
+const struct nvkm_mmu_func
+nv04_mmu = {
+ .oneinit = nv04_mmu_oneinit,
+ .dtor = nv04_mmu_dtor,
+ .limit = NV04_PDMA_SIZE,
+ .dma_bits = 32,
+ .pgt_bits = 32 - 12,
+ .spg_shift = 12,
+ .lpg_shift = 12,
+ .map_sg = nv04_vm_map_sg,
+ .unmap = nv04_vm_unmap,
+ .flush = nv04_vm_flush,
};
+
+int
+nv04_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
+{
+ return nv04_mmu_new_(&nv04_mmu, device, index, pmmu);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h
index 7bf6f4b38f1d..363e33b296d5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h
@@ -1,19 +1,18 @@
#ifndef __NV04_MMU_PRIV__
#define __NV04_MMU_PRIV__
+#define nv04_mmu(p) container_of((p), struct nv04_mmu, base)
+#include "priv.h"
-#include <subdev/mmu.h>
-
-struct nv04_mmu_priv {
+struct nv04_mmu {
struct nvkm_mmu base;
struct nvkm_vm *vm;
dma_addr_t null;
void *nullp;
};
-static inline struct nv04_mmu_priv *
-nv04_mmu(void *obj)
-{
- return (void *)nvkm_mmu(obj);
-}
+int nv04_mmu_new_(const struct nvkm_mmu_func *, struct nvkm_device *,
+ int index, struct nvkm_mmu **);
+void *nv04_mmu_dtor(struct nvkm_mmu *);
+extern const struct nvkm_mmu_func nv04_mmu;
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c
index 61ee3ab11660..c6a26f907009 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c
@@ -23,7 +23,6 @@
*/
#include "nv04.h"
-#include <core/device.h>
#include <core/gpuobj.h>
#include <core/option.h>
#include <subdev/timer.h>
@@ -36,45 +35,50 @@
******************************************************************************/
static void
-nv41_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+nv41_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
{
pte = pte * 4;
+ nvkm_kmap(pgt);
while (cnt) {
u32 page = PAGE_SIZE / NV41_GART_PAGE;
u64 phys = (u64)*list++;
while (cnt && page--) {
- nv_wo32(pgt, pte, (phys >> 7) | 1);
+ nvkm_wo32(pgt, pte, (phys >> 7) | 1);
phys += NV41_GART_PAGE;
pte += 4;
cnt -= 1;
}
}
+ nvkm_done(pgt);
}
static void
-nv41_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt)
+nv41_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
{
pte = pte * 4;
+ nvkm_kmap(pgt);
while (cnt--) {
- nv_wo32(pgt, pte, 0x00000000);
+ nvkm_wo32(pgt, pte, 0x00000000);
pte += 4;
}
+ nvkm_done(pgt);
}
static void
nv41_vm_flush(struct nvkm_vm *vm)
{
- struct nv04_mmu_priv *priv = (void *)vm->mmu;
-
- mutex_lock(&nv_subdev(priv)->mutex);
- nv_wr32(priv, 0x100810, 0x00000022);
- if (!nv_wait(priv, 0x100810, 0x00000020, 0x00000020)) {
- nv_warn(priv, "flush timeout, 0x%08x\n",
- nv_rd32(priv, 0x100810));
- }
- nv_wr32(priv, 0x100810, 0x00000000);
- mutex_unlock(&nv_subdev(priv)->mutex);
+ struct nv04_mmu *mmu = nv04_mmu(vm->mmu);
+ struct nvkm_device *device = mmu->base.subdev.device;
+
+ mutex_lock(&mmu->base.subdev.mutex);
+ nvkm_wr32(device, 0x100810, 0x00000022);
+ nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x100810) & 0x00000020)
+ break;
+ );
+ nvkm_wr32(device, 0x100810, 0x00000000);
+ mutex_unlock(&mmu->base.subdev.mutex);
}
/*******************************************************************************
@@ -82,76 +86,56 @@ nv41_vm_flush(struct nvkm_vm *vm)
******************************************************************************/
static int
-nv41_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv41_mmu_oneinit(struct nvkm_mmu *base)
{
- struct nvkm_device *device = nv_device(parent);
- struct nv04_mmu_priv *priv;
+ struct nv04_mmu *mmu = nv04_mmu(base);
+ struct nvkm_device *device = mmu->base.subdev.device;
int ret;
- if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
- !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) {
- return nvkm_object_ctor(parent, engine, &nv04_mmu_oclass,
- data, size, pobject);
- }
-
- ret = nvkm_mmu_create(parent, engine, oclass, "PCIEGART",
- "pciegart", &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.create = nv04_vm_create;
- priv->base.limit = NV41_GART_SIZE;
- priv->base.dma_bits = 39;
- priv->base.pgt_bits = 32 - 12;
- priv->base.spg_shift = 12;
- priv->base.lpg_shift = 12;
- priv->base.map_sg = nv41_vm_map_sg;
- priv->base.unmap = nv41_vm_unmap;
- priv->base.flush = nv41_vm_flush;
-
- ret = nvkm_vm_create(&priv->base, 0, NV41_GART_SIZE, 0, 4096,
- &priv->vm);
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(nv_object(priv), NULL,
- (NV41_GART_SIZE / NV41_GART_PAGE) * 4, 16,
- NVOBJ_FLAG_ZERO_ALLOC,
- &priv->vm->pgt[0].obj[0]);
- priv->vm->pgt[0].refcount[0] = 1;
+ ret = nvkm_vm_create(&mmu->base, 0, NV41_GART_SIZE, 0, 4096, NULL,
+ &mmu->vm);
if (ret)
return ret;
- return 0;
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
+ (NV41_GART_SIZE / NV41_GART_PAGE) * 4, 16, true,
+ &mmu->vm->pgt[0].mem[0]);
+ mmu->vm->pgt[0].refcount[0] = 1;
+ return ret;
}
-static int
-nv41_mmu_init(struct nvkm_object *object)
+static void
+nv41_mmu_init(struct nvkm_mmu *base)
{
- struct nv04_mmu_priv *priv = (void *)object;
- struct nvkm_gpuobj *dma = priv->vm->pgt[0].obj[0];
- int ret;
-
- ret = nvkm_mmu_init(&priv->base);
- if (ret)
- return ret;
-
- nv_wr32(priv, 0x100800, dma->addr | 0x00000002);
- nv_mask(priv, 0x10008c, 0x00000100, 0x00000100);
- nv_wr32(priv, 0x100820, 0x00000000);
- return 0;
+ struct nv04_mmu *mmu = nv04_mmu(base);
+ struct nvkm_device *device = mmu->base.subdev.device;
+ struct nvkm_memory *dma = mmu->vm->pgt[0].mem[0];
+ nvkm_wr32(device, 0x100800, 0x00000002 | nvkm_memory_addr(dma));
+ nvkm_mask(device, 0x10008c, 0x00000100, 0x00000100);
+ nvkm_wr32(device, 0x100820, 0x00000000);
}
-struct nvkm_oclass
-nv41_mmu_oclass = {
- .handle = NV_SUBDEV(MMU, 0x41),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv41_mmu_ctor,
- .dtor = nv04_mmu_dtor,
- .init = nv41_mmu_init,
- .fini = _nvkm_mmu_fini,
- },
+static const struct nvkm_mmu_func
+nv41_mmu = {
+ .dtor = nv04_mmu_dtor,
+ .oneinit = nv41_mmu_oneinit,
+ .init = nv41_mmu_init,
+ .limit = NV41_GART_SIZE,
+ .dma_bits = 39,
+ .pgt_bits = 32 - 12,
+ .spg_shift = 12,
+ .lpg_shift = 12,
+ .map_sg = nv41_vm_map_sg,
+ .unmap = nv41_vm_unmap,
+ .flush = nv41_vm_flush,
};
+
+int
+nv41_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
+{
+ if (device->type == NVKM_DEVICE_AGP ||
+ !nvkm_boolopt(device->cfgopt, "NvPCIE", true))
+ return nv04_mmu_new(device, index, pmmu);
+
+ return nv04_mmu_new_(&nv41_mmu, device, index, pmmu);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c
index b90ded1887aa..a648c2395545 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c
@@ -23,7 +23,6 @@
*/
#include "nv04.h"
-#include <core/device.h>
#include <core/gpuobj.h>
#include <core/option.h>
#include <subdev/timer.h>
@@ -36,16 +35,16 @@
******************************************************************************/
static void
-nv44_vm_fill(struct nvkm_gpuobj *pgt, dma_addr_t null,
+nv44_vm_fill(struct nvkm_memory *pgt, dma_addr_t null,
dma_addr_t *list, u32 pte, u32 cnt)
{
u32 base = (pte << 2) & ~0x0000000f;
u32 tmp[4];
- tmp[0] = nv_ro32(pgt, base + 0x0);
- tmp[1] = nv_ro32(pgt, base + 0x4);
- tmp[2] = nv_ro32(pgt, base + 0x8);
- tmp[3] = nv_ro32(pgt, base + 0xc);
+ tmp[0] = nvkm_ro32(pgt, base + 0x0);
+ tmp[1] = nvkm_ro32(pgt, base + 0x4);
+ tmp[2] = nvkm_ro32(pgt, base + 0x8);
+ tmp[3] = nvkm_ro32(pgt, base + 0xc);
while (cnt--) {
u32 addr = list ? (*list++ >> 12) : (null >> 12);
@@ -75,24 +74,25 @@ nv44_vm_fill(struct nvkm_gpuobj *pgt, dma_addr_t null,
}
}
- nv_wo32(pgt, base + 0x0, tmp[0]);
- nv_wo32(pgt, base + 0x4, tmp[1]);
- nv_wo32(pgt, base + 0x8, tmp[2]);
- nv_wo32(pgt, base + 0xc, tmp[3] | 0x40000000);
+ nvkm_wo32(pgt, base + 0x0, tmp[0]);
+ nvkm_wo32(pgt, base + 0x4, tmp[1]);
+ nvkm_wo32(pgt, base + 0x8, tmp[2]);
+ nvkm_wo32(pgt, base + 0xc, tmp[3] | 0x40000000);
}
static void
-nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
{
- struct nv04_mmu_priv *priv = (void *)vma->vm->mmu;
+ struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu);
u32 tmp[4];
int i;
+ nvkm_kmap(pgt);
if (pte & 3) {
u32 max = 4 - (pte & 3);
u32 part = (cnt > max) ? max : cnt;
- nv44_vm_fill(pgt, priv->null, list, pte, part);
+ nv44_vm_fill(pgt, mmu->null, list, pte, part);
pte += part;
list += part;
cnt -= part;
@@ -101,51 +101,57 @@ nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
while (cnt >= 4) {
for (i = 0; i < 4; i++)
tmp[i] = *list++ >> 12;
- nv_wo32(pgt, pte++ * 4, tmp[0] >> 0 | tmp[1] << 27);
- nv_wo32(pgt, pte++ * 4, tmp[1] >> 5 | tmp[2] << 22);
- nv_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17);
- nv_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000);
+ nvkm_wo32(pgt, pte++ * 4, tmp[0] >> 0 | tmp[1] << 27);
+ nvkm_wo32(pgt, pte++ * 4, tmp[1] >> 5 | tmp[2] << 22);
+ nvkm_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17);
+ nvkm_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000);
cnt -= 4;
}
if (cnt)
- nv44_vm_fill(pgt, priv->null, list, pte, cnt);
+ nv44_vm_fill(pgt, mmu->null, list, pte, cnt);
+ nvkm_done(pgt);
}
static void
-nv44_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt)
+nv44_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
{
- struct nv04_mmu_priv *priv = (void *)nvkm_mmu(pgt);
+ struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu);
+ nvkm_kmap(pgt);
if (pte & 3) {
u32 max = 4 - (pte & 3);
u32 part = (cnt > max) ? max : cnt;
- nv44_vm_fill(pgt, priv->null, NULL, pte, part);
+ nv44_vm_fill(pgt, mmu->null, NULL, pte, part);
pte += part;
cnt -= part;
}
while (cnt >= 4) {
- nv_wo32(pgt, pte++ * 4, 0x00000000);
- nv_wo32(pgt, pte++ * 4, 0x00000000);
- nv_wo32(pgt, pte++ * 4, 0x00000000);
- nv_wo32(pgt, pte++ * 4, 0x00000000);
+ nvkm_wo32(pgt, pte++ * 4, 0x00000000);
+ nvkm_wo32(pgt, pte++ * 4, 0x00000000);
+ nvkm_wo32(pgt, pte++ * 4, 0x00000000);
+ nvkm_wo32(pgt, pte++ * 4, 0x00000000);
cnt -= 4;
}
if (cnt)
- nv44_vm_fill(pgt, priv->null, NULL, pte, cnt);
+ nv44_vm_fill(pgt, mmu->null, NULL, pte, cnt);
+ nvkm_done(pgt);
}
static void
nv44_vm_flush(struct nvkm_vm *vm)
{
- struct nv04_mmu_priv *priv = (void *)vm->mmu;
- nv_wr32(priv, 0x100814, priv->base.limit - NV44_GART_PAGE);
- nv_wr32(priv, 0x100808, 0x00000020);
- if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001))
- nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808));
- nv_wr32(priv, 0x100808, 0x00000000);
+ struct nv04_mmu *mmu = nv04_mmu(vm->mmu);
+ struct nvkm_device *device = mmu->base.subdev.device;
+ nvkm_wr32(device, 0x100814, mmu->base.limit - NV44_GART_PAGE);
+ nvkm_wr32(device, 0x100808, 0x00000020);
+ nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x100808) & 0x00000001)
+ break;
+ );
+ nvkm_wr32(device, 0x100808, 0x00000000);
}
/*******************************************************************************
@@ -153,95 +159,78 @@ nv44_vm_flush(struct nvkm_vm *vm)
******************************************************************************/
static int
-nv44_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nv44_mmu_oneinit(struct nvkm_mmu *base)
{
- struct nvkm_device *device = nv_device(parent);
- struct nv04_mmu_priv *priv;
+ struct nv04_mmu *mmu = nv04_mmu(base);
+ struct nvkm_device *device = mmu->base.subdev.device;
int ret;
- if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
- !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) {
- return nvkm_object_ctor(parent, engine, &nv04_mmu_oclass,
- data, size, pobject);
- }
-
- ret = nvkm_mmu_create(parent, engine, oclass, "PCIEGART",
- "pciegart", &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.create = nv04_vm_create;
- priv->base.limit = NV44_GART_SIZE;
- priv->base.dma_bits = 39;
- priv->base.pgt_bits = 32 - 12;
- priv->base.spg_shift = 12;
- priv->base.lpg_shift = 12;
- priv->base.map_sg = nv44_vm_map_sg;
- priv->base.unmap = nv44_vm_unmap;
- priv->base.flush = nv44_vm_flush;
-
- priv->nullp = pci_alloc_consistent(device->pdev, 16 * 1024, &priv->null);
- if (!priv->nullp) {
- nv_error(priv, "unable to allocate dummy pages\n");
- return -ENOMEM;
+ mmu->nullp = dma_alloc_coherent(device->dev, 16 * 1024,
+ &mmu->null, GFP_KERNEL);
+ if (!mmu->nullp) {
+ nvkm_warn(&mmu->base.subdev, "unable to allocate dummy pages\n");
+ mmu->null = 0;
}
- ret = nvkm_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096,
- &priv->vm);
+ ret = nvkm_vm_create(&mmu->base, 0, NV44_GART_SIZE, 0, 4096, NULL,
+ &mmu->vm);
if (ret)
return ret;
- ret = nvkm_gpuobj_new(nv_object(priv), NULL,
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
(NV44_GART_SIZE / NV44_GART_PAGE) * 4,
- 512 * 1024, NVOBJ_FLAG_ZERO_ALLOC,
- &priv->vm->pgt[0].obj[0]);
- priv->vm->pgt[0].refcount[0] = 1;
- if (ret)
- return ret;
-
- return 0;
+ 512 * 1024, true,
+ &mmu->vm->pgt[0].mem[0]);
+ mmu->vm->pgt[0].refcount[0] = 1;
+ return ret;
}
-static int
-nv44_mmu_init(struct nvkm_object *object)
+static void
+nv44_mmu_init(struct nvkm_mmu *base)
{
- struct nv04_mmu_priv *priv = (void *)object;
- struct nvkm_gpuobj *gart = priv->vm->pgt[0].obj[0];
+ struct nv04_mmu *mmu = nv04_mmu(base);
+ struct nvkm_device *device = mmu->base.subdev.device;
+ struct nvkm_memory *gart = mmu->vm->pgt[0].mem[0];
u32 addr;
- int ret;
-
- ret = nvkm_mmu_init(&priv->base);
- if (ret)
- return ret;
/* calculate vram address of this PRAMIN block, object must be
* allocated on 512KiB alignment, and not exceed a total size
* of 512KiB for this to work correctly
*/
- addr = nv_rd32(priv, 0x10020c);
- addr -= ((gart->addr >> 19) + 1) << 19;
-
- nv_wr32(priv, 0x100850, 0x80000000);
- nv_wr32(priv, 0x100818, priv->null);
- nv_wr32(priv, 0x100804, NV44_GART_SIZE);
- nv_wr32(priv, 0x100850, 0x00008000);
- nv_mask(priv, 0x10008c, 0x00000200, 0x00000200);
- nv_wr32(priv, 0x100820, 0x00000000);
- nv_wr32(priv, 0x10082c, 0x00000001);
- nv_wr32(priv, 0x100800, addr | 0x00000010);
- return 0;
+ addr = nvkm_rd32(device, 0x10020c);
+ addr -= ((nvkm_memory_addr(gart) >> 19) + 1) << 19;
+
+ nvkm_wr32(device, 0x100850, 0x80000000);
+ nvkm_wr32(device, 0x100818, mmu->null);
+ nvkm_wr32(device, 0x100804, NV44_GART_SIZE);
+ nvkm_wr32(device, 0x100850, 0x00008000);
+ nvkm_mask(device, 0x10008c, 0x00000200, 0x00000200);
+ nvkm_wr32(device, 0x100820, 0x00000000);
+ nvkm_wr32(device, 0x10082c, 0x00000001);
+ nvkm_wr32(device, 0x100800, addr | 0x00000010);
}
-struct nvkm_oclass
-nv44_mmu_oclass = {
- .handle = NV_SUBDEV(MMU, 0x44),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv44_mmu_ctor,
- .dtor = nv04_mmu_dtor,
- .init = nv44_mmu_init,
- .fini = _nvkm_mmu_fini,
- },
+static const struct nvkm_mmu_func
+nv44_mmu = {
+ .dtor = nv04_mmu_dtor,
+ .oneinit = nv44_mmu_oneinit,
+ .init = nv44_mmu_init,
+ .limit = NV44_GART_SIZE,
+ .dma_bits = 39,
+ .pgt_bits = 32 - 12,
+ .spg_shift = 12,
+ .lpg_shift = 12,
+ .map_sg = nv44_vm_map_sg,
+ .unmap = nv44_vm_unmap,
+ .flush = nv44_vm_flush,
};
+
+int
+nv44_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
+{
+ if (device->type == NVKM_DEVICE_AGP ||
+ !nvkm_boolopt(device->cfgopt, "NvPCIE", true))
+ return nv04_mmu_new(device, index, pmmu);
+
+ return nv04_mmu_new_(&nv44_mmu, device, index, pmmu);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
index b83550fa7f96..a1f8d65f0276 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
@@ -21,31 +21,28 @@
*
* Authors: Ben Skeggs
*/
-#include <subdev/mmu.h>
-#include <subdev/bar.h>
-#include <subdev/fb.h>
-#include <subdev/timer.h>
+#include "priv.h"
-#include <core/engine.h>
#include <core/gpuobj.h>
-
-struct nv50_mmu_priv {
- struct nvkm_mmu base;
-};
+#include <subdev/fb.h>
+#include <subdev/timer.h>
+#include <engine/gr.h>
static void
-nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_gpuobj *pgt[2])
+nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_memory *pgt[2])
{
u64 phys = 0xdeadcafe00000000ULL;
u32 coverage = 0;
if (pgt[0]) {
- phys = 0x00000003 | pgt[0]->addr; /* present, 4KiB pages */
- coverage = (pgt[0]->size >> 3) << 12;
+ /* present, 4KiB pages */
+ phys = 0x00000003 | nvkm_memory_addr(pgt[0]);
+ coverage = (nvkm_memory_size(pgt[0]) >> 3) << 12;
} else
if (pgt[1]) {
- phys = 0x00000001 | pgt[1]->addr; /* present */
- coverage = (pgt[1]->size >> 3) << 16;
+ /* present, 64KiB pages */
+ phys = 0x00000001 | nvkm_memory_addr(pgt[1]);
+ coverage = (nvkm_memory_size(pgt[1]) >> 3) << 16;
}
if (phys & 1) {
@@ -57,8 +54,10 @@ nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_gpuobj *pgt[2])
phys |= 0x20;
}
- nv_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys));
- nv_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys));
+ nvkm_kmap(pgd);
+ nvkm_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys));
+ nvkm_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys));
+ nvkm_done(pgd);
}
static inline u64
@@ -75,17 +74,18 @@ vm_addr(struct nvkm_vma *vma, u64 phys, u32 memtype, u32 target)
}
static void
-nv50_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+nv50_vm_map(struct nvkm_vma *vma, struct nvkm_memory *pgt,
struct nvkm_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
{
+ struct nvkm_ram *ram = vma->vm->mmu->subdev.device->fb->ram;
u32 comp = (mem->memtype & 0x180) >> 7;
u32 block, target;
int i;
/* IGPs don't have real VRAM, re-target to stolen system memory */
target = 0;
- if (nvkm_fb(vma->vm->mmu)->ram->stolen) {
- phys += nvkm_fb(vma->vm->mmu)->ram->stolen;
+ if (ram->stolen) {
+ phys += ram->stolen;
target = 3;
}
@@ -93,6 +93,7 @@ nv50_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
pte <<= 3;
cnt <<= 3;
+ nvkm_kmap(pgt);
while (cnt) {
u32 offset_h = upper_32_bits(phys);
u32 offset_l = lower_32_bits(phys);
@@ -113,129 +114,118 @@ nv50_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
}
while (block) {
- nv_wo32(pgt, pte + 0, offset_l);
- nv_wo32(pgt, pte + 4, offset_h);
+ nvkm_wo32(pgt, pte + 0, offset_l);
+ nvkm_wo32(pgt, pte + 4, offset_h);
pte += 8;
block -= 8;
}
}
+ nvkm_done(pgt);
}
static void
-nv50_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+nv50_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
{
u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 3 : 2;
pte <<= 3;
+ nvkm_kmap(pgt);
while (cnt--) {
u64 phys = vm_addr(vma, (u64)*list++, mem->memtype, target);
- nv_wo32(pgt, pte + 0, lower_32_bits(phys));
- nv_wo32(pgt, pte + 4, upper_32_bits(phys));
+ nvkm_wo32(pgt, pte + 0, lower_32_bits(phys));
+ nvkm_wo32(pgt, pte + 4, upper_32_bits(phys));
pte += 8;
}
+ nvkm_done(pgt);
}
static void
-nv50_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt)
+nv50_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
{
pte <<= 3;
+ nvkm_kmap(pgt);
while (cnt--) {
- nv_wo32(pgt, pte + 0, 0x00000000);
- nv_wo32(pgt, pte + 4, 0x00000000);
+ nvkm_wo32(pgt, pte + 0, 0x00000000);
+ nvkm_wo32(pgt, pte + 4, 0x00000000);
pte += 8;
}
+ nvkm_done(pgt);
}
static void
nv50_vm_flush(struct nvkm_vm *vm)
{
- struct nv50_mmu_priv *priv = (void *)vm->mmu;
- struct nvkm_bar *bar = nvkm_bar(priv);
- struct nvkm_engine *engine;
+ struct nvkm_mmu *mmu = vm->mmu;
+ struct nvkm_subdev *subdev = &mmu->subdev;
+ struct nvkm_device *device = subdev->device;
int i, vme;
- bar->flush(bar);
-
- mutex_lock(&nv_subdev(priv)->mutex);
- for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
+ mutex_lock(&subdev->mutex);
+ for (i = 0; i < NVKM_SUBDEV_NR; i++) {
if (!atomic_read(&vm->engref[i]))
continue;
/* unfortunate hw bug workaround... */
- engine = nvkm_engine(priv, i);
- if (engine && engine->tlb_flush) {
- engine->tlb_flush(engine);
- continue;
+ if (i == NVKM_ENGINE_GR && device->gr) {
+ int ret = nvkm_gr_tlb_flush(device->gr);
+ if (ret != -ENODEV)
+ continue;
}
switch (i) {
- case NVDEV_ENGINE_GR : vme = 0x00; break;
- case NVDEV_ENGINE_VP :
- case NVDEV_ENGINE_MSPDEC: vme = 0x01; break;
- case NVDEV_SUBDEV_BAR : vme = 0x06; break;
- case NVDEV_ENGINE_MSPPP :
- case NVDEV_ENGINE_MPEG : vme = 0x08; break;
- case NVDEV_ENGINE_BSP :
- case NVDEV_ENGINE_MSVLD : vme = 0x09; break;
- case NVDEV_ENGINE_CIPHER:
- case NVDEV_ENGINE_SEC : vme = 0x0a; break;
- case NVDEV_ENGINE_CE0 : vme = 0x0d; break;
+ case NVKM_ENGINE_GR : vme = 0x00; break;
+ case NVKM_ENGINE_VP :
+ case NVKM_ENGINE_MSPDEC: vme = 0x01; break;
+ case NVKM_SUBDEV_BAR : vme = 0x06; break;
+ case NVKM_ENGINE_MSPPP :
+ case NVKM_ENGINE_MPEG : vme = 0x08; break;
+ case NVKM_ENGINE_BSP :
+ case NVKM_ENGINE_MSVLD : vme = 0x09; break;
+ case NVKM_ENGINE_CIPHER:
+ case NVKM_ENGINE_SEC : vme = 0x0a; break;
+ case NVKM_ENGINE_CE0 : vme = 0x0d; break;
default:
continue;
}
- nv_wr32(priv, 0x100c80, (vme << 16) | 1);
- if (!nv_wait(priv, 0x100c80, 0x00000001, 0x00000000))
- nv_error(priv, "vm flush timeout: engine %d\n", vme);
+ nvkm_wr32(device, 0x100c80, (vme << 16) | 1);
+ if (nvkm_msec(device, 2000,
+ if (!(nvkm_rd32(device, 0x100c80) & 0x00000001))
+ break;
+ ) < 0)
+ nvkm_error(subdev, "vm flush timeout: engine %d\n", vme);
}
- mutex_unlock(&nv_subdev(priv)->mutex);
+ mutex_unlock(&subdev->mutex);
}
static int
-nv50_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length,
- u64 mm_offset, struct nvkm_vm **pvm)
+nv50_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset,
+ struct lock_class_key *key, struct nvkm_vm **pvm)
{
- u32 block = (1 << (mmu->pgt_bits + 12));
+ u32 block = (1 << (mmu->func->pgt_bits + 12));
if (block > length)
block = length;
- return nvkm_vm_create(mmu, offset, length, mm_offset, block, pvm);
+ return nvkm_vm_create(mmu, offset, length, mm_offset, block, key, pvm);
}
-static int
-nv50_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+static const struct nvkm_mmu_func
+nv50_mmu = {
+ .limit = (1ULL << 40),
+ .dma_bits = 40,
+ .pgt_bits = 29 - 12,
+ .spg_shift = 12,
+ .lpg_shift = 16,
+ .create = nv50_vm_create,
+ .map_pgt = nv50_vm_map_pgt,
+ .map = nv50_vm_map,
+ .map_sg = nv50_vm_map_sg,
+ .unmap = nv50_vm_unmap,
+ .flush = nv50_vm_flush,
+};
+
+int
+nv50_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
{
- struct nv50_mmu_priv *priv;
- int ret;
-
- ret = nvkm_mmu_create(parent, engine, oclass, "VM", "vm", &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.limit = 1ULL << 40;
- priv->base.dma_bits = 40;
- priv->base.pgt_bits = 29 - 12;
- priv->base.spg_shift = 12;
- priv->base.lpg_shift = 16;
- priv->base.create = nv50_vm_create;
- priv->base.map_pgt = nv50_vm_map_pgt;
- priv->base.map = nv50_vm_map;
- priv->base.map_sg = nv50_vm_map_sg;
- priv->base.unmap = nv50_vm_unmap;
- priv->base.flush = nv50_vm_flush;
- return 0;
+ return nvkm_mmu_new_(&nv50_mmu, device, index, pmmu);
}
-
-struct nvkm_oclass
-nv50_mmu_oclass = {
- .handle = NV_SUBDEV(MMU, 0x50),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = nv50_mmu_ctor,
- .dtor = _nvkm_mmu_dtor,
- .init = _nvkm_mmu_init,
- .fini = _nvkm_mmu_fini,
- },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
new file mode 100644
index 000000000000..27cedc60b507
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
@@ -0,0 +1,39 @@
+#ifndef __NVKM_MMU_PRIV_H__
+#define __NVKM_MMU_PRIV_H__
+#define nvkm_mmu(p) container_of((p), struct nvkm_mmu, subdev)
+#include <subdev/mmu.h>
+
+void nvkm_mmu_ctor(const struct nvkm_mmu_func *, struct nvkm_device *,
+ int index, struct nvkm_mmu *);
+int nvkm_mmu_new_(const struct nvkm_mmu_func *, struct nvkm_device *,
+ int index, struct nvkm_mmu **);
+
+struct nvkm_mmu_func {
+ void *(*dtor)(struct nvkm_mmu *);
+ int (*oneinit)(struct nvkm_mmu *);
+ void (*init)(struct nvkm_mmu *);
+
+ u64 limit;
+ u8 dma_bits;
+ u32 pgt_bits;
+ u8 spg_shift;
+ u8 lpg_shift;
+
+ int (*create)(struct nvkm_mmu *, u64 offset, u64 length, u64 mm_offset,
+ struct lock_class_key *, struct nvkm_vm **);
+
+ void (*map_pgt)(struct nvkm_gpuobj *pgd, u32 pde,
+ struct nvkm_memory *pgt[2]);
+ void (*map)(struct nvkm_vma *, struct nvkm_memory *,
+ struct nvkm_mem *, u32 pte, u32 cnt,
+ u64 phys, u64 delta);
+ void (*map_sg)(struct nvkm_vma *, struct nvkm_memory *,
+ struct nvkm_mem *, u32 pte, u32 cnt, dma_addr_t *);
+ void (*unmap)(struct nvkm_vma *, struct nvkm_memory *pgt,
+ u32 pte, u32 cnt);
+ void (*flush)(struct nvkm_vm *);
+};
+
+int nvkm_vm_create(struct nvkm_mmu *, u64, u64, u64, u32,
+ struct lock_class_key *, struct nvkm_vm **);
+#endif